       x 
  y "   ?*   ,   \/   @8   ;  *F  *G  *M  *Y  *C\  *$]  *d  *Ar   +  +  +  +  +*  +   +D  +  +ʴ  	+  
+(  +}  +  +  +  +  +*  + +$ +& +%3 +%3 +@ +L +M +V +\ +_ +qi +Lp +qs +w  +R !+ "+ #+͐ $+2 %+̩ &+ϯ '+X (+" )+Q *+= /+ 0+_ 1+ 2+} 3+ 4+ 5+| 6+ 7+ 8+ 9+$ :+ ;+ <+ =+ >+\& ?+; @+ A+3# B+n U+ f+r g+ h+ j+ k+ l+	 m+ n+! o+z p+2 q+ r+b s+F t+ u+ v+ w+ x+ y+ z+} {+ |+3 }+X ~+ + + + + +$ +#/ +5 +:: +? +.F +'K +[ +m +r +6s + +Ԅ +t + + + + +u +ߣ + + + +w +Q +  +U +m + + +$ +G +@ + +T +; + + +F +0
	 +	 +t	 +	 +	 +)	 +ip
 +
 +
 +> +G +` +r +|y +	  , , , , ,7 ,ϴ , ,r ,r 	, 
, ,
 ,# ,$ ,) ,/ ,0 ,3 ,< ,Z ,jd ,<o ,p ,z ,E , ,% ,Ј ,O ,7 ,N ,۰  ,ȴ !,{ ", #, $,z %,j &, ',V (, ), *, +,G ,,U -,W .,] /,9^ 0,f 1,S 2, 3, 4, 5, 6,O 7,z 8, 9, :, ;,$ <," =,W" m,D$ n,T& o,z= p,'C q,fK r,] s,rw t,qz u,} v,} w, x,8 y,g z,U {, |,H },H ~,e ,o ,r ,ct ,} , , , , ,% , ,d ,<h ,i ,j ,m , , , ,1 , , ,9 ,K ,R ,TX ,Fp ,q ,\r ,| , , ," , ,? , , ,b , , , ,J , ,h ,P , ,Z ,}+ ,K, ,0 ,q2 ,=8 .\ . .1 . .$ /, // /2 /5L /N /Q /BT /T 	/X 
/k />o /p /* 81 91گ R5 S5? rBC sB! tB'	! uBd! vB	! wB! xB! yB_,! zB2! {B\! |B# }BE"# ~B## B2# B^6# B># BG# BHZ# Bl# Bq# Br# B}z# Bx# Bҏ# BeR& BW& B4Z& B[& Bb& B:e& Bf& Bg& Bp& Bs& Bt& B{& B0& B& B& Bݙ' Be' B( B2( B( B( B+( Bi( B( B) B) B) Br) BC) B) B#) B-) B6) B8) B9) BH;) BR?) BTn) B*o) Bp) B`s) BKu) Blx) O|) Oˁ) O) O) O8) O) O) O) OT) O) O) O ) Oj) O) Oi) O) O) O) O) O) O) OF* O* O* OO* O* OF* O#* FPi* GPw+ a.4 c;)4 c^84 c<4 cA4 c<F4 c4G4 cK4 c[N4 c^T4 c^X4 c^4 cc4 cf4 cSj4 cm4 cn4 c4 c24 c4 c4 cI4 cB4 cz4 c4 ck
5 cO5 c5 co5 c!5 c*5 cj+5 cI=5 cv7 cv7 cz7 c7 c^7 c7 cz7 c`7 c7 cl7 c7 {7 {7 {>7 {7   7 +d ,O 
#<
bin  * 
pdf  * 
rtf  * 
swfD * 
splE * 
crx *
001 * 
7z4 * 
ace * 
arc * 
arj: * 
b64 * 
balz * 
bhx * 
bz * 
bz28 * 
bzip2 * 
cab * 
cpio@ * 
fat * 
gz6 * 
gzip * 
hfs * 
hqx * 
iso * 0
lha< * 
lpaq1 * 
lpaq5 * 
lpaq8 * 
lzh; * 
lzma? * 
mim * 
ntfs * 
paq8f * 
paq8jd * 
paq8l * 
paq8o * 
pea * 
quad * 
r00 * 0
r01 * 0
r02 * 0
r03 * 0
r04 * 0
r05 * 0
r06 * 0
r07 * 0
r08 * 0
r09 * 0
r10 * 0
r11 * 0
r12 * 0
r13 * 0
r14 * 0
r15 * 0
r16 * 0
r17 * 0
r18 * 0
r19 * 0
r20 * 0
r21 * 0
r22 * 0
r23 * 0
r24 * 0
r25 * 0
r26 * 0
r27 * 0
r28 * 0
r29 * 0
rar * 0
squashfs * 
swm * 
tar9 * 
taz * 
tbz * 
tbz2 * 
tgz7 * 
tpz * 
txz * 
tz * 
udf * 
uu * 
uue * 
vhd * 
vhdx * 
vmdk * 
wim= * 
wrc * 
xar * 
xxe * 
xz5 * 
z> * 
zip * 0
zipx * 
zpaq * 
class * 
jar * 
jnlp * 
pl * 
py * 
pyc * 
pyd * 
pyo * 
pyw * 
rb * 
efi * 
torrent * 
btapp * 
btskin * 
	btinstall * 
btkey * 
btsearch * 
oxt * 
msi * 
msp! * 
mst" * 
adeb *
adpc *
madd *
mafe *
magf *
mamg *
maqh *
mari *
masj *
matk *
mavl *
mawm *
mdan *
mdbo *
mdep *
mdtq *
mdwr *
mdzs *
ocxZ * 
ops[ *
paf  * 
pcd\ *
pif
 * 
plg] *
prf^ *
prg_ *
pst` *
cpi * 
docx  * 
docm  * 
dott  * 
dotm  * 
docb  * 
xlsx  * 
xlsm  * 
xltx  * 
xltm  * 
pptx  * 
pptm  * 
potx  * 
ppam  * 
ppsx  * 
sldx  * 
sldm  * 
partial * 
xrm-ms * 
rels * 
svg * 
xml * 
xsl * 
ps1+ * 
ps1xml, * 
ps2- * 
ps2xml. * 
psc1/ * 
psc20 * 
url * 
website * 
js * 
jse * 
vb * 
vbe * 
vbs * 
vbscript  * 
ws{ * 
wsc| * 
wsf3 * 
wsh} * 
msh% * 
msh1& * 
msh2( * 
mshxml* * 
msh1xml' * 
msh2xml) * 
ad  *
appB *
applicationF *
	appref-ms * 
aspG *
asxH *
bas# *
bat * 
cfgI *
chiJ *
chmK *
cmdA * 
com * 
cplL * 
crta *
dhtml * 
dhtm * 
dht * 
dll	 * 
drv * 
eml *
exe  * 
fon * 
fxpM *
gadget * 
grp *
hlpN *
hta$ * 
htm * 
html * 
httO * 
infP * 
iniQ *
insR *
inx  * 
isu  * 
ispS *
job  * 
lnkT * 
localU *
manifestV *
mauW *
mht *
mhtml *
mmcX *
mofY *
msc  * 
msg *
reg * 
rgs  * 
scf1 * 
scr * 
sct2 *
	search-ms * 
settingcontent-ms * 
shbt *
shsu *
shtml * 
shtm * 
sht * 
slk *
sys * 
u3p  * 
vdx *
vsx *
vtx *
vsdx *0
vssx *0
vstx *0
vsdm *0
vssm *0
vstm *0
vsdv *
vsmacrosw *
vssx *
vsty *
vswz *
xbap~ * 
xht * 
xhtm * 
xhtml * 
xnk *
cdr * 0
dart * 0
dc42 * 0

diskcopy42 * 0
dmg * 0
dmgpart * 0
dvdr * 0
img * 0
imgpart * 0
ndif * 0
smi * 0
sparsebundle * 0
sparseimage * 0
toast * 0
udif * 0
action  * 
as * 0
cpgz * 0
command * 
applescript * 
scpt * 
scptd * 
seplugin * 
osas * 
osax * 
mpkg * 
pax * 0
workflow  * 
xip * 0
pkg * 
deb * 
pet * 
pup * 
rpm * 
slp * 
out  * 
run  * 
bash * 
csh * 
ksh * 
sh * 
shar * 
tcsh * 
desktop * 
dex * 
apk * "
  * (
{
  "x-version": 53,
  "adobe-flash-player": {
    "mime_types": [
      "application/futuresplash",
      "application/x-shockwave-flash"
    ],
    "versions": [
      {
        "version": "32.0.0.142",
        "status": "requires_authorization",
        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-06.html"
      }
    ],
    "lang": "en-US",
    "name": "Adobe Flash Player",
    "help_url": "https://support.google.com/chrome/?p=plugin_flash",
    "url": "https://support.google.com/chrome/answer/6258784",
    "displayurl": true,
    "group_name_matcher": "*Shockwave Flash*"
  },
  "google-chrome-pdf": {
    "mime_types": [
    ],
    "versions": [
      {
        "version": "0",
        "status": "fully_trusted",
        "comment": "Google Chrome PDF Viewer has no version information."
      }
    ],
    "name": "Chrome PDF Viewer",
    "group_name_matcher": "*Chrome PDF Viewer*"
  },
  "chromium-pdf": {
    "mime_types": [
    ],
    "versions": [
      {
        "version": "0",
        "status": "fully_trusted",
        "comment": "Chromium PDF Viewer has no version information."
      }
    ],
    "name": "Chromium PDF Viewer",
    "group_name_matcher": "*Chromium PDF Viewer*"
  },
  "google-chrome-pdf-plugin": {
    "mime_types": [
    ],
    "versions": [
      {
        "version": "0",
        "status": "fully_trusted",
        "comment": "Google Chrome PDF Plugin has no version information."
      }
    ],
    "name": "Chrome PDF Plugin",
    "group_name_matcher": "*Chrome PDF Plugin*"
  },
  "chromium-pdf-plugin": {
    "mime_types": [
    ],
    "versions": [
      {
        "version": "0",
        "status": "fully_trusted",
        "comment": "Chromium PDF Plugin has no version information."
      }
    ],
    "name": "Chromium PDF Plugin",
    "group_name_matcher": "*Chromium PDF Plugin*"
  }
}
{
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqOhnwk4+HXVfGyaNsAQdU/js1Na56diW08oF1MhZiwzSnJsEaeuMN9od9q9N4ZdK3o1xXOSARrYdE+syV7Dl31nf6qz3A6K+D5NHe6sSB9yvYlIiN37jdWdrfxxE0pRYEVYZNTe3bzq3NkcYJlOdt1UPcpJB+isXpAGUKUvt7EQIDAQAB",
  "name": "Cloud Print",
  "version": "0.1",
  "description": "Cloud Print",
  "icons": {
  },
  "app": {
    "launch": {
      "web_url": "https://www.google.com/cloudprint"
    },
    "urls": [
      "https://www.google.com/cloudprint/enable_chrome_connector"
    ]
  },
  "permissions": [
    "cloudPrintPrivate"
  ],
  "display_in_launcher": false
}
{
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtl3tO0osjuzRsf6xtD2SKxPlTfuoy7AWoObysitBPvH5fE1NaAA1/2JkPWkVDhdLBWLaIBPYeXbzlHp3y4Vv/4XG+aN5qFE3z+1RU/NqkzVYHtIpVScf3DjTYtKVL66mzVGijSoAIwbFCC3LpGdaoe6Q1rSRDp76wR6jjFzsYwQIDAQAB",
  "name": "Web Store",
  "version": "0.2",
  "description": "Chrome Web Store",
  "icons": {
    "16": "webstore_icon_16.png",
    "128": "webstore_icon_128.png"
  },
  "app": {
    "launch": {
      "web_url": "https://chrome.google.com/webstore"
    },
    "urls": [
      "https://chrome.google.com/webstore"
    ]
  },
  "permissions": [
    "webstorePrivate",
    "management",
    "system.cpu",
    "system.display",
    "system.memory",
    "system.network",
    "system.storage"
  ]
}
{
  "name": "CryptoTokenExtension",
  "description": "CryptoToken Component Extension",
  "version": "0.9.74",
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq7zRobvA+AVlvNqkHSSVhh1sEWsHSqz4oR/XptkDe/Cz3+gW9ZGumZ20NCHjaac8j1iiesdigp8B1LJsd/2WWv2Dbnto4f8GrQ5MVphKyQ9WJHwejEHN2K4vzrTcwaXqv5BSTXwxlxS/mXCmXskTfryKTLuYrcHEWK8fCHb+0gvr8b/kvsi75A1aMmb6nUnFJvETmCkOCPNX5CHTdy634Ts/x0fLhRuPlahk63rdf7agxQv5viVjQFk+tbgv6aa9kdSd11Js/RZ9yZjrFgHOBWgP4jTBqud4+HUglrzu8qynFipyNRLCZsaxhm+NItTyNgesxLdxZcwOz56KD1Q4IQIDAQAB",
  "manifest_version": 2,
  "permissions": [
    "hid",
    "u2fDevices",
    "usb",
    "cryptotokenPrivate",
    "externally_connectable.all_urls",
    "tabs",
    "https://*/*",
    "http://*/*",
    {
      "usbDevices": [
        {
          "vendorId": 4176,
          "productId": 529
        }
      ]
    }
  ],
  "externally_connectable": {
    "matches": [
      "https://*/*"
    ],
    "ids": [
      "fjajfjhkeibgmiggdfehjplbhmfkialk"
    ],
    "accepts_tls_channel_id": true
  },
  "background": {
    "persistent": false,
    "scripts": [
      "util.js",
      "b64.js",
      "cbor.js",
      "sha256.js",
      "timer.js",
      "countdown.js",
      "countdowntimer.js",
      "devicestatuscodes.js",
      "approvedorigins.js",
      "errorcodes.js",
      "webrequest.js",
      "messagetypes.js",
      "factoryregistry.js",
      "closeable.js",
      "requesthelper.js",
      "asn1.js",
      "enroller.js",
      "requestqueue.js",
      "signer.js",
      "origincheck.js",
      "textfetcher.js",
      "appid.js",
      "watchdog.js",
      "logging.js",
      "webrequestsender.js",
      "window-timer.js",
      "cryptotokenorigincheck.js",
      "cryptotokenapprovedorigins.js",
      "gnubbydevice.js",
      "hidgnubbydevice.js",
      "usbgnubbydevice.js",
      "gnubbies.js",
      "gnubby.js",
      "gnubby-u2f.js",
      "gnubbyfactory.js",
      "singlesigner.js",
      "multiplesigner.js",
      "generichelper.js",
      "inherits.js",
      "individualattest.js",
      "devicefactoryregistry.js",
      "usbhelper.js",
      "usbenrollhandler.js",
      "usbsignhandler.js",
      "usbgnubbyfactory.js",
      "googlecorpindividualattest.js",
      "cryptotokenbackground.js"
    ]
  },
  "incognito": "split"
}
{
  // chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai
  "manifest_version": 2,
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN6hM0rsDYGbzQPQfOygqlRtQgKUXMfnSjhIBL7LnReAVBEd7ZmKtyN2qmSasMl4HZpMhVe2rPWVVwBDl6iyNE/Kok6E6v6V3vCLGsOpQAuuNVye/3QxzIldzG/jQAdWZiyXReRVapOhZtLjGfywCvlWq7Sl/e3sbc0vWybSDI2QIDAQAB",
  "name": "<NAME>",
  "version": "1",
  "description": "",
  "offline_enabled": true,
  "incognito": "split",
  "permissions": [
    "chrome://resources/",
    "contentSettings",
    "metricsPrivate",
    "resourcesPrivate",
    {"fileSystem": ["write"]}
  ],
  "mime_types": [
    "application/pdf"
  ],
  "content_security_policy": "script-src 'self' 'wasm-eval' blob: filesystem: chrome://resources; object-src * blob: externalfile: file: filesystem: data:; plugin-types application/x-google-chrome-pdf",
  "mime_types_handler": "index.html"
}
5
3sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI=5
3sha256/m/nBiLhStttu1YmOz7Y3D2u1iB1dV2CbIfFa3R2YW5M=5
3sha256/8Iuf4xRbVCmCMQTJn3rxlglIO1IOKoyuSUgmXyfaIKs=5
3sha256/8IHdrS+r6IWzSMcRcD/GA6mBxk1ECX8tGRW0rtGWILE=5
3sha256/k/2eeJTznE32mblA/du19wpVDSIReFX44M8wXa2JY30=5
3sha256/urWd7jMwR6DJgvWhp6xfRHF5b/cba3iG0ggXtTR6AfM=5
3sha256/IJPCDSE5tM9H3nuD5m6RU2i9KDdPXVn4qmC/ULlcZzc=5
3sha256/0Gy8RMdbxHNWR2GQJ62QKDXORYf5JmMmnr1FJFPYpzM=5
3sha256/8tTICtyaxIQrdbYYDdgZhTN0OpM9kYndvoImtw1Ys5E=5
3sha256/F7HIlsaG0bpJW8CzYekRbtFqLVTTGqwvuwPDqnlLct0=5
3sha256/zaV2Aw1A742R1+WpXWvL5atsJbGmeSS6dzZOfe6f1Yw=5
3sha256/UwOkRGMlP0K/mKNJdpQ0sTg2ean9Tje8UTOvFYzt1GE=5
3sha256/w7KUXE4/BAo1YVZdO3mBsrMpu4IQuN0mhUXUI//agVU=5
3sha256/JnPvGqEn36FjHQlBXtG1uWwNtdMj1o2ojR/asqyypNk=5
3sha256/AUSXlKDCf1X30WhWeAWbjToABfBkJrKWPL6KwEi5VH0=5
3sha256/zSyVjjFJMIeXK0ktVTIjewwr6U5OePRqyY/nEXTI4P8=5
3sha256/9dcHlrXN2WV/ehbEdMxMZ8IV4qvGejCtNC5r6nfTviM=5
3sha256/E+0WZLGSIe5nddlVKZ5fYzaNHHCE3hNqi/OWZD3iKgA=5
3sha256/QJ/69CTHYPRa0I3UVlwD6N4MtToxpQ1+0izyGnqEHQo=5
3sha256/LKtpdq9q7F7msGK0w1+b/gKoDHaQcZKTHIf9PTz2u+U=-
BadSSL AntivirusBadSSL MITM Software TestF
Avast Antivirusavast! Web/Mail Shield Rootavast! Web/Mail ShieldK
Bitdefender Antivirus%Bitdefender Personal CA\.Net-DefenderBitdefender/
Cisco UmbrellaCisco Umbrella Root CACisco5
Cisco UmbrellaCisco Umbrella Primary SubCACiscoO
ContentKeeper"ContentKeeper Appliance CA \(\d+\)ContentKeeper Technologies3
Cyberoam FirewallCyberoam Certificate Authority1

ForcePointForcepoint Cloud CAForcepoint LLC#
	FortigateFortiGate CAFortinet
FortinetFortinet( Ltd\.)?M
Kaspersky Internet Security.Kaspersky Anti-Virus Personal Root Certificate(
McAfee Web GatewayMcAfee Web Gateway(
NetSparkwww\.netspark\.comNetSparkD
SmoothWall Firewall-Smoothwall-default-root-certificate-authority@
SonicWall Firewall*HTTPS Management Certificate for SonicWALL+
SophosSophos SSL CA_[A-Z0-9\-]+Sophos
SophosSophos_CA_[A-Z0-9]++

Sophos UTMsophosutm Proxy CA	sophosutm8
Sophos Web ApplianceSophos Web Appliance
Sophos Plc!
Symantec Blue CoatBlue Coat.*>
/Trend Micro InterScan Web Security Suite (IWSS)IWSS\.TREND
ZscalerZscaler Inc\."@
3sha256/cH02TnKuUhQx3ZU4l/nEhG1bjDJCmP5T+9StofLRFX8="Mitel(0"@
3sha256/cH02TnKuUhQx3ZU4l/nEhG1bjDJCmP5T+9StofLRFX8="Mitel(0"@
3sha256/atuOPgVUYJItFQHLl/lMagLjnI8ndMpAiCW3tYN53BQ="Mitel(0"@
3sha256/SQtuxr6y1gNHILUUm2spzTVRWYjMFq+FQUiwe5sfihE="Mitel(0"@
3sha256/71UShHFSMt6S4kbDIzKTYrEySTuxa1ieR3VSC+uHGlY="Mitel(0"@
3sha256/71UShHFSMt6S4kbDIzKTYrEySTuxa1ieR3VSC+uHGlY="Mitel(0"O
3sha256/DEPqi83p/DvKFlZkrIIVVn40idU5OgyB4aeRQZkuGVM="Sennheiser HeadSetup(0"O
3sha256/j1kfeqTcPv6UkMOKRpLJAR7RKPHeWVVpQG13tvofa0w="Sennheiser HeadSetup(0     j0y
Ncta0vv$*$%o?7(F߯O^>e	^G%Rz`.`ڪBI@Bb`E.=Zh&(%N@}b#[ >7Z*rU,0Ul1w>yKj/RHSŞ
Ԙ<ЩFC쭈RPcǋHmBc`5Pf2S%x-XܜHɻ%1\xݱ&7 E       Xn8}WLmNµI
ɶ&#0(ilHx~>Er|i]9spfΓ0l|0+\V/28(lih4G4A܀Qb pF%&ر@<FIl6eb&!@2.i1fq(()Ɛ!BLZ(	Fp	'1He=LH	hQ&3'*f	FGpyM&n\i@qblZd7մRV8Ct`M \慝}Lc%}@Y&{>_FJΈFL}R}󍄆1[	GW=LTf*)(`yF`Hhc14]~4Y!)mϓUa l:'6Ъ;lKcᵭ EJ'I,7؆
Nl0Y<_^~}W=ۆ}~-*PvGz={{_˗[w#eVvCt`Unޤbhr뤺,w3E}B,LC
NCGlO|0xQ.S~dڮt\`6UE4݆\9BJzn3t"7qK,zQv75R~Olwr;$hz$5GuCrEUꄤQ_s)~SܺVbúBEcfE#niT~ؙI?3s;V~j!@,)sJpS)&*yNnTKKfXzt<rV$3E$@)⛵}΂eN@m*'jR%.g>(~BWTy\6?,ť{c59J׹K=2̔`/o^uxͩDtt~Th?k,͚Ri`:6RɸLndtosdty74]s[UFwnt~|Wy-xS},[Mj6l2H{=Is=MV2f)%G![+puFL؜wk B/(27)'r|Wa݉Z d!k?Dm0#K!p/M@f94z Y%,WzL8g懕kI5=-{5NC*c* AL?K)_Ԏ>OJ.4D? 2 T	ʘ9M[F!aKpsvA&͵Z@amw7p +xtx7ܦ gt!ªSًVI0BQ3`oպr0/.:aʩkE9u9JWgW҈y4Mca[5-܃_qy       Zr8}W U[#)ɾlxKv]q.3$!	c2D?_ H)3NV ׃Z9䳹&9K,!LυTC2cb&)"brɢhDn#bJ+D&CFB13d2e	Vҫ,ezN5	iJ"K#SgB9ؔۉU4KCEOt2 cKɂD$
Jܸ$tN&҄|J/"^s0j&<TNTCMT,i1Ј3Kw;b @2ɔ|J$`rM&$e3;D}rhJBq\2W='3sށYOWo9OBHtLyL^?qzERMG2 :):4"'۾ۮW`U5{(1Y-}sr"EV⃁jB +tHW,gqȘU9z-rp5J-aoxx{er۠B~q{0;Yqe)K%/3WcE.n1w=iXRd+`xeD2c,]w*dݵAi?ik[;KLLϹB	sQ)s@SD׆%½ufQ>rI} =tJ;4*afǺ˲.܎WR$cyث2Xe^٥75')b].J1_p5q6O4Ac!O򗞥n~y\SP
gU};vB4W}2R4Al)/J%<]d a,Z5`F\]\na<=<<,51a:R,Nѱ!p/`gj薵vvl7kE,{`S!C$#%+AmiŢk}?Go_XHbRy4$	iyC@K~VŅ?N5QشaEr!IhAf)]R#R|2ÊZ}E}<϶ ?u,wWXrdDJC$'9TmoFN*b[-bh35q[5abC\AЃ"^%LvQF MsZlN\Hٲw?Iδ,ۇ+(p!gOKtkGad4ƅj5e\
Z |Yp
UL6ؤ,8dODz={ȺUI	~Lqa"Dn,].8UIGlCXF\TԣgMC-[A^֠YԶ5E76L 7Iwb9f[)<b.z?6,KR؀09K#ث1;~w|t1M(/yq<ƚ0YЌ|ȷք(sFMo'7wo.8{uMӿuE|<w]_q]E`<g%ɮ񇋈4nͻr7\:M!O#37! qbdgidpR9q66;qF\M,n}Զء7ĉ$׆6ŌJR
MEGy9s&=nB֥gMRCZRT
,nbb/|n$HyBEAWa[)@Y[2TF=[nsJb }E%ϋy
+rWc!)ILC>[{.yu䍹:w%C%ؖ"QfQUIWVᎎ/	`&~D tU2:6⽙ZN&˺ X0Ma&ڳ_t(lVJm 
W-4xSc3\Uk[s55b)X:l4EU3
2aH@ARes' d)gi iKfkm [d+9ķE0cp;W?ҘGjl6Pi:nAg߿{@/6;8ڣըUkG	;4ʋzÖ7e?Z<*:<t6|@#wSը8F;bǰT36J>SKOK]MУ8NE}go7FtI(gP)ǚ["@؃7B{nYׁ%fɤhh3 sSBX;!llV;6Z.O@Zb?ٙuí[870Q*mXׇ\:<Ջϣtۓᇑ˙N,Ɇv]ߟ?زdW톸o^p9.?7ݪYx[('nWD\-b؋M	{ڢ+rͯ}+ǯy7-Uf7].!eCDBa`I^D9 35WOqE},΄a^)ZPok2K[!6/H.PCɟaKqv]͚0mQeOZB_0
ٚL}~M[l-户}nTiƶ9pzpQb]yFI[{)$7_plMB!Qomo;{׼m]lzhGmO#^Ś]mM6o[FkWqcĹj\5vFw{7V߰XhW3&[}Z	3       TMO0WL#R)ݞmDUHU/B+=I\;mq>6A@ aym.I,+OpY!TԲnJAr`ѡݡXD?)Wҁ3rKCQv\&5yL´ZR".7)'Jh520n۲\.B*Q-E|=FΔI<ʔ7Ԣ:ec,G1#uR].|ƨ}v8*Q{"BtSpF5Al9Ve*IofJMB3YVKǙEҲ#L:h邥蒚IM c(18.5WxkIޏ,yxo+< eT5
></"5IQWr~z:-]4Ӣg%\:><͖xrY̓,g	.O{?p=ooG.W3Md?ߨكXRFz*p0KPވ#0cLPTOt.q+"?];)3G̫       j0DN{*)us(PH5dV{^:q^]mߖɕ	m=a,4:$"%Xd h׸P.+4۔WOx70ԷluƠ./jN|~yJ}EN_Ƹ4h1i;i6,qd= s4:sS.TH@	       Zn6Sچ6@d'in!K[ XЋ8aD[l(R )'؃zO'!%۔,nV(,|xᡔ_HA[ttI4FTutB
I^W>UHT"$bH$'!FJAFGj}Q\_}zvgl?\I̐l< (&kZ.! ڀp"A;d0_r|v(%sƉC$s/0f˷KUHǬ6h*xר|nvlX=@ʱ"8K&aW#
gBSG{!UA:$N<c,ɹ^&uȟ	1(D_r?kMcMt<A1NOOM>#}Do)2C<I&ޫ7	w|7k'הS'III1*Pţ\k-Ȩ,#H%7Q"l혿vcm\c -cP%X$A̨8*M#k4iXqPT3bq8c?PGM.Uxl!Z
9J>v D$bXBoׅAǌҋV^bO%ZRE{Q=*ݞx6ئ&&XxxH's'Zr]-")Cl
$rʐI Bsh3"%5i}夨6UҙM0QiOlF&Uc[ӽY;a`|/NCeAVk8Әog$t:g5u1iRYF[4D՟=̜r:Td.3\c'_ʥ5,b'g`/N{Ƥ.Zk;W'By*\T:W15l˗XpIӗͨbG?kDxNtjφ^)kxgl4~/b.Q)fX·S3mM̐,*GsUTνb΀]$k
6'\+P󘛫Lgv4p(2RW1xRܳe/Xu,#Urar?/=-)	}'%awPmƽ{vfKx.1xj2.d~uk`%.{dxGIם2r9[/nvBwlxn]-s!hV"T8c156}i:+"*}3y6P\fo@G ҹ4]ŽD8ZxW1^r
W1@`];@	\lͶ|LyY教mb)۰oVrTduxnݺst`aX[֚*V8$8{Ro*Da3g$` 2c＋Y>lrJj&N7S7]NV)[w~}\ɂ;,&LSse+,kv_Ϋ*A,{ɘ;`
BhE\5d5YkeĶ?S2β0@UYUT1ees0;͹A]JBl*aX)2TXWM]iW7/|Ɲ@@%ӶOnuhYV2m<0()>8[ϻa[)iLý*}XX#Odw5eF6Ghs!CbHw[@RW1Msxf0fO*{? T iےel꓿W\0Z@'       [ms6_C%l܇Nr9M;DB/A9j~x!7L2&zzJ||!ɫ #0]~*\$GQ"XĚ)yH3"aB
sf"fn%oNB0L.$>ɔO〄1|gf4,wt/`0fN&>AAiؗ!=N
)B_v.?ӊ
$?|݄3o=ġT-g&SS#F-ׂBǆN?Dr+%Z)mՅWy(J^	!fB-4i^np5W5l.`ж ـ/4ɄN(Li^n%:-B|dh4O<ߪBzi1#߾C'VwZLS8khDldM0")a%NS&XgD=XI*)	9p)1UzITkF'@xbwk2QlЮ>&SK)^KB7=_Mi4Ӝ=?e'td(#ʒW:}Q*A
'db .tWpb-Eeg;aoKrNN^j!A,
EWw-_[c?J٥kܵXxh&2k/SEϑEc^1&魊D3c3G"C3MQN9{opثByv<oRةU)~{7u0
%ǈSHi`+1
ZVr=	A̧-f,R	c^gM\$F4}L09[#;AHb-`Hn!N
ȅ,='7뙌+q7f]jmpMEQ!ɒdSRsRv^u97jA&Ȇ1NC?oB͏/tPR
*Ũ|8Ϡ;'J6V$D#T-IW~Dx9t`]IF;wR@xM)i=	!P7 2Lr]/a^Ӣ[ !OÚқ3y' \Ô3N/A;ǊqQI<!õ@L% y,r.jV4i1c3D@oU2*Rfw0_nwn2m*!xl,upScIBV18PHiYFͲqwFtkY,H''@=U7ȑ,qvǰTxVg /+,ٮ/_øYӜM-qqml<yrԋ.ސ%W;^[IQ;*dN0&,iz;(f#ck&r﻿݁fqb{%ʥZj͕<_0$*_FWWrYAE{IwXҁ`iGooUaj[>7ec;hAP֙<d{ݚx7Nv-┙zjQGFLǺfûnoDJcۂHy(mtsUqiu4EKM^RȜ#ؓrM[3Pj+Jړd1Qh[2Ǌ_WX7d8TM>I&b$DQ]0Z ~sSf9ܒdEj}
5ܽ%横<6$4;PU
yA9^i!X\)C,t;ԭх|,/U"6ݞRLWp`gh
ff-P1 S9&+:g7ׂ/sqʀJuTn;TG-J梄us6d\eIooHǸ H;+p;3(r.h8R"#?=drSk\.eĂ^z<6|+:Uz|[]s58%O"Tե>7b?kBvVyOnX`3u'kP)6%SW6+p/SnXgkMACS5.ayT5<U <ǋyGgj㷝<U2-O1=uq	O#$SvT)V .ka%M%_Bu)#,JT#&8ˤJh&J# 94Lh!Z?
!<f<MM
[TYC"FHPj:+9jB
vIa1yyvvVgk. [ #d!-_ODī2DsZV:-Ca/7/R\gɃ\ZUnf<ɯO#ğii!,Q^@*CeáHl[xFס|Poe$;EWBor0)N]zܣu8x|.s)Zzi@]U߀l}HkSh0,i]P{qٺ>R;]UJ6ƺg2W؜7f=>@ Ա
'99`/<2ڟd}lT͒]#LϚ=129~$+Cxȡ6f	%<\.8rtML#Fah
kޙb@W`&h(Ƨ˱^0b}eQOv-Ua_XܬO	MX@uՏ6MD7:̋ z3I8VU&h5=-w7a-ѷħ-_sS<
q}owe;:\RYIa뒅}wXX/쨸#F-.X?zjC6[,/W:?4D}M鎙6;%)57\y~psGقEYQӬ EB4GORz827/	<`>÷}%japL^{ºXy甧z0ȗ( [UXKiVi,zه"V6<{ʈRO ]n1 Cgk-	3lU{Ch~73sZa݇SU^6fdV-XZh+~^^N)fojǝՆ=Mj?F~.7?V5:       [YsȖ~LT2wo 2zF[~ s{f:Q'5ϟFqTU]/=C/+Wa/+/~9ە}e^Lb]W'</mUWڋ8슷5 bW+T_C`U~+A;]t+O[?^1fսJxI%zWeAL0f#t_q~(iI==}_;֏S}d6ƾ%
ķ_~/IT9>ңm]+?um??9/z~uW*Ķyzlo~>wYO'Kk/C_Y`M?s&;.&T,JU[4&U3i'zꙁiHy')jOM4%iASg&9Eb>oxǐgMmEkVEQWZ{h\v/ھzc')!Mk,{ChM]mV^:tU?n۾b;Vuy\sג_;XvpO_9[ku!39nJ}3>7O=Cu^dB+4mqc4^T<\?:~o>wj ѻ֐A?;u=M:ox֯w}Jj[:|ΧY}}8xЋ~іk~_:[QV1dH^{NCnulWb|_|Aco"?+'/~ΝڲARa?\yOطdd ccv󭙴v):ϫ4i<k3djY螚S^3{̥(ng{w"͇ɹبgjTvVAYRƸ:=i|M}x4#!5
N9ҙ/U{@k{]Boma3;޴Nap,ӐtS_+۫Y{4FZ}	:~lBrԶB'ӣ=CItr]gM5'ݍLi`]{zިg͚ߪ>aJᬪ|_UWx9Y4Fh:3ًMY`	赉;Hd[uFۻ5g^ǹwF+gI\GsFZ'K^ݷ]+DBf=҆,_A=נ{Е8i/5x y-u ПԧV|Q14UY3ӷ8؍E /_z{|k-pޚϷqՇlGǘ-t g9p1*ǈcڏA}ڬh23ڶ!UaЏA{mo=GVGfRw8K߀WVdX667}|'vddɬsbo#
<h<&˟͹wgaYҳ|apȽD[|jt vџBAbOȰ%-Me߃ıh5=4 [	ƞm<e{֠OR/Q-oygгhYy&^ɶQl@[{
?-,YXb_2V):W^
`Й73Nҝz47WK^`Mo5]̇W	|S{vCoӒZb8 :ʐXch3~d (4v$szoȑGeWU!lZ,|+w#%>XݔG}n>&FYvo` |G?{Z>`HD%Rt45bed|<'zֈOiըpu夭ϊI(AKnsS'd_3S]wI1#ń8ڮٳx09]eʖ`!d7{^ήyp᳚ٞ{;w:b?7ME߷3_7\abͭ+CbUմ[<uX.=췑!U	]_ 241&苄?Ҹs#ށ`E#,o1
	z=}1۵Lboi)d8ו/cuIs+
ߣ?,WJ8ܷmD9Yޓ909aRWkG{L7n{.>g4s<'A|!:<vnp0̀sX<v M@TP\+'l@O{4߲^sݥ;='g3ج!͖kYGg1g%f}W|/=b~{}Zi?w[2yVkՂ@y-^_G"Y)o
C)Ơpzc)Oi@|r};"/HFE;Ҽ`#)_MY#j,6R3hOX|37jsL(wh[yabh~}`=IF+&I09~4v5(yC13؃OޔlT|-l]wYx"ߋX lWm|t`l밂CN[ne(*-焳_	].;#b1}W.t9l40>RzqS=BqF})mt\hti3cȕ|8OH7#!s]9+ǭ¡D~07(io<	6K\&W:8cçsyܞNIS.cGΙɭِK5)b'	a@xOzeTLc:rfuT7bS<0!~o=]3?I9Pts(h?'xy4%0ٌ.rP<'o3l5Z0lNaW ؄x9m&˘wKz\wE̙[3Yc=3WݒM)p։+*	l3+ٻ2Yn	Sۃç6G2r8eOdwsPMl	<΂5d6Gdj\7En͉|gڢ뺨,juNU9zFJؙ<6>}}q&Ϋf^RȾ\3-_3ʅ'>BW6E"olI|b<W'Y~䈇)AkX'-DLo0GTuľ
L@ dsgP`d<.qtߘolf5S^QǞIdثZ;YP7NYjjc9":K,f#u`~g5\;	JvrNtW!׽meaς'\&H_Q:!tu8/X'0_akdtOؚЫ,'ZB8w4ɶdY<̊{9?&vߨ8mcƚAi>
I&,hs?&3oaE,g!+F:_.bx[5!f/<o4 5MƢPZroKX:޶Latzf߂	=jY.E13yndur=9G-˙>fE9iFgy'tӤQ{yΏ1Y咷9&.Ҹhtʚyi'rm<羝IuKfzOX۰:x_tvzq3)'Xσᩈ5Jt;9WCOAq/y|>b~,ϋ^s1\QOv)l+zDnWt\V77D^%K2NQ/y"/W:0d]|:nGĞy$q H wd?tI39J{>Yi\}	zҘF9fBw2MoBN ;izdr?CQ>SO(pǐbju[p̤n=1Af,TkQtxf_oY*<FRf"9{zk	n[<q_[6}ckŌo,G8ofv},椱Y[8st9X49=+ng[֬19x=rӅ/8R-ݼk]n#Կ&&~u?܇ͬni8F5`oyh2QIDrLyҫ1܏)꯼(3PV
ż=5U5^E}g gy&\wNmAӜ(ϩ)hzy{滒uV{-uZ7-Sfהji>e4>f:^5DO5P7/DwOYͣL"#ϥ=u]*Ȏg?y󥵾YfZsmXF^_t9}s-+'lldJ<ۚ'ԨX}{+)?}E?Fȃtú%)Q჋<%%ӚOs|ݿ#1o)#^g.MzX-LmeY@ԼXME>fyD><ig2r,)~~h1߇isGqO(svZ.m%&bMs@6忭'b2˄zo߆7qkSGA,ײnײZX7fkQu&;և<7z;Q?yaLfM/|:=YX,fG=<c\o=^cRݡid=15KsɞF=}޳ŽK~tMQ,)~A{sV/"qo_:C%fYk]ci.=pE1׉xڊ䒽$|}y,*ݵX>.b0ؽ\S.6PnKG/eX63KrV@ί;WkSeU`?;zH>_mkq[{!8xߠ@cIf(Do^gj>sHK>v9搛o{xwoʮ'+C$YwDH{`Oy{
=^yO%xU>dǿX=j21X] 3>88iyN-aw`q=W9,+npg=ؐ.R'ƙ\_~mCP.dcDdU)xǧZ"WӸ>ϛg:E|\={k3l׬}q&7D)bwfoػ?T*/@Pl$O#"/c*'5hOsANΞ f?6[/<YmJG/ez^t筺uW76.dcey[ў"w"Riؽ7,sP[E̵Q7:#dueeO7v7 xE 5i-.e}xewxw~%qP}vwrߩxdý7xn܍X[txh>UUuOa{s[}?ӞNzo)]Wcol_OgOFW!ǚ@       Sn0+PPNOM 0A4GWT!8>wv83cHd*^>?cJpeM)&pUU@jTddd*C$Cpܠ m6mPk3%5Q)z\Zwm|_@+$ѽU:ǼqhSg#wO	 N ;Y$ zԗF5K&R*5RӧgusoTzc,[U{	).ɬR(؆	hIOW}Q|8L!er+2å&>y pa"H[
*FZlhR|_NHIptЬDvºۛBҼHXKՂC>^a{F6:}{og.~ӦV^ʹo?uF3(v<7GM/dZ4!.:7f)\O9du38<
+lH&9ar-i6w5-x:ߏB       RMo0WL#q#hIV**!.-kOb^ٓB@wIv
DHMfbS!x|aob8H&TÕs0DLPׄ: c0FF`O=j8L uhr*L##	p`=>o@gEqkHKJ	GPz.Dx[hfxM0cd2-t'NUBEhQ,I߷%rW 4d&%NX%7 IPFƄԖ#uՇrM9@]["`"vmBMPye3"L*' E,R?r׈%̼d'R?Ac'GGܸ9xEѾ]CZNa-\n6o>:oXџ2WdS8w!m4ⴻ&s.Oy"/2@       Wn7}WLw 4ul6Z_<Hb"+U}C!@3䮴J%Ϝr8ކ#=8x-Fe>1fxӸAs $:EϾQBw
_o4Cd@8H.2SO*hӣuz2øHLbO*lF0I-o D9Zgd⢽-);Y'Ra,-C&*ohARKE;m:ӟ4aBe 'a!m''.7
It2FeҙGo"1g#]#mp@lfE
s N`{wJOC	6UX!n-W%Gs;n+}?UB;հ^fi4|SfEh_ErJ1W|Hp_qb4BBF\6d"Q9&a#3.:F>=+$E389
Vʇ]+	!lRMYPDr̃}zMf"|ƊiۦUVQPQ;v?ssY83R6hLRl)534Q[X%1$[zDtT?vPr>A(tk/,hb9Y:zPS[4aP?J;G/;WNoo:t2U a9@N.nj*GXAۮU9;~ i5E4}Ng}_^dX'}vq~sR:ëBo^S|ϚkY+B=oE%ؕ5Ԣ|ĢFXYbe,8*wXX0,g^ʴ~.jM_k<@ǃnaՓ|'@=5U:wTW*ojX95p<17Ec1]nJO-d0/xjM~`d&?8I=`byBs_F}	LācɂYۨ*K.4Ԋ<t$Nt<oq~F+?!\> =<r /jxnelQ=BSO;w)+X"XQXADﱭ'(} )	N)D*7*%يAZTȎ2E!㤖fatqq	N슲Q`^ԪçD-vٚzxA~Smtΐ:p9?Уp)8~-ypH6?k+R˳ 핿蟿h0eHsm< ,Wl =FBN\UQUFW]
ϻܭܪՀ_:ѻTϻӽ#j=       o8+B>,{BĀ]l~v \$EZ>rό3CC,rwC"0\	TI$AIĆVӁ$VT䩈D<&|C#1̟ý?z+sB aL3iSez"G	fyTsh)ՆЌzҙJ;Zo&,81eXqIDQBQJ2z y(S:XTNĭncfk[,XiRI·-LBiNk"C~շ7AT*_Y.)0LǸ:f)R ˀyka[	M΁A?qe%q	GX-ؙϗ,{8H7@71i[< wBߌ^~Cn_4r=t{=*@'>Y7ܽi\!qkc&['#?na+o~a0ۏ%Ro]-`1ʵ̥ڣ}W0$sgvȝ]l\E+ؙɝ~vC&yB#AvM	z<ySONŖ:3z|h{U\bb,I}5E?\a$ӾYq=W?@p&Sk!ߟy5E}	3uK^a9;A/4Uj(w/_8^kۍZdboz,μ.6Q(;UT`]-p>929 \yr;N;zqص[Dq$       ]s۸?t.TeqiǱKLPdLz	ʎ{^ )H)Y"..~ig:`wz:^~ֱZQ!d L/vv+,jY_,ƿ&ѲwC,:[;۳ƀPobA?և󓳋3k
]Ga ыsB{˺k'[C;,O r`hYpjuȷ>B̵!H~	t.mBzǼ=؁yIl껮 
7knX :^ZE.|K1;'GL1&U%'6BLމarسA + D}K:yI8aׅS<:.^x0F!f/ۨ,Zɀᑘ}CQW9G*MҍO/kʩVHp'I4gw迚u!*؏q_ cw?HIOO.pAQO''NNqݢr/}8ņE>_\;pE
zE^gμ. =y1zsk:6]9<+ "F11?dD!:bnT8&O9?"p7-Cb1? />]E(ӿ/.>qZg]ځ`(zlL1H{Lmu{	~*.M@H>A6)1HE̓ xОW)syFbN~!J=%@~kAέ>=xJ;fňc:jwFkHc @JBە`
:LOw	KC TmF/)uU7 \&0+=}~ݔmcH@yO-WXd&Mɣhxd &G,d0p{PF	$;I
;09Jcq<9<1>Ma5Y za}oȗfc[RΕ8KC{9Xs9CF!!eV`Lt5}	2߼=Yj{"_g瀏FXfHܦ687'q4W(K{${xYY\JoI&!\@}6z8fOysKzusnKz\ygCEL.T \!vԵ.TAjZ2STaipjFtjQߒv!%(;Bp#b7	Sbl)r=Vwd3l&+RrZֹzy0׷z8Dz[)m$rmLx޾{X6~JJ"C8NTPqqD&pljq2 u&"(c	:Xkٱ*V1ُVOlM8;Lgzި9oHWw_i#1_"F#7\ab#?ϲy`.5T$f{rRQH*b.Vd橋%aErD&Q3fpRPZfJż}	";3DWjf Rhtzg^<35+7 mܳYM۬>kDtT(|+HTvSΙLcFLI[bL(2JTOv	)V]'kg%!6M.R4CQTyum8YFjKӮRx=HTH߭SBv2MN/l'9'cA>q7.݃'72-V8GqԋBZU:.5{/_{`=.倫tfP(+q@"-ZpN\Q+5=X7ژ
4MHf]WH̱ y $x	"{;w63/ Z.?{;$fC!&|bHK'30fQ/lO(<&Kl$fwHV3CLX6hʲ@JAj#JE!IF-Kqx9@)ԍG5	o$5ߚȸJTL7sQlUKTd:*u:fiBZLn:̪g38kf9IzT!J,#ҩJk$;\6QUQ[`5%Vkqv2<$B~cIfD$>LҪٜVj:ձAFQN7'X:0xD3zb01W >׬C<ҡx}6%QzQ¹5|IvYp\cORݸ~Ky~tu2i/wR1|g]Vmٔs=^uc6t0-?ہ=CWV_cKm'NA'SУ5Lj=Hf>Ei>720|h#	JH1-S?œU}#hwcX5VvUo=θc?,Lf]8-\E˛d2$zDVr>	}BL>Etm61Pre<(Ca\^JW6j.PƣBƩr(sa=7wbC8$ 0s<a1A2COmk3J ԇx4$޽}*Bbŝ>
X`BX^IsK{bA/6xfKzal^ )ii_kV{}1_e*L@&]SmF\3jS{ZAVM
mhf-6k,.h;N<,s0Í5˶KԳr4KfΕeKۮry֕j
U6.HF6 1	rU0rܑq|bw)n2-j4/'1VVvRKn+~S<[m)vϥ냙9vڃ6s zҪw|FEp[XԲR.6`m0(
7a.jIV  ]TqCrv`&+hT^,ۂ6zZi[zY[!FqАh&5Lb}κeM\:?!nv
ժjG~]˴ qhguoT¹٢6q=o}%*U[q{Zm[{~l,oRj NSsVϫZkt=impͮko+[wYUjp@F@׻u	F7o^F{4Pp`ot;(=VY׃7{{{ץuy/oTyNjG`/RstnmoOst4Àzz v .{a.I=rrqf'xd\VxK{,ɝ' D0yip¾=`:1^Viww0UHi`~	5nMogc"k&D3B,+h@ߞNT( YKnR-E\!4t|p!z(?^@ڧG/;CE-ޙP8j^Ocˈb^^RmŢfC%bY܍q+SɠNR*m}q<<&8?[uif(2%qq|l*0SN .wйM--*p';Q3Y-.#Kv˦s> 1
+kGS,l\r\dYP^]j?ފ,iF^\*,iԭ&7m̵ʤ4DFLAݏ_[XJ'Qn:lK|YP}_>qx_=[)-jW4|l==OM]Gi_'99[A߳Ϥ+dw.+LJs7lҁ'ᠦBa}մ{sM7k{%鉬TB9T4xQ|nɡr@=AR5e3Դv8Shfj#^5zIZ
x~kp\ NlX[Laew&7vҿI^G(X-(6)DDMPʹU\ъԭ)-cCQTSzJ#^oUUXA+*	3â*Om=/U9RE/;clFL&*1XiM'58Apƃ5  1Z%b!YDEt %:`VSOeTy$EiT{B=sK
	0Z$zVz,*hY$<ktezDR&#|(^Ska44Ҵ+c &pvVއ[pED?Nι)D@ûSMsWr!eCjD	h;?M&l|^Bw>"Tg~|bI&+Ⱦ2euNY'6mnÙyt\3+N~2bdEV,hlgX͵h~,Xē=n۱O4`
*o[#3+ns*S=wZjl/=o^eZ#a,Lh])*)Ƅj$_$6i3]=8l8qmDL[nz"U )QNwifRF1u*I]afQ{5sHwY&(2.S.EoY..u [Ib\iSwYDh|X[eORnɲd#XWA
\2dkM+#GrM][
$4@%	+z\T-qY@mgiMb\`&qqJ6Ԃ]hqcivUXHO\Dv+zo37֗~IVr!,XI?,)BKp1..L{NcbNLP'{%'2{*w~A8eP1Nʃ70|$oXI YB3~0=|6frْ2KJ(F.Q$wc1"bJ<ܽH(Tԏn,%	SN,san{?x)      Uo0~_q{"h,n>i::/UUl*c'	ߏ]Zi|!\Δ\bI#2(4(ԨDAwA`f\b q*&0Y6!1
J33f f&hRY ;p4B3UP6Ǧ0-Dla%S?:shn^LP4w'Lc7W2FxVB)qa-"Zd	&mB@	-ӊ)V2b(γ2EfxN@}-x[lK4P>ocoxEBU5ul]i-c&v<*e<aF?|̥2zYNscXNa@{w`177$JaJOW|%dN?^cF4l#:](;6vuz%T/Ht'-MZ*Uhu*vwcw,:cv%TʬP]9jV,Iq|wb#ME)WХM5V9Y(=Ըc|AJ:۪h/[7 P):nGmn8V5=*M	^:: `m;)1_lkӸ/ L;#^wsc/E5׀n~}&R!pոĞMK)#Fi3ڏ酸_*C׮KU<<yv8'TYbQ19}LRܠoT{{>{@N%^Ne,_  Q~iXRe       %1o0FwNK'4M*]s"{z}X$bvK$Q;S,`3"QcR(O	a$/uɄ<uUxW0y*}ck;ӪPeE7'W7]u	)F        Tn0+@ ?mOEI\=DBI9{/Y >zl{U*߿~/ºR;SIS!
5=i\_ K0UAN,h{T!uMxkbr&`(TGxz\od(ki,D`X}-l<Ge'rSKxmz4@$Qm)!XVApLr)n`b]X{*٢25pg;P^_@IzIĨL-vNk-A8Oڭn o2hjErDud}nۆBzcjރX%D r9dHb mpt6?w2x΃C?<$hhj6öL#*v(|P
Yʆ>.T1
xd0ȱqmh[;]T1lt ģ]|Z
+zmYdcLsk3{sQSJ} &Xyu.y׈W!٭CN!QZsSMdq>!!ӳ! ~aj&c(^$FGAC59B?8wT;vrOv:W!/:Eikm%_'>;
+il3uM        \[o8~4(yȥv&	f(Ym5A$R7KImc߹VF#t'+O$^dtA'a8QN1y3mQ<Ct(3a>Fv?`aMWE7N*(<2p)M14GAzq=!vSJMkE=-Gh= 8&~4&$=i͉,l8|@(!snolo4.=Yc8E,AGhK	0pnӌD3q,]r_d"U1"v.ؔv4bΓcnj)J )$&4-;l<ŗ.HY
H"$$wOtqeӧnuV8`Ҹq*㙼CEr1KVDt);*0K6sQ2k*?I]0y9Z`h{_,$0RQۋkw/Yl'f82`9V%C(ЇqPLt`s)(,ٌn} `ƙ[T<&k@H:R@f1Q<iYXctMÜN@̇9'^$0W@܀uK0sJ6Y3!1`i${CI`vll{}&gR38>.Rb/.9W1I
o>K`銲Lv|!!r[HPhskF}#v!1;̛w6a۳h_?ip[1>w|f1>Gx1Bt|IбǏ6,H\͸?@t~SK'\C\HO!%ľLe,eaڍ[@bUMJ4#	(jitaqiNjE){:6a^P̲)n挿p&./=*ƋلyWk|1es:SzBSF)+5T5Vij*5Tn*4ג`GQG09e,p~gIv˲N&!$qLeD;f(~-KyY:?۲T/q;9Gmݶ$\+`5fw"/;+8CBԍN6oo<g4.PP"ư6FRSKZaar>@n87zv-Z_Ln8mQbg:ô6wNk q̉=!]hsX]4rؼ<FF_l42݅ЇBؿC<Bpᵚ}}Phg%r]j;T2$V㗗MPgZ=[k*Իiw3Saga<[&w`zv]kٯ{CXj|^0_>ﻪbq[+mYdUجvPG-QG&q}{X|$ksw/wr+lp޻tsʝmKe~@lv/JE%5ApƆZ}Mp#?W^ÙqMt0|a?#J043V:)IxCG"Q礖&e.VI\Բ{.FSȟI~u<0يIWY{dP'sHmeHR\ju:zEgn:r]c&SDf>7I܀	)`?2ϖ"bmߥH4,Cmr ²uѱh}lsE*eA	F)o9]2т#y٢^{-YR\`D2?6촷LOAEZ4r-zNI
|]*7zζ%M3Gu2䡫z wm&"OCs0NQ!-mY?AA4H2#tbC
!_HD@F)?F*RXMQxbKO;=-}Ȓ$'Y+8/ƛZt!LK]ewJGZId,neo(eՔҒ6>dP9ryŰ0Uӿ>-mzOU.$KNŹMjhMLt
aW)/O+H&GY]J(tW$cr &,R
tEkXLHJlP,̈́)x}UX:4#'ո75vMgwКlZ{۰l}Yt!1!R7nF٥+CT=FJvF'a3(u*ʑ=	#RV.4K	nnBk@QUrP\śzx@355/0.H*KK'OC *-F  <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<style>
body {
  margin: 10px;
  min-width: 47em;
}

a {
  color: blue;
  font-size: 103%;
}

#header {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMiA0Mmg0NEwyNCA0IDIgNDJ6bTI0LTZoLTR2LTRoNHY0em0wLThoLTR2LThoNHY4eiIvPgo8L3N2Zz4K)
      left center / 48px no-repeat;
  box-sizing: border-box;
  margin-bottom: 1.05em;
  overflow: hidden;
  padding-inline-start: 0;
  position: relative;
}

html[dir=rtl] #header {
  background-position-x: right;
}

#header h1 {
  line-height: 48px;
  padding-inline-start: 51px;
}

h1 {
  font-size: 156%;
  font-weight: bold;
  margin: 0;
  padding: 0;
}

#blurb-container {
  font-size: 120%;
  padding-bottom: 1.5em;
}

#third-party-conflicts-status {
  padding-bottom: 1.5em;
}

div.content {
  font-size: 88%;
  margin-top: 5px;
}

.section-header {
  background: rgb(235, 239, 249);
  border-top: 1px solid rgb(181, 199, 222);
  font-size: 99%;
  padding-bottom: 2px;
  padding-inline-start: 5px;
  padding-top: 3px;
  width: 100%;
}

.section-header > table > tr > td:first-child {
  width: 100%;
}

.section-header > table {
  width: 100%;
}

.section-header-title {
  font-weight: bold;
}

.vbox-container {
  -webkit-box-orient: vertical;
  display: -webkit-box;
}

.wbox {
  -webkit-box-align: stretch;
  -webkit-box-flex: 1;
  display: -webkit-box;
}

#top {
  padding-inline-end: 5px;
}

.module-loaded > td {
  padding-bottom: 4px;
  padding-top: 5px;
}

.module {
  border-bottom: 1px solid #cdcdcd;
}

.module-name {
  font-weight: bold;
}

.no-modules {
  font-size: 1.2em;
  margin: 6em 0 0;
  text-align: center;
}

.suspected-bad {
  color: rgb(221, 119, 0);
}

.confirmed-bad {
  color: red;
}

.nowrap {
  white-space: nowrap;
}

.extra-info-text {
  margin-bottom: 1em;
  margin-top: -1em;
}

.clearing {
  clear: left;
  float: left;
}

html[dir=rtl] .clearing {
  clear: right;
  float: right;
}

.datacell {
  border-bottom: 1px solid #aaa;
}
</style>
</head>
<body>
<div id="loading-message">Loading…</div>

<div id="body-container" style="visibility:hidden">

  <div id="header"><h1>Modules loaded</h1></div>

  <div id="blurb-container">
    <span>This page lists all modules loaded into the browser and renderer processes and modules registered to load at a later point.</span>
  </div>

  <div id="modulesTemplate">

    <div id="third-party-conflicts-status">
      Third-Party Module Features Status
      <div>
        <span jscontent="thirdPartyFeatureStatus">STATUS</span>
      </div>
    </div>

    <div id="container" class="vbox-container">
      <div id="top" class="wbox">

        <div class="section-header">
          <table cellpadding="0" cellspacing="0"><tr valign="center">
            <td>
              <span class="section-header-title"
                    jscontent="moduleCount">COUNT</span> modules
            </td>
          </tr></table>
        </div>

      </div>
    </div>

    <div class="content">
      <div class="module-name no-modules"
           jsdisplay="moduleList.length === 0">
        <div>Unable to detect any modules loaded.</div>
      </div>

      <div jsdisplay="moduleList.length &gt; 0">
      <table width="100%" cellpadding="0" cellspacing="0">
      <tr class="module-loaded">
      <td valign="top">
        <table cellpadding="2" cellspacing="0" border="0">
          <tr>
            <td class="datacell">
              <span dir="ltr">Software</span>
            </td>
            <td class="datacell">
              <span dir="ltr">Signed by</span>
            </td>
            <td class="datacell">
              <span dir="ltr">Version</span>
            </td>
            <td class="datacell">
              <span dir="ltr">Code Id</span>
            </td>
            <td class="datacell">
              <span dir="ltr">Location</span>
            </td>
            <td jsdisplay="thirdPartyFeatureEnabled" class="datacell">
              <span dir="ltr">Conflicts Status</span>
            </td>
          </tr>
          <tr jsselect="moduleList">
            <td valign="top" class="datacell">
              <span dir="ltr"
                    jsvalues=".innerHTML:description"
                    class="clearing nowrap"></span>
            </td>
            <td valign="top" class="datacell">
              <span dir="ltr" jscontent="digital_signer" class="nowrap">
                SIGNER
              </span>
            </td>
            <td valign="top" class="datacell">
              <span dir="ltr" jscontent="version" class="nowrap">VERSION</span>
            </td>
            <td valign="top" class="datacell">
              <span dir="ltr" jscontent="code_id" class="nowrap">CODE_ID</span>
            </td>
            <td valign="top" class="datacell">
              <span class="nowrap">
                <span dir="ltr" jscontent="location">LOCATION</span>
                <strong>
                  <span dir="ltr" jscontent="name">NAME</span>
                </strong>
                <span dir="ltr" jsdisplay="type_description.length &gt; 0">
                    (
                    <span dir="ltr" jscontent="type_description">
                      MODULE_TYPE
                    </span>
                    )
                </span>
              </span>
            </td>
            <span jsdisplay="third_party_module_status.length &gt; 0">
              <td valign="top" class="datacell nowrap">
                <span jscontent="third_party_module_status">
                  THIRD_PARTY_MODULE_STATUS
                </span>
              </td>
            </span>
          </tr>
        </table>
      </td>
      </tr>
      </table>
      </div>
    </div>
  </div>
</div>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/promise_resolver.js"></script>
<script src="chrome://resources/js/util.js"></script>

<script src="chrome://conflicts/strings.js"></script>

<script src="chrome://conflicts/conflicts.js"></script>
</body>
</html>
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * This variable structure is here to document the structure that the template
 * expects to correctly populate the page.
 */
const moduleListDataFormat = {
  'moduleList': [{
    'type_description':
        'The type of module (string), defaults to blank for regular modules',
    'location': 'The module path, not including filename',
    'name': 'The name of the module',
    'product_name': 'The name of the product the module belongs to',
    'description': 'The module description',
    'version': 'The module version',
    'digital_signer': 'The signer of the digital certificate for the module',
    'code_id': 'The code id of the module',
    'third_party_module_status': 'The module status'
  }]
};

/**
 * Takes the |moduleListData| input argument which represents data about
 * the currently available modules and populates the html jstemplate
 * with that data. It expects an object structure like the above.
 * @param {Object} moduleListData Information about available modules.
 */
function renderTemplate(moduleListData) {
  // This is the javascript code that processes the template:
  const input = new JsEvalContext(moduleListData);
  const output = $('modulesTemplate');
  jstProcess(input, output);
}

/**
 * Asks the C++ ConflictsHandler to get details about the available modules
 * and return detailed data about the configuration.
 */
function requestModuleListData() {
  cr.sendWithPromise('requestModuleList').then(returnModuleList);
}

/**
 * Called by the WebUI to re-populate the page with data representing the
 * current state of installed modules.
 * @param {Object} moduleListData Information about available modules.
 */
function returnModuleList(moduleListData) {
  renderTemplate(moduleListData);
  $('loading-message').style.visibility = 'hidden';
  $('body-container').style.visibility = 'visible';
}

// Get data and have it displayed upon loading.
document.addEventListener('DOMContentLoaded', requestModuleListData);
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<style>
.key {
  font-weight: bold;
}

.value {
  margin-left: 15px;
}
</style>
</head>
<body>
<div id="loading-message">$i18n{loadingMessage}</div>
<div id="body-container" style="visibility:hidden">
  <div id="header"><h1>$i18n{flashLongTitle}</h1></div>

  <div id="flashInfoTemplate">
    <table cellpadding="2" cellspacing="0" border="0">
      <tr jsselect="flashInfo">
        <td><span dir="ltr" jscontent="key" class="key">KEY</span></td>
        <td><span dir="ltr" jscontent="value" class="value">VALUE</span></td>
      </tr>
    </table>
  </div>
</div>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://flash/about_flash.js"></script>
<script src="chrome://flash/strings.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
<script src="chrome://resources/js/util.js"></script>
</body>
</html>
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Takes the |moduleListData| input argument which represents data about
 * the currently available modules and populates the html jstemplate
 * with that data. It expects an object structure like the above.
 * @param {Object} moduleListData Information about available modules
 */
function renderTemplate(moduleListData) {
  // This is the javascript code that processes the template:
  const input = new JsEvalContext(moduleListData);
  const output = $('flashInfoTemplate');
  jstProcess(input, output);
}

/**
 * Asks the C++ FlashUIDOMHandler to get details about the Flash and return
 * the data in returnFlashInfo() (below).
 */
function requestFlashInfo() {
  chrome.send('requestFlashInfo');
}

/**
 * Called by the WebUI to re-populate the page with data representing the
 * current state of Flash.
 * @param {Object} moduleListData Information about available modules.
 */
function returnFlashInfo(moduleListData) {
  $('loading-message').style.visibility = 'hidden';
  $('body-container').style.visibility = 'visible';
  renderTemplate(moduleListData);
}

// Get data and have it displayed upon loading.
document.addEventListener('DOMContentLoaded', requestFlashInfo);
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <link rel="stylesheet" href="chrome://nacl/about_nacl.css">
</head>
<body>
<div id="loading-message">Loading...</div>
<div id="body-container" hidden>
  <div id="header">
    <h1>About NaCl</h1>
  </div>
  <div id="naclInfoTemplate">
    <span jsselect="naclInfo">
      <span jscontent="key" class="key"></span>
      <span jscontent="value" class="value"></span>
      <br>
    </span>
  </div>
</div>
<script src="chrome://resources/js/promise_resolver.js"></script>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://nacl/about_nacl.js"></script>
<script src="chrome://nacl/strings.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
<script src="chrome://resources/js/util.js"></script>
</body>
</html>
/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.key {
  font-weight: bold;
  width: 200px;
}

.value {
  margin-left: 10px;
}
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

(function() {
/**
 * Takes the |moduleListData| input argument which represents data about
 * the currently available modules and populates the html jstemplate
 * with that data. It expects an object structure like the above.
 * @param {Object} moduleListData Information about available modules
 */
function renderTemplate(moduleListData) {
  // Process the template.
  const input = new JsEvalContext(moduleListData);
  const output = $('naclInfoTemplate');
  jstProcess(input, output);
}

/**
 * Asks the C++ NaClUIDOMHandler to get details about the NaCl and
 * re-populates the page with the data.
 */
function requestNaClInfo() {
  cr.sendWithPromise('requestNaClInfo').then((moduleListData) => {
    $('loading-message').hidden = 'hidden';
    $('body-container').hidden = '';
    renderTemplate(moduleListData);
  });
}

// Get data and have it displayed upon loading.
document.addEventListener('DOMContentLoaded', requestNaClInfo);

})();
<!doctype html>
<html id="t" dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>$i18n{title}</title>
    <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
    <style>/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

#anchor {
  display: none;
}

body {
  font-size: 84%;
  margin: 0;
  min-width: 45em;
  padding: 0.75em;
}

.global-button {
  margin: 1px 3px 0 3px;
}

h1,
h2 {
  margin: 0;
}

h1 {
  color: rgb(74, 142, 230);
  font-size: 110%;
  font-weight: bold;
  padding: 0;
}

h2 {
  color: rgb(58, 117, 189);
  display: inline-block;
  font-size: 110%;
  font-weight: normal;
  padding-inline-end: 1em;
  padding-inline-start: 0;
}

#header {
  background: rgb(82, 150, 222);
  background-size: 100%;
  border: 1px solid rgb(58, 117, 189);
  border-radius: 6px;
  color: white;
  margin-bottom: 0.75em;
  overflow: hidden;
  padding: 0.5em 0;
  position: relative;
  text-shadow: 0 0 2px black;
}

html[dir='rtl'] #header {
  padding: 0.6em 0 0.75em 1em;
}

#header h1 {
  color: white;
  display: inline;
}

div#header h1::before {
  /* grit doesn't flatten -webkit-mask, so define the properties separately
  * for now. */
  -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzAwMDAwMCI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMzguODYgMjUuOTVjLjA4LS42NC4xNC0xLjI5LjE0LTEuOTVzLS4wNi0xLjMxLS4xNC0xLjk1bDQuMjMtMy4zMWMuMzgtLjMuNDktLjg0LjI0LTEuMjhsLTQtNi45M2MtLjI1LS40My0uNzctLjYxLTEuMjItLjQzbC00Ljk4IDIuMDFjLTEuMDMtLjc5LTIuMTYtMS40Ni0zLjM4LTEuOTdMMjkgNC44NGMtLjA5LS40Ny0uNS0uODQtMS0uODRoLThjLS41IDAtLjkxLjM3LS45OS44NGwtLjc1IDUuM2MtMS4yMi41MS0yLjM1IDEuMTctMy4zOCAxLjk3TDkuOSAxMC4xYy0uNDUtLjE3LS45NyAwLTEuMjIuNDNsLTQgNi45M2MtLjI1LjQzLS4xNC45Ny4yNCAxLjI4bDQuMjIgMy4zMUM5LjA2IDIyLjY5IDkgMjMuMzQgOSAyNHMuMDYgMS4zMS4xNCAxLjk1bC00LjIyIDMuMzFjLS4zOC4zLS40OS44NC0uMjQgMS4yOGw0IDYuOTNjLjI1LjQzLjc3LjYxIDEuMjIuNDNsNC45OC0yLjAxYzEuMDMuNzkgMi4xNiAxLjQ2IDMuMzggMS45N2wuNzUgNS4zYy4wOC40Ny40OS44NC45OS44NGg4Yy41IDAgLjkxLS4zNy45OS0uODRsLjc1LTUuM2MxLjIyLS41MSAyLjM1LTEuMTcgMy4zOC0xLjk3bDQuOTggMi4wMWMuNDUuMTcuOTcgMCAxLjIyLS40M2w0LTYuOTNjLjI1LS40My4xNC0uOTctLjI0LTEuMjhsLTQuMjItMy4zMXpNMjQgMzFjLTMuODcgMC03LTMuMTMtNy03czMuMTMtNyA3LTcgNyAzLjEzIDcgNy0zLjEzIDctNyA3eiIvPgo8L3N2Zz4K);
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 24px;
  background-color: white;
  content: '';
  display: inline-block;
  height: 20px;
  vertical-align: middle;
  width: 37px;
}

#header p {
  color: white;
  display: inline;
  font-size: 84%;
  font-style: italic;
  padding-inline-start: 0.4em;
}

.list {
  border-collapse: collapse;
  font-size: 84%;
  line-height: 200%;
  width: 100%;
}

.list:not(.filtered) tr:nth-child(odd) td {
  background: rgb(239, 243, 255);
}

.list td {
  font-family: 'Courier New', monospace;
  line-height: 1.4em;
  padding: 0 0.5em;
  padding-top: 0.35em;
  vertical-align: top;
}

.list tr td:nth-last-child(1),
.list tr th:nth-last-child(1) {
  padding-inline-end: 1em;
}

.list:not(.filtered) .tab .name {
  padding-inline-start: 1.5em;
}

.list .name {
  width: 20%;
}

.list .button-cell {
  width: 7%;
}

.list .name div {
  height: 1.6em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.button-hidden {
  display: none;
}

.number-expanded,
.number-collapsed  {
  text-align: left;
  text-overflow: ellipsis;
  width: 80%;
}

html[dir='rtl'] .number-expanded,
html[dir='rtl'] .number-collapsed  {
  text-align: right;
}

tr > *:nth-child(1),
tr > *:nth-child(2) {
  border-inline-end: 1px solid rgb(181, 198, 222);
}

.name {
  background-position: 5em center;
  background-repeat: no-repeat;
}

.stat-value {
  text-overflow: ellipsis;
  white-space: pre-wrap;
}

html[dir='rtl'] #details .name {
  background-position-left: auto;
  background-position-right: 5em;
}

.number-collapsed .stat-value {
  display: none;
}

.number-expanded .stat-value {
  display: auto;
}
</style>
    <script src="chrome://resources/js/util.js"></script>
    <script src="chrome://resources/js/i18n_template_no_process.js"></script>
    <script src="chrome://resources/js/jstemplate_compiled.js"></script>
    <script>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Contents of lines that act as delimiters for multi-line values.
const DELIM_START = '---------- START ----------';
const DELIM_END = '---------- END ----------';

// Limit file size to 10 MiB to prevent hanging on accidental upload.
const MAX_FILE_SIZE = 10485760;

function getValueDivForButton(button) {
  return $(button.id.substr(0, button.id.length - 4));
}

function getButtonForValueDiv(valueDiv) {
  return $(valueDiv.id + '-btn');
}

function handleDragOver(e) {
  e.dataTransfer.dropEffect = 'copy';
  e.preventDefault();
}

function handleDrop(e) {
  const file = e.dataTransfer.files[0];
  if (file) {
    e.preventDefault();
    importLog(file);
  }
}

function showError(fileName) {
  $('status').textContent = loadTimeData.getStringF('parseError', fileName);
}

/**
 * Toggles whether an item is collapsed or expanded.
 */
function changeCollapsedStatus() {
  const valueDiv = getValueDivForButton(this);
  if (valueDiv.parentNode.className == 'number-collapsed') {
    valueDiv.parentNode.className = 'number-expanded';
    this.textContent = loadTimeData.getString('collapseBtn');
  } else {
    valueDiv.parentNode.className = 'number-collapsed';
    this.textContent = loadTimeData.getString('expandBtn');
  }
}

/**
 * Collapses all log items.
 */
function collapseAll() {
  const valueDivs = document.getElementsByClassName('stat-value');
  for (let i = 0; i < valueDivs.length; i++) {
    const button = getButtonForValueDiv(valueDivs[i]);
    if (button && button.className != 'button-hidden') {
      button.textContent = loadTimeData.getString('expandBtn');
      valueDivs[i].parentNode.className = 'number-collapsed';
    }
  }
}

/**
 * Expands all log items.
 */
function expandAll() {
  const valueDivs = document.getElementsByClassName('stat-value');
  for (let i = 0; i < valueDivs.length; i++) {
    const button = getButtonForValueDiv(valueDivs[i]);
    if (button && button.className != 'button-hidden') {
      button.textContent = loadTimeData.getString('collapseBtn');
      valueDivs[i].parentNode.className = 'number-expanded';
    }
  }
}

/**
 * Collapse only those log items with multi-line values.
 */
function collapseMultiLineStrings() {
  const valueDivs = document.getElementsByClassName('stat-value');
  const nameDivs = document.getElementsByClassName('stat-name');
  for (let i = 0; i < valueDivs.length; i++) {
    const button = getButtonForValueDiv(valueDivs[i]);
    button.onclick = changeCollapsedStatus;
    if (valueDivs[i].scrollHeight > (nameDivs[i].scrollHeight * 2)) {
      button.className = '';
      button.textContent = loadTimeData.getString('expandBtn');
      valueDivs[i].parentNode.className = 'number-collapsed';
    } else {
      button.className = 'button-hidden';
      valueDivs[i].parentNode.className = 'number';
    }
  }
}

/**
 * Read in a log asynchronously, calling parseSystemLog if successful.
 * @param {File} file The file to read.
 */
function importLog(file) {
  if (file && file.size <= MAX_FILE_SIZE) {
    const reader = new FileReader();
    reader.onload = function() {
      if (parseSystemLog(this.result)) {
        // Reset table title and status
        $('tableTitle').textContent =
            loadTimeData.getStringF('logFileTableTitle', file.name);
        $('status').textContent = '';
      } else {
        showError(file.name);
      }
    };
    reader.readAsText(file);
  } else if (file) {
    showError(file.name);
  }
}

/**
 * Convert text-based log into list of name-value pairs.
 * @param {string} text The raw text of a log.
 * @return {boolean} True if the log was parsed successfully.
 */
function parseSystemLog(text) {
  const details = [];
  const lines = text.split('\n');
  for (let i = 0, len = lines.length; i < len; i++) {
    // Skip empty lines.
    if (!lines[i]) {
      continue;
    }

    const delimiter = lines[i].indexOf('=');
    if (delimiter <= 0) {
      if (i == lines.length - 1) {
        break;
      }
      // If '=' is missing here, format is wrong.
      return false;
    }

    const name = lines[i].substring(0, delimiter);
    let value = '';
    // Set value if non-empty
    if (lines[i].length > delimiter + 1) {
      value = lines[i].substring(delimiter + 1);
    }

    // Delimiters are based on kMultilineIndicatorString, kMultilineStartString,
    // and kMultilineEndString in components/feedback/feedback_data.cc.
    // If these change, we should check for both the old and new versions.
    if (value == '<multiline>') {
      // Skip start delimiter.
      if (i == len - 1 || lines[++i].indexOf(DELIM_START) == -1) {
        return false;
      }

      ++i;
      value = '';
      // Append lines between start and end delimiters.
      while (i < len && lines[i] != DELIM_END) {
        value += lines[i++] + '\n';
      }

      // Remove trailing newline.
      if (value) {
        value = value.substr(0, value.length - 1);
      }
    }
    details.push({'statName': name, 'statValue': value});
  }

  const templateData = {'details': details};
  jstProcess(new JsEvalContext(templateData), $('t'));

  collapseMultiLineStrings();
  return true;
}

document.addEventListener('DOMContentLoaded', function() {
  jstProcess(loadTimeData.createJsEvalContext(), $('t'));

  $('collapseAll').onclick = collapseAll;
  $('expandAll').onclick = expandAll;

  const tp = $('t');
  tp.addEventListener('dragover', handleDragOver, false);
  tp.addEventListener('drop', handleDrop, false);

  collapseMultiLineStrings();
});
</script>
  </head>
  <body>
    <div id="header">
      <h1>$i18n{title}</h1>
      <p>$i18n{description}</p>
    </div>
    <div id="content">
      <h2 id="tableTitle">$i18n{tableTitle}</h2>
      <div id="anchor" jscontent="anchor"></div>
      <button id="expandAll" class="global-button">$i18n{expandAllBtn}</button>
      <button id="collapseAll" class="global-button">
        $i18n{collapseAllBtn}
      </button>
      <p id="status"></p>
      <table class="list" id="details">
        <tr jsselect="details">
          <td class="name">
            <div class="stat-name" jscontent="statName"></div>
          </td>
          <td class="button-cell">
            <button jsvalues="id:statName + '-value-btn'"
              class="expand-status"></button>
          </td>
          <td class="number">
            <div class="stat-value" jscontent="statValue"
              jsvalues="id:statName + '-value'"></div>
          </td>
        </tr>
      </table>
    </div>
  </body>
</html>
     Xmo6_qs1t+*InsYWl@R0tPFRa}GŒc{v6,5{G?KTlW%BnLfg##Z,7\iZ*༲fB4Ѡd|4*sFU:FU@_3uZb
|w}hJ $531aJ&%-"x[Hq9d ilT4f7,qnWp!-!`'\ސlю טb4&r;c&~б3GzY EG$K{b	&Ad6LYj3&$X<}J\K>-gex૯pK%K.0R֪b^:ѿY}P@`j|.(dUmz9"ccHuw	3JOݧg1+-v3x[{ߠd6>u9ER
iLM)0o7n2Ν~DjłĈU;Lw%!OҔ>ݟ"ⴍXɄֈmdX2QVuru֬&Ȍ`MwNrSX$TvZeY_]g<{o}/kl>K}yixkDB?Q %/zUCrm9Y,\k^Y.)fwsׂf~e^d~`|ݶl8ç (}J.;[LS=9>:l$8	7u0AhՊ^wه2qXzNNy6bpLUJ۞]o߄GhBWmHSwRt;QEJpzLgĔN_-9[@g.0:H;Eg:!hh(Jyz\
,.A8IHhh<6q>@..WWv(Fvcр离ȍzY)[r7*@sF Jf+M>KZ`{]۝+	h]ꦏItȃsGxӻ8N!`YFWRu}1KU>k;XMbqLPQ
MSwJU;G(lbJhXcO=$r"L8L|	֧QsyvvXEO!UGArc ;CGa,A4xݥ*IˡEOi[h/yuVOk,V86@;c*+R:J0g%u1z%yoCc(]sv̿6R[eD{1nv3X%AGe~/e_\f^[lf1xp1aT^ P<k>^4-eD^#;/7(wTTQP\Ю19e<'Bֺy˗ֶH~˪K-}_}ǎP!=Uk ~4I&r       SKo0WTBE-]D*R8xplv<OE5wT7^o`-{mikaӅ8R0 =8P.`*ys%Bi$F	E>}N}5B#BCQ2@_loBE
eF'V%q$[BˢfFx9,WvCp5i=1d0!6uMj]rPXo0uףwczN&#8myH&HrΩ]e\g9;$iLJ[boȄ~HV	ap}ZO}WSWa\PTt7/Hԝ֢;,CvNώ&yg4Z
?;Sxc>Ǝqrϧb%
Tvf&
ſ[=H.ŏ<n:G       kS;BT<z>'81>Eig;2͌9ӭHX֤r> uZּxArUy&({?ˌ^/Q-3QV19s +Rw,^ _*FČȌWu0s.XYLWWr3&3*IB2eHi&"%uFNO/NȌ,J8e3^QDUU4!H$hL~"$r%K`l2DڰGUxV*reNu/d|B/opVԋ* `+I~?Tr{N%cGVd~Mv'zlz۝=sZpKMߘ}iv/3)+f3jL[͓w"_iOd]|w-w?CECcXLa~z4&{XL¿reG﨤OoY	.=)5h~,E\Fpy
⯕(Ђi^1bE:*<7k|FFj]RYWu"Mr1WpKXR7$Tv<^ҲbC[5.> O<"dT]L$Z9:U0R;dDqRԒ@4=t %mw(Z$۲ce)Q-Ľi1G]%(%yΎXl;!:B;)Q`<	P?>V3;lb"0v^);DƖ/
3E#V<NylN
Q0#ӆzeyBOucc-Iu]-P%V F~	!|wJɴ(A5-(TZ
Q><7ro̐JG%%RL.@$LRȺHyL"J)Rs2p:}hbƠc.G~4ڻ>pKj)CA
oj~quK`7PhP^toY˩!EĿ釉r"϶'{S1a_x%97rM QC0|<Ezv*Y-wel ~(	Ł?*K|؏EpTuV`*MdhEBKSQk@4 #isVe+;;4AA^FޡŚsº-̚ŀyh` ւ. (O"9́?)q :ô'Kz!Pci	hs:?ڽVr1\wh rr:GxV0(
sm5:/}NhZWnN*Z\$	C='/0{}zipj!3RZT0MT4>7&s3
 >5[,:Y܏`˕[)[cCPm<\kפKy"C<ŗ;6F<.<EuGZSp7Revexet9GeK~|+15/xi1)YU	])2hF8lܠCkWb~pd\iwF,׍lZc6VܘA#mL+N??x:%==FV-i܆nqO垓Z,pv|'sH]oUU5l@TD.Y
I	@V"A7_Fb 	6z(Krb'DuM 9){ֲWҲW# b*WD'=2[ÁW'­»Q3SyH/Q`A	"}@*--Hۖ#:Pb>A_miwU5!{4PQU=4݉u~/vN|Yʯ80xm4BZw_:еԷ#NLoz\}6?XE*"e0aue`@nvoI${κ<aXGP:<lt.1S^Q`;7*ԑt.1'ݒӽ=6d>
]D3wh.7BS3. W5FFaOJphLCte0,y&MbWNd>_@I_Ӏ;FIΓ[)83D3q{1n}΢7?=x3
s*E	/ceWxaO D? !l(:7%epȾFwGYP"J{8YX=Dn-Vq92U>gjcge{=:KC|̢º-Y<mX
×).\7ͽ9U5[F6=<fҫFyѳwm|olQ&	̗O v
:+f1!"p[xro"n?qiH8Cj(օlzE[zǼ+cM>:Y1QRbg^)gQ];-}^EngoX-DЯ	?ELRq~`=+7,CAs&}1=h>vm5@8i}ҙu~6lQWHw6T}u`&ˌD_"L'k֥lwwwCpBS^wgJn6~:UN0r^?_2kR[ĻJH/(2zǈ~MfJaAЛNw&6׳OF7?92iqYzJN¯-;!-KO	}E@/7ƐaFgtQJdVgю	h}xp^-L}hy& O2.       ]OH_+d3yC#m&df"wiC9ہaG߯4;`wWWl=qǩzM1O{f,f㪨g6r]<a]=8>F.FySEpm#~u4zA4<뽘[͛jkaBib/,\Ep5ab@Y@ssVos.m}aCed.gT%fqpz~ۖ?]coI1Aڷ-bwaz#ŇXZpDjEM{w>{W9t#3ܻ!gB(yΊ(e  {qus{i]WU!BT77׷ 7Pg^_}>\\=/AR|	w	}̶޿ƧgU>!%!v]ön%alj DI5Gnjn%߄,B9g;w_U&ӎ[ȉ{;1x-QĝM4KoK!Ȟ{yb;Ɠa=jbNԣ\S~>in9c^ ?~FIFt
*ȭP8@%ZřDK7B}^>#~Btp,`PЄ"02xC_Q&eRMUkƘc`T-Ȱtf%k(KsN
Ӏdi= 	n~]l\z^ou:kEL?\n|qwUTi	: g˂i4NOv<C
_)j&~;02z\HeyٳMN<5S1ƠHQdt!vhPpɨr]G8rNHKYHMd࿢X8Mse̊CXMd 7|)؞#|;ڋ;(#rT2P0&)8,q	n$瑄g='3pa9AΔ&ygdFFfO:;׼fM(m0t,7Rk[Wo!`2v.3nC0LWЌ0Έ|3xAQGji	~xAn01X#Tq J[" 
7I4!$uꮄvaD"R#֓fl@7`߲5d-f#в=3^jB}my6)VIt?8<"GQzuEdےbr$63t]][81d~%l+6X83HŉcA6jWdaf34*K6O@&}l08tHA2q>l>F|R)*cn0*s0E+$Lh}
1 m?HۼH %$
0|*)k7Qh&|$!iߴ]Da-tшo|@5ƛܥe{E\;#7Y8oD˄-jL>q2=h$hKd$81@?d 25ȶMYKtG&1P̘@Ώ/г$4ᙉ&yhYgD܏AYvHlg [so97R3*-6`l`}g'csRfsZV^Ocwgd'-hZ]kՊRH-gd kbP5NfQN|ڣoؚ5sNegc!*FVk6Ce e-L3{B̯/6ZUkwNZ1dq&J&269stR~4X߫XD[U]AYe>߼2or NFIxy}j05$K"s&mf;㏐w~$m/WJ*KtmMˤB9	d:H5v"O)JS[8D3TdR{|,tUUVM0JW}˛.`Y)c-T#/o#p_ͱz{- 86hd{D{n&A`WNFu!6l9BqJSc	@DQ9tv!
yzR$%`с9Ҕf~Z
W' {ABip$Dlq+	,@ fOC9ۍzꖓlI[VY4NIA7-C3	3*%Ip\¤-9"Uv0x뫄ߌئz+1~˵2fՑjas]8lE8]UʪWE(]ek*m$RWܖ6HX}=V<˔#Czy;ʐ_ddRΫl-OKRBWJ \<3HJ.:-[=I/NYT:IPZjJG$uDV.O~ex/tu;CV
t}ISuOS\
"{!98h0#BǿdDl\픗OǗ4:\u-[Yg+RRv:'9\U껟Cqd++iƋ-ۯ̢(yR>gXqqMpC.H`>`Ƃ2p='exfb8[d'(w[4vL4ਹ[@6Gg<7&Ԣ.gd?Tvu+8DJNNm_PV5ڎV|Bi\]Mʦ')aokak\V`]fW*#P]D轣՛&%%FKӟ973:zf%%UMfՕfݓ؅Z^5ȘWqJg_՘Ev4ިyRM(=J+mneMEqkHOqA"a"~ʭLUۯ;uBQѩpD_o(TP(eR*MJHٍ       ksHŤ*U9`|\-G{W[@Ѯ8C37zAؖ{PK_miaj@F/5B7A&xƲpvu#}̅B.c>а$aܨkf.$$M14ךc :ag5Pff,?uAL/Q*>/M56u\jY`gWޝw藙}ӛg]ϫ 76@;zy~#nrlUbf@1 _3*>ƣɠ3?$$iĊ1?N@ݶj2bql6ǣϝ'CS~16Zcۨmxw#TX=ĖZ'胁7ǿ9k*L:>DY*WCoTH\_nQQN4Í$sG'4U3k치pjup=p. (}lL)LzG4B$/L#'x޵B~@8>QPN""Mq4d~7sDu|™|썻)(L$o}nQg !%]cuڝak GA5"9KZ*!cy!=9Di²3SXbjg`kLhn!Bq%# 4Y[`)1X43S7lP "bU``}wgV~Q+/wλHs\Zm- oH\>l2'Q"bʳdbӟzE 82~%PǊ.$\&w@k<]ntA}P~fu- 	uMluҭm?me&	,s<*4Er&8#&Dz}e9[^cSEoX^`,nb*ad2*spB&[;Rokڥs-Iۡ>S'[G[3T6VҀ\wD$\ߖm@!$ @\AT]C	>V$Y@{}]UcIRn-XY]ypUOКABP̈^VUQK♴ML>
ޅh	ȃ	~v,b\/k굛u.QكH,FF]z.lh <S!3PLl![WrF(!1
Zr(To*]a(S. ʎD{$rW-ٻ~Vܖku&SVv͗=GMG{ȃz<oRwl=?Eq*[sA
Ӎ@kԐΆe@cgLhmG\7ؾW+ejFΤA@k@bweDwؐX3 [lKKsI,Q6Qg"DozuS2:oF˚x~A<;`.w4Ix&5}+@1q[44m=%8mܟb4]8-bc+.v}7Zb/p7	X-`m*:?`(첉<a@Ut~tyQT^~Кj$n$s)@-qg#	~L*>u!pA̴'nȄhj/PTsaI.
Zq!\tم(lg+sR.բ4+Qi(T6[>[ҳ%-ԚYv"rbJA6m%cmbQi:rĘT6^vMnae/|+
t}Smc<JYa]VE6a
{'*`r|rz c.Ue}E;:Da7f4qL(=]9 'h
=i,֧EٴRT:4l_2w5Lp,nv2[2%?yN8ؤ8CnCp/yVtl9gfa.W CfM7'xj%Sn*5T$2^?j+E4ʟz%h0M*a_F=úb%5CTUDW(Kxbf悚8-ifAQ`TwK		L2DД	l+S4@Q`8 ty@s5P*놭U"#MܽVIzO4;EL'bBH_
؂Ք$ S(h*- WsVER
'E"{4{]{s%ԠY]wláՐV+l?[idnVfA߷ۼ']ݚjym*.g8ش 2S"i(|X,
[1y+UeH;*?ԝx|3Bt3Pא3nĔ<׬X~$G;g*wCJ3 jf#9}@.HS~$uGP%M9)SP1Y֮N*m,?O`R?=7
ߟez{]rq@BIxIӰ;afō,q^3N?hAMڀ뚙`wr-+l~xY)8u_	eonTjz§ʡ].Qxo2{5wIq( ˅|dÏBcR,TAaCQKSH& j)2oq|Q#:h)	poGTP9n_YRtl>{>ZJ`i~X[=8#%565uS?C=}{~6Y>PӟI.أ?lӵϮ2c
G}<A|8K_4ۯܙ(<]Jt:.Wޯ}CDziU&&x=x^EѲE66|rTʄtp       mMO1+^'1p2c`KJK)]#ΡwiIXM0*
q1%"KK+p),v&' pdH8_[>H9)eS*J;U@('<OG+!)B喍9mFB26<Ӆ3鈵2T۰SwAE"r,xm(SkM_r9!#Zw#|Ƭ/|9hOٗ9sF7-nuZXa>OdnDv~~ BU<GT'QN3Qir?ɶC       YYo8~ϯ ,`7,ErL`@k'$TϠv'"u~uy*`\eߐ@rQY'?*/OId@'[r&,kI~ܕ/ 
Hr c Ձ,*҂$)m˺+po>}Od8{..6, Ȩx*TKf݂,hn19^^2ܜmH\Pe2nTؐrITAkjCVw՛}ۺHNX$1W-Hx8nFXF5[.	\P,C4%"(`Lx%셊y2Gͽ'HoR|՞/.2;3 s;rDX{}dfrAoh97[BVlKP H"ITY2/_9j@(sa9BUvЯ힄;])@`Cjgax~lV^
}1Ek˗цGN@Z~&m\Yk5;44LsH12F955/))/;P8[E&z1t0q__ذԡ-]ZV, %s&+ᾛAhJ%+@䑺S=-a)ؓ0E𸹒r+S0čLbܢ7zx79?H|O1Yqzؐ-#^7VJz+H9O1y<;,wTDIy|2R}/u75IdYA1M%M=LMum+u %9yHǏL`_Vu(`lEBu!=dt
ٞ5ȆPٱ&.3gZgGsR}
MvGI=:M";)A4`Pd(ҸS'dƠwR=lϧ.k&[^š*&7RhӅFU) G=J/ .6d8w)(COqF=ubC
YQ?`UoGw\i
ۨ&+O}><tT]2}U?zUaG9$ ՟U=pK}`@k4{~|W^Iz$Kgzxܳ ۾-ݦr#Cꍭ!Y=1?Y|5O-D4G?6WV?ö,{$Sm~"cu[tmt&\OT`cNT9e$@5@C.no8&!&nf7mM-wɌz<®Y?r;qor9HyQnb+2Dguӿ̄U\h64_:Su=j/ރGhd0\SYoю8VY'K4\dp}E;x?A׼Da־"J"4Nsj)RCӴǒ&zT&_]s]o	ME6үA^)(H>jQdjc}+ jܢPj/,ڋ&tFJYF8M;?K܂Ő^se3>qd҅@+/͇	_/JX&5=Br1|vAԴ5Iy<N)KԽNW4YBu|;= @HT?TM䨣CXLP7Ќ1oqnhSp]U R*atS(>&Mߕw]u'ww^ܽу7i?fHfXmģGiz^7@۟zAnP)r&_n_(ПN6vc,V2Zπ8ujBhۖu+3*"迓/x&LҬf-bN'lLt2/F'sM)}<PKgM7w>?[:#|4Y2K3R]~k09)]S^XW9rOv6zЪ` x5~<qbS<(-NU^c       Xo6~_qy\f/E<tI`0DjeR#)'^}w$%@!ȻwwI0Fe7K?k^r-\e
NKJp`4(Z4As0LJ8$2倯7r͕)7lvRM!.P,	sH!8d4a<t/^tL'*+J+8MYa:S3WP0y^r#Y~RN/2.s>έ1,JL Doͦ x%?U\)yْe5AFӶ}L'͌kv]L=f
%[q$&=ɒk.k2qc1qfOlx' G9w\_]5q\gk'
cǷIδuSɒ	\RsMZcf[S幼Es45F.9JIgd,B63a\g).밳$ĒשiI".\⬕a&ܺu˒p'Lmܒ>٪<X
.A3\$sܰ(*0FO*#Uz`rQo_oŬ#Q[xԡ!uxp:4l֎řqێ;rםgVDLȏQ\nX*eu?hWl!fAs7O۶?@kC8\OVSͱYp>bmCCq=?ў)9fڞ{N)vɍOBr( (=)_a}-IӾ3=(xwz}M'h'ã3Y v$%ԫMLӊR	dGio<vn6fwv!Q}ıwF1>}kVZxa4f}}y~%j^ UW~7)/rVr%ם5TnJT'`[v^#Sotb<ǧDh@oNNN&moiXZ	[@6Lp谳~︱I3)r7%jܞ}l	TG?Lܾ4UZ!Smٶ(37'hޔ|S=mvG2>8i؝X|-(Sxܷ4^i8l-obm|{@f)vt17V>v~x-j,Y7X.lUݓJr-xߺ˴
?ā7[.5.C]_4-}V>iRHeK*;DRsJQ=2xb%*Ŵ-R|Q*GqoD>U1^|ٺw)<]
.0* ]	nf!*qfl=(01+cרcѠECLG?<Tp6       U]o0}WIVl{DUԩt{B&!ﻶZ*M{!~c$0VVUa˧_@ZEQmQYw2Ѡ`zI?QNR!v6%fd`D(El-\RjdGOoSEKNO{p
TʒQ+zW؇PT8|&ɲ*e)yiFHIja.$8>LP2> 冋TIc)6\K@`.K({ͦ? 2B4
Sҧ)\!-ª'>fV=&ue2M:WB:;ߚ?i[>bj	,9pNUɷ3[r4ʆ++uZ(3Gn	u%P򲌝JMTGek=m4k~A("wV6{ gZUv7Z0^U4q!,>}PƜ4Q\Z?5>hK+nN gZ?8Jz{5FNR%6mZ46V>j)tǖBi:P*
mb0FNn4 QAkeU+_4oc.*?_Vj:y&"_8_<_ނ?ӻ{=f?ۦ{{S}]i.?QwiMÃ?ྣ<o+       ks{~/5v:әdreۥ͒t:aƦ HmI~A| ,KCwǄl8?
w$޲F{ԅQJ!)M4p/CxJ)kB%>$@b|cH!d>oD:G)O&,.@R?a;	JIs3  2a	b=p
1\1#C~t"s|3>9^] G($Qp	-- =sZDV!-${80F'!TOl
BX;uXbB>&&T.3[~ct)lW0><x|ٛ>MO	 |r{'5%fbHwKthb$Iʑ)D850NW!JYLs6s5c@j,9[qp&Q'xaO#./e/ƞ$"H.U+Q8`7QC&]1~@BLJ(p>>aLVŰfSF~rܡʺ0;`m8gB+s(\Tл&bZӀS鮥E&uQ~>w3j2R 	rY"Pf-tqD%l8;ЌPx 20_:SB;b\J
AFK,${ǉ!+n1fki=13t)|NoE䒼4Tt%{`8($TXT^F瀮'Ǟ(2\|H5L,m7%ytzgi}a!1pJtqtr&oˆE(]L%y0VzLZd2@}ohFb+#:.tH/aUIs]}6CBIt]	yN_^wYn
 ?9V{xP3D[ѫiXN&	-u8I˂A1ct;%H1C,ZfFKBsVPZ`|[M*E=Eʪia\p}?Fe~:Nd40:L͚My>]NқOut}"17^;gvvOgݨ¿>Tl)o3*/,uy&-'1/7f}OG'^*v{?zmu2I^MfwϏhZ?\MZw3<]bk·Z>Þ'qS<ev8hsyhnTKFʞ,:Wv{%Չ6[}[gl|`k˅MGFr$ggQ|ih0rSknI`]L_"Z!6&K~[[l:ɺ؞SX	u8߂cND?"$`Q}u
#2d:raak2ՏQQs+JiipKMc!7icQ  ۼjJ"'ZknDߐLRgF5{ϣ^=qTlfeSmQtW$#>?9 Lpc23 ܿe9a榦T5*{'_qf	y-fo!wR{<XQҔBvβZ *PUS)`a+"s~B.Os/hEf$mD.ޭpվĭjbX[hMmry/GT|j's9Β+k/\d5ەK98ۍԴ>ă^Ls~y_	;la֝Vת`q.k5~kRle:qތ㐒6i*y'Ȏٰ~k'Tbk9S Opҧ=mEI*@ls" PzLUҪj=@ѿ8o#kºvʄ
@:LwC@ 
!0]C礐;^?مu+e!K~z󂮸	L_[4LkuxcbPDt](D׺=5jK:10Y1qVIKZe<æqԩgQWUl}
^i](	5rMODMgH,7D)Y*Q	M}M*օ8,vP#7
=crH6˗w2?JΜX}aH%dK74lt31fl 2b_k
q'       ]o6ݿ$;sm0 Afeh"I`EHIdɱ$Fp-~_q.jBps4d@#Z$7'#@ΥV:D .ZL$0 OݤR[ySAfj% 3j|0LF''=8?X˥Eh/~/+CE""I>q6MӕJ,rS3b5b1GIIu"hU[  ?x8kԚoP)\ [IV>oE?/Q>MDguC"^%D@20OVx,ErԏZ-BgZ`˛lDAW ]rsnE D7ЭJ&DS~-X 
HRsDe7Ʊ\J7S"Trk-zWa[b!2[ʺr!\BL;vBDU*XЫO%|ޔNZ:-$uI`ƗIP!M~qcСe\Bg+םuPpls h50w.E.`ז(p&4U	rܡ-!%Z`''z*INpѐ<E'[#4	t2q*P*IT1V Bͽ\gcja-Jg9mn	eR~X;	R\Zs9#&W.?1x#)|*2İ-]-ox9k.Pfqʍ!Oj;%FOhi7>L
^ٝ[僰mb~:Uɠ٢\{]RITy|YqkL&VbH[@n;,9mJ_וBwՐYxRgnY!H\ub>4#6	a2{u躪Q<@5%ZYyH;:K?O~
DO+
\؇1F\GBp?Wds]l7;-^｛k\IM%߇D3g.d/>t*lKj uyʵ\o%DjY*@jJ.
FSuɇ<oLۧmw)@<Y}/nJwg߶CN1a=tM'[6b0.Fm7_{AthmYj=&y:#u-Sޫ4=?B>&2U*<̽PoЌFtg<\n>níwHv>VLp˃9I9YG~`B
A1?64'q@ NH |q['<KMrOK}R;m
fܔkWb3GqZΏxFDU&*/#azywC_ш,{=Qo|+f+rѰ-y[rhL{2h}@c9YLE=wGuzTBdz?dOVrB+dl*3_W{8@Xvx()rK;(56W "A[;*(xAI~ zx/w5[>pRt/>7?N 7;jJN_g^ca^-?^?       UQo0~ϯ>5T42])ESvT<B;ZcBPw}Y1dT|g\90L.`XP'iPQ-08Af`rAJ%Ls&0]smBTfrf ah2Y8hy/0
,3L' _S%cQq<-*4RCtXb=))j/OH`IZ]OKRLќ,m?,%Df(Vi*/+.eP/
r5Ej5"i>X]X 9Cq`T<Q]vc%#+/Qtշa{NEs[ΣVɓ]ǲ75Sͤ{W A3.0<ݳY%jqx_=?RVmdҖ<NaҔ3*vxVv|V*v	Hvjh{Y'%a;'	mfc{`ڏŎU*ieUAO.)bsX97%
M򦮊!3./F Nʷ /F34/]+RM ?O[j-TDީ	$++-]m=*ҳvn	?+9lx~w>.I1.X)"|EA:tj7u}3n~^	3I-wݡ0y۾a{\ro/<>hc6OcEm܀       VKs8WI)aNdg3[ʤxzYN3ө } $_}si䚗k,M.()iPQm1$ `rARJnQ	`NOQə	XȀ#{=fQDp-өC
pK(05\1`I[}6$ɢ(HiS.
ĤDQ\(s>pcx \0@gS)Wm)[2+VQ&c;)iNto;.Z,%RaOCmB*W+{7YUd	nAy	z>DV鋕TQ#GJqlPd.b+f\(jʑ#;益TdE`%'pգ,(M iĊvڨ2556L1郋뇦!qKş0Ww`5!ؒ}Ա8uU٦`==0,_BH`C㣓=>N;o,Ƒ6yA剛̤9a,h&y\C\a9qK0 %56:yd9a(V&'OޓFN\?|	>pqQOQhJ%J롊&ʢJYʕj\6?Oћ$RU~nՃۭpfbki'8+&e,<vin<.sҚ[]n4ZǬ[NN#b2.^_;t^P]7ZeVhik54 6]wLmدB
;g@WYtJ֥68Rxl%쥠/w4lh8 &.uZ>| Ui0?ʦ@V[xIUoi?N[T AcG!LR55aʵMg?'ӛ,!4ffp%{pp_mk`B]斞÷3oprU*Yo0ݗb2*	ƴ       Xo7_1])Pm_릎.R'$PfE$Wr?swyWp8f0?~ÿ~`Qrˋ-\f#&p4(ڳf3]3k0ABR1rϔ`@6AS&P)bZ".p<gd4|9+S*3H3#}`2w9=h(AOjYe,q٣V`&%(ɖ
\ ;):XVyfhe15fxfgQH\qeYVd
BK1 B RhaO_ 2*8~s+b7{,M?t$Î#G >*c ack&Va'K[lL
HY2 	fC/o/^0pAr[Y֫quQcR2wyB K֜)j5Ah+bqSX+@I5əx0KKʪ!5-c3Ͷ6q0ҳB0.O@YԖEjt\NɹVID˽\*۝R0a<x9n5dϠH uz.Uʎ*ϸx\QHO%{߆L~=V\:z7y6O]-b5;aw
M*bTW^v{.<'NjW.חJOmA{MΕv.@ys)GFbb'Xq|-o1G3C!iG0do6e|Il/y li͝D^(>up|⢐RI齾u[[V2t\,noW:}yG1^k	gLC8en,?ʴ*DWmQ%{L``RL;Gl9^bvŪzOGmN')ieHm\ߺjҍ;f8/[;Wlb!E+Qn$6<N\G#T`ӤuZ6q[5g_{bh;4\IٚrZ52RWJp@zև_øB,"R3=G1.C̞۬ps]	yul'ң>>a^ qOdg%#譛{뚋ꃰA}PuXiX,5-*8Jj$$4;ɞñ\ښoz}6eJI~,fQG2Mmmڪ\%S,5SL`hn{:ŶMS_mcͽie}!SY6Doc*mO-q ,4iM뻻wSHQdڈ=!欍 yҺB.Uõn1k՝/mb(xHfЃkߝs}]$u٘:(9vl6/>Big\WӉx̸5Ш,NJ&6TC뫯&A(嚵TViؾ'-o_5$(HGh8s#@/xG!:3J~|yO=q}O}#5Y/,A,9u 
~n"ţgVec=hu|z-5k*t#\.j{bNyE35f	% :&:`Fhn6]B4 'xFAR~Yx4\p79Y-8vf=BJ6H~4_:찞؋2ƝXrf-Uנrh̺M}&0&P~wӛ.T_IMV%5\oS&F^Aϑ=6piQOW#,yuY5Qr~Z0E[~M1eKm3\VBA1 <=Aҏ4,Zhegs]
G?e       Ys6_)Dǃ7q;[d<$@[২N<$"]a,ߟ\m7Rly\oT'	")&XCV
+P"Hs-LYc	X&),qZ<b:X͛w$4RKUDX`CD7`pL7<ըOă^$x|/6xyXiH>< B	ח9d'qӗ|>w|>c>^wnƟgjy__!؍HOڝosq͂pv 
B풉45;8m,+Ǔ<UD	3\[>Nr`>F"UZҭ4#m0F$lBv`p$9/ҲA>f߅s)ÇUlp;+{NI$1P2XD9)m&fǚm{ />$,zr3 DPv7j2)+i0kpUԃ^Ռ	 C%цQKN~Q""~0aa̤51PN2;'?3>ҩQ)|$Q\.aUE´r' daVnsBҀ\|`2,2ܢz.Hsl-Y}?jD <b&5X]GQ[i]r%IS`,4k%ex<}Z_f~	WS&Yksg\g	QrXtse+'e؆SI5<ť>3]WSJ-坁9{ͨBRXuT+l)\~pA]V;{Nk~rގ_~hbUتj~)ڔQSE>O{v$bEզM^Ь'do5
&*VƹbkNUǲ-%er9f:ɨFY$FLH*>;k׊E2r{Qad! .^y=]Nnum:g:1'Pz2k|{'siWr3[ZsͬH4~'}XBf:VU!]"*=cQ˲GpH[L?ʲdd~5w O)m#^E{m4
"YX%<.KQ2#GS}{w޾'-ԍ'ytŹp/xY\WԳbF~#i\iN{ͼ_Gq92^ 2ȏ!@i)-0)E9)	B%^ӳj@$CBLp^h}LR@c;1"/ϥYEJJa<үdSS'bzfvm'^OumuEb;W@p0]dOIxرKU1+D4ESzPn^@C"\%fE[5Z3 Dh^-vdŲ|>׮V]=viLTF/Z5%Eazy]u<X9w05xE=>SHccECec-m0H]sx#*_z{wSZ5Ibsp~RK'Ŭ8Y`	Nϱ^Y2eRd5,C Ew{M'nʟYSAF-=ZSLF&S&S(YBl{t(>m7d;	?IXjՆ_NHn:1!Tb6:1M%K ^E#fADUd=PAm*S;pɒt5{I\oZ{S?99J       UMo8WLу.ЃIHM:ՠŭL$嬑C4AoYSlXU^xn+iZk8omap^h47X$APK0`TBRKȷ|vbFE`
.!GiZYdGx9_RȒ$;>N>7%o3P(sW1D
N,[JDHKym2F^YGi-a
%GGp %8+4p<7@ZO.驙[8MB$qmk|F.-,Gzm=ݦs0x^ Mؿo?^^`nƯ;8	5Rr!UB^jQ/ntGo4pc]l:}eZ'
^#icCuIgkg=roK<]y$E֙ج_nsLgbxPJ0[z;(;ɭLf,/6(GaH7$@AЭw-i-*crƪuN6_ez߱\ȐZ0v"F+}-޶XL85id}MT;)\t*S?5pӽaAsFe=lzCtLj?V!ҥ\ݠyA/) ]+U#'=t\ү<? \ #P?̝fGvn>sCoxxT8%f=>ii\Mii!甂kI\#z$/hZ"1+hmT?woF5ͿIKmelț?m9=^; nzJ	       WMo7WLNk7ml#:9r%J-$Wg,K7UB-_;|V;Qྲ&{)hP'4/AmQ2VQa} $fsf!cEڨ 
ZGXL&/g&Ӣdadgk@{Kw7( 9~xkYUsQXBˤIJ'L'7+Ia7
U̮y@}
BqiDܝ5s(;nn0߃;i˙*J9/lسjhk!M*4ʬqQ(nSzwynIbzYmR+DrXjuCp(0SYbĝOI!9rʚGƲ<zdɛJrƫKB}dǸ<Ký\w$d8n	㼭C9w(]Zk-pV)Je7r?o#勎d'ԫUJJ֢3vʒȅAqĸ<ngxEP&%Nu6	*SRR*f;x^+%Ƽ#:͏qB$VۓF}Hb6F=eyyazrT)6:@g0m~j]^#z̺<ZJ5+u.䤶M2t׏iw=|Bc/5s[ێC|v/:sw@i
4q6m#~$R4n@N}>qg=DXUV՚1kUUW)Ioޥ) zWQlgS	mDt="D?#f޹n[v&':i/2iv;jލGiI_cMX|79ržU^	,AhReQ?VӴ*{D7qjD1& xnZ uR	Rj'.]1buW-ѾǻfgV4ۦgX"Y0g	oT͠n}iU#0+Ta;=nFD*u,G#͹ۻx;xSׇ?n~Gjzȹ       kSH;b֩]˖_lMHj$=\`߯!Y%	p.bkӣ=mt59\v]{F`g7@7W];y~}!s@!v:	vq?|fVI푒EÀ  <Rh@9Ş`ErRd8y1a]4Q=vTSȣwRc|l7
}o6#8	kΉӀRb$Zѐh.>q	
4i0qz@e$zvv3#(!Rr = x  k0:rI0@.48AͨG:͝~E XDҰC/([^Zun{G)(ʀ[:zVKVWϰ):刏aNaNàԌ7wTujwN}Lc³cچE^(v:2먱hnJX ˭ň$g, }`zb\.,={GY97us3@#\cRS؇)Mڒ ut7{AYhW]dŜAᓁ=$.H)a[f#`W
<d椏u0}d?}w.Y/&L{>^vu&ޣۏӧm:p;gW/cӾ/ghu0v:OS7F&Ǘrǐ;>\9܌瓇Icg<tϗkN@;g
y` 춮>?=O%*ih<cxz ߧ{<x3y?ݎ`&7-xIzczPMdz=:3}f0['maH@D)	Slw1mjhͶKe6caK{9{cj8yIonBYZh`ˬ^J.o>Kk`=&`018l*yo<ra~WH/_p~rlA*oZC)/DN@1 %iU"~ y(dHEa`G(/؊6>(<%ʉVDՉ\y gU .@&0cO>R?ݤGLh>ŐC>yDjOzM4%(V'Z7{.!9l@OR^/%4y0;F!],=6q'ҕEȥCjz)VYmwL=\].u/[4|P̸_PI]@_1fCV4-}SrՑ$o8#0
B;G>~N8yO-[b1oEzJX ߬`6ʳH!|9e0,]#Ñ	(Z5W7tSϖ)c0t!Xͨ*gup.RTyS^i(.QS"M\IrSj">,;ܾ;| 6,TD-*k'ϟ.擇susʧ_K:/v<69Zjkqr5sƕT(MY}̙MfYr3,˅bC@2VSQ&`"{K$*_ 	!mzF~:ԽoB2 12jQv2z),ӔnRŢCYK]%8'j͂)Pz&#hB+}L_y7^|[2[pH[pIPjR賬ʖQ8aI@}D*n/ϯ%X:̌" pFJe;"b٫ʖӜ)Po@6GNu$ͽ}N2"TH1G8r5e7P4{{ILU!`6+puC/V
٩ŏģh  6msq
δdwOl*ɸcrduMɫe¬ 0B/DѦVﺿ*XҔF_Cޤ[O~9v6.RBo<pfZ# ac/Cdl[J%fB2VN
E	yC fPJFΩ,YrE8g3y$wC%L@VV-,u<vWRiBiu`C;mɜ"NumsvFOݬ~WU7^Ɨ$^{N:QFzsIx2,/T+#,l۔=k<}'QQ+P1m]1Ј$zx;j,D$jnpXƌTžZ%ͬ)+P}}}d>?<Ǭ-}9i	T{3IkĒަpGzu7Xlۄl}^D~Q Y굕c"ۂb fC(6-&Kii"uQ9e#c,kdni+akƁӟ(JE_v6/"Uf[;ݤ03=;S"B7"TRiqԸ!,I{v5kz`/&rQɵň$'FV7eW,!t+nd` xv\k3ym+mh09ncv/P_TxCZC_َ5c:|yx
ZN8Nyw~g;}z L0z5U8Smޯk ˺_ADtD8IT{_A14ՠ|#N"٥8EQ/3pN6p!QE*qL@58vVrM^N7Ίm٭@U.Kf`γ8uՋ[ '2EAuA=}yrrḩ^9/+JnI--0jH n6ɥU-ADVD0R|#/
`nKT+_u.'*>|^>A~"+3xoKX	Zͯ8P\]㩾ȕ

Spsb-oS&Smo'fP4xc@!l&EF2,[9it=Ĝ+T+B"ee	}f쭄J` R"DаsBvhf$C~1i(POY͂>e:M:Sx>nr;x?6CGQu֩.WѧfG9wf4cH(?AYx*_ ;H'!ZN񺩥?2tU8敖qnyVLE<,gc"tL~+*^.&:Z(%P@.3       Zs_DU>7'ۍ;c9͍"!	1E0(z]|$2m K v_bLDb_o~d/VPKː%	ѓ$əd`<&JFĜ%D"D\5SنPaz~,&a$KL-"MɌ!(Ҙx5^9OX8߽wtMeL̒)!
jAÿUb'qIu\RC5_2!{Ť"Oj14Y.Y-XӜPH>H).\Lʁ*Hé_% ØyʂaՆ#2/RppDD"
jUl2zwΙ<Alּ]jv_h
0Kì)@-ЍGuP8fOd>i m:FG!^xZ 賨#YIfJ.V9fʤosesl<c+DhVOOJd@=f>nfrQ;@.XL ESCՒp0͋H܎/$_wSj2'<(:­ݟfPB0]JÃ{x8!]UoKsRQ<<	yi,DDTޒ%,9nHBp{=qkZ5xeL(DN'zUd4+7npiqz^D,bRBh`Ty0:֓GM a@C=Z*c+VvWK*Zvwgǐ,s*RD7ӄ+|	* ),2%W`	U0xxB%>'OdBKButY?`E?"C	&V`*nia$MNv?_Cb,ynU(Rt&ⱦQD%t*OehQk$3;t|qCqei>JW	XRtX2{CUB`#.zd*b("ukEx[!}{UZ5Ks%,(|~w*x,*Bъk[.œ掹Sg.r5'԰Ҿѡ#V9=!B[G$&DZX;	'hKbU`ضoZI\mK-aTF6cT(rUڦB @tYDqWhCH6*	KD
7/43V(\8fHɞkP|{ 7qE2[^_^S% [C b`rDII=UT2ffv5JMhU.G^}̰_'<j0kĨ
bT5m5]9ǛUSDz.w6bwjngjV6`]8?h>p<1]r)r8d	݌MJمlkBT;lo1p<ܗƱ&3̞I*^
jYC'Pcufmgǌj575xxsy =O7C̔ɳTb@|?
z̀~, )/jjgr:AvM}=ɝVzϯ.AޓM[@t	I->	
G]/Gcv=K:pq<PR) dAArmN|BX Wk~/6հ(,p}Unwl?=;B<V42<h+jjU^kog3rfAxm塊20訬ѵSunwu\fuy2=txе8)q؜tWwִUEմۗ{hˮOƻRUO:~ޚTTqi6喑Ey.mߟjll;hg_R]ׄWKsfҿ1<Pݽ_qj;Ǔ=em;HECk0Z)UqSn[z'-27cyu?ko	V{D}N,8{rW]-:tyV,-g*v^ƣGEkK^ێ.LDE#&oT}~Ҽ7^N^o#&Vxx<x5_+ǁwٶ5Ҙ͚j:V+J&i,Ătho0zk]fReLbz{8#>==KjըmT-r&m\- kز#	A͕Ǯջ%\++vlbri~ ۻ/Y.ְgzhg?(oYpE
\7:5Ej@9KUA:*ׅ"3` ̼w?E=ZKq=y>H!h,ʃA۷!|I9[O]f_`vWt'}oYxzB\݉K_lz4K
(W!x~nB]_ؠ	Ň֬jcx~}s" ]o5$%obGt(       Xmo6_q
2%]XIn6HOCPmHoz'^u;=w<Tsf^i&E+	"8sHi)
b
:c
dB!)9TrB<'W~PzSYB9hHOSQ>~8=tuShgTr%Kp
UDkO~+"r:whb[vYBw~%<ͩVTi8$'Jbz($,[kf1*B5U9!X";=7˝e+ʜ#ؐ=%XR|mMGKYt󮛸dDS̼[0bJSsBT҅i?N.Q"TpN?Rȳ[,ȥpU7X{+&hFzO++J+}w\^b-qSN5,({^,1bSٜSȌ^UbSƇj9po>.1a{@a+`EySׯ~z`~!_n.̼VƗT8KtL~TyB^#ƌfeeCEv]8 ؼp$C	eԨ#!ϥw&G-
}Ĵa#@z8qָ_;m 6a=A&fZ$i^-Hl1|vm<DΘU>ＹQ3GF/"P^p9\gw6w,w1-ܖb[2Udj=vmVSC_eρ/휚(&9fSd(R%cw	f20t5(pUh+'\5E$1CipI#@*LI1X*nVD#vUG!2dvY3cGMk7j2D42gC[;oa`xUXb<m
2kMC)mh(znܺڪrX{-/V,)TZ Qvc7Ϝ?22oG)2s{vc`|yjɩݨ!#N%Cez?wG۪]vƹť$ruo-oy:wȰ~rI2X%AgyiOtodi.&AZȴ
be( E \@1i%YPڛCs|fY2FLp'>AfzKFˇu2F_?fe)VLמY,DN	_µ{6ZYMƦт;N3~Iӽ{Y:tq.^yVgUjR?;IrsaŁb9'K+W@ik	='OA_&OٰiG
0{FQqF{7>tq4rYIWyn)lb;"@       VMs6Wl.!TKgubSg3NN"W"
 ] ?b{>ݷo.0åFnJ?/D,foWjc3xSU,hvXd>[WJV7&Gu@7zFax{wujݡBd\)B
iUT5ed2?9	;as#kG>!*(
A!m]TZ]q-Q6r=f,ؾ-4%G-:Fd{S@;Q5(SkrfL֮<wsO&
\KiR\ѓ;U:1v%-5pEhC
^V1Ta۫'9><p˽[A*RyKLD e	nz˱k/YјhOؑӜ4`ksb@Mա*,m+o3ϝ+΁dȣqۇ4B~˥\.НlY6{%ӈ~tI3!"lzA5DE3[Wk#ٶS),w%W[LE;V#Nc6pቼ=|hD sPM@QG_vfQC{Q/GXcYO2F1B8]GQ-ܿj%Gے OƆۊ`,?U>Z@~gҎvb#,rCXKZD~{7f}ri^#J?
y@xŉa4r%1<C=yG'JB%qL+~dQi4yMgCzeʙ>lV8߭?gGK4Z_5J]<dw|H}~oЅYӤdyd,ilot]C訹tP.~d<k:.KYit~QG"5<uDKVm}MV;yfSi.:M(=ЉCz4; &Sݢ\툎G7'}x&^rpz  mN       Xo6_q}96 h3;2idEݑԧ%'iN	LfCbןDɵpD*e%Ҡjp0A$B8D2?䖫ǰ?Smv)TD<C60`IJY"sW7+Xd '72)1H`fB`[}mzNX3Ny&es#INEfNIT RaW"@;ecXYd̆#> @C$32-Sp͘a0)\ E<>dzڠl:.V}$x[<cѷ%~ q݆wq'VWf[s0(lKЛx˯<2
st[fȴGdJ,}8OOWsr	 3g
\!}xK@[%LW@A.yW/F KR[K%ʉ"tJ s\qx[D=;!.=/+`ٴaKL8Qg94JF̈g4ʚWBaXs:anõ*a-{dFa1qMb_gWyd*U􆶓ÚQ#<eZk;
y8:aX`^\,3OLQmTKԔE=[fx6w[qmQGRSM9ٲМu13o+35rj(BPUvS--֋(+E$OZe!Xʲ4wM.N%b\P蜵o!7R5y8.S2F>sgQZle^/x=.Hj<0]0s-naY,iqmRC'_eD5 )*$kxNL袞.Wˇ]sa{/{_TY2	Cؕ06(vz]d%8J{ðB~?5di"xxX(	-9 :|
'䷃T|=  Llߘ
hUʟ:,Qæ(+>%*xS8za6	RHHOd1=6xC=y;t|Zb琼*^CGzc{/U,EQ%z=qm*nVX`жf]gys7.ʞ9FbMAjڕׅFak:ѹO`9+)6}psx0fywJXJrAsCIYT&NeA{1W}BF'	^h)/YՏԟ
qE;MG&G797GaZ7˙b$Nynhz{%`Ibc?\;BBzm_Gɻ_ZɛJɮ;
}x~wFjGT;U⵵JL.b7| w& PgV8n 8 c뛣#:Іv-EK!+C2jhb_ULTnaJk@-hʳO"*Yuq]xuwn| )&}`er~@RoK,ֻ?_;d       WKs"7+z2'=*^UٔN)ĨaDҀ)4/0~l%֧{crk2wwa
.+kc\EZ4kl0A/҂Օ2-qh
oç#B!3TA#-tHE_W7wW`|r2͌,6p'ι9,iȼ8ENkr/x0
Fʜ* Ln["/0XgZ{<v`[8\L+/ܮ]~劾\ UIVvc7߀7Qq	sX"t72+Z.8ŭSeNz䆯Ƚ	\xiVN[(A%,<xv;7fva!a/QX"ufDgtSM1)ᖜvOf{z>Ӥe"5ݥ?cf":R9M
	9!\Y )vB\ɰCd1<&X\*n׎o|+C׎gC#zVeWpdQ'JW~xvVa6dke88Qh^@.G;hbZ/~v!;S4i/ihDl6c8mo."n(9Pl
YJbG@ӓ] Wx OC	U>X`>蓖&kD B7kA3D/l)}\(ӫ/K$NTO6rS':Xt\"ɟ*Lu'3ql**ZTH?VWT6uB3"fۋJ~:7"HMXosŖ%ɢ . I,Җ>oϋi`Am2|[rş(+2B)篓Fk%^~%Q8cPkg`ЯH,i|(<u.c-Ł4+;{\tj3[?=Ё}GJkȋgbYpwwt4tGCgwOx1'5KYDk#SxT76w4uOӅe
Ky0\\{;6#&&Yru!pA;z:IHg|O{6z?mnYF;=!cB0*࡮#Y߿@}F       Ymo_1ڹKNb(ZcbeI%)3|%ى1537(R<n4|{Xl8L7؊jוR:)\q7WšXd!)RqV{`L$<kz4$,'NS9s2oa-2>&=J(5RK,b_̵,25+Q|HH	~9Л"(d&^")_q`]E>s _H
t-W=KPZq>m*aij1":Gv8?&Mq_ubiڮ<K/˛׋|OW_Y<\gD_
v7d >/ -je\N@oΓ9;n/K|]au:PUIt\?OLݝ><?)Tb-FvRO*3'u(--$7݂g|sjSTY
y1>0,fLS!yfxY:
ˬR֬	Mr+
pWJr(eQriYnuJ(Y%Cj
^ˍZ};XAJD:riΖKh>RӎzyI!|l|Iu*$ydd=.G,	X1 b}l^"4*r KFZ$Q;1:##FXYS6dߒ~ \z7(5z!4=kp|]/e!A[`d8*xBxp*4-@-h{<KI2¡Y.0d?Tױns<
^
[^<'YRLG5@1G&_$XoL̗L2LZU F,CJ$ԩ3WCSRV8	//п^̦cnKa5o_% \&)'4ǒ!Sb:8rTk&6tvRÊיrÔ3Or2C7DzbB!c-nY툻k6'=_M'F*&
57]:<iԝ'u%g{؈4w]ĪNWw!Lr]4+(hPd4lS,Z֯pr=,
k=6&"k\ǰp2G@ɍݭofC2AUK+AXKOeS;sm[2N#AĴe_ɷ8 Ѕp[l =3 6\M ߗvSW+u֍Aqcp-o׊Qs4|Mբ<_SLAgdy'C<޲Q&mlM/͇ƨć?\8:XI%%ZJû?yƉ?uϪ(P}]& &G3H6j˓91C|?*X8#4V5-6d[~&i[)>W!,ʼżF1fU:T*<F:m+Xn~k$^D,o\UKNfD&{UDhc[?֮*3
MM;
:6[M;SGsnΩhSbpÅy|K?lL>div
nMQyBWtG#pۢQQb'REÃ4CHM%r~]yn5QMa$,0|BR^#<Zn.ks0mzZǿ}DMCa-`=O_˂qvc
zx)A_q!ѰVZȗوb\Oau3ujqY us(jxby>^wUw2(3x(zzjdƊ:=EќaWo>jںna;7mk't]6bgTg6:2/Q)=FklNSD`CRB<UuF	k#vUЖ~3Ocw18:$^7.}Sa~ͫLj/4M=zoMdo/H\F/׫Af       [ms6_tn**!VsWV$qvz-6lM~x!YNˇ8ž<]01f|słBd˸XB.2Sr$DD5xLdWD.Y!BN,~\<"a\nN8),&IR2*+҈)sd:{}>#Wq=Yx%Z_XRiJ%#"W 9	Q~~8ρBf\ǩiX)텂F*Ny0X#PsU2`H>0KXHL'$7vlһbmp|pا@B?_l\8Ө?S	
\aEĵj3ނMaEيs!H國;1
PztaS,]}1Lzt<:zyH/-x/MͿx=LPE~>"hGʹ/lCshgM9r"3XqHdJf*f$ωd3RޭYbĀ˫A[pĖ;Dx	QFy(BlFV`yP# bDi|(Df7*.Das`xܡo|If5$E%z*,DkyT?#D܍$QS~Sj,oJf*	}uԎk<
%e50@iER._A\ɷk7,C{`J #Rz%yF&4@"KȓR \- ;&\p~׷B>Hw`&.'{;bu&W$]k~ױo|.YE)/>|6ϥ7*A _gpp:Af!Y[+׈g5VH@!Mxz-rګ&oڑ[<(wǅ|O4+-57	i^7Gdpp;*mWi?faw*Qs~mRMC'K^6@g-<	`0,+L t0l	+#fv0~Xθ~ё]" 2:s<E#oL{pd,H;@ScJ(}C/O
kxpP젍O~>gTJTVmJlU0dpP)y`3Ul6$^R'vu߳8`K,Ӵ賃o28UV]lVm8^P(Qc{-P8m	0 -;h{Oq*šNȠ2|X?
Pd>ˍ NIX&\j %Rْ_Kf0,TJZ^"	\<@4`2Ij&} YTZyݐJ4Aբy,xK"۬	u7 Zy
x=KiƁ'q`@g.YKy.!z*fCeUT\/X20dV>bigθDQΆHYGހRe7֖3&Q,KT	lH+^_qwM'/3{EHhz⫊02% eQdZliBz[>XYx-NŪHq((݉IlҀ[__2~h諣_/Ϗ.O^_̞&)[8ake(Hʣ	`B]	b4S.Ny=`	"&SEz*O9^`78yJU3I)*/[k-;8jxW7)4_d7K3M%pkG==w) ঺=BAfo;s$TCG.M0pG^aTIP:Ta+)ZTnZ͡jG
zl.<zV+H8@v8dfŗ]Wp8-K}:ӛe1ŉA=+ZͫM;Z]D\ansWX'릨dڡ<$)L/Maasj`\%v\fRa*9)StRRrr<HZ^dS	AmI@߶˶ p2-CRK)=71i,y98/+sTegJO_I'A9仙Qaior[3U[NERP6DգB ҄:A^ݵ9v	88\N44%)[lIֳz6;:'OlA3{˷'/N\\>}}>+Oެ0pGnDfV36fI(:3lU!'Icww {2|M{w[ܫ7G45V}<TWC}Vܙuo:h18=>B1/i-}?ux JX5d-/?#VLL)S'Z*/OT{s*}Wu`mefKuiy˛Ydnt
·	jtr,:t2/hk)KD%1#&D1nY27hq*f%BE>Z}s<P)";VÁ~Zw
M+Д~<zDt&ͤe\ִdB|gԒx780{@SySEnV,5i+|0eD{>oylW$uf+˘L+28CjXy'^kwQ^ḽ]k^W`m{NyNjټI<;TRl+;|mgd֥z?-?-l7F*G_ꘟG]LWeÇ '壽πVWܘ0Vo;xg> 5yICW m#2  <html>
<head>
<title>Inspectable pages</title>
<meta name="referrer" content="no-referrer">
<style>
body {
  color: #222;
  font-family: Helvetica, Arial, sans-serif;
  margin: 0;
  text-shadow: rgba(255, 255, 255, 0.496094) 0px 1px 0px;
}

#caption {
  font-size: 16px;
  margin-top: 15px;
  margin-bottom: 10px;
  margin-left: 20px;
  height: 20px;
  text-align: left;
}

#items {
  display: flex;
  flex-direction: column;
  margin: 10px;
}

.item {
  color: #222;
  display: flex;
  flex-direction: row;
  text-decoration: none;
  padding: 10px;
  transition-property: background-color, border-color;
  transition: background-color 0.15s, 0.15s;
  transition-delay: 0ms, 0ms;
}

.item:not(.connected):hover {
  background-color: rgba(242, 242, 242, 1);
  border-color: rgba(110, 116, 128, 1);
  color: black;
}

.item.connected:hover {
  border-color: rgba(184, 184, 184, 1);
  color: rgb(110, 116, 128);
}

.item.custom {
    cursor: pointer;
}

.description {
  display: flex;
  flex-direction: column;
}

.title, .subtitle, .custom-url {
  font-size: 13px;
  margin: 4px 0px 0px 6px;
  overflow: hidden;
  padding-left: 20px;
}

.title {
  background-repeat: no-repeat;
  background-size: 16px;
  font-size: 15px;
}

.custom-url {
  display: flex;
}

.custom-url-label {
  flex: 0 0 auto;
}

.custom-url-value {
  font-family: monospace;
  margin-left: 1em;
}

</style>

<script>

function onLoad() {
  var tabsListRequest = new XMLHttpRequest();
  tabsListRequest.open('GET', '/json/list', true);
  tabsListRequest.onreadystatechange = onReady;
  tabsListRequest.send();
}

function onReady() {
  if(this.readyState == 4 && this.status == 200) {
    if(this.response != null)
      var responseJSON = JSON.parse(this.response);
      for (var i = 0; i < responseJSON.length; ++i)
        appendItem(responseJSON[i]);
  }
}

function customFrontendURL(url) {
  if (!url || !window.location.hash)
    return null;

  var hashParams = new URLSearchParams(location.hash.substring(1));
  if (!hashParams.get("custom"))
    return null;

  var searchIndex = url.indexOf("?");
  if (searchIndex === -1)
    return null;
  var originalParams = url.substring(searchIndex + 1);
  if (hashParams.get("experiments"))
    originalParams += "&experiments=true";

  return "chrome-devtools://devtools/custom/inspector.html?" + originalParams;
}

function appendItem(item_object) {
  var item_element;
  var customURL = customFrontendURL(item_object.devtoolsFrontendUrl);
  if (customURL) {
    item_element = document.createElement('div');
    item_element.title = item_object.title;
    item_element.className = 'custom';
  } else if (item_object.devtoolsFrontendUrl) {
    item_element = document.createElement('a');
    item_element.href = item_object.devtoolsFrontendUrl;
    item_element.title = item_object.title;
  } else {
    item_element = document.createElement('div');
    item_element.className = 'connected';
    item_element.title = 'The tab already has an active debug session';
  }
  item_element.classList.add('item');

  var description = document.createElement('div');
  description.className = 'description';

  var title = document.createElement('div');
  title.className = 'title';
  title.textContent = item_object.description || item_object.title;
  if (item_object.faviconUrl) {
    title.style.backgroundImage = 'url(' + item_object.faviconUrl + ')';
  }
  description.appendChild(title);

  var subtitle = document.createElement('div');
  subtitle.className = 'subtitle';
  subtitle.textContent = (item_object.url || '').substring(0, 300);
  description.appendChild(subtitle);

  if (customURL) {
    var urlContainer = document.createElement('div');
    urlContainer.classList.add("custom-url");
    var urlLabel = document.createElement('div');
    urlLabel.classList.add("custom-url-label");
    urlLabel.textContent = "Click to copy URL:";
    urlContainer.appendChild(urlLabel);
    var urlValue = document.createElement('div');
    urlValue.classList.add("custom-url-value");
    urlValue.textContent = customURL;
    urlContainer.appendChild(urlValue);
    description.appendChild(urlContainer);
    item_element.addEventListener('click', selectNodeText.bind(null, urlValue));
  }

  item_element.appendChild(description);

  document.getElementById('items').appendChild(item_element);
}

function selectNodeText(selectElement, event)
{
  var selection = window.getSelection();
  if (!selection.isCollapsed)
    return;
  var range = document.createRange();
  range.selectNode(selectElement);
  selection.removeAllRanges();
  selection.addRange(range);
  event.stopPropagation();
  event.preventDefault();
}
</script>
</head>
<body onload='onLoad()'>
  <div id='caption'>Inspectable pages</div>
  <hr>
  <div id='items'>
  </div>
</body>
</html>
     UMo0WF[TN/n;P$:V&KD_37:EG..tljjE~]/7/#%ig20'[wbOYD. IH,R&Fl@GFj6wࢗrBE/V"
~yIFh[U6
30@suK|6,H|wMka)]je=EНbԱ'RfS^zf{wvsJ
\qRgņ1\N"4<jQzby׶cK;Cg6ZJIOz/s[$=QE~NEۉ0?4=lFw`hnrg-Araջqd_Y6s.Gk{ׅjۀb@bSd@:MK&(\8u"o[\!l:,~0}0DHx9Yw3\7Q@Tj^EsU4j/,ڷ a7oCRm)*_{{>Jhy	vS"ԦN\uibyUoZȇKig       A0EI5^ q ځ6)3Ӓp{y%Zlgp>.x9B499ЄRlU[	<!9Pb-a3$,i=KnH0CHsqǽ}PMΘ        uQAn1+P`׀nSj"iy,q!QN/N@rCr4a7ď뗋o}WEr+12eJ[rm5!b9#ǒ,FG1n)rX`~9<[
&XRKpub~=UeS@MpG͚=:1>St%X	U@]tLVy7\ǰ^=LmlZ1d;0r\yy;EK97#/"GZhxm''u $
Yz~@/$JOGqwtΖ<O5έp
Q^Q GN/gqxe       Xmo6_q	*e6/@u_J<[L(Q#);ް#%98ɒb](ޙ(RQgdt` zHQ`"^3ivv~jVTsܢΙ4 ,a08/$sn!ǙH0]4a`BII08IUQѨR'hĘH
cvqJi*GEp^'K|,mG)3ߠ!v`5
նd
@˩C NC%HLNb6eCiʜ;狓/Wg0u:i"%>={Dȏ\Sli<Ƅ|'Ce:[mptjTr^9=k̒v+yN81!YLx	Hbl+B	m+yh=ѣ׊`ʄBl96	b!IC?cp6**;i%*L)WeDwͬ|xT
ca1{%z7"1gB6 uI(,)+MySFlcq՜>.]<__8lDM;Ċ/j9sM?]Y-4\D;i\@;%&5Q'v(}R \;F5)$K0U#5ڂ\6ϻx˲k;临V8ef`tvT+':lc2~곺
I%3oO៩ȇKfƩp9u&R'Vmrl+Қ\Ef-DU-Z/򳁔QSs sh+p`eaWMPƈX.jO t:cV X9aN(>m [8ѭWetMډdvwZ;.1(1>	m1c(àch%gN:Nлܜr .,ʘx<qZ
ɶaU95O;ytN,)q"rAs/_?TrpE+amGym:}ybѳchEJ,>`¢7V̝<UvFSE׷Ϛ䌼5~y,81ik sah[7h"C=ŬU	v[@w}~F׈[ѵ{u[E }       MN09[ҪIӨPVt8jjGZwǉ !efff9N5-"5+®$6u@!QxT[	Z	\#-)Gv7RjI:gB2?(DMKϫ"{pZt]WDx8	gvbrOBCy̶f`JZ߈7 JW|Kg#pS;>I/ס5cX޻[<
9똨Y$D^|ӇtаָMy8t!G	圌@D麿3%p"upcV8=E{>1       Xn7}WLZ':K8
(JԮA<wg%6+R%vTCmWvPds83s!f+r痯~|%Śk8.JHqQ]@ByY<:<
AWLLR!ПKqc[H`)r2ӫDCpFg8#\. gƣQ*s1g"N&P	%O5<:$t%KhDϟïzA{ֱ߷GIqKG$B*p]#O֛"^>!t\<2پ S\ۆ/
f룡(L0{4]M4՘kh&zȱȱ҂mM)d
)+&/w,YfS`@7d_}(2+'ǥS8~3Y$
Ksmg3gdY3~6髀
ImLAxmv#IJj)˙4"H!'
,SToO`dƶefg6pZ5 ghm5#|3_ao	,HfT\X1	U<)>MRiwݡb;4%i/S_Sbꡧb|䩭_[z\ktkI;/uK~@R)^Xx9_%|Yd|َbn"fGc£>RMG{;2$;`&0wL	δaSg-<	zn-h߬9<y,O㛄"Q+IEl/M%./^K+/.a-q$~rKx<??tZaaZ*ItU`؋Q)ؐtw^hfiY$kϢ'ntub{}o&QEn;Sz }T-2k؞s"5)?1OiÆ*
SΒ#<Du
:,;j܃[_N=ӌp0[,)?XgawK)hG#GzXȘ?N7JkX@U*Yai:C7AڒGCsE@ݚT˽P."I+ xJo]_ű5E,*PZ!;#]yeLok[:?F}EȊ..+ѽ2PH[u)yNU%MՍ2k:!mabO3:,dأڿ.إ       V]6}ϯ<(}lWENP "PDｶ0P`$ι^vaO	o0p6mlv&7i
ZI 'wwnf [$s	$"ß<dI(M$aQXi2CB'0]X%)XVтG̔(B	I"0DioJ~	]ZKF؄Gwzg_wكX6g}װ^hlbBwYhNFTiKOO'HE=>	/և+#n;˵xde*K6nwr(/19W:g Be8SC{u3+oG4_} dCch1?wxb
Tud^	yKgF\B|,:|??#rj?&JsgTT/3oXS!U+V3ۣ98(ƮaGbQ}S=0hXI޻(R+d5))i7:W[	d%qƧ,g<Y,xc)bqBb3P=h5>o&O
#=ȳ>S?xڅ.ʄ
`,%-QR<]N;+*m\
C*|;Vңo(62	0U'JD*H֍q8'uжZ1"8*5ߙ01)v
>'2Rį'ag$8ʊ$oR*Q_ܨ?#Ȋ{ɺYKไ5>J}2_֩,R<ZdK	Dnntm|zͬJ`TMG(\Vl(nw)"Ʒsu&OV0yykbꁼrwլ[5љk*}`=.5v#ʮC(C<MnvXehUuqw[Ed0 D       TM0+'Xi	m/@{HQS@$ce	굷B]:,-IWͅx7AmfO_ LG?L*9 
5&Ng0F)i2W1B,{*	l@aN8g1
[f2j 6X02	0aYH eN'VN)&r//e\O\ĆIѻnn/FtG8af.mhv0qu׊ @36)uIygFkXLtuD}{Q#v(tñыKOJx~YZ;x@J
Iy۟Ed\-"2yAU[Q.㟘\6pW!\os؛[$j>Yi͟e5p^)Lgkk/jXe	pv[Y۲nl%QJײpZeWmƱ}OVdܙGe{kdeO߰)y{/ވF%       WQo6~ϯMNCvXM[&H*HJYXĔxxG<3S/,+GB8f_\)F,:(;~;3_I4#p#4h5
,/r
AI|<pa	kj-@jAxu~KJ<|%3Ei:=^1Пfiq+kӌa1R"c7>lt2LUKEK_tr{9zrgڻ#?4ޅ#=4.X.ISB=eϘ-.5<	!uYQ}lh8 17J!7.O*m`Z:42	,ɀ
GkP@:)cWcxKᫎY$J>fc2)|N.BZEAAAFd_h_弒J!ݲ̐nUw5-Etu5Osē"y@n,@hPsxLKAcUgIZױKUclX렷1u&۝pTRk^fӈ"vhr#mD~NN+d$҆y Fr.<Fj
9^T4{p)5M
}xm4ffFJ_ɏH㬯]>YdWX&'6fI!4Nk"I<lʥ[9Hfw-*=\QIvn,^u?3E8-58+s*+|_KӔ/IfQR=kԦe1O^)]=>>X򫉹!3	*GFf<(Ñ饧_Ër2Lo|8db#$]w6q9ҿu
7444f4ؽ@b홦WR,u,[(Οlt[(nѵl8s9\B7gVS~ds=e6V$>pr^x.\F DD51e*JDOԏRPq'ưcq 5b9{KF}<!,xw9_]y׿(ԥNo1}sB'+j.w\=Dp"}oL;w|_v`j(6gz΂XuЅ.4ޛTޔ%>4i݌Càm6MFo`ͮ&xiL2'uo`c5m       [oU~48r*K
VnQwKm݇̐\rwla4oIASu\*]?kUIۍ:juQՑ:2œjUZW7:<}>ZWYZj,sU*׉ZlU^_|S7L,]˚uܨe&JWE'*]7gǧ*tӯ~VjNJFJ\>YoGUoBWh~$ӍzbQt7vHiT=*N>f@TM-u=5MĐJ0jPSWP,KxQc4b(LǹafpZuZ<!8؅']gNq9k^ibMguqGꌬQWlm<UEjNrI\vUQ>;Q)f.JҺ-۸HJ,QrG2LgdDBS^myGYR˶w95Bb?+!'*$oiJը[#UY'ZS+hsmĺMܠ*UhرYCg9m|Xv@kHJofK~mewo.O 7٤|5TX ĆdZ)_.^LϘ3ݷШ3^dԉ5DDNaqW.fA1C&UZ6r2⍺=PGna|n*wQm q'[A^89e`JFZ#bZ`uLAfcD~DWCB2LNA=J=٧$S|"RWdݮ^йd<"JgpBFlc(zz6H>nqrA4g]1u}V<CЁE
pdqB2)1Dd4!B֒5K}֒Αpp*`NˎG{)uOnN!eNEv:#|]ED܇!'`8Ʉ6gx4*r_d bQ.0BܫxwrzlfO2gh<
#s<4b?JX 1`#L?Շ*SW9P%R5=X1.dY ;Do9Io/	~qU>q0P'M!0EpN菄+*]Vzj_ c9;'YͽDb2ph(8C'	 9@" mQb'bB&Obuo1X ><<pjW#G( by92a	Yp5JaÇ
6oyg:_?/鏕\Z_'9.,[}Y#u̬t&so9ۋQօ}6|f]ذf90ɞ\..p{7ۀi,us2p$,.זIỜ݉ls&h2u,]o<O6[_k]ƹc٧[9!G]J:Jci8lv/̹oS	M9rypm|%6g*cMZe}SNn3u*!'0a➄fM? $NY,)cE'B20,fy35B4&\8xIkɈZA |EWi/QJ$JubcrcRt
cCh%&9_1JOc&ԌIuQ5:>Šitz7W[6bl)D6ENQmmcm>S<WCNmI6
gJy~-F$N.p	`5pcǂ:gV^mmAD_,S؃lCu=BW5@TW:6D3&+l/'NG"BxԀE`	gXzw{OGs>XЀIUZ
QI܉ļMڻv	ٰ7ŹS0Q'2j۳̞I3D/L<
=AȀ܍`5r|A1g6%2Js<՛a/u؆ !Mlk+J4u#uXY]0_uX
Fg]-%^E?<s3-e^*|UUYMԪ*ڒjGoG($Bܖ~&g!'ʘ-	;@;,Y>|@2~_.v,eٽZSJSޏհ})(ͺ a44WħhDuW2m6XhuaQm.#!A+5`E`&vZ?/8#|/y<Fڥt<;a(f9Wy맾:%I0!9z2/+Hw;-%\/mBk .#jvP"5vU^X`qX:/
Қ%ˇ3WebnI>q*NswJ&UxZ7ifs	]vtBSR!ʤ
2H'T<+V,LH,3
 '75R_T/zNqF1chU&eǭKJJRe1#]B\ޮƫA\sw
:Ф-J$lГ{mNWktƙGE#{uzW^3+gI=3x9o}e˶k_fvE39f$wi,BdIlӊ.ե,ƶ"1yOsaHȊ:m-h}7Xpˣ Fj*A@䖚.9ܠ9e)Rcjen)96:Xұ5{Jϙ'X}e="O	˳O\x>2V^:U9~w=;;R8i/C]zzH7^cq8k&=	1O:+~Ue~ÉeFo9}u+t-TMżxٴӕV.%PbBddbӵBOO;ӕMH7xSJ_B6
r L0b-z#F-ܢu|CINΩHy,.%9ecC\QKt	[#eݓM3m[,P^{vN]60~0ՋlitO@b(ީmBvj&:0Jkry$Eczl, }z;p6"p,|V=D~H֦hҤf$R
s$-䗷d򞟧2	H _gks5:dm/WA^^뤓ƓOs27_	17'ړr9yEwkiLɽR@hsNvv/:9І<+yAeגyk:`,Vn"(><g!W-N=4C5SQmL3P҄AT*a'`	[]2'>r4R\Jo]:&-ښ
+uٓr#9|\X``RFڞ'wj<2emDTDr Y- z+:fV6@i @`)buJYJTAv7p.N))1@x+jw֔:6ji
#`oݗL n9޽WFU4dfuLdT߷&*ɛb^	i~pQP|]=Da3ٸNNʱ/GﯻъטQ׈=vd)q}Lrӂo6!-=:ߩ?=)>6Ivߏ-1]kfz+FU^S`k6wK,OݧQAqr`HWPKbr1ecfVENtd]Swk1*I|rp~I1wނl]nbT	ռ۬U0QQ3mVbc7򟧬QdWW4l
0/e(ho{a+HKg+¡$8pGI\>!KےsWR:N_@Aוw4jF%,5P֊}2	3PVpi\="3zۆBҿ-9       TQO0~8
$x{[uvZi}g'	h6q}wwzT)\W,j*kNkHAzt	O`Wm8ݠ3(/O_3vA+`A (02lc(C#<~ +11}~b1@<֌y@`єP2'6{P1W*kǘP~I3bXr5YB`|]XiN}d.+
M8,T.tS
 (*I[VqU"Ⱦ$IWڲNh\!BZ]NƊSqkL	2Riqb8}zGpܠ9/GAIuO2:ρеeSքl/j8kn9%3F5)c]mˋǝx9H%j1[׉s"}m-+Wx:YUq)HotϺuq][er9D9O zX4Uzp%]([GSnv
5L{vֱs:7z˂)DdcY'HK*l\Eo UH^)z?݀hh$'7`:J:<ƛk&eCbG&\&َ]&0:@W'CTk~C	(˛hK¾PL3rp!  PNG

   IHDR         7   uIDATxڕ	 ]7h RW7pk{H$$Kgq|D`D N*`LEP]M3T Xԡf	 qvՕx9d	    IENDB`PNG

   IHDR           s  9IDATx͕Ak@FO+.BNbTBhIO^"x%u0dy|a<Tb FeQ#
u<eSa&iI0AT8칝A7#M k+vlDY́Y"K"Fr9$ZR=9~AΙϖT|1g>AM*!l(."Ziͅ7{]I)JH)tl^0L_Sr_dMaѴ%W ,$en%.	~|XOqDr޿IE    IENDB`PNG

   IHDR   w      q<;  )IDATx]ktT$ B[*Vȣ*RH(@K@ BiMNI,qϷ)h}`RBy4g@0!<BJ&9wx ̽s9g}LRb@"Zi~Ӥoq*'`lGn7
lN:E崟c.NjoTҳT߰Av~N">!5\[2"pKIZs?E+m{q$GL֞\67_ACo"k.ujRUbW$:,GC'\lܜsڨ9kZ.W 9.ĦdӜԞh{+e깯UTFb<s֝DsjuVb@-H)zRc,c)*w58H~ŕGPFLCD"YA1*X=\ [^Yznd˄%?<(3brJd`!ps)ĕWbEeSdN!'}JE5q<Dޡdv57Vm;TQY
lPF\VWhҨF!:' bG:k!+$
<gAW!%*ݸ6퉕Y\Fnǧt9ĞT_)ejDYi!
nW`D.16fkύЇ&"[ӝhD)l&iݱ9Lp_6_;ؙ
!A!߀߾pfHC	Lt,]*(Lpn,mnt*E4dm6C5Hְ֗Qj'a'1Jw.s.#ϧJ!H˹EPbY&\LHP0-J7⾵@V\$X]Tg6KHsyBE9ҞlX-sPQSmho-eX>^#]2ż/>x"3BE4.h,+Eze8Wg;1D9K5`mz威]u
u2cfB1#yG}nb ?g;{*c<\?9oC3VWis1H9\Hhne?Lj$<MtG;}>6'=km6YnoL4N:g1-8bc[+HIm\>~DHje7fڡA˚52=wX(s֞cIw5Ca_bL)2diph6&iekgmsVTfv&!dmfs@T[±<'fԘ)E1^6`M(B1ZTNΥ 3=5n/7}$%KJ˸jV]l{8
-HOd5#:$M68	Ok5}J	K[ķ=~n3tL̶pM0\OvQEZ*KսV\kVi
ΰUS;ǳ%)͌4d+	Sd[U<_?^Q}=Dw]KsdM-ҠvS}rU<Iz5oBأV]
<"W-M7ᥛ)60^A,ꚋgo%ȫ)4K-0}vwn6Y/'{pGpr	THԢq8m{,rBpuO,I|W/%1}dhK{r PMT<Juz5M2,?X;daˈ
REm]iIhR+1.fݨjdRL7!_
i~|^۷̉oabߟWl<[BM+I03
_eu ^:+/8y|dʖ	'm9y5
oxW9MPk(x03f=/5tpS*PHvqE,P+I2F	C74=S*l?vx菪2M#|TGA'ZpKvF9҆_h.ھoĴaUEnӵc~qjn6	kn=Wg0/SoIMyi0uL周䥩.:WuMMp+5@PI:ca%ݨ՗iاF pHQ bid${TgO#oV@]%^.=jrny?[X_pEyjS\eSeo&5Q%ё2z4¥չ3Jw֛F^M4)U鏩RM>ʳh	ҍʪuhSgf]|ǫp32_Mj(1r}{<jWS#ۣpsMɡQDp".xg{"n]9ufqcm_3Fyպ܀K[ .FV;\{ػp_ucW{Vjbz#܀K']ޅŞKKpgW;L+Sx	|p`u@|\%OP7xY1W(rygp!@vZI^0U71P;lTɶ1%+5Iᘹbf)U%aƄ?VҦ    IENDB`PNG

   IHDR     !     PLTE      R   tRNS 
	 >&jJ-<6Hܓ!4RD%'ZmE3M=xviǪel{KN0[`*asyb5q_Qo}.OUc,r/p#;@ۅ٧B|TkGunw+L$У]~\FW"XzdؾCY?g9P7(SA8ɩ^h1)IV:ʌf2I  IDATx݅?O$,BxqZ(PZE(ԥ~z^&L2d3k{Nj̓2m$wWSlkkG.-҂ߚ>jV.;(t\.jeW;U~~vQ9$V<+AuDXKT%nrAU:Sa]Te,pOaUͨ^ K܄Eͦ:C4cwT' ^`y;B&D*XR#rd{hFU4
ͥ:@Ж`=R䄳Dz3XCTŞR)T	ʝ`G2";2e~RU:
6RQn(oJVSx8ԇ%RB&Py9ѰWU9|x,XNՇbOL˧O:	\\"&a#صsPjUK%D9YXgn_HX评/(kGaVZI=t%$QqNXw~XǰXo`	C2,kzkxz8kL=,5C=%wPV	Q`aR`OP©"XB=ʟ6QcaSvg*Kx
[Qa+㰆G`Sa	)6jU(=Mɨ8-S(iu=zmfM̐,T?RCze"hl	QQݠA|8%N6]_|ײz>W,q
POa0ײUpm+>MEI0Tf(TNFK:̟ ;@2_ץ_bړATc[T/NޅjǨNЀJ ]/99=R*8Qq;F5>J`GV:.Vs|~yԩLikC(nR$~{oFP%~AƷl2OZǠ9j_SO	?ϊa9o	ca-QM&a)e`	i-XyDXB;йurLout/-.u3B}?GՉYMÜ*0#+4c6LhRɬB~A`2E4NuLkh3̥1F
E"Oӯr
tqE`f[9\64T/"M&kgMhEWn̻4Vn2|C@Z`=oT(S4hNiB7hCm<ׇ
خ,h76}AYAu*?ĀVT~jhcr?0P\Ц!/AIaO]v鲙_S@߆yU-BQ>C֏b۹=eN1 }&C6RÛ2=ŀ\z~KՂ
Ya=WѺKGAa_Qgݼ67+	OB٩m74JeR a7?_oFw \H7CQjT;G?wq1dt +a9T\҆~Y	mz\QQk]( [LeS_I,ݭ{z[FT^oB=
ʍZ7Q"|h
2/{hI{?xJPn#z*AC۠n4N	_QP弍:jQJp7Jw?{ATdk
EE$vn|ˎ4XؐOʪR	rNC%ZP/:c~$ʢ6SIк"xs⠔Cʨ >r:!ɹa+e.ٔ,SN#	I;RQ"(0AU('nE$Rҭ9	Eҋh^D%A*>GM5niX9<,L
|pʱqR7rb!z?ŖAJQNhȘN)@-mŢK3Oh<_/4{ei/R HH	pj|25pSkC;R!foG(עE:r=C)r~H||4eRe?17Lzq2(NA9@P)c$e2GPRJ(Mi=U=dho]PR=iW&!x*HhH:n]w5"R
5*rrE"!-2TնV:TkCO3vrSTgP.tP @g9Mk3r@LE!'=/F ե=!XE5# C('Ʋ۵ /):ߕA)z
~2]`(Ii-!ȳї1T9O dSx$G5(*cjES9ҷQ2E)'}qF"zQkZNFSd$tPԚK/)%I(EA7ҷJ *Oo]$hC·A}Z?ω2mT	}tophNo "n,E^K]PrBgfS^.==ݴEYG6zN1p(#	^NSq'>V*նQ6JZ[z:z;%CtPA!5g^{c,"o*okS);tzGzr,wW7(jom)=tf̆)k\PNxB<議G.A@\@TjEibFׂV
^>Ԁ)앯Yh0itD	[?"y!
ۉ\BSXJOryDLgl2&s7X H0)y0+Lwy"
 Q{(+SJ	YFy90avz-֍ l8wjkR00zo+In0?Bi݌jm} &vRͅ68
&%<QPI>ϐ0%jKPd_dWzjoTf{0^4WnXDDz
jO?Vx]y~ST,XKLX4ykiLNP\*:#s"	*	lS6JbԂ5ݠVu=aUlnbOXZ =XqEX_Nը;--}}MoGEJie$7>0١ՊG;doo^^R<"P}k@S:@Y`(gѷoD\Μ)mH'ݚǉ7<KOo@o)piԿ,tל^y	Ce ]zx4?tfU0sP.b݅ECw;&ӉyGpn}X;d.3yȹ%`ȃIg7߇Zi)Mٟ!R*D$VtuY,zJ/7G(rQUYkY|Xr)(ȝ+]zH藩#o͟S)\OP`	7\5Vp,$w b0lyH7=Tzy	f-sw(H]7S)8f;
:\(2]C zp.tiM/ft.z7Þv
f^vuImHkeR]IէbaOOt-I@aOS$.՛mӧ0=X^UIKөYp4k?dLgV GaRili4a0)F	j[I=&5I`N4,[4tLjP&59aR4@oTs`>L%&5
T@ &FIe -懲9L=צ_@ohQ0:4t>L:PR@fNY2`VS թ`Z#*`ZեlgafM첫E0A̜/:77yjoB`[woe,%:U=xh1h55n!ǨN4%҇c
~smLȉ%TszH}"]״'HI:8q׫`_Ls&(    IENDB`// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('mdDownloads.mojom');



/** @export */
mdDownloads.mojom.PageHandlerFactoryRequest = class {
  /** @param {!MojoHandle} handle */
  constructor(handle) {
    /** @public {!MojoHandle} */
    this.handle = handle;
  }
};



/** @implements { mdDownloads.mojom.PageHandlerFactoryInterface } */
mdDownloads.mojom.PageHandlerFactoryProxy = class {
  /** @param {MojoHandle=} opt_handle */
  constructor(opt_handle) {
    /** @private {!mojo.internal.interfaceSupport.InterfaceProxyBase} */
    this.proxy =
        new mojo.internal.interfaceSupport.InterfaceProxyBase(opt_handle);

    /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
    this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
  }

  /**
   * @return {!mdDownloads.mojom.PageHandlerFactoryRequest}
   * @export
   */
  createRequest() {
    let {handle0, handle1} = Mojo.createMessagePipe();
    this.proxy.bindHandle(handle0);
    return new mdDownloads.mojom.PageHandlerFactoryRequest(handle1);
  }

  /**
   * @param { !mdDownloads.mojom.PageProxy } page
   * @param { !mdDownloads.mojom.PageHandlerRequest } handler
   * @export
   */
  createPageHandler(
      page,
      handler) {
    this.proxy.sendMessage(
        1128265880,
        mdDownloads.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
        null,
        [
          page,
          handler
        ]);
  }


  /**
   * @return {!Promise}
   * @export
   */
  flushForTesting() {
    return this.proxy.flushForTesting();
  }
};

/**
 * An object which receives request messages for the PageHandlerFactory
 * mojom interface. Must be constructed over an object which implements that
 * interface.
 *
 * @export
 */
mdDownloads.mojom.PageHandlerFactory = class {
  /**
   * @param {!mdDownloads.mojom.PageHandlerFactoryInterface } impl
   */
  constructor(impl) {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;

    this.target_.registerHandler(
        1128265880,
        mdDownloads.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
        null,
        impl.createPageHandler.bind(impl));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched to this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Returns a proxy for this interface which sends messages to the browser.
   * The browser must have an interface request binder registered for this
   * interface and accessible to the calling document's frame.
   *
   * @return {!mdDownloads.mojom.PageHandlerFactoryProxy}
   * @export
   */
  static getProxy() {
    let proxy = new mdDownloads.mojom.PageHandlerFactoryProxy;
    Mojo.bindInterface('md_downloads.mojom.PageHandlerFactory',
                       proxy.createRequest().handle);
    return proxy;
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!mdDownloads.mojom.PageHandlerFactoryProxy}
   * @export
   */
  createProxy() {
    let proxy = new mdDownloads.mojom.PageHandlerFactoryProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }
};


/**
 * @const {string}
 * @export
 */
mdDownloads.mojom.PageHandlerFactory.$interfaceName =
    'md_downloads.mojom.PageHandlerFactory';

/**
 * An object which receives request messages for the PageHandlerFactory
 * mojom interface and dispatches them as callbacks. One callback target exists
 * on this object for each message defined in the mojom interface, and each
 * target can have any number of listeners added to it.
 *
 * @export
 */
mdDownloads.mojom.PageHandlerFactoryCallbackRouter = class {
  constructor() {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;
    this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;

    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.createPageHandler =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1128265880,
        mdDownloads.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
        null,
        this.createPageHandler.createTargetHandler(false /* expectsResponse */));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched as callbacks on this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Closes all bindings bound to this target. The target will not receive any
   * further message message events unless rebound to one or more handles.
   */
  closeBindings() {
    this.target_.closeBindings();
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!mdDownloads.mojom.PageHandlerFactoryProxy}
   * @export
   */
  createProxy() {
    let proxy = new mdDownloads.mojom.PageHandlerFactoryProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }

  /**
   * @param {number} id An ID returned by a prior call to addListener.
   * @return {boolean} True iff the identified listener was found and removed.
   * @export
   */
  removeListener(id) {
    return this.router_.removeListener(id);
  }
};
/** @export */
mdDownloads.mojom.PageHandlerRequest = class {
  /** @param {!MojoHandle} handle */
  constructor(handle) {
    /** @public {!MojoHandle} */
    this.handle = handle;
  }
};



/** @implements { mdDownloads.mojom.PageHandlerInterface } */
mdDownloads.mojom.PageHandlerProxy = class {
  /** @param {MojoHandle=} opt_handle */
  constructor(opt_handle) {
    /** @private {!mojo.internal.interfaceSupport.InterfaceProxyBase} */
    this.proxy =
        new mojo.internal.interfaceSupport.InterfaceProxyBase(opt_handle);

    /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
    this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
  }

  /**
   * @return {!mdDownloads.mojom.PageHandlerRequest}
   * @export
   */
  createRequest() {
    let {handle0, handle1} = Mojo.createMessagePipe();
    this.proxy.bindHandle(handle0);
    return new mdDownloads.mojom.PageHandlerRequest(handle1);
  }

  /**
   * @param { !Array<!string> } searchTerms
   * @export
   */
  getDownloads(
      searchTerms) {
    this.proxy.sendMessage(
        1173218956,
        mdDownloads.mojom.PageHandler_GetDownloads_Params.$,
        null,
        [
          searchTerms
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  openFileRequiringGesture(
      id) {
    this.proxy.sendMessage(
        831725473,
        mdDownloads.mojom.PageHandler_OpenFileRequiringGesture_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  drag(
      id) {
    this.proxy.sendMessage(
        880354138,
        mdDownloads.mojom.PageHandler_Drag_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  saveDangerousRequiringGesture(
      id) {
    this.proxy.sendMessage(
        649057477,
        mdDownloads.mojom.PageHandler_SaveDangerousRequiringGesture_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  discardDangerous(
      id) {
    this.proxy.sendMessage(
        578901877,
        mdDownloads.mojom.PageHandler_DiscardDangerous_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  retryDownload(
      id) {
    this.proxy.sendMessage(
        1001145349,
        mdDownloads.mojom.PageHandler_RetryDownload_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  show(
      id) {
    this.proxy.sendMessage(
        648670268,
        mdDownloads.mojom.PageHandler_Show_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  pause(
      id) {
    this.proxy.sendMessage(
        1687023430,
        mdDownloads.mojom.PageHandler_Pause_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  resume(
      id) {
    this.proxy.sendMessage(
        1821777601,
        mdDownloads.mojom.PageHandler_Resume_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  remove(
      id) {
    this.proxy.sendMessage(
        287212656,
        mdDownloads.mojom.PageHandler_Remove_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @export
   */
  undo() {
    this.proxy.sendMessage(
        932911157,
        mdDownloads.mojom.PageHandler_Undo_Params.$,
        null,
        [
        ]);
  }

  /**
   * @param { !string } id
   * @export
   */
  cancel(
      id) {
    this.proxy.sendMessage(
        1242812307,
        mdDownloads.mojom.PageHandler_Cancel_Params.$,
        null,
        [
          id
        ]);
  }

  /**
   * @export
   */
  clearAll() {
    this.proxy.sendMessage(
        1243418498,
        mdDownloads.mojom.PageHandler_ClearAll_Params.$,
        null,
        [
        ]);
  }

  /**
   * @export
   */
  openDownloadsFolderRequiringGesture() {
    this.proxy.sendMessage(
        1119879914,
        mdDownloads.mojom.PageHandler_OpenDownloadsFolderRequiringGesture_Params.$,
        null,
        [
        ]);
  }


  /**
   * @return {!Promise}
   * @export
   */
  flushForTesting() {
    return this.proxy.flushForTesting();
  }
};

/**
 * An object which receives request messages for the PageHandler
 * mojom interface. Must be constructed over an object which implements that
 * interface.
 *
 * @export
 */
mdDownloads.mojom.PageHandler = class {
  /**
   * @param {!mdDownloads.mojom.PageHandlerInterface } impl
   */
  constructor(impl) {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;

    this.target_.registerHandler(
        1173218956,
        mdDownloads.mojom.PageHandler_GetDownloads_Params.$,
        null,
        impl.getDownloads.bind(impl));
    this.target_.registerHandler(
        831725473,
        mdDownloads.mojom.PageHandler_OpenFileRequiringGesture_Params.$,
        null,
        impl.openFileRequiringGesture.bind(impl));
    this.target_.registerHandler(
        880354138,
        mdDownloads.mojom.PageHandler_Drag_Params.$,
        null,
        impl.drag.bind(impl));
    this.target_.registerHandler(
        649057477,
        mdDownloads.mojom.PageHandler_SaveDangerousRequiringGesture_Params.$,
        null,
        impl.saveDangerousRequiringGesture.bind(impl));
    this.target_.registerHandler(
        578901877,
        mdDownloads.mojom.PageHandler_DiscardDangerous_Params.$,
        null,
        impl.discardDangerous.bind(impl));
    this.target_.registerHandler(
        1001145349,
        mdDownloads.mojom.PageHandler_RetryDownload_Params.$,
        null,
        impl.retryDownload.bind(impl));
    this.target_.registerHandler(
        648670268,
        mdDownloads.mojom.PageHandler_Show_Params.$,
        null,
        impl.show.bind(impl));
    this.target_.registerHandler(
        1687023430,
        mdDownloads.mojom.PageHandler_Pause_Params.$,
        null,
        impl.pause.bind(impl));
    this.target_.registerHandler(
        1821777601,
        mdDownloads.mojom.PageHandler_Resume_Params.$,
        null,
        impl.resume.bind(impl));
    this.target_.registerHandler(
        287212656,
        mdDownloads.mojom.PageHandler_Remove_Params.$,
        null,
        impl.remove.bind(impl));
    this.target_.registerHandler(
        932911157,
        mdDownloads.mojom.PageHandler_Undo_Params.$,
        null,
        impl.undo.bind(impl));
    this.target_.registerHandler(
        1242812307,
        mdDownloads.mojom.PageHandler_Cancel_Params.$,
        null,
        impl.cancel.bind(impl));
    this.target_.registerHandler(
        1243418498,
        mdDownloads.mojom.PageHandler_ClearAll_Params.$,
        null,
        impl.clearAll.bind(impl));
    this.target_.registerHandler(
        1119879914,
        mdDownloads.mojom.PageHandler_OpenDownloadsFolderRequiringGesture_Params.$,
        null,
        impl.openDownloadsFolderRequiringGesture.bind(impl));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched to this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Returns a proxy for this interface which sends messages to the browser.
   * The browser must have an interface request binder registered for this
   * interface and accessible to the calling document's frame.
   *
   * @return {!mdDownloads.mojom.PageHandlerProxy}
   * @export
   */
  static getProxy() {
    let proxy = new mdDownloads.mojom.PageHandlerProxy;
    Mojo.bindInterface('md_downloads.mojom.PageHandler',
                       proxy.createRequest().handle);
    return proxy;
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!mdDownloads.mojom.PageHandlerProxy}
   * @export
   */
  createProxy() {
    let proxy = new mdDownloads.mojom.PageHandlerProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }
};


/**
 * @const {string}
 * @export
 */
mdDownloads.mojom.PageHandler.$interfaceName =
    'md_downloads.mojom.PageHandler';

/**
 * An object which receives request messages for the PageHandler
 * mojom interface and dispatches them as callbacks. One callback target exists
 * on this object for each message defined in the mojom interface, and each
 * target can have any number of listeners added to it.
 *
 * @export
 */
mdDownloads.mojom.PageHandlerCallbackRouter = class {
  constructor() {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;
    this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;

    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.getDownloads =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1173218956,
        mdDownloads.mojom.PageHandler_GetDownloads_Params.$,
        null,
        this.getDownloads.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.openFileRequiringGesture =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        831725473,
        mdDownloads.mojom.PageHandler_OpenFileRequiringGesture_Params.$,
        null,
        this.openFileRequiringGesture.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.drag =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        880354138,
        mdDownloads.mojom.PageHandler_Drag_Params.$,
        null,
        this.drag.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.saveDangerousRequiringGesture =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        649057477,
        mdDownloads.mojom.PageHandler_SaveDangerousRequiringGesture_Params.$,
        null,
        this.saveDangerousRequiringGesture.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.discardDangerous =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        578901877,
        mdDownloads.mojom.PageHandler_DiscardDangerous_Params.$,
        null,
        this.discardDangerous.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.retryDownload =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1001145349,
        mdDownloads.mojom.PageHandler_RetryDownload_Params.$,
        null,
        this.retryDownload.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.show =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        648670268,
        mdDownloads.mojom.PageHandler_Show_Params.$,
        null,
        this.show.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.pause =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1687023430,
        mdDownloads.mojom.PageHandler_Pause_Params.$,
        null,
        this.pause.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.resume =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1821777601,
        mdDownloads.mojom.PageHandler_Resume_Params.$,
        null,
        this.resume.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.remove =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        287212656,
        mdDownloads.mojom.PageHandler_Remove_Params.$,
        null,
        this.remove.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.undo =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        932911157,
        mdDownloads.mojom.PageHandler_Undo_Params.$,
        null,
        this.undo.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.cancel =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1242812307,
        mdDownloads.mojom.PageHandler_Cancel_Params.$,
        null,
        this.cancel.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.clearAll =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1243418498,
        mdDownloads.mojom.PageHandler_ClearAll_Params.$,
        null,
        this.clearAll.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.openDownloadsFolderRequiringGesture =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1119879914,
        mdDownloads.mojom.PageHandler_OpenDownloadsFolderRequiringGesture_Params.$,
        null,
        this.openDownloadsFolderRequiringGesture.createTargetHandler(false /* expectsResponse */));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched as callbacks on this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Closes all bindings bound to this target. The target will not receive any
   * further message message events unless rebound to one or more handles.
   */
  closeBindings() {
    this.target_.closeBindings();
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!mdDownloads.mojom.PageHandlerProxy}
   * @export
   */
  createProxy() {
    let proxy = new mdDownloads.mojom.PageHandlerProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }

  /**
   * @param {number} id An ID returned by a prior call to addListener.
   * @return {boolean} True iff the identified listener was found and removed.
   * @export
   */
  removeListener(id) {
    return this.router_.removeListener(id);
  }
};
/** @export */
mdDownloads.mojom.PageRequest = class {
  /** @param {!MojoHandle} handle */
  constructor(handle) {
    /** @public {!MojoHandle} */
    this.handle = handle;
  }
};



/** @implements { mdDownloads.mojom.PageInterface } */
mdDownloads.mojom.PageProxy = class {
  /** @param {MojoHandle=} opt_handle */
  constructor(opt_handle) {
    /** @private {!mojo.internal.interfaceSupport.InterfaceProxyBase} */
    this.proxy =
        new mojo.internal.interfaceSupport.InterfaceProxyBase(opt_handle);

    /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
    this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
  }

  /**
   * @return {!mdDownloads.mojom.PageRequest}
   * @export
   */
  createRequest() {
    let {handle0, handle1} = Mojo.createMessagePipe();
    this.proxy.bindHandle(handle0);
    return new mdDownloads.mojom.PageRequest(handle1);
  }

  /**
   * @param { !number } index
   * @export
   */
  removeItem(
      index) {
    this.proxy.sendMessage(
        1361843498,
        mdDownloads.mojom.Page_RemoveItem_Params.$,
        null,
        [
          index
        ]);
  }

  /**
   * @param { !number } index
   * @param { !Object } data
   * @export
   */
  updateItem(
      index,
      data) {
    this.proxy.sendMessage(
        519970639,
        mdDownloads.mojom.Page_UpdateItem_Params.$,
        null,
        [
          index,
          data
        ]);
  }

  /**
   * @param { !number } index
   * @param { !Array<!Object> } items
   * @export
   */
  insertItems(
      index,
      items) {
    this.proxy.sendMessage(
        1754984836,
        mdDownloads.mojom.Page_InsertItems_Params.$,
        null,
        [
          index,
          items
        ]);
  }

  /**
   * @export
   */
  clearAll() {
    this.proxy.sendMessage(
        802963285,
        mdDownloads.mojom.Page_ClearAll_Params.$,
        null,
        [
        ]);
  }


  /**
   * @return {!Promise}
   * @export
   */
  flushForTesting() {
    return this.proxy.flushForTesting();
  }
};

/**
 * An object which receives request messages for the Page
 * mojom interface. Must be constructed over an object which implements that
 * interface.
 *
 * @export
 */
mdDownloads.mojom.Page = class {
  /**
   * @param {!mdDownloads.mojom.PageInterface } impl
   */
  constructor(impl) {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;

    this.target_.registerHandler(
        1361843498,
        mdDownloads.mojom.Page_RemoveItem_Params.$,
        null,
        impl.removeItem.bind(impl));
    this.target_.registerHandler(
        519970639,
        mdDownloads.mojom.Page_UpdateItem_Params.$,
        null,
        impl.updateItem.bind(impl));
    this.target_.registerHandler(
        1754984836,
        mdDownloads.mojom.Page_InsertItems_Params.$,
        null,
        impl.insertItems.bind(impl));
    this.target_.registerHandler(
        802963285,
        mdDownloads.mojom.Page_ClearAll_Params.$,
        null,
        impl.clearAll.bind(impl));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched to this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Returns a proxy for this interface which sends messages to the browser.
   * The browser must have an interface request binder registered for this
   * interface and accessible to the calling document's frame.
   *
   * @return {!mdDownloads.mojom.PageProxy}
   * @export
   */
  static getProxy() {
    let proxy = new mdDownloads.mojom.PageProxy;
    Mojo.bindInterface('md_downloads.mojom.Page',
                       proxy.createRequest().handle);
    return proxy;
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!mdDownloads.mojom.PageProxy}
   * @export
   */
  createProxy() {
    let proxy = new mdDownloads.mojom.PageProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }
};


/**
 * @const {string}
 * @export
 */
mdDownloads.mojom.Page.$interfaceName =
    'md_downloads.mojom.Page';

/**
 * An object which receives request messages for the Page
 * mojom interface and dispatches them as callbacks. One callback target exists
 * on this object for each message defined in the mojom interface, and each
 * target can have any number of listeners added to it.
 *
 * @export
 */
mdDownloads.mojom.PageCallbackRouter = class {
  constructor() {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;
    this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;

    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.removeItem =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1361843498,
        mdDownloads.mojom.Page_RemoveItem_Params.$,
        null,
        this.removeItem.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.updateItem =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        519970639,
        mdDownloads.mojom.Page_UpdateItem_Params.$,
        null,
        this.updateItem.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.insertItems =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1754984836,
        mdDownloads.mojom.Page_InsertItems_Params.$,
        null,
        this.insertItems.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.clearAll =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        802963285,
        mdDownloads.mojom.Page_ClearAll_Params.$,
        null,
        this.clearAll.createTargetHandler(false /* expectsResponse */));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched as callbacks on this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Closes all bindings bound to this target. The target will not receive any
   * further message message events unless rebound to one or more handles.
   */
  closeBindings() {
    this.target_.closeBindings();
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!mdDownloads.mojom.PageProxy}
   * @export
   */
  createProxy() {
    let proxy = new mdDownloads.mojom.PageProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }

  /**
   * @param {number} id An ID returned by a prior call to addListener.
   * @return {boolean} True iff the identified listener was found and removed.
   * @export
   */
  removeListener(id) {
    return this.router_.removeListener(id);
  }
};


/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.Data =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandlerFactory_CreatePageHandler_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_GetDownloads_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_OpenFileRequiringGesture_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Drag_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_SaveDangerousRequiringGesture_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_DiscardDangerous_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_RetryDownload_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Show_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Pause_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Resume_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Remove_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Undo_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_Cancel_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_ClearAll_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.PageHandler_OpenDownloadsFolderRequiringGesture_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.Page_RemoveItem_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.Page_UpdateItem_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.Page_InsertItems_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mdDownloads.mojom.Page_ClearAll_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    mdDownloads.mojom.Data.$,
    'Data',
    120,
    [
      mojo.internal.StructField(
        'fileExternallyRemoved', 0,
        0,
        mojo.internal.Bool,
        false,
        false /* nullable */),
      mojo.internal.StructField(
        'otr', 0,
        1,
        mojo.internal.Bool,
        false,
        false /* nullable */),
      mojo.internal.StructField(
        'resume', 0,
        2,
        mojo.internal.Bool,
        false,
        false /* nullable */),
      mojo.internal.StructField(
        'retry', 0,
        3,
        mojo.internal.Bool,
        false,
        false /* nullable */),
      mojo.internal.StructField(
        'percent', 4,
        0,
        mojo.internal.Int32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'started', 8,
        0,
        mojo.internal.Int32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'total', 12,
        0,
        mojo.internal.Int32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'byExtId', 16,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'byExtName', 24,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'dangerType', 32,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'dateString', 40,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'fileName', 48,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'filePath', 56,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'fileUrl', 64,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'id', 72,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'lastReasonText', 80,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'progressStatusText', 88,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'sinceString', 96,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'state', 104,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'url', 112,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
    'PageHandlerFactory_CreatePageHandler_Params',
    16,
    [
      mojo.internal.StructField(
        'page', 0,
        0,
        mojo.internal.InterfaceProxy(mdDownloads.mojom.PageProxy),
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'handler', 8,
        0,
        mojo.internal.InterfaceRequest(mdDownloads.mojom.PageHandlerRequest),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_GetDownloads_Params.$,
    'PageHandler_GetDownloads_Params',
    8,
    [
      mojo.internal.StructField(
        'searchTerms', 0,
        0,
        mojo.internal.Array(mojo.internal.String, false),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_OpenFileRequiringGesture_Params.$,
    'PageHandler_OpenFileRequiringGesture_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Drag_Params.$,
    'PageHandler_Drag_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_SaveDangerousRequiringGesture_Params.$,
    'PageHandler_SaveDangerousRequiringGesture_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_DiscardDangerous_Params.$,
    'PageHandler_DiscardDangerous_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_RetryDownload_Params.$,
    'PageHandler_RetryDownload_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Show_Params.$,
    'PageHandler_Show_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Pause_Params.$,
    'PageHandler_Pause_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Resume_Params.$,
    'PageHandler_Resume_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Remove_Params.$,
    'PageHandler_Remove_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Undo_Params.$,
    'PageHandler_Undo_Params',
    0,
    [
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_Cancel_Params.$,
    'PageHandler_Cancel_Params',
    8,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_ClearAll_Params.$,
    'PageHandler_ClearAll_Params',
    0,
    [
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.PageHandler_OpenDownloadsFolderRequiringGesture_Params.$,
    'PageHandler_OpenDownloadsFolderRequiringGesture_Params',
    0,
    [
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.Page_RemoveItem_Params.$,
    'Page_RemoveItem_Params',
    8,
    [
      mojo.internal.StructField(
        'index', 0,
        0,
        mojo.internal.Int32,
        0,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.Page_UpdateItem_Params.$,
    'Page_UpdateItem_Params',
    16,
    [
      mojo.internal.StructField(
        'index', 0,
        0,
        mojo.internal.Int32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'data', 8,
        0,
        mdDownloads.mojom.Data.$,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.Page_InsertItems_Params.$,
    'Page_InsertItems_Params',
    16,
    [
      mojo.internal.StructField(
        'index', 0,
        0,
        mojo.internal.Int32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'items', 8,
        0,
        mojo.internal.Array(mdDownloads.mojom.Data.$, false),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    mdDownloads.mojom.Page_ClearAll_Params.$,
    'Page_ClearAll_Params',
    0,
    [
    ]);

     }ksFw
g&@SX<sr<㰼S(h @J}_w2T tS"̬zd=ͷzֶ^>V^/t_S_-_Ϭ*w.)qVMڧy9(@?i:m
k[gٶW5 ~/Uxjx˛mkgsi[X?쫇ۢ~on7Ueƪ|mX>/k]XwM[wдwo*,V[+m)<J7e[/^ol?Ol{+djs~?ӏo]{WO?~~ˆ6@:5Yh`dZ5'ݚ|oV</Q5:ݵ3ᛟ~ǟ(a=%/-/-/--'hS+ۦ54]3-۪xɜRK'_G˲vimo
çg:~+Y{Aray
~΂C]83Pb^Xt``]][ԛ4+o/6N?}ܕ*o_tx-Cj}}-*mHҾ{8V9=}u'WeNjY
8:桻m΂f7厢OJ[vP+]Ww殄*rN%ER|d VKŶ=70]\<tv|%-Ђ+kSvR&^Y/z~%<G4~R}+VC Vljro?2.ٻҠ{]Wm]/Rɾ8{Ww`ꬠ&@7wԬhmٰ[Gحu*w1nmʊv'W~!d(A#hewMvs(rSf@Dih,kHA}FYl~Wާ}}W	Ry"Lۢi@ȼӨg2J? ~˶bv`fH@wKH=Gse@{sjoZS{޿YF4eoo1CJxx90ķP A~	Ӕl
|dqsjݮi\Xe-7}\Z: g.}E;jIjYC7"R%'i-͂vT#<#P_<kEўug7Y\\&6_C彵-ؽ8;^o3/^UQ٧ &j6S/PZMiDmn:Otg̺Fkw}M3TuCEo-DTclw'zKvsxqOZM<*` ~s󒍍oS1 [z*Z, ?Nخ֍G,rm]#Cb?KNp|~9l<ˁԓѶb+}}]T-m}.+@lS`sҖtpPK޾ǹݺ^eks2<"P(֒aϾp{oKME2A4CP|gC`0Z#C#%JGcz-wq
@gF R1PkZ)ci!8;)!þ)i *Z8)Լ۳Z(u.|&Tέly,fhW>yǂv/SV$^%Z9'K^uHFTR+뮮u? ƲKIgN7!ϊLC\,Sh鼸2!4S|P1~a/o&ېS(҄(}x(keh2{h=Cwu{"Fۗa 碙Sh+>R `t.R,׈˰d3nux!/ʼT74ƵHnw}0>àh:?PlGpq\#/úGMK))Ga2{y=44BMS-N=[ŗa4z:>]K1tDV)<=`g]=}م;aQ|$mJiTQZggg 0@)/r]VeЯGeDq40}iN~<]*k0R}/ӯŶ~CW]{DkiY923cN\?.|w]&^GaHxjE&oRط=/	7	M *M3+Rv]R^+,G~&/,߈?ݠSǥ$r;ƺɯbW5_jdV=jU42mСvC̺/zqX$$
22e?QcOvLX%6eU8C>#xmk# %[	<Dge7:gAD@eZ$Y򗮇߃A ܕ,}
|܅.Y+('߷^2{K'] m" ^/#	^z8eZ~Z&wKob#4B|Np,X7>y'[52M,£_n* [z W; $
`&Y5}Y+ϥ[;woGC\4ޅ[EڵWv$)Cߗ_ A~Vvbw O=Ꝯ}? V[nP6
g"@q©{;`Dj	v{["y9Ub'ʲm!$heϣ+C׊)XC }MWMB6'퀺> ԃxJ6j0гp&F!npO}/"^cO?8=;NA_eh[l{Iހ-G.~^$>؂)	AܶBeލvY޻sS	3n%~	FD|%(=#I][۳|Eߠy#.֟w;ȤARc4H$4hGl/P6VEe bϮS" C[N",ڦh
K0J.(q6SB!Uj"F,BÎuO+5^wWT`B?P+wW.:$.l r&)au٤#@Ap/  <Xa/_0q7=y6ܣB<X;{sJ	m֣$5c,}68+¿׫{p7*/ƄX0TG;ʋz0n>ߔFCӚ(殪.3)IDX`uw`?	$>B GAA
 hq=O>x<_'}tɵV2`1+ɇDeyFsAʤG+*d nxe߿b68A1"hӻ_0^Ag7Eix6!HtHd+qXA`$fEٞlM+8}aE=Oa3s	XC8@܈чY0aZv1}Fl"d6? . 4-QWb fMehnq<&=mmlhÿp-neǚr[f&Д(iǟ+2 |G%cmh#A2f6Q%?	TIǑ>\T]%Q%#q`-䫡CbMg1̇VY$qmv(:?B?.5[tָbmn v2tʠMaLPV
DKhuB?CQ7JqNGM71?&&Mt M61ؠ!`F=C]׺A\(ƞ0DbՐ,M+Ͱw.Jć!x nU6^
ē8^Ւ	֧WA@!M=nG1.j\;t#WcŮ("DoӐVo9/8Wlg6)Dydw1*@	F&P}hV["Lz 1D;p^*bd9>'qWVe2U-^*6{PA5Q-]H܃rFXO0`L%p+';NVNcA<(G3',cBU@C<R7C<A	'7rkv'\W6	3(4fq}B#f4#L;pB8>/XO\vhMo@m o,N~> #,~"ygfFRtPp&`	p]\ZLLDo'k$8GlO\z> =8NkoG^F@^D88σ1وM0CT &\& 1)6w0ܗ;r,˙
!f (D^ cVX4!H@;C~
lt3Qk4[+>_f	)hE?ŖAft[.cZDÓ !D200(Y:RHŃ-0\lJ F# ;
^,@$%	a7t4z f'N}yrQ5+IudpZ5xݼMBb6a&
bDHޠ-EC"/`RE&s`G2/ |2Kwlg$'a1a3dw).0^M|Lm)h/8`%:F}pIzzټ8_iT!Luf}6 3ګeu9Ad`zS,g[w 5J|c%h%aW+4UGy*/pU*⾊aAf+.
=M5ZSH t	\?^O'(j0'\M8^M'1\͈xnpQOx!rtցkPiDw"J@\O5#55uBr9.jvb((B(&;#顨G3bU=6]qABj'ws]X]T]q_olH]X]}AW_zx0 
"ToGUETOh'K\*^J,k !M.gD(>sO#*]>}~|3-y H>b<}omt>KtW:v37ӽO946 @ ` nZ `<P~fB̊P$z;Z Fdl֮qD0Af4[D2Ou'!*\k0X@$Nl 8T_G'I`B׍<Uw5fm2p(6.t B͊'*u%	6(]:{fAVoRxA@(_⵻I=q	rAb"ɹN10fm	Y`h`68H"/"(Nn18J_zj*,mg޳f~BFG]/O18Aũ3GwAFd'f3
H9gA>HYf9Ef3uITU2;0Jj&yj ([@h,Zg3]*X(_|߬6^+ B5M=?. LI*6C?7F<5~fު`0 -}b.<Pm`rvT5T(X: ڐK5#R?U Tn$僻#$ Tn *Y'pz0lUA&
oL1<'DPU"p0Jx&6Gx#בRt	F"Z(/Irw,a`qG6aZqprf8Y0GY8kgXCclbU=Xo<-ǛVzL)\- Ӄ(r=6- fqkO6Z &i'r"=\ !\ xK	b iI( D .lZ .ufZ .4R}hF#G$Z .d|WK4Zz"D<p LiziMo(`D7iHOGl^0i4K(3@PJ0 Lq$C02Z%>:B!`?uW1+ZgޫMå8ia :lG.,	}H-HynU"β"Wia{Za,ϲhՁdA:fTm/Պ0LfEg~Ӑ,lV( G%Ǵ%6dmAӍ5:sgoVuqnGq6AkCTLs=P&4PM<WZ H6YZ@*Vh،8rH>#6\<i"` XGZNf[Z!\ +uhf |t17UsE&L}m yN?O7{&r74LXVlF4޸&u3 gSMܫNcMjaF~sa'WL8XH=pO%|4Ru} \'C01o־
:&ϋoLLƛщ E0pq`ұ$0VԵgNw7E'`P0\g@8Yp 7=3QKAVcydFC3H"3ȊMkDFtNׁf5RvjMfU%U=ꙉpFVcc
Ip1g1-;f#g䜎`ϝq@{Fg#pe\0% ӏN4̻wD56)#ͺ)'χa`jB!Q!J@`{ŞXL=Spb&  l?Z u?42~ ,0
G hVl&=;_\l'yfbꬋ,4CB'ԈbaTrV#5UB'ΓQn+b_EAlPa<wphLe%cm6W$iuU"n"Ӄ\$JQ'@Qiܥ#z~)mtl{~ܦg#@!yC'K~u;"י?4 GHnkn4Ľ.ϑ^7?Vwj0@|K,?W\G0VGoWmtOC(n2Cz0d}'j6=V
V-z^\ܙ\ȹݛktxMXƤz@u?a_ ۟۟SvvcC`p= vOZ%PjkH<pՆ˘tyJPciǮT]unNΩ_8^s<]s<fET1ړqk
5\|q*Wcf,uWg~ܖml VT=`qm_x+:W5.fOinȑ>3Ѧ-we[>mh筙mmޔEU.ňB|W̐LK!-'w#L:!v/^҉DhraTI ?	v9L[!].{\uɎ?C-擢Ҽ,v9aZ:B0,Ͷg  @'
plnĎٙS3G9p+Upb%&DwY*=}N¸2a%%)/Yok}34
bZ6dK'H>HbpHԜt4GޞI	4Wqv/(]7ot#mi&,s]($w`z:UqQ9;oTTR+<#xU-o1*852GrW.aتH7G^Y-`6#-HVy?6iK{
XSNpgǬd%T6'pƀ:\u^dHgX0DZ7;z7 	vG.A8@TwC9Xy-^"xc!bsFU#FB"_ȢCS6:X=cڻQSoc*oT:@/e:VD
.<$ד|5e/sk [n0D4r." @8^\:2p@ׅRj{^*XO=B|8Z^7Y'=ΎH^b(#^`;1:sHQ*bj#b$֠bTdɈi*6!؈z(neh%c/緷[uQ?Gkyvƚ鮫	mc.G>a3q4O'5H0
óq%~z
6fya]܎Aw}mLauVs`u~6\]1ЪhQ;@/4Q.f*:[n)NR*_XԌ!};6OF< 5LF݊<"`ur؊?ȓEnfPr|/ָ&J]AMDWFՂ䆫N(1Q畤5v:ub]SdPYxg@{Vq
[DOS>;Y
E[MSH굣s2akrKٚ+p_gNLGGLL禣ň}"`Vly5fl%u&{p"Nx^6xJi p"Z7\se_,ڞ!%f)FOKר8<v(:h i4⒟
K"\&+j(IK+g@khp$7t7W=&>5. B`R"פwXFENKňNÈPeE˟C1/PflAAz3;֫DgT "}kxA$x)h:b.cXXIYkXA[REst+ŠR8YS&5R+1EV-,s]1(%쀙CǴ*<FSϒ4c"Әuatl81bg1XE}V*sè:}70j}hg6Dvк]VTiVm䐹â<GJO՜U]6$V}ټZx5!ߎi6kf#k䔫R>cfPWp\#ڞ~G@@%3cKzGNcvn`3]w![(ӹd?lg& k	3
:P`_pMCjKuI\u en+*5D}GV-S*.swji/ʐz=*H4k>1AcOIC
(i)qY:?\.6<&	L0a`&2=LlIzaV&\5B	vn+d-V+Mtώi+
>x*)SܔVK??РnkΩ\zɦ1h?x|EJ1fhJ֤ؠ!Q¤bEz2Ͷb챩X=*zjg㉢29˴r3`wTJ0~й|p|*+e:;pr4vlet݀φ0l_\#1Mp<e2hUHO|$
 VbǹߎxS~°~I?Ӄ8ڿ~i^lf@̡! s v U`FtB"]IB M>uS-}p[ԗ_zwK_K2-Ұ;Yi׍@G*0gEۙ~ɰHW-J:y?:xPpo8KB-J3Kly|AN-u!4}|bdΌM͐c3tQ*4(MinAan[e+N>h&3
O̔:;fZq4ˏ+sO
#nQy)\V5¥.>>޵\aWW殭cΗYYgU=t+:
~l)_ndɐ}IYE},*%fXf`m<R;Xk{aXsg5P_3ˏlZۓHG)'HItfN{EǸdhFȘ $Ƈ'O8:#5yyj;,#umc|D=#7M )#oä~bb+CG4%}hSlj'	pV]KL8Z1_q`H.,aGNtpFWCShr]CDޟ>:}0}rp&zWG~-eEH~vMJjJP0#ř{Ai dUmڙxSxB?E<!)SBH8EHx<!6ېNChAYʃMigg@R.7%#m馻/d6H4aB7X6ߦ{<M\M%+wck&x{ ,mưIq/[U]~ ;v,s`aN77,>`0Ϻ3C~:9	;ܞ
tar֌8QpZl}&h71q%;PPNH^aN܆+LjvOwF6T%<?͜y;ap|SUt#~WظSI'}IUQ66Jzi]]>;gPJ2(OW9SC;h\QG@G%tƟ=o:)%cGuqy_s鼺ȥaO9xRfm9~Л
J7-C'/|VH)MR .]ai^>YӀsx[$n /Vj@+w|8ꙷ;:lY[Y
k(	T|u}2(m48$bq[o.P* @%/)-7u;V=nAyfo%-@a޼N&zu,&$$:ğְlxj>]mW;2@]]9t$:MM 6xDSD6!ĤZNoFտ<qelws_QMgqx|PTFiK.wʥu"J-c2­etxbJW+	a=ł1g^CЏșŇg F;K`GԼ@hiސg}tiP+m:nэK^BІ؉>SbΡ.|Bd!X0uI[<\Z-)K`	]K7ҮӞ$%M7
>>f^wYM;vs^DdIn;˒;v͕cl'x8<~Ƽ<#ӴϚkNt	`mȐ0I<J6ql,jz1YNx?cw#b]On4U}~)ސPf1i8vdB$U xGx52➾ӌ}uQ&<Zn~g^96Yk櫅po5=yP\Jʊ'!@+KBr7Oj7%Pd}\cvll]q* $DD1
nmctA-̛:} 9d=ą{묾5(`;z<HYY?Rz&bj<ym>p,z4P=N/|+ɧKO׈t=u|e?vZU| abT|ӹ6L:#i&Lxuu+V%N&~Nlؗn#ޡ c57H3NRvT#JalTUwdInsRY#;<Fe_(V&qsN>VbN0MbZ" 5(j{@9*y'ӹ_DGBȭ2Il/#ʟgӿgrs,sg}?}O]ٕힹ4̣	bAtV޹nJtU.awsO0xFާQ-LYn2SbS[wI,1]ShHd#[mql{}_aF:#9oy۶/inX|r'MY Y78ﾅ/oI3+Ҧ!Sy|CU6r7|gL-&Yz0	("řer&9Ӽ؄߀ ￃ8+^ #[OJ=Hn>c=> *%VIѓ3y;Eb+zcW
' LyX)d#ui!tCWF
6g$@AK8%aבwUßvߖϤJ,GRQEӗIsŁ^
1+şAgCk?i踲H?AG2DtY=% Y7o
u"'ł_5.(۟j$xJ@a_xaMy60B]<&DrMY2BRGrg(ql1tՏ>GCrUplåtStƏbgMΰu.{[xB{DWV/?nA@뢭di#biH,KjALtFj⥼6pA`¤txd!74~1R"ɑ-1S4)Gʽ-ĄϘ8Pɀ#lOR\訤BIQ2a_mz_țuPFaJIkw$C;S^ $|S6ߛx|zħ]'q%y\V)"aP޿C3fQCS^&F/$1V]DFyC.SFnM2K&DM]o~<%Z`PIƏ*tybww%𙖼ƒTζeZo$`	ݞ2c,iw[jv4wg8#ѝEl6``،xhfql8mCmkku__-Vhر	z/鲉tdS:=\l Q n![.h̋4ښ߱AqoIZ-.&5mQ{+IO90ƬG4Y/6?MfW#~L8YhXC<egaϋ3ማf<A^?/|pԴLf$^UÑ:l\Hkp.`k-R}]%cP~HVM8Ca IU%T	
|@-5n㰾y{	̸@^ֱ܂N:\a\̤_m;}C̫6	D.1ObJN(x>T߬a1^T~{gqXW!k0٨-meK`{
>.dEH12q85inK'OS*nA<kpX		y8BBݥQR2&Xwf?([J =/&0@i,2c%Yi۴g6nm/kU#(I7n}Q	CO[KbpDQPp!/rI@(X31(Fg78vTT\ឦ4XygJRT
($׀b,?`P6UFCTSVܘ^]YO7g۪^T5I4_PI3yV#O5EkbDslDfYgLO(#?7XmжHНćS
39>S"qz`r.s刓mUo]$oGR?y(͌>;u_2s]TZ#Y&*~e*:}8zň<ϗRofM;{dՃlrk,ϐS{Ztޫj5NHP"xL>7IZM:-SM9p0Jn9hO;Y+}qk
}ߛW<+2˒=J05#yZ0OQR8Z+0`p+gyP*S}"
rGN^,ԔfdSHMJ^,5/sz!!L1BfIaIKF}f(̞3Nu+ZEӨ
(Gi4Ovȅ\ݎZɻcH5bz:,J<K~
QZᎮx(;IyraqmܤyOD?H^c[P-Y. uFo؋;CӸ͓à͠;;$pvt :a,Q,d,VdNTvEJi4xW+-^FPVg*M<&%uaRxIjS=]q(}Rii0Hz#+%qSiA|8#1&,]ny:m~	RPVy	9 M.7EËP :Oݶp|4Wslm6{E$߀%"y͍&[	&].w%zZ蚸B글N'ÖMz =hmYzsG <è4EբnT{,fr5o%4͢j5T9YQܚ,-}蚦gu֕Oy Q0k133SQ<⎷/ N}czih/VG^(sjO/,}w-ǂPTA%&r++AKN0c?)hGkzӏx"-pfxZg[{SU~$&r-qB1g?}W~TKߜQJPq=.pj"܍B_*h4c-Dys z| vhQhh24WS)_*+E)`eؼIdbui4%\fvmp@ůpKTԷrKFvonP^HV]yL~5˛J3:8=b2,3U9@ؔomԐ!s_6庬 pJ#Gi|S7p.p#_+	)p՝a<C^X
,c]64s~pǎtL0pH@кҎ!0ѓODoҵ~XedN뛭Xڈ`ԓ]Ϡ{niduʌ2[`5vn$yD%nR$p-}||i/Ղs;;Ͳ2;y}Wv'9~Jט9e(qAMRS&ofȗ(S>Q٘ߡ=zqw$ kKGy_@VE~kc.J(@ft2c<߾BtӇȹ)b]x{#Y@{-0&l=upNnޔD?bIPS~ڦ	ZD7C1bxM8^38ޫ	LcJVa##=e$р9r^tt)9 R诫q=pU-fE£+,SJgHYhqkSU`X.+RͽbF}E/>yY@Ð|Nq H]"ǯFg$#4lFezҒTG*a4AwxOե&/Q4TUm^c/"O@*rӊ^L%@Chvs-Sadb3mu>i<ڌݝgBZJتpnTpߝ;`Aï.H>ⲓ+w"nPK7[7MiEVؓ$7Ngp1LCʴ]B$W 3N5S<ݶ
m+|	V'2~A6=GO3i	0,TBhѣCi9h|n}5h9b QM׽>3QKԥ*Ȕ7݄J.ƮJƶ<h؆I"xw ĄZc+xK}u_bܛ.9<(&}r i)50a̢c:"a;ha
 L(k9'Hq@@$__$|HM +~qv.\[oWO3

Nm`RC#%&.NM~qz5jsP|ny?2Hw&f
c+"XFo>FtGlqRsJӞ>-NϾЫdtM_Jƕ_AڴC>uY~WC;?t~ζ$'_swdȠ-t3 W9aP?X2@ilRlDo[jo8at/z!䰵2f"VA0rR}9E)Վd~T4zBA}OPOb-7R>m{N_9c-m^0-sr*B%jKV>Bl-Ĵ|dkn`/.&XY&'_=y-i~)xko>hǆ|^L@j0>P-ݤi_bF(6)+SciFuSt(ڭ}kW4ni݁$ɧ"Ryx(BQS~#\򓸛Xp:kA¿!ئ#4P?6p.R`)T>iv+9o0"/ˬ&]"G<J=~3㙘ArO$q.se)ivԁM~c``J JX.}Q=ҏ#+qJzO_lKaFFSk5^m]=&2',;4 0hG`B	) 1{bٱDwY`vNXq(ٍ%h*S /ma=^cDAcHT^-,]gi	4m-=-%n>﵍S&# a^ŧGLg]Yt=ZٜpsS{. Bi=~n}?:cMiB*C
{-~FV&mw=jl;!ds*WBAH_=|E6_3$+quN2.ONL"	['C~3Rz*rݭՉF&:'aWQRFh~-O'$+Y õ|o`P;vwМҫU,_(nZN9e;I
M$dm_dBA ){kk~цrG/hS&hD,yeHr$_1,r]ݾM.=T|/CFD'iSY?7)y`2k#y      }ksFw
ZٳDoGG99NqX^)4fcv %z?ݯ_r PU )xoǴn +++3++YϾ/?ڶ7Ջg?nk[|jk~Uk?ߦ<ΪiU4/wgï m/Ӧuy~mMqIb@}eۏ*b^uymlayZ?o}uS֏/@m,Xu]/-+u[]uo)rvPwVW6{xk-0= Zleӛ?,O#$+-hJ)Yϯ#lkr}O__"/򲡸{iM*C0dց1VQs&۽4KTNw~?gJmO?K?K?K?#zvSmyіmU`N)~'_G˲vimo
ç:>\HU_Ͻ `Bg87o2PX]k/b006Z-MKwO6N?}	ܕ*o_ux-Cj}}-*mHҾ{{8V9=}u'WeNjY
8:桻m΂f厢KJ[/wP+]W*rN%ER|d VKŶ=70]\<tv|--ЂKkSvR&^Z/z)'$zѐзt
ų'GX3- vUegVn}[A`{1,ʸ|")7aay{3aѭY
)0I
j5tzGZݖ{{ZrG3֦h}tY-L4Vv۴Jqa7"+7eDTVݰ)؍keV]Z`i7wu 5'̴Ͼ)K<
y*SǺl[9)nhDtAK,Ts:]<.q8+>aHڻQ63d7#@|n
tA0MͦG^=7QXlUРrc؋޷ ʥ?3g)8ZmnԨ5t#"uPrx6,xjG5#.0U gY-l8-#=y5TؤU\KxH݂eggmek *j2XDԆy*7Y]Z3m4OPۮ6]'b`;}u3T/uCEo-DT7cl{r^9~gAMxT Bg ]&~5c@!m<,e>X5~r=]/CY/7庯;ۺΝG28=O8A-$ٓaYl5}^뫢*n4O,v6V1!AV~!w8[XKcPv?'#)@?`0-8؉KF;]j,OV8ˈHǇhe}+NwV`휴u>YD
2oA_*wj-H@+3򳦅xdg`	xLhPPn>j#P1vstEY.9_m7]2BѮ_},v;8_Bͬ҃IBKsNLzr8:m]L
y Are`#B$=F)4ןF|=Y*9veCE9h$bh_HN'MP!}P8	!Sz VQ,W0dl3z
U2koQ 1D/AlE3ŧV|:@D\X˗agTC,_y0oHiT''
]st~A|!tBH)t6B_u$盖S(b`e zvih<h[{ 8/îKGiu}bĉRxzN>xf##v8àHښӨ5κ@aSyW6庬!_hC5MOhga <XKOK0zH	e$^_ˋ8m}E]{D+nY9b3cN\e.|wk]&^GaHxjE&oRط/		M *M3+Rv]R^+,G~&/,߈?ݠSǥ$r;ƺɯbW5_jȖ=j42ǷvCo̺+z~X$$
22e?QcOvLX>%6eU=?C>#xm+# Ӆ]	<Dge7:ggD@eZ$Y򗮇߁A ܕ,}
|܅.Y+('߷^2{K'] m" ^/#	^z8eZ~Z&wKob#4B|Np,X7>y'[52M,£_n* [z W; $
`&Y5}Y+ϥ[;wgGB\Zކ[EW$)C藉_ F~Vvbw O5<ꝮA V[nP6
g"@r©{;`[Dj	vy["y9Ub'ʲm!$h_eϣ+C׊)XC ]M\1uB6'퀺> ԃxJ6j1гp&F!npO}/"^cO?8=CgE߯2-rE6x$o`o#{ /l nr낲oG,@Kd9PրԀ)܀~{X#U"^U~ٞ$wˍ	o<בFoϻ	vd 1IRm$Fli#6
l(RԢV _2
g)wP``-kd'`~AkmleȀIކ%G`|@V%8)E*Wt#aǺ'Nr/{цq*tz[Kp6saom*lґm?b+ N/A8͞ނdHm!,mRrぁ%v	E~Bʄ6K{fʚ1nmX߫ cB,tWf_E=_{o\siM	zfes[UMVЙ[pO,WE:;`uC{Xe`| L8 w	8Zx'  /B>:Z~C`}rAFD+|I𘎕C"af e#2Z KN7_n~}kwo領KL]/q	h/fƇĠ4<`aa$:$XA`8 b "lO"ﰁՙ{,}U!X dn,CF0^U>#NzDJ AĀX1Fr}24c7866f6_QſſcM)As_chJ\ٴϛۣ16 Q3}Xz.٨80vҡk1P3GP,8o;[tָbmwn v2tʠMaLPV
DKhuB?CQ7JqNGM71?&&Mt M61ؠ!`F=C]WA\(ƞ0DbՐ,M+Ͱ
Jć!x nU6^ē8^Ւ	ƧWA@!M=nG1.j\;t#WcŮ("DoӐVo9/8Wۺlg6)Dydw1*@	F&P}hV["Lz 1-D[p^*bݻd9>'׿pWVe2U-^*6{PA5Q-]H܃rFXO0`L%p+';NVNcA<(G3',cBU@C<R7C<A	'7rkv'\W6	3(4fq}B#f4#L;pB8>/XO\vhMo@m o,N~> #,~"ygfFRtPp&`	p]\ZLLDo'k$8GlO\z> =8NkoG^F@^D88kσ1وM0CT :\& 1)60ܕ;r,˙
!f (D^ cVX4!H@;C~
lt3Qk4[+>_f	)hE?ŖAft[.cZDÓ !D200(Y:RHŃ-0\lJ F# ;
^,@$%	~7t4z f'N}yrQ5KIudpZ5xݼMBb6a&
bDH^-EC$/`RE&s`F2/ |2Kwlg$'a1a3dw).0^M|L&w)h/8`%:F]p1Jzz<?_i仄 !Luz}	6 œܫeuCd`z蛞$S,h[w 5J|c%h%aW+4UGy*/pU*⾊aA+<.
=M5ZSH 
\?^O'(j0s\M8^M'1킩\͈xqQOx!rtցkPiDw"J@\O5#55uBr9.jvb((B(&;#龨GfU=6]qABj'ws]X]T]q_olH]X]}^W_z7u/
"ToGUETOh'K\*^J, !/ǛM.D(>sO#*]>}~|S-y H>b<}omt>KtW:v37ӽO946 @ ` nZ `<P>0!fEP(Dd- #2H6kW@q"oi ӧz	-"_@E':I TiaL6Z^Ng$zVqBd0fF*9PEQAPZnl f:Bx=5Q ̋׎7) M /ݤ8JʄJ9H 1\@amsg6]ܬL0Ui
0EyQ$yo['Qs7|=G5`aѶ`3h3b?]cpT!U#QU ỠB`Jd  ,Bw3H"Utsc]$EpRUS%}I<5PWI ]a3穉ZMCURSE/oVU/Õo ঞ&$[SML#?S3oUAQ>x1J^ 09;Y~FqCU mHग़{*Z *_HB]őm *[7BU qj\=d6zʪ HReW&ADE\M* 8%<q`QI#`HU~#`[U`o$;08^#`L0^GN8ЋpL3,s3ZSZ>1p6*QiW7M+
=yAEC[IL_EǇ8 LN'- 9.cFIM\%y1 i$m^\F h- :J3- h>4#J- hDr>īH%B=\A8Z &4=ƴ&7I0szN4T$'I#	U/K4~%E (iGjgq!sAO @mT:gzq{z3}&]m0t6#oaq7*eEgYBpp=-0qgY4@ XLoE*j㏶jE&ko3Ǣ3?AqiHm6+gcG6à7ͺиX7ܣ8  l!*Uq`SAz&dy+- Ub_O$جoB_ lF9WO$~ Y^`-'I3-MT\rB:43>}@|F9&j̾6Pn<Q'=TƛUx&,+6#o\뺙WnU'Gӱ&5ðVmH#f+ ,S[8Cu>Bd>	e!7k_HD7&&MdD\"@880aX+ڳw__(XDG ,KLXq@x؋ 1UļN2#H$ardņ5t]#c:YYK;
5&ŪKerӿrnPD8	`+1BWD3H\m[33ʿNIVErNGE0Y8 [SͽL3zGu2N r'zyfizݻID
AfݔJ00A5!ʃL([cXۏlupC0ϽbET)DL1 Z - e:ǟz
?Z `с?Z J +6?E~[iɓ<3C1MuEJjC0*Y9*PP1[Sul 6f(0;g84f1׶p+4*r7PMw^C]`Xq uOC\
uґx={"mtl{~ئg#@!yC'K~u;"י?4 GHnkn4Ľ.ϑ^7?Vwj0@|K,?W\G0VGoWmtOC(n2Cz0d}'7=V
V-z^\ܙ\ȹݛktxMXƤz@u?a_ ۟۟SvvcC`p vOZ%PjkH<pՆ˘tyJPciǮT]unNΩ_8^s<]s<fET1ړqk
5u]5q*Wcf,ul~ܖmt VT`qe_xQ:5.fO:inȑ>5Ѧ-we[>{mh獙mmޔEU.B|̐LK!-'w#L:!v/^҉DhrTo ?	v9L[!]A{XuɎ?C-擢Ҽ,v9aZ:B0,ζg  @'
plnĎBڙS3G9p-Kȅpb%&Dw7\*=}N¸2a%в-/k5Yok}34bn[&d{(H>HbpHԜt5G^I	5sv(@/t#mi,s핝@]($`z:UqQK:;/TTRR+<#n}U-o1W*852GrW.a#تH7G^Y-`67#-HVy?6iK{
XSNpgǬd%T6'pƀ:\u^dHgX0DZ;z7 	vZ.A8@TwCLXy-^"xc!bsFU#FB"_ȢCS6:X=cڻQSoc*oT:@/m:VD
.<$ד|=ewk [n0D4r." @8^\:2p@ׅRj{^*XO=B|8Z^7Y'=ΎH^b(#Ϗީ}o;1:wsHQ*bj#b$֠bTdɈi*6!؈z(neh%c[uQ?Fkyvƚ鮫	Mc.G>a3q4O'5H0
óq%~z
6fya]܌Aw}mLauVs`u>EjZL`^hUHwM3Llr[B)/g,(L'v6XRrn;9Skl ۓEnjfPr|R/ָkJ]AMDWZՂ䆫11Qew:2ue]Sdxٟp@{Vq
[tDOS>;Y
u\MSH굣Ӗ2akʱsKOٚ+hgUGGUň}"`NVly5fl%ur{p"~8?xJhK p"Z7\se_,ڞ!,%f)FOKר8<v(:h iK5⒟
K^&+jtIK'@khp$8t7}=&>[. kBR"󀺟^ލ^/;`;9]A<-n#BY,?=Fg_X#wX!wȏ-aƩ<5A&gqI[Ir]Ut\XT:ñv%%,FlAYap.MjVb%>ZX溎cQԳK3iEUx%iD.1K(Hpbvb_dU)Q5tqo\?`;2@8l<ui'xD,"sEVy6,z9LBlOb/ޕo'PM݌fK nΒq\Ny?*_X3fվ[c-t\B Z<\8p0?\mF8u7央<5|H.wt-:`}UubGl	@uZ8FA 
lu|TzɄ 	5.28ZXMqr]ȪbJenov#u\MqC#{^?CV%õ5'&hI=4zHS{6%N:Kʆzg{0	&aBLD&M0I`V=:#+@F(ٮmlS6	|1mQ-W /4S3rb5_j{ym09۝Rw<@58^Ǣؙoh40RѠ#1&Mɚ43JZH/WF]]vX=6R+6'REO^z<QTV&GsY#cV^J	=:OeE7PVV|aƮ@QK7nUIcPy߂kJ	{"MmU{4\L o8v툀7'S=[quZj8^/iB*
2\obP5	fD($!^ 
]r75rW7Eνr>lLO2-GH<c	@G*0Y~aHݗJ=y?y[Upp8cCyaąP?xX< G>Ws>WP'KfkױyCqR(lA˴n[e+Ӟh󇴋O̧j;fZir4J-s(.)Gs>S^-@K/\||$ny.-][/hǶ/Ϊb{|7VD>ݯ!.3`)YTK@:H[HwHð,]@%5g,-mOْֵ'בSHON!7H'9vqv=1AIO$>puG'7vX<GvB4&`U16!8	Z"{Fn@hWG
OۇIPs+V##fhKѦԈO%֮/@5'xvv^TR_PEϳwt=T*My轙3GfONCD⤥Ot!I U f"u??sޫ4 ]Z;oxBS'?`xBS		'$rF#qK	
-8ciZmr??;[]VEwby2icogA4<vGCpkITi3:Fp+V|BOSjӄIFƊi+ޚi:K1loc<
[0lVAv;˸12XƏ7>gY|&yh?nucvy	Z^:WVkFOl߼P?.RQv>NQ{	Y ^ѝWY(V$G0M'&S5;1c%p}ӦLMޝ0
8̈**źSiwlԤW|>ՉN)Od./QzQ:PF!T~:v?:0إ;&6`2\݀>"eƟkᑽґz)s,gV(Aq72u~}ɳÐ2hĀxt2tʫ̧nR$ݏz럙khw@$@5 "˞
`:_,N`zn>[3gfa>RcZ:: E  p"]2DJ.$N:I@ܖk{s
bjeNKK;|]O⺽8"# ߝ[o`-\ͤlA4̛AHCղad4ZA'o@M'6|a';"T5rVˁ.^)2Xvݽ |i% hhڻ>Dصs0s_ MhGײ.}6vk	">ʨ Yz2.~|\NP%rQTF.t6\,Zjv=#L3RcnYb X3,wsfr	9x`tg	hW&v>2Cc:*4p jr[,uchg@.!G2t->v^Ҙ3hB~a?|R.v}I%I 3LB]*`;BtiK%ikww	z>fCnw_wZ;vs^Ddn;˒zÝcx8=~eǼ'Ӵk<NtycmjȐIN6u)wj3 U#*'靥|%GlŰ-h5H!hb0q5*ɄIȥ;K?(jd=}[Z_<6^y02^oO!OϦsRmzPDw mzҡNq/ VVn!
oJ L@_/(rmlę Hr7¡̉>c"a$j[4uzOs( ݑw7Y}kPz,xL4sLľduy@7j%}XhNLp{!	^|[W,Pw]HO88.E"촪f د"ŨfC!'m&uF0=O~L[JҝMfo/]FA,Yak&ȑ&/$$.83쪫Fب<&n}ɒ6j>$_Z	z^ОP~zLgޝ&|̭>&6,eD@:kP>rUO@smЉ2[eط-'\&;G܉9UM-X2(~wl+=si|92Gł,s ؽs,IWPla.faONq~MV e)Y6[b,ۦsSܒ34)0G*>KŻw ^t3uF>v@7m^"X9-xٓ?Ge*rfd^l!Y^άJ̚FWe-17WV|ǹv+DhfF:gxg]7"șW{;M
Gx=]JzRRArP)J!5wtW,_ѫR?aJJ);ѯ[0/H2RYUfP sz/}K\GUE[T}W6HcYXOॢ/#$*"c/W?׬+Bi*fqe?|@qOd*{JZ":o^W*E^OKa۷ÿk8<\P?RH4E?zþH
{m`yL0[@%rMY2BRGrg(-)+tl1v<.GCrUpmnիtStƏbgMΰu.{xB{DWV/?n+A@뢭dibiH,KjALtFj y<T	MQ*LL7H
gpArCOc*KN3N3B"|ܻAHBLΊs՜:RWeCZ}BĘ(~DG%N*ȸc5j8oһb@޴2
P(MZ?-ߐL%z5uٴ5j|	O : .OhKMb*R@EN1B1Jf̢.L$IbL镎ط 8.(1%d(gO̛Q7}0hwU򔈣ok6GC%?Хo1YgZ
K~L6,ۦ0~f>(RMbf דzC#LƼ,,N]Tq͙y(5pݖԯv9Қ;-5T9;\g%]FGb6;2>\`x@jM<hr-
[#n+>ji©#45C5Q-Iťu7}-b~G%4̘"1S(kr:Æ}S';c6YR> *|.j‏Bdϋ3XftA^?uݮSN3aБ|WGj]p#6ͿHJcwBcJj"[:hYa%_ܸMLf+p"@c~G-Ȧ8h.^3}b Dw%7wHvүF!n)Kw.sObJN(xʖTob,C#"Wެ/LX9N*~!;l]O{z,{i?0F@C&
W95inKfOl;0|zPz/%$Pi
uw*'JɰabyzYhl)5􌥚 -Ռ`@fYnFԟi۸oW8s$iADEM&@D`Dm/FVC-XTv% `Ġȋ`kS.t{Ҡc8 LrRfF!Dc3¤2Э
z!=57^"/=IߕZJbȗUOaqUwMhTV֐Ȭ18;IWcygPpqJZa?S.ϔIDq\h[-G>;$RO/J)ftSnz݈ wI.Z.Z֑jJŋr y>A*wFgRWd݌=jRB65uFtI\=Z:;Vm'$yj`@uYOIM|LO>o>D-1}[}a4s)w`V<xw ĥ7xWd/~%[)jF8^a6jk=pBWH1`v!1$TGlsg܏^(Ȧ,y@Õ[hf-񝱳C9hч>Βv5S:Q=-fWG!
'[QYxhP^{CPǐ2l,tXƓB-]&}YQnw.NڸI&WF;$z8ƶš[,Cf!$wԏqNG2A;AwwIp'3^u5!Y)YY9fѧh!tOWZz e*M<&%uaRxۤSXۆ8zOTx̡6jyȽ3=KܛmRzxyyd׻v`bI_k¯ԸaBޠaB$iV~cVygk}_'#v-0au87gI$H^sa:W¯I]	or`:.ɰ%:xpp@lk)e4w 6O0*"l&bQ$9DCãUxEq}D,B	uA$*zna}36rKG<除CuS_|">: zTd775ZTtS_t	w׋6/YJNmsH_d(sjb/,!w̂}괷A%WW6s+AK~0?){hiGkzϐy"m-pfzZg[{SU~y'Lҵ
}ǜ+/I\*{[-7tnƯQtF)ŏx]YFE
'ǋdݪ[Z7(Q\qó[ѧ~qۭyJc(񦉡آ[Z3PiG-QӎsQ96IAJ{iS#)|m6ID0o*5PH A77sSȊeSCSC7k]ٔ"m+IO45&V#NR?èWfÑG66f#ǍewDya*@L07{Uۈ#;rƈT~{8"uBX;l JFO>U%KOcE9$m:Bov/c0h#RO1<︡cQFdBԝ,3Hl1lJL3{{J)hv7&={ާA͛ lX[Բ2;]Ŏov3	~Nט9e(9PR"ofS>LU٘ߣ=z~ַ$ k۳'C6|}rk0ΑPe80'y&}ӗh9u	?3Xź翇/7Ul[`zMZ5 Pϱ##'S+ܼ)Y$mǛ
16M안nb"QǅY~fpzXa4p0mǊ;2	'fs^Y8]Ss^-zރ_zן-:GWh䕎do1=z7&&H¥:Aԛ{ō..rk{}}򼃙X!c\9%E_?Ό+,HFj,n%MD c;h.R{?+ekTB_6hN6h)}op{~* z ŌVVb.? bdԥПivs-SJbd3muB!i<ݝB\J$©J(3X~w aUB/]`BG,sl̥q+u[aO3 ߴs;Ť6}9n>gN2*>#\$O@Nd?g8t1+&$ZX}x $:#>{0"d8Sy
F*;͟!W爁&4}`\H.UD&Ur1v]qB6A6LR)pL}=&Fo[^V]2J^wXnB2 בK
9MP1&6,	
g	AkS 	Џd_x^A<F'"y<Wп*L*Hj-)mQ[s(ުxCǾ߿?|ZQPpul[4HHn01Ev1v*oP^%iBT&eYr|Fa+1rlF^-S<tj{姅n'z&nUP+H::_҇lKAO=OE3Kjz!tCsG~z-;P*#*]H(Qm>ߍmZ#'L'E/$ADlZ
JR/edڑV̯ۊ[(#PF^qq+'<XxIw0羅PzNbG\MHm󄕾?yv\Ki$Or*^`tL\O"|T%m?IS66g0C|6}U7E'QI1u})ҏ26OM
Ōmr3V
ީB10{K貵[Ʈht4PIO]^!D};pZ0<fWg:Nn)?;spn'|![t:nN#}^ЋΕm@qo,yL/$N1xJwun0$ɋ2+0 ۉRW߆o&x԰I˜ _9`:3I~1k=YHKi@$~%,CPK2!0&|Dnj#5ӿ5!g~nc቉y1Ab1+,+jj!̒ڑ/PBC-$@L)qva>qGdVܐJpdAm	ZOٕ?iJ|tPpF6.2WpYZe],g˳~-qt;9,W߫阮ˡY1/Y˦v>?cwJsR%x!@(Ҕkլ)}ZHuq(ҖUao7#"e܄vx kAAH_=E6I@NHToܼ<;1)+0ly'JՃ\aԐn!P5Z7I>	B2
`Yrs&'# #~/
nc399gukI.([MJ6F)4$_
ҸfWqn(w$m6e^G"\OE*jx+)}/޽;sIu̗>;grt@t:hKC7a& %Tz      ܽZI(?ŨL!==kFrnsp_fF%f@w<yVg}mTy̌\-v+Ϸ]9Wvo']1[ٙMoI^W`2ɫ|)*_)WERI?_闃|>oOdVWg{~~>jlF+W9B.gJ1|`wlq=E9Z*hzꗣA	I9nnaOW$/v&¸  Bi**ףJnjO&$WWKrͰʆ¸? iI5՛rrWbtӝdDbĊA4W9ZPf|
qdMGƣrzg|B|&c~4PF yygy2LqUz
0zT-ZNQ9].FB QvEA8䇉?A4qjZMו|՛\4>fH= LJ2\;-tDwдeCd޾*F zMKֿU 'Wx H!NA2f0l.EjI̇BV@D1Av)_?8,i>']LOQO&C4tRQW˸LOmY1
	d</yɬ3Lk񰘶vwq&i##ҽ=".ivm)U5ce4)'.lr%/-9,HH(D%S]I|7pAQi&m6[l/K
臢^|4m5#vFj@IՏ.Vs{;Afl#+amm.v6x&6َ<,?0>gU윟vZǇ=N*!ͻ6V)0u.k\@ZаLI):4aף^K*ŅUrޭ&l)xq;mRˁ5t}Um1a9bZߖP}W4nX%F*,ڸTF	yφCVO271,KT+kg/#Jt8lw)5NTjx#=uDhr	"µDkh)eQ0`F
LCoQ,H=>zlIz!0Xc,$Qxgr=$Y1ʥfGeMubb9r#=Tb@NFYq7,uҫ":D6$P)߱zLjqG7oRɅ!X@^0<V!8B%#Yt(崠+{y՟i9II,Hv:A#J5f,G2EL"KTDz-7
T*xء@}+F?.m&5_&glF;~[ޔPlg^MWO%QF0(u]6Ϩ~Ab٬ϫ*H讠c^ W KPhCämYIf|#l3c1UPE/L&ٽa
Vސ4mƮ164)	4ónn#EұJ[v_lZgIϋq^2>upU.*lȬjģTUBH>*BcZ+VuCx@@#SEl8Lk.r,L"}_?{G :w׺j]pzet~ ;ްhvHB?:*mPZ[{J)6%6?/D*}SOJt7I~&a!NN"K'}c~&,QuObRgHiTv$K:t:@a4ۻ5:Z6ٞDOMxMeŪƏ@sejAZd+͏LYެ';7xXf_L-|B`RZ$<ꁍeqrßr9G&cmӻ
[rĲ|5*}]khf&)ir oEYw67};+ʅb1kGԻf|<}J&kd}].[$!@LE-^WVuEq	tdOqNBJ!t/S0-63l5J(3jo{TvN\h`OAо#&|1ȿ_쑋tc)xpGv9߬fcd9hõ6]J࿈d*dOnTJ|ҏ`rR&fhiO.kCGJwV/I|aWӖS2nec"+~XÔZE	*HOy8-JtOh;_f=)ъ"Uqդ)Y@	GW^tNn9:lf`MuA#54C;MS^pDi_/:U!ṭWˏ];I;}OoNw8I"rl8S;R&RRժz5σM1Ҵ"F2TQb-0<+0/&'34J((w=}Wkd7S+g6pa\)wa
oN.$WU*u[DPBK)2`Iȃر?pfwϙC㴇<lrNG罽Oߟu"3JޛN~Olswa%$)J!8>23~G1;9<׉B΀yp;9=to}D!B?!9CwޟQB4J'(41?ƴhYV1В0m2B!Ų᫚K[>LpqDq߫_^s[{y>ށOjRMk+kkY`rk66*-$ƢٶuuWrPu%sMՉhP|BtlRdCtq9,]'I{\VFtt469N4ڲP)tFyhzAKʃpEVahYЭ<rWOonU#p<,WCst]Ai~(s٫i a6@H?DL?,ܟdj~ZT-e(8Ł٤ۮ@ݴc%)YTOyXEjeL^LRC5Q*P십˔~l_)Q㜀*8gܹftE>BN`	u4ɟdFer6?iK|Dxuz J`h]-yh:[C;+^쇌@Ǉ.%χL>lSE_nMbTyF5$rΫjMە9ZMo([WaemS<V^yGV\ckve[C'o4fpzzU*W'0te`]瘰{au9;脤>ghJt"$w	Ԕsw {2I/rS 2[M괧4hHVTus[== .FuCEgjzPl"n@lb0j	P4EkoGD0n`3GխMH?"dl^I5Aڷ8o~m @{)U;}T<]Isbħ˷xxn]fK.mlUh.,&ZЀV<*JV*ҴfˡbJ}<C7PR[E`	ACaQJ4~9D*h=>s+:Q5M6ZHN4D(HD~k?t2_w4_?/} hT4B1Ɉ,ZU*HIԛeب&uH\6vJ|d\bWmdj5ItD軶_FZn6'و@llJN]xytDr08CvM%Slݳ[z-kdh"nq 7FkHPE%`Q;tDFv(鷀a:1.#nPWgX=gGgCU &zhayRwvTVXό42zZv7FI}AéoĈ1+?P|}/Ur}9ר7?c-z_wd>4?!ut>po.?|!a!Ň?t.-4^%`%cT.>R**kD*3Nno*7<A6G2d\()wiQф[lN1W<~(Х͕g Zyi{^E>ZZ%]]mlSbedL#a]'6W4*Ϫ6SwY~)w"0K"O@K><Z_Vu47@ȃ-*\j`w3(z `UjG_\.A֘^4èNёz{r`@HHk^li	9v*e2Mx|3\NuPQN+l5u]Vtݡ`wi	aX`<Cy5]D|D!`5k"D Gq`~8'%;tSLSLjQAh^b>W]E/Q	L Gx2;~tro6BP֠5Z˓KnV??9mZd7~aMu(^4c~&.鸟3?O_OBgHW^4YxX9[aSWvv}*T"F9!壌p%r+a"v jm>@zBw<DQ VI?NvV# VrX j&h:g56ٰ#ڍ$uO\|RI9zAƐ+"\lBRڌ?(1bE?(r9="/uѠ۩j81=\E7:x3q(UwB/`wT𹶆+ųM_࿗kkrŅ"X0L=.TzQ[3:K_}%0|U}>gk\a"
7FTT̩>uB"=4ĕ}!{Ј:nm={5!+vCwk=U'* oD_W=S:zMъꔘK֨t^K()ht5@)t_P'_lYtYnܖq\.A>T2+z味ȩ:7YT|!	-SV1CհXI[sʙarY%,B`"T0
OOVjcPs76Cէwѹ;٬Ʉf2|*EfwWD?Γt} xӍdVSPPOru"бlFE爨Dw2s05lEG0O	܈LTǆcc;`]d6Fh}ZBzLBtDzp1,P`*mx:KVh8^٥>Q S~ `u1a(c(=(W-WܐǠ'vު?OIkZY#5$>e tkNϱ0\VgS.GK;mrDbů&n Ea7NI,t1kībeM,no 
jgpB(gXpa,iCбCЭNͪQP{ p1U	GtX=4݉aN;a+»Q\`x!=e"vjZ+~Ѳ,!LiOr8tMgN[(U2~@zHr*T&X}:Mݦ2t ']uϟ۟m[[[$Do|*ϯ/47~Zq6#bUEѸ,02T3+vVecws1vVNEfHkk
%pbk]$T$l/|vȔKKR7ԮGI7}<]EE[/3N5NVswgKHBaɯJJ,,)RŵEFQ7C?&m{dۡEtX>9{E;";# |>TOK6;[ N	ȣQYI4d7!X6"#߉kAam-'F85||,cZ:/O'x?-aNJa׍ޕ xQjT#"''bP#z8[7Vinkc!Dl|B]C=c䁋hbR~\3b"&Z0#9\>AH2z9:+q~cwdAC^-y|zJdLgs>:xDC;Q(P/@U௦zRs`ԯiIFSmXYbxl LeQej]ZVްF;K-0ssmOYEC63]]26ԁwt+#*݅^+.
k6N7y<؛V<TSaIs:lm45ΐ4)]6΢,m-ͼ^jC"GZHnuCSEvs|fELʾgDM$&	V@f8bT2 &/U?89DMyAd]	gU>am6_gjJm!;I{Jen2QH%Б񩨊bXLQdC~Z;ael_xD	"Zp1}|l	=1 ײ"כAu5*y;d.u5ii\]v[ sTɁ4H2Z@}{e$K
^-nMQoTI%@\D[.UT|}llWID-".*G#\i_`X@yR\80uV%]1+@;P9{cg;.oɤ26K&
{^O<Zl3	:0Qn+n\JԦF\rW  @T{^ƻi\QCFPnE ~5%flsC%)L媪{g㳖9h#LF
$zSB ͌(F>%3<p?Wc{~~op,cA=kn39z͕\uG:Oe𰞖7708'\cfҲ8C<Teػ,<TשċYbザ#)X>W7_IeD3?GBWC_xբu(vw<nS0}Nm-IOa::	5ىlm|@T)lG%W_mÔOSU%7;o˻\Wܪe>X<w~^bT˾*%d"7dS+|r\03/F{2f 0Z?	ڏvUm('̶*Z?~RX/P~>[@:3O781lav1nKNHI1گr`9bB1늾lK"蜯f}>E0S y>NU0',5%I;~x\lIqˉA/mnH`4OQ rco>K3Usq4C\'kV)LN}cHrK>iԅ쳯JڢvU>#7g[vY|I8bYJ'MOGD,
ʻ>?7D^F""a,pa#@	]8FOB+u2>]Lޖp!sUsX Fj&]"5z86W=Yt@ʭw-a6p4,%ê7Z]k\Y-u[4_*^@iqۦ/OT" h S>c{>gm`*'rkIδL@Nw3lu׼e6X\IpkQ$2-UJ@F#$nOhmMuMq'/ -oM9X֫oZ0~e`	>+s}Jݵ⵵:8"4p4g/1-2SBMEERǪYZ(sT\Bbm(&,obֹP'4ϹKSXƲ#U{8i$':JEvf[U;MB8	iIhEHEo(TRz,u(ޚ,ymm5 ݃*F+,avvr碠Iuݒ9HTKt.biQ%{.l<A.(Ǧ?Cn٭&GB4N-=
qQ+
6rzWX;ҁ4NSF);+ %|ǽC׺ݛdtK&}/EΪ\u۷ۼ5s3gTA|Et] eg-Vt)p?<sA6J.ٔ	QEOegA\i$,R۸1>+7v4,[4<]Ib6Luuzq/Ok[^h1-qIC7;[~68<0uknk%	}O;IUYLW0U/~}ݹUܑAloyfa)GuO#j*,Pohê7jvoM5L;oOӇ֟ax5hĿ@6^~y՗[i7Fs~g_ B8!'oȿY;,:-$> 028ƨ64C(V'b #log="E0>KH "D	D|*J!rP(=$hTv?6r2:'MxNvv%:ٺ&+?ە,ͦq;peQy6E6&  @-czK/尕QY0+
&fUmCaw]s4q@4Q7m.ED}{͆_d#L.yMFR9 gJH{jɴ>]Znƅsd&!D7?Y`d2ޯDq'T+ͲPE58LxSKCvgG5݄[itTҞ  "2wf?^ٲηMLj{kLU( ?[.?٭o}\/@)r# ;$3dt\$qnaK0׶<J!mh/Q;	MZzԸdoP9B9pzwUJxfM7JL$(C4Lj~WUĻ!{A{.ii~De2kjFWd/tI){[L9B{XU?Iz#Iu<>fwr*Du]/	Q)`RK^@ᬇ"HKpTL[	A
)ZN߾=CH6҅{!./Ieb]JIpeYt5zXIp,l9L2Arxԙ41*+Q=3lTOEʎͱJW>3WUL6ΡD	j`iZUM0(I|㠦<"lSx#j_z>L3فsjIVj袹<`I( ^Km-
cͳԢRv@_=<2tp	:+IVԪm謤7ZrPy	!f?WE\%ygCVW<;T]3C;1\o/x@BA[TT.Qɺ=ж p(+AM _*`S,
Z[n&>1>C!`5\aఠ`g}lX'hZY0Ǘ
{ݺڤkdPB׸lWz7v9ϱA>pkCZc0M\m)>?o-\UGGpLwKKש64ke_@zU-_k[Z=ȩf"+wo
ZًT/裉ޟx.n k5ԥl<,-zL]SBB<?x-Mԫƨ	J?~^K(H\!ж4cIBsX=ZTMV{-}(.NfΖ ysOZ!%{9i>N;9i/
f]cm1SR_MI|R0NX$}*;#qK	``$eN|1]WvܚyRw685K祉ɞPcF<Ok}FNK3@.FB5ݻj[7Eq>xhNsvk7!gkj-I_do܁=-D`AG辶C7sWYZHS*3b%U<~d-p|nCeVUء}BNV)sNHE1[w":ӼALgJvo->`fW0f/b	(xʌH`1#gƣMpt~fEbrԇH>0D2kY_ԳfW)#lkH^bS,ml5* o3
#ԀvߣoTdFl%9} #/ۼ\@|+Z+4r{f]LMtq{jGϡmfpo& a尧9.N+LH Ф(@@MI	FlAW=0U)BPXȁ	r+Y	V3oDGͱGtW^]v;{v?L.H_w6Frɨub wVfꞶYr\yL:T3m(	d٨Do"Sx{tw+|a*JTuvST0w8kD359t`ײ2^rsYu{פF#	ZgDt;d*1D`ѨXWQ	=6E:)TAaD)V12ٖ(fh@xȈ,`m>ڼH$Vk*? nNF]AdcS&JLze}>M79 G_|Y)#YA{B_=g̗^,:MHk&9;;x;)vk]z{Owz?K:xz_^ i~sseGc2mqgg>?ug nLc Bj\:dz-ުKjIvQ6E`%>o=%#`0,~|n~탩]]ʦCk_0oo*'^x xeYzOѬx?怫kٵ*BY=SX\)B(.GU)_Ło7X1qql$p4ִ眘'+M jVZݖWk=fZ[ȳm	mxF1X 2bM0$Z?u$9*B쥿<׫ǯ3j.]$>+ySUMNV,U+J2\E+%& s~azqz𥳕w	2IiQ^'YJ[/'Cm/}_ԏ{?MCYŽ+F-gM89"3 ~>/x=IVֽ$Ęj3Z[[ug?9|,q3SƁbL˳bˠv`*G5{-N_ytAn(BG|iQe|6*P{0Y\DSA|zŭ-m:bq{`6a959Z,ƳfX޴dVg]DU߸NJ/6lLg*Li)36d-f¬56if&Չdg@:qE?? ܜÖy&[ xf
?%k Sv6iy(:#rw[jp$zUp*Q>jcx1^5DtQq&vzn]޲$Wl5y*hN8P|u9VPWjS:q]~#eOPu	{4AB̶њ\Ԉ
m0cGlbV%mWGN\PS;ŠGlUg?~teSpfq#  fT\)kΏ:KT"/n2
àl%xWpa)u ?'v4$w2/qDt@֐G}ߙ+$	Ejڹk2_DWb3G@/6A"I{W@Ɋ:U4ᗼvQl-rY{_D;VȖ<P,Ԇ:MS:U-(\ФcID@-/2RFqFiC= [^L	zշbb{=i!ɓP՟x+KXT]SNT,%L2dUK&`q2JEs:0hK%Diފ	a!Ɛ#	4b.[O/TQ5i{?vjW2Ts9dv2+q!V&J즦](KjZFX&@
aԖ:E#231Z
_ij8fyŤ?$zRMXuex}iDwhim(}	HI7:0т!xd_D"2!ߡPe%*oav7a_(ޔsF WSΖ$K
<@oƴt~sTҍ&q4CxmV_/Hl
o^g)]0|?D"%Hoo.Ӣ:ʎZWNr瓣|bKUq}Fh:Yߌ3X<xreƳ[g@niځʝ>q9diǾ,'?WS&Yqʍ}3^V6d@%p
D.y*(N󘮇u]`#$)^ܪxVNٛ0ף8Zr>`*x-P5ZPQe<[~JȗL+\mTyPqLqH=׊HEϙi&NrJu_˟jj*>aʙNmVF։ ȫyk)eDϜgs<5#!bٗ'Q.ZċA~Viw.'|%RUT_|&Koln	uB`egSqx<+΃{H~e0iWdXا/0GpxJ-jwS>ܬߢ6H_tXZq##%v`JfW7!T8| zs5+=\ VLv˴(fE.~&̖ݴ?zWoq#ÍXOE{ͪxrW{_!'B-Ǆd$.X$+."KLS oYK_`.3o\!R~kYh4RάO'ʿbϔ7lrwד34r/zu^]?cQ>%qƀr~b52uUݮphm%ߢ^	O%dΠsk;yJDE|[TUޙN~4J
N^ն;f0j;9?_[[5j4BfX{PB0/_}&=UCxq> ]i.\wM޴"{h>y{p"p=n_r(\FNc")qUh+(]SflKi"i?)ƈ]`a53ZsjXV{;G?0C&@t{spY8tjE#n0O rGGO*i	?>H$G0wh)czsxsя;Ӛ8˧x	&WS}솧QN30p^jVqO: yr.`(мh 9?<SO.*| sz?y?E_m_ӚT-]7`uemes;5-eW>6._XxWXѺĂ7??0GUGrM4mz&b\@!1{;n8uʯI:vl6Ey2y6.)g]C
^mԉYaLY"h*S떴jkcOĘgmHF,duq;x[[FzƋeIXHA%)"띯y]cu#-gkSq޴֗rF6ueg7<D3,+ZNZ!M\@E:ϪrRhՃثK(D֌̲/BRP6v1PR26ĎbV{AcD]Gef%Hd>Okn |ͬk/~v25`~ų$W|ګYG /^AnwI*Ol[h'@Vw+QCgrHF $9{,[`ջPX>=f9	iYqw:X==f:Ey"&\#4NR)u,Ԩ˩{B)@o@:FG;YMg<Ӱ9zzlsW
ő'-u$fԺ[t,69<pJ=|"L[]yD&z֖WTAv-92rpNAsj	far4lSwxh;L.nZe(fc~	
1VCqírRAId4}翜i}=y=4]'9l08C7gC6ԎUg~o
_NOHcrwXe+WG*b{e4WJ˹5|͇*3ˢ4ʇMf.){*ȇ蝩QyǨf7O{WPu"L[[c?ɕ,f3uI^歧9d$x"ʓT[GR֘aI	OkFrYګ Rf:ŴHg\0n΀θ9ZJ ]2Js}Yin4Wkm !iM0azvbX/#^h	bFaԈ^"ZL:\V
CO[}c㹥 V˫(U.<4R#T`OBWPYܒtRh&Vy~U9-JӸ&[zC1>4}BSDpQ9n0 E	^S
kH˾8ӆ"Ↄ2ƳT{+e:\}	KtWY-5I>.(Dj Q33c[4z XUu5. p5WP1	O& Lg'ZFwVu6[R}f]s,&uqڙ ,ޛۉwXEm[9+sRE,5m8|?\TH
RZ0 OQ(gS; 	D#@膋6`7OԸ>=~$,EtO:;ؑI}tIA]~w/ "Excπ6'7!M^*+$Ȧ
:ɫ`#.'aҮg-_UL5vz4QB ۊa]#LKrdy5P.4@[qzւm%n99<9m5"P7BVD#rAp)NӚ\FLQ/`]Y	`_NU9CEպGN^bspus%T>x񾃫OՉ4GHk@b+wgԿEeX>s|;;9=l<OvޜڂV":R?㓽zz;ggi4	;:;!)wye;:Q!ѧ@QhzȷHJ .Zdn	^v>*1GC̆ikymjZzBv
CJYMǛÂX}:!N_7 YllѭOjai-VܞS"Y,--=%[#lS`9j80 Qz΂yaaO d_~?5;q@DҌtCvaY@*Զؓl{,*{xTB6XҢx(?S^+坈~B#r/J(|I~Irт`2}A{E6,opۗ]CԕDkZrLgzT7tyYl$gY5@9\	cMa'1K+@ꈞC䱐IũSj:#ՐBeG8-+6TKaHMNﴴ5Oyv=>/v9j\-i"2%
ßnbE7+knYzKEӚ1-*CoL4[iIT.?0QJdXUy?VM1ݶxCH'Zޫmbݘbu.,qf~xZHNfѝ*%
a\\6]72$6dg2.tY*h^|m#t"/
E=Nu<]fn@\M%X;]F
=`m$ m,X*
 u,-ۖỶ=|ܭ92D4]:ԅ]]z Dv<JeexWM5|ap)6OI<af-@l3_x0lO'
㤺%t	V%+R
wlttҧ
=3i&Gy>Ɇk: ˑ5AqE4mg
\;A%O i *~5+:RhVQjN+t5STS2TYt˱_ZCqkkQ|Wh1"T2!qWY@Ê
^cs.ne].jg-X{mj$n(LMM@4ڊ4xRc}LO]jfE#^Sr:-R}=Ph"yX'cS~Ov4PCX
>/:~|}@UV4VE)<X:Č:l^ΉkFyh!\S'&!SgL)-3JjKRvS?1+jlaks;bҸKбE֠in^K[?x>d ;>n˖o#q̻(uSqO0Uճ@9daWQ1Fwde!s|v1#|6D(ڻbQpQ/	;) oHygڛ#~HzM`t0l`/fxj6@0ڌt=.m6*%gJ ̮UBѿ"Kδ 	6
(Z5gÜkD{n3$px6|rUrJq!!R껭g-m1hnr0Lk8owF	E(+k^Wq܄^}cy=\S5wk#_,TfӪ6EI霫P8fZ߼I0Y¼=KOzQ#bmF_AVO?wB
?)6ʀKbo{O%,H!ϗ76AO~92,lo:#ܿ3up\.	}EHycZ^I	b%eéEoUVI3svЛ-ryͯG4Hs\7Qс*gcv	
&K_BTN(@C3-&^p2sI-"]r3D2/VޫH"88!OGFvhޒbye/3oZ7%T5[j#0 !MAWUt\{|B8j(1pLk)ז4ZO8nWp@{!˔
ư!vq} @͢5*4NeG=MIa-{lȎVnS[aQskCV$EF{'a?F=Z S崙8=<oXT-d?92}D`9Ò{614>bQ NZI zueϼ2ti1È!p'}j2:Ϯhjc6UKW%=-%7Ck.4M\'ĴpGL-m9| 5kvPe
1Mdz8,W#jI^8IEb̓ȓd7XB0޾
rLc6ArƗCG 
lծ֑"|TswbB&H9%CE^-gHBOFNzd~$yyp摱HsUWΤ[+>F(Ӆ{k=z'*7ೄ*|N~Sr`@<UZ
NE-b˞,px(b=Z\_A#w8$m1l8Q[6t2$$n-]t8 Z.#Ҏ	Xwj<]Ua9׈ı0b80h
-yWͲ{OwX㲪M͌,OP3ɤ;CAVePj7,TD+O1=&:Mĥ[Q"=ZtC[I/m@^JClǼưrD*.$N}E*ݻLΦPgwiyPu4vZgTm} v%ңJT[nx~,]NdV#kǣ|$[FhOTؿM7EU]^}vFQIOU<
9W Wf_V=ײF{O%\Z҉LV(q%+	^[	4oq>1ހ XeeR-Q	QȆC0*MxjG~fϣQ4kP4l$K^^OYvSbwˋv%Ҁx$f^)lشz	&$`8I5PS`ƻleg	C+/WF.^KgSu@29xq-#hn48Ɛ{w? ϋ$4QMd;NlRj=͉XOױ^`=Ċ7)iEyM:\#DНCOp{$
h)Q4H!/gqưֵSabx :o.߿x9=?= it;f5ɴ}S7Qm+Weq8-'QD)e9=q=q{{TugTtJθ.*i_樸qK&J۹I|qސEh .6w7/?yu
(X^%c~TmоQ|phlRcjHQ!Ju!@>P՛RRAr}T^UJLEą"]>+U/ZX# 2I#1@;:,?݌nI<.a,l8%?-傫GmtǘBBu]c~O|W9^QDhǢqhdmm"7qJJNU0'	Z;Z#aAL6[eRTx{~05(/Ec@n47YOZ/>^*fWnY9^({⊞3>0 ,0.t]h`3-Ŀ5H^]ɷ*;̗@>g0&mC\tC';Ye&`#Z}$zK8X=}[ڹ͎X"d;CbT+j&W+_/KK6Ru؞vNd R؀7AUe IǪ8H8]ڧinfqэ Sʬ |6s4u+}UPޟ߅Y7W=
J')dJ\O8j^4jµ<YaޒՖD'Zb9??3OU__XЂ	ܰHd&YeazJhUԧk
"G4$óLW3u0R hAPZlr+#M@BS,h/Ag-HG;(uR.%N
XֶeYrGE&w2!M&` zճSn-O'>ήٱ%Yu7U-Q񸟞mdϯb"8XS涘b.I	tڰ#=)cd>odo^	>3誸gTo˷o4?}bSy%s8T-Ў_) ;			PbϿ7S(71BA1<Y1֢]GY4I
BPR^6xuH{o|En^*	3CժAx2mTZR}f:b;B2@_[|6;6r ] \?qKTl$f78/Wjc+e!I9~!rQ{nZ>>qbgx=6'Zeuz"~ORsN"9'yϼ`|/y^_%|J= b;L:䜩*
w9%6띪eha͒Уrb3$S@,F7B'+دc|⮁@lR_6~7of1~yma%O3y؄MS~b.iH[F${c8;l7N.h(sϻ3T׿	&|=.<MMЃ98߫j#zmk.C0sUC-P(CrD`%uSe-8s)5f*̓-v۫yi_my[^Zhɯ$|{FORpR0Kȭtw)
azEJmʾ 땳ʲ[b+haLͲA>	h2NG9rPzb zc~upٴ7RͷzF욮:eD/T 7DOH\ﻺ5,Wl_-"8u;6fC*Ĉgfݻ?1w Ǆ㣝x_QIobb /ޜ%)= I/1z޾+x	D-@!5 $0{Wg
IЮ`J@i[e;˧%
f{|7;!+ŢDDTd)^Xv|0mOrzYRڻi#1aT`֎؂˾[_2wݴ_#gvzlM10݀qK87y#ǸY! vxZJvlOPl=`#Ǌ5'`F`N#kK&m& =òbe	:VO-ne]vZbMWTf635!HVp:qZX/kQÁVʛa9z4 &ЫVvYXjvP\]^kװ-+-:pY[o^_vN-7ឹwSfhug͡d)vIVWBS`|p2ݳ)5	0cۊDowhd^	o+?SNNt0ZU.}@n664yת aa幃$Q4)q}~%8A#bCDM86)ܦ$B.[gsi&#hW-
_H_?do`*o"kWg/YKqb3nP5*c?n*h}^/Kq6!@nCf6m#y1f7mG'KGDG).q8ks?W>8>KG YNЊ0ٹ]X֫m9A~ƯVvO+g+x| ݷÃSH[[./_b{ovN|vs=~t~Koz?ݢw	6`me㳢6w^" .zṶ8\A_eK99?8>9yRWȝ~ ٛ	{*I>)A{w D,W0gmaͦCBohp0ĹCDh-P0yBƖ"GPT6H_
!=ȳhaA :8!?bՂrw gQ/A6#GT$}hUN/
=QET:=	nWyk D,CCk'Y'OXASN;y˔Tvo﫢vj}@A$3NvTL3<zSySmOOM884CTrCH@QE/'Ū\#mpQUBUgӟMX4б͟T킺N"һrHVk$#BI`*Pdv>ɡL<,h.aBr^˛>d\@05}OբoA7xxԦqf(ءB8" aΝYCo1[ّE\!NE#XS%>3̧9UѾO9a,*=<"4T81&&["vz蛻98\߀Svw"L㌄Z
zƸ08F|!ŖM:rpbذܝ9
T
8{d$w4tB3(kIG^5m:]}N3=iKPU>M,kY,8Y1 +(bOYx]V: .ՠ6Fő֤U{+PIȸ>;䰦mU\/ 9dmj$wM
I#޸3s+.%tʅFZae1N'Nڈa=a%jYrkzQ00,5ZElV	(b3,#6cflXupD7zծ-W/&PAĳlxtqo_bB'?umΓ[,l?GNBW8SO̛i9]B)uLj$j0p_?jIW9ԙJ[miVG .1Wۘ2R`0U_2UiGUqٺQ{Zҗdnؖnmd})r&oƆPEH}aކek0M9ـ
Z43onD*XTz3TeH7qN
[u*Zd$*2it;GnvQvUSҘئW-q}G4E;ur| xC9i;ςS9{-y	+UES&{Tzihm+5u'J& 9KH4;T+x}S+Y|"]V'ճĐlŉ9d {u=)!v1'*/3Q%QQx,R&'qyRN&~lB,Q׮edi=̾Dh[6-ۖ@^jZ&caS*q٭6X;	BlDyyHgCjaܘa<|["C},V k=uG4<35w~2Sjjb}e0xї-ĝc=o#,k;RGǳ:DuJH]th;l`oE}.A؉}P293\+${O<&?d`)s8d n:<TS+Qg23^3[21Fw]X"=Ld3"dbiOD+,iGÆ=NI /[Fe5E6}2bt5|;8dt٥w̚;zU%6,~YiHFG\:$('s>Ag!:UN~IBXߊnc"J(eVnRUcmVe	CzZzܨjrM<5@gRċ-+<ZsXaw%j+n=$a7+_:^iR*/!V<1Lpסc5E-C6"Z9V5,*/jֺڨPw\U@1%9m5ƴ7(_9CU(#䕍G4uZ\U68kuWC	k8dPê-^6״f}dGh/yiFb__lszkvρ~'{ww)4x)dO|dcukbݒƺ&8ɔھzHHMȾHPd2N}+z"VߕOt#QbPEo0=vNBFDu.$Tec	60N2<i:_\b'_+l:OH~_D#G>aY?}|bJJoJ;σ(F2m,8E1ȰE90f4E>(S&cx=9^{6+ *c,F#,eFJ., P"ĿϥOwHv UB
oO	gs	/TQXvDNc閍y Hfbmo{NЄog7IX1<lJ.TmgN$Z1G۰%`'E-@vؑ~mh'=A 1l4  `&k{WM
F=tZ`xxȠe4:tbq_a;
)>Xѱضf~cKW|~^׷+꿫{ _:&$@9^
(oZ]>G8YTEG61'ƪK5zn}MP$߄mhO~$m@ubjL5cDi>aj4M)ren&$ѱme:cd̯\86襻ڝl,s؈.uÃ/5i]K:4w+9%(raMF P.1zM$`ƖrOX+hfchG60$~Lbb*$I,;?kh2ATs{b[1ǙޕV9e0_073#^v>YȨl7L;IՄẽd_XB|29Gi[B*us
mN'䘰4{ SvntSr1v5k퍲iu96׻!/=Q	3oZoWd#9H@؊خH[4[~fv5ݡG_0{v1HY!W[O-0L^̚Wqz.V	I"ynCz~e6\Et͜`ZџTL`>CZ^(e)FӨsXXt,rrZfjc8`|kB)p}%bxZpy`h!tvxtb7 1@f]@g
z=?z^0 jC9t\ۛ&?1li+Z#bޅ_ge-qIO?a-#G=%Xfă6䯙sNۜvN`b_E/c)F$MVjUs<GY@TY`jDd5ajdR6M6ګEG+BYR~j)HO(ŧ_5وtvu߹_&н*NOӪ-Vmc-hhu<_xiU#jʺǺ^tNڕ95ڱzaidGQ!-\UꬻMV'=:6_hT-{<<Da@=Pu3:?Z;u/߈Mn}4c|\<<gv%tۈS#Yfg"压)|6[Nuaٓ#ox.uFNsx=7GAӣJ+HYMkP$~77u)w|sup$ȶzDܿM-jvGբs-	'QYj[4+axo@WFv{b d5 `(q>7x$UNkv8\%S,&%7cT.r
tL;TTc)ruYQ"-Y?鈦"'86yѝvbJˀ4pY\#/ܯѳ^aзBvؚf%Wyt(tRt&ʎ]KM"z	U(:%ja	ʞj?<c=WT,NxNJ7yl	 5呢q:X -c:a/C4SZ~wO 9q
M$jUg,
VO49ѫZ$=3{iv2T4woD#YPTӃz]?T<[~WZ{Xm%ErHy$ut%mx~߸SPo\*Zk_m+X@qHPW|k  -I'I,ȸ^]Idu-|Y\0Q5Sge\e݉K)q^IwCRO緤<WoM*~]?ɚ\?`;ꕇѩco_Llρ*-mM9(^/-?Sν XK /Rܷ{uQ\@O#GKEq}&BIɛMN6~y69`6Xe[>0AԈY1aZ>pb͂3~4U!w.zBJж_]QSHvlLD,HEplpmQ[02pNGa*b3t)ѬCʳc0Si,Նuz#yت0Lk
iim5Ri{դiym.9X,z%"9* A}\y㋐lHjsL5q᮰bLx2̗><1!jM0gdeRɃ4UaT$)tS/Q+Ɋ$:h:>pn@Cl|u0㘓U"4
dҨFŊ}*xכ^2َt"x<5ƸyZȯ{x%6Nk6t@Aa"{" }UDD|**8uZ&""YKR9#goNͨwM/Ml-c M0c@9%V-̷i\z4՗!cHִC5%7	2:+wj^9$j[ɐ,u[Dfi80	_	+G,Z붬Yj!cBѺL6Na_\j8xUqȭ+M, ;8%9EXpzO%hn\N%]i'#xc[X<s;@iڜ髗4p[-ZsmTD @C V7~Ү4SzȢMʋ#	f	eP¹^a鴓%NLHBFZ/xG8FHIw:Ge0tpsןg:/!7rb?M*Tuu.E`opwa\8YV`g/d?6na5M<`wGu\=w|f~=[ד0=3Z@p䔪"//	{d>.ve=H<^{RWo!ga&%*볦+nd2FtxLxZO	)[[or.~\:Q,FukB&d DlNwuTi|ijtX4&.g+|)#W*ik'kș.ܦRi]My1b^DA`XGOqbi~No6SmL8uqX'^zO,?oӳ~ݸrmE /Ww?܁g_<ˉ5Zo<21g/mY"m{fP<i\ܯzt8ևUzv{zq\y+[g:?Z/oWU̵e~
	9մuqߚ?yG{\i8ٴ.'E=]Aۘ	|w Wd|9#2ȬIjt?zbVd2a_.[T꼝\9XSO
\)M)KeX[CS7o05]Ƹ kqnӪ9ۙo~ƹmm1iPes,^m|Ny%+]er1K.+ ;}^͠^	bm!
]TMw:g[`x_YvUamVsf`bF' Ær1zj,TC}婺^RĜsjZSr.\AP!VL:]Cz"NTɗ=tQWa`Bk\!VLµi85ͱ6m[2ko w
J{E2R(0pG)A,?2,ܳf 6ogn?6dŀl5;{5[U z&)	:%z>7|\g**YRTMa\9^&cWr+qL}`c9;m|;X!c"2¥A^ʦ.kBTJ,ݤ|KLMN	_F/f{!,ke֧l>g1䙋2|-ta;Wlts`w38~n {q>1n?hanAۓ9i mNay(r^pL[{rr2Yu*rym( |@ vz)UM:5^$dNÉ*'lA:,<H:,ZS#a/CBSs錨KNHw~ lKF>+GáCD"BfrSܥ2!OMvfX%Xvvs*
GC#@bԋv(h߼7DcZ0<R
,zlZ*v;L1&#Qp	{']g&zы$JX̞{#%	O\5Ud&j~tfyFDM4CD[-Bm0 sJ(8䜄ITWSU<'LnV>*Zz4 %0Vr
Poo$PaP8k0M/iN:%Dw=`
2MJS,{Yd;A[/1R7jxe[.0DXRa.~~t>~ՀxP\j$8?v<Y\u-.a*Fi`U$%ŠhЋL+i.vn&c~"Yl5c[
h<Cږ0mk%.̙8׫%y/ik~y, t$0\hX {
  // chrome-extension://gfdkimpbcpahaombhbimeihdjnejgicl/
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMZElzFX2J1g1nRQ/8S3rg/1CjFyDltWOxQg+9M8aVgNVxbutEWFQz+oQzIP9BB67mJifULgiv12ToFKsae4NpEUR8sPZjiKDIHumc6pUdixOm8SJ5Rs16SMR6+VYxFUjlVW+5CA3IILptmNBxgpfyqoK0qRpBDIhGk1KDEZ4zqQIDAQAB",
  "name": "Feedback",
  "version": "1.0",
  "manifest_version": 2,
  "incognito" : "split",
  "description": "User feedback extension",
  "icons": {
    "48": "images/icon48.png",
    "192": "images/icon192.png"
  },
  "permissions": [
      "feedbackPrivate",
      "chrome://resources/"
  ],
  "app": {
    "background": {
      "scripts": ["js/event_handler.js"]
    },
    "content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem: chrome://resources; style-src 'unsafe-inline' blob: chrome: file: filesystem: data: *; img-src * blob: chrome: file: filesystem: data:; media-src 'self' blob: filesystem:"
  },
  "display_in_launcher": false,
  "display_in_new_tab_page": false
}
     VYoF~ׯ-&0TqICQ;4W^.ݡwiӔwvo.&p*ƪۜ3V-U𾦼.ZCC{282ʕW6EHKA	r!thR4,F Hβ6a"oW),ՇW|
gZE&
$i.CZ5e;K4.ꊽV]b-\bvI1GA)bR1GFԹ+%f"MV^"(5GVCKMڲ9m5;R5Rvޕ͒M)>KuJ.d|9)TtHpqTi:#ɣ $)_%dͱ$6\OKHA>鞭F*:BܚJ09k"ŴQwU 3/r~ڷeʹQ~?IҢ_25	8niVƈxPٛJ{anmbBR8;Uqj-~|8uV6amc~j^-% j*d"c6莽o,^~Accǩ7	b{IZhCAy~r#gaVBŧ3//x	i*AܺXG29i;lZ&)ۈ ӿ<ʼpyҰo}͹'G`Eh_Yjz
Rs8qf:)ϧ}1򻊿Az&2=-f<*'\7&r-iGnb||_`nkJuZ'6񅲻EwY }2
       Tn0+$Hr2P4M{(PT@#0E$eG-%);c%A͛w~7ji`$CaZ5mີLiõ@4kAP5X
R.D
eݾJfP	%zZΎ͇Ϸc8;L D,Fm#0˓|rCcR#YF\N V	tzQ\]L!Ȧ͒SY+i#84I!z](ej
H1jGtj\ɀܬ
%FPr@/֪1lz3N)>JbPEK0mL_(?#+k"ZOX]HˢqAO$r{^_#O%v&`tOsr^#,yoཻ}y#𣺮{C>Jr˗U}Яo 14ފt>ZpVV?uD_N`l!?[%7t8aGWipbQ{Z'cɂt,՝3k~$Dom^j6Q70JXZkzj96ϲ}4)ѮlD|>"8l,OҀ\FV~\G       Wn8}WZ)l9[/l.fѤ-c6(S7!)%I}-j83gƣriћ?df\VszW66wJQdزYpF#jLZ2Ss&<s,IӡuKŤdp&5MuU$3]|<9|uFS82<'̻ƩJ8!-*MƄM"sR= \=I'?d./	/p{ߓ3ae
GԇVv.JL:VҾ ݊gp_$8&BU|{\	ߧ<>߮zp]C\I1+֦(^D?{+v-K6`sK+ʒIõct&7k^@MwAA.rO{ae~z<?NOf<) i+Ԁ
~R2hΛ))Rs;M* f8oqZ]9GxD:BE)S;RrJI7zSvx(zSufKFѣUIa`D?kMdbnr҅Z[	BGP@(Z3͜+x4!4ӹ)6w#.FF5vZU܃eQȹ!& z`	tXvOr[%M;M+&PvZ\dcfWV!8EHLH,hEՙť1Ğ$P|#ʩ $j}!P,kQW."_Hn@ogFLsΣ&oHn?-8.SZ
_<ݰLMO+fQ@~V =Ι09ǘrD^~RHc1?K&,xeOx^Bq	2vv;9Er@A{tD|I(AWp7vH~];W
;5K\cօiG}3`8t꺁 T{@oVu?dq*Vu_¸JjByy[7}4~:G_]QsUm~UsVA#sL`_@i3Η1psAY
#xoVZ)Dkq"g`փ	U6V<{UK^A&ZQUsXݳk]LI$\R,fdó	x7=mtOE'FdY5<.j50c۷Ҟnn6uO0fYdej7dUæ/[-iZVvuWvE0/mk G􃟳VLK;]Q8B+,b	'Q.ڙSP=MzkY8I]a
o-vooOKlv0҃t3u&BaAn=vAxdCnHwxO;aݺo1N>vz(\h5:*>  // Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('mojoBase.mojom');





/**
 * @const {!Object}
 * @export
 */
mojoBase.mojom.BigBufferSharedMemoryRegion =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
mojoBase.mojom.BigBuffer =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    mojoBase.mojom.BigBufferSharedMemoryRegion.$,
    'BigBufferSharedMemoryRegion',
    8,
    [
      mojo.internal.StructField(
        'bufferHandle', 0,
        0,
        mojo.internal.Handle,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'size', 4,
        0,
        mojo.internal.Uint32,
        0,
        false /* nullable */),
    ]);


mojo.internal.Union(
    mojoBase.mojom.BigBuffer.$, 'BigBuffer',
    {
      'bytes': {
        'ordinal': 0,
        'type': mojo.internal.Array(mojo.internal.Uint8, false),
      },
      'sharedMemory': {
        'ordinal': 1,
        'type': mojoBase.mojom.BigBufferSharedMemoryRegion.$,
      },
      'invalidBuffer': {
        'ordinal': 2,
        'type': mojo.internal.Bool,
      },
    });
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('skia.mojom');





/**
 * @const {!Object}
 * @export
 */
skia.mojom.Bitmap =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
skia.mojom.InlineBitmap =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    skia.mojom.Bitmap.$,
    'Bitmap',
    32,
    [
      mojo.internal.StructField(
        'imageInfo', 0,
        0,
        skia.mojom.ImageInfo.$,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'rowBytes', 8,
        0,
        mojo.internal.Uint64,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'pixelData', 16,
        0,
        mojoBase.mojom.BigBuffer.$,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    skia.mojom.InlineBitmap.$,
    'InlineBitmap',
    24,
    [
      mojo.internal.StructField(
        'imageInfo', 0,
        0,
        skia.mojom.ImageInfo.$,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'rowBytes', 8,
        0,
        mojo.internal.Uint64,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'pixelData', 16,
        0,
        mojo.internal.Array(mojo.internal.Uint8, false),
        null,
        false /* nullable */),
    ]);

// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('skia.mojom');




/**
 * @const {!Object}
 * @export
 */
skia.mojom.ColorType = { $: mojo.internal.Enum() };
skia.mojom.ColorType.UNKNOWN = 0;
skia.mojom.ColorType.ALPHA_8 = skia.mojom.ColorType.UNKNOWN + 1;
skia.mojom.ColorType.RGB_565 = skia.mojom.ColorType.ALPHA_8 + 1;
skia.mojom.ColorType.ARGB_4444 = skia.mojom.ColorType.RGB_565 + 1;
skia.mojom.ColorType.RGBA_8888 = skia.mojom.ColorType.ARGB_4444 + 1;
skia.mojom.ColorType.BGRA_8888 = skia.mojom.ColorType.RGBA_8888 + 1;
skia.mojom.ColorType.INDEX_8 = skia.mojom.ColorType.BGRA_8888 + 1;
skia.mojom.ColorType.GRAY_8 = skia.mojom.ColorType.INDEX_8 + 1;
skia.mojom.ColorType.MIN_VALUE = 0;
skia.mojom.ColorType.MAX_VALUE = 7;


/**
 * @const {!Object}
 * @export
 */
skia.mojom.AlphaType = { $: mojo.internal.Enum() };
skia.mojom.AlphaType.UNKNOWN = 0;
skia.mojom.AlphaType.ALPHA_TYPE_OPAQUE = skia.mojom.AlphaType.UNKNOWN + 1;
skia.mojom.AlphaType.PREMUL = skia.mojom.AlphaType.ALPHA_TYPE_OPAQUE + 1;
skia.mojom.AlphaType.UNPREMUL = skia.mojom.AlphaType.PREMUL + 1;
skia.mojom.AlphaType.MIN_VALUE = 0;
skia.mojom.AlphaType.MAX_VALUE = 3;



/**
 * @const {!Object}
 * @export
 */
skia.mojom.ImageInfo =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    skia.mojom.ImageInfo.$,
    'ImageInfo',
    24,
    [
      mojo.internal.StructField(
        'colorType', 0,
        0,
        skia.mojom.ColorType.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'alphaType', 4,
        0,
        skia.mojom.AlphaType.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'serializedColorSpace', 8,
        0,
        mojo.internal.Array(mojo.internal.Uint8, false),
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'width', 16,
        0,
        mojo.internal.Uint32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'height', 20,
        0,
        mojo.internal.Uint32,
        0,
        false /* nullable */),
    ]);

// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('gfx.mojom');





/**
 * @const {!Object}
 * @export
 */
gfx.mojom.ImageSkiaRep =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
gfx.mojom.ImageSkia =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    gfx.mojom.ImageSkiaRep.$,
    'ImageSkiaRep',
    16,
    [
      mojo.internal.StructField(
        'bitmap', 0,
        0,
        skia.mojom.Bitmap.$,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'scale', 8,
        0,
        mojo.internal.Float,
        0,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    gfx.mojom.ImageSkia.$,
    'ImageSkia',
    8,
    [
      mojo.internal.StructField(
        'imageReps', 0,
        0,
        mojo.internal.Array(gfx.mojom.ImageSkiaRep.$, false),
        null,
        false /* nullable */),
    ]);

// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('appManagement.mojom');




/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PwaPermissionType = { $: mojo.internal.Enum() };
appManagement.mojom.PwaPermissionType.CONTENT_SETTINGS_TYPE_GEOLOCATION = 5;
appManagement.mojom.PwaPermissionType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS = 6;
appManagement.mojom.PwaPermissionType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC = 9;
appManagement.mojom.PwaPermissionType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA = 10;
appManagement.mojom.PwaPermissionType.MIN_VALUE = 5;
appManagement.mojom.PwaPermissionType.MAX_VALUE = 10;

/** @export */
appManagement.mojom.PageHandlerFactoryRequest = class {
  /** @param {!MojoHandle} handle */
  constructor(handle) {
    /** @public {!MojoHandle} */
    this.handle = handle;
  }
};



/** @implements { appManagement.mojom.PageHandlerFactoryInterface } */
appManagement.mojom.PageHandlerFactoryProxy = class {
  /** @param {MojoHandle=} opt_handle */
  constructor(opt_handle) {
    /** @private {!mojo.internal.interfaceSupport.InterfaceProxyBase} */
    this.proxy =
        new mojo.internal.interfaceSupport.InterfaceProxyBase(opt_handle);

    /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
    this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
  }

  /**
   * @return {!appManagement.mojom.PageHandlerFactoryRequest}
   * @export
   */
  createRequest() {
    let {handle0, handle1} = Mojo.createMessagePipe();
    this.proxy.bindHandle(handle0);
    return new appManagement.mojom.PageHandlerFactoryRequest(handle1);
  }

  /**
   * @param { !appManagement.mojom.PageProxy } page
   * @param { !appManagement.mojom.PageHandlerRequest } handler
   * @export
   */
  createPageHandler(
      page,
      handler) {
    this.proxy.sendMessage(
        1128265880,
        appManagement.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
        null,
        [
          page,
          handler
        ]);
  }


  /**
   * @return {!Promise}
   * @export
   */
  flushForTesting() {
    return this.proxy.flushForTesting();
  }
};

/**
 * An object which receives request messages for the PageHandlerFactory
 * mojom interface. Must be constructed over an object which implements that
 * interface.
 *
 * @export
 */
appManagement.mojom.PageHandlerFactory = class {
  /**
   * @param {!appManagement.mojom.PageHandlerFactoryInterface } impl
   */
  constructor(impl) {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;

    this.target_.registerHandler(
        1128265880,
        appManagement.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
        null,
        impl.createPageHandler.bind(impl));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched to this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Returns a proxy for this interface which sends messages to the browser.
   * The browser must have an interface request binder registered for this
   * interface and accessible to the calling document's frame.
   *
   * @return {!appManagement.mojom.PageHandlerFactoryProxy}
   * @export
   */
  static getProxy() {
    let proxy = new appManagement.mojom.PageHandlerFactoryProxy;
    Mojo.bindInterface('app_management.mojom.PageHandlerFactory',
                       proxy.createRequest().handle);
    return proxy;
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!appManagement.mojom.PageHandlerFactoryProxy}
   * @export
   */
  createProxy() {
    let proxy = new appManagement.mojom.PageHandlerFactoryProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }
};


/**
 * @const {string}
 * @export
 */
appManagement.mojom.PageHandlerFactory.$interfaceName =
    'app_management.mojom.PageHandlerFactory';

/**
 * An object which receives request messages for the PageHandlerFactory
 * mojom interface and dispatches them as callbacks. One callback target exists
 * on this object for each message defined in the mojom interface, and each
 * target can have any number of listeners added to it.
 *
 * @export
 */
appManagement.mojom.PageHandlerFactoryCallbackRouter = class {
  constructor() {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;
    this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;

    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.createPageHandler =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1128265880,
        appManagement.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
        null,
        this.createPageHandler.createTargetHandler(false /* expectsResponse */));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched as callbacks on this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Closes all bindings bound to this target. The target will not receive any
   * further message message events unless rebound to one or more handles.
   */
  closeBindings() {
    this.target_.closeBindings();
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!appManagement.mojom.PageHandlerFactoryProxy}
   * @export
   */
  createProxy() {
    let proxy = new appManagement.mojom.PageHandlerFactoryProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }

  /**
   * @param {number} id An ID returned by a prior call to addListener.
   * @return {boolean} True iff the identified listener was found and removed.
   * @export
   */
  removeListener(id) {
    return this.router_.removeListener(id);
  }
};
/** @export */
appManagement.mojom.PageHandlerRequest = class {
  /** @param {!MojoHandle} handle */
  constructor(handle) {
    /** @public {!MojoHandle} */
    this.handle = handle;
  }
};



/** @implements { appManagement.mojom.PageHandlerInterface } */
appManagement.mojom.PageHandlerProxy = class {
  /** @param {MojoHandle=} opt_handle */
  constructor(opt_handle) {
    /** @private {!mojo.internal.interfaceSupport.InterfaceProxyBase} */
    this.proxy =
        new mojo.internal.interfaceSupport.InterfaceProxyBase(opt_handle);

    /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
    this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
  }

  /**
   * @return {!appManagement.mojom.PageHandlerRequest}
   * @export
   */
  createRequest() {
    let {handle0, handle1} = Mojo.createMessagePipe();
    this.proxy.bindHandle(handle0);
    return new appManagement.mojom.PageHandlerRequest(handle1);
  }

  /**
   * @return {Promise}
   * @export
   */
  getApps() {
    return this.proxy.sendMessage(
        1173218956,
        appManagement.mojom.PageHandler_GetApps_Params.$,
        appManagement.mojom.PageHandler_GetApps_ResponseParams.$,
        [
        ]);
  }

  /**
   * @param { !string } appId
   * @return {Promise}
   * @export
   */
  getExtensionAppPermissionMessages(
      appId) {
    return this.proxy.sendMessage(
        831725473,
        appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_Params.$,
        appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_ResponseParams.$,
        [
          appId
        ]);
  }

  /**
   * @param { !string } appId
   * @param { number } pinned
   * @export
   */
  setPinned(
      appId,
      pinned) {
    this.proxy.sendMessage(
        880354138,
        appManagement.mojom.PageHandler_SetPinned_Params.$,
        null,
        [
          appId,
          pinned
        ]);
  }

  /**
   * @param { !string } appId
   * @param { !Object } permission
   * @export
   */
  setPermission(
      appId,
      permission) {
    this.proxy.sendMessage(
        649057477,
        appManagement.mojom.PageHandler_SetPermission_Params.$,
        null,
        [
          appId,
          permission
        ]);
  }

  /**
   * @param { !string } appId
   * @export
   */
  uninstall(
      appId) {
    this.proxy.sendMessage(
        578901877,
        appManagement.mojom.PageHandler_Uninstall_Params.$,
        null,
        [
          appId
        ]);
  }

  /**
   * @param { !string } appId
   * @export
   */
  openNativeSettings(
      appId) {
    this.proxy.sendMessage(
        1001145349,
        appManagement.mojom.PageHandler_OpenNativeSettings_Params.$,
        null,
        [
          appId
        ]);
  }


  /**
   * @return {!Promise}
   * @export
   */
  flushForTesting() {
    return this.proxy.flushForTesting();
  }
};

/**
 * An object which receives request messages for the PageHandler
 * mojom interface. Must be constructed over an object which implements that
 * interface.
 *
 * @export
 */
appManagement.mojom.PageHandler = class {
  /**
   * @param {!appManagement.mojom.PageHandlerInterface } impl
   */
  constructor(impl) {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;

    this.target_.registerHandler(
        1173218956,
        appManagement.mojom.PageHandler_GetApps_Params.$,
        appManagement.mojom.PageHandler_GetApps_ResponseParams.$,
        impl.getApps.bind(impl));
    this.target_.registerHandler(
        831725473,
        appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_Params.$,
        appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_ResponseParams.$,
        impl.getExtensionAppPermissionMessages.bind(impl));
    this.target_.registerHandler(
        880354138,
        appManagement.mojom.PageHandler_SetPinned_Params.$,
        null,
        impl.setPinned.bind(impl));
    this.target_.registerHandler(
        649057477,
        appManagement.mojom.PageHandler_SetPermission_Params.$,
        null,
        impl.setPermission.bind(impl));
    this.target_.registerHandler(
        578901877,
        appManagement.mojom.PageHandler_Uninstall_Params.$,
        null,
        impl.uninstall.bind(impl));
    this.target_.registerHandler(
        1001145349,
        appManagement.mojom.PageHandler_OpenNativeSettings_Params.$,
        null,
        impl.openNativeSettings.bind(impl));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched to this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Returns a proxy for this interface which sends messages to the browser.
   * The browser must have an interface request binder registered for this
   * interface and accessible to the calling document's frame.
   *
   * @return {!appManagement.mojom.PageHandlerProxy}
   * @export
   */
  static getProxy() {
    let proxy = new appManagement.mojom.PageHandlerProxy;
    Mojo.bindInterface('app_management.mojom.PageHandler',
                       proxy.createRequest().handle);
    return proxy;
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!appManagement.mojom.PageHandlerProxy}
   * @export
   */
  createProxy() {
    let proxy = new appManagement.mojom.PageHandlerProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }
};


/**
 * @const {string}
 * @export
 */
appManagement.mojom.PageHandler.$interfaceName =
    'app_management.mojom.PageHandler';

/**
 * An object which receives request messages for the PageHandler
 * mojom interface and dispatches them as callbacks. One callback target exists
 * on this object for each message defined in the mojom interface, and each
 * target can have any number of listeners added to it.
 *
 * @export
 */
appManagement.mojom.PageHandlerCallbackRouter = class {
  constructor() {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;
    this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;

    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.getApps =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1173218956,
        appManagement.mojom.PageHandler_GetApps_Params.$,
        appManagement.mojom.PageHandler_GetApps_ResponseParams.$,
        this.getApps.createTargetHandler(true /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.getExtensionAppPermissionMessages =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        831725473,
        appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_Params.$,
        appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_ResponseParams.$,
        this.getExtensionAppPermissionMessages.createTargetHandler(true /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.setPinned =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        880354138,
        appManagement.mojom.PageHandler_SetPinned_Params.$,
        null,
        this.setPinned.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.setPermission =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        649057477,
        appManagement.mojom.PageHandler_SetPermission_Params.$,
        null,
        this.setPermission.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.uninstall =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        578901877,
        appManagement.mojom.PageHandler_Uninstall_Params.$,
        null,
        this.uninstall.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.openNativeSettings =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1001145349,
        appManagement.mojom.PageHandler_OpenNativeSettings_Params.$,
        null,
        this.openNativeSettings.createTargetHandler(false /* expectsResponse */));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched as callbacks on this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Closes all bindings bound to this target. The target will not receive any
   * further message message events unless rebound to one or more handles.
   */
  closeBindings() {
    this.target_.closeBindings();
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!appManagement.mojom.PageHandlerProxy}
   * @export
   */
  createProxy() {
    let proxy = new appManagement.mojom.PageHandlerProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }

  /**
   * @param {number} id An ID returned by a prior call to addListener.
   * @return {boolean} True iff the identified listener was found and removed.
   * @export
   */
  removeListener(id) {
    return this.router_.removeListener(id);
  }
};
/** @export */
appManagement.mojom.PageRequest = class {
  /** @param {!MojoHandle} handle */
  constructor(handle) {
    /** @public {!MojoHandle} */
    this.handle = handle;
  }
};



/** @implements { appManagement.mojom.PageInterface } */
appManagement.mojom.PageProxy = class {
  /** @param {MojoHandle=} opt_handle */
  constructor(opt_handle) {
    /** @private {!mojo.internal.interfaceSupport.InterfaceProxyBase} */
    this.proxy =
        new mojo.internal.interfaceSupport.InterfaceProxyBase(opt_handle);

    /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
    this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
  }

  /**
   * @return {!appManagement.mojom.PageRequest}
   * @export
   */
  createRequest() {
    let {handle0, handle1} = Mojo.createMessagePipe();
    this.proxy.bindHandle(handle0);
    return new appManagement.mojom.PageRequest(handle1);
  }

  /**
   * @param { !Object } app
   * @export
   */
  onAppAdded(
      app) {
    this.proxy.sendMessage(
        1361843498,
        appManagement.mojom.Page_OnAppAdded_Params.$,
        null,
        [
          app
        ]);
  }

  /**
   * @param { !Object } update
   * @export
   */
  onAppChanged(
      update) {
    this.proxy.sendMessage(
        519970639,
        appManagement.mojom.Page_OnAppChanged_Params.$,
        null,
        [
          update
        ]);
  }

  /**
   * @param { !string } appId
   * @export
   */
  onAppRemoved(
      appId) {
    this.proxy.sendMessage(
        1754984836,
        appManagement.mojom.Page_OnAppRemoved_Params.$,
        null,
        [
          appId
        ]);
  }


  /**
   * @return {!Promise}
   * @export
   */
  flushForTesting() {
    return this.proxy.flushForTesting();
  }
};

/**
 * An object which receives request messages for the Page
 * mojom interface. Must be constructed over an object which implements that
 * interface.
 *
 * @export
 */
appManagement.mojom.Page = class {
  /**
   * @param {!appManagement.mojom.PageInterface } impl
   */
  constructor(impl) {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;

    this.target_.registerHandler(
        1361843498,
        appManagement.mojom.Page_OnAppAdded_Params.$,
        null,
        impl.onAppAdded.bind(impl));
    this.target_.registerHandler(
        519970639,
        appManagement.mojom.Page_OnAppChanged_Params.$,
        null,
        impl.onAppChanged.bind(impl));
    this.target_.registerHandler(
        1754984836,
        appManagement.mojom.Page_OnAppRemoved_Params.$,
        null,
        impl.onAppRemoved.bind(impl));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched to this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Returns a proxy for this interface which sends messages to the browser.
   * The browser must have an interface request binder registered for this
   * interface and accessible to the calling document's frame.
   *
   * @return {!appManagement.mojom.PageProxy}
   * @export
   */
  static getProxy() {
    let proxy = new appManagement.mojom.PageProxy;
    Mojo.bindInterface('app_management.mojom.Page',
                       proxy.createRequest().handle);
    return proxy;
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!appManagement.mojom.PageProxy}
   * @export
   */
  createProxy() {
    let proxy = new appManagement.mojom.PageProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }
};


/**
 * @const {string}
 * @export
 */
appManagement.mojom.Page.$interfaceName =
    'app_management.mojom.Page';

/**
 * An object which receives request messages for the Page
 * mojom interface and dispatches them as callbacks. One callback target exists
 * on this object for each message defined in the mojom interface, and each
 * target can have any number of listeners added to it.
 *
 * @export
 */
appManagement.mojom.PageCallbackRouter = class {
  constructor() {
    this.target_ = new mojo.internal.interfaceSupport.InterfaceTarget;
    this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;

    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.onAppAdded =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1361843498,
        appManagement.mojom.Page_OnAppAdded_Params.$,
        null,
        this.onAppAdded.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.onAppChanged =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        519970639,
        appManagement.mojom.Page_OnAppChanged_Params.$,
        null,
        this.onAppChanged.createTargetHandler(false /* expectsResponse */));
    /** @public {!mojo.internal.interfaceSupport.InterfaceCallbackTarget} */
    this.onAppRemoved =
        new mojo.internal.interfaceSupport.InterfaceCallbackTarget(
            this.router_);
    this.target_.registerHandler(
        1754984836,
        appManagement.mojom.Page_OnAppRemoved_Params.$,
        null,
        this.onAppRemoved.createTargetHandler(false /* expectsResponse */));
  }

  /**
   * Binds a new handle to this object. Messages which arrive on the handle will
   * be read and dispatched as callbacks on this object.
   *
   * @param {!MojoHandle} handle
   * @export
   */
  bindHandle(handle) {
    this.target_.bindHandle(handle);
  }

  /**
   * Closes all bindings bound to this target. The target will not receive any
   * further message message events unless rebound to one or more handles.
   */
  closeBindings() {
    this.target_.closeBindings();
  }

  /**
   * Returns a proxy for this interface which sends messages directly to this
   * object. Any number of proxies may be created to the same object.
   *
   * @return {!appManagement.mojom.PageProxy}
   * @export
   */
  createProxy() {
    let proxy = new appManagement.mojom.PageProxy;
    this.target_.bindHandle(proxy.createRequest().handle);
    return proxy;
  }

  /**
   * @param {number} id An ID returned by a prior call to addListener.
   * @return {boolean} True iff the identified listener was found and removed.
   * @export
   */
  removeListener(id) {
    return this.router_.removeListener(id);
  }
};


/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.App =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.ExtensionAppPermissionMessage =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandlerFactory_CreatePageHandler_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_GetApps_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_GetApps_ResponseParams =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_ResponseParams =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_SetPinned_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_SetPermission_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_Uninstall_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.PageHandler_OpenNativeSettings_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.Page_OnAppAdded_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.Page_OnAppChanged_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
appManagement.mojom.Page_OnAppRemoved_Params =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    appManagement.mojom.App.$,
    'App',
    56,
    [
      mojo.internal.StructField(
        'id', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'type', 8,
        0,
        apps.mojom.AppType.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'title', 16,
        0,
        mojo.internal.String,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'description', 24,
        0,
        mojo.internal.String,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'isPinned', 12,
        0,
        apps.mojom.OptionalBool.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'version', 32,
        0,
        mojo.internal.String,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'size', 40,
        0,
        mojo.internal.String,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'permissions', 48,
        0,
        mojo.internal.Map(mojo.internal.Uint32, apps.mojom.Permission.$, false),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.ExtensionAppPermissionMessage.$,
    'ExtensionAppPermissionMessage',
    16,
    [
      mojo.internal.StructField(
        'message', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'submessages', 8,
        0,
        mojo.internal.Array(mojo.internal.String, false),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandlerFactory_CreatePageHandler_Params.$,
    'PageHandlerFactory_CreatePageHandler_Params',
    16,
    [
      mojo.internal.StructField(
        'page', 0,
        0,
        mojo.internal.InterfaceProxy(appManagement.mojom.PageProxy),
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'handler', 8,
        0,
        mojo.internal.InterfaceRequest(appManagement.mojom.PageHandlerRequest),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_GetApps_Params.$,
    'PageHandler_GetApps_Params',
    0,
    [
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_GetApps_ResponseParams.$,
    'PageHandler_GetApps_ResponseParams',
    8,
    [
      mojo.internal.StructField(
        'apps', 0,
        0,
        mojo.internal.Array(appManagement.mojom.App.$, false),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_Params.$,
    'PageHandler_GetExtensionAppPermissionMessages_Params',
    8,
    [
      mojo.internal.StructField(
        'appId', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_GetExtensionAppPermissionMessages_ResponseParams.$,
    'PageHandler_GetExtensionAppPermissionMessages_ResponseParams',
    8,
    [
      mojo.internal.StructField(
        'messages', 0,
        0,
        mojo.internal.Array(appManagement.mojom.ExtensionAppPermissionMessage.$, false),
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_SetPinned_Params.$,
    'PageHandler_SetPinned_Params',
    16,
    [
      mojo.internal.StructField(
        'appId', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'pinned', 8,
        0,
        apps.mojom.OptionalBool.$,
        0,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_SetPermission_Params.$,
    'PageHandler_SetPermission_Params',
    16,
    [
      mojo.internal.StructField(
        'appId', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'permission', 8,
        0,
        apps.mojom.Permission.$,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_Uninstall_Params.$,
    'PageHandler_Uninstall_Params',
    8,
    [
      mojo.internal.StructField(
        'appId', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.PageHandler_OpenNativeSettings_Params.$,
    'PageHandler_OpenNativeSettings_Params',
    8,
    [
      mojo.internal.StructField(
        'appId', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.Page_OnAppAdded_Params.$,
    'Page_OnAppAdded_Params',
    8,
    [
      mojo.internal.StructField(
        'app', 0,
        0,
        appManagement.mojom.App.$,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.Page_OnAppChanged_Params.$,
    'Page_OnAppChanged_Params',
    8,
    [
      mojo.internal.StructField(
        'update', 0,
        0,
        appManagement.mojom.App.$,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    appManagement.mojom.Page_OnAppRemoved_Params.$,
    'Page_OnAppRemoved_Params',
    8,
    [
      mojo.internal.StructField(
        'appId', 0,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);

// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';



mojo.internal.exportModule('apps.mojom');




/**
 * @const {!Object}
 * @export
 */
apps.mojom.AppType = { $: mojo.internal.Enum() };
apps.mojom.AppType.kUnknown = 0;
apps.mojom.AppType.kArc = apps.mojom.AppType.kUnknown + 1;
apps.mojom.AppType.kBuiltIn = apps.mojom.AppType.kArc + 1;
apps.mojom.AppType.kCrostini = apps.mojom.AppType.kBuiltIn + 1;
apps.mojom.AppType.kExtension = apps.mojom.AppType.kCrostini + 1;
apps.mojom.AppType.kWeb = apps.mojom.AppType.kExtension + 1;
apps.mojom.AppType.MIN_VALUE = 0;
apps.mojom.AppType.MAX_VALUE = 5;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.Readiness = { $: mojo.internal.Enum() };
apps.mojom.Readiness.kUnknown = 0;
apps.mojom.Readiness.kReady = apps.mojom.Readiness.kUnknown + 1;
apps.mojom.Readiness.kDisabledByBlacklist = apps.mojom.Readiness.kReady + 1;
apps.mojom.Readiness.kDisabledByPolicy = apps.mojom.Readiness.kDisabledByBlacklist + 1;
apps.mojom.Readiness.kDisabledByUser = apps.mojom.Readiness.kDisabledByPolicy + 1;
apps.mojom.Readiness.kTerminated = apps.mojom.Readiness.kDisabledByUser + 1;
apps.mojom.Readiness.kUninstalledByUser = apps.mojom.Readiness.kTerminated + 1;
apps.mojom.Readiness.MIN_VALUE = 0;
apps.mojom.Readiness.MAX_VALUE = 6;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.OptionalBool = { $: mojo.internal.Enum() };
apps.mojom.OptionalBool.kUnknown = 0;
apps.mojom.OptionalBool.kFalse = apps.mojom.OptionalBool.kUnknown + 1;
apps.mojom.OptionalBool.kTrue = apps.mojom.OptionalBool.kFalse + 1;
apps.mojom.OptionalBool.MIN_VALUE = 0;
apps.mojom.OptionalBool.MAX_VALUE = 2;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.IconType = { $: mojo.internal.Enum() };
apps.mojom.IconType.kUnknown = 0;
apps.mojom.IconType.kArc = apps.mojom.IconType.kUnknown + 1;
apps.mojom.IconType.kExtension = apps.mojom.IconType.kArc + 1;
apps.mojom.IconType.kResource = apps.mojom.IconType.kExtension + 1;
apps.mojom.IconType.MIN_VALUE = 0;
apps.mojom.IconType.MAX_VALUE = 3;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.IconCompression = { $: mojo.internal.Enum() };
apps.mojom.IconCompression.kUnknown = 0;
apps.mojom.IconCompression.kUncompressed = apps.mojom.IconCompression.kUnknown + 1;
apps.mojom.IconCompression.kCompressed = apps.mojom.IconCompression.kUncompressed + 1;
apps.mojom.IconCompression.MIN_VALUE = 0;
apps.mojom.IconCompression.MAX_VALUE = 2;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.LaunchSource = { $: mojo.internal.Enum() };
apps.mojom.LaunchSource.kUnknown = 0;
apps.mojom.LaunchSource.kFromAppListGrid = apps.mojom.LaunchSource.kUnknown + 1;
apps.mojom.LaunchSource.kFromAppListGridContextMenu = apps.mojom.LaunchSource.kFromAppListGrid + 1;
apps.mojom.LaunchSource.kFromAppListQuery = apps.mojom.LaunchSource.kFromAppListGridContextMenu + 1;
apps.mojom.LaunchSource.kFromAppListQueryContextMenu = apps.mojom.LaunchSource.kFromAppListQuery + 1;
apps.mojom.LaunchSource.kFromAppListRecommendation = apps.mojom.LaunchSource.kFromAppListQueryContextMenu + 1;
apps.mojom.LaunchSource.MIN_VALUE = 0;
apps.mojom.LaunchSource.MAX_VALUE = 5;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.TriState = { $: mojo.internal.Enum() };
apps.mojom.TriState.kAllow = 0;
apps.mojom.TriState.kBlock = apps.mojom.TriState.kAllow + 1;
apps.mojom.TriState.kAsk = apps.mojom.TriState.kBlock + 1;
apps.mojom.TriState.MIN_VALUE = 0;
apps.mojom.TriState.MAX_VALUE = 2;


/**
 * @const {!Object}
 * @export
 */
apps.mojom.PermissionValueType = { $: mojo.internal.Enum() };
apps.mojom.PermissionValueType.kBool = 0;
apps.mojom.PermissionValueType.kTriState = apps.mojom.PermissionValueType.kBool + 1;
apps.mojom.PermissionValueType.MIN_VALUE = 0;
apps.mojom.PermissionValueType.MAX_VALUE = 1;



/**
 * @const {!Object}
 * @export
 */
apps.mojom.App =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
apps.mojom.Permission =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
apps.mojom.IconKey =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };

/**
 * @const {!Object}
 * @export
 */
apps.mojom.IconValue =
    { $: /** @type {!mojo.internal.MojomType} */ ({}) };




mojo.internal.Struct(
    apps.mojom.App.$,
    'App',
    56,
    [
      mojo.internal.StructField(
        'appType', 0,
        0,
        apps.mojom.AppType.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'appId', 8,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'readiness', 4,
        0,
        apps.mojom.Readiness.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'name', 16,
        0,
        mojo.internal.String,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'iconKey', 24,
        0,
        apps.mojom.IconKey.$,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'permissions', 32,
        0,
        mojo.internal.Array(apps.mojom.Permission.$, false),
        null,
        false /* nullable */),
      mojo.internal.StructField(
        'installedInternally', 40,
        0,
        apps.mojom.OptionalBool.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'showInLauncher', 44,
        0,
        apps.mojom.OptionalBool.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'showInSearch', 48,
        0,
        apps.mojom.OptionalBool.$,
        0,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    apps.mojom.Permission.$,
    'Permission',
    16,
    [
      mojo.internal.StructField(
        'permissionId', 0,
        0,
        mojo.internal.Uint32,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'valueType', 4,
        0,
        apps.mojom.PermissionValueType.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'value', 8,
        0,
        mojo.internal.Uint32,
        0,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    apps.mojom.IconKey.$,
    'IconKey',
    24,
    [
      mojo.internal.StructField(
        'iconType', 0,
        0,
        apps.mojom.IconType.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'uKey', 8,
        0,
        mojo.internal.Uint64,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'sKey', 16,
        0,
        mojo.internal.String,
        null,
        false /* nullable */),
    ]);



mojo.internal.Struct(
    apps.mojom.IconValue.$,
    'IconValue',
    24,
    [
      mojo.internal.StructField(
        'iconCompression', 0,
        0,
        apps.mojom.IconCompression.$,
        0,
        false /* nullable */),
      mojo.internal.StructField(
        'uncompressed', 8,
        0,
        gfx.mojom.ImageSkia.$,
        null,
        true /* nullable */),
      mojo.internal.StructField(
        'compressed', 16,
        0,
        mojo.internal.Array(mojo.internal.Uint8, false),
        null,
        true /* nullable */),
    ]);

<link rel="import" href="chrome://resources/html/cr.html">
<script src="actions.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Module for functions which produce action objects. These are
 * listed in one place to document available actions and their parameters.
 */

cr.define('app_management.actions', function() {
  /**
   * @param {App} app
   */
  function addApp(app) {
    return {
      name: 'add-app',
      app: app,
    };
  }

  /**
   * @param {App} update
   */
  function changeApp(update) {
    return {
      name: 'change-app',
      update: update,
    };
  }

  /**
   * @param {string} id
   */
  function removeApp(id) {
    return {
      name: 'remove-app',
      id: id,
    };
  }

  /**
   * @param {PageType} pageType
   * @param {string=} id
   */
  function changePage(pageType, id) {
    if (pageType == PageType.DETAIL && !id) {
      console.warn(
          'Tried to load app detail page without providing an app id.');
    }

    return {
      name: 'change-page',
      pageType: pageType,
      id: id,
    };
  }

  return {
    addApp: addApp,
    changeApp: changeApp,
    removeApp: removeApp,
    changePage: changePage,
  };
});
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="actions.html">
<link rel="import" href="store.html">
<link rel="import" href="util.html">
<script src="chrome://apps/api_listener.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('app_management.apiListener', function() {
  let initialized = false;

  async function init() {
    assert(!initialized);

    const {apps: initialApps} =
        await app_management.BrowserProxy.getInstance().handler.getApps();
    const initialState = app_management.util.createInitialState(initialApps);
    app_management.Store.getInstance().init(initialState);

    const callbackRouter =
        app_management.BrowserProxy.getInstance().callbackRouter;

    callbackRouter.onAppAdded.addListener(onAppAdded);
    callbackRouter.onAppChanged.addListener(onAppChanged);
    callbackRouter.onAppRemoved.addListener(onAppRemoved);

    initialized = true;
  }

  /**
   * @param {cr.ui.Action} action
   */
  function dispatch(action) {
    app_management.Store.getInstance().dispatch(action);
  }

  /**
   * @param {App} app
   */
  function onAppAdded(app) {
    dispatch(app_management.actions.addApp(app));
  }

  /**
   * @param {App} app
   */
  function onAppChanged(app) {
    dispatch(app_management.actions.changeApp(app));
  }

  /**
   * @param {string} appId
   */
  function onAppRemoved(appId) {
    dispatch(app_management.actions.removeApp(appId));
  }

  init();

  return {};
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="actions.html">
<link rel="import" href="browser_proxy.html">
<link rel="import" href="chrome_app_permission_view.html">
<link rel="import" href="main_view.html">
<link rel="import" href="notifications_view.html">
<link rel="import" href="pwa_permission_view.html">
<link rel="import" href="router.html">
<link rel="import" href="store.html">
<link rel="import" href="store_client.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">

<link rel="import" href="chrome://apps/api_listener.html">

<dom-module id="app-management-app">
  <template>
    <style include="app-management-shared-css">
    :host {
      font-size: var(--app-management-font-size);
      line-height: var(--app-management-line-height);
    }

    cr-toolbar {
      background: var(--md-toolbar-color);
    }
    </style>
    <cr-toolbar page-name="$i18n{title}" search-prompt="$i18n{searchPrompt}">
    </cr-toolbar>
    <template is="dom-if" if="[[mainViewSelected_]]">
      <app-management-main-view></app-management-main-view>
    </template>
    <template is="dom-if" if="[[notificationsViewSelected_]]">
      <app-management-notifications-view></app-management-notifications-view>
    </template>
    <template is="dom-if" if="[[pwaPermissionViewSelected_]]">
      <app-management-pwa-permission-view></app-management-pwa-permission-view>
    </template>
    <template is="dom-if" if="[[chromeAppPermissionViewSelected_]]">
      <app-management-chrome-app-permission-view>
      </app-management-chrome-app-permission-view>
    </template>
    <app-management-router></app-management-router>
  </template>
  <script src="app.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'app-management-app',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /**
     * @private {boolean}
     */
    mainViewSelected_: Boolean,

    /**
     * @private {boolean}
     */
    notificationsViewSelected_: Boolean,

    /**
     * @private {boolean}
     */
    pwaPermissionViewSelected_: Boolean,

    /**
     * @private {boolean}
     */
    chromeAppPermissionViewSelected_: Boolean,
  },

  /** @override */
  attached: function() {
    // TODO(ceciliani) Generalize page selection in a nicer way.
    this.watch('mainViewSelected_', (state) => {
      return state.currentPage.pageType == PageType.MAIN;
    });

    this.watch('pwaPermissionViewSelected_', (state) => {
      // TODO(rekanorman): Remove AppType.kExtension case once PWA's are sent
      // thorough with the correct app type.
      return this.appTypeSelected(state, AppType.kWeb) ||
          this.appTypeSelected(state, AppType.kExtension);
    });

    this.watch('chromeAppPermissionViewSelected_', (state) => {
      return this.appTypeSelected(state, AppType.kExtension);
    });

    this.watch('notificationsViewSelected_', (state) => {
      return state.currentPage.pageType === PageType.NOTIFICATIONS;
    });

    this.updateFromStore();
  },

  /**
   * Returns true if the current page is the detail page of an app of the
   * given type.
   * @param {AppManagementPageState} state
   * @param {AppType} type
   * @return {boolean}
   */
  appTypeSelected: function(state, type) {
    if (!state.currentPage.selectedAppId) {
      return false;
    }

    const selectedApp = state.apps[state.currentPage.selectedAppId];
    return state.currentPage.pageType == PageType.DETAIL &&
        selectedApp.type == type;
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="actions.html">
<link rel="import" href="shared_style.html">
<link rel="import" href="shared_vars.html">
<link rel="import" href="store_client.html">
<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">

<dom-module id="app-management-app-item">
  <template>
    <style include="app-management-shared-css cr-icons">
      :host {
        align-items: center;
        border-top: var(--card-separator);
        color: var(--primary-text-color);
        display: flex;
        flex-direction: row;
        font-weight: 400;
        height: 64px;
      }

      #app-title {
        flex: 1;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      #app-icon {
        height: 32px;
        margin-inline-end: 20px;
        margin-inline-start: 24px;
        width: 32px;
      }
    </style>
    <img id="app-icon" src="[[iconUrlFromId_(app)]]">
    <div id="app-title">[[app.title]]</div>
    <slot name="right-content"></slot>
  </template>
 <script src="app_item.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Polymer({
  is: 'app-management-app-item',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /** @type {App} */
    app: {
      type: Object,
    },
  },

  listeners: {
    'click': 'onClick_',
  },

  /**
   * @private
   */
  onClick_: function() {
    this.dispatch(
        app_management.actions.changePage(PageType.DETAIL, this.app.id));
  },

  /**
   * @param {App} app
   * @return {string}
   * @private
   */
  iconUrlFromId_: function(app) {
    return app_management.util.getAppIcon(app);
  },
});
<link rel="import" href="chrome://resources/html/cr.html">
<script src="chrome://resources/js/mojo_bindings_lite.js"></script>
<script src="big_buffer.mojom-lite.js"></script>
<script src="image_info.mojom-lite.js"></script>
<script src="bitmap.mojom-lite.js"></script>
<script src="image.mojom-lite.js"></script>
<script src="types.mojom-lite.js"></script>
<script src="app_management.mojom-lite.js"></script>

<script src="browser_proxy.js"></script>
<script src="fake_page_handler.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('app_management', function() {
  class BrowserProxy {
    constructor() {
      /** @type {appManagement.mojom.PageCallbackRouter} */
      this.callbackRouter = new appManagement.mojom.PageCallbackRouter();

      /** @type {appManagement.mojom.PageHandlerInterface} */
      this.handler = null;

      const urlParams = new URLSearchParams(window.location.search);
      const useFake = urlParams.get('fakeBackend');

      if (useFake) {
        this.handler = new app_management.FakePageHandler(
            this.callbackRouter.createProxy());

        const /** @type {!Array<App>}*/ appList = [
          app_management.FakePageHandler.createApp(
              'ahfgeienlihckogmohjhadlkjgocpleb'),
          app_management.FakePageHandler.createApp(
              'aohghmighlieiainnegkcijnfilokake',
              {type: apps.mojom.AppType.kExtension}),
          app_management.FakePageHandler.createApp(
              'blpcfgokakmgnkcojhhkbfbldkacnbeo'),
          app_management.FakePageHandler.createApp(
              'pjkljhegncpnkpknbcohdijeoejaedia'),
          app_management.FakePageHandler.createApp(
              'aapocclcgogkmnckokdopfmhonfmgoek'),
        ];

        this.handler.setApps(appList);

      } else {
        this.handler = new appManagement.mojom.PageHandlerProxy();
        const factory = appManagement.mojom.PageHandlerFactory.getProxy();
        factory.createPageHandler(
            this.callbackRouter.createProxy(), this.handler.createRequest());
      }
    }
  }

  cr.addSingletonGetter(BrowserProxy);

  return {BrowserProxy: BrowserProxy};
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="shared_style.html">
<link rel="import" href="store_client.html">
<link rel="import" href="util.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">

<dom-module id="app-management-chrome-app-permission-view">
  <template>
    <style include="app-management-shared-css">
      ul {
        list-style: none;
        margin: 0;
        padding-inline-start: 24px;
      }

      li::before {
        content: '- ';
      }

      #app-info {
        padding: 24px;
      }

      #app-description {
        padding-bottom: 12px;
      }

      #no-permissions {
        padding-inline-start: 24px;
      }
    </style>
    <app-management-permission-view-header app="[[app_]]">
    </app-management-permission-view-header>
    <div class="card-container">
      <div id="app-info">
        <div id="app-description" class="secondary-text">
          [[app_.description]]
        </div>
        <div>$i18n{permissions}</div>
        <template is="dom-if" if="[[!hasPermissions_(messages_)]]">
          <div id="no-permissions">$i18n{appNoPermission}</div>
        </template>
        <ul>
          <template is="dom-repeat"
              items="[[getPermissionMessages_(messages_)]]"
              as="message">
            <li>[[message]]</li>
            <ul>
              <template is="dom-repeat"
                  items="[[getPermissionSubmessagesByMessage_(index, messages_)]]"
                  as="submessage">
                <li>[[submessage]]</li>
              </template>
            </ul>
          </template>
        </ul>
      </div>
    </div>
    <app-management-metadata-view app="[[app_]]"></app-management-metadata-view>
  </template>
  <script src="chrome_app_permission_view.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Polymer({
  is: 'app-management-chrome-app-permission-view',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /**
     * @private {App}
     */
    app_: {
      type: Object,
      observer: 'onAppChanged_',
    },

    /**
     * @private {Array<ExtensionAppPermissionMessage>}
     */
    messages_: Object,
  },

  attached: function() {
    this.watch('app_', (state) => {
      const selectedAppId = state.currentPage.selectedAppId;
      if (selectedAppId) {
        return state.apps[selectedAppId];
      }
    });

    this.updateFromStore();
  },

  /**
   * @param {App} app
   * @return {string}
   * @private
   */
  iconUrlFromId_: function(app) {
    return app_management.util.getAppIcon(app);
  },

  /**
   * @private
   */
  onAppChanged_: async function() {
    const {messages: messages} =
        await app_management.BrowserProxy.getInstance()
            .handler.getExtensionAppPermissionMessages(this.app_.id);
    // TODO(ceciliani) Remove this after app service can fetch description.
    this.$['app-description'].hidden = this.app_.description.length === 0;
    this.messages_ = messages;
  },

  /**
   * @param {!Array<ExtensionAppPermissionMessage>} messages
   * @return {Array<string>}
   * @private
   */
  getPermissionMessages_: function(messages) {
    return messages.map(m => m.message);
  },

  /**
   * @param {number} index
   * @param {!Array<ExtensionAppPermissionMessage>} messages
   * @return {?Array<string>}
   * @private
   */
  getPermissionSubmessagesByMessage_: function(index, messages) {
    // Dom-repeat still tries to access messages[0] when app has no
    // permission therefore we add an extra check.
    if (!messages[index]) {
      return null;
    }
    return messages[index].submessages;
  },

  /**
   * @param {!Array<ExtensionAppPermissionMessage>} messages
   * @return {boolean}
   * @private
   */
  hasPermissions_: function(messages) {
    return messages.length > 0;
  }
});
<script src="constants.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * The number of apps displayed in app list in the main view before expanding.
 * @const {number}
 */
const NUMBER_OF_APPS_DISPLAYED_DEFAULT = 4;

/**
 * The maximum number of apps' titles previewed in notification sublabel.
 * @const {number}
 */
const APP_LIST_PREVIEW_APP_TITLES = 3;

/**
 * Enumeration of the different subpage types within the app management page.
 * @enum {number}
 * @const
 */
const PageType = {
  MAIN: 0,
  DETAIL: 1,
  NOTIFICATIONS: 2,
};

/**
 * A number representation of a Bool. Permission values should be of this type
 * for permissions with value type PermissionValueType.kBool.
 * @enum {number}
 * @const
 */
const Bool = {
  kFalse: 0,
  kTrue: 1,
};

const PwaPermissionType = appManagement.mojom.PwaPermissionType;

const AppType = apps.mojom.AppType;

const PermissionValueType = apps.mojom.PermissionValueType;

const TriState = apps.mojom.TriState;

const OptionalBool = apps.mojom.OptionalBool;
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('app_management', function() {
  /**
   * @implements {appManagement.mojom.PageHandlerInterface}
   */
  class FakePageHandler {
    /**
     * @param {number} permissionId
     * @param {Object=} config
     * @return {!Permission}
     */
    static createPermission(permissionId, config) {
      const permission = app_management.util.createPermission(
          permissionId, PermissionValueType.kTriState, TriState.kBlock);

      if (config) {
        Object.assign(permission, config);
      }

      return permission;
    }

    /**
     * @param {string} id
     * @param {Object=} config
     * @return {!App}
     */
    static createApp(id, config) {
      const permissionIds = [
        PwaPermissionType.CONTENT_SETTINGS_TYPE_GEOLOCATION,
        PwaPermissionType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
        PwaPermissionType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
        PwaPermissionType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
      ];

      const permissions = {};

      for (const type of permissionIds) {
        permissions[type] = FakePageHandler.createPermission(type);
      }

      const app = {
        id: id,
        type: apps.mojom.AppType.kWeb,
        title: 'App Title',
        version: '5.1',
        size: '9.0MB',
        isPinned: apps.mojom.OptionalBool.kUnknown,
        permissions: permissions,
      };

      if (config) {
        Object.assign(app, config);
      }

      return app;
    }

    /**
     * @param {appManagement.mojom.PageInterface} page
     */
    constructor(page) {
      /** @type {appManagement.mojom.PageInterface} */
      this.page = page;

      /** @type {!Array<App>} */
      this.apps_ = [];
    }

    async getApps() {
      return {apps: this.apps_};
    }

    /**
     * @param {string} appId
     * @return {!Promise}
     */
    async getExtensionAppPermissionMessages(appId) {
      return [];
    }
    /**
     * @param {!Array<App>} appList
     */
    setApps(appList) {
      this.apps_ = appList;
    }

    /**
     * @param {string} appId
     * @param {OptionalBool} pinnedValue
     */
    setPinned(appId, pinnedValue) {
      const app = app_management.Store.getInstance().data.apps[appId];

      const newApp =
          /** @type {App} */ (Object.assign({}, app, {isPinned: pinnedValue}));
      this.page.onAppChanged(newApp);
    }

    /**
     * @param {string} appId
     * @param {Permission} permission
     */
    setPermission(appId, permission) {
      const app = app_management.Store.getInstance().data.apps[appId];

      // Check that the app had a previous value for the given permission
      assert(app.permissions[permission.permissionId]);

      const newPermissions = Object.assign({}, app.permissions);
      newPermissions[permission.permissionId] = permission;
      const newApp = /** @type {App} */ (
          Object.assign({}, app, {permissions: newPermissions}));
      this.page.onAppChanged(newApp);
    }

    /**
     * @param {string} appId
     */
    uninstall(appId) {
      this.page.onAppRemoved(appId);
    }

    /**
     * @param {string} appId
     */
    openNativeSettings(appId) {}
  }

  return {FakePageHandler: FakePageHandler};
});
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf8">
  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
  <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
  <style>
    html {
      /* Remove 300ms delay for 'click' event, when using touch interface. */
      touch-action: manipulation;
    }

    html,
    body {
      background: var(--md-background-color);
      height: 100%;
      margin: 0;
    }
  </style>
</head>
<body>
  <app-management-app></app-management-app>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="strings.js"></script>
  <link rel="import" href="app.html">
</body>
</html>
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="app_item.html">
<link rel="import" href="shared_style.html">
<link rel="import" href="store_client.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">

<dom-module id="app-management-main-view">
  <template>
    <style include="app-management-shared-css">
      #app-list-title {
        padding: 16px 24px;
      }

      #expand-button {
        height: 36px;
        margin-inline-end: 12px;
        width: 36px;
      }

      #expander-row {
        align-items: center;
        border-top: var(--card-separator);
        color: var(--secondary-text-color);
        display: flex;
        height: 50px;
        justify-content: space-between;
        padding-inline-end: 8px;
        padding-inline-start: 24px;
      }

      .notification-row-sublabel {
        display: flex;
        flex-direction: column;
        overflow: hidden;
        padding: 11px 0;
      }

      .collapsible {
        max-width: 250px;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      #notifications-sublabel {
        display: flex;
        overflow: hidden;
      }

      #notifications-sublabel > span {
        white-space: pre;
      }

      .notification-row {
        align-items: center;
        display: inline-flex;
        justify-content: space-between;
        padding: 0 24px;
      }

      .app-management-item-arrow {
        margin-inline-end: 8px;
        padding: 12px;
      }
    </style>

    <div class="card-container">
      <div id="app-list-title" class="header-text">$i18n{appListTitle}</div>
      <template is="dom-repeat" items="[[displayedApps_]]">
        <app-management-app-item app="[[item]]">
          <paper-icon-button-light slot="right-content"
              class="subpage-arrow app-management-item-arrow" actionable>
            <button></button>
          </paper-icon-button-light>
        </app-management-app-item>
      </template>

      <iron-collapse opened="[[listExpanded_]]">
        <template is="dom-repeat" items="[[collapsedApps_]]">
          <app-management-app-item app="[[item]]">
            <paper-icon-button-light slot="right-content"
                class="subpage-arrow" actionable>
              <button></button>
            </paper-icon-button-light>
          </app-management-app-item>
        </template>
      </iron-collapse>

      <div id="expander-row" class="expander-list-row"
          on-click="toggleListExpanded_">
        <span>[[moreAppsString_(apps_.length,listExpanded_)]]</span>
        <paper-icon-button-light class="expand-button">
          <button>
            <iron-icon icon="[[getCollapsedIcon_(listExpanded_)]]">
            </iron-icon>
          </button>
        </paper-icon-button-light>
      </div>
    </div>

    <div class="card-container">
      <span class="notification-row">
        <div class="notification-row-sublabel">
          <div class="header-text">
              $i18n{notifications}
          </div>
          <div id="notifications-sublabel" class="secondary-text"></div>
        </div>
        <paper-icon-button-light class="subpage-arrow" actionable
            on-click="onClickNotificationSublabel_">
          <button></button>
        </paper-icon-button-light>
      </span>
    </div>
  </template>
  <script src="main_view.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'app-management-main-view',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /**
     * List of all apps.
     * @private {Array<App>}
     */
    apps_: {
      type: Array,
      value: () => [],
      observer: 'onAppsChanged_',
    },

    /**
     * List of apps displayed before expanding the app list.
     * @private {Array<App>}
     */
    displayedApps_: {
      type: Array,
      value: () => [],
    },

    /**
     * List of apps displayed after expanding app list.
     * @private {Array<App>}
     */
    collapsedApps_: {
      type: Array,
      value: () => [],
    },

    /**
     * @private {boolean}
     */
    listExpanded_: {
      type: Boolean,
      value: false,
    },

    /**
     * List of apps with the notification permission.
     * @private {Array<App>}
     */
    notificationApps_: {
      type: Array,
      value: () => [],
      observer: 'getNotificationSublabel_',
    },
  },

  attached: function() {
    this.watch('apps_', function(state) {
      return Object.values(state.apps);
    });
    this.updateFromStore();
  },

  /**
   * @param {number} numApps
   * @param {boolean} listExpanded
   * @return {string}
   * @private
   */
  moreAppsString_: function(numApps, listExpanded) {
    return listExpanded ?
        loadTimeData.getString('lessApps') :
        loadTimeData.getStringF(
            'moreApps', numApps - NUMBER_OF_APPS_DISPLAYED_DEFAULT);
  },

  /**
   * @private
   */
  toggleListExpanded_: function() {
    this.listExpanded_ = !this.listExpanded_;
    this.onAppsChanged_();
  },

  /**
   * @private
   */
  onAppsChanged_: function() {
    this.$['expander-row'].hidden =
        this.apps_.length <= NUMBER_OF_APPS_DISPLAYED_DEFAULT;
    this.displayedApps_ = this.apps_.slice(0, NUMBER_OF_APPS_DISPLAYED_DEFAULT);
    this.collapsedApps_ =
        this.apps_.slice(NUMBER_OF_APPS_DISPLAYED_DEFAULT, this.apps_.length);
    this.notificationApps_ = this.apps_.slice();
  },

  /**
   * @param {boolean} listExpanded
   * @return {string}
   * @private
   */
  getCollapsedIcon_: function(listExpanded) {
    return listExpanded ? 'cr:expand-less' : 'cr:expand-more';
  },

  /** @private */
  onClickNotificationSublabel_: function() {
    this.dispatch(app_management.actions.changePage(PageType.NOTIFICATIONS));
  },

  /**
   * Show a string with apps' |title|(s) previewed into a label, with each
   * title ellipsised if too long.
   * @private
   */
  getNotificationSublabelPieces_: async function() {
    const /** @type {string} */ label = await cr.sendWithPromise(
        'getPluralString', 'appListPreview', this.notificationApps_.length);

    const substitutions = [];
    for (let i = 0;
         i < APP_LIST_PREVIEW_APP_TITLES && i < this.notificationApps_.length;
         i++) {
      substitutions.push(this.notificationApps_[i].title);
    }

    // Add X more apps if the length is more than APP_LIST_PREVIEW_APP_TITLES.
    if (this.notificationApps_.length >= APP_LIST_PREVIEW_APP_TITLES + 1) {
      substitutions.push(
          this.notificationApps_.length - APP_LIST_PREVIEW_APP_TITLES);
    }
    // Only APP_LIST_PREVIEW_APP_TITLES of apps' titles get ellipsised
    // if too long. the element after that is "X other apps"
    const placeholder = APP_LIST_PREVIEW_APP_TITLES + 1;
    const pieces =
        loadTimeData.getSubstitutedStringPieces(label, ...substitutions)
            .map(function(p) {
              // Make the titles of app collapsible but make the number in the
              // "X other app(s)" part non-collapsible.
              p.collapsible = !!p.arg && p.arg != '$' + placeholder;
              return p;
            });
    return pieces;
  },

  /**
   * Create <span> for each app title previewed,
   * making certain text fragments collapsible.
   */
  getNotificationSublabel_: async function() {
    const pieces = await this.getNotificationSublabelPieces_();
    // Create <span> for each app title previewed,
    // making certain text fragments collapsible.
    const textContainer = this.$['notifications-sublabel'];
    textContainer.textContent = '';
    for (const p of pieces) {
      if (p.value.length == 0) {
        return;
      }

      const span = document.createElement('span');
      span.textContent = p.value;
      if (p.collapsible) {
        span.classList.add('collapsible');
      }

      textContainer.appendChild(span);
    }
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="app_item.html">
<link rel="import" href="shared_style.html">
<link rel="import" href="store_client.html">
<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">

<dom-module id="app-management-notifications-view">
  <template>
    <style include="app-management-shared-css">
      cr-toggle {
        margin-inline-end: 24px;
      }

      paper-icon-button-light {
        margin-inline-start: 0;
      }

      #notification-view-header {
        align-items: center;
        display: flex;
        margin: 24px auto;
        width: var(--card-width)
      }

      #notification-title {
        padding-start: 12px;
      }
    </style>
    <!-- TODO(ceciliani) Make this view a separate element to avoid duplicate
    code with main view -->
    <div id="notification-view-header">
      <paper-icon-button-light class="icon-arrow-back">
        <button id="closeButton" on-click="onClickBackButton_"
        aria-label="$i18n{back}">
          <paper-ripple class="circle"></paper-ripple>
        </button>
      </paper-icon-button-light>
      <div id="notification-title" class="page-title">$i18n{notifications}</div>
    </div>

    <div class="card-container">
      <template is="dom-repeat" items="[[displayedApps_]]">
        <app-management-app-item app="[[item]]">
          <cr-toggle slot="right-content"></cr-toggle>
        </app-management-app-item>
      </template>

      <iron-collapse opened="[[listExpanded_]]">
        <template is="dom-repeat" items="[[collapsedApps_]]">
          <app-management-app-item app="[[item]]">
            <cr-toggle slot="right-content"></cr-toggle>
          </app-management-app-item>
        </template>
      </iron-collapse>

      <div class="expander-list-row" on-click="toggleListExpanded_">
        <span>[[moreAppsString_(apps_.length,listExpanded_)]]</span>
        <paper-icon-button-light class="expand-button">
          <button>
            <iron-icon icon="[[getCollapsedIcon_(listExpanded_)]]">
            </iron-icon>
          </button>
        </paper-icon-button-light>
      </div>
    </div>
  </template>
 <script src="notifications_view.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'app-management-notifications-view',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /**
     * List of all apps.
     * @private {Array<App>}
     */
    apps_: {
      type: Array,
      value: () => [],
    },

    /**
     * List of apps with notification permission
     * displayed before expanding the app list.
     * @private {Array<App>}
     */
    displayedApps_: {
      type: Array,
      value: function() {
        const /** @type {!Array<App>}*/ appList = [
          app_management.FakePageHandler.createApp(
              'blpcfgokakmgnkcojhhkbfbldkacnbeo'),
          app_management.FakePageHandler.createApp(
              'pjkljhegncpnkpknbcohdijeoejaedia'),
          app_management.FakePageHandler.createApp(
              'aapocclcgogkmnckokdopfmhonfmgoek'),
          app_management.FakePageHandler.createApp(
              'ahfgeienlihckogmohjhadlkjgocpleb'),
        ];
        return appList;
      },
    },

    /**
     * List of apps without notification permission
     * displayed after expanding app list.
     * @private {Array<App>}
     */
    collapsedApps_: {
      type: Array,
      value: function() {
        const /** @type {!Array<App>}*/ appList = [
          app_management.FakePageHandler.createApp(
              'aohghmighlieiainnegkcijnfilokake',
              {type: apps.mojom.AppType.kArc}),
        ];
        return appList;
      },
    },

    /**
     * @private {boolean}
     */
    listExpanded_: {
      type: Boolean,
      value: true,
    },
  },

  attached: function() {
    this.watch('apps_', (state) => {
      return Object.values(state.apps);
    });
    this.updateFromStore();
  },

  /**
   * @param {number} numApps
   * @param {boolean} listExpanded
   * @return {string}
   * @private
   */
  moreAppsString_: function(numApps, listExpanded) {
    // TODO(ceciliani) Make view display apps with notification permission
    // first.
    return listExpanded ?
        loadTimeData.getString('lessApps') :
        loadTimeData.getStringF(
            'moreApps', numApps - NUMBER_OF_APPS_DISPLAYED_DEFAULT);
  },

  /**
   * @private
   */
  toggleListExpanded_: function() {
    this.listExpanded_ = !this.listExpanded_;
  },

  /** @private */
  onClickBackButton_: function() {
    if (!window.history.state) {
      this.dispatch(app_management.actions.changePage(PageType.MAIN));
    } else {
      window.history.back();
    }
  },

  /**
   * @param {boolean} listExpanded
   * @return {string}
   * @private
   */
  getCollapsedIcon_: function(listExpanded) {
    return listExpanded ? 'cr:expand-less' : 'cr:expand-more';
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="shared_style.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">

<dom-module id="app-management-permission-view-header">
  <template>
    <style include="app-management-shared-css paper-button-style">
      :host {
        align-items: center;
        display: flex;
        margin: 24px auto;
        width: var(--card-width);
      }

      #permission-view-header-icon {
        height: 26px;
        margin-inline-end: 8px;
        margin-inline-start: 24px;
        width: 26px;
      }

      #app-title {
        flex: 1;
        font-size: 16px;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      paper-icon-button-light {
        margin-inline-start: 0;
      }

      #uninstall-button {
        background: white;
      }
    </style>
    <paper-icon-button-light class="icon-arrow-back">
      <button id="closeButton" on-click="onClickBackButton_"
      aria-label="$i18n{back}">
        <paper-ripple class="circle"></paper-ripple>
      </button>
    </paper-icon-button-light>
    <img id="permission-view-header-icon" src="[[iconUrlFromId_(app)]]">
    <div class="page-title">[[app.title]]</div>
    <slot name="extra-right-buttons"></slot>
    <paper-button id="uninstall-button" on-click="onClickUninstallButton_">
      $i18n{uninstall}
    </paper-button>
  </template>
  <script src="permission_view_header.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Polymer({
  is: 'app-management-permission-view-header',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /** @type {App} */
    app: {
      type: Object,
    },
  },

  attached: function() {
    this.watch('app', (state) => {
      const selectedAppId = state.currentPage.selectedAppId;
      if (selectedAppId) {
        return state.apps[selectedAppId];
      }
    });

    this.updateFromStore();
  },

  /**
   * @param {App} app
   * @return {string}
   * @private
   */
  iconUrlFromId_: function(app) {
    return app_management.util.getAppIcon(app);
  },

  /**
   * @private
   */
  onClickBackButton_: function() {
    if (!window.history.state) {
      this.dispatch(app_management.actions.changePage(PageType.MAIN));
    } else {
      window.history.back();
    }
  },

  /**
   * @private
   */
  onClickUninstallButton_: function() {
    app_management.BrowserProxy.getInstance().handler.uninstall(this.app.id);
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="browser_proxy.html">
<link rel="import" href="shared_style.html">

<dom-module id="app-management-metadata-view">
  <template>
    <style include="app-management-shared-css">
    #shelf-switch-row {
      align-items: center;
      display: flex;
      justify-content: space-around;
      padding-bottom: 20px;
    }

    #shelf-switch {
      display: flex;
      justify-content: space-between;
    }

    cr-toggle {
      padding-inline-start: 12px;
    }

    #metadata-overview {
      display: flex;
      flex-direction: column;
    }

    #metadata-overview > span {
      text-align: center;
    }

    .metadata-row {
      display: flex;
      justify-content: space-around;
    }
    </style>
    <template is="dom-if" if="[[pinToShelfToggleVisible_(app)]]">
      <div id="shelf-switch-row">
        <span id="shelf-switch" class="header-text">
          $i18n{pinToShelf}
          <cr-toggle checked="[[isPinned_(app)]]" on-change="togglePinned_">
          </cr-toggle>
        </span>
      </div>
    </template>

    <div id="metadata-overview" class="secondary-text">
      <span>[[versionString_(app)]]</span>
      <span>[[sizeString_(app)]]</span>
      <!--TODO(ceciliani): Placeholder for legal declaration-->
    </div>
  </template>
  <script src="metadata_view.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'app-management-metadata-view',

  properties: {
    /** @type {App} */
    app: {
      type: Object,
    },
  },

  /**
   * @param {App} app
   * @return bool
   * @private
   */
  pinToShelfToggleVisible_: function(app) {
    return !(app.isPinned === OptionalBool.kUnknown);
  },

  /**
   * Returns a bool representation of the app's isPinned value, used to
   * determine the position of the "Pin to Shelf" toggle.
   * @param {App} app
   * @return bool
   * @private
   */
  isPinned_: function(app) {
    return app.isPinned === OptionalBool.kTrue;
  },

  togglePinned_: function() {
    assert(this.app);

    let newPinnedValue;

    switch (this.app.isPinned) {
      case OptionalBool.kFalse:
        newPinnedValue = OptionalBool.kTrue;
        break;
      case OptionalBool.kTrue:
        newPinnedValue = OptionalBool.kFalse;
        break;
      default:
        assertNotReached();
    }

    app_management.BrowserProxy.getInstance().handler.setPinned(
        this.app.id, newPinnedValue);
  },

  /**
   * @param {App} app
   * @return {string?}
   * @private
   */
  versionString_: function(app) {
    if (!app.version) {
      return null;
    }

    return loadTimeData.getStringF('version', assert(app.version));
  },

  /**
   * @param {App} app
   * @return {string?}
   * @private
   */
  sizeString_: function(app) {
    if (!app.size) {
      return null;
    }

    return loadTimeData.getStringF('size', assert(app.size));
  },

});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="shared_style.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">

<dom-module id="app-management-permission-item">
  <template>
    <style include="app-management-shared-css">
      :host {
        align-items: center;
        display: flex;
        justify-content: space-between;
      }

      #permission-icon {
        color: var(--permission-icon-color);
        padding-inline-end: var(--permission-icon-padding);
      }
    </style>
    <!-- `permission-item` does not include any icon-set, so containing
     elements should import the icon-set needed for the specified |icon|. -->
    <div class="permission-row-controls">
      <template is="dom-if" if="[[icon]]">
        <iron-icon id="permission-icon" icon="[[icon]]"></iron-icon>
      </template>
      <div id="permission-label">[[permissionLabel]]</div>
    </div>
    <cr-toggle
        checked="[[permissionValueBool_(permissionValueType_, permissionValue_)]]"
        on-change="togglePermission_">
    </cr-toggle>
  </template>
  <script src="permission_item.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Polymer({
  is: 'app-management-permission-item',

  properties: {
    /**
     * The name of the permission, to be displayed to the user.
     * @type {string}
     */
    permissionLabel: String,

    /**
     * A string version of the permission type, corresponding to a value of
     * the PwaPermissionType enum.
     * @type {string}
     */
    permissionType: String,

    /**
     * @type {App}
     */
    app: Object,

    /**
     * @private {PermissionValueType}
     */
    permissionValueType_: {
      type: Number,
      computed: 'getPermissionValueType_(app)',
    },

    /**
     * The semantics of permissionValue_ depend on permissionValueType_,
     * see chrome/services/app_service/public/mojom/types.mojom
     * @private {?number}
     */
    permissionValue_: {
      type: Number,
      computed: 'getPermissionValue_(app, permissionType)',
    },

    /** @type {string} */
    icon: String,
  },

  /**
   * @param {App} app
   * @return {number}
   * @private
   */
  getPermissionValueType_: function(app) {
    // TODO(rekanorman): Change to a suitable conditional statement once the
    // PermissionValueType corresponding to each AppType is known.
    return PermissionValueType.kTriState;
  },

  /**
   * @param {App} app
   * @param {string} permissionType
   * @return {?number}
   * @private
   */
  getPermissionValue_: function(app, permissionType) {
    if (!app) {
      return null;
    }

    // TODO(rekanorman): Remove once permissions are implemented for all
    // app types.
    if (Object.keys(app.permissions).length === 0) {
      return null;
    }

    // TODO(rekanorman): Make generic once permissions are implemented for
    // other app types.
    return app.permissions[PwaPermissionType[permissionType]].value;
  },

  /**
   * Returns a boolean representation of the permission value, which used to
   * determine the position of the permission toggle.
   * @param {PermissionValueType} permissionValueType
   * @param {number} permissionValue
   * @return {boolean}
   * @private
   */
  permissionValueBool_: function(permissionValueType, permissionValue) {
    return (permissionValueType === PermissionValueType.kBool &&
            permissionValue === Bool.kTrue) ||
        (permissionValueType === PermissionValueType.kTriState &&
         permissionValue === TriState.kAllow);
  },

  /**
   * @private
   */
  togglePermission_: function() {
    /** @type {!Permission} */
    let newPermission;

    switch (this.permissionValueType_) {
      case PermissionValueType.kBool:
        newPermission = this.getNewPermissionBoolean_();
        break;
      case PermissionValueType.kTriState:
        newPermission = this.getNewPermissionTriState_();
        break;
      default:
        assertNotReached();
    }

    app_management.BrowserProxy.getInstance().handler.setPermission(
        this.app.id, newPermission);
  },

  /**
   * @private
   * @return {!Permission}
   */
  getNewPermissionBoolean_: function() {
    /** @type {number} */
    let newPermissionValue;

    switch (this.permissionValue_) {
      case Bool.kFalse:
        newPermissionValue = Bool.kTrue;
        break;
      case Bool.kTrue:
        newPermissionValue = Bool.kFalse;
        break;
      default:
        assertNotReached();
    }

    return app_management.util.createPermission(
        PwaPermissionType[this.permissionType], PermissionValueType.kBool,
        newPermissionValue);
  },

  /**
   * @private
   * @return {!Permission}
   */
  getNewPermissionTriState_: function() {
    let newPermissionValue;

    switch (this.permissionValue_) {
      case TriState.kBlock:
        newPermissionValue = TriState.kAllow;
        break;
      case TriState.kAsk:
        newPermissionValue = TriState.kAllow;
        break;
      case TriState.kAllow:
        newPermissionValue = TriState.kAsk;
        break;
      default:
        assertNotReached();
    }

    return app_management.util.createPermission(
        PwaPermissionType[this.permissionType], PermissionValueType.kTriState,
        newPermissionValue);
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="browser_proxy.html">
<link rel="import" href="metadata_view.html">
<link rel="import" href="permission_item.html">
<link rel="import" href="permission_view_header.html">
<link rel="import" href="shared_style.html">
<link rel="import" href="store_client.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">

<dom-module id="app-management-pwa-permission-view">
  <template>
    <style include="app-management-shared-css paper-button-style">
    #permission-list {
      display: flex;
      flex-direction: column;
    }

    .control-divider {
      background: var(--control-separator-color);
      height: 24px;
      margin: 0 24px;
      width: 1px;
    }

    #site-settings-button {
      --paper-button-ink-color: none;
      border: none;
      display: flex;
      font-size: 12px;
    }

    #site-settings-icon {
      display: flex;
      margin-inline-start: 0;
    }

    .subpermission-row {
      height: 48px;
    }

    #subpermission-list {
      align-items: stretch;
      display: flex;
      flex-direction: column;
      padding: 8px 0;
    }

    #permission-list > * {
      flex: 0 0 var(--permission-list-item-height);
    }

    #extra-button {
      margin-inline-end: 16px;
    }
    </style>
    <app-management-permission-view-header app="[[app_]]">
      <div slot="extra-right-buttons" id="extra-button">
        <paper-button id="site-settings-button"
            class="secondary-text"
            on-click="onClickSiteSettingsButton_">
          $i18n{openSiteSettings}
          <paper-icon-button-light id="site-settings-icon"
              class="icon-external">
            <button></button>
          </paper-icon-button-light>
        </paper-button>
      </div>
    </app-management-permission-view-header>

    <div id="permission-list" class="card-container">
      <app-management-permission-item
        class="permission-card-row separated-row header-text"
        app="[[app_]]"
        permission-label="$i18n{notifications}"
        permission-type="CONTENT_SETTINGS_TYPE_NOTIFICATIONS">
      </app-management-permission-item>
      <div class="permission-card-row">
        <div id="subpermission-list">
          <div class="subpermission-row separated-row"
              on-click="toggleListExpanded_">
            <div class="header-text">$i18n{permissions}</div>
            <div class="permission-row-controls">
              <paper-icon-button-light>
                <button>
                  <iron-icon icon="[[getCollapsedIcon_(listExpanded_)]]">
                  </iron-icon>
                </button>
              </paper-icon-button-light>
              <div class="control-divider"></div>
              <cr-toggle class="left-separated-control"></cr-toggle>
            </div>
          </div>

          <iron-collapse opened="[[listExpanded_]]">
            <app-management-permission-item
                class="subpermission-row"
                app="[[app_]]"
                icon="cr:location-on"
                permission-label="$i18n{location}"
                permission-type="CONTENT_SETTINGS_TYPE_GEOLOCATION">
            </app-management-permission-item>
            <app-management-permission-item
                class="subpermission-row"
                app="[[app_]]"
                icon="cr:videocam"
                permission-label="$i18n{camera}"
                permission-type="CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA">
            </app-management-permission-item>
            <app-management-permission-item
                class="subpermission-row"
                app="[[app_]]"
                icon="cr:mic"
                permission-label="$i18n{microphone}"
                permission-type="CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC">
            </app-management-permission-item>
          </iron-collapse>
        </div>
      </div>
    </div>
    <app-management-metadata-view app="[[app_]]"></app-management-metadata-view>
  </template>
  <script src="pwa_permission_view.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Polymer({
  is: 'app-management-pwa-permission-view',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /**
     * @private {App}
     */
    app_: Object,

    /**
     * @private {boolean}
     */
    listExpanded_: {
      type: Boolean,
      value: false,
    },
  },

  attached: function() {
    this.watch('app_', (state) => {
      const selectedAppId = state.currentPage.selectedAppId;
      if (selectedAppId) {
        return state.apps[selectedAppId];
      }
    });

    this.updateFromStore();
  },

  onClickSiteSettingsButton_: function() {
    app_management.BrowserProxy.getInstance().handler.openNativeSettings(
        this.app_.id);
  },

  /**
   * @private
   */
  toggleListExpanded_: function() {
    this.listExpanded_ = !this.listExpanded_;
  },

  /**
   * @param {App} app
   * @return {string}
   * @private
   */
  iconUrlFromId_: function(app) {
    return app_management.util.getAppIcon(app);
  },

  /**
   * @param {boolean} listExpanded
   * @return {string}
   * @private
   */
  getCollapsedIcon_: function(listExpanded) {
    return listExpanded ? 'cr:expand-less' : 'cr:expand-more';
  },
});
<link rel="import" href="chrome://resources/html/cr.html">
<script src="reducers.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Module of functions which produce a new page state in response
 * to an action. Reducers (in the same sense as Array.prototype.reduce) must be
 * pure functions: they must not modify existing state objects, or make any API
 * calls.
 */

cr.define('app_management', function() {
  const AppState = {};

  /**
   * @param {AppMap} apps
   * @param {Object} action
   * @return {AppMap}
   */
  AppState.addApp = function(apps, action) {
    const newAppEntry = {};
    newAppEntry[action.app.id] = action.app;
    return Object.assign({}, apps, newAppEntry);
  };

  /**
   * @param {AppMap} apps
   * @param {Object} action
   * @return {AppMap}
   */
  AppState.changeApp = function(apps, action) {
    assert(apps[action.update.id]);

    const changedAppEntry = {};
    changedAppEntry[action.update.id] = action.update;
    return Object.assign({}, apps, changedAppEntry);
  };

  /**
   * @param {AppMap} apps
   * @param {Object} action
   * @return {AppMap}
   */
  AppState.removeApp = function(apps, action) {
    assert(apps[action.id]);

    delete apps[action.id];
    return Object.assign({}, apps);
  };

  /**
   * @param {AppMap} apps
   * @param {Object} action
   * @return {AppMap}
   */
  AppState.updateApps = function(apps, action) {
    switch (action.name) {
      case 'add-app':
        return AppState.addApp(apps, action);
      case 'change-app':
        return AppState.changeApp(apps, action);
      case 'remove-app':
        return AppState.removeApp(apps, action);
      default:
        return apps;
    }
  };

  const CurrentPageState = {};

  /**
   * @param {AppMap} apps
   * @param {Object} action
   * @return {Page}
   */
  CurrentPageState.changePage = function(apps, action) {
    if (action.pageType == PageType.DETAIL && apps[action.id]) {
      return {
        pageType: PageType.DETAIL,
        selectedAppId: action.id,
      };
    } else if (action.pageType == PageType.NOTIFICATIONS) {
      return {
        pageType: PageType.NOTIFICATIONS,
        selectedAppId: null,
      };
    } else {
      return {
        pageType: PageType.MAIN,
        selectedAppId: null,
      };
    }
  };

  /**
   * @param {Page} currentPage
   * @param {Object} action
   * @return {Page}
   */
  CurrentPageState.removeApp = function(currentPage, action) {
    if (currentPage.pageType == PageType.DETAIL &&
        currentPage.selectedAppId == action.id) {
      return {
        pageType: PageType.MAIN,
        selectedAppId: null,
      };
    } else {
      return currentPage;
    }
  };

  /**
   * @param {AppMap} apps
   * @param {Page} currentPage
   * @param {Object} action
   * @return {Page}
   */
  CurrentPageState.updateCurrentPage = function(apps, currentPage, action) {
    switch (action.name) {
      case 'change-page':
        return CurrentPageState.changePage(apps, action);
      case 'remove-app':
        return CurrentPageState.removeApp(currentPage, action);
      default:
        return currentPage;
    }
  };

  /**
   * Root reducer for the App Management page. This is called by the store in
   * response to an action, and the return value is used to update the UI.
   * @param {!AppManagementPageState} state
   * @param {Object} action
   * @return {!AppManagementPageState}
   */
  function reduceAction(state, action) {
    return {
      apps: AppState.updateApps(state.apps, action),
      currentPage: CurrentPageState.updateCurrentPage(
          state.apps, state.currentPage, action),
    };
  }

  return {
    reduceAction: reduceAction,
    AppState: AppState,
    CurrentPageState: CurrentPageState,
  };
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="actions.html">
<link rel="import" href="store_client.html">
<link rel="import" href="constants.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-location/iron-location.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-location/iron-query-params.html">

<dom-module id="app-management-router">
  <template>
    <iron-location query="{{urlQuery_}}" path="{{path_}}" dwell-time="-1">
    </iron-location>
    <iron-query-params params-string="{{query_}}"
        params-object="{{queryParams_}}"></iron-query-params>
  </template>
  <script src="chrome://apps/router.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'app-management-router',

  behaviors: [
    app_management.StoreClient,
  ],

  properties: {
    /** @private {string} */
    path_: String,

    /** @private {Object} */
    queryParams_: Object,

    /** @private {string} */
    query_: {
      type: String,
      observer: 'onQueryChanged_',
    },

    /** @private {string} */
    urlQuery_: {
      type: String,
      observer: 'onUrlQueryChanged_',
    },

    /** @private {PageType} */
    currentPageType_: {
      type: Number,
    },

    /** @private {?string} */
    selectedAppId_: {
      type: String,
    },
  },

  observers: [
    'onUrlChanged_(path_, queryParams_)',
    'onStateChanged_(currentPageType_, selectedAppId_)',
  ],

  attached: function() {
    this.watch('currentPageType_', function(state) {
      return state.currentPage.pageType;
    });
    this.watch('selectedAppId_', function(state) {
      return state.currentPage.selectedAppId;
    });
    this.updateFromStore();
  },

  /**
   * @param {?string} current Current value of the query.
   * @param {?string} previous Previous value of the query.
   * @private
   */
  onQueryChanged_: function(current, previous) {
    if (previous !== undefined) {
      this.urlQuery_ = this.query_;
    }
  },

  /** @private */
  onUrlQueryChanged_: function() {
    this.query_ = this.urlQuery_;
  },

  /** @private */
  onStateChanged_: function() {
    this.debounce('publishUrl', this.publishUrl_);
  },

  /** @private */
  publishUrl_: function() {
    this.publishQueryParams_();
    this.publishPath_();
  },

  /** @private */
  publishQueryParams_: function() {
    const newId = this.selectedAppId_;

    this.queryParams_.id = newId;
    if (!newId) {
      delete this.queryParams_.id;
    }

    this.queryParams_ = Object.assign({}, this.queryParams_);
  },

  /** @private */
  publishPath_: function() {
    let path = '';
    if (this.currentPageType_ === PageType.DETAIL) {
      path = 'detail';
    } else if (this.currentPageType_ === PageType.NOTIFICATIONS) {
      path = 'notifications';
    }

    this.path_ = '/' + path;
  },

  /** @private */
  onUrlChanged_: function() {
    this.debounce('parseUrl', this.parseUrl_);
  },

  /** @private */
  parseUrl_: function() {
    const newId = this.queryParams_.id;

    const pageFromUrl = this.path_.substr(1).split('/')[0];
    let newPage = PageType.MAIN;
    if (pageFromUrl === 'detail') {
      newPage = PageType.DETAIL;
    } else if (pageFromUrl === 'notifications') {
      newPage = PageType.NOTIFICATIONS;
    } else {
      newPage = PageType.MAIN;
    }

    if (newPage === PageType.DETAIL) {
      this.dispatch(app_management.actions.changePage(PageType.DETAIL, newId));
    } else {
      this.dispatch(app_management.actions.changePage(newPage));
    }
  },
});
<link rel="import" href="shared_vars.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">

<!-- Common styles for App Management. -->
<dom-module id="app-management-shared-css">
  <template>
    <style include="cr-shared-style">
      .card-container {
        @apply --cr-card-elevation;
        background-color: #fff;
        border-radius: var(--cr-card-border-radius);
        display: flex;
        flex-direction: column;
        margin: 24px auto;
        width: var(--card-width);
      }

      .separated-row {
        align-items: center;
        display: inline-flex;
        justify-content: space-between;
      }

      .permission-card-row {
        border-top: var(--card-separator);
        padding: 0 24px;
      }

      .permission-card-row:first-child {
        border-style: none;
      }

      .header-text {
        color: var(--header-text-color);
        font-weight: var(--header-font-weight);
      }

      .permission-row-controls {
        align-items: center;
        display: inline-flex;
      }

      .secondary-text {
        color: var(--secondary-text-color);
        font-weight: var(--secondary-font-weight);
      }

      .expand-button {
        height: 36px;
        margin-inline-end: 12px;
        width: 36px;
      }

      .expander-list-row {
        align-items: center;
        border-top: var(--card-separator);
        color: var(--secondary-text-color);
        display: flex;
        height: 50px;
        justify-content: space-between;
        padding-inline-end: 8px;
        padding-inline-start: 24px;
      }

      .page-title {
        flex: 1;
        font-size: 16px;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    </style>
  </template>
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">

<custom-style>
<style is="custom-style">
  html {
    --app-management-font-size: 13px;
    --app-management-line-height: 1.54; /* 20px */
    --card-separator: 1px solid rgba(0, 0, 0, 0.12);
    --card-width: 676px;
    --control-separator-color: rgb(218, 220, 224);
    --expanded-permission-row-height: 48px;
    --header-font-weight: 500;
    --header-text-color: #5A5A5A;
    --permission-icon-color: #757575;
    --permission-icon-padding: 12px;
    --permission-list-item-height: 64px;
    --primary-text-color: rgba(0, 0, 0, 0.87);
    --secondary-font-weight: 400;
    --secondary-text-color: rgba(0, 0, 0, 0.54);
  }
</style>
</custom-style>
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui/store_client.html">
<link rel="import" href="store.html">

<script src="store_client.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Defines StoreClient, a Polymer behavior to tie a front-end
 * element to back-end data from the store.
 */

cr.define('app_management', function() {
  /**
   * @polymerBehavior
   */
  const AppManagementStoreClientImpl = {
    /**
     * @param {string} localProperty
     * @param {function(!AppManagementPageState)} valueGetter
     */
    watch: function(localProperty, valueGetter) {
      this.watch_(localProperty, valueGetter);
    },

    /**
     * @return {AppManagementPageState}
     */
    getState: function() {
      return this.getStore().data;
    },

    /**
     * @return {cr.ui.Store<AppManagementPageState>}
     */
    getStore: function() {
      return app_management.Store.getInstance();
    },
  };

  /**
   * @polymerBehavior
   * @implements {cr.ui.StoreObserver}
   */
  const StoreClient = [cr.ui.StoreClient, AppManagementStoreClientImpl];

  return {
    AppManagementStoreClientImpl: AppManagementStoreClientImpl,
    StoreClient: StoreClient,
  };
});
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui/store.html">
<link rel="import" href="reducers.html">
<link rel="import" href="util.html">

<script src="store.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview A singleton datastore for the App Management page. Page state
 * is publicly readable, but can only be modified by dispatching an Action to
 * the store.
 */

cr.define('app_management', function() {
  class Store extends cr.ui.Store {
    constructor() {
      super(
          app_management.util.createEmptyState(), app_management.reduceAction);
    }
  }

  cr.addSingletonGetter(Store);

  return {
    Store: Store,
  };
});
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Closure typedefs for App Management.
 */

/**
 * @typedef {appManagement.mojom.App}
 */
let App;

/**
 * @typedef {appManagement.mojom.ExtensionAppPermissionMessage}
 */
let ExtensionAppPermissionMessage;

/**
 * @typedef {apps.mojom.Permission}
 */
let Permission;

/**
 * Maps app ids to Apps.
 * @typedef {!Object<string, App>}
 */
let AppMap;

/**
 * @typedef {{
 *   pageType: PageType,
 *   selectedAppId: ?string,
 * }}
 */
let Page;

/**
 * @typedef {{
 *   apps: AppMap,
 *   currentPage: Page,
 * }}
 */
let AppManagementPageState;
<link rel="import" href="chrome://resources/html/cr.html">
<script src="util.js"></script>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Utility functions for the App Management page.
 */

cr.define('app_management.util', function() {
  /**
   * @return {!AppManagementPageState}
   */
  function createEmptyState() {
    return {
      apps: {},
      currentPage: {
        pageType: PageType.MAIN,
        selectedAppId: null,
      }
    };
  }

  /**
   * @param {!Array<App>} apps
   * @return {!AppManagementPageState}
   */
  function createInitialState(apps) {
    const initialState = createEmptyState();

    for (const app of apps) {
      initialState.apps[app.id] = app;
    }

    return initialState;
  }

  /**
   * @param {number} permissionId
   * @param {!PermissionValueType} valueType
   * @param {number} value
   * @return {!Permission}
   */
  function createPermission(permissionId, valueType, value) {
    return {
      permissionId: permissionId,
      valueType: valueType,
      value: value,
    };
  }

  /**
   * @param {App} app
   * @return {string}
   */
  function getAppIcon(app) {
    return `chrome://extension-icon/${app.id}/128/1`;
  }

  return {
    createEmptyState: createEmptyState,
    createInitialState: createInitialState,
    createPermission: createPermission,
    getAppIcon: getAppIcon,
  };
});
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#4285F4">
  <path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575">
  <path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path>
</svg>
     kȱ ]n6[X㳚8{4^DMX|d㘟q_d3z [9qG$UYO<W^oo^_^K替GZz[[?<.Wb-c bחPmU_?ݪ.͡zz{׷ˣyQOvޟۿBwwv{߭V}u|e}ŃݬYwC5GǇUz:}]_]X^0>~>>Azwv-jv6ӛ?;gvs׳I~Dկ2B狃+RW8}r+6^1bgA}9?>i'iOg?ݼZo=uUowan{W.=Pq_c}\U[}qŞ[bz\5:r]wa~8leŤnQ@U:.%lVaM:hͥ[ԫjɓv{$H;KqvUY/Xm:x(,4{[ow}6Gj҃7?+ʏ{DΧJY^LW`p GOxU\^4Vw?	K}}<VpfD@=%xv5+2ixAh	'(9r{88k}־;G^9zA "2[} )[RlM%3M/{ꛈ {訷dnJ2
yi0 WQ"g8Qg#rO \ OmwPdbaD\!'a_YGV	`Al>^\0Or[!n@ThpSRbX~ֲBqs5/ܪ`m	^u>-a4@whum[/hfM[r/xIfCۖLݴcТ7a|#m-j[yeqmc>BZ;Jª*02ct6To#(
$@ʄe'/$#ݫWwU"zyAUu0_^a*M

ͼZwf=C6%{ΐ01|gUzZC68~fR/{uLڰ UJ.<'^́Xbttsv0̮a:Tov` Imq4zƿiO@z4Hw +bbs V7P~,0ٍJ-Hc]_ 3k)hNP8 m(x*[^JO\8Zh怔|n}3Ρ>`@)ڍ"L.I\0i`&sLZ&oar̴`@"x
%	%;m@/lo7~}+K9ca-fno ^XA*J2E_o|OYy㰾!]0˭aV$1:~J
#O*Ku]菺^ >^S1#TFh!;_9vX.b1x#JU-GqOQ{_9eRQOz@;&&mQ1仯lO>bf֪YmZ*jQ-f:y8a>ժZ2-ej>oqsKt+w)UE	@8/;?W*Trv0E۷[?wBC.|{;e.HwCc01"݁r;_z;COJZA]xPwqS7)WkMG}CUrhTuiWYo1w5&J|Ҽl3j[] zM7)[+
MۏY=gI}ǥYԄS:4{n#2%.`"B_[|Gz	\;K/i*0[g$05WM#q GRj$v6w66Љ,RWh"Nz&&&&mzAڜ	Fp'_idiF@[ڑ+^7L	1	P'vbw;qw;_5W376mc#Q
5,]b j!sgKqGKqOKBNJ;J{j)&Ά&uZ-۪4>b8Vfhu\2A ٘L܍]}aҮҾ&m[wmM[dǃ{d=tW8_vbw;qw;Ҩ/_vRw;iw;pZb\L܍iDy=],YU=&r>l#z_-ŴtObO4xnEO8l3^<S{y-}N,ʣ~JgKB(/rk8 N`>\|L,2|6V d/fqd4pFI0)q$iXer̎$C	&T:0f0I'V <dah6~&An'`(t؁haVi\C9õ
aN ٲ8;+td2+EiMf7( .Y("qV܅.sv-H4cs1u^,nϫjWd0<,j|$`Nr:e^F;A,l"T:2_F"cѤ|!Pg?<_,:'e2d$pAUaL׷[..yU!BgP.|^8@|LyV _i["g	D<M!F8ӅA4v0	(TVWKiziyZaDŢ2ͽeuV1Du0W" ,LEծ<͒Yj$QaZgiNEl`<50:IfZxYj0dRV &*IHM'SĄCdEpQkHMᐠ"c c<Y`ɢ0Yf
x\LIX3[< 9d2wqit&d"[%#(n8F pŦ/`119JdDlY"ѵa>
 +T'V (K{&
qpNYq<-UpBơBd#-4cUF^pt06-gebeEi-2ӆ8r~dynͧ;ifͦIdV bviQp^C4]QHJ"5,iiWY`<3Gʽ܁(I j`M"Hxp[CpYZE<=]d3EPTff"[i옩%./EnrYYYMZyZE^T4eY|VIqf'QT"/4gѢ{gqb\,A' K;9ǥe-A	f8ZLbbEI[CVU
9LR+ _H0$xj`"Pۑ+Yͬ j:+ _C.#)V@ݮӀ8 '`$YXZ[M[N25f"AX b͸[ <7p#ǋiGZ|Et]kV^ϮWLC{gnM|+АvmBpzB,	(y1M0A"pAb]|<^dNDl>I\4$I5Y۪ap\p`9@ej<MDDsd8gyq\) 硓0Yv%nӪY5Za\l':	yg7$@$ihZR2܄3)i\783]YIFHUt
JgU(Hσn@:JO«Ýqs ?;Cp˳,"Cp>sS%2֥|YMl}>MLyR{,k;]rI<> yn{"]X	@z7
9s;d+ wRp + 'e?V)_I~@KΪ׾-Ѵ\y̪2uC HLnT>-]`2gn(Gdy𝿴0WZ(FxL>#gy}_(I0%FrC1[UsP d4OLܘڃ `\ʊD._4g4rmuGwg7▎Ϸ\z=xct{opqe,Mx<d:e_sG7^×0h\&^e7Io^ÔJaH%b9^*X,㿱ZxO`Rۦ_)C Ŷ[_
y?;xqs9ڰ3΢,w_./uUྮ>~E^
/)q̋d}3G_|>_^R]x%࿠ze'} \U
x7//,@U\üqyad8A^Ӥ 8_Kqe1{)8S އr?& ]ȣX[  2$V&?gG8gL8gG#LC2dL-Am#ґ؛|_/
8@G4eM8	T2>x	ClH{͞,^,9@0^}{?{2{.#xGu1yQ _U
[=IE0M@m۝xaJ} `vVE
U,O^";D]m5
THeB1Y!rO"
VkmJ+p
}"j/b+Л0$WWG{TVtAN菷9Wؙm%}B{<VU,#LG|g3x	uH LC?̞Gl"|Fq?-Qc`%,]Mv"TI
å.[sd}/ ^P5h%e_@EorP&E1hsPGG(߇/k?s|ޠzL`>G9QC({aڠNPmoxQAjPנ_)Pvbb˛}1ab" *;ĂS[
G<gYg>^QPQ
Zi
J&(կ{lVs.Rb*vlG]UPoU+>p~RC Je:D$$ԅS"MR4}?Tp7  <(3qo>&zlSuTrf!`*7DS0 !aT&.]ĺ	0tOD14;%ރ~y`~#ԘAs^lWiVMja0HmԭVĽPU.ђz3c\C @0$1C ;vP @Pk>Ũ~!ʏ`#׋wV4e-:	>J-PlL#"2&" h"0OYc>8@6b-8Gw:~Kf]vв,_i~hF 燨}ӡBǡTLSyI`'DfJ +}5'k\#=~N, 5&hÌSF@1M߄qVmI-`z>FB.@4=tQ}	< $0W[|L#u/tuA|JzB*vue]Z5rߢkJj.|6@`gD,q.=bD(A ׌e8$P`~Aby(DэQ^/E2C_'f XO)
nZh"qh8?Ls$N=MM߁vWmzoO=}6MpPn>L@SWbL4'4}#uOK_a N aTi,L''	/ilM:Nl*6eJZP%כFmR:q2SaQvssa ܓ@PSt/>:B
6S-.
)pZ+G4yOɇ$u0|<%<Kw1{Ⱦ}fqG1Mc)<N߂if]~t<s@08SEX;z&񭀢v	N|IR.locRGL0BlDlI t:]3c[A>'L୦xY
q̡:Epx 1X-0^3A1E,-!8A=,'(SP@ Ru{c 3AfSjsX,elnY(HD%qy3S 1MJASغG:`Ј'p	`5}c2<HR:KP
tb_X/jc-88p:cEAM1d_&%90;1KƀY4@9G$@w	nqfr^`0s:MLY1Y_\'αw,t4AS
WC\Rymh 	lF<>CL} ߦ :=L5aGv-˅f (xQs-"hC-O)nt>3hv`v hZl2͒)6[&>Nbd+r2G04#	οeSy2801YThOt$0Aؑ&q 8FlˡsMОo	\1gbLAq!_(5$z <
p:hσY^HN\E[ԥפri %P-~%./W܀qW܇B	-*LThC\-]fbVPPkR.T7QC;bhE~'>=*pG'bjatMTI+˚():@WY	r0P&NI@kZ`=I@FBa(Ě6wIWYrC`?Bqހtu7@+\]7k)4u70(Z1P&5Zo<7&J5gkڅ^ ✇pxH۝!ٜEN]e`8" ZH-Ukm$^;qr6%ꔳL_񐶥HTHuauiNզNnyKO"R+n[*Z.͙6LFT_C)(.&Yi,YzUꞖr)lgvVtL8ŵE/la	nmwյWoc]/%صn*_jYJLc-$js77:̍YdiDp2 dS(krGHTrR A&CS@!ʡƝfPqx 7 awz
_19J
o~dd\5-*  	@Ll?OI{0ӎm$p2l&DvFmGw;Yj(m)3<gw#j~9rQ+glf=ۀz;CG(e
	eoŖ+o!"Oh(T F"-GG75,V3#LB0y'NG3pksK7 )OhYb@sdj2_`x Bk0iH]O\s!+2J/`DcIs	OaڬMZkZ[?>uAeڄ]iB:x357i0ɣ9IEM [Fn7ܞpW0HN)7#&$(j_ˤ7qoߚ7I$ժWJB/dZջC}@3OE(۬i7*&'l8ވ6<<	vto:\`c*F8l:(5\qxDi q@b̰US.<T|SҨ{i m6Z;añ򖱩
<¼8` fn_0aI=7duq>Zٚ4NYY2vsA!$;kn7vUXO7;|cN`%Wq_lFyp<2<ҏviw&@lJRCɸ&y]ngQ]XS,nXB-5𜀲Fu7@zj(^:7,QH\17XJpxꃙtwgC	;Kk&ͱ^W7X;X13غ؀+f{2{h+^F>/㘁xL1L]ܭS(/}\K%Zy(SHiw/h"Ak-BkWPe16YP)gmzCu;^*~(S?s 9%		y#	3:Ӏ^/.zGAʟ/#m^nܵ(y}'2fBJ_+lf]
5
yߔjmhm ;mM>7X·.V[ײkYs_}XZfSr#	dJQ.**Ȕ㓓!t0E*|}ͅ{危4^"UUc'Ph/к$*:[VV8V)jg`4֥vS!e>SLa1=ڊ_qXpY::?MGbEZkRYX=vliaTzjoHzڊ)-Iy֢kL{//?_=Ƈ7~Bsi}]03_P׷M[p(W_^[5j{?ntF7s
3ʪ77x-KްgĿ)8Gl5NYSW3-c^$pﶵR,_xqQ2	[4l6[ԙny/m=̴DV9`H\΍S)[+jv^9ހ %S}SAwӶ|*psA?h)}X*RFm&!*O)Rm0 2ͷ6<6Ay`x";E6Oyꝥ&k\yTC8SQ)v*!ꊤn
!uK2*F[Gt+>QzZBMvӳZ-($9vX]S/ɒ<+KǢ&Юw,)it$(oYX'/ql{4/Pl; e~@C\
m]P] '9DK3;Y5Ѱްi6ȺDh-nɖuJGzKOؔNZ9fkⓙn4B9E;#MC]0AǾt2vM'nA,M}kfY飏׉d^}TixvvjҞ,6er,Q~Ǡ:-ZjU0(=eв+j{׻XsGwcҽzr\C|fc}3)E5ke3:ȏQ'+u>gMu҈DZt*tzv|TK"k7yN80<zY^8l"cW=!
ŶGʇ][HkuRuՂvԏH@w4gK/
Wl^*Ũc mwazNlzX_`A%9c&K ЍYL`ޏ8,|$q;WA*Vuh4[9p=]]qܾ	-Td`-_FG`FO<|4鸞̩ٛހ>}i|IS9x5vA=:{$-ݬx-{x_`B%saTA-Q!le<|0lȅ|-bL*vq+8d'vQ <.tWGDsx#C=Wx|k+:X$[Ic8bEw}mgm}0a]ÛJ.؎v-ݵw<-r[oM4G؆$S9cL+P՝|_-Z$WD4\c|K9iyMPOuܶ="HTV~|%ۆ;>,#ʵ16qmGpt<Zp4
;'dhw#omDvBj\^r'y摶`nQ阪Oawx4b<a&q	e3ȱK(m*fgv*:PU :YMl\	WN
x.ޔyk$G8Z+(1t,p2֎R+J-'I\&TKL<8g9P4l4*z#Pu:*f}a-["y!>SS¼W|<tng_K4¯1pEs}@MϓnP ECҺhgN0yoQCEX['hw`A
3X?aэP-{}0N"w~KTR=福z +H}t]߃D0~L_;!З&*&: E)ʰ4zH-O3fkҴׄp,{XCŠı
I!/փn+4;=Hq<4scq4gm4SVzdG̐X5iSҊҋC
ICPCN)ЌVj}@7SJLc91۠8hIw9%OqYoPҭ
+wyX`X7\B4QREj$JgD6*ĦXWB
SW_4A*Z?9,n-TmǠ?Hz(M?V;j+֖wG_%I
\.Uq\Mz@?mw?T7*h*[T{R;:0Il:FXoPg*y]iuƦwCJWԂTv痧sFhj]q;&0YKx#eiVcLsM-"OI}Z]5Wi]%7sS[*baى,kvT@GrFg~f}7`vkA<m1z5l5S5fߣ*{`׶)]ǡhCܹ?뮨{b],n4zwʐ1Umv}BS}}GCb};=ħ}Q޺jH h[C$B7ja4cص]cYQOcTN;R;C]i/8Ux:6(qpZJlP`>sCvlhC:elq<.?ܢMz涶R9K)dWbF z%O%^-ϖޱvMq3	$T6	%aZxgTe`+j\}:#tPXKԌs+Î=1ͣ6''imheIKU}^e=Ej;Sb6sBGwYuT
"! [vL۟-Ğf]iYpdk'XFke+tK+*3F|}XtZځYA޴z	=l;X)o@>\_SE.tҲ%]wr?b]|^U4̈x^Ϭ{L5jx#v!%v_)LgXͻcO}O0QJy^9TdT+}E5@6p+Q9TҫmOo,*TnO1]zrSJ"{Λ%SZ#bUc oiϣjnl1vẂ2^
[+Pa:q};ռsŗB]bɲ~Z#^<|H`㏤Hd=oW	Pa{wKkCZWU8!`!ZoOSO-XM5РKLxF+PX˂46Fw24 ]ƮR*,hw1sZҞ,N
5	ѺJp ЌA~N2fjy0WV+AJ̑hIk%U7䗺?Ɖ8c{酣ES3Nz@PH܏;,*'P r(A2v؆:Vz~Ćz&`7v$#N%?<̆{ցFg>=܆|.U؁>	o"GJցTt >uyx~:.MM]J;_餦%Ї~zz/"Ĺ^LqDf\r%IՉ΄tG|_+u8+x}iptB'ʹ*=c&knZX>?07ÎU>9x`y'ϫ>X}hCYc k L!NY "IpPv "Q"D !H|"I"$ !HjAs},:f7K5lF7yxiLٕR
-*J@βhYR9ps=}F}mBo?387m,,Xﴏ'~$tǼML,dk/uuԵPf%3lg}qe]v5JMgS*ZiUqi+@+MڣH
p#{P˝~=OȖ  Z<z})M#hڏ+0_eJ$ռ>6aݺw&=[S>Yڛ}ShnwtJ+jmud~W7ÿ)K>Zu]riQBw/<:_0;#_{v'	^h~%NG
ٯOnB@[UMR='k>O_xǤyw#ݺWONwzJDwRF{~wkuQQy@;PPQn05C @sޮC7>93͚esWr:&:Ǯq=IGP*-G@-H@W`m3!8ؾahb1xf{k"SŋV-rAIaPּ4Fk9/15z^qr܄_H%_bcV=#!ekbH44mY0{f<c8NXrτ6tۜ;vKW?gtUеca>X-W~VZH!6vvR널k?boM
*Rf}ƕ]LeF#?,7O5im7@Umj
?,QߞWR]JP Jqo5 IMO`jiH}<Ժ#O'HfrX^Fe6Ygd
gdu~쿜to8^vh?s=}5n/4FTV07_S"qVXC,OĬ֮_4̷q[V%(@	V?#<Q<Pv&p(@].{}!;C2,p9o=q^zˈ"UJk*x7eWF9-&zǭU3NڹڂS0()颮b"WVԁ-Ex1zqehp+",VIYrN9.^vZzq"ѱBHl7z#~y`9I+l-Ӱ܀eF#eՎfD]ȸ;97'V7jaXDbO"R6VSsWNIGE($16VfFW9QT
Oe70|sRIi; u?v4Nz~/6CfQ=K YWC-kvTKmSrf#(g4Wrwy{BX(^_~?śÚ-ZDh8h<NX=FN*&ya4|[`Yn(o?31=(Ї?G]̶V}<ccvY+*f`6:5/6ǃis4~ ;Mi{I3tKJ\{բ[oz=Bs>ThGf7p-xsq;YXYUSjD}qL[NY/ORa@޶TB3;9o˛f\i5(`qD5RjiQ|q@W	`t#/EhvA!ajTy0ܢ}(;}b@R0Z9jaqFF~lߟt.R36DIXghw>+R7rDQ`zvHBTFf{:q#HJ[\x ¤{.˂^e+5mJ(Gίȕn<+2-oXe{cC f<V<pzėFsks?/'! Ջ+9ݲf.+N/_D
.,	wkJBrzkg 8K`}rфg;}9Q^WF>c3TlFXYtS݂(k;hC;JΛ~e0@؂UwmA͝y\EPKf*~=k0=V#RSӲ&=Tl6ƙ8ZY]-ѹ zjr>sz謈sz3[0mGNlyTݣa~Ge\ޓ |?[	RvݎuH_Yg鹞Tͬկ1k&KgZ

+-=_YѕQg
]\iېvs@C@+FA`=TAo8VN~i].U*gh<YӴbqFlCs-C32[E~*"'4.=鸦4dX#Q-%޽j:F;,P3rIlqHBc}&=cDO^ھzlf><"/ڨnZ	V39"Bv4jn"w~a[vW݅Sn Q|<m>xn`k䯶h^0ڨmq85Z29;kQO8BO}zVᏖ.ÉC<`;CbHJ5̤gf౺ތyGf?"ř~uĖ6pe
Dg⼥龎,9iFoFk	~<QwyA.aٓɎQwxyYX]1X念Z뺜D:wLI'ޕLV ;n YY3ZQM۽]'m$v)tJS7#?$+xP&C13P	i"w{~?ajU?:3Yb4߸(N'@oo|Hg,5].'cvt\pƳ#*MZ>.&E]\ӫk*Z8&DwYNv \d=f[og)U}UR	|KJ)4RPDEd"	J\\1ce;`v@SbF>NŻ1<w$OgWɹS"POwtJp33+u8Y?Nh6q?&mY눰H[r'8_ ȓIFs%nz{ؑKGғiuwՃ0MEŘ
Ehb\j"-CTiqlzUnѰe>^VcXܜ'6+zA]QW0=nNC%3/[dB<7cgΏW*xLR/v@gO-W1j#o#m(_MyWМ9Y8ձ3S媒q+^n+Nq)R[[i]$긷>Rǳ T<SBJ#82y	3wBb]̆UnXNSzRY_%c'}`$:D7]z*mԢ[KX_4~3cZ#>褚#k͸bTTqlZᖺQwrR݉[<l*WEc.\q?L
hllYTV˱^&n#rRFK5ކO%1ReCZ(OKOH㢘cP_}tbi'VV}rbQEš0(0NnzIHIIԝ}iԝ;4uOz;4i wP=,Ċ,D$D$B~nPgdJjO3i@OmOz9CU 3ciԃ->VVmN,]4`XX0EXh6JaI`|eG;Dg; ǹ{͵㥱nINMf$7jIwlkWj C8y$K7ꥣMW:k9YBP3]3ȧ3&NİwZO5XLhQ`F|w>pn\R*^7yt}xr{@إZN0)j*VwwLp?AXV-5?ZÉ;eo^a%௾z*m)z;k33h:Gdio95dݢ!_9"g,77vx3O/=}s=ȇYֈjFnn<Ց4YԅU cc"l9h&,꼋WB4x14K6vaQW#T1BnsiEq ~ޅsL${s@)BM-3ܿyx/.=sV%Zo,>UcZqڲm.Qgi5(TVJc9_N>^W׬VlvI.|
>\n`zgyK?~ZHy.ƭaqI]=-nz_gĹ<Rԟl݈?⸹'`t(k;cyD(K̉&b!@C+9ơ}Miǫ['4W(ϷB|}-iP,sx5ZEGh9}h4,9]mDi0Ya}t{ nux"_S@fo^VPt\5rLmӈ5Q_,n0NKxZ+'B4ʈcݱ\,(LM͞3-Y:A
iAʏGw})CٞDGFP=Z!$3BvշL?E}zq/@)5|wӷWM:fVAj>{h[cY|%XCԷڲcY4=m:ݾy{r[;\VxeQՅ;@Q &B7eKF;][!XWS`oZ6pś/*S~\=hCf̘U,Σ1$S~@ḡX'?:"`Pa@8P$r UEK$lJ>!lk
ig}YKg{چjVhF#Q0_K3f48қ	
['[{VE7eA!~ l=qໜg_f-XWc3zVԌ( Q)tLocR4
gR3]TwXz-&>c 4FF!h{Z̄Y?]gSӱ0;&Une=:g4&*d~vxojp<@\?S0zdv̎'ͷ-S:'zr\Hڋ#]mU;BN[tExXZөeG/g(/};vo]ԸeKT;%YrO}{a&(!f'#a$Q,!xw$!7ϰ,A~:mgߖl'Pr>fm,$W 2띑<uצR51dnZ V?kOe$$ٲ<[
sqZ
1E0Sv{`t?7ÍgZPkVѨ8{[UCp	w]9oCl\^"3)OKhϣ
α\V)wFcq;hsr+?ӉSfis%cpl{:݁{CsSďT4F.Dս
}575):,\?W}$itӥId㉜<r0{)pYĹsK#7vʝaew[Ϛ<eG*+5ێ&Q׷-nZhv+Y~7Ĩ΀VVG뜝%/FG:n4R"Khla:&vR/}lu㱿	#A"ab!{_#ev3I$8&ĀX=H +(g?@i4ozs{*jmyE]1ԶӬqf̎Fy<ݺH)JC»; 옝a'=SY̾#~ -Zp'{i<o+IIȝbD~mBQf'Jكۯ;Jt3Fl`pR" 0`pӓ7}[)0".9`Xh7RCTVVGJZ%@m2Mzy3ÑԸ<{g3K^^楕0vf, sU-S[_h{DTvgERkȰљ(i`>,(v]_TO`ӄ/o;Й˞<]ɮbP8q:'@ m1TeO}/hp]^`T!Ekj~/ÍnK{FQ19t{v7XqAޡ)4&KNɼ}*kVQ끌ޜ6,tLccq1|9j^5OOo>+ScSHH{?|VyVZq2=Oފ0HMX?D'/<(b<zbdbCNƣNDJJ"[z~CJ)	RPp)voU)0_dYBx=Х0zCF~^)      kȱ ]n6[X㳚8cݫ A	/z3lfVPO dKOI *+3++/~_;oy\^޼޿:7;V*v˅*6~+n+x\j[ ///.ڪz+U]VCvoGY9 La]?V0[<?xPɏy孋oY=xʻ;Tsn3jPo}m{-#tڱFǷqy7۫?n|||hnU+P+ZlH7w
港gwǓj}???_#-d=x}oW1
qB!ap7ǭWlb>Obsݟw!}O/yzo7_'b]\{ˋ"^q?=÷WWZjt~=3qˊI|Wh22u\)J ٬uњKWՓ'0I^yw8nח?쪲^% Ymu6PxYS=h>nP4_bUmԤosVoO^{ٳ(/(¯4=ܟ (4繊h؟*@Ox6(|)5:xT{zJ,$TjVe<@'OPr>pq$}3"Bwt?.jsSӗ}O@BEwejRSѽvJFg^z)4u7QoMd-~%e^/>x^K&aK>.Eօ1lqأ`϶G`L_(e:j
JrÈBOv3v3?2$fi9؎}(ay@?yBT;Ω7<0İeKrkP^U$4o(}Zh; %XEY۶_Т5zw*k^>Ͷ󇦷-iǠEo F<[Z}ӵD43>|1	?nw!#U=oU`d4lQ<Fj;PH	{qEZO^ IfG/vW/؁zD~j9,x-aH(IT
&jy(Vz>lJ!//.`bπϫjOkomzwmq<9^>	/Z/a^]xOI|ݟ``]t_14AbhCۻ-Vϟ4*hX)( VJ3cJ)$So{AoVo~1Y`*5.^[Ǻ<R1AwMG[gvRvG?틝(q@MI%: PTq$)UfC}8RvE.]0I`&ud-L悙0L.i3uD	JPJ"v(Qۀ>_bUnX\ǱWs([ LU\eċhKUa6a}멡C`[wHjcHYuTUwF֟zU&2uqZ-4AG}bZGx9',rCvrձ\cW)c(bGZl㞢r>:	˥hW>vLLVb.w_
CU}̀U0۴TewC-(Ԧ
[;Vupӟhy||U`e,2Z+4Oc}߀vR4WV+ /qS*pr˽_v0xQUܩ`6o_d `# ]vN]X1!h5v)02 `bE.%!!vv~&8^á:ߧnJ]YSZ'֠}xE맪gĺ۬ 0
17neQTJXԫhO2ѥXLUh~̢(nHjS=?.Bw&ҡsLUTqMKH[j[/K{:O.sPbHl]f_y7aKHH4B'K]M&&&p:_:8Mi&lmiGz0%b$@	ډ4|2h7w@\ͤff;Sf&f:sG۷OD)
lր[RtoX+Ν--=-5L
;!Jvn(h(iBȦ;8t4jmx[֫ҚZ_q%dc2q7w55Z;JJښmu5j{l=ȓ*.=$^T$~ډH*l~I4,is52q7brl3tfU<}>fI<m^>=j?I8x4Nm>Oq9/(r)M2,mAȭ("oH8@8yJsz3@s$lX8IV EE
Y&xnǑ aV y2;%P
Y$X7<egPhTaeYdrn[Uq.*;q0djs:T̒ɬ|Ae4߼p0Lfᢈ YΦZ"Lrڅ 	3LҌzU 0=j^MLiOYi:Iyy=hISSp~i͋FF"c BB2|dɼ0KE sW!3f^nUa)SR8C}(y a1Y9s~e6+.l4&4] ^L&Q$ ,xR9@8rZ-\-qq6_8aiJ61X1m^ 80U"4Kf)N:DeFjQ87N'im mf)g8̓IZ_#dvF$#E4L]EF"5C!dQt1N'2^L:D'g)Jq1]$`LK`nA,`lƥ!L'Y`nQ2L`t`Z|(6\>(UEdDת^<B+ RrX8,M4t+ w
9dAfA8WnWѓY@Uj8-Z{´@p@pt@pL@p4NH
:L@p4v$GyX8G	^!">-s{G9GyjptQG")bԴEe^eaZr0(r'vn\f3`s$`-16 qmj2#;fi9tNAQ9@M2oce{ge57iii{Q<K^Yg}LY'E\}YD]pSɧL*4E.8L]p\BrK,IXq' 3L"3kz3]*"X$elYUMK+@,l2I |i"Ԏr>/@	>ClGl,fI40O<J |EЎXnuN~ZH*/06C𞀑dYcmVho17y*o9!Ԝ9X>Y;@bJ5J.l~<s0.\<.\2/Ej"tYy>Zj^m|0i
7bY]g[0;7b @C!UGvyjG3ћ0'"&v,6) =ux9!W A$qҐ$q6gfv_lnqe!tY eEx6Iѣbe]2ild"ơ$rdʧ4t4N4.fFfіvZM
gմKk|/KsCk]pqEhZf2$H;(iIpϤ]p9ߠKⰳ|tgA'!Vy	((UI7 a<<*-23o?	wSL-ϲ(0M Xyf74Mx0IIiZHﱀO|wwCp˽&Ql ,=taYb& aV ~ + #l?8r~ 1J
 X|%-9_ZDr1Kj0w
"1=Q4vw	<aU求jw\kI2In(N,П'g4^}7ݷ'8alUe <B0x|zDkL>1qc.jrȂs*+v.ptќ>T)ˋrޡ>'v W+[:?߮zs{]m(diʾ4H&)?;⿩p?5|	OoHU&~ÛD5L$T~OY)_8%2G@0i	
)5~Om2Rl~MeWHPsˎ遛ȋW:;,r{9^W!o_^^%90<2!̼hMOv'?/>%ՅW^^	[&}	pYU^ o"T5K?F&5M p#Nd^:_!|8B>3>ű?8L}(Wl2r%Џ< Oq:'ARhe/zh8qz?sh
&zD8B>$ O6"yu<[$J{D#૟@%)I샗?Ϻ5˒㥟gK?7-2G}Y.`E%^Ezc?8A$[D|w;&{
`iU+PbTU*RC5VcЫ@>Z !-`֖XTڷ	,"9	C~uuGeEw攎xqV'=7_l`U{M2+O=~ħHy= 1i^8dyԍP308i%+g2xG'o{OJR`.}0tAؒ4'0 |؀*@AO/)(z+7X.HEK/?>B>~^+c"}tv9z̉C} ܇w܈<DMDuj{wī
JT#=H'OA"[\ k!|Q~Pع&RF~~`<>:{yWl*FRH$HT(Ur0AA~ݫd˰UHuPc=|6zZ0QD`8P*@!$!Q6=.]Ξ	ߧoҧ#
Ɔx GS=~_|7{`#{4[AxUi}	'!	82Ov	~"M&Zi)̍C9i0To:v6o%:TfjFj# JP-7{?&͕,Q; h]P_ #MøL<}mo`	ZSJ ^ 	f0r@1 }gESV21+CexF4")c2I-&^5md)֒s4z̸TmUk-b懌fR|~0qMX';*?}a	*K>	L$0'|@d$~ooག]Wx]x"MF8b7a.Pc68iMwaږnc(DIC~WYA@x1H54PB\T'roWWuu!L\#-gM V}Fd2O"S/F$z]J?	(ƙ>Bx%Q$3qb%:i馅&F=ô>HLۃxTԀ)owƯ7{7`#,'	D4u%ƤMpBN(8RWD%]y0z$F%[xbqYf.&jؤ$IaPA	uZ}9jT&50{0iȰ'3&e7Y8Ǚ2=ij	5E@yM=#aS;Ur ipD|H'q^G1Sr,~+{/Q! gw8YA[=-vhFNG:D}oC=^Du)k
(jė*ݾ>>6:)E~4	*t@	J&}$@%13) s4yj>wnX@Y	.ʌy92%?S({
\\r[Ksrh}2D"+XG_=1
p8 ;dl6 :ǁ~
K^f8OxƠ-DT7S\<ӤT9ՍzSyP&X3:,ʃ(E P@'i!E6~ꛎcG3F]@OJeRI`HsJdHEKTsHa~g&% Z9PMt$H%x%p2=.{B_NG4p%:%,'Ff3T<ާ(n	m:S<Ts_{}mwH?_Ȼn%0gM"<	Hg곯8C!fFPjfkˠ&,)+Ole$_KH-/zC3"Ix_8_F8e'ccE۫A<,&hD*KD	iW1cĶ:H}fn>>I FU^C`N 3ڈ<ku)$-Q,dU葿E]>yM/GP	5Xx	w}X+ĘD%?	nIx܂ѵm&fEx!%&=a᫾O~Ye<#6:.8`Qtow-O-ݣw{t"F,Q0AA"껬Q. t՟L(,e$
%}mDd!։baLino#qt!0#GHWYWyl!K(U}U}ñ6OBSwS-̌,|nXeZi[xC!hZsq	V]P~-y(ɻێێYXv	Fʕ#<`U"8`Z,OB쵣z,q\jNQL(PN9i[DTGfYwi鐶Tm6'-OI$"U>&Rrߜi1j$M5BqbRFboˣiYXi)"~qogE4pZ\^&i_a**pv(z[]{>Jb[bfA]&[R{ݯE]Un*;B"6wxQܘEF'OX9&wI1Sq+I+a Bd24Tj )[lIa%7q06 { p[@8HFhU`=ѲyRh0 tδ0φP zaqۯ0.ʋ 'ɦkH:agtvt㚥+Xn:ݖcqvw<N淘()Ar֎>L]iCXͯ7.><dx)aH.<RPaJWl9ojjaX(b"rFMbdۊ~XK-r|hYp]i bU>S[P;?< ybt:n1QV6D|c[|&(+51Q4X~,0A&֏Xr+j;1FNUKZ5;)I444ͺ4%ŸiSdX6M%&tC@7#_}#+`<
]@M]4ڔeF3pӁr3bARRZFLzYqCۜKYyա$ "AVU;,y4Tۏ>͚qϩJ)/l{2ΦQXhSpa͓hoG'ʅ=;i4æc*R!^G*AԛD+Va[x8eC7hi:--7f56+oJ*`Q#LՋ _l` KxQsCV<hQuIĘ5*#kL(9=ϨM"vcW܎)%ApLAV<AxƥnŦi	.3#,#iɜn/v:yl"A/NԱ);kg)qj݌n0bꆵi[,$R	(kTwsԨ&ⵀ#~ō$sӍׁ>Iwwf;`þ&
uu3//x3r=nǪ/XX@?oD/@KEX~k懮YCnAeb(<.gd9ӻL_hx_]E*0#;[;.PIݡ>Ρbzl5g$ڳ̢RVжl6 w3iYHT\SSrK&b-$Fˋ@Rtќh>us=Sр{ve1_a3pVW /NlIoJ5m6+R6`̂鶦Y,ƫXmoIp\ϑ>暑ٻnSaO$F\ocUYNk#^gvlPO'aC56ƲxAtHN꟩
uT~eQqdSOӨeAL`x&GO2nnĆiIr8,,M"kRYk-*+ڃj'otꘖ6&Fϸ;{?T9),wM/<pxɍxy\x"b9>k|xs+4^N 3N
r~؀ȓs:DϛZueU;y%oXG/إgc#h~qxԜh.@3JDܛv,1+Y+	Nm~s7NBCJdNw [K[3%*47U=XAR#5gsU9ʖmegx܆.o@[RuJK\+)܏Ti[>Hln>w,H)s/R'Pyy6K&e.~AF[V0A<py#u'b_)=WfӵYiz<	G\u?RMuER7X]u:ӥX?#Eƭ#C:ACg(=-&D?C	HE,Z;.ŏחdIsc!JYNZ/]XFS^ƥ`IVFĖw>a-^(WV^:J@?QsӡOFP.茮ilu蓼fC\sҬEÚFhXo4hI{d]RtNV7dˎL_jeut'lJ'3x5ru\Iu؈.c܇ ^cre:pYVCAF ЦQaѧ]xT]g{]	S=l:ڧv`GTI{:ؔJ>FhU"3bջƖq+Q:
b}UmǂoBeu+k3
k0Ff_l\)<8(C^Ө5Øv(UyFʌ
<Y8LS?>'BtWIi`g5:J$rvɣ|镉CǖY=d hծ*hoBM~Z]]&c5;?s7$cY6P>Iw3J*Jp{1t$.LMe 1ȵ21<qF}U}	d[1>91忒$n:~`Z#HjZfK6`ݾ=~"!@sp"~?hs0㉇|U❏A<#{S9ua007է/5/0c5_w?Qsױ=&#u`_tDs0{j Qx6"f#%:z-lX(~EIcx.γ>zeAT5W`Dw3J@Å.~q}ha}}g
o,/qm%_Gd+ivL],nMQyoOf]=}x\;4gH?qK2.F-!x8vY2lvu'WVa`9#mGV<'kގZquS=UH>w>>ի_.175͸lzv&,4汢n3^c\5xyqqh01F#|ECu|nr|(;νJmÞkUCC : QveKGT}u&/4D֠?VC[WM0/f_BGY^jk<C,oW1%B!4^t?CucqwZSu\rI\:+\^{=q1}%]xCݬvN[)eTj98=Y6}	W]a0ᭅd?lD?Xj()W $ir;,i94{GE|[+mLra^+~:/0cJDlƃ>|l~ 1 2;u΃s5bQZ.oBD_`lVqGo(&;7W'|nAԻ&cB*sG=(b!]cӈ5Br?JdN{W]Ulb(eXWZИ;ik"8t)<}AkP5oe$[{!Ν8P97hJE8ڶ6X(+=iWEsףLYf,	[d4(_iE
:y!!T(¢LgfxJ^+>|3%0L̫XmF4"ҧ7n(鮆<,D_欜@Oo.\R)Ȅ"53EbS+^NFE\+
/ ͉P\_ODRERx?Tm栧?Hzp(M?V;0j?+֖wG_%I
8].Uq\Mz@?nwoTжUQR]5vtJ_,ݓ,ux'ˀT^ZP؁nz7ĹtGh*J%~kwy+{1w
k޷k3cNj7RFk54N'ɇ4us=o́ \r
1Bǽ>z\Ю*,ΒJP-hWAt$o~`
nV?zs!HB-n~׾[f=fVa{4<*;S%b;,3p68zwp PqZ?QՃіFN2沰Mݮahx/bhH Rx/8[WkiwmktDdZ*&}M;߆ݱ9ёXKr,}i,uݦ<{^
!⊇Q>xUq|;"Y2&%HP^KI
,JyrhqZݫbR,7gF֝;xchGشy=%3j+ȧ'eYTCŢ̭T#·)}FdFdFv7͑vB횼lxE kɶ_gPJГ3+4{ܜuv=}ّYk20
yEs譵,i*+VDayxJ_06W?>c@SZf$D?@/}>u[4-l$VhAmţԲe2⸿[yETt\Ԉ/Q2.\T;pAօ*6V/<{^>=AS-_H4чk_PZ;__.T6^ϫjs{\қ9oJU׻z&RMo9_n~~;%ݾy[ף_5}xy컼:
7U	<gs,@yg%=q\yGp9mN,TnO1]zrSJ"{ǎ%[bUc~E?ڞZ??Y]Y5󲌗8WOTs OFa\e5s6W5ëbDPXlٟֈ0/R3-0QA=o	Pa{wYZ/X8!`!ЎJ@'ꩧ|^Fʦo%ÜufqE(BtvC.;NdW)
~b9TMi `ҢE't,o]%8[h O?q\Qy<b+ HГ䵒'oY]gs]DʽQ{Lu="MQIG^ŎBZʧib( ~d;lmzlC+LA=?؅zҍzbC=qu%z{f=@|nC>*@7@*:ށ:` =?ZK	]&؅.X%tRMOCw?=uSEPw/8"3NAciDgJ<j:q'eX݀KO|U@{SƖ5ܴ.I.iߤ;V}4gU>?t`fz֏'(3b;emFCˋ''VځD}D#H܇H|:"9$}$#HڇHz:"Gf!gL+_w-W)5e;K)(+AN1v:jУaǺN}HWS0k=s׾fݓTr`^=ۣ$뻱|#$y\b<?TkN҉ 3}r>!|9k/uT5Y 
)BKoʧlg*5ɊNH_ kU?ŧE?gqH4FF&Pt,Ӎ7,*#[-Jh4Kζۏi?pt9^+nWl{gO;&392rNNTL?|֏Y}w:tsՇA7~][58CG+^^[替aGXt,|nTtAwۯ@B9M9( cuJ׷B:$qv3R^]~k^(ةXY_+`jHCq/5۔4**h"X`*ʕf(Vvۮ(Q	pYsٝlGJN@g?')J@(È	hd[MH6ᕤ>oED&%ڽo+^Yf.#yXFg\?rpX5$rzf+Iq7>x%ޑ3Kve1A%؞Oin5%߿Jϐ,cK3)\\,rB0Rҕaa/nbgtC".GU|?bXs_F;uuHA`SA=#5눞3G.2]QcFS̫.L/toJ;ciPNG%r)SEPR}J; v&?4u5vPj]aHYP
$j	9,X2Z,3Hls&2:[UMB$_mݱr^SBbtPGո?_ݗ^zjYoFh~iO	ĹKc'_`vT<*~F\3o}`hEP*
ʯ7ߋ{&-:yt(@.`{=&;-`T2,ɁBo=(r^zˈ% UJkQ4x7W><-9zǭUa=NڹbS-$ꢮ*c"W^
KppvsXW^?4V8	Jkʒ[Qh_=V'{Y朥?rlyXq/t-8X!$E_w`ґEH.seorǥNnmL֖YnS	~ܚXjGb,ٮJ~k~q0+)-M}IT[z'ɤ?"%u[ޯ+3F{(?YcnڲykY9$47;WlVjid`,$q%ʭ֡5;*ץ)3+9˽Uր{aJ,/WaM-HhޞT JŊ]WW\j@L#N	m3N̧k<0Q!b>[w-[~	rNvALTf{2
T1N3FW( 4C^&ym7{p@jI%I.cijQܭ7ZpC=4 P|Ϲ^pg#T3%Z_b|r -0Ϭ窩H5yHmj8(0 oۏwxHYMJ3CZGn)wִxubY8Kk1C@7ޢ^^^4ۧڐYVT_r]inѱnGÝ>1{| Mm-5D0\ϸM#lw`O:g)Np;'m+)K݁2dXl rÇ#:~NR_ʄ5xۅ(L]̽g/X}]Vxl
R<֬$:jju";LayUvr_xj&7dJK}? s]--[_<"L|(>$M W/t닚PIBGtmw|$Scwz*xgxz~`ߠѷ-[N ͓)Ϙnu`jvpO^-_ wQ`H7-6ũtX^YO-Ж*{POsmݙٻ\nDmY 'ILG%ekn3E+i0AN1m~WKtq@; gim|Vhdn$\ 8\ãlS)+[h#}Gi~;+Xe.|K]ۦ)n:,>^3tx[fi"SZM-rWMV?VZF6{+GΜAg	ciml!sG|yb@!7^ssJ+'.|J4o,|src#s6+Y[빿!^4Rr[چust\pF,(RER ^5G}D[
9fV$)r>e4'qm_ң6Oo|T݋@MڜuՏxl;Wrc_7Zj;>#Ͷ$??Ӎ
c! @KK)&WE5xu}]j_mg1Ҽ=aηQpjh*%0$+WhY3888nI
<4X,d&1QF|;,h謞w$1)`#RIz['{FNl)rW*OH$J'NjКY?#e\JkJn*֧ǜuXAۙ=8gu7hZk{R]G]Z)|單-<Gr5e`vAT|ΨOpYE<(#vuG}IrNƅlCɄ4Q[=64Ūk::qSy3"Yq(H"Y-/O'+gǐ4WV~\e[h`/[W:lUpzMN
0<>*)H-)OU{)DRR&vd
Rh2(E~ȂY_^}EN.b3vC{38쀦$1Č42cy@_I jZQE(e%jdtgRgVs;q*mLaL~N93WIN+%F9Z̝`ڳ#ۗz$	.jU7-p3W1e6i(3|tE7TP3Kcds"DJZF\4lG? >AˁkKui*̳D?K*6QYȞ-ǖZƿtHpu$+Rv^<e9?h+i2Y }2}6R<D+DYKTwܛ#HxX;<P*xѰv;m$'rʵīRn+<ZV[[<BJQ-82IO3G7B1b]̆UnW SRY_%c'`$:7]ˀ֝0mԢ[K7_~3Z#>褚#k͸cTTqlZvQwrR݉[<*WEc2\q?L
llYTV˱^n#ry*R
K5٢O%8;SeCZ(OKOH㢘cTM_}tbi'VV}rbQEš0(0NnzIHIIԝ}iԝ;4uOz;4i wP=,Ċ,D$D$B~nPgdJjO3i@OmOz9CU t4
SS{R+^ihA6pKM!&֧v&>LGKM!fV	5l8g\{NOxpy{ܢ109TXܯo$/=@rz}MNcY~Ǯ8^::Nޤ|8MP7;Ө:#~>cyK~r4ŔMmTw+x؁e+╛{CG?#WDd.ubpRIQSmVg
5	Dp%,j 6Xj9XIN,I-~ǧsU,uKl4@UiKѣaXk8FӹU<"Qc 3E]+G].RusSn;Z:<c*C7߃ȈmVh(VMp^(^B9o&(v#JfբxD'E_D)9iKmWhtuEN<~OU\}.|^w|h'ggXh$j2MJ2DsҎ됗a3ǩq9YS5>-k9;;QSROe-9,m39;~}κu6l']gf~27e;/Q1jz=.	o^qo7c6/ (oP"Aݮi8)	g3[xRȜ(`~(T?қO`\	Єّq.1r*Ms}(Oע˜fmtKoP%20ݭYc)EP7ӗ"Fqve\.yIfOTM([7<O8,ZQ]w' 5d6hE?EU#68XC/Qsd{\-j5/kJH<n{n!ܥ/̂.F{`	Ȉ  G,ܺĔW"t%#\Ǹo\6Bl
^K#ɾ ۋ+f^3 U5=lrt0
Pb[^gwmYaE,O!P؋n<-|Qsy^.+*(VT(`Odz!S?&	#8W.C)7}v-ZgMωOv=qf@\IUcǆ92$.SAgLA~lXsH
/\:»`PEb8b$rTUE!U%lJR%,lkzig}cQUg{چ;jqF#Q _Kh48"/
[[{u7eA!&lsKૢf-XcFzVԌ(h!eQ,rcRG5ygR6]TKvah5,rXZoV9	&i!f!sC4i4v*N%PZM@YzW46ws7*ҘǓe(1qSxwVͳ 4h%Q#WGap|ʥs/d;
jp8s(P#MB!i PJg%0ZV}${2oSmg{@	Yi@uSHd̼VRm|9RW&B~Xa{|;Arkxr7vl`-ilz2%7c6 M Xxmzr1ŅH&-kdF
&{f1˳e.0W;zieQm3Ceر-&-+\xlNJSH@5|A߼Vbu]'߱6Q,͞p)DݕvdO9E-&b=^R[Lf<``eEҾ^odk?>>ό6'By3YL34g:ԒQa=CaS {{em=SK#!|ɾG.q}O_!v>:R֤DyTpTun<KlMF\9%EIΈ粇TܭgM	OP2-śmZϨ9bHIJ0am,Dbdg@F/GƬ5xNjf+ג,##jI7)dA֥l;@d}VSY)~җIԌw6aWڠk{Cϩ^CDC񝑿Sv9G.q!`,%={LWPj^$&TN򺻺bhrL'3uURw|ɩĲwwʳA.1a9c!2NɏGAZ77|[x:v;*vz35o7_7m)wH!oR_Y`.>i┧'R`E]r4*ІR%ifE:RV.o3˛11	WP?ll6/9fbowΧ*FbRqJ;tfݭ7}&Ӝ4{E-wGt6Oj*lNN>Q["U0"U`2,fإ<7UHq8ڂ{&!G '^E@G*MgW|{,",MÉ,97k~D˚mz7CS@XXgo=ͤ$`;5eGMWӛTMÎO:{߆{(l"=UL"籶r`FjA=ˍ3rؐo	S0RHND)vK<RDgJ\
bT^t
hAY$n,>_tP#__mA`      iW#I(
GKE^C,9@rIN 7B!%IΙ_3?l~kx2{^כ:/杫d8+IUo*',Ku^9?uy]즨{iJښh_e,fIHW}<*&+Lɪ:- f­NC9Ӫԡ|B YB}L~a0cm>U>Wpڲs sXĵF\f>>  ?(糜`Dq?TFg#E=Qb֭:Xi**_,ǗgHEzٴ[ 26%Ƅ. y>qkk>F:(Þ;:EDm`(լ넨)ΪbrSSppJ,SkRΊdVzN+~]<eW*sM@)gJ71F.]g3@An(*N}Cep,~G<I~טOFNIEWsj'@bT	p[XxRWE&ya609֬JXt7?g{JhLnwtYˉ˛q&ͽz)R̦
YU=j8'y4OGPg;8^)jlxQ  C!|~6i`wޙ vM3D=ͪYRQWOŬ%(S*ڛӎs9I*Y"[W:Z[m殬o 4\6NJ/n$=`>ܨ#We9㑁]i
~pҡugp48R&BfmTKQɦ$vß	
|ҹ+&.6md |Grcϯ˔|nALGp~-`ok31)8Mmmny7fʮq^eªWSžV'lH+>''*E3"\PE淗y%K?.j6>,D2ͅ1̴e6>r"fykyJ5.,
d	<Dz6@
}MIZ/^7d1X0CQP	Jb8qe:Rc=9sg`eqR\PC稀;TeUH@#d)UJ>>jXf@Cdf慦2bj
CcǠiAU]A}>J&j4 Nêfaf)h--v1iRcyM"4,Gkkg&uN4*)/C(: هk'Qd$>V#՛  uywwwt68:݃AR)ۂE 	W bGv([}յ-0hL4ѬqVU#~8&pjVO	.? -*߀#lTiLN$Zժ<O;y1 EHsR2;5w?oiBhLv"9sZ~l賤%kpZZm9*J`*Cc3}:GFε$k*Gf6&/^/H	n^RiʛoBmlDz$?a]@ԯ6 NVp\
iI
A֊+uġښB/\hl\m]pXOC1ۘU٤Mauc+mybsH?Z }zuh~=O$qZ:,F-$T
F]JJ.,)Tj%H3n¬/Vv}cvW^nn\9Wvn߮lg7eUV`dV`";ؒW4oVUsGMWjV.Wקԡqtjl2&+9B*Js0_9ك]Ux3ܬw6X`1[Y7U~e&$J=eQ%c].-ڎ؄CܟM'"qr[858jys#g4g}:ˮJk9;9>!ƀq@5 ,j-;|R;(B6`zv__/XYFXE%"] 	8&oyrO"@Qb]XzMbݽl3 МL,RX_>p-[,. jTOզF''uu:#:Uyb	3bRVtZVLD6܅IU.B}&$Uɤ tanOEd&h>'s>.9lDFXѡ?tHU/.*C5_U͒:?8/-Lr=swoVYXduE(ÔZlѐUA!1<lBՃu׬픙%DvD'T
IQ 5$Z1fUZIflʮ	0tzt;2P3Я&ctZihIHLSȟt#C¼}A$Ｃ7'?
"iQN*#,IA8Djz%]-O+ַM(6nP|ON
xE,(BHӭW29?bɰz7	ga+c΍5.҂LAp1hzJE'h]Z{	]C3Rz8wXbGбPv f/P2J*a~glN$-#u6)fO&yhp!`vt"`{snݫU{ clP|8cA,DgAI(,/l<]22
}*YMymy	f:BRH纓z詣Bnf"<OAIwd? ]s
ٷS[y=Ϯs~}[@;
AOBuuT`-y]C7I[Y}Z9DWE+bjw=J`aJ,DՇL׼2 *08o,i1*V
O.j!p3]
IIZVգrv%66w
kV-x󘎉Cř04]@=@bn`He`=%ǽ퓳ToWE]5Zѽ,/^MӢp6dx,5IUY΀y_s[~\g!W$ P>+QחcRP ,9oLU,j羽?Ys1yEC6]WlcSy>PGU/~/Й)tvCPNbIHphlVO;f$N3D!`2ѡ|GczxhIwa}򅶏"Λ<$8}ʐ|Lf>
Ayn9Gk0 &MZV3$Pm@b <.Vu!~v" $)2(UfFH`4i!P
0#k+>8R΍U:53^<?b6tp-՛Mϳrjyb$<zQlPGFD["DݑxOqQo+t4>{ܼ:ǒ
3PJ4R:IeΜWFl6Q9>&F`95q9Ħd-Yc]c=bh@ʼgg)ȩiT-5>GBȝ1A:Ο0{cQ;/:y}qG_mf{VwڨǝS&Q}vvDF'BgѢocC>P' pdigMnVǌ1VE	pwIvs<^7Ԭ?mkjKaSoxHTh4P}gfz7saWvUCv2|tM`Y_E_FoIL_ʰrV_H8=~QOh	EȥsDDk-9$m mT*hX316ׅBcšEImxKJ=$ʽy1ʥ[fESwrlRxȉ?hZ6S:
c@Tm_^Pm;1ځBUy]K\0%}<stx, QO[`3OU;Nq3h
C)]aULge AkXL~G 8 ,0U2PuaJF8	<*S]2;n4ه,T:a?4bQt ?xd\ Dr~h㱔Ņ3['Xʲ4v0GvmdN[Ot>uWODL}&^ Ej@eq&yŎHMa#+{l-5馮164)	4ónɯ~+Eҩ2uY}9osŦupU2~w]x}NEb/
#q
FI禊/O]sk$HD1kKYo]/u>GPh? \@MoX5s;T}^3(=I˔wҷi W8<u$i&z+,?%gVRprPY@ZlYJOl֭m3?b?!JH=9xqP$YtLP]l>^fy=Ucq9g3?ymjAӵVj;i޼ΫktUEϨ=UagTݷ,fM9O9Zł'JTN4DŖeiòGLbˎ\tfǥ`WIlT+\E]/Z8Ue΋v|l+"ҍ|hˎ{G'y]s_ue 46;Ï^yQ<.i0LލEHqF23b)eIw맍}BJRmf^gZ=n΀Wθ.5v>$J}maLd76WF5Hvd1.nؤL糟@8-߅n@P#n|$뮘TTw3/IPys
	z UnCj[XrKiH; H/#; aU=Qߖu
2{$7tq~5۰;}>^(4k]o):]Ʋ(v.+-S1ݴCHQaG,yNaf iT5D1mg_ۛ9٫U9Fc@zE-4NbEeﾃXLwcNu"b( #gr~LO W8XoIDkXNo1}EOjeBѽM)vqY 2*pG>%(9L+*QM2':W$Ojيa糬@a5PRN9E;XOx^E,7mX.:JL`ĥ:N9n]!p$ꇷ-V7 i&n=KV7>7oxKUey&[1,[cdn)FӲ&w$$?7?6AO#|'0A񙢾
\wV+Ѱu&BPqH,_iZ5#ib۸&StyAC,i2m+%&tۨzMIp[	d8?]HX`"QZ d&br(?##xi/-7cR$l|ʮ5X%.jBzbb$0U=0+㸼D; Yd`Z&E	 eC%REv@EnJ|rBKMLX /ebTt>m|7-fo6aj,6]#vY$A*`yHb_	TÖ4N~{_BJgv%D7,9#k[9^qT
rZ\1jt7on>eXM(7\/,d]|6+utkđ
 I7dX%M8Wȴ&e7/t,:=YL/4}qQn\X?zs.,_9pHˮfL$97-I<:eV(mӼ6#;҃jޒqHZN	ر;=bDVKԈJ\wnf4㬮Q^,DPb4#"nϧ$#LR 댚8{oY[)euw ^ޘt4@zPv$K^Bl|6oeUSx6|-?D";sGъD[C|w},`("EgX~RTIQbp9`]Э{^҇~'q1ZQQE	n:/<W/*QӪ:'IMVP؁&K\#aoټaoX[UiH9&u05ĔpÀi1 ri|uo֪S~"MWW,4w%bqjfT ?^_:4/[A9>0$+3hmvj~Fnz]w-Hwo_>TI~yrWWH,iJTj7HP VaOpnDO  >zU<ߡmԢIz|>55'R,Y|F	݉M|BrUmG4ULǹڬ"V4$QD *fY?V7W4~H
Jx~Kƺ=mU(n)v!6bxwd]m[v,Zi)ܘʋ^3̶8g8G]VOMfU}e`i}1s~amoj<WCR8?o=[v4** Zv(]9Eso0%`kLar5̥lWX9} MCtl礰"I
ֲe: =}s]!$ui/DT/[grBo>ʮJm%5q<٣篃0d՟pxxTUQ1"j.i7iLǖ^V7/KG78j9-&[[%OY ͛/eGC\]ZˤOu>㐒[x(oo@.+ENWos_I9|xOdS.^J5-AWE^h7x%ݾc,Y_rNh`0e'n>>-O&,S4i{]Y5VN]oc+16lOtfxbk: tCR
YjcTdz)yclE,RewyEPPB8G;'?.lwb2Gy!96J#Es
 
3P]Uyi_Ns؁WV*x/Ѱ6uE]6ߦԛFa	vSh4mFbdKOe3j]1#fhZ1!Licpm̟`}Bv	&4.iH5;F;;-nCM	z*dfǞR@2G10P`%P,GS)*nry|VAUz9`aybfcʑ'W+l`jJ'}F(c[^@.5	1r%"(AI
o'V%'p([ިkr)Y(Hc7~/XMM[wuTd[u.Hp~ѿ5HLӓc8<kqGgo^^*`Ji6\Q{bk(q>p.-/3(9,m>'8(0A 0kl0_IenKQX	gx
*uUq
{דR>OǍ9Y/y60Z1ܴUT0.bw}ۀY "Hwet)U	NCU¾60U,v *٧eUĴ/KqdE*7FM>fۘx)+fvKD-jh*Fb'ᰙ %aJ.8/1Vhbs7~sQNP4mg~',TIk%O FGWEP

JaX^OY1+e1.f2N\M{oOvva*TL$AN4?4XJQM#Hhlr6P/R@
C[XcWLؑ
]bĶ'G,{ZS}z%Wl^$g$qVҖ<	3+'mbmv!`Jnf	s`8px6VA+v6(5/gNZ×wIBAL`S~F9SFAKCl$e~}YWںSBR'n@(I3uO!nC
)X##l4oiO7SG97ѿ~Geomo_U$)LX}('aXXŝ)NgT
$h>Ļz짒Ͳ&TH so=@?&coA;W`C-L?(:ǋl<mð検WƤ(}SɟE6)E 铡:{Kqma.Saػ̯k$?f5*d]R/#mznSxt6%2I})}Un)>ٷaEkH03e4drgŪJ({ꍊtuـ,5,i8	݇0"-?+3&	п#wTݭ[ڙ>%(y;893ew/@@ݽh] 'N?9h8s2'{[N	-$z;KnB[OO OOlխoܷ/1 4;lƇۿ~>xR8'Shw8;ك t!C9M@{ swnżL^;ӳC}7ޯit7|4`5DFcGzۖ4TɊ#em,ҝ7'gGtO$Qr~wpߞno+Cc^mnJEױ)$샘(0ϧ%2[~\A݅T*hĚ.]U2԰hdCA68(qaq=<,blR@6vil0m4vRN[6;jzf=<U?,hSݖ{+ɏR,X
-Orsubyݲ\o8|95,ʅxӼDz΁n߆}Oޞ$g	\n5smؠ-NIs¼ो1®麅IQuoA a%'_΁2z+E_j&>6b|.UbhQe>_PMz۶e>nƌEQ
\Vx%DF ~䅾S.߭^iIp	$stcN>5,[:R9P1|LhU1 9dgͲATڥrNq19Ԍƣ=働[
ZlV>0բ利;ڟ5L=UƱ!Y[Vw,ㄊS&\{\&5uzgmrB$flVv5i7;3
WLqH&$kkJ.Ma8s
dWahP|YOFsh>qn:.0Eh|7QwK!	(~!ͨ܄UɰZ*o/v[/SS6mRUUzL)1]F9v):L}"0?r>ci6o53Ţ2/v3Zd&4tۈ/XZvڈEmHo=٤ׁ˪ڄ8hoSڦC:.
mԾF&}ؕó9=>YY_5F]rřv_L_y%Rw7tK9wc*S0ks:Сr|kJ:+-# 23}ӟ41] BK}U"#vhhqj,-
*W3l%9m{2Rg^xVra?tixB}ڴ_"3EM
.m}o,yֆ?,7>@'=xr*f ڈ_"#ǓȭFfslcIxtm^
L
s~x[)uk1	a%cR3kҦ1")MBXsyeuXؖU2pWE
"W9.$];sP[tcoГg	"=Dd0WĎ,ulk9It<u@lȚ17[ݴ;]ow]oC_E\Ъl&EIe-ɾVejt)D| .ѼGK`ŧFY~k4!ҁS</?Q
]I2t!iGl6hbRjVf 7+& ]F3BS\RE>q&Ĺ>PrwYiYE<kZrx糖`\`HP+0V""wFlھszi[v5Tx>!O_8zO]fQ<,	om&Yf句Kh?;<t6IyqlɈZ۸{	(tWyT@#G<XRCAK
X(,5rcߖV}!d~#,R0'ێmIm߉@/U1X	ٟhQ| rocVXbئ\$lrZ(UGaaoL9ܟ41Em΅m.iGt|fv07E<fz+7{;n
KO'Lב?!N}ǞOYͫLzטI -y' 'Ojfjރ6'=BSM	{[oqTԔj7%BEiZUB-Z.`2AG)1 FҖ1!ՅwRJ^I`Q42NvWYȑV]r {3}B.-6ƜHEyphH*QvXheW7KF'`(E%-ݾ?Ac2&?N:]f,-;uxAstFޒX;H B>Π7^qKZ(	-fFC2u؎g3iޘ4;N'KzcXDtID"ᡏ'93Ȫ8HN0j:hAeet AG!7gFԎKg,Z"V7/]T\t)dPÍ|ϋ2%ACZ,o5FwшM$D-n2$ٹkyK 8xrb{-nJj!Э#5jܰkQhItC`Z (4pθt)9n.f7 ]ax9Lhݾnk$>[FzhL46jm8]Afc\8O /쿺%O,tHonFJ`rԌLhӰ)؟wh;g MP:B?>iY-tr2*z]Y}XAq|Q}yfBת`MFYG2tלJ(;Hz5=;cPC=9=LͲk웦{';Gߝ~<`FJ_A> >9BCq+謂P/`ݷhh'\@SuUj|Pᡟ= sMto_eS"S}lBWǯxtz? g2ӚAdkkY`N"\}l&oy]fy綾6g37sSVC^nG
itU|W4+vmY4nKP*yV}\>E)_3x<>׏>z|:޿j+W/zu i a^;!Qyz.W8`֝q)zlŎt>a6uqurZ/Ai(&ם-#R=bZs֧Z/΋U9`uٰH<&N@Gs+>s4S|>>'YNT"d0|.Qd=wlNzQ?_U]:t}1 d]Ö5Pu78]]9A;
&2Sp}1huy|ol\[zxNؠjȋn:Eǂ?yV@(R,ѯv([Wa'1"6TyE!][eY|#ukD&,9SNO/AЪzgZl)=l/u@N:45O%{Om[6wL:Q?k.;(\[?<FɊ,='DaIm˘RFG fGpqJ^YK=)(vGkPZ9%iX-&|C~_;VH?<fl^4OiX޴oVt7qߋT|O$I`ZE>k,\j tzJloh;BA7U~MobˠkگrQ(&j;;;bʿ/?C~G}l|eT*S{( I+:
Hj~DjXSy=>6sKШ1[]d},A蟕JE&b3,V@3?Y%/EQz4:tDV-@jj-J-zP`ꘀp@rN\S !vBᗽ̊M
tT2[uͫ&MF(Ә$=C7FoHOyҷkZO?Ӎ+ʿ+ڤvM` VǠDu'*Q;kI4*8Po
-
[ΰ*r
e͊Xu%~~9:͍F^M&/1xZ`bVJNЊʛ)V3M\}Zv;G]gNx&Fy&o
֔#zBsTƋwcv*HV|Y~%[Ysޯww?_O߯'֞41w Z#Q[JpEM*C󑚟,x9UVSW.ՔQ͐1R[YV(+ĢyX,֞Da_N>(zaZЭXoIWW;j!GAVr)K9Tk9:Ѧ'nOgM@*Sk{\\OH|xdc[%/7g?b	ԹK#Ʌ𷎘{rvFlѨ*x\@EQ߼9;K6	ioURb.QtbBldZ[9lYԴjeV5(#ˠXcfArA<}l2N_7 ')L?V~T?c
04L多$ᩡ`"kZۈuW,KCϯ	-Z,ޖ[EmQE=0#[z>)	 6yQgz&0pR]KD+SULz׆<ɕM>y}A,y6WZ|>':2ʉz:os(v1P}@,bY6D30ej|:ԤGT[]C,o[`i97z*?a"PQo;"|"`&(մ9N*nZ qterQ0uzj:#y#ѸR/v16]u¯CxPie)[^ArˀmmGxZ!*DJ6K=wwcl{b`+gDتeXwEQLS~|TG?0Q:aUQ4ogCtH-B/tҠcJ9RXzѭ*ȏ&sdK e)]OAېfVO&vQ); 1d}u 䧘C!Owk>Xr;c@D1
Dzh1ęo Pvc7UBOS6:>'c]3։H-RvwN||oo1z^8kkź=-bX=nQy^uEָXG\B5ꮧ%h[)jiSh: TB^h=3YS_9y|1c8KC3_~Zθ^#]0c˸<kiں>0߀,xEq@(R#ʥOo̖maIWɌla"ͧK`-͹(|J?9]ODIEʩdZ7GCo4h uʐ.neHCP7eU6Ȼko`n\CZ~IQ?WWR8,bxMvim&zfE#4"
MRg$岜`&1ʘ7dAK(/L_5eWW0VgHlU^hU;n" IȰkPZͼ
vfףHBN?d62 䱍C$)դʯL_*v[YZgbgf5MGCw:츛{OnC;ݹ7/&W%G
aѸ]Ժ	lG*^Ô	&+|8U%<
-'. ?B:(FGnh:A:G	q0Ȅe~}, \1Y~;g3 Du]W'|{$4s8UÌ;+Vډ_}Lm JG3F7=d|#0YlvuDgg^3z |>k:q]vq- SȪ:@&OMP(qUr-N$Zk; k^ȱu[m!"4^PmXԫ^.&?,=]sN,̪:;:w>D7772i6DYHYv)[3r>y	|-t;;ǻ{÷
̭o @4SGz?'Myy  w/4C+	h?6ׂ.;M ˁk,>l|\xBDrNkwy͍~}2:'nL-z|v{gOˬ̽b^(B߬xRN!H xATׁЅұ)|rsPdC"3ƍ=1LRV`R]\'<aOvQ:}b:lĿkZdJ]fO~ H{jɴ>pt'q\.&d&'OL!һu槨oiW
.!QM7zU;;"@%y52Z[ҿnZTu盗
&҂SuUr
o [E㷁ګ (9}.E.^07P5"Hv%|G	πl
6s'$wCLK<>F^⸬FK!*8iT2VDXHS]~uVWW	v2J]QZDSH2r$]?Iz!Iܐ吜~a[zJx-euB0\KG
g=do
8W:3$!/`o]Țpp4ҹ{....uEaG!򜼧,Y檛UxɢdǹzE0Ar2i=UPW"/P_6YR{lomClUD3:	'%%) ,a/@0eN*@M	jYKa:kk0- NNPuA#~"֯'рkYǥH@]|2W[4ygoX7.q'Ke Χ"pnoJP>*]V~Kg%]X7D/~ilƕegGؙ"iOS<_sҵqzo,0o<c<;o!ƦUerŎJV[Ce)Xfb`!Mrm8_ۭ?0	e ;C<A[ZYO
kݺZdP\׸eeݨp|<v7zMKzR<lrfrjc+Z3	epjd)}j#&ȸEl}קE-k4ݒT+v#RgH^JNdrfPZ	oq=I*/2J>{-WB] X:.q޷wp@ߙ!Wc䵔b(^]?h/kቫ;B3Vsi+׍>s=ꆮJR}(.Ԟ̒'~	;{2T?KT@<v;zӀ)a7S1uו:/X|w\6EJR܎$aBAǤ@|LIE B EQk*8z/ŊAw8ވS;PCkjڏn1TwmY>2=TXmkzH}OkS{(.uD =|F;}~s1m|=E˪޼aWH(^Two?|j;-_\bgKѸ1\ZCzmw{߂\Ff-9=.V;-sͬgȶ=r,+n6|&*J1:nJB=V.τlJI4P5wT6xt]nlVEx=WjBoDt-W^m]X4'9+aUq6V`9[$=ʽ>^W>)0$fKK(4ፃ&}?Zt02`^hAݕ/K=	EqeI]=k6>3!qdxڄyGF.(\R+OS"&%s9=u*9	h!fcDBT"=_E8QdKTdDK}EטAenW2YvI1Ր=|ug
' v[uºJ \bf9apNޤ@KPaZHuJeww{[~e[H%aw^^_#
Ҟ5gR-P5Bs;am׍uH̗2%RE6 4)[|%yDF|
)WxB9t pkoXN
Gd#AΥ6S;#(:y_"zNĠ;kOlNKjikUE>;_@+-6M gkDC]LM:٩2lq?6 }]RBlxf24^8ĩΈ2'gM	h0P0X5/7xhyۿawƍXx7w'*(ViKfbM:~P@[]>CoAFtkPkľʠ]ښԲ]QTt]G,"	^GWbj6+kdmF=*vk_fᦌgK)}͜:_z̧%^)^8qd{w/7쇽4}w}|48<Mt ᧭~+2Ox6>:pqRN(DOj_u.5j}i:FULxE(p$D'̐5%9709ZZ*m4c1zY#/v9o`0"~|^ț6Dm|owrnmuqx_ݔ,/ʴ6-R;#K͋wS~SmCUhUm:,W
$d^6脆HQ@xOU)#-6.~Lɻ~{Zk<'}jT +oCv"4(Pʹ h4PfHmf&@i$1G:EϨηu}4(]U2
nB@b\)xVbZ(Zr@5*dBwA,+yfS'~YTfZj3tazVҖ ƉPaS|s'!FżNuD:gU:|d|ëpXtt뉟60^vWν$tsђhmmЫ89|>8q`p|.d]/Hfv^_qhӗ_.H%Uȟ?zzE٤EA7H982v=^+5lm&Z_6LnkHI':1ٗtOn\JlToXGjEzR[B<_ZIlOXRK5fֲڤً<SnzY,ܭEG-q9b9)^U<M7CQ=)@"6m9l,|>ɹ7fs\ Mۨ,^./.f$7[tSvd+fVr'9@wl8܏z[mշ:ݦFG"̔J~['ՇЎPx|v8PЎصvr<=01.Ai]U/b;ՠPNAΓs>(&hSEv	v}ljZv*
 lP7׍g:sB%S@ykpj	m3
à,%tGqa)y OxNx2cq(!3S9@3IjZkeOa>ײ=٦bXN6xjoB
5gUbqܝ'0"--1\O5qn{7ujs<*\lv4 \rh~"z7itD-{KI  9`:'vP$=q@	Ra.X _ijC|pwâk{nc]<ܝ|E8u]\O*+=R喕DA`Q؅f5ueeCފ+<UxEh{d|bp9v>M P}FܰEwdQ g#;i{ҴD`eJ8"+l^r,H퇆cVemI-EPpT1}v:%`,~#F)xp!omMZ7ɡluN&1d砷mڱggDlPe(0>Tng6˝DF<rrA|K[yjo:(*BHVԳNPWmpDK<pWN;i>8 &>>4#CLQԍp{8(Ř.`ؚ~ZWAꁰC@¶&̳*俕4ڜX-ԓ˟@%_O+Ri3I6PBC&kvVe5[tRg`#E%%B;w:%ُ$YIfD>E[VT`dwfT3R=c_\	>E@:/xiE*tЃ}ŭpQDo-OUbϛ + 5m=qsY3eTpMzUɤuΕEunDJ`)kNIF޽˥gstriO?%-3C|G2f$hwzsH/҇qN͗H(`S`kqa|koQL6,YEj~Li`(&SWvEWOH-3n=}C»Kv. e d%)&Kfd\R<d7χY^l-=&i:D\\I3VkHSHW\0KaP_g_Ab\,'l~qED>ub<Q_{ⰙlWd5_uJ_v!-R$L[S{=9'*Ԇ d,ɊFC'LsVQzc^7d.3?玟`@E"Հ{nYJh{2z7Ր{v7tfoJ9X@5yJt`4.`Xx#U0\dOP͓mi6꾓\p C4&{%W-/ٖ,&--3tWDU[ۛzE՞`9AoVO`nl275|BT{kUfyEeU%o_``GXs.{h%EWo0W1JaѾ:g'/Lm)
bA#$c%jE(9;D%rքf6:<@W$X+P7Py_0hI]	zs
xH{
h3BPz1.ٙOECYGmQM|x6#كHoJ<t/s'ڧ|n~@o-:CPc	$)[Zǘ!>핟yaskX @,#{OửeHg?Vu,0Ukf:q[@x7GPy)fqzUYQ?wv9œT/ٌuLMOhiJ˿GGEa%	zҙzz
o?o*5_UE-f4N<95Tx3}d-8lx~l]~5zO(jkFu^ ~}"n`ޫfř֩%qZu'ڡsrVC*c7]s½mu~ zf`LWքѵ;4BIXaAMJ%RfW;"|-d4ٍzuȭ	^=ˍll	G
L FW|WϦAIMֲ".Ӫ	p{ͦɋѺK@ e,#2/Ai6-:x~хG(ssp@ўL({ňd,5܀bvՊf~KmOu\ܛU;?Bo4/qG8rAu[:0xÊJ/}ANqoMӇwvr6Mf|篋NڑE+kYU&nx\!=lރS<iXq)rU@-UIUA@k-2ߔ~/$4	)B$2\"ioATy|ԕeT@#z͊zR
~,I=BgA8YzQ9;ɉ{;(ZI`MQFL$k?.K>#<hP	WCal
s=+)n₶I[F)ooHe7R\{#trв4T'5J"uh`SР9~#1bؤ44qЍWT
A(t{{GG{2:}UQb(d妽T6ZXY1L59ofw'rѲآ5P&'}`a-,}fLfSy*YՏYyʱhIݽ8ڥґZ۽#JX>Yaplu̪Si5vS<yFwP\jKk+OU]}.r
9lLΞ=λ3ij
oCUcSQU%é0n=!/$E9s]*k:|?hBء$F҃$w~HLpA7uM6^vʾ)+lX 2%,}:u8ܷFI!;mEާ|n QLbҞv"Ed2y}*Y3
X5`*=Ye(aԲl]r-gf`53/GMBй={[rp
&a=KH<N>r]F ++ƚV(QyۻczFt>Y59:r)[A!GK7TD$,
5,zKA!O%{klgFXcƔNڙO~}WD0m$	4yCQ8)b$&Q!F!pتBbw($Hp5}+bLQc:R6B,ʻjegXiXuKs!)8sg-5eEpPqrA3
E-T3|{r9h\,%<PMn%0xwrfQ;v=8>1f8سڞg{kk-ݴU/gRAe|t>lpt7$ޮ2v8?;~>>ߒFPץəFa3ǽ3kH~H7f¿Bh#o|i
EU7G<#OCY[dX^OY1+e1.f~(`od$y Q3C7^C?KW_y"_6z1Jɀػ[S:WtʞhXEbteguh4!TSVRVCweЙ̏ې8>ESGQ4lf%l`"E]c"N}yx6V4Fq 	#n*P<!ΰc7C?.? 8<fc-sgHﮍv<Æm\}xAۯ(nexYZՠbROW)%)r(S,~|6#*`>'.l8v&ˌ{wiK[GqAZ;P{P?GԷYhU+D[\{ҰZ/&K̦+֝ϡ"@){l#z*U$\N٥cC>u4)mOY'0dAhlQҐwKNAc2b.7dhV\"bTLk詖ϔb(R/ŕA^ J~{^[eyp(mF}v
KoDic%ʣɋ|{ey= /FD
yO񝼽Gn;kzjVXD>xw2:,l\%ͧcaWEI l~^nsek9"QzZEk>hi0#\׷>mn2l[B֪W>\[_YUf#X
	IuZO5ܥ8	er)wĪ#qB}5<;t?8Uɫ0eֱi;z2;zaw"
n=v	>"u4Z,콱EF1e٬hW\kUNUB.EU&Ƃ/gѫݻ ߄&BǶ4Yvلw;]:,M\DAS@x1£w)~!q}
]~u>IK:,r>)^z\Rvu{/ءbX%yn5Tbvc=@B$yF
LCmRzJ:>ruydڑljL-aD"A41*54~%trAށX`@}r6&xV*sdHhKDɩ[aN֡imtVph9uFC
>r!JWAt1w "vTCR.=*-ޓk*vs?E+:C}DU$:M3`L^Z[0fPV&ulUa\<l{Z{?ƏxI(pTFKޖ}S<C<}c,fm\5d'kk+<$QFx=hoJ|g'{eX;nsO~'>8Uts-vRN80h쟞8<l:) !|!tL;f2/h3=etlԮ{4XtkD6+Mn\p@{9C@&23߮uBvW&u$[h+VhMK.+5Ξ9>ِw(JR9nMSq6%gtuu˪k%ϰؾ)+YRwmNX)oh<$R+LV'S	7E@ӥ7e»Cml1A0:xA~ʊ'unXUr`L3kZ✯6/}mm37Y}Hl<sx3aAaއo3oy=?Ⱦ}tt&hH^,WFN^EOd{nĽQY*Fݓg?쁎tn JD['b@ʷuF)E $0/tMAd9(.h.jAs4AτsE0LowF,}hTMIJ.6;x wO#Pat[4f<23Q%as{6|?"##"AtY,FbbD__A0:O#e+*B s-Lz^5yqr>K6ûU FIwEn0;=l\w뙔E:cD/1䪤ݢq29kw|oۯ0WH2]Q-3ӹS@'"v舉F38w5̠c!}B6)ʜڱUbyw	u1SvܷGa}b yOgL`Ux{etT_7(@!#"0]ГfCs?,%i㬏:圼y\)=K<KUQix?v:=h>4ԑ9pau֊
8eT/:܄`|I;xWpx|`UEVvI.39FC|P,gF h+ S
HS>MD;+zY>Ѵ
t=U>u⿱F+N7ߟ(zSzL!pѵ,B5;S>%1ˎOHo^)]G2FshP3?"y\y&݊/%/1>@G9Ilb#xp 	4f\7ڂYසT`n.7-DZѪi'e-{P{V:r -ƓRq#0~!j5}䯘2tn Ut98ƙes2<s94@A5RkM򚻈hǪ$G*G =Zd,jbpRǟ#\Ro!+VNmrϰ3b˞UD5BD"}X,%sWz%LB"t"WOTbV7VZJH^O!%$@Hu86eeXm)[3]?6&WPŐ?BqY2PD-USql׬4,sG$$b.iRRϜJ%F`Ś<]y[6C;M`+́ Nͼ"*PqF9hBE }[_KFU4s3»쩂VPr%Sp0-Ů5Vcv<|Br6-+&vY4}Xe*ޚfZD,2'HQıf|/Ҭe=W6&;ڎSW^~l1^=k8#w;UO,hxVd67˟T'EVqҡ9E̴@]YwG6 8nO-&HX=WDBck{.B꿊s/[;@Jǥ7]!;׻ٴ.<eD Vj=$)m֖~&M!l6ƈu+9AV7Čr/d^3u>!}|U@<VVvFöYfxuZ#o
6ƹ=0)DJYb(ۮ*fלN&UA2^Gi55*rk0by&%CPoH#9@w P0se<,~IQ/k#~U$<ᢞ`;~{ނVۋrn8~Ѥz?=>?M㦺^wH./l	=cO+suֆ?maHWბFjr/"%Omg4CIceH^8<cl9zRv$zۑGnnPӮ;oآX _؇K(CI[ȰG]5_lWAFF$YůAI{QVY	@WHPP{OGc5$iduAmõwzO\ZgD\5bD'Bug3zV'GC_/;+O*ړF, RP't7sd<uUa! ~nGy`oO>]uGfg̺G漐uEq5IK0`+`CI8lHtq31SOԅ@+A@C,!TF2-aZsϦI~*7*zw&î4-s2ϝSx`^.Z7nqosRoԺZX+M7 {C6h ,rV9aT|9zWX%XP]\tI0uB؝7ݰ3WF;k\/|,FJnfQ~S*ZhB|qUܭjV5תQah9QIU(y7_>LA1Grq-YQmqPV7y-H=xL=5EؼW|QQC5&IUó;'BS ->7m̮=r᝷`jFj8M<c'9tmt:~xwZfU93f+4{B5:
*oh%QdbYFC~fn!DvZiıupG:+):biWU=6Jy`R[l> ｌ>c|TA1* "gKmUr^A Ѹ[뭒p-Faf55yCU]c|I\f|\JaFށ!h߼w=GxR (Ut\V9ne@Tc ӥp]G
VQ,EQf=tAkTШ2*)j<;;00Lna%jCPrݭs#8lJ>dK؁H5uA /-||D2\XDL¡Li9-a{<IȢNRFhwАJƣzk8ujyx~L*,1W=V|-v!T*6wVmq5"xg;,}ަ,-8<w]|<v5D@?%7n`%{ae>W3'V;YŲ+XZۇ*[M@ZS
-Cel֕+-ҋA=\bdeM'g(jo7$ݤ掘öni9n%H\:`X%T'{1Ol`e],UCc<};ztEu_#!7d75],<gS4ogo^.mW|4,.u_bT@"2	@tV&rgBCr35䝝Ʉ,#@Hj ,Dɴ(E-޺9Ї_2D;NTB#WulS{La$tv}Je6ɼmY'/hȯ^X@hHWꆟ/d߳{fHBm(S,'6Z8'|_c_'	}M)p-7~9g\L
,,[-w/8ka{>BS'T
GPsDATpUbh1o{jnH&Lrt͊WV%#iu9E~c@	YQ33&{E t<󷖍_[i^'PEh}D=QmZ{ˬzhl?cCJiWiYCͧIef1ӧHG.DFvCwϷ*`fn*Q\ a@!;O19/N$%r^~gq9G Cwh]^Jݣʜ(ȃ5)4]lr+22:Pj\{ŎeB5ֈE7Hst?`1Fl3Utέq7j.UX&lJ{$@C5ޚUwT{զ	v$&~xE54qL:X~Ӏ`Vد:m/j1fȃ҉ӊsQ)7gGo3SyqA=^KW5/;ݔia595\ŠedG4)O'5zb?1Fzh2{7 U,Ρs.yKr U^m)r"Z]=o9^84],yޕyVg9~l݃o9U3@jvBܑ,58uKm8
Q|4套,NV-#sfql;ڦWqcx[1>`_bT՝^3? U+Kgjce}8aH94myBx	"HYdlS@!'FndjKhAIz|`U?5K[cG/|rFE)J07~wZe:|e6dLU@lܽ| _1ͮs	w3v*}9ܸsH
Z+BR58t]bC]D땽*gG~#j͎
o\l@2)҆><>' E큯%
ovI8ύtwFít;qCO_}{\5꟏;/b1O_xw3'ozPgG7g:98 CT3#q+0w!i{}wtc]]zڃy׳Mf+>/frإEQ;[Hm`sYOwGIs*V_S(X.g!s$j9 iaJ<[*@^4t*i6~~CVBo&"5mQ@#NyM9ctj;Ɠɤc@:3G'$~.ұ;]MV`v5.x̫"^DYq3_j޵8*=[<(zGq{u(TJS6Ld{OMZQW
/d:y4[&3ԁ~_ UB@/ΘuhfPARb)a<*z3{8>S-b(R~bnkǤC5@\Ίb:WX#D+z4k1+ؕZln|cB HzY.uV[n
,CBppw[a868y@XjpףᰘpdS{-o_ QMuL|\uLC
GAIFE*4 SnRܩPtd[r+ٖ%)ӢDY	P-]"bAEVdSfV;4ucnuo`3,Cʻ"U-ŉĸ#pf>Cw4[0;-wݙSMfR|{KidIPIzvt^pWApίX╠o<-,8<09uoŪTA/
Kг(RCA>죛*N.}pjv.p8
gĩ"vWl?!w!9)l8⠦֎UnrLQT9tcO9t6.B[xw L:Dm_V N&	T`ǟ˶r6~T-:Kd}Zl^j<trYƑmZΖ5&QͶG"r0b8-l	&*5PeTHjp4$?ctĄfW#4:+$TI{CaiJU<{+yd*7wEy{ytR(Prݟuc=dnVDO:)@Ip2svX;z+!UGhc2jE9Mγnv4?9{kڀJޏ͔{.>@!grnd4\z߫4Q9T/ywaI&sFSNS*t1Mj+F`@-إXEjJxUWNjp1ob鋐I(^(&"({/Ѕv5ζvYВ7z/dP֋ye @r;EgՓ霻E`pVIא
':rɘ6"uuQl|UUh} *X:ʼ%+ؠXty^Dm~,RY'#pH8#hqa(ˎ2)Td\ɇɑ\˚$JK@BݓeP	=IKI+`@S}_"^y"ЫnܗYHl. x<Xgu	Fj3IZD}e2n'W+{"w6ѩ<CfpKgD[;/d6x+苊@tuՏq-Xc+6oGPhk'+;OxfhÛ9s%pb?Ȏ<XwomL>,kk+zZ,Bh?9L=ﰸE0`_jjL_ҤݍsGԚ`4j0vdtfǡE#&CҢT@K?c(O?e>Y"'P[og}6^eja
/9bD^ FOi<bfasc;fal5lK[e4lA_V<FX"%Xj>r@LEWqګU$M6.˙f8٘FPesǈpUCgnn^ZV-,WE@CaDv#ca8i1`:Q+>#0:Am'::xb*.cH5UE@3#xЋyhA%$	tuAT+Y
h$_fFtbM,WZ;NxrSEVaKd.jxSǪ_v\kSg;4qfF9-ŭ07AJXhl&nJޯ}si/zb{	!	&PZvĽȡ3)M)uhɐ9*uqhKm"JffU ìѬo6t+ݸ(Y<RSgù5,otI2IhAM]%W汞`u$+^w;&|q`(9:7V7h`>hSѱ {z4"jv-۳|5Si:z{\Z;x)-XKv
6yy>Sr;&k,
pNϙy#:ǯ>`듽MTw E\
FA/	GĨ.
36ۤFiy=jE~Y5Nl~(k:i{WArG&vżL:abd&`'0A_-pu!<}d;n4_p%0>,@"m-7P*Z+鴞۶]o>n0D	F[8=tN:ڟ|)vu)7=2ٻa_zN u9[qh$
+&=>G%GbeyKE`dq/ByRlOr9d"U׾j%m೓<*E{+ ^"g'8M}P,4+0T?A2=ȉC-	x7'ǫ={2Yec:}pXcH1
\7NYyΡ=Tk	|2,iT*~VxޫrN&WF^ .%uk*VK\r@aVe:Њ<ys[gVP$j&I &FR$zFP:Zk/yb;#A&)=ˍ,훝L4Eoxy\YkGzj` ZF+[-
օ%A:9-PlKYӋuhI	srtءXQ?sC!I/`٪n=bqeW&
6ZϥXLgd!H@X.HYD4[MfJcO>zExwEJzwrhĹu"2+6jM֊l;ʓG틼c `٭v"<D;gĵ`x%ʥV碷$vΨI4GlPY_t	}jc3@>:͔DO8JMm~5YEtd/&7"Xf8
"0z{w-b\t;+菓"6uvbX^5E=rY<x7Vǣq^y+JMV7(|_3gmCĪVzYW7	-n]DW5WâDvZQyWܸ8tRMd	[j;lڨAϨΧe1|bxIo{?d#Tؔ}o2?u+7VeNqtzނߗ\Z;`/jAt<2f!U,A=ubvvRo;60iی7^8؝Qn"%\TY7=HNnWwZ/<jHs^½ɟulӚgD&nD}\<l{nGVmxMBllDggQ.hrFM%dZnu*m;qn1
-T҇;o1Lan+h*Y!v":ц	Zx\;k..yT0Bn
VͲDy|0Nf5aC葞&<YM8|/(EHY*QW<>N
mv܈FþtQj$yU`]͡[͒'q:H`*5c3!qcb.~k]iVyޚk{p܋Է+lYc^zMQFP8	"+-mP1T|1bEQcmVlQ3AGT#=:E}IU]|!fB5=:1ÎyS	ϔJc2`e(yV"Xm.H}\M5UFpKl1ۢ19' 502 Ӛ;AZ<P;Za"HVߊ;mZV@\Zm˛
eowvz0>Cةa5gojm.oUٍ;ѣʥҁ%<[@\f$MTb=@ĕ	Zyb5|0[W%f*ҳ "/LЅP??3xV<5SlڥI18˺@@)1^˓nCPNl=ЯW[	No?<HoՏ7<3F>0jk+N)xj$\ݍl2S5/RTےѽu*/Bkw;tާ]xqIɋq'zq+/D6162n0UuL^U>vQWV&MZ'NZPznCZǥ*
AQs2](.+wAI+2i8eL'zgy˘]v֜QՀ+5rS56F5cC
8>-z΍FpDVn9GݻW)w}Tiid}Q2F*_dC%pEuCPmi`_ކB6f`wvgQQ&|Ç*D5朴L*̵=yPK<>S5S-^+I?o8qa\#7j4`&e>'>xgyQ ƨX,ӏ
ժU*Lz$+=UѯDf"D!+#
)^T-64@Aa"[" U׫)L,ɒ$3G+]M~uқF/jOa+uJ=8aȯGMeurAfEo1T}j	ip:jWLD:ج)']T-/㙥fbGJh=f!XyT6k":ylQ7߰u.7҄`ban陌Z;6p9vw`"iJxƼ ^fql
*^ 1GM[V^=L՘%6t6(ǟlH48ϝRhWyr6+N;ɎL/	cK1 i6b܃W>	\904Tt0^VArK;;2hE[yI.9c[g<\]	:8'5&,M?'M{躯t啯v[;A]sn=iEN;>M0i*У>=gf7Iv3sރژJ̌#*n"@#P$E'tbg&<>G6#znؓ}6rjPRLy[6+MCB
]m)!ekEEل׮SbSg`6JɢG+x&tԷY2!!`ev1tWEʁM!'٘mhme
G=rrcm	-~0ǲ"ϭ
Ԕ/F@LO=h2tk)1''Fa
)MP{r);zqZa7ڜs)e-Lt-s3>U[σs`ԾJGE#z:/m@h#|::7H6SwBV;4qOmoo*3ОxuzVތno6nl7|Pp+<@vvYl\nOcR7.7/O[`=Q׃`qQ@KWnj o_;=PhKW3Q?Gj[#Pt~ Ero:}|hX1rXhppSJhr{W3jaY-]1>d4Zu)ZC
f&*>K@w{r`}b#	@Ρ<٪Vr8>9ߏmd_b:\('^́cJ	2*X9M:ïs$ASf`7a쭭ΣuZB$LJN=oA-g%o|+&BFtx7e c|m$ڡxҢ>@@B84pP*tt@[(]@ZKT[:׈^<24R[Aw+bQ _8y?9?{v{s3l,t+'?;#QGH>j_)݂4]w?2;h~+Wr8/yChX&}
r2F<t865=jM>螕
*4wWVVաCPWjuev(SLMhһ	qDqd2}$:m <jRm0WdËIۿdP1) f-#2Y*qp{g:#ۺ)
@)ui]vZ[&`ynW/BUqӵ*nIKh-uT_0٤y
$IQ謯#BxhԯĞpKJ1L&?)]Ԑu|&f0`[/#7	taЧ}xvpW5!H|XޤTɺVır5kNjun3 ˢ0FE`D ]Pn twnqg29\۶D]L`|ӴGot<1*0Xr0<ݠa=zJ÷-@d1P|Yƛ3MCp婹ݢ}$ l~~ۤ.y
TM>Rvi`W;$0wك<ٛ/oAuSĨaߘaAd$#|v_9Zcq l
ᴦi?xgf 8H7^E^{fvf>3N2)+gߕw?LJsE˩&:%[|m](DKs59'uO)wl$m`_$~jFa=BR8M,_GJ0/d?݄!}/bƛ?V 
GYOKؓyHM/oA;n`tN+sWH!I/<a
d#u-sSsN6t;z0Ё}BG熹x|1u`6dkI1L{4zn@J&[I[
n9`]G._7K]ΪϔI)4jCtMܭ%}QJstVa&@4_U,#̳#<
:6|X0zI]/xHҐ|~9&pq.qK/]vYlMeզmn6Yَ,bUzb"MHt,F\8u'o097%6zm'2k]EA>uv{!g41`+	s76D)拽ϊ+\ƣŽ"*BћI-XO|.V8f袺Æ8>P*̈(ׅ/vGå+AO\d 퐿ۣC;8F	+DV_#x2{Hhyog` Ih'̫ʼQ<}1.vM2j$0%PG@?˽'`KU`3mKdԵ И뛗+2+n{3kxFɄŜ`Pybj*¯TuLSę1arSGW#Pe-k@'cr |˩L	3hHdѝ> *:NK _!HDY{"A_toV|PA4er-RP=VȻIhešI7s#&rQwf큵Ȳm/	7,
K,MZj{,[(]AeTGDCVEYey%ri`K`+TuM%-gbV/uQ\&VO _}ܪ[[~՘oMySxϳ1L~%\]f6F]x(t^%%I|D*LYkDC굺qnP#k`R;ٕ;N.
✕qd̫hvUPzʄZخ?cG0'WOŻR);곸d|Ќƛ$chس '؜,uU4~VȇQt{{ꫦoo}L=<=[ƅVgQ#~s}i×rp^(("|ՠ䜬+M#o8_"^Yoa]!gFe*m̤4rX+',:chQнb9/XEé_GjeEN.ǷTuh@I*+2UV?nZҢ*1.	})g?-~e{!z9\Ҥ|ѫal3yHgX{T4\%^,An݃EC\YgD+Yq>kthn/_ڟR]dm0wrb.HA]^╧fzAN"D>ܜ8΀_xA}.LTXڗK#*׊w줹b"7`%iEUB	:OYƆKGN!K`1X#Wo@ٗstgE4ɢ[zف$}R(vrtSp.TmIsFURwMvgNn:mP$L,[8c G)b4c4sWŏW)P\ҟTcJ#I5(wtW0VFY5xjR}PIQ_ZȗW^кRVҴ4>K*|1w	SwUnN|R~iliӱ_6xv|
2B5[ʠZbO[NC0}˫|M|4U}*Ai&$?16/qr/62Rb+mlϚh::Ўc^ݘv4ʹR{7t!	;N.Ib(lRѮ^ 0No=KئxJZ[蠷bݘ0kg7C8Yx_f,	!8ׁ4g,Sx	Qd&` !7܎(WT>&6+e9J^ԥG&*T"gFnr1U5z@:~N}҂46KYUCBF"sUtmD'& yOT
ĎgO7*[7+(k*Sہ9{)kX,{fP0Z>DS描ɒs0O̶S.9?%Vڃљ|ݔ 2^>i{IiCNԮ`')'5s.Uٿ&?'AHE9M)&
񞫂U .54'NQ50t,[A/5Rna:pM9.^d5\,(ԇd6ƿVihpyЖ^$P(?(vi.(@qn[Hc1㣟+ʥ,5KZH*R/ti&Bk24ŷ.[V؁ ɶ:I^[*mM]~xqm"۵,qasqV3"WwndI54}^-`{f|}k]AxRLo4"_M	.H6e| yHZMQZ5L^d3Vt-d:8$>C.kbW3{i2|֥[TWsU|n.{xpeqwsJDuw#>4XVG!u"O
1>nY&ͤϢbP|(,ò'rY1q8-+	5G/9WԒn%'/qc2eܝsR𘪵_ϻ`'ZH#J&(kdi5o=mu}E\dn+5al}t+n)}=A䋎`UŢW+QBJ܊"xSzNvb!2"nl部oG{';;ydn"k(b,NMiORv?%1_<!Xcɢ6i$	Pjp#EHs+t&	`cD=tTi
 ]`2?F#a5W/'kѰה^Fu^+֢ct;C"QP1-&dsS[PD2ۀER uI[))n--^`*qn8#^71ׂRoQcqq*U^! L0hi0ZƜ09٪b!QQJ"㮓Qޛ0XFqL)Q֋d:MZ
X\j
Zn̞t>(>hb4+h˱b:{$ZQ]G3Zc}IqO۠s1Ps,ʎ(TCP5qٰzP_3"<ߏB2R-`TMOw8ذEt3&"6&VoxWn6>L9&E[l;LDi~Te+dkDO.DCgiHл#ULP-<8.g#5p2+?~=_͈~=*CQ**.o߷u%sM-24*VSxpmYu|!$ 
OumOGUG~=rZNIy@]_y͞(A[ZHWi r`-Fjoh/ KTP.5JpXjX6&T<ftZ;wMk3YNQ+(Ǒ"<(9/f=P+lT}i8ucn
o2c;۱Gin)6r03nhsquU[̵&V8G"dW msJ+@Wi-[
N~wocs-韩]5Hf) [qQfCcvk=\Bᷳd4YN3}]`W4!	_ʝբzN}wH}D.qv]OFK MZsGiO6(d:k»e}BAtxuCM::]Q|v~IJWyMVq_puɃGNYh2)fqn?]h!Og` w*EK5Ud$DW!YV&Z4Y(Q&g3'>TE13zVՌ2lگ7Pܤ5R:FCU>"`@{
@ $]FԷ#a:TQKB;YȨS1t$i=Ugb(jNg5qN0<@MH+`hiGYN`X_`i>0WZNmVa){1X㴘j΂śNن3Լ]o%^5&Xe3:T0r#uo2B89@I=
!g6Uw0X0q2Lf+B{Җ脟.0DEuOBK¶Ah,
`BE=P%ĝcc]ˈYh>x]]~ҵUS,ں fUy9A᝝¡>FV=_ mO°64R
,YbkSߡ(\eyX\s]Nхf*XAwSIqD!jx2D*QA{K+T
:58=uDu2lW` in#@9[eiR$°gS.V;KƠyՍQ&"V=MQ[a{dצ:Ԃ0Dibб# RR>pJ3s	BH%R'Uq.  C!z gqE50T;}puPs+
iB"#*9VB؋t:p](X׍isx?C_I[73U4)yW޶,/PКBCb<b0zv#^'R^ЬL/Z[B&~L~c=IۃMr~d8_fON7Ʊ'Kn)]u%t}x\TpUI¿f!GǠteዾ{(L-9v0wy[='K֌etǵQIe-@T>췛[ ԝ](i옕bs5UHVjy̾y뙛ƪ?	#
"^Ɂb_{<,C:<M{>R48H'JImyLWJ|H4RoU`WAhZ#i9ܲVֈwWr]un|yMXєb{C^ƷbEa"xLйiۥx^%p"P˽@U+`p'[P,$:ۃ{S.&MPaIz	quBO{mE~RJ*1T!:xj1k}.'vnB$VK%D9f#ch4tY!7g@}RdUKtZqnx׊Q06[x_}c!7Z0r>'̒("+N85k_ ˿/_yUc:mUYQ4gqà,o߁ᐮ:2.'1R=Yu.x޾dgFCMW6V񫽷ӳ㓽+wvOH5̓.vAON߁hҴzP!ݔHEHo (hCI]ж`*??}̊r谙F5B$A)PBNe9kVA[25rrA9cW	'A*WZyiWe>%y2yR{*j(ŬoV_fFD2ݻoGm]62|>Mda8;98x\4UY}/J_1w
m7SꫧS#yBt')_
An@C- JVO8^@d/&ܒQʵy
Ǧ}l4662Yi$uKeGN-5H:psF-6Y߈mSuJs4܉%Q~uXz$q&kk_jK ;H,C^9T<?FS@
aNHFtRz6}C
U`RU]z1~,.>
ڂ9VT:^(@f
 R7t}z)IdJ-a	sO // Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Globals:
/** @type {number} */ const RESULTS_PER_PAGE = 150;

/**
 * Amount of time between pageviews that we consider a 'break' in browsing,
 * measured in milliseconds.
 * @type {number}
 */
const BROWSING_GAP_TIME = 15 * 60 * 1000;

/**
 * The largest bucket value for UMA histogram, based on entry ID. All entries
 * with IDs greater than this will be included in this bucket.
 * @type {number}
 */
const UMA_MAX_BUCKET_VALUE = 1000;

/**
 * The largest bucket value for a UMA histogram that is a subset of above.
 * @type {number}
 */
const UMA_MAX_SUBSET_BUCKET_VALUE = 100;

/**
 * Histogram buckets for UMA tracking of which view is being shown to the user.
 * Keep this in sync with the HistoryPageView enum in histograms.xml.
 * This enum is append-only.
 * @enum {number}
 */
const HistoryPageViewHistogram = {
  HISTORY: 0,
  DEPRECATED_GROUPED_WEEK: 1,
  DEPRECATED_GROUPED_MONTH: 2,
  SYNCED_TABS: 3,
  SIGNIN_PROMO: 4,
  END: 5,  // Should always be last.
};

/** @type {string} */
const SYNCED_TABS_HISTOGRAM_NAME = 'HistoryPage.OtherDevicesMenu';

/**
 * Histogram buckets for UMA tracking of synced tabs.
 * @enum {number}
 */
const SyncedTabsHistogram = {
  INITIALIZED: 0,
  SHOW_MENU_DEPRECATED: 1,
  LINK_CLICKED: 2,
  LINK_RIGHT_CLICKED: 3,
  SESSION_NAME_RIGHT_CLICKED_DEPRECATED: 4,
  SHOW_SESSION_MENU: 5,
  COLLAPSE_SESSION: 6,
  EXPAND_SESSION: 7,
  OPEN_ALL: 8,
  HAS_FOREIGN_DATA: 9,
  HIDE_FOR_NOW: 10,
  LIMIT: 11  // Should always be the last one.
};
     VKo6WLk^'mu&hrGc>TZI;];N-g~/kj*.:U_=z:bw	H.|B] A/ V
=f֡_'/_%Qx1xwk)5XN}r5
Yfљ¹LHc݌NI? ;P\9(Y𼐢~xڟFoڢ=ڒ8l@7)-A1-Vp:wS'+7bQT_| SV检B4%ԂsށYq]YjfT^FFܢ%PVX"B1	[*NOqM`5Z||sysdl]4)	^[ycO5Zh\^܎lq`9)M@lMKT4:Du)4¡b]1#GSNf*omE
uXzo",ZQ"f01?7\HGst@d0m4N~{
hB)%ގNVh:6gSm>VK1N,wqIɚNpih0Аzcdd¤t*<eކsϟ~Ei	ʲܧ =SX0[l
Mm̒Es`B|#ӷz:&X4}g/?cçieL%1,vb>kzkQc׃)= CzY;EO(;2&W?**B2DTuuN.د.nXIbV`^Ee22-UF8
TnV@f%aVZ_tJ>T'ݸoH)^{+cO00VP{(tGz!g;FSitiL->	zS T/0"2!',gӬ%?[[	  // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Send the history query immediately. This allows the query to process during
// the initial page startup.
chrome.send('queryHistory', ['', RESULTS_PER_PAGE]);
chrome.send('getForeignSessions');

/** @type {Promise} */
let upgradePromise = null;

/**
 * Adding this on |window| since it is accessed by tests.
 * @type {boolean}
 */
window.resultsRendered = false;

/**
 * @return {!Promise} Resolves once the history-app has been fully upgraded.
 */
function waitForAppUpgrade() {
  if (!upgradePromise) {
    upgradePromise = new Promise(function(resolve, reject) {
      // TODO(dpapad): Need to update this to work with Polymer 2.
      if (window.Polymer && Polymer.isInstance &&
          Polymer.isInstance($('history-app'))) {
        resolve();
      } else {
        $('bundle').addEventListener('load', resolve);
      }
    });
  }
  return upgradePromise;
}

// Chrome Callbacks-------------------------------------------------------------

/**
 * Our history system calls this function with results from searches.
 * @param {HistoryQuery} info An object containing information about the query.
 * @param {!Array<HistoryEntry>} results A list of results.
 */
function historyResult(info, results) {
  waitForAppUpgrade().then(function() {
    const app = /** @type {HistoryAppElement} */ ($('history-app'));
    app.historyResult(info, results);
    document.body.classList.remove('loading');

    if (!window.resultsRendered) {
      window.resultsRendered = true;
      app.onFirstRender();
    }
  });
}

/**
 * Called by the history backend after receiving results and after discovering
 * the existence of other forms of browsing history.
 * @param {boolean} includeOtherFormsOfBrowsingHistory Whether to include
 *     a sentence about the existence of other forms of browsing history.
 */
function showNotification(includeOtherFormsOfBrowsingHistory) {
  waitForAppUpgrade().then(function() {
    const app = /** @type {HistoryAppElement} */ ($('history-app'));
    app.set(
        'footerInfo.otherFormsOfHistory', includeOtherFormsOfBrowsingHistory);
  });
}

/**
 * Receives the synced history data. An empty list means that either there are
 * no foreign sessions, or tab sync is disabled for this profile.
 *
 * @param {!Array<!ForeignSession>} sessionList Array of objects describing the
 *     sessions from other devices.
 */
function setForeignSessions(sessionList) {
  waitForAppUpgrade().then(function() {
    /** @type {HistoryAppElement} */ ($('history-app'))
        .setForeignSessions(sessionList);
  });
}

/**
 * Called when the history is deleted by someone else.
 */
function historyDeleted() {
  waitForAppUpgrade().then(function() {
    /** @type {HistoryAppElement} */ ($('history-app')).historyDeleted();
  });
}

/**
 * Called by the history backend after user's sign in state changes.
 * @param {boolean} isUserSignedIn Whether user is signed in or not now.
 */
function updateSignInState(isUserSignedIn) {
  waitForAppUpgrade().then(function() {
    if ($('history-app')) {
      /** @type {HistoryAppElement} */ ($('history-app'))
          .updateSignInState(isUserSignedIn);
    }
  });
}
 Exif  II*             Ducky     9   Adobe d     

		!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  >                                !1QqRA23Ss4aBTd"br5D#C$%      1Qa2A!"q#   ?               Ro                            #uN                               r_M0<4H:[MFifrRZC?w9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>sw9{~>s̍muvr<vjWuN8:)                       dJ4ț      RoOx<~0v                          G㿑܅|.tV                      }@ۀ\D7^@,     \Z{GiKh&           mёU.DUa~r{_l/Am6 6rM9a~rCi9!_l/Am6 6rM9bJ:TCؾ&s/FB\zS+
@                      FuDUXԴZ  [Ls    %qxaRZ	 aoDw-ls}Mbmc"h;oSl)6J؆ze!EcmZG1(f_l=WJIL/\Ctu),ֈV*١ȩ{O^ \r'j0           1>+uy:<ÓѨw;7T                       P(͋ܲfVB7F#v2   DMv]܌E,תQJ9w.ՠ,=5^JW&h5|GLk!eȩK-+:YgK   TmUWPUN4r]qxC%T2]qxE:MrXŴC;(_mas}Mb-o69&6ܜQPU-S};bVu17ht%I517h$ݢtSvRMLn*7AI517h$ݢtSvRMLn*7AI517h$ݢtSvRX 1>+uy:<ÓѨw;7T                       P\	Eifd\*7  ELWy.tHo%=r{GiKh&UTSWRg                    x-\pH:%n'GXrz5GrFQXR [@Mq@Pq@Pq@Pq@Pl             Jy?]u( 2j@/Yya@ >f&%	m@[}j9=#4¥ڴEn|*q)٫=L                    !Zp3m!q jxia~;WWAqEaHagڳrPa<&9R[g6'X6'X6'X6'X6'X6'X6'XJNIDTcczhFڪR6B<$b7^            Vm0٫ J-JN&LL4Er-`9St@*P9w.ՠ+uW0/SoN]g1                    
Ӏi	TPĭKOFB\zS+
@Yi/g*Rh[UIXjSxDjl
#.B˫P2*l
,:hZw
KCIuG*br?W_1            Vk!R<  r䶋JQG%JPS+ZV )DrRpޕj2ZIO;
jM7f3֘                  !k-.-^L^+b#m6<$1fWY6[i%Tc}Vty'Qw!_?=]n -Ju.31+즛v"­ڴa6-9	E'HE   hdY2r(#Gn/?rbbлea1             ϚU->_@   e?-5;'%7@%MЃ[BYUzRoOx<~0v[q}
sxvjS=i                 k-/mYlΊ&lCJ3{?ЪZUiRLe"6.)3|<CuA jx|8oS޴5,%+v˜E^WWMLc1ܕNr*ҷr[tRb^[a)*4$"gRQ":,F+is2D6BRB ~?O̥GFCZY	U-5kxM^Ðe9?XS^  |Y!e+uQ1             \xIu,}yBT  ~
mSIcX,J	T`r2?x3O*]A4V`_w§2'Zb                ̢XenȏŮb9K3nnEEڿ{~J{m!5LuJ^N%i3)DSHha)4JOMmFUam#S^}:p_zȇ9O\VYn##~e^[r9:T$^I-Kߩ?!/ixbt'*T>1Zg$Dw-;?wWyܷd'`^,7@8c*4r6(%Ix~/+uQ1              IZ9@  !V5ޔrRD$U+{p /& ;
jM7f3֘             &S"3Xۆ>obB՘֢  jl]SO+yG9x	g/na>ղblļy]z{ZN!'5?r)鯋X   Dxkך__/foGi5}	vs T xx~/-DWbڠ               (Lˬ5g1p\ f#YulԴ  %qxaRZ	U~8?z             EIJU٣~uN&')b7enb4bsH   d9wM?G6̤EJa=dnWyOCWL   erb5n*.vM.ez܊"cd I~ V.]T.@ =*[?ö?//޳Ceè[T            T4)hL+*Ҩ@62j3-R\P-rk΅
աBP7%1Un -]NUP.4Y~7姼d~f?TVh_N9e;5tO穞            Ri[*4cfQsrҪb|5Ȋ     !͋i??| ae$ Yjn]uTZ?|(i [NK)*IT޻'uOK盡 ,	F:X+M(XSp˭ŗ_;OUs!9UR6Wpdbo  LThW&g4~^Qq\ S +gv%%|H{Xu^j          +a-2RV-@E4  -2EVQ)HRvUDt	]Ziv \Z{GiKh&UTSWDzL@           zCjw$YE^sk+H    vC{~JmLI [@{UB5l=*޵whDfQe'   <6(2ڻF?b1 ҩ ;ck>$=^[:}ŵ@          Km/AlV#Q1x %cE@3lE9["9V%p--5h1KGZ  RoOx<~0v[q}
sxvjS=i           U)[Hy3AF4U}Դ&|ܗv]ͰWL      !͋i??| ae$ NJfdln#3ݏ	]2   ~ܪY8ϡ*~<YH S +gv%%|H{Xu^j                T6Ćj*@"D^ .  ~7姼d~f?TVh_N9e;5tO穞           5զ82þ+~UL      l]SO+s}3)' N_;wZ'Jc^    vWvD5=	sڀ J 'VKK yn&:3              `*F뽖5 56/ b7TZ},m\ 6ˇ eiqxaRZ	U~8?z         r1!}lL؊{UrS鬯DQ^      .sbr~_?ØmI=  _W Ћ>
Sي/Th    3P5[7	KQ=;sh9]R3wު%>_;/
c6I1oSdUac3!=ԣ1Ui//޳Bw6cC1mP             x)    |3o;
jM7f3֘         
O/Ռ6        d9wM?G6̤ .ԫEhǧ\z%TLRZ0   QgrpZisH9hkK@ dzω_)[:}ŵ@             b  @  @mqxaRZ	V9 ʍDWRa9r)٫tIw*2c3arݻ4%`˖٤+\n$6X2vi&1J-۳I1VnݚImevLcl.[fcdrݻ4%`˖٤+\n$6X2vi&1JC˽ejc)dk;["(gp3K徥)=徥)=徥)=徥)=徥)=徥)=徥)=徥)=徥)=De{Q-opzӎ5s&,F=' uU\zDG_S'--U#̽$}%t%%ܣ|7V]J\.^t.v?bƤՔya+[
)6\!l_f)#׀ 7x~RXu^j             5KJi[ b    f^09w.ՠ(TVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀ5mVۀf@  .Umr͢)sZD|.z&4G:m9UxJ+
3\߇ %P6YjY[QD9ņk\>
h/6µMU"W6K7Cllj
  dzω_)[:}ŵ@             nS  E  n^ #}xkj"P^%4l
jD%(mQ. CjqJTK*Pڢ\AR
6TD%(mQ. CjqJTK*Pڢ\AR
6TD%(mQ. CjqJTK*Pڢ\AR
6TD%(mQ. CjqJTK*Pڢ\AR
zFZ8tǫ8nj<t֦?UUc     |Y!e+uQ1              g%ʗ-( #	  RG6wѳnT                          ~۹9Sǫ8^kVQtW"*=i4q­kg!ҨY*Y*Y*Y*Y*Y*7FJV+(Buus^j              ah( M2ĉ[NZ/t`ˠ; _91b&bCj]ύPU4D~\G+CUi:[(=7VfHpzn~ufk53_98Y!qk8=7VfHs\q麳5CMՙpzn~ufk53_98Y!qk8=7VfHs\q麳5CMՙpzn~ufk53_98Y!qk8=7VfHs\q麳5CMՙpzn~ufk53_98Y!qk8=7VfHs\q|M%#_[eԥ
FtRR"sUiNi+n*Qw@+*?1ǽUD]b#uU_'-lOY3%My=g6?r['LoSlOY3%My=g6|UXÝw9U-"9T-^ųW[1EaP               "Z5p% @=p                               ܻL5JU.       /JnځX      eJe٠Z XkUmբՐU(Vl{T,~C蔫lg"s[Z*{"f0 <.cpoo!@y\3DL <.cp" <&kp"70 <*"f0 <.cp"na5@y\na10"a5@yKy-""f0 <&ja_u0^2PiP؈@g⧺8y\yl|*{Ì5qÌEn`BEr-KkXU55pV:\@%(H
b/[`BhҶ .b [@ kh7@; E& E n `R݀   [l@/  @Ǻ`	h ,  % 7=@p@ 	K@  J  
(x	u@%=-(@N Exif  II*             Ducky     9   Adobe d     

		!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! {                            	  !1AQqRa23S4d5"rsBbCT#c$D%      1Qa2A!q"R#   ?                          Xqմ                                                   +Xp                                                      cEV,                                                   cl                                                      [@                                                  W                                         -             [@1c}a\.@                                               z}Q×;7cuRjV:v\                                        SLɢllH}d            .:`c[!5R\                                               =ׇ.vo)jǢt킸                                        Uƾp\aƑmWW,           h5o>0˓U%                                               O>]sxrfz.M_JN+                                        9UƮ"&ɴٗ'Pm"2           .:`c[!5R\                                               =ׇ.vo)jǢt킸                                        xuU&w ӆ68l=EsNpo          4\um<ƷsCrj                     wQ{DNy:=GS9E;VJ"+%jN5uȧr
CSd]r)܂P殹AY(sW\w 9E;VJ"+%jN5uȧr
CSd]r)܂P殹AY(sW\w 9E;VJ"+%jN5uȧr
CSd]r)܂P殹AY(sW\w 9E;VJ"+%jN5uȧr
CSdE86mfeJ7*@ T|-X]TW                                        ⽋7d4͓6DY$m5R˛ؼ'         h5o>0˓U%                     3~(:=Qh                     
wqr Gˮ{\RՏEIXp                                       L.g0x mz2A1ʦٙEvLc0/M1U         [@1c}a\.@   TQUuEGȌ/&hop淪\r|#Xާ>淩'59qc{8Nkzr|#Xާ>淩,o5^wEWYM1mSƦpFĽ6Jwq,UoWoTI7w6I7w6I7w6I7w6I7w6I7w6KJo/.1ͱ=i{mWX  ;;G⎺3uր                     o)@ T|-X]TW                                        3:
  U0u118"ܶoy0        ;jf٦whc[!5R\   ƣN\`\.o˸Ƽ    x$˝_F{yb ϩN;7Z.ɺ!T[IXA0    c]4LT[MQdG;UUuVNsFnUbԚ  ;;G⎺3uր                     o)@ T|-X]TW                                        5:
   6<húűATN8H-h79;^ Y       *hjO샨1c}a\.@  nM'Ktz8K8b,1fBRftXS
M\jfςP֥/GuuE7Wqe4E3YDEz     1Mcؗ^f߄(sW9V
m+j65y~
CͿ`^f߂QOX&*1E+qgF=2kzx5N9>}Gs[x5N9ewu776DLL3켜Wd-+§|,'Bҽ<&6дGO	t-+olJ{'Bҽ<&6дGO	t-+olJ{'Bҽ<&6дGO	t-+olJ{'Bҽ<&6дGO	t-+olJ{'Bҽ<&6дGO	t-+olJ{'Bҽ<&6дGO	t-+olI,bٛcm-	  4B5 ꏗ\^ټWұӶ
                                       cGZA@  TMݰMSqN(U3bqwyEq      <{hrpVOS{ kw>:|a&K AI _2{|                                   gu۫ħZ@  *i-ƅkP .9syKV=U&cl                                       2-9   LnF
l@ES-7_7V    
z]7TN
w=u5o>0˓U%  ~Ǥ =]E                                   zO
^N%8Բ  SN an4.SZ =>uu˝Z躩5}+;`   3 swܐ9LH&w$n;7yɝrgr@93 swܐ9LH&w$n;7yɝɝ                         դŷRs@  <Y&l	˖ ŋ6Fǂc^sqVXV6   V{]X);d :zsPc[!5R\ zO _ֽas                                   FfWN&,  TӿǷ[֠ O>]sxrfz.M_JN+ 6]]M1-SE4Eŀ           5QMqeQh*MqH5                      "QU9`   LcVY<[3`o/8Y^^   ?H/fTi }A 1|t0.MT  sd>u{hd\                                  4ѳ ٤=૭/mSK   4B5 ꏗ\^ټWұӶ
b&f"1 ^1@)Wh\_q/(Oض0Lb3tC_G7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7Q GyyWt7v46nkriLqj1u{DULWL8f&&bq @                      {OsL    en3O@cw\^QMq0  s1pF9'@GdOS{ kw>:|a&K AI _2{|׽l2.`                                   {hـl}U֗tq)֥  
wqr Gˮ{\RՏEIXp?lno+ַSM<Lȥ3_;rwt{N}߂;P:='~
G@ܝ(rwt{N}߂;P:='~
GAuyFy5E9T[Wc^@k                       P)Q
    x*c` 
W޲UÊqH3n<yt>;<ƷsCrj  $ۘ s'˭{F"                                   	']i{n'GMjY   o)@ T|-X]TW .<;}`\ 1|t0.M\(ijq5DJڢΚSl       5]WMLEOF<<mCT+qjM
wv5                      +[ww     wՒ'bA  Sofb,:f-L
ꊱm LDfq*ɫd5o>0˓U%  ~Ǥ =]k60                                   M=l6i>{*Kuy:8kR  M;{}йMj  =ׇ.vo)jǢt킸 qi<ƷsCrj..몙1Lv:Z.&lLY=<       m"&o)*xmF%wBPwZ5oLaaIr:8Zky̘kURl¥_-^N յ                      WLWL?14      R=5eòn|sF9&A \., ָ1OEV,kw>:|a&K AI _2{|׽l2.`                                 fl1(^E8)ӼǓܶ4έwwו]͑ƌo}gX[8"]']ivmՎtq)֥  
wqr Gˮ{\RՏEIXpӷyoC2Ir  [ [         :+)f<V[]`k                       GLq}x`      ^Ъ\A`g 6a- ΍q켮>Hh5o>0˓U%  ~Ǥ =]k60                                DŵMEY{VqoVX2{^mm`%-lFUgq =uݤO
u`Jq5d  =h\  z}Q×;7cvIiSӶ
6E[7wESM?{09Zfآd#<fi6إ]V4޻{bg؞8i:8򽚣.8nTjnUOewW!B3}^톽auE:ISuTőgk?G䮫6=       u5WSRxū14)ڶ                       ];w4       ƅUO*:o&˺ UWmDL2w&*vcEV,kw>:|a&K AI _2{|׽l2.`                              D[8!FL}ȏū^mm:k2;=wF%}U֗[SK   4B5.j>fn"mS&Ֆ[WN,vlYgbVqCz577v(gMMYYF,"Ӛ    b&upr[%XΕ:kY	1;0;GS3*ƗIѫq^U1oV&qD]
~Cn׆%       u5WSRxū14)ڶ                        
:]r;Z산     qom2L]:Wqiۜuqwu\ [@1c}a\.@ 	c='|/^Ѱȹ                             W]Vf\Ͷ~5UӃ6G/&kզb4`   wzS[?pK=૭/V	ħZ@  *i-ƅkP_]%WS;G/Z$M=lENq)ݵ\>at?݈sca:}bj8Uϻgter]͊ޏK(ٶPz{'NVFpra:^8띫!\9'.;z0]S*-/vF38&j SBtzzMq_'?DU7%=     ]eWυ1yB6+)f<V[]`k                        5bs+n*     16LN`ufxӊ"s/+ˋ`kn   ƋX 1|t0.MT  sd>u{hd\                            EUSD[T_|[:*^WNڛ1Djĸ    yO]n/87i.X'GMjY   o)AgSUQ)Q?w5D7%Q.       ۚ5]u)'˛Wk]}]1LDU1}Wٶ?u1)_poHCt:f?=\&zAz3Ke =N{W	ސnL=竄oH7OSi~l4Oy6[_p-د{
^P~k;}ҟ
ocn-^N յ                        J)Sӿ      ^٣눙{Zp:    h5o>0˓U%  ~Ǥ =]k60                           nF3f"Ʋsru\T_oUhZ@    ;=wF%}U֗[SK   4B53jW )w,2&w9a~"],?*.c@        lO]gXg&'%QWy}'?ÙV@    k/b|(sqyC]8 J|*Yz&; ;VX                         ,F	4    *$DF/h|K4@o   [@1c}a\.@ 	c='|/^Ѱȹ                          
O- Z,*s@      gq =uݤZeSNTce6kh鷶brx]͹MN tO	MN tO	WYƈ-YJ-35kI./9UTJRWۘGZ_? Gs        - ҨMO1Fmq5y/.i݊RMj     ^{PpYMCT{+qjM
wv5                         1d~q7U[hS    +9<F(    4\um<ƷsCrj  $ۘ s'˭{F"                         &bfȇ]TϻN
zFfoFVc,k@      ǞT#vŤ~(si2%   NL8y/^Hh۱ 9t1O渍       ƃ6icOhHЯyQyLM3wzʧs:@    Y{sCmgu5WSRxū14)ڶ                       ǜuFsgn **i- Us6'H   -hT[]Ubِ]    4\um<ƷsCrj  $ۘ s'˭{F"                         #TűY{U+g51\$kȵ`        ]*zqyIttbJ_Eg9h4t   -^Wꋚ6?c?mا
/o        tYHzn_2B<eWu 6{ɾjf Re£E    k/b|(sqyC]8 J|*Yz&; ;VX                    EUE1ƪl
\⻋#<ꮬs338TyAUT1iw4uAbLrwb&&-'("b*'UݵQ͖\  CCso*f{ +3l`sS0gK͕SgVXxYH,hyoC2Ir  H;1?Oc~/ZE                        EUSE3UX"+/b*{{U8"1C4͖YP        ;=wF%ӽI*}PݣӉdK   7iJQsb+r7<~f_0      6EGNV{TUuu(f[3/Yd~bhtXjaOZ3fbQuEY8*nDpя8ڦkwU<_}??ۛGiM    k/b|(sqyC]8 J|*Yz&; ;VX                   	q@(_^1mk =+c0can,6&mb  w}yu?rpes{7 7EEާU
w}83Թ-Ԁc{Ď-=F+ARj	`5U]",esw7NLs h5o>0˓U%  ~Ǥ =]k60                       EUE15U!b"W{Vjc8NIea0         yO]n/87i.ZOW>FN"^   "^ھ}QWe<M8c\qk0k0ƌQz&qDO)l+	̗7Byy<yK<9f^칪6R9&ކx}a& ;ȋbc&,VL7Y=UVe]H&x5EjYj_՝!&ؚ̽sk9MGEaG^Bmxcm    k/b|(sqyC]8 J|*Yz&; ;VX                   )#.K,#3T-Æ6@bq@   .W˻ÒZ 뺺&ȴcTFy[Fhs&ꜳ@jgUsŦ-q4Tm 4\um<ƷsCrj  $ۘ s'˭{F"                      3(y3AJo&cg41ٵ`          3^qn];شүY}<8&D    'WzU&jgZ/^L^W1̸y,nlč       n(fw˸a:K5m;p<    ^{PpYMCT{+qjM
wv5                   (3 #Sr&c33     q~vu\$pt- :獾DhW1ٞ nb ƋX 1|t0.MT  sd>u{hd\                      U/ӊ1w+_4ie?2           gq =uݤ:wi?_/yq:Lz    N tmUҴUfc=v'^,k4kT        u]S8&% 0^E&LN~se    zmeWυn/(kG>_OK7@ЧjX                   L_%Qffpd     6Ss{V*'wYN XcA=13ov*c-pRL    cEV,kw>:|a&K AI _2{|׽l2.`                     :E8ӽ~}HWc7           ǞT#vŤ~(si2%    &UFOa<+qi1 Nxqsf*        i b[pxW_^Dlq{s՚    鵗^>9wSPe>,ǊZB k`                   k-QlN@VA{Jd7
=; kTo(s׼Bs2F"vpdSM=DlE 	=#EZx/jp8pu     4\um<ƷsCrj  $ۘ s'˭{F"                     1.隧j[YJk4Pq˃ut[b(^           3^qn];شүY}<8&D    U4jv9z]*0;.'7chfX        ,j_?U㵥޺TU.	!ɫ   鵗^>9wSPe>,ǊZB k`                              qњAZh:    .:`c[!5R\ zO _ֽas                     9֜N/}ߍ!U            3^qn];شүY}<8&D    :=\M?E5MQ$2fv.'oƬȴ        ogQ}yʼ-&}%us֟.Ԥ    Y{sCmgu5WSRxū14)ڶ                              zD[q\u-`:5q`   ƋX 1|t0.MT  sd>u{hd\                   HSŎڮmen+k5Sq            ǞT#vŤ~(si2%    Wq&I&gGNsLK?5Tb\        6e/? u4Zs՟İόM    د{
^P~k;}ҟ
ocn-^N յ                       5Dc888Fjsz9QTnƧ<nǣiENs&f, UŻ+Np`Xʍ8rt=qFz9QTnΉU3518<ƷsCrj  $ۘ s'˭{F"                   3(y3HW7Sɾ[m"U$             <⧮~GN-'eVyCv#N'I/@    j"%װ.9wtU.>xKms@        q6^ȳ P8 +MUs՟̰q    Y{sCmgu5WSRxū14)ڶ                       Um75ۋ't9@nA1,m6`tg\cE  f;7ρeɪ  v?nc̞_.m                   U{>JF_U             ǞT#vŤ~(si2%    /b%sTNk//<jَtC        2/)ل򇓢M'CE]S<yņq~ҬwXr^4 w3g4 ʞ8z7{ 'u>w1?qSz7{ 'u>w1?qSz7{ 'u>w1?qUaq^yMUTl&{hgl,b#bSPe>,ǊZB k`                       5_cjf g&#uA9b$Z9l     _՘;/kw>:|a&K AI _2{|׽l2.`                   (^WǮjp2tu(R@             ;=wF%ӽI*}PݣӉdK    5UuL㿗?7Y'        "lDTmWg P~7s6+c     u5WSRxū14)ڶ                       U@j lcF,m NL @  @   /wd5o>0˓U%  ~Ǥ =]k60                  "-ݙjde:meIk               gq =uݤ:wi?_/yq:Lz    *z/ c5UNR4l,2]k       :Lj2y-mHdnz     u5WSRxū14)ڶ                       ]}&f:ط F@$r{A F0 @ yA|c[!5R\ zO _׽DE8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8fU(")ł\j.M!CO1}I 1}q_tu9GW哊_z:,WNbd⿤ sގ''7GSu~Y8?:I /_N+On1}q_tu9GW哊_z:,WNbd⿤ sގ''7GSu~Y8?:I /_N+On1}q_tu9GW哊_z:,WNbd⿤ /h-':X:uIiŤ~yC<8&D     @=Nvo)jF+,RjF
      LST≗%SWnQK6.o˩EqDӻ7cDUMߗ۸ue    >_OK7@ЧjX                       o;IEme3eLFMF@  1lf    1w=_ 1|t0.MT  C_7q8*l[fdJ-tF5_+Yn|~8no㚯|sU~ỡjOW7t7WS>9?y_p5_+N~)wC|~8no㚯|sU~ỡjOW7t7WS>9?y_p5_+N~)wC|~8no㚯|sU~ỡjOW7t7WS>9?y_p5_+N~)wC|~8no㚯|sU~ỡjOW7t7WS>9?y_p5_+N~)wC|~8no㚯|sU~ỡjOW7t7WS>9?y_p5_+N~)wC|~8no㚯|sU~ỡjOW7t7WS>9?y_p5_+N~)wC|5iZW^Wwj뻮c\[3LctL~MG/@    Ԙ..=5W.vo)jǢ֑V!M03,V7F+<FѶ`e-Yjמ9,ey/#(Ѯ̧k..m۔7n|T]9ɺU:4x31#7wVרn  WsSE[M\|*~4w
Ky!^7_o+U=h(=^r4}gMzUUU֊Rr*h1YnL$     u5WSRxū14)ڶ                       1lLgl8v&s0Yp	Հ:L80,$ dY<ƷsCrj  kD8z      ;ڪnm)fpGm.vo)jǢz@U;V։T]v?`4UF {V;25~俟7ժRiz"zLtq^+ȣb{1 -+^FyueŲ(屳6EMT+}yo.ƝU<m:*N
S]B[#Dh3LF!^    }ҟ
ocn-^N յ                        W*8ۺaN<N<8 , pŀOTX;a@&`'p^՘;/kw>:|a&K                                               W\RՏDNIi83
t]HGpg\uƱ!5Si          jl¥[WbhSmu                        oNpkYY0a0l"-7pldlm@' ]ո2v_ZEk;f&bgkPwy[T(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(top(V\U4_TW .<;}`\ 1|t06MT[Z@          u5WSRxū14)ڶ                        o"g1,0͸#pǰ.0& `F	̂6@` YA{V{ owo@                                               {]A S_)hGERjV:v\ lpc[!5R\           jl¥[WbhSmu                         V-S 1=`0[6FE8w A@2-	qX	ct]ո6 owo@                                               {]A S_)hGERjV:v\ lpc[!5R\           jl¥[WbhSmu                         kl 4͛@#t,q	8MF #&- A8DyA|/_H?ߋX                                               ?w ҦRft킸 qi<yiG8mzgkPѿU
/7 RK  J/7 RK T (tJ/7 RK T (tJ/7 RK T (tJ: :-]Lg'[Wb^jX                         L[p[6ٖro0& ss]SM[n #w:;t#wA1_ N wAcC.8{>YԴvyto'-1N>4f_fmJ+ʷ~dxϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;n֯:woƪjlgU!e7u^Y4ـ⸋fG3X3ș z Gq Ζ^0~j           k/?FVcשڶ                          {G8ю:lcsLbf"&ṕ8]׀t                                                       3`58A0[GmNmX~]9s8k88љ}(+*I߫>Wc}'~>cO_},3?{~Y;g~v8ϤgqI߫ϱ>Wc}'~>cO_},3?{~Y;g~v8ϤgqG"Q4qx\smi̯&]J%muSmu                          f1],p	)0d-j=Wូ                                                        -نΠ0Vru1dU              \kʧ                           DUNPV$cusz7h}_z                                                       n8[lck7QTUX            ئ&{iP            E	h Seǧ> "gr= =1́7FP"g(zg/\=6n> "=p9#sgސ93H#ɝ32Hdf0O3ffoЯ(&يg,fޙrrr4n^:fޞ :nޞ :fޞ :nޫN*4y^tn^'Lѧzx=7FO 3GO #+J=3G|;Lѱrrr :foo< Nzx 7/zx ?/4n^tn^4i}t< tzx7GO 'h6'GO 3FO 7GO 3GO 7FO 7FO 3GVO 3FO 3Fޞ :fm}hܽhkԞ :fޞ :noo< t< t-xv*t	7/zx 7/zx 7/z :nޞ :nޞ GL{pcLѹ{Lѱqr4|?l}< ؞ OMѹ{Lׇ,Y< قv4l\}x 7/zx 3G؞ :fޞ :fޞ #Lѹ{Mѹ{Mѹ{Mѹ{<>tn^:e+W &fg< Ǥ]Y?zd&mpOR@&ثzAiwYgzAJoH02'.:ܻt?G;t뎮>n\bøNn::u[w -:}WpqtNq[ ½2Ӄe<H$r9Do(r9DQmQrpOzsx 6 1F0DٜmX۴߻ 	DlLك7T1ȷd	&͠'|5LN\xwmf<f)`13s`'k<"ef'c("z&3.P6fN,@01 Y2q8ePL"̀OX, oT	6-pfx#b:A6Dl,mP1b|"&2ā`Ր,<@&pr0@qd@Dg ,LS̂0ff 6uA N-,,Ø	18 f ,p2Ř`0ddqfS`,ŖM'le6et1Y	,͜.@H1-rf316n0&#N:	Ɍeň	dc/S1F831Z6c&͎; 0"&Ŕ-# 6D[dfXe N 	 ͠F^"0D81Ÿ 20ȍ r<#LF<[N0e3,	ADNN"c&g*8{q1ͬ m@,&00[	nlq  ",ŋ8Iǖ,2`9n@L,"3=<@mc/0MN2lٙ3l ô	Ә	0e 		l1ȋ0m00'`'.63:Px N(pF`"gN "[0"rLܠ^@6H&3U0O&q[8"X1lbqfXˈf|`"Τ3@Xlɉ Y	11[`#,nra#Šb1	mŇ'MmpN:Fs{ Un<}PF< 0 gas'	2m=3ac@1YSr	1PDDYfn&-6Y5[h'`L\끋@'0 $ 0,3FP2 #,# }x7 #g>@ML[`q}`O(2#cu@&&qemDAgc˰dskdq䳪@1d͖dߴ(ؐcv9 v xZ{8`#(''xv O(&qdF@2Om0#'dd?Whm2@h&scs2s 4}
=` NL]2<y32e1 e@F#(&qF LN, ʜ_lƬyvX&<l6-L ɷ`N@Dk S9A z}chn쁃A4b|Vٷ9-ϗ"X72(1 De@; 	iqG@hc "M8끗w# dL[fMDdŎ@DeZ	Yv GRݼXegA9@{`qPM81(&1A <link rel="import" href="chrome://resources/html/load_time_data.html">

<script src="chrome://history/strings.js"></script>
     }rH໿G6gw%f=Xlwc"Id}ۯ/̺ u@I3DYYYYYYzoMQѫplGI1sϏוz{oM8:>릝;n:MVMU޴NQozusVs/P~{=n+jxGg}<.>=JWz9OOyUԻö:VN[z,Rr
?ϯ[+¢xW?ݿQB^6,oZWuyC*C0d΁1oQ{$ߏ,7MϷjquϔ0}|XɿZٿZѿZ?ծvMS[(w|}m]Oe]޾|^nn,3h˪s@ŶjЎ틳P73gTgźwS_7E>Ŋ:iYɧ7}=zn%<ji)ٖ/u^^"W(WDnSynsp(:w ?'7yĄf6{f*v&VIh$$*IvĶ*bk`)_EZEW\n^"+phC=""C[N(~<RLzB{=p=\	C&U۫dPjR{5jj/'J~y&MUIM;ej>f֚:!5;WTTw!S ʝ֊ҁt[mG(PMb RЍ4WUUV;늇JxcJ[`2ǭgw[AV8_zB{=p=Bλ_zb{=p=pXlJtR:py<^eU=3&BEYy_"78>b0#GQ&	.q`ezEdAfz _}噱y bM SGM 
{ >)bQEF$yψ̖30"l T+/		4f ,*	 Te/3P@~F *,he::yF^ff(4Bh~n`dVJSlAi|躩[T, T<
mPeF-, ]z*߬
<PK*$*(F.svea͋u}sV94iUuD^UlFi/"Cpe(ՀEE9Gۚ1/g "J|Q0֍GAgCpT58HsoG
)2̲jr:-r0 ms\ә;\L]*ՅA)XY[@~,)ڮHF-**D"ʗWA"P L+~V,&&8LʕeMXƹ*Z!f(a|t[E "U"8N6$
rÈO"YF *_ʲʌ_m *[?Nb] WFi\dVfʪ(reEH6A$oqTu!g g~0*hUt 7r
!p<h ,a`.{2r i 	4ziWDpuXk=pu+_{*%J3*0iUe,70=H4cyk220{yQle`/1e[Q0d!/co;+=hҽ6%Z,%L%'hdH%-R3"1p&L$hTFI4Oq1m*e
̜*5ER∭bYJi`0EEf\&K3D3W[(l^d*09`UZ_˸
,tp{J
Kct+/, ]M[dqh)UKYc*Ǧq{^qEl^ >ٲ|.aseCpl-V`{VqVCplv&0(1)jy0xb䘶j元0hAgv|fZVk=ZFYF 4U~ljBQE0P(`d+e, TjQȁ#盉+r`Mi`Y "%$X*u[NЇfAKHA|h1f\UqF-_*UYf⹸xF.jg˂+ƺnl[{5ɑt0U21H;-7v{[4Cpj+/\eGSޚ"'8R3jgdJ+PYF6,K"kE]{M:Atz-̆xF(O䙍Z
<[ELˬA2!Alh}+H'ҷ2u05 m*|Y-*"з;D?v[g&^>lQL`)D'%¥LQ/2A`;؞*LAuJ2os:a@°ٞjY6G>Ýq} 0O?;3C0ϳ<2C02$RڤLP>Ǒ	ID!̵vW*TfWA-9<3g
Kz7@ٹ,癙FMb1ف?F   ?Uy[i*C1MUۡNGbӨl-jd^ZfK;#J?VCl/տ=L4Z١0,?9á˼-77C^l7A26_nR~2T[>݊`q:4:mt:B2PLEe.Uqisz_=zl~T:{ߡg#@</~ U<%Kf	9LZ moEwYʄ|TWIm[jm;pX`!w`~$ċ\Gd##+1:lϗ!4H[PYwP!T3}6AC{刞t9OrϦ'
~5ժڵpV1uk+hJρaƎQ6\w8^w8"cU6D&ecEgo|lj.I\OxNZˌN[8ŋ\G'px0ox9/hOn@*\4?p>ݢͅc4}Pj,UZM.◫8ͱzU&ǠKrYrsq`[aܙ3s''9q1G?F[Uul&ߊ_3ΝmUզږ6_V۩`$?!٨`evC%\Oh9yzr$
cxnxI"| ϽD>nO ?	ʭ 8I0_uю?Aж*G61zݯLd;ыyQPtF wϦPeHMMG%8oa2]_sa/,"BfIHWI?勱91U8o,q8z?V#شg+gz>*a [Vz{t7܏9	|fs30X(0k:L=-xW,AB)+0llS1c)F[`y64
yx" 7~qAw]G:Uaыu;Ֆ8HoWu&aG5kl_=!ڗ%v	BiU=rIVSEїW^Au?ʢnC6(S~>.iK{Er]ϦW{Jw@كJ͉!t-7sNO0D\݂$bhY7{ iM{Pd>iEouo`l2Dl.j)#!/dn5Y y ލ~R)_ t,+`ױdm`LBὙ(-Ǻ7"~0D¤Bc^7# @8LZuleᐁue?_>y!؅+{ohyCdikPW*%Z@Gv=DuC>
kY*bȪ3yN̜RSmI3ICmxv6.k_w vP2?֭n\23 ?oyql}W)k]k/#[ə5Hp|g}GoJ*5af S1$j7a0c5Y[kC?.uP:&5n#~'ŝ&%wN 7@ڙؿ}ϻmׅӄ[PO{jNF ۑdE}z_^̕;ISAcK˗v</y_8#^r&cBSM2wa%<?HӞpg?\?a\;K^Ғ6h'vVv\NFtz'(PK[!呛Ta_xzjAb(/eN_ fGL~͔F{߭)%Wk0]^VZ(5]u+i2"xDa]CSPGEԭvM5͖بХgS\'rxD}`q_ދLRP7DR\֔T	×^[U^mt;d$  yBAfݚ/0U		a݇HfywbYz5$e;.醊80CpȾiԽrp<\ld/ZFLqcvA3h.FKd֨:<v(9h CqOVR%ta5YקD!p^GĞK@o⦏0	)eU|_^ލVa{Rtk\4}oZ(2R.kv~2cK)IG~lŞlsSdrfoQ2,rSnčHh:bΜS5XXIMkpݠ-{j	[z\)+
٘I4JL'^i8fv	&01M!]TyI~Hp`4'vA,X$g挌=w>.ǽ!p)'ڧvbCdK{:"V>=_AyX4`yɾv&=-hI{	k'-EhE/y0! 7c'!fa"V	9鏆A!%MOg< NGYdbQ̞9/#Gb`cL@Mu#vEwSƦt
)8Ish5= Ebޝ%/+u}b5$	ي7WgN!.4ALC\,»O0ܛaWeC3N񝄺>
忒ݝ4ATBIYuWx{VQ,0dlzxT{!b}>=߅!"Uރ%b:,7=,ރ]Tgb̻;TZF8xޝH}}yA|!J]Bm =q8Ib7#w݃eaؽe.Դ_g(G`/w'o؅N*»O˦>W8p?b'^/IAx7(-#LxAlrw׸Ѷk֫Ճ0}mޝXҮsm76b{]KNoH$|=(-k")ONѧ҆=@)'I|RҶ2_KGIH5M{ =ݬ]mavm&l2"z^K{ɶ'𬂰c#(]`E~}5֥_RiX*S*zꆣ\,0Db!:
 ;(4|ov?0-pqXW!!ZNh\y۪4;,	^¦=
z8vc8dpzlNuh%I5"i(B[<\j<FK9TJ%p1
qf5W4GS"prB]P	dW:oEyGظ1w҃w;a"%6X۝gT	#V݀=΅Ӏrs&Spfޓ4> ;77'uCR`)t8NBQLy!Դ{ n]rFc{781aEԀZON(e/.(sPٔx&"*&'2{Lqwȱ|	еE'۰@2eCV_B_%|zC%?B O8D;K5ܒ6a1<sN0	KbGWЈC#fP19hw@+h1L];C@Ryz}lyakusV*2mel$˵oL22Fpf/?Cέ% 
i?3~ıt#I&!MY|bkj2:$!S@3C!YX?61$Q[a(+!YZ:aa=L2 ŕT1xD$daJtj!A=xNIQ\.ᔋz<\,w>Vvrs9p@9A0eܴi$7eF`'{J>y%!VǺE1yE,K}hDNI7$:)vU\C4s-P`[B^)v}67_X.=uu)zLLvvvUW*	plLA7[y}ԷȊG1)8	{@uW4rpޮ_ݎ<i#5Eam';Y.U&/f2kb4ޝg+oe-6<\?W^%7NY9ptڦ0ouq̏-h1[y69\!͕wd<s8Opx˗FUȸ	7{@9ΛO7?ς$M`H'_yt_37):^Λ&y&)I>)I~/h#q~@
KoD~	)SbR9bWL	n+Ś/xB+6MCփPϟh'h8 fX5{gͦ]G/	<r">L`,OҺ?/>ܷZm0ƮuFBe(;O .6MW/>9-MΜY(Ln2sARo:8*N4C'/	s>g/TF>̓v؝{Ff7.+yTw<tFl wn:O$ZRx	IwiJRG>΃Ic!{M4RcHt] Wa>z?s>* ? W7$D-D&95}YU^QR`&Yo`<JnA\]@nc ?n!O"ٸm۝x"<;3aHZ"Mk5
\nJnyx͔ʊu%$hDe/+CI)PC MCb`MF6&$퀺">"ԃxl<
0Cѳp&E䱃Ï9O?g O1<3}S?=4@$@A
S,urxh$qſ]-z7ugZxg:LA &`Gn!~FLT2^U*X~d7yn4uFis
DN~F	a{oQsdǏ;2i{()D!M&`CT- QH>AO?h
l\ m1X#7ksZk~g-KVg[6<*`'鈄>A3^EX1WxhLS1p.-@>C 2z\yCf b.mF_GK:T7<{ ɣ9z Zsٓ;l# -@e8KQ~PbPfL?m& b)hqX[cF,t׃bSy܊,|~)sOTӚiz?8^':qCb5Zށ &`Ē/#mxx0<d9-#w	8Zx  /B!::aK`CrAVD|I𘎕C&a輆f e#2Z KN7r;E={(&cĒ3tzF\6:~U!!#1l|(X%~: ?Eh, B|XA YuvG[Q.Z	6r:3a_?LY)00L~8Dն.hJz	=MGI¯)<9+h`T/?-C30..-*uL.jnS(M#[}SSbĥ.@ ^MB؞$؏aBK	18kƿoU"P`|AByGAV/U20 `;*Z(*v?3D5mES@KwwGux>]p5Xۍ]6h~[wDKAY Uj
!78|q[pn,HR45tЁ$h#4	p1{mn!80؅Бac4K1NZs_|8|ws3ݠGB$c0y nm]9<%sH2q>,t/܃KoC~98»Bt-U`1<^,ހkn8S_cW,"FoӘVo9/0WfsUMlRSU8%_ }dh&X;p@]q X0Ch4~0?XD`eKL͇dx`%*8pQfȊYd`Ec0E$.>$@gXO0`ȃ J%+';NMΰc<Fy\%,pppn:)JAXp4B#m=${)b@$&S(e	-!ܙ-2ڇ>6~%AXPDظ`˙YPԣ%3IX..-&L&K5W29GlsH\z! =Nko1WF@ADDx  )لL`<OǨn0M< bp^PsiIG1!lK|>w!GGe%)إ_qB8.`ZMזʃOƷYb+YOt%uqï]햖8!#",¿ wap"3nc,^)dŃ-0L<qr%"` "z ɜHc@H۽h|-0]o>};;d[U]@Fg [r^H3FzD=7hKGpH0!_|n-s`nMYa'1#%?d*4>H0OačSf^Pޥ!kvlGcaP(rh/%:F	=$;-ODW ky;$Tݏ ,Tn.q;aL$HvR`]75"'EK㢦jȘ+s
KmuJkri9{]wl ^?CrLV%YgVr=&e̐g72o7x7h76	m0Q`&$=LbI{0f,l0'0ܳBo֠ɱ8Y?_*Glվ4W /S3rb5.=_Z唶`j!5REYoh40TQ?z])dM)a&eD+2˕QTbcmM	TS;5^XEǴ1j)3&d!a}.k[J9ʰ]
.՞KJo:W%{ #Q:נR6wzi] ݬLB1@Jf'L68ڿ/86BBߛ%-BQEAA@,&D)18@7ْ%j=bi:!~Vv9p_Mc ?zߘgggv+,\o:8$"XGAҋ0ΙĻݤE%DalwAqFfKb@:=T@TH93
E%`ׁ47e1+LxgaB5JKODe')A^A)-`$(H@uB[[$ƺσX\cL/G$O®3K85u>dyyCF]"-m+%~6;Xc8YJz'0_#x$HTH =ۛZ֍i~k`҃]5DxK]R>F,xpcA'ėݭ3nILtFK+^tGzJIaWͲr$hfcWNsHӢs\>_VtqeUG٘bs"rFs+<c1vs`XIs|lD
X,389}xB]v1Cmƚ,ߴ
g,9OeV7Tg̙B)eJ%ak氜ZmUOwچ_zv1eNyz4V'.Ape}a)pp/K!T=>^>_UIuNrOlV}~{{?Wn vЫrO3{!*\z\~ل2S6_	sӶ|p> QboYv-M&$O.;Ik.:=`#R*/)!G1DWO۷;Wq5Ԃϟ
M=	"@E"TyvNG!
cPo?Y2Vu6CuLswL)#5w7D. G t۟BkZٵPAP}3gOS1Ѿlk-~m-
Osk\HFQ*I[veYrxn6+U/|,>c.!Q*mII5{

@R~he&c61D_dUIzs~zu`TOi3=pHVy9$!F'C]US ^@3bK$?+*ߑDԄPC_7v擞yg'ho45?PsС0&J>Ȫ]]Nk&U-Wv3zW|]\$'%95#nB.a	[r1LWX3WnɷX-]C?w	ƨ-$W{=od>J՟(&c~9V+hj#k#tpڧȗe*jRw(n@}H	"ڪaaҊb1_I8_7DA<I/8W|KNg||ؚ LzڗcqnJn&07T; S^F2L)XiDL.ދ&D|42~3zyI7{E.
7銱oKJ?^5yBӃ8=ڋz`n_IsR1dW}44$kP6GKgl+[o۾4^&Tp)ճ1̑fx7r眈~ɯQ_ޜ3A!2jДf7@J=>DmY4?EXyIrO_;Lb~'o0[bԟz@.h㈦_΅9LR-	@_&	hkj.U)>AXnT/#^,v'Lu0~tF,h93vF[ru~]5
;V&^)%	K]KD9bG<3Nĳty?,ӵzb=g&N;]bAㇾ`tþIurmKFى8Hvcetƛ'Z`wd*;CĴ9͙Mt)M;_Z3َ)\l %	r]CC-9XLnP"qb?SMod ϛKPϻ=P0˺;Hu\WMEm{"뾩k<aBéhFt`zytmJ
 BAN*FCYUnЮ9\ᑤ=a&)YaBx)_*g&Hth?y`l"Jܐ^A\Yg5FNv,7(TB=K\⏮[64G*+pKe '2kNβgf5K]l2otb="3*@4z ?Koin+~Ѧm<՜gOGOވ^yC`/;.L_p+a:0Q"NofS*n^a<cr&c`Ǯ8FQwpѓ쁛nT	 i{CVflYld ->is	*F=-bcawqzY:+S_GZWq)hX_GGp`[|+a0xQ[|˒Ctlx´SW/=6fsz߃EK̮$;2A"3b[!QnnWMZ_kڻW(ȓ0j.dcHMZ̏ih*@oGQ0X7%9׷120'aq;ZC84"l;:	wd}EԬ4O.rA	=CP`{`"`zf&,OpM<ڐ;'/B˚rtq'U^VqЇ'OC>l^jtߌX?mF3a:;:ܱ7GdING3ÝM{uG(,#ԈH&b&~"'z"vbIi<Ӆ/^~(+?36#Ԓ܆HW0z6sRii8LWjlC܋TxM61jiʽ0=l<KzI|<ac= ^6WGF2=)_h]\T;sGaX1:{ЌQ=`K'%<>ZNEek"BϜHZδƲv+7`D@OH=&.໻JtcKoѶAmQuVD؎MĢIRECcUxE3y5	s20P7	ԌRf'qk:\+LMkQ:UW]⃠bF,EFebLp: 85[F}(-Nqj;;ۢ߿,-}>A.~>wJR./1H0譬!EϱS̒S6OWZ"xuzv7,]m*֟N3C|J _"6ℍaw%yǏ]k&-9NsB)C-Y텔>Gw#ыd0O-Dys z| v8*Qhh2u)7=rJUw4Me8#+Ŵiffiel{j>(?.~[,#%qM@۪o&oF(fnHy
ir[ vn|1>ƽPH޺]$'̟7FL,$zGI9y]kt
hYQٸ-,缙I4C~Mf<+{N( EM,bEi缒SiOdJrvkS3ZIH2(="Ly<s[?bE9$MK@6l	b9<﹡cQjFdB43*HlYl91O)7'=M5TJDoט@IT/]Mş=Yvg!}q)P?LP_>u鉄 z5y#4kD*zY@3C54'A/ΎunX۞?<漯MDA UkcaJ(@b;j&oBi"b$D9ccs8h'^m[)t=02r>EaS$7jɗ0ʛ
o".L1 JÔ8ё\+j d03PN94po/<18B&˲kM)R7}LV4BkzH>foOɑkr5$f]'OCRҰnff̰k8-N%¿btst`IO#<yg<c$# ./\@d^dAez1Uݬ̦p"m`Uj?{?+[MB_L=KlyoU,.>@nA(zY. ߿hTq8gjRq`n.pƞ7iamp̚tGZiccwL"ċe~mM[鿔v7Os2gbqɛ3O#^=0774bEsܒ[)$ eiEnx3%rv\BR#L%Xq'VCiLbBt5V4`Ryό	g_fjRR|קE"StffǷDC. 29wZ̐I)x&%nB^ePjl-9hh}{*$yC
ILS̥{>U|WX䞠:r2@4t`p1ƣ;9GS\w#
Ln<HqtUA$ձ'l,$#L!ɰTjn!%&o<S܇O3

αXW-AUMcjSo- BaDtVNnİąʡu7$.o,9M#'ϽyXwke:q8}Xo|ǟ37xX·n?vu.#o靯VRiVK#kX9ey²w}yECnJLиe O&X5xk{K'OcyJS,L>úBf\ƭV]0YOD$(DYG/f	/]rSfADeawiz =U&FW|q!%$YeaP/K1ȱÈ0HEXf~^PG{Ii3)6,2Rn"}GYn4'ϸttFWrشOXu$Qbj6Ї8fԩ3F]|ÜXM4sm]u˥޲b"*$ru<
b'yU/^<ʑ]>^>CzECεcAaY>$A.˰$ht%j~[n n݄uJ}ۧo<Vza@xИ)ga[N!b.@>zy:oZtC+U	M#g01Eo1FϚlak-ӬڭwPh}x<u]PzKӦ^z0>z*mx?ʿ=w{<TlVφqIm:.8?{B̟0-~ypMV$?էCo_*GsRlCA>Wo+?@qe/qgXPn5.aV*҄#֬3+J\FT$3؆$7G1rtFqJuaPᄞgUwwElH׺Һkh]Z~-#5!;lJZ.HlJjJ\:V:(lbۃl,l3Q6vVlt6۸\+K~@(.U* P#b	`dy}]Zn8b,v $54L+ԋɚb{D{@]1~]mQ(~(TY7(=P}]ITsvM:wp͟Ƶ)0SfL.l(.zζ8º־+2ZO!5Bw܄SUPd0!ԋzX+Kl	'[i9¯ly5'ʇД,K9s^װ!\kL!Qe54𝬑ZF$#uIMw+\ӸOPgg)7NiGJL̉OzݭzP\:d:TnnfBVں>Y2d4^c&˦.rssX:~XxIm0Ӌk㍙d [1Ip -R/|D'߅7Ac1H,R9u0͈azç'DF΅'U9~@ÄCO&9fFBţEӠ<̨POt=s	(/SL;2]?t+g0#>#c܍<*W%8D~q6'GMu*lGk !Fa)id9;3*'w
g<
aQol~.ޝtr?ikoEU/[;"DBT)]aV;^O	w[5He^nq=Cl);xL
#N4eS51eDO\kYvW]OͨBdTH7Q?ǗRT ڣGZтIdG?WfUg]Е.)uY'Y=NK"͟򏿲rRkCɶޣ[iD~8|D{g0*0i89fUBKyвO"X 1Ao'$e8hPc6i|&fA~ߒDHTyW <K:=.̰N%ľ
3W0`n%1!P @tkG%$P(>o.Ā \gJɰppa8+9  &f}P?TIwSբqNz(<ǀ<G⍱D0з4}Z}'4wO}L~+&2֪PDрIMїR}O4F8nU*&E,]T<EqLc^vJ|v $vDjŜ?'R<cSc*)%_mOL+#(`lHN|{,}cM:_ABWOwq ?e=1p@XPU6jлNDpmIzWFC}Z[9:[-}$07oV<tuUM!hg?#6+ DR_ެ?{x!#c&LGH4<7SN[V73/opəNxUZ74A
=7ü-<b%CNJkl[p:4)@)
	"b] X=ǰ[bh(nqS#4XXcIF|}Fr%^#CGblGz4̄Jޒ-|:^?
{oz      }rH໿#OG;@3sܱ9>ލu8  &	-w3mnd3*T Jri%ʺd߹?n7EoGmZ'	<?v~^W_j6ߪviu|4U[57U9z:E]V.uYVu[4G@xV᭓xx@+_m|S?}ë?OGHVQX9mutꕓSH)?ZlǓ+Ei).`׺sRr!s|֏%~|e9n}u~+U~_~O)))vnzuܺ@QknKT?*/_>J,rs7eY_A\V*UO_>nvl_mv99Z8+MFМ))V$H/g%{yqK#yNpNՙS-4d-_뼬?D$ίPu ݦ*]jyQt9 }왩\(*	=`MZI8XI,*IvĶ*bk`)_EZEU/^WD!WІzdDB(~<RLzB{=p=B.IՄ!V٪>Ta5^̀xKɰ _I*IQ_af))IɇٙxxP$VT4 j?J-@FaZnjUoMEfhl\FnppX]^W<TW<VWՅ[7PW:Tpߺ#UY=n=vcJ¡	zUv.~D*ItyZU˪zfxMLZ-Enzq}a=3Gꏢ0LL?\=2V>#$Ȃ~A/S3(3c8 "0 X/LEU=#2[.K7P9$XF &"F$4PQLDR>BK# f^Q4̫*.Ph&"$%z̏4╦ZuS%aY@dy6ڠ|♍ZYA, TYDyn|I*, TI/6,TQG\&
:
ly&}sV94iUuPD^UlFi/"Cpe(ՀEE9Gۚ1/g "J|Q0֍GAgCpT58HsoG
)2̲jr:-r0 ms\ә;\L]*ՅA)XY[@~,)ڮHF-**D"ʗWA"P L+~V,&&8LʕeMXƹ*Z!L͖Q!x1Z^鶊 09{EnEq-c] mH?E
 T~e僿H$ T~ĺ *Y7p0ȬUQ6ʊ`.l)H2,W!AqC@1 F	2Z`TѪW o2Bix/V XK]dYe,M ?N0^i02(<oñzVL?UKgTU`xӪʌiCYzo`zIied`0W!le`/1e[Q0d!/z *
+=hҽ6%Z,%L%'hdH%-R3"1p&L$hTFI4Oq1m*e
̜BHtǚD")qVeIƏJ
4Dr0""3s.%P-
6
s/|*-e\:X%1\Wa4pYZFjI+R쬨J}>-ñy\y<GWeCpE2@,(K؜fFdU8^q-	CpLCbZxlX<(9-iZy  k3~jЙ_Yqn孢"4Ň z-MDiPe. T
3f"jK# ZAd`+rf"puE`=3k	8I5VBV.Sy	A@!bi	9-׌*Ξ٨+B*L_<`Zȥ2^-,aYtX'V^AζګIF&ðV |\ؙS No,0CpIM!xk\ߟ2KL̫esBp~"+*BWγ2lXK"kE=K|&_UBaaa\oX@8Eٰp/Өi<QKAgyVC;H6;ȂMo.}+cedYťiUUEjQץ{r/
}C_Cp"=35`3؎bCpL!=).er1(LWaO(ɢʼA@養9d{ePtfwS<\<"{?tH!h21rB|G:&$eT`{,0S3]`:P!^ifʷ)D2,1 F v# eğgf
?F 61f>+1,J::vV8nŪ4[VElb;^3Mzi-Pl0J*XA8W:(0hebO .lJy9^8ܗ`|JPmU{t+Qסz0YF#q uԥ}\uޗG?e?U:=3ۃd kbqj?*R%YB:@`!AC<K𞯞
<!uS]6,̏ĒxxuDCu$qe<F2i!!AL5gCPx:LZ+X);d:p gqx6=7(^S]Kg5}>AS){Y9Pwt= ʆ=xZd&XtlT"u[#[mizM$ u'vI<D)'ve-EudxxJ^BHp7ttȊbjg'7 j.OGusM\bRJ)e^r`Gq9Vz`ն1hҽ\֟\\\8|`8w	w<!q~̑>58zU]8ɷrWu.sgg[r{U7;w͗v*38d] >iP	G?ZN}I1<X7$>o^"C7G'W}k[_aVV{$|`nܯ:hǟh[rSOpkE3S4g0{6NtbhD Q+ݳ=7w$wOzO覣0ծJoNUL!$iI?勱v91U8o,q8z?V#شg+guz>*` [Vz{t7܏9	|fs30QX(0k<ëuE !"8+m*a,կuc@}~b5B^8E-59p\1 F]NgXsbh@]{1 7UG0joa0TfMPk'TRc®12ApeuUOZGTiUiWiݏHl`6^e=+ƼK ^îaCg8ٴjA7{P#97$pN'n_wr}A$jO\$QTuJ ʙVܴm~EVZfN{VG,xc!rsFVMY	| vsh7	ȃ޾v1jMLUJBodXEvf=ޛrqs![SAL}i,w3R	C ѩQVePP5^ڎ]hϾ2h7M։u5eYnHn\v2Y@Lct@3EFb#&#tmBFe@A|bgh%ch˥9 n(1#f ago&ߋJY?Z{dbHĝ6t?̮@k`:<;zs~?Rf_M=%3OvCТ)0ښ\t_쀲EW'f# B$Ћ&wN7@g3=y	wuy۶3	홓`q=+Ըً9  ce@amQ*8i!g!|*{l}ҹh|rOˌ|TtLEM*]%<?ؒ)aO;&53a1%C%-ia4#/?	Y/gleUn*n}pꌡJ@̠Z+;hQ_J&WwwyZijaҫ-#Dn#uQ9A]>"r*j&-WV ϻ'ڱS\(sxB@0+E&v)7$DJ\֔T	W^[U^fmt;d n yBAfݚ/0řyyaݿHfj{wf,S4vN7Tч]]UvO3cSѺO+АeT7i46bLfnónʰ`z(.Jd.h&ktSWv8Z7(ؓL5	P,&!tKB58o{,~OWjn˳~#<-oMEf_euϝPfl^AR㑟@iynjJ-JeSX}n^%J#9Z՝ٴaUڊ+VKG͍6B署nhi?)H4Y1K|u(hftJj"z˪p!?I\lcQPѡ>ȝb!zÿ>Y/9#cyyTD;!lmѥ=yj+kag/ :,d?]^aSFVo%OOl2hNmuϙ7͋清i8#_6G7>яx"0ӬsèOYeG6jĔ?uR?nΣ{:JoXe#vYN83{֜1;5ajC_F(Wc<56xC9[lg|jiZ?VӽM^ԓwz˼i9A.Gv(>1 Klۛ@uQzPvQ_a!cN]h#02!hNBVys_INn}BIYeZx{VQ,0dvlzxT{!b}>߅!"Uރ%b:,7,ރ]Tgb̻;ލ*p;%8C >C	>w%:'ߌtޅ"v1_a"cƻPVfu!:LTލ)b"Z̺;q2}^6?ｲ}Յ_a0Q|"mDwB?8<4wͦ,7[<w|m/)MnZ=.f݉51G]cuS~-;^&mu;7
/wtnCH:ej@X,D'/%F7;w䢧md$Z`isu^:M?N-0<]]BdxAzi/َr6xȦȯF|ӺkU2{=.,V#T񂳋Ai1gF*I`]Pń:I՝rT%T{K@R\϶w| \(詾EЇFٴߞSÉv!O;z'gBDk& (!Pvcy|P	y~P)[(hƙ0^`YAhDP	dW:oey߂ظ1xӣvD),m[W
|An@>Υrs&{Շ߼'
>| onNReBpwUɝz1Keu)* ߺ5#8w?npZcXɆU;IXmӸWͦ#,2A Il39#.3|	.ӵE'2
>g~ˆ!Jÿ9gJ>|~86Ň$)B ^>Vǉ@'ꊘDٱs`fi<?1<l'Cq#kP19w@+`̳H_;C@Rgyz}lyaM
kus*mj$ћQ9(_$χLғ,LI"9%Ձnʊ=^S+"+4̌ ]6+E*rPĐ
C)^	Ɇq \e3*#XCQ\xSI?HbKV URSKNcz
HBOs	\ YbI%[j]#Ϲ6%*,d6de)~ՓRAڛ?F)y+5&ԵNT{wFpLÊSik=
Pň.Ueߜ%㑠UF =)WWNd89O9FIXBUm_M`"uN$C0[Z Y5kY!ΐI)ܥ6KDӘoK:y~t;NfƎtC UYcDJ4_3x%G#d.N؞r4	S`fn6<]7KTzŽ'<;ea)i8[%ݗe~kqGʳQhQ^|mo}#cX|"[RZ1"C)4$5Nxcp:os?u<4Q|ł~ߤpOGx_|O7M "*M3R}R^,G~&/,߈?H	)SbR9bWL	n+Ś/xB+6sCփPϟ7$P!h8 fX5{gͦ]FG<r">L`,OҺ?/>ܵZm0+ƮuFBe(;O.6MW/>9-MΜY(Jn2sARo:8*N4C'/	s>g/TF>̓C؝{F&7.+yw<tFl wn:O$ZRx	IwiJRG>΃Ic!{M4RcHt] Wa>z?s>* ? W7$D-D&95}z9`?\Mv7y߸:yxD@nc ?n!O"m۝x"<Cm	w
f>îpDjvk""2"𶙛R++֕W}@}'D_C7	!^i؏7WؘꊐPͶ+%3)"~ħy> >ygاy0LOV@И m?Q:+N\|E5k:>t]P`םhI:P^0XwKL5
^g
`\,P@HHv{wnfAI_]Amzm^(3i?!5=p}-
7 ` IMlA($4hi@l|6Mujr9:}DAT`XphYK?8䟃_Z>lYcuEoÑ#l0>AA
f|z(D1J1]Ĉ%hرsg-4qlT`C?P+wW>:$>l f)auT#@Apγ  <Z`/0qu7=y6ܠB<Xû x=sJ]6$5C,߰"-NzwAzqG8U"o\i4	feuܾ?8^':qCb5Zށ &`Ē/#mxx0<d9wv	8Zx  /B!::aK`CrAVD|I𘎕C`輆f e#2Z KN7r;E={(&cĒ3tzF\6:~U!!#1l|(X%~: ?Eh, B|XA YuvG[QZ	6r˰ǯ},}yk?j[6z	=MGI¯)<9+h`T/?-C30..-*uL.jnSG%K=]=Iم:!!cp֌&8D':*8w΃_.dsa`vUȾkSVpGP,8o
S(Nww{|5Dk|?;"m&0%(Sgw;߃A:t9BZoh8|qB,L8Mt`:=lbA)cbzf?6j@G7FD~BGGf01%PX-ρ/>VnS"
1< .A
9$O⸎zs:drA%·!}H]q!:*o/oC7rS~x@〩`l#iLķKh+u9MlRSU8%_ }dh&X;p@]q X0Ch4~0?XD`eKL͇dx%*8pQfȊYd`Ec0E$.>$@gXO0`ȃ J%+';NMΰc<Fy\%,pppn:)JAXp4B#m=${)b@$&S(te	-!ܙ-2 AI
 ,p("l\, bђ$,y&%+d͕L&9[ lH<a/.wK#  EW
W}\RL"yM@oޔlBM0YcT&g 18Slaٴ$$%>ɻn#`J#2	hgү8B!ntF0j-k`',1ŕ,'ْ8ׂ{vKetchx_0[8d`71J}/A
`yt`DCO\ElI E#;^*@2'-vw4zI.7>{^AN{ #3ڀyYK ֥\uL63Q0GER4+b2#tD*p_rpfSV0})HY%;+̓pq3s)n.07{;.8`QpcB;Χ}S=Țr8GtI~A1<X3ƟWaz	RS~+s
KmuJ%k^iX;{]wl ^?CrLٯJ*1PϬj?@{RM˘!%όoen^@o0Rol0a`&LlI:v0&`2̢Y`|Obg%(
%1ۗAcqڵ49+2T@ٮ}i ^A*fJ2Xk\zrSaY)m0)۝ӛyCj107"_hadGc@7DlHvSd|4&kRV*aRFVh"\uMu,b챭X=:j'㑢29Z˴r3wtJ0p;#)IH {D\-{zaui7`7GVDEaؽs]卸gT%.6(*U74*X_JIܕKE{=3W}ϻYD.c̔Nl3q{+lxݱ1h7KZ$nL!K@ US`tB"] IB"KxɒѷXa#nҴ!VXxoSeq0bOHLV@^u"qpJ0kO?*J/J8oS{$VsfJK|dfIdrͣ &>\nR1`r<K3!x My`q3^}PM/2_Aϲ \50I@B[D\$GoUù^sHʉ#,Agr&XND/Il,7AiWـ`7(`Ix'.;[|=^#Q!8no]_%RMs~k`B)@BÕ.h#EDJ<$Ӈ$&_8Cx#=OIfY׿@_\C}

;U'%R^?W +=82ƣlLSV99IbXn90,Ԥ\PY,RэѿrAjuy<{r"P[f K7mG3QmrQH`3{ZA)ޔ{ѲJVVkI7+ 7a970y>i~)$Te9>ݛnJcp'u`lRNJW|_;"Tg|zd[VͿHjsGl~bsjvP=3)ݐgg(?_{Gw˥&	Dp!|'{=ÙPHJWSo[C'{Toi7%yr)$y- v䃍K}ǪĦU`hBH^U?C;o^0>*5Ub0Lt' KS%3 B'Ǡ}w\A<g	XD_&&g S
Fj7D. G t۟BkZ)ZأAY}3]c}ZfGuw[*hs
W\HFs]ī6LH[uUY<₫9>mh1W>mYLI5{=%L1
mLcpu3Bt9vZ+f!U7hm^O{	4Pd@s6￯h&b&tp}3\Ԩ̃>;GASDk~@0fJs~Vr3MFZj]5b	.HO$^@sGA<"ӑ	P,z9\XZ3j>oɷX-]RJRz
eT ]LK\Pߟ(&c~9V+h*#k#tze6ȗ%Ӆ*jSRG6n. 	"ڪa饑e1_y9_Dq<0K%X|Kܱ5AKu/',fa}UDMDax@f7nr2eHSL.e~f">gziI{e/&<}+JOIL].-2:jSq{-s>SWIŌg\Ԓ*>bܮAYLQ@b\]:c^{˴>wРb4чK[|19""ߓ&" FG1|1:xFDuȨAS On*9}]U,7(lb'7svqc3MmlWZ@oRԻ rD8lΝk\YA;	ˣiDlsB'>R T7}/#*vsLu0~ArF.h9Esc4
9wvnױm=kw0v,L3GVX$D򩚡vwȬ`: =")sˍ;w2-K0teezpL8@9H.t9.trLw([x|>i%j-)1SW*vʽ%M3)^ٜtǉHm1%rv"ZX2~54ݒ_ꮃŔkڳ#o<b?SmoXPֽ{XO=P([$|:+g-Vu50lF0<6C%%  ͞[7hݜ^H{0[\ 2g£
)$dh4V<0P6V@XRܐ^A\YN9h5F,7(TB=+\⏮[64G)+qV	NfΝe?̤kaؠUބ!{E2gU~A቗h.K9^O>u[+BmCFP_?Fy&7>;'z%_|0g-9i?f3<fV2Clv7x~vk3ܐ/󑆻Ttsΰw,I>gM߿ǿdc{$n*'EdP0 MC`EFv
*EM}k~{'ٮe&{yqqa8+moE8iŋޒ0eXP3zR1cӳLZav	 oBHv仪+ѱnኂ<	fN?NA6dV&/t|ơ^Dw|Ə~l%UI#f'!o+<Nq_a6h5@kb.H{'J!3
&gfrzﲿ^n
wY}ToBQl0|").)?Eyrpm\e)UeG>8}x"4щ#š8͈Ø`8H!qܑ'pp	TNG3_&н25"I(II)gX;;C%s4=Ӆ/^}*?26#Ԓ܆HW0l<Ǥp
񩙮؆4O14Bmb 3]{gz7	:0xzAuņ6WGF2=`_h]\W;s Rcc\+I$,HΏ3p/x.6ށmXnIkיXss/ܕIIj4\|ww2\>9hC~,֝WvM<־3H#jПch죡Z$F^QgLy{\"L%Mj5T9YIܚ,-}g}Օ/us 耘QgܲkLf&8MwEqSz/ N}-;0~q׆%`K~wkrnBUs!jL=?U-\^bϑaJ^BcG?G	^-A-x _k `+˼ajSaɰJev=ZcWK&(u;_q}c?;kM6GXs;J'؈4~)\칣P2QQ[&ZHS
]q&ʛsn&;PñgDVDi!mSEV-4nm]2q[-53M33cSS7׸%.{>	ݠ|{y[)c6YH%U"ͯ`KV|a;9'c*5[WD>~>]c|Rp}T$7A֖q+Ǉsnr`O>Λ$rɌgeU	HeXll1uMS|NjhvlS$D(=RMy<y[?bE9$SKovS0h+}3R0ѠdPFab͹yQ5Vwsf;P)e~K_]c')S >{awX2+'$8{3yИ'3!I
ڗ^7r	NFd/Ax}}fcꒆD!ٱ0kJԜw(*]m,99	H,nL}++WfLb)=IB1\ki@;IGlo7Q##'QA[6k"/y^IyWACą)$X%yY/.u$K?tzjgf$i6&u:n2e`8ǎ5wdp'E LikM#*1n=ԬiJD?|k-.ߞ}Ըf]t,OCs335<3_AttJay͋#㷕<q!C)SsOMyéGBݲT.tnc$MN
ԛ`,n~Vl:}ؠ̓؉SzZMnFѓȢ|z3ǉ?SSvvs̭3Ik5O3=+B}t[F=!^\,+pu+m&(qSx1X۫z>9'(=+<;F&Cئy#(	4ʨZD"w[UCN[ϙo;g!u dxwbzӪ8ad,P+;S}'K{yόlh_Oˮ]*hRL@ȇVoY#\>Adbr!KfNY&nB^HA@(5xdT@N׮L}%J?;ސB
/sU-ɕ9)͟SC~U%U8M;'|5!rC9e[LZV8sNѝ#x5|A滮xNu5R>]hCy	CK9H&IC< [~qD[3OV쌂s,UtP0>PcjZgAuPDjNaKCnHFAݶ#I?r8ǇGO{,3>t.[	׮ǋڃ;up>*?_,	 ECܟg~Twsw]\`9|Au.#fo靯$+_#ְ>rʊeGsݔءqbAGMjm{Wd1Ҽ^S,LnúĽR^Y&n(_ϓ<%I;
C3Kφ42r,sy$2ֻ4>YQ$ݗ!%YzaP/K|ȱ 0EZ$gn1PvYQ;Ii3)6,2eSm"}-JUn4=(YCT\HVD0J,.'>4}pt09V14n]53uoS3b2*Ju<Nb	'yU/JuNe.C/U]!g۱}J_A#k깬.B˰޿;z{ǚ/M-򃸩v8o Z R>b'd[vAH[jvѫ .Jg_tFqk6a]`topY)MWkNkt->͢=;wK'4v]<hx~]WxވcmǳGDpx2yw-^OoϝoB(5ճ!43aʡ0)K+=Ώ/0yaC(\gCxO`P[MdKѼ[}՛m#xP^kE0<!V*TmCiMKh4ȧ5k̊*ra7c Qv ]_B8Qɂ0(qBϳwEڲlH׺Һkh]Z~-{ZGzC
lJZ.HlJjJ\:V:6Xg6ۣlóF6n㺯sݮ*/.\θ\Cp]5r=.PNNԘNe83!2a2ER\<M0^^NՔn%*JjKrw@psv=EVO9s|_w
՜s]SÝ5&\qm z\E~`?:_s]=g;a;lk{2ZO{zAjIh=1t_WX%aCC%+V)5`tN6H҆s_وjNOʇauEh9{k15f(@{fN [-#Q`R}x`p
(?0߄k4ԙv*\?:'δ3_^4svB@:W?0_ܠJ[w}Sb#уx>e[X.cn!f]VǏ13)Ğ3Y6ޘ8AezfqT=NJ .ɧy}C8ƘĢ~9e9Fq0o@ȹ*lpthWGc7l"P>_EGdFF;c0x'bWeRBrG;s%FfvuTqQGrӈxd_翂|'Q_Uz{t~<u1ܑ2zIS~9LZس.yΎ<9R%?>H_9_;ePK^_>Wvrv_TS)L$
̄ޟR99.[:j'Zq)a{)x5ᶐs۪mq}ĖĀQϔ$(\9	_)s\V>i[	{h
By|q`o@{H2Z0,$j 1uYf)=NK"͟򏿲rK֬m=G,3pG&=vd8AHZuҡkǑ+'Mäj.N])	~(|[<!a.p<f0ϩΏ4;-!@@bÔzEpFz\6'}$eΥ`B\ab( !P @kM%P(*\١B.P)Q((Ќ3aRC `rR!hDP	$hx/b-(*f_O$ޏy%lAco	}oi<W2Ә|?1Xk"Zc 1FJ1epCmZ9HKϢqoJi-M3Qf9n0}XBNVsxSJ6>Xc]Z}@.*򉉔^2
*KXX.5WJƮRݔ'Hˎʦ\:ohU[P#$V|Vvcw%ͪ:`p׫[O6;diFUS
+#/zƏꈍgfJ>HWvF7`G(zĘ	S)71Kuq{
f}WYtfST8)WP|N3dp{;La/1Jݪ'[2\DeaCc:!]P3"U%+2!8bEB:5cEGi0gX&cj/SJH*Bs^nmξ04{,p^Lh_[9o-Bx`gۏ3E|      ܽ}_ɱ0b=2$Ҏ57x\GΌd ~_{znhz{_ŭZyk,n&˛rq]U7`**/mo>Uyl-'U*(oqނϫK^q⾕^TiޚNF-EkZ9B,qk2pAr2ͻvb*hzbU]䲽aih4ڣ2h ں[і(բeQuںE6M5I](78To4ՠrF\cĊA4Ws6!ԭsZ2+PdC8γu>v	|M\14+Fv1U|=YDFyqMyLq]b@=@gmQڬX9Hw@QijzP8;azD8qzZ=壅ToSs}Xr!i
+m3]Ayn%/3+,J U	3gUb21#voQWE66`֚xT^I`ƫA*z4Y.3oѤf0|(DaJTA.q1|֟O&" SFe:*db?DK ^-h:E-")H 8bZϬ\T)VdюQ<f,PGFdp	{Dӝ泫f?SN'0y[6@r<(rX-HH(D%SSIje6ei9xRͳ&u6ۋٗU%0bI1M/lі5"̻2#!FRc8u5^.v'[X.r[OX=)l^9NwŻ6/3\JЄ#0>GdeZ::z7䄋"
j )_,ӌpXv$vjs0pZBj/ס	#-dD3Q|5&l)x};]YCZ
m_gUc,5E(D#gҜxCXۢ/r%IOuQb2«kJekQ6Ҷ|q	`Y_םEFpL=8;Rqr5~@3O!׮u&X6H	(+
iD=$VUI5G- 7p8sCBy6"dZDA`rF@Ei"Dn[pkXjo9BU "Sh]z9̧9KJt1:ي~Pz]ʃ*ߗum&[Ex, ,[fD\ՎI{P:T匠_ըEXVYuXXh(
Kך
f`1S~D_T[ Һ4@EavhGܠi&\^B1O;4QZH} |ŪԜǹċ	`Rqw\70??dcjM)
l>
E{fcNؕ}dΡ|ޞIuJJ;tW1BP&8[%
7یWvmGV4Y\kGbN2l[`5FHNS%a٦qx4R$Шd%e([Of^V3Vי@l#Ru
!ϨF^o

!Ԓl^f4ȱD0#E!c=>ѹ޾6XSlC7F-Pfn4!;Q]sJٴZnSb LB4j-㡾I?$,I@dτ%>Iշ?)uGO뾟J?x|}'A^&Φw
	,jE^-@T2pOXPl-HxJ[m<:[Vyw&坭EϨ7U3J,'u1O1^ՊB&QDv4B%B(aa8^ɖ%j`=.
ZgWB)WHE +9Ŕ>O^O4e&ԁY>e
Mšԑk)m>R^dWW@] [r|b{tX5u5qTQi*%ƤVi@Qn 	M0)Vf^eWF<n΀
Kg\hr,Ç+lVO`w8$l8L/("b:2_.4OyV-̈́+^rjV{KNo~)y;NeNf)3GryߪQqB9Te" hurC*K6_z*Bp9 
 a=QxEBzp4}=/Q@llgz!xQ|i\^Pt eQ\W[bilX9ztxѨN="bA̘yS6\N	KQ[-zӓ6uA!*폰 'f- :T;% wlQWǻ|ry%'	0g=^ȳ}QVi$nFdUdur
Zͪt<3)'j$E6Af5PAq]s3HORb^3d%^#s@~E,3mX߽_L	t*	*J񠱂*0ҫU/N'7y\p@S"a.ڀ*q}{N_2o{߉}7O~=i 	`@V:v+M1h"ŵsc;(8~F3S.Q6]D}5ZSfI>Qrշ"6:'wYJ,Ĉ?Cz˱_t8~2tg"SE	rޠ.ﳬ i]T?uVbޢC=^#!ټb C`s3-#ԡtHSqg8HτF /"7a{><?|~b#L~XCG=LO5ڎa;UhmA@,5b٭bكn]s:&qִ]/6{wJLP`g*C >!ԝ-"L^!jw9(Tc;Ǔ
ƞ7:#m8 B}ď숸[,?H=>a׏Vx^x}S@3Xj:m]EUi:GـtB;<e`U3"INܝğ]4bV w5 v2%.D"ñn4mH'-ʭµٜՖD"F	9Pj|Eֿ[kCFQ&i~Xv/B}:+wCٸɁp
Fn๓2f++KXÕ0Z(P3,אIޚ|MyUAvmH'S勞9)|:Eįض$kv E}K!TڣŐWڭ̖'♳6gP5iVɺnQZ񸟙]0Cא!EZWTqXb=6p`zt1zmHkiף6JR~HڢnoS-_M_?-
4o\u1³lh.z:%UtPO|{|YX`nFkևUzvbMɣy>SJ2iь<HAWEǣ=^F}RG<Pv5K){Gfr3i{|ܨ'x8wØҌo@ҜWyVɬ6hhǱ^#$Ǵ ^,BR89*;I6-:  MikcxZ(evo3-Yy}'ޟA͟F8PiLއY＋:v.OҕzTe=o?/ cs!*ξL2}ܗ2w>jV*w:MGԛZa]~{W575o%aFhoZ^A̮`-W_.0_V\[K/km=Eod}t<}F4M]Ҡjd5:
^XLo`f<L~4)Y&6!-ҮR(=
WE1ͳ;+	Gh6O.*!	;$e?L*U2@oiRCUQr"I$ݧѬW<b*8e4C҅o9Y@垀KDDv;ty $}/-&eHӨ<ڊ$m3l$h[:	cY![Lrmjta(C>VL>RCͤ?k8!y==B.so <Ɉ
ĳa1P) Y)gOc:ɓbJ{˓b&R"l^qòeffGYK&E# MQ*SͽA&WI}+kX-/IfYDCP2o	{r041;DlqIspL`\>zQIo9Eٚuu>}B/@,!T"0.Oq NTiXrWقSk6	\g4wm-cV%PʧcDD<g{e؏-bqR>[T~b &ƩlՖ뱶ru#dBkV-^iGOvv,ӌ10݂qK86gL0r:)d()A'tgZdcɻ=QlX]7+l~qyF;8>x~{.F~iT32æyI;I5RE"[qPҾڣ.?rZrgC#^Ě&uf9]Lvv٘ߎn2H )6Vu.Kex*goBw-{I	 +1^[QAie#3l#+$P06F5@KiT :` jΝQ	vKl@T[Ny앇`5Lp6kta M3O+(%;.	ad8#|-VLOu} hbȺXd{`|mqQEq`ttLsvb-w(rPJy'@l~ɥYsP֊&y? 칳͞%=.iT2Z#a7dQ_uCo=t8(.FN[k'R9xl]~J׭R'6
+iZb6Ļ˾:su4;,M
מ{:qɮ:MPO>r׎]Aq1ZT=-(
C~1Z$vw+!b(Sҷ`2Ogx~DǙډ9)l{,T-`xஇÊvI:=6,s/ZUj,
>u5i֎- \{Y`>-hE?Q:!;IƱr\1>a5T"	w<WۈBXJ#>`@i-Ԍc\,z=]I1x4kaʂPH !yJPHM\j`]M%;2n[{ΰTwA$mA2mJdޝX8W]ńM5ɀ;ܦH4u0dȅ"׶FT馰#;$7`EWt`@p`k7+"BQud䡝BUa3jlgi3hJM͞0l]ا([~rxG\;K4GA@!&a4xu;0>+݈+D:Ht\Yi`a3B6s(Xu}@e-hu1J4L;>ާP;Aut{p{=A:puF˕&_LC_{
7,EmHPTT|GɃ1I:<y͚<GU^EɅ:<Yo~9wO~(Gif'uCȏYZAfyuh>i
*QBuGܤJ:VjvـHKZ⌂hALdh	AD A⼍X"sU18pA095;c|ɲ95U݂Tm1W9G]L<wUuoG+ڒ=pRWS%'4X3RjG͡dϒ[N2Lxzm52vS*lʴRͰT($0%d9ͷ_5^= O
*>b.D́׮ aʥ e ITp#߂&KcDRRe|THhz)܆CGH6k yH):UV&GUCkH6xz
]9p>1*hPnx)s9^G Ɛ1lZ&QC C;xW.;>''r0G!m䉈@+ ]ۛ1&T<ʠw,35#b4ڎB^["}4}q^US>Dd
xwLg\\vعEg^rҦ*@
DC;hP.XotfѶC9[uqï@m0lD+5h$?=e+-UU~YN?1{̡pk3N:,EݩW0m`U:6I,D{21@brAln,n Œt
y̋d3<^	VA/uZC72>p>*kΫwZR2t(;6:lzTY%;uݫAʡ67WW4qk|KGѐ%)\ b|cF248)cs`z@gEW
=<7Ci>GxS3<z.+̫|уOY?ߐxL;G҇;` [9J^ڳoo~]7   
QE@~;F&+^!5bo@%xoCEeSqwnc8^ߟoSQ]e}-N;>>6nwV-'|?PEVƻypj<nFX٬ƀFfJf<MuVV<<C\0ѡ0Pfxs@kE7Y10yPm(nbcËQ7W!nsa8ZDԇ>ir5O#vt
frlj)>Pt@8uM$d&F)HB(Nv~7T!v/AW!,d9j	٧á Չ./vsS}'/4CLjg煀9S.-]v ~{QY ;z; 4>SE~dĿ(9Tx>a9sQa%!hKxd[@8n69~|MBSc$RE^Љ7aR$"{_	ij
FƆc:4+UNn1hK4[Fn!(BCʗ3|ڕmF;rav-	bׂ!ˑH(5f@=Ƨ0_h<
nl sg d?(9gڹ
2u &"{YYXY)Gqяˮ9B_M;mZij+lK~*V!^1zq~Z@8C\{:lT;}S0lT5kفVm"I.ͣ-
!9/Z?q#6vVEvftbp8H)Pô>SQkفv:#qPC`Homj[U'qVbتtGSK{somM=#3ןڝnd8*x@B!
ţ.ɦ=2HpȒv,k8gIOϡP'GBl_1-)c-`g}nX'6Z@C+kӭ>w+uIx[Kb'|N
J$,\,=v`\/vv;;w>?o]UgGp8O,hB)sߤJa|U]Kh!3xH!\}Hή8AN0y^{^%6VY.RQlj}1J Pn&o qXL]>]Χ@jp֩Ӵ"SB]zZJDԫ	J?~^#5soCBEY'6FYC߭T`J%-翔>R&&Z'/a't\]奥\;ķTӽD_tGNS΅dN(ekmSKAy	cv㒂u'Sw\\4a.)d?:IW4&ۻ}z~0g mNZo۬ѧÓw?B&e{*ާwÏorrnie=|/i>=x?ӷ0Mۃßޞ;|p|p:<{uSEO?0wb N>?H.'l6ķZU&0rRC 
`w`ɨ,Ns@ֱKY6}$W"{edg)vU?;=1]ǸSP2Rv`.&n_XɓZ\G| "T3 4h1P)G+pG[U
y8`u-FS݊OׇߦSa'.K|]DCzw+n7$X RwR=vZ=&42&O0
ރNgW}|K+_&baUUv^)Glrh_&-\OaIOMrrpi QBTe);	ӬMv;tyjS~ΎIQ5S	n>{*}L"f4p⶿ßeqk)=G܉@a̧@ȩTUw# i0 w>)*(jv>szX\Q.j'@vy3X}L\|jGV}1DT	o8(2ιqmɡ`vd!,%i@3Xg's ]"bNKd~'0CS0EW?NzPouf
w7Y\ޝ03j=>fƸ8F|!ǞSb^9hr1lXNǜjry3#1Ý:l'XQ&MߝJ|of!m	TjТ.[Y@pWkY';Q(BEl_^iWa`U[<
.-Uz |8-&R^1nl'~&8vh	#]ai$wM+Fj-qs;f\]JE]p;׺e<sFG	%)̪opn@.Ш40,5Zu$c1#㤶%nmhbul_'c~kψ;Tg|BSWY6X )@
}h~AGngUYۮ?nS>D3-:kqP	ɖV	F2?a"kyp<:SW fxKhWiuݞ}[8ԳE1]v}a]e.OJ</Mr1S{T !Q솼>8mL }tpZ\aI&q)1PA+]dIDQYΥTejXϜp0TvQe]Idi/Aѿ.ߖT
O]wA]AIZ  ǧ!~]-37ef`>+'Kۿe/U2_VhuRۛ0^K{wg%kp| xbO H4X9T+xPbqOP˪#y>(=:M=OE2бg?Y\'/3Qe;JQQJH]jA6#YSf&4id-	)KKk`DzzJmŽ,7Uw].r_I2	܉8Pc!QP0	V\LDyNQD}O(q:^/Sg??\r~ٶSjK42X, Vї:ձhbDlc0k;':#rJ*:;OQ|Q>(.G؉<(YigbaNErS|VinbCa]{^c:)BnF	XxoM#&^jB~*/N'}!<"'¥v|V-ܞӍdaj ";
<9:}yH~SSS8:)lt,eϫa#-gt0?!g7xzUf T9	]$a}+6j&֨(K)+_7Gj]csVcs	CVZzʪjrM<T#,5@﻿%JQ?d50</
qp]Ck&vB;S*/6^
1LT.C&/k2^>~:q95!уU~5[jBqU͔sn΢(_9CZVz	+G4uFFuٺZYjPê_/5ۮ`ŹUʾR"4}vOb_D}לAp9;i-ikP(<rdJ t=hP(S/l9.@cvV֩q@&e^2E	toiLQb\D1{W7Ә.8	!݇CKdx*yOu.~nItA-Rxzp,E'>4!UM@HLxl:_X#iz407hnzɚK'a0Zr!^MQ{t4(QcȅG@?QΛ㽟LX7E\	^=5์"B@N\(MՌ>>VTX{P.2Ġy0]y#d[I54:GUf$	t̢]}Rfd܉DۆH#Nx
uւ[m7nzzm9?4!i=zҙ<
Ŏ?+LAB(\vtg;Vhӵhln}%Nt18{g/(?eěb^5D}4zŜyř\Jo
0a7~3~B	iޛiPY5$F"0u{7O6Э÷j;֓Z-f^NrMzZ0u1	G1udCݪ"]c;O{J{|TL6V%mO>=,.(k]d z8݋!nX2aǩV
Y{sSvΡo6k|*4-7̴A3R:u@qEDRr=.3V5G0)DKTla
+JR%;^yr(oG]V0ￛ"4gd|7>02cFN1.ZOJ&tI{Jl-{	`Ç^6|ޑ^˺֬;({ږ޹e5(u-_BGUr6\ʕ,`2ABon֒Fq@6Vn5J
%s1SLl[N<,4ntم齅?Lsaӕӏ|S􃷪,ҧZkb,1f0YYUBS1t)/RwrRh9Gf:5tچ	鉄<Oxʳح}9۬O(JFI$
>2T[}zB%ր2EeY4'\@bW/)+a{fʦ'*_bˈ]ކf˙lwlK9A`C.E/lꅚa$~fVs8xͺ{bTZS)t{%ckN~αx`\z=Oƽgx&P>yJy/k'S%h	bc,F~xX:pjD-m~Qɂ@]W:U(K5>Ȟ3IdoqL{PPol
v2и=:09(ˇXJE$(@*Farȫ¦Gys}rAyl,(ji54/G#ے$XSkwKFh+k!XPa]TO=iƠNQr㪨<n{3{YG0nnZ<,6O Oһy;GnN灠aA{K_ׁkD@;^_]I\N+6<&3lggQ,=,	4P]u_Bn}}	9ac*ep2=Pһ;;lhxø}a?Rv,buC~W؂?k&hy@Iz0=5w}ɃnauCLjܐIԇr#MC7K\NkIW6쿇zeɿD@ek]
哞uy~8Uw,fyܴ,u(5Z@q1*&d	Eסv[(Dka9b ⁱ4k469`/DS[Jˀ48Y*魵p'z⎞Ƿ1m=ݭuXF^(4V:&(,m<-B\}MUFе0j[{f*z|DGkRa7_M^cy'pc܁432E\6)[Z"x@@@H15[Lkh229PHW0SkG%,mi 	"2w`kkhw39ն?,=#{
ao2me{:LAs|V{t|[If1Im4?{=. Oԓ-&	8S%8&t>o(LYP2~qg)5֯𕖨9l8jfjiؗu%&	2hS1[kIaC3*MS{j&8\?>Gi萣A4ǌaT_DxjhYPKTM>I2+A qyJ])~W풦(k y~wTqɋlu⩅'oey`o0UOՑU]tRScBJ.uXs]ٙпҚ~_Dt0ɈuS7/e.2ȑ!CՉz>SΎi\TMI/P*uxsG	j{XkPEVvzFmRԭ0]	bzо~+U͓ltizj4l"5c,z)"9rCJ{os:_bCpu#P0y4`ц6t̿;F<*O/9zxͅhor9g/ڞ=hIJy|S3N lQ+ً?0@#7>LJ&xk9Q``X*ͮM*L|[:?c^wI=nBuB~|&~Ɇ X0X#HH,=P~zj{?i3{*",YJJ9e8VqlynGtFo_B??l52{l׃q\55WyNE2xd ahklb%@bD_'2˚-KEw:6mA~X'l0`ϙuWG`O8|/%<17YL{*Nu}_p[nڵдX$!5^)V3[G5 X}3i~ү^_V5sByɆdijv(\rd/g²lX	Kα@HrFskK\:QhBЉ4r
]ڙ_D˻pd_wAqu^{c.N(t߀}y[[c8zUkk jW?>ikFZuOaq3,ܸ6qR_pdUE|qtd{tdG'u=-M|h	3znԓ:ku5$o#38 Jn$ZE8wM	i[	UWx-,Eq2}(YП_7͵B&hDem&)<.'ezKl:y(Ue7a=ly
m}6rf.P(WMUԉ
SLz:y4G'}|#95ƔQ@Εq&7uZ'ZO-/ު
	+Wr7b~݃qY~ge#;omـK6%fo1BmtHWRr;kf}t9:/<NJs14~,xk)Ozh6{rSuQN]ӵylz})NzڿG%tΟ.W>Ly΋)䙖8}{|tz=z:ś9"Zx	Ivzfф{[Fيz_d%XB@t8Sc؄#"(۔jԑeqc?`e+=TO>	E>u_=ݶ `'p:wrVh}jaɐnU<\|j#/Ms2MSEiojfN9hBYNƃnGڿ.򦵷\dE)7bO+[U,Gyk;+0Y>n]ܷ֫bx-fPmq-Zlֺ%:b pAo#ԧ0d;EQ;Ūj*[c/r
CzE9+-s<&f(?܏H*``z0Ng c1;'ecmTȏ8v"+3r{MYò1?&㍊2T&iBfv;QF8crAƊE%sޝMV~nC`QrE@
bN*!SfWzfKD0ׇ$~0:Ie'Φx?FrʿnEƿ%f<gf*">2#Zi8v"k{F~p
Оq^MZR
v(7읣p83   sL7)wbfQě=-|uJ]u4V uZ<j9/ӵ\mJ/=&AYT
ƦI __AZbJqr]ڵ sqG-!O *f?(]̓w? 4~u牶c7x{`dڶ5lGVT7wE>ud1.x7*exH:+"iʨˆ4:Z&еYhS>Hmqa֍iE,y媰w1tUWw,EpDW(@
!qPkO8eQ۠-(ˉ~Ux5hH}>"Fƶ`mHq8Hq"w"iOtJm$%Hl/HhcؙŸ_SJDk
_vq3=Th	𐤣EF$FP&P>Vr)NT0Ⱥ2jIjݷhs͑e+ !oooGc=z sj_(Ëi6Vn@3(D{чs !`Qk@i114Mnzn57M>Fس0=,ȢH`DJ %
xqݖn,ڳάKqTN<%r!pA܌;A2~r4zsq:(K@FfoE"fŢUn_4kM,+_*]"}&,dFjz|qsH@63~sfjbzpmͶ=/bCƤ/|g®)iӶSq^EAƃB߀XQ)E[d]Bq[<BZ?Aye$3}{kU1SΈTcրꐙ5f_{eZ2"1y%BBԞ7My&
t9)[3{BqE&߰NԎ$=тi-԰T?\`bڭ	fE΢VtntMR#	e|@ŵH^q:=}$lРʼZXjPn"DS=UP#ʸOwYK?e)MPEPVhqZI.(,QnEx0O}h&S6g25?I.C4HuԹJ.&HgiX|5,4>3kj N*'t;:^\^kkx5D*JZ/ga5/.*AKtCԷT&@Gwă-9یӇ!J%BS<j:WB5++198f9.{|2t7!CZn	na|ѩ\S&&fɄ8B'/~J7:uiqMS3֞u2<5"爨LOA&H:O4ќ8(BLbc/gs{Q6Qcp3wH`7N.OYJ&
AY>%2cI*;UCtv48R+X|^9RѠ @AUr\ LQMCB1D5+%p2h{W%i}dGL\_O#0W9Wo[YLo:3y,(]cT67OD]q- NhavȼpPEx-Ooޤ!{U 	RzoyAS1bwƙp0OS;[FF:D ZqLPV<tm< [D4j.bG>İ_{i;:ϣc-}v\?D֮fвc}:Ě鷾_ϳ2?rMI諠%zb]N	I"	~&Kf*$Æ'loovo^MB@	ƳzUܥ)o\7FV4VDUѼ@CU{栥~bZ>Z8WD$=675J.{BɬkmxVu'CreX;;	_v5G9vd>^yMMxP/ܫ0ߏ0{?P=sGJK,R4+R}7L;x\8Nl9/fޚeyS`J l=Ƹ$Fg3ruׁM+
H_U7'lGIk/-Z/ͽo!ku/5f{ }|4ΐ0rNoSm%}@hT?M`^ֶRfl-jdTC"T-(\ko]r*#'C78	ڠ(r2z.㠋Sq 'b Ic#z>,7ԇQ1TQI/sTUƴU+kvS(.u4DA_!IOU.tS=uJ06O1Lǟ^EaBL&>vx|lp8GO.kY|Y(g)6/B+|?WtT<l$>
+k0V|4ޤ~ӆWbz;4:+]>Ξ=}+	cxNFP1{CrUj]k`xGByS\8rގs^:y}@'^:^V-;FRab!˙bT<W}TJW`jeG0<jn\JԦA\/s 5gn6wQ̉ީ9xCvrot+jsG_1-*O
(ys1/7tmܛ<M,8MM3MpC^HB ͌q:eDB4I@F	4|0wrnϹόs<9o0ݪQNS;{Xs\0*|eR4F6G66X]trA߃g.^Rl՗$4ow1<yOjD
vycX t?W[yzwI65pa)/+!q>)^NDNR: }1\N*%	R4mśKXx $u`NڜǨ<QCԪ-nrSW>}CӂFSAVbT%Dno^IlPSZ+8U\;PAc!AA`OjqS_5d(j"΋?nx=>u Um Y.TfGrD.'ܯ{>%]1=UMVtguEj9U"Ěa}O%[}`؇?oyT:GBʂ9SBig/Nъl{(/˖V	,Eｲ|_GZv|nEԕY)m	椇cpƾB=Rо$(;#W$e.d#][nlH0Fvޜm˲	hb4^T&mzmFZBMgD`,*THHQ	f<RcDzauD'G+^qhW<#oîQW: g5&%L
Y"z86WHE`L
/umh,-FS-pk5.	#aXMzin|?Q
3zu[GXynJaѬʟ7U5S	;۞6q5wiHC-?|dwt]ŰMٕ<,iA0IB7ԾQ	iSR<Q.KMSfA&N֚MMl8U{y}M1?8QEesS^.PonֱqDZ/iθZ3bZd)eTE%/mnvi\po̓p:x9y78~C}^*ܹ-}ƒ80 8сwt'tfYTkK4we+!us3p91VPfkF ݃*(|^:;y*&5pKX~<Ix	mC QH1L#/#Z	Z|jA\P0pfe>4iewqj{?gI,&Q
kGg.5~SF)};+ K\7זNMJe*b^::!KAsT}6z|_DD}6J}̖wkaPaMϏs5qrOɭlUW0S9m#Uvp ?dQ̐z[.9Vf[]x]'bas	F9C	6nT)"aVG܀&or92MWx޽yOf:gv|X\i}[^RC=dZ-JkٿR4㉔lȀ׀|qT0 V39xR;IY4}]/?*JE^4HS/zv_wQL epONwۓ4 dgiV,O.;s0%ۮ)pAw.
i[n$l~v!u3O/*G^GhUV[^P@'
%t A& W+ *q?kش'yQ,}zw:;98UF[H).hH%}JReNΓD
z=t\#7X)Uuȭ6殨+7yv,X17৐+0V
sFĭ;RM&ȯI
W-obhG1mwo=	Ӑ"^*)`X4gƍfk iQ-sevuE+"^9J4L5,/ZPh,GT46z(#K
/UG2kq}rN1䉣)fw.U旘~Z[41M_W`6w.C_μX.%؍i1$^EGnG3"׽*,S67H4%٭ub-lXtR6 T'!SCgtX;C^wJG>I=ۭ?b>p.W/b'Аu~	ҝ7Pg,1x>=eګOG"a=R"f=gg<hąD͕tz8aG}!ф[hi6-@oG4Ժ6H"u~k?FRwDB5nF,on?~91o(/{vhQB1qQG{N8d7w`х
7!m@JwA7d{$Qqlz_^9H|mix세=`8ryhw:395U;4Y*f2}f8ˁ[=A^XDut%mipȰ;N_iLWKl]GٞIegůgEsIFZ`(BȚyVx6ףi!%Qb}~o~Wxp:yݧ8:pp1ՅN>E-hrtE=CГi}-68*Rȭ	ߑlDA92w[u9,0䝌b=W3(Sd$w@/Q
zk<Yji}U@ox"|6mZ<+KS^ۧ2/;I3ȧ'V"zm^gREvW~n沫^__^O˴6*7ȜB8n$AF=)!zI|U,16r}_Gi*8\le,7paX!1r#Wz՜f>[=ke"\js1{kIW/\N'Re/xezT]@FQE궆scNXRYmt8]=9ϥss_9O#ـ1PV=^BO4;ɦb CrhUNbJ,߼jG Ju:ucZf2:bK6fv*dTyKE_
O^JNQ'kz0pk
@O<IW`*;J*X.^7OQR^3xrR\:ڜ0dVߟp%_& oJy )ڨ7{m\5Ƥgɩ)&jh,#:(x6܎_z35h.u/)T~R"chhkp01_q)eiltү$S[RP%c>'V~mwP)ַF\ZCMXIMvucjVAGm.#4g4BsJtlEkwc؁.=Nw|65ve@k`⏦gQ=ՙ߱]pe鯶΀# h]PR4E*g
S?Zd;P\/ʆnt*M0UG4We^ݓ07lE>v_s\XՆrPr&ׄ8[L,0a[U1Xyj.)5g2B:OxL/5	s0PP4fwG§DQY)B3 ͗˃; ,vQ֏x;LRԨ:GyM|` if%Rj\QKx1?r%=*UvJ} X.
4Dm,iwn2BWz擰P|[N㫙{_Ǿw&Wl7a_(|FG?3;TR詮+U'*iZȚu}4'oQ.*23~d-Sޔ*BlSs:+;NB!06|B2oV鮕&nO,ethAeɧ$MWi5.ID\I{>i%Jo	qAJILW%Ďf3$f H4_s]x$h`gDt<kPC9}U`Xws1>nq{Gp] 쏪dvTIHr$&7&\dZN7zuVҍR:Mh<zpjHYHfy>^LR.էf!,6;
z;K M >Fwud}5nms﬘]S.6Rצ`ůtrO{	^6$^mHf8ܡ0Qyio1BNTPsԩ.I=
֪7yكW(w꭛JSۻѬpıbÑW^$^B6/'F=DL,8R<CT<Fɻd+T0Y_59eQ0XAu<^1\p^sĩMI[$ڿIZ"%7|:w}~PݺO^Y1u0lhb_ð*1p6_:ff2fpl-n[?aϥyra9+(ti@DTckTa`0] "YNs4ԈF!墡	
R<BLW⻿:;m#gİ{p9=DRN1G@7y±q*1}#19Ymk%ell
}LV7dkV~K97˜J9.UwKUmm_%Qm^ռ]MOztk/wVwG[a*\vܼ	fGjҡg<xL51,cIXPfs7jlҥW[םהLsu5	]g(zteRh9m5tIVik;L/kꋐ|J
Mu_^rUe-T4o&KܞŻ0Mnq^Hgix:@:g3c"<CmS$+>\,/`+/Gʰ	+2ʎH`1Y{Iֱp/ϭ_c^>TAԱb-T:fbHyPOj:$>Ҷ?*Wل1*ԀvnHP#j6@eoSw@%n\/W PZ+4r{]x3Qm3CEki ?SN+L* 0t .nG(Yx|/2Lu+3Gm,tY	s+ips~
+ͤZc$)u\JPW޶r.}WD6d4w#Y7̹x[E64da2IAu)=>t0ړqӜB9$/b2 8~q? }][!2^rsRaCaGIF#	ZgԛMM~[KL8Y)T00X480jwluxs'0M4g'.}˕tbu:HLvԳb3 <d, j
Ҽ1& &T 61FSA1m:S^Ym)8l$=tQ_bnʊ}"=(]|O笕33VmMI|^ųׇNѺ}aч*EJNrܽH_0tw;Tw:/i˪)m.=x[g v|Dhupl~@ti+mTxlsO_Ō9	P`;Kewva P~bq"Ci[vh?iTt1hlMt:L>m&ѽVEo9՞D!H~,)1_űc7\Z	m?z[I<n)眲N4-(`ԎAYCM,b6ӂ}\$:h ƍ`%@	,'F׏An$6G#2m VgTM>3"չzTw<œSU}:(Lϟ;4\ז5^%]{~YJ$ϪTE"5&Co>b;BgɲnHnh#u)
?᠏,>x8pYwVվW	1Dmnn3jΟ>t8)t1l<v`*?Vvb9iHsm4{'~.gJ|h;>oE1Im"J:b;q{xY7i,ƳfZ\(Ə$*<Fˋɨs}SEd:ѻ(oA"ev'Jg{z20kVjĳB7
f:ugUEQ&Q3xfAڊ=x
]ULE귾 ۔|C~$=gW:HKQ"QY_'x}'Vܪ|;=a.o	IgT<\	hN<PX:EUyZMkFG"1h۷>	i$Bϡly|CONԈ
mڙϪeiW&5JnWV4sHfiK
2բP60s-1OhEs2܁6wP ꎮenDTcC%S@qcq7P_aP6[I>ׯ簚:_8[NƁP-g*CtL{(q?'\mh5MO5_a{.vh
5g燢RH#^O5Q>͝Z8ShZ(%n 8S;?O9m4`XYzlGN Mn3q} %0aiV<1XAng,B8DhNFf=Q`OMєVvz8VwMm%lA`oRH{"6^؆TR$1A~LKMn?ƚytTKXku}8rtkj[}^CL|F~jhmK史<LߦD3ZF8^>3r8N9ӻbEI
x=pQt2_%JSXNGEqD܂h;HL1	L"ipmnc+%JƗdN0&phu2JM%FF们̢Sŷ +UK;݃L#h+WiY/~A5:V&:Ӵ( ô6EluPe$NCa9X͞k&e'/7CWRnWSP}AUS :+Fls-m_RS*%vo6fI&;3+]lѾI_ʎI.>$8Ko`?xP/£}+84d!K;k^ņע21pHuhAÞj«F^<wlA6JV`{E.)x dI{ݸcBbM۲`q8O<= |hZӉ|^stBx34giB$DNJcxPS.,}C@
h&]tn{[Bِ%aa7NCM|.'ăs6'$^d׽OcݾJJL΂ݰSizJmIr*bo}xﻷ5dH`%@*ga4J _!vؠiidױڬ{apυP_~oiYs)=Lom?;v6}@c_#A^ֽ|Qt`0kO,]e	E^^JlB{T,c5EdRM$AƓ@'d3zA><ёpJqJ*:(dD'z;};>Dc O5?x|Spp_2F(,Io7|!SPiYZD3|D|^ q2\ry=g $;6U]IF%Ew-dEh^IENPdciqW"?4țO #QphT1g2ȍ@	oF,]wip9g'qV<`>ˀ92uгKcx|.~RDxEՒ0pT1Wk1?%%Pѿ@bG쪭,AIZ27N?YrV䀩}KʗlT	7e
&[ԧVґ>$Q2l ɺbk@xes|*9óχm30GvA1	.1{?`J.rMη<ܸ@UIU-Y<nQMc<1j.'l2LgY}ct:[gz緡Fzjiwz?7ShPM>|y'U x]ngGMqߋkMMpl|`#j;怴Ե*ԧ쾹Ug!^_yC_~o@bD[[xxhV-ڀCc=d @<0ѕYQwOי!l
4$mŇoB,'q)Ah|4=c.F0&zLI=\9%`S8chY`O'ڲao˳cnlo.̲ʱ]^c}?m0Z|5g IGuSt9KLiX[ѡWdBRv3H qI^l@I-,]qBC^2y]Л^^龺_Ilu,T:;:ȘtoLg4VaW3v^ni_m-Ϸ;2ʱ^WFVw%Yw]!e/`z_OI?gv_/ͪ#*ef^P+1[dRDF*R5nCF74NGchT}0l;ڊW2qȌ3d'R)?(N)CUe#[Oiv(SݴvH{XlF Rr$+4og:3xfc.&Eӓ#o#}g`/MYիFjw独谉
gTG3jeBo'5@:i?}B%4<->Y|]^<ɀC4To
Rμ!)ឈ=T;zLC[|՜&̃4
a KnA;$Ղ|ǐMUG/pKpƔMF^|F Ń"4J`x4BV=le`)q{g[U@mmdk.[oa%j5\,\c	Yu8C<pȡ\T%nX&N.搢aZm2lܗDiy&HipN9y7K=C\r+Ol-[PTӎ4LVJTmU?_pPͧG$ }{2uJNeg"L[S~IITzR'vAPx®^6 i~=$M68M/Znޗ")i纈`KmT+yU6޻[2BZtѽ=YS*C^!
.F/kdn+2'Z	a-H*^OCMwyy!f|KT4{`ƌ@c}\*C]>ט+.F{]o7H:f<x%vJqD4sYwp_c۪2F2f!=䖰$AA<=iJIX(惡^B-P_"FaU%K1.q)-?iq\giq	YvMZ;5iw|jl; :BU8=?<3A)a(B&<I\.Z 	0@b
s*Wnm4Wi{v2hw
|e1%΍tzXdMc\LO
ed;0a~,9R|yܡ
$fz:?(]GFy"3\,,R68G3&'XKN0LKB7fNڸ`\<zhd:嫂Hڞ	֊: e[~CTୢĂۘ=R~3V4@ǯ~g" | f3uܰ_8p>46ӫɕ^ofC\~TL=<g<ݎ9F6~Im[V]PxW30@(^ ^{baWԹ[KQ済+sfy;`6
ͬYvTCjG}\h^Ѷ5hxUDOX}^?{LXWb;k-d6L4CbJK6
mtX-7[SwKe']FڡǆrPyr:y^r6ؖL4Mw	.%%H_1bGMT?]y~ݝLuU}ݿ/%t <_pMU(>`	~K@;W 2'4dr&R6.n-tF`|AnR/"ޣQ?|I7c/pc*8#faJMkn$!*AS^+i2>G!YEu"u˜I:[WcAAdM~Ic^'` 	mo2%R/ZǮz^sEx<&~0U⿞ޖW'/ǔ3e"{`,Gx*k*돑p<`#PlA!ouphHħ n\TSNnL8z+iެǔ20+=Hdhgbᒯ%zЧOvByX`,	|.?p%eܒf梢P Q7eÏ͒'&a	y1_R^Bf lmflU8z0hr2\TlRI˰t#94vyXb"L3B^EpcQ\մ-&alF/#O'% BxzUbm]T 1ńuP^EP&'ȕ3i/<
;j<ӧฃ.)Z\!~/	>0Y<sGZSjTp7=abC|#s]E;)́f?HNJ
mp"3++n}wKo`?Cp][ok1\eg<XYT2W<J#-[$ZaA|W;Wc\hap1<߶Ѽ?8SL=3,}3"	^%7aڵN9B2z|qh"<Lך'2iN!ʈ|{@_<naO;DLdg9)z3LXOIOɬ7%7ޤq\%{'BWo7Nɻki	=cJKE0V%᭞/Mdf1pA"քP73ryܔuqBU:[Nݒq;ZΓ\?ֶv7W1U4Ig%DV~iCĈ&lW&V A))b#kJ).r p>0EcA䞌tǇ_Z虃ɤWwzh2Вx>D	5QUfr\uwIW|PKS;X!Wfu~ӰT2P+_X4g*U߁d}i5y*{7 ũ@g4Ȥ+0/T?|(,҈x5'AHL_ $6(^%JOX?hR#zSZsjxYu]@7bw哹͔f{ПIxI8{,uFXu$1"I:3z'	ʸ)@\=m1M{o7@SF6'K'Qa;VV24^-0WN%n	'pƈPwa\q̡/ 2#fx8M%ᒔ-uޕNjSy5+@ޥChHoҾ^|0	
O(;|cZmyCZdGЌNEWq)vC}eZkU%Kf܉z/BLEϷx).ф3D(yq-}b	)^t8 W[W3R=IgB;2Pxh0k3%M!QMJPnm9M|֒=1YX_gp?0Mw<赺EPU|{=^lmaB?( pE=99~5ȗŶ+дGV	ȏǷF&U1ԒvϏov.zc	Kgcmۨ󋓳H}8R'U(Vu.kXHTNp<=PTh_IŝUǕ]k[u      ]oFb+?Aw9c>צA>@+5E
$o*RJz8A;;;;YrU$Y盗"Y*tuh0FeQnU^=6M_xqv(cʳ1ږ8F,2|wK-r(EaVU72Vy/||󧛟{suD؊&F%P@!cv;oC7^QUE2V{Q}ۧ?V~Od'%bh3"NmAaZGvN
8<Sw1M8BqVIVN#2M7yQuЪN*5a9"e(y\C?g`e0JJ uPT0$:*5FA^2y+Aot};O`$8&hpJNѰP%?rghd&yWW?`o̶4<XÓc0tO91g`n46C0 ݙF֬]CX??n'.'~f}8ؗR0ܟ3g;h` Od`EptN^c S1:7p0<_{tar+r?J?xeybt s@3Đ!^c˾n.c}[bmuX"	SV  	UsJ)}gxtJbZ+0	:䖶t})V 	WM.1`Gb826g1,NZXn;'$vIK燑$?tہN{7t]E-T/%OUQgN2vm
EU%#&FF32:q#ȤLadtFFܯe>cjgְh oURrF!I(^S./. *H2p8 
dͺ4E`UjLsx	H j45j+׊H4YF'6dɈ|dSW4JQX, : Oj<	\ nXRt?$UP`,W)0 i^\۲ENd+au+/b}(,ɄTQ1alaBeے;tKnYm2cuX;1~ؐA5^DڸENRт(_aa@0rՊv@LE?F%
}?+cg6L;쀩bYx
,hd0)q|{/<,bX(Yt<aYIc窹N<%TDmtCGٕLy䏽[m ?)w2f	`Bid!U'(!L4ǰQ3^U0a"#6YqZH|EwncX&ZhHZfy47D5hV%UT6ĹD.."xUtz5ϐ\j۠=@1mS+^j9"W+*Z4c 
. oE
^%Ӊ2$5})~nC,)rR(TO ҖKJg1PF
DVڒ<nlZ*Ʀ{tOEHʽYnpɢfTk~*SxtLR%h<DQZ=y9"Oka@Gqy<sOE)k0^mlz>1(FVY>>i,sdX #4ܔx/7Rk1(Eq{[Ȃ6=EB Vxƃ%z=bRS	5@"v`9}`c:jD&guȳ)VIY˗,]$AV#0 ,?e҅滟Uf@s2pᳰzT(&E0\y!TASڷy`ebutLH iF򖭠r6,.`Z=,Xit(cP}Uİl*Y;wD<[xT)Rd&:.yv-sG1V4M6eR.hDQCyįBF3B$Ӿ Xa.G֨K߉톪lG,@	4®+phyv[nvHg	:%lP@gXRr:p<*5:(j	0l<%$*:U\6F>Q{+zʮ* twv5fH@):s}wGA_{*TWI4E3ID,@M:/p {rmP-턁c~P6~wmJeyG2<bQlW6kKZ\A_&o	б{^zK^N8&S$Iښ-D<eqoSKE@Ñ: i1Wb}܁eװ<"	{QxC@TiA㒪H f;HhfXIcCule%n{ۂ^-0@ B;Uw@:f;fdW~'ԝ9w+gHP"Z,>I+`7)@bM-<%}w`\VfطG tEoDGN{J5.gkq8Vkq_w0P"DELrN 0IS.e:&I`/V͒l)ustfi3zZ	XYU
lnh4(EDih+*	DP1$II#]g;1vWhN]
4rm2
,C|h7Yfܨ=J}['#8\$ ;_l{Pq--ggjFͣNBJj~7I ZUMKc=aХgخi&CeIuUttZT2UCe+Tt _vLZ*f?f7tϵr駎L5wwK)z^*"yuՒr5xMYCC)ӇePV폁Ω\3ڢUV1ګ&X#$<>o1P_^jz#{tj~yA/`	_V0ʲO4dyM;FjMScp sV1ͭl|myZY%f}6$X<^4;^;7̺!13*qq2BxE~:MITG(V]OaVwTQF6G$c0O88hNb$7  ٢=vQYe'ONDGWV,ɠ)\~GL:{?5C\\7tz؜Nvd	dItMq25h.Ae&q~rD3v5#ArU$كؤXJxg.X6J4%(gfNN+ى<>r5=\
Ev}Yl	!תGȠO]T98Lc8˪A^$tJH̅^rrФaⳉOpJݷ|Q֮=eKVΚ{4BCT2u{`]"|mΊZ]aQ *듃]cȮQKiѦ6ɡADuYmCrY95gԽaŦQ?/V2ǩ0XTӝI]oMo0
(^hYYŚW"|/#\	izS=(NHnIn<UŶQgRq\EyT2dcڨIoPT:rYg<+L}CNo5[J|Qi2lSjga^\:RuǲΦaVܬ?TK2Ub.C^[z:tZYkW|@~Քp1``)PqST>`	&PaQK>dn*o+I6_=Z";+~*k.l=K7=)ƻ>ڻj`"Hql8s<i|yr~:؝[6O;vc8,9ݗVRr9t<ap#*b$/=7H/=ߵA3ho|:lcU756Y0n1ĽZxN2H>#֦38Ut}3X:{Z1C̓y;_O~&°z|'!8L`)OjܤEG\vn	3=}8_,g5ORBm=ބ=Sow[25jޏ;\0oIcb(qpK&?M{9bv)!Y#۾kkiM7HyEQgf3S?YjkQK_6l6ۙ|i:MVR@zn"I^rczǤuUFpC㉤~ 3?Yg"%ԇ6dN:<xR6
R^Ie<jQ꣸cP&qO͌pM("|"Klmt>Ӿi"Mmc-Dw/zX,{
!`gfT&0M<Q8,MΛ%']>A0{Mv\su2߼6zfiN87jL̙><* il۵NֵL}lt7tOo^F[.cl!K6iaƥ9	5,n7ToYcOv:a
5@WX܁~t8ݝ9D:Ea*Х;rU S&K&k䂝ּt3Qa!i9o87VSum58[˘g_S*7"i0,naߥuUG(<xى$ݗXVM@:k(o;cu{܀b(T[eV:'DČ[EKusYͰ4I 
^/7*Ԫ\\^ڮ2E`_ @53GHO,pct	!׃Gg2ԫnP蠄^b],lAaܶPW7	܈1a~sE:*.XsٕrAP\Ùs*Ƹ-nQXWH=n7L"H RHFXq;F4\6vD:DK1 T2K0YҸ
%dj       ][oȒ~'ka.2l3`>@-cHʗ߷oEJ,$"jUN/W$/O␤9zmx*éw",y^gnU=mx~ zG,":x4y$idJ W	x"R/(UYn.봷vދ/^T![a$$^AJ/[xcv;oC7,-x-O|ǭ eb?{ʲ%>(MP*AI9}.3/H 2 >~_AZ۟?2|i_>UG,z>(~VqV}Nß2{7Y^vUNWpgkrȶyH>*>t!|0^ۢ>]RtlqT:^X08:*5F^%2zsXys5&ɠ79XtoU#)YJfEh⻪Մ$!Q1oyp2` I!4j6;5ڊu$89CXױ>^Y}ĥ6?H?w1.w>]WT` ;Dgr?+y!`Wq\AQ4@yLC5tQ{`|^'Q;=1{uƱe_7k^g-MJAj _6AjaN)ְZN[$ Ӛri|0ې:./VYQz+|f&YxUgIpm@]xFێ%a-ɟF~Ғa-]k礧z"b}-ZJ5UEn=wΰɨ@YTEvնddhFF02nbd?#C412ٟ!L)BLJ}
kgWqIMt<lK6.#`&ǥg-8:A* Q&`@[&?ǋgC	PQ[M2:8]^<gOU:N8*W`Y+EA =Ԓy/s'\x9G2K6*^C I_Ц۲Er̰$O%sY0(qBȨ 0mSR\ۼ@>7Y3V|'ipNdO_q`'qa^^À`a(uaQ	ҷ:272)01-Yti0mKzN8IpA{?[۬jqA/{<ς<kO#͊J&"*: t0(+8?{2S5)ݻ>y -Sd"Hc`Bj&\fM-$U'(!L6$+cqY}2Nd0Հa!]mn@ϸ#I3lbli,_64Y5-{1Q텽[E7rSZis.^&+YqZ.cghV6Km{e]O!9kvbSoNY@@ɮTV"1 SP w4V@L`(ʙ	VCV^$E R"Me2m:v[u)4#J[QW{c tVx-bEHmQiIUXbώWs
$:S&Y
/K?QV{/g/(:pxsswӗ/\0FAګ?չa#tD+,PôNq2KH$	6Z֘F00:G.$+!m@-Q,Jjz "%.b=jPA'LWJ {&<3xShUFb}w,-~uce
xNCPNyC$2t 9|wtaȹ@7Vn:x]c
8bR
jwuۀwZ]OXZǴ3HmRhHY`&grI̧ѡAAvJx!#	%.'dQ
^=ɬÕwW]Zpss,4S5%Io`](e59)ʢKV9J* :-]0EרK	톪lG,A	4:®>hyr_nCfׂ`6v-e EGÍ3<}p9`6aуft99en+Z؈<m8G6be4+KD!|U̖˄TH0jxROZϻce_*d%R2uTA_/_@P]aW''8N!Y!uv)ڠ.[	 m
`xxżaoʵ%J.KMAVL$rcsI_N8LS$I_FJm(qTH58R -_׷oM\Zv}KT2s! QeQZи:"%ltSHLVVj0Amk @	"}RwwJf~
Ǻ31{l	I+4)pf5(=.˾{Ujw:6þu8쇸/Z~#?<;WhIao>[Ck^sku~:H!(Tu7J£@#$/yVFx1'\V;в? Y6yzn7|:m3i3zZ^iƵppi4ـ/&ED@lDa"y\P<m!&>Q6`n̤+&=5*کSaWGGł?0N_6i`!np4~U7YfΫnȝL}[(#8\9`=ͅlȄ~z--fr	-NBNj#*m	0LkU5Q/fZL:l`vI4Z7VeCt#F`ЕDl50jM_SvCOp9LoJks][R7LX3ՖݥW3yA٩WI]%5g_XAIX?T:Zsg|E3m2ګ&X#$
>1PZj?v}P%$j`eJi"MNvdkMcp 3V1@X{6X}jZY%f}6EZ~=y/䡿dEw"s]}8-OwXxID8Q^c,ׄWdxs$[,`A*ATLn)*hf'=((y%@K4tgQ]m/ nAqteNwRɉ݊%:R;@<2u6Sgyh~jNdGPqq(J,$۔vGϊ8-SvȒ8jO䌬\]yKsP׺Xqz%H'7ޙR"qMZ[M	)Y?\ӊ;VFՖg6VAYd<3!$Zu`ɠ'iDiYN	a!+
26!>h'}lS[lYsV=H`.<`"˶tۊ$[SZ<#m TtU]cȮQKiW6ɡP9uYmCrY95gԽaŦQ?-V2'VP˱ŧ;m	64M=x٧:5W}/#\ۙlzS=N~Έ~8E?y?ѡ2VQ]*.(u\Fq!@5[sXr^7k `ɪ:#]鵒EgIl	[ZkEK 7/l$_:cjSVYD̓}.<XJ^G&ϵI_ƞ:t![YkvaR0WSL	4}B9NOޠk?u4eYB_ 0xP)!êSnVN=3k\XYok.rvf R wH̅}ֵ(Nc?Ȳx8gѳpX;3VIuKjzVF&}&[C%^
 8ţG	EZuHM=0=CY]urچ
f.k̎=ΐH@8mg)<s[Zpա8ܣ֪j\aoz6A@53sāMJ]t4e0߱p2%^7)MٷƎUOH\0oIcb(HpKX?h;.`>p&cGc]wkA!};f&ZmڢljUw03ɹ2P4cfZ9L ٌ@Ɯ\;YQuiMM`(i|O7 'M{Obya]OiCt銫ΜJWD${GUj2cxJmf%뗨L~%9}~hhj+*xMh Bûb|ƕffIepFtQ
 O%=#W,YeA}.SWYυ#SNpu?>QCΨFgߪ|m8Z5۶kE>)3cr~%{2 r׻.p{ȦdsȠ"foZsUpw-˸78 X|zM{-sUJJ|Lۑ,g>Mwg+)1%쎙:5D}U$$3T,wwj"^ҳѾY%pO=Eud T@U}[\U2])JPHc$пt
k|z|	-s5qz8ٗXVE@g^֌Z9p<it_֯2+CLY1T݆Q-KʩdT]{^Yo] c_+]\HtR-P+Ң
(8n1#[j#ץ5mu(^tލ],t溅aW9Rntj0?Ts:/X`+9,"/\Ù(s*Ƹ-nQXP]7L"O%j~9_FXq;F4@vCDKCL<K Y?a%zk=3!Rk       =r㸑2IgJKRr<gG˥P"lq"c  xv/@h4ݍ櫯:1eWLs̳UYu62ˋA(I:TtrQBtNNm,Ht>(TDc'켙1$^˰,´3.ۤQ'N\tǧ]o wq*ĞIeޓy-6wyA!3ȳ"VuYS|feދ.L
g). /zO]6a
A(	@D@<i9{Qn+wY~.]MB)?n @c=YZh1~_!\o0eW}F(;x\> r{zOZ5뿢Qv'@X	}FG\՘Yp[o2߈u4+mLj~u{#&>Љ7I	E(797`, > ?e],:KnndG(qh]bd.HШE`=s-m|>J]88bjh
[b#TIĈ§o%`V%=@ug?lk(5UߒaAC5o hajL'D܇̏gD=bQ༄RVX^VMXo%KTQQ3[mC ~.VΛ\pP;)}k;&Yj*`	P1՜g%Z?GTB*^fk@??qmڸa,R<UҰx%+µl2K߈e11(	61)cQ@d>ȇnkËj.rD,ivTy<ߔbCy]#}W9my1f0YlS{jDqX\,D4`7~4<y> Vk^,;ˬ(+ay7'Fx~Iޡiz#?yG$4EjL'al7ir*H6X8 yC$Ca}'OeՎ}"Yקo+4JDo'%0%oB0 '1T]uߧdQJ``aGr׿oP~iZM9Y~'vac
63JV}FZ2s	|[+yK&%ZPֳ(C>]0	{5":[g2pt548z:XFlz~r~+q$=eA_N|oi)rt$:Q&_Cc_N(hs+,.J̙-Tiۅ;2NPfltԆhTէ 3ZҦ_6AIexz GWE{7Dbqaݢw)$KpG93Tha"?e *{J⩂fƈ)h5Vk6ڷsuqu"'K0MKwH\eE2)+XpP}Isl2=_Go}Зp'WO/N.㳣$"P븬q)Vިk,.IB4|vr:^
ٰ;0X89L|B#9]1k`*NUbQxKLk8_b0r67iIMx0jW_b̙Fy͹8]~Q~K|onLL?FyX.)8504<dkʔ"QI#h#XGIKTGa9$⮄?K~<Q5aC"?A O_ۭe-~H%x9w"*8
!<BW[m*,	܁RW(oV),0-pSfb-R3,9pbg}Y8p`zI3t#GI4gedfWƢiy*FTL1CC'qd&8zXbAPK@%3&7j]픫QTD٪+ɗ@oTZY`9jՒV)Ȁ&"6#0E>3υj*kf*CU
XW =ӻ8GzFIiC倨c2xNi!saD{~V__KB#u!>^nͮNѮnHju#	!But[v88݄DiM	氕u&=,aKx~pbLQV(a8x`U:yI#T*uuׯH$SQ8eUV
E-7HhRֲQ(k̖0x'>ؓ\*	6F
|Z	i0NnͰH`X5_fH}{CRylPH! o,t%(ƞn*>0U{J‘/vdpGuc6D5F!8xHV=/+ѴT$^פE^b`0Gε/ЦpIWخ]j阮{] PBW9[Pudg}(8-?a|w!D$D>p|	XqIE׼S 7UӺt3'(ˁ^B
` S< "	~#@_K9GzTK??hmkIO͟Iϣ0g@.U?F5|U6叉h$<ZC9,EΩb>P٬g!݆
5;H  f<
ܨ~GSGm55Ԍf!C(V	CcjkKCM,0"vd#|$oł#KYYf `T4*UQ&(UD:Wn`d_X
u]ÿUFvw@B`FvQE[(<&P@0{Ԫk@5$K[w)Coc*B[R^RM\cUeLoR2ݠ^l]Ԉ]maz |Yޔ<<:hs7ӻ~~6-nGxnNY)hXU49dcw,TC@εUx,-P}iY~;9""r{[o8XR<!>#U&is"clsV}kSa<mUCg@R(?Yو&dYa>I u(Y*q7=m&ㆳyiGcPK]+؍+R&yY: g]h\8fH#tZ45P<e$AȸfRy2|U2'ضq{=o#̒yCؗ!22#.}ϨQa3Śq]	)%Bm?9DƤq}YEpa~]?ӮRmd|m2\Rx?K *5Y9T` #4 RyoBfavu{CHCy;Btb 
fImT{?,u8h<1lr%"b궱lX?MnK
 
_^
kGo+B/⮱_b!*ZAso*4>r0fj&Rdg&'k-RD}_2f&FrCuwjh6](%r6ތsFӢRʍʓ(š]*vX	J٩$|X$TfcxL"G#/4p^HC̫3vkXz,cth+K,/JU*mJe"˩W
4iShcz
QdL{ׁ_ȂH	>L  [C1ldq`79Ulq`(2-ӏTCt=>U~Ktti#m*HܨnR,C" ]tyB$ƍD"' {1'M0f&OWr*>S1XH[ń' t ^*Ijp=A\ӡ<z-p՝xq|z2ލ'ﮏgGXTş|<m}˦%Dc>d|	ס1HdS?2h ڻ\8<;;&b:D^8#_2 v1>6Ly1NA/Pxx&[O0	̃74
V0`< T@m~GkS6څɛir8;D.V,z;:Q`?.	[p4{:@?n[m9:X)O6{V7yo⚜[хRK'B9EYIFe8(n^ZKF*a<QucvbR#2z$s-+PAÚںT3P;jؿbhטܕ{	YVc<Ndo*sʓӉ[ث[t=UJma2{u	`cRixQr̜a꒵qe݉rAjI7\DT{=U/ƅziɆf`^57	5O<]yaْ
00n q
UClu{Zq8L8(VEl6yPapnxͭ:*mTXcﶲ4 =q(0f,J2q7P9Ӎت 1cJ۩L<£$'wEm}5Q'at
>콳A!%({4KӐ7?,ceXhzZH /y$qUFtF6'i+liuw@bAO9t~	M`9UUOql4&mfT02pomJ9|DTrߨn_WL^ћ4't
ɻ4;?xS1'P=XYa&iN?3˫Ӌ/N|M"(N^񩷑*u{#g˫:|:̻\j;c8;x=hs&SX(_ ͭaƆE(Ψ^[{J>r
ww_ 3]u:	E4ƹU/сE΁6pCĶ-yy4id>4v:M6鱻&4>L8:]3_zxE/./\4/*̉`HKI!tVx˂fksŵ(6IYxU(X[C{|l VTZ)*[i-jL*SIa
Z^Q,o٩éW5FMPMvm29de(a}TN2͘O6%C(o[ɡ(K5v]}AI)KRJmbc OkГ~ʲkpFqVJ#6aʰᙼC$ج"$09LX|g氟ΨΤ:ttG";fx/B!ѣfg#(HP\]I"u1fiUZFI1R iKQ7edA<7=-rHؤ0K>Rz_cK1@9@~l35_3Wn+RM^_kZhF|G2+_x`%ޗ*H/&`al
aQfټW7P՛!{wIi=n/TBi$rUI f&;(hp <9I`Iz͒pK^vw<V|6_Hhu;qv&:ViiT`c`X̯QQa6yWYx,	}\ s	ɯ4+vY gviжɋT2b蕼A؂!IAwAYY	+I.4;FK;]i`yeʩ;ଝx	+'}|=DjSb!_pQۃ_p]'Lf*;SkNڞOh1+9T*6*hC$©18L	^x\SPr#yz(āźC)ZimmX>PdVo4@[[]hj.*!h%?UAKMf4p"I!]Ε\{~aE,q507F}c;M*T%ccV}(M<z/AEeRIs"Hi65p5~WLY0k277'e !QҊt	EWq|EE06WON^Cގ>k2E4>Twt\X-W}=;<[Y;b,oVzw;Mt8_XËn7|O^ߕq]ܸqo[r2}ߑ!^ ذsg4rzs7t>QM/D~/Ͻ^b/H:TE8wꯔ8߽	۞5DoQK{t[<g8/O]lq<`!˾?L{b*=K=e({O׀b2쑛֥oL4ko;28bN70Cwx*,᭞;]~JZFg/uzx70~A0;?",1"6){zq<|0Սbf/{l|ye;)sߨFn4$x#Z=Yy-zav!^uڼgSw'"^g;*7!:7cBO1Oi/ӳˬVdt>qUl߅4*ES;ϠsCg,&#Qb(Um=TP*ǲ[p=_	4dW(ߣ3qkX3U`M{&;ԭD̔_3uVy^=JZ<zЖQuP٪8|VUTbru쩨%m2\<!)1;'4{`w]\1WȝGTlXxF؎ܟshMPK˫jϠRuCWN3eĵ/pZRײdos{Oo  <!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta charset="utf-8">
    <title>$i18n{pageTitle}</title>
    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
    <style>
      h1 {
        color: #6e6e6e;
        font-weight: 500;
        margin-top: 80px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <h1>$i18n{pageHeading}</h1>
  </body>
</html>
{
  // chrome-extension://ahjaciijnoiaklcomgnblndopackapon
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNyyvaNmqNZsjBwes4YNlrsy64asdP710pdMUM27jtvOe2YkXUdvglcC6r2ihlvPg16mjYK+ZmvxchcEu497KUPqBq34jXILabiUuXLrQJlvl3A7QMLatuZlijSx1qXL/5w5/ggF2Tblo9SHSVtlVyhwyyGkT9ckga5erBUbbwkQIDAQAB",
  "name": "Identity API Scope Approval UI",
  "version": "1.1",
  "manifest_version": 2,
  "description": "Displays scope approval dialog boxes for the Identity API",

  "permissions": [
    "chrome://theme/",
    "identityPrivate",
    "resourcesPrivate",
    "webview"
  ],

  "app": {
    "background": {
      "scripts": [
	"background.js"
      ]
    },
    "content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem:; style-src 'self' blob: filesystem:; img-src chrome://theme; object-src 'self' blob: filesystem:"
  },
  "display_in_launcher": false,
  "display_in_new_tab_page": false
}
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <title>$i18n{title}</title>
  <link rel="import" href="chrome://resources/html/polymer.html">
  <link rel="import" href="chrome://resources/cr_elements/icons.html">
  <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
  <link rel="stylesheet" href="chrome://resources/css/spinner.css">
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <link rel="stylesheet" href="chrome://chrome-signin/inline_login.css">
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/cr/event_target.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="chrome://chrome-signin/gaia_auth_host.js"></script>
  <script src="chrome://chrome-signin/inline_login.js"></script>
  <script src="chrome://chrome-signin/strings.js"></script>
</head>
<body>
  <div id="contents" class="loading">
    <webview id="signin-frame" name="signin-frame" allowscaling></webview>
    <div id="spinner-container">
      <div class="spinner"></div>
    </div>
  </div>
  <paper-icon-button id="navigation-button"
                     icon="cr:close"></paper-icon-button>
</body>
</html>
/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html,
body,
#contents,
#signin-frame {
  height: 100%;
  margin: 0;
  overflow: hidden;
  padding: 0;
  width: 100%;
}

#signin-frame,
#spinner-container {
  background-color: #f5f5f5;
  bottom: 0;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

#spinner-container {
  -webkit-box-align: center;
  -webkit-box-pack: center;
  display: -webkit-box;
}

#contents:not(.loading) #spinner-container {
  display: none;
}

#navigation-button {
  color: white;
  position: absolute;
  top: 0;
  visibility: hidden;
}

#navigation-button.enabled {
  visibility: visible;
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Inline login UI.
 */

cr.define('inline.login', function() {
  'use strict';

  /**
   * The auth extension host instance.
   * @type {cr.login.GaiaAuthHost}
   */
  let authExtHost;

  /**
   * Whether the auth ready event has been fired, for testing purpose.
   */
  let authReadyFired;

  /**
   * Whether the login UI is loaded for signing in primary account.
   */
  let isLoginPrimaryAccount;

  function onResize(e) {
    chrome.send('switchToFullTab', [e.detail]);
  }

  function onAuthReady(e) {
    $('contents').classList.toggle('loading', false);
    authReadyFired = true;
    if (isLoginPrimaryAccount) {
      chrome.send('metricsHandler:recordAction', ['Signin_SigninPage_Shown']);
    }
  }

  function onDropLink(e) {
    // Navigate to the dropped link.
    window.location.href = e.detail;
  }

  function onNewWindow(e) {
    window.open(e.detail.targetUrl, '_blank');
    e.detail.window.discard();
  }

  function onAuthCompleted(e) {
    completeLogin(e.detail);
  }

  function completeLogin(credentials) {
    chrome.send('completeLogin', [credentials]);
    $('contents').classList.toggle('loading', true);
  }

  /**
   * Initialize the UI.
   */
  function initialize() {
    $('navigation-button').addEventListener('click', navigationButtonClicked);
    authExtHost = new cr.login.GaiaAuthHost('signin-frame');
    authExtHost.addEventListener('dropLink', onDropLink);
    authExtHost.addEventListener('ready', onAuthReady);
    authExtHost.addEventListener('newWindow', onNewWindow);
    authExtHost.addEventListener('resize', onResize);
    authExtHost.addEventListener('authCompleted', onAuthCompleted);
    chrome.send('initialize');
  }

  /**
   * Loads auth extension.
   * @param {Object} data Parameters for auth extension.
   */
  function loadAuthExtension(data) {
    // TODO(rogerta): in when using webview, the |completeLogin| argument
    // is ignored.  See addEventListener() call above.
    authExtHost.load(data.authMode, data, completeLogin);
    $('contents')
        .classList.toggle(
            'loading',
            data.authMode != cr.login.GaiaAuthHost.AuthMode.DESKTOP ||
                data.constrained == '1');
    isLoginPrimaryAccount = data.isLoginPrimaryAccount;
  }

  /**
   * Closes the inline login dialog.
   */
  function closeDialog() {
    chrome.send('dialogClose', ['']);
  }

  /**
   * Sends a message 'lstFetchResults'. This is a specific message  sent when
   * the inline signin is loaded with reason REASON_FETCH_LST_ONLY. Handlers of
   * this message would expect a single argument a base::Dictionary value that
   * contains the values fetched from the gaia sign in endpoint.
   * @param {string} arg The string representation of the json data returned by
   *    the sign in dialog after it has finished the sign in process.
   */
  function sendLSTFetchResults(arg) {
    chrome.send('lstFetchResults', [arg]);
  }

  /**
   * Invoked when failed to get oauth2 refresh token.
   */
  function handleOAuth2TokenFailure() {
    // TODO(xiyuan): Show an error UI.
    authExtHost.reload();
    $('contents').classList.toggle('loading', true);
  }

  /**
   * Returns the auth host instance, for testing purpose.
   */
  function getAuthExtHost() {
    return authExtHost;
  }

  /**
   * Returns whether the auth UI is ready, for testing purpose.
   */
  function isAuthReady() {
    return authReadyFired;
  }

  function showBackButton() {
    $('navigation-button').icon =
        isRTL() ? 'cr:arrow-forward' : 'cr:arrow-back';

    $('navigation-button')
        .setAttribute(
            'aria-label', loadTimeData.getString('accessibleBackButtonLabel'));
  }

  function showCloseButton() {
    $('navigation-button').icon = 'cr:close';
    $('navigation-button').classList.add('enabled');
    $('navigation-button')
        .setAttribute(
            'aria-label', loadTimeData.getString('accessibleCloseButtonLabel'));
  }

  function navigationButtonClicked() {
    chrome.send('navigationButtonClicked');
  }

  return {
    closeDialog: closeDialog,
    sendLSTFetchResults: sendLSTFetchResults,
    getAuthExtHost: getAuthExtHost,
    handleOAuth2TokenFailure: handleOAuth2TokenFailure,
    initialize: initialize,
    isAuthReady: isAuthReady,
    loadAuthExtension: loadAuthExtension,
    navigationButtonClicked: navigationButtonClicked,
    showBackButton: showBackButton,
    showCloseButton: showCloseButton
  };
});

document.addEventListener('DOMContentLoaded', inline.login.initialize);
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview
 * Provides a HTML5 postMessage channel to the injected JS to talk back
 * to Authenticator.
 */
'use strict';

// // Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Channel to the background script.
 */
function Channel() {
  this.messageCallbacks_ = {};
  this.internalRequestCallbacks_ = {};
}

/** @const */
Channel.INTERNAL_REQUEST_MESSAGE = 'internal-request-message';

/** @const */
Channel.INTERNAL_REPLY_MESSAGE = 'internal-reply-message';

Channel.prototype = {
  // Message port to use to communicate with background script.
  port_: null,

  // Registered message callbacks.
  messageCallbacks_: null,

  // Internal request id to track pending requests.
  nextInternalRequestId_: 0,

  // Pending internal request callbacks.
  internalRequestCallbacks_: null,

  /**
   * Initialize the channel with given port for the background script.
   */
  init: function(port) {
    this.port_ = port;
    this.port_.onMessage.addListener(this.onMessage_.bind(this));
  },

  /**
   * Connects to the background script with the given name.
   */
  connect: function(name) {
    this.port_ = chrome.runtime.connect({name: name});
    this.port_.onMessage.addListener(this.onMessage_.bind(this));
  },

  /**
   * Associates a message name with a callback. When a message with the name
   * is received, the callback will be invoked with the message as its arg.
   * Note only the last registered callback will be invoked.
   */
  registerMessage: function(name, callback) {
    this.messageCallbacks_[name] = callback;
  },

  /**
   * Sends a message to the other side of the channel.
   */
  send: function(msg) {
    this.port_.postMessage(msg);
  },

  /**
   * Sends a message to the other side and invokes the callback with
   * the replied object. Useful for message that expects a returned result.
   */
  sendWithCallback: function(msg, callback) {
    const requestId = this.nextInternalRequestId_++;
    this.internalRequestCallbacks_[requestId] = callback;
    this.send({
      name: Channel.INTERNAL_REQUEST_MESSAGE,
      requestId: requestId,
      payload: msg
    });
  },

  /**
   * Invokes message callback using given message.
   * @return {*} The return value of the message callback or null.
   */
  invokeMessageCallbacks_: function(msg) {
    const name = msg.name;
    if (this.messageCallbacks_[name]) {
      return this.messageCallbacks_[name](msg);
    }

    console.error('Error: Unexpected message, name=' + name);
    return null;
  },

  /**
   * Invoked when a message is received.
   */
  onMessage_: function(msg) {
    const name = msg.name;
    if (name == Channel.INTERNAL_REQUEST_MESSAGE) {
      const payload = msg.payload;
      const result = this.invokeMessageCallbacks_(payload);
      this.send({
        name: Channel.INTERNAL_REPLY_MESSAGE,
        requestId: msg.requestId,
        result: result
      });
    } else if (name == Channel.INTERNAL_REPLY_MESSAGE) {
      const callback = this.internalRequestCallbacks_[msg.requestId];
      delete this.internalRequestCallbacks_[msg.requestId];
      if (callback) {
        callback(msg.result);
      }
    } else {
      this.invokeMessageCallbacks_(msg);
    }
  }
};

/**
 * Class factory.
 * @return {Channel}
 */
Channel.create = function() {
  return new Channel();
};


const PostMessageChannel = (function() {
  /**
   * Allowed origins of the hosting page.
   * @type {Array<string>}
   */
  const ALLOWED_ORIGINS = ['chrome://oobe', 'chrome://chrome-signin'];

  /** @const */
  const PORT_MESSAGE = 'post-message-port-message';

  /** @const */
  const CHANNEL_INIT_MESSAGE = 'post-message-channel-init';

  /** @const */
  const CHANNEL_CONNECT_MESSAGE = 'post-message-channel-connect';

  /**
   * Whether the script runs in a top level window.
   */
  function isTopLevel() {
    return window === window.top;
  }

  /**
   * A simple event target.
   */
  function EventTarget() {
    this.listeners_ = [];
  }

  EventTarget.prototype = {
    /**
     * Add an event listener.
     */
    addListener: function(listener) {
      this.listeners_.push(listener);
    },

    /**
     * Dispatches a given event to all listeners.
     */
    dispatch: function(e) {
      for (let i = 0; i < this.listeners_.length; ++i) {
        this.listeners_[i].call(undefined, e);
      }
    }
  };

  /**
   * ChannelManager handles window message events by dispatching them to
   * PostMessagePorts or forwarding to other windows (up/down the hierarchy).
   * @constructor
   */
  function ChannelManager() {
    /**
     * Window and origin to forward message up the hierarchy. For subframes,
     * they defaults to window.parent and any origin. For top level window,
     * this would be set to the hosting webview on CHANNEL_INIT_MESSAGE.
     */
    this.upperWindow = isTopLevel() ? null : window.parent;
    this.upperOrigin = isTopLevel() ? '' : '*';

    /**
     * Channle Id to port map.
     * @type {Object<number, PostMessagePort>}
     */
    this.channels_ = {};

    /**
     * Deferred messages to be posted to |upperWindow|.
     * @type {Array}
     */
    this.deferredUpperWindowMessages_ = [];

    /**
     * Ports that depend on upperWindow and need to be setup when its available.
     */
    this.deferredUpperWindowPorts_ = [];

    /**
     * Whether the ChannelManager runs in daemon mode and accepts connections.
     */
    this.isDaemon = false;

    /**
     * Fires when ChannelManager is in listening mode and a
     * CHANNEL_CONNECT_MESSAGE is received.
     */
    this.onConnect = new EventTarget();

    window.addEventListener('message', this.onMessage_.bind(this));
  }

  ChannelManager.prototype = {
    /**
     * Gets a global unique id to use.
     * @return {number}
     */
    createChannelId_: function() {
      return (new Date()).getTime();
    },

    /**
     * Posts data to upperWindow. Queue it if upperWindow is not available.
     */
    postToUpperWindow: function(data) {
      if (this.upperWindow == null) {
        this.deferredUpperWindowMessages_.push(data);
        return;
      }

      this.upperWindow.postMessage(data, this.upperOrigin);
    },

    /**
     * Creates a port and register it in |channels_|.
     * @param {number} channelId
     * @param {string} channelName
     * @param {DOMWindow=} opt_targetWindow
     * @param {string=} opt_targetOrigin
     */
    createPort: function(
        channelId, channelName, opt_targetWindow, opt_targetOrigin) {
      const port = new PostMessagePort(channelId, channelName);
      if (opt_targetWindow) {
        port.setTarget(opt_targetWindow, opt_targetOrigin);
      }
      this.channels_[channelId] = port;
      return port;
    },

    /*
     * Returns a message forward handler for the given proxy port.
     * @private
     */
    getProxyPortForwardHandler_: function(proxyPort) {
      return function(msg) {
        proxyPort.postMessage(msg);
      };
    },

    /**
     * Creates a forwarding porxy port.
     * @param {number} channelId
     * @param {string} channelName
     * @param {!DOMWindow} targetWindow
     * @param {!string} targetOrigin
     */
    createProxyPort: function(
        channelId, channelName, targetWindow, targetOrigin) {
      const port =
          this.createPort(channelId, channelName, targetWindow, targetOrigin);
      port.onMessage.addListener(this.getProxyPortForwardHandler_(port));
      return port;
    },

    /**
     * Creates a connecting port to the daemon and request connection.
     * @param {string} name
     * @return {PostMessagePort}
     */
    connectToDaemon: function(name) {
      if (this.isDaemon) {
        console.error(
            'Error: Connecting from the daemon page is not supported.');
        return;
      }

      const port = this.createPort(this.createChannelId_(), name);
      if (this.upperWindow) {
        port.setTarget(this.upperWindow, this.upperOrigin);
      } else {
        this.deferredUpperWindowPorts_.push(port);
      }

      this.postToUpperWindow({
        type: CHANNEL_CONNECT_MESSAGE,
        channelId: port.channelId,
        channelName: port.name
      });
      return port;
    },

    /**
     * Dispatches a 'message' event to port.
     * @private
     */
    dispatchMessageToPort_: function(e) {
      const channelId = e.data.channelId;
      const port = this.channels_[channelId];
      if (!port) {
        console.error('Error: Unable to dispatch message. Unknown channel.');
        return;
      }

      port.handleWindowMessage(e);
    },

    /**
     * Window 'message' handler.
     */
    onMessage_: function(e) {
      if (typeof e.data != 'object' || !e.data.hasOwnProperty('type')) {
        return;
      }

      if (e.data.type === PORT_MESSAGE) {
        // Dispatch port message to ports if this is the daemon page or
        // the message is from upperWindow. In case of null upperWindow,
        // the message is assumed to be forwarded to upperWindow and queued.
        if (this.isDaemon ||
            (this.upperWindow && e.source === this.upperWindow)) {
          this.dispatchMessageToPort_(e);
        } else {
          this.postToUpperWindow(e.data);
        }
      } else if (e.data.type === CHANNEL_CONNECT_MESSAGE) {
        const channelId = e.data.channelId;
        const channelName = e.data.channelName;

        if (this.isDaemon) {
          const port =
              this.createPort(channelId, channelName, e.source, e.origin);
          this.onConnect.dispatch(port);
        } else {
          this.createProxyPort(channelId, channelName, e.source, e.origin);
          this.postToUpperWindow(e.data);
        }
      } else if (e.data.type === CHANNEL_INIT_MESSAGE) {
        if (ALLOWED_ORIGINS.indexOf(e.origin) == -1) {
          return;
        }

        this.upperWindow = e.source;
        this.upperOrigin = e.origin;

        for (let i = 0; i < this.deferredUpperWindowMessages_.length; ++i) {
          this.upperWindow.postMessage(
              this.deferredUpperWindowMessages_[i], this.upperOrigin);
        }
        this.deferredUpperWindowMessages_ = [];

        for (let i = 0; i < this.deferredUpperWindowPorts_.length; ++i) {
          this.deferredUpperWindowPorts_[i].setTarget(
              this.upperWindow, this.upperOrigin);
        }
        this.deferredUpperWindowPorts_ = [];
      }
    }
  };

  /**
   * Singleton instance of ChannelManager.
   * @type {ChannelManager}
   */
  const channelManager = new ChannelManager();

  /**
   * A HTML5 postMessage based port that provides the same port interface
   * as the messaging API port.
   * @param {number} channelId
   * @param {string} name
   */
  function PostMessagePort(channelId, name) {
    this.channelId = channelId;
    this.name = name;
    this.targetWindow = null;
    this.targetOrigin = '';
    this.deferredMessages_ = [];

    this.onMessage = new EventTarget();
  }

  PostMessagePort.prototype = {
    /**
     * Sets the target window and origin.
     * @param {DOMWindow} targetWindow
     * @param {string} targetOrigin
     */
    setTarget: function(targetWindow, targetOrigin) {
      this.targetWindow = targetWindow;
      this.targetOrigin = targetOrigin;

      for (let i = 0; i < this.deferredMessages_.length; ++i) {
        this.postMessage(this.deferredMessages_[i]);
      }
      this.deferredMessages_ = [];
    },

    postMessage: function(msg) {
      if (!this.targetWindow) {
        this.deferredMessages_.push(msg);
        return;
      }

      this.targetWindow.postMessage(
          {type: PORT_MESSAGE, channelId: this.channelId, payload: msg},
          this.targetOrigin);
    },

    handleWindowMessage: function(e) {
      this.onMessage.dispatch(e.data.payload);
    }
  };

  /**
   * A message channel based on PostMessagePort.
   * @extends {Channel}
   * @constructor
   */
  function PostMessageChannel() {
    Channel.apply(this, arguments);
  }

  PostMessageChannel.prototype = {
    __proto__: Channel.prototype,

    /** @override */
    connect: function(name) {
      this.port_ = channelManager.connectToDaemon(name);
      this.port_.onMessage.addListener(this.onMessage_.bind(this));
    },
  };

  /**
   * Initialize webview content window for postMessage channel.
   * @param {DOMWindow} webViewContentWindow Content window of the webview.
   */
  PostMessageChannel.init = function(webViewContentWindow) {
    webViewContentWindow.postMessage({type: CHANNEL_INIT_MESSAGE}, '*');
  };

  /**
   * Run in daemon mode and listen for incoming connections. Note that the
   * current implementation assumes the daemon runs in the hosting page
   * at the upper layer of the DOM tree. That is, all connect requests go
   * up the DOM tree instead of going into sub frames.
   * @param {function(PostMessagePort)} callback Invoked when a connection is
   *     made.
   */
  PostMessageChannel.runAsDaemon = function(callback) {
    channelManager.isDaemon = true;

    const onConnect = function(port) {
      callback(port);
    };
    channelManager.onConnect.addListener(onConnect);
  };

  return PostMessageChannel;
})();

/** @override */
Channel.create = function() {
  return new PostMessageChannel();
};

// // Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview
 * Provides WebviewEventManager which can register and keep track of listeners
 * on EventTargets and WebRequests, and unregister all listeners later.
 */
'use strict';

/**
 * Creates a new WebviewEventManager.
 */
function WebviewEventManager() {
  this.unbindWebviewCleanupFunctions_ = [];
}

WebviewEventManager.prototype = {
  /**
   * Adds a EventListener to |eventTarget| and adds a clean-up function so we
   * can remove the listener in unbindFromWebview.
   * @param {Object} webview the object to add the listener to
   * @param {string} type the event type
   * @param {Function} listener the event listener
   * @private
   */
  addEventListener: function(eventTarget, type, listener) {
    eventTarget.addEventListener(type, listener);
    this.unbindWebviewCleanupFunctions_.push(
        eventTarget.removeEventListener.bind(eventTarget, type, listener));
  },

  /**
   * Adds a listener to |webRequestEvent| and adds a clean-up function so we can
   * remove the listener in unbindFromWebview.
   * @param {Object} webRequestEvent the object to add the listener to
   * @param {string} type the event type
   * @param {Function} listener the event listener
   * @private
   */
  addWebRequestEventListener: function(
      webRequestEvent, listener, filter, extraInfoSpec) {
    webRequestEvent.addListener(listener, filter, extraInfoSpec);
    this.unbindWebviewCleanupFunctions_.push(
        webRequestEvent.removeListener.bind(webRequestEvent, listener));
  },

  /**
   * Unbinds this Authenticator from the currently bound webview.
   * @private
   */
  removeAllListeners: function() {
    for (let i = 0; i < this.unbindWebviewCleanupFunctions_.length; i++) {
      this.unbindWebviewCleanupFunctions_[i]();
    }
    this.unbindWebviewCleanupFunctions_ = [];
  }
};

/**
 * Class factory.
 * @return {WebviewEventManager}
 */
WebviewEventManager.create = function() {
  return new WebviewEventManager();
};


/**
 * @fileoverview Saml support for webview based auth.
 */

cr.define('cr.login', function() {
  'use strict';

  /**
   * The lowest version of the credentials passing API supported.
   * @type {number}
   */
  const MIN_API_VERSION_VERSION = 1;

  /**
   * The highest version of the credentials passing API supported.
   * @type {number}
   */
  const MAX_API_VERSION_VERSION = 1;

  /**
   * The key types supported by the credentials passing API.
   * @type {Array} Array of strings.
   */
  const API_KEY_TYPES = [
    'KEY_TYPE_PASSWORD_PLAIN',
  ];

  /** @const */
  const SAML_HEADER = 'google-accounts-saml';

  /** @const */
  const injectedScriptName = 'samlInjected';

  /**
   * The script to inject into webview and its sub frames.
   * @type {string}
   */
  const injectedJs = String.raw`
      // // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview
 * Provides a HTML5 postMessage channel to the injected JS to talk back
 * to Authenticator.
 */
'use strict';

// // Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Channel to the background script.
 */
function Channel() {
  this.messageCallbacks_ = {};
  this.internalRequestCallbacks_ = {};
}

/** @const */
Channel.INTERNAL_REQUEST_MESSAGE = 'internal-request-message';

/** @const */
Channel.INTERNAL_REPLY_MESSAGE = 'internal-reply-message';

Channel.prototype = {
  // Message port to use to communicate with background script.
  port_: null,

  // Registered message callbacks.
  messageCallbacks_: null,

  // Internal request id to track pending requests.
  nextInternalRequestId_: 0,

  // Pending internal request callbacks.
  internalRequestCallbacks_: null,

  /**
   * Initialize the channel with given port for the background script.
   */
  init: function(port) {
    this.port_ = port;
    this.port_.onMessage.addListener(this.onMessage_.bind(this));
  },

  /**
   * Connects to the background script with the given name.
   */
  connect: function(name) {
    this.port_ = chrome.runtime.connect({name: name});
    this.port_.onMessage.addListener(this.onMessage_.bind(this));
  },

  /**
   * Associates a message name with a callback. When a message with the name
   * is received, the callback will be invoked with the message as its arg.
   * Note only the last registered callback will be invoked.
   */
  registerMessage: function(name, callback) {
    this.messageCallbacks_[name] = callback;
  },

  /**
   * Sends a message to the other side of the channel.
   */
  send: function(msg) {
    this.port_.postMessage(msg);
  },

  /**
   * Sends a message to the other side and invokes the callback with
   * the replied object. Useful for message that expects a returned result.
   */
  sendWithCallback: function(msg, callback) {
    const requestId = this.nextInternalRequestId_++;
    this.internalRequestCallbacks_[requestId] = callback;
    this.send({
      name: Channel.INTERNAL_REQUEST_MESSAGE,
      requestId: requestId,
      payload: msg
    });
  },

  /**
   * Invokes message callback using given message.
   * @return {*} The return value of the message callback or null.
   */
  invokeMessageCallbacks_: function(msg) {
    const name = msg.name;
    if (this.messageCallbacks_[name]) {
      return this.messageCallbacks_[name](msg);
    }

    console.error('Error: Unexpected message, name=' + name);
    return null;
  },

  /**
   * Invoked when a message is received.
   */
  onMessage_: function(msg) {
    const name = msg.name;
    if (name == Channel.INTERNAL_REQUEST_MESSAGE) {
      const payload = msg.payload;
      const result = this.invokeMessageCallbacks_(payload);
      this.send({
        name: Channel.INTERNAL_REPLY_MESSAGE,
        requestId: msg.requestId,
        result: result
      });
    } else if (name == Channel.INTERNAL_REPLY_MESSAGE) {
      const callback = this.internalRequestCallbacks_[msg.requestId];
      delete this.internalRequestCallbacks_[msg.requestId];
      if (callback) {
        callback(msg.result);
      }
    } else {
      this.invokeMessageCallbacks_(msg);
    }
  }
};

/**
 * Class factory.
 * @return {Channel}
 */
Channel.create = function() {
  return new Channel();
};


const PostMessageChannel = (function() {
  /**
   * Allowed origins of the hosting page.
   * @type {Array<string>}
   */
  const ALLOWED_ORIGINS = ['chrome://oobe', 'chrome://chrome-signin'];

  /** @const */
  const PORT_MESSAGE = 'post-message-port-message';

  /** @const */
  const CHANNEL_INIT_MESSAGE = 'post-message-channel-init';

  /** @const */
  const CHANNEL_CONNECT_MESSAGE = 'post-message-channel-connect';

  /**
   * Whether the script runs in a top level window.
   */
  function isTopLevel() {
    return window === window.top;
  }

  /**
   * A simple event target.
   */
  function EventTarget() {
    this.listeners_ = [];
  }

  EventTarget.prototype = {
    /**
     * Add an event listener.
     */
    addListener: function(listener) {
      this.listeners_.push(listener);
    },

    /**
     * Dispatches a given event to all listeners.
     */
    dispatch: function(e) {
      for (let i = 0; i < this.listeners_.length; ++i) {
        this.listeners_[i].call(undefined, e);
      }
    }
  };

  /**
   * ChannelManager handles window message events by dispatching them to
   * PostMessagePorts or forwarding to other windows (up/down the hierarchy).
   * @constructor
   */
  function ChannelManager() {
    /**
     * Window and origin to forward message up the hierarchy. For subframes,
     * they defaults to window.parent and any origin. For top level window,
     * this would be set to the hosting webview on CHANNEL_INIT_MESSAGE.
     */
    this.upperWindow = isTopLevel() ? null : window.parent;
    this.upperOrigin = isTopLevel() ? '' : '*';

    /**
     * Channle Id to port map.
     * @type {Object<number, PostMessagePort>}
     */
    this.channels_ = {};

    /**
     * Deferred messages to be posted to |upperWindow|.
     * @type {Array}
     */
    this.deferredUpperWindowMessages_ = [];

    /**
     * Ports that depend on upperWindow and need to be setup when its available.
     */
    this.deferredUpperWindowPorts_ = [];

    /**
     * Whether the ChannelManager runs in daemon mode and accepts connections.
     */
    this.isDaemon = false;

    /**
     * Fires when ChannelManager is in listening mode and a
     * CHANNEL_CONNECT_MESSAGE is received.
     */
    this.onConnect = new EventTarget();

    window.addEventListener('message', this.onMessage_.bind(this));
  }

  ChannelManager.prototype = {
    /**
     * Gets a global unique id to use.
     * @return {number}
     */
    createChannelId_: function() {
      return (new Date()).getTime();
    },

    /**
     * Posts data to upperWindow. Queue it if upperWindow is not available.
     */
    postToUpperWindow: function(data) {
      if (this.upperWindow == null) {
        this.deferredUpperWindowMessages_.push(data);
        return;
      }

      this.upperWindow.postMessage(data, this.upperOrigin);
    },

    /**
     * Creates a port and register it in |channels_|.
     * @param {number} channelId
     * @param {string} channelName
     * @param {DOMWindow=} opt_targetWindow
     * @param {string=} opt_targetOrigin
     */
    createPort: function(
        channelId, channelName, opt_targetWindow, opt_targetOrigin) {
      const port = new PostMessagePort(channelId, channelName);
      if (opt_targetWindow) {
        port.setTarget(opt_targetWindow, opt_targetOrigin);
      }
      this.channels_[channelId] = port;
      return port;
    },

    /*
     * Returns a message forward handler for the given proxy port.
     * @private
     */
    getProxyPortForwardHandler_: function(proxyPort) {
      return function(msg) {
        proxyPort.postMessage(msg);
      };
    },

    /**
     * Creates a forwarding porxy port.
     * @param {number} channelId
     * @param {string} channelName
     * @param {!DOMWindow} targetWindow
     * @param {!string} targetOrigin
     */
    createProxyPort: function(
        channelId, channelName, targetWindow, targetOrigin) {
      const port =
          this.createPort(channelId, channelName, targetWindow, targetOrigin);
      port.onMessage.addListener(this.getProxyPortForwardHandler_(port));
      return port;
    },

    /**
     * Creates a connecting port to the daemon and request connection.
     * @param {string} name
     * @return {PostMessagePort}
     */
    connectToDaemon: function(name) {
      if (this.isDaemon) {
        console.error(
            'Error: Connecting from the daemon page is not supported.');
        return;
      }

      const port = this.createPort(this.createChannelId_(), name);
      if (this.upperWindow) {
        port.setTarget(this.upperWindow, this.upperOrigin);
      } else {
        this.deferredUpperWindowPorts_.push(port);
      }

      this.postToUpperWindow({
        type: CHANNEL_CONNECT_MESSAGE,
        channelId: port.channelId,
        channelName: port.name
      });
      return port;
    },

    /**
     * Dispatches a 'message' event to port.
     * @private
     */
    dispatchMessageToPort_: function(e) {
      const channelId = e.data.channelId;
      const port = this.channels_[channelId];
      if (!port) {
        console.error('Error: Unable to dispatch message. Unknown channel.');
        return;
      }

      port.handleWindowMessage(e);
    },

    /**
     * Window 'message' handler.
     */
    onMessage_: function(e) {
      if (typeof e.data != 'object' || !e.data.hasOwnProperty('type')) {
        return;
      }

      if (e.data.type === PORT_MESSAGE) {
        // Dispatch port message to ports if this is the daemon page or
        // the message is from upperWindow. In case of null upperWindow,
        // the message is assumed to be forwarded to upperWindow and queued.
        if (this.isDaemon ||
            (this.upperWindow && e.source === this.upperWindow)) {
          this.dispatchMessageToPort_(e);
        } else {
          this.postToUpperWindow(e.data);
        }
      } else if (e.data.type === CHANNEL_CONNECT_MESSAGE) {
        const channelId = e.data.channelId;
        const channelName = e.data.channelName;

        if (this.isDaemon) {
          const port =
              this.createPort(channelId, channelName, e.source, e.origin);
          this.onConnect.dispatch(port);
        } else {
          this.createProxyPort(channelId, channelName, e.source, e.origin);
          this.postToUpperWindow(e.data);
        }
      } else if (e.data.type === CHANNEL_INIT_MESSAGE) {
        if (ALLOWED_ORIGINS.indexOf(e.origin) == -1) {
          return;
        }

        this.upperWindow = e.source;
        this.upperOrigin = e.origin;

        for (let i = 0; i < this.deferredUpperWindowMessages_.length; ++i) {
          this.upperWindow.postMessage(
              this.deferredUpperWindowMessages_[i], this.upperOrigin);
        }
        this.deferredUpperWindowMessages_ = [];

        for (let i = 0; i < this.deferredUpperWindowPorts_.length; ++i) {
          this.deferredUpperWindowPorts_[i].setTarget(
              this.upperWindow, this.upperOrigin);
        }
        this.deferredUpperWindowPorts_ = [];
      }
    }
  };

  /**
   * Singleton instance of ChannelManager.
   * @type {ChannelManager}
   */
  const channelManager = new ChannelManager();

  /**
   * A HTML5 postMessage based port that provides the same port interface
   * as the messaging API port.
   * @param {number} channelId
   * @param {string} name
   */
  function PostMessagePort(channelId, name) {
    this.channelId = channelId;
    this.name = name;
    this.targetWindow = null;
    this.targetOrigin = '';
    this.deferredMessages_ = [];

    this.onMessage = new EventTarget();
  }

  PostMessagePort.prototype = {
    /**
     * Sets the target window and origin.
     * @param {DOMWindow} targetWindow
     * @param {string} targetOrigin
     */
    setTarget: function(targetWindow, targetOrigin) {
      this.targetWindow = targetWindow;
      this.targetOrigin = targetOrigin;

      for (let i = 0; i < this.deferredMessages_.length; ++i) {
        this.postMessage(this.deferredMessages_[i]);
      }
      this.deferredMessages_ = [];
    },

    postMessage: function(msg) {
      if (!this.targetWindow) {
        this.deferredMessages_.push(msg);
        return;
      }

      this.targetWindow.postMessage(
          {type: PORT_MESSAGE, channelId: this.channelId, payload: msg},
          this.targetOrigin);
    },

    handleWindowMessage: function(e) {
      this.onMessage.dispatch(e.data.payload);
    }
  };

  /**
   * A message channel based on PostMessagePort.
   * @extends {Channel}
   * @constructor
   */
  function PostMessageChannel() {
    Channel.apply(this, arguments);
  }

  PostMessageChannel.prototype = {
    __proto__: Channel.prototype,

    /** @override */
    connect: function(name) {
      this.port_ = channelManager.connectToDaemon(name);
      this.port_.onMessage.addListener(this.onMessage_.bind(this));
    },
  };

  /**
   * Initialize webview content window for postMessage channel.
   * @param {DOMWindow} webViewContentWindow Content window of the webview.
   */
  PostMessageChannel.init = function(webViewContentWindow) {
    webViewContentWindow.postMessage({type: CHANNEL_INIT_MESSAGE}, '*');
  };

  /**
   * Run in daemon mode and listen for incoming connections. Note that the
   * current implementation assumes the daemon runs in the hosting page
   * at the upper layer of the DOM tree. That is, all connect requests go
   * up the DOM tree instead of going into sub frames.
   * @param {function(PostMessagePort)} callback Invoked when a connection is
   *     made.
   */
  PostMessageChannel.runAsDaemon = function(callback) {
    channelManager.isDaemon = true;

    const onConnect = function(port) {
      callback(port);
    };
    channelManager.onConnect.addListener(onConnect);
  };

  return PostMessageChannel;
})();

/** @override */
Channel.create = function() {
  return new PostMessageChannel();
};

// // Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview
 * Script to be injected into SAML provider pages, serving three main purposes:
 * 1. Signal hosting extension that an external page is loaded so that the
 *    UI around it should be changed accordingly;
 * 2. Provide an API via which the SAML provider can pass user credentials to
 *    Chrome OS, allowing the password to be used for encrypting user data and
 *    offline login.
 * 3. Scrape password fields, making the password available to Chrome OS even if
 *    the SAML provider does not support the credential passing API.
 */

(function() {
function APICallForwarder() {}

/**
 * The credential passing API is used by sending messages to the SAML page's
 * |window| object. This class forwards API calls from the SAML page to a
 * background script and API responses from the background script to the SAML
 * page. Communication with the background script occurs via a |Channel|.
 */
APICallForwarder.prototype = {
  // Channel to which API calls are forwarded.
  channel_: null,

  /**
   * Initialize the API call forwarder.
   * @param {!Object} channel Channel to which API calls should be forwarded.
   */
  init: function(channel) {
    this.channel_ = channel;
    this.channel_.registerMessage(
        'apiResponse', this.onAPIResponse_.bind(this));

    window.addEventListener('message', this.onMessage_.bind(this));
  },

  onMessage_: function(event) {
    if (event.source != window || typeof event.data != 'object' ||
        !event.data.hasOwnProperty('type') ||
        event.data.type != 'gaia_saml_api') {
      return;
    }
    // Forward API calls to the background script.
    this.channel_.send({name: 'apiCall', call: event.data.call});
  },

  onAPIResponse_: function(msg) {
    // Forward API responses to the SAML page.
    window.postMessage(
        {type: 'gaia_saml_api_reply', response: msg.response}, '/');
  }
};

/**
 * A class to scrape password from type=password input elements under a given
 * docRoot and send them back via a Channel.
 */
function PasswordInputScraper() {}

PasswordInputScraper.prototype = {
  // URL of the page.
  pageURL_: null,

  // Channel to send back changed password.
  channel_: null,

  // An array to hold password fields.
  passwordFields_: null,

  // An array to hold cached password values.
  passwordValues_: null,

  // A MutationObserver to watch for dynamic password field creation.
  passwordFieldsObserver: null,

  /**
   * Initialize the scraper with given channel and docRoot. Note that the
   * scanning for password fields happens inside the function and does not
   * handle DOM tree changes after the call returns.
   * @param {!Object} channel The channel to send back password.
   * @param {!string} pageURL URL of the page.
   * @param {!HTMLElement} docRoot The root element of the DOM tree that
   *     contains the password fields of interest.
   */
  init: function(channel, pageURL, docRoot) {
    this.pageURL_ = pageURL;
    this.channel_ = channel;

    this.passwordFields_ = [];
    this.passwordValues_ = [];

    this.findAndTrackChildren(docRoot);

    this.passwordFieldsObserver = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        Array.prototype.forEach.call(mutation.addedNodes, function(addedNode) {
          if (addedNode.nodeType != Node.ELEMENT_NODE) {
            return;
          }

          if (addedNode.matches('input[type=password]')) {
            this.trackPasswordField(addedNode);
          } else {
            this.findAndTrackChildren(addedNode);
          }
        }.bind(this));
      }.bind(this));
    }.bind(this));
    this.passwordFieldsObserver.observe(
        docRoot, {subtree: true, childList: true});
  },

  /**
   * Find and track password fields that are descendants of the given element.
   * @param {!HTMLElement} element The parent element to search from.
   */
  findAndTrackChildren: function(element) {
    Array.prototype.forEach.call(
        element.querySelectorAll('input[type=password]'), function(field) {
          this.trackPasswordField(field);
        }.bind(this));
  },

  /**
   * Start tracking value changes of the given password field if it is
   * not being tracked yet.
   * @param {!HTMLInputElement} passworField The password field to track.
   */
  trackPasswordField: function(passwordField) {
    const existing = this.passwordFields_.filter(function(element) {
      return element === passwordField;
    });
    if (existing.length != 0) {
      return;
    }

    const index = this.passwordFields_.length;
    const fieldId = passwordField.id || passwordField.name || '';
    passwordField.addEventListener(
        'input', this.onPasswordChanged_.bind(this, index, fieldId));
    this.passwordFields_.push(passwordField);
    this.passwordValues_.push(passwordField.value);
  },

  /**
   * Check if the password field at |index| has changed. If so, sends back
   * the updated value.
   */
  maybeSendUpdatedPassword: function(index, fieldId) {
    const newValue = this.passwordFields_[index].value;
    if (newValue == this.passwordValues_[index]) {
      return;
    }

    this.passwordValues_[index] = newValue;

    // Use an invalid char for URL as delimiter to concatenate page url,
    // password field index and id to construct a unique ID for the password
    // field.
    const passwordId =
        this.pageURL_.split('#')[0].split('?')[0] + '|' + index + '|' + fieldId;
    this.channel_.send(
        {name: 'updatePassword', id: passwordId, password: newValue});
  },

  /**
   * Handles 'change' event in the scraped password fields.
   * @param {number} index The index of the password fields in
   *     |passwordFields_|.
   * @param {string} fieldId The id or name of the password field or blank.
   */
  onPasswordChanged_: function(index, fieldId) {
    this.maybeSendUpdatedPassword(index, fieldId);
  }
};

function onGetSAMLFlag(channel, isSAMLPage) {
  if (!isSAMLPage) {
    return;
  }
  const pageURL = window.location.href;

  channel.send({name: 'pageLoaded', url: pageURL});

  const initPasswordScraper = function() {
    const passwordScraper = new PasswordInputScraper();
    passwordScraper.init(channel, pageURL, document.documentElement);
  };

  if (document.readyState == 'loading') {
    window.addEventListener('readystatechange', function listener(event) {
      if (document.readyState == 'loading') {
        return;
      }
      initPasswordScraper();
      window.removeEventListener(event.type, listener, true);
    }, true);
  } else {
    initPasswordScraper();
  }
}

const channel = Channel.create();
channel.connect('injected');
channel.sendWithCallback(
    {name: 'getSAMLFlag'}, onGetSAMLFlag.bind(undefined, channel));

const apiCallForwarder = new APICallForwarder();
apiCallForwarder.init(channel);
})();


  `;

  /**
   * Creates a new URL by striping all query parameters.
   * @param {string} url The original URL.
   * @return {string} The new URL with all query parameters stripped.
   */
  function stripParams(url) {
    return url.substring(0, url.indexOf('?')) || url;
  }

  /**
   * Extract domain name from an URL.
   * @param {string} url An URL string.
   * @return {string} The host name of the URL.
   */
  function extractDomain(url) {
    const a = document.createElement('a');
    a.href = url;
    return a.hostname;
  }

  /**
   * A handler to provide saml support for the given webview that hosts the
   * auth IdP pages.
   */
  class SamlHandler extends cr.EventTarget {
    /** @param {webview} webview */
    constructor(webview) {
      super();

      /**
       * The webview that serves IdP pages.
       * @type {webview}
       */
      this.webview_ = webview;

      /**
       * Whether a Saml IdP page is display in the webview.
       * @type {boolean}
       */
      this.isSamlPage_ = false;

      /**
       * Pending Saml IdP page flag that is set when a SAML_HEADER is received
       * and is copied to |isSamlPage_| in loadcommit.
       * @type {boolean}
       */
      this.pendingIsSamlPage_ = false;

      /**
       * The last aborted top level url. It is recorded in loadabort event and
       * used to skip injection into Chrome's error page in the following
       * loadcommit event.
       * @type {string}
       */
      this.abortedTopLevelUrl_ = null;

      /**
       * The domain of the Saml IdP.
       * @type {string}
       */
      this.authDomain = '';

      /**
       * Scraped password stored in an id to password field value map.
       * @type {Object<string, string>}
       * @private
       */
      this.passwordStore_ = {};

      /**
       * Whether Saml API is initialized.
       * @type {boolean}
       */
      this.apiInitialized_ = false;

      /**
       * Saml API version to use.
       * @type {number}
       */
      this.apiVersion_ = 0;

      /**
       * Saml API token received.
       * @type {string}
       */
      this.apiToken_ = null;

      /**
       * Saml API password bytes.
       * @type {string}
       */
      this.apiPasswordBytes_ = null;

      /*
       * Whether to abort the authentication flow and show an error messagen
       * when content served over an unencrypted connection is detected.
       * @type {boolean}
       */
      this.blockInsecureContent = false;

      this.webviewEventManager_ = WebviewEventManager.create();

      this.webviewEventManager_.addEventListener(
          this.webview_, 'contentload', this.onContentLoad_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'loadabort', this.onLoadAbort_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'loadcommit', this.onLoadCommit_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'permissionrequest',
          this.onPermissionRequest_.bind(this));

      this.webviewEventManager_.addWebRequestEventListener(
          this.webview_.request.onBeforeRequest,
          this.onInsecureRequest.bind(this),
          {urls: ['http://*/*', 'file://*/*', 'ftp://*/*']}, ['blocking']);
      this.webviewEventManager_.addWebRequestEventListener(
          this.webview_.request.onHeadersReceived,
          this.onHeadersReceived_.bind(this),
          {urls: ['<all_urls>'], types: ['main_frame', 'xmlhttprequest']},
          ['blocking', 'responseHeaders']);

      this.webview_.addContentScripts([{
        name: injectedScriptName,
        matches: ['http://*/*', 'https://*/*'],
        js: {code: injectedJs},
        all_frames: true,
        run_at: 'document_start'
      }]);

      PostMessageChannel.runAsDaemon(this.onConnected_.bind(this));
    }

    /**
     * Whether Saml API is used during auth.
     * @return {boolean}
     */
    get samlApiUsed() {
      return !!this.apiPasswordBytes_;
    }

    /**
     * Returns the Saml API password bytes.
     * @return {string}
     */
    get apiPasswordBytes() {
      return this.apiPasswordBytes_;
    }

    /**
     * Returns the first scraped password if any, or an empty string otherwise.
     * @return {string}
     */
    get firstScrapedPassword() {
      const scraped = this.getConsolidatedScrapedPasswords_();
      return scraped.length ? scraped[0] : '';
    }

    /**
     * Returns the number of scraped passwords.
     * @return {number}
     */
    get scrapedPasswordCount() {
      return this.getConsolidatedScrapedPasswords_().length;
    }

    /**
     * Gets the de-duped scraped passwords.
     * @return {Array<string>}
     * @private
     */
    getConsolidatedScrapedPasswords_() {
      const passwords = {};
      for (const property in this.passwordStore_) {
        passwords[this.passwordStore_[property]] = true;
      }
      return Object.keys(passwords);
    }

    /**
     * Removes the injected content script and unbinds all listeners from the
     * webview passed to the constructor. This SAMLHandler will be unusable
     * after this function returns.
     */
    unbindFromWebview() {
      this.webview_.removeContentScripts([injectedScriptName]);
      this.webviewEventManager_.removeAllListeners();
    }

    /**
     * Resets all auth states
     */
    reset() {
      this.isSamlPage_ = false;
      this.pendingIsSamlPage_ = false;
      this.passwordStore_ = {};

      this.apiInitialized_ = false;
      this.apiVersion_ = 0;
      this.apiToken_ = null;
      this.apiPasswordBytes_ = null;
    }

    /**
     * Check whether the given |password| is in the scraped passwords.
     * @return {boolean} True if the |password| is found.
     */
    verifyConfirmedPassword(password) {
      return this.getConsolidatedScrapedPasswords_().indexOf(password) >= 0;
    }

    /**
     * Invoked on the webview's contentload event.
     * @private
     */
    onContentLoad_(e) {
      // |this.webview_.contentWindow| may be null after network error screen
      // is shown. See crbug.com/770999.
      if (this.webview_.contentWindow) {
        PostMessageChannel.init(this.webview_.contentWindow);
      } else {
        console.error('SamlHandler.onContentLoad_: contentWindow is null.');
      }
    }

    /**
     * Invoked on the webview's loadabort event.
     * @private
     */
    onLoadAbort_(e) {
      if (e.isTopLevel) {
        this.abortedTopLevelUrl_ = e.url;
      }
    }

    /**
     * Invoked on the webview's loadcommit event for both main and sub frames.
     * @private
     */
    onLoadCommit_(e) {
      // Skip this loadcommit if the top level load is just aborted.
      if (e.isTopLevel && e.url === this.abortedTopLevelUrl_) {
        this.abortedTopLevelUrl_ = null;
        return;
      }

      // Skip for none http/https url.
      if (!e.url.startsWith('https://') && !e.url.startsWith('http://')) {
        return;
      }

      this.isSamlPage_ = this.pendingIsSamlPage_;
    }

    /**
     * Handler for webRequest.onBeforeRequest, invoked when content served over
     * an unencrypted connection is detected. Determines whether the request
     * should be blocked and if so, signals that an error message needs to be
     * shown.
     * @param {Object} details
     * @return {!Object} Decision whether to block the request.
     */
    onInsecureRequest(details) {
      if (!this.blockInsecureContent) {
        return {};
      }
      const strippedUrl = stripParams(details.url);
      this.dispatchEvent(new CustomEvent(
          'insecureContentBlocked', {detail: {url: strippedUrl}}));
      return {cancel: true};
    }

    /**
     * Invoked when headers are received for the main frame.
     * @private
     */
    onHeadersReceived_(details) {
      const headers = details.responseHeaders;

      // Check whether GAIA headers indicating the start or end of a SAML
      // redirect are present.
      for (let i = 0; headers && i < headers.length; ++i) {
        const header = headers[i];
        const headerName = header.name.toLowerCase();

        if (headerName == SAML_HEADER) {
          const action = header.value.toLowerCase();
          if (action == 'start') {
            this.pendingIsSamlPage_ = true;
          } else if (action == 'end') {
            this.pendingIsSamlPage_ = false;
          }
        }
      }

      return {};
    }

    /**
     * Invoked when the injected JS makes a connection.
     */
    onConnected_(port) {
      if (port.targetWindow != this.webview_.contentWindow) {
        return;
      }

      const channel = Channel.create();
      channel.init(port);

      channel.registerMessage('apiCall', this.onAPICall_.bind(this, channel));
      channel.registerMessage(
          'updatePassword', this.onUpdatePassword_.bind(this, channel));
      channel.registerMessage(
          'pageLoaded', this.onPageLoaded_.bind(this, channel));
      channel.registerMessage(
          'getSAMLFlag', this.onGetSAMLFlag_.bind(this, channel));
    }

    sendInitializationSuccess_(channel) {
      channel.send({
        name: 'apiResponse',
        response: {
          result: 'initialized',
          version: this.apiVersion_,
          keyTypes: API_KEY_TYPES
        }
      });
    }

    sendInitializationFailure_(channel) {
      channel.send(
          {name: 'apiResponse', response: {result: 'initialization_failed'}});
    }

    /**
     * Handlers for channel messages.
     * @param {Channel} channel A channel to send back response.
     * @param {Object} msg Received message.
     * @private
     */
    onAPICall_(channel, msg) {
      const call = msg.call;
      if (call.method == 'initialize') {
        if (!Number.isInteger(call.requestedVersion) ||
            call.requestedVersion < MIN_API_VERSION_VERSION) {
          this.sendInitializationFailure_(channel);
          return;
        }

        this.apiVersion_ =
            Math.min(call.requestedVersion, MAX_API_VERSION_VERSION);
        this.apiInitialized_ = true;
        this.sendInitializationSuccess_(channel);
        return;
      }

      if (call.method == 'add') {
        if (API_KEY_TYPES.indexOf(call.keyType) == -1) {
          console.error('SamlHandler.onAPICall_: unsupported key type');
          return;
        }
        // Not setting |email_| and |gaiaId_| because this API call will
        // eventually be followed by onCompleteLogin_() which does set it.
        this.apiToken_ = call.token;
        this.apiPasswordBytes_ = call.passwordBytes;

        this.dispatchEvent(new CustomEvent('apiPasswordAdded'));
      } else if (call.method == 'confirm') {
        if (call.token != this.apiToken_) {
          console.error('SamlHandler.onAPICall_: token mismatch');
        }
      } else {
        console.error('SamlHandler.onAPICall_: unknown message');
      }
    }

    onUpdatePassword_(channel, msg) {
      if (this.isSamlPage_) {
        this.passwordStore_[msg.id] = msg.password;
      }
    }

    onPageLoaded_(channel, msg) {
      this.authDomain = extractDomain(msg.url);
      this.dispatchEvent(new CustomEvent('authPageLoaded', {
        detail: {
          url: msg.url,
          isSAMLPage: this.isSamlPage_,
          domain: this.authDomain
        }
      }));
    }

    onPermissionRequest_(permissionEvent) {
      if (permissionEvent.permission === 'media') {
        // The actual permission check happens in
        // WebUILoginView::RequestMediaAccessPermission().
        this.dispatchEvent(new CustomEvent('videoEnabled'));
        permissionEvent.request.allow();
      }
    }

    onGetSAMLFlag_(channel, msg) {
      return this.isSamlPage_;
    }
  }

  return {SamlHandler: SamlHandler};
});

// Note: webview_event_manager.js is already included by saml_handler.js.

/**
 * @fileoverview An UI component to authenciate to Chrome. The component hosts
 * IdP web pages in a webview. A client who is interested in monitoring
 * authentication events should pass a listener object of type
 * cr.login.GaiaAuthHost.Listener as defined in this file. After initialization,
 * call {@code load} to start the authentication flow.
 *
 * See go/cros-auth-design for details on Google API.
 */

cr.define('cr.login', function() {
  'use strict';

  // TODO(rogerta): should use gaia URL from GaiaUrls::gaia_url() instead
  // of hardcoding the prod URL here.  As is, this does not work with staging
  // environments.
  const IDP_ORIGIN = 'https://accounts.google.com/';
  const IDP_PATH = 'ServiceLogin?skipvpage=true&sarp=1&rm=hide';
  const CONTINUE_URL =
      'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/success.html';
  const SIGN_IN_HEADER = 'google-accounts-signin';
  const EMBEDDED_FORM_HEADER = 'google-accounts-embedded';
  const LOCATION_HEADER = 'location';
  const SERVICE_ID = 'chromeoslogin';
  const EMBEDDED_SETUP_CHROMEOS_ENDPOINT = 'embedded/setup/chromeos';
  const EMBEDDED_SETUP_CHROMEOS_ENDPOINT_V2 = 'embedded/setup/v2/chromeos';
  const SAML_REDIRECTION_PATH = 'samlredirect';
  const BLANK_PAGE_URL = 'about:blank';

  /**
   * The source URL parameter for the constrained signin flow.
   */
  const CONSTRAINED_FLOW_SOURCE = 'chrome';

  /**
   * Enum for the authorization mode, must match AuthMode defined in
   * chrome/browser/ui/webui/inline_login_ui.cc.
   * @enum {number}
   */
  const AuthMode = {DEFAULT: 0, OFFLINE: 1, DESKTOP: 2};

  /**
   * Enum for the authorization type.
   * @enum {number}
   */
  const AuthFlow = {DEFAULT: 0, SAML: 1};

  /**
   * Supported Authenticator params.
   * @type {!Array<string>}
   * @const
   */
  const SUPPORTED_PARAMS = [
    'gaiaId',        // Obfuscated GAIA ID to skip the email prompt page
                     // during the re-auth flow.
    'gaiaUrl',       // Gaia url to use.
    'gaiaPath',      // Gaia path to use without a leading slash.
    'hl',            // Language code for the user interface.
    'service',       // Name of Gaia service.
    'continueUrl',   // Continue url to use.
    'frameUrl',      // Initial frame URL to use. If empty defaults to
                     // gaiaUrl.
    'constrained',   // Whether the extension is loaded in a constrained
                     // window.
    'clientId',      // Chrome client id.
    'needPassword',  // Whether the host is interested in getting a password.
                     // If this set to |false|, |confirmPasswordCallback| is
                     // not called before dispatching |authCopleted|.
                     // Default is |true|.
    'flow',          // One of 'default', 'enterprise', or 'theftprotection'.
    'enterpriseDisplayDomain',     // Current domain name to be displayed.
    'enterpriseEnrollmentDomain',  // Domain in which hosting device is (or
                                   // should be) enrolled.
    'emailDomain',                 // Value used to prefill domain for email.
    'chromeType',                // Type of Chrome OS device, e.g. "chromebox".
    'clientVersion',             // Version of the Chrome build.
    'platformVersion',           // Version of the OS build.
    'releaseChannel',            // Installation channel.
    'endpointGen',               // Current endpoint generation.
    'chromeOSApiVersion',        // GAIA Chrome OS API version
    'menuGuestMode',             // Enables "Guest mode" menu item
    'menuKeyboardOptions',       // Enables "Keyboard options" menu item
    'menuEnterpriseEnrollment',  // Enables "Enterprise enrollment" menu item.
    'lsbReleaseBoard',           // Chrome OS Release board name
    'isFirstUser',               // True if this is non-enterprise device,
                                 // and there are no users yet.
    'obfuscatedOwnerId',         // Obfuscated device owner ID, if neeed.

    // The email fields allow for the following possibilities:
    //
    // 1/ If 'email' is not supplied, then the email text field is blank and the
    // user must type an email to proceed.
    //
    // 2/ If 'email' is supplied, and 'readOnlyEmail' is truthy, then the email
    // is hardcoded and the user cannot change it.  The user is asked for
    // password.  This is useful for re-auth scenarios, where chrome needs the
    // user to authenticate for a specific account and only that account.
    //
    // 3/ If 'email' is supplied, and 'readOnlyEmail' is falsy, gaia will
    // prefill the email text field using the given email address, but the user
    // can still change it and then proceed.  This is used on desktop when the
    // user disconnects their profile then reconnects, to encourage them to use
    // the same account.
    'email',
    'readOnlyEmail',
    'realm',
  ];

  /**
   * Initializes the authenticator component.
   */
  class Authenticator extends cr.EventTarget {
    /**
     * @param {webview|string} webview The webview element or its ID to host
     *     IdP web pages.
     */
    constructor(webview) {
      super();

      this.isLoaded_ = false;
      this.email_ = null;
      this.password_ = null;
      this.gaiaId_ = null, this.sessionIndex_ = null;
      this.chooseWhatToSync_ = false;
      this.skipForNow_ = false;
      this.authFlow = AuthFlow.DEFAULT;
      this.authDomain = '';
      this.videoEnabled = false;
      this.idpOrigin_ = null;
      this.continueUrl_ = null;
      this.continueUrlWithoutParams_ = null;
      this.initialFrameUrl_ = null;
      this.reloadUrl_ = null;
      this.trusted_ = true;
      this.readyFired_ = false;
      this.webviewEventManager_ = WebviewEventManager.create();

      this.clientId_ = null;

      this.confirmPasswordCallback = null;
      this.noPasswordCallback = null;
      this.insecureContentBlockedCallback = null;
      this.samlApiUsedCallback = null;
      this.missingGaiaInfoCallback = null;
      /**
       * Callback allowing to request whether the specified user which
       * authenticates via SAML is a user without a password (neither a manually
       * entered one nor one provided via Credentials Passing API).
       * @type {function(string, string, function(boolean))} Arguments are the
       * e-mail, the GAIA ID, and the response callback.
       */
      this.getIsSamlUserPasswordlessCallback = null;
      this.needPassword = true;
      this.services_ = null;
      /**
       * Caches the result of |getIsSamlUserPasswordlessCallback| invocation for
       * the current user. Null if no result is obtained yet.
       * @type {?boolean}
       * @private
       */
      this.isSamlUserPasswordless_ = null;

      this.bindToWebview_(webview);

      window.addEventListener(
          'message', this.onMessageFromWebview_.bind(this), false);
      window.addEventListener('focus', this.onFocus_.bind(this), false);
      window.addEventListener('popstate', this.onPopState_.bind(this), false);
    }

    /**
     * Reinitializes authentication parameters so that a failed login attempt
     * would not result in an infinite loop.
     */
    resetStates() {
      this.isLoaded_ = false;
      this.email_ = null;
      this.gaiaId_ = null;
      this.password_ = null;
      this.readyFired_ = false;
      this.chooseWhatToSync_ = false;
      this.skipForNow_ = false;
      this.sessionIndex_ = null;
      this.trusted_ = true;
      this.authFlow = AuthFlow.DEFAULT;
      this.samlHandler_.reset();
      this.videoEnabled = false;
      this.services_ = null;
      this.isSamlUserPasswordless_ = null;
    }

    /**
     * Resets the webview to the blank page.
     */
    resetWebview() {
      if (this.webview_.src && this.webview_.src != BLANK_PAGE_URL) {
        this.webview_.src = BLANK_PAGE_URL;
      }
    }

    /**
     * Binds this authenticator to the passed webview.
     * @param {!Object} webview the new webview to be used by this
     *     Authenticator.
     * @private
     */
    bindToWebview_(webview) {
      assert(!this.webview_);
      assert(!this.samlHandler_);

      this.webview_ = typeof webview == 'string' ? $(webview) : webview;

      this.samlHandler_ = new cr.login.SamlHandler(this.webview_);
      this.webviewEventManager_.addEventListener(
          this.samlHandler_, 'insecureContentBlocked',
          this.onInsecureContentBlocked_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.samlHandler_, 'authPageLoaded',
          this.onAuthPageLoaded_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.samlHandler_, 'videoEnabled', this.onVideoEnabled_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.samlHandler_, 'apiPasswordAdded',
          this.onSamlApiPasswordAdded_.bind(this));

      this.webviewEventManager_.addEventListener(
          this.webview_, 'droplink', this.onDropLink_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'newwindow', this.onNewWindow_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'contentload', this.onContentLoad_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'loadabort', this.onLoadAbort_.bind(this));
      this.webviewEventManager_.addEventListener(
          this.webview_, 'loadcommit', this.onLoadCommit_.bind(this));

      this.webviewEventManager_.addWebRequestEventListener(
          this.webview_.request.onCompleted,
          this.onRequestCompleted_.bind(this),
          {urls: ['<all_urls>'], types: ['main_frame']}, ['responseHeaders']);
      this.webviewEventManager_.addWebRequestEventListener(
          this.webview_.request.onHeadersReceived,
          this.onHeadersReceived_.bind(this),
          {urls: ['<all_urls>'], types: ['main_frame', 'xmlhttprequest']},
          ['responseHeaders']);
    }

    /**
     * Unbinds this Authenticator from the currently bound webview.
     * @private
     */
    unbindFromWebview_() {
      assert(this.webview_);
      assert(this.samlHandler_);

      this.webviewEventManager_.removeAllListeners();

      this.webview_ = undefined;
      this.samlHandler_.unbindFromWebview();
      this.samlHandler_ = undefined;
    }

    /**
     * Re-binds to another webview.
     * @param {Object} webview the new webview to be used by this Authenticator.
     */
    rebindWebview(webview) {
      this.unbindFromWebview_();
      this.bindToWebview_(webview);
    }

    /**
     * Loads the authenticator component with the given parameters.
     * @param {AuthMode} authMode Authorization mode.
     * @param {Object} data Parameters for the authorization flow.
     */
    load(authMode, data) {
      this.authMode = authMode;
      this.resetStates();
      // gaiaUrl parameter is used for testing. Once defined, it is never
      // changed.
      this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN;
      this.continueUrl_ = data.continueUrl || CONTINUE_URL;
      this.continueUrlWithoutParams_ =
          this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) ||
          this.continueUrl_;
      this.isConstrainedWindow_ = data.constrained == '1';
      this.isNewGaiaFlow = data.isNewGaiaFlow;
      this.clientId_ = data.clientId;
      this.dontResizeNonEmbeddedPages = data.dontResizeNonEmbeddedPages;
      this.chromeOSApiVersion_ = data.chromeOSApiVersion;

      this.initialFrameUrl_ = this.constructInitialFrameUrl_(data);
      this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_;
      // Don't block insecure content for desktop flow because it lands on
      // http. Otherwise, block insecure content as long as gaia is https.
      this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP &&
          this.idpOrigin_.startsWith('https://');
      this.needPassword = !('needPassword' in data) || data.needPassword;

      if (this.isNewGaiaFlow) {
        this.webview_.contextMenus.onShow.addListener(function(e) {
          e.preventDefault();
        });
      }

      this.webview_.src = this.reloadUrl_;
      this.isLoaded_ = true;
    }

    constructChromeOSAPIUrl_() {
      if (this.chromeOSApiVersion_ && this.chromeOSApiVersion_ == 2) {
        return this.idpOrigin_ + EMBEDDED_SETUP_CHROMEOS_ENDPOINT_V2;
      }

      return this.idpOrigin_ + EMBEDDED_SETUP_CHROMEOS_ENDPOINT;
    }

    /**
     * Reloads the authenticator component.
     */
    reload() {
      this.resetStates();
      this.webview_.src = this.reloadUrl_;
      this.isLoaded_ = true;
    }

    constructInitialFrameUrl_(data) {
      if (data.doSamlRedirect) {
        let url = this.idpOrigin_ + SAML_REDIRECTION_PATH;
        url = appendParam(url, 'domain', data.enterpriseEnrollmentDomain);
        url = appendParam(
            url, 'continue',
            data.gaiaUrl + 'programmatic_auth_chromeos?hl=' + data.hl +
                '&scope=https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthLogin&' +
                'client_id=' + encodeURIComponent(data.clientId) +
                '&access_type=offline');

        return url;
      }

      let url;
      if (data.gaiaPath) {
        url = this.idpOrigin_ + data.gaiaPath;
      } else if (this.isNewGaiaFlow) {
        url = this.constructChromeOSAPIUrl_();
      } else {
        url = this.idpOrigin_ + IDP_PATH;
      }

      if (this.isNewGaiaFlow) {
        if (data.chromeType) {
          url = appendParam(url, 'chrometype', data.chromeType);
        }
        if (data.clientId) {
          url = appendParam(url, 'client_id', data.clientId);
        }
        if (data.enterpriseDisplayDomain) {
          url = appendParam(url, 'manageddomain', data.enterpriseDisplayDomain);
        }
        if (data.clientVersion) {
          url = appendParam(url, 'client_version', data.clientVersion);
        }
        if (data.platformVersion) {
          url = appendParam(url, 'platform_version', data.platformVersion);
        }
        if (data.releaseChannel) {
          url = appendParam(url, 'release_channel', data.releaseChannel);
        }
        if (data.endpointGen) {
          url = appendParam(url, 'endpoint_gen', data.endpointGen);
        }
        if (data.chromeOSApiVersion == 2) {
          let mi = '';
          if (data.menuGuestMode) {
            mi += 'gm,';
          }
          if (data.menuKeyboardOptions) {
            mi += 'ko,';
          }
          if (data.menuEnterpriseEnrollment) {
            mi += 'ee,';
          }
          if (mi.length) {
            url = appendParam(url, 'mi', mi);
          }

          if (data.lsbReleaseBoard) {
            url = appendParam(url, 'chromeos_board', data.lsbReleaseBoard);
          }
          if (data.isFirstUser) {
            url = appendParam(url, 'is_first_user', true);
          }
          if (data.obfuscatedOwnerId) {
            url =
                appendParam(url, 'obfuscated_owner_id', data.obfuscatedOwnerId);
          }
        }
      } else {
        url = appendParam(url, 'continue', this.continueUrl_);
        url = appendParam(url, 'service', data.service || SERVICE_ID);
      }
      if (data.hl) {
        url = appendParam(url, 'hl', data.hl);
      }
      if (data.gaiaId) {
        url = appendParam(url, 'user_id', data.gaiaId);
      }
      if (data.email) {
        if (data.readOnlyEmail) {
          url = appendParam(url, 'Email', data.email);
        } else {
          url = appendParam(url, 'email_hint', data.email);
        }
      }
      if (this.isConstrainedWindow_) {
        url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE);
      }
      if (data.flow) {
        url = appendParam(url, 'flow', data.flow);
      }
      if (data.emailDomain) {
        url = appendParam(url, 'emaildomain', data.emailDomain);
        // ChromeOS embedded signin page uses 'hd' (hosted domain) as the query
        // argument to show an email domain.
        url = appendParam(url, 'hd', data.emailDomain);
      }
      return url;
    }

    /**
     * Dispatches the 'ready' event if it hasn't been dispatched already for the
     * current content.
     * @private
     */
    fireReadyEvent_() {
      if (!this.readyFired_) {
        this.dispatchEvent(new Event('ready'));
        this.readyFired_ = true;
      }
    }

    /**
     * Invoked when a main frame request in the webview has completed.
     * @private
     */
    onRequestCompleted_(details) {
      const currentUrl = details.url;

      if (!this.isNewGaiaFlow &&
          currentUrl.lastIndexOf(this.continueUrlWithoutParams_, 0) == 0) {
        if (currentUrl.indexOf('ntp=1') >= 0) {
          this.skipForNow_ = true;
        }

        this.maybeCompleteAuth_();
        return;
      }

      if (!currentUrl.startsWith('https')) {
        this.trusted_ = false;
      }

      if (this.isConstrainedWindow_) {
        let isEmbeddedPage = false;
        if (this.idpOrigin_ && currentUrl.lastIndexOf(this.idpOrigin_) == 0) {
          const headers = details.responseHeaders;
          for (let i = 0; headers && i < headers.length; ++i) {
            if (headers[i].name.toLowerCase() == EMBEDDED_FORM_HEADER) {
              isEmbeddedPage = true;
              break;
            }
          }
        }

        // In some cases, non-embedded pages should not be resized.  For
        // example, on desktop when reauthenticating for purposes of unlocking
        // a profile, resizing would cause a browser window to open in the
        // system profile, which is not allowed.
        if (!isEmbeddedPage && !this.dontResizeNonEmbeddedPages) {
          this.dispatchEvent(new CustomEvent('resize', {detail: currentUrl}));
          return;
        }
      }

      this.updateHistoryState_(currentUrl);
    }

    /**
     * Manually updates the history. Invoked upon completion of a webview
     * navigation.
     * @param {string} url Request URL.
     * @private
     */
    updateHistoryState_(url) {
      if (history.state && history.state.url != url) {
        history.pushState({url: url}, '');
      } else {
        history.replaceState({url: url}, '');
      }
    }

    /**
     * Invoked when the sign-in page takes focus.
     * @param {object} e The focus event being triggered.
     * @private
     */
    onFocus_(e) {
      if (this.authMode == AuthMode.DESKTOP &&
          document.activeElement == document.body) {
        this.webview_.focus();
      }
    }

    /**
     * Invoked when the history state is changed.
     * @param {object} e The popstate event being triggered.
     * @private
     */
    onPopState_(e) {
      const state = e.state;
      if (state && state.url) {
        this.webview_.src = state.url;
      }
    }

    /**
     * Invoked when headers are received in the main frame of the webview. It
     * 1) reads the authenticated user info from a signin header,
     * 2) signals the start of a saml flow upon receiving a saml header.
     * @return {!Object} Modified request headers.
     * @private
     */
    onHeadersReceived_(details) {
      const currentUrl = details.url;
      if (currentUrl.lastIndexOf(this.idpOrigin_, 0) != 0) {
        return;
      }

      const headers = details.responseHeaders;
      for (let i = 0; headers && i < headers.length; ++i) {
        const header = headers[i];
        const headerName = header.name.toLowerCase();
        if (headerName == SIGN_IN_HEADER) {
          const headerValues = header.value.toLowerCase().split(',');
          const signinDetails = {};
          headerValues.forEach(function(e) {
            const pair = e.split('=');
            signinDetails[pair[0].trim()] = pair[1].trim();
          });
          // Removes "" around.
          this.email_ = signinDetails['email'].slice(1, -1);
          this.gaiaId_ = signinDetails['obfuscatedid'].slice(1, -1);
          this.sessionIndex_ = signinDetails['sessionindex'];
          this.isSamlUserPasswordless_ = null;
        } else if (headerName == LOCATION_HEADER) {
          // If the "choose what to sync" checkbox was clicked, then the
          // continue URL will contain a source=3 field.
          const location = decodeURIComponent(header.value);
          this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/);
        }
      }
    }

    /**
     * Returns true if given HTML5 message is received from the webview element.
     * @param {object} e Payload of the received HTML5 message.
     */
    isGaiaMessage(e) {
      if (!this.isWebviewEvent_(e)) {
        return false;
      }

      // The event origin does not have a trailing slash.
      if (e.origin !=
          this.idpOrigin_.substring(0, this.idpOrigin_.length - 1)) {
        return false;
      }

      // Gaia messages must be an object with 'method' property.
      if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) {
        return false;
      }
      return true;
    }

    /**
     * Invoked when an HTML5 message is received from the webview element.
     * @param {object} e Payload of the received HTML5 message.
     * @private
     */
    onMessageFromWebview_(e) {
      if (!this.isGaiaMessage(e)) {
        return;
      }

      const msg = e.data;
      if (msg.method == 'attemptLogin') {
        this.email_ = msg.email;
        if (this.authMode == AuthMode.DESKTOP) {
          this.password_ = msg.password;
        }
        this.isSamlUserPasswordless_ = null;

        this.chooseWhatToSync_ = msg.chooseWhatToSync;
        // We need to dispatch only first event, before user enters password.
        this.dispatchEvent(
            new CustomEvent('attemptLogin', {detail: msg.email}));
      } else if (msg.method == 'dialogShown') {
        this.dispatchEvent(new Event('dialogShown'));
      } else if (msg.method == 'dialogHidden') {
        this.dispatchEvent(new Event('dialogHidden'));
      } else if (msg.method == 'backButton') {
        this.dispatchEvent(new CustomEvent('backButton', {detail: msg.show}));
      } else if (msg.method == 'showView') {
        this.dispatchEvent(new Event('showView'));
      } else if (msg.method == 'menuItemClicked') {
        this.dispatchEvent(
            new CustomEvent('menuItemClicked', {detail: msg.item}));
      } else if (msg.method == 'identifierEntered') {
        this.dispatchEvent(new CustomEvent(
            'identifierEntered',
            {detail: {accountIdentifier: msg.accountIdentifier}}));
      } else if (msg.method == 'userInfo') {
        this.services_ = msg.services;
        if (this.email_ && this.gaiaId_ && this.sessionIndex_) {
          this.maybeCompleteAuth_();
        }
      } else {
        console.warn('Unrecognized message from GAIA: ' + msg.method);
      }
    }

    /**
     * Invoked by the hosting page to verify the Saml password.
     */
    verifyConfirmedPassword(password) {
      if (!this.samlHandler_.verifyConfirmedPassword(password)) {
        // Invoke confirm password callback asynchronously because the
        // verification was based on messages and caller (GaiaSigninScreen)
        // does not expect it to be called immediately.
        // TODO(xiyuan): Change to synchronous call when iframe based code
        // is removed.
        const invokeConfirmPassword =
            (function() {
              this.confirmPasswordCallback(
                  this.email_, this.samlHandler_.scrapedPasswordCount);
            }).bind(this);
        window.setTimeout(invokeConfirmPassword, 0);
        return;
      }

      this.password_ = password;
      this.onAuthCompleted_();
    }

    /**
     * Check Saml flow and start password confirmation flow if needed.
     * Otherwise, continue with auto completion.
     * @private
     */
    maybeCompleteAuth_() {
      const missingGaiaInfo =
          !this.email_ || !this.gaiaId_ || !this.sessionIndex_;
      if (missingGaiaInfo && !this.skipForNow_) {
        if (this.missingGaiaInfoCallback) {
          this.missingGaiaInfoCallback();
        }

        this.webview_.src = this.initialFrameUrl_;
        return;
      }
      // TODO(https://crbug.com/837107): remove this once API is fully
      // stabilized.
      // @example.com is used in tests.
      if (!this.services_ && !this.email_.endsWith('@gmail.com') &&
          !this.email_.endsWith('@example.com')) {
        console.warn('Forcing empty services.');
        this.services_ = [];
      }
      if (!this.services_) {
        return;
      }

      if (this.isSamlUserPasswordless_ === null &&
          this.authFlow == AuthFlow.SAML && this.email_ && this.gaiaId_ &&
          this.getIsSamlUserPasswordlessCallback) {
        // Start a request to obtain the |isSamlUserPasswordless_| value for the
        // current user. Once the response arrives, maybeCompleteAuth_() will be
        // called again.
        this.getIsSamlUserPasswordlessCallback(
            this.email_, this.gaiaId_,
            this.onGotIsSamlUserPasswordless_.bind(
                this, this.email_, this.gaiaId_));
        return;
      }

      if (this.isSamlUserPasswordless_ && this.authFlow == AuthFlow.SAML &&
          this.email_ && this.gaiaId_) {
        // No password needed for this user, so complete immediately.
        this.onAuthCompleted_();
        return;
      }

      if (this.samlHandler_.samlApiUsed) {
        if (this.samlApiUsedCallback) {
          this.samlApiUsedCallback();
        }
        this.password_ = this.samlHandler_.apiPasswordBytes;
        this.onAuthCompleted_();
        return;
      }

      if (this.samlHandler_.scrapedPasswordCount == 0) {
        if (this.noPasswordCallback) {
          this.noPasswordCallback(this.email_);
          return;
        }

        // Fall through to finish the auth flow even if this.needPassword
        // is true. This is because the flag is used as an intention to get
        // password when it is available but not a mandatory requirement.
        console.warn('Authenticator: No password scraped for SAML.');
      } else if (this.needPassword) {
        if (this.samlHandler_.scrapedPasswordCount == 1) {
          // If we scraped exactly one password, we complete the authentication
          // right away.
          this.password_ = this.samlHandler_.firstScrapedPassword;
          this.onAuthCompleted_();
          return;
        }

        if (this.confirmPasswordCallback) {
          // Confirm scraped password. The flow follows in
          // verifyConfirmedPassword.
          this.confirmPasswordCallback(
              this.email_, this.samlHandler_.scrapedPasswordCount);
          return;
        }
      }

      this.onAuthCompleted_();
    }

    /**
     * Invoked to complete the authentication using the password the user enters
     * manually for non-principals API SAML IdPs that we couldn't scrape their
     * password input.
     */
    completeAuthWithManualPassword(password) {
      this.password_ = password;
      this.onAuthCompleted_();
    }

    /**
     * Invoked when the result of |getIsSamlUserPasswordlessCallback| arrives.
     * @param {string} email
     * @param {string} gaiaId
     * @param {boolean} isSamlUserPasswordless
     * @private
     */
    onGotIsSamlUserPasswordless_(email, gaiaId, isSamlUserPasswordless) {
      // Compare the request's user identifier with the currently set one, in
      // order to ignore responses to old requests.
      if (this.email_ && this.email_ == email && this.gaiaId_ &&
          this.gaiaId_ == gaiaId) {
        this.isSamlUserPasswordless_ = isSamlUserPasswordless;
        this.maybeCompleteAuth_();
      }
    }

    /**
     * Invoked to process authentication completion.
     * @private
     */
    onAuthCompleted_() {
      assert(
          this.skipForNow_ ||
          (this.email_ && this.gaiaId_ && this.sessionIndex_));
      // Chrome will crash on incorrect data type, so log some error message
      // here.
      if (this.services_) {
        if (!Array.isArray(this.services_)) {
          console.error('FATAL: Bad services type:' + typeof this.services_);
        } else {
          for (let i = 0; i < this.services_.length; ++i) {
            if (typeof this.services_[i] == 'string') {
              continue;
            }

            console.error(
                'FATAL: Bad services[' + i +
                '] type:' + typeof this.services_[i]);
          }
        }
      }
      if (this.isSamlUserPasswordless_ && this.authFlow == AuthFlow.SAML &&
          this.email_) {
        // In the passwordless case, the user data will be protected by non
        // password based mechanisms. Clear anything that got collected into
        // |password_|, if any.
        this.password_ = '';
      }
      this.dispatchEvent(new CustomEvent(
          'authCompleted',
          // TODO(rsorokin): get rid of the stub values.
          {
            detail: {
              email: this.email_ || '',
              gaiaId: this.gaiaId_ || '',
              password: this.password_ || '',
              usingSAML: this.authFlow == AuthFlow.SAML,
              chooseWhatToSync: this.chooseWhatToSync_,
              skipForNow: this.skipForNow_,
              sessionIndex: this.sessionIndex_ || '',
              trusted: this.trusted_,
              services: this.services_ || [],
            }
          }));
      this.resetStates();
    }

    /**
     * Invoked when |samlHandler_| fires 'insecureContentBlocked' event.
     * @private
     */
    onInsecureContentBlocked_(e) {
      if (!this.isLoaded_) {
        return;
      }

      if (this.insecureContentBlockedCallback) {
        this.insecureContentBlockedCallback(e.detail.url);
      } else {
        console.error('Authenticator: Insecure content blocked.');
      }
    }

    /**
     * Invoked when |samlHandler_| fires 'authPageLoaded' event.
     * @private
     */
    onAuthPageLoaded_(e) {
      if (!this.isLoaded_) {
        return;
      }

      if (!e.detail.isSAMLPage) {
        return;
      }

      this.authDomain = this.samlHandler_.authDomain;
      this.authFlow = AuthFlow.SAML;

      this.webview_.focus();
      this.fireReadyEvent_();
    }

    /**
     * Invoked when |samlHandler_| fires 'videoEnabled' event.
     * @private
     */
    onVideoEnabled_(e) {
      this.videoEnabled = true;
    }

    /**
     * Invoked when |samlHandler_| fires 'apiPasswordAdded' event.
     * @private
     */
    onSamlApiPasswordAdded_(e) {
      // Saml API 'add' password might be received after the 'loadcommit' event.
      // In such case, maybeCompleteAuth_ should be attempted again if GAIA ID
      // is available.
      if (this.gaiaId_) {
        this.maybeCompleteAuth_();
      }
    }

    /**
     * Invoked when a link is dropped on the webview.
     * @private
     */
    onDropLink_(e) {
      this.dispatchEvent(new CustomEvent('dropLink', {detail: e.url}));
    }

    /**
     * Invoked when the webview attempts to open a new window.
     * @private
     */
    onNewWindow_(e) {
      this.dispatchEvent(new CustomEvent('newWindow', {detail: e}));
    }

    /**
     * Invoked when a new document is loaded.
     * @private
     */
    onContentLoad_(e) {
      if (this.isConstrainedWindow_) {
        // Signin content in constrained windows should not zoom. Isolate the
        // webview from the zooming of other webviews using the 'per-view' zoom
        // mode, and then set it to 100% zoom.
        this.webview_.setZoomMode('per-view');
        this.webview_.setZoom(1);
      }

      // Posts a message to IdP pages to initiate communication.
      const currentUrl = this.webview_.src;
      if (currentUrl.lastIndexOf(this.idpOrigin_) == 0) {
        const msg = {
          'method': 'handshake',
        };

        // |this.webview_.contentWindow| may be null after network error screen
        // is shown. See crbug.com/770999.
        if (this.webview_.contentWindow) {
          this.webview_.contentWindow.postMessage(msg, currentUrl);
        } else {
          console.error('Authenticator: contentWindow is null.');
        }

        if (this.authMode == AuthMode.DEFAULT) {
          chrome.send('metricsHandler:recordBooleanHistogram', [
            'ChromeOS.GAIA.AuthenticatorContentWindowNull',
            !this.webview_.contentWindow
          ]);
        }

        this.fireReadyEvent_();
        // Focus webview after dispatching event when webview is already
        // visible.
        this.webview_.focus();
      } else if (currentUrl == BLANK_PAGE_URL) {
        this.fireReadyEvent_();
      }
    }

    /**
     * Invoked when the webview fails loading a page.
     * @private
     */
    onLoadAbort_(e) {
      this.dispatchEvent(new CustomEvent(
          'loadAbort', {detail: {error: e.reason, src: e.url}}));
    }

    /**
     * Invoked when the webview navigates withing the current document.
     * @private
     */
    onLoadCommit_(e) {
      if (this.gaiaId_) {
        this.maybeCompleteAuth_();
      }
    }

    /**
     * Returns |true| if event |e| was sent from the hosted webview.
     * @private
     */
    isWebviewEvent_(e) {
      // Note: <webview> prints error message to console if |contentWindow| is
      // not defined.
      // TODO(dzhioev): remove the message. http://crbug.com/469522
      const webviewWindow = this.webview_.contentWindow;
      return !!webviewWindow && webviewWindow === e.source;
    }
  }

  /**
   * The current auth flow of the hosted auth page.
   * @type {AuthFlow}
   */
  cr.defineProperty(Authenticator, 'authFlow');

  /**
   * The domain name of the current auth page.
   * @type {string}
   */
  cr.defineProperty(Authenticator, 'authDomain');

  /**
   * True if the page has requested media access.
   * @type {boolean}
   */
  cr.defineProperty(Authenticator, 'videoEnabled');

  Authenticator.AuthFlow = AuthFlow;
  Authenticator.AuthMode = AuthMode;
  Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS;

  return {
    // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old
    // iframe-based flow is deprecated.
    GaiaAuthHost: Authenticator,
    Authenticator: Authenticator
  };
});
/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

* {
  box-sizing: border-box;
}

html {
  height: 100%;
}

body {
  color: rgb(48, 57, 66);
  display: flex;
  flex-direction: column;
  font-size: 13px;
  height: 100%;
  margin: 0;
  overflow: auto;
}

.hidden {
  display: none !important;
}

img {
  flex-shrink: 0;
  height: 16px;
  padding-left: 2px;
  padding-right: 5px;
  vertical-align: top;
  width: 23px;
}

#container {
  display: flex;
  height: 100%
}

#infobar {
  background: rgb(255, 212, 0);
  display: none;
  padding: 4px 0;
  text-align: center;
}

#infobar.show {
  display: block;
}

#navigation {
  flex-shrink: 0;
  padding-top: 20px;
  width: 150px;
}

#content {
  flex-grow: 1;
}

#caption {
  color: rgb(92, 97, 102);
  font-size: 150%;
  padding-bottom: 10px;
  padding-left: 20px;
}

#serviceworker-internals {
  visibility: hidden;
}

.tab-header {
  border-inline-start: 6px solid transparent;
  padding-left: 15px;
}

.tab-header.selected {
  border-inline-start-color: rgb(78, 87, 100);
}

.tab-header > button {
  background-color: white;
  border: 0;
  cursor: pointer;
  font: inherit;
  line-height: 17px;
  margin: 6px 0;
  padding: 0 2px;
}

.tab-header:not(.selected) > button {
  color: #999;
}

#content > div {
  min-width: 32em;
  padding: 0 20px 65px 0;
}
#content > div:not(.selected) {
  display: none;
}

.content-header {
  background: linear-gradient(white, white 40%, rgba(255, 255, 255, 0.92));
  border-bottom: 1px solid #eee;
  font-size: 150%;
  padding: 20px 0 10px 0;
  z-index: 1;
}

#devices-help {
  margin-top: 10px;
}

.device-header {
  -webkit-box-align: baseline;
  -webkit-box-orient: horizontal;
  display: -webkit-box;
  margin: 10px 0 0;
  padding: 2px 0;
}

.device-name {
  font-size: 150%;
}

.device-serial {
  color: #999;
  font-size: 80%;
  margin-left: 6px;
}

.device-ports {
  -webkit-box-orient: horizontal;
  display: -webkit-box;
  margin-left: 8px;
}

.port-icon {
  background-color: rgb(64, 192, 64);
  border: 0 solid transparent;
  border-radius: 6px;
  height: 12px;
  margin: 2px;
  width: 12px;
}

.port-icon.error {
  background-color: rgb(224, 32, 32);
}

.port-icon.transient {
  background-color: orange;
  transform: scale(1.2);
}

.port-number {
  height: 16px;
  margin-right: 5px;
}

.browser-header {
  align-items: center;
  display: flex;
  flex-flow: row wrap;
  min-height: 33px;
  padding-top: 10px;
}

.browser-header > .browser-name {
  font-size: 110%;
  font-weight: bold;
}

.browser-header > .browser-user {
  color: #999;
  margin-left: 6px;
}

.browser-fallback-note {
  display: flex;
  flex-flow: row wrap;
  margin-left: 4px;
  margin-top: 5px;
  min-height: 15px;
}

.used-for-port-forwarding {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzVGNjM2OCI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgNEMxMi45NSA0IDQgMTIuOTUgNCAyNHM4Ljk1IDIwIDIwIDIwIDIwLTguOTUgMjAtMjBTMzUuMDUgNCAyNCA0em0yIDMwaC00VjIyaDR2MTJ6bTAtMTZoLTR2LTRoNHY0eiIvPgo8L3N2Zz4K);
  height: 15px;
  margin-left: 20px;
  width: 15px;
}

.row {
  padding: 6px 0;
  position: relative;
}

.properties-box {
  display: flex;
}

.subrow-box {
  display: inline-block;
  vertical-align: top;
}

.subrow {
  display: flex;
  flex-flow: row wrap;
}

.subrow > div {
  margin-right: 0.5em;
}

.webview-thumbnail {
  display: inline-block;
  flex-shrink: 0;
  margin-right: 5px;
  overflow: hidden;
  position: relative;
  vertical-align: top;
}

.screen-rect {
  background-color: #eee;
  position: absolute;
}

.view-rect {
  background-color: #ccc;
  min-height: 1px;
  min-width: 1px;
  position: absolute;
}

.view-rect.hidden {
  background-color: #ddd;
}

.guest {
  padding-left: 20px;
}

.invisible-view {
  color: rgb(151, 156, 160);
}

.url {
  color: #999;
}

.list {
  margin-top: 5px;
}

.action {
  color: rgb(17, 85, 204);
  cursor: pointer;
  margin-right: 15px;
}

.action:hover {
  text-decoration: underline;
}

.browser-header .action {
  margin-left: 10px;
}

.list:not(.pages) .subrow {
  min-height: 19px;
}

.action.disabled {
  opacity: 0.5;
  pointer-events: none;
}

.open > input {
  border: 1px solid #aaa;
  height: 17px;
  line-height: 17px;
  margin-left: 20px;
  padding: 0 2px;
}

.open > input:focus {
  border-color: rgb(77, 144, 254);
  outline: none;
  transition: border-color 200ms;
}

.open > button {
  line-height: 13px;
}

#device-settings {
  border-bottom: 1px solid #eee;
  padding: 5px 0;
}

.settings-bar {
  padding: 5px 0 5px 0;
}

.settings-bar label {
  display: inline-block;
  width: 35ex;
}

.node-frontend-action {
  margin: 6px 4px;
}

dialog.config::backdrop {
  background-color: rgba(255, 255, 255, 0.75);
}

dialog.config {
  background: white;
  border: 0;
  border-radius: 3px;
  box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
  color: #333;
  padding: 17px 17px 12px;
  position: relative;
}

#port-forwarding-enable {
  vertical-align: middle;
}

.close-button {
  background-image: url(chrome://theme/IDR_CLOSE_DIALOG);
  height: 14px;
  width: 14px;
}

.close-button:active {
  background-image: url(chrome://theme/IDR_CLOSE_DIALOG_P);
}

.close-button:hover {
  background-image: url(chrome://theme/IDR_CLOSE_DIALOG_H);
}

dialog.config > .close-button {
  position: absolute;
  right: 7px;
  top: 7px;
}

dialog.config > .title {
  font-size: 130%;
}

dialog.config > .list {
  border: 1px solid #eee;
  height: 180px;
  margin-bottom: 10px;
  margin-top: 10px;
  overflow-x: hidden;
}

.config-list-row {
  -webkit-flex-direction: row;
  display: -webkit-flex;
}

.config-list-row:hover {
  background-color: #eee;
}

.config-list-row.selected,
.config-list-row.selected:hover {
  background-color: #ccc;
}

.config-list-row input {
  border: 1px solid transparent;
  line-height: 20px;
  margin: 4px;
  min-width: 0;
  padding: 0 3px;
}

.config-list-row.fresh:not(.selected) input {
  border-color: #eee;
}

.config-list-row input.port {
  width: 4em;
}

.config-list-row input.location {
  -webkit-flex: 1;
  width: 100%;
}

.config-list-row:not(.empty) input.invalid {
  background-color: rgb(255, 200, 200);
}

.config-list-row .close-button {
  margin: 8px 8px;
}

.config-list-row.fresh .close-button,
.config-list-row:not(.selected):not(:hover) .close-button:not(:hover) {
  background-image: none;
  pointer-events: none;
}

.config-list-row:not(.selected) .close-button:not(:hover) {
  opacity: 0.5;
}

dialog.config > .message {
  margin-bottom: 12px;
  width: 20em;
}

.config-buttons {
  align-items: center;
  display: flex;
}

dialog.port-forwarding .target-discovery {
  display: none;
}

dialog.target-discovery .port-forwarding {
  display: none;
}

.config-buttons > label {
  flex-grow: 1
}
<!doctype html>
<html lang="en">
<!--
Copyright (c) 2012 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<head>
<meta charset="utf-8">
<title>Inspect with Chrome Developer Tools</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

* {
  box-sizing: border-box;
}

html {
  height: 100%;
}

body {
  color: rgb(48, 57, 66);
  display: flex;
  flex-direction: column;
  font-size: 13px;
  height: 100%;
  margin: 0;
  overflow: auto;
}

.hidden {
  display: none !important;
}

img {
  flex-shrink: 0;
  height: 16px;
  padding-left: 2px;
  padding-right: 5px;
  vertical-align: top;
  width: 23px;
}

#container {
  display: flex;
  height: 100%
}

#infobar {
  background: rgb(255, 212, 0);
  display: none;
  padding: 4px 0;
  text-align: center;
}

#infobar.show {
  display: block;
}

#navigation {
  flex-shrink: 0;
  padding-top: 20px;
  width: 150px;
}

#content {
  flex-grow: 1;
}

#caption {
  color: rgb(92, 97, 102);
  font-size: 150%;
  padding-bottom: 10px;
  padding-left: 20px;
}

#serviceworker-internals {
  visibility: hidden;
}

.tab-header {
  border-inline-start: 6px solid transparent;
  padding-left: 15px;
}

.tab-header.selected {
  border-inline-start-color: rgb(78, 87, 100);
}

.tab-header > button {
  background-color: white;
  border: 0;
  cursor: pointer;
  font: inherit;
  line-height: 17px;
  margin: 6px 0;
  padding: 0 2px;
}

.tab-header:not(.selected) > button {
  color: #999;
}

#content > div {
  min-width: 32em;
  padding: 0 20px 65px 0;
}
#content > div:not(.selected) {
  display: none;
}

.content-header {
  background: linear-gradient(white, white 40%, rgba(255, 255, 255, 0.92));
  border-bottom: 1px solid #eee;
  font-size: 150%;
  padding: 20px 0 10px 0;
  z-index: 1;
}

#devices-help {
  margin-top: 10px;
}

.device-header {
  -webkit-box-align: baseline;
  -webkit-box-orient: horizontal;
  display: -webkit-box;
  margin: 10px 0 0;
  padding: 2px 0;
}

.device-name {
  font-size: 150%;
}

.device-serial {
  color: #999;
  font-size: 80%;
  margin-left: 6px;
}

.device-ports {
  -webkit-box-orient: horizontal;
  display: -webkit-box;
  margin-left: 8px;
}

.port-icon {
  background-color: rgb(64, 192, 64);
  border: 0 solid transparent;
  border-radius: 6px;
  height: 12px;
  margin: 2px;
  width: 12px;
}

.port-icon.error {
  background-color: rgb(224, 32, 32);
}

.port-icon.transient {
  background-color: orange;
  transform: scale(1.2);
}

.port-number {
  height: 16px;
  margin-right: 5px;
}

.browser-header {
  align-items: center;
  display: flex;
  flex-flow: row wrap;
  min-height: 33px;
  padding-top: 10px;
}

.browser-header > .browser-name {
  font-size: 110%;
  font-weight: bold;
}

.browser-header > .browser-user {
  color: #999;
  margin-left: 6px;
}

.browser-fallback-note {
  display: flex;
  flex-flow: row wrap;
  margin-left: 4px;
  margin-top: 5px;
  min-height: 15px;
}

.used-for-port-forwarding {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzVGNjM2OCI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgNEMxMi45NSA0IDQgMTIuOTUgNCAyNHM4Ljk1IDIwIDIwIDIwIDIwLTguOTUgMjAtMjBTMzUuMDUgNCAyNCA0em0yIDMwaC00VjIyaDR2MTJ6bTAtMTZoLTR2LTRoNHY0eiIvPgo8L3N2Zz4K);
  height: 15px;
  margin-left: 20px;
  width: 15px;
}

.row {
  padding: 6px 0;
  position: relative;
}

.properties-box {
  display: flex;
}

.subrow-box {
  display: inline-block;
  vertical-align: top;
}

.subrow {
  display: flex;
  flex-flow: row wrap;
}

.subrow > div {
  margin-right: 0.5em;
}

.webview-thumbnail {
  display: inline-block;
  flex-shrink: 0;
  margin-right: 5px;
  overflow: hidden;
  position: relative;
  vertical-align: top;
}

.screen-rect {
  background-color: #eee;
  position: absolute;
}

.view-rect {
  background-color: #ccc;
  min-height: 1px;
  min-width: 1px;
  position: absolute;
}

.view-rect.hidden {
  background-color: #ddd;
}

.guest {
  padding-left: 20px;
}

.invisible-view {
  color: rgb(151, 156, 160);
}

.url {
  color: #999;
}

.list {
  margin-top: 5px;
}

.action {
  color: rgb(17, 85, 204);
  cursor: pointer;
  margin-right: 15px;
}

.action:hover {
  text-decoration: underline;
}

.browser-header .action {
  margin-left: 10px;
}

.list:not(.pages) .subrow {
  min-height: 19px;
}

.action.disabled {
  opacity: 0.5;
  pointer-events: none;
}

.open > input {
  border: 1px solid #aaa;
  height: 17px;
  line-height: 17px;
  margin-left: 20px;
  padding: 0 2px;
}

.open > input:focus {
  border-color: rgb(77, 144, 254);
  outline: none;
  transition: border-color 200ms;
}

.open > button {
  line-height: 13px;
}

#device-settings {
  border-bottom: 1px solid #eee;
  padding: 5px 0;
}

.settings-bar {
  padding: 5px 0 5px 0;
}

.settings-bar label {
  display: inline-block;
  width: 35ex;
}

.node-frontend-action {
  margin: 6px 4px;
}

dialog.config::backdrop {
  background-color: rgba(255, 255, 255, 0.75);
}

dialog.config {
  background: white;
  border: 0;
  border-radius: 3px;
  box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
  color: #333;
  padding: 17px 17px 12px;
  position: relative;
}

#port-forwarding-enable {
  vertical-align: middle;
}

.close-button {
  background-image: url(chrome://theme/IDR_CLOSE_DIALOG);
  height: 14px;
  width: 14px;
}

.close-button:active {
  background-image: url(chrome://theme/IDR_CLOSE_DIALOG_P);
}

.close-button:hover {
  background-image: url(chrome://theme/IDR_CLOSE_DIALOG_H);
}

dialog.config > .close-button {
  position: absolute;
  right: 7px;
  top: 7px;
}

dialog.config > .title {
  font-size: 130%;
}

dialog.config > .list {
  border: 1px solid #eee;
  height: 180px;
  margin-bottom: 10px;
  margin-top: 10px;
  overflow-x: hidden;
}

.config-list-row {
  -webkit-flex-direction: row;
  display: -webkit-flex;
}

.config-list-row:hover {
  background-color: #eee;
}

.config-list-row.selected,
.config-list-row.selected:hover {
  background-color: #ccc;
}

.config-list-row input {
  border: 1px solid transparent;
  line-height: 20px;
  margin: 4px;
  min-width: 0;
  padding: 0 3px;
}

.config-list-row.fresh:not(.selected) input {
  border-color: #eee;
}

.config-list-row input.port {
  width: 4em;
}

.config-list-row input.location {
  -webkit-flex: 1;
  width: 100%;
}

.config-list-row:not(.empty) input.invalid {
  background-color: rgb(255, 200, 200);
}

.config-list-row .close-button {
  margin: 8px 8px;
}

.config-list-row.fresh .close-button,
.config-list-row:not(.selected):not(:hover) .close-button:not(:hover) {
  background-image: none;
  pointer-events: none;
}

.config-list-row:not(.selected) .close-button:not(:hover) {
  opacity: 0.5;
}

dialog.config > .message {
  margin-bottom: 12px;
  width: 20em;
}

.config-buttons {
  align-items: center;
  display: flex;
}

dialog.port-forwarding .target-discovery {
  display: none;
}

dialog.target-discovery .port-forwarding {
  display: none;
}

.config-buttons > label {
  flex-grow: 1
}
</style>
<script src="chrome://resources/js/util.js"></script>
<script src="inspect.js"></script>
</head>

<body>

<div id="infobar">Port forwarding is active. Closing this page terminates it.</div>
<div id="container">
  <div id="navigation">
    <div id="caption">DevTools</div>
  </div>
  <div id="content">
    <div id="devices">
      <div class="content-header">Devices</div>
      <div id="device-settings">
        <div class="settings-bar">
          <label title="Enable Remote Debugging of Chrome for Android over raw USB
                        interface (no need to install / run Android Debug Bridge).">
            <input id="discover-usb-devices-enable" type="checkbox" disabled>
            Discover USB devices
          </label>
          <button id="port-forwarding-config-open" disabled>
              Port forwarding...</button>
        </div>
        <div class="settings-bar">
          <label title="Enable Remote Debugging over network.">
            <input id="discover-tcp-devices-enable" type="checkbox" disabled>
            Discover network targets
          </label>
          <button id="tcp-discovery-config-open">
            Configure...</button>
        </div>
        <div id="node-frontend" class="action node-frontend-action">
          Open dedicated DevTools for Node
        </div>
      </div>
      <div id="devices-help" hidden="true">No devices detected. Please read the
        <a href="https://developers.google.com/chrome-developer-tools/docs/remote-debugging">
        remote debugging documentation</a> to verify your device is enabled for
        USB debugging.
      </div>
      <div id="devices-incognito" hidden="true">
        Remote debugging is not available in Incognito mode.
      </div>
      <div id="devices-list"></div>
    </div>
    <div id="pages">
      <div class="content-header">Pages</div>
      <div id="pages-list" class="list pages"></div>
    </div>
    <div id="extensions">
      <div class="content-header">Extensions</div>
      <div id="extensions-list" class="list"></div>
    </div>
    <div id="apps">
      <div class="content-header">Apps</div>
      <div id="apps-list" class="list"></div>
    </div>
    <div id="workers">
      <div class="content-header">Shared workers</div>
      <div id="workers-list" class="list"></div>
    </div>
    <div id="service-workers">
      <div class="content-header">Service workers</div>
      <div id="service-workers-list" class="list"></div>
    </div>
    <div id="other">
      <div class="content-header">Other</div>
      <div id="others-list" class="list"></div>
    </div>
  </div>
</div>
<dialog id="config-dialog" class="config">
  <div id="config-dialog-close" class="close-button"></div>
  <div id="port-forwarding-config-title" class="title port-forwarding">Port forwarding settings</div>
  <div id="target-discovery-config-title" class="title target-discovery">Target discovery settings</div>
  <div id="config-list" class="list">
  </div>
  <div id="port-forwarding-message" class="message port-forwarding">
      Define the listening port on your device that maps to a port accessible
      from your development machine.
      <a href="https://developer.chrome.com/devtools/docs/remote-debugging#reverse-port-forwarding"
         target="_blank">Learn more</a>
  </div>
  <div id="targets-message" class="message target-discovery">
      Specify hosts and ports of the target discovery servers.
  </div>
  <div class="config-buttons">
    <label class="port-forwarding">
      <input id="port-forwarding-enable" type="checkbox" disabled>Enable port forwarding
    </label>
    <button id="button-done">Done</button>
  </div>
</dialog>
</body>
</html>
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

const MIN_VERSION_TAB_CLOSE = 25;
const MIN_VERSION_TARGET_ID = 26;
const MIN_VERSION_NEW_TAB = 29;
const MIN_VERSION_TAB_ACTIVATE = 30;
const WEBRTC_SERIAL = 'WEBRTC';
let HOST_CHROME_VERSION;

const queryParamsObject = {};
let browserInspector;
let browserInspectorTitle;

(function() {
const chromeMatch = navigator.userAgent.match(/(?:^|\W)Chrome\/(\S+)/);
if (chromeMatch && chromeMatch.length > 1) {
  HOST_CHROME_VERSION = chromeMatch[1].split('.').map(s => Number(s) || 0);
}

const queryParams = window.location.search;
if (!queryParams) {
  return;
}
const params = queryParams.substring(1).split('&');
for (let i = 0; i < params.length; ++i) {
  const pair = params[i].split('=');
  queryParamsObject[pair[0]] = pair[1];
}

if ('trace' in queryParamsObject || 'tracing' in queryParamsObject) {
  browserInspector = 'chrome://tracing';
  browserInspectorTitle = 'trace';
} else {
  browserInspector = queryParamsObject['browser-inspector'];
  browserInspectorTitle = 'inspect';
}
})();

function isVersionNewerThanHost(version) {
  if (!HOST_CHROME_VERSION) {
    return false;
  }
  version = version.split('.').map(s => Number(s) || 0);
  for (let i = 0; i < HOST_CHROME_VERSION.length; i++) {
    if (i > version.length) {
      return false;
    }
    if (HOST_CHROME_VERSION[i] > version[i]) {
      return false;
    }
    if (HOST_CHROME_VERSION[i] < version[i]) {
      return true;
    }
  }
  return false;
}

function sendCommand(command, args) {
  chrome.send(command, Array.prototype.slice.call(arguments, 1));
}

function sendTargetCommand(command, target) {
  sendCommand(command, target.source, target.id);
}

function removeChildren(element_id) {
  const element = $(element_id);
  element.textContent = '';
}

function removeAdditionalChildren(element_id) {
  const element = $(element_id);
  const elements = element.querySelectorAll('.row.additional');
  for (let i = 0; i != elements.length; i++) {
    element.removeChild(elements[i]);
  }
}

function removeChildrenExceptAdditional(element_id) {
  const element = $(element_id);
  const elements = element.querySelectorAll('.row:not(.additional)');
  for (let i = 0; i != elements.length; i++) {
    element.removeChild(elements[i]);
  }
}

function onload() {
  const tabContents = document.querySelectorAll('#content > div');
  for (let i = 0; i != tabContents.length; i++) {
    const tabContent = tabContents[i];
    const tabName = tabContent.querySelector('.content-header').textContent;

    const tabHeader = document.createElement('div');
    tabHeader.className = 'tab-header';
    const button = document.createElement('button');
    button.textContent = tabName;
    tabHeader.appendChild(button);
    tabHeader.addEventListener('click', selectTab.bind(null, tabContent.id));
    $('navigation').appendChild(tabHeader);
  }
  onHashChange();
  initSettings();
  sendCommand('init-ui');
}

function onHashChange() {
  const hash = window.location.hash.slice(1).toLowerCase();
  if (!selectTab(hash)) {
    selectTab('devices');
  }
}

/**
 * @param {string} id Tab id.
 * @return {boolean} True if successful.
 */
function selectTab(id) {
  const tabContents = document.querySelectorAll('#content > div');
  const tabHeaders = $('navigation').querySelectorAll('.tab-header');
  let found = false;
  for (let i = 0; i != tabContents.length; i++) {
    const tabContent = tabContents[i];
    const tabHeader = tabHeaders[i];
    if (tabContent.id == id) {
      tabContent.classList.add('selected');
      tabHeader.classList.add('selected');
      found = true;
    } else {
      tabContent.classList.remove('selected');
      tabHeader.classList.remove('selected');
    }
  }
  if (!found) {
    return false;
  }
  window.location.hash = id;
  return true;
}

function populateTargets(source, data) {
  if (source == 'local') {
    populateLocalTargets(data);
  } else if (source == 'remote') {
    populateRemoteTargets(data);
  } else {
    console.error('Unknown source type: ' + source);
  }
}

function populateAdditionalTargets(data) {
  removeAdditionalChildren('others-list');
  for (let i = 0; i < data.length; i++) {
    addAdditionalTargetsToOthersList(data[i]);
  }
}

function populateLocalTargets(data) {
  removeChildren('pages-list');
  removeChildren('extensions-list');
  removeChildren('apps-list');
  removeChildren('workers-list');
  removeChildren('service-workers-list');
  removeChildrenExceptAdditional('others-list');

  for (let i = 0; i < data.length; i++) {
    if (data[i].type === 'page') {
      addToPagesList(data[i]);
    } else if (data[i].type === 'background_page') {
      addToExtensionsList(data[i]);
    } else if (data[i].type === 'app') {
      addToAppsList(data[i]);
    } else if (data[i].type === 'shared_worker') {
      addToWorkersList(data[i]);
    } else if (data[i].type === 'service_worker') {
      addToServiceWorkersList(data[i]);
    } else {
      addToOthersList(data[i]);
    }
  }
}

function showIncognitoWarning() {
  $('devices-incognito').hidden = false;
}

function alreadyDisplayed(element, data) {
  const json = JSON.stringify(data);
  if (element.cachedJSON == json) {
    return true;
  }
  element.cachedJSON = json;
  return false;
}

function updateBrowserVisibility(browserSection) {
  const icon = browserSection.querySelector('.used-for-port-forwarding');
  browserSection.hidden = !browserSection.querySelector('.open') &&
      !browserSection.querySelector('.row') && !browserInspector &&
      (!icon || icon.hidden);
}

function updateUsernameVisibility(deviceSection) {
  const users = new Set();
  const browsers = deviceSection.querySelectorAll('.browser');

  Array.prototype.forEach.call(browsers, function(browserSection) {
    if (!browserSection.hidden) {
      const browserUser = browserSection.querySelector('.browser-user');
      if (browserUser) {
        users.add(browserUser.textContent);
      }
    }
  });
  const hasSingleUser = users.size <= 1;

  Array.prototype.forEach.call(browsers, function(browserSection) {
    const browserUser = browserSection.querySelector('.browser-user');
    if (browserUser) {
      browserUser.hidden = hasSingleUser;
    }
  });
}

function populateRemoteTargets(devices) {
  if (!devices) {
    return;
  }

  if ($('config-dialog').open) {
    window.holdDevices = devices;
    return;
  }

  function browserCompare(a, b) {
    if (a.adbBrowserName != b.adbBrowserName) {
      return a.adbBrowserName < b.adbBrowserName;
    }
    if (a.adbBrowserVersion != b.adbBrowserVersion) {
      return a.adbBrowserVersion < b.adbBrowserVersion;
    }
    return a.id < b.id;
  }

  function insertBrowser(browserList, browser) {
    for (let sibling = browserList.firstElementChild; sibling;
         sibling = sibling.nextElementSibling) {
      if (browserCompare(browser, sibling)) {
        browserList.insertBefore(browser, sibling);
        return;
      }
    }
    browserList.appendChild(browser);
  }

  const deviceList = $('devices-list');
  if (alreadyDisplayed(deviceList, devices)) {
    return;
  }

  function removeObsolete(validIds, section) {
    if (validIds.indexOf(section.id) < 0) {
      section.remove();
    }
  }

  const newDeviceIds = devices.map(function(d) {
    return d.id;
  });
  Array.prototype.forEach.call(
      deviceList.querySelectorAll('.device'),
      removeObsolete.bind(null, newDeviceIds));

  $('devices-help').hidden = !!devices.length;

  for (let d = 0; d < devices.length; d++) {
    const device = devices[d];

    let deviceSection = $(device.id);
    if (!deviceSection) {
      deviceSection = document.createElement('div');
      deviceSection.id = device.id;
      deviceSection.className = 'device';
      deviceList.appendChild(deviceSection);

      const deviceHeader = document.createElement('div');
      deviceHeader.className = 'device-header';
      deviceSection.appendChild(deviceHeader);

      const deviceName = document.createElement('div');
      deviceName.className = 'device-name';
      deviceHeader.appendChild(deviceName);

      const deviceSerial = document.createElement('div');
      deviceSerial.className = 'device-serial';
      const serial = device.adbSerial.toUpperCase();
      deviceSerial.textContent = '#' + serial;
      deviceHeader.appendChild(deviceSerial);

      if (serial === WEBRTC_SERIAL) {
        deviceHeader.classList.add('hidden');
      }

      const devicePorts = document.createElement('div');
      devicePorts.className = 'device-ports';
      deviceHeader.appendChild(devicePorts);

      const browserList = document.createElement('div');
      browserList.className = 'browsers';
      deviceSection.appendChild(browserList);

      const authenticating = document.createElement('div');
      authenticating.className = 'device-auth';
      deviceSection.appendChild(authenticating);
    }

    if (alreadyDisplayed(deviceSection, device)) {
      continue;
    }

    deviceSection.querySelector('.device-name').textContent = device.adbModel;
    deviceSection.querySelector('.device-auth').textContent =
        device.adbConnected ? '' :
                              'Pending authentication: please accept ' +
            'debugging session on the device.';

    const browserList = deviceSection.querySelector('.browsers');
    const newBrowserIds = device.browsers.map(function(b) {
      return b.id;
    });
    Array.prototype.forEach.call(
        browserList.querySelectorAll('.browser'),
        removeObsolete.bind(null, newBrowserIds));

    for (let b = 0; b < device.browsers.length; b++) {
      const browser = device.browsers[b];
      const majorChromeVersion = browser.adbBrowserChromeVersion;
      let pageList;
      let browserSection = $(browser.id);
      const browserNeedsFallback =
          isVersionNewerThanHost(browser.adbBrowserVersion);
      if (browserSection) {
        pageList = browserSection.querySelector('.pages');
      } else {
        browserSection = document.createElement('div');
        browserSection.id = browser.id;
        browserSection.className = 'browser';
        insertBrowser(browserList, browserSection);

        const browserHeader = document.createElement('div');
        browserHeader.className = 'browser-header';

        const browserName = document.createElement('div');
        browserName.className = 'browser-name';
        browserHeader.appendChild(browserName);
        browserName.textContent = browser.adbBrowserName;
        if (browser.adbBrowserVersion) {
          browserName.textContent += ' (' + browser.adbBrowserVersion + ')';
        }
        if (browser.adbBrowserUser) {
          const browserUser = document.createElement('div');
          browserUser.className = 'browser-user';
          browserUser.textContent = browser.adbBrowserUser;
          browserHeader.appendChild(browserUser);
        }
        browserSection.appendChild(browserHeader);

        if (browserNeedsFallback) {
          const browserFallbackNote = document.createElement('div');
          browserFallbackNote.className = 'browser-fallback-note';
          browserFallbackNote.textContent =
              '\u26A0 Remote browser is newer than client browser. ' +
              'Try `inspect fallback` if inspection fails.';
          browserSection.appendChild(browserFallbackNote);
        }

        if (majorChromeVersion >= MIN_VERSION_NEW_TAB) {
          const newPage = document.createElement('div');
          newPage.className = 'open';

          const newPageUrl = document.createElement('input');
          newPageUrl.type = 'text';
          newPageUrl.placeholder = 'Open tab with url';
          newPage.appendChild(newPageUrl);

          const openHandler = function(sourceId, browserId, input) {
            sendCommand(
                'open', sourceId, browserId, input.value || 'about:blank');
            input.value = '';
          }.bind(null, browser.source, browser.id, newPageUrl);
          newPageUrl.addEventListener('keyup', function(handler, event) {
            if (event.key == 'Enter' && event.target.value) {
              handler();
            }
          }.bind(null, openHandler), true);

          const newPageButton = document.createElement('button');
          newPageButton.textContent = 'Open';
          newPage.appendChild(newPageButton);
          newPageButton.addEventListener('click', openHandler, true);

          browserHeader.appendChild(newPage);
        }

        const portForwardingInfo = document.createElement('div');
        portForwardingInfo.className = 'used-for-port-forwarding';
        portForwardingInfo.hidden = true;
        portForwardingInfo.title = 'This browser is used for port ' +
            'forwarding. Closing it will drop current connections.';
        browserHeader.appendChild(portForwardingInfo);

        if (browserInspector) {
          const link = document.createElement('span');
          link.classList.add('action');
          link.setAttribute('tabindex', 1);
          link.textContent = browserInspectorTitle;
          browserHeader.appendChild(link);
          link.addEventListener(
              'click',
              sendCommand.bind(
                  null, 'inspect-browser', browser.source, browser.id,
                  browserInspector),
              false);
        }

        pageList = document.createElement('div');
        pageList.className = 'list pages';
        browserSection.appendChild(pageList);
      }

      if (!alreadyDisplayed(browserSection, browser)) {
        pageList.textContent = '';
        for (let p = 0; p < browser.pages.length; p++) {
          const page = browser.pages[p];
          // Attached targets have no unique id until Chrome 26. For such
          // targets it is impossible to activate existing DevTools window.
          page.hasNoUniqueId = page.attached && majorChromeVersion &&
              majorChromeVersion < MIN_VERSION_TARGET_ID;
          const row = addTargetToList(page, pageList, ['name', 'url']);
          if (page['description']) {
            addWebViewDetails(row, page);
          } else {
            addFavicon(row, page);
          }
          if (majorChromeVersion >= MIN_VERSION_TAB_ACTIVATE) {
            addActionLink(
                row, 'focus tab',
                sendTargetCommand.bind(null, 'activate', page), false);
          }
          if (majorChromeVersion) {
            addActionLink(
                row, 'reload', sendTargetCommand.bind(null, 'reload', page),
                page.attached);
          }
          if (majorChromeVersion >= MIN_VERSION_TAB_CLOSE) {
            addActionLink(
                row, 'close', sendTargetCommand.bind(null, 'close', page),
                false);
          }
          if (browserNeedsFallback) {
            addActionLink(
                row, 'inspect fallback',
                sendTargetCommand.bind(null, 'inspect-fallback', page),
                page.hasNoUniqueId || page.adbAttachedForeign);
          }
        }
      }
      updateBrowserVisibility(browserSection);
    }
    updateUsernameVisibility(deviceSection);
  }
}

function addToPagesList(data) {
  const row = addTargetToList(data, $('pages-list'), ['name', 'url']);
  addFavicon(row, data);
  if (data.guests) {
    addGuestViews(row, data.guests);
  }
}

function addToExtensionsList(data) {
  const row = addTargetToList(data, $('extensions-list'), ['name', 'url']);
  addFavicon(row, data);
  if (data.guests) {
    addGuestViews(row, data.guests);
  }
}

function addToAppsList(data) {
  const row = addTargetToList(data, $('apps-list'), ['name', 'url']);
  addFavicon(row, data);
  if (data.guests) {
    addGuestViews(row, data.guests);
  }
}

function addGuestViews(row, guests) {
  Array.prototype.forEach.call(guests, function(guest) {
    const guestRow = addTargetToList(guest, row, ['name', 'url']);
    guestRow.classList.add('guest');
    addFavicon(guestRow, guest);
  });
}

function addToWorkersList(data) {
  const row =
      addTargetToList(data, $('workers-list'), ['name', 'description', 'url']);
  addActionLink(
      row, 'terminate', sendTargetCommand.bind(null, 'close', data), false);
}

function addToServiceWorkersList(data) {
  const row = addTargetToList(
      data, $('service-workers-list'), ['name', 'description', 'url']);
  addActionLink(
      row, 'terminate', sendTargetCommand.bind(null, 'close', data), false);
}

function addToOthersList(data) {
  addTargetToList(data, $('others-list'), ['url']);
}

function addAdditionalTargetsToOthersList(data) {
  addTargetToList(data, $('others-list'), ['name', 'url']);
}

function formatValue(data, property) {
  let value = data[property];

  if (property == 'name' && value == '') {
    value = 'untitled';
  }

  let text = value ? String(value) : '';
  if (text.length > 100) {
    text = text.substring(0, 100) + '\u2026';
  }

  const div = document.createElement('div');
  div.textContent = text;
  div.className = property;
  return div;
}

function addFavicon(row, data) {
  const favicon = document.createElement('img');
  if (data['faviconUrl']) {
    favicon.src = data['faviconUrl'];
  }
  const propertiesBox = row.querySelector('.properties-box');
  propertiesBox.insertBefore(favicon, propertiesBox.firstChild);
}

function addWebViewDetails(row, data) {
  let webview;
  try {
    webview = JSON.parse(data['description']);
  } catch (e) {
    return;
  }
  addWebViewDescription(row, webview);
  if (data.adbScreenWidth && data.adbScreenHeight) {
    addWebViewThumbnail(
        row, webview, data.adbScreenWidth, data.adbScreenHeight);
  }
}

function addWebViewDescription(row, webview) {
  const viewStatus = {visibility: '', position: '', size: ''};
  if (!webview.empty) {
    if (webview.attached && !webview.visible) {
      viewStatus.visibility = 'hidden';
    } else if (!webview.attached) {
      viewStatus.visibility = 'detached';
    }
    viewStatus.size = 'size ' + webview.width + ' \u00d7 ' + webview.height;
  } else {
    viewStatus.visibility = 'empty';
  }
  if (webview.attached) {
    viewStatus.position =
        'at (' + webview.screenX + ', ' + webview.screenY + ')';
  }

  const subRow = document.createElement('div');
  subRow.className = 'subrow webview';
  if (webview.empty || !webview.attached || !webview.visible) {
    subRow.className += ' invisible-view';
  }
  if (viewStatus.visibility) {
    subRow.appendChild(formatValue(viewStatus, 'visibility'));
  }
  if (viewStatus.position) {
    subRow.appendChild(formatValue(viewStatus, 'position'));
  }
  subRow.appendChild(formatValue(viewStatus, 'size'));
  const subrowBox = row.querySelector('.subrow-box');
  subrowBox.insertBefore(subRow, row.querySelector('.actions'));
}

function addWebViewThumbnail(row, webview, screenWidth, screenHeight) {
  const maxScreenRectSize = 50;
  let screenRectWidth;
  let screenRectHeight;

  const aspectRatio = screenWidth / screenHeight;
  if (aspectRatio < 1) {
    screenRectWidth = Math.round(maxScreenRectSize * aspectRatio);
    screenRectHeight = maxScreenRectSize;
  } else {
    screenRectWidth = maxScreenRectSize;
    screenRectHeight = Math.round(maxScreenRectSize / aspectRatio);
  }

  const thumbnail = document.createElement('div');
  thumbnail.className = 'webview-thumbnail';
  const thumbnailWidth = 3 * screenRectWidth;
  const thumbnailHeight = 60;
  thumbnail.style.width = thumbnailWidth + 'px';
  thumbnail.style.height = thumbnailHeight + 'px';

  const screenRect = document.createElement('div');
  screenRect.className = 'screen-rect';
  screenRect.style.left = screenRectWidth + 'px';
  screenRect.style.top = (thumbnailHeight - screenRectHeight) / 2 + 'px';
  screenRect.style.width = screenRectWidth + 'px';
  screenRect.style.height = screenRectHeight + 'px';
  thumbnail.appendChild(screenRect);

  if (!webview.empty && webview.attached) {
    const viewRect = document.createElement('div');
    viewRect.className = 'view-rect';
    if (!webview.visible) {
      viewRect.classList.add('hidden');
    }
    function percent(ratio) {
      return ratio * 100 + '%';
    }
    viewRect.style.left = percent(webview.screenX / screenWidth);
    viewRect.style.top = percent(webview.screenY / screenHeight);
    viewRect.style.width = percent(webview.width / screenWidth);
    viewRect.style.height = percent(webview.height / screenHeight);
    screenRect.appendChild(viewRect);
  }

  const propertiesBox = row.querySelector('.properties-box');
  propertiesBox.insertBefore(thumbnail, propertiesBox.firstChild);
}

function addTargetToList(data, list, properties) {
  const row = document.createElement('div');
  row.className = 'row';
  row.targetId = data.id;

  const propertiesBox = document.createElement('div');
  propertiesBox.className = 'properties-box';
  row.appendChild(propertiesBox);

  const subrowBox = document.createElement('div');
  subrowBox.className = 'subrow-box';
  propertiesBox.appendChild(subrowBox);

  const subrow = document.createElement('div');
  subrow.className = 'subrow';
  subrowBox.appendChild(subrow);

  for (let j = 0; j < properties.length; j++) {
    subrow.appendChild(formatValue(data, properties[j]));
  }

  const actionBox = document.createElement('div');
  actionBox.className = 'actions';
  subrowBox.appendChild(actionBox);

  if (data.isAdditional) {
    addActionLink(
        row, 'inspect', sendCommand.bind(null, 'inspect-additional', data.url),
        false);
    row.classList.add('additional');
  } else if (!data.hasCustomInspectAction && data.type !== 'iframe') {
    addActionLink(
        row, 'inspect', sendTargetCommand.bind(null, 'inspect', data),
        data.hasNoUniqueId || data.adbAttachedForeign);
    if (data.type === 'page') {
      addActionLink(
          row, 'pause', sendTargetCommand.bind(null, 'pause', data),
          data.hasNoUniqueId || data.adbAttachedForeign);
    }
  }

  list.appendChild(row);
  return row;
}

function addActionLink(row, text, handler, opt_disabled) {
  const link = document.createElement('span');
  link.classList.add('action');
  link.setAttribute('tabindex', 1);
  if (opt_disabled) {
    link.classList.add('disabled');
  } else {
    link.classList.remove('disabled');
  }

  link.textContent = text;
  link.addEventListener('click', handler, true);
  function handleKey(e) {
    if (e.key == 'Enter' || e.key == ' ') {
      e.preventDefault();
      handler();
    }
  }
  link.addEventListener('keydown', handleKey, true);
  row.querySelector('.actions').appendChild(link);
}

function initSettings() {
  checkboxSendsCommand(
      'discover-usb-devices-enable', 'set-discover-usb-devices-enabled');
  checkboxSendsCommand('port-forwarding-enable', 'set-port-forwarding-enabled');
  checkboxSendsCommand(
      'discover-tcp-devices-enable', 'set-discover-tcp-targets-enabled');

  $('port-forwarding-config-open')
      .addEventListener('click', openPortForwardingConfig);
  $('tcp-discovery-config-open').addEventListener('click', openTargetsConfig);
  $('config-dialog-close').addEventListener('click', function() {
    $('config-dialog').commit(true);
  });
  $('node-frontend')
      .addEventListener('click', sendCommand.bind(null, 'open-node-frontend'));
}

function checkboxHandler(command, event) {
  sendCommand(command, event.target.checked);
}

function checkboxSendsCommand(id, command) {
  $(id).addEventListener('change', checkboxHandler.bind(null, command));
}

function handleKey(event) {
  switch (event.keyCode) {
    case 13:  // Enter
      const dialog = $('config-dialog');
      if (event.target.nodeName == 'INPUT') {
        const line = event.target.parentNode;
        if (!line.classList.contains('fresh') ||
            line.classList.contains('empty')) {
          dialog.commit(true);
        } else {
          commitFreshLineIfValid(true /* select new line */);
          dialog.commit(false);
        }
      } else {
        dialog.commit(true);
      }
      break;
  }
}

function commitDialog(commitHandler, shouldClose) {
  const element = $('config-dialog');
  if (element.open && shouldClose) {
    element.onclose = null;
    element.close();
    document.removeEventListener('keyup', handleKey);
    if (window.holdDevices) {
      populateRemoteTargets(window.holdDevices);
      delete window.holdDevices;
    }
  }
  commitFreshLineIfValid();
  commitHandler();
}

function openConfigDialog(dialogClass, commitHandler, lineFactory, data) {
  const dialog = $('config-dialog');
  if (dialog.open) {
    return;
  }

  dialog.className = dialogClass;
  dialog.classList.add('config');

  document.addEventListener('keyup', handleKey);
  dialog.commit = commitDialog.bind(null, commitHandler);
  dialog.onclose = commitDialog.bind(null, commitHandler, true);
  $('button-done').onclick = dialog.onclose;

  const list = $('config-dialog').querySelector('.list');
  list.textContent = '';

  list.createRow = appendRow.bind(null, list, lineFactory);
  for (const key in data) {
    list.createRow(key, data[key]);
  }
  list.createRow(null, null);

  dialog.showModal();
  const defaultFocus = dialog.querySelector('.fresh .preselected');
  if (defaultFocus) {
    defaultFocus.focus();
  } else {
    doneButton.focus();
  }
}

function openPortForwardingConfig() {
  function createPortForwardingConfigLine(port, location) {
    const line = document.createElement('div');
    line.className = 'port-forwarding-pair config-list-row';

    const portInput =
        createConfigField(port, 'port preselected', 'Port', validatePort);
    line.appendChild(portInput);

    const locationInput = createConfigField(
        location, 'location', 'IP address and port', validateLocation);
    locationInput.classList.add('primary');
    line.appendChild(locationInput);
    return line;
  }

  function commitPortForwardingConfig() {
    const config = {};
    filterList(['.port', '.location'], function(port, location) {
      config[port] = location;
    });
    sendCommand('set-port-forwarding-config', config);
  }

  openConfigDialog(
      'port-forwarding', commitPortForwardingConfig,
      createPortForwardingConfigLine, window.portForwardingConfig);
}

function openTargetsConfig() {
  function createTargetDiscoveryConfigLine(index, targetDiscovery) {
    const line = document.createElement('div');
    line.className = 'target-discovery-line config-list-row';

    const locationInput = createConfigField(
        targetDiscovery, 'location preselected', 'IP address and port',
        validateLocation);
    locationInput.classList.add('primary');
    line.appendChild(locationInput);
    return line;
  }

  function commitTargetDiscoveryConfig() {
    const entries = [];
    filterList(['.location'], function(location) {
      entries.push(location);
    });
    sendCommand('set-tcp-discovery-config', entries);
  }

  openConfigDialog(
      'target-discovery', commitTargetDiscoveryConfig,
      createTargetDiscoveryConfigLine, window.targetDiscoveryConfig);
}

function filterList(fieldSelectors, callback) {
  const lines = $('config-dialog').querySelectorAll('.config-list-row');
  for (let i = 0; i != lines.length; i++) {
    const line = lines[i];
    const values = [];
    for (const selector of fieldSelectors) {
      const input = line.querySelector(selector);
      const value = input.classList.contains('invalid') ? input.lastValidValue :
                                                          input.value;
      if (!value) {
        break;
      }
      values.push(value);
    }
    if (values.length == fieldSelectors.length) {
      callback.apply(null, values);
    }
  }
}

function updateCheckbox(id, enabled) {
  const checkbox = $(id);
  checkbox.checked = !!enabled;
  checkbox.disabled = false;
}

function updateDiscoverUsbDevicesEnabled(enabled) {
  updateCheckbox('discover-usb-devices-enable', enabled);
}

function updatePortForwardingEnabled(enabled) {
  updateCheckbox('port-forwarding-enable', enabled);
  $('infobar').classList.toggle('show', enabled);
  $('infobar').scrollIntoView();
}

function updatePortForwardingConfig(config) {
  window.portForwardingConfig = config;
  $('port-forwarding-config-open').disabled = !config;
}

function updateTCPDiscoveryEnabled(enabled) {
  updateCheckbox('discover-tcp-devices-enable', enabled);
}

function updateTCPDiscoveryConfig(config) {
  window.targetDiscoveryConfig = config;
  $('tcp-discovery-config-open').disabled = !config;
}

function appendRow(list, lineFactory, key, value) {
  const line = lineFactory(key, value);
  line.lastElementChild.addEventListener('keydown', function(e) {
    if (e.key == 'Tab' && !hasKeyModifiers(e) &&
        line.classList.contains('fresh') && !line.classList.contains('empty')) {
      // Tabbing forward on the fresh line, try create a new empty one.
      if (commitFreshLineIfValid(true)) {
        e.preventDefault();
      }
    }
  });

  const lineDelete = document.createElement('div');
  lineDelete.className = 'close-button';
  lineDelete.addEventListener('click', function() {
    const newSelection = line.nextElementSibling || line.previousElementSibling;
    selectLine(newSelection, true);
    line.parentNode.removeChild(line);
    $('config-dialog').commit(false);
  });
  line.appendChild(lineDelete);

  line.addEventListener('click', selectLine.bind(null, line, true));
  line.addEventListener('focus', selectLine.bind(null, line, true));
  checkEmptyLine(line);

  if (!key && !value) {
    line.classList.add('fresh');
  }

  return list.appendChild(line);
}

function validatePort(input) {
  const match = input.value.match(/^(\d+)$/);
  if (!match) {
    return false;
  }
  const port = parseInt(match[1]);
  if (port < 1024 || 65535 < port) {
    return false;
  }

  const inputs = document.querySelectorAll('input.port:not(.invalid)');
  for (let i = 0; i != inputs.length; ++i) {
    if (inputs[i] == input) {
      break;
    }
    if (parseInt(inputs[i].value) == port) {
      return false;
    }
  }
  return true;
}

function validateLocation(input) {
  const match = input.value.match(/^([a-zA-Z0-9\.\-_]+):(\d+)$/);
  if (!match) {
    return false;
  }
  const port = parseInt(match[2]);
  return port <= 65535;
}

function createConfigField(value, className, hint, validate) {
  const input = document.createElement('input');
  input.className = className;
  input.type = 'text';
  input.placeholder = hint;
  input.value = value || '';
  input.lastValidValue = value || '';

  function checkInput() {
    if (validate(input)) {
      input.classList.remove('invalid');
    } else {
      input.classList.add('invalid');
    }
    if (input.parentNode) {
      checkEmptyLine(input.parentNode);
    }
  }
  checkInput();

  input.addEventListener('keyup', checkInput);
  input.addEventListener('focus', function() {
    selectLine(input.parentNode);
  });

  input.addEventListener('blur', function() {
    if (validate(input)) {
      input.lastValidValue = input.value;
    }
  });

  return input;
}

function checkEmptyLine(line) {
  const inputs = line.querySelectorAll('input');
  let empty = true;
  for (let i = 0; i != inputs.length; i++) {
    if (inputs[i].value != '') {
      empty = false;
    }
  }
  if (empty) {
    line.classList.add('empty');
  } else {
    line.classList.remove('empty');
  }
}

function selectLine(line, opt_focusInput) {
  if (line.classList.contains('selected')) {
    return;
  }
  const selected =
      line.parentElement && line.parentElement.querySelector('.selected');
  if (selected) {
    selected.classList.remove('selected');
  }
  line.classList.add('selected');
  if (opt_focusInput) {
    const el = line.querySelector('.preselected');
    if (el) {
      line.firstChild.select();
      line.firstChild.focus();
    }
  }
}

function commitFreshLineIfValid(opt_selectNew) {
  const line = $('config-dialog').querySelector('.config-list-row.fresh');
  if (line.querySelector('.invalid')) {
    return false;
  }
  line.classList.remove('fresh');
  const freshLine = line.parentElement.createRow();
  if (opt_selectNew) {
    freshLine.querySelector('.preselected').focus();
  }
  return true;
}

function populatePortStatus(devicesStatusMap) {
  for (const deviceId in devicesStatusMap) {
    if (!devicesStatusMap.hasOwnProperty(deviceId)) {
      continue;
    }
    const deviceStatus = devicesStatusMap[deviceId];
    const deviceStatusMap = deviceStatus.ports;

    const deviceSection = $(deviceId);
    if (!deviceSection) {
      continue;
    }

    const devicePorts = deviceSection.querySelector('.device-ports');
    if (alreadyDisplayed(devicePorts, deviceStatus)) {
      continue;
    }

    devicePorts.textContent = '';
    for (const port in deviceStatusMap) {
      if (!deviceStatusMap.hasOwnProperty(port)) {
        continue;
      }

      const status = deviceStatusMap[port];
      const portIcon = document.createElement('div');
      portIcon.className = 'port-icon';
      // status === 0 is the default (connected) state.
      if (status === -1 || status === -2) {
        portIcon.classList.add('transient');
      } else if (status < 0) {
        portIcon.classList.add('error');
      }
      devicePorts.appendChild(portIcon);

      const portNumber = document.createElement('div');
      portNumber.className = 'port-number';
      portNumber.textContent = ':' + port;
      devicePorts.appendChild(portNumber);
    }

    function updatePortForwardingInfo(browserSection) {
      const icon = browserSection.querySelector('.used-for-port-forwarding');
      if (icon) {
        icon.hidden = (browserSection.id !== deviceStatus.browserId);
      }
      updateBrowserVisibility(browserSection);
    }

    Array.prototype.forEach.call(
        deviceSection.querySelectorAll('.browser'), updatePortForwardingInfo);

    updateUsernameVisibility(deviceSection);
  }

  function clearBrowserPorts(browserSection) {
    const icon = browserSection.querySelector('.used-for-port-forwarding');
    if (icon) {
      icon.hidden = true;
    }
    updateBrowserVisibility(browserSection);
  }

  function clearPorts(deviceSection) {
    if (deviceSection.id in devicesStatusMap) {
      return;
    }
    const devicePorts = deviceSection.querySelector('.device-ports');
    devicePorts.textContent = '';
    delete devicePorts.cachedJSON;

    Array.prototype.forEach.call(
        deviceSection.querySelectorAll('.browser'), clearBrowserPorts);
  }

  Array.prototype.forEach.call(
      document.querySelectorAll('.device'), clearPorts);
}

document.addEventListener('DOMContentLoaded', onload);
window.addEventListener('hashchange', onHashChange);
     io8{~Š"_;ۦYl{`X(ТdDQl#Q݋ej.O.f5"T?(IjTujFw
.%<W$MUJMHd^NͩE2fiEJQ@wMy.#c&/&BR$Q	%DK9*'ˋ=o˿c4D(;sDLJ:ّ?JwkYA%r+z N^8A//d
ͧ猠+-*-m2.e @q-W:_$A|TF%HH	IѻaFh*
%8G1єּS8'㇫O7hM|&''1Oo "-Z-eK=*SV@"	oHIo*I%K}R7H(9ysX;;i@apM~yl>>m%9K#ŋ%X
At
RFwİ5ÛH'uF '.qrV=zz\u"SZJǱ6.y8dCMAS5]EU $A}=V9}PbDeQ`<@"X7h>Мql	-1=l	G;I_8OÁ	.$99hUʂFZټd$"Ō'X 2x7&ݧ.wֵ1\3GMN:ITUYpS'a8&f|2 Mʆ~OJ!uVqS
1%+6aawd8JBl! e@8Ѵj$MS/b5$SH+Hy7-+@W=<OYj}n~0zml=x7x	kzORϰVDa:+6	ܥ%J4y4Vzie((K4}*.S]7tY֖auX0E]xz@RbG*Zպ k.Rcjwޟ;EcAmlp`EmMkcA+gv
wV|^a+P5Ks*K﨤1eTAi'_,3=N!9y*KVnRsp*{.n=PM;v.)v3Ƌxaf zF-";ģ35wMp")*EfO!,T ]O5dh hCthTՑ^b~D:jA8!v\wϾgAʎ%)϶ׁjlA e7[@ÙQڌKuoy}x.5[x{M=ۺڻЦW|S~tuֵ\8J}x]p93VkJ˝NSt#YU$ig>NΪSw|K[۬
+|̌R jz#РnxOTSVHB]W.O5QkqK@	.&O_N]~.:0,j,>4X  f1Ff1xhYɈ<G91F%InIP̓"=o zb_EТ*-*_M\Mc7Wn\!{o4_xz
#9<n(rWSH- 뒞Σ߾H#ՙ!1"KG_)I1-Тze+.`wkhekNKq1Q~
&6<~'i{KoiԮLȖ߱~b襼.4P|H(bh	ɠ(+ǍTnD4;ߑ.wČJCȁ >Rе%DNLES5Z{'\g8R:|x
 7Y2A@vcV
f/FS0G`+Ј5aSTd~Nyg,Ĳݡsmظ}I>>b!^k(4hPjy>~|Y7pC#\B4S	ր?tKDڒd&f|m&|o&-]<Ü]T2An;$7G-@ǋN̇*9	w8qfLz(\qv7if? HE#       <ksF+ƻ[K&!'wlZrYn]\)p@@ɼH13pU(0i`_u+oSV"_$:^U(CuХ.uVLUTe*ZMX+uXݮUNneNJ GFՈiX%͹%_$yZd%FVW9"0yVEկzq^RoO.9<>fɇ:R,Ohk\n,/v:99*ӤL 8tH>e͛3C]Wїd;Uj \42% tHS/.uvb1/gyd"BqB}4G"dQjptfhxgF'7[e
t.cg	h:T)]
9PCx0yQ?{JF`D=|X|r;3J-M%rpZD8>IrMb Ƚ~SbqPaY$mA*C|Q|:}03*NDYƂ+eAO~~ˊpy@v]$n.@/pqSqnC0GtVe>R}?FA@67# Y {!lUlE?K{M҆#h3@0b /p7CHx/$)RY ~ԩ^zeg0lT(S0xQ i`@AH)̧IF>.;}?:5(C?OgD^\]3OD"m]$	I<?:/)S	3-P~v[ԁ!idKY4,`=*mVx!\X긂MQ:LS- Xb0Dm)8ha
}KK-%*aww{t$P`Lӭ,{Hl3z(fc	LDh&.~MWÂHYX%8zm 7(郡:  $>{$wP7VK0׻4i, Q`UD]ԼZi#G9T] .~=F1e8φѬ8	U9|y=K@U sP*7D9z;7~mW!Ř$6X@q&_ 7
kvڀ"_,AvP􍦏V<BT,LfX4/ VZw;g}1%(FmseoQ1ӖO`AYe<'GƙTXVkC5Kx8:BT>fY'9l"I[fdU2k0lQU4~v19f-!?  $mim:ʞ6\XQ*`'0HޝE)&9"k6 [r7~ʊ{DL!{5YxfPLS/:ߍ7i\5j1rWGYDtjZ}4GFzJ[/l'!W]$-M|Hu\,{8"XavƲ{Vew!e礀$Im6,#q yzmz>.ES @jEB#'4BOjUfSYle}v~GHIiG8WDeo~PI(~86|+Cq?눋jXlYyWOf[&EjVw䫒ߨ,)Ze:=i{MAVf3	LIy
|1E3db]oL͙+DN˼gws.k#<. w
XV/)2DsU:hYެeRC-pߘI<#(x#%U]5]Ȃa&i&tP3VOѲ89pRMCڲ <pN(GInM&|HpP\U$|O(L:X;-Ys`"LEUazVӛL% \Pyi^!$n6p+VPBxy`s-yZ-H;cvGzIwƇΚUH|_&n
"(yɩƋN&`/CZj|Cyũ풒)ߺؓ7N'}i4+ ձ	Fѓ_7hH .>4{x8y-0]xٗ{;-(ɟdw|GI[7<?KXpѧݷ$ĝ<f/X<Vqo54pʌݰj%<IލNqn805m2HI_[wDǋ!{NLIVHԔUI1+Ec{Ush+`d4Y}wl>Q>f`tls	4\yhH	\VO8LǨM>2aIﵝT\ytew\rwJwH	]"DFS`9Zo؀ǢX))y<s"ԾWS+&ua'H/Ь`W6NRSp~	'qGWFФ5c1f>~zrleb.3BC%PZh`E>+y:R=	OUưg!`,^Q52z
/h* ֳ8únEvig
2vOnGհ]Q7+p'wFN\yjK< Nȩ"OJRDs:[eV*6YoxuDu:PgLdQfC9PGDWٯ@	&9mgvIWn޳8efTȄs,\9=|V@r֢)35*O`.a1A<7 
PBea5ʬ;#:=Rܷ]9*5ay6ڨ6XHvɐD:#+:LՂ^m*C\VbqV֗m<islF3͎=}@HyvYϼ6dea~jn޺w?m.Ζuݥh$1	VF󄬁'طzO3袭5I&yݑYĽGBvӠ*1_Ϝs
]Z&#UeX E\J5Q^4hO4	!5yt
種STxr
0	fefNrZ.s~|4ʼe nr]wM8猨(_ ,aN8ݗqIީkTns>$ѦrJY+گ	&&YUqCl\aU2\^ݢ'x/ 9_j'AM"-Q/v_[W3O;abNݾzFfL`nmIg}+Ho$S!g[|#psz\##R)	`^sb|*Y"B[t{-}&@
K~6M
ڊ>˚?^{+6n/@@!:38Ě!doH;/!$`GVвQC<vRuS.5F5FU|yGDoQ.Y]`8-#CQㅯې^ÁA/N/Y}D6!Meu '`K%}zvmplDnl)PjvPr#8mBwm{胯8nwInkEk< ĠձUHM|}U3eLg{%b^}`c纤pCf(Ϸ1uO~Թ;ѶkTܷ+εig&˞ ,$*.h,A!+Mgo
qy x;(q!B7
e#IȫNU:aP"";AG|Hbm.mK}D&;USl]3=C	PwB&AOʚ8~с/}M2x!O=G{iWwk_Esulk"} Mk{<Dd'AW<~ M^?qi<2C{A(YS/]id|ywFqc6򜜋g8CEV9ƅ"]8}߼&+rrm:ʨВm$ YJtYEժܻ4Ex]s/SHLNl9^&e1tvjPhgB{č.p'vnx_:AT`UQ)-jlWԛcJ;n}Sh?U;eN-mclgcPO!wQP9H"1nvYƋwDkz	R?XYuZfQG2{7X,HgeJ~+Jc 6]VX3\VfEDV='?AR$KgR:b._5_! =2a9J-Rbjch5:QD7_ .:5AsJ;"3]p~:Nş,nUM*;XL".
kAD=Z?Gtpu,9KA9D.ڗ)v{ZM8'~ӢPه-v]CҤzWi?S~.	gc	Q /^|=!~w%aq-&mϹIג,kXCn#?ӝ{`Oo=?IKZ)Ћi!0rWJy&JȴIi/vvRmbbZ@0K2jKbA0hD)llыTXaC&?c\#+'/OitW̡v:EBo̅_*}IS_^u6I^_z:&ŚK JmQ->Q8ll(Q|ۻ[s/ ׮.<J ro?DV q-o?}{ Z{v8#71b0M]!pd#-ԝfz;wtˋK
B'YOg]rp\:"d~gD#u	YG4PV szn;|m!x {4i.Pz6K;p켤\-oX=,QFG]Ü
1',6.L]X3:p*Y:BZ=țS/%ډ7߹Q+;Ȑ>%%_xKqovFGxڿաx?Y<<,E%u=>wbX:^mGWifzC1T1qn[=/֣Փ;:SsZڥܬg*AHZАZ'C%xNߕNF5Ubq|]Yŝ}-Hfxv-bUz;iX-/~Ŝn5Xkh͇QoR#gYTZ({[H&&'Iu@LԼJ?eTǺl }c.|k'&gWF.sȍc/Giqho{yܻ[?pCW?1.Wۀ7fT]lsvn	h7v` VB~v+\~g CNK%6נR'fn{"x;<nGz=ņ?C<|\       ][s6~@;;55%uwz&u2M}t2ٌ)RKRv])@luZ"ssn1pnn#0[o,f"^. !ᤷ>S:!E0`O @_o{xp||0zt!p1P֎5Ĕ C!xwy~qLvvv|8=ٱo9gu_; _1]to=kǋ0~y=$Q{ 8S`o=焿|{'mCG?؁g?8a9s/3	gtNcj??|N)kǛVC/{l?vNވAgIk:;6(̿!s{]	8UUQW=#Sg/"wJ;o<d%"+8ahe  ^^\z{R!ig
SY!|?Fv-ԗDoF~$o~v;AiE?9CCJ{qcπp]a.5E7͎̍x:Js21~~`amb}Mڷއ z$:ŘNx"L/sMΰߙt0b2- W%1
7.1_H ~wvZ!#E}~A*`L'O@t1NiSA0B"YISOQH*7VKr?vsA[Dǐ8UskDYYOzIY	QmT#xɓUJ4þ>t'-隣mҔl/@<}Fݽ?KS(/+K-d`iM¿oV'  5C,Fkd{'U
㵄<AU+RZ8cYJ;W Q7$yg5?h;A_ɈEÊ"*Iٵo ]Y:Ә(Lc-KAX<J&و6]F r9Ã±@x\暂`\K*,1
A5	@*$GGF<8߯1M"2E1\)\C<c"tq72x S8ȍV~McQ{ 7"<>.䔨"zDN|͚ȉ:&QT>"HTiSCJڹFJH*֒" Zb2h6eYX<8d$+r#) f%[xb{_#k/Tv`L.Błkim[`/{4bq-u<Y@돈(jH/*î8\ГFy!'cʬy`ѦLxf?2QmVcԍ
)C~s:4?vA{KeX( )tF+%4 E.*g͌S]}·07\q,`TEDrnqȋOEj`,jx*sCPQBW̦3MGJ]r^=Ŵj%<pM_Xz]6-&lmjz]֥eͮm3jjXl[R5K]'Cf>uP	p9e+CX#t[,1XgbS|A&u0&4q@ݯp[[RE*0CضKwSz?[t7.	Q<;X/VRNL6s#<Piу[H!0+#^ɖȒ^(-wF7VmԠA	u7l0-6dΗw|G 4qȯ4D,z< #o  T:jSo6qć LuAhR`R=4'$;˺R-X'aj.j]9ߢTfIV61<I<]8<6s?dHtn<PS/r_휾bX߆Cv;ď^\+8SsN1uJNaA	bnK[NcTkMV	KYWBTTЯf)K:w{YOq4C9ٶ"e0&h%;9ok)W{v˶kΟ/Ss`\rح-N]1<|tnbГsLԠoeuM	,)sR5:k,qu~N4TsHu\O=R-j1s*nPQs*69ϡ3+V^Oh`ze)ޣ.Wz2oPapB3{^Q:?<8<ꓫ,nKog6oiFEu98#O73UD|Aayo%rްx-E"iuadL*82Z2Z7FcD	7jT5:=ZCAe1hgI'%/$Khl㹔zQ={>w-(T)YP3ɽ=RrU-Lоu]'5B+i8.*U9͢0'E!rB(=EyiqG?NgQA.͑!*q0S
58겡MZLɬ)ʃ[+)5=yڛ,[YԒϏqAI79zjYa)4e^lV .h|E>QfEkqtl@Kt.*q<6jMUXȻ~o	q~U
ں>3_9I!ܞ+g鞎+.b{?X//24<u-jޫ.*#;s͡VmDAr:WvnaNO͚̜T[Ӹʵ٘U*p|Ǝ`f=G~=Q)Do׭Ǿd"CtI}iµYbG=]<UTJؑIOl]|	E`>8+bw{\FtlPpiΜ&Id%7'
$	Qfŕ K}Pcx]̈́9ɾ~薤xvݥgn5~eJ^0kpgQC-m̟˩Ioi.-ϸțYvAu:D_[Ħ.(>[GMgXRfd@j"ϱpe͘`Vm%+-e?l]{-@65[:H2;ov!pi%}ph9w0b8VkH]2[y ߻S}y
n;B	q-Ɋ"w41yT	ՕO%Yr'љVψawzsRg/6y]Wt[lGSuT%.pUiec(qNPBzWYm )v #QKs"EU Z0Fkjx6Lщ2ʓ!s냹D2:r1%v_7;aH%p?8^Q)Q<^bMP2^2dʏQRa1&umY[޾nh7]eZ֍VJLkFf(6=^|+^ҟ`)Dս]NxjDͥې IGfM//U[Oz/FEʺ/uC^(A졤VlCRBPMCFrZ[3R5FrWmng"
̈́LJݘ"D8~:q#K|t}QQZ i	q.]c!*%B8/Wr	6ac3:|זɴGfPi*s3zwyBeS#A\	&r 2ST{ٳ*[/#8!2Y2|{'RX>HqC(JE%lie(?RVT9"gc ճ[~}VMfEZv;"H@WȪ23Wj/T|8=Nk4fF:/5!L
<Pӛ5/
C.IQW8)8v_[,Z۷+qREp]dpRVc)+l֓M>+LMp+x,[Uٜ+]u;z}бfI)\jyqYA؉bW@(>_b9w_"2"*(Iь*쀕i eVRr$E^ޜOsLW       X[o6~M(MݤXCn0i+Ej$e'wxݠ<<r_ߢC	'&]g95VҬ992+2'(P;FLvC薥4r?sN_:R&/mO=|O>Vm29Qt)2GKI/kΑ#HQm%{7M\#1,UJAUB-Ȧ%>XAsLJ@	ֲ1oњqjL'D{/WDk3~Bп%~|^+9+-eu@t/ٕ`Ԭ|L.4E'TrVHm9z'y^QJ$'v1jDddw^VE4ؔ:b^R'I쑯9D60Aǯ8TU$1R86ʂ^ٳaw"x'RRv3gcq\Pl
Lw&m¹^%4
[*ÆQZ|ʢ*: B"X,X%]t=DZa?4M▌XtMR^d
G@.8]=W) xwcG'cM$A8jAu'Ei4 2s4mSGOG	+mg[w?-ZHVM(iR·RCmx(K1vr@;zץX[KULSBH#-؁C6[cH$r
vևxi
^Nv#腗;?^4d	kvGIñ^EkRO!F>~ձwhSɢ4cIBJJe쐪gQX_ޠjy\fX@WˁP*V;/T|]`g^rpv
Sd|p8`>Sۖևq&_%7S>z통FF8YzUnf	@i󭦗'} :X2;Mc9pU1mrXڄI-x ܀pԍ+4eBexeUpatm7h;#+̖yrb7҃5u©^Q<Z5aB M멆 {:i68̴*ǩPW睆ZsY|@
Wqs\_|̾==G}SYټXyĄب26S};ױ&O$sPImh排[ؾ5UuF-Uf堫g|ZorG4b/?_	a@-#fhϥ@prz`Fa*)^lFEu 	i_H rM;ZY%6rIՉ=7GEV]WoDj9zYͩxӜ|Ogu]!"@N3Q/C,F4?9Ӧ[x$lR9i)#wEM{i.p^	)g4SzdՋ}bMIǒj~/RլމTn33Qy= W DX  {
   "background": {
      "scripts": [ "tts_extension.js" ],
      "persistent": false
   },
   "description": "Component extension providing speech via the Google network text-to-speech service.",
   "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8GSbNUMGygqQTNDMFGIjZNcwXsHLzkNkHjWbuY37PbNdSDZ4VqlVjzbWqODSe+MjELdv5Keb51IdytnoGYXBMyqKmWpUrg+RnKvQ5ibWr4MW9pyIceOIdp9GrzC1WZGgTmZismYR3AjaIpufZ7xDdQQv+XrghPWCkdVqLN+qZDA1HU+DURznkMICiDDSH2sU0egm9UbWfS218bZqzKeQDiC3OnTPlaxcbJtKUuupIm5knjze3Wo9Ae9poTDMzKgchg0VlFCv3uqox+wlD8sjXBoyBCCK9HpImdVAF1a7jpdgiUHpPeV/26oYzM9/grltwNR3bzECQgSpyXp0eyoegwIDAQAB",
   "manifest_version": 2,
   "name": "Google Network Speech",
   "permissions": [
     "systemPrivate",
     "ttsEngine",
     "https://www.google.com/"
   ],
   "tts_engine": {
      "voices": [
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "de-DE",
          "voice_name": "Google Deutsch",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "en-US",
          "voice_name": "Google US English",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "en-GB",
          "voice_name": "Google UK English Female",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "male",
          "lang": "en-GB",
          "voice_name": "Google UK English Male",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "es-ES",
          "voice_name": "Google español",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "es-US",
          "voice_name": "Google español de Estados Unidos",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "fr-FR",
          "voice_name": "Google français",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "hi-IN",
          "voice_name": "Google हिन्दी",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "id-ID",
          "voice_name": "Google Bahasa Indonesia",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "it-IT",
          "voice_name": "Google italiano",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "ja-JP",
          "voice_name": "Google 日本語",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "ko-KR",
          "voice_name": "Google 한국의",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "nl-NL",
          "voice_name": "Google Nederlands",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "pl-PL",
          "voice_name": "Google polski",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "pt-BR",
          "voice_name": "Google português do Brasil",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "ru-RU",
          "voice_name": "Google русский",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "zh-CN",
          "voice_name": "Google 普通话（中国大陆）",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "zh-HK",
          "voice_name": "Google 粤語（香港）",
          "remote": true
        },
        {
          "event_types": [ "start", "end", "error" ],
          "gender": "female",
          "lang": "zh-TW",
          "voice_name": "Google 國語（臺灣）",
          "remote": true
        }
      ]
   },
   "version": "1.0"
}
     Wn8}WL-e;1:$] >-M,2)TȿdŗH"27a/nQ dnO:cB7~8s4EVL=?.#LL: 9:<cƢ;Joq٠icIr8n]8s%AK&$ui=׀cSk(7SV-ĥo!y[ ba,sa*C8d9e.9AK-?A2i
\`,!9LTJTpsHe]8H:AqϙI5`wN%'M)&HL63\ul78y9mns)\obÄ,-9~U.;^_*RFp`@m&VR~'_jUUpKٙaV!p[)\ jm8*}kXQ9[՛7(ƺg2}KQKeY% ef,uBZ_)C7ᖗQh^2.D*:1zoxoSk3wL(	9$Kvqă`]]@YТ[+~%!cAR>[1I5/.1$^ϙ8*~vd7N{`V݊M8eEUl5&a!"C>_1y϶
]a^%!oBԬNMc\57Uչش65(]0DD	>ȿQf"/dgh4]KJ2J	mznː&5>}ؔ.qDA+61xWϐjfZyqل+ڔlm_QP7>Hkw6o45]9pDi5jX&!TgjA!uh6 5V{NXu V
[ERV]j=ڵNT^ؾ1*[O8>k+}vwlate,|ĝ$%77W lnWK^OWPl4k@5B+j[^pOm5ͽ Vhwʯ@Ӗ2
       Wko6_qJZlZ/V }IEaPuD&=k|HIzOmls}:ކ5[hqVXH<yNBWBi^Y74Ѡ<lo&`aJsry.QK![ .JRpff3	:dB:񳃣'G0%!9MxWh3əe#	q+(ln&V(IteJw^iJf| p6@]UCE60JZzL5MJ CF*EK~1ͦev^-ɉSf,GH^Vg]dRKadJHMP(	X@ɲ\)!+)o(9a굪Qt\ݩ_옒9fY2| S^콂}פhj@Y԰&mC\Osa]P/$/<C	ǱU|I^yZu9q>_P[fhlzϾa:)Hf}r-|s	L.b=r"gt+a>JPI]m#Ei2ԙ~ISAk84pP" hmgD~l--Qbc E(z.|<fL/T^ ]9||R*=~jPdD+xAZyKfFn\u@e?CKjGSaIziۛv%ܛU$FHf3
sP2OnL1'nZcg2rR50bIKuO1C_vaHCQ8W'h8hp'442ph@i(3M6,Ϗ.1uu_>Ǌ܌(5zT	Z^MzU*Z]pͪTSF:r.InTܑ78\9G 6^;"^"'~3!l3=q'~TYLvuп}~>WyT|Ž^KZ5gq\k]dV2'Q?jo.YgѼntCȫ3/Rmk7Wy֑j=$|ZW'I$2/ᷮ^Z3#exÌw&Y.*`1Z<4<OzPBU5;JИ)4Z׳σ:?<?Xݎwϖux5{cWK`S
y2c}fYvֻ-o<PƶrjpCW]ARo|P[VӌdLYsq=Ax!u)#\9[1}E+}H>kbX#mkx{i$Sa~#%&\LMK̏ݳtb2TBFN@HszUd6NYޓ+O3V  <!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>$2</title>
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <style>
  body {
    font-size: 13px;
  }
  </style>
</head>
<body dir="$3"><div id="$1">$2</div></body>
</html>
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>$1</title>
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <style type="text/css">
  #title,
  #description {
    font-size: 13px;
  }
  #title {
    font-weight: bold;
  }
  </style>
</head>
<body dir="$3">
  <div id="title">$1</div>
  <div id="description">$2</div>
</body>
</html>
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>$2</title>
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <style>
  body {
    direction: $5;
  }
  #icon {
    height: 32px;
    width: 32px;
    float: $4;
  }
  #title {
    margin-$4: 38px;
    font-weight: bold;
    font-size: 13px;
  }
  #description {
    margin-$4: 38px;
    font-size: 13px;
  }
  </style>
</head>
<body>
  <div id="icon"><img src="$1" width="32" height="32"></div>
  <div id="title">$2</div>
  <div id="description">$3</div>
</body>
</html>
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>$i18n{devicesTitle}</title>
  <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
  <link rel="stylesheet" href="chrome://resources/css/overlay.css">
  <link rel="stylesheet" href="chrome://resources/css/spinner.css">
  <style>/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  margin: 21px 10px 24px 10px;
}

h1 {
  margin: 0 0 13px 0;
}

h2 {
  margin: 23px 0 0 0;
}

header {
  border-bottom: 1px solid #eee;
  max-width: 718px;
}

.device {
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAsklEQVR4Xr3UvQ2DMBSF0StKpmCBLMAsVIyBWCCKBEpIjDH5KVJlSuIiusL2syMadDo/fY39ZCwb7RzgLosHHY6CLh70OAn6eHCWBQEdZEGAHA3efzTIGWQtDC5RA5RlspYBZgwJY1mXNUbMDKBxTdBFVVTQ0OvglqDwspQcaAFnDDBB/Uz+lTozBoaBWUDSjLdETiDMnBfmZnobvH7xcAhXer0f1sdjz+LBU7Z5W/f9BL71COOFW+QSiQAAAABJRU5ErkJggg==) no-repeat;
  margin: 23px 0;
  max-width: 695px;
  overflow: hidden;
}

html[dir='rtl'] .device {
  background-position: right top;
}

.device .device-info {
  float: left;
  padding-inline-start: 40px;
}

html[dir='rtl'] .device .device-info {
  float: right;
}

.device button {
  float: right;
}

html[dir='rtl'] .device button {
  float: left;
}

.subline,
.device-subline {
  color: #999;
  margin: 5px 0;
}

h3.device-name {
  margin: 0;
}

.register-page {
  padding: 15px;
  width: 600px;
}

.register-page .button-list {
  padding-top: 15px;
  text-align: right;
}

html[dir='rtl'] .register-page .button-list {
  text-align: left;
}

.controls {
  border-bottom: 1px solid #eee;
  max-width: 711px;
}

html[dir='rtl'] .controls {
  padding: 13px 4px 7px 3px;
}

.controls .subline {
  margin-inline-start: 10px;
}

.login-promo {
  padding-bottom: 5px;
  padding-top: 5px;
}

.inline-login-promo {
  display: inline;
}

.inline-spinner {
  position: relative;
  top: 3px;
}

.cloud-print-message {
  margin: 23px 0;
}

section {
  margin-bottom: 23px;
}

.dialog-contents {
  padding-left: 17px;
}
</style>

  <script src="chrome://resources/js/action_link.js"></script>
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/cr/ui/overlay.js"></script>
  <script src="chrome://resources/js/cr/ui/focus_manager.js"></script>
  <script src="local_discovery.js"></script>
  <script src="strings.js"></script>
</head>
<body>
  <div class="page" id="main-page">
    <div class="overlay" id="overlay" hidden>
      <div id="register-overlay" class="page">
        <div class="close-button"></div>
        <div id="register-page-confirm" class="register-page">
          <h1>$i18n{confirmRegistration}</h1>
          <div class="dialog-contents">
            <div id="register-message">
              $i18nRaw{registerPrinterInformationMessage}
            </div>

            <div class="button-list">
              <div id="register-overlay-login-promo"
                   class="inline-login-promo"
                   hidden>
                <span>$i18n{registerNeedLogin}</span>
                <a is="action-link" id="register-overlay-login-button">
                  $i18n{cloudDevicesLogin}
                </a>
              </div>
              <button class="register-cancel">$i18n{cancel}</button>
              <button id="register-continue">$i18n{confirm}</button>
            </div>
          </div>
        </div>

        <div id="register-printer-page-adding1" class="register-page">
          <h1>$i18n{addingPrinter}</h1>
          <div class="dialog-contents">
            <div>$i18n{addingPrinterMessage1}</div>
            <div class="button-list">
              <button class="register-cancel">$i18n{cancel}</button>
            </div>
          </div>
        </div>

        <div id="register-printer-page-adding2" class="register-page">
          <h1>$i18n{addingPrinter}</h1>
          <div class="dialog-contents">
            <div class="inline-spinner"> </div>
            <span>$i18n{addingPrinterMessage2}</span>
            <div class="button-list">
              <button class="register-cancel">$i18n{cancel}</button>
            </div>
          </div>
        </div>

        <div id="register-page-error" class="register-page">
          <h1>$i18n{addingError}</h1>
          <div class="dialog-contents">
            <div id="error-message">$i18n{addingErrorMessage}</div>
            <div class="button-list">
              <button id="register-error-exit">$i18n{ok}</button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <header>
      <h1>$i18n{devicesTitle}</h1>
    </header>

    <div class="controls" id="printers">
      <h2>$i18n{availableDevicesTitle}</h2>

      <div id="register-login-promo" class="login-promo cloud-print-message"
           hidden>
        <span>$i18n{registerNeedLogin}</span>
        <a is="action-link" id="register-login-link">
          $i18n{cloudDevicesLogin}
        </a>
      </div>
      <div id="no-printers-message" class="cloud-print-message">
        $i18n{noPrintersOnNetworkExplanation}
      </div>

      <div class="devices" id="register-device-list"></div>

      
        <section id="cloud-print-connector-section">
          <h2>$i18n{titleConnector}</h2>
          <div>
            <p id="cloudPrintConnectorLabel"></p>

          <div>
            <button id="cloudPrintConnectorSetupButton"></button>
          </div>
        </div>
        </section>
      
    </div>

    <div id="my-devices-container">
    <h2>$i18n{myDevicesTitle}</h2>
    <div id="cloud-devices-loading" class="cloud-print-message" hidden>
      <div class="inline-spinner"> </div> <span>$i18n{loading}</span>
    </div>
    <div id="cloud-devices-login-promo" class="login-promo cloud-print-message"
         hidden>
      <span>$i18n{cloudDevicesNeedLogin}</span>
      <a is="action-link" id="cloud-devices-login-link">
        $i18n{cloudDevicesLogin}
      </a>
    </div>
    <div id="cloud-devices-unavailable"
         class="cloud-print-message" hidden>
      <span>$i18n{cloudDevicesUnavailable}</span>
      <a is="action-link" role="button" id="cloud-devices-retry-link">
        $i18n{retryLoadCloudDevices}
      </a>
    </div>
    <div id="cloud-devices">

    </div>
    </div>
  </div>
</body>
</html>
/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  margin: 21px 10px 24px 10px;
}

h1 {
  margin: 0 0 13px 0;
}

h2 {
  margin: 23px 0 0 0;
}

header {
  border-bottom: 1px solid #eee;
  max-width: 718px;
}

.device {
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAsklEQVR4Xr3UvQ2DMBSF0StKpmCBLMAsVIyBWCCKBEpIjDH5KVJlSuIiusL2syMadDo/fY39ZCwb7RzgLosHHY6CLh70OAn6eHCWBQEdZEGAHA3efzTIGWQtDC5RA5RlspYBZgwJY1mXNUbMDKBxTdBFVVTQ0OvglqDwspQcaAFnDDBB/Uz+lTozBoaBWUDSjLdETiDMnBfmZnobvH7xcAhXer0f1sdjz+LBU7Z5W/f9BL71COOFW+QSiQAAAABJRU5ErkJggg==) no-repeat;
  margin: 23px 0;
  max-width: 695px;
  overflow: hidden;
}

html[dir='rtl'] .device {
  background-position: right top;
}

.device .device-info {
  float: left;
  padding-inline-start: 40px;
}

html[dir='rtl'] .device .device-info {
  float: right;
}

.device button {
  float: right;
}

html[dir='rtl'] .device button {
  float: left;
}

.subline,
.device-subline {
  color: #999;
  margin: 5px 0;
}

h3.device-name {
  margin: 0;
}

.register-page {
  padding: 15px;
  width: 600px;
}

.register-page .button-list {
  padding-top: 15px;
  text-align: right;
}

html[dir='rtl'] .register-page .button-list {
  text-align: left;
}

.controls {
  border-bottom: 1px solid #eee;
  max-width: 711px;
}

html[dir='rtl'] .controls {
  padding: 13px 4px 7px 3px;
}

.controls .subline {
  margin-inline-start: 10px;
}

.login-promo {
  padding-bottom: 5px;
  padding-top: 5px;
}

.inline-login-promo {
  display: inline;
}

.inline-spinner {
  position: relative;
  top: 3px;
}

.cloud-print-message {
  margin: 23px 0;
}

section {
  margin-bottom: 23px;
}

.dialog-contents {
  padding-left: 17px;
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Javascript for local_discovery.html, served from chrome://devices/
 * This is used to show discoverable devices near the user as well as
 * cloud devices registered to them.
 *
 * The object defined in this javascript file listens for callbacks from the
 * C++ code saying that a new device is available as well as manages the UI for
 * registering a device on the local network.
 */

cr.define('local_discovery', function() {
  'use strict';

  // Histogram buckets for UMA tracking.
  /** @const */ const DEVICES_PAGE_EVENTS = {
    OPENED: 0,
    LOG_IN_STARTED_FROM_REGISTER_PROMO: 1,
    LOG_IN_STARTED_FROM_DEVICE_LIST_PROMO: 2,
    ADD_PRINTER_CLICKED: 3,
    REGISTER_CLICKED: 4,
    REGISTER_CONFIRMED: 5,
    REGISTER_SUCCESS: 6,
    REGISTER_CANCEL: 7,
    REGISTER_FAILURE: 8,
    MANAGE_CLICKED: 9,
    REGISTER_CANCEL_ON_PRINTER: 10,
    REGISTER_TIMEOUT: 11,
    LOG_IN_STARTED_FROM_REGISTER_OVERLAY_PROMO: 12,
    MAX_EVENT: 13,
  };

  /**
   * Map of service names to corresponding service objects.
   * @type {Object<string,Service>}
   */
  const devices = {};

  /**
   * Whether or not the user is currently logged in.
   * @type bool
   */
  let isUserLoggedIn = true;

  /**
   * Whether or not the user is supervised or off the record.
   * @type bool
   */
  let isUserSupervisedOrOffTheRecord = false;

  /**
   * Whether or not the path-based dialog has been shown.
   * @type bool
   */
  let dialogFromPathHasBeenShown = false;

  /**
   * Focus manager for page.
   */
  let focusManager = null;

  /**
   * Object that represents a device in the device list.
   * @param {Object} info Information about the device.
   * @constructor
   */
  function Device(info, registerEnabled) {
    this.info = info;
    this.domElement = null;
    this.registerButton = null;
    this.registerEnabled = registerEnabled;
  }

  Device.prototype = {
    /**
     * Update the device.
     * @param {Object} info New information about the device.
     */
    updateDevice: function(info) {
      this.info = info;
      this.renderDevice();
    },

    /**
     * Delete the device.
     */
    removeDevice: function() {
      this.deviceContainer().removeChild(this.domElement);
    },

    /**
     * Render the device to the device list.
     */
    renderDevice: function() {
      if (this.domElement) {
        clearElement(this.domElement);
      } else {
        this.domElement = document.createElement('div');
        this.deviceContainer().appendChild(this.domElement);
      }

      this.registerButton = fillDeviceDescription(
          this.domElement, this.info.display_name, this.info.description,
          loadTimeData.getString('serviceRegister'),
          this.showRegister.bind(this));

      this.setRegisterEnabled(this.registerEnabled);
    },

    /**
     * Return the correct container for the device.
     */
    deviceContainer: function() {
      return $('register-device-list');
    },

    /**
     * Register the device.
     */
    register: function() {
      recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CONFIRMED);
      chrome.send('registerDevice', [this.info.service_name]);
      setRegisterPage('register-printer-page-adding1');
    },
    /**
     * Show registrtation UI for device.
     */
    showRegister: function() {
      recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CLICKED);
      $('register-continue').onclick = this.register.bind(this);

      showRegisterOverlay();
    },
    /**
     * Set registration button enabled/disabled
     */
    setRegisterEnabled: function(isEnabled) {
      this.registerEnabled = isEnabled;
      if (this.registerButton) {
        this.registerButton.disabled = !isEnabled;
      }
    }
  };

  /**
   * Manages focus for local devices page.
   * @constructor
   * @extends {cr.ui.FocusManager}
   */
  function LocalDiscoveryFocusManager() {
    cr.ui.FocusManager.call(this);
    this.focusParent_ = document.body;
  }

  LocalDiscoveryFocusManager.prototype = {
    __proto__: cr.ui.FocusManager.prototype,
    /** @override */
    getFocusParent: function() {
      return document.querySelector('#overlay .showing') || $('main-page');
    }
  };

  /**
   * Returns a textual representation of the number of printers on the network.
   * @return {string} Number of printers on the network as localized string.
   */
  function generateNumberPrintersAvailableText(numberPrinters) {
    if (numberPrinters == 0) {
      return loadTimeData.getString('printersOnNetworkZero');
    } else if (numberPrinters == 1) {
      return loadTimeData.getString('printersOnNetworkOne');
    } else {
      return loadTimeData.getStringF(
          'printersOnNetworkMultiple', numberPrinters);
    }
  }

  /**
   * Fill device element with the description of a device.
   * @param {HTMLElement} deviceDomElement Element to be filled.
   * @param {string} name Name of device.
   * @param {string} description Description of device.
   * @param {string} buttonText Text to appear on button.
   * @param {function()?} buttonAction Action for button.
   * @return {HTMLElement} The button (for enabling/disabling/rebinding)
   */
  function fillDeviceDescription(
      deviceDomElement, name, description, buttonText, buttonAction) {
    deviceDomElement.classList.add('device');

    const deviceInfo = document.createElement('div');
    deviceInfo.className = 'device-info';
    deviceDomElement.appendChild(deviceInfo);

    const deviceName = document.createElement('h3');
    deviceName.className = 'device-name';
    deviceName.textContent = name;
    deviceInfo.appendChild(deviceName);

    const deviceDescription = document.createElement('div');
    deviceDescription.className = 'device-subline';
    deviceDescription.textContent = description;
    deviceInfo.appendChild(deviceDescription);

    let button;
    if (buttonAction) {
      button = document.createElement('button');
      button.textContent = buttonText;
      button.addEventListener('click', buttonAction);
      deviceDomElement.appendChild(button);
    }

    return button;
  }

  /**
   * Show the register overlay.
   */
  function showRegisterOverlay() {
    recordUmaEvent(DEVICES_PAGE_EVENTS.ADD_PRINTER_CLICKED);

    const registerOverlay = $('register-overlay');
    registerOverlay.classList.add('showing');
    registerOverlay.focus();

    $('overlay').hidden = false;
    setRegisterPage('register-page-confirm');
  }

  /**
   * Hide the register overlay.
   */
  function hideRegisterOverlay() {
    $('register-overlay').classList.remove('showing');
    $('overlay').hidden = true;
  }

  /**
   * Clear a DOM element of all children.
   * @param {HTMLElement} element DOM element to clear.
   */
  function clearElement(element) {
    while (element.firstChild) {
      element.removeChild(element.firstChild);
    }
  }

  /**
   * Announce that a registration failed.
   */
  function onRegistrationFailed() {
    $('error-message').textContent =
        loadTimeData.getString('addingErrorMessage');
    setRegisterPage('register-page-error');
    recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_FAILURE);
  }

  /**
   * Announce that a registration has been canceled on the printer.
   */
  function onRegistrationCanceledPrinter() {
    $('error-message').textContent =
        loadTimeData.getString('addingCanceledMessage');
    setRegisterPage('register-page-error');
    recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CANCEL_ON_PRINTER);
  }

  /**
   * Announce that a registration has timed out.
   */
  function onRegistrationTimeout() {
    $('error-message').textContent =
        loadTimeData.getString('addingTimeoutMessage');
    setRegisterPage('register-page-error');
    recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_TIMEOUT);
  }

  /**
   * Update UI to reflect that registration has been confirmed on the printer.
   */
  function onRegistrationConfirmedOnPrinter() {
    setRegisterPage('register-printer-page-adding2');
  }

  /**
   * Update device unregistered device list, and update related strings to
   * reflect the number of devices available to register.
   * @param {string} name Name of the device.
   * @param {string} info Additional info of the device or null if the device
   *                          has been removed.
   */
  function onUnregisteredDeviceUpdate(name, info) {
    if (info) {
      if (devices.hasOwnProperty(name)) {
        devices[name].updateDevice(info);
      } else {
        devices[name] = new Device(info, isUserLoggedIn);
        devices[name].renderDevice();
      }

      if (name == getOverlayIDFromPath() && !dialogFromPathHasBeenShown) {
        dialogFromPathHasBeenShown = true;
        devices[name].showRegister();
      }
    } else {
      if (devices.hasOwnProperty(name)) {
        devices[name].removeDevice();
        delete devices[name];
      }
    }

    updateUIToReflectState();
  }

  /**
   * Create the DOM for a cloud device described by the device section.
   * @param {Object} device The device to create the DOM for.
   */
  function createCloudDeviceDOM(device) {
    const devicesDomElement = document.createElement('div');

    const description =
        device.description || loadTimeData.getString('noDescriptionPrinter');

    fillDeviceDescription(
        devicesDomElement, device.display_name, description,
        loadTimeData.getString('manageDevice'),
        manageCloudDevice.bind(null, device.id));
    return devicesDomElement;
  }

  /**
   * Handle a list of cloud devices available to the user globally.
   * @param {Array<Object>} devicesList List of devices.
   */
  function onCloudDeviceListAvailable(devicesList) {
    const devicesListLength = devicesList.length;
    const devicesContainer = $('cloud-devices');

    clearElement(devicesContainer);
    $('cloud-devices-loading').hidden = true;

    for (let i = 0; i < devicesListLength; i++) {
      devicesContainer.appendChild(createCloudDeviceDOM(devicesList[i]));
    }
  }

  /**
   * Handle the case where the list of cloud devices is not available.
   */
  function onCloudDeviceListUnavailable() {
    if (isUserLoggedIn) {
      $('cloud-devices-loading').hidden = true;
      $('cloud-devices-unavailable').hidden = false;
    }
  }

  /**
   * Handle the case where the cache for local devices has been flushed..
   */
  function onDeviceCacheFlushed() {
    for (const deviceName in devices) {
      devices[deviceName].removeDevice();
      delete devices[deviceName];
    }

    updateUIToReflectState();
  }

  /**
   * Update UI strings to reflect the number of local devices.
   */
  function updateUIToReflectState() {
    const numberPrinters = $('register-device-list').children.length;
    if (numberPrinters == 0) {
      $('no-printers-message').hidden = false;

      $('register-login-promo').hidden = true;
    } else {
      $('no-printers-message').hidden = true;
      $('register-login-promo').hidden =
          isUserLoggedIn || isUserSupervisedOrOffTheRecord;
    }
    if (!($('register-login-promo').hidden) ||
        !($('cloud-devices-login-promo').hidden) ||
        !($('register-overlay-login-promo').hidden)) {
      chrome.send(
          'metricsHandler:recordAction', ['Signin_Impression_FromDevicesPage']);
    }
  }

  /**
   * Announce that a registration succeeeded.
   * @param {!Object} deviceData data describing the device that was registered.
   */
  function onRegistrationSuccess(deviceData) {
    hideRegisterOverlay();

    if (deviceData.service_name == getOverlayIDFromPath()) {
      window.close();
    }

    const deviceDOM = createCloudDeviceDOM(deviceData);
    $('cloud-devices').insertBefore(deviceDOM, $('cloud-devices').firstChild);
    recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_SUCCESS);
  }

  /**
   * Set the page that the register wizard is on.
   * @param {string} pageId ID string for page.
   */
  function setRegisterPage(pageId) {
    const pages = $('register-overlay').querySelectorAll('.register-page');
    const pagesLength = pages.length;
    for (let i = 0; i < pagesLength; i++) {
      pages[i].hidden = true;
    }

    $(pageId).hidden = false;
  }

  /**
   * Request the device list.
   */
  function requestDeviceList() {
    if (isUserLoggedIn) {
      clearElement($('cloud-devices'));
      $('cloud-devices-loading').hidden = false;
      $('cloud-devices-unavailable').hidden = true;

      chrome.send('requestDeviceList');
    }
  }

  /**
   * Go to management page for a cloud device.
   * @param {string} deviceId ID of device.
   */
  function manageCloudDevice(deviceId) {
    recordUmaEvent(DEVICES_PAGE_EVENTS.MANAGE_CLICKED);
    chrome.send('openCloudPrintURL', [deviceId]);
  }

  /**
   * Record an event in the UMA histogram.
   * @param {number} eventId The id of the event to be recorded.
   * @private
   */
  function recordUmaEvent(eventId) {
    chrome.send(
        'metricsHandler:recordInHistogram',
        ['LocalDiscovery.DevicesPage', eventId, DEVICES_PAGE_EVENTS.MAX_EVENT]);
  }

  /**
   * Cancel the registration.
   */
  function cancelRegistration() {
    hideRegisterOverlay();
    chrome.send('cancelRegistration');
    recordUmaEvent(DEVICES_PAGE_EVENTS.REGISTER_CANCEL);
  }

  /**
   * Retry loading the devices from Google Cloud Print.
   */
  function retryLoadCloudDevices() {
    requestDeviceList();
  }

  /**
   * User is not logged in.
   */
  function setUserLoggedIn(userLoggedIn, userSupervisedOrOffTheRecord) {
    isUserLoggedIn = userLoggedIn;
    isUserSupervisedOrOffTheRecord = userSupervisedOrOffTheRecord;

    $('cloud-devices-login-promo').hidden =
        isUserLoggedIn || isUserSupervisedOrOffTheRecord;
    $('register-overlay-login-promo').hidden =
        isUserLoggedIn || isUserSupervisedOrOffTheRecord;
    $('register-continue').disabled =
        !isUserLoggedIn || isUserSupervisedOrOffTheRecord;

    $('my-devices-container').hidden = userSupervisedOrOffTheRecord;

    if (isUserSupervisedOrOffTheRecord) {
      $('cloud-print-connector-section').hidden = true;
    }

    if (isUserLoggedIn && !isUserSupervisedOrOffTheRecord) {
      requestDeviceList();
      $('register-login-promo').hidden = true;
    } else {
      $('cloud-devices-loading').hidden = true;
      $('cloud-devices-unavailable').hidden = true;
      clearElement($('cloud-devices'));
      hideRegisterOverlay();
    }

    updateUIToReflectState();

    for (const device in devices) {
      devices[device].setRegisterEnabled(isUserLoggedIn);
    }
  }

  function openSignInPage() {
    chrome.send('showSyncUI');
  }

  function registerLoginButtonClicked() {
    recordUmaEvent(DEVICES_PAGE_EVENTS.LOG_IN_STARTED_FROM_REGISTER_PROMO);
    openSignInPage();
  }

  function registerOverlayLoginButtonClicked() {
    recordUmaEvent(
        DEVICES_PAGE_EVENTS.LOG_IN_STARTED_FROM_REGISTER_OVERLAY_PROMO);
    openSignInPage();
  }

  function cloudDevicesLoginButtonClicked() {
    recordUmaEvent(DEVICES_PAGE_EVENTS.LOG_IN_STARTED_FROM_DEVICE_LIST_PROMO);
    openSignInPage();
  }

  /**
   * Set the Cloud Print proxy UI to enabled, disabled, or processing.
   * @private
   */
  function setupCloudPrintConnectorSection(disabled, label, allowed) {
    if (!cr.isChromeOS) {
      $('cloudPrintConnectorLabel').textContent = label;
      if (disabled || !allowed) {
        $('cloudPrintConnectorSetupButton').textContent =
            loadTimeData.getString('cloudPrintConnectorDisabledButton');
      } else {
        $('cloudPrintConnectorSetupButton').textContent =
            loadTimeData.getString('cloudPrintConnectorEnabledButton');
      }
      $('cloudPrintConnectorSetupButton').disabled = !allowed;

      if (disabled) {
        $('cloudPrintConnectorSetupButton').onclick = function(event) {
          // Disable the button, set its text to the intermediate state.
          $('cloudPrintConnectorSetupButton').textContent =
              loadTimeData.getString('cloudPrintConnectorEnablingButton');
          $('cloudPrintConnectorSetupButton').disabled = true;
          chrome.send('showCloudPrintSetupDialog');
        };
      } else {
        $('cloudPrintConnectorSetupButton').onclick = function(event) {
          chrome.send('disableCloudPrintConnector');
          requestDeviceList();
        };
      }
    }
  }

  function getOverlayIDFromPath() {
    if (document.location.pathname == '/register') {
      const params = parseQueryParams(document.location);
      return params['id'] || null;
    }
  }

  document.addEventListener('DOMContentLoaded', function() {
    cr.ui.overlay.setupOverlay($('overlay'));
    cr.ui.overlay.globalInitialization();
    $('overlay').addEventListener('cancelOverlay', cancelRegistration);

    [].forEach.call(
        document.querySelectorAll('.register-cancel'), function(button) {
          button.addEventListener('click', cancelRegistration);
        });

    $('register-error-exit').addEventListener('click', cancelRegistration);


    $('cloud-devices-retry-link')
        .addEventListener('click', retryLoadCloudDevices);

    $('cloud-devices-login-link')
        .addEventListener('click', cloudDevicesLoginButtonClicked);

    $('register-login-link')
        .addEventListener('click', registerLoginButtonClicked);

    $('register-overlay-login-button')
        .addEventListener('click', registerOverlayLoginButtonClicked);

    focusManager = new LocalDiscoveryFocusManager();
    focusManager.initialize();

    chrome.send('start');
    recordUmaEvent(DEVICES_PAGE_EVENTS.OPENED);
  });

  return {
    onRegistrationSuccess: onRegistrationSuccess,
    onRegistrationFailed: onRegistrationFailed,
    onUnregisteredDeviceUpdate: onUnregisteredDeviceUpdate,
    onRegistrationConfirmedOnPrinter: onRegistrationConfirmedOnPrinter,
    onCloudDeviceListAvailable: onCloudDeviceListAvailable,
    onCloudDeviceListUnavailable: onCloudDeviceListUnavailable,
    onDeviceCacheFlushed: onDeviceCacheFlushed,
    onRegistrationCanceledPrinter: onRegistrationCanceledPrinter,
    onRegistrationTimeout: onRegistrationTimeout,
    setUserLoggedIn: setUserLoggedIn,
    setupCloudPrintConnectorSection: setupCloudPrintConnectorSection,
  };
});
     N0D&w+BiOPei%TߓB,<d[@cw2P*̪
;;ĒlfHVސ 99"V@/#F:FU,[O(2V);f֎Y>qv?7Kb|Gnn5 E\I\6h&ܒA]i̲OtNևy!i
QbR,       EAk1+ޡkYҍ5npJEf-Zr)f$!0%؃a||^a0m:!!x&TQDHLoH#؈SP5!_Lȗ0YE.%T&>9r6vkvir`<˨=qVL^gd>N+`3=T@*eka+,eMt;&#DtbW:$XAOy*?̯Dk}{~Q%lU:f^j>Mk36%ݮ0&z-T#9fټԵWM]u~Rw]{MYTV]]5ex2!  <!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="strings.js"></script>
  <script src="hats.js"></script>
</head>
<body>
  <webview id="survey" src="http://surveys.google.com/unit?site=z4cctguzopq5x2ftal6vdgjrui">
  </webview>
</body>
</html>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('hats', function() {
  'use strict';

  // Install the survey script from HaTS.
  function setScript() {
    const webview = $('survey');
    const loadstop = function() {
      webview.executeScript({
        code: 'document.getElementById(\'contain-402\').style.position =' +
            ' \'static\''
      });
      chrome.send('afterShow');
    };
    webview.addEventListener('loadstop', loadstop);
  }
  // Return an object with all of the exports.
  return {
    setScript: setScript,
  };
});


document.addEventListener('DOMContentLoaded', hats.setScript);
     <rHs1OZxjePVCREYkmmm
WpGj_#Gʓ{f  @ǗW-9g-XL˼;bq^v	_rf@%T|`js;643=iT/,`j ΂t84ՠgGۘ~&5K~4?ƚztr^ҦcёG}'4iEN'jh~JhOKӀHRєBcEa0u<LڦIxC0B<8LO0yx5T'%Q}WhaC`DSm2iℶārJLI䧣=Κhj{}kE؊明"1~s||H!5tEE=ڳ!qDllEd(.[dbR^<qi9вO70'R=A
ayW:an9L8V+ّ`1g17 $+@2oc/˙9(,_%KABv4`Gg&@Iwk)[S'vmitv$ʴ
@`UqWjPU[SNZO(j2FfPwBMDCa`tHjdU\ڈJ.rkBN&4JD]%Ơ@0 |q7|
*l0(n2ޛ:55}hB
T曧3_b{k 9HSR(TH)
	O*b&`)Xp]?hPQKLpʵ~(!/槠Q0<uA|\ޗ`<d萴&%dF (XGD;+kS=c,C`l੶˲nbk^$F$S/Ϫsd7nLC3oFNCECKڿ:~42mF(%-b;67ɸH
Kc͹tl| ivj:}nrr90m(+ .!86* ,u\'"?Mp]NM<R5@L^sbI2\V=4cK _TtͤSR<Oޒ\/gcrm1=4cўlQ&72P]UɺMbY_P,@4Lk+a[hQ"ׁPEzRb9vsճqɈ2@Y1	IQMB,ff-r9&Q[CmFHARm%zݒ-nOqŸn-NdėXG'NJqfj磥tf+՚r@ dwD "
ā(#r#"EQL$ I$Bf_6fQߓ!UJʇM-R5]xet`Oe, |,Jȿf_5|]s9բ"RU=mMY8FWߏ2O!Ǎ71~\ڪԛz]_6eE=tޭtKc}|-^rjJ[W޿n:y۫_vi͆k5_V~m|=ϏUs<=~fڹ|`ۋgZsܩ>wjvuC>kϮYemhe}GeT=+c0,߯jWWpe6߇vpXGP7}~:kok8><9}?@6{6WXo hlGUA>7E>/I2jF%Jn>CX %RX+(Qrl+uAp3MhV 9֨W^iyrpp:)jX$w (3
Hg  9H
¨Wj=`hm@{Ŀ&%\M gX\ >t/vWo.YHGA`;z~>wu]oFahsUliEi@P7t/ZɆI{>񤰼ǵ	OT{zl<]߱c@8Fõ|^q6ѝ1x6j47( \7sXm@T徱cezYF
j?@	#0`v}z޸
k _ +A~M{AZǮYTCxR|J\dԠ\^y"]ӫn5oKELc3VF}~Nթxr7Pnf3T}aQ.jh V{\A9sTHh]&{:/0p4rMdHѩcKW."e[ON-11
]N7a+߹WZ@ζ=;с^iLuLͨv3 2)ġ<&ǍifL,gBT{IQ4u`䜙&	]᱋O\>gkazE0[
cegt|z*YO @匇0hrC^A~9AB㕵 @k@W&#<R3,/ :.19 `;jr}9SYl" t(ԐD@i42L4#94y)ILYIEtPd:DbyZV#ft)RKUJG\vU%.^KMRkZnQl!,	y,(59tQ)@7` :p"Yh K͙HwȐգ@I@ h@7*X= NNv'|OVF{{r|ٵIyKΔ.z\2\S-08v~'_Qbsmhܑz(z|tFDB QnSjPiɹA3#ЯBq!i:JշS$ZC`?$5d%KUQ݅^d!+$I|Xs.م$y$E,G6|W7#}D+#ѵ%BP3ST v- eLA|^60io@~ +cc !$AjQ'4cGbH!֮;/MgTKX`#(x; gcLң::h56UydBnXK%yDS%yߡﻌIŊOtc1Y	baA.,x~ҦWGta9	Ա /;<tś$8Cj}=@9!+"?a)(q +W[ B"ǩr7r	LՄ-"O g9(eJwgD0.x"긒
r@<x4j"1.B`Ho/n\~EЄxR$7r7ɿxk\V"?$o}|ҩEXׅV (|
 !3Vh<~t-4u9-Pk~܇.&dVK~*OUܽƝI
B(7XĈ@P/Lƪ[ dY_C?$4F.#2y>߇o܊1bSU.T <q}3>ﯚT]#Rھo!KG>eC} j]rtS9#8hEtDlRQ=ϱ39"kyݾhTtQ@oyS`܌[LW5"<U{	q,K1)8/O`/L"-y6
Ȅ-@3YP/6!.\&ZdtEȣ:>ހ  X-\G:6/vV.?N-	Ybք࢈+*yh}t҈RR0LԌDC}	ӛ1Q}!?>9t(Ac3MGՕXp.HWO#|GP^
wa(`%NӰ`I0s!-
6ѿS0"ْrKDDxBfHl%k"F8pq@=BL $Ke7WDrKR3+CE0Gc&D_U9t(xv5?ML MMPW\A?(og7(T^'L>wH7ɋ< 6;'Z  1uY\$uKVr(ڔz$͋4yNA=ѲX{Siɜcy<jQFs3oV p:L^!'N.`6ƭdZ-arh&L:*( jјYu 5L%& 5q*1wrv,(eLx~`
Dv<p]5%ZnJ0 tMܰO#])Elrg^^4oE3cdlgbαxJa46i*KӌewΕ$b㧈"m"+If/,9f$g7&"u|iɅ 4N4_s 2%=L K)7]/<Rbxz03?MBM#^wҔAx,[P^c>`-N~!6 .& _w[9\>??UNZw%M8\qsЄF0;DC j=	s{ox1.M'qȋs|)իkC@%o`^d,,$ejَ4ݿv)~O#|7m{s27m[VelS"2A~
m`1Fj F >;_I{^38nS&eWeO}D81χWin; k!@wڿL7$P$֠[j2O;6H,9rLi&Hϥ; \L4qr-":EdYA%pv*+$f`dɗbXK`&);K#|βl܎Sj+,+ _Ugc tF[WIܸgv)"U4|<?lM7Z{]to:tnvqk,o.1Iyz4m]o֫h7|'
.o^~[=W0ﻘ͹+ʗA?k0ϣaQo"\ޟ=,E1?-0v0otF?\b.&q>4G+LԄ>aN\1Σ4?)+;jƉz$'\N3X%9 拡H^p8WL8Gݖ=6pʈw$<.`6@~".\8ss	ˌ˻%W|(QD7\uG?2t_[\nYD+wSEQCLvFXb1_K==^?qo+AA*(@TW02E+:jZֱMy |MS99Lߥ8;*~^OUt\B~=Nز%캯9>צzM+6F|qԉD3*/=16+q33>.<mLL*,\BAhb=p-+?9`!Υ0	b;b5HKC&|
-]M&M*HvGnS|sّFJ;f.bX       ePN +NbLt<bq&ƍnBt]ư qr>S83Ojq=i_Zkd#OHbY`gO-Tގ;{$gHpx[0iVLpfPJjh<nxx<UGHJ5jtW|EcŔd<(kJnu5\ל]\,lXo]65	r!ĮBKR?餩ƾ^+TRfSVS&]
(ww7́NEG2Aָ!GLeqU(3!˄`U]       W[o6~8"qS.Àa/ݞ`#D
$e-wxMɲEZ"yxTVWP)sPiPQmSqZv*Ge@E%l~[;FyLL@VS);Q J^YZIm I*9e-U
ߕkpv&a5߈~RsO)Kx.ER)OgҚţٲ6.!bX4x2-f{ŘilFz]ōSIU -ܶϔeMu,nIw
e.$tA+5=I4ש	Wz9#HY׊TK]f735t^JW	*nu?cC#:0V '02elRdE(N:b~;(	L|.`Bpti)Nz8x8}X`=I
L>S1I'Vu/QLhK6->"Ed;v>q'5B֓0|:;!֛5M:<<-JRRƩݸpsk\<gq.3dvV#ڹ|>Qv3Y)?	.GA-8ޝtxa*bCsߒ*8oV鷴IWAu?<Efl}h߳"Jj,I242S-GܪvB1%xÏ0}5x/O$P`Vɚo+wCa20-)VaM׎Հ齁$<1<gg(7}ii%*>ĥYvL	+uyPduLV:M8!7 Dn !K1]Lbxͺփ]<='އf+,.qęyeV63[ARnHc~4S;ib-S)X֑sS̘l4na1ڨp9{x=Zkyq'rz),Y^}<ɿFy	4zNOLU2o؆|Tf>_:aFSO6p'釔vsuQ4Ѐ6b9}~Ce_(շO1;	nm4:2}x0U2){?٪\K",H c[       Wn6}WP|C/ۢEPbCIvIɲ|I"3gf-|Έu`>ï%J4k\M,hHFpYW
V7&Gu@3d;ӏ̺D"GEjr Cҍ*@(zO>#n'qy+%2}ԍkTq#
W$v0> +hi֒R)BI?=&PB	,6Y2휮R-mxF1{iQ;!ag䔎3?';ݔ¡̴!T_o)Rcy<j?1bM-q0/CL	:-OWZ9fߘBr`euJ۷-iS}>iL-'z^gCd "5ƸC3zB)@&ATiw#ON`"Szcx=(D;PJQ[ajA1F!sm0R{i*TaĖGH\ofD6ёJ+bGX\0^ς٢&{%IAiHBzL	hMnHw0Ǫ>'EI&< P^HZ/<7`!8аB/fDo{hm۴kkRMqhuj^k!pikǕCbM0q~(x
ͅF;펽~0FCcEBxF2*6ֱ)_5))M@]c9jˉcIͅadAL`kJa;tA?	J`7t(@
uXh׃f\oCPMҪ2dP-!M:RgS{	J&M]=e>޵'	eߒ+{@tE̫^n["\u-G`%B4E#ݮ߿ä9_W,a_#*FF9klGy1sW6NVj/Ή!4$نE[xD{TRbk7"!;smŊ6ndZK/0y#'mpkݭnȝsǣXmvN6L 1>J._dmdM-|ų i'1&_br!~TD~oKnL-rQ֙i/*v~DB]eHYFvE5R*{&(UJ*kX9cpHBPZ:ߛBaX,Ko/`:O`^˶A0E=yrI//W       mN@y
_R5TEp	q} wa,Dwg]m2Ͽ߂jy~`Tmᶳ p#J'`24`3d8&=i"^lC$(6h0JtR'xz\?<<@Ñ0;E umh	>+{p~qS}iH=&7I2JSn%6]\M
gp՝Sv )rb<s~0Yi؉߻?ј%0c1%ԘuSeW|*4Eh.e*k͔叕rc)XP%оkˆ`8}       TN0}W*^JOBERxٍ[-m̙9ge0UcĢppU L
KQpPB,hn1O,oAյ\зh0kuD2W0)GZ #N/0$pB\2ki*RfC4ym.%hv<p7tL/SfdIrŏrC[8:?{8[% 4W̰V!Ԣe%(Ts16
Ѝ>}?^̔9x1-X4݅Pژ>1m@wz؀UkI!d'5jkW'HM:Q||m9 }`w/h	Q6xt(SdhAj$tPGrk75&Vmn%bȠ"RQ=aH|N|aw6=#^r5%wڋĬcNpxvj RY\jd!yGi~=,W'] I.JY_'.~Mq&y:eE6ԠU6ؽZR,?bEacq$S|2JP$y;}+h^Ӹ]^:M~]Z.       Z[o6~ϯ`1l"%Oδ(ZmmdR%)gI$E "υ|#_\9Xo$ζEEja\]Y"I N;g 	V󌠌5NI{яD}IPYd`2Lђ(N+Vn~gg_W$'+"]3*s\(AwmUIJʒ+d$ڭYY_B^!Zo?	gzM*Nv;ZJD6?1Gs*&QT;CԄņ=FODԥ6jӂH\%@Ϝ튜:)!U;U3u<qK%"1y$[3 ($ә~J	3D8#d2֛hܕn<)	9:0(z0(ZJ2I9.%[, e]YNz|/v8Db6y՜ghJ?n[	O̓[UOxԢL6GuRN2vt-6?Ϳ챭=,R;DSMKFo0]!]4>?ʾ*ѥsT BIP[Tˎ749ZA&m-ɺTm,JaPcs^+[eYkH5Y{Q6i{l I)Aa1=Bw|S]沬a9vH/ mq ;ɍSHInMg$S)
t/m μPv%QL2=NA؉Q-Γc/,O@8$Bk');!VrO3ouLSN-Yu$:ȉFGDXS*?
TWP݁tV;#nzDd:RᗃY'mM|[a;[G-c잦hگ#4Q**-cCPS1٨.uڑl$z9"mjt2SXh7	\7+'%F'Z6ɓ'U)MB] 	cm9fSvlCGF
Mu(v˚x2ݢmlӁ'4d[0ѕĹH2c9p೩IWqBS8`ǡlPXk	m9̫#l뇆{Dҧ^x$0zv;۽Pz\~<v9VRꈋtCLRM#Y>>"m!,Oiv(h6,$j(=Ҁ$\i0"B`?cPߓ?P^<K]kI3T{2n~8'~4%kAWv[Fos"c6ds#t쓪gvݣ7	ԡtU* W]io'h$g;=sAcMBwΞj9vw'v8w<5pٺj'vec4r롶-jᘠ7-`FkXnR`;5t~F-$szc"%JNiGMoGeT @o\)=aØbt'ppձ{7.Ixz9ʣM;4뵵[E?ѻ;:Jwěk6}z5ݜJ.e0`(O!{\:oZlmqfG-$cD3=nDx+:!?zͯjNN֫i%1p=H!,tY4dA1nVpA4aDz_-~=KTFMfԐ]|FD+҃~)oS`.FԦOA3<4P0UifX	ll7Tʨc.>~NBFϦVaجeZv1N	|:}<i7ƹĲew̻\]}
\zoN`77<Lݕ|ߞȸR rA|^56x]a0Gr$@שvhNLhM^k6u*d"GJrɍ _"xaMmPz+A»c`ʌl^1? {u TU$       =ksȑ+{.I͇+)X_gIZ	F$  dEO0/MUV+3=====ш2LkWMNOb.fdoQO
^֨"%hyMpk4"_*J+ROӊTŢ)9)iӄoID~>>VmFI4n4IdLUwGUpk+.Ä^9z,OŷbQuo@y\E!9S};Ћ;xQVERMlLˁ|]3<L"QN&U]D=L-{gX.G3Y]:Jjg#N4hFftFzI(u 4KJ	'xN|^eU!3Ú KD*΢"9?2y
Tȁ).ʠZinnX<j3?	ez%gbV~\x8Qodѡ'2Ϭs	k{RަPrOw8JȜ9b^RzY]t-or X@ټB:V/--eD~a@µÆ*]AzR B	z4%<qV֨>۴[L2b`oYSi,o/a&FuB<47z4M,Yk~y0buQHA@E֫nkQmю=cQO9!h5EKcXa<	M`KvF
3Oc:l`;%p1$?jp0"cl.yLG?U\A1;aGhS<*(&!i0~7ӳ9</)~7+$-/ipz䫋J|zռF露DI.arS.Z\pj60]!yŻS霳Q6n9~w>9Gd1&&
\h~9
eC6ߜ^v$s0}AӠ_pκB\nX EkˍIh-)&~;jwڙK=3[[a6v5f*}Qfm rdLl/nhy4&4HShh峡3|Ev_?.ORdBxiH!BcT$mb#\'qsXy XzY-
%éø("p#qX1L/H!PETH(`0INz&(z Q?E\ç4b}$@ѭk<r$bW3z6@no}Ʀ-BKx\Џγg OvwkRJL+JtQ	qX.}x!FMҵ8W/P
>Ͳ.Cᴬ%;RzQvҁoZY6o+#^Tg(AASNa܉[oEg'T-h+3e+W-$/^5&<l~1W%$G5HlN2ZUNcv
$S-Ƴ1JA( 4%iLq04		
١ Usf` H%n'ဠA
Xp.NhNKІDDq4BP\3h̜_\YqP ei%ۧbb j35<lL81͊PbE~)7V@>2(7SJ)Xf,&-kyمK.WN!O4m;q1g؏2O$Lռ׬7mzZjM~4=5-`4fEGiS:* bGM'b^i`7҉Hs|Z'.]ݗz0}#vÆ/[S;hTCpc2Ewhrw[Vp|+7yb~)1-T<PvgH#tNkuFpT%	ONit$# {.>};\S\c:rT!oO޿#p3s4딭la(hdzͤU#1nsVlEbyv^&dY]az0+ͨc֔}k7R,ci&10aߊXVFF'ڵMyuHڔ4Ryq!oc>k֭ݧQWx4j{v5z;eE`\{W ̯c$-DeϜYiL\2|71Uiq\|딘ׁxmq9;0aWdO<~JE<e:"LJϣ\s*r5<;7ڧiiꕝ.*eϻu>&E kbXdRQ[Ğc>{;c5kAu-#i6D<r=ϒO[^?ǰcf7Mb+mU;nj4囎&,=	`?)K0J̨7qh7 ﯽ>5O`$7-iGk=[W̪c>םyXIwfu7Kx7n!nŋi7ü(mV@ujUA1.H	BWN~TTPzi;$&c%*hJù(2h;	m/.jj/.8]%^b"jWVmm fb[$̈́̀Ym.kdYX1V=[__wduƺSIKk#epcqn6= +1LeۗKȧnrh-tR!wvro%
Ayug
ZV~./ùpU1>rxXa;֬rnĦnyYw%͆6ƃP@]1Z;[}qtػ]\f9m͛*6xh@Ĵ:FKo쒻eև o{yr@L*|?w/LPv'AO:Fgm`vpa:,S%mxt*gFoύD(@ĒE]h?&DqriӜсt?Ã_>j[""HtUd@	9D|@@60pTôkg@N}Ȟ;U\-?NК7tBI*΂J۫x+W:߽fUѵZLX8q]0\xЙa̙CJnRL
Հ1_^LI%Ɏ'a%0Ҟ#se<k_OZ\uJcVbCX[SQ)7ʮ9ؐ-D-{#A:CkԂ?/RV-E}k)^VIqN@V##l>7,\51-	GT4½<rTvmIp9C1f+in\wݚ+nYbč@hOs^5˭FZY2r'$C2&g]16fMlA'.n_"1W=Npm:iIEQs*-WmYi=ߣս)
XρtxxXrl2My!0HYsX*!$9T(:Z{mC5 \R=@GN-6R=#;)x8ʪwK*l
sMn|t\[+\ERbEzcSe;ɿ≎4cDqkroBG6^mXgqŷ9-fV%k'gU}&U;R:b{ĵkS>KuIݛ5B3/5]V7pK.Sw0UƼ۴v9( L6CXyD[ܴͩFmjoeT#4^\>ayX֣W}g+KWW^a~Om$nw[
zxo .ɇX8HkqyKZf	KX ^cEcWh#UxVr@ uv{os\qgwjyQ&f#37qy ] ˾;nSZ)IDX1gC6J
z.E\,\R̢val5]c6Wf7g2Վ%֦@ވgoFޱ7"(b:-O'2X/X7tZ!T'4w*w@QmP⪌jAKiLTwt+@=~:o>/̌#:l;.v?v,vir=Vx
X	p_A<iXkirKokw6I2kq?%obT\.
݇(;oZٓGZyD ;YI~˺4b\gi7ۧpvv,?aS|Sw I|}7udKnUWlҪ")Dl-|{0g=!oMh@~\-"w'KuO5qdY+~m7n0oZIгfEA)	>{(zx:ZH'гi ~8k%J f?,~e]ELfFZE;jbѪŶfLgXTXSe<faAerCHh4uH O)YnwY~	(wz|Y7n,Ϳn~v!`=]R|ZVr
4amRww<t{4HϪ˄upm4u"Lܕx`4!B0+C@	$U''헬hOWdDIuXo?ſu;.ߊ]>J-S".`E$Q[c~7ݗ**ΚxjTsxy0UPpꢯn9h_I%5q:!qTC/&xW]VfCxF|C@_A *9N-"ۏE{d܁7$m߲ l+0s<!Sa(աfZx9ߘafi2DZX]o3WHL6W;JF[Fv;,<i\ètNM7TwJJ:@ziś_-ӳsnG%Ξ>9{"1 ~c_C+X1]NeE>&Q5v,?r1Ucf,
}yZGt(Ј
ى$XU|5Y7yؤ(&xV1@ä_yJKrf
335ٖp4 !# 8 7a d_> _qL.%\l؈4/_N))'d2O!=^R{?.Nqr_NނqUVj57\R<rnoԟU!s3ߧx'sXF쀹F82dT奓1UetuϿC =Mx9j7dmcUUTt<zq>UxZ}z
ƶDz[E}Jͼ6_ZWv@>pie06eF/d^f	(*΍Hڠ=hh,_yx5AOj7<(^m"/؉uYrEX&(n |M;4Pc4Mf=t4cvLvDދ3|#h%/ %?0ׂf=ްG^8~T=`e)V>` Mh#HQMԽbӨU\؁d~4]QQ">ݐڧ|Ax|!O8!0|٧qXQ?Ã޽sJ<aRVb+!	Lh\iɈ}/&Zcy퉦~n]Ag(
KKSUa≾*.5[fRCt'2 fAIɋ<p	(2oUMTͣ	d=30nX,MEFګQQHN3t*3%YGx,qg6]@iH= 'VKGXF	ǧmZ*&db&f7Jv6*~C)3ML$DDc)6-o-xͽ(KJ\x :T܋2Vі0ʾ/̤sGaBV:}{iũ{àjxA`Ϡ;6F"xN2F}Ğysd(
}Ga[D*}ktUfIS2;C!&.ffm5BTi_,@{ǆ#lxuh%m{	F`O"=!ψ|>3,O=qgȘݞ%ஊBE9Gt4wkE oWL4}V+ݖC<KY)Fq=,8%2Iް:9p̃k,+!|uv$eu٣Z^oat/9ث"NYh&/Eo\xTNgv R	d	ibO'Jl^'զk+h[@N\*d1ϸMSb\發5	~.4TN6lb r_KՆӫ46\!t4̅w#ΛﳋUբծiXMŊD-(f_20}%|,@Fm>t/FQrɖo~Jx˳J[O~zϷ6 "/xoj $g']Dܙ\љLHZ`x.H1,zYQKfMG2P)#@H #X+"Z Kِak8~3Y;=$\"vmڳ7"Tg       Ymo8_:]?6${^mH/I;)ɉʜ<ߟ#'3%653tAXBML-XU{͈3h٪RVT."6L QCJ*ȘlEEuF^:#^b08|x@WtAu "|,3#"М?{vxIuVbvE. E0LY(˾pRc;n88;(.@I-amR!I[#Kk8w\jįAlT,Y*Ǽ5|s19
"r6ptu'91nD%S-[͠4ɖh ϕ+NьN#tɓ'.	6TkmF0J5Z,8gvxҺ8D0ulk*p!u/ԚƓUhtB/=Zq=ʭ`PlҊC6$?j 6	ejuȿ7#'&yt]5lKOe_	ξΥ2G9u
wJ~]8Z<JȽ(fG.ŔܿVS~)qd,*k5mbEͩͽ$J>3XՖ,y[AL4蔝Ծ-Z;ĞڢLݐD%GXO@1l[<'DA=uLeV~`#N[wfs} 1kVcB/X%@!['p!OTJIU!J2W6VlqYmdY3&5Ux 0f%mmIءEn14  pmYLŮZrQe![Da+*n!?,.w/sk&fIIz0{veU?Qļ竅ɺ^q[w zZݲ7X%ShxJmey; Z"bW(pfgAhW1erf̜Nd;P*y
k5bDDیQ	+ndڀ={^p9iYGDlxNLG\bpD[$)zےs@ZDzHND;"/;n|Kl/#-̞'-)(qKnUhL[vXQ1kʱqVlNe`(6k8363ږPJKNjYSNal;lL[A]Z0{^9u\{"wfWHw`۸
vc~h; >k).i<ha	X>#!B5Nx@d~P4*tb_?v4wo&[/΂Iy0pg豂P==~lf]ȧQm}U$;sX!{X2;29ڼ
&chAkt޽I7bUY"A>dOٓWG<:V!ODCTޅC,w`6vd\pax62STu5$)igHH2,8ֻ/A:im.mvYާr{K^:8o~,4)k  N#ϯ.lG"pu;:kNk\6$.z;JU5%UUTج0Qr5eJI;` (B6lFR)n_K׵|MG: n#y]K7!@_]]-X>Yulg{1845|[<#ȐomN$/_̙
NH)vS>>eC:A
 8j=_QU>^4\mG|ן-W	*l
j%r^ϡ3\뛹%(e5qXko}4%5[PQz=r׵H&VZ"Wȭ݅o=efߝ\zq4ozaÇeAv++b
ן><9͛!WG$Ews3psGn8Rl+c^2?N	eŞ"	5Q|F;5pK[4uJ8/oSng4(y+-nITnʅ\v~[{ئw#㸭q
'gONNygk<<m|@?.IzTZ}W"c)J cV       \O_1+UJ@\@ɭ*-VEwi@?Vȱ'd';3؉vwKds~gN=tJ3F&z#t3t¨OBbBб!5#9fص7#1!q2#;zY]4!\G41r \iLE$1hL<lmuB#߂?I-X,cJnnG~wոiȈg;p=̮_!}@gsRS6}Lch!5 X#(hz8asD4f>E'yS8 ?2Rc4?_&%?f"&?21ϲ2rofmC"pT*<'6ϩda7_P%(AY)BQLpECKHo"uEJmmnm& dX,0 ܌׾^(C1F0c<,УFo׸ZP-=s\)F$p5 =3/ ZZ;M"sбG@rx׸I5vcnV(n/%lnI&%~bK ]pB`k*?fD!tU4Ce<N0 G'dKʉt|僦K><4SƘ(sKƼRAVOe<#c)aN"l&=b6̟Rqd%
dVVnRM79+gU~?xw^K<@YVRmzU\#[/%_TV~c/O݀80).L(u&ę&X2Mb|S\jr(|a'dp"%ŒeVZKIdO/U莄$Kd6d[سQHc1|G82^"HLSyY˚+1n6(hiywrqTW?#^h3`P{zy Ik\p^OmLs9[Ňz"s*J)&12+a01 Fo#=AMpŢH!M@=zdԢ81EHa{L.uB:s@8֕VQyiAjTњBa)TP\WJnS*L뤓BOGͶR4ylEWq0CA1.W&0Ƿg*+nd5*'Jd#Ԯh5U=jr97YH鲴o6L&`#8B_DZz4H@9\<&U	r-1A&텞*f뮫ݏ:[HgL2LmYq,ub RP!׼ ɮDϢ&hq7S+̧T0Eh6dXLLG\Hl	'<(!ZG#uC)Df)g"TDFFd8d_UCs-(d>eVd{	*Vn+jZIPAiQfC-H࿙lnd.膅XVdL`<T
?FkqpV~ϪknD=:͝P-E:9MMo0uzїҕD`R.ET6=z~ҳ55YS~wxLK׏XO[I͇ͧ3[xΣr@UU{wjM Sbg߬9pWn;}KhXĺr͒7RsS_;;[:u{9M6YҢm(?Cښ)) jlVH{z8MF8]+G?dr6^oOC^nKH{:ַcj#zoBllOd@6Jp!T3[Ch=?Q 'p1HmA*fL#*fM*YOB *x5\")bnuQ?hO{n?;񬳋z	mehf~I,ی|ol ro{!(GPqH^}OM7Ob!l:NY'1rF`vH4A8P-d,.`rbV3f43!H6I:O m<4W5zߘZ/_5~/J!K	r:hsۊ ` k+C-J{COP䘎f"$jHNf@J~یn&6Go9u1`KTG1aB|a7kfSO>ehcFK	yV=sLCJ,1{֭Pj/S	-^;EÞP>{%byTfɨܸsurQźX5^,
kŢMaBfXHMԋ\ Fk9_OxusGV@:%Zy[0οTox؎H=:U݊t;5FN{;7Z~]7ٟjg״ZqY3^l~X+JZ3j]Zgԝbd}I$-ap'6A0e/9vjZUF-a'x{$a;xC㋴8"|e[       SMk@WB@p	!	`TrW#kծg$竆|yvgeE1?8"*kjj_R)`ɑ}"3G0%|%	V).YM+8|JW50&Rsjtq3@)Q_#^3Ԟs辰AQ/VM-6$T<֟;~ƺZ6h[,[^k}Sԯ寛_7SlM5nmRxܹqgw)I' 8QQM mBsV2W|Y҆9.h+iFJBʌ֡tU}h4<)<wFfzȹkyQt_x-       Y{sڸO%7W&$a@@@o["X|{lCӽ4y?~G"WفSF\F
?xؓWf)y"yFGFFmri(8]ŕ`
i3_!>_ܕ#	KL<qC6[nx^,LbhIYDlLgB6(%`*R6K2ti>Hs h"	%.[Y2r$Jb6#s&%f6J"|`S.UĢ>14fMt;`ˍ{I~hpNJ߹o,:~`e9
DH_VN5	f|DG'D+d6U=]QΝwOQW>ߖ7ї29{0v0V슽Uzyo\Z+۳xΞ~{>:ǻj߾_t&UooڭQŁk5͏	9jO:ki5ϭn}Y}{/OfrMty&_}&a^\v'v_=~4w˽Ew؁ǫK+uUϞ_W;AUwX#eZjyж' Ys;y~ЙV`˭cv'ͧao~mS^}PUSz|7>z<z}{Vh7@[UoP|41NàWli7GFqJ-U?Zyr@E?% PER=>?0B6eTaU',j;PAlQM/5lB/"Xԉm620T:1V 9[Q*>guBd75|-ize]6V]&{tX(e4̄h\ґ`a+my4jZ8[!@ 2aX@* TuR;#^B1lִ)] mf/.2,IzSDk1.L4ӗQ4BR˅n$Vܢ ;iriR'T!CGVs;LWP&5h*貞$-iODT!S{;tT	$L.,,M@-PA;$q8ق)Zt_!@Pk7OfjQx'/;jjms=΢~ho*e#RTc54\ ;~4BŇ4]6 VWr0\.&gcY8i6*)XAo(ğx9&A@g{m}5ú88
{~N+OVYVX>O,bk_1lէ(oxG8z@Y.A{!Hq| S蠀#Ʒw(Yb3-10%cΒY!Ikg$K8J9SdCtZW8لC$U֊ǌ!Cf􌴙\O5H7hDJnRL?0 )#&FBoZ*߉
(fG0tWP3ϗxa:m(B-~ףQ!fj(x܃wѸv5OǇ\{YTq!zG 3::Q8fP ߷e#8!nTj20BF.P}ɱ/-RbAjNsIiӏf)zk=N]/!VK}<nyɯs.<.E|#7lQWnWiuUFqd8'[lr*Mq`$ETJ>u!7%$I_Bb Ϧ*A_!Md|HDGk-s-ƅ6Mں8r"XM{)w}}nDqֆ9alب0bωLdRj	}HIˎTӫdE㞏I*&S)Fe/:8i<b"dNŌA
)by)K/Md2@j&tDfl}d\"ԽГx>JULˬGc65;`;={	k	e~"wRi=S@Gt%223ř04񋸬E<[XI<6Psw{˯Oz
G3fiRxe+bWʴ`       W]oܶ}_1(u앓pѺpv\b%uE6gHJZM0`|֛F*O_+Ikծm\NZSrH'{Yc$%J9rm
I-%ueecdI	zwu6s~%iUHc
ah!YҶ$e.b~꜖J|2Z;ߨg'zADӈM Kv][#RxnKeVtqvDFT	:d=59LlնnYYH6f)ugP:= &\ZXs/`G:r<Oipnޒilw_W`[KW획zTQUqPR,,p+gaְdf&;+yy)"֟Ӆ'G-p39$mpPdP ֢k1>.:^(|	>AW]!v	$5	Lb)<!S:Y89/"$algq/\ѨǔΨ[H:i$)X|_skxwӬuX S[#QAZ#__Bc}CX52.GPT-:f|FO=r£YR2C!mE_Z,P%e7!8j6WV\H~~x_}"͹Q0#WNc1A}lr"u6jjq1
\HKv*AvMYJ^En"f]q ^8s]aNK+,-M<;7zC7=-e^eGN *xw~V+i_-7YBG"+Ҭֲ-Ȕ)w45kCS#]$apS|HFy%㾬z:"O)٩Ծ;nQԜMΆ<ӟʇ I,8
FnɳZPkIf9ifVTEcp<(yyZs-WX9<qnsqIw8%TvB]USu9|&sy)gzq T67VUiGP}4-\nZ睵Z
3͔xDvp!fivbYAhrڙ~ܐŭ9{[*oZ>Shg3V3LZȶLXxRD]Y[0z2%/y` Bodc&býQ2,5 0\W3ZwZoTWv2"w8<;Nm|bNYſ(n
k9-Xs=7߼FRF#c]etr3øxu&nO.Ifkēǀz٘ VAvO&~g,q4\x5TE*y2&8n.mG24<8ms!l@م#Y}`X-;,q0DUF,.ݥCYK6{ϵtޙ	YgGt6L\cA9`N瓞EY"TGN3K_BZt︍       Rn0w[(.C~CHLTCdE* H"ґMaU_~ʅ{>0<{dQ{1^ēG˚CJv9 SfS#5٭nܬs
<䝅kQ0M6ڻM/${Km@"/,_vyE%M
AGKwTq=*1d72P6ls
)>$#g۝8+<<2!N(mܹ%p"#2Fib(v :u`&Z'kpzQsfxG\>ٿm/ U254       Vmo6_q.NlCmlHOQ"JI9IId]}%s7TϚ3g!CfZmxfJ 2ѠbF# ،0	BRz]-j),g xl,$LJ2.;V\`E<E*dbdV	sǍ@ؠL>*\6x䇴+YWGctEyz&`ٖy6DKPS2US5NlzJv&JZG6/<qpKS3dFȒ,[Ri6eV#H%Oe!D8\S+k,}TX.!UI!D#x#н#]CC?IYa/RUx:pk,)S縗Wku[Lx/wRdKlu7hZzOOeB}LIg*јK=;٭?[h,&qf^KUr"B ҮB쫷U] PL2Tuymj:Mm@řRQʵUr>{ 
\ԆwYذO;+qEC+ea2"JSrpJ,Qlbf|{\S1kD0c]*A~iµ?{0*igldP:V
|BU&HjףfJs򪭴|ƣ
]gvm>T71O՝/f8/sV4(IQРYJ
|XG6so>7ه]Vg=]E#0Wр<wN^t{Ϸ.a>C-< zA9E&<C8|hiBڶ6 $r]9Y?v
ޘvF5[;~[Qu
ڸgcxtL9|vԲ2PzQ#fRyzR./MdnqM.3U@S*[vg R0pE׵B=B^0ذVt=)5ںdr!Ta~Xw;?PTPC;64lF/~3<       RM0W<Cwɶ,JR,{B9$ؑ=6Bw[K3ޛ%v7J_cZo%;:Y(Rؓ)2,	4A{CHaT#=ϣ`YK4i@+&΀]>~zG͖
,o-wEM1.Y"!?;Q(GUc,ym~fYdM$aBuH{X6MuY߾scgS)թа+^î)q%~kxdGtLXi%rr֪JJiU\lϼՙd\Yn}y5	*9gl+b8Yfr$-,ڒJ\}ڇNq%]WJ*Y       ZyS#7O8n`3@2;JQrlG6&5}ߓv	
ӻ$yj32T8X?s_)yG
4dsZAFF}0E72aj[ɆCʈqIU!^*٘j_H0$'~ŕ`>ZGH&+Co(k5ɒ(Kj^z6̯*QO$6Ií7͐#di@S5dR%BM~=akG[H'jb}FuOzBcG%,RE<CI(}Cg{trq}B\*֋	kx6FkwlEvv6L@倇LQڤьޭ}5i,ޗ$-k!G}{۲`.X,F<	V88$QI`x\Qdē+o!A "FcH/1	AE4ֶ!3i[?`<{mr$UI<Aњ]Љ1@7zS{.1NIH *'ZCUH 'l±	AUX(::5	39Ct`q>N)Ն1c1}@" hq@] PYz 3f{N3簦+K^YHeltE^cS'`<uvSRl'Ns7~E螅$KE&6w\08XDȑJ00%o(Ș) #*RL,9BF
e0F|WE6t
q!.1U8jN
Y PuzLB&]n6V>m(eQmf!]Ig|uBX	TGĂ?-c*Ip RiK*,,0NDReJ3#]&ͅ5&Vyz2?UfR,k}aBH L:U&3O,Il/*juS^T"~_FvX	ԅJ`Z4Uќxl?R`T/5=aLbcFzآHFDRXD	P4šN6@)NHy@1f3qR{t+`li_o 1	v3ku>ObHۤ'"GF62U|{h6ٿrXd23oyҕtZɡHoK>snge<l?t~qh~6
S$'z
=)1haZ&[r/AAhZ3B+Gie-r[ֆ~K9QG9FY|>jGh˚^jB-ëXJAWm 2%12gwh! |0Rm^k']sڨw떱jiRU6M]|ݯ:m$]wō1%dNI0k/e	.OF+lAPmn>4.p6OmISeFu8Zb@p7-Yyl,tr;bs0hykƶOm^KFNkE}!]NO\85?nOG^G{~9>\w.}$Bzq{KQ9ѡ{/Hz.>~\u?tw_ң 1=AO	̥ƶ|w7W.w N݇s~xy2huU4VG.6n.Ͱ{yY]rvz7k(ӽz;NĚALaS}98oh:-xq>ݳ&Ӡn. l,H8iPYoK	dV(jwH:	vWmVX	y*sQJUnS3wZϼ#yފucE-NKjTo`zLV<ٓᩥl~m*4m@Cp+0xuU3wkhZ+}. Y{'U1Tʁlt,>lU>J! <6ӉE*9ua-Ɠ/'MWЩs<at9sBI~I /:،8i0XJ.Sacu9PړZՉ؀3(4,lѯW}Nz}y(`BdT2z",(5_17 zx6W|Ui;<_@>]Ϧ63H9o琱 Vi`~8%3)DnYvv2W,?ovt[Ҫ9"ly.<-
l+\JpX򄝄x8B}Y9,kHo./l7{N!vl#6oUhUn^IA͇Կ%LOlji/ Hc5OӼx(ܫ#,[9ʈ0櫭gk\X7pD]>v	K`iXVVY8+묓\
ǈ]S58?J_6cgLf.mo3z	$&_l5ks3`
s<-2饫)p6r_	
 "3& hp&cBTāC&}:GFJ$q~xQOP<#3ǽ\ى<D3zf(<u1yg?k+A};Ev&ď;íWz|)9əŅٴ1;/U;\/<g7%:53^o'J/=vF?z9% s +       <isF+:ީTfMZmƖ쉦tL9r@)8 ( I֦R	t~~W@u$?gq=d^Zz^X2A+QJ2wLsUXIJ?{Y2ӵ騪יJdy\$T"YSrx.ɫ+1S%83A,`:*OjU}ioOO\8 B$s	P3 E\Jjk"b
`YfN@593UVu9nrTcR֫2E8JTgR ZUbqF
DZ$kKߔ|;Y媖I?hf{%Df2rXo+oAҔ"ʋ\FG0(\ozU!mX.A&Ry08s<\ljAȏJ|Y:LBNh嗀ұ Y)#B-Xe1#ͨw-1K4 MIR.@_u@AHaD}"YxYuQ2# {%ϾObaPt1Df,W3Gh؁Ĭ(?;IQ-=|l0k>*k9 OEOe&$l^ހ$)U@;TFʥLUBk\rdp]qN"90 x-g+|-@ؐƵh#qHrz7FCP8CUIeq<EзmCT	M*4AX#N4]2~,L||,"@ )e~QF1@@\8M؃NpJQ3T -޳xm3Z\M(hTTrتdmZOU/ʘ W5<>v^ԓLL1Dqz4c<g rG.'4x0"`^M!/#^M[j8<.,]rQTPJ,ME^_ee70::g 8<>0BzG:<%Р#F%}ۉQA4+ӇNyDO4Oev;%P(tRU>AhkڢY(f1O U<ŋ7g4GRyi޼X$ڼZBt!󣳴o%Ӡbm0Nӌ@clDc\;Jn@+kp^\l'3$>Éz]|A0oŗa~|PK`Kg'o$#Q[ A^[aFZ'%*K}	4>joG]5~T/zTY)&^CVpF
O8P3bW<ۂ5}]f,r~TGv\L_؉$'P32)gI,A?9=:#YYV<p) Ct'sxoD%XU^Xhʍz?Ec]܁H4ǰ2rZ8M_A\W
dO,( Ad[_}-uHFE!M1VÜ"}[&y@M	GS#b1\RC70IqCD:(G1-13p,~ٍ{e493$;8N+Nii̾wG^V⏋ N!	/@~HErW9^{.2(J
+Z|($p|V7D\ec#@?3{.:1&eX\\Nifqn,퉦vԙxo	@9y;6tB*'C۵Z|2LKDUrX4޼u5MJzF%>*߶>[r1m"6fA^7:1ۗU	i~f~h/ ;7aCUǹea	4)D2QWL>Vv'^ƭYHUYT<̱]e*.E6OF/
[v<U	KF>C\/O WM=@}ܬ>^l\y_;ʳZLahSe9uafﻪݸ\u +wVs=s_NO_]ޞ\ܞ]^\<;u۫K߭90'2˺{L=z  <.AFRɏL	[spz;m6N?=}*D^]8UJAFrz}[+['ͿW5^'ߟ##O]4Xhd
R7L5eqOnAAqhWёݩt;c\f4CwT,"0-B*_DYY
uD%tV9g*RWEN^GNPL;`D
},.";c$β%3<|UcEER{æBnj[E9\3"MXD%. 'ȓCAMr	"`ANCÎ4 i(Dxl k? zkQ,5]i;1:7h,*?&F5h鱗Idl 4Oq75_o1Xu0O~a~t<z2dؘsZI޼o:2[<" gNd΢[QeeQQ
w*kvh#$MAdW,bʩ,s6eQQ*zmd6:F=hArTC쀿[^q
:V.׉G.M]OȎƸß	}%Cvʣm3iOJLXOE%HH 1FDz[<l[zGArN0w-TV
͸]UBFgN#3xU< !TZ\~. ¡ZҷHOFS[١1U_yp;kA|CC^;UȞwV5zVڿ6xBpmCdUzZkPV|§Cw[DP%S
w+v4",8U4Ji547M[ʣǽ{gx.,?yx
H5ٮԶ]P.{m fؼDG0ZFyUP6އϠ{|z|Rin\^C̓JqMJd^BG:h/fxKlJⳲXX@3V/A5cjY%
a'XU	LHx3YyG_:aUfS7ev7=_^P8E=xV>trUAcq&`|򔩳]tUNlR(զ=Bbzyl䘞E:)!]Q3aKA
M'd8}r=l]ƇNL@]&3Szg̀p7v퐫WAa+8DYsEUL
(5Z6(fr!;9.f=|힣Auuq^<69?zC4Gn6zYyzUb(070uTmBd׻%wo@ aG#FﴽśTsycO.Ҵ^Z[?}3Hh.x5t>fGVhN2DC`1|l6P;H؍@#`8YftW%7FdO=:3w2-xyv#=(ɟL3'	Lx:#8wc8;ئn/D;zkjX1fs*WNTbȆl]NߝH&7?Hz]5_<D6>o➫!G@Ręv#ZE34,o(UK6VyB^I^06֏j}Lb8IIJ'LA<j,%<g0ohtߟlש?xWW9q)z=P:TrOZ{kK@PDza# Z6K>'4.mA^N\N<ݰ_Mi]kax܊PnZ?/[Tlj'MudOv1VMU9}ss,y=f+232cƢC6(k2n1G++U1_&qgM,[{YKl'YMDhswu_p
<H@iPp@I1h3߬N?(h{j`g,j5[k2雚TJIdMMy)5ex :@$?1rsZ_t A{(0︫.Vu{gL%EVury /4o>U$>@%t$M|	bRn&4e`QIʹ>cK.o%Vm\#Cf {)*^8?ޏGܶaYFӅ[+Iw@^X(?I4ˢ0kruٳeua?bE1jF)mo6&Z,xE>\agc|X`]?YamDsY+CA	,C		ןfAH{w[Zy,}zv`/Rj|9
asYpDKN)[_?~qxpЩR-:t71S|7"W<!b~Xuݭ}Z_<S#-ꪜ]y;bg@mu(Vnr#nB譧ItC[WXgy{ej#y)1yw"GLd;爝XZ-	GM!}v%-EWh=pMCXmt7h27kY;kB-',07O儧NdFGލ8gN75#;a"ږ԰[lɫ {hN9~mS=1=mB`*ο˛ա&t?&|Wu-(W|76=hvYݢ㆒Ã-2HYQІPks9-uAn^n.\m6Cg(̙@k#y^񣈚ov/oi":1y]5!=D5B׊FOncgW
J97tFʜ:Lq̮Zorˋl52^^c?
맡iw6oZxr]!u_>s:grj>W=.E׉

GO셌ئ-Rvi|1xOh؛Z-nrruUg&gl[a&:*b-qWWŪj=x;)B;ynu,O&nNR̄R>33<%?\<B\       un0E|wRXv5 uCBbCEJ+خkhu48Tpwq14ą콇͘ b8UE]gB=)L `r9#n6<<&NJs|jK=yT*?7iCLBӷ
fK^{~9E]Ô䃶ă*l0ӈ,J[99Sde9vǷ&BAא?X{I4,+wؖ:¥@~       UMo6WXL&H`l=(z%%I?8 93o޼³'':\f~?kڙF|jCmR.zpQd3<BoZW"F iP/_~e>%jr5PrH[jRߞ?3lnf=hfR+Brr|ǧ?!+QVOd\}X@.PL3D1^itNH(;xF.Х0
#ވR:m4&:4꫐deї:L[Ī%FcZ[`сcg'8	UWңJQ/2\g뫙xϕyLӚ9&nS_Jê`}bL/c(zU׫bӆYC$?e^~n7W9a)44	IBrƑ,Jq)v%<>O&ʹa2Jf`cC3!%6a9,-
_kHW|xV2IO+G
HTY.i*)RK7%DU9<1:^*(HbsOjgI"ڸ&2SAyDdRdV`'a^3Kx/vR]тٞvx':CSti9Rc*%G+Fgxҥx֥#P8;rD5e	8c/$,f9/vJR6|'o-tmI8.P$*HuI{<Qt[,Vb҄U|Vz>p礝?<]/K|:       Vmo6_q&+6,pe]`hOIbKI1
Ŗ;Msx6
K=RY6Zb50E?עmĎ($}-1J<YT<zKE+ʺAfM@CI\f]3BXf	*hw6MZhjeC=|h%"((+]4Iz[}yowE9&yNb.j|xϓƩ0%z	oPZVkh@bW.o`sІIZvΠ]܄MU4J LeȎǇC4"Vn`)\LR0Ѷa\QO)\!{%T8aːODc)>|~/34;ӷǶ!KAQGYwle*,A}T6(ĔaCdZ(NE	q2@D[z.n8~k̇6Zf
>Qˇ|!u[ƼwUm09Aƶ%Ӥ#p9U.;9_|"<MN#>_wA|H+V wl4gҏy1R%1*i| ͩ;T+4xGl$s;킗WGLi?tJr)vLH,I.!4P iХФRhB(['MWaz4+@N:w	ʒ*<ESNBL{}쇅k4xs9@wvsUNTl7CvOۀ$O*7O5_/Ap]}^ԞH2tȴFyc{؇uc74q/Lw#mjb=p 8'!6gmxA1\1g砶S=$VZe&p(`qJi޽"Bq       XYoF~ׯ$c.<+rdnCrݥ.)hȹvkS8WˍwncXT)6Vp$h4W> KF:DU@?
u7 ͛!!ffca!̑%-TE 3zpuy~2`0Nf.ғ_ZfwŻ%T#Uf^³3O)[;$h%Kd0u@ea*2q)fvx<-@JY$I$)*5C,JА4d(h׈Vk|I0:yh.CR˕D^l^$?`^̠2]&K+G'd;#8LZ)?b Es(#ɒ( oN9wESs1pba8	H9$}W`Lt*	+A&VkXH"\>#!SŌU%{ktJBa0ƍ67qO@Q7ϕcm,l8bE,Db0g`MWzs	:HW$sY!uu(5x&|AlC c
GFq9#ZM,ayY1.5rf.VZ.-C{.,-7u,ØD V:*ڕ&cV_$Z3_:*"U+hI옽-e(g<_Rt?4.;m77bJ\"}%ePqmut	fw67:j8_*j##4 'z+-\fUj^a":fRt+S|ņa$/dgDC' :X.	*LQ`\EP'	Ex7(0Rbkdd+'O44e: ĵc^}hx8ȟJĽc`D`&4Զݳv$i7T*-ᅠQMs
SBb5ptwflȓ8ǃ|{y]VN}tHkhvFICJ|6Ɍcx֣'d#m]3)hEMO'i )#lXȺҬת1A`g
z{ZuNW*ɭ&_+eS(ykڵ)g#h[ڀۣ-uZ4Ѱn9Z/i͹-_]O};_r,/ὒw7%-j RZ(-XӖ5o/r+ŭޚj8h؋M*I:zڈѶ>V=g8@UJ+tǈTWN2].c~O:iEOpuCp;eZ>I.;J;0:He@Mp{>6qwZ<HXwةSBg7e|XE7_R1y?V}o/sżtj'ɔʡ5}j\S.`b4,+lX`F:G߼[4+w9<.nh+ՠ~Ie!       uj0E]L--HYB7iW!zȒ1^Ζλ#X-/!lL--nz1>7bE^H	^BF9@[eMTʡ`	wRy^
eG	m/sEO^cy;5݇է}!)KCvmZ;wipuĞ=0vwn<~hUROX/4m%1Ui҇p:cygdo.8to{O"P?>=7w/S˒ ܸ59O1>w7@2W|7\X&k$"Ko.;c@       ZmS۸ίf'Rvɽ@[`a[Is$q섴l<:{C(=32qtqHe/<HhF"9|N鐽ԐLSTLwkxl81&MB	DYdSQ7d0ϼT1驀Fn"P:b0|~9jر'D[Sz15bt$tkHuɔHeT#Pc:}LH`f܍9E&$#!UD1
A~&(FĀWĪ%PLLXH3B3Ϩ%x 6=4!}"MBgwz~}{N<buscc/A@|$da}C~!o`&r'&ʨ?xi<>$#k)Gsoϱ`)u7Y&x`Vs&QQԧ)8N)\%тЉ!p0:tP#1ɐ!U t Sznޝ
rb$uI*Ehљ1rZnC
)g UI 3DG!*I0jvtLyUṂ :,_=Іș\ :vvWƒƠ@j۱1CEc+$
RPYC,o\{Jo(iaM[`.nv_?lmB |Gʂ۱	"A*%DcX=?KK>8dL~!M\Y,%kYR\2e/) 2Q
($˲φAb5R	 %iYY4$Ƽ*r5`Jl
]tJϢB4$u愇l*"cGX=2661KWt:WZ)L	@'A$q,,C^B,DڱGv^*b]st(tj. ! Qݚ]9:VVsd^)X!c0EGvd̒Tg)DbCGJDfE]|M [ͯ+a+:ua	pjQqOƩۤ5r2jmśpWb4jIr n$>if-d "%J f҂ClR؝&3(ySCS@cf֥-{V֤&Vӡ] \#c&f!dCưvH?#XK6
L@G5<%[f\b/(4uN7Α4
SW.$n
~[@@ Nmt8;-g LB@zR i`I<PߊC3sZh%֠(l[ r:oiO<sYگ`&nTz)䓎Hقi'o!7ul^oRJzYV)Wg9@C#	2f'Bf}`hw=,mmZƺ=Gdf;LuZ_uLhOogk.no|pk/eɠ](lW؆nys~5{(SDC7Q!6tڑ*h!	!}hp<`Jy]&_6nl+TF[!մcj2)=o＿n}m?>ōnvf{ &W'ӫ0x"o{+>z\NW';~#?y׺_NɰwzrOO>5Lهv2o~|R0[{Q,{0x8ÇȘpߞ|?]wv}ݴ/ݍ؟^ލz.>Q~D`M3eM{`'ښA'M=]'fW`}uYk蝍xo~(.w!
'|;I id@IjzXWe[ɲ΢|=X#"8xmj/9,)z1COȺYQE6*6Zz԰wZ_yG6fV{|vcGpcM^=5[=j? `x9Hw5"HսH5>	;l6Sͣ2WުnapYpa6njƪ[ät9ı˝#sD)<ˏ]5bN3nV@D³`+|@%^Dw+顿	$k
67n=>jna"WAD]&i
KS~ȟzZx6	̉BL9"GLØj$DN5\{E{ڏ9(BcE$M_<߲,VtZ6dI5;[CxBl4pQ+$u/z$qaYHd9K%,\\<Oy,LvT]Xp^ϲ3%37Eb-Q
^IɌvdy:'lI,Aƀ&<󦝻1SP;BH\+ՂrgKpb=_IG5-GVv|j;SW	ɯĞgv-S&N^7i(r0{n][*@ǒoc{,\Ge7ߣ$#;"AI	gQ
zF։Z`X򚮀o<bBtXyRیl]l6*@Y	.^\@Gf6y(R䑊0@3h[HkWH7[zY":V`ժ8v{.MBf)Z+I,Х"ςbyp<r[.'R`
f(ܮ~wDUxխu*,*2;á%SBkDp%)6-m6PHR͓j	.) 8TWe׀&c_.bS?ZNwĭpkMlM.j^#gi$g';:{\IFë+!Gsv06/n|`fWJK2Ԏ{s_žzI\T*O-%       Sn0+64KaK [-DNbю:KӝR|tޔu~{^!+Oiko" -$T W&@9i	Kڢw!@8pg	+Ő+LNqGe
c1m}4uC!!~T<U%YL~E %AJZҸ}(+wqFKuUŸ'LRqAص	U]
>s!	jS]Gdf)߬ΔB5Ţ!sA8`\T-h,yQYšasfǌ{EI)99FqM;JaWǖ=59w.S:|,rѫU
9zh6RyL^lS\5j[P8K,Ag%ݗc{e ~P-ӄsNB%B       Zo+y;wR|9^Mk hȢ+Qyt3CR^!q8g~3;RL.Ʈ-3Ŋ}.Re}NFD9D.[.39UEE*AdqxDDF"mz5xf9UL^ӣ	DO
8k<6*L"ϥJ1R_>g9יLlJ"vfw,+A[k=Bsv8d"4<Ր}0P8% H@D/A8+Td_πI]2Ic{\e,LB&ϕ).r	֨UT|(\DS\^]^^ɐxRںOHAE"ZR&qh6ԉM2xHB x!/!3	`+qU-c`X#E?⏁.S0;"El9!J:ȩHm)X<ɝ^҂fp5PB˭[DckIF,ǖ^R(Q'bEk]I4;)lI@CRÚf2Db!=(dtr̘c8d\C<ENuKwbl<uĒH2Lm;tiRHCAx`b["{t;}OKmTPzc*Sڕ4D0u9
:^}
xQ0ZC<U31k|;M	""KdMcCH+}ya7t3Gczsʸm*HFꔊvmꔻF9b%W4oIr:ƛ{EQ͖<(bE{zXM*fein_..(^>0nuK5¹IAh i\>opx&3~^Wp}@vFq!ǿ/TgcEIK},8'~8xwHPAdLՑD@.4#{:	H9@*WD#ړ mm.x}өW\iAGxAbXCOV?^F=U"KMGT:#KgUx=ǸTpC汝tbz P$%~7UJ1TQ4l%O~7_]3!#Pt@Gk\wl,ZZ	hVhM<t՗1zQC>#Ķ0E;JTb'aY
Z5*;!Ii<U:jwo3mnN'z"7{F7XtFxZL+biTb0hŧcIg̦+Ys^ _(-ϵrA,|AP2euﳈ9V`PjP
3'	OcʜZ ?R9Xyh+Xa8f7WV3x3FxtRf53۳_ ܆q- yn71j tc6[ V37AQ:wH:sz[;2m~ⴺz?N.i A1\gaQY4[-vXv?M
r7]i*"Ph$
GQ@]AM{`2LPj@3f'-::ʸhL.D<0u+똵ݘ	>TZ@9&*%-썿$\VMJ9tG8q9wZt~2fkg}N8-5O "]mbS  O֐?E|AvݧddZ,0Y#2&6wvmz9[Q`S>+RG^}G=PCǦȭgf͟5fhP{jisW9W#WX
ãKHxTaWj,L>lD%ik@h7:v踖+q5ǔ9_a`mGe 2Pll01:Soq:Tigrɲ#e3Kop=˺#:Gҋ"Bd/3S`Wsz"TsmYy?K	pRt@GP547}zy16kPzÎٓ3:+OԳA@
krIwyl%lvRz2˶ƾԗzMs01qf{r[kxgP Z /U=gh_ZtEـHbC l( a0.L.?7 [4AXA(9xAETqZmBCW/~[ǈ\D͛ 9d_T{{	j8 ʰXA(ö^7z:m)KpqPl6yL`2ǏCŇ lGqvrA/T,؎Î~47z>klԻ֊a!<"ʾ~:yPp|cMuN:op03?MIW9;n7C}y"CDOGc  @ŠeőRM_9*68<hv>Ϊ2}n/%q`'       Vn8)Cl'UanmoEPdB9Z- {ާ'X7RJ?^exxX
5<~TzPAYҙCș:yb?DaAYJ 1iGBZSA$i W|*F7$KU2ggT<.Tpg˒.B$.ɭY:	lH{ W=*z0y켬+-<2VWJRvuv1mAN}* 5lsc0ZƑD< \+sF:6d^*JLٖn'eaM[)dr7`{No6ƨ&#To/iB5\dYZqܞ؂56:
)bZ_zjCC;R܎p'hEKULt4:dsGBc!nݱr3V~\EM^TݴYBoպ^棣I3{K@!-hDafG5vf}W=oM4ĉXMƚSdv ]Vu{@QRM>eH8N[< %?HK{A0%ƭ_dn2Ụ^C;6~!ju[fC0QORR~#˰|k\:z&4ww>'w2=۵IOÕxR{mcMU̒D~ iK	       Ys6_REۙKU'w9'籓N PV{w=g.`.Ka+jK*
L\=,99;\Ʌ-krHeW򉫒gSmBD13)+a	i)2Q{wϏ7ONNQ"5세Ae]FHO"s:F&i@79/	tUl!gɼJVu/Wȳ楁&
X{F^2kl+#3>lQp%%wNшֆ΄{TuoTZ
%wKōXPE1;IeFzOG&1穙;TUxyvvUy.C6D)`{!~s3Y2-WKIǟ7qqk$r	@ovstZf[\?#LQ$E <|vOhc!Rmz E@tUUKei	T<H-,8+bLjxH뇜3
˘cCrtFQ$E)^R*[|?5I&wo޸p-aYvwB^rG)o)ļ=p~lԊ]t6<o%.\@&-<</8S:%+zHd\DL5y;#3]YjٺIZ0əkMCu?}~1}8zcǭ:=C 00l@ƞl?}Wa8}ET#۫x$N)~,=O]u9,.Xbn|rwDGMAnbl#QyA1z`~dG&#w;i:?1Z0THYI
cVeU#si/  &{M	Q3@%J1(\nn-\1S|);/erhgMVXEQ+1X}j8Pª
̜rv5	˲~3 ;mzM]<+2bG5fGk	x"zuuTcA !و;K`@T9g8
~3h n+Y` ڄ$%A\	B SӸ0XZ?*&*6a0,ݥ4\Աph|td%)/T)6y=&!m=̩g݄)p~~>d`Cm=vkM}n\LdIxid	#iJӞ(WCeNA
}⺜x=jW{1"4ulan-c{avnڹZΰ9k`ZcEx>wlGy7,;8z-00m:հ}%4F#L@mqiif-g|٥rGo3aa~	55|u`^ юx:aGǅnBR)Yqe7 \P\^1#p+l;˺*O*r誏/;\}YFxsؾ`zf!-=bSǼrI{'*%sHlgh2
Ju_bIB:]Gx6Ӌ&*kk ^Yk}8
cf*Moӊ5	H֠;e	F |SW,vWX֊Ah7qix"k|?[3ybYB_`-31
W4_},ܸl2vہ&{KN>mrv90ȭm'ͽI0p窐]E#r!C(ܛ$;b*/d	PprlImh.zj*OW6g00r=u`eDPo >g$8{O$=!cZ       [[o6~`dl<6@Na05E{(R%ȝ`&x97R9Y,i8qt0?D0:Q29:MP(B (f>{ >b$FcSia|tvw(p(c	I1
ch藫K4	#z{	gz$qџ=|_	x@3H:ԟ9c0b^:(#N#0 y!UB1;+#P6fd|i	MH0J%t.'`1;F{_(F1Oh,>QO$)<2ʚ}HϪ
Tu>Q89yA(g~O3|탦?Ξ7w$5M1]N=?D%^lqdl1.% B e2ў俊~z=a-٥ve3Z8e@'>xwC]M8jނNrdaiJE a8"5񣻀P}Cg=̈Hs5Ti9I2i':gV"GD*g7-%LRr]=NJ!m(8ԳTi%e(ؔw.i϶KaJ% Ki{i1rH2}KG.V#T99ɷlF令o/sKX#2>)	XjO.%pJ|l5+J^꥔;^[F%;=`'4꣉JiI|Bq*I6oj$ [xAZy`C0NuaA6-1:Ҍ$y1ьmEWɹع޴jL2pK}o5V0K~k7zNXS¼rO1c3*ؒBJ~EeMAFWY'l^HQm:-\m1vANb.ɨ(O8'(_j%_SN]o_uzRٮ>꧉EQS#U%w}~%fy~PJ);?P1XSnfl]oi^0殬YVH{5<aLBC}f[ {VٯF#]zT힠sbk+[C;+cpEWC{ 3v`N/&mkoV[b4X`x`IdѿϾ^:3?GF|̈́,N>^cY'~a99%Qve7OY.lU;/%mLk]?;a@kYoT#V^vn>{*&	-9W~X+I=+XJ>/>9$]QsΖ\UDn؂_,9 "˧D7YrN{ﻼ>PFn/RHbyJQ`B|g1BK"$' hӸÛuJНeE}~P2֋dgKymJI	ԑlQ-A4K3ٳ2N:3K0j+7*M3?t :9f1Pn+|
~DT_:[*1c- s5ˠiO4bAB1Uk6&:JeTlY(ҪfHuJ]h. g6_egɭ m_e+ULsǓ#<<T4Y}Z%VF|)RfCwe^}mk~)/i.ӌM-s({!3!GI)v.hI86 B-ҳ."ƵY, ſ84Qqw,OYacEognx׽O8틸@-hlq7GP:ߥ*YO$["m[uWuR[V
+6RND	f°fRQ҆-N+P_4<$uy'MvfF\0*gp/#5Ac|֚ℋS,8ypQZY7Fhm+_髵nѕ/P
ص`u܊shS<)of|r_5	L[,u){29e yiq/NMfr(k3E@~vT%VLB:qٷ:/+tm$=ڂTKpR_6߬&tiD
WKMKP+`L}A       UYo@~>a$iUUAyAH)DKU=-4w9JV
;7;t:p)+'GrW38D*¹4(ԨQC 0AJe8T%0Z;mVAKr3f c%"*s%n/{A
.0VE(V7*3e',!g9ARzKyb{Jyi)_F8@$(RKd[.B.y9l¬);gOokJIס)4*<fLM1F)쬪3eƙⰁmEdMZ`HAsקV(90nmL#^wJB]
aqsq(QQ$hҹFwAX@"G.u LR8QUHۚ8]r'L.;%%Icy=8WbS͎j&MMO)G/{.*3_fOg'nV\-꛳ Հį&o<&m'!?-Լ{uq#l'k㤴ƚ^#Mw]@3 `Bcz;ce;Ng/xsc/QSK+ey9{qvIQTPn4$`O<NuQO*)nlux6ۙz	S}.`.7U:yhODf#U]ۍ	7=	q   /* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.picture img {
  border-radius: 50%;
  max-height: 100%;
  max-width: 100%;
}

.details {
  padding: 0 24px;
}

#picture-container {
  align-items: center;
  display: flex;
  justify-content: center;
  padding-bottom: 32px;
  padding-top: 24px;
}

.picture {
  height: 96px;
  margin-inline-start: 84px;
  position: relative;
  width: 96px;
}

#profile-picture,
.checkmark-circle {
  position: absolute;
}

.message-container {
  display: flex;
  margin-bottom: 16px;
}

.message-container:last-child {
  margin-bottom: 32px;
}

.message-container .logo {
  background-size: cover;
  flex-shrink: 0;
  height: 20px;
  margin-inline-end: 20px;
  position: relative;
  top: -2px;
  width: 20px;
}

#chrome-logo {
  background-image: url(../../../../../ui/webui/resources/images/200-logo_chrome.png);
}

#googleg-logo {
  background-image: url(../../../../../ui/webui/resources/images/200-logo_googleg.png);
}

.message-container .title {
  font-weight: 500;
  margin-bottom: 4px;
}

.message-container .body {
  color: #646464;
}

.message-container .text {
  line-height: 20px;
}

.message-container #activityControlsCheckbox {
  margin-inline-start: 40px;
}

#undoButton {
  margin-inline-start: 8px;
}

#syncDisabledDetails {
  line-height: 20px;
  margin-bottom: 8px;
  margin-top: 16px;
  padding: 0 24px;
}

#illustration {
  height: 96px;
  margin: 0 auto;
  position: relative;
  width: 264px;
}

#checkmark-circle {
  background: rgb(66, 133, 244);
  border: 2px solid #fff;
  border-radius: 50%;
  bottom: 0;
  height: 24px;
  position: absolute;
  right: 0;
  transform: scale(0);
  width: 24px;
}

.loaded #checkmark-circle {
  animation: scale-circle 300ms cubic-bezier(0, 0, 0.2, 1) forwards;
}

@keyframes scale-circle {
  from { transform: scale(0); }
  to { transform: scale(1); }
}

#checkmark-check {
  left: 5px;
  position: absolute;
  top: 7px;
}

.loaded #checkmark-path {
  animation: draw-path 300ms cubic-bezier(0, 0, 0.2, 1) 100ms forwards;
}

@keyframes draw-path {
  from { stroke-dashoffset: 16; }
  to { stroke-dashoffset: 0; }
}

#icons {
  height: 96px;
  position: absolute;
  width: 264px;
}

#icons > div {
  animation-delay: 200ms;
  animation-duration: 1.4s;
  animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(0.25, 0.45, 0.4, 0.7);
  background-size: cover;
  opacity: 0;
  position: absolute;
}

#icon-bookmarks {
  background: url(../../../../../ui/webui/resources/images/icon_bookmarks.svg);
  height: 36px;
  left: 58px;
  top: 0;
  width: 36px;
}

#icon-extensions {
  background: url(../../../../../ui/webui/resources/images/icon_extensions.svg);
  height: 24px;
  left: 30px;
  top: 30px;
  width: 24px;
}


#icon-passwords {
  background: url(../../../../../ui/webui/resources/images/icon_passwords.svg);
  height: 30px;
  left: 38px;
  top: 66px;
  width: 40px;
}

#icon-history {
  background: url(../../../../../ui/webui/resources/images/icon_history.svg);
  height: 36px;
  left: 190px;
  top: 6px;
  width: 36px;
}

#icon-tabs {
  background: url(../../../../../ui/webui/resources/images/icon_tabs.svg);
  height: 24px;
  left: 222px;
  top: 44px;
  width: 24px;
}

#icon-themes {
  background: url(../../../../../ui/webui/resources/images/icon_themes.svg);
  height: 30px;
  left: 184px;
  top: 62px;
  width: 32px;
}

#icon-circle-open {
  border: 2px solid #000;
  border-radius: 50%;
  height: 8px;
  left: 6px;
  top: 56px;
  width: 8px;
}

.icon-circle {
  background: #000;
  border-radius: 50%;
  height: 4px;
  width: 4px;
}

#icon-circle-1 {
  left: 64px;
  top: 50px;
}

#icon-circle-2 {
  left: 178px;
  top: 18px;
}

#icon-circle-3 {
  left: 194px;
  top: 50px;
}

#icon-circle-4 {
  left: 258px;
  top: 36px;
}

.loaded .fade-top-left {
  animation-name: fade-in-icon-top-left;
}

.loaded .fade-top-right {
  animation-name: fade-in-icon-top-right;
}

.loaded .fade-middle-left {
  animation-name: fade-in-icon-middle-left;
}

.loaded .fade-middle-right {
  animation-name: fade-in-icon-middle-right;
}

.loaded .fade-bottom-left {
  animation-name: fade-in-icon-bottom-left;
}

.loaded .fade-bottom-right {
  animation-name: fade-in-icon-bottom-right;
}

@keyframes fade-in-icon-top-left {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(-4px, -4px);
  }
}

@keyframes fade-in-icon-top-right {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(4px, -4px);
  }
}

@keyframes fade-in-icon-middle-left {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(-4px, 0);
  }
}

@keyframes fade-in-icon-middle-right {
  from {
    opacity: 0;
     transform: translate(0, 0);
    }
  to {
    opacity: 0.1;
    transform: translate(4px, 0);
  }
}

@keyframes fade-in-icon-bottom-left {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(-4px, 4px);
  }
}

@keyframes fade-in-icon-bottom-right {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(4px, 4px);
  }
}
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta charset="utf-8">
    <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
    <link rel="import" href="chrome://resources/html/polymer.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
    <link rel="import" href="signin_shared_css.html">
    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
    <style>/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.picture img {
  border-radius: 50%;
  max-height: 100%;
  max-width: 100%;
}

.details {
  padding: 0 24px;
}

#picture-container {
  align-items: center;
  display: flex;
  justify-content: center;
  padding-bottom: 32px;
  padding-top: 24px;
}

.picture {
  height: 96px;
  margin-inline-start: 84px;
  position: relative;
  width: 96px;
}

#profile-picture,
.checkmark-circle {
  position: absolute;
}

.message-container {
  display: flex;
  margin-bottom: 16px;
}

.message-container:last-child {
  margin-bottom: 32px;
}

.message-container .logo {
  background-size: cover;
  flex-shrink: 0;
  height: 20px;
  margin-inline-end: 20px;
  position: relative;
  top: -2px;
  width: 20px;
}

#chrome-logo {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAIRklEQVR4AbWYfYwcZR3HP88zs7u9u153S9/bu6OgLQIxrqTKe3tFFEmKlgBqNJIGiQQt0IYXY/zj0qCJMYqtf6BCIsaXaEChyEs1JdwWStAgyUFTUSppS3t9ufbo3sve3ezM8/ycmexeb264zV7A7+WbmefZuTyf/f1mfr9nR8HsdfT+zSsR6RZvYp1UvaL4fhHAeh6RdDYLIuC6fSqb61O53B6EUuf2Xx5illKzBOsOge6xI8MbbWWUECwGiSS1Y22QOCrXRbe1odvzO1Umu6NzxyOlDxWw/zt3ddvx8R5TPtMdgZEGqQMmP5ucO3uuW+fi5Asl1dKyrXPHo6UPBHjkgc0FZUyPGSpvCeGI1SBSIjIz4OQcsXS+EILO3x5Gd1vnzx4tM4M0M+jg/d8uBBPjvd6xo1tCQFCKWarh/0Rf2O9/d4sN1zhy9+2FWQH+9947i8FQ+WD1eH/R+j7SFMDsJYGPf/xo0QyXD4aQxaYA/731mwV/6Eyvd+pEwRiDFYuE/r/JWoKBk4UwS71H7vpGoSHgG+EF/vhY78TJEwVrBbEWiY4i7w8pQkOJ0KyCwVOFMN0pSJcpGvP9Ho4eKWYBLYIFFIKKT8BRjViEDyRj8I8dLWa7zusBtqYiuPGvP+j+y2JnixcEGLGxJYIUG1pq542j1Pxcg3SfOrkljGJ3KoJDXqXnudUtrHozwwWeH5MbBWiNwobWoAQV/yUXDEQI8gVMfj5BEBCUzyBD5VQpUgnYacVcpAYyjNvS1gOUJuvgF3d9v/vgyEBvxZ/g4/1VbnvhbRY7mqxWaKVxdGilQkfnigg5kjcvj1x1DW2fvpy2ZSvI5nLEwL5Pdfg444f34h98Btc/hdKgFbWjoDU4tbnoXEVjRxHPZVpw8ueuz639TUkBrN353af6K4MbAbI4bHruHT5xepQFjsbVU8CiY2ilFBOXXc2STXcwp6WFSG8dVxweJNa5C+DCZUIkv1pl5I2H0Sd2ES8+xRkX3MghmNbJtqFal+3MXPnnG9UNux5cGcIdLHsV6uoYgc1P7GOBq8nrs5BaKVQ4llu+zooNNzIRaJ58XfPy24pKNZnRliysWy3ctMbSkhGGDzxL7ujPyWUjMEXWrZNMOlleM/Ogdel5LtB9ZmK09oEi0vF2zd7iCq59ox8HmBdFDQkN5rK1dIVwR844bN+tOT0CQhJOgLEq7NqneO2Qw73XWbpWbcCXw7SN/S0JElsAlQBWMgJqebe68qkHHjtWeW8T07Sg6nD34/tYbCxtjmaudpD559Dx0CNYp4XvPenMCBdrynhRO/zwZkNW+cx56w5yDNZ45CzQJKBMspJb8mt3LPCKQlIKGMwadl96Ll/a+w4e4Ajk1302vud+92o9cs1pYFj40z8Vt16RYSx/PXNGf1+DUKTTO2VOeUU3EBsCSu0bJKPw2uo8nzwwj4sGRvDF0nbplQDRPZeAaxS9ukr/iQAFzrkcW/kD2qkBITAJNZ3AFl1jTW0qHY9x8XnxkuV85Pm3yM1fxNzlHeHTmnogGsLVO0zFg/3H4GNLlhFkFpFTp6kjkvy6Z49i0CLCVE/Xv5ZmeX3VIqQwP65zhwdnD1cfHw6ZtNYEzsKmdkLWCq7neeDM3FMDhGcv7+CKfZpYkkppI7jU5+nWJ6RVr6ET6LjnQsJ11cenXcMLi2tFeCFIE3AprloBt9aSoTwT9bShRYtNpzYFKsLTHcKJ8XLcIVqzqQsbwwm05uCi5YL1BnHNAGmlfx5YCxorfcRjaehxU2XPyf1A3CESYI3hiLXuAiGSHnkNrSwgzdyDfVoZ25dMb1Iyxb868CJA3L4WtqejHEnScPG1N6+x8U6ndWx3g9QmdzhVnz7teGZPCmgG4MOVU/xo/844xVH7WtR+NsIkwJJw933e0poRnFNPkDXvNgUXaXTM7nFFpKS9AJNzaEaPHejlwnwHN3SsCdtX3CHiIlzxkuu05uK0xpGL4CYG/s6i8edpVpVxASgpgK6Hv/aU3+ZuVEo1taWPrrt91bXcd/EXqGt/P4ntVvRA1Ldbv3jlj9y5/FXOcQeajt57ZbNzwWdeujEmWrn9K91+e6bXuprGSqZ95dxFbProNaxfejFL5xSoK/B9jo8O8uKhPn775m5uXVJh8+oyiN8UnFcVBgaD9V0b9pYUNXU+/NVevy3TTVJNRdRRms62BaEX4odwx4ZP0z84gPGqrBDDP66bg2sHm4KLNHjGlBZe+9L6xG8SXTXbdEZ326zTECgtwYjh0OhAbAHUWICY0EHAjz+Vx5WTTcONT1jGJuy2930307njyz+tzsttQTWf6NTIWhj1Ec/nspxi5zrQZrgpOGuFE6eD7Suu35v+2RlJWdmWGfX6QGjghh1HfANB6Kph+5qWGpw0BXf6jOkzhnr00oDvbn28rAK73hnzyzQu2mmw0BiLhHA29G2drZzXWoejIVykoRFb9qoSPRiJtV2m6cjWJ8odD92yHqE3aM0UUA0fkiSkMeAb8mJ54CJQdiwBNlPkIriwKKfgGr4fDCEL1lW9QVumKLpBfawvHhjED12p8uD5LXzr/LisNIxaYCSqd32pyDUDGGnFQzcXQrgem3O2mDluHSgNaQXxA6gGdIV+/XM5dDDY8LXHSMWGNtujey4N1xgwDfqTm7ptRveYnBuWIZ0uGL6BEFDGqzx9STtXzz8ZUb8v2PiERGClMGoRWOlDfYm+PAQVR90Tgm6MQEUrxFgkgvN8rsppnrnCQjA0LZURmI36607ftztSYE0DNg+6UkQi2HVGpCjGFGXC55W17XRlTuL7UgfrC8/7qr7sAUpdG14+xCz1PwpkBlVa8GzxAAAAAElFTkSuQmCC);
}

#googleg-logo {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAACK0lEQVR4Ae3WP4vUQBjHcRtB1CLFgW3Q1mIRPTxEfPzTiAgBK61SaZtSsHAbEUEYsNBCYZorhPPIFQoHCnkJ012b2hOJggqnxeNvioFl7kLmyU4SkQt8uiX73Zk8kz3S59q9fiGFHDQY4BYGSigglX+TPIygBO6pgmyosAo4EgMUIywBBTwQtWycAR6YgUQaN4MGeCSZdOXGjMulq2f+2bieA1FCDuRNvTsnm1hxJJ1ASAIfmbk4zr8E51wNM8Gt/cGTx/35dJS+P0wFR8LIFwJL4F8vV/jLrXNtcQ2kU8SlwM7e5gn+eu+s/KwaMDAHXvT7/TH+VpxZjKumaHOBGvggP9UpF0hTBhrgNnsbJ2vJ/a49+VHF4gK5gxYGckSzkMBiwkAKCaTDwHb0X2yxnjrQdATWU0+xbotrPh7n+5vE59/eIUEgBdJdga2vOmtne4Vvb9y0cVb0Vx0CTEegcYGJH7f14bSN8mUR4wi4g9r3d8tu6eOtVRfkayAdafWsbDGQ7JbefXfDj/IZSJaM0wFx+wfTPmfAAWqY9QhLAuOs+UGBBCygQlcTn8uhvvRqPSSugaTtRgpYqIQcyPuxGSiogZ2L+hFffborWz0v0gAPaXX9AV95vtN6tHQFJtAAD+3yi21/a8NOCTsEY0WuvVbY8s82TjR4biXNCJHN2ptnsjgvUg0YVy11rnpTWcVcNShEEYLQcomwGgr5qslDU8hBg+kIqmAOvZ6zv3thp2JBo8GPAAAAAElFTkSuQmCC);
}

.message-container .title {
  font-weight: 500;
  margin-bottom: 4px;
}

.message-container .body {
  color: #646464;
}

.message-container .text {
  line-height: 20px;
}

.message-container #activityControlsCheckbox {
  margin-inline-start: 40px;
}

#undoButton {
  margin-inline-start: 8px;
}

#syncDisabledDetails {
  line-height: 20px;
  margin-bottom: 8px;
  margin-top: 16px;
  padding: 0 24px;
}

#illustration {
  height: 96px;
  margin: 0 auto;
  position: relative;
  width: 264px;
}

#checkmark-circle {
  background: rgb(66, 133, 244);
  border: 2px solid #fff;
  border-radius: 50%;
  bottom: 0;
  height: 24px;
  position: absolute;
  right: 0;
  transform: scale(0);
  width: 24px;
}

.loaded #checkmark-circle {
  animation: scale-circle 300ms cubic-bezier(0, 0, 0.2, 1) forwards;
}

@keyframes scale-circle {
  from { transform: scale(0); }
  to { transform: scale(1); }
}

#checkmark-check {
  left: 5px;
  position: absolute;
  top: 7px;
}

.loaded #checkmark-path {
  animation: draw-path 300ms cubic-bezier(0, 0, 0.2, 1) 100ms forwards;
}

@keyframes draw-path {
  from { stroke-dashoffset: 16; }
  to { stroke-dashoffset: 0; }
}

#icons {
  height: 96px;
  position: absolute;
  width: 264px;
}

#icons > div {
  animation-delay: 200ms;
  animation-duration: 1.4s;
  animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(0.25, 0.45, 0.4, 0.7);
  background-size: cover;
  opacity: 0;
  position: absolute;
}

#icon-bookmarks {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBkPSJNMjIgOS4yNGwtNy4xOS0uNjJMMTIgMiA5LjE5IDguNjMgMiA5LjI0bDUuNDYgNC43M0w1LjgyIDIxIDEyIDE3LjI3IDE4LjE4IDIxbC0xLjYzLTcuMDNMMjIgOS4yNHpNMTIgMTUuNGwtMy43NiAyLjI3IDEtNC4yOC0zLjMyLTIuODggNC4zOC0uMzhMMTIgNi4xbDEuNzEgNC4wNCA0LjM4LjM4LTMuMzIgMi44OCAxIDQuMjhMMTIgMTUuNHoiLz4KICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+Cjwvc3ZnPgo=);
  height: 36px;
  left: 58px;
  top: 0;
  width: 36px;
}

#icon-extensions {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgo8L3N2Zz4K);
  height: 24px;
  left: 30px;
  top: 30px;
  width: 24px;
}


#icon-passwords {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgaGVpZ2h0PSIzMCIgdmlld0JveD0iMCAwIDQwIDMwIj4KICA8cGF0aCBkPSJNMyA1LjAwNXYxOS45OUMzIDI2LjEwMyAzLjg5NSAyNyA1IDI3aDMwYzEuMTA4IDAgMi0uODk4IDItMi4wMDVWNS4wMDVDMzcgMy44OTcgMzYuMTA1IDMgMzUgM0g1Yy0xLjEwOCAwLTIgLjg5OC0yIDIuMDA1em0tMyAwQzAgMi4yNDIgMi4yMzQgMCA1IDBoMzBjMi43NjMgMCA1IDIuMjQyIDUgNS4wMDV2MTkuOTlDNDAgMjcuNzU4IDM3Ljc2NiAzMCAzNSAzMEg1Yy0yLjc2MyAwLTUtMi4yNDItNS01LjAwNVY1LjAwNXpNMjkgOGgzdjEzaC0zVjh6bS02IDYuMTRsLS42MzItMS44MzQtLjE0Ny4wNDYtMy4xOTUuOThWMTBIMTYuOTh2My4zM2wtMy4yLS45NzgtLjE0OC0uMDQ2TDEzIDE0LjE0bC4xNDYuMDQ1IDMuMjEuOTg0LTEuOTg3IDIuNTgtLjA5LjExNUwxNS45MyAxOWwuMDktLjExOEwxOCAxNi4zMTZsMS45NzggMi41NjYuMDkuMTE4IDEuNjU1LTEuMTMzLS4wOS0uMTE3LTEuOTg4LTIuNTggMy4yMS0uOTg1LjE0NS0uMDQ1ek03LjIyMiAxMi4zNTJsLTMuMi45OFYxMEgzdjYuMzE2bDEuOTc3IDIuNTY2LjA5LjExOCAxLjY1NC0xLjEzMy0uMDktLjExNy0xLjk4NS0yLjU4IDMuMjEtLjk4NUw4IDE0LjE0bC0uNjMtMS44MzQtLjE0OC4wNDZ6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4KPC9zdmc+Cg==);
  height: 30px;
  left: 38px;
  top: 66px;
  width: 40px;
}

#icon-history {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTEzIDNjLTQuOTcgMC05IDQuMDMtOSA5SDFsMy44OSAzLjg5LjA3LjE0TDkgMTJINmMwLTMuODcgMy4xMy03IDctN3M3IDMuMTMgNyA3LTMuMTMgNy03IDdjLTEuOTMgMC0zLjY4LS43OS00Ljk0LTIuMDZsLTEuNDIgMS40MkM4LjI3IDE5Ljk5IDEwLjUxIDIxIDEzIDIxYzQuOTcgMCA5LTQuMDMgOS05cy00LjAzLTktOS05em0tMSA1djVsNC4yOCAyLjU0LjcyLTEuMjEtMy41LTIuMDhWOEgxMnoiLz4KPC9zdmc+Cg==);
  height: 36px;
  left: 190px;
  top: 6px;
  width: 36px;
}

#icon-tabs {
  background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6Ii8+CiAgICA8cGF0aCBkPSJNMTQgMkg2Yy0xLjEgMC0xLjk5LjktMS45OSAyTDQgMjBjMCAxLjEuODkgMiAxLjk5IDJIMThjMS4xIDAgMi0uOSAyLTJWOGwtNi02em0tMSA3VjMuNUwxOC41IDlIMTN6TTYgNGg1djE2SDZWNHptNSA3aDd2OWgtN3YtOXoiIGZpbGw9IiMwMDAiLz4KICA8L2c+Cjwvc3ZnPgo=);
  height: 24px;
  left: 222px;
  top: 44px;
  width: 24px;
}

#icon-themes {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMCIgdmlld0JveD0iMCAwIDMyIDMwIj4KICA8cGF0aCBkPSJNMjAuMDQgMTYuNzRMMTIuNzc2IDI0bC0yLjQyLTIuNDJjLS42NjgtLjY2OCAwLTIuNDIgMC0yLjQybDEuMjEtMy42MzJjLjMwMi0uOTEuMzY0LTIuMDU3IDAtMi40MjItMy42My0zLjYzLTguNDcyLTYuMDUtOS42ODQtNy4yNi0xLjMzNy0xLjMzOC0xLjMzNy0zLjUwNyAwLTQuODQyIDEuMzQtMS4zNCAzLjUwNi0xLjM0IDQuODQyIDAgMS4yMSAxLjIxIDMuNjMgNi4wNSA3LjI2MyA5LjY4Mi4zNjMuMzYzIDEuNTEyLjMwMyAyLjQyIDBsMy42My0xLjIxczEuNzU0LS42NjggMi40MjIgMGwyLjQyIDIuNDItNC44NCA0Ljg0M3pNMy42NTcgMi40NGMtLjU4Ni41ODUtLjU4NiAxLjUzNSAwIDIuMTIuNTg1LjU4NiAxLjUzNS41ODYgMi4xMjIgMCAuNTgyLS41ODUuNTgyLTEuNTM1IDAtMi4xMi0uNTktLjU4Ny0xLjU0LS41ODctMi4xMjUgMHpNMjQuMzIgMjQuOWgtMy40djMuNGwtMS43IDEuNy01LjEtNS4xTDI2LjAyIDEzbDUuMSA1LjEtNi44IDYuOHoiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPgo8L3N2Zz4K);
  height: 30px;
  left: 184px;
  top: 62px;
  width: 32px;
}

#icon-circle-open {
  border: 2px solid #000;
  border-radius: 50%;
  height: 8px;
  left: 6px;
  top: 56px;
  width: 8px;
}

.icon-circle {
  background: #000;
  border-radius: 50%;
  height: 4px;
  width: 4px;
}

#icon-circle-1 {
  left: 64px;
  top: 50px;
}

#icon-circle-2 {
  left: 178px;
  top: 18px;
}

#icon-circle-3 {
  left: 194px;
  top: 50px;
}

#icon-circle-4 {
  left: 258px;
  top: 36px;
}

.loaded .fade-top-left {
  animation-name: fade-in-icon-top-left;
}

.loaded .fade-top-right {
  animation-name: fade-in-icon-top-right;
}

.loaded .fade-middle-left {
  animation-name: fade-in-icon-middle-left;
}

.loaded .fade-middle-right {
  animation-name: fade-in-icon-middle-right;
}

.loaded .fade-bottom-left {
  animation-name: fade-in-icon-bottom-left;
}

.loaded .fade-bottom-right {
  animation-name: fade-in-icon-bottom-right;
}

@keyframes fade-in-icon-top-left {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(-4px, -4px);
  }
}

@keyframes fade-in-icon-top-right {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(4px, -4px);
  }
}

@keyframes fade-in-icon-middle-left {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(-4px, 0);
  }
}

@keyframes fade-in-icon-middle-right {
  from {
    opacity: 0;
     transform: translate(0, 0);
    }
  to {
    opacity: 0.1;
    transform: translate(4px, 0);
  }
}

@keyframes fade-in-icon-bottom-left {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(-4px, 4px);
  }
}

@keyframes fade-in-icon-bottom-right {
  from {
    opacity: 0;
    transform: translate(0, 0);
  }
  to {
    opacity: 0.1;
    transform: translate(4px, 4px);
  }
}
</style>
    <custom-style>
      <style is="custom-style" include="signin-dialog-shared paper-button-style">

      </style>
    </custom-style>
  </head>
  <body>
    <!--
      Use the 'consent-description' attribute to annotate all the UI elements
      that are part of the text the user reads before consenting to the Sync
      data collection . Similarly, use 'consent-confirmation' on UI elements on
      which user clicks to indicate consent.
    -->
    <div class="container">
      <div class="top-title-bar" consent-description>
        $i18n{syncConfirmationTitle}
      </div>
      <div class="details" id="syncConfirmationDetails">
        <div id="picture-container">
          <div id="illustration">
            <div id="icons">
              <div id="icon-bookmarks" class="fade-top-left"></div>
              <div id="icon-extensions" class="fade-top-left"></div>
              <div id="icon-passwords" class="fade-bottom-left"></div>
              <div id="icon-history" class="fade-top-right"></div>
              <div id="icon-tabs" class="fade-middle-right"></div>
              <div id="icon-themes" class="fade-bottom-right"></div>
              <div id="icon-circle-open" class="fade-middle-left"></div>
              <div id="icon-circle-1" class="icon-circle fade-middle-left"></div>
              <div id="icon-circle-2" class="icon-circle fade-top-right"></div>
              <div id="icon-circle-3" class="icon-circle fade-middle-right"></div>
              <div id="icon-circle-4" class="icon-circle fade-top-right"></div>
            </div>
            <div class="picture">
              <img id="profile-picture">
              <div id="checkmark-circle">
                <svg id="checkmark-check" width="13" height="10" viewBox="0 0 13 10">
                  <path id="checkmark-path" d="M1 5l3.5 3.5L12 1" stroke="#FFF"
                        stroke-width="2" stroke-dasharray="16"
                        stroke-dashoffset="16" fill="none"></path>
                </svg>
              </div>
            </div>
          </div>
        </div>
        <div class="message-container">
          <!--
            "Chrome sync" is the Google Cloud Based services used for sync. Thus
            this section uses the Chrome logo even for Chromium builds.
          -->
          <div id="chrome-logo" class="logo"></div>
          <div>
            <div class="title" consent-description>
              $i18n{syncConfirmationChromeSyncTitle}
            </div>
            <div class="body text" consent-description>
              $i18n{syncConfirmationChromeSyncBody}
            </div>
          </div>
        </div>
        <div class="message-container">
          <!--
            This section uses the Google logo even for Chromium builds as the
            user can personalize their Google services from this screen.
          -->
          <div id="googleg-logo" class="logo"></div>
          <div>
            <div class="title" consent-description>
              $i18n{syncConfirmationPersonalizeServicesTitle}
            </div>
            <div class="body text" consent-description>
              $i18n{syncConfirmationPersonalizeServicesBody}
            </div>
          </div>
        </div>
        <div class="message-container">
          <div class="body" consent-description consent-confirmation>
            $i18nRaw{syncConfirmationSyncSettingsLinkBody}
          </div>
        </div>
      </div>
      <div class="details" id="syncDisabledDetails">
        <div class="body text" consent-description>
          $i18n{syncDisabledConfirmationDetails}
        </div>
      </div>
      <div class="action-container">
        <paper-button class="action-button" id="confirmButton"
            consent-confirmation>
          $i18n{syncConfirmationConfirmLabel}
        </paper-button>
        <paper-button id="undoButton">
          $i18n{syncConfirmationUndoLabel}
        </paper-button>
      </div>
    </div>
  </body>
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="sync_confirmation.js"></script>
  <script src="chrome://sync-confirmation/strings.js"></script>
</html>
/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

cr.define('sync.confirmation', function() {
  'use strict';

  /**
   * @param {!Array<!HTMLElement>} path Path of the click event. Must contain
   *     a consent confirmation element.
   * @return {string} The text of the consent confirmation element.
   * @private
   */
  function getConsentConfirmation(path) {
    let consentConfirmation;
    for (const element of path) {
      if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
          element.hasAttribute('consent-confirmation')) {
        return element.innerHTML.trim();
      }
    }
    assertNotReached('No consent confirmation element found.');
    return '';
  }

  /** @return {!Array<string>} Text of the consent description elements. */
  function getConsentDescription() {
    const consentDescription =
        Array.from(document.querySelectorAll('[consent-description]'))
            .filter(element => element.clientWidth * element.clientHeight > 0)
            .map(element => element.innerHTML.trim());
    assert(consentDescription);
    return consentDescription;
  }

  function onConfirm(e) {
    chrome.send(
        'confirm', [getConsentDescription(), getConsentConfirmation(e.path)]);
  }

  function onUndo(e) {
    chrome.send('undo');
  }

  function onGoToSettings(e) {
    chrome.send(
        'goToSettings',
        [getConsentDescription(), getConsentConfirmation(e.path)]);
  }

  function initialize() {
    document.addEventListener('keydown', onKeyDown);
    $('confirmButton').addEventListener('click', onConfirm);
    $('undoButton').addEventListener('click', onUndo);
    if (loadTimeData.getBoolean('isSyncAllowed')) {
      $('settingsLink').addEventListener('click', onGoToSettings);
      $('profile-picture').addEventListener('load', onPictureLoaded);
      $('syncDisabledDetails').hidden = true;
    } else {
      $('syncConfirmationDetails').hidden = true;
    }

    // Prefer using |document.body.offsetHeight| instead of
    // |document.body.scrollHeight| as it returns the correct height of the
    // even when the page zoom in Chrome is different than 100%.
    chrome.send('initializedWithSize', [document.body.offsetHeight]);
  }

  function clearFocus() {
    document.activeElement.blur();
  }

  function setUserImageURL(url) {
    if (loadTimeData.getBoolean('isSyncAllowed')) {
      $('profile-picture').src = url;
    }
  }

  function onPictureLoaded(e) {
    if (loadTimeData.getBoolean('isSyncAllowed')) {
      $('picture-container').classList.add('loaded');
    }
  }

  function onKeyDown(e) {
    // If the currently focused element isn't something that performs an action
    // on "enter" being pressed and the user hits "enter", perform the default
    // action of the dialog, which is "OK, Got It".
    if (e.key == 'Enter' &&
        !/^(A|PAPER-(BUTTON|CHECKBOX))$/.test(document.activeElement.tagName)) {
      $('confirmButton').click();
      e.preventDefault();
    }
  }

  // TODO(scottchen): clearFocus and setUserImageURL are called directly by the
  // C++ handler. C++ handlers should not be calling JS functions by name
  // anymore. They should be firing events with FireWebuiListener and have the
  // page itself decide whether to listen or not listen to the event.
  return {
    clearFocus: clearFocus,
    initialize: initialize,
    setUserImageURL: setUserImageURL
  };
});

document.addEventListener('DOMContentLoaded', sync.confirmation.initialize);
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
    <link rel="import" href="sync_confirmation_app.html"></link>
    <style>
      body {
        margin: 0;
        padding: 0;
        width: 512px;
      }
    </style>
  </head>
  <body>
    <sync-confirmation-app></sync-confirmation-app>
  </body>
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="sync_confirmation.js"></script>
</html>
/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

cr.define('sync.confirmation', function() {
  'use strict';

  function initialize() {
    const syncConfirmationBrowserProxy =
        sync.confirmation.SyncConfirmationBrowserProxyImpl.getInstance();
    // Prefer using |document.body.offsetHeight| instead of
    // |document.body.scrollHeight| as it returns the correct height of the
    // even when the page zoom in Chrome is different than 100%.
    syncConfirmationBrowserProxy.initializedWithSize(
        [document.body.offsetHeight]);
    // The web dialog size has been initialized, so reset the body width to
    // auto. This makes sure that the body only takes up the viewable width,
    // e.g. when there is a scrollbar.
    document.body.style.width = 'auto';
  }

  function clearFocus() {
    document.activeElement.blur();
  }

  // The C++ handler calls out to this Javascript function, so it needs to
  // exist in the namespace. However, this version of the sync confirmation
  // doesn't use a user image, so we do not need to actually implement this.
  // TODO(scottchen): make the C++ handler not call this at all.
  function setUserImageURL() {}

  return {
    clearFocus: clearFocus,
    initialize: initialize,
    setUserImageURL: setUserImageURL
  };
});

document.addEventListener('DOMContentLoaded', sync.confirmation.initialize);
<link rel="import" href="chrome://resources/html/cr.html">
<script src="sync_confirmation_browser_proxy.js"></script>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview A helper object used by the sync confirmation dialog to
 * interact with the browser.
 */

cr.define('sync.confirmation', function() {

  /** @interface */
  class SyncConfirmationBrowserProxy {
    /**
     * Called when the user confirms the Sync Confirmation dialog.
     * @param {!Array<string>} description Strings that the user was presented
     *     with in the UI.
     * @param {string} confirmation Text of the element that the user
     *     clicked on.
     */
    confirm(description, confirmation) {}

    /** Called when the user undoes the Sync confirmation.
     */
    undo() {}

    /**
     * Called when the user clicks on the Settings link in
     *     the Sync Confirmation dialog.
     * @param {!Array<string>} description Strings that the user was presented
     *     with in the UI.
     * @param {string} confirmation Text of the element that the user
     *     clicked on.
     */
    goToSettings(description, confirmation) {}

    /** @param {!Array<number>} height */
    initializedWithSize(height) {}

    /**
     * Called when the WebUIListener for "account-image-changed" was added.
     */
    requestAccountImage() {}
  }

  /** @implements {sync.confirmation.SyncConfirmationBrowserProxy} */
  class SyncConfirmationBrowserProxyImpl {
    /** @override */
    confirm(description, confirmation) {
      chrome.send('confirm', [description, confirmation]);
    }

    /** @override */
    undo() {
      chrome.send('undo');
    }

    /** @override */
    goToSettings(description, confirmation) {
      chrome.send('goToSettings', [description, confirmation]);
    }

    /** @override */
    initializedWithSize(height) {
      chrome.send('initializedWithSize', height);
    }

    /** @override */
    requestAccountImage() {
      chrome.send('accountImageRequest');
    }
  }

  cr.addSingletonGetter(SyncConfirmationBrowserProxyImpl);

  return {
    SyncConfirmationBrowserProxy: SyncConfirmationBrowserProxy,
    SyncConfirmationBrowserProxyImpl: SyncConfirmationBrowserProxyImpl,
  };
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/load_time_data.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="signin_shared_css.html">
<link rel="import" href="sync_confirmation_browser_proxy.html">

<script src="chrome://sync-confirmation/strings.js"></script>

<dom-module id="sync-confirmation-app">
  <template>
    <style include="signin-dialog-shared paper-button-style">
      :host {
        display: block;
      }

      paper-button {
        padding-left: 16px;
        padding-right: 16px;
      }

      .action-container {
        bottom: 0;
        box-sizing: border-box;
        position: absolute;
        width: 100%;
      }

      paper-button:not(.action-button) {
        margin-inline-start: 8px;
      }



      #illustration-container {
        height: 168px;
        margin-bottom: 32px;
        position: relative;
        width: 100%;
      }

      #illustration {
        background: url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgMTY4Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2ZmZjt9LmNscy0ye2ZpbGw6IzQyODVmNDt9LmNscy0ze2ZpbGw6I2U4ZTllYjt9LmNscy00e2ZpbGw6I2Y0ZjRmNDt9LmNscy01e2ZpbGw6I2JkYzBjNTt9LmNscy02e2ZpbGw6IzM0YTc1MTt9LmNscy03e2ZpbGw6I2Y3YmIyYTt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPmNvbmZpcm1hdGlvbkAxeDwvdGl0bGU+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjU2LDg5YTQxLDQxLDAsMCwwLTQxLDM5LjEzSDI5N0E0MSw0MSwwLDAsMCwyNTYsODlaIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOTcuNzYsNzJIMTAzYzAtMTAuODMsMi45LTE5LjM0LDguNjMtMjUuMyw5LTkuMzcsMjIuMTUtOS40MSwyMi4yOC05LjQxTDEzNCwzMmMtLjYyLDAtMTUuMzIsMC0yNS44NCwxMC45MUMxMDEuMzcsNDkuOSw5Ny43Niw1OS42OSw5Ny43Niw3MloiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik04Mi40MSwxMDIuNDJBMzUuMjcsMzUuMjcsMCwwLDEsNjcsMTA2Ljc1VjExMmE0MC4zNiw0MC4zNiwwLDAsMCwxOC01YzguMjMtNC42MSwxOC0xNC40MiwxOC0zNUg5Ny43NkM5Ny43Niw4Ni40OCw5Mi42LDk2LjcxLDgyLjQxLDEwMi40MloiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xNDMuNzgsMzMuMjd2NS4zM2g3LjQxYTYuMzUsNi4zNSwwLDAsMS0yLjc3LDQuMTUsOC4yOCw4LjI4LDAsMCwxLTEyLjM2LTQuMzVoMGE4LjI5LDguMjksMCwwLDEsNy43MS0xMC45MUE3LjUyLDcuNTIsMCwwLDEsMTQ5LDI5LjU0TDE1MywyNS41OUExMy4yMiwxMy4yMiwwLDAsMCwxNDMuNzgsMjJhMTMuNzUsMTMuNzUsMCwwLDAtMTIuMyw3LjYsMTMuNjQsMTMuNjQsMCwwLDAsMCwxMi4zNWgwYTEzLjc2LDEzLjc2LDAsMCwwLDEyLjMsNy41OSwxMy4xNSwxMy4xNSwwLDAsMCw5LjEyLTMuMzNBMTMuNDYsMTMuNDYsMCwwLDAsMTU3LDM2LjA5YTE1LjgyLDE1LjgyLDAsMCwwLS4yNS0yLjgyWiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTQzMywxMDloMTh2LTguNDhBMTEsMTEsMCwwLDAsNDMzLDEwOVoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik00OTEsNTkuNDlINDYwLjhhNS42LDUuNiwwLDAsMC01LjU5LDUuNTl2NzIuMzZBNS42LDUuNiwwLDAsMCw0NjAuOCwxNDNINDkxYTUuNiw1LjYsMCwwLDAsNS41OS01LjU5VjY1LjA4QTUuNiw1LjYsMCwwLDAsNDkxLDU5LjQ5Wm00Ljg5LDc3Ljk1YTQuODksNC44OSwwLDAsMS00Ljg5LDQuODlINDYwLjhhNC44OSw0Ljg5LDAsMCwxLTQuODktNC44OVY2NS4wOGE0Ljg5LDQuODksMCwwLDEsNC44OS00Ljg5SDQ5MWE0Ljg5LDQuODksMCwwLDEsNC44OSw0Ljg5WiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTQxOC40Myw5Mi44YzYuMS0xMC45MiwxNy4wNi0xNi40NiwzMi41Ni0xNi40NlY3MC43MmMtMjIsMC0zMi41MywxMC41Mi0zNy40NiwxOS4zNGE0My4zNSw0My4zNSwwLDAsMC01LjM2LDE5LjI3aDUuNjJBMzcuODgsMzcuODgsMCwwLDEsNDE4LjQzLDkyLjhaIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMzQyLDUwLjQ1YTkuMjgsOS4yOCwwLDAsMS04LjE3LTQuODZsLTkuMzgtMTYuMjFBMjEuODQsMjEuODQsMCwwLDAsMzIxLDQwLjkyYTIxLDIxLDAsMCwwLDE3LjU2LDIwLjg2bDctMTEuOTRBMTAuNjYsMTAuNjYsMCwwLDEsMzQyLDUwLjQ1WiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTM0Ny45MSwzMy42N0E5LjU4LDkuNTgsMCwwLDEsMzUxLjQ1LDQxYTguNDcsOC40NywwLDAsMS0xLjI4LDQuNjFMMzQwLjY2LDYyaDEuMjZhMjAuOTMsMjAuOTMsMCwwLDAsMTUuMjEtNi40OWgtMi44MWE4LjY0LDguNjQsMCwwLDEsNy44Mi04LjYsMjAuOCwyMC44LDAsMCwwLC44Ny01LjgyLDIxLjYzLDIxLjYzLDAsMCwwLTEuMjMtNy4zNVoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0zNDIsMzEuNTVsMTguNjkuMDdhMjAuNTIsMjAuNTIsMCwwLDAtMTMuNzgtMTFBNTAuNDksNTAuNDksMCwwLDAsMzQxLC4xNkwzNDEsMGgtNmMuNi45LDEuMTQsMS43OSwxLjYyLDIuNjdBNDQuODEsNDQuODEsMCwwLDEsMzQxLjgzLDIwYTIwLjg3LDIwLjg3LDAsMCwwLTE1Ljk0LDcuNDlsNi44OCwxMkE5LjQ3LDkuNDcsMCwwLDEsMzQyLDMxLjU1WiIvPjxjaXJjbGUgY2xhc3M9ImNscy0zIiBjeD0iMzQyIiBjeT0iNDEiIHI9IjcuMzUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI5OS42MyAzODIuODMpIHJvdGF0ZSgtODkuNzcpIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMjU4LjU2LDE2Ni44OEEzNy4wNiwzNy4wNiwwLDAsMSwyMjEuNzcsMTQ0SDIyNnYtOC40OGExMSwxMSwwLDAsMC02Ljg2LTIuNTFjMC0uMTYsMC0uMzIsMC0uNDhhMzcsMzcsMCwwLDEsMzQuMzYtMzkuNDdsLS4wNy0xYTM4LDM4LDAsMCwwLTM1LjI5LDQwLjUzYzAsLjE1LDAsLjMsMCwuNDVBMTEsMTEsMCwwLDAsMjA4LDE0NGgxMi42OGEzOCwzOCwwLDAsMCw3My4yMS0xMS4zNWwtMS0uMDdBMzcsMzcsMCwwLDEsMjU4LjU2LDE2Ni44OFoiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik02Mi43Miw0OC41SDB2ODguMzNINjcuNTFWNTMuMjhBNC43OCw0Ljc4LDAsMCwwLDYyLjcyLDQ4LjVaIi8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNNjgsNTMuMjhBNS4zLDUuMywwLDAsMCw2Mi43Miw0OEgwdjFINjIuNzJBNC4yOCw0LjI4LDAsMCwxLDY3LDUzLjI4djgzLjA2SDB2MUg2OFoiLz48cmVjdCBjbGFzcz0iY2xzLTUiIHk9IjE0My4wMSIgd2lkdGg9Ijg2IiBoZWlnaHQ9IjAuOTkiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik00NTEuNzIsMTM5LjFWNjMuNzNhNy45LDcuOSwwLDAsMSw3Ljg5LTcuODloMjUuMDd2LS43SDQ1OS42MmE4LjYsOC42LDAsMCwwLTguNiw4LjU5VjEzOS4xYTguNiw4LjYsMCwwLDAsOC42LDguNTlINDcyVjE0N0g0NTkuNjJBNy45LDcuOSwwLDAsMSw0NTEuNzIsMTM5LjFaIi8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNNDk1LjIyLDU1LjU1di43NWE3LjksNy45LDAsMCwxLDUuMjYsNy40M1YxMzkuMWE3LjksNy45LDAsMCwxLTcuODksNy44OUg0ODAuMnYuN2gxMi4zOWE4LjYsOC42LDAsMCwwLDguNi04LjU5VjYzLjczQTguNjEsOC42MSwwLDAsMCw0OTUuMjIsNTUuNTVaIi8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNNDk5LjQ4LDcuNmMtMTEuNiwxMS43LTExLjYsMjgtMTEuNTksMjguNzQsMCwuMTUsMCwxNC43OC0xMCwyNC43OC02LjM0LDYuMzctMTUuMzgsOS42LTI2Ljg5LDkuNnY1LjYyYzEzLjA4LDAsMjMuNDgtMy44LDMwLjkxLTExLjMsMTEuNi0xMS43LDExLjYtMjgsMTEuNTktMjguNzQsMC0uMTUsMC0xNC43OCwxMC0yNC43OEEyOS43MywyOS43MywwLDAsMSw1MTIsNS41OFYwaC0xLjI4QTM1LjQ2LDM1LjQ2LDAsMCwwLDQ5OS40OCw3LjZaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNjIuNTYsOTkuMjhhMTEuNzcsMTEuNzcsMCwwLDAtOS40OCw1LDcuNDIsNy40MiwwLDAsMC0yLjctLjUyYy00LjQ5LDAtOC4xMiw0LTguMTIsOUg3NC43NUM3NC43NSwxMDUuMyw2OS4yOSw5OS4yOCw2Mi41Niw5OS4yOFoiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik02OCw3MHYuNTNhOC4zNSw4LjM1LDAsMCwxLDguNDQsNy45NEg2OFY3OWg5di0uMjZBOC44OCw4Ljg4LDAsMCwwLDY4LDcwWiIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTE2Ni41LDgxYTIsMiwwLDAsMSwyLTJoNC43MlY3N2EyLjU1LDIuNTUsMCwwLDEsNS4xMSwwVjc5aC40OVY3N2EzLDMsMCwwLDAtNi4wOSwwdjEuNDRoLTQuMjNBMi40OCwyLjQ4LDAsMCwwLDE2Niw4MXY0LjVoLjQ5WiIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTE4Nyw4NS4xOWgtMS40M1Y4MUEyLjQ5LDIuNDksMCwwLDAsMTgzLDc4LjQ4aC0zLjI1Vjc5SDE4M2EyLDIsMCwwLDEsMiwydjQuNzJIMTg3YTIuNTUsMi41NSwwLDAsMSwwLDUuMTFIMTg1di40OUgxODdhMywzLDAsMCwwLDAtNi4wOVoiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0xODUsOTUuNTJhMiwyLDAsMCwxLTIsMmgtNFY5Ni4wOGEzLjI3LDMuMjcsMCwwLDAtNi41NCwwVjk4SDE3M1Y5Ni4wOGEyLjc4LDIuNzgsMCwwLDEsNS41NiwwVjk4SDE4M2EyLjQ5LDIuNDksMCwwLDAsMi40OC0yLjQ4VjkyLjI2SDE4NVoiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0xNjYuNDksOTUuNTJ2LTRoMS40M2EzLjI3LDMuMjcsMCwxLDAsMC02LjU0aC0uMjR2LjQ5aC4yNGEyLjc4LDIuNzgsMCwwLDEsMCw1LjU2SDE2NnY0LjVBMi40OSwyLjQ5LDAsMCwwLDE2OC40OCw5OGgzdi0uNDloLTNBMiwyLDAsMCwxLDE2Ni40OSw5NS41MloiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0yMzEuNSwzMi4zVjQ3LjExaDIuNjRWMzIuM1ptMi4xNSwxNC4zMkgyMzJWMzIuNzloMS42NloiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0yMzQuNjEsMjhIMjA3LjM5QTIuNCwyLjQsMCwwLDAsMjA1LDMwLjM5djMuMWguNDl2LTMuMWExLjksMS45LDAsMCwxLDEuOS0xLjloMjcuMjFhMS45LDEuOSwwLDAsMSwxLjksMS45VjQ5YTEuOSwxLjksMCwwLDEtMS45LDEuOUgyMDcuMzlhMS45LDEuOSwwLDAsMS0xLjktMS45VjQyLjQ4bDEuODcsMi41OCwyLjE0LTEuNTUtMi4xMy0yLjkzLDMuNDQtMS4xMkwyMTAsMzYuOTVsLTMuNDMsMS4xMVYzNC40NEgyMDV2LjQ5aDEuMDd2My44bDMuNjEtMS4xNy41MSwxLjU3LTMuNjIsMS4xNywyLjI0LDMuMDgtMS4zNCwxTDIwNSw0MXY4YTIuNCwyLjQsMCwwLDAsMi4zOSwyLjM5aDI3LjIxQTIuNCwyLjQsMCwwLDAsMjM3LDQ5VjMwLjM5QTIuNCwyLjQsMCwwLDAsMjM0LjYxLDI4WiIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTIxOS42OCwzNC40NHYzLjYybC0zLjQzLTEuMTEtLjgyLDIuNTEsMy40NCwxLjEyLTIuMTMsMi45MywyLjE0LDEuNTVMMjIxLDQyLjE0bDIuMTIsMi45MiwyLjE0LTEuNTUtMi4xMy0yLjkzLDMuNDQtMS4xMi0uODItMi41MS0zLjQzLDEuMTFWMzQuNDRabTUuNzUsMy4xMy41MSwxLjU3LTMuNjEsMS4xNywyLjI0LDMuMDgtMS4zNCwxTDIyMSw0MS4zMWwtMi4yMywzLjA2LTEuMzQtMSwyLjI0LTMuMDgtMy42Mi0xLjE3LjUxLTEuNTcsMy42MSwxLjE3di0zLjhoMS42NnYzLjhaIi8+PHBvbHlnb24gY2xhc3M9ImNscy01IiBwb2ludHM9IjI5Ni43NSA2OS44NiAyOTYuMjUgNjkuODYgMjk2LjI1IDczLjYxIDI5MS4wNSA2OC40MSAyOTYuMjUgNjMuMiAyOTYuMjUgNjYuOTYgMjk2Ljc1IDY2Ljk2IDI5Ni43NSA2MiAyOTAuMzQgNjguNDEgMjk2Ljc1IDc0LjgyIDI5Ni43NSA2OS44NiIvPjxwb2x5Z29uIGNsYXNzPSJjbHMtNSIgcG9pbnRzPSIyOTYuMjUgODcuMjggMjk2Ljc1IDg3LjI4IDI5Ni43NSA4My41MyAzMDEuOTUgODguNzMgMjk2Ljc1IDkzLjk0IDI5Ni43NSA5MC4xOSAyOTYuMjUgOTAuMTkgMjk2LjI1IDk1LjE0IDMwMi42NiA4OC43MyAyOTYuMjUgODIuMzIgMjk2LjI1IDg3LjI4Ii8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNMjk2LjUsNjguMDd2LjVhMTAsMTAsMCwwLDEsOC42MiwxNS4wOGwuNDMuMjVhMTAuNSwxMC41LDAsMCwwLTktMTUuODNaIi8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNMjk2LjUsODguNTdhMTAsMTAsMCwwLDEtOC42Mi0xNS4wOGwtLjQzLS4yNWExMC41LDEwLjUsMCwwLDAsOSwxNS44M1oiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik00NywzMS43VjIwLjU4SDIzLjQ5di0zYTIuMSwyLjEsMCwwLDEsMi4wOS0yLjExSDQ0LjRhMi4xMSwyLjExLDAsMCwxLDIuMTEsMi4xMXYySDQ3di0yQTIuNiwyLjYsMCwwLDAsNDQuNCwxNUgyNS42QTIuNTksMi41OSwwLDAsMCwyMywxNy42djMuNDhINDYuNTFWMzEuN2EyLjExLDIuMTEsMCwwLDEtMi4xMSwyLjExSDI1LjZhMi4xMSwyLjExLDAsMCwxLTIuMTEtMi4xMXYtOEg0NS45NFYyMy4ySDIzdjguNWEyLjYsMi42LDAsMCwwLDIuNiwyLjZINDQuNEEyLjYsMi42LDAsMCwwLDQ3LDMxLjdaIi8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNMzU0LDEwMS41NWE0Ljc4LDQuNzgsMCwxLDAsNC43OCw0Ljc4QTQuNzksNC43OSwwLDAsMCwzNTQsMTAxLjU1Wm0wLDkuMDZhNC4yOCw0LjI4LDAsMSwxLDQuMjgtNC4yOEE0LjI4LDQuMjgsMCwwLDEsMzU0LDExMC42MloiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0zNjUuOSwxMDIuMjdsLTIuNDEtNC4xOGEuODguODgsMCwwLDAtMS4wNS0uMzhsLTIuODgsMS4xNmE5LDksMCwwLDAtMS44NS0xLjA3bC0uNDMtMy4wNmEuODUuODUsMCwwLDAtLjg1LS43M2gtNC44NGEuODQuODQsMCwwLDAtLjg0LjczbC0uNDMsMy4wNmE5LjMzLDkuMzMsMCwwLDAtMS44NSwxLjA3bC0yLjg4LTEuMTZhLjg1Ljg1LDAsMCwwLTEsLjM4bC0yLjQyLDQuMTlhLjg0Ljg0LDAsMCwwLC4yMiwxLjA5bDIuNDQsMS45YTcuNTYsNy41NiwwLDAsMC0uMDksMS4wNyw4LDgsMCwwLDAsLjA3LDEuMDdsLTIuNDQsMS45MWEuODguODgsMCwwLDAtLjIxLDEuMDlsMi40MSw0LjE4YS44Ny44NywwLDAsMCwxLjA1LjM4bDIuODgtMS4xNmE5LDksMCwwLDAsMS44NSwxLjA3bC40NCwzLjA3YS44Ny44NywwLDAsMCwuODUuNzJoNC44NGEuODMuODMsMCwwLDAsLjg0LS43M2wuNDMtMy4wNmE5LjM0LDkuMzQsMCwwLDAsMS44NS0xLjA3bDIuODgsMS4xNmEuODUuODUsMCwwLDAsMS0uMzhsMi40Mi00LjE5YS44NC44NCwwLDAsMC0uMjItMS4wOWwtMi40MS0xLjkxYTkuODIsOS44MiwwLDAsMCwuMDYtMS4wNyw3LjkzLDcuOTMsMCwwLDAtLjA3LTEuMDdsMi40NC0xLjkxQS44OC44OCwwLDAsMCwzNjUuOSwxMDIuMjdabS0uNTIuNy0yLjY3LDIuMDksMCwuMTVhNy4yOCw3LjI4LDAsMCwxLC4wOSwxLjE0LDkuNzYsOS43NiwwLDAsMS0uMDcsMS4xNWwwLC4xNCwyLjY0LDIuMDlhLjMzLjMzLDAsMCwxLC4wOC40NEwzNjMsMTE0LjM0YS4zNC4zNCwwLDAsMS0uNDMuMTZsLTMuMTQtMS4yNi0uMTEuMDlhOC44OSw4Ljg5LDAsMCwxLTIsMS4xNWwtLjEzLjA1LS40NywzLjM2YS4zMy4zMywwLDAsMS0uMzQuMjloLTQuODRhLjM2LjM2LDAsMCwxLS4zNi0uM2wtLjQ3LTMuMzQtLjEzLS4wNmE4LjU4LDguNTgsMCwwLDEtMi0xLjE1bC0uMTEtLjA5LTMuMTIsMS4yNmEuMzYuMzYsMCwwLDEtLjQ0LS4xNmwtMi40MS00LjE4YS4zNy4zNywwLDAsMSwuMDgtLjQ1bDIuNjctMi4wOSwwLS4xNWE3LjQsNy40LDAsMCwxLS4wOS0xLjE0LDcuMjgsNy4yOCwwLDAsMSwuMS0xLjE0bDAtLjE1TDM0Mi42NCwxMDNhLjMzLjMzLDAsMCwxLS4wOC0uNDRMMzQ1LDk4LjMzYS4zNC4zNCwwLDAsMSwuNDMtLjE2bDMuMTQsMS4yNi4xMS0uMDlhOC45LDguOSwwLDAsMSwyLTEuMTVsLjEzLS4wNS40Ny0zLjM0YS4zNC4zNCwwLDAsMSwuMzQtLjNoNC44NGEuMzUuMzUsMCwwLDEsLjM2LjNsLjQ3LDMuMzUuMTMuMDVhOC41OCw4LjU4LDAsMCwxLDIsMS4xNWwuMTEuMDksMy4xMi0xLjI2YS4zNi4zNiwwLDAsMSwuNDQuMTZsMi40MSw0LjE4QS4zNy4zNywwLDAsMSwzNjUuMzcsMTAzWiIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTYyLjU2LDk5QTEyLDEyLDAsMCwwLDUzLDEwNGE3LjY0LDcuNjQsMCwwLDAtMi42Mi0uNDdjLTQuNjIsMC04LjM4LDQuMTQtOC4zOCw5LjI0VjExM0g3NXYtLjI4Qzc1LDEwNS4xNSw2OS40Miw5OSw2Mi41Niw5OVptMTEuOTMsMTMuNDRoLTMyYy4xMy00LjY2LDMuNjEtOC40LDcuODctOC40YTcuMTksNy4xOSwwLDAsMSwyLjYyLjVsLjE3LjA3LjExLS4xNWExMS41LDExLjUsMCwwLDEsOS4yOC00LjlDNjkuMDYsOTkuNTYsNzQuMzUsMTA1LjMxLDc0LjQ5LDExMi40NFoiLz48cGF0aCBjbGFzcz0iY2xzLTUiIGQ9Ik0zNzUuOTEsNDIuMjhhMTMuMTgsMTMuMTgsMCwwLDAtMTAuMTcsNC43N0E4Ljg5LDguODksMCwwLDAsMzU0LDU1LjUxdi4yN2gzNS4xdi0uMjdBMTMuMjQsMTMuMjQsMCwwLDAsMzc1LjkxLDQyLjI4Wm0tMjEuMzMsMTNhOC4zNSw4LjM1LDAsMCwxLDExLjE1LTcuNjFsLjE4LjA2LjEyLS4xNWExMi42OSwxMi42OSwwLDAsMSwyMi41Niw3LjdaIi8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNNDQxLDMzLjUxYTIuNSwyLjUsMCwxLDAtMi41LTIuNUEyLjUxLDIuNTEsMCwwLDAsNDQxLDMzLjUxWk00NDEsMjlhMiwyLDAsMSwxLTIsMkEyLDIsMCwwLDEsNDQxLDI5WiIvPjxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTQ0MSwzOGE3LDcsMCwwLDAsNi41My00LjQ5SDQ1MlYzOGg1VjMzLjUxaDJ2LTVINDQ3LjUzQTcsNywwLDEsMCw0NDEsMzhabTAtMTMuNDhhNi40OCw2LjQ4LDAsMCwxLDYuMTEsNC4zMmwuMDYuMTdoMTEuMzJ2NGgtMnY0LjQ5aC00VjMzaC01LjNsLS4wNi4xN0E2LjQ4LDYuNDgsMCwxLDEsNDQxLDI0LjUyWiIvPjxwYXRoIGNsYXNzPSJjbHMtNyIgZD0iTTI1Niw5MnYxYTM3LDM3LDAsMCwxLDM3LDM3aDFBMzgsMzgsMCwwLDAsMjU2LDkyWiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQxMS4wOCwxMjFBMTYuODEsMTYuODEsMCwwLDAsMzk4LDEyNy4yN2ExMS4yMSwxMS4yMSwwLDAsMC0xNSwxMC41OGg0NC45M0ExNi44NSwxNi44NSwwLDAsMCw0MTEuMDgsMTIxWiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTQxMS4wOCwxMjEuN2ExNi4xNywxNi4xNywwLDAsMSwxNi4xMywxNS40NEgzODMuNzNhMTAuNSwxMC41LDAsMCwxLDE0LTkuMjJsLjQ3LjE3LjMxLS4zOWExNi4wOSwxNi4wOSwwLDAsMSwxMi41Ni02bTAtLjdBMTYuODEsMTYuODEsMCwwLDAsMzk4LDEyNy4yN2ExMS4yMSwxMS4yMSwwLDAsMC0xNSwxMC41OGg0NC45M0ExNi44NSwxNi44NSwwLDAsMCw0MTEuMDgsMTIxWiIvPjwvc3ZnPg==);
        background-size: 100% 100%;
        height: 100%;
        position: absolute;
        top: 0;
        width: 100%;
      }

      #illustration-container > img {
        background: white;
        border-radius: 50%;
        height: 68px;
        left: 0;
        margin: auto;
        position: absolute;
        right: 0;
        top: 96px;
        width: 68px;
      }

      .heading {
        color: var(--paper-grey-800);
        font-weight: normal;
        margin-bottom: 32px;
        padding: 0 24px;
        text-align: center;
      }

      #content-container {
        /* Saves space for button row. */
        padding-bottom: 96px;
        position: relative;
        width: 100%;
      }

      .message-container {
        line-height: 20px;
        margin-bottom: 16px;
        padding: 0 24px;
      }

      .secondary {
        color: var(--paper-grey-600);
      }

      #grey-banner {
        background: var(--paper-grey-50);
        height: 128px;
        top: 0;
        width: 100%;
      }

      #footer {
        margin-bottom: 0;
        padding-top: 12px;
      }

      #settingsButton {
        left: 16px;
        position: absolute;
      }

      :host-context([dir='rtl']) #settingsButton {
        left: auto;
        right: 16px;
      }
    </style>

    <!--
      Use the 'consent-description' attribute to annotate all the UI elements
      that are part of the text the user reads before consenting to the Sync
      data collection . Similarly, use 'consent-confirmation' on UI elements on
      which user clicks to indicate consent.
    -->

    <div id="illustration-container">
      <div id="grey-banner"></div>
      <div id="illustration"></div>
      <img src="[[accountImageSrc_]]">
    </div>
    <div id="content-container">
      <h1 id="syncConfirmationHeading" class="heading" consent-description>
        $i18n{syncConfirmationTitle}
      </h1>
      <div class="message-container">
        <div consent-description>$i18n{syncConfirmationSyncInfoTitle}</div>
        <div class="secondary" consent-description>
          $i18n{syncConfirmationSyncInfoDesc}
        </div>
      </div>
      <div id="footer" class="message-container secondary">
        $i18n{syncConfirmationSettingsInfo}
      </div>
      <div class="action-container">
        <paper-button class="action-button" id="confirmButton"
            on-click="onConfirm_" consent-confirmation>
          $i18n{syncConfirmationConfirmLabel}
        </paper-button>
        <paper-button on-click="onUndo_">
          $i18n{syncConfirmationUndoLabel}
        </paper-button>
        <paper-button id="settingsButton" on-click="onGoToSettings_"
            consent-confirmation>
          $i18n{syncConfirmationSettingsLabel}
        </paper-button>
      </div>
    </div>
  </template>
  <script src="sync_confirmation_app.js"></script>
</dom-module>
/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

Polymer({
  is: 'sync-confirmation-app',

  behaviors: [
    WebUIListenerBehavior,
  ],

  properties: {
    /** @private */
    accountImageSrc_: {
      type: String,
      value: function() {
        return loadTimeData.getString('accountPictureUrl');
      },
    },
  },

  /** @private {?sync.confirmation.SyncConfirmationBrowserProxy} */
  syncConfirmationBrowserProxy_: null,

  /** @private {?function(Event)} */
  boundKeyDownHandler_: null,

  /** @override */
  attached: function() {
    this.syncConfirmationBrowserProxy_ =
        sync.confirmation.SyncConfirmationBrowserProxyImpl.getInstance();
    this.boundKeyDownHandler_ = this.onKeyDown_.bind(this);
    // This needs to be bound to document instead of "this" because the dialog
    // window opens initially, the focus level is only on document, so the key
    // event is not captured by "this".
    document.addEventListener('keydown', this.boundKeyDownHandler_);
    this.addWebUIListener(
        'account-image-changed', this.handleAccountImageChanged_.bind(this));
    this.syncConfirmationBrowserProxy_.requestAccountImage();
  },

  /** @override */
  detached: function() {
    document.removeEventListener('keydown', this.boundKeyDownHandler_);
  },

  /** @private */
  onConfirm_: function(e) {
    this.syncConfirmationBrowserProxy_.confirm(
        this.getConsentDescription_(), this.getConsentConfirmation_(e.path));
  },

  /** @private */
  onUndo_: function() {
    this.syncConfirmationBrowserProxy_.undo();
  },

  /** @private */
  onGoToSettings_: function(e) {
    this.syncConfirmationBrowserProxy_.goToSettings(
        this.getConsentDescription_(), this.getConsentConfirmation_(e.path));
  },

  /** @private */
  onKeyDown_: function(e) {
    if (e.key == 'Enter' && !/^(A|PAPER-BUTTON)$/.test(e.path[0].tagName)) {
      this.onConfirm_(e);
      e.preventDefault();
    }
  },

  /**
   * @param {!Array<!HTMLElement>} path Path of the click event. Must contain
   *     a consent confirmation element.
   * @return {string} The text of the consent confirmation element.
   * @private
   */
  getConsentConfirmation_: function(path) {
    for (const element of path) {
      if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
          element.hasAttribute('consent-confirmation')) {
        return element.innerHTML.trim();
      }
    }
    assertNotReached('No consent confirmation element found.');
    return '';
  },

  /** @return {!Array<string>} Text of the consent description elements. */
  getConsentDescription_: function() {
    const consentDescription =
        Array.from(this.shadowRoot.querySelectorAll('[consent-description]'))
            .filter(element => element.clientWidth * element.clientHeight > 0)
            .map(element => element.innerHTML.trim());
    assert(consentDescription);
    return consentDescription;
  },

  /**
   * Called when the account image changes.
   * @param {string} imageSrc
   * @private
   */
  handleAccountImageChanged_: function(imageSrc) {
    this.accountImageSrc_ = imageSrc;
  },

});
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta charset="utf-8">
    <link rel="import" href="chrome://resources/html/polymer.html">
    <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
    <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html">
    <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
    <link rel="import" href="signin_shared_css.html">
    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
    <link rel="import" href="chrome://resources/html/cr.html">
    <link rel="import" href="chrome://resources/html/load_time_data.html">
    <link rel="import" href="chrome://resources/html/util.html">
    <custom-style>
      <style is="custom-style" include="signin-dialog-shared paper-button-style">
        .container {
          /* The sign-in confirmation dialog uses a width that is larger than
           * the other sign-in dialogs to fit cases when the user has an email
           * name that is very large. */
          width: 512px;
        }

        .details {
          line-height: 20px;
          margin-inline-start: -8px;
          padding: 8px 24px 0;
        }

        .radio-button-title-container {
          font-weight: 500;
          line-height: 20px;
        }

        .radio-button-subtitle-container {
          line-height: 20px;
        }

        .top-title-bar {
          color: #333;
          height: auto;

          /* The signin email confirmation dialog needs to support cases when the
           * title extends multiple lines. In that case, the height of the title
           * bar is equal to padding + height of the text (which is equal to
           * 2*16px + nb_lines * 22px). */
          line-height: 22px;
          padding: 16px 24px;
        }

        #closeButton {
          margin-inline-start: 8px;
        }


      </style>
    <custom-style>
  </head>
  <body>
    <div class="container">
      <div class="top-title-bar" id='dialogTitle'>
          $i18n{signinEmailConfirmationTitle}
      </div>
      <div class="details">
        <cr-radio-group selected="createNewUser">
          <cr-radio-button id="createNewUserRadioButton"
              name="createNewUser">
            <div class="radio-button-title-container">
              $i18n{signinEmailConfirmationCreateProfileButtonTitle}
            </div>
            <div class="radio-button-subtitle-container"
                id="createNewUserRadioButtonSubtitle">
              $i18n{signinEmailConfirmationCreateProfileButtonSubtitle}
            </div>
          </cr-radio-button>
          <cr-radio-button id="startSyncRadioButton" name="startSync">
            <div class="radio-button-title-container">
              $i18n{signinEmailConfirmationStartSyncButtonTitle}
            </div>
            <div class="radio-button-subtitle-container"
                id="startSyncRadioButtonSubtitle">
              $i18n{signinEmailConfirmationStartSyncButtonSubtitle}
            </div>
          </cr-radio-button>
        </cr-radio-group>
      </div>
      <div class="action-container">
        <paper-button class="action-button" id="confirmButton">
          $i18n{signinEmailConfirmationConfirmLabel}
        </paper-button>
        <paper-button id="closeButton">
          $i18n{signinEmailConfirmationCloseLabel}
        </paper-button>
      </div>
    </div>
  </body>
  <script src="signin_email_confirmation.js"></script>
  <script src="chrome://signin-email-confirmation/strings.js"></script>
</html>
/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

cr.define('signin.emailConfirmation', function() {
  'use strict';

  function initialize() {
    const args = JSON.parse(chrome.getVariableValue('dialogArguments'));
    const lastEmail = args.lastEmail;
    const newEmail = args.newEmail;
    $('dialogTitle').textContent =
        loadTimeData.getStringF('signinEmailConfirmationTitle', lastEmail);
    $('createNewUserRadioButtonSubtitle').textContent = loadTimeData.getStringF(
        'signinEmailConfirmationCreateProfileButtonSubtitle', newEmail);
    $('startSyncRadioButtonSubtitle').textContent = loadTimeData.getStringF(
        'signinEmailConfirmationStartSyncButtonSubtitle', newEmail);

    document.addEventListener('keydown', onKeyDown);
    $('confirmButton').addEventListener('click', onConfirm);
    $('closeButton').addEventListener('click', onCancel);
  }

  function onKeyDown(e) {
    // If the currently focused element isn't something that performs an action
    // on "enter" being pressed and the user hits "enter", perform the default
    // action of the dialog, which is "OK".
    if (e.key == 'Enter' &&
        !/^(A|PAPER-BUTTON)$/.test(document.activeElement.tagName)) {
      $('confirmButton').click();
      e.preventDefault();
    }
  }

  function onConfirm(e) {
    const action = document.querySelector('cr-radio-group').selected;
    chrome.send('dialogClose', [JSON.stringify({'action': action})]);
  }

  function onCancel(e) {
    chrome.send('dialogClose', [JSON.stringify({'action': 'cancel'})]);
  }

  return {
    initialize: initialize,
  };
});

document.addEventListener(
    'DOMContentLoaded', signin.emailConfirmation.initialize);
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta charset="utf-8">
    <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
    <link rel="import" href="chrome://resources/html/polymer.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
    <link rel="import" href="signin_shared_css.html">
    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
    <link rel="import" href="chrome://resources/html/cr.html">
    <link rel="import" href="chrome://resources/html/load_time_data.html">
    <link rel="import" href="chrome://resources/html/util.html">
    <custom-style>
      <style is="custom-style" include="signin-dialog-shared paper-button-style">
        .details {
          line-height: 20px;
          margin-bottom: 8px;
          margin-top: 16px;
          padding: 0 24px;
        }

        .details p {
          margin-bottom: 0;
        }

        #closeButton {
          margin-inline-start: 8px;
        }

        #normal-error-message p:empty,
        #normal-error-message a:empty {
          display: none;
        }

        #profile-blocking-error-message {
          margin-top: 30px;
        }

        #profile-blocking-error-message p {
          background-position: 0 3px;
          background-repeat: no-repeat;
          background-size: 20px;
          line-height: 18px;
          padding-inline-start: 35px;
        }

        html[dir=rtl] #profile-blocking-error-message p {
          background-position: right 3px;
        }

        #profile-blocking-error-message p:empty {
          display: none;
        }

        #profile-blocking-error-message p:nth-child(1) {
          background-image:
            url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgMTRWNkg0djM2aDQwVjE0SDI0ek0xMiAzOEg4di00aDR2NHptMC04SDh2LTRoNHY0em0wLThIOHYtNGg0djR6bTAtOEg4di00aDR2NHptOCAyNGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTIwIDI0SDI0di00aDR2LTRoLTR2LTRoNHYtNGgtNHYtNGgxNnYyMHptLTQtMTZoLTR2NGg0di00em0wIDhoLTR2NGg0di00eiIvPgo8L3N2Zz4K);
        }

        #profile-blocking-error-message p:nth-child(2) {
          background-image:
            url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzVGNjM2OCI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgNEMxMi45NSA0IDQgMTIuOTUgNCAyNHM4Ljk1IDIwIDIwIDIwIDIwLTguOTUgMjAtMjBTMzUuMDUgNCAyNCA0em0yIDMwaC00VjIyaDR2MTJ6bTAtMTZoLTR2LTRoNHY0eiIvPgo8L3N2Zz4K);
        }


      </style>
    <custom-style>
  </head>
  <body>
    <div class="container">
      <div class="top-title-bar">$i18n{signinErrorTitle}</div>
      <div id="normal-error-message" class="details">
        <p>$i18nRaw{signinErrorMessage}</p>
        <a id="learnMoreLink" href="#">$i18nRaw{signinErrorLearnMore}</a>
      </div>
      <div id="profile-blocking-error-message" class="details">
        <p>$i18n{profileBlockedMessage}</p>
        <p>$i18n{profileBlockedAddPersonSuggestion}</p>
        <p>$i18n{profileBlockedRemoveProfileSuggestion}</p>
      </div>
      <div class="action-container">
        <paper-button class="action-button" id="switchButton">
          $i18n{signinErrorSwitchLabel}
        </paper-button>
        <paper-button id="closeButton">
          $i18n{signinErrorCloseLabel}
        </paper-button>
        <paper-button id="confirmButton" hidden>
          $i18n{signinErrorOkLabel}
        </paper-button>
      </div>
    </div>
  </body>
  <script src="signin_error.js"></script>
  <script src="chrome://signin-error/strings.js"></script>
</html>
/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

cr.define('signin.error', function() {
  'use strict';

  function initialize() {
    document.addEventListener('keydown', onKeyDown);
    $('confirmButton').addEventListener('click', onConfirm);
    $('closeButton').addEventListener('click', onConfirm);
    $('switchButton').addEventListener('click', onSwitchToExistingProfile);
    $('learnMoreLink').addEventListener('click', onLearnMore);
    if (loadTimeData.getBoolean('isSystemProfile')) {
      $('learnMoreLink').hidden = true;
    }

    // Prefer using |document.body.offsetHeight| instead of
    // |document.body.scrollHeight| as it returns the correct height of the
    // even when the page zoom in Chrome is different than 100%.
    chrome.send('initializedWithSize', [document.body.offsetHeight]);
  }

  function onKeyDown(e) {
    // If the currently focused element isn't something that performs an action
    // on "enter" being pressed and the user hits "enter", perform the default
    // action of the dialog, which is "OK".
    if (e.key == 'Enter' &&
        !/^(A|PAPER-BUTTON)$/.test(document.activeElement.tagName)) {
      $('confirmButton').click();
      e.preventDefault();
    }
  }

  function onConfirm(e) {
    chrome.send('confirm');
  }

  function onSwitchToExistingProfile(e) {
    chrome.send('switchToExistingProfile');
  }

  function onLearnMore(e) {
    chrome.send('learnMore');
  }

  function clearFocus() {
    document.activeElement.blur();
  }

  function removeSwitchButton() {
    $('switchButton').hidden = true;
    $('closeButton').hidden = true;
    $('confirmButton').hidden = false;
  }

  return {
    initialize: initialize,
    clearFocus: clearFocus,
    removeSwitchButton: removeSwitchButton
  };
});

document.addEventListener('DOMContentLoaded', signin.error.initialize);
     N0DUQ)=$ĥ-vd;U"ĿRmw<v*׍^*f}Ew'ݟr>,3)?\X5\t@p$!;$QX!-ȦXT<Bp&Rz+m	Ox@MsVEyꌐ,7x+yI	g_/E%ݐ~ff٦Km5]7|/5-sXFG"Ftv%HD69B/.[Od/Lצ47y       U[O0~8RÄTJx@B{a<WN|Ҙ9vd;ݴcUS(Si/I|.߹}>)	SuVFExz1PgA\F ECpO,*
gp=Z͕+X;XTB 4kZ0fљVXs5wc@Ntk+g[pdUch(CD1	<:So*#0Kkp%!A
5{Rmz-@j#~}Z*qhyIB ?X6Rs8!}߼κUR/ry
c6RJe&s%z$Yv|K`GEwj!E{F584(I+"?*+;VD'"9E#Zdԡ 7 ~1ֻu}I|A[kj{t~5ǤJkKz\n/i BO`iYمgXKm_Y2&E=!g_yX+}[=dp ~AFE,!Oɕt>l+P`j&!\n0: oJ>!
(@Jvm̄T>&(2Hwf%*^v u]_էIAA?4m4{LV-!9&CbF%<KNe=-#|fFtOsh̴[olF41q.e0u       UKoFW̡ IZ=bERn8`Im>
{gQd4E73|r	+nOsjnow6;)!,hXd/AajoJRWwhVP绅u{ E\\AS@(:Gx|ȒdyuηܖFlx[|Q.-k\+52doK.FedWZe9RO->fsUI4D:(Uj=.lctֲDD"_Ay)od`@֤js[AX9̐хfQPuȃ\l4)x[])Y"M0&HҴrg6}Ǻ#;"ҥoQ9V%D-fPHko*J*$-;GulXD8h+!iT5<z&ٟ74ƫ~KV[&KKo5pW%Mq1ֹ7(xsY{QI._D3L?ŻtjYeAT̋x3BG)ǋ:x}#SeZNa(ٹGe=(>HP+ٖKN^ņ| a<g֗aN_m Z2E/KZ6h'>-7a0go!1EBzshce;9̺^w'ylp-|;he]\6aPUԜu\qZ?_&$rJ{#u՟zk:=!q+):}1[*paON'3lƁۿuor	       n6_C-a[Cfh6	{(
Cl5][,[;#%o<!ٚų /NN%@..|As1{<I#B#"1', X
!O._:& )HJӐ)y{}yusE8zNi{Ȃ~된~ J:
$N
')tMHGyvӋ;!ajM9E)W>K^DtH.Y䉈3GO~cEY*7_c᳇m	q"W6[v/  \I e	:5 q!nKO .~"g
d)U(nCDsA^Cƭr@ l1|d|;T,[d7Hտix_iI#hd^ۈC7~&*f_pCLR<!11QWCABY{uu%5*B+ZxU"dŊ(sdUY#NI?*c4&֚pZj(w킍V)z*3dwU: *qӼAfo{/X7E9@w&a$gggeQ+4.}ZBƇO8"Hڲ|6ߗz}DN$k!髍rbCYG)W`/ףѪa5A3F(
?fa7qT'T
P폧Gr$^aq*vpvK*S`jgcG<^BTTJӿd6`3vq2>
V<$*X,Xsɞ4Nj,x6b5-_ŸKr'3W:hk=aOOAiJdTl2q?oQѻЯ db])~@xVNKTw|07ٷsrԶF[2m0eYMe'hEWo̒m=uEgYvlHy3Z7C{^Ul!RY'GuJ`2Oنs{u0{N.fVlh؞^%<C{X3|^䊐 Li^Swa.NT$`3yyce0NU!
hn)T-pIB*832J&á>2^J2QwhlML<lVZ
hNm&sV{M.S;@"/,ע3`UV<¸Q/l#yԕ3򼑚9nyrL\I24G.2ݸQ[~h$МJwhjϴaܺhZ1oi4lo̅nZFa[tp'tJ} al/_低hiJͱle`geQtDv lT-|7_|sﵻe؁:$j@;ƠqMp8       ]ms۸_tbrҒ:}Z\lO^2MBc^ HHP."P0'`c.(8FaJ !z0$ ȃ}QQ}p?.x_q2!FY2vT0N#)`tRR'(Nqd .k<#b?t=gw7rG%'N ~r(!zw/CجK@̌pL{rQdQa?ш)C ڂI&؞OP>ͤ!(?U=&.zirM"(v1MF_NG7|7|^~(-%N]Z|>PZ(38ˌuH]y>Udq$c[8bTr5E3+  ;J]9~3;:25G^o3˯alLaX@j]⎐?9OyC(	v(Nd6<2-(Gi@$JP1"=_J=ptrDNGn0+zcdQJ)$?c<E(B̘ 1U?g_h$̔ך P_Ett	1LnY` $_htr?$(Abb,(ه?{5JYB !-L\Ǉ_!¤MC3#+?.ɛYBU0CnJI4Ug`U& `62<C7ތ4>[xvȈҊ=$yh4gpR	²5b/n!aD3U*8Zڔ*JJ <@4L>]ԉ2fEjs":}"#0ksī)*XΜUj³j&ۤu-	R'Q3\ IE8O(H .d/n+=c?5ͧY:SZUѲ<T9iʩ'|F[!;}Vsw.r'xܲaύijn-mjQ͉`WjInd:E<2SKMĔX"l[3u-u$s9X]!GS[#kb!ߏy4f8/}N!QRR%^8g99&kFŔVfSlʱk
x~=}@ǅ0LԌ"l,itiq5z'}~ǔ:Tf;
kwSNGv
+;_z1knj^8XG;W=ϻr.U=x[հmgdZcnx;(FJg9)bfKNsԒU;`Nh>Q2?aRܪZi;]G&1[CoKzXCfn#1f;jx[C9m7vn{m5ySW=<L,;Gȝ5;f0kouޗ.my\rQulH\Dѽm@g5#l:l]yA5wpj	\HwaoP-4hppک1	n߳ᐩ4A<nīġAR"!gTƐjjR񂵬muod;ZŹqZAI*!+#P@kf7qbo3AVg 
)Sks`1]UϵN FFI!OE~iwF yeh.$#P.(Պud铒[-0,>AnKk ]8Ma-	{ZL6Hh2ߦ>,_0S=jEWLF.5JړcHlxlt\σ<B[d#2r[@ݴgFL9(	Ν.yJꖻmso+Yd3ǵ2Zm@F:BZr~ $Cm2] WiiŊp*"ۑ6C>~]X
 deȪTZ>p̊
k6M=ef#̩ߏok
`NvcKݪC[>,TK.ucW-:x`zTͨV"LnFLM[ մU38j^TW)W+&94D¹곳r| S}A2fEr,+BŰ~hW[v3s]NQCy:=#z>T5_3&Mt7Ej"lJtVZrWC']+pCz+j{En5h?0Ots9M`1JWoy\y6IMEڍFB<{RlKQY=ŗ5ejkRQqH"^N4լ%z*iE,liBؼ]7FɲZ/没_c)WT|ۇ8it`W҄Wz³F"9D$-YY3{eekTeWaX`"mEb \p*dLO8ߦptWW-evLEN=ʩH8I+jm̙'&ܒduNJq1P\,SQaj\uf<kz[ t3&Ǣg  <!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>$i18n{webrtcLogsTitle}</title>
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <style>/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  margin: 20px;
}

h1 {
  font-size: 156%;
  font-weight: bold;
  margin: 0;
  padding-bottom: 20px;
  padding-top: 20px;
}

html[dir=rtl] h1 {
  background-position: right;
}

.log-banner {
  background-color: rgb(235, 239, 250);
  border: 1px solid #bbb;
  border-radius: 2px;
  font-size: 100%;
  padding: 4px;
}

.log-list h3 {
  font-size: 100%;
}

.log-list > div > * {
  margin: 0.75em 0;
}

.log-list a:visited {
  color: #666;
}

.log-list > div:not(:last-child) {
  border-bottom: 1px solid #bbb;
}
</style>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="strings.js"></script>
  <script src="webrtc_logs.js"></script>
</head>
<body>
  <header><h1>$i18n{webrtcLogsTitle}</h1></header>
  
  <h2 id="text-log-banner" class="log-banner"></h2>
  <div id="text-log-list" class="log-list"></div>
  <p id="text-no-logs" hidden>$i18n{noTextLogsMessage}</p>

  <h2 id="event-log-banner" class="log-banner"></h2>
  <div id="event-log-list" class="log-list"></div>
  <p id="event-no-logs" hidden>$i18n{noEventLogsMessage}</p>
</body>
</html>
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Requests the list of WebRTC logs from the backend.
 */
function requestWebRtcLogsList() {
  chrome.send('requestWebRtcLogsList');
}

/**
 * Callback from backend with the list of WebRTC logs. Builds the UI.
 * @param {array} textLogsList The list of WebRTC text logs.
 * @param {array} eventLogsList The list of WebRTC event logs.
 * @param {string} version The browser version.
 */
function updateWebRtcLogsList(textLogsList, eventLogsList, version) {
  updateWebRtcTextLogsList(textLogsList, version);
  updateWebRtcEventLogsList(eventLogsList);
}

function updateWebRtcTextLogsList(textLogsList, version) {
  $('text-log-banner').textContent =
      loadTimeData.getStringF('webrtcTextLogCountFormat', textLogsList.length);

  const textLogSection = $('text-log-list');

  // Clear any previous list.
  textLogSection.textContent = '';

  for (let i = 0; i < textLogsList.length; i++) {
    const textLog = textLogsList[i];

    const logBlock = document.createElement('div');

    const title = document.createElement('h3');
    title.textContent = loadTimeData.getStringF(
        'webrtcLogHeaderFormat', textLog['capture_time']);
    logBlock.appendChild(title);

    const localFileLine = document.createElement('p');
    if (textLog['local_file'].length == 0) {
      localFileLine.textContent =
          loadTimeData.getString('noLocalLogFileMessage');
    } else {
      localFileLine.textContent =
          loadTimeData.getString('webrtcLogLocalFileLabelFormat') + ' ';
      const localFileLink = document.createElement('a');
      localFileLink.href = 'file://' + textLog['local_file'];
      localFileLink.textContent = textLog['local_file'];
      localFileLine.appendChild(localFileLink);
    }
    logBlock.appendChild(localFileLine);

    const uploadLine = document.createElement('p');
    if (textLog['id'].length == 0) {
      uploadLine.textContent =
          loadTimeData.getString('webrtcLogNotUploadedMessage');
    } else {
      uploadLine.textContent =
          loadTimeData.getStringF(
              'webrtcLogUploadTimeFormat', textLog['upload_time']) +
          '. ' +
          loadTimeData.getStringF('webrtcLogReportIdFormat', textLog['id']) +
          '. ';
      const link = document.createElement('a');
      const commentLines = [
        'Chrome Version: ' + version,
        // TODO(tbreisacher): fill in the OS automatically?
        'Operating System: e.g., "Windows 7", "Mac OSX 10.6"', '',
        'URL (if applicable) where the problem occurred:', '',
        'Can you reproduce this problem?', '',
        'What steps will reproduce this problem? (or if it\'s not ' +
            'reproducible, what were you doing just before the problem)?',
        '', '1.', '2.', '3.', '',
        '*Please note that issues filed with no information filled in ' +
            'above will be marked as WontFix*',
        '', '****DO NOT CHANGE BELOW THIS LINE****', 'report_id:' + textLog.id
      ];
      const params = {
        template: 'Defect report from user',
        comment: commentLines.join('\n'),
      };
      let href = 'http://code.google.com/p/chromium/issues/entry';
      for (const param in params) {
        href = appendParam(href, param, params[param]);
      }
      link.href = href;
      link.target = '_blank';
      link.textContent = loadTimeData.getString('bugLinkText');
      uploadLine.appendChild(link);
    }
    logBlock.appendChild(uploadLine);

    textLogSection.appendChild(logBlock);
  }

  $('text-no-logs').hidden = (textLogsList.length != 0);
}

function updateWebRtcEventLogsList(eventLogsList) {
  const eventLogSection = $('event-log-list');

  eventLogSection.textContent = '';  // Clear any previous list.

  let entries = 0;

  for (let i = 0; i < eventLogsList.length; i++) {
    const entry = createEventLogEntryElement(eventLogsList[i]);
    if (entry) {
      eventLogSection.appendChild(entry);
      entries += 1;
    }
  }

  $('event-log-banner').textContent =
      loadTimeData.getStringF('webrtcEventLogCountFormat', entries);

  $('event-no-logs').hidden = (entries != 0);
}

function createEventLogEntryElement(eventLogEntry) {
  // See LogHistory in webrtc_event_log_manager_remote.cc for an explanation
  // of the various states.
  const state = eventLogEntry['state'];
  if (!state) {
    console.error('Unknown state.');
    return;
  } else if (state == 'pending' || state == 'actively_uploaded') {
    return createPendingOrActivelyUploadedEventLogEntryElement(eventLogEntry);
  } else if (state == 'not_uploaded') {
    return createNotUploadedEventLogEntryElement(eventLogEntry);
  } else if (state == 'upload_unsuccessful') {
    return createUploadUnsuccessfulEventLogEntryElement(eventLogEntry);
  } else if (state == 'upload_successful') {
    return createUploadSuccessfulEventLogEntryElement(eventLogEntry);
  } else {
    console.error('Unrecognized state.');
  }
}

function createPendingOrActivelyUploadedEventLogEntryElement(eventLogEntry) {
  const expectedFields = ['capture_time', 'local_file'];
  if (!verifyExpectedFields(eventLogEntry, expectedFields)) {
    return;
  }

  const logBlock = document.createElement('div');

  appendCaptureTime(logBlock, eventLogEntry);
  appendLocalFile(logBlock, eventLogEntry);

  const uploadLine = document.createElement('p');
  if (eventLogEntry['state'] == 'pending') {
    uploadLine.textContent = loadTimeData.getString('webrtcLogPendingMessage');
  } else {
    uploadLine.textContent =
        loadTimeData.getString('webrtcLogActivelyUploadedMessage');
  }
  logBlock.appendChild(uploadLine);

  return logBlock;
}

function createNotUploadedEventLogEntryElement(eventLogEntry) {
  const expectedFields = ['capture_time', 'local_id'];
  if (!verifyExpectedFields(eventLogEntry, expectedFields)) {
    return;
  }

  const logBlock = document.createElement('div');

  appendCaptureTime(logBlock, eventLogEntry);
  appendLocalLogId(logBlock, eventLogEntry);

  const uploadLine = document.createElement('p');
  uploadLine.textContent =
      loadTimeData.getString('webrtcLogNotUploadedMessage');
  logBlock.appendChild(uploadLine);

  return logBlock;
}

function createUploadUnsuccessfulEventLogEntryElement(eventLogEntry) {
  const expectedFields = ['capture_time', 'local_id', 'upload_time'];
  if (!verifyExpectedFields(eventLogEntry, expectedFields)) {
    return;
  }

  const logBlock = document.createElement('div');

  appendCaptureTime(logBlock, eventLogEntry);
  appendLocalLogId(logBlock, eventLogEntry);

  const uploadLine = document.createElement('p');
  uploadLine.textContent = loadTimeData.getStringF(
      'webrtcLogFailedUploadTimeFormat', eventLogEntry['upload_time']);
  logBlock.appendChild(uploadLine);

  return logBlock;
}

function createUploadSuccessfulEventLogEntryElement(eventLogEntry) {
  const expectedFields =
      ['capture_time', 'local_id', 'upload_id', 'upload_time'];
  if (!verifyExpectedFields(eventLogEntry, expectedFields)) {
    return;
  }

  const logBlock = document.createElement('div');

  appendCaptureTime(logBlock, eventLogEntry);
  appendLocalLogId(logBlock, eventLogEntry);

  const uploadLine = document.createElement('p');
  uploadLine.textContent =
      loadTimeData.getStringF(
          'webrtcLogUploadTimeFormat', eventLogEntry['upload_time']) +
      '. ' +
      loadTimeData.getStringF(
          'webrtcLogReportIdFormat', eventLogEntry['upload_id']) +
      '. ';
  logBlock.appendChild(uploadLine);

  return logBlock;
}

function verifyExpectedFields(entry, expectedFields) {
  for (const fieldIdx in expectedFields) {
    const field = expectedFields[fieldIdx];
    if (!entry[field]) {
      console.error('|' + field + '| expected.');
      return false;
    }
  }
  return true;
}

function appendCaptureTime(logBlock, eventLogEntry) {
  const title = document.createElement('h3');
  title.textContent = loadTimeData.getStringF(
      'webrtcLogHeaderFormat', eventLogEntry['capture_time']);
  logBlock.appendChild(title);
}

function appendLocalFile(logBlock, eventLogEntry) {
  // Local file on disk, if still on disk.
  const localFileLine = document.createElement('p');
  localFileLine.textContent =
      loadTimeData.getString('webrtcLogLocalFileLabelFormat') + ' ';
  const localFileLink = document.createElement('a');
  localFileLink.href = 'file://' + eventLogEntry['local_file'];
  localFileLink.textContent = eventLogEntry['local_file'];
  localFileLine.appendChild(localFileLink);
  logBlock.appendChild(localFileLine);
}

function appendLocalLogId(logBlock, eventLogEntry) {
  const localIdLine = document.createElement('p');
  localIdLine.textContent =
      loadTimeData.getStringF(
          'webrtcEventLogLocalLogIdFormat', eventLogEntry['local_id']) +
      '';
  logBlock.appendChild(localIdLine);
}

document.addEventListener('DOMContentLoaded', requestWebRtcLogsList);
{
  // chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/
  "key": "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC4L17nAfeTd6Xhtx96WhQ6DSr8KdHeQmfzgCkieKLCgUkWdwB9G1DCuh0EPMDn1MdtSwUAT7xE36APEzi0X/UpKjOVyX8tCC3aQcLoRAE0aJAvCcGwK7qIaQaczHmHKvPC2lrRdzSoMMTC5esvHX+ZqIBMi123FOL0dGW6OPKzIwIBIw==",
  "name": "GaiaAuthExtension",
  "version": "0.0.1",
  "manifest_version": 2,
  "description": "GAIA Component Extension",
  "incognito": "split",
  "web_accessible_resources": [
    "success.html"
  ]
}
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

(function() {
// Since all we want here is forwarding of certain commands, all can be done
// in the anonymous function's scope.

function wireUpWindow() {
  $('launch-button').addEventListener('click', function() {
    chrome.send('SetAsDefaultBrowser:LaunchSetDefaultBrowserFlow');
  });
}

window.addEventListener('DOMContentLoaded', wireUpWindow);
})();
<!doctype html>
<!-- Copyright (c) 2012 The Chromium Authors. All rights reserved.
     Use of this source code is governed by a BSD-style license that can be
     found in the LICENSE file. -->
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<title>$i18n{pageTitle}</title>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="chrome://resources/js/cr/event_target.js"></script>
<script src="set_as_default_browser.js"></script>
<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
<link rel="stylesheet" href="chrome://resources/css/widgets.css">
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* The main (outer) container. */
#metro-setup-outer-container {
  -webkit-box-align: center;
  -webkit-box-orient: vertical;
  -webkit-box-pack: start;
  background-color: rgba(255, 255, 255, 0.75);
  bottom: 0;
  display: -webkit-box;
  left: 0;
  overflow: auto;
  position: fixed;
  right: 0;
  top: 0;
  transition: 200ms opacity;
}

/* The page block within the outer container. */
#metro-setup-outer-container .page {
  -webkit-box-orient: vertical;
  background: white;
  background-color: white;
  border-radius: 3px;
  color: #333;
  display: -webkit-box;
  min-width: 40px;
  padding-top: 90px;
  position: relative;
  user-select: none;
  width: 500px;
}

#metro-setup-outer-container .page .content-area {
  -webkit-box-flex: 1;
  margin: 0;
  overflow: auto;
  padding: 0;
}

#metro-setup-overlay {
  background-color: transparent;
  margin: 0;
  width: 100%;
}

/* Page Title. */
#metro-title-container {
  display: block;
  margin: 37px 44px 35px;
  text-align: center;
}

#metro-setup-outer-container .page h1 {
  border-bottom: 0;
  color: #323232;
  font-size: 300%;
  font-weight: normal;
  margin: 0;
  padding-bottom: 0;
  padding-top: 0;
  text-align: center;
}

#metro-setup-outer-container .page h2 {
  border-bottom: 0;
  color: #787878;
  font-size: 150%;
  font-weight: normal;
  margin-bottom: 84px;
  margin-top: 15px;
  text-align: center;
}

#metro-setup-overlay .content-area {
  padding: 10px 15px;
  text-align: end;
}

/* Action buttons. */
#metro-action-box button {
  border-radius: 2px;
  display: inline-block;
  font-size: 13px;
  height: 32px;
  line-height: 27px;
  margin-inline-end: 0.4em;
  margin-inline-start: 0;
  margin-top: 0;
  min-width: 80px;
  transition: all 218ms;
  user-select: none;
}

#metro-action-box button:hover {
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
  transition: all 0ms;
}

#metro-action-box button:focus {
  box-shadow: inset 0 0 0 1px white;
  outline: none;
  z-index: 4 !important;
}

#metro-action-box button:active,
#metro-action-box button:focus:active {
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3);
}

#metro-action-box button:focus:hover {
  box-shadow: inset 0 0 0 1px white, 0 1px 1px rgba(0, 0, 0, 0.1);
}

#metro-action-box button[disabled],
#metro-action-box button[disabled]:hover,
#metro-action-box button[disabled]:active {
  background-color: rgb(77, 144, 254);
  border: 1px solid rgb(48, 121, 237);
  box-shadow: none;
  color: white;
  opacity: 0.5;
}

/* Launch button has a special look-and-feel. */
#metro-action-box #launch-button {
  background-image: -webkit-linear-gradient(top, rgb(77, 144, 254),
                                                 rgb(71, 135, 237));
  border: 1px solid rgb(48, 121, 237);
  color: white;
  font-weight: bold;
}

#metro-action-box #launch-button:hover {
  background-image: -webkit-linear-gradient(top, rgb(77, 144, 254),
                                                 rgb(53, 122, 232));
  border-color: rgb(47, 91, 183);
  color: white;
}

#metro-action-box #launch-button:focus {
  border-color: rgb(77, 144, 254);
  outline: none;
  z-index: 4 !important;
}

.button-strip {
  margin: 1px;
  text-align: center;
}

#chrome-logo-box {
  bottom: 30px;
  position: absolute;
  text-align: center;
  width: 100%;
}
</style>
</head>
<body>
<div id="metro-setup-outer-container">
  <div id="metro-setup-overlay" class="page">
    <div>
      <div class="content-area">
        <h1>$i18n{flowTitle}</h1>
        <h2>$i18n{flowDescription}</h2>
      </div>
      <div id="metro-action-box" class="content-area">
        <div class="button-strip">
          <button id="launch-button" class="custom-appearance">
            $i18n{flowNext}
          </button>
        </div>
      </div>
    </div>
  </div>
  <div id="chrome-logo-box">
    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAYCAQAAACmC5BlAAADR0lEQVR4XtWYy4scVRSH78DMIIha4hMNpOI8ICDYG8GFi1r4B7QgiMTBUiMIg6TjjOvUxpVI74NS42OhiJbY7sud3yJQxB5MouLgOGJUsCHJEFTISXO4HHLoQIpEsZtvc87lUvw+6j6qO4iDZY4zYJvdMdsM2GBVwiwQxOAR3uEi4uESJcszJMJz/IYYnt85MiMivIbcgGPtBOiQkWj133I9EZ5GWpC3EqkRsv9L5An+cgIX+ZbTfKOcjgz5ivumWoSjEnjLJH5mnRiYORaZ11q7qX4jrPI3R7idPdX4mgeY5yglW7zKnRLY5FM+Mg5Nr8gGwo8s8CLCHvdzmDNI5AyPscIFxNicCJ5SUFHTJyeRKDKmoKaiR4IK6EhKQk/H0zjW167QXqEgJ5DHZ2YE7UpqSu0i+iSdQ0dFGGjAExIYsski3yMY427RnWgDr0HuZqdRpEaMUQxZIHTZIc4koXKz8igiNGPE6LmuHzU6jPwxFNiO2/sgj/MgryAeXuYe9q3bdhqZjhUaK6NnS0soNX6qIUoTGWnglIxAH6HRKlFJoaMipkVCaTIJgR6CaJWoRqErINc6C+wiysca40PEw5YEzlm360QqhGJyj1DbHukg7GhlYZUEQdyCEioTyW3c3oLSIGRRqbIUBUJpIlzhKQl8gHgoJfDd9UXQMJMi5FpZFB9V6SLUBCO1eV5Qd5zv4mjXrYtal1bklITJpUXOvexbN/QiyA1OLS9SaOW7iBMJLUQ8Ehi4/bDAWadxlgW32b+YGpGG+loCbyDGeR5ihaH1Qx7lbn5BjNf/JZEcobolkWzyQryMGKc4wBxrnBzzAndJ4G3E2GfJiewgdG9KpIMwIrg907QWKRHKyU+U9xH3VjZ4WIMckMBh9hHjXR9awzUksUvailio0s6wRjXbimT+I5aUdFywxJ+I4zI/8BPvSeAT96vkoBeJAUZUlNRIexG70hoKyliFtiLxFhIa+lSaoVAjnkcm+IeUJ93IM1HAq2gMpWknYqRUdq8XJO1FlK4KKFRkMRAbiIc3JYB1V1iflZ+6a/yBGHvcxpp1v/LsLP35sMIWlxDlJe7gvFYXOMkhCTMjYjLH+ZLPmGOdc3zOMT1wZ4CrdKjdS5IW3vcAAAAASUVORK5CYII=" alt="$i18n{chromeLogoString}">
  </div>
</div>
</body>
</html>
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="/profile_browser_proxy.html">
<link rel="import" href="/shared_styles.html">
<link rel="import" href="/strings.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">

<dom-module id="control-bar">
  <template>
    <style include="shared-styles iron-flex iron-flex-alignment iron-positioning">
      #container {
        align-items: center;
        min-height: 32px;
        padding-bottom: 12px;
        padding-inline-end: 8px;
        padding-inline-start: 24px;
        padding-top: 12px;
      }

      #logo {
        margin-inline-end: auto;
        user-select: none;
      }

      paper-button + paper-button {
        margin-inline-start: 8px;
      }
    </style>
    <div id="container" class="layout horizontal end-justified">
      <div id="logo" class="product-logo" alt=""></div>
      <paper-button id="launchGuest"
          on-tap="onLaunchGuestTap_"
          hidden="[[!showGuest]]">$i18n{browseAsGuest}</paper-button>
      <paper-button id="addUser" on-tap="onAddUserTap_"
          hidden="[[!showAddPerson]]">$i18n{addUser}</paper-button>
    </div>
  </template>
  <script src="control_bar.js"></script>
</dom-module>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview 'control-bar' is the horizontal bar at the bottom of the user
 * manager screen.
 */
Polymer({
  is: 'control-bar',

  behaviors: [
    I18nBehavior,
  ],

  properties: {
    /**
     * True if 'Browse as Guest' button is displayed.
     * @type {boolean}
     */
    showGuest: {type: Boolean, value: false},

    /**
     * True if 'Add Person' button is displayed.
     * @type {boolean}
     */
    showAddPerson: {type: Boolean, value: false},

    /** @private {!signin.ProfileBrowserProxy} */
    browserProxy_: Object,

    /**
     * True if the force sign in policy is enabled.
     * @private {boolean}
     */
    isForceSigninEnabled_: {
      type: Boolean,
      value: function() {
        return loadTimeData.getBoolean('isForceSigninEnabled');
      },
    }
  },

  /** @override */
  created: function() {
    this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
  },

  /**
   * Handler for 'Browse as Guest' button click event.
   * @param {!Event} event
   * @private
   */
  onLaunchGuestTap_: function(event) {
    this.browserProxy_.areAllProfilesLocked().then(allProfilesLocked => {
      if (!allProfilesLocked || this.isForceSigninEnabled_) {
        this.browserProxy_.launchGuestUser();
      } else {
        document.querySelector('error-dialog')
            .show(this.i18n('browseAsGuestAllProfilesLockedError'));
      }
    });
  },

  /**
   * Handler for 'Add Person' button click event.
   * @param {!Event} event
   * @private
   */
  onAddUserTap_: function(event) {
    this.browserProxy_.areAllProfilesLocked().then(allProfilesLocked => {
      if (!allProfilesLocked || this.isForceSigninEnabled_) {
        // Event is caught by user-manager-pages.
        this.fire('change-page', {page: 'create-user-page'});
      } else {
        document.querySelector('error-dialog')
            .show(this.i18n('addProfileAllProfilesLockedError'));
      }
    });
  }
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="/profile_browser_proxy.html">
<link rel="import" href="/shared_styles.html">
<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
<link rel="import" href="chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/action_link.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">

<dom-module id="create-profile">
  <template>
    <style
        include="shared-styles iron-positioning md-select">
      :host {
        align-self: center;
      }

      .container {
        color: var(--cr-primary-text-color);
        width: var(--page-width);
      }

      #message-container {
        -webkit-transition: top 400ms cubic-bezier(.4, 0, .2, 1),
                            visibility 0s linear 400ms;
        align-items: center;
        background-color: var(--paper-red-50);
        box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .12);
        color: var(--google-red-700);
        display: flex;
        height: 40px;
        left: 0;
        overflow: hidden;
        padding: 0 16px;
        position: absolute;
        right: 0;
        top: -40px;
        visibility: hidden;
      }

      #message-container[visible] {
        -webkit-transition: top 400ms cubic-bezier(.4, 0, .2, 1),
                            visibility 0s linear 0s;
        top: 0;
        visibility: visible;
      }

      #message-container iron-icon {
        --iron-icon-height: 20px;
        --iron-icon-width: 20px;
      }

      #message-container #message {
        margin-inline-start: 16px;
      }

      #message-container a {
        color: inherit;
        text-decoration: underline;
      }

      #title-bar {
        font-size: 16px;
        font-weight: 500;
      }

      #nameInput {
        --cr-input-input: {
          border-bottom: 1px solid var(--paper-grey-800);
        }
        margin-bottom: 24px;
        margin-top: 32px;
        width: 300px;
      }

      cr-checkbox {
        margin-top: 24px;
      }

      #actions {
        bottom: 16px;
        display: flex;
        position: absolute;
        right: 16px;
      }

      :host-context([dir='rtl']) #actions {
        left: 16px;
        right: auto;
      }

      #actions paper-spinner-lite {
        align-self: center;
        height: 20px;
        margin-inline-end: 8px;
        width: 20px;
      }
    </style>
    <div id="message-container" visible$="[[isMessageVisble_]]">
      <iron-icon icon="cr:warning"></iron-icon>
      <span id="message" inner-h-t-m-l="[[message_]]"></span>
    </div>
    <div class="container">
      <div id="title-bar">$i18n{createProfileTitle}</div>
      <cr-input id="nameInput" value="{{profileName_}}" pattern=".*\S.*"
          auto-validate spellcheck="false">
      </cr-input>
      <cr-profile-avatar-selector avatars="[[availableIcons_]]"
          selected-avatar="{{selectedAvatar_}}">
      </cr-profile-avatar-selector>
      <cr-checkbox id="createShortcutCheckbox" checked="{{createShortcut_}}"
          hidden="[[!isProfileShortcutsEnabled_]]">
        $i18n{createDesktopShortcutLabel}
      </cr-checkbox>
      <div id="actions">
        <paper-spinner-lite active="[[isSpinnerActive_(createInProgress_)]]">
        </paper-spinner-lite>
        <paper-button id="cancel" class="cancel-button"
            on-tap="onCancelTap_">
          $i18n{cancel}
        </paper-button>
        <paper-button id="save" class="action-button" on-tap="onSaveTap_"
            disabled="[[isSaveDisabled_(createInProgress_, profileName_)]]">
          $i18n{createProfileConfirm}
        </paper-button>
      </div>
    </div>
  </template>
  <script src="create_profile.js"></script>
</dom-module>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview 'create-profile' is a page that contains controls for creating
 * a profile, including choosing a name, and an avatar.
 */

(function() {
Polymer({
  is: 'create-profile',

  behaviors: [I18nBehavior, WebUIListenerBehavior],

  properties: {
    /**
     * The current profile name.
     * @private {string}
     */
    profileName_: {type: String, value: ''},

    /**
     * The list of available profile icon Urls and labels.
     * @private {!Array<!AvatarIcon>}
     */
    availableIcons_: {
      type: Array,
      value: function() {
        return [];
      }
    },

    /**
     * The currently selected profile avatar, if any.
     * @private {?AvatarIcon}
     */
    selectedAvatar_: Object,

    /**
     * True if a profile is being created or imported.
     * @private {boolean}
     */
    createInProgress_: {type: Boolean, value: false},

    /**
     * True if the error/warning message is displaying.
     * @private {boolean}
     */
    isMessageVisble_: {type: Boolean, value: false},

    /**
     * The current error/warning message.
     * @private {string}
     */
    message_: {type: String, value: ''},

    /**
     * if true, a desktop shortcut will be created for the new profile.
     * @private {boolean}
     */
    createShortcut_: {type: Boolean, value: true},

    /** @private {!signin.ProfileBrowserProxy} */
    browserProxy_: Object,

    /**
     * True if the profile shortcuts feature is enabled.
     * @private
     */
    isProfileShortcutsEnabled_: {
      type: Boolean,
      value: function() {
        return loadTimeData.getBoolean('profileShortcutsEnabled');
      },
      readOnly: true
    },

    /**
     * True if the force sign in policy is enabled.
     * @private {boolean}
     */
    isForceSigninEnabled_: {
      type: Boolean,
      value: function() {
        return loadTimeData.getBoolean('isForceSigninEnabled');
      },
    },
  },

  /** @override */
  created: function() {
    this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
  },

  /** @override */
  ready: function() {
    this.addWebUIListener(
        'create-profile-success', this.handleSuccess_.bind(this));
    this.addWebUIListener(
        'create-profile-warning', this.handleMessage_.bind(this));
    this.addWebUIListener(
        'create-profile-error', this.handleMessage_.bind(this));
    this.addWebUIListener('profile-icons-received', icons => {
      this.availableIcons_ = icons;
    });
    this.addWebUIListener(
        'profile-defaults-received', this.handleProfileDefaults_.bind(this));

    this.browserProxy_.getAvailableIcons();
  },

  /** @override */
  attached: function() {
    // cr-input's focusable element isn't defined until after it's attached.
    Polymer.RenderStatus.afterNextRender(this, () => this.$.nameInput.focus());
  },

  /**
   * Handles tap events from:
   * - links within dynamic warning/error messages pushed from the browser.
   * @param {!Event} event
   * @private
   */
  onTap_: function(event) {
    const element = Polymer.dom(event).rootTarget;

    if (element.id == 'sign-in-to-chrome') {
      this.browserProxy_.openUrlInLastActiveProfileBrowser(element.href);
      event.preventDefault();
    } else if (element.id == 'reauth') {
      const elementData = /** @type {{userEmail: string}} */ (element.dataset);
      this.browserProxy_.authenticateCustodian(elementData.userEmail);
      this.hideMessage_();
      event.preventDefault();
    }
  },

  /**
   * Handler for when the profile defaults are pushed from the browser.
   * @param {!ProfileInfo} profileInfo Default Info for the new profile.
   * @private
   */
  handleProfileDefaults_: function(profileInfo) {
    this.profileName_ = profileInfo.name;
  },

  /**
   * Handler for the 'Save' button tap event.
   * @param {!Event} event
   * @private
   */
  onSaveTap_: function(event) {
    this.createProfile_();
  },

  /**
   * Creates the new profile.
   * @private
   */
  createProfile_: function() {
    this.hideMessage_();
    this.createInProgress_ = true;
    const createShortcut =
        this.isProfileShortcutsEnabled_ && this.createShortcut_;
    // Select the 1st avatar if none selected.
    const selectedAvatar = this.selectedAvatar_ || this.availableIcons_[0];
    this.browserProxy_.createProfile(
        this.profileName_, selectedAvatar.url, createShortcut);
  },

  /**
   * Handler for the 'Cancel' button tap event.
   * @param {!Event} event
   * @private
   */
  onCancelTap_: function(event) {
    this.fire('change-page', {page: 'user-pods-page'});
  },

  /**
   * Handles profile create/import success message pushed by the browser.
   * @param {!ProfileInfo} profileInfo Details of the created/imported profile.
   * @private
   */
  handleSuccess_: function(profileInfo) {
    this.createInProgress_ = false;
    this.fire('change-page', {page: 'user-pods-page'});
  },

  /**
   * Hides the warning/error message.
   * @private
   */
  hideMessage_: function() {
    this.isMessageVisble_ = false;
  },

  /**
   * Handles warning/error messages when a profile is being created/imported.
   * @param {*} message An HTML warning/error message.
   * @private
   */
  handleMessage_: function(message) {
    this.createInProgress_ = false;
    this.message_ = '' + message;
    this.isMessageVisble_ = true;
  },

  /**
   * Returns a translated message that contains link elements with the 'id'
   * attribute.
   * @param {string} id The ID of the string to translate.
   * @private
   */
  i18nAllowIDAttr_: function(id) {
    const opts = {
      'attrs': {
        'id': function(node, value) {
          return node.tagName == 'A';
        }
      }
    };

    return this.i18nAdvanced(id, opts);
  },

  /**
   * Computed binding determining whether the paper-spinner is active.
   * @param {boolean} createInProgress Is create in progress?
   * @return {boolean}
   * @private
   */
  isSpinnerActive_: function(createInProgress) {
    return createInProgress;
  },

  /**
   * Computed binding determining whether 'Save' button is disabled.
   * @param {boolean} createInProgress Is create in progress?
   * @param {string} profileName Profile Name.
   * @return {boolean}
   * @private
   */
  isSaveDisabled_: function(createInProgress, profileName) {
    /** @type {CrInputElement} */
    const nameInput = this.$.nameInput;
    return createInProgress || !profileName || !nameInput.validate();
  },
});
}());
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="/shared_styles.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">

<dom-module id="error-dialog">
  <template>
    <style include="shared-styles">
      :host {
        color: var(--cr-primary-text-color);
      }

      #message {
        margin-bottom: 52px;
        white-space: pre-wrap;
        word-wrap: break-word;
      }
    </style>
    <cr-dialog id="dialog" show-close-button>
      <div slot="body">
        <div id="message">[[message_]]</div>
      </div>
    </cr-dialog>
  </template>
  <script src="error_dialog.js"></script>
</dom-module>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview 'error-dialog' is a dialog that displays error messages
 * in the user manager.
 */
(function() {
Polymer({
  is: 'error-dialog',

  properties: {
    /**
     * The message shown in the dialog.
     * @private {string}
     */
    message_: {type: String, value: ''}
  },

  /**
   * Displays the dialog populated with the given message.
   * @param {string} message Error message to show.
   */
  show: function(message) {
    this.message_ = message;
    this.$.dialog.showModal();
  }
});
})();
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
<script src="profile_browser_proxy.js"></script>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Helper object and related behavior that encapsulate messaging
 * between JS and C++ for creating/importing profiles in the user-manager page.
 */

/**
 * @typedef {{name: string,
 *            filePath: string}}
 */
let ProfileInfo;

cr.define('signin', function() {
  /** @interface */
  class ProfileBrowserProxy {
    /**
     * Gets the available profile icons to choose from.
     */
    getAvailableIcons() {}

    /**
     * Launches the guest user.
     */
    launchGuestUser() {}

    /**
     * Creates a profile.
     * @param {string} profileName Name of the new profile.
     * @param {string} profileIconUrl URL of the selected icon of the new
     *     profile.
     * @param {boolean} createShortcut if true a desktop shortcut will be
     *     created.
     */
    createProfile(profileName, profileIconUrl, createShortcut) {}

    /**
     * Initializes the UserManager
     * @param {string} locationHash
     */
    initializeUserManager(locationHash) {}

    /**
     * Launches the user with the given |profilePath|
     * @param {string} profilePath Profile Path of the user.
     */
    launchUser(profilePath) {}

    /**
     * Opens the given url in a new tab in the browser instance of the last
     * active profile. Hyperlinks don't work in the user manager since its
     * browser instance does not support tabs.
     * @param {string} url
     */
    openUrlInLastActiveProfileBrowser(url) {}

    /**
     * Switches to the profile with the given path.
     * @param {string} profilePath Path to the profile to switch to.
     */
    switchToProfile(profilePath) {}

    /**
     * @return {!Promise<boolean>} Whether all (non-supervised and non-child)
     *     profiles are locked.
     */
    areAllProfilesLocked() {}

    /**
     * Authenticates the custodian profile with the given email address.
     * @param {string} emailAddress Email address of the custodian profile.
     */
    authenticateCustodian(emailAddress) {}
  }

  /** @implements {signin.ProfileBrowserProxy} */
  class ProfileBrowserProxyImpl {
    /** @override */
    getAvailableIcons() {
      chrome.send('requestDefaultProfileIcons');
    }

    /** @override */
    launchGuestUser() {
      chrome.send('launchGuest');
    }

    /** @override */
    createProfile(profileName, profileIconUrl, createShortcut) {
      chrome.send(
          'createProfile', [profileName, profileIconUrl, createShortcut]);
    }

    /** @override */
    initializeUserManager(locationHash) {
      chrome.send('userManagerInitialize', [locationHash]);
    }

    /** @override */
    launchUser(profilePath) {
      chrome.send('launchUser', [profilePath]);
    }

    /** @override */
    openUrlInLastActiveProfileBrowser(url) {
      chrome.send('openUrlInLastActiveProfileBrowser', [url]);
    }

    /** @override */
    switchToProfile(profilePath) {
      chrome.send('switchToProfile', [profilePath]);
    }

    /** @override */
    areAllProfilesLocked() {
      return cr.sendWithPromise('areAllProfilesLocked');
    }

    /** @override */
    authenticateCustodian(emailAddress) {
      chrome.send('authenticateCustodian', [emailAddress]);
    }
  }

  // The singleton instance_ is replaced with a test version of this wrapper
  // during testing.
  cr.addSingletonGetter(ProfileBrowserProxyImpl);

  return {
    ProfileBrowserProxy: ProfileBrowserProxy,
    ProfileBrowserProxyImpl: ProfileBrowserProxyImpl,
  };
});
<!doctype html>
<html build="$i18n{buildType}"
    dir="$i18n{textdirection}"
    lang="$i18n{language}"
    screen="$i18n{screenType}">
<head>
  <meta charset="utf-8">
  <meta name="google" value="notranslate">
  <title>$i18n{title}</title>

  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

.account-picker.flying-pods #account-picker {
  transition: width 180ms ease, height 180ms ease;
}

#bubble {
  z-index: 1;
}

#signin-banner-container1 {
  bottom: 100%;
  margin-bottom: 10px;
  position: absolute;
  width: 100%;
}

html[screen=login] #signin-banner-container1 {
  margin-bottom: 6px;
}

#signin-banner-container2 {
  display: inline-block;
  position: relative;
  right: -50%;
}

html[dir=rtl] #signin-banner-container2 {
  left: -50%;
  right: auto;
}

#signin-banner {
  background-color: rgba(0, 0, 0, 0.75);
  border-radius: 4px;
  color: whitesmoke;
  display: none;
  left: -50%;
  max-width: 722px;
  padding: 20px;
  position: relative;
  text-align: center;
  width: max-content;
}

html[dir=rtl] #signin-banner {
  left: auto;
  right: -50%;
}

html[screen=user-adding] #signin-banner {
  display: inline-block;
}

html[screen=login] #signin-banner {
  padding: 20px 24px;
}

html[screen=login] #signin-banner,
html[screen=lock] #signin-banner {
  display: inline-block;
  opacity: 0;
  visibility: hidden;
}

html[screen=login] #signin-banner.message-set,
html[screen=lock] #signin-banner.message-set {
  opacity: 1;
  transition: opacity 1s;
  visibility: visible;
}
</style>
  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * This is the stylesheet used by user pods row of account picker UI.
 */

podrow {
  /* Temporarily disabled because animation interferes with updating screen's
   size. */
  height: 100%;
  overflow: visible;
  position: absolute;
  width: 100%;
}

/* Hide the pod row while images are loading. */
podrow.images-loading {
  visibility: hidden;
}

pin-keyboard {
  display: block;
}

.pod {
  -webkit-tap-highlight-color: transparent;
  background-color: white;
  border-radius: 2px;
  box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2),
              0 2px 6px rgba(0, 0, 0, 0.15),
              0 3px 0 rgba(0, 0, 0, 0.08);
  cursor: pointer;
  height: 213px;
  outline: none;
  position: absolute;
  top: 0;
  transform: scale3d(0.9, 0.9, 0.9);
  width: 180px;
  z-index: 0;
}

.account-picker.flying-pods .pod {
  transition: all 180ms;
}

.pod.pin-enabled {
  height: 417px;
  top: -87px !important;
}

.pod .pin-container {
  height: 204px;
  position: absolute;
  top: 170px;
}

.pod.faded {
  opacity: .75;
}

podrow[ncolumns='6'] .pod {
  transform: scale3d(0.8, 0.8, 0.8);
}

.pod.focused {
  /* Focused pod has the same size no matter how many pods. */
  cursor: default;
  transform: scale3d(1, 1, 1) !important;
  z-index: 1;
}

.pod.focused[auth-type='userClick'] {
  cursor: pointer;
}

.user-image-pane {
  background-color: white;
  height: 160px;
  left: 10px;
  position: absolute;
  top: 10px;
  transition: height 180ms ease-in-out,
              left 180ms ease-in-out,
              right 180ms ease-in-out,
              top 180ms ease-in-out,
              width 180ms ease-in-out;
  width: 160px;
  z-index: 3;
}

html[dir=rtl] .user-image-pane {
  left: auto;
  right: 10px;
}

.user-image-container {
  align-items: center;
  display: flex;
  height: 100%;
  justify-content: center;
  width: 100%;
}

.pod .user-image {
  flex: none;
}

.pod.focused .user-image {
  display: none;
}

.pod .animated-image {
  display: none;
}

.pod.focused .animated-image {
  display: block;
}

/* TODO(noms): Refactor this out into a CrOS-specific file and simplify the
 style rule once it is included on CrOS only. crbug.com/397638 */
html:not([screen=login-add-user]) .pod .user-image {
  max-height: 160px;
  max-width: 160px;
  opacity: 0.7;
  position: absolute;
}

html:not([screen=login-add-user]) .pod.focused .user-image {
  opacity: 1;
}

.pod.multiprofiles-policy-applied .user-image {
  -webkit-filter: grayscale(100%);
}

.signed-in-indicator {
  display: none;
}

.pod.signed-in .signed-in-indicator {
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
  display: block;
  font-size: small;
  position: absolute;
  text-align: center;
  top: 0;
  width: 100%;
}

.main-pane {
  left: 10px;
  position: absolute;
  top: 10px;
  z-index: 2;
}

html[dir=rtl] .main-pane {
  left: auto;
  right: 10px;
}

.name-container,
.pod.focused:not(.multiprofiles-policy-applied) .auth-container {
  background-color: white;
  display: flex;
  position: absolute;
  top: 160px;
/* On chromeos we extend the width to cover the padding on the user pods. This
 is so the submit button on chromeos can extend onto the padding as shown on
 mocks. */

  width: 160px;


}

.auth-container .submit-button[disabled] {
  color: #000;
  opacity: 0.26;
}

.auth-container .submit-button {
  box-sizing: border-box;
  color: var(--google-blue-500);
  height: 43px;
  min-height: 43px;
  min-width: 43px;
  padding: 11.5px 10px;
  position: relative;
  width: 43px;
}

.auth-container .submit-button.error-shown {
  color: #CD2A00;
}

.name-container {
  transition: transform 180ms;
}

.pod.focused .name-container {
  display: none;
}

.pod.focused.multiprofiles-policy-applied .name-container {
  display: flex;
}

.name {
  color: #565656;
  /* This should be 15.6px - the equivalent of 14px at 90% scale. */
  flex: auto;
  font-size: 16px;
  margin-top: 12px;
  outline: none;
  overflow: hidden;
  padding: 0 6px;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.learn-more-container,
.auth-container,
.password-entry-container,
.reauth-hint-container {
  display: none;
}

.pod[is-active-directory] .reauth-warning {
  display: none;
}

.pod[auth-type='offlinePassword'].focused .password-entry-container,
.pod[auth-type='forceOfflinePassword'].focused .password-entry-container {
  display: flex;
  flex: auto;
}

.password-container {
  flex: auto;
}

.pod input[type='password'] {
  background-color: white;
  border: none;
  padding: 4px 6px;
  position: relative;
  top: 6px;
  width: 100%;
}

.capslock-hint-container {
  display: none;
}



.capslock-hint {
  -webkit-margin-end: 6px;
  -webkit-margin-start: -2px;
  margin: auto;
  position: relative;
  top: 15px;
}

.password-label,
.signin-transition-container {
  display: none;
}

.pod[auth-type='userClick']:not(.signing-in) .password-label,
.pod[auth-type='userClick'].signing-in .signin-transition-container {
  color: grey;
  display: block;
  flex: auto;
  margin-top: 11px;
  outline: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.custom-icon {
  -webkit-margin-end: 0;
  -webkit-margin-start: auto;
  background-position: center;
  background-repeat: no-repeat;
  flex: none;
  height: 27px;
  margin: 8px 0;
  width: 27px;
}

.custom-icon.faded {
  transition: opacity 200ms ease-in-out, visibility 200ms ease-in-out;
}

.custom-icon-hardlocked {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_HARDLOCKED);
}

.custom-icon-hardlocked.icon-with-tooltip:hover {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_HARDLOCKED_HOVER);
}

.custom-icon-hardlocked.interactive-custom-icon:active {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_HARDLOCKED_PRESSED);
}

.custom-icon-locked {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_LOCKED);
}

.custom-icon-locked.icon-with-tooltip:hover {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_HOVER);
}

.custom-icon-locked.interactive-custom-icon:active {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_PRESSED);
}

.custom-icon-locked-to-be-activated {
  background-image:
      url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED);
}

.custom-icon-locked-to-be-activated.icon-with-tooltip:hover {
  background-image:
      url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED_HOVER);
}

.custom-icon-locked-to-be-activated.interactive-custom-icon:active {
  background-image:
      url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED_PRESSED);
}

.custom-icon-locked-with-proximity-hint {
  background-image:
      url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT);
}

.custom-icon-locked-with-proximity-hint.icon-with-tooltip:hover {
  background-image:
      url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT_HOVER);
}

.custom-icon-locked-with-proximity-hint.interactive-custom-icon:active {
  background-image:
      url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT_PRESSED);
}

.custom-icon-unlocked {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_UNLOCKED);
}

.custom-icon-unlocked.icon-with-tooltip:hover {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_UNLOCKED_HOVER);
}

.custom-icon-unlocked.interactive-custom-icon:active {
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_UNLOCKED_PRESSED);
}

/**
 * Preloads resources for custom icon. Without this, the resources will be
 * loaded when CSS properties using them are first applied, which has visible
 * delay and may cause a short white flash when the icon background changes.
 */
.custom-icon::after {
  content:
    url(chrome://theme/IDR_EASY_UNLOCK_HARDLOCKED)
    url(chrome://theme/IDR_EASY_UNLOCK_HARDLOCKED_HOVER)
    url(chrome://theme/IDR_EASY_UNLOCK_HARDLOCKED_PRESSED)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_HOVER)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_PRESSED)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED_HOVER)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_TO_BE_ACTIVATED_PRESSED)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT_HOVER)
    url(chrome://theme/IDR_EASY_UNLOCK_LOCKED_WITH_PROXIMITY_HINT_PRESSED)
    url(chrome://theme/IDR_EASY_UNLOCK_UNLOCKED)
    url(chrome://theme/IDR_EASY_UNLOCK_UNLOCKED_HOVER)
    url(chrome://theme/IDR_EASY_UNLOCK_UNLOCKED_PRESSED);
  display: none;
}

.custom-icon-spinner {
  animation: easy-unlock-spinner-animation 2s steps(45) infinite;
  background-image: url(chrome://theme/IDR_EASY_UNLOCK_SPINNER);
}

@keyframes easy-unlock-spinner-animation {
  from { background-position: 0 }
  to { background-position: -1215px }
}

.interactive-custom-icon {
  cursor: pointer;
}

.pod[auth-type='onlineSignIn'] .custom-icon-container {
  display: none;
}

.fingerprint-icon-container,
.custom-icon-container {
  display: flex;
  flex: none;
  flex-direction: column;
  height: 43px;
  width: 27px;
}

.launch-app-button-container {
  display: block;
  flex: auto;
  text-align: center;
}

.launch-app-button {
  display: inline;
  margin-top: 6px !important;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pod[auth-type='onlineSignIn'] .reauth-hint-container {
  display: flex;
  justify-content: center;
  margin-top: 8px;
  width: 100%;
}

.reauth-hint-container .reauth-warning {
  -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMiA0Mmg0NEwyNCA0IDIgNDJ6bTI0LTZoLTR2LTRoNHY0em0wLThoLTR2LThoNHY4eiIvPgo8L3N2Zz4K);
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 20px;
  background-color: #f4b400;
  height: 24px;
  width: 24px;
}

.reauth-hint-container .reauth-name-hint {
  align-self: center;
  color: #565656;
  font-size: 16px;
  outline: none;
  overflow: hidden;
  padding: 0 6px;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.action-box-area,
.user-type-icon-area {
  background-color: white;
  border-radius: 2px;
  position: absolute;
  top: 0;
}

.action-box-area {
  opacity: 0;
  outline: none;
  right: 0;
  transition: opacity 100ms;
  z-index: 4;
}

html[dir=rtl] .action-box-area {
  left: 0;
  right: auto;
}

.action-box-area:focus,
.action-box-area.hovered,
.action-box-area.active,
.action-box-area.forced {
  opacity: 1;
}

.action-box-button {
  background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_NORMAL);
  height: 13px;
  margin: 5px;
  width: 13px;
}

.action-box-button:hover {
  background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_HOVER);
}

.action-box-area.active .action-box-button {
  background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_PRESSED);
}

.action-box-area .action-box-icon {
  /* overriden in chrome/browser/resources/md_user_manager/user_manager.css */
  display: none;
}

.user-image-gradient-area {
  /* overriden in chrome/browser/resources/md_user_manager/user_manager.css */
  display: none;
}

.user-type-icon-area {
  left: 0;
  z-index: 5;
}

html[dir=rtl] .user-type-icon-area {
  left: auto;
  right: 0;
}

.user-type-icon-image {
  height: 16px;
  margin: 5px;
  width: 16px;
}

.user-type-icon-area.legacySupervised .user-type-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMzMgMjRjMi43NiAwIDQuOTgtMi4yNCA0Ljk4LTVzLTIuMjItNS00Ljk4LTVjLTIuNzYgMC01IDIuMjQtNSA1czIuMjQgNSA1IDV6bS0xNS0yYzMuMzEgMCA1Ljk4LTIuNjkgNS45OC02cy0yLjY3LTYtNS45OC02Yy0zLjMxIDAtNiAyLjY5LTYgNnMyLjY5IDYgNiA2em0xNSA2Yy0zLjY3IDAtMTEgMS44NC0xMSA1LjVWMzhoMjJ2LTQuNWMwLTMuNjYtNy4zMy01LjUtMTEtNS41em0tMTUtMmMtNC42NyAwLTE0IDIuMzQtMTQgN3Y1aDE0di00LjVjMC0xLjcuNjctNC42NyA0Ljc0LTYuOTRDMjEgMjYuMTkgMTkuMzEgMjYgMTggMjZ6Ii8+Cjwvc3ZnPgo=);
  background-size: 18px;
}

.user-type-icon-area.child .user-type-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMjQgNGMzLjMxIDAgNiAyLjY5IDYgNnMtMi42OSA2LTYgNi02LTIuNjktNi02IDIuNjktNiA2LTZ6Ii8+CiAgICA8cGF0aCBmaWxsPSJub25lIiBkPSJNMCAwaDQ4djQ4SDBWMHoiLz4KICAgIDxjaXJjbGUgZmlsbD0ibm9uZSIgY3g9IjI0IiBjeT0iMjYiIHI9IjQiLz4KICAgIDxwYXRoIGQ9Ik0yNCAxOGMtNi4xNiAwLTEzIDMuMTItMTMgNy4yM3YxMS41NGMwIDIuMzIgMi4xOSA0LjMzIDUuMiA1LjYzIDIuMzIgMSA1LjEyIDEuNTkgNy44IDEuNTkuNjYgMCAxLjMzLS4wNiAyLS4xNHYtNS4yYy0uNjcuMDgtMS4zNC4xNC0yIC4xNC0yLjYzIDAtNS4zOS0uNTctNy42OC0xLjU1LjY3LTIuMTIgNC4zNC0zLjY1IDcuNjgtMy42NS44NiAwIDEuNzUuMTEgMi42LjI5IDIuNzkuNjIgNS4yIDIuMTUgNS4yIDQuMDR2NC40N2MzLjAxLTEuMzEgNS4yLTMuMzEgNS4yLTUuNjNWMjUuMjNDMzcgMjEuMTIgMzAuMTYgMTggMjQgMTh6bTAgMTJjLTIuMjEgMC00LTEuNzktNC00czEuNzktNCA0LTQgNCAxLjc5IDQgNC0xLjc5IDQtNCA0eiIvPgo8L3N2Zz4K);
  background-size: 18px;
}

.user-type-icon-area.policy .user-type-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgMTRWNkg0djM2aDQwVjE0SDI0ek0xMiAzOEg4di00aDR2NHptMC04SDh2LTRoNHY0em0wLThIOHYtNGg0djR6bTAtOEg4di00aDR2NHptOCAyNGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTIwIDI0SDI0di00aDR2LTRoLTR2LTRoNHYtNGgtNHYtNGgxNnYyMHptLTQtMTZoLTR2NGg0di00em0wIDhoLTR2NGg0di00eiIvPgo8L3N2Zz4K);
  background-size: 18px;
}

.user-type-icon-area.app .user-type-icon-image {
  background-image: url(chrome://theme/IDR_KIOSK_APP_USER_POD_ICON);
}

.fingerprint-icon-container.hidden {
  display: none;
}

.fingerprint-icon-container.default .fingerprint-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjciIGhlaWdodD0iMjciIHZpZXdCb3g9IjAgMCAyNyAyNyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+ZmluZ2VycHJpbnRfZ3JleV8xeDwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBvcGFjaXR5PSIuMzQiPjxwYXRoIGQ9Ik0yMC4wMzYgNS4wM2MtLjA5IDAtLjE3NC0uMDI0LS4yNi0uMDYzLTIuMTUzLTEuMTE0LTQuMDI2LTEuNTkyLTYuMjY1LTEuNTkyLTIuMjMyIDAtNC4zMzYuNTM0LTYuMjY1IDEuNTg2LS4yNzYuMTQ3LS42MTMuMDUyLS43NjUtLjIyNC0uMTQ2LS4yNzUtLjA1LS42MTMuMjI1LS43NjUgMi4wOTgtMS4xNCA0LjM4Ny0xLjcyIDYuODA2LTEuNzIgMi4zOTggMCA0LjQ5LjUzIDYuNzg1IDEuNzE2LjI3Ni4xNC4zODIuNDgzLjI0Mi43Ni0uMS4xOS0uMjk4LjMwMy0uNS4zMDN6TTMuOTM3IDEwLjkzNGMtLjExMiAwLS4yMjQtLjAzNC0uMzI2LS4xLS4yNTItLjE4LS4zMTQtLjUzLS4xMzQtLjc4M0M0LjU5IDguNDc3IDYuMDEzIDcuMjQgNy43IDYuMzY4YzMuNTQtMS44MyA4LjA2LTEuODM0IDExLjYwNS0uMDEyIDEuNjgyLjg2NyAzLjEgMi4wOTMgNC4yMiAzLjY1Ni4xOC4yNTQuMTIzLjYwMi0uMTMuNzgyLS4yNTQuMTgtLjYwOC4xMjQtLjc4OC0uMTMtMS4wMTMtMS40MTYtMi4yOTUtMi41My0zLjgxNC0zLjMwNi0zLjIzLTEuNjYtNy4zNTItMS42NTQtMTAuNTc1LjAxLTEuNTI0Ljc4OC0yLjgxMiAxLjkwOC0zLjgyIDMuMzM2LS4xMTIuMTUyLS4yODYuMjMtLjQ2LjIzem03LjAzNyAxMy41NzNjLS4xNDYgMC0uMjg3LS4wNTYtLjQtLjE3LS45NzItLjk4My0xLjUtMS42MDctMi4yNi0yLjk2My0uNzc3LTEuMzg0LTEuMTg3LTMuMDc3LTEuMTg3LTQuODg4IDAtMy4zNCAyLjg1Ny02LjA2NCA2LjM3My02LjA2NHM2LjM3MyAyLjcxNyA2LjM3MyA2LjA2NGMwIC4zMS0uMjUzLjU2Mi0uNTYyLjU2Mi0uMzEgMC0uNTYyLS4yNTQtLjU2Mi0uNTYzIDAtMi43MjMtMi4zNS00Ljk0LTUuMjQ4LTQuOTQtMi44OSAwLTUuMjQ4IDIuMjE3LTUuMjQ4IDQuOTQgMCAxLjYyLjM2IDMuMTE2IDEuMDQgNC4zMzcuNzI2IDEuMjkzIDEuMjEgMS44NSAyLjA3NiAyLjcyMi4yMi4yMi4yMi41OC0uMDA1Ljc5My0uMTAyLjExNy0uMjQ4LjE2OC0uMzkuMTY4em04LjA2LTIuMDhjLTEuMzM4IDAtMi41MTMtLjM0LTMuNDg2LS45OTctMS42Ny0xLjEzNS0yLjY3Mi0yLjk4LTIuNjcyLTQuOTM4IDAtLjMxLjI1My0uNTYyLjU2Mi0uNTYyLjMxIDAgLjU2My4yNTMuNTYzLjU2MyAwIDEuNTguODE2IDMuMDc2IDIuMTgzIDQuMDA1Ljc5My41NCAxLjcyNy44MDQgMi44NTIuODA0LjI3IDAgLjcyNi0uMDI4IDEuMTc2LS4xMDcuMzA0LS4wNTYuNTk3LjE1Mi42NTMuNDU2LjA1Ni4zMDQtLjE1Mi41OTctLjQ1Ni42NTMtLjY1OC4xMTgtMS4yMTUuMTI0LTEuMzcyLjEyNHpNMTYuNzcgMjQuNzVjLS4wNSAwLS4xLS4wMDYtLjE0Ni0uMDIzLTEuNzk0LS40OS0yLjk2NC0xLjE1My00LjE4LTIuMzYyLTEuNTctMS41NjQtMi40MzUtMy42NS0yLjQzNS01Ljg3MiAwLTEuODMgMS41NTItMy4zMTQgMy40NjUtMy4zMTQgMS45MTIgMCAzLjQ2NSAxLjQ4NCAzLjQ2NSAzLjMxMyAwIDEuMjAzIDEuMDUyIDIuMTg4IDIuMzQgMi4xODggMS4yODggMCAyLjM0LS45NzggMi4zNC0yLjE4OCAwLTQuMjQtMy42NTYtNy42OS04LjE1LTcuNjktMy4yIDAtNi4xMiAxLjc4LTcuNDM3IDQuNTM1LS40NC45MS0uNjU4IDEuOTc0LS42NTggMy4xNTUgMCAuODc4LjA4IDIuMjYyLjc0OCA0LjA1Ni4xMDcuMjkzLS4wNC42MTMtLjMzMi43MjYtLjI5Mi4xMDctLjYxMy0uMDQtLjcyNi0uMzMyLS41NS0xLjQ4LS44Mi0yLjkzLS44Mi00LjQ1IDAtMS4zNS4yNTgtMi41NzYuNzctMy42NCAxLjUwMi0zLjEzOCA0LjgyLTUuMTY4IDguNDUtNS4xNjggNS4xMTIgMCA5LjI3NCAzLjk1NCA5LjI3NCA4LjgxNCAwIDEuODI4LTEuNTU4IDMuMzEzLTMuNDY1IDMuMzEzLTEuOTA2IDAtMy40NjQtMS40ODQtMy40NjQtMy4zMTIgMC0xLjIwNC0xLjA1Mi0yLjE4OC0yLjM0LTIuMTg4LTEuMjg4IDAtMi4zNC45OC0yLjM0IDIuMTg4IDAgMS45MTguNzQ4IDMuNzI0IDIuMTA0IDUuMDc0IDEuMDYzIDEuMDU3IDIuMDk4IDEuNjQyIDMuNjg0IDIuMDc2LjI5OC4wODQuNDc4LjM5My4zOTQuNjktLjA2Ny4yNS0uMjkyLjQxMi0uNTQuNDEyeiIgZmlsbD0iIzAwMCIvPjxwYXRoIGQ9Ik0wIDBoMjd2MjdIMCIvPjwvZz48L3N2Zz4=);
}

.fingerprint-icon-container.default:hover .fingerprint-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjciIGhlaWdodD0iMjciIHZpZXdCb3g9IjAgMCAyNyAyNyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+ZmluZ2VycHJpbnRfYmx1ZV8xeDwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNMjAuMDM2IDUuMDNjLS4wOSAwLS4xNzQtLjAyNC0uMjYtLjA2My0yLjE1My0xLjExNC00LjAyNi0xLjU5Mi02LjI2NS0xLjU5Mi0yLjIzMiAwLTQuMzM2LjUzNC02LjI2NSAxLjU4Ni0uMjc2LjE0Ny0uNjEzLjA1Mi0uNzY1LS4yMjQtLjE0Ni0uMjc1LS4wNS0uNjEzLjIyNS0uNzY1IDIuMDk4LTEuMTQgNC4zODctMS43MiA2LjgwNi0xLjcyIDIuMzk4IDAgNC40OS41MyA2Ljc4NSAxLjcxNi4yNzYuMTQuMzgyLjQ4My4yNDIuNzYtLjEuMTktLjI5OC4zMDMtLjUuMzAzek0zLjkzNyAxMC45MzRjLS4xMTIgMC0uMjI0LS4wMzQtLjMyNi0uMS0uMjUyLS4xOC0uMzE0LS41My0uMTM0LS43ODNDNC41OSA4LjQ3NyA2LjAxMyA3LjI0IDcuNyA2LjM2OGMzLjU0LTEuODMgOC4wNi0xLjgzNCAxMS42MDUtLjAxMiAxLjY4Mi44NjcgMy4xIDIuMDkzIDQuMjIgMy42NTYuMTguMjU0LjEyMy42MDItLjEzLjc4Mi0uMjU0LjE4LS42MDguMTI0LS43ODgtLjEzLTEuMDEzLTEuNDE2LTIuMjk1LTIuNTMtMy44MTQtMy4zMDYtMy4yMy0xLjY2LTcuMzUyLTEuNjU0LTEwLjU3NS4wMS0xLjUyNC43ODgtMi44MTIgMS45MDgtMy44MiAzLjMzNi0uMTEyLjE1Mi0uMjg2LjIzLS40Ni4yM3ptNy4wMzcgMTMuNTczYy0uMTQ2IDAtLjI4Ny0uMDU2LS40LS4xNy0uOTcyLS45ODMtMS41LTEuNjA3LTIuMjYtMi45NjMtLjc3Ny0xLjM4NC0xLjE4Ny0zLjA3Ny0xLjE4Ny00Ljg4OCAwLTMuMzQgMi44NTctNi4wNjQgNi4zNzMtNi4wNjRzNi4zNzMgMi43MTcgNi4zNzMgNi4wNjRjMCAuMzEtLjI1My41NjItLjU2Mi41NjItLjMxIDAtLjU2Mi0uMjU0LS41NjItLjU2MyAwLTIuNzIzLTIuMzUtNC45NC01LjI0OC00Ljk0LTIuODkgMC01LjI0OCAyLjIxNy01LjI0OCA0Ljk0IDAgMS42Mi4zNiAzLjExNiAxLjA0IDQuMzM3LjcyNiAxLjI5MyAxLjIxIDEuODUgMi4wNzYgMi43MjIuMjIuMjIuMjIuNTgtLjAwNS43OTMtLjEwMi4xMTctLjI0OC4xNjgtLjM5LjE2OHptOC4wNi0yLjA4Yy0xLjMzOCAwLTIuNTEzLS4zNC0zLjQ4Ni0uOTk3LTEuNjctMS4xMzUtMi42NzItMi45OC0yLjY3Mi00LjkzOCAwLS4zMS4yNTMtLjU2Mi41NjItLjU2Mi4zMSAwIC41NjMuMjUzLjU2My41NjMgMCAxLjU4LjgxNiAzLjA3NiAyLjE4MyA0LjAwNS43OTMuNTQgMS43MjcuODA0IDIuODUyLjgwNC4yNyAwIC43MjYtLjAyOCAxLjE3Ni0uMTA3LjMwNC0uMDU2LjU5Ny4xNTIuNjUzLjQ1Ni4wNTYuMzA0LS4xNTIuNTk3LS40NTYuNjUzLS42NTguMTE4LTEuMjE1LjEyNC0xLjM3Mi4xMjR6TTE2Ljc3IDI0Ljc1Yy0uMDUgMC0uMS0uMDA2LS4xNDYtLjAyMy0xLjc5NC0uNDktMi45NjQtMS4xNTMtNC4xOC0yLjM2Mi0xLjU3LTEuNTY0LTIuNDM1LTMuNjUtMi40MzUtNS44NzIgMC0xLjgzIDEuNTUyLTMuMzE0IDMuNDY1LTMuMzE0IDEuOTEyIDAgMy40NjUgMS40ODQgMy40NjUgMy4zMTMgMCAxLjIwMyAxLjA1MiAyLjE4OCAyLjM0IDIuMTg4IDEuMjg4IDAgMi4zNC0uOTc4IDIuMzQtMi4xODggMC00LjI0LTMuNjU2LTcuNjktOC4xNS03LjY5LTMuMiAwLTYuMTIgMS43OC03LjQzNyA0LjUzNS0uNDQuOTEtLjY1OCAxLjk3NC0uNjU4IDMuMTU1IDAgLjg3OC4wOCAyLjI2Mi43NDggNC4wNTYuMTA3LjI5My0uMDQuNjEzLS4zMzIuNzI2LS4yOTIuMTA3LS42MTMtLjA0LS43MjYtLjMzMi0uNTUtMS40OC0uODItMi45My0uODItNC40NSAwLTEuMzUuMjU4LTIuNTc2Ljc3LTMuNjQgMS41MDItMy4xMzggNC44Mi01LjE2OCA4LjQ1LTUuMTY4IDUuMTEyIDAgOS4yNzQgMy45NTQgOS4yNzQgOC44MTQgMCAxLjgyOC0xLjU1OCAzLjMxMy0zLjQ2NSAzLjMxMy0xLjkwNiAwLTMuNDY0LTEuNDg0LTMuNDY0LTMuMzEyIDAtMS4yMDQtMS4wNTItMi4xODgtMi4zNC0yLjE4OC0xLjI4OCAwLTIuMzQuOTgtMi4zNCAyLjE4OCAwIDEuOTE4Ljc0OCAzLjcyNCAyLjEwNCA1LjA3NCAxLjA2MyAxLjA1NyAyLjA5OCAxLjY0MiAzLjY4NCAyLjA3Ni4yOTguMDg0LjQ3OC4zOTMuMzk0LjY5LS4wNjcuMjUtLjI5Mi40MTItLjU0LjQxMnoiIGZpbGw9IiM0Mjg1RjQiLz48cGF0aCBkPSJNMCAwaDI3djI3SDAiLz48L2c+PC9zdmc+);
}

.fingerprint-icon-container.signin .fingerprint-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjciIGhlaWdodD0iMjciIHZpZXdCb3g9IjAgMCAyNyAyNyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+ZmluZ2VycHJpbnRfYmx1ZV8xeDwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNMjAuMDM2IDUuMDNjLS4wOSAwLS4xNzQtLjAyNC0uMjYtLjA2My0yLjE1My0xLjExNC00LjAyNi0xLjU5Mi02LjI2NS0xLjU5Mi0yLjIzMiAwLTQuMzM2LjUzNC02LjI2NSAxLjU4Ni0uMjc2LjE0Ny0uNjEzLjA1Mi0uNzY1LS4yMjQtLjE0Ni0uMjc1LS4wNS0uNjEzLjIyNS0uNzY1IDIuMDk4LTEuMTQgNC4zODctMS43MiA2LjgwNi0xLjcyIDIuMzk4IDAgNC40OS41MyA2Ljc4NSAxLjcxNi4yNzYuMTQuMzgyLjQ4My4yNDIuNzYtLjEuMTktLjI5OC4zMDMtLjUuMzAzek0zLjkzNyAxMC45MzRjLS4xMTIgMC0uMjI0LS4wMzQtLjMyNi0uMS0uMjUyLS4xOC0uMzE0LS41My0uMTM0LS43ODNDNC41OSA4LjQ3NyA2LjAxMyA3LjI0IDcuNyA2LjM2OGMzLjU0LTEuODMgOC4wNi0xLjgzNCAxMS42MDUtLjAxMiAxLjY4Mi44NjcgMy4xIDIuMDkzIDQuMjIgMy42NTYuMTguMjU0LjEyMy42MDItLjEzLjc4Mi0uMjU0LjE4LS42MDguMTI0LS43ODgtLjEzLTEuMDEzLTEuNDE2LTIuMjk1LTIuNTMtMy44MTQtMy4zMDYtMy4yMy0xLjY2LTcuMzUyLTEuNjU0LTEwLjU3NS4wMS0xLjUyNC43ODgtMi44MTIgMS45MDgtMy44MiAzLjMzNi0uMTEyLjE1Mi0uMjg2LjIzLS40Ni4yM3ptNy4wMzcgMTMuNTczYy0uMTQ2IDAtLjI4Ny0uMDU2LS40LS4xNy0uOTcyLS45ODMtMS41LTEuNjA3LTIuMjYtMi45NjMtLjc3Ny0xLjM4NC0xLjE4Ny0zLjA3Ny0xLjE4Ny00Ljg4OCAwLTMuMzQgMi44NTctNi4wNjQgNi4zNzMtNi4wNjRzNi4zNzMgMi43MTcgNi4zNzMgNi4wNjRjMCAuMzEtLjI1My41NjItLjU2Mi41NjItLjMxIDAtLjU2Mi0uMjU0LS41NjItLjU2MyAwLTIuNzIzLTIuMzUtNC45NC01LjI0OC00Ljk0LTIuODkgMC01LjI0OCAyLjIxNy01LjI0OCA0Ljk0IDAgMS42Mi4zNiAzLjExNiAxLjA0IDQuMzM3LjcyNiAxLjI5MyAxLjIxIDEuODUgMi4wNzYgMi43MjIuMjIuMjIuMjIuNTgtLjAwNS43OTMtLjEwMi4xMTctLjI0OC4xNjgtLjM5LjE2OHptOC4wNi0yLjA4Yy0xLjMzOCAwLTIuNTEzLS4zNC0zLjQ4Ni0uOTk3LTEuNjctMS4xMzUtMi42NzItMi45OC0yLjY3Mi00LjkzOCAwLS4zMS4yNTMtLjU2Mi41NjItLjU2Mi4zMSAwIC41NjMuMjUzLjU2My41NjMgMCAxLjU4LjgxNiAzLjA3NiAyLjE4MyA0LjAwNS43OTMuNTQgMS43MjcuODA0IDIuODUyLjgwNC4yNyAwIC43MjYtLjAyOCAxLjE3Ni0uMTA3LjMwNC0uMDU2LjU5Ny4xNTIuNjUzLjQ1Ni4wNTYuMzA0LS4xNTIuNTk3LS40NTYuNjUzLS42NTguMTE4LTEuMjE1LjEyNC0xLjM3Mi4xMjR6TTE2Ljc3IDI0Ljc1Yy0uMDUgMC0uMS0uMDA2LS4xNDYtLjAyMy0xLjc5NC0uNDktMi45NjQtMS4xNTMtNC4xOC0yLjM2Mi0xLjU3LTEuNTY0LTIuNDM1LTMuNjUtMi40MzUtNS44NzIgMC0xLjgzIDEuNTUyLTMuMzE0IDMuNDY1LTMuMzE0IDEuOTEyIDAgMy40NjUgMS40ODQgMy40NjUgMy4zMTMgMCAxLjIwMyAxLjA1MiAyLjE4OCAyLjM0IDIuMTg4IDEuMjg4IDAgMi4zNC0uOTc4IDIuMzQtMi4xODggMC00LjI0LTMuNjU2LTcuNjktOC4xNS03LjY5LTMuMiAwLTYuMTIgMS43OC03LjQzNyA0LjUzNS0uNDQuOTEtLjY1OCAxLjk3NC0uNjU4IDMuMTU1IDAgLjg3OC4wOCAyLjI2Mi43NDggNC4wNTYuMTA3LjI5My0uMDQuNjEzLS4zMzIuNzI2LS4yOTIuMTA3LS42MTMtLjA0LS43MjYtLjMzMi0uNTUtMS40OC0uODItMi45My0uODItNC40NSAwLTEuMzUuMjU4LTIuNTc2Ljc3LTMuNjQgMS41MDItMy4xMzggNC44Mi01LjE2OCA4LjQ1LTUuMTY4IDUuMTEyIDAgOS4yNzQgMy45NTQgOS4yNzQgOC44MTQgMCAxLjgyOC0xLjU1OCAzLjMxMy0zLjQ2NSAzLjMxMy0xLjkwNiAwLTMuNDY0LTEuNDg0LTMuNDY0LTMuMzEyIDAtMS4yMDQtMS4wNTItMi4xODgtMi4zNC0yLjE4OC0xLjI4OCAwLTIuMzQuOTgtMi4zNCAyLjE4OCAwIDEuOTE4Ljc0OCAzLjcyNCAyLjEwNCA1LjA3NCAxLjA2MyAxLjA1NyAyLjA5OCAxLjY0MiAzLjY4NCAyLjA3Ni4yOTguMDg0LjQ3OC4zOTMuMzk0LjY5LS4wNjcuMjUtLjI5Mi40MTItLjU0LjQxMnoiIGZpbGw9IiM0Mjg1RjQiLz48cGF0aCBkPSJNMCAwaDI3djI3SDAiLz48L2c+PC9zdmc+);
}

.fingerprint-icon-container.failed .fingerprint-icon-image {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI0U1MUMyMyI+CiAgICA8cGF0aCBmaWxsPSJub25lIiBkPSJNMCAwaDI0djI0SDBWMHoiLz4KICAgIDxwYXRoIGQ9Ik0xMSAxNWgydjJoLTJ6bTAtOGgydjZoLTJ6bS45OS01QzYuNDcgMiAyIDYuNDggMiAxMnM0LjQ3IDEwIDkuOTkgMTBDMTcuNTIgMjIgMjIgMTcuNTIgMjIgMTJTMTcuNTIgMiAxMS45OSAyek0xMiAyMGMtNC40MiAwLTgtMy41OC04LThzMy41OC04IDgtOCA4IDMuNTggOCA4LTMuNTggOC04IDh6Ii8+Cjwvc3ZnPgo=);
}

.pod input[type='password'].hidden::-webkit-input-placeholder {
  color: grey;
}

.pod input[type='password'].default::-webkit-input-placeholder {
  color: grey;
}

.pod input[type='password'].signin::-webkit-input-placeholder {
  color: var(--google-blue-500);
}

.pod input[type='password'].failed::-webkit-input-placeholder {
  color: var(--google-red-500);
}

.action-box-menu {
  display: none;
  z-index: 6;
}

.action-box-area.active ~ .action-box-menu {
  background-color: white;
  border: 1px solid lightgray;
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  font-size: 13px;
  position: absolute;
  right: 5px;
  width: 220px;
}

.action-box-area.active ~ .action-box-menu.left-edge-offset {
  left: 0 !important;
}

.action-box-area.active ~ .action-box-menu.right-edge-offset {
  right: 0 !important;
}

.action-box-area.active ~ .action-box-menu:not(.menu-moved-up) {
  top: 18px;
}

.action-box-area.active ~ .action-box-menu.menu-moved-up {
  bottom: 207px;
}

.action-box-area.menu-moved-up {
  transform: rotate(180deg);
}

html[dir=rtl] .action-box-area.active ~ .action-box-menu {
  left: 5px;
  right: auto;
}

.action-box-menu-title {
  color: #757575;
  display: flex;
  flex-direction: column;
  padding: 7px 20px;
}

.action-box-menu-title:focus {
  outline-style: none;
}

.action-box-menu-title-name,
.action-box-menu-title-email {
  flex: none;
  height: 23px;
  line-height: 19px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.action-box-menu-remove {
  border-top: 1px solid lightgray;
  line-height: 19px;
  min-height: 24px;
  outline: none;
  padding: 12px 20px 7px;
}

.action-box-menu-remove:hover,
.action-box-menu-remove:focus {
  background-color: #f3f3f3;
}

.action-box-remove-user-warning {
  border-top: 1px solid lightgray;
  font-size: 12px;
  line-height: 18px;
  padding: 20px;
}

.action-box-remove-user-warning > div,
.action-box-remove-user-warning > table {
  padding-bottom: 20px;
}

.total-count {
  font-weight: bold;
}

.action-box-remove-user-warning-table-nonsync {
  border-spacing: 0;
  width: 100%;
}

.action-box-remove-user-warning-table td {
  padding: 0;
}

.action-box-remove-user-warning-table-numbers {
  color: #757575;
  text-align: end;
}

/* Hide dialog elements not in a correct category. Only combinations currently
   in use are included here. */
.pod.legacy-supervised .non-sync,
.pod.legacy-supervised .action-box-remove-user-warning-text,
.pod.legacy-supervised .action-box-remove-non-owner-user-warning-text,
.pod:not(.legacy-supervised)
    .action-box-remove-legacy-supervised-user-warning-text,
.pod.synced .non-sync {
  display: none;
}

.user-type-bubble {
  background-color: white;
  border: 1px solid lightgray;
  border-radius: 2px;
  left: 5px;
  opacity: 0;
  padding: 17px;
  position: absolute;
  top: 20px;
  transition: all 100ms;
  visibility: hidden;
  width: 200px;
  z-index: 7;
}

html[dir=rtl] .user-type-bubble {
  left: auto;
  right: 5px;
}

.bubble-shown,
.user-type-icon-area.policy:hover ~ .user-type-bubble {
  opacity: 1;
  visibility: visible;
}

.user-type-bubble-header {
  font-weight: bold;
  margin-bottom: 14px;
}

/**** Public account user pod rules *******************************************/

.pod.public-account.expanded {
  height: 230px;
  width: 500px;
}

.pod.public-account.expanded.advanced {
  height: 280px;
  width: 610px;
}

.pod.public-account.focused .name-container {
  display: flex;
}

.pod.public-account.expanded .name-container {
  display: none;
}

.pod.public-account .learn-more-container {
  display: block;
  flex: none;
}

.pod.public-account .learn-more {
  top: 22px;
}

.expanded-pane {
  display: none;
}

.pod.public-account.animating .expanded-pane,
.pod.public-account.expanded .expanded-pane {
  display: block;
  font-size: 12px;
  margin: 10px;
  overflow: hidden;
  z-index: 1;
}

.expanded-pane-contents {
  display: flex;
  flex-direction: column;
  float: right;
  height: 213px;
  width: 490px;
}

.pod.public-account.transitioning-to-advanced .expanded-pane-contents {
  transition: width 180ms;
}

.pod.public-account.expanded.advanced .expanded-pane-contents {
  height: 263px;
  width: 600px;
}

html[dir=rtl] .expanded-pane-contents {
  float: left;
}

.side-container {
  -webkit-margin-start: 200px;
  flex: auto;
}

.expanded-pane-name {
  font-size: 19px;
  margin-bottom: 11px;
  margin-top: -2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.expanded-pane-container {
  color: grey;
}

.reminder {
  margin-top: 20px;
}

.language-and-input-section {
  display: none;
}

.pod.public-account.transitioning-to-advanced .language-and-input-section {
  display: block;
  opacity: 0;
  transition: opacity 180ms ease 180ms;
}

.pod.public-account.expanded.advanced .language-and-input-section {
  display: block;
  opacity: 1;
}

.select-with-label {
  display: flex;
  margin-top: 20px;
}

.language-select-label,
.keyboard-select-label {
  flex: none;
  margin-top: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 170px;
}

.select-container {
  flex: auto;
}

.language-select,
.keyboard-select {
  width: 100%;
}

.bottom-container {
  -webkit-margin-start: 20px;
  align-items: center;
  display: flex;
  flex-direction: row-reverse;
  flex: none;
  font-size: 13px;
  justify-content: space-between;
  margin-bottom: 4px;
}

.expanded-pane-learn-more-container,
.enter-button {
  flex: none;
}

.expanded-pane-learn-more,
.pod.public-account .learn-more {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgMTRWNkg0djM2aDQwVjE0SDI0ek0xMiAzOEg4di00aDR2NHptMC04SDh2LTRoNHY0em0wLThIOHYtNGg0djR6bTAtOEg4di00aDR2NHptOCAyNGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTIwIDI0SDI0di00aDR2LTRoLTR2LTRoNHYtNGgtNHYtNGgxNnYyMHptLTQtMTZoLTR2NGg0di00em0wIDhoLTR2NGg0di00eiIvPgo8L3N2Zz4K);
  background-size: 18px;
  height: 18px;
  margin-top: -10px;
  position: relative;
  width: 18px;
}

.expanded-pane-learn-more {
  top: 5px;
}

.info {
  flex: auto;
  margin: -10px 25px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.monitoring-container {
  margin-top: 35px;
}

.monitoring-learn-more {
  color: rgb(49, 106, 197);
  text-decoration: none;
}

.monitoring-dialog-container .cr-dialog-shield {
  background: black;
  opacity: 0.5;
}

.monitoring-dialog-container .cr-dialog-buttons {
  display: none;
}

.monitoring-dialog-container .cr-dialog-frame {
  height: 170px;
  left: -46px;
  padding: 0px;
  position: relative;
  top: -24px;
  width: 430px;
}

.monitoring-dialog-container.advanced .cr-dialog-frame {
  left: -110px;
  top: 0px;
}

.monitoring-dialog-container .cr-dialog-close {
  color: grey;
  height: 34px;
  position: absolute;
  top: 0px;
  width: 34px;
}

.monitoring-dialog-container .cr-dialog-title {
  font-size: 16px;
  font-weight: bold;
  left: 20px;
  position: absolute;
  top: 15px;
}

.monitoring-dialog-container .cr-dialog-text {
  color: grey;
  font-size: 13px;
  overflow: visible;
  position: absolute;
  top: 20px;
}

.monitoring-dialog-container .cr-dialog-item {
  -webkit-margin-start: 42px;
  display: list-item;
  margin-bottom: -6px;
}

.language-and-input-container {
  -webkit-margin-end: 25px;
  flex: none;
}

.language-and-input {
  color: rgb(49, 106, 197);
  text-decoration: none;
}

.pod.public-account.expanded.advanced .language-and-input-container {
  display: none;
}

.enter-button {
  background-color: rgb(66, 133, 244);
  color: white;
  font-size: 12px;
  text-transform: none;
}

.enter-button.keyboard-focus {
  font-weight: normal;
}

.horizontal-line {
  border-bottom: 1px double #cccccc;
  bottom: 8px;
  position: relative;
}

/* Animations for the animated ellipsis: */
.animated-ellipsis-component0 {
  animation: ellipsis-component0 1.5s infinite;
}

@keyframes ellipsis-component0 {
  0% { opacity: 0; }
  25% { opacity: 1; }
  50% { opacity: 1; }
  75% { opacity: 1; }
  100% { opacity: 0; }
}

.animated-ellipsis-component1 {
  animation: ellipsis-component1 1.5s infinite;
}

@keyframes ellipsis-component1 {
  0% { opacity: 0; }
  25% { opacity: 0; }
  50% { opacity: 1; }
  75% { opacity: 1; }
  100% { opacity: 0; }
}

.animated-ellipsis-component2 {
  animation: ellipsis-component2 1.5s infinite;
}

@keyframes ellipsis-component2 {
  0% { opacity: 0; }
  25% { opacity: 0; }
  50% { opacity: 0; }
  75% { opacity: 1; }
  100% { opacity: 0; }
}
</style>
  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Css based bubble.
 */

.bubble {
  background: rgba(0, 0, 0, 0.8);
  border-radius: 2px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  color: rgba(255, 255, 255, 0.87);
  font-size: 12px;
  margin: 2px;
  max-width: 240px;
  padding: 8px;
  position: absolute;
  transition: opacity 200ms ease-in-out;
}

body.chromeos .bubble {
  margin: unset;
  padding: 14px;
}

/* --- oldstyle begin --- */

.bubble[oldstyle] {
  background: white;
  border: 1px solid rgba(0, 0, 0, 0.25);
  color: unset;
}

.bubble[oldstyle]::before {
  border-style: solid;
  border-width: 8px;
  content: '';
  display: block;
  position: absolute;
}

.bubble-top::before {
  border-color: rgba(0, 0, 0, 0.25) transparent transparent transparent;
  bottom: -16px;
}

html[dir=ltr] .bubble-top::before {
  left: 17px;
}

html[dir=rtl] .bubble-top::before {
  right: 17px;
}

html[dir=ltr] .bubble-right::before,
html[dir=rtl] .bubble-left::before {
  border-color: transparent rgba(0, 0, 0, 0.25) transparent transparent;
  left: -16px;
  top: 17px;
}

.bubble-bottom::before {
  border-color: transparent transparent rgba(0, 0, 0, 0.25) transparent;
  top: -16px;
}

html[dir=ltr] .bubble-bottom::before {
  left: 17px;
}

html[dir=rtl] .bubble-bottom::before {
  right: 17px;
}

html[dir=ltr] .bubble-left::before,
html[dir=rtl] .bubble-right::before {
  border-color: transparent transparent transparent rgba(0, 0, 0, 0.25);
  right: -16px;
  top: 17px;
}

.bubble[oldstyle]::after {
  border-style: solid;
  border-width: 8px;
  content: '';
  display: block;
  position: absolute;
}

.bubble-top::after {
  border-color: white transparent transparent transparent;
  bottom: -15px;
}

html[dir=ltr] .bubble-top::after {
  left: 17px;
}

html[dir=rtl] .bubble-top::after {
  right: 17px;
}

html[dir=ltr] .bubble-right::after,
html[dir=rtl] .bubble-left::after {
  border-color: transparent white transparent transparent;
  left: -15px;
  top: 17px;
}

.bubble-bottom::after {
  border-color: transparent transparent white transparent;
  top: -15px;
}

html[dir=ltr] .bubble-bottom::after {
  left: 17px;
}

html[dir=rtl] .bubble-bottom::after {
  right: 17px;
}

html[dir=ltr] .bubble-left::after,
html[dir=rtl] .bubble-right::after {
  border-color: transparent transparent transparent white;
  right: -15px;
  top: 17px;
}

/* --- oldstyle end --- */

body.chromeos .error-message-bubble::before {
  -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMiA0Mmg0NEwyNCA0IDIgNDJ6bTI0LTZoLTR2LTRoNHY0em0wLThoLTR2LThoNHY4eiIvPgo8L3N2Zz4K);
  -webkit-mask-position: left top;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 20px;
  background-color: rgb(255,255,255);
  content: '';
  display: block;
  height: 20px;
  left: 14px;
  position: absolute;
  top: 10px;
  width: 20px;
}

body:not(.chromeos) .error-message-bubble {
  -webkit-padding-start: 30px;
  background: url(chrome://theme/IDR_WARNING) left top no-repeat;
  background-size: 24px;
}

body.chromeos .error-message-bubble {
  padding-top: 19px;
}

.bubble[match-width] .error-message-bubble {
  -webkit-padding-start: unset;
  padding-top: 20px;
}

body.chromeos .bubble a {
  color: #7baaf7;
  text-decoration: none;
}

.error-message-bubble-padding {
  margin-bottom: 10px;
}

html[dir=rtl] .error-message-bubble {
  background-position: right top;
}
</style>
  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * This is the stylesheet used by the Out of the box experience (OOBE) flow,
 * sign in and lock screens.
 */

html,
body {
  height: 100%;
  width: 100%;
}

body {
  background-color: transparent;
  cursor: default;
  font-size: 14px;
  margin: 0;
  overflow: hidden;
  padding: 0;
  position: fixed;
  top: 0;
}

html[full-screen-dialog] body {
  background-color: white;
}

body.solid {
  background-color: white;
}

button {
  font-family: inherit;
  outline: none;
}

/* Follow same focus coloring as in widgets.css */
/* Do not apply this style to restricted button state. */
button.custom-appearance:not(.button-restricted):not(.button-fancy):not(
    [is="gaia-icon-button"]) {
  border: 2px solid transparent;
  /* Don't grey out disabled buttons. */
  color: buttontext !important;
  transition: border-color 200ms;
}

/* ':focus' used three times to increase specificity. */
button.custom-appearance:focus:focus:focus {
  border-color: rgba(66, 133, 244, 0.6); /* #4285f4 */
}

button:not(.custom-appearance) {
  min-width: 72px !important;
}

button.button-fancy {
  min-width: 72px !important;
}

button.button-blue {
  background-image: linear-gradient(rgb(93, 154, 255),
                                    rgb(93, 154, 255) 38%,
                                    rgb(88, 145, 240));
  border: 1px solid rgba(45, 102, 195, 1);
  border-radius: 2px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.15), inset 0 1px 2px
              rgba(255, 255, 255, 0.4);
  color: #fff;
  font-size: 14px;
  margin: 0 1px 0 0;
  min-height: 2em;
  min-width: 4em;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
}


button.button-blue:hover {
  background-image: linear-gradient(rgb(101, 158, 253),
                                    rgb(101, 158, 253) 38%,
                                    rgb(96, 151, 241));
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25), inset 0 1px 2px
              rgba(255, 255, 255, 0.4);
}

button.button-blue:active {
  background-image: linear-gradient(rgb(96, 149, 237),
                                    rgb(96, 149, 237) 38%,
                                    rgb(96, 149, 237));
  border: 1px solid rgba(38, 84, 160, 1);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
}

button.button-red {
  background-image: linear-gradient(rgb(221, 75, 57),
                                    rgb(221, 75, 57) 38%,
                                    rgb(197, 66, 49));
  border: 1px solid rgba(167, 57, 44, 1);
  border-radius: 2px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.15), inset 0 1px 2px
      rgba(255, 255, 255, 0.4);
  color: #fff;
  margin: 0 1px 0 0;
  min-height: 2em;
  min-width: 4em;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.15);
}

button.button-red:hover {
  background-image: linear-gradient(rgb(231, 78, 59),
                                    rgb(231, 78, 59) 38%,
                                    rgb(209, 70, 52));
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25), inset 0 1px 2px
      rgba(255, 255, 255, 0.4);
}

button.button-red:active {
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}

.label,
.flexible-label {
  display: block;
  margin: 5px 5px 5px 0;
  padding: 5px 5px 5px 0;
}

.label {
  width: 170px;
}

.flexible-label {
  max-width: 250px;
}

[hidden] {
  display: none !important;
}

#bubble {
  transition: 250ms opacity;
}

span.bold {
  font-weight: bold;
}

#version-labels {
  color: #fff;
  font-size: 11px;
  margin: 10px;
  position: relative;
  text-align: end;
  text-shadow:
      0 0 4px rgba(0,0,0,.6),
      0 1px 2px rgba(0,0,0,.8),
      0 -1px 2px rgba(0,0,0,1);
  transition: all 500ms linear;
  z-index: 1;
}

#bluetooth-name {
  background: rgba(255,255,255,.17);
  border-radius: 4px;
  display: inline-block;
  font-size: 12px;
  height: 28px;
  line-height: 28px;
  padding: 0 12px;
}

#background {
  background-size: 100% 100%;
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  transition: 700ms opacity;
  width: 100%;
}

.background-initial {
  opacity: 0;
}

.dimmed-background {
  background-color: black;
  opacity: 0.5;
}

.throbber {
  -webkit-margin-end: 0.5em;
  margin-top: 1px;
}
</style>
  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#outer-container {
  -webkit-box-align: center;
  -webkit-box-pack: center;
  bottom: 57px;  /* Leave space for the header bar */
  display: -webkit-box;
  left: 0;
  min-height: 717px; /* This enables scrolling. Min resolution: 1024x768 */
  perspective: 1px; /* Workaround, see http://crbug.com/360567 */
  position: absolute;
  right: 0;
  top: 0;
  z-index: 1;
}

.oobe-display #outer-container {
  bottom: 47px; /* header-bar is 47 pixels high during OOBE */
  perspective: 600px;
}

.pin-container.pin-enabled {
  opacity: 1;
  transition: opacity 200ms ease-in-out 180ms;
  visibility: visible;
}

.pin-container.pin-disabled {
  opacity: 0; /* Opacity is set to 1 after the pin element is loaded. */
  transition: none;
  visibility: hidden; /* Needed because pin-keyboard's offsetHeight is
                         checked to determine if loaded. */
}

#scroll-container {
  bottom: 0;        /* Allows content overlap with control bar. */
  left: 0;
  overflow-x: hidden;
  overflow-y: auto;
  position: absolute;
  right: 0;
  top: 0;
}

#scroll-container::-webkit-scrollbar {
  display: none;
}

#inner-container {
  border-radius: 2px;
  position: relative;
}

#inner-container.animation {
  overflow: hidden;
}

#inner-container.disabled {
  opacity: 0.4;
  pointer-events: none;
}

/* Screens that have a border and background. */
#oobe.auto-enrollment-check #inner-container,
#oobe.autolaunch #inner-container,
#oobe.confirm-password #inner-container,
#oobe.debugging #inner-container,
#oobe.enrollment #inner-container,
#oobe.fatal-error #inner-container,
#oobe.gaia-signin #inner-container,
#oobe.hid-detection #inner-container,
#oobe.kiosk-enable #inner-container,
#oobe.oauth-enrollment #inner-container,
#oobe.password-changed #inner-container,
#oobe.ad-password-change #inner-container,
#oobe.supervised-user-creation #inner-container,
#oobe.supervised-user-creation-dialog #inner-container,
#oobe.terms-of-service #inner-container,
#oobe.arc-tos #inner-container,
#oobe.update #inner-container,
#oobe.update-required #inner-container,
#oobe.user-image #inner-container,
#oobe.wrong-hwid #inner-container,
#oobe.unrecoverable-cryptohome-error #inner-container {
  background: white;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3),
              0 4px 23px 5px rgba(0, 0, 0, 0.2),
              0 2px 6px rgba(0, 0, 0, 0.15);
}

#oobe.error-message #inner-container,
#oobe.tpm-error-message #inner-container {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3),
              0 4px 23px 5px rgba(0, 0, 0, 0.2),
              0 2px 6px rgba(0, 0, 0, 0.15);

}

/* Only play this animation when 'down' class is removed. */
.oobe-display #inner-container:not(.down) {
  transition: transform 200ms ease-in-out;
}

.oobe-display #inner-container.down {
  transform: translateY(50px) rotateX(-2.5deg);
}

#oobe #step-logo {
  display: none;
}

#account-picker-dot,
#app-launch-splash-dot,
#arc-kiosk-splash-dot,
#auto-enrollment-check-dot,
#autolaunch-dot,
#confirm-password-dot,
#debugging-dot,
#device-disabled-dot,
#enrollment-dot,
#error-message-dot,
#fatal-error-dot,
#hid-detection-dot,
#kiosk-enable-dot,
#oauth-enrollment-dot,
#password-changed-dot,
#reset-dot,
#supervised-user-creation-dialog-dot,
#supervised-user-creation-dot,
#terms-of-service-dot,
#arc-tos-dot,
#tpm-error-message-dot,
#update-required-dot,
#wrong-hwid-dot,
#unrecoverable-cryptohome-error-dot {
  display: none;
}

#oobe.connect #connect-dot,
#oobe.enrollment #gaia-signin-dot,
#oobe.enrollment #signin-dot,
#oobe.eula #eula-dot,
#oobe.gaia-signin #gaia-signin-dot,
#oobe.oauth-enrollment #gaia-signin-dot,
#oobe.oauth-enrollment #signin-dot,
#oobe.signin #signin-dot,
#oobe.update #update-dot,
#oobe.user-image #user-image-dot {
  opacity: 1;
}

body:not(.oobe-display) #inner-container {
  height: 262px;
  padding: 0;
  width: 1100px;
}

#outer-container.fullscreen,
#outer-container.fullscreen #oobe,
#outer-container.fullscreen #oobe #inner-container {
  height: 100%;
  width: 100%;
}

html[build=chrome] #header-sections {
  -webkit-margin-start: -48px;
  margin-top: -1px;
}

html[build=chromium] #header-sections {
  -webkit-margin-start: 5px;
  margin-top: -1px;
}

.header-section {
  color: rgb(119, 120, 123);  /* Should matching text color of the logo. */
  display: none;
  font-size: 23px;
  line-height: 31px;
  text-transform: lowercase;
  width: 23em;
}

.header-section::before {
  /* Divider in header between product name and title,
   * like "[Product name] > [step header]". */
  content: '\00A0\203A\00A0\00A0';
}
</style>
  <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">

  <link rel="import" href="chrome://resources/html/polymer.html">
  <link rel="import" href="/control_bar.html">
  <link rel="import" href="/error_dialog.html">
  <link rel="import" href="/shared_styles.html">
  <link rel="import" href="/strings.html">
  <link rel="import" href="/user_manager_pages.html">
  <link rel="import" href="/user_manager_tutorial.html">
  <link rel="import" href="chrome://resources/html/cr/ui.html">
  <link rel="import" href="chrome://resources/html/util.html">
  <!-- Make sure iron-icon and cr iconset are imported to use in
       user_pod_template.html -->
  <link rel="import" href="chrome://resources/cr_elements/icons.html">
  <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
  <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
  <!-- Make sure paper-button is imported to use in user_pod_template.html -->
  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
  <custom-style>
    <style is="custom-style" include="shared-styles">
      user-manager-pages,
      #login-header-bar {
        bottom: 0;
        left: 0;
        position: absolute;
        right: 0;
      }

      user-manager-pages {
        top: 0;
      }

      #login-header-bar.shadow {
        box-shadow: 0 -1px 3px rgba(0, 0, 0, .2);
      }

      /* Overrides src/ui/login/screen_container.css for the desktop user
       * manager. */

      #outer-container {
        -webkit-box-orient: vertical;
        min-height: 0;
        overflow-x: hidden;
        overflow-y: auto;
        padding: 40px 0 30px;
        z-index: initial;
      }

      .bubble {
        font: inherit;
      }

      .bubble.faded {
        opacity: 0;
      }

      /* The name-container font-sizes is to counteract the countainer's
       * scale(0.8), so that the text still stays legible. */
      podrow[ncolumns='6'] .pod .name-container {
        font-size: 1.25em;
        transition: font-size 180ms;
      }

      podrow[ncolumns='6'] .pod.focused .name-container {
        font-size: 1em;
      }

      .pod {
        @apply --cr-card-elevation;
        border-radius: var(--cr-card-border-radius);
        color: var(--cr-primary-text-color);
        cursor: default;
        height: auto;
        transform: none;
        width: auto;
      }

      .pod.faded {
        opacity: .6;
      }

      .pod.focused {
        box-shadow: 0 10px 10px 0 rgba(0, 0, 0, .26),
                    0 14px 28px 0 rgba(0, 0, 0, .25);
      }

      .pod .user-image-gradient-area,
      .pod .user-image-pane {
        border-top-left-radius: 2px;
        border-top-right-radius: 2px;
      }

      .pod .user-image-pane {
        overflow: hidden;
        position: static;
      }

      .pod .user-image {
        height: 160px;
        width: 160px;
      }

      .pod .main-pane {
        line-height: 20px;
        padding: 10px;
        position: static;
      }

      .pod .main-pane .name-container {
        display: block;
        position: static;
        width: auto;
      }

      .pod .main-pane .name-container .name,
      .reauth-hint-container .reauth-name-hint {
        font-size: inherit;
        margin: 0;
        padding: 0;
        text-align: initial;
        width: 120px;
      }

      .pod.locked.child .name-container .name {
        width: 92px;
      }

      .pod .indicator-container {
        bottom: 10px;
        display: flex;
        left: auto;
        position: absolute;
        right: 10px;
        top: auto;
      }

      html[dir='rtl'] .pod .indicator-container {
        left: 10px;
        right: auto;
      }

      /* Using -webkit-mask on the indicators allows us to tweak the color. */
      .pod .indicator-container > .indicator {
        -webkit-mask-position: center;
        -webkit-mask-repeat: no-repeat;
        -webkit-mask-size: 16px;
        background: var(--paper-grey-600);
        display: none;
        height: 20px;
        width: 20px;
      }

      .pod.locked .locked-indicator {
        -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzAwMCI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMzYgMTZoLTJ2LTRjMC01LjUyLTQuNDgtMTAtMTAtMTBTMTQgNi40OCAxNCAxMnY0aC0yYy0yLjIxIDAtNCAxLjc5LTQgNHYyMGMwIDIuMjEgMS43OSA0IDQgNGgyNGMyLjIxIDAgNC0xLjc5IDQtNFYyMGMwLTIuMjEtMS43OS00LTQtNHpNMjQgMzRjLTIuMjEgMC00LTEuNzktNC00czEuNzktNCA0LTQgNCAxLjc5IDQgNC0xLjc5IDQtNCA0em02LjItMThIMTcuOHYtNGMwLTMuNDIgMi43OC02LjIgNi4yLTYuMiAzLjQyIDAgNi4yIDIuNzggNi4yIDYuMnY0eiIvPgo8L3N2Zz4K);
        display: block;
      }

      .pod.locked.child .locked-indicator {
        margin-inline-start: 8px;
      }

      .pod.legacy-supervised .legacy-supervised-indicator {
        -webkit-mask-image:
            url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMzMgMjRjMi43NiAwIDQuOTgtMi4yNCA0Ljk4LTVzLTIuMjItNS00Ljk4LTVjLTIuNzYgMC01IDIuMjQtNSA1czIuMjQgNSA1IDV6bS0xNS0yYzMuMzEgMCA1Ljk4LTIuNjkgNS45OC02cy0yLjY3LTYtNS45OC02Yy0zLjMxIDAtNiAyLjY5LTYgNnMyLjY5IDYgNiA2em0xNSA2Yy0zLjY3IDAtMTEgMS44NC0xMSA1LjVWMzhoMjJ2LTQuNWMwLTMuNjYtNy4zMy01LjUtMTEtNS41em0tMTUtMmMtNC42NyAwLTE0IDIuMzQtMTQgN3Y1aDE0di00LjVjMC0xLjcuNjctNC42NyA0Ljc0LTYuOTRDMjEgMjYuMTkgMTkuMzEgMjYgMTggMjZ6Ii8+Cjwvc3ZnPgo=);
        display: block;
      }

      .pod.child .child-indicator {
        -webkit-mask-image:
            url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMjQgNGMzLjMxIDAgNiAyLjY5IDYgNnMtMi42OSA2LTYgNi02LTIuNjktNi02IDIuNjktNiA2LTZ6Ii8+CiAgICA8cGF0aCBmaWxsPSJub25lIiBkPSJNMCAwaDQ4djQ4SDBWMHoiLz4KICAgIDxjaXJjbGUgZmlsbD0ibm9uZSIgY3g9IjI0IiBjeT0iMjYiIHI9IjQiLz4KICAgIDxwYXRoIGQ9Ik0yNCAxOGMtNi4xNiAwLTEzIDMuMTItMTMgNy4yM3YxMS41NGMwIDIuMzIgMi4xOSA0LjMzIDUuMiA1LjYzIDIuMzIgMSA1LjEyIDEuNTkgNy44IDEuNTkuNjYgMCAxLjMzLS4wNiAyLS4xNHYtNS4yYy0uNjcuMDgtMS4zNC4xNC0yIC4xNC0yLjYzIDAtNS4zOS0uNTctNy42OC0xLjU1LjY3LTIuMTIgNC4zNC0zLjY1IDcuNjgtMy42NS44NiAwIDEuNzUuMTEgMi42LjI5IDIuNzkuNjIgNS4yIDIuMTUgNS4yIDQuMDR2NC40N2MzLjAxLTEuMzEgNS4yLTMuMzEgNS4yLTUuNjNWMjUuMjNDMzcgMjEuMTIgMzAuMTYgMTggMjQgMTh6bTAgMTJjLTIuMjEgMC00LTEuNzktNC00czEuNzktNCA0LTQgNCAxLjc5IDQgNC0xLjc5IDQtNCA0eiIvPgo8L3N2Zz4K);
        display: block;
      }

      .action-box-area:focus ~ .user-image-gradient-area,
      .action-box-area.hovered ~ .user-image-gradient-area {
        background-image: linear-gradient(rgba(0, 0, 0, .2), transparent 100%);
        display: initial;
        height: 40px;
        position: absolute;
        top: 0;
        width: 100%;
      }

      .action-box-area {
        background-color: transparent;
      }

      .action-box-area.menu-moved-up {
        transform: none;
      }

      .action-box-area .action-box-button {
        display: none;
      }

      .action-box-area .action-box-icon {
        color: white;
        display: inline-flex;
        margin-top: 4px;
      }

      .pod.focused:not(.locked) .auth-container {
        display: none;
      }

      .pod.focused:not(.multiprofiles-policy-applied) .auth-container {
        left: 0;
      }

      .pod .auth-container input[type='password'] {
        font: inherit;
        line-height: inherit;
        padding: 10px;
        top: 0;
        width: 140px;
      }

      .pod .auth-container input[type='password']:focus {
        outline: 0;
      }

      .pod[auth-type='onlineSignIn'] .reauth-hint-container {
        flex-direction: row-reverse;
        margin: 0;
        padding: 10px;
      }

      .reauth-hint-container .reauth-warning {
        -webkit-mask-size: 16px;
        height: 20px;
        width: 20px;
      }

      .action-box-area.active .action-box-button {
        display: none;
      }

      .action-box-area.active ~ .action-box-menu:not(.menu-moved-up) {
        top: 8px;
      }

      .action-box-area.active ~ .action-box-menu {
        border: none;
        border-radius: var(--cr-card-border-radius);
        box-shadow: 0 10px 20px 0 rgba(0, 0, 0, .19);
        right: 8px;
        width: 224px;
      }

      html[dir=rtl] .action-box-area.active ~ .action-box-menu {
        left: 8px;
        right: auto;
      }

      .action-box-menu-title {
        color: inherit;
        padding: 16px 12px;
      }

      .action-box-menu-title-name,
      .action-box-menu-title-email {
        height: auto;
      }

      .action-box-menu-title-name {
        color: var(--cr-primary-text-color);
      }

      .action-box-menu-title-email {
        color: var(--cr-secondary-text-color);
      }

      .action-box-menu-remove {
        border-radius: var(--cr-card-border-radius);
        border-top: var(--user-manager-separator-line);
        line-height: 32px;
        padding: 8px 12px;
      }

      .action-box-remove-user-warning {
        align-items: center;
        border-top: var(--user-manager-separator-line);
        display: flex;
        flex-direction: column;
        font-size: inherit;
        line-height: 20px;
        padding: 12px;
      }

      .action-box-remove-user-warning-text {
        max-width: 100%;
      }

      .action-box-remove-user-warning > * {
        word-wrap: break-word;
      }

      .total-count,
      .pod:not(.synced) .action-box-remove-user-warning-text {
        font-weight: 500;
      }

      #user-manager-prompt-message {
        background-image:
            url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNMjQgMTRWNkg0djM2aDQwVjE0SDI0ek0xMiAzOEg4di00aDR2NHptMC04SDh2LTRoNHY0em0wLThIOHYtNGg0djR6bTAtOEg4di00aDR2NHptOCAyNGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTAtOGgtNHYtNGg0djR6bTIwIDI0SDI0di00aDR2LTRoLTR2LTRoNHYtNGgtNHYtNGgxNnYyMHptLTQtMTZoLTR2NGg0di00em0wIDhoLTR2NGg0di00eiIvPgo8L3N2Zz4K);
        background-position: 0 center;
        background-repeat: no-repeat;
        background-size: 19px;
        font-size: 19px;
        margin-bottom: 45px;
        padding-left: 30px;
        text-align: center;
      }

      html[dir=rtl] #user-manager-prompt-message {
        background-position: right center;
        padding-left: 0;
        padding-right: 30px;
      }

      #user-manager-prompt-message:empty {
        display: none;
      }

    </style>
  </custom-style>
</head>
<body>
  <user-manager-pages>
    <div id="outer-container">
      <div id="user-manager-prompt-message">$i18n{userManagerPromptMessage}</div>
      <user-manager-tutorial></user-manager-tutorial>
      <div id="oobe" class="faded">
        <div id="inner-container">
          <div id="step-logo" hidden>
            <div id="header-sections"></div>
          </div>
          <div id="account-picker" class="step faded hidden no-logo" hidden>
  <div id="signin-banner-container1">
    <div id="signin-banner-container2">
      <div id="signin-banner">$i18n{signinBannerText}</div>
    </div>
  </div>
  <podrow id="pod-row" class="podrow images-loading"></podrow>
</div>

        </div>
      </div>
    </div>
    <div id="bubble" class="bubble faded" hidden></div>
    <control-bar id="login-header-bar"></control-bar>
    <error-dialog></error-dialog>
    <dom-module id="user-pod-template-shared-styles">
  <template>
    <style>/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * This is the stylesheet imported into the style module in
 * user_pod_template.html.
 */

.action-box-remove-user-warning .remove-warning-button {
  --paper-button: {
    background: var(--google-red-700);
    color: white;
    font-weight: 600;
    @apply(--layout-vertical);
  };
  --paper-button-flat-keyboard-focus: {
    background: rgb(173, 50, 36);
  };
  @apply(--action-button);
}
</style>
  </template>
</dom-module>

<style is="custom-style" include="user-pod-template-shared-styles"></style>

<iron-iconset-svg name="user-pod" size="24">
  <svg>
    <defs>
      <!--
      Inlined from Polymer's iron-icons to avoid importing everything.
      See http://goo.gl/Y1OdAq for instructions on adding additional icons.
      -->
      <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"/></g>
      <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g>
    </defs>
  </svg>
</iron-iconset-svg>

<div id="user-pod-template" class="pod disabled" hidden>
  <div class="user-image-pane">
    <div class="user-image-container">
      <img class="user-image" alt>
      <img class="user-image animated-image" alt>
    </div>
    <div class="signed-in-indicator">$i18n{signedIn}</div>
    <div class="indicator-container">
      <div class="indicator legacy-supervised-indicator"></div>
      <div class="indicator child-indicator"></div>
      <div class="indicator locked-indicator"></div>
    </div>
  </div>

  <div class="main-pane">
    <div class="name-container">
      <div class="learn-more-container">
        <div class="learn-more"></div>
      </div>
      <div class="name"></div>
    </div>
    <div class="auth-container">
      <!-- Password Authentication -->
      <div class="custom-icon-container" hidden></div>

      <div class="password-entry-container">
        <div class="password-container">
          <input type="password" class="password"
              placeholder="$i18n{passwordHint}">
        </div>

      </div>
      <!-- User Click Authentication -->
      <div class="password-label"></div>
      <div class="signin-transition-container">
        <span class="signing-in-label">$i18n{signingIn}</span>
        <span class="animated-ellipsis-component0">.</span>
        <span class="animated-ellipsis-component1">.</span>
        <span class="animated-ellipsis-component2">.</span>
      </div>
      <div class="reauth-hint-container">
        <span class="reauth-warning"></span>
        <span class="reauth-name-hint"></span>
      </div>
      <div class="launch-app-button-container" hidden>
        <button class="launch-app-button">$i18n{launchAppButton}</button>
      </div>
    </div>
  </div>
  <div class="action-box-area">
    <div class="custom-appearance action-box-button"></div>
    <!-- iron-icon is imported inside user_manager.html -->
    <iron-icon icon="cr:more-vert" class="action-box-icon"></iron-icon>
  </div>
  <div class="user-image-gradient-area">
  </div>
  <div class="user-type-icon-area" hidden>
    <div class="custom-appearance user-type-icon-image"></div>
  </div>
  <div class="action-box-menu">
    <div class="action-box-menu-title">
      <span class="action-box-menu-title-name"></span>
      <span class="action-box-menu-title-email"></span>
    </div>
    <div class="action-box-menu-remove">
      <span class="action-box-menu-remove-command"/>
    </div>
    <div class="action-box-remove-user-warning" hidden>
      <div class="action-box-remove-user-warning-text"></div>
      <table class="action-box-remove-user-warning-table-nonsync
                    non-sync has-stats">
        <tbody>
          <tr>
            <td>$i18n{removeUserWarningTextHistory}</td>
            <td class="action-box-remove-user-warning-history
                       action-box-remove-user-warning-table-numbers">
              $i18n{removeUserWarningTextCalculating}
            </td>
          </tr>
          <tr>
            <td>$i18n{removeUserWarningTextPasswords}</td>
            <td class="action-box-remove-user-warning-passwords
                       action-box-remove-user-warning-table-numbers">
              $i18n{removeUserWarningTextCalculating}
            </td>
          </tr>
          <tr>
            <td>$i18n{removeUserWarningTextBookmarks}</td>
            <td class="action-box-remove-user-warning-bookmarks
                       action-box-remove-user-warning-table-numbers">
              $i18n{removeUserWarningTextCalculating}
            </td>
          </tr>
          <tr>
            <td>$i18n{removeUserWarningTextAutofill}</td>
            <td class="action-box-remove-user-warning-autofill
                       action-box-remove-user-warning-table-numbers">
              $i18n{removeUserWarningTextCalculating}
            </td>
          </tr>
        </tbody>
      </table>
      <div class="action-box-remove-legacy-supervised-user-warning-text">
        $i18n{removeLegacySupervisedUserWarningText}
      </div>
      <div class="action-box-remove-non-owner-user-warning-text">
        $i18n{removeNonOwnerUserWarningText}
      </div>
      <!-- paper-button is imported inside user_manager.html -->
      <paper-button class="remove-warning-button action-button">
        $i18n{removeUserWarningButtonTitle}
      </paper-button>
    </div>
  </div>
  <div class="user-type-bubble">
    <div class="user-type-bubble-header">
      <span class="mp-policy-title">
        $i18n{multiProfilesRestrictedPolicyTitle}
      </span>
    </div>
    <div class="user-type-bubble-body">
      <span class="mp-policy-not-allowed-msg" hidden>
        $i18n{multiProfilesNotAllowedPolicyMsg}
      </span>
      <span class="mp-policy-primary-only-msg" hidden>
        $i18n{multiProfilesPrimaryOnlyPolicyMsg}
      </span>
      <span class="mp-owner-primary-only-msg" hidden>
        $i18n{multiProfilesOwnerPrimaryOnlyMsg}
      </span>
    </div>
  </div>
</div>

<!-- Extra elements that are appended to above "user-pod-template" for public
     account user pod. Note that only the children of the template div are
     appended. -->
<div id="public-account-user-pod-extras-template" hidden>
  <div class="expanded-pane">
    <div class="expanded-pane-contents">
      <div class="side-container">
        <div class="expanded-pane-name"></div>
        <div class="expanded-pane-container">
          <div class="expanded-pane-learn-more-container">
            <div class="expanded-pane-learn-more"></div>
          </div>
          <div class="info"></div>
          <div class="monitoring-container">
            <span class="monitoring-warning">
              $i18n{publicAccountMonitoringWarning}
            </span>
            <a class="monitoring-learn-more" href="#" role="button">
              $i18n{publicAccountLearnMore}
            </a>
          </div>
          <div class="reminder">$i18n{publicAccountReminder}</div>
          <div class="language-and-input-section">
            <div class="select-with-label">
              <label class="language-select-label">
                $i18n{publicSessionSelectLanguage}
              </label>
              <div class="select-container">
                <select class="language-select"></select>
              </div>
            </div>
            <div class="select-with-label">
              <label class="keyboard-select-label">
                $i18n{publicSessionSelectKeyboard}
              </label>
              <div class="select-container">
                <select class="keyboard-select"></select>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="horizontal-line"></div>
      <div class="bottom-container">
        <paper-button raised class="enter-button"
            aria-label="$i18n{publicAccountEnterAccessibleName}">
          $i18n{publicAccountEnter}
        </paper-button>
        <div class="language-and-input-container">
          <a class="language-and-input" href="#" role="button">
            $i18n{publicSessionLanguageAndInput}
          </a>
        </div>
      </div>
    </div>
  </div>
</div>

  </user-manager-pages>
  <link rel="import" href="chrome://resources/html/i18n_template.html">
  <script src="user_manager.js"></script>
</body>
</html>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Base class for all login WebUI screens.
 */
cr.define('login', function() {
  /** @const */ var CALLBACK_CONTEXT_CHANGED = 'contextChanged';
  /** @const */ var CALLBACK_USER_ACTED = 'userActed';

  function doNothing() {};

  function alwaysTruePredicate() { return true; }

  var querySelectorAll = HTMLDivElement.prototype.querySelectorAll;

  var Screen = function(sendPrefix) {
    this.sendPrefix_ = sendPrefix;
    this.screenContext_ = null;
    this.contextObservers_ = {};
  };

  Screen.prototype = {
    __proto__: HTMLDivElement.prototype,

    /**
     * Prefix added to sent to Chrome messages' names.
     */
    sendPrefix_: null,

    /**
     * Context used by this screen.
     */
    screenContext_: null,

    get context() {
      return this.screenContext_;
    },

    /**
     * Dictionary of context observers that are methods of |this| bound to
     * |this|.
     */
    contextObservers_: null,

    /**
     * Called during screen initialization.
     */
    decorate: doNothing,

    /**
     * Returns minimal size that screen prefers to have. Default implementation
     * returns current screen size.
     * @return {{width: number, height: number}}
     */
    getPreferredSize: function() {
      return {width: this.offsetWidth, height: this.offsetHeight};
    },

    /**
     * Called for currently active screen when screen size changed.
     */
    onWindowResize: doNothing,

    /**
     * @final
     */
    initialize: function() {
      return this.initializeImpl_.apply(this, arguments);
    },

    /**
     * @final
     */
    send: function() {
      return this.sendImpl_.apply(this, arguments);
    },

    /**
     * @final
     */
    addContextObserver: function() {
      return this.addContextObserverImpl_.apply(this, arguments);
    },

    /**
     * @final
     */
    removeContextObserver: function() {
      return this.removeContextObserverImpl_.apply(this, arguments);
    },

    /**
     * @final
     */
    commitContextChanges: function() {
      return this.commitContextChangesImpl_.apply(this, arguments);
    },

    /**
     * Creates and returns new button element with given identifier
     * and on-click event listener, which sends notification about
     * user action to the C++ side.
     *
     * @param {string} id Identifier of a button.
     * @param {string} opt_action_id Identifier of user action.
     * @final
     */
    declareButton: function(id, opt_action_id) {
      var button = this.ownerDocument.createElement('button');
      button.id = id;
      this.declareUserAction(button,
                             { action_id: opt_action_id,
                               event: 'click'
                             });
      return button;
    },

    /**
      * Adds event listener to an element which sends notification
      * about event to the C++ side.
      *
      * @param {Element} element An DOM element
      * @param {Object} options A dictionary of optional arguments:
      *   {string} event: name of event that will be listened,
      *            default: 'click'.
      *   {string} action_id: name of an action which will be sent to
      *                       the C++ side.
      *   {function} condition: a one-argument function which takes
      *              event as an argument, notification is sent to the
      *              C++ side iff condition is true, default: constant
      *              true function.
      * @final
      */
    declareUserAction: function(element, options) {
      var self = this;
      options = options || {};

      var event = options.event || 'click';
      var action_id = options.action_id || element.id;
      var condition = options.condition || alwaysTruePredicate;

      element.addEventListener(event, function(e) {
        if (condition(e))
          self.sendImpl_(CALLBACK_USER_ACTED, action_id);
        e.stopPropagation();
      });
    },

    /**
     * @override
     * @final
     */
    querySelectorAll: function() {
      return this.querySelectorAllImpl_.apply(this, arguments);
    },

    /**
     * Does the following things:
     *  * Creates screen context.
     *  * Looks for elements having "alias" property and adds them as the
     *    proprties of the screen with name equal to value of "alias", i.e. HTML
     *    element <div alias="myDiv"></div> will be stored in this.myDiv.
     *  * Looks for buttons having "action" properties and adds click handlers
     *    to them. These handlers send |CALLBACK_USER_ACTED| messages to
     *    C++ with "action" property's value as payload.
     * @private
     */
    initializeImpl_: function() {
      if (cr.isChromeOS)
        this.screenContext_ = new login.ScreenContext();

      this.decorate();

      this.querySelectorAllImpl_('[alias]').forEach(function(element) {
        var alias = element.getAttribute('alias');
        if (alias in this)
          throw Error('Alias "' + alias + '" of "' + this.name() + '" screen ' +
              'shadows or redefines property that is already defined.');
        this[alias] = element;
        this[element.getAttribute('alias')] = element;
      }, this);
      var self = this;
      this.querySelectorAllImpl_('button[action]').forEach(function(button) {
        button.addEventListener('click', function(e) {
          var action = this.getAttribute('action');
          self.send(CALLBACK_USER_ACTED, action);
          e.stopPropagation();
        });
      });
    },

    /**
     * Sends message to Chrome, adding needed prefix to message name. All
     * arguments after |messageName| are packed into message parameters list.
     *
     * @param {string} messageName Name of message without a prefix.
     * @param {...*} varArgs parameters for message.
     * @private
     */
    sendImpl_: function(messageName, varArgs) {
      if (arguments.length == 0)
        throw Error('Message name is not provided.');
      var fullMessageName = this.sendPrefix_ + messageName;
      var payload = Array.prototype.slice.call(arguments, 1);
      chrome.send(fullMessageName, payload);
    },

    /**
     * Starts observation of property with |key| of the context attached to
     * current screen. This method differs from "login.ScreenContext" in that
     * it automatically detects if observer is method of |this| and make
     * all needed actions to make it work correctly. So it's no need for client
     * to bind methods to |this| and keep resulting callback for
     * |removeObserver| call:
     *
     *   this.addContextObserver('key', this.onKeyChanged_);
     *   ...
     *   this.removeContextObserver('key', this.onKeyChanged_);
     * @private
     */
    addContextObserverImpl_: function(key, observer) {
      var realObserver = observer;
      var propertyName = this.getPropertyNameOf_(observer);
      if (propertyName) {
        if (!this.contextObservers_.hasOwnProperty(propertyName))
          this.contextObservers_[propertyName] = observer.bind(this);
        realObserver = this.contextObservers_[propertyName];
      }
      this.screenContext_.addObserver(key, realObserver);
    },

    /**
     * Removes |observer| from the list of context observers. Supports not only
     * regular functions but also screen methods (see comment to
     * |addContextObserver|).
     * @private
     */
    removeContextObserverImpl_: function(observer) {
      var realObserver = observer;
      var propertyName = this.getPropertyNameOf_(observer);
      if (propertyName) {
        if (!this.contextObservers_.hasOwnProperty(propertyName))
          return;
        realObserver = this.contextObservers_[propertyName];
        delete this.contextObservers_[propertyName];
      }
      this.screenContext_.removeObserver(realObserver);
    },

    /**
     * Sends recent context changes to C++ handler.
     * @private
     */
    commitContextChangesImpl_: function() {
      if (!this.screenContext_.hasChanges())
        return;
      this.sendImpl_(CALLBACK_CONTEXT_CHANGED,
                     this.screenContext_.getChangesAndReset());
    },

    /**
     * Calls standart |querySelectorAll| method and returns its result converted
     * to Array.
     * @private
     */
    querySelectorAllImpl_: function(selector) {
      var list = querySelectorAll.call(this, selector);
      return Array.prototype.slice.call(list);
    },

    /**
     * Called when context changes are recieved from C++.
     * @private
     */
    contextChanged_: function(diff) {
      this.screenContext_.applyChanges(diff);
    },

    /**
     * If |value| is the value of some property of |this| returns property's
     * name. Otherwise returns empty string.
     * @private
     */
    getPropertyNameOf_: function(value) {
      for (var key in this)
        if (this[key] === value)
          return key;
      return '';
    }
  };

  Screen.CALLBACK_USER_ACTED = CALLBACK_USER_ACTED;

  return {
    Screen: Screen
  };
});

cr.define('login', function() {
  return {
    /**
     * Creates class and object for screen.
     * Methods specified in EXTERNAL_API array of prototype
     * will be available from C++ part.
     * Example:
     *     login.createScreen('ScreenName', 'screen-id', {
     *       foo: function() { console.log('foo'); },
     *       bar: function() { console.log('bar'); }
     *       EXTERNAL_API: ['foo'];
     *     });
     *     login.ScreenName.register();
     *     var screen = $('screen-id');
     *     screen.foo(); // valid
     *     login.ScreenName.foo(); // valid
     *     screen.bar(); // valid
     *     login.ScreenName.bar(); // invalid
     *
     * @param {string} name Name of created class.
     * @param {string} id Id of div representing screen.
     * @param {(function()|Object)} proto Prototype of object or function that
     *     returns prototype.
     */
    createScreen: function(name, id, template) {
      if (typeof template == 'function')
        template = template();

      var apiNames = template.EXTERNAL_API || [];
      for (var i = 0; i < apiNames.length; ++i) {
        var methodName = apiNames[i];
        if (typeof template[methodName] !== 'function')
          throw Error('External method "' + methodName + '" for screen "' +
              name + '" not a function or undefined.');
      }

      function checkPropertyAllowed(propertyName) {
        if (propertyName.charAt(propertyName.length - 1) === '_' &&
            (propertyName in login.Screen.prototype)) {
          throw Error('Property "' + propertyName + '" of "' + id + '" ' +
              'shadows private property of login.Screen prototype.');
        }
      };

      var Constructor = function() {
        login.Screen.call(this, 'login.' + name + '.');
      };
      Constructor.prototype = Object.create(login.Screen.prototype);
      var api = {};

      Object.getOwnPropertyNames(template).forEach(function(propertyName) {
        if (propertyName === 'EXTERNAL_API')
          return;

        checkPropertyAllowed(propertyName);

        var descriptor =
            Object.getOwnPropertyDescriptor(template, propertyName);
        Object.defineProperty(Constructor.prototype, propertyName, descriptor);

        if (apiNames.indexOf(propertyName) >= 0) {
          api[propertyName] = function() {
              var screen = $(id);
              return screen[propertyName].apply(screen, arguments);
          };
        }
      });

      Constructor.prototype.name = function() { return id; };

      api.contextChanged = function() {
        var screen = $(id);
        screen.contextChanged_.apply(screen, arguments);
      }

      api.register = function(opt_lazy_init) {
        var screen = $(id);
        screen.__proto__ = new Constructor();

        if (opt_lazy_init !== undefined && opt_lazy_init)
          screen.deferredInitialization = function() { screen.initialize(); }
        else
          screen.initialize();
        Oobe.getInstance().registerScreen(screen);
      };

      cr.define('login', function() {
        var result = {};
        result[name] = api;
        return result;
      });
    }
  };
});

// // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Bubble implementation.
 */

// TODO(xiyuan): Move this into shared.
cr.define('cr.ui', function() {
  /**
   * Creates a bubble div.
   * @constructor
   * @extends {HTMLDivElement}
   */
  var Bubble = cr.ui.define('div');

  /**
   * Bubble key codes.
   * @enum {number}
   */
  var Keys = {
    TAB: 'Tab',
    ENTER: 'Enter',
    ESC: 'Escape',
    SPACE: ' '
  };

  /**
   * Bubble attachment side.
   * @enum {number}
   */
  Bubble.Attachment = {
    RIGHT: 0,
    LEFT: 1,
    TOP: 2,
    BOTTOM: 3
  };

  Bubble.prototype = {
    __proto__: HTMLDivElement.prototype,

    // Anchor element for this bubble.
    anchor_: undefined,

    // If defined, sets focus to this element once bubble is closed. Focus is
    // set to this element only if there's no any other focused element.
    elementToFocusOnHide_: undefined,

    // With help of these elements we create closed artificial tab-cycle through
    // bubble elements.
    firstBubbleElement_: undefined,
    lastBubbleElement_: undefined,

    // Whether to hide bubble when key is pressed.
    hideOnKeyPress_: true,

    persistent_: false,

    /** @override */
    decorate: function() {
      this.docKeyDownHandler_ = this.handleDocKeyDown_.bind(this);
      this.selfClickHandler_ = this.handleSelfClick_.bind(this);
      this.ownerDocument.addEventListener('click',
                                          this.handleDocClick_.bind(this));
      // Set useCapture to true because scroll event does not bubble.
      this.ownerDocument.addEventListener('scroll',
                                          this.handleScroll_.bind(this),
                                          true);
      this.ownerDocument.addEventListener('keydown',
                                          this.docKeyDownHandler_);
      window.addEventListener('blur', this.handleWindowBlur_.bind(this));
      this.addEventListener('transitionend',
                            this.handleTransitionEnd_.bind(this));
      // Guard timer for 200ms + epsilon.
      ensureTransitionEndEvent(this, 250);
    },

    /**
     * Element that should be focused on hide.
     * @type {HTMLElement}
     */
    set elementToFocusOnHide(value) {
      this.elementToFocusOnHide_ = value;
    },

    /**
     * Element that should be focused on shift-tab of first bubble element
     * to create artificial closed tab-cycle through bubble.
     * Usually close-button.
     * @type {HTMLElement}
     */
    set lastBubbleElement(value) {
      this.lastBubbleElement_ = value;
    },

    /**
     * Whether the bubble should remain shown on user action events (e.g. on
     * user clicking, or scrolling outside the bubble). Note that
     * {@code this.hideOnKeyPress} has precedence.
     * @type {boolean}
     */
    set persistent(value) {
      this.persistent_ = value
    },

    /**
     * If set, the element at which the bubble is anchored.
     * @type {HTMLElement|undefined}
     */
    get anchor() {
      return this.anchor_;
    },

    /**
     * Element that should be focused on tab of last bubble element
     * to create artificial closed tab-cycle through bubble.
     * Same element as first focused on bubble opening.
     * @type {HTMLElement}
     */
    set firstBubbleElement(value) {
      this.firstBubbleElement_ = value;
    },

    /**
     * Whether to hide bubble when key is pressed.
     * @type {boolean}
     */
    set hideOnKeyPress(value) {
      this.hideOnKeyPress_ = value;
    },

    /**
     * Whether to hide bubble when clicked inside bubble element.
     * Default is true.
     * @type {boolean}
     */
    set hideOnSelfClick(value) {
      if (value)
        this.removeEventListener('click', this.selfClickHandler_);
      else
        this.addEventListener('click', this.selfClickHandler_);
    },

    /**
     * Handler for click event which prevents bubble auto hide.
     * @private
     */
    handleSelfClick_: function(e) {
      // Allow clicking on [x] button.
      if (e.target && e.target.classList.contains('close-button'))
        return;
      e.stopPropagation();
    },

    /**
     * Sets the attachment of the bubble.
     * @param {!Attachment} attachment Bubble attachment.
     */
    setAttachment_: function(attachment) {
      var styleClassList = ['bubble-right', 'bubble-left',
                            'bubble-top', 'bubble-bottom'];
      for (var i = 0; i < styleClassList.length; ++i)
        this.classList.toggle(styleClassList[i], i == attachment);
    },

    /**
     * Shows the bubble for given anchor element.
     * @param {!Object} pos Bubble position (left, top, right, bottom in px).
     * @param {HTMLElement} opt_content Content to show in bubble.
     *     If not specified, bubble element content is shown.
     * @param {Attachment=} opt_attachment Bubble attachment (on which side of
     *     the element it should be displayed).
     * @param {boolean=} opt_oldstyle Optional flag to force old style bubble,
     *     i.e. pre-MD-style.
     * @private
     */
    showContentAt_: function(pos, opt_content, opt_attachment, opt_oldstyle) {
      this.style.top = this.style.left = this.style.right = this.style.bottom =
          'auto';
      for (var k in pos) {
        if (typeof pos[k] == 'number')
          this.style[k] = pos[k] + 'px';
      }
      if (opt_content !== undefined)
        this.replaceContent(opt_content);

      if (opt_oldstyle) {
        this.setAttribute('oldstyle', '');
        this.setAttachment_(opt_attachment);
      }

      this.hidden = false;
      this.classList.remove('faded');
    },

    /**
     * Replaces error message content with the given DOM element.
     * @param {HTMLElement} content Content to show in bubble.
     */
    replaceContent: function(content) {
      this.innerHTML = '';
      this.appendChild(content);
    },

    /**
     * Shows the bubble for given anchor element. Bubble content is not cleared.
     * @param {!HTMLElement} el Anchor element of the bubble.
     * @param {!Attachment} attachment Bubble attachment (on which side of the
     *     element it should be displayed).
     * @param {number=} opt_offset Offset of the bubble.
     * @param {number=} opt_padding Optional padding of the bubble.
     */
    showForElement: function(el, attachment, opt_offset, opt_padding) {
      /* showForElement() is used only to display Accessibility popup in
       * oobe_screen_welcome*. It requires old-style bubble, so it is safe
       * to always set this flag here.
       */
      this.showContentForElement(
          el, attachment, undefined, opt_offset, opt_padding, undefined, true);
    },

    /**
     * Shows the bubble for given anchor element.
     * @param {!HTMLElement} el Anchor element of the bubble.
     * @param {!Attachment} attachment Bubble attachment (on which side of the
     *     element it should be displayed).
     * @param {HTMLElement} opt_content Content to show in bubble.
     *     If not specified, bubble element content is shown.
     * @param {number=} opt_offset Offset of the bubble attachment point from
     *     left (for vertical attachment) or top (for horizontal attachment)
     *     side of the element. If not specified, the bubble is positioned to
     *     be aligned with the left/top side of the element but not farther than
     *     half of its width/height.
     * @param {number=} opt_padding Optional padding of the bubble.
     * @param {boolean=} opt_match_width Optional flag to force the bubble have
     *     the same width as the element it it attached to.
     * @param {boolean=} opt_oldstyle Optional flag to force old style bubble,
     *     i.e. pre-MD-style.
     */
    showContentForElement: function(
        el, attachment, opt_content, opt_offset, opt_padding, opt_match_width,
        opt_oldstyle) {
      /** @const */ var ARROW_OFFSET = 25;
      /** @const */ var DEFAULT_PADDING = 18;

      if (opt_padding == undefined)
        opt_padding = DEFAULT_PADDING;

      if (!opt_oldstyle)
        opt_padding += 10;

      var origin = cr.ui.login.DisplayManager.getPosition(el);
      var offset = opt_offset == undefined ?
          [Math.min(ARROW_OFFSET, el.offsetWidth / 2),
           Math.min(ARROW_OFFSET, el.offsetHeight / 2)] :
          [opt_offset, opt_offset];

      var pos = {};
      if (isRTL()) {
        switch (attachment) {
          case Bubble.Attachment.TOP:
            pos.right = origin.right + offset[0] - ARROW_OFFSET;
            pos.bottom = origin.bottom + el.offsetHeight + opt_padding;
            break;
          case Bubble.Attachment.RIGHT:
            pos.top = origin.top + offset[1] - ARROW_OFFSET;
            pos.right = origin.right + el.offsetWidth + opt_padding;
            break;
          case Bubble.Attachment.BOTTOM:
            pos.right = origin.right + offset[0] - ARROW_OFFSET;
            pos.top = origin.top + el.offsetHeight + opt_padding;
            break;
          case Bubble.Attachment.LEFT:
            pos.top = origin.top + offset[1] - ARROW_OFFSET;
            pos.left = origin.left + el.offsetWidth + opt_padding;
            break;
        }
      } else {
        switch (attachment) {
          case Bubble.Attachment.TOP:
            pos.left = origin.left + offset[0] - ARROW_OFFSET;
            pos.bottom = origin.bottom + el.offsetHeight + opt_padding;
            break;
          case Bubble.Attachment.RIGHT:
            pos.top = origin.top + offset[1] - ARROW_OFFSET;
            pos.left = origin.left + el.offsetWidth + opt_padding;
            break;
          case Bubble.Attachment.BOTTOM:
            pos.left = origin.left + offset[0] - ARROW_OFFSET;
            pos.top = origin.top + el.offsetHeight + opt_padding;
            break;
          case Bubble.Attachment.LEFT:
            pos.top = origin.top + offset[1] - ARROW_OFFSET;
            pos.right = origin.right + el.offsetWidth + opt_padding;
            break;
        }
      }
      this.style.width = '';
      this.removeAttribute('match-width');
      if (opt_match_width) {
        this.setAttribute('match-width', '');
        var elWidth =
            window.getComputedStyle(el, null).getPropertyValue('width');
        var paddingLeft = parseInt(window.getComputedStyle(this, null)
            .getPropertyValue('padding-left'));
        var paddingRight = parseInt(window.getComputedStyle(this, null)
            .getPropertyValue('padding-right'));
        if (elWidth)
          this.style.width =
              (parseInt(elWidth) - paddingLeft - paddingRight) + 'px';
      }

      this.anchor_ = el;
      this.showContentAt_(pos, opt_content, attachment, opt_oldstyle);
    },

    /**
     * Shows the bubble for given anchor element.
     * @param {!HTMLElement} el Anchor element of the bubble.
     * @param {string} text Text content to show in bubble.
     * @param {!Attachment} attachment Bubble attachment (on which side of the
     *     element it should be displayed).
     * @param {number=} opt_offset Offset of the bubble attachment point from
     *     left (for vertical attachment) or top (for horizontal attachment)
     *     side of the element. If not specified, the bubble is positioned to
     *     be aligned with the left/top side of the element but not farther than
     *     half of its weight/height.
     * @param {number=} opt_padding Optional padding of the bubble.
     */
    showTextForElement: function(
        el, text, attachment, opt_offset, opt_padding) {
      var span = this.ownerDocument.createElement('span');
      span.textContent = text;
      this.showContentForElement(el, attachment, span, opt_offset, opt_padding);
    },

    /**
     * Hides the bubble.
     */
    hide: function() {
      if (!this.classList.contains('faded'))
        this.classList.add('faded');
    },

    /**
     * Hides the bubble anchored to the given element (if any).
     * @param {!Object} el Anchor element.
     */
    hideForElement: function(el) {
      if (!this.hidden && this.anchor_ == el)
        this.hide();
    },

    /**
     * Handler for faded transition end.
     * @private
     */
    handleTransitionEnd_: function(e) {
      if (this.classList.contains('faded')) {
        this.hidden = true;
        if (this.elementToFocusOnHide_)
          this.elementToFocusOnHide_.focus();
      }
    },

    /**
     * Handler of scroll event.
     * @private
     */
    handleScroll_: function(e) {
      if (!this.hidden && !this.persistent_)
        this.hide();
    },

    /**
     * Handler of document click event.
     * @private
     */
    handleDocClick_: function(e) {
      // Ignore clicks on anchor element.
      if (e.target == this.anchor_)
        return;

      if (!this.hidden && !this.persistent_)
        this.hide();
    },

    /**
     * Handle of document keydown event.
     * @private
     */
    handleDocKeyDown_: function(e) {
      if (this.hidden)
        return;

      if (this.hideOnKeyPress_) {
        this.hide();
        return;
      }
      // Artificial tab-cycle.

      if (e.key == Keys.TAB && e.shiftKey == true &&
          e.target == this.firstBubbleElement_) {
        this.lastBubbleElement_.focus();
        e.preventDefault();
      }
      if (e.key == Keys.TAB && e.shiftKey == false &&
          e.target == this.lastBubbleElement_) {
        this.firstBubbleElement_.focus();
        e.preventDefault();
      }
      // Close bubble on ESC or on hitting spacebar or Enter at close-button.
      if ((e.key == Keys.ESC && !this.persistent_) ||
          ((e.key == Keys.ENTER || e.key == Keys.SPACE) && e.target &&
           e.target.classList.contains('close-button')))
        this.hide();
    },

    /**
     * Handler of window blur event.
     * @private
     */
    handleWindowBlur_: function(e) {
      if (!this.hidden && !this.persistent_)
        this.hide();
    }
  };

  return {
    Bubble: Bubble
  };
});

// // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview JS helpers used on login.
 */

cr.define('cr.ui.LoginUITools', function() {
  return {
    /**
     * Computes max-height for an element so that it doesn't overlap shelf.
     * @param {element} DOM element
     * @param {wholeWindow} Whether the element can go outside outer-container.
     */
    getMaxHeightBeforeShelfOverlapping : function(element, wholeWindow) {
      var maxAllowedHeight =
          $('outer-container').offsetHeight -
          element.getBoundingClientRect().top -
          parseInt(window.getComputedStyle(element).marginTop) -
          parseInt(window.getComputedStyle(element).marginBottom);
      if (wholeWindow) {
        maxAllowedHeight +=
           parseInt(window.getComputedStyle($('outer-container')).bottom);
      }
      return maxAllowedHeight;
    },

    /**
     * Computes max-width for an element so that it does fit the
     * outer-container.
     * @param {element} DOM element
     */
    getMaxWidthToFit : function(element) {
      var maxAllowedWidth =
          $('outer-container').offsetWidth -
          element.getBoundingClientRect().left -
          parseInt(window.getComputedStyle(element).marginLeft) -
          parseInt(window.getComputedStyle(element).marginRight);
      return maxAllowedWidth;
    },
  }
});

// // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Display manager for WebUI OOBE and login.
 */

// TODO(xiyuan): Find a better to share those constants.
/** @const */ var SCREEN_OOBE_WELCOME = 'connect';
/** @const */ var SCREEN_OOBE_NETWORK = 'network-selection';
/** @const */ var SCREEN_OOBE_HID_DETECTION = 'hid-detection';
/** @const */ var SCREEN_OOBE_EULA = 'eula';
/** @const */ var SCREEN_OOBE_ENABLE_DEBUGGING = 'debugging';
/** @const */ var SCREEN_OOBE_UPDATE = 'update';
/** @const */ var SCREEN_OOBE_RESET = 'reset';
/** @const */ var SCREEN_OOBE_ENROLLMENT = 'oauth-enrollment';
/** @const */ var SCREEN_OOBE_DEMO_SETUP = 'demo-setup';
/** @const */ var SCREEN_OOBE_DEMO_PREFERENCES = 'demo-preferences';
/** @const */ var SCREEN_OOBE_KIOSK_ENABLE = 'kiosk-enable';
/** @const */ var SCREEN_OOBE_AUTO_ENROLLMENT_CHECK = 'auto-enrollment-check';
/** @const */ var SCREEN_GAIA_SIGNIN = 'gaia-signin';
/** @const */ var SCREEN_ACCOUNT_PICKER = 'account-picker';
/** @const */ var SCREEN_USER_IMAGE_PICKER = 'user-image';
/** @const */ var SCREEN_ERROR_MESSAGE = 'error-message';
/** @const */ var SCREEN_TPM_ERROR = 'tpm-error-message';
/** @const */ var SCREEN_PASSWORD_CHANGED = 'password-changed';
/** @const */ var SCREEN_APP_LAUNCH_SPLASH = 'app-launch-splash';
/** @const */ var SCREEN_ARC_KIOSK_SPLASH = 'arc-kiosk-splash';
/** @const */ var SCREEN_CONFIRM_PASSWORD = 'confirm-password';
/** @const */ var SCREEN_FATAL_ERROR = 'fatal-error';
/** @const */ var SCREEN_KIOSK_ENABLE = 'kiosk-enable';
/** @const */ var SCREEN_TERMS_OF_SERVICE = 'terms-of-service';
/** @const */ var SCREEN_ARC_TERMS_OF_SERVICE = 'arc-tos';
/** @const */ var SCREEN_WRONG_HWID = 'wrong-hwid';
/** @const */ var SCREEN_DEVICE_DISABLED = 'device-disabled';
/** @const */ var SCREEN_UPDATE_REQUIRED = 'update-required';
/** @const */ var SCREEN_UNRECOVERABLE_CRYPTOHOME_ERROR =
    'unrecoverable-cryptohome-error';
/** @const */ var SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE =
    'ad-password-change';
/** @const */ var SCREEN_SYNC_CONSENT = 'sync-consent';
/** @const */ var SCREEN_FINGERPRINT_SETUP = 'fingerprint-setup';
/** @const */ var SCREEN_RECOMMEND_APPS = 'recommend-apps';
/** @const */ var SCREEN_APP_DOWNLOADING = 'app-downloading';
/** @const */ var SCREEN_DISCOVER = 'discover';
/** @const */ var SCREEN_MARKETING_OPT_IN = 'marketing-opt-in';

/* Accelerator identifiers. Must be kept in sync with webui_login_view.cc. */
/** @const */ var ACCELERATOR_CANCEL = 'cancel';
/** @const */ var ACCELERATOR_ENABLE_DEBBUGING = 'debugging';
/** @const */ var ACCELERATOR_ENROLLMENT = 'enrollment';
/** @const */ var ACCELERATOR_KIOSK_ENABLE = 'kiosk_enable';
/** @const */ var ACCELERATOR_VERSION = 'version';
/** @const */ var ACCELERATOR_RESET = 'reset';
/** @const */ var ACCELERATOR_DEVICE_REQUISITION = 'device_requisition';
/** @const */ var ACCELERATOR_DEVICE_REQUISITION_REMORA =
    'device_requisition_remora';
/** @const */ var ACCELERATOR_APP_LAUNCH_BAILOUT = 'app_launch_bailout';
/** @const */ var ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG =
    'app_launch_network_config';
/** @const */ var ACCELERATOR_DEMO_MODE = "demo_mode";
/** @const */ var ACCELERATOR_SEND_FEEDBACK = "send_feedback";

/* Signin UI state constants. Used to control header bar UI. */
/** @const */ var SIGNIN_UI_STATE = {
  HIDDEN: 0,
  GAIA_SIGNIN: 1,
  ACCOUNT_PICKER: 2,
  WRONG_HWID_WARNING: 3,
  DEPRECATED_SUPERVISED_USER_CREATION_FLOW: 4,
  SAML_PASSWORD_CONFIRM: 5,
  PASSWORD_CHANGED: 6,
  ENROLLMENT: 7,
  ERROR: 8,
  SYNC_CONSENT: 9,
};

/* Possible UI states of the error screen. */
/** @const */ var ERROR_SCREEN_UI_STATE = {
  UNKNOWN: 'ui-state-unknown',
  UPDATE: 'ui-state-update',
  SIGNIN: 'ui-state-signin',
  KIOSK_MODE: 'ui-state-kiosk-mode',
  LOCAL_STATE_ERROR: 'ui-state-local-state-error',
  AUTO_ENROLLMENT_ERROR: 'ui-state-auto-enrollment-error',
  ROLLBACK_ERROR: 'ui-state-rollback-error'
};

/* Possible types of UI. */
/** @const */ var DISPLAY_TYPE = {
  UNKNOWN: 'unknown',
  OOBE: 'oobe',
  LOGIN: 'login',
  LOCK: 'lock',
  USER_ADDING: 'user-adding',
  APP_LAUNCH_SPLASH: 'app-launch-splash',
  ARC_KIOSK_SPLASH: 'arc-kiosk-splash',
  DESKTOP_USER_MANAGER: 'login-add-user',
  GAIA_SIGNIN: 'gaia-signin'
};

/* Possible lock screen enabled app activity state. */
/** @const */ var LOCK_SCREEN_APPS_STATE = {
  // No lock screen enabled app available.
  NONE: 'LOCK_SCREEN_APPS_STATE.NONE',
  // A lock screen enabled note taking app is available, but has not been
  // launched to handle a lock screen action.
  AVAILABLE: 'LOCK_SCREEN_APPS_STATE.AVAILABLE',
  // A lock screen enabled app is running in background - behind lock screen UI.
  BACKGROUND: 'LOCK_SCREEN_APPS_STATE.BACKGROUND',
  // A lock screen enabled app is running in foreground - an app window is
  // shown over the lock screen user pods (header bar should still be visible).
  FOREGROUND: 'LOCK_SCREEN_APPS_STATE.FOREGROUND',
};

/** @const */ var USER_ACTION_ROLLBACK_TOGGLED = 'rollback-toggled';

cr.define('cr.ui.login', function() {
  var Bubble = cr.ui.Bubble;

  /**
   * Maximum time in milliseconds to wait for step transition to finish.
   * The value is used as the duration for ensureTransitionEndEvent below.
   * It needs to be inline with the step screen transition duration time
   * defined in css file. The current value in css is 200ms. To avoid emulated
   * transitionend fired before real one, 250ms is used.
   * @const
   */
  var MAX_SCREEN_TRANSITION_DURATION = 250;

  /**
   * Groups of screens (screen IDs) that should have the same dimensions.
   * @type Array<Array<string>>
   * @const
   */
  var SCREEN_GROUPS = [[
    SCREEN_OOBE_WELCOME, SCREEN_OOBE_NETWORK, SCREEN_OOBE_EULA,
    SCREEN_OOBE_UPDATE, SCREEN_OOBE_AUTO_ENROLLMENT_CHECK
  ]];
  /**
   * Group of screens (screen IDs) where factory-reset screen invocation is
   * available.
   * @type Array<string>
   * @const
   */
  var RESET_AVAILABLE_SCREEN_GROUP = [
    SCREEN_OOBE_WELCOME,
    SCREEN_OOBE_NETWORK,
    SCREEN_OOBE_EULA,
    SCREEN_OOBE_UPDATE,
    SCREEN_OOBE_ENROLLMENT,
    SCREEN_OOBE_AUTO_ENROLLMENT_CHECK,
    SCREEN_GAIA_SIGNIN,
    SCREEN_ACCOUNT_PICKER,
    SCREEN_KIOSK_ENABLE,
    SCREEN_ERROR_MESSAGE,
    SCREEN_USER_IMAGE_PICKER,
    SCREEN_TPM_ERROR,
    SCREEN_PASSWORD_CHANGED,
    SCREEN_TERMS_OF_SERVICE,
    SCREEN_ARC_TERMS_OF_SERVICE,
    SCREEN_WRONG_HWID,
    SCREEN_CONFIRM_PASSWORD,
    SCREEN_UPDATE_REQUIRED,
    SCREEN_FATAL_ERROR,
    SCREEN_SYNC_CONSENT,
    SCREEN_RECOMMEND_APPS,
    SCREEN_APP_DOWNLOADING,
    SCREEN_DISCOVER,
    SCREEN_MARKETING_OPT_IN,
  ];

  /**
   * Group of screens (screen IDs) where enable debuggingscreen invocation is
   * available.
   * @type Array<string>
   * @const
   */
  var ENABLE_DEBUGGING_AVAILABLE_SCREEN_GROUP = [
    SCREEN_OOBE_HID_DETECTION,
    SCREEN_OOBE_WELCOME,
    SCREEN_OOBE_NETWORK,
    SCREEN_OOBE_EULA,
    SCREEN_OOBE_UPDATE,
    SCREEN_TERMS_OF_SERVICE
  ];

  /**
   * Group of screens (screen IDs) that are not participating in
   * left-current-right animation.
   * @type Array<string>
   * @const
   */
  var NOT_ANIMATED_SCREEN_GROUP = [
    SCREEN_OOBE_ENABLE_DEBUGGING,
    SCREEN_OOBE_RESET,
  ];

  /**
   * Group of screens (screen IDs) where demo mode setup invocation is
   * available.
   * @type Array<string>
   * @const
   */
  var DEMO_MODE_SETUP_AVAILABLE_SCREEN_GROUP = [
    SCREEN_OOBE_WELCOME,
  ];

  /**
   * OOBE screens group index.
   */
  var SCREEN_GROUP_OOBE = 0;

  /**
   * Constructor a display manager that manages initialization of screens,
   * transitions, error messages display.
   *
   * @constructor
   */
  function DisplayManager() {
  }

  DisplayManager.prototype = {
    /**
     * Registered screens.
     */
    screens_: [],

    /**
     * Current OOBE step, index in the screens array.
     * @type {number}
     */
    currentStep_: 0,

    /**
     * Whether version label can be toggled by ACCELERATOR_VERSION.
     * @type {boolean}
     */
    allowToggleVersion_: false,

    /**
     * Whether keyboard navigation flow is enforced.
     * @type {boolean}
     */
    forceKeyboardFlow_: false,

    /**
     * Whether the virtual keyboard is displayed.
     * @type {boolean}
     */
    virtualKeyboardShown: false,

    /**
     * Type of UI.
     * @type {string}
     */
    displayType_: DISPLAY_TYPE.UNKNOWN,

    /**
     * Number of users in the login screen UI. This is used by the views login
     * screen, and is always 0 for WebUI login screen.
     * TODO(crbug.com/808271): WebUI and views implementation should return the
     * same user list.
     * @type {number}
     */
    userCount_: 0,

    /**
     * Number of reloadContent() calls since start for testing.
     * @type {number}
     */
    reloadContentNumEvents_: 0,

    /**
     * Stored OOBE configuration for newly registered screens.
     * @type {!OobeTypes.OobeConfiguration}
     */
    oobe_configuration_: undefined,

    /**
     * Detects multi-tap gesture that invokes demo mode setup in OOBE.
     * @type {?MultiTapDetector}
     * @private
     */
    demoModeStartListener_: null,

    /**
     * Error message (bubble) was shown. This is checked in tests.
     */
    errorMessageWasShownForTesting_: false,

    get displayType() {
      return this.displayType_;
    },

    set displayType(displayType) {
      this.displayType_ = displayType;
      document.documentElement.setAttribute('screen', displayType);
    },

    get newKioskUI() {
      return loadTimeData.getString('newKioskUI') == 'on';
    },

    /**
     * Returns dimensions of screen exluding header bar.
     * @type {Object}
     */
    get clientAreaSize() {
      var container = $('outer-container');
      return {width: container.offsetWidth, height: container.offsetHeight};
    },

    /**
     * Gets current screen element.
     * @type {HTMLElement}
     */
    get currentScreen() {
      return $(this.screens_[this.currentStep_]);
    },

    /**
     * Hides/shows header (Shutdown/Add User/Cancel buttons).
     * @param {boolean} hidden Whether header is hidden.
     * TODO(crbug/914578): talk to the views login shelf through Mojo.
     */
    get headerHidden() {
      return $('login-header-bar').hidden;
    },

    set headerHidden(hidden) {
      if (this.showingViewsBasedShelf && !hidden) {
        // When views-based shelf is enabled, toggling header bar visibility
        // is handled by ash. Prevent showing a duplicate header bar here.
        return;
      }
      $('login-header-bar').hidden = hidden;
    },

    /**
     * The header bar should be hidden when views-based shelf is shown.
     */
    get showingViewsBasedShelf() {
      // TODO: remove this method once webui shelf has been removed.
      return true;
    },

    /**
     * Returns true if we are showing views based login screen.
     * @return {boolean}
     */
    get showingViewsLogin() {
      return loadTimeData.valueExists('showViewsLogin') &&
          loadTimeData.getString('showViewsLogin') == 'on' &&
          (this.displayType_ == DISPLAY_TYPE.GAIA_SIGNIN);
    },

    /**
     * Returns true if the login screen has user pods.
     * @return {boolean}
     */
    get hasUserPods() {
      var userCount =
          this.showingViewsLogin ? this.userCount_ : $('pod-row').pods.length;
      return !!userCount;
    },

    /**
     * Sets the current size of the client area (display size).
     * @param {number} width client area width
     * @param {number} height client area height
     */
    setClientAreaSize: function(width, height) {
      var clientArea = $('outer-container');
      var bottom = parseInt(window.getComputedStyle(clientArea).bottom);
      clientArea.style.minHeight = cr.ui.toCssPx(height - bottom);
    },

    /**
     * Toggles background of main body between transparency and solid.
     * @param {boolean} solid Whether to show a solid background.
     */
    set solidBackground(solid) {
      if (solid)
        document.body.classList.add('solid');
      else
        document.body.classList.remove('solid');
    },

    /**
     * Forces keyboard based OOBE navigation.
     * @param {boolean} value True if keyboard navigation flow is forced.
     */
    set forceKeyboardFlow(value) {
      this.forceKeyboardFlow_ = value;
      if (value) {
        keyboard.initializeKeyboardFlow(false);
        for (var i = 0; i < this.screens_.length; ++i) {
          var screen = $(this.screens_[i]);
          if (screen.enableKeyboardFlow)
            screen.enableKeyboardFlow();
        }
      }
    },

    /**
     * Returns true if keyboard flow is enabled.
     * @return {boolean}
     */
    get forceKeyboardFlow() {
      return this.forceKeyboardFlow_;
    },

    /**
     * Returns current OOBE configuration.
     * @return {!OobeTypes.OobeConfiguration}
     */
    getOobeConfiguration: function() {
      return this.oobe_configuration_;
    },

    /**
     * Shows/hides version labels.
     * @param {boolean} show Whether labels should be visible by default. If
     *     false, visibility can be toggled by ACCELERATOR_VERSION.
     */
    showVersion: function(show) {
      $('version-labels').hidden = !show;
      this.allowToggleVersion_ = !show;
    },

    /**
     * Sets the number of users on the views login screen.
     * @param {number} userCount The number of users.
     */
    setLoginUserCount: function(userCount) {
      this.userCount_ = userCount;
    },

    /**
     * Handle accelerators.
     * @param {string} name Accelerator name.
     */
    handleAccelerator: function(name) {
      if (this.currentScreen && this.currentScreen.ignoreAccelerators) {
        return;
      }
      var currentStepId = this.screens_[this.currentStep_];
      if (name == ACCELERATOR_CANCEL) {
        if (this.currentScreen && this.currentScreen.cancel) {
          this.currentScreen.cancel();
        }
      } else if (name == ACCELERATOR_ENABLE_DEBBUGING) {
        if (ENABLE_DEBUGGING_AVAILABLE_SCREEN_GROUP.indexOf(currentStepId) !=
            -1) {
          chrome.send('toggleEnableDebuggingScreen');
        }
      } else if (name == ACCELERATOR_ENROLLMENT) {
        if (currentStepId == SCREEN_GAIA_SIGNIN ||
            currentStepId == SCREEN_ACCOUNT_PICKER) {
          chrome.send('toggleEnrollmentScreen');
        } else if (
            currentStepId == SCREEN_OOBE_WELCOME ||
            currentStepId == SCREEN_OOBE_NETWORK ||
            currentStepId == SCREEN_OOBE_EULA) {
          // In this case update check will be skipped and OOBE will
          // proceed straight to enrollment screen when EULA is accepted.
          chrome.send('skipUpdateEnrollAfterEula');
        }
      } else if (name == ACCELERATOR_KIOSK_ENABLE) {
        if (currentStepId == SCREEN_GAIA_SIGNIN ||
            currentStepId == SCREEN_ACCOUNT_PICKER) {
          chrome.send('toggleKioskEnableScreen');
        }
      } else if (name == ACCELERATOR_VERSION) {
        if (this.allowToggleVersion_)
          $('version-labels').hidden = !$('version-labels').hidden;
      } else if (name == ACCELERATOR_RESET) {
        if (currentStepId == SCREEN_OOBE_RESET)
          $('reset').send(
              login.Screen.CALLBACK_USER_ACTED, USER_ACTION_ROLLBACK_TOGGLED);
        else if (RESET_AVAILABLE_SCREEN_GROUP.indexOf(currentStepId) != -1)
          chrome.send('toggleResetScreen');
      } else if (name == ACCELERATOR_DEVICE_REQUISITION) {
        if (this.isOobeUI())
          this.showDeviceRequisitionPrompt_();
      } else if (name == ACCELERATOR_DEVICE_REQUISITION_REMORA) {
        if (this.isOobeUI())
          this.showDeviceRequisitionRemoraPrompt_(
              'deviceRequisitionRemoraPromptText', 'remora');
      } else if (name == ACCELERATOR_APP_LAUNCH_BAILOUT) {
        if (currentStepId == SCREEN_APP_LAUNCH_SPLASH)
          chrome.send('cancelAppLaunch');
        if (currentStepId == SCREEN_ARC_KIOSK_SPLASH)
          chrome.send('cancelArcKioskLaunch');
      } else if (name == ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG) {
        if (currentStepId == SCREEN_APP_LAUNCH_SPLASH)
          chrome.send('networkConfigRequest');
      } else if (name == ACCELERATOR_DEMO_MODE) {
        this.startDemoModeFlow();
      } else if (name == ACCELERATOR_SEND_FEEDBACK) {
        chrome.send('sendFeedback');
      }
    },

    /**
     * Appends buttons to the button strip.
     * @param {Array<HTMLElement>} buttons Array with the buttons to append.
     * @param {string} screenId Id of the screen that buttons belong to.
     */
    appendButtons_: function(buttons, screenId) {
      if (buttons) {
        var buttonStrip = $(screenId + '-controls');
        if (buttonStrip) {
          for (var i = 0; i < buttons.length; ++i)
            buttonStrip.appendChild(buttons[i]);
        }
      }
    },

    /**
     * Disables or enables control buttons on the specified screen.
     * @param {HTMLElement} screen Screen which controls should be affected.
     * @param {boolean} disabled Whether to disable controls.
     */
    disableButtons_: function(screen, disabled) {
      var buttons = document.querySelectorAll(
          '#' + screen.id + '-controls button:not(.preserve-disabled-state)');
      for (var i = 0; i < buttons.length; ++i) {
        buttons[i].disabled = disabled;
      }
    },

    screenIsAnimated_: function(screenId) {
      return NOT_ANIMATED_SCREEN_GROUP.indexOf(screenId) != -1;
    },

    /**
     * Updates a step's css classes to reflect left, current, or right position.
     * @param {number} stepIndex step index.
     * @param {string} state one of 'left', 'current', 'right'.
     */
    updateStep_: function(stepIndex, state) {
      var stepId = this.screens_[stepIndex];
      var step = $(stepId);
      var header = $('header-' + stepId);
      var states = ['left', 'right', 'current'];
      for (var i = 0; i < states.length; ++i) {
        if (states[i] != state) {
          step.classList.remove(states[i]);
          header.classList.remove(states[i]);
        }
      }

      step.classList.add(state);
      header.classList.add(state);
    },

    /**
     * Switches to the next OOBE step.
     * @param {number} nextStepIndex Index of the next step.
     */
    toggleStep_: function(nextStepIndex, screenData) {
      var currentStepId = this.screens_[this.currentStep_];
      var nextStepId = this.screens_[nextStepIndex];
      var oldStep = $(currentStepId);
      var newStep = $(nextStepId);
      var newHeader = $('header-' + nextStepId);

      // Disable controls before starting animation.
      this.disableButtons_(oldStep, true);

      if (oldStep.onBeforeHide)
        oldStep.onBeforeHide();

      $('oobe').className = nextStepId;

      // Need to do this before calling newStep.onBeforeShow() so that new step
      // is back in DOM tree and has correct offsetHeight / offsetWidth.
      newStep.hidden = false;

      if (newStep.onBeforeShow)
        newStep.onBeforeShow(screenData);

      // We still have several screens that are not implemented as a single
      // Polymer-element, so we need to explicitly inform all oobe-dialogs.
      //
      // TODO(alemate): make every screen a single Polymer element, so that
      // we could simply use OobeDialogHostBehavior in stead of this.
      for(let dialog of newStep.getElementsByTagName('oobe-dialog'))
        dialog.onBeforeShow();

      if (newStep.defaultControl && newStep.defaultControl.onBeforeShow)
        newStep.defaultControl.onBeforeShow();

      newStep.classList.remove('hidden');

      if (this.isOobeUI() && this.screenIsAnimated_(nextStepId) &&
          this.screenIsAnimated_(currentStepId)) {
        // Start gliding animation for OOBE steps.
        if (nextStepIndex > this.currentStep_) {
          for (var i = this.currentStep_; i < nextStepIndex; ++i)
            this.updateStep_(i, 'left');
          this.updateStep_(nextStepIndex, 'current');
        } else if (nextStepIndex < this.currentStep_) {
          for (var i = this.currentStep_; i > nextStepIndex; --i)
            this.updateStep_(i, 'right');
          this.updateStep_(nextStepIndex, 'current');
        }
      } else {
        // Start fading animation for login display or reset screen.
        oldStep.classList.add('faded');
        newStep.classList.remove('faded');
        if (!this.screenIsAnimated_(nextStepId)) {
          newStep.classList.remove('left');
          newStep.classList.remove('right');
        }
      }

      this.disableButtons_(newStep, false);

      // Adjust inner container height based on new step's height.
      this.updateScreenSize(newStep);

      if (newStep.onAfterShow)
        newStep.onAfterShow(screenData);

      // Workaround for gaia and welcome screens.
      // Due to other origin iframe and long ChromeVox focusing correspondingly
      // passive aria-label title is not pronounced.
      // Gaia hack can be removed on fixed crbug.com/316726.
      if (nextStepId == SCREEN_GAIA_SIGNIN ||
          nextStepId == SCREEN_OOBE_ENROLLMENT) {
        newStep.setAttribute(
            'aria-label', loadTimeData.getString('signinScreenTitle'));
      }

      // Default control to be focused (if specified).
      var defaultControl = newStep.defaultControl;

      var outerContainer = $('outer-container');
      var innerContainer = $('inner-container');
      var isOOBE = this.isOobeUI();
      if (this.currentStep_ != nextStepIndex &&
          !oldStep.classList.contains('hidden')) {
        if (oldStep.classList.contains('animated')) {
          innerContainer.classList.add('animation');
          oldStep.addEventListener('transitionend', function f(e) {
            oldStep.removeEventListener('transitionend', f);
            if (oldStep.classList.contains('faded') ||
                oldStep.classList.contains('left') ||
                oldStep.classList.contains('right')) {
              innerContainer.classList.remove('animation');
              oldStep.classList.add('hidden');
              if (!isOOBE)
                oldStep.hidden = true;
            }
            // Refresh defaultControl. It could have changed.
            var defaultControl = newStep.defaultControl;
            if (defaultControl)
              defaultControl.focus();
          });
          ensureTransitionEndEvent(oldStep, MAX_SCREEN_TRANSITION_DURATION);
        } else {
          oldStep.classList.add('hidden');
          oldStep.hidden = true;
          if (defaultControl)
            defaultControl.focus();
        }
      } else {
        // First screen on OOBE launch.
        if (this.isOobeUI() && innerContainer.classList.contains('down')) {
          innerContainer.classList.remove('down');
          innerContainer.addEventListener('transitionend', function f(e) {
            innerContainer.removeEventListener('transitionend', f);
            outerContainer.classList.remove('down');
            chrome.send('loginVisible', ['oobe']);
            // Refresh defaultControl. It could have changed.
            var defaultControl = newStep.defaultControl;
            if (defaultControl)
              defaultControl.focus();
          });
          ensureTransitionEndEvent(
              innerContainer, MAX_SCREEN_TRANSITION_DURATION);
        } else {
          if (defaultControl)
            defaultControl.focus();
          chrome.send('loginVisible', ['oobe']);
        }
      }
      this.currentStep_ = nextStepIndex;

      $('step-logo').hidden = newStep.classList.contains('no-logo');

      $('oobe').dispatchEvent(
          new CustomEvent('screenchanged', {detail: this.currentScreen.id}));
      chrome.send('updateCurrentScreen', [this.currentScreen.id]);
    },

    /**
     * Make sure that screen is initialized and decorated.
     * @param {Object} screen Screen params dict, e.g. {id: screenId, data: {}}.
     */
    preloadScreen: function(screen) {
      var screenEl = $(screen.id);
      if (screenEl.deferredInitialization !== undefined) {
        screenEl.deferredInitialization();
        delete screenEl.deferredInitialization;
      }
    },

    /**
     * Show screen of given screen id.
     * @param {Object} screen Screen params dict, e.g. {id: screenId, data: {}}.
     */
    showScreen: function(screen) {
      // Do not allow any other screen to clobber the device disabled screen.
      if (this.currentScreen.id == SCREEN_DEVICE_DISABLED)
        return;

      // Prevent initial GAIA signin load from interrupting the kiosk splash
      // screen.
      // TODO: remove this special case when a better fix is found for the race
      // condition. This if statement was introduced to fix http://b/113786350.
      if ((this.currentScreen.id == SCREEN_APP_LAUNCH_SPLASH ||
           this.currentScreen.id == SCREEN_ARC_KIOSK_SPLASH) &&
          screen.id == SCREEN_GAIA_SIGNIN) {
        console.log(
            this.currentScreen.id +
            ' screen showing. Ignoring switch to Gaia screen.');
        return;
      }

      var screenId = screen.id;
      if (screenId == SCREEN_ACCOUNT_PICKER && this.showingViewsLogin) {
        chrome.send('hideOobeDialog');
        return;
      }

      // Make sure the screen is decorated.
      this.preloadScreen(screen);

      if (screen.data !== undefined && screen.data.disableAddUser)
        DisplayManager.updateAddUserButtonStatus(true);


      // Show sign-in screen instead of account picker if pod row is empty.
      if (screenId == SCREEN_ACCOUNT_PICKER && $('pod-row').pods.length == 0 &&
          cr.isChromeOS) {
        // Manually hide 'add-user' header bar, because of the case when
        // 'Cancel' button is used on the offline login page.
        $('add-user-header-bar-item').hidden = true;
        Oobe.showSigninUI();
        return;
      }

      var data = screen.data;
      var index = this.getScreenIndex_(screenId);
      if (index >= 0)
        this.toggleStep_(index, data);
    },

    /**
     * Gets index of given screen id in screens_.
     * @param {string} screenId Id of the screen to look up.
     * @private
     */
    getScreenIndex_: function(screenId) {
      for (let i = 0; i < this.screens_.length; ++i) {
        if (this.screens_[i] == screenId)
          return i;
      }
      return -1;
    },

    /**
     * Register an oobe screen.
     * @param {Element} el Decorated screen element.
     */
    registerScreen: function(el) {
      var screenId = el.id;
      this.screens_.push(screenId);

      var header = document.createElement('span');
      header.id = 'header-' + screenId;
      header.textContent = el.header ? el.header : '';
      header.className = 'header-section';
      $('header-sections').appendChild(header);
      this.appendButtons_(el.buttons, screenId);

      if (el.updateOobeConfiguration && this.oobe_configuration_)
        el.updateOobeConfiguration(this.oobe_configuration_);
    },

    /**
     * Updates inner container size based on the size of the current screen and
     * other screens in the same group.
     * Should be executed on screen change / screen size change.
     * @param {!HTMLElement} screen Screen that is being shown.
     */
    updateScreenSize: function(screen) {
      // Have to reset any previously predefined screen size first
      // so that screen contents would define it instead.
      $('inner-container').style.height = '';
      $('inner-container').style.width = '';
      screen.style.width = '';
      screen.style.height = '';

      $('outer-container').classList.toggle(
        'fullscreen', screen.classList.contains('fullscreen'));

      var width = screen.getPreferredSize().width;
      var height = screen.getPreferredSize().height;
      for (let i = 0; i < SCREEN_GROUPS.length; ++i) {
        let screenGroup = SCREEN_GROUPS[i];
        if (screenGroup.indexOf(screen.id) != -1) {
          // Set screen dimensions to maximum dimensions within this group.
          for (let j = 0; j < screenGroup.length; ++j) {
            let screen2 = $(screenGroup[j]);
            width = Math.max(width, screen2.getPreferredSize().width);
            height = Math.max(height, screen2.getPreferredSize().height);
          }
          break;
        }
      }

      if (screen.classList.contains('fullscreen')) {
        $('inner-container').style.height = '100%';
        $('inner-container').style.width = '100%';
      } else {
        $('inner-container').style.height = height + 'px';
        $('inner-container').style.width = width + 'px';
      }
      // This requires |screen| to have 'box-sizing: border-box'.
      screen.style.width = width + 'px';
      screen.style.height = height + 'px';
      screen.style.margin = 'auto';

      if (this.showingViewsLogin) {
        chrome.send('updateOobeDialogSize', [width, height]);
        $('scroll-container').classList.toggle('disable-scroll', true);
        $('inner-container').classList.toggle('disable-scroll', true);
        $('inner-container').style.top =
            cr.ui.toCssPx($('scroll-container').scrollTop);
      }
    },

    /**
     * Updates localized content of the screens like headers, buttons and links.
     * Should be executed on language change.
     */
    updateLocalizedContent_: function() {
      for (let i = 0; i < this.screens_.length; ++i) {
        let screenId = this.screens_[i];
        var screen = $(screenId);
        var buttonStrip = $(screenId + '-controls');
        if (buttonStrip)
          buttonStrip.innerHTML = '';
        // TODO(nkostylev): Update screen headers for new OOBE design.
        this.appendButtons_(screen.buttons, screenId);
        if (screen.updateLocalizedContent)
          screen.updateLocalizedContent();
      }
      var isInTabletMode = loadTimeData.getBoolean('isInTabletMode');
      this.setTabletModeState_(isInTabletMode);

      var currentScreenId = this.screens_[this.currentStep_];
      var currentScreen = $(currentScreenId);
      this.updateScreenSize(currentScreen);
      ++this.reloadContentNumEvents_;
    },

    /**
     * Updates Oobe configuration for screens.
     * @param {!OobeTypes.OobeConfiguration} configuration OOBE configuration.
     */
    updateOobeConfiguration_: function(configuration) {
      this.oobe_configuration_ = configuration;
      for (let i = 0; i < this.screens_.length; ++i) {
        let screenId = this.screens_[i];
        var screen = $(screenId);
        if (screen.updateOobeConfiguration)
          screen.updateOobeConfiguration(configuration);
      }
    },

    /**
     * Updates "device in tablet mode" state when tablet mode is changed.
     * @param {Boolean} isInTabletMode True when in tablet mode.
     */
    setTabletModeState_: function(isInTabletMode) {
      for (let i = 0; i < this.screens_.length; ++i) {
        let screenId = this.screens_[i];
        var screen = $(screenId);
        if (screen.setTabletModeState)
          screen.setTabletModeState(isInTabletMode);
      }
    },

    /**
     * Initialized first group of OOBE screens.
     */
    initializeOOBEScreens: function() {
      if (this.isOobeUI() && $('inner-container').classList.contains('down')) {
        for (let i = 0; i < SCREEN_GROUPS[SCREEN_GROUP_OOBE].length; ++i) {
          let screen = $(SCREEN_GROUPS[SCREEN_GROUP_OOBE][i]);
          screen.hidden = false;
        }
      }
    },

    /** Initializes demo mode start listener. */
    initializeDemoModeMultiTapListener: function() {
      if (this.displayType_ == DISPLAY_TYPE.OOBE) {
        this.demoModeStartListener_ = new MultiTapDetector(
            $('outer-container'), 10, this.startDemoModeFlow.bind(this));
      }
    },

    /**
     * Prepares screens to use in login display.
     */
    prepareForLoginDisplay_: function() {
      for (var i = 0, screenId; screenId = this.screens_[i]; ++i) {
        var screen = $(screenId);
        screen.classList.add('faded');
        screen.classList.remove('right');
        screen.classList.remove('left');
      }
      if (this.showingViewsLogin) {
        $('top-header-bar').hidden = true;
      }
    },

    /**
     * Shows the device requisition prompt.
     */
    showDeviceRequisitionPrompt_: function() {
      if (!this.deviceRequisitionDialog_) {
        this.deviceRequisitionDialog_ =
            new cr.ui.dialogs.PromptDialog(document.body);
        this.deviceRequisitionDialog_.setOkLabel(
            loadTimeData.getString('deviceRequisitionPromptOk'));
        this.deviceRequisitionDialog_.setCancelLabel(
            loadTimeData.getString('deviceRequisitionPromptCancel'));
      }
      this.deviceRequisitionDialog_.show(
          loadTimeData.getString('deviceRequisitionPromptText'),
          this.deviceRequisition_,
          this.onConfirmDeviceRequisitionPrompt_.bind(this));
    },

    /**
     * Confirmation handle for the device requisition prompt.
     * @param {string} value The value entered by the user.
     * @private
     */
    onConfirmDeviceRequisitionPrompt_: function(value) {
      this.deviceRequisition_ = value;
      chrome.send('setDeviceRequisition', [value == '' ? 'none' : value]);
    },

    /**
     * Called when window size changed. Notifies current screen about
     * change.
     * @private
     */
    onWindowResize_: function() {
      for (var i = 0, screenId; screenId = this.screens_[i]; ++i) {
        var screen = $(screenId);
        if (screen.onWindowResize)
          screen.onWindowResize();
      }
    },

    /*
     * Updates the device requisition string shown in the requisition
     * prompt.
     * @param {string} requisition The device requisition.
     */
    updateDeviceRequisition: function(requisition) {
      this.deviceRequisition_ = requisition;
    },

    /**
     * Shows the special remora/shark device requisition prompt.
     * @private
     */
    showDeviceRequisitionRemoraPrompt_: function(promptText, requisition) {
      if (!this.deviceRequisitionRemoraDialog_) {
        this.deviceRequisitionRemoraDialog_ =
            new cr.ui.dialogs.ConfirmDialog(document.body);
        this.deviceRequisitionRemoraDialog_.setOkLabel(
            loadTimeData.getString('deviceRequisitionRemoraPromptOk'));
        this.deviceRequisitionRemoraDialog_.setCancelLabel(
            loadTimeData.getString('deviceRequisitionRemoraPromptCancel'));
      }
      this.deviceRequisitionRemoraDialog_.show(
          loadTimeData.getString(promptText),
          function() {  // onShow
            chrome.send('setDeviceRequisition', [requisition]);
          },
          function() {  // onCancel
            chrome.send('setDeviceRequisition', ['none']);
          });
    },

    /**
     * Starts demo mode flow. Shows the enable demo mode dialog if needed.
     */
    startDemoModeFlow: function() {
      var isDemoModeEnabled = loadTimeData.getBoolean('isDemoModeEnabled');
      if (!isDemoModeEnabled) {
        console.warn('Cannot setup demo mode, because it is disabled.');
        return;
      }

      var currentStepId = this.screens_[this.currentStep_];
      if (!DEMO_MODE_SETUP_AVAILABLE_SCREEN_GROUP.includes(currentStepId))
        return;

      if (!this.enableDemoModeDialog_) {
        this.enableDemoModeDialog_ =
            new cr.ui.dialogs.ConfirmDialog(document.body);
        this.enableDemoModeDialog_.setOkLabel(
            loadTimeData.getString('enableDemoModeDialogConfirm'));
        this.enableDemoModeDialog_.setCancelLabel(
            loadTimeData.getString('enableDemoModeDialogCancel'));
      }
      var configuration = Oobe.getInstance().getOobeConfiguration();
      if (configuration && configuration.enableDemoMode) {
        // Bypass showing dialog.
        chrome.send('setupDemoMode');
      } else {
        this.enableDemoModeDialog_.showWithTitle(
            loadTimeData.getString('enableDemoModeDialogTitle'),
            loadTimeData.getString('enableDemoModeDialogText'),
            function() {  // onOk
              chrome.send('setupDemoMode');
            });
      }
    },

    /**
     * Returns true if Oobe UI is shown.
     */
    isOobeUI: function() {
      return document.body.classList.contains('oobe-display');
    },

    /**
     * Sets or unsets given |className| for top-level container. Useful
     * for customizing #inner-container with CSS rules. All classes set
     * with with this method will be removed after screen change.
     * @param {string} className Class to toggle.
     * @param {boolean} enabled Whether class should be enabled or disabled.
     */
    toggleClass: function(className, enabled) {
      $('oobe').classList.toggle(className, enabled);
    },

    /**
     * Notifies the C++ handler in views login that the OOBE signin state has
     * been updated. This information is primarily used by the login shelf to
     * update button visibility state.
     * @param {number} state The state (see SIGNIN_UI_STATE) of the OOBE UI.
     */
    setSigninUIState: function(state) {
      if (Oobe.getInstance().showingViewsLogin)
        chrome.send('updateSigninUIState', [state]);
    },

  };

  /**
   * Initializes display manager.
   */
  DisplayManager.initialize = function() {
    var givenDisplayType = DISPLAY_TYPE.UNKNOWN;
    if (document.documentElement.hasAttribute('screen')) {
      // Display type set in HTML property.
      givenDisplayType = document.documentElement.getAttribute('screen');
    } else {
      // Extracting display type from URL.
      givenDisplayType = window.location.pathname.substr(1);
    }
    var instance = Oobe.getInstance();
    Object.getOwnPropertyNames(DISPLAY_TYPE).forEach(function(type) {
      if (DISPLAY_TYPE[type] == givenDisplayType) {
        instance.displayType = givenDisplayType;
      }
    });
    if (instance.displayType == DISPLAY_TYPE.UNKNOWN) {
      console.error(
          'Unknown display type "' + givenDisplayType +
          '". Setting default.');
      instance.displayType = DISPLAY_TYPE.LOGIN;
    }

    instance.initializeOOBEScreens();
    instance.initializeDemoModeMultiTapListener();

    window.addEventListener('resize', instance.onWindowResize_.bind(instance));
  };

  /**
   * Returns offset (top, left) of the element.
   * @param {!Element} element HTML element.
   * @return {!Object} The offset (top, left).
   */
  DisplayManager.getOffset = function(element) {
    var x = 0;
    var y = 0;
    while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
      x += element.offsetLeft - element.scrollLeft;
      y += element.offsetTop - element.scrollTop;
      element = element.offsetParent;
    }
    return { top: y, left: x };
  };

  /**
   * Returns position (top, left, right, bottom) of the element.
   * @param {!Element} element HTML element.
   * @return {!Object} Element position (top, left, right, bottom).
   */
  DisplayManager.getPosition = function(element) {
    var offset = DisplayManager.getOffset(element);
    return {
      top: offset.top,
      right: window.innerWidth - element.offsetWidth - offset.left,
      bottom: window.innerHeight - element.offsetHeight - offset.top,
      left: offset.left
    };
  };

  /**
   * Disables signin UI.
   */
  DisplayManager.disableSigninUI = function() {
    $('pod-row').disabled = true;
  };

  /**
   * Shows signin UI.
   * @param {string} opt_email An optional email for signin UI.
   */
  DisplayManager.showSigninUI = function(opt_email) {
    var currentScreenId = Oobe.getInstance().currentScreen.id;
    if (currentScreenId == SCREEN_GAIA_SIGNIN)
      Oobe.getInstance().setSigninUIState(SIGNIN_UI_STATE.GAIA_SIGNIN);
    chrome.send('showAddUser', [opt_email]);
  };

  /**
   * Resets sign-in input fields.
   * @param {boolean} forceOnline Whether online sign-in should be forced.
   *     If |forceOnline| is false previously used sign-in type will be used.
   */
  DisplayManager.resetSigninUI = function(forceOnline) {
    var currentScreenId = Oobe.getInstance().currentScreen.id;

    if ($(SCREEN_GAIA_SIGNIN))
      $(SCREEN_GAIA_SIGNIN)
          .reset(currentScreenId == SCREEN_GAIA_SIGNIN, forceOnline);
    $('pod-row').reset(currentScreenId == SCREEN_ACCOUNT_PICKER);
  };

  /**
   * Creates a div element used to display error message in an error bubble.
   *
   * @param {string} message The error message.
   * @param {string} link Text to use for help link.
   * @param {number} helpId Help topic Id associated with help link.
   * @return {!HTMLElement} The error bubble content.
   */
  DisplayManager.createErrorElement_ = function(message, link, helpId) {
    var error = document.createElement('div');

    var messageDiv = document.createElement('div');
    messageDiv.className = 'error-message-bubble';
    messageDiv.textContent = message;
    error.appendChild(messageDiv);

    if (link) {
      messageDiv.classList.add('error-message-bubble-padding');

      var helpLink = document.createElement('a');
      helpLink.href = '#';
      helpLink.textContent = link;
      helpLink.addEventListener('click', function(e) {
        chrome.send('launchHelpApp', [helpId]);
        e.preventDefault();
      });
      error.appendChild(helpLink);
    }

    error.setAttribute('aria-live', 'assertive');
    return error;
  };

  /**
   * Shows sign-in error bubble.
   * @param {number} loginAttempts Number of login attemps tried.
   * @param {string} message Error message to show.
   * @param {string} link Text to use for help link.
   * @param {number} helpId Help topic Id associated with help link.
   */
  DisplayManager.showSignInError = function(
      loginAttempts, message, link, helpId) {
    var error = DisplayManager.createErrorElement_(message, link, helpId);

    var currentScreen = Oobe.getInstance().currentScreen;
    if (currentScreen && typeof currentScreen.showErrorBubble === 'function') {
      currentScreen.showErrorBubble(loginAttempts, error);
      this.errorMessageWasShownForTesting_ = true;
    }
  };

  /**
   * Shows a warning to the user that the detachable base (keyboard) different
   * than the one previously used by the user got attached to the device. It
   * warn the user that the attached base might be untrusted.
   *
   * @param {string} username The username of the user with which the error
   *     bubble is associated. For example, in the account picker screen, it
   *     identifies the user pod under which the error bubble should be shown.
   * @param {string} message Error message to show.
   * @param {string} link Text to use for help link.
   * @param {number} helpId Help topic Id associated with help link.
   */
  DisplayManager.showDetachableBaseChangedWarning = function(
      username, message, link, helpId) {
    var error = DisplayManager.createErrorElement_(message, link, helpId);

    var currentScreen = Oobe.getInstance().currentScreen;
    if (currentScreen &&
        typeof currentScreen.showDetachableBaseWarningBubble === 'function') {
      currentScreen.showDetachableBaseWarningBubble(username, error);
    }
  };

  /**
   * Hides the warning bubble shown by {@code showDetachableBaseChangedWarning}.
   *
   * @param {string} username The username of the user with wich the warning was
   *     associated.
   */
  DisplayManager.hideDetachableBaseChangedWarning = function(username) {
    var currentScreen = Oobe.getInstance().currentScreen;
    if (currentScreen &&
        typeof currentScreen.hideDetachableBaseWarningBubble === 'function') {
      currentScreen.hideDetachableBaseWarningBubble(username);
    }
  };

  /**
   * Shows password changed screen that offers migration.
   * @param {boolean} showError Whether to show the incorrect password error.
   * @param {string} email What user does reauth. Being used for display in the
   * new UI.
   */
  DisplayManager.showPasswordChangedScreen = function(showError, email) {
    login.PasswordChangedScreen.show(showError, email);
  };

  /**
   * Shows TPM error screen.
   */
  DisplayManager.showTpmError = function() {
    login.TPMErrorMessageScreen.show();
  };

  /**
   * Shows password change screen for Active Directory users.
   * @param {string} username Display name of the user whose password is being
   * changed.
   */
  DisplayManager.showActiveDirectoryPasswordChangeScreen = function(username) {
    login.ActiveDirectoryPasswordChangeScreen.show(username);
  };

  /**
   * Clears error bubble.
   */
  DisplayManager.clearErrors = function() {
    $('bubble').hide();
    this.errorMessageWasShownForTesting_ = false;

    var bubbles = document.querySelectorAll('.bubble-shown');
    for (var i = 0; i < bubbles.length; ++i)
      bubbles[i].classList.remove('bubble-shown');
  };

  /**
   * Sets text content for a div with |labelId|.
   * @param {string} labelId Id of the label div.
   * @param {string} labelText Text for the label.
   */
  DisplayManager.setLabelText = function(labelId, labelText) {
    $(labelId).textContent = labelText;
  };

  /**
   * Sets the text content of the enterprise info message and asset ID.
   * @param {string} messageText The message text.
   * @param {string} assetId The device asset ID.
   */
  DisplayManager.setEnterpriseInfo = function(messageText, assetId) {
    $('asset-id').textContent =
        ((assetId == '') ? '' :
                           loadTimeData.getStringF('assetIdLabel', assetId));
  };

  /**
   * Sets the text content of the Bluetooth device info message.
   * @param {string} bluetoothName The Bluetooth device name text.
   */
  DisplayManager.setBluetoothDeviceInfo = function(bluetoothName) {
    $('bluetooth-name').hidden = false;
    $('bluetooth-name').textContent = bluetoothName;
  };

  /**
   * Disable Add users button if said.
   * @param {boolean} disable true to disable
   */
  DisplayManager.updateAddUserButtonStatus =
      function(disable) {
    $('add-user-button').disabled = disable;
    $('add-user-button')
        .classList[disable ? 'add' : 'remove']('button-restricted');
    $('add-user-button').title =
        disable ? loadTimeData.getString('disabledAddUserTooltip') : '';
  }

      /**
       * Clears password field in user-pod.
       */
      DisplayManager.clearUserPodPassword = function() {
    $('pod-row').clearFocusedPod();
  };

  /**
   * Restores input focus to currently selected pod.
   */
  DisplayManager.refocusCurrentPod = function() {
    $('pod-row').refocusCurrentPod();
  };

  // Export
  return {
    DisplayManager: DisplayManager
  };
});

// // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Account picker screen implementation.
 */

login.createScreen('AccountPickerScreen', 'account-picker', function() {
  /**
   * Maximum number of offline login failures before online login.
   * @type {number}
   * @const
   */
  var MAX_LOGIN_ATTEMPTS_IN_POD = 3;

  /**
   * Distance between error bubble and user POD.
   * @type {number}
   * @const
   */
   var BUBBLE_POD_OFFSET = 4;

   return {
     EXTERNAL_API: [
       'loadUsers',
       'runAppForTesting',
       'setApps',
       'setShouldShowApps',
       'showAppError',
       'updateUserImage',
       'setCapsLockState',
       'forceLockedUserPodFocus',
       'removeUser',
       'showBannerMessage',
       'showUserPodCustomIcon',
       'hideUserPodCustomIcon',
       'setUserPodFingerprintIcon',
       'removeUserPodFingerprintIcon',
       'setPinEnabledForUser',
       'setAuthType',
       'setTabletModeState',
       'setPublicSessionDisplayName',
       'setPublicSessionLocales',
       'setPublicSessionKeyboardLayouts',
       'setLockScreenAppsState',
     ],

     preferredWidth_: 0,
     preferredHeight_: 0,

     // Whether this screen is shown for the first time.
     firstShown_: true,

     // Whether this screen is currently being shown.
     showing_: false,

     // Last reported lock screen app activity state.
     lockScreenAppsState_: LOCK_SCREEN_APPS_STATE.NONE,

     /** @override */
     decorate: function() {
       login.PodRow.decorate($('pod-row'));
       this.ownerDocument.addEventListener(
           'click', this.handleOwnerDocClick_.bind(this));
     },

     /** @override */
     getPreferredSize: function() {
       return {width: this.preferredWidth_, height: this.preferredHeight_};
     },

     /** @override */
     onWindowResize: function() {
       $('pod-row').onWindowResize();

       // Reposition the error bubble, if it is showing. Since we are just
       // moving the bubble, the number of login attempts tried doesn't matter.
       var errorBubble = $('bubble');
       if (errorBubble && !errorBubble.hidden)
         this.showErrorBubble(0, undefined /* Reuses the existing message. */);
     },

     /**
      * Sets preferred size for account picker screen.
      */
     setPreferredSize: function(width, height) {
       this.preferredWidth_ = width;
       this.preferredHeight_ = height;
     },

     /**
      * When the account picker is being used to lock the screen, pressing the
      * exit accelerator key will sign out the active user as it would when
      * they are signed in.
      */
     exit: function() {
       // Check and disable the sign out button so that we can never have two
       // sign out requests generated in a row.
       if ($('pod-row').lockedPod && !$('sign-out-user-button').disabled) {
         $('sign-out-user-button').disabled = true;
         chrome.send('signOutUser');
       }
     },

     /* Cancel user adding if ESC was pressed.
      */
     cancel: function() {
       if (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING)
         chrome.send('cancelUserAdding');
     },

     /**
      * Event handler that is invoked just after the frame is shown.
      * @param {string} data Screen init payload.
      */
     onAfterShow: function(data) {
       $('pod-row').handleAfterShow();
     },

     /**
      * Event handler that is invoked just before the frame is shown.
      * @param {string} data Screen init payload.
      */
     onBeforeShow: function(data) {
       this.showing_ = true;
       chrome.send('loginUIStateChanged', ['account-picker', true]);
       $('login-header-bar').signinUIState = SIGNIN_UI_STATE.ACCOUNT_PICKER;
       // Header bar should be always visible on Account Picker screen.
       Oobe.getInstance().headerHidden = false;
       chrome.send('hideCaptivePortal');
       var podRow = $('pod-row');
       podRow.handleBeforeShow();

       // In case of the preselected pod onShow will be called once pod
       // receives focus.
       if (!podRow.preselectedPod)
         this.onShow();
     },

     /**
      * Event handler invoked when the page is shown and ready.
      */
     onShow: function() {
       if (!this.showing_) {
         // This method may be called asynchronously when the pod row finishes
         // initializing. However, at that point, the screen may have been
         // hidden again already. If that happens, ignore the onShow() call.
         return;
       }
       chrome.send('getTabletModeState');
       if (!this.firstShown_)
         return;
       this.firstShown_ = false;

       // Ensure that login is actually visible.
       window.requestAnimationFrame(function() {
         chrome.send('accountPickerReady');
         chrome.send('loginVisible', ['account-picker']);
       });
     },

     /**
      * Event handler that is invoked just before the frame is hidden.
      */
     onBeforeHide: function() {
       $('pod-row').clearFocusedPod();
       this.showing_ = false;
       chrome.send('loginUIStateChanged', ['account-picker', false]);
       $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN;
       $('pod-row').handleHide();
     },

     /**
      * Shows sign-in error bubble.
      * @param {number} loginAttempts Number of login attemps tried.
      * @param {HTMLElement} content Content to show in bubble.
      */
     showErrorBubble: function(loginAttempts, error) {
       var activatedPod = $('pod-row').activatedPod;
       if (!activatedPod) {
         $('bubble').showContentForElement(
             $('pod-row'), cr.ui.Bubble.Attachment.RIGHT, error);
         return;
       }
       // Show web authentication if this is not a supervised user.
       if (loginAttempts > MAX_LOGIN_ATTEMPTS_IN_POD &&
           !activatedPod.user.supervisedUser) {
         chrome.send(
             'maxIncorrectPasswordAttempts', [activatedPod.user.emailAddress]);
         activatedPod.showSigninUI();
       } else {
         if (loginAttempts == 1) {
           chrome.send(
               'firstIncorrectPasswordAttempt',
               [activatedPod.user.emailAddress]);
         }
         // Update the pod row display if incorrect password.
         $('pod-row').setFocusedPodErrorDisplay(true);

         /** @const */ var BUBBLE_OFFSET = 25;
         // -8 = 4(BUBBLE_POD_OFFSET) - 2(bubble margin)
         //      - 10(internal bubble adjustment)
         var bubblePositioningPadding = -8;

         var bubbleAnchor;
         var attachment;
         if (activatedPod.pinContainer &&
             activatedPod.pinContainer.style.visibility == 'visible') {
           // Anchor the bubble to the input field.
           bubbleAnchor =
               (activatedPod.getElementsByClassName('auth-container'))[0];
           if (!bubbleAnchor) {
             console.error('auth-container not found!');
             bubbleAnchor = activatedPod.mainInput;
           }
           attachment = cr.ui.Bubble.Attachment.RIGHT;
         } else {
           // Anchor the bubble to the pod instead of the input.
           bubbleAnchor = activatedPod;
           attachment = cr.ui.Bubble.Attachment.BOTTOM;
         }

         var bubble = $('bubble');

         // Cannot use cr.ui.LoginUITools.get* on bubble until it is attached to
         // the element. getMaxHeight/Width rely on the correct up/left element
         // side positioning that doesn't happen until bubble is attached.
         var maxHeight = cr.ui.LoginUITools.getMaxHeightBeforeShelfOverlapping(
                             bubbleAnchor) -
             bubbleAnchor.offsetHeight - BUBBLE_POD_OFFSET;
         var maxWidth = cr.ui.LoginUITools.getMaxWidthToFit(bubbleAnchor) -
             bubbleAnchor.offsetWidth - BUBBLE_POD_OFFSET;

         // Change bubble visibility temporary to calculate height.
         var bubbleVisibility = bubble.style.visibility;
         bubble.style.visibility = 'hidden';
         bubble.hidden = false;
         // Now we need the bubble to have the new content before calculating
         // size. Undefined |error| == reuse old content.
         if (error !== undefined)
           bubble.replaceContent(error);

         // Get bubble size.
         var bubbleOffsetHeight = parseInt(bubble.offsetHeight);
         var bubbleOffsetWidth = parseInt(bubble.offsetWidth);
         // Restore attributes.
         bubble.style.visibility = bubbleVisibility;
         bubble.hidden = true;

         if (attachment == cr.ui.Bubble.Attachment.BOTTOM) {
           // Move error bubble if it overlaps the shelf.
           if (maxHeight < bubbleOffsetHeight)
             attachment = cr.ui.Bubble.Attachment.TOP;
         } else {
           // Move error bubble if it doesn't fit screen.
           if (maxWidth < bubbleOffsetWidth) {
             bubblePositioningPadding = 2;
             attachment = cr.ui.Bubble.Attachment.LEFT;
           }
         }
         var showBubbleCallback = function() {
           activatedPod.removeEventListener(
               'transitionend', showBubbleCallback);
           $('bubble').showContentForElement(
               bubbleAnchor, attachment, error, BUBBLE_OFFSET,
               bubblePositioningPadding, true);
         };
         activatedPod.addEventListener('transitionend', showBubbleCallback);
         ensureTransitionEndEvent(activatedPod);
       }
     },

     /**
      * Loads given users in pod row.
      * @param {array} users Array of user.
      * @param {boolean} showGuest Whether to show guest session button.
      */
     loadUsers: function(users, showGuest) {
       $('pod-row').loadPods(users);
       $('login-header-bar').showGuestButton = showGuest;
       // On Desktop, #login-header-bar has a shadow if there are 8+ profiles.
       if (Oobe.getInstance().displayType == DISPLAY_TYPE.DESKTOP_USER_MANAGER)
         $('login-header-bar').classList.toggle('shadow', users.length > 8);
     },

     /**
      * Runs app with a given id from the list of loaded apps.
      * @param {!string} app_id of an app to run.
      * @param {boolean=} opt_diagnostic_mode Whether to run the app in
      *     diagnostic mode.  Default is false.
      */
     runAppForTesting: function(app_id, opt_diagnostic_mode) {
       $('pod-row').findAndRunAppForTesting(app_id, opt_diagnostic_mode);
     },

     /**
      * Adds given apps to the pod row.
      * @param {array} apps Array of apps.
      */
     setApps: function(apps) {
       $('pod-row').setApps(apps);
     },

     /**
      * Sets the flag of whether app pods should be visible.
      * @param {boolean} shouldShowApps Whether to show app pods.
      */
     setShouldShowApps: function(shouldShowApps) {
       $('pod-row').setShouldShowApps(shouldShowApps);
     },

     /**
      * Shows the given kiosk app error message.
      * @param {!string} message Error message to show.
      */
     showAppError: function(message) {
       // TODO(nkostylev): Figure out a way to show kiosk app launch error
       // pointing to the kiosk app pod.
       /** @const */ var BUBBLE_PADDING = 12;
       $('bubble').showTextForElement(
           $('pod-row'), message, cr.ui.Bubble.Attachment.BOTTOM,
           $('pod-row').offsetWidth / 2, BUBBLE_PADDING);
     },

     /**
      * Updates current image of a user.
      * @param {string} username User for which to update the image.
      */
     updateUserImage: function(username) {
       $('pod-row').updateUserImage(username);
     },

     /**
      * Updates Caps Lock state (for Caps Lock hint in password input field).
      * @param {boolean} enabled Whether Caps Lock is on.
      */
     setCapsLockState: function(enabled) {
       $('pod-row').classList.toggle('capslock-on', enabled);
     },

     /**
      * Enforces focus on user pod of locked user.
      */
     forceLockedUserPodFocus: function() {
       var row = $('pod-row');
       if (row.lockedPod)
         row.focusPod(row.lockedPod, true);
     },

     /**
      * Remove given user from pod row if it is there.
      * @param {string} user name.
      */
     removeUser: function(username) {
       $('pod-row').removeUserPod(username);
     },

     /**
      * Displays a banner containing |message|. If the banner is already present
      * this function updates the message in the banner. This function is used
      * by the chrome.screenlockPrivate.showMessage API.
      * @param {string} message Text to be displayed or empty to hide the
      *     banner.
      * @param {boolean} isWarning True if the given message is a warning.
      */
     showBannerMessage: function(message, isWarning) {
       var banner = $('signin-banner');
       banner.textContent = message;
       banner.classList.toggle('message-set', !!message);
     },

     /**
      * Shows a custom icon in the user pod of |username|. This function
      * is used by the chrome.screenlockPrivate API.
      * @param {string} username Username of pod to add button
      * @param {!{id: !string,
      *           hardlockOnClick: boolean,
      *           isTrialRun: boolean,
      *           tooltip: ({text: string, autoshow: boolean} | undefined)}}
      * icon The icon parameters.
      */
     showUserPodCustomIcon: function(username, icon) {
       $('pod-row').showUserPodCustomIcon(username, icon);
     },

     /**
      * Hides the custom icon in the user pod of |username| added by
      * showUserPodCustomIcon(). This function is used by the
      * chrome.screenlockPrivate API.
      * @param {string} username Username of pod to remove button
      */
     hideUserPodCustomIcon: function(username) {
       $('pod-row').hideUserPodCustomIcon(username);
     },

     /**
      * Set a fingerprint icon in the user pod of |username|.
      * @param {string} username Username of the selected user
      * @param {number} state Fingerprint unlock state
      */
     setUserPodFingerprintIcon: function(username, state) {
       $('pod-row').setUserPodFingerprintIcon(username, state);
     },

     /**
      * Removes the fingerprint icon in the user pod of |username|.
      * @param {string} username Username of the selected user.
      */
     removeUserPodFingerprintIcon: function(username) {
       $('pod-row').removeUserPodFingerprintIcon(username);
     },

     /**
      * Sets the authentication type used to authenticate the user.
      * @param {string} username Username of selected user
      * @param {number} authType Authentication type, must be a valid value in
      *                          the AUTH_TYPE enum in user_pod_row.js.
      * @param {string} value The initial value to use for authentication.
      */
     setAuthType: function(username, authType, value) {
       $('pod-row').setAuthType(username, authType, value);
     },

     /**
      * Sets the state of tablet mode.
      * @param {boolean} isTabletModeEnabled true if the mode is on.
      */
     setTabletModeState: function(isTabletModeEnabled) {
       $('pod-row').setTabletModeState(isTabletModeEnabled);
     },

     /**
      * Enables or disables the pin keyboard for the given user. This may change
      * pin keyboard visibility.
      * @param {!string} user
      * @param {boolean} enabled
      */
     setPinEnabledForUser: function(user, enabled) {
       $('pod-row').setPinEnabled(user, enabled);
     },

     /**
      * Updates the display name shown on a public session pod.
      * @param {string} userID The user ID of the public session
      * @param {string} displayName The new display name
      */
     setPublicSessionDisplayName: function(userID, displayName) {
       $('pod-row').setPublicSessionDisplayName(userID, displayName);
     },

     /**
      * Updates the list of locales available for a public session.
      * @param {string} userID The user ID of the public session
      * @param {!Object} locales The list of available locales
      * @param {string} defaultLocale The locale to select by default
      * @param {boolean} multipleRecommendedLocales Whether |locales| contains
      *     two or more recommended locales
      */
     setPublicSessionLocales: function(
         userID, locales, defaultLocale, multipleRecommendedLocales) {
       $('pod-row').setPublicSessionLocales(
           userID, locales, defaultLocale, multipleRecommendedLocales);
     },

     /**
      * Updates the list of available keyboard layouts for a public session pod.
      * @param {string} userID The user ID of the public session
      * @param {string} locale The locale to which this list of keyboard layouts
      *     applies
      * @param {!Object} list List of available keyboard layouts
      */
     setPublicSessionKeyboardLayouts: function(userID, locale, list) {
       $('pod-row').setPublicSessionKeyboardLayouts(userID, locale, list);
     },

     /**
      * Updates UI based on the provided lock screen apps state.
      *
      * @param {LOCK_SCREEN_APPS_STATE} state The current lock screen apps
      *     state.
      */
     setLockScreenAppsState: function(state) {
       if (Oobe.getInstance().displayType != DISPLAY_TYPE.LOCK ||
           state == this.lockScreenAppsState_) {
         return;
       }

       this.lockScreenAppsState_ = state;
       $('login-header-bar').lockScreenAppsState = state;
       // When an lock screen app window is in background - i.e. visible behind
       // the lock screen UI - dim the lock screen background, so it's more
       // noticeable that the app widow in background is not actionable.
       $('background')
           .classList.toggle(
               'dimmed-background', state == LOCK_SCREEN_APPS_STATE.BACKGROUND);

       if (state === LOCK_SCREEN_APPS_STATE.FOREGROUND)
         $('pod-row').clearFocusedPod();

     },

     /**
      * Handles clicks on the document which displays the account picker UI.
      * If the click event target is outer container - i.e. background portion
      * of UI with no other UI elements, and lock screen apps are in background,
      * a request is issued to chrome to move lock screen apps to foreground.
      * @param {Event} event The click event.
      */
     handleOwnerDocClick_: function(event) {
       if (this.lockScreenAppsState_ != LOCK_SCREEN_APPS_STATE.BACKGROUND ||
           event.target != $('outer-container')) {
         return;
       }
       chrome.send(
           'setLockScreenAppsState', [LOCK_SCREEN_APPS_STATE.FOREGROUND]);

       event.preventDefault();
       event.stopPropagation();
     },
   };
});

// // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview User pod row implementation.
 */

cr.define('login', function() {
  /**
   * Number of displayed columns depending on user pod count.
   * @type {Array<number>}
   * @const
   */
  var COLUMNS = [0, 1, 2, 3, 4, 5, 4, 4, 4, 5, 5, 6, 6, 5, 5, 6, 6, 6, 6];

  /**
   * Mapping between number of columns in pod-row and margin between user pods
   * for such layout.
   * @type {Array<number>}
   * @const
   */
  var MARGIN_BY_COLUMNS = [undefined, 40, 40, 40, 40, 40, 12];

  /**
   * Mapping between number of columns in the desktop pod-row and margin
   * between user pods for such layout.
   * @type {Array<number>}
   * @const
   */
  var DESKTOP_MARGIN_BY_COLUMNS = [undefined, 32, 32, 32, 32, 32, 32];

  /**
   * Maximal number of columns currently supported by pod-row.
   * @type {number}
   * @const
   */
  var MAX_NUMBER_OF_COLUMNS = 6;

  /**
   * Maximal number of rows if sign-in banner is displayed alonside.
   * @type {number}
   * @const
   */
  var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2;

  /**
   * Variables used for pod placement processing. Width and height should be
   * synced with computed CSS sizes of pods.
   */
  var CROS_POD_WIDTH = 180;
  var DESKTOP_POD_WIDTH = 180;
  var MD_DESKTOP_POD_WIDTH = 160;
  var PUBLIC_EXPANDED_BASIC_WIDTH = 500;
  var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610;
  var CROS_POD_HEIGHT = 213;
  var DESKTOP_POD_HEIGHT = 226;
  var MD_DESKTOP_POD_HEIGHT = 200;
  var POD_ROW_PADDING = 10;
  var DESKTOP_ROW_PADDING = 32;
  var CUSTOM_ICON_CONTAINER_SIZE = 40;
  var CROS_PIN_POD_HEIGHT = 417;

  /**
   * Minimal padding between user pod and virtual keyboard.
   * @type {number}
   * @const
   */
  var USER_POD_KEYBOARD_MIN_PADDING = 20;

  /**
   * Maximum time for which the pod row remains hidden until all user images
   * have been loaded.
   * @type {number}
   * @const
   */
  var POD_ROW_IMAGES_LOAD_TIMEOUT_MS = 3000;

  /**
   * Public session help topic identifier.
   * @type {number}
   * @const
   */
  var HELP_TOPIC_PUBLIC_SESSION = 3041033;

  /**
   * Tab order for user pods. Update these when adding new controls.
   * @enum {number}
   * @const
   */
  var UserPodTabOrder = {
    POD_INPUT: 1,        // Password input field, Action box menu button and
                         // the pod itself.
    PIN_KEYBOARD: 2,     // Pin keyboard below the password input field.
    POD_CUSTOM_ICON: 3,  // Pod custom icon next to password input field.
    HEADER_BAR: 4,       // Buttons on the header bar (Shutdown, Add User).
    POD_MENU_ITEM: 5     // User pad menu items (User info, Remove user).
  };

  /**
   * Supported authentication types. Keep in sync with the enum in
   * components/proximity_auth/public/interfaces/auth_type.mojom
   * @enum {number}
   * @const
   */
  var AUTH_TYPE = {
    OFFLINE_PASSWORD: 0,
    ONLINE_SIGN_IN: 1,
    NUMERIC_PIN: 2,
    USER_CLICK: 3,
    EXPAND_THEN_USER_CLICK: 4,
    FORCE_OFFLINE_PASSWORD: 5
  };

  /**
   * Names of authentication types.
   */
  var AUTH_TYPE_NAMES = {
    0: 'offlinePassword',
    1: 'onlineSignIn',
    2: 'numericPin',
    3: 'userClick',
    4: 'expandThenUserClick',
    5: 'forceOfflinePassword'
  };

  /**
   * Supported fingerprint unlock states.
   * @enum {number}
   * @const
   */
  var FINGERPRINT_STATES = {
    HIDDEN: 0,
    DEFAULT: 1,
    SIGNIN: 2,
    FAILED: 3,
  };

  /**
   * The fingerprint states to classes mapping.
   * {@code state} properties indicate current fingerprint unlock state.
   * {@code class} properties are CSS classes used to set the icons' background
   * and password placeholder color.
   * @const {Array<{type: !number, class: !string}>}
   */
  var FINGERPRINT_STATES_MAPPING = [
    {state: FINGERPRINT_STATES.HIDDEN, class: 'hidden'},
    {state: FINGERPRINT_STATES.DEFAULT, class: 'default'},
    {state: FINGERPRINT_STATES.SIGNIN, class: 'signin'},
    {state: FINGERPRINT_STATES.FAILED, class: 'failed'}
  ];

  // Supported multi-profile user behavior values.
  // Keep in sync with the enum in login_user_info.mojom
  var MULTI_PROFILE_USER_BEHAVIOR = {
    UNRESTRICTED: 0,
    PRIMARY_ONLY: 1,
    NOT_ALLOWED: 2,
    OWNER_PRIMARY_ONLY: 3
  };

  // Focus and tab order are organized as follows:
  //
  // (1) all user pods have tab index 1 so they are traversed first;
  // (2) when a user pod is activated, its tab index is set to -1 and its
  // main input field gets focus and tab index 1;
  // (3) if user pod custom icon is interactive, it has tab index 2 so it
  // follows the input.
  // (4) buttons on the header bar have tab index 3 so they follow the custom
  // icon, or user pod if custom icon is not interactive;
  // (5) Action box buttons have tab index 4 and follow header bar buttons;
  // (6) lastly, focus jumps to the Status Area and back to user pods.
  //
  // 'Focus' event is handled by a capture handler for the whole document
  // and in some cases 'mousedown' event handlers are used instead of 'click'
  // handlers where it's necessary to prevent 'focus' event from being fired.

  /**
   * Helper function to remove a class from given element.
   * @param {!HTMLElement} el Element whose class list to change.
   * @param {string} cl Class to remove.
   */
  function removeClass(el, cl) {
    el.classList.remove(cl);
  }

  /**
   * Creates a user pod.
   * @constructor
   * @extends {HTMLDivElement}
   */
  var UserPod = cr.ui.define(function() {
    var node = $('user-pod-template').cloneNode(true);
    node.removeAttribute('id');
    return node;
  });

  /**
   * Stops event propagation from the any user pod child element.
   * @param {Event} e Event to handle.
   */
  function stopEventPropagation(e) {
    // Prevent default so that we don't trigger a 'focus' event.
    e.preventDefault();
    e.stopPropagation();
  }

  /**
   * Creates an element for custom icon shown in a user pod next to the input
   * field.
   * @constructor
   * @extends {HTMLDivElement}
   */
  var UserPodCustomIcon = cr.ui.define(function() {
    var node = document.createElement('div');
    node.classList.add('custom-icon-container');
    node.hidden = true;

    // Create the actual icon element and add it as a child to the container.
    var iconNode = document.createElement('div');
    iconNode.classList.add('custom-icon');
    node.appendChild(iconNode);
    return node;
  });

  /**
   * The supported user pod custom icons.
   * {@code id} properties should be in sync with values set by C++ side.
   * {@code class} properties are CSS classes used to set the icons' background.
   * @const {Array<{id: !string, class: !string}>}
   */
  UserPodCustomIcon.ICONS = [
    {id: 'locked', class: 'custom-icon-locked'},
    {id: 'locked-to-be-activated',
     class: 'custom-icon-locked-to-be-activated'},
    {id: 'locked-with-proximity-hint',
     class: 'custom-icon-locked-with-proximity-hint'},
    {id: 'unlocked', class: 'custom-icon-unlocked'},
    {id: 'hardlocked', class: 'custom-icon-hardlocked'},
    {id: 'spinner', class: 'custom-icon-spinner'}
  ];

  /**
   * The hover state for the icon. When user hovers over the icon, a tooltip
   * should be shown after a short delay. This enum is used to keep track of
   * the tooltip status related to hover state.
   * @enum {string}
   */
  UserPodCustomIcon.HoverState = {
    /** The user is not hovering over the icon. */
    NO_HOVER: 'no_hover',

    /** The user is hovering over the icon but the tooltip is not activated. */
    HOVER: 'hover',

    /**
     * User is hovering over the icon and the tooltip is activated due to the
     * hover state (which happens with delay after user starts hovering).
     */
    HOVER_TOOLTIP: 'hover_tooltip'
  };

  /**
   * If the icon has a tooltip that should be automatically shown, the tooltip
   * is shown even when there is no user action (i.e. user is not hovering over
   * the icon), after a short delay. The tooltip should be hidden after some
   * time. Note that the icon will not be considered autoshown if it was
   * previously shown as a result of the user action.
   * This enum is used to keep track of this state.
   * @enum {string}
   */
  UserPodCustomIcon.TooltipAutoshowState = {
    /** The tooltip should not be or was not automatically shown. */
    DISABLED: 'disabled',

    /**
     * The tooltip should be automatically shown, but the timeout for showing
     * the tooltip has not yet passed.
     */
    ENABLED: 'enabled',

    /** The tooltip was automatically shown. */
    ACTIVE : 'active'
  };

  UserPodCustomIcon.prototype = {
    __proto__: HTMLDivElement.prototype,

    /**
     * The id of the icon being shown.
     * @type {string}
     * @private
     */
    iconId_: '',

    /**
     * A reference to the timeout for updating icon hover state. Non-null
     * only if there is an active timeout.
     * @type {?number}
     * @private
     */
    updateHoverStateTimeout_: null,

    /**
     * A reference to the timeout for updating icon tooltip autoshow state.
     * Non-null only if there is an active timeout.
     * @type {?number}
     * @private
     */
    updateTooltipAutoshowStateTimeout_: null,

    /**
     * Callback for click and 'Enter' key events that gets set if the icon is
     * interactive.
     * @type {?function()}
     * @private
     */
    actionHandler_: null,

    /**
     * The current tooltip state.
     * @type {{active: function(): boolean,
     *         autoshow: !UserPodCustomIcon.TooltipAutoshowState,
     *         hover: !UserPodCustomIcon.HoverState,
     *         text: string}}
     * @private
     */
    tooltipState_: {
      /**
       * Utility method for determining whether the tooltip is active, either as
       * a result of hover state or being autoshown.
       * @return {boolean}
       */
      active: function() {
        return this.autoshow == UserPodCustomIcon.TooltipAutoshowState.ACTIVE ||
               this.hover == UserPodCustomIcon.HoverState.HOVER_TOOLTIP;
      },

      /**
       * @type {!UserPodCustomIcon.TooltipAutoshowState}
       */
      autoshow: UserPodCustomIcon.TooltipAutoshowState.DISABLED,

      /**
       * @type {!UserPodCustomIcon.HoverState}
       */
      hover: UserPodCustomIcon.HoverState.NO_HOVER,

      /**
       * The tooltip text.
       * @type {string}
       */
      text: ''
    },

    /** @override */
    decorate: function() {
      this.iconElement.addEventListener(
          'mouseover',
          this.updateHoverState_.bind(this,
                                      UserPodCustomIcon.HoverState.HOVER));
      this.iconElement.addEventListener(
          'mouseout',
          this.updateHoverState_.bind(this,
                                      UserPodCustomIcon.HoverState.NO_HOVER));
      this.iconElement.addEventListener('mousedown',
                                        this.handleMouseDown_.bind(this));
      this.iconElement.addEventListener('click',
                                        this.handleClick_.bind(this));
      this.iconElement.addEventListener('keydown',
                                        this.handleKeyDown_.bind(this));

      // When the icon is focused using mouse, there should be no outline shown.
      // Preventing default mousedown event accomplishes this.
      this.iconElement.addEventListener('mousedown', function(e) {
        e.preventDefault();
      });
    },

    /**
     * Getter for the icon element's div.
     * @return {HTMLDivElement}
     */
    get iconElement() {
      return this.querySelector('.custom-icon');
    },

    /**
     * Updates the icon element class list to properly represent the provided
     * icon.
     * @param {!string} id The id of the icon that should be shown. Should be
     *    one of the ids listed in {@code UserPodCustomIcon.ICONS}.
     */
    setIcon: function(id) {
      this.iconId_ = id;
      UserPodCustomIcon.ICONS.forEach(function(icon) {
        this.iconElement.classList.toggle(icon.class, id == icon.id);
      }, this);
    },

    /**
     * Sets the ARIA label for the icon.
     * @param {!string} ariaLabel
     */
    setAriaLabel: function(ariaLabel) {
      this.iconElement.setAttribute('aria-label', ariaLabel);
    },

    /**
     * Shows the icon.
     */
    show: function() {
      // Show the icon if the current iconId is valid.
      var validIcon = false;
      UserPodCustomIcon.ICONS.forEach(function(icon) {
        validIcon = validIcon || this.iconId_ == icon.id;
      }, this);
      this.hidden = validIcon ? false : true;
    },

    /**
     * Updates the icon tooltip. If {@code autoshow} parameter is set the
     * tooltip is immediatelly shown. If tooltip text is not set, the method
     * ensures the tooltip gets hidden. If tooltip is shown prior to this call,
     * it remains shown, but the tooltip text is updated.
     * @param {!{text: string, autoshow: boolean}} tooltip The tooltip
     *    parameters.
     */
    setTooltip: function(tooltip) {
      this.iconElement.classList.toggle('icon-with-tooltip', !!tooltip.text);

      this.updateTooltipAutoshowState_(
          tooltip.autoshow ?
              UserPodCustomIcon.TooltipAutoshowState.ENABLED :
              UserPodCustomIcon.TooltipAutoshowState.DISABLED);
      this.tooltipState_.text = tooltip.text;
      this.updateTooltip_();
    },

    /**
     * Sets up icon tabIndex attribute and handler for click and 'Enter' key
     * down events.
     * @param {?function()} callback If icon should be interactive, the
     *     function to get called on click and 'Enter' key down events. Should
     *     be null to make the icon  non interactive.
     */
    setInteractive: function(callback) {
      this.iconElement.classList.toggle('interactive-custom-icon', !!callback);

      // Update tabIndex property if needed.
      if (!!this.actionHandler_ != !!callback) {
        if (callback) {
          this.iconElement.setAttribute('tabIndex',
                                         UserPodTabOrder.POD_CUSTOM_ICON);
        } else {
          this.iconElement.removeAttribute('tabIndex');
        }
      }

      // Set the new action handler.
      this.actionHandler_ = callback;
    },

    /**
     * Hides the icon and cleans its state.
     */
    hide: function() {
      this.hideTooltip_();
      this.clearUpdateHoverStateTimeout_();
      this.clearUpdateTooltipAutoshowStateTimeout_();
      this.setInteractive(null);
      this.hidden = true;
    },

    /**
     * Clears timeout for showing a tooltip if one is set. Used to cancel
     * showing the tooltip when the user starts typing the password.
     */
    cancelDelayedTooltipShow: function() {
      this.updateTooltipAutoshowState_(
          UserPodCustomIcon.TooltipAutoshowState.DISABLED);
      this.clearUpdateHoverStateTimeout_();
    },

    /**
     * Handles mouse down event in the icon element.
     * @param {Event} e The mouse down event.
     * @private
     */
    handleMouseDown_: function(e) {
      this.updateHoverState_(UserPodCustomIcon.HoverState.NO_HOVER);
      this.updateTooltipAutoshowState_(
          UserPodCustomIcon.TooltipAutoshowState.DISABLED);

      // Stop the event propagation so in the case the click ends up on the
      // user pod (outside the custom icon) auth is not attempted.
      stopEventPropagation(e);
    },

    /**
     * Handles click event on the icon element. No-op if
     * {@code this.actionHandler_} is not set.
     * @param {Event} e The click event.
     * @private
     */
    handleClick_: function(e) {
      if (!this.actionHandler_)
        return;
      this.actionHandler_();
      stopEventPropagation(e);
    },

    /**
     * Handles key down event on the icon element. Only 'Enter' key is handled.
     * No-op if {@code this.actionHandler_} is not set.
     * @param {Event} e The key down event.
     * @private
     */
    handleKeyDown_: function(e) {
      if (!this.actionHandler_ || e.key != 'Enter')
        return;
      this.actionHandler_(e);
      stopEventPropagation(e);
    },

    /**
     * Changes the tooltip hover state and updates tooltip visibility if needed.
     * @param {!UserPodCustomIcon.HoverState} state
     * @private
     */
    updateHoverState_: function(state) {
      this.clearUpdateHoverStateTimeout_();
      this.sanitizeTooltipStateIfBubbleHidden_();

      if (state == UserPodCustomIcon.HoverState.HOVER) {
        if (this.tooltipState_.active()) {
          this.tooltipState_.hover = UserPodCustomIcon.HoverState.HOVER_TOOLTIP;
        } else {
          this.updateHoverStateSoon_(
              UserPodCustomIcon.HoverState.HOVER_TOOLTIP);
        }
        return;
      }

      if (state != UserPodCustomIcon.HoverState.NO_HOVER &&
          state != UserPodCustomIcon.HoverState.HOVER_TOOLTIP) {
        console.error('Invalid hover state ' + state);
        return;
      }

      this.tooltipState_.hover = state;
      this.updateTooltip_();
    },

    /**
     * Sets up a timeout for updating icon hover state.
     * @param {!UserPodCustomIcon.HoverState} state
     * @private
     */
    updateHoverStateSoon_: function(state) {
      if (this.updateHoverStateTimeout_)
        clearTimeout(this.updateHoverStateTimeout_);
      this.updateHoverStateTimeout_ =
          setTimeout(this.updateHoverState_.bind(this, state), 1000);
    },

    /**
     * Clears a timeout for updating icon hover state if there is one set.
     * @private
     */
    clearUpdateHoverStateTimeout_: function() {
      if (this.updateHoverStateTimeout_) {
        clearTimeout(this.updateHoverStateTimeout_);
        this.updateHoverStateTimeout_ = null;
      }
    },

    /**
     * Changes the tooltip autoshow state and changes tooltip visibility if
     * needed.
     * @param {!UserPodCustomIcon.TooltipAutoshowState} state
     * @private
     */
    updateTooltipAutoshowState_: function(state) {
      this.clearUpdateTooltipAutoshowStateTimeout_();
      this.sanitizeTooltipStateIfBubbleHidden_();

      if (state == UserPodCustomIcon.TooltipAutoshowState.DISABLED) {
        if (this.tooltipState_.autoshow != state) {
          this.tooltipState_.autoshow = state;
          this.updateTooltip_();
        }
        return;
      }

      if (this.tooltipState_.active()) {
        if (this.tooltipState_.autoshow !=
                UserPodCustomIcon.TooltipAutoshowState.ACTIVE) {
          this.tooltipState_.autoshow =
              UserPodCustomIcon.TooltipAutoshowState.DISABLED;
        } else {
          // If the tooltip is already automatically shown, the timeout for
          // removing it should be reset.
          this.updateTooltipAutoshowStateSoon_(
              UserPodCustomIcon.TooltipAutoshowState.DISABLED);
        }
        return;
      }

      if (state == UserPodCustomIcon.TooltipAutoshowState.ENABLED) {
        this.updateTooltipAutoshowStateSoon_(
            UserPodCustomIcon.TooltipAutoshowState.ACTIVE);
      } else if (state == UserPodCustomIcon.TooltipAutoshowState.ACTIVE) {
        this.updateTooltipAutoshowStateSoon_(
            UserPodCustomIcon.TooltipAutoshowState.DISABLED);
      }

      this.tooltipState_.autoshow = state;
      this.updateTooltip_();
    },

    /**
     * Sets up a timeout for updating tooltip autoshow state.
     * @param {!UserPodCustomIcon.TooltipAutoshowState} state
     * @private
     */
    updateTooltipAutoshowStateSoon_: function(state) {
      if (this.updateTooltipAutoshowStateTimeout_)
        clearTimeout(this.updateTooltupAutoshowStateTimeout_);
      var timeout =
          state == UserPodCustomIcon.TooltipAutoshowState.DISABLED ?
              5000 : 1000;
      this.updateTooltipAutoshowStateTimeout_ =
          setTimeout(this.updateTooltipAutoshowState_.bind(this, state),
                     timeout);
    },

    /**
     * Clears the timeout for updating tooltip autoshow state if one is set.
     * @private
     */
    clearUpdateTooltipAutoshowStateTimeout_: function() {
      if (this.updateTooltipAutoshowStateTimeout_) {
        clearTimeout(this.updateTooltipAutoshowStateTimeout_);
        this.updateTooltipAutoshowStateTimeout_ = null;
      }
    },

    /**
     * If tooltip bubble is hidden, this makes sure that hover and tooltip
     * autoshow states are not the ones that imply an active tooltip.
     * Used to handle a case where the tooltip bubble is hidden by an event that
     * does not update one of the states (e.g. click outside the pod will not
     * update tooltip autoshow state). Should be called before making
     * tooltip state updates.
     * @private
     */
    sanitizeTooltipStateIfBubbleHidden_: function() {
      if (!$('bubble').hidden)
        return;

      if (this.tooltipState_.hover ==
              UserPodCustomIcon.HoverState.HOVER_TOOLTIP &&
          this.tooltipState_.text) {
        this.tooltipState_.hover = UserPodCustomIcon.HoverState.NO_HOVER;
        this.clearUpdateHoverStateTimeout_();
      }

      if (this.tooltipState_.autoshow ==
             UserPodCustomIcon.TooltipAutoshowState.ACTIVE) {
        this.tooltipState_.autoshow =
            UserPodCustomIcon.TooltipAutoshowState.DISABLED;
        this.clearUpdateTooltipAutoshowStateTimeout_();
      }
    },

    /**
     * Returns whether the user pod to which the custom icon belongs is focused.
     * @return {boolean}
     * @private
     */
    isParentPodFocused_: function() {
      if ($('account-picker').hidden)
        return false;
      var parentPod = this.parentNode;
      while (parentPod && !parentPod.classList.contains('pod'))
        parentPod = parentPod.parentNode;
      return parentPod && parentPod.parentNode.isFocused(parentPod);
    },

    /**
     * Depending on {@code this.tooltipState_}, it updates tooltip visibility
     * and text.
     * @private
     */
    updateTooltip_: function() {
      if (this.hidden || !this.isParentPodFocused_())
        return;

      if (!this.tooltipState_.active() || !this.tooltipState_.text) {
        this.hideTooltip_();
        return;
      }

      // Show the tooltip bubble.
      var bubbleContent = document.createElement('div');
      bubbleContent.textContent = this.tooltipState_.text;

      /** @const */ var BUBBLE_OFFSET = CUSTOM_ICON_CONTAINER_SIZE / 2;
      // TODO(tengs): Introduce a special reauth state for the account picker,
      // instead of showing the tooltip bubble here (crbug.com/409427).
      /** @const */ var BUBBLE_PADDING = 8 + (this.iconId_ ? 0 : 23);
      $('bubble').showContentForElement(this,
                                        cr.ui.Bubble.Attachment.LEFT,
                                        bubbleContent,
                                        BUBBLE_OFFSET,
                                        BUBBLE_PADDING);
    },

    /**
     * Hides the tooltip.
     * @private
     */
    hideTooltip_: function() {
      $('bubble').hideForElement(this);
    }
  };

  /**
   * Unique salt added to user image URLs to prevent caching. Dictionary with
   * user names as keys.
   * @type {Object}
   */
  UserPod.userImageSalt_ = {};

  UserPod.prototype = {
    __proto__: HTMLDivElement.prototype,

    /**
     * Whether click on the pod can issue a user click auth attempt. The
     * attempt can be issued iff the pod was focused when the click
     * started (i.e. on mouse down event).
     * @type {boolean}
     * @private
     */
    userClickAuthAllowed_: false,

    /**
     * Whether the user has recently authenticated with fingerprint.
     * @type {boolean}
     * @private
     */
    fingerprintAuthenticated_: false,

    /**
     * True iff the pod can display the pin keyboard. The pin keyboard may not
     * always be displayed even if this is true, ie, if the virtual keyboard is
     * also being displayed.
     */
    pinEnabled: false,

    /** @override */
    decorate: function() {
      this.tabIndex = UserPodTabOrder.POD_INPUT;
      this.actionBoxAreaElement.tabIndex = UserPodTabOrder.POD_INPUT;

      this.addEventListener('keydown', this.handlePodKeyDown_.bind(this));
      this.addEventListener('click', this.handleClickOnPod_.bind(this));
      this.addEventListener('mousedown', this.handlePodMouseDown_.bind(this));

      if (this.pinKeyboard) {
        this.pinKeyboard.passwordElement = this.passwordElement;
        this.pinKeyboard.addEventListener('pin-change',
            this.handleInputChanged_.bind(this));
        this.pinKeyboard.tabIndex = UserPodTabOrder.PIN_KEYBOARD;
      }

      this.actionBoxAreaElement.addEventListener('mousedown',
                                                 stopEventPropagation);
      this.actionBoxAreaElement.addEventListener('click',
          this.handleActionAreaButtonClick_.bind(this));
      this.actionBoxAreaElement.addEventListener('keydown',
          this.handleActionAreaButtonKeyDown_.bind(this));
      this.actionBoxAreaElement.addEventListener('focus', () => {
        this.isActionBoxMenuActive = false;
      });

      this.actionBoxMenuTitleElement.addEventListener('keydown',
          this.handleMenuTitleElementKeyDown_.bind(this));
      this.actionBoxMenuTitleElement.addEventListener('blur',
          this.handleMenuTitleElementBlur_.bind(this));

      this.actionBoxMenuRemoveElement.addEventListener('click',
          this.handleRemoveCommandClick_.bind(this));
      this.actionBoxMenuRemoveElement.addEventListener('keydown',
          this.handleRemoveCommandKeyDown_.bind(this));
      this.actionBoxMenuRemoveElement.addEventListener('blur',
          this.handleRemoveCommandBlur_.bind(this));
      this.actionBoxRemoveUserWarningButtonElement.addEventListener('click',
          this.handleRemoveUserConfirmationClick_.bind(this));
      this.actionBoxRemoveUserWarningButtonElement.addEventListener('keydown',
          this.handleRemoveUserConfirmationKeyDown_.bind(this));

      if (this.fingerprintIconElement) {
        this.fingerprintIconElement.addEventListener(
            'mouseover', this.handleFingerprintIconMouseOver_.bind(this));
        this.fingerprintIconElement.addEventListener(
            'mouseout', this.handleFingerprintIconMouseOut_.bind(this));
        this.fingerprintIconElement.addEventListener(
            'mousedown', stopEventPropagation);
      }

      var customIcon = this.customIconElement;
      customIcon.parentNode.replaceChild(new UserPodCustomIcon(), customIcon);
    },

    /**
     * Initializes the pod after its properties set and added to a pod row.
     */
    initialize: function() {
      this.passwordElement.addEventListener('keydown',
          this.parentNode.handleKeyDown.bind(this.parentNode));
      this.passwordElement.addEventListener('keypress',
          this.handlePasswordKeyPress_.bind(this));
      this.passwordElement.addEventListener('input',
          this.handleInputChanged_.bind(this));

      if (this.submitButton) {
        this.submitButton.addEventListener('click',
            this.handleSubmitButtonClick_.bind(this));
      }

      this.imageElement.addEventListener('load',
          this.parentNode.handlePodImageLoad.bind(this.parentNode, this));

      var initialAuthType = this.user.initialAuthType ||
          AUTH_TYPE.OFFLINE_PASSWORD;
      this.setAuthType(initialAuthType, null);

      if (this.user.isActiveDirectory)
        this.setAttribute('is-active-directory', '');

      this.userClickAuthAllowed_ = false;

      // Lazy load the assets needed for the polymer submit button.
      var isLockScreen = (Oobe.getInstance().displayType == DISPLAY_TYPE.LOCK);
      if (cr.isChromeOS && isLockScreen &&
          !cr.ui.login.ResourceLoader.alreadyLoadedAssets(
              'custom-elements-user-pod')) {
        cr.ui.login.ResourceLoader.registerAssets({
            id: 'custom-elements-user-pod',
            html: [{ url: 'custom_elements_user_pod.html' }]
         });
        cr.ui.login.ResourceLoader.loadAssetsOnIdle('custom-elements-user-pod');
      }
    },

    /**
     * Whether the user pod is disabled.
     * @type {boolean}
     */
    disabled_: false,
    get disabled() {
      return this.disabled_;
    },
    set disabled(value) {
      this.disabled_ = value;
      this.querySelectorAll('button,input').forEach(function(element) {
        element.disabled = value
      });

      // Special handling for submit button - the submit button should be
      // enabled only if there is the password value set.
      var submitButton = this.submitButton;
      if (submitButton)
        submitButton.disabled = value || !this.passwordElement.value;
    },

    /**
     * Resets tab order for pod elements to its initial state.
     */
    resetTabOrder: function() {
      // Note: the |mainInput| can be the pod itself.
      this.mainInput.tabIndex = -1;
      this.tabIndex = UserPodTabOrder.POD_INPUT;
    },

    /**
     * Handles keypress event (i.e. any textual input) on password input.
     * @param {Event} e Keypress Event object.
     * @private
     */
    handlePasswordKeyPress_: function(e) {
      // When tabbing from the system tray a tab key press is received. Suppress
      // this so as not to type a tab character into the password field.
      if (e.keyCode == 9) {
        e.preventDefault();
        return;
      }
      this.customIconElement.cancelDelayedTooltipShow();
    },

    /**
     * Handles a click event on submit button.
     * @param {Event} e Click event.
     */
    handleSubmitButtonClick_: function(e) {
      this.parentNode.setActivatedPod(this, e);
    },

    /**
     * Top edge margin number of pixels.
     * @type {?number}
     */
    set top(top) {
      this.style.top = cr.ui.toCssPx(top);
    },

    /**
     * Top edge margin number of pixels.
     */
    get top() {
      return parseInt(this.style.top);
    },

    /**
     * Left edge margin number of pixels.
     * @type {?number}
     */
    set left(left) {
      this.style.left = cr.ui.toCssPx(left);
    },

    /**
     * Left edge margin number of pixels.
     */
    get left() {
      return parseInt(this.style.left);
    },

    /**
     * Height number of pixels.
     */
    get height() {
      return this.offsetHeight;
    },

    /**
     * Gets image element.
     * @type {!HTMLImageElement}
     */
    get imageElement() {
      return this.querySelector('.user-image');
    },

    /**
     * Gets animated image element.
     * @type {!HTMLImageElement}
     */
    get animatedImageElement() {
      return this.querySelector('.user-image.animated-image');
    },

    /**
     * Gets name element.
     * @type {!HTMLDivElement}
     */
    get nameElement() {
      return this.querySelector('.name');
    },

    /**
     * Gets reauth name hint element.
     * @type {!HTMLDivElement}
     */
    get reauthNameHintElement() {
      return this.querySelector('.reauth-name-hint');
    },

    /**
     * Gets the container holding the password field.
     * @type {!HTMLInputElement}
     */
    get passwordEntryContainerElement() {
      return this.querySelector('.password-entry-container');
    },

    /**
     * Gets password field.
     * @type {!HTMLInputElement}
     */
    get passwordElement() {
      return this.querySelector('.password');
    },

    /**
     * Gets submit button.
     * @type {!HTMLInputElement}
     */
    get submitButton() {
      return this.querySelector('.submit-button');
    },

    /**
     * Gets the password label, which is used to show a message where the
     * password field is normally.
     * @type {!HTMLInputElement}
     */
    get passwordLabelElement() {
      return this.querySelector('.password-label');
    },

    get pinContainer() {
      return this.querySelector('.pin-container');
    },

    /**
     * Gets the pin-keyboard of the pod.
     * @type {!HTMLElement}
     */
    get pinKeyboard() {
      return this.querySelector('pin-keyboard');
    },

    /**
     * Gets user online sign in hint element.
     * @type {!HTMLDivElement}
     */
    get reauthWarningElement() {
      return this.querySelector('.reauth-hint-container');
    },

    /**
     * Gets the container holding the launch app button.
     * @type {!HTMLButtonElement}
     */
    get launchAppButtonContainerElement() {
      return this.querySelector('.launch-app-button-container');
    },

    /**
     * Gets launch app button.
     * @type {!HTMLButtonElement}
     */
    get launchAppButtonElement() {
      return this.querySelector('.launch-app-button');
    },

    /**
     * Gets action box area.
     * @type {!HTMLInputElement}
     */
    get actionBoxAreaElement() {
      return this.querySelector('.action-box-area');
    },

    /**
     * Gets user type icon area.
     * @type {!HTMLDivElement}
     */
    get userTypeIconAreaElement() {
      return this.querySelector('.user-type-icon-area');
    },

    /**
     * Gets user type bubble like multi-profiles policy restriction message.
     * @type {!HTMLDivElement}
     */
    get userTypeBubbleElement() {
      return this.querySelector('.user-type-bubble');
    },

    /**
     * Gets action box menu.
     * @type {!HTMLDivElement}
     */
    get actionBoxMenu() {
      return this.querySelector('.action-box-menu');
    },

    /**
     * Gets action box menu title (user name and email).
     * @type {!HTMLDivElement}
     */
    get actionBoxMenuTitleElement() {
      return this.querySelector('.action-box-menu-title');
    },

    /**
     * Gets action box menu title, user name item.
     * @type {!HTMLSpanElement}
     */
    get actionBoxMenuTitleNameElement() {
      return this.querySelector('.action-box-menu-title-name');
    },

    /**
     * Gets action box menu title, user email item.
     * @type {!HTMLSpanElement}
     */
    get actionBoxMenuTitleEmailElement() {
      return this.querySelector('.action-box-menu-title-email');
    },

    /**
     * Gets action box menu, remove user command item.
     * @type {!HTMLInputElement}
     */
    get actionBoxMenuCommandElement() {
      return this.querySelector('.action-box-menu-remove-command');
    },

    /**
     * Gets action box menu, remove user command item div.
     * @type {!HTMLInputElement}
     */
    get actionBoxMenuRemoveElement() {
      return this.querySelector('.action-box-menu-remove');
    },

    /**
     * Gets action box menu, remove user command item div.
     * @type {!HTMLInputElement}
     */
    get actionBoxRemoveUserWarningElement() {
      return this.querySelector('.action-box-remove-user-warning');
    },

    /**
     * Gets action box menu, remove user command item div.
     * @type {!HTMLInputElement}
     */
    get actionBoxRemoveUserWarningButtonElement() {
      return this.querySelector('.remove-warning-button');
    },

    /**
     * Gets the custom icon. This icon is normally hidden, but can be shown
     * using the chrome.screenlockPrivate API.
     * @type {!HTMLDivElement}
     */
    get customIconElement() {
      return this.querySelector('.custom-icon-container');
    },

    /**
     * Gets the elements used for statistics display.
     * @type {Object.<string, !HTMLDivElement>}
     */
    get statsMapElements() {
      return {
          'BrowsingHistory':
              this.querySelector('.action-box-remove-user-warning-history'),
          'Passwords':
              this.querySelector('.action-box-remove-user-warning-passwords'),
          'Bookmarks':
              this.querySelector('.action-box-remove-user-warning-bookmarks'),
          'Autofill':
              this.querySelector('.action-box-remove-user-warning-autofill')
      }
    },

    /**
     * Gets the fingerprint icon area.
     * @type {!HTMLDivElement}
     */
    get fingerprintIconElement() {
      return this.querySelector('.fingerprint-icon-container');
    },

    /**
     * Updates the user pod element.
     */
    update: function() {
      var animatedImageSrc = 'chrome://userimage/' + this.user.username +
          '?id=' + UserPod.userImageSalt_[this.user.username];
      this.imageElement.src = animatedImageSrc + '&frame=0';
      this.animatedImageElement.src = animatedImageSrc;

      this.nameElement.textContent = this.user_.displayName;
      this.reauthNameHintElement.textContent = this.user_.displayName;
      this.classList.toggle('signed-in', this.user_.signedIn);

      if (this.isAuthTypeUserClick)
        this.passwordLabelElement.textContent = this.authValue;

      this.updateActionBoxArea();

      this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
        'passwordFieldAccessibleName', this.user_.emailAddress));

      this.customizeUserPodPerUserType();
    },

    updateActionBoxArea: function() {
      if (this.user_.publicAccount || this.user_.isApp) {
        this.actionBoxAreaElement.hidden = true;
        return;
      }

      this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove;

      this.actionBoxAreaElement.setAttribute(
          'aria-label', loadTimeData.getStringF(
              'podMenuButtonAccessibleName', this.user_.emailAddress));
      this.actionBoxMenuRemoveElement.setAttribute(
          'aria-label', loadTimeData.getString(
               'podMenuRemoveItemAccessibleName'));
      this.actionBoxMenuTitleNameElement.textContent = this.user_.isOwner ?
          loadTimeData.getStringF('ownerUserPattern', this.user_.displayName) :
          this.user_.displayName;
      this.actionBoxMenuTitleEmailElement.textContent = this.user_.emailAddress;

      this.actionBoxMenuTitleEmailElement.hidden =
          this.user_.legacySupervisedUser;

      this.actionBoxMenuCommandElement.textContent =
          loadTimeData.getString('removeUser');
    },

    customizeUserPodPerUserType: function() {
      if (this.user_.childUser && !this.user_.isDesktopUser) {
        this.setUserPodIconType('child');
      } else if (this.user_.legacySupervisedUser && !this.user_.isDesktopUser) {
        this.setUserPodIconType('legacySupervised');
        this.classList.add('legacy-supervised');
      } else if (this.multiProfilesPolicyApplied) {
        // Mark user pod as not focusable which in addition to the grayed out
        // filter makes it look in disabled state.
        this.classList.add('multiprofiles-policy-applied');
        this.setUserPodIconType('policy');

        if (this.user.multiProfilesPolicy ==
            MULTI_PROFILE_USER_BEHAVIOR.PRIMARY_ONLY) {
          this.querySelector('.mp-policy-primary-only-msg').hidden = false;
        } else if (this.user.multiProfilesPolicy ==
            MULTI_PROFILE_USER_BEHAVIOR.OWNER_PRIMARY_ONLY) {
          this.querySelector('.mp-owner-primary-only-msg').hidden = false;
        } else {
          this.querySelector('.mp-policy-not-allowed-msg').hidden = false;
        }
      } else if (this.user_.isApp) {
        this.setUserPodIconType('app');
      }
    },

    isPinReady: function() {
      return this.pinKeyboard && this.pinKeyboard.offsetHeight > 0;
    },

    set showError(visible) {
      if (this.submitButton)
        this.submitButton.classList.toggle('error-shown', visible);
    },

    updatePinClass_: function(element, enable) {
      element.classList.toggle('pin-enabled', enable);
      element.classList.toggle('pin-disabled', !enable);
    },

    setPinVisibility: function(visible) {
      if (this.isPinShown() == visible)
        return;

      // Do not show pin if virtual keyboard is there.
      if (visible && Oobe.getInstance().virtualKeyboardShown)
        return;

      // Do not show pin keyboard if the pod does not have pin enabled.
      if (visible && !this.pinEnabled)
        return;

      var elements = this.getElementsByClassName('pin-tag');
      for (var i = 0; i < elements.length; ++i)
        this.updatePinClass_(elements[i], visible);
      this.updatePinClass_(this, visible);

      // Set the focus to the input element after showing/hiding pin keyboard.
      this.mainInput.focus();

      // Change the password placeholder based on pin keyboard visibility.
      this.passwordElement.placeholder = loadTimeData.getString(visible ?
          'pinKeyboardPlaceholderPinPassword' : 'passwordHint');
    },

    isPinShown: function() {
      return this.classList.contains('pin-enabled');
    },

    setUserPodIconType: function(userTypeClass) {
      this.userTypeIconAreaElement.classList.add(userTypeClass);
      this.userTypeIconAreaElement.hidden = false;
    },

    isFingerprintIconShown: function() {
      return this.fingerprintIconElement && !this.fingerprintIconElement.hidden;
    },

    /**
     * The user that this pod represents.
     * @type {!Object}
     */
    user_: undefined,
    get user() {
      return this.user_;
    },
    set user(userDict) {
      this.user_ = userDict;
      this.update();
    },

    /**
     * Returns true if multi-profiles sign in is currently active and this
     * user pod is restricted per policy.
     * @type {boolean}
     */
    get multiProfilesPolicyApplied() {
      var isMultiProfilesUI =
        (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING);
      return isMultiProfilesUI && !this.user_.isMultiProfilesAllowed;
    },

    /**
     * Gets main input element.
     * @type {(HTMLButtonElement|HTMLInputElement)}
     */
    get mainInput() {
      if (this.isAuthTypePassword) {
        return this.passwordElement;
      } else if (this.isAuthTypeOnlineSignIn) {
        return this;
      } else if (this.isAuthTypeUserClick) {
        return this.passwordLabelElement;
      }
    },

    /**
     * Whether action box button is in active state.
     * @type {boolean}
     */
    get isActionBoxMenuActive() {
      return this.actionBoxAreaElement.classList.contains('active');
    },
    set isActionBoxMenuActive(active) {
      if (active == this.isActionBoxMenuActive)
        return;

      if (active) {
        this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove;
        this.actionBoxRemoveUserWarningElement.hidden = true;

        // Clear focus first if another pod is focused.
        if (!this.parentNode.isFocused(this)) {
          this.parentNode.focusPod(undefined, true);
          this.actionBoxAreaElement.focus();
        }

        // Hide user-type-bubble.
        this.userTypeBubbleElement.classList.remove('bubble-shown');

        this.actionBoxAreaElement.classList.add('active');

        // Invisible focus causes ChromeVox to read user name and email.
        this.actionBoxMenuTitleElement.tabIndex = UserPodTabOrder.POD_MENU_ITEM;
        this.actionBoxMenuTitleElement.focus();

        // If the user pod is on either edge of the screen, then the menu
        // could be displayed partially ofscreen.
        this.actionBoxMenu.classList.remove('left-edge-offset');
        this.actionBoxMenu.classList.remove('right-edge-offset');

        var offsetLeft =
            cr.ui.login.DisplayManager.getOffset(this.actionBoxMenu).left;
        var menuWidth = this.actionBoxMenu.offsetWidth;
        if (offsetLeft < 0)
          this.actionBoxMenu.classList.add('left-edge-offset');
        else if (offsetLeft + menuWidth > window.innerWidth)
          this.actionBoxMenu.classList.add('right-edge-offset');
      } else {
        this.actionBoxAreaElement.classList.remove('active');
        this.actionBoxAreaElement.classList.remove('menu-moved-up');
        this.actionBoxMenu.classList.remove('menu-moved-up');
      }
    },

    /**
     * Whether action box button is in hovered state.
     * @type {boolean}
     */
    get isActionBoxMenuHovered() {
      return this.actionBoxAreaElement.classList.contains('hovered');
    },
    set isActionBoxMenuHovered(hovered) {
      if (hovered == this.isActionBoxMenuHovered)
        return;

      if (hovered) {
        this.actionBoxAreaElement.classList.add('hovered');
        this.classList.add('hovered');
      } else {
        if (this.multiProfilesPolicyApplied)
          this.userTypeBubbleElement.classList.remove('bubble-shown');
        this.actionBoxAreaElement.classList.remove('hovered');
        this.classList.remove('hovered');
      }
    },

    /**
     * Set the authentication type for the pod.
     * @param {number} An auth type value defined in the AUTH_TYPE enum.
     * @param {string} authValue The initial value used for the auth type.
     */
    setAuthType: function(authType, authValue) {
      this.authType_ = authType;
      this.authValue_ = authValue;
      this.setAttribute('auth-type', AUTH_TYPE_NAMES[this.authType_]);
      this.update();
      this.reset(this.parentNode.isFocused(this));
    },

    /**
     * The auth type of the user pod. This value is one of the enum
     * values in AUTH_TYPE.
     * @type {number}
     */
    get authType() {
      return this.authType_;
    },

    /**
     * The initial value used for the pod's authentication type.
     * eg. a prepopulated password input when using password authentication.
     */
    get authValue() {
      return this.authValue_;
    },

    /**
     * True if the the user pod uses a password to authenticate.
     * @type {bool}
     */
    get isAuthTypePassword() {
      return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD ||
             this.authType_ == AUTH_TYPE.FORCE_OFFLINE_PASSWORD;
    },

    /**
     * True if the the user pod uses a user click to authenticate.
     * @type {bool}
     */
    get isAuthTypeUserClick() {
      return this.authType_ == AUTH_TYPE.USER_CLICK;
    },

    /**
     * True if the the user pod uses a online sign in to authenticate.
     * @type {bool}
     */
    get isAuthTypeOnlineSignIn() {
      return this.authType_ == AUTH_TYPE.ONLINE_SIGN_IN;
    },

    /**
     * Updates the image element of the user.
     */
    updateUserImage: function() {
      UserPod.userImageSalt_[this.user.username] = new Date().getTime();
      this.update();
    },

    /**
     * Focuses on input element.
     */
    focusInput: function() {
      // Move tabIndex from the whole pod to the main input.
      // Note: the |mainInput| can be the pod itself.
      this.tabIndex = -1;
      this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
      this.mainInput.focus();
    },

    /**
     * Activates the pod.
     * @param {Event} e Event object.
     * @return {boolean} True if activated successfully.
     */
    activate: function(e) {
      if (this.isAuthTypeOnlineSignIn) {
        this.showSigninUI();
      } else if (this.isAuthTypeUserClick) {
        Oobe.disableSigninUI();
        this.classList.toggle('signing-in', true);
        chrome.send('attemptUnlock', [this.user.username]);
      } else if (this.isAuthTypePassword) {
        if (this.fingerprintAuthenticated_) {
          this.fingerprintAuthenticated_ = false;
          return true;
        }
        var pinValue = this.pinKeyboard ? this.pinKeyboard.value : '';
        var password = this.passwordElement.value || pinValue;
        if (!password)
          return false;
        Oobe.disableSigninUI();
        chrome.send('authenticateUser', [
          this.user.username, password, this.isPinShown() && !isNaN(password)
        ]);
      } else {
        console.error('Activating user pod with invalid authentication type: ' +
            this.authType);
      }

      return true;
    },

    showSupervisedUserSigninWarning: function() {
      // Legacy supervised user token has been invalidated.
      // Make sure that pod is focused i.e. "Sign in" button is seen.
      this.parentNode.focusPod(this);

      var error = document.createElement('div');
      var messageDiv = document.createElement('div');
      messageDiv.className = 'error-message-bubble';
      messageDiv.textContent =
          loadTimeData.getString('supervisedUserExpiredTokenWarning');
      error.appendChild(messageDiv);

      $('bubble').showContentForElement(
          this.reauthWarningElement,
          cr.ui.Bubble.Attachment.TOP,
          error,
          this.reauthWarningElement.offsetWidth / 2,
          4);
      // Move warning bubble up if it overlaps the shelf.
      var maxHeight =
          cr.ui.LoginUITools.getMaxHeightBeforeShelfOverlapping($('bubble'));
      if (maxHeight < $('bubble').offsetHeight) {
        $('bubble').showContentForElement(
            this.reauthWarningElement,
            cr.ui.Bubble.Attachment.BOTTOM,
            error,
            this.reauthWarningElement.offsetWidth / 2,
            4);
      }
    },

    /**
     * Shows signin UI for this user.
     */
    showSigninUI: function() {
      if (this.user.legacySupervisedUser && !this.user.isDesktopUser) {
        this.showSupervisedUserSigninWarning();
      } else {
        // Special case for multi-profiles sign in. We show users even if they
        // are not allowed per policy. Restrict those users from starting GAIA.
        if (this.multiProfilesPolicyApplied)
          return;

        this.parentNode.showSigninUI(this.user.emailAddress);
      }
    },

    /**
     * Resets the input field and updates the tab order of pod controls.
     * @param {boolean} takeFocus If true, input field takes focus.
     */
    reset: function(takeFocus) {
      this.passwordElement.value = '';
      if (this.pinKeyboard)
        this.pinKeyboard.value = '';
      this.updateInput_();
      this.classList.toggle('signing-in', false);
      if (takeFocus) {
        if (!this.multiProfilesPolicyApplied)
          this.focusInput();  // This will set a custom tab order.
      }
      else
        this.resetTabOrder();
    },

    /**
     * Removes a user using the correct identifier based on user type.
     * @param {Object} user User to be removed.
     */
    removeUser: function(user) {
      chrome.send('removeUser',
                  [user.isDesktopUser ? user.profilePath : user.username]);
    },

    /**
     * Handles a click event on action area button.
     * @param {Event} e Click event.
     */
    handleActionAreaButtonClick_: function(e) {
      if (this.parentNode.disabled)
        return;
      this.isActionBoxMenuActive = !this.isActionBoxMenuActive;
      e.stopPropagation();
    },

    /**
     * Handles a keydown event on action area button.
     * @param {Event} e KeyDown event.
     */
    handleActionAreaButtonKeyDown_: function(e) {
      if (this.disabled)
        return;
      switch (e.key) {
        case 'Enter':
        case ' ':
          if (this.parentNode.focusedPod_ && !this.isActionBoxMenuActive)
            this.isActionBoxMenuActive = true;
          e.stopPropagation();
          break;
        case 'ArrowUp':
        case 'ArrowDown':
          if (this.isActionBoxMenuActive) {
            this.actionBoxMenuRemoveElement.tabIndex =
                UserPodTabOrder.POD_MENU_ITEM;
            this.actionBoxMenuRemoveElement.focus();
          }
          e.stopPropagation();
          break;
        // Ignore these two, so ChromeVox hotkeys don't close the menu before
        // they can navigate through it.
        case 'Shift':
        case 'Meta':
          break;
        case 'Escape':
          this.actionBoxAreaElement.focus();
          this.isActionBoxMenuActive = false;
          e.stopPropagation();
          break;
        case 'Tab':
          if (!this.parentNode.alwaysFocusSinglePod)
            this.parentNode.focusPod();
        default:
          this.isActionBoxMenuActive = false;
          break;
      }
    },

    /**
     * Handles a keydown event on menu title.
     * @param {Event} e KeyDown event.
     */
    handleMenuTitleElementKeyDown_: function(e) {
      if (this.disabled)
        return;

      if (e.key != 'Tab') {
        this.handleActionAreaButtonKeyDown_(e);
        return;
      }

      if (e.shiftKey == false) {
        if (this.actionBoxMenuRemoveElement.hidden) {
          this.isActionBoxMenuActive = false;
        } else {
          this.actionBoxMenuRemoveElement.tabIndex =
              UserPodTabOrder.POD_MENU_ITEM;
          this.actionBoxMenuRemoveElement.focus();
          e.preventDefault();
        }
      } else {
        this.isActionBoxMenuActive = false;
        this.focusInput();
        e.preventDefault();
      }
    },

    /**
     * Handles a blur event on menu title.
     * @param {Event} e Blur event.
     */
    handleMenuTitleElementBlur_: function(e) {
      if (this.disabled)
        return;
      this.actionBoxMenuTitleElement.tabIndex = -1;
    },

    /**
     * Handles a click event on remove user command.
     * @param {Event} e Click event.
     */
    handleRemoveCommandClick_: function(e) {
      this.showRemoveWarning_();
    },

    /**
     * Move the action box menu up if needed.
     */
    moveActionMenuUpIfNeeded_: function() {
      // Skip checking (computationally expensive) if already moved up.
      if (this.actionBoxMenu.classList.contains('menu-moved-up'))
        return;

      // Move up the menu if it overlaps shelf.
      var maxHeight = cr.ui.LoginUITools.getMaxHeightBeforeShelfOverlapping(
          this.actionBoxMenu, true);
      var actualHeight = parseInt(
          window.getComputedStyle(this.actionBoxMenu).height);
      if (maxHeight < actualHeight) {
        this.actionBoxMenu.classList.add('menu-moved-up');
        this.actionBoxAreaElement.classList.add('menu-moved-up');
      }
    },

    /**
     * Shows remove user warning. Used for legacy supervised users
     * and non-device-owner on CrOS, and for all users on desktop.
     */
    showRemoveWarning_: function() {
      this.actionBoxMenuRemoveElement.hidden = true;
      this.actionBoxRemoveUserWarningElement.hidden = false;

      if (!this.user.isDesktopUser) {
        this.moveActionMenuUpIfNeeded_();
        if (!this.user.legacySupervisedUser) {
          this.querySelector(
              '.action-box-remove-user-warning-text').style.display = 'none';
          this.querySelector(
              '.action-box-remove-user-warning-table-nonsync').style.display
              = 'none';
          var message = loadTimeData.getString('removeNonOwnerUserWarningText');
          this.updateRemoveNonOwnerUserWarningMessage_(this.user.profilePath,
                                                       message);
        }
      } else {
        // Show extra statistics information for desktop users
        this.querySelector(
          '.action-box-remove-non-owner-user-warning-text').hidden = true;
        this.RemoveWarningDialogSetMessage_();
        // set a global handler for the callback
        window.updateRemoveWarningDialog =
            this.updateRemoveWarningDialog_.bind(this);
        var is_synced_user = this.user.emailAddress !== "";
        if (!is_synced_user) {
          chrome.send('removeUserWarningLoadStats', [this.user.profilePath]);
        }
      }
      chrome.send('logRemoveUserWarningShown');
    },

    /**
     * Refresh the statistics in the remove user warning dialog.
     * @param {string} profilePath The filepath of the URL (must be verified).
     * @param {Object} profileStats Statistics associated with profileURL.
     */
    updateRemoveWarningDialog_: function(profilePath, profileStats) {
      if (profilePath !== this.user.profilePath)
        return;

      var stats_elements = this.statsMapElements;
      // Update individual statistics
      for (var key in profileStats) {
        if (stats_elements.hasOwnProperty(key)) {
          stats_elements[key].textContent = profileStats[key].count;
        }
      }
    },

    /**
     * Set the new message in the dialog.
     */
    RemoveWarningDialogSetMessage_: function() {
      var is_synced_user = this.user.emailAddress !== "";
      message = loadTimeData.getString(
          is_synced_user ? 'removeUserWarningTextSync' :
                           'removeUserWarningTextNonSync');
      this.updateRemoveWarningDialogSetMessage_(this.user.profilePath,
                                                message);
    },

    /**
     * Refresh the message in the remove user warning dialog.
     * @param {string} profilePath The filepath of the URL (must be verified).
     * @param {string} message The message to be written.
     * @param {number|string=} count The number or string to replace $1 in
     * |message|. Can be omitted if $1 is not present in |message|.
     */
    updateRemoveWarningDialogSetMessage_: function(profilePath, message,
                                                   count) {
      if (profilePath !== this.user.profilePath)
        return;
      // Add localized messages where $1 will be replaced with
      // <span class="total-count"></span> and $2 will be replaced with
      // <span class="email"></span>.
      var element = this.querySelector('.action-box-remove-user-warning-text');
      element.textContent = '';

      messageParts = message.split(/(\$[12])/);
      var numParts = messageParts.length;
      for (var j = 0; j < numParts; j++) {
        if (messageParts[j] === '$1') {
          var elementToAdd = document.createElement('span');
          elementToAdd.classList.add('total-count');
          elementToAdd.textContent = count;
          element.appendChild(elementToAdd);
        } else if (messageParts[j] === '$2') {
          var elementToAdd = document.createElement('span');
          elementToAdd.classList.add('email');
          elementToAdd.textContent = this.user.emailAddress;
          element.appendChild(elementToAdd);
        } else {
          element.appendChild(document.createTextNode(messageParts[j]));
        }
      }
      this.moveActionMenuUpIfNeeded_();
    },

    /**
     * Update the message in the "remove non-owner user warning" dialog on CrOS.
     * @param {string} profilePath The filepath of the URL (must be verified).
     * @param (string) message The message to be written.
     */
    updateRemoveNonOwnerUserWarningMessage_: function(profilePath, message) {
      if (profilePath !== this.user.profilePath)
        return;
      // Add localized messages where $1 will be replaced with
      // <span class="email"></span>.
      var element = this.querySelector(
          '.action-box-remove-non-owner-user-warning-text');
      element.textContent = '';

      messageParts = message.split(/(\$[1])/);
      var numParts = messageParts.length;
      for (var j = 0; j < numParts; j++) {
        if (messageParts[j] == '$1') {
          var elementToAdd = document.createElement('span');
          elementToAdd.classList.add('email');
          elementToAdd.textContent = this.user.emailAddress;
          element.appendChild(elementToAdd);
        } else {
          element.appendChild(document.createTextNode(messageParts[j]));
        }
      }
      this.moveActionMenuUpIfNeeded_();
    },

    /**
     * Handles a click event on remove user confirmation button.
     * @param {Event} e Click event.
     */
    handleRemoveUserConfirmationClick_: function(e) {
      if (this.isActionBoxMenuActive) {
        this.isActionBoxMenuActive = false;
        this.removeUser(this.user);
        e.stopPropagation();
      }
    },

    /**
     * Handles mouseover event on fingerprint icon.
     * @param {Event} e MouseOver event.
     */
    handleFingerprintIconMouseOver_: function(e) {
      var bubbleContent = document.createElement('div');
      bubbleContent.textContent =
          loadTimeData.getString('fingerprintIconMessage');
      this.passwordElement.placeholder =
          loadTimeData.getString('fingerprintHint');

      /** @const */ var BUBBLE_OFFSET = 25;
      /** @const */ var BUBBLE_PADDING = -8;
      var attachment = this.isPinShown() ? cr.ui.Bubble.Attachment.RIGHT :
                                           cr.ui.Bubble.Attachment.BOTTOM;
      var bubbleAnchor = this.getBubbleAnchorForFingerprintIcon_();
      $('bubble').showContentForElement(
          bubbleAnchor, attachment, bubbleContent, BUBBLE_OFFSET,
          BUBBLE_PADDING, true);
    },

    /**
     * Handles mouseout event on fingerprint icon.
     * @param {Event} e MouseOut event.
     */
    handleFingerprintIconMouseOut_: function(e) {
      var bubbleAnchor = this.getBubbleAnchorForFingerprintIcon_();
      $('bubble').hideForElement(bubbleAnchor);
      this.passwordElement.placeholder = loadTimeData.getString(
          this.isPinShown() ? 'pinKeyboardPlaceholderPinPassword' :
                              'passwordHint');
    },

    /**
     * Returns bubble anchor of the fingerprint icon.
     * @return {!HTMLElement} Anchor element of the bubble.
     */
    getBubbleAnchorForFingerprintIcon_: function() {
      var bubbleAnchor = this;
      if (this.isPinShown())
        bubbleAnchor = (this.getElementsByClassName('auth-container'))[0];
      return bubbleAnchor;
    },

    /**
     * Handles a keydown event on remove user confirmation button.
     * @param {Event} e KeyDown event.
     */
    handleRemoveUserConfirmationKeyDown_: function(e) {
      if (!this.isActionBoxMenuActive)
        return;

      // Only handle pressing 'Enter' or 'Space', and let all other events
      // bubble to the action box menu.
      if (e.key == 'Enter' || e.key == ' ') {
        this.isActionBoxMenuActive = false;
        this.removeUser(this.user);
        e.stopPropagation();
        // Prevent default so that we don't trigger a 'click' event.
        e.preventDefault();
      }
    },

    /**
     * Handles a keydown event on remove command.
     * @param {Event} e KeyDown event.
     */
    handleRemoveCommandKeyDown_: function(e) {
      if (this.disabled)
        return;
      switch (e.key) {
        case 'Enter':
          e.preventDefault();
          this.showRemoveWarning_();
          e.stopPropagation();
          break;
        case 'ArrowUp':
        case 'ArrowDown':
          e.stopPropagation();
          break;
        // Ignore these two, so ChromeVox hotkeys don't close the menu before
        // they can navigate through it.
        case 'Shift':
        case 'Meta':
          break;
        case 'Escape':
          this.actionBoxAreaElement.focus();
          this.isActionBoxMenuActive = false;
          e.stopPropagation();
          break;
        default:
          this.actionBoxAreaElement.focus();
          this.isActionBoxMenuActive = false;
          break;
      }
    },

    /**
     * Handles a blur event on remove command.
     * @param {Event} e Blur event.
     */
    handleRemoveCommandBlur_: function(e) {
      if (this.disabled)
        return;
      this.actionBoxMenuRemoveElement.tabIndex = -1;
    },

    /**
     * Handles mouse down event. It sets whether the user click auth will be
     * allowed on the next mouse click event. The auth is allowed iff the pod
     * was focused on the mouse down event starting the click.
     * @param {Event} e The mouse down event.
     */
    handlePodMouseDown_: function(e) {
      this.userClickAuthAllowed_ = this.parentNode.isFocused(this);
    },

    /**
     * Called when the input of the password element changes. Updates the submit
     * button color and state and hides the error popup bubble.
     */
    updateInput_: function() {
      if (this.submitButton) {
        this.submitButton.disabled = this.passwordElement.value.length == 0;
        if (this.isFingerprintIconShown()) {
          this.submitButton.hidden = this.passwordElement.value.length == 0;
        } else {
          this.submitButton.hidden = false;
        }
      }
      this.showError = false;
      $('bubble').hide();
    },

    /**
     * Handles input event on the password element.
     * @param {Event} e Input event.
     */
    handleInputChanged_: function(e) {
      this.updateInput_();
    },

    /**
     * Handles click event on a user pod.
     * @param {Event} e Click event.
     */
    handleClickOnPod_: function(e) {
      if (this.parentNode.disabled)
        return;

      if (!this.isActionBoxMenuActive) {
        if (this.isAuthTypeOnlineSignIn) {
          this.showSigninUI();
        } else if (this.isAuthTypeUserClick && this.userClickAuthAllowed_) {
          // Note that this.userClickAuthAllowed_ is set in mouse down event
          // handler.
          this.parentNode.setActivatedPod(this);
        } else if (this.pinKeyboard &&
                   e.target == this.pinKeyboard.submitButton) {
          // Sets the pod as activated if the submit button is clicked so that
          // it simulates what the enter button does for the password/pin.
          this.parentNode.setActivatedPod(this);
        }

        if (this.multiProfilesPolicyApplied)
          this.userTypeBubbleElement.classList.add('bubble-shown');

        // Prevent default so that we don't trigger 'focus' event and
        // stop propagation so that the 'click' event does not bubble
        // up and accidentally closes the bubble tooltip.
        stopEventPropagation(e);
      }
    },

    /**
     * Handles keydown event for a user pod.
     * @param {Event} e Key event.
     */
    handlePodKeyDown_: function(e) {
      if (!this.isAuthTypeUserClick || this.disabled)
        return;
      switch (e.key) {
        case 'Enter':
        case ' ':
          if (this.parentNode.isFocused(this))
            this.parentNode.setActivatedPod(this);
          break;
      }
    }
  };

  /**
   * Creates a public account user pod.
   * @constructor
   * @extends {UserPod}
   */
  var PublicAccountUserPod = cr.ui.define(function() {
    var node = UserPod();

    var extras = $('public-account-user-pod-extras-template').children;
    for (var i = 0; i < extras.length; ++i) {
      var el = extras[i].cloneNode(true);
      node.appendChild(el);
    }

    return node;
  });

  PublicAccountUserPod.prototype = {
    __proto__: UserPod.prototype,

    /**
     * "Enter" button in expanded side pane.
     * @type {!HTMLButtonElement}
     */
    get enterButtonElement() {
      return this.querySelector('.enter-button');
    },

    /**
     * Boolean flag of whether the pod is showing the side pane. The flag
     * controls whether 'expanded' class is added to the pod's class list and
     * resets tab order because main input element changes when the 'expanded'
     * state changes.
     * @type {boolean}
     */
    get expanded() {
      return this.classList.contains('expanded');
    },

    set expanded(expanded) {
      if (this.expanded == expanded)
        return;

      this.resetTabOrder();
      this.classList.toggle('expanded', expanded);
      if (expanded) {
        // Show the advanced expanded pod directly if there are at least two
        // recommended locales. This will be the case in multilingual
        // environments where users are likely to want to choose among locales.
        if (this.querySelector('.language-select').multipleRecommendedLocales)
          this.classList.add('advanced');
        this.usualLeft = this.left;
        this.makeSpaceForExpandedPod_();
      } else if (typeof(this.usualLeft) != 'undefined') {
        this.left = this.usualLeft;
      }

      var self = this;
      this.classList.add('animating');
      this.addEventListener('transitionend', function f(e) {
        self.removeEventListener('transitionend', f);
        self.classList.remove('animating');

        // Accessibility focus indicator does not move with the focused
        // element. Sends a 'focus' event on the currently focused element
        // so that accessibility focus indicator updates its location.
        if (document.activeElement)
          document.activeElement.dispatchEvent(new Event('focus'));
      });
      // Guard timer set to animation duration + 20ms.
      ensureTransitionEndEvent(this, 200);
    },

    get advanced() {
      return this.classList.contains('advanced');
    },

    /** @override */
    get mainInput() {
      if (this.expanded)
        return this.enterButtonElement;
      else
        return this.nameElement;
    },

    /** @override */
    decorate: function() {
      UserPod.prototype.decorate.call(this);

      this.classList.add('public-account');

      this.nameElement.addEventListener('keydown', (function(e) {
        if (e.key == 'Enter') {
          this.parentNode.setActivatedPod(this, e);
          // Stop this keydown event from bubbling up to PodRow handler.
          e.stopPropagation();
          // Prevent default so that we don't trigger a 'click' event on the
          // newly focused "Enter" button.
          e.preventDefault();
        }
      }).bind(this));

      var learnMore = this.querySelector('.learn-more');
      learnMore.addEventListener('mousedown', stopEventPropagation);
      learnMore.addEventListener('click', this.handleLearnMoreEvent);
      learnMore.addEventListener('keydown', this.handleLearnMoreEvent);

      learnMore = this.querySelector('.expanded-pane-learn-more');
      learnMore.addEventListener('click', this.handleLearnMoreEvent);
      learnMore.addEventListener('keydown', this.handleLearnMoreEvent);

      var languageSelect = this.querySelector('.language-select');
      languageSelect.tabIndex = UserPodTabOrder.POD_INPUT;
      languageSelect.manuallyChanged = false;
      languageSelect.addEventListener(
          'change',
          function() {
            languageSelect.manuallyChanged = true;
            this.getPublicSessionKeyboardLayouts_();
          }.bind(this));

      var keyboardSelect = this.querySelector('.keyboard-select');
      keyboardSelect.tabIndex = UserPodTabOrder.POD_INPUT;
      keyboardSelect.loadedLocale = null;

      var languageAndInput = this.querySelector('.language-and-input');
      languageAndInput.tabIndex = UserPodTabOrder.POD_INPUT;
      languageAndInput.addEventListener('click',
                                        this.transitionToAdvanced_.bind(this));

      var monitoringLearnMore = this.querySelector('.monitoring-learn-more');
      monitoringLearnMore.tabIndex = UserPodTabOrder.POD_INPUT;
      monitoringLearnMore.addEventListener(
          'click', this.onMonitoringLearnMoreClicked_.bind(this));

      this.enterButtonElement.addEventListener('click', (function(e) {
        this.enterButtonElement.disabled = true;
        var locale = this.querySelector('.language-select').value;
        var keyboardSelect = this.querySelector('.keyboard-select');
        // The contents of |keyboardSelect| is updated asynchronously. If its
        // locale does not match |locale|, it has not updated yet and the
        // currently selected keyboard layout may not be applicable to |locale|.
        // Do not return any keyboard layout in this case and let the backend
        // choose a suitable layout.
        var keyboardLayout =
            keyboardSelect.loadedLocale == locale ? keyboardSelect.value : '';
        chrome.send('launchPublicSession',
                    [this.user.username, locale, keyboardLayout]);
      }).bind(this));
    },

    /** @override **/
    initialize: function() {
      UserPod.prototype.initialize.call(this);

      id = this.user.username + '-keyboard';
      this.querySelector('.keyboard-select-label').htmlFor = id;
      this.querySelector('.keyboard-select').setAttribute('id', id);

      var id = this.user.username + '-language';
      this.querySelector('.language-select-label').htmlFor = id;
      var languageSelect = this.querySelector('.language-select');
      languageSelect.setAttribute('id', id);
      this.populateLanguageSelect(this.user.initialLocales,
                                  this.user.initialLocale,
                                  this.user.initialMultipleRecommendedLocales);
    },

    /** @override **/
    update: function() {
      UserPod.prototype.update.call(this);
      this.querySelector('.expanded-pane-name').textContent =
          this.user_.displayName;
      this.querySelector('.info').textContent =
          loadTimeData.getStringF('publicAccountInfoFormat',
                                  this.user_.enterpriseDisplayDomain);
    },

    /** @override */
    focusInput: function() {
      // Move tabIndex from the whole pod to the main input.
      this.tabIndex = -1;
      this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
      this.mainInput.focus();
    },

    /** @override */
    reset: function(takeFocus) {
      if (!takeFocus)
        this.expanded = false;
      this.enterButtonElement.disabled = false;
      UserPod.prototype.reset.call(this, takeFocus);
    },

    /** @override */
    activate: function(e) {
      if (!this.expanded) {
        this.expanded = true;
        this.focusInput();
      }
      return true;
    },

    /** @override */
    handleClickOnPod_: function(e) {
      if (this.parentNode.disabled)
        return;

      this.parentNode.focusPod(this);
      this.parentNode.setActivatedPod(this, e);
      // Prevent default so that we don't trigger 'focus' event.
      e.preventDefault();
    },

    /**
     * Updates the display name shown on the pod.
     * @param {string} displayName The new display name
     */
    setDisplayName: function(displayName) {
      this.user_.displayName = displayName;
      this.update();
    },

    /**
     * Handle mouse and keyboard events for the learn more button. Triggering
     * the button causes information about public sessions to be shown.
     * @param {Event} event Mouse or keyboard event.
     */
    handleLearnMoreEvent: function(event) {
      switch (event.type) {
        // Show informaton on left click. Let any other clicks propagate.
        case 'click':
          if (event.button != 0)
            return;
          break;
        // Show informaton when <Return> or <Space> is pressed. Let any other
        // key presses propagate.
        case 'keydown':
          switch (event.keyCode) {
            case 13:  // Return.
            case 32:  // Space.
              break;
            default:
              return;
          }
          break;
      }
      chrome.send('launchHelpApp', [HELP_TOPIC_PUBLIC_SESSION]);
      stopEventPropagation(event);
    },

    makeSpaceForExpandedPod_: function() {
      var width = this.classList.contains('advanced') ?
          PUBLIC_EXPANDED_ADVANCED_WIDTH : PUBLIC_EXPANDED_BASIC_WIDTH;
      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;
      var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
                                              POD_ROW_PADDING;
      if (this.left + width > $('pod-row').offsetWidth - rowPadding)
        this.left = $('pod-row').offsetWidth - rowPadding - width;
    },

    /**
     * Transition the expanded pod from the basic to the advanced view.
     */
    transitionToAdvanced_: function() {
      var pod = this;
      var languageAndInputSection =
          this.querySelector('.language-and-input-section');
      this.classList.add('transitioning-to-advanced');
      setTimeout(function() {
        pod.classList.add('advanced');
        pod.makeSpaceForExpandedPod_();
        languageAndInputSection.addEventListener('transitionend',
                                                 function observer() {
          languageAndInputSection.removeEventListener('transitionend',
                                                      observer);
          pod.classList.remove('transitioning-to-advanced');
          pod.querySelector('.language-select').focus();
        });
        // Guard timer set to animation duration + 20ms.
        ensureTransitionEndEvent(languageAndInputSection, 380);
      }, 0);
    },

    /**
     * Show a dialog when user clicks on learn more (monitoring) button.
     */
    onMonitoringLearnMoreClicked_: function() {
      if (!this.dialogContainer_) {
        this.dialogContainer_ = document.createElement('div');
        this.dialogContainer_.classList.add('monitoring-dialog-container');
        var topContainer = document.querySelector('#scroll-container');
        topContainer.appendChild(this.dialogContainer_);
      }
      // Public Session POD in advanced view has a different size so add a dummy
      // parent element to enable different CSS settings.
      this.dialogContainer_.classList.toggle(
          'advanced', this.classList.contains('advanced'))
      var html = '';
      var infoItems = ['publicAccountMonitoringInfoItem1',
                       'publicAccountMonitoringInfoItem2',
                       'publicAccountMonitoringInfoItem3',
                       'publicAccountMonitoringInfoItem4'];
      for (item of infoItems) {
        html += '<p class="cr-dialog-item">';
        html += loadTimeData.getString(item);
        html += '</p>';
      }
      var title = loadTimeData.getString('publicAccountMonitoringInfo');
      this.dialog_ = new cr.ui.dialogs.BaseDialog(this.dialogContainer_);
      this.dialog_.showHtml(title, html, undefined,
                            this.onMonitoringDialogClosed_.bind(this));
      this.parentNode.disabled = true;
    },

    /**
     * Cleanup after the monitoring warning dialog is closed.
     */
    onMonitoringDialogClosed_: function() {
      this.parentNode.disabled = false;
      this.dialog_ = undefined;
    },

    /**
     * Retrieves the list of keyboard layouts available for the currently
     * selected locale.
     */
    getPublicSessionKeyboardLayouts_: function() {
      var selectedLocale = this.querySelector('.language-select').value;
      if (selectedLocale ==
          this.querySelector('.keyboard-select').loadedLocale) {
        // If the list of keyboard layouts was loaded for the currently selected
        // locale, it is already up to date.
        return;
      }
      chrome.send('getPublicSessionKeyboardLayouts',
                  [this.user.username, selectedLocale]);
     },

    /**
     * Populates the keyboard layout "select" element with a list of layouts.
     * @param {string} locale The locale to which this list of keyboard layouts
     *     applies
     * @param {!Object} list List of available keyboard layouts
     */
    populateKeyboardSelect: function(locale, list) {
      if (locale != this.querySelector('.language-select').value) {
        // The selected locale has changed and the list of keyboard layouts is
        // not applicable. This method will be called again when a list of
        // keyboard layouts applicable to the selected locale is retrieved.
        return;
      }

      var keyboardSelect = this.querySelector('.keyboard-select');
      keyboardSelect.loadedLocale = locale;
      keyboardSelect.innerHTML = '';
      for (var i = 0; i < list.length; ++i) {
        var item = list[i];
        keyboardSelect.appendChild(
            new Option(item.title, item.value, item.selected, item.selected));
      }
    },

    /**
     * Populates the language "select" element with a list of locales.
     * @param {!Object} locales The list of available locales
     * @param {string} defaultLocale The locale to select by default
     * @param {boolean} multipleRecommendedLocales Whether |locales| contains
     *     two or more recommended locales
     */
    populateLanguageSelect: function(locales,
                                     defaultLocale,
                                     multipleRecommendedLocales) {
      var languageSelect = this.querySelector('.language-select');
      // If the user manually selected a locale, do not change the selection.
      // Otherwise, select the new |defaultLocale|.
      var selected =
          languageSelect.manuallyChanged ? languageSelect.value : defaultLocale;
      languageSelect.innerHTML = '';
      var group = languageSelect;
      for (var i = 0; i < locales.length; ++i) {
        var item = locales[i];
        if (item.optionGroupName) {
          group = document.createElement('optgroup');
          group.label = item.optionGroupName;
          languageSelect.appendChild(group);
        } else {
          group.appendChild(new Option(item.title,
                                       item.value,
                                       item.value == selected,
                                       item.value == selected));
        }
      }
      languageSelect.multipleRecommendedLocales = multipleRecommendedLocales;

      // Retrieve a list of keyboard layouts applicable to the locale that is
      // now selected.
      this.getPublicSessionKeyboardLayouts_();
    }
  };

  /**
   * Creates a user pod to be used only in desktop chrome.
   * @constructor
   * @extends {UserPod}
   */
  var DesktopUserPod = cr.ui.define(function() {
    // Don't just instantiate a UserPod(), as this will call decorate() on the
    // parent object, and add duplicate event listeners.
    var node = $('user-pod-template').cloneNode(true);
    node.removeAttribute('id');
    return node;
  });

  DesktopUserPod.prototype = {
    __proto__: UserPod.prototype,

    /** @override */
    initialize: function() {
      if (this.user.needsSignin) {
        if (this.user.hasLocalCreds) {
          this.user.initialAuthType = AUTH_TYPE.OFFLINE_PASSWORD;
        } else {
          this.user.initialAuthType = AUTH_TYPE.ONLINE_SIGN_IN;
        }
      }
      UserPod.prototype.initialize.call(this);
    },

    /** @override */
    get mainInput() {
      if (this.user.needsSignin && this.user.hasLocalCreds)
        return this.passwordElement;
      else
        return this.nameElement;
    },

    /** @override */
    update: function() {
      this.imageElement.src = this.user.userImage;
      this.animatedImageElement.src = this.user.userImage;
      this.nameElement.textContent = this.user.displayName;
      this.reauthNameHintElement.textContent = this.user.displayName;

      var isLockedUser = this.user.needsSignin;
      var isLegacySupervisedUser = this.user.legacySupervisedUser;
      var isChildUser = this.user.childUser;
      var isSyncedUser = this.user.emailAddress !== "";
      var isProfileLoaded = this.user.isProfileLoaded;
      this.classList.toggle('locked', isLockedUser);
      this.classList.toggle('legacy-supervised', isLegacySupervisedUser);
      this.classList.toggle('child', isChildUser);
      this.classList.toggle('synced', isSyncedUser);

      if (this.isAuthTypeUserClick)
        this.passwordLabelElement.textContent = this.authValue;

      this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
        'passwordFieldAccessibleName', this.user_.emailAddress));

      UserPod.prototype.updateActionBoxArea.call(this);
    },

    /** @override */
    activate: function(e) {
      if (!this.user.needsSignin) {
        Oobe.launchUser(this.user.profilePath);
      } else if (this.user.hasLocalCreds && !this.passwordElement.value) {
        return false;
      } else {
        chrome.send('authenticatedLaunchUser',
                    [this.user.profilePath,
                     this.user.emailAddress,
                     this.passwordElement.value]);
      }
      this.passwordElement.value = '';
      return true;
    },

    /** @override */
    handleClickOnPod_: function(e) {
      if (this.parentNode.disabled)
        return;

      Oobe.clearErrors();
      this.parentNode.lastFocusedPod_ = this;

      // If this is a locked pod and there are local credentials, show the
      // password field.  Otherwise call activate() which will open up a browser
      // window or show the reauth dialog, as needed.
      if (!(this.user.needsSignin && this.user.hasLocalCreds) &&
          !this.isActionBoxMenuActive) {
        this.activate(e);
      }

      if (this.isAuthTypeUserClick)
        chrome.send('attemptUnlock', [this.user.emailAddress]);
    },
  };

  /**
   * Creates a user pod that represents kiosk app.
   * @constructor
   * @extends {UserPod}
   */
  var KioskAppPod = cr.ui.define(function() {
    var node = UserPod();
    return node;
  });

  KioskAppPod.prototype = {
    __proto__: UserPod.prototype,

    /** @override */
    decorate: function() {
      UserPod.prototype.decorate.call(this);
      this.launchAppButtonElement.addEventListener('click',
                                                   this.activate.bind(this));
    },

    /** @override */
    update: function() {
      this.imageElement.src = this.user.iconUrl;
      this.imageElement.alt = this.user.label;
      this.imageElement.title = this.user.label;
      this.animatedImageElement.src = this.user.iconUrl;
      this.animatedImageElement.alt = this.user.label;
      this.animatedImageElement.title = this.user.label;
      this.passwordEntryContainerElement.hidden = true;
      this.launchAppButtonContainerElement.hidden = false;
      this.nameElement.textContent = this.user.label;
      this.reauthNameHintElement.textContent = this.user.label;

      UserPod.prototype.updateActionBoxArea.call(this);
      UserPod.prototype.customizeUserPodPerUserType.call(this);
    },

    /** @override */
    get mainInput() {
      return this.launchAppButtonElement;
    },

    /** @override */
    focusInput: function() {
      // Move tabIndex from the whole pod to the main input.
      this.tabIndex = -1;
      this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
      this.mainInput.focus();
    },

    /** @override */
    get forceOnlineSignin() {
      return false;
    },

    /** @override */
    activate: function(e) {
      var diagnosticMode = e && e.ctrlKey;
      this.launchApp_(this.user, diagnosticMode);
      return true;
    },

    /** @override */
    handleClickOnPod_: function(e) {
      if (this.parentNode.disabled)
        return;

      Oobe.clearErrors();
      this.parentNode.lastFocusedPod_ = this;
      this.activate(e);
    },

    /**
     * Launch the app. If |diagnosticMode| is true, ask user to confirm.
     * @param {Object} app App data.
     * @param {boolean} diagnosticMode Whether to run the app in diagnostic
     *     mode.
     */
    launchApp_: function(app, diagnosticMode) {
      if (!diagnosticMode) {
        chrome.send('launchKioskApp', [app.id, false]);
        return;
      }

      var oobe = $('oobe');
      if (!oobe.confirmDiagnosticMode_) {
        oobe.confirmDiagnosticMode_ =
            new cr.ui.dialogs.ConfirmDialog(document.body);
        oobe.confirmDiagnosticMode_.setOkLabel(
            loadTimeData.getString('confirmKioskAppDiagnosticModeYes'));
        oobe.confirmDiagnosticMode_.setCancelLabel(
            loadTimeData.getString('confirmKioskAppDiagnosticModeNo'));
      }

      oobe.confirmDiagnosticMode_.show(
          loadTimeData.getStringF('confirmKioskAppDiagnosticModeFormat',
                                  app.label),
          function() {
            chrome.send('launchKioskApp', [app.id, true]);
          });
    },
  };

  /**
   * Creates a new pod row element.
   * @constructor
   * @extends {HTMLDivElement}
   */
  var PodRow = cr.ui.define('podrow');

  PodRow.prototype = {
    __proto__: HTMLDivElement.prototype,

    // Whether this user pod row is shown for the first time.
    firstShown_: true,

    // True if inside focusPod().
    insideFocusPod_: false,

    // Focused pod.
    focusedPod_: undefined,

    // Activated pod, i.e. the pod of current login attempt.
    activatedPod_: undefined,

    // Pod that was most recently focused, if any.
    lastFocusedPod_: undefined,

    // Pods whose initial images haven't been loaded yet.
    podsWithPendingImages_: [],

    // Whether pod placement has been postponed.
    podPlacementPostponed_: false,

    // Standard user pod height/width.
    userPodHeight_: 0,
    userPodWidth_: 0,

    // Array of apps that are shown in addition to other user pods.
    apps_: [],

    // True to show app pods along with user pods.
    shouldShowApps_: true,

    // Array of users that are shown (public/supervised/regular).
    users_: [],

    // If we're in tablet mode.
    tabletModeEnabled_: false,

    /** @override */
    decorate: function() {
      // Event listeners that are installed for the time period during which
      // the element is visible.
      this.listeners_ = {
        focus: [this.handleFocus_.bind(this), true /* useCapture */],
        click: [this.handleClick_.bind(this), true],
        mousemove: [this.handleMouseMove_.bind(this), false],
        keydown: [this.handleKeyDown.bind(this), false]
      };

      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;
      var isNewDesktopUserManager = Oobe.getInstance().newDesktopUserManager;
      this.userPodHeight_ = isDesktopUserManager ?
          isNewDesktopUserManager ? MD_DESKTOP_POD_HEIGHT :
                                    DESKTOP_POD_HEIGHT :
          CROS_POD_HEIGHT;
      this.userPodWidth_ = isDesktopUserManager ?
          isNewDesktopUserManager ? MD_DESKTOP_POD_WIDTH :
                                    DESKTOP_POD_WIDTH :
          CROS_POD_WIDTH;
    },

    /**
     * Returns all the pods in this pod row.
     * @type {NodeList}
     */
    get pods() {
      return Array.prototype.slice.call(this.children);
    },

    /**
     * Return true if user pod row has only single user pod in it, which should
     * always be focused except desktop and tablet modes.
     * @type {boolean}
     */
    get alwaysFocusSinglePod() {
      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;

      return (isDesktopUserManager || this.tabletModeEnabled_) ?
          false :
          this.children.length == 1;
    },

    /**
     * Returns pod with the given app id.
     * @param {!string} app_id Application id to be matched.
     * @return {Object} Pod with the given app id. null if pod hasn't been
     *     found.
     */
    getPodWithAppId_: function(app_id) {
      for (var i = 0, pod; pod = this.pods[i]; ++i) {
        if (pod.user.isApp && pod.user.id == app_id)
          return pod;
      }
      return null;
    },

    /**
     * Returns pod with the given username (null if there is no such pod).
     * @param {string} username Username to be matched.
     * @return {Object} Pod with the given username. null if pod hasn't been
     *     found.
     */
    getPodWithUsername_: function(username) {
      for (var i = 0, pod; pod = this.pods[i]; ++i) {
        if (pod.user.username == username)
          return pod;
      }
      return null;
    },

    /**
     * True if the the pod row is disabled (handles no user interaction).
     * @type {boolean}
     */
    disabled_: false,
    get disabled() {
      return this.disabled_;
    },
    set disabled(value) {
      this.disabled_ = value;
      this.pods.forEach(function(pod) {
        pod.disabled = value;
      });
    },

    /**
     * Creates a user pod from given email.
     * @param {!Object} user User info dictionary.
     */
    createUserPod: function(user) {
      var userPod;
      if (user.isDesktopUser)
        userPod = new DesktopUserPod({user: user});
      else if (user.publicAccount)
        userPod = new PublicAccountUserPod({user: user});
      else if (user.isApp)
        userPod = new KioskAppPod({user: user});
      else
        userPod = new UserPod({user: user});

      userPod.hidden = false;
      return userPod;
    },

    /**
     * Add an existing user pod to this pod row.
     * @param {!Object} user User info dictionary.
     */
    addUserPod: function(user) {
      var userPod = this.createUserPod(user);
      this.appendChild(userPod);
      userPod.initialize();
    },

    /**
     * Performs visual changes on the user pod if there is an error.
     * @param {boolean} visible Whether to show or hide the display.
     */
    setFocusedPodErrorDisplay: function(visible) {
      if (this.focusedPod_)
        this.focusedPod_.showError = visible;
    },

    /**
     * Shows or hides the pin keyboard for the current focused pod.
     * @param {boolean} visible
     */
    setFocusedPodPinVisibility: function(visible) {
      if (this.focusedPod_)
        this.focusedPod_.setPinVisibility(visible);
    },

    /**
     * Runs app with a given id from the list of loaded apps.
     * @param {!string} app_id of an app to run.
     * @param {boolean=} opt_diagnosticMode Whether to run the app in
     *     diagnostic mode. Default is false.
     */
    findAndRunAppForTesting: function(app_id, opt_diagnosticMode) {
      var app = this.getPodWithAppId_(app_id);
      if (app) {
        var activationEvent = cr.doc.createEvent('MouseEvents');
        var ctrlKey = opt_diagnosticMode;
        activationEvent.initMouseEvent('click', true, true, null,
            0, 0, 0, 0, 0, ctrlKey, false, false, false, 0, null);
        app.dispatchEvent(activationEvent);
      }
    },

    /**
     * Enables or disables the pin keyboard for the given user. A disabled pin
     * keyboard will never be displayed.
     *
     * If the user's pod is focused, then enabling the pin keyboard will display
     * it; disabling the pin keyboard will hide it.
     * @param {!string} username
     * @param {boolean} enabled
     */
    setPinEnabled: function(username, enabled) {
      var pod = this.getPodWithUsername_(username);
      if (!pod) {
        console.error('Attempt to enable/disable pin keyboard of missing pod.');
        return;
      }

      // Make sure to set |pinEnabled| before toggling visiblity to avoid
      // validation errors.
      pod.pinEnabled = enabled;

      if (this.focusedPod_ == pod) {
        if (enabled) {
          ensurePinKeyboardLoaded(
              this.setPinVisibility.bind(this, username, true));
        } else {
          this.setPinVisibility(username, false);
        }
      }
    },

    /**
     * Shows or hides the pin keyboard from the pod with the given |username|.
     * This is only a visibility change; the pin keyboard can be reshown.
     *
     * Use setPinEnabled if the pin keyboard should be disabled for the given
     * user.
     * @param {!user} username
     * @param {boolean} visible
     */
    setPinVisibility: function(username, visible) {
      var pod = this.getPodWithUsername_(username);
      if (!pod) {
        console.error('Attempt to show/hide pin keyboard of missing pod.');
        return;
      }
      if (visible && pod.pinEnabled === false) {
        console.error('Attempt to show disabled pin keyboard');
        return;
      }
      if (visible && this.focusedPod_ != pod) {
        console.error('Attempt to show pin keyboard on non-focused pod');
        return;
      }

      pod.setPinVisibility(visible);
    },

    /**
     * Removes user pod from pod row.
     * @param {!user} username
     */
    removeUserPod: function(username) {
      var podToRemove = this.getPodWithUsername_(username);
      if (podToRemove == null) {
        console.warn('Attempt to remove pod that does not exist');
        return;
      }
      this.removeChild(podToRemove);
      if (this.pods.length > 0)
        this.placePods_();
    },

    /**
     * Returns index of given pod or -1 if not found.
     * @param {UserPod} pod Pod to look up.
     * @private
     */
    indexOf_: function(pod) {
      for (var i = 0; i < this.pods.length; ++i) {
        if (pod == this.pods[i])
          return i;
      }
      return -1;
    },

    /**
     * Populates pod row with given existing users and start init animation.
     * @param {array} users Array of existing user emails.
     */
    loadPods: function(users) {
      this.users_ = users;

      this.rebuildPods();
    },

    /**
     * Scrolls focused user pod into view.
     */
    scrollFocusedPodIntoView: function() {
      var pod = this.focusedPod_;
      if (!pod)
        return;

      // First check whether focused pod is already fully visible.
      var visibleArea = $('scroll-container');
      // Visible area may not defined at user manager screen on all platforms.
      // Windows, Mac and Linux do not have visible area.
      if (!visibleArea)
        return;
      var scrollTop = visibleArea.scrollTop;
      var clientHeight = visibleArea.clientHeight;
      var podTop = $('oobe').offsetTop + pod.offsetTop;
      var padding = USER_POD_KEYBOARD_MIN_PADDING;
      if (podTop + pod.height + padding <= scrollTop + clientHeight &&
          podTop - padding >= scrollTop) {
        return;
      }

      // Scroll so that user pod is as centered as possible.
      visibleArea.scrollTop = podTop - (clientHeight - pod.offsetHeight) / 2;
    },

    /**
     * Rebuilds pod row using users_ and apps_ that were previously set or
     * updated.
     */
    rebuildPods: function() {
      var emptyPodRow = this.pods.length == 0;

      // Clear existing pods.
      this.innerHTML = '';
      this.focusedPod_ = undefined;
      this.activatedPod_ = undefined;
      this.lastFocusedPod_ = undefined;

      // Switch off animation
      Oobe.getInstance().toggleClass('flying-pods', false);

      // Populate the pod row.
      for (var i = 0; i < this.users_.length; ++i)
        this.addUserPod(this.users_[i]);

      for (var i = 0, pod; pod = this.pods[i]; ++i)
        this.podsWithPendingImages_.push(pod);

      // TODO(nkostylev): Edge case handling when kiosk apps are not fitting.
      if (this.shouldShowApps_) {
        for (var i = 0; i < this.apps_.length; ++i)
          this.addUserPod(this.apps_[i]);
      }

      // Make sure we eventually show the pod row, even if some image is stuck.
      setTimeout(function() {
        $('pod-row').classList.remove('images-loading');
      }, POD_ROW_IMAGES_LOAD_TIMEOUT_MS);

      var isAccountPicker = $('login-header-bar').signinUIState ==
          SIGNIN_UI_STATE.ACCOUNT_PICKER;

      // Immediately recalculate pods layout only when current UI is account
      // picker. Otherwise postpone it.
      if (isAccountPicker) {
        this.placePods_();
        this.maybePreselectPod();

        // Without timeout changes in pods positions will be animated even
        // though it happened when 'flying-pods' class was disabled.
        setTimeout(function() {
          Oobe.getInstance().toggleClass('flying-pods', true);
        }, 0);
      } else {
        this.podPlacementPostponed_ = true;

        // Update [Cancel] button state.
        if ($('login-header-bar').signinUIState ==
                SIGNIN_UI_STATE.GAIA_SIGNIN &&
            emptyPodRow &&
            this.pods.length > 0) {
          login.GaiaSigninScreen.updateControlsState();
        }
      }
    },

    /**
     * Adds given apps to the pod row.
     * @param {array} apps Array of apps.
     */
    setApps: function(apps) {
      this.apps_ = apps;
      this.rebuildPods();
      chrome.send('kioskAppsLoaded');

      // Check whether there's a pending kiosk app error.
      window.setTimeout(function() {
        chrome.send('checkKioskAppLaunchError');
      }, 500);
    },

    /**
     * Sets whether should show app pods.
     * @param {boolean} shouldShowApps Whether app pods should be shown.
     */
    setShouldShowApps: function(shouldShowApps) {
      if (this.shouldShowApps_ == shouldShowApps)
        return;

      this.shouldShowApps_ = shouldShowApps;
      this.rebuildPods();
    },

    /**
     * Shows a custom icon on a user pod besides the input field.
     * @param {string} username Username of pod to add button
     * @param {!{id: !string,
     *           hardlockOnClick: boolean,
     *           isTrialRun: boolean,
     *           ariaLabel: string | undefined,
     *           tooltip: ({text: string, autoshow: boolean} | undefined)}} icon
     *     The icon parameters.
     */
    showUserPodCustomIcon: function(username, icon) {
      var pod = this.getPodWithUsername_(username);
      if (pod == null) {
        console.error('Unable to show user pod button: user pod not found.');
        return;
      }

      if (!icon.id && !icon.tooltip)
        return;

      if (icon.id)
        pod.customIconElement.setIcon(icon.id);

      if (icon.isTrialRun) {
        pod.customIconElement.setInteractive(
            this.onDidClickLockIconDuringTrialRun_.bind(this, username));
      } else if (icon.hardlockOnClick) {
        pod.customIconElement.setInteractive(
            this.hardlockUserPod_.bind(this, username));
      } else {
        pod.customIconElement.setInteractive(null);
      }

      var ariaLabel = icon.ariaLabel || (icon.tooltip && icon.tooltip.text);
      if (ariaLabel)
        pod.customIconElement.setAriaLabel(ariaLabel);
      else
        console.warn('No ARIA label for user pod custom icon.');

      pod.customIconElement.show();

      // This has to be called after |show| in case the tooltip should be shown
      // immediatelly.
      pod.customIconElement.setTooltip(
          icon.tooltip || {text: '', autoshow: false});

      // Hide fingerprint icon when custom icon is shown.
      this.setUserPodFingerprintIcon(username, FINGERPRINT_STATES.HIDDEN);
    },

    /**
     * Hard-locks user pod for the user. If user pod is hard-locked, it can be
     * only unlocked using password, and the authentication type cannot be
     * changed.
     * @param {!string} username The user's username.
     * @private
     */
    hardlockUserPod_: function(username) {
      chrome.send('hardlockPod', [username]);
    },

    /**
     * Records a metric indicating that the user clicked on the lock icon during
     * the trial run for Easy Unlock.
     * @param {!string} username The user's username.
     * @private
     */
    onDidClickLockIconDuringTrialRun_: function(username) {
      chrome.send('recordClickOnLockIcon', [username]);
    },

    /**
     * Hides the custom icon in the user pod added by showUserPodCustomIcon().
     * @param {string} username Username of pod to remove button
     */
    hideUserPodCustomIcon: function(username) {
      var pod = this.getPodWithUsername_(username);
      if (pod == null) {
        console.error('Unable to hide user pod button: user pod not found.');
        return;
      }

      // TODO(tengs): Allow option for a fading transition.
      pod.customIconElement.hide();

      // Show fingerprint icon if applicable.
      this.setUserPodFingerprintIcon(username, FINGERPRINT_STATES.DEFAULT);
    },

    /**
     * Set a fingerprint icon in the user pod of |username|.
     * @param {string} username Username of the selected user
     * @param {number} state Fingerprint unlock state
     */
    setUserPodFingerprintIcon: function(username, state) {
      var pod = this.getPodWithUsername_(username);
      if (pod == null) {
        console.error(
            'Unable to set user pod fingerprint icon: user pod not found.');
        return;
      }
      pod.fingerprintAuthenticated_ = false;
      if (!pod.fingerprintIconElement)
        return;
      if (!pod.user.allowFingerprint || state == FINGERPRINT_STATES.HIDDEN ||
          !pod.customIconElement.hidden) {
        pod.fingerprintIconElement.hidden = true;
        pod.submitButton.hidden = false;
        return;
      }

      FINGERPRINT_STATES_MAPPING.forEach(function(icon) {
          pod.fingerprintIconElement.classList.toggle(
              icon.class, state == icon.state);
      });
      pod.fingerprintIconElement.hidden = false;
      pod.submitButton.hidden = pod.passwordElement.value.length == 0;
      this.updatePasswordField_(pod, state);
      if (state == FINGERPRINT_STATES.DEFAULT)
        return;

      pod.fingerprintAuthenticated_ = true;
      this.setActivatedPod(pod);
      if (state == FINGERPRINT_STATES.FAILED) {
        /** @const */ var RESET_ICON_TIMEOUT_MS = 500;
        setTimeout(
            this.resetIconAndPasswordField_.bind(this, pod),
            RESET_ICON_TIMEOUT_MS);
      }
    },

    /**
     * Reset the fingerprint icon and password field.
     * @param {UserPod} pod Pod to reset.
     */
    resetIconAndPasswordField_: function(pod) {
      if (!pod.fingerprintIconElement)
        return;
      this.setUserPodFingerprintIcon(
          pod.user.username, FINGERPRINT_STATES.DEFAULT);
    },

    /**
     * Remove the fingerprint icon in the user pod.
     * @param {string} username Username of the selected user
     */
    removeUserPodFingerprintIcon: function(username) {
      var pod = this.getPodWithUsername_(username);
      if (pod == null) {
        console.error('No user pod found (when removing fingerprint icon).');
        return;
      }
      this.resetIconAndPasswordField_(pod);
      if (pod.fingerprintIconElement) {
        pod.fingerprintIconElement.parentNode.removeChild(
            pod.fingerprintIconElement);
      }
      pod.submitButton.hidden = false;
    },

    /**
     * Updates the password field in the user pod.
     * @param {UserPod} pod Pod to update.
     * @param {number} state Fingerprint unlock state
     */
    updatePasswordField_: function(pod, state) {
      FINGERPRINT_STATES_MAPPING.forEach(function(item) {
        pod.passwordElement.classList.toggle(item.class, state == item.state);
      });
      var placeholderStr = loadTimeData.getString(
          pod.isPinShown() ? 'pinKeyboardPlaceholderPinPassword' :
                             'passwordHint');
      if (state == FINGERPRINT_STATES.SIGNIN) {
        placeholderStr = loadTimeData.getString('fingerprintSigningin');
      } else if (state == FINGERPRINT_STATES.FAILED) {
        placeholderStr = loadTimeData.getString('fingerprintSigninFailed');
      }
      pod.passwordElement.placeholder = placeholderStr;
    },

    /**
     * Sets the authentication type used to authenticate the user.
     * @param {string} username Username of selected user
     * @param {number} authType Authentication type, must be one of the
     *                          values listed in AUTH_TYPE enum.
     * @param {string} value The initial value to use for authentication.
     */
    setAuthType: function(username, authType, value) {
      var pod = this.getPodWithUsername_(username);
      if (pod == null) {
        console.error('Unable to set auth type: user pod not found.');
        return;
      }
      pod.setAuthType(authType, value);
    },

    /**
     * Sets the state of tablet mode.
     * @param {boolean} isTabletModeEnabled true if the mode is on.
     */
    setTabletModeState: function(isTabletModeEnabled) {
      this.tabletModeEnabled_ = isTabletModeEnabled;
      this.pods.forEach(function(pod, index) {
        pod.actionBoxAreaElement.classList.toggle(
            'forced', isTabletModeEnabled);
      });
    },

    /**
     * Updates the display name shown on a public session pod.
     * @param {string} userID The user ID of the public session
     * @param {string} displayName The new display name
     */
    setPublicSessionDisplayName: function(userID, displayName) {
      var pod = this.getPodWithUsername_(userID);
      if (pod != null)
        pod.setDisplayName(displayName);
    },

    /**
     * Updates the list of locales available for a public session.
     * @param {string} userID The user ID of the public session
     * @param {!Object} locales The list of available locales
     * @param {string} defaultLocale The locale to select by default
     * @param {boolean} multipleRecommendedLocales Whether |locales| contains
     *     two or more recommended locales
     */
    setPublicSessionLocales: function(userID,
                                      locales,
                                      defaultLocale,
                                      multipleRecommendedLocales) {
      var pod = this.getPodWithUsername_(userID);
      if (pod != null) {
        pod.populateLanguageSelect(locales,
                                   defaultLocale,
                                   multipleRecommendedLocales);
      }
    },

    /**
     * Updates the list of available keyboard layouts for a public session pod.
     * @param {string} userID The user ID of the public session
     * @param {string} locale The locale to which this list of keyboard layouts
     *     applies
     * @param {!Object} list List of available keyboard layouts
     */
    setPublicSessionKeyboardLayouts: function(userID, locale, list) {
      var pod = this.getPodWithUsername_(userID);
      if (pod != null)
        pod.populateKeyboardSelect(locale, list);
    },

    /**
     * Called when window was resized.
     */
    onWindowResize: function() {
      var layout = this.calculateLayout_();
      if (layout.columns != this.columns || layout.rows != this.rows)
        this.placePods_();

      // Wrap this in a set timeout so the function is called after the pod is
      // finished transitioning so that we work with the final pod dimensions.
      // If there is no focused pod that may be transitioning when this function
      // is called, we can call scrollFocusedPodIntoView() right away.
      var timeOut = 0;
      if (this.focusedPod_) {
        var style = getComputedStyle(this.focusedPod_);
        timeOut = parseFloat(style.transitionDuration) * 1000;
      }

      setTimeout(function() {
        this.scrollFocusedPodIntoView();
      }.bind(this), timeOut);
    },

    /**
     * Returns width of podrow having |columns| number of columns.
     * @private
     */
    columnsToWidth_: function(columns) {
      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;
      var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] :
                                          MARGIN_BY_COLUMNS[columns];
      var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
                                              POD_ROW_PADDING;
      return 2 * rowPadding + columns * this.userPodWidth_ +
          (columns - 1) * margin;
    },

    /**
     * Returns height of podrow having |rows| number of rows.
     * @private
     */
    rowsToHeight_: function(rows) {
      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;
      var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
                                              POD_ROW_PADDING;
      return 2 * rowPadding + rows * this.userPodHeight_;
    },

    /**
     * Calculates number of columns and rows that podrow should have in order to
     * hold as much its pods as possible for current screen size. Also it tries
     * to choose layout that looks good.
     * @return {{columns: number, rows: number}}
     */
    calculateLayout_: function() {
      var preferredColumns = this.pods.length < COLUMNS.length ?
          COLUMNS[this.pods.length] : COLUMNS[COLUMNS.length - 1];
      var maxWidth = Oobe.getInstance().clientAreaSize.width;
      var columns = preferredColumns;
      while (maxWidth < this.columnsToWidth_(columns) && columns > 1)
        --columns;
      var rows = Math.floor((this.pods.length - 1) / columns) + 1;
      if (getComputedStyle(
          $('signin-banner'), null).getPropertyValue('display') != 'none') {
        rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER);
      }
      if (!Oobe.getInstance().newDesktopUserManager) {
        var maxHeigth = Oobe.getInstance().clientAreaSize.height;
        while (maxHeigth < this.rowsToHeight_(rows) && rows > 1)
         --rows;
      }
      // One more iteration if it's not enough cells to place all pods.
      while (maxWidth >= this.columnsToWidth_(columns + 1) &&
             columns * rows < this.pods.length &&
             columns < MAX_NUMBER_OF_COLUMNS) {
         ++columns;
      }
      return {columns: columns, rows: rows};
    },

    /**
     * Places pods onto their positions onto pod grid.
     * @private
     */
    placePods_: function() {
      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;
      if (isDesktopUserManager && !Oobe.getInstance().userPodsPageVisible)
        return;

      var layout = this.calculateLayout_();
      var columns = this.columns = layout.columns;
      var rows = this.rows = layout.rows;
      var maxPodsNumber = columns * rows;
      var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] :
                                          MARGIN_BY_COLUMNS[columns];
      this.parentNode.setPreferredSize(
          this.columnsToWidth_(columns), this.rowsToHeight_(rows));
      var height = this.userPodHeight_;
      var width = this.userPodWidth_;
      var pinPodLocation = { column: columns + 1, row: rows + 1 };
      if (this.focusedPod_ && this.focusedPod_.isPinShown())
        pinPodLocation = this.findPodLocation_(this.focusedPod_, columns, rows);

      this.pods.forEach(function(pod, index) {
        if (index >= maxPodsNumber) {
           pod.hidden = true;
           return;
        }
        pod.hidden = false;
        if (pod.offsetHeight != height &&
            pod.offsetHeight != CROS_PIN_POD_HEIGHT) {
          console.error('Pod offsetHeight (' + pod.offsetHeight +
              ') and POD_HEIGHT (' + height + ') are not equal.');
        }
        if (pod.offsetWidth != width) {
          console.error('Pod offsetWidth (' + pod.offsetWidth +
              ') and POD_WIDTH (' + width + ') are not equal.');
        }
        var column = index % columns;
        var row = Math.floor(index / columns);

        var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
                                                POD_ROW_PADDING;
        pod.left = rowPadding + column * (width + margin);

        // On desktop, we want the rows to always be equally spaced.
        pod.top = isDesktopUserManager ? row * (height + rowPadding) :
                                         row * height + rowPadding;
      });
      Oobe.getInstance().updateScreenSize(this.parentNode);
    },

    /**
     * Number of columns.
     * @type {?number}
     */
    set columns(columns) {
      // Cannot use 'columns' here.
      this.setAttribute('ncolumns', columns);
    },
    get columns() {
      return parseInt(this.getAttribute('ncolumns'));
    },

    /**
     * Number of rows.
     * @type {?number}
     */
    set rows(rows) {
      // Cannot use 'rows' here.
      this.setAttribute('nrows', rows);
    },
    get rows() {
      return parseInt(this.getAttribute('nrows'));
    },

    /**
     * Whether the pod is currently focused.
     * @param {UserPod} pod Pod to check for focus.
     * @return {boolean} Pod focus status.
     */
    isFocused: function(pod) {
      return this.focusedPod_ == pod;
    },

    /**
     * Focuses a given user pod or clear focus when given null.
     * @param {UserPod=} podToFocus User pod to focus (undefined clears focus).
     * @param {boolean=} opt_force If true, forces focus update even when
     *     podToFocus is already focused.
     * @param {boolean=} opt_skipInputFocus If true, don't focus on the input
     *     box of user pod.
     */
    focusPod: function(podToFocus, opt_force, opt_skipInputFocus) {
      if (this.isFocused(podToFocus) && !opt_force) {
        // Calling focusPod w/o podToFocus means reset.
        if (!podToFocus)
          Oobe.clearErrors();
        return;
      }

      // Make sure there's only one focusPod operation happening at a time.
      if (this.insideFocusPod_) {
        return;
      }
      this.insideFocusPod_ = true;

      for (var i = 0, pod; pod = this.pods[i]; ++i) {
        if (!this.alwaysFocusSinglePod) {
          pod.isActionBoxMenuActive = false;
        }
        if (pod != podToFocus) {
          pod.isActionBoxMenuHovered = false;
          pod.classList.remove('focused');
          pod.setPinVisibility(false);
          this.setUserPodFingerprintIcon(
              pod.user.username, FINGERPRINT_STATES.HIDDEN);
          // On Desktop, the faded style is not set correctly, so we should
          // manually fade out non-focused pods if there is a focused pod.
          if (pod.user.isDesktopUser && podToFocus)
            pod.classList.add('faded');
          else
            pod.classList.remove('faded');
          pod.reset(false);
        }
      }

      // Clear any error messages for previous pod.
      if (!this.isFocused(podToFocus))
        Oobe.clearErrors();

      this.focusedPod_ = podToFocus;
      if (podToFocus) {
        // Only show the keyboard if it is fully loaded.
        if (podToFocus.isPinReady())
          podToFocus.setPinVisibility(true);
        podToFocus.classList.remove('faded');
        podToFocus.classList.add('focused');
        if (!podToFocus.multiProfilesPolicyApplied) {
          podToFocus.classList.toggle('signing-in', false);
          if (!opt_skipInputFocus)
            podToFocus.focusInput();
        } else {
          podToFocus.userTypeBubbleElement.classList.add('bubble-shown');
          // Note it is not necessary to skip this focus request when
          // |opt_skipInputFocus| is true. When |multiProfilesPolicyApplied|
          // is false, it doesn't focus on the password input box by default.
          podToFocus.focus();
        }

        if (!podToFocus.user.isApp)
          chrome.send(
              'focusPod',
              [podToFocus.user.username, true /* loads wallpaper */]);
        this.firstShown_ = false;
        this.lastFocusedPod_ = podToFocus;
        this.scrollFocusedPodIntoView();
        this.setUserPodFingerprintIcon(
            podToFocus.user.username, FINGERPRINT_STATES.DEFAULT);
      } else {
        chrome.send('noPodFocused');
      }
      this.insideFocusPod_ = false;
    },

    /**
     * Returns the currently activated pod.
     * @type {UserPod}
     */
    get activatedPod() {
      return this.activatedPod_;
    },

    /**
     * Sets currently activated pod.
     * @param {UserPod} pod Pod to check for focus.
     * @param {Event} e Event object.
     */
    setActivatedPod: function(pod, e) {
      if (this.disabled) {
        console.error('Cannot activate pod while sign-in UI is disabled.');
        return;
      }
      if (pod && pod.activate(e))
        this.activatedPod_ = pod;
    },

    /**
     * The pod of the signed-in user, if any; null otherwise.
     * @type {?UserPod}
     */
    get lockedPod() {
      for (var i = 0, pod; pod = this.pods[i]; ++i) {
        if (pod.user.signedIn)
          return pod;
      }
      return null;
    },

    /**
     * The pod that is preselected on user pod row show.
     * @type {?UserPod}
     */
    get preselectedPod() {
      var isDesktopUserManager = Oobe.getInstance().displayType ==
          DISPLAY_TYPE.DESKTOP_USER_MANAGER;
      if (isDesktopUserManager) {
        // On desktop, don't pre-select a pod if it's the only one.
        if (this.pods.length == 1)
          return null;

        // The desktop User Manager can send an URI encoded profile path in the
        // url hash, that indicates a pod that should be initially focused.
        var focusedProfilePath =
            decodeURIComponent(window.location.hash.substr(1));
        for (var i = 0, pod; pod = this.pods[i]; ++i) {
          if (focusedProfilePath === pod.user.profilePath)
            return pod;
        }
        return null;
      }

      var lockedPod = this.lockedPod;
      if (lockedPod)
        return lockedPod;
      for (i = 0; pod = this.pods[i]; ++i) {
        if (!pod.multiProfilesPolicyApplied)
          return pod;
      }
      return this.pods[0];
    },

    /**
     * Resets input UI.
     * @param {boolean} takeFocus True to take focus.
     */
    reset: function(takeFocus) {
      this.disabled = false;
      if (this.activatedPod_)
        this.activatedPod_.reset(takeFocus);
    },

    /**
     * Restores input focus to current selected pod, if there is any.
     */
    refocusCurrentPod: function() {
      if (this.focusedPod_ && !this.focusedPod_.multiProfilesPolicyApplied) {
        this.focusedPod_.focusInput();
      }
    },

    /**
     * Clears focused pod password field.
     */
    clearFocusedPod: function() {
      if (!this.disabled && this.focusedPod_)
        this.focusedPod_.reset(true);
    },

    /**
     * Shows signin UI.
     * @param {string} email Email for signin UI.
     */
    showSigninUI: function(email) {
      // Clear any error messages that might still be around.
      Oobe.clearErrors();
      this.disabled = true;
      this.lastFocusedPod_ = this.getPodWithUsername_(email);
      Oobe.showSigninUI(email);
    },

    /**
     * Updates current image of a user.
     * @param {string} username User for which to update the image.
     */
    updateUserImage: function(username) {
      var pod = this.getPodWithUsername_(username);
      if (pod)
        pod.updateUserImage();
    },

    /**
     * Handler of click event.
     * @param {Event} e Click Event object.
     * @private
     */
    handleClick_: function(e) {
      if (this.disabled)
        return;

      // Clear all menus if the click is outside pod menu and its
      // button area.
      if (!findAncestorByClass(e.target, 'action-box-menu') &&
          !findAncestorByClass(e.target, 'action-box-area')) {
        for (var i = 0, pod; pod = this.pods[i]; ++i)
          pod.isActionBoxMenuActive = false;
      }

      // Clears focus if not clicked on a pod and if there's more than one pod.
      var pod = findAncestorByClass(e.target, 'pod');
      if ((!pod || pod.parentNode != this) && !this.alwaysFocusSinglePod) {
        this.focusPod();
      }

      if (pod)
        pod.isActionBoxMenuHovered = true;

      // Return focus back to single pod.
      if (this.alwaysFocusSinglePod && !pod) {
        if ($('login-header-bar').contains(e.target))
          return;
        this.focusPod(this.focusedPod_, true /* force */);
        this.focusedPod_.userTypeBubbleElement.classList.remove('bubble-shown');
        this.focusedPod_.isActionBoxMenuHovered = false;
      }
    },

    /**
     * Handler of mouse move event.
     * @param {Event} e Click Event object.
     * @private
     */
    handleMouseMove_: function(e) {
      if (this.disabled)
        return;
      if (e.movementX == 0 && e.movementY == 0)
        return;

      // Defocus (thus hide) action box, if it is focused on a user pod
      // and the pointer is not hovering over it.
      var pod = findAncestorByClass(e.target, 'pod');
      if (document.activeElement &&
          document.activeElement.parentNode != pod &&
          document.activeElement.classList.contains('action-box-area')) {
        document.activeElement.parentNode.focus();
      }

      if (pod)
        pod.isActionBoxMenuHovered = true;

      // Hide action boxes on other user pods.
      for (var i = 0, p; p = this.pods[i]; ++i)
        if (p != pod && !p.isActionBoxMenuActive)
          p.isActionBoxMenuHovered = false;
    },

    /**
     * Handles focus event.
     * @param {Event} e Focus Event object.
     * @private
     */
    handleFocus_: function(e) {
      if (this.disabled)
        return;
      if (e.target.parentNode == this) {
        // Focus on a pod
        if (e.target.classList.contains('focused')) {
          if (!e.target.multiProfilesPolicyApplied)
            e.target.focusInput();
          else
            e.target.userTypeBubbleElement.classList.add('bubble-shown');
        } else
          this.focusPod(e.target);
        return;
      }

      var pod = findAncestorByClass(e.target, 'pod');
      if (pod && pod.parentNode == this) {
        // Focus on a control of a pod but not on the action area button.
        if (!pod.classList.contains('focused')) {
          if (e.target.classList.contains('action-box-area') ||
              e.target.classList.contains('remove-warning-button')) {
            // focusPod usually moves focus on the password input box which
            // triggers virtual keyboard to show up. But the focus may move to a
            // non text input element shortly by e.target.focus. Hence, a
            // virtual keyboard flicking might be observed. We need to manually
            // prevent focus on password input box to avoid virtual keyboard
            // flicking in this case. See crbug.com/396016 for details.
            this.focusPod(pod, false, true /* opt_skipInputFocus */);
          } else {
            this.focusPod(pod);
          }
          pod.userTypeBubbleElement.classList.remove('bubble-shown');
          e.target.focus();
        }
        return;
      }

      // Clears pod focus when we reach here. It means new focus is neither
      // on a pod nor on a button/input for a pod.
      // Do not "defocus" user pod when it is a single pod.
      // That means that 'focused' class will not be removed and
      // input field/button will always be visible.
      if (!this.alwaysFocusSinglePod)
        this.focusPod();
      else {
        // Hide user-type-bubble in case this is one pod and we lost focus of
        // it.
        this.focusedPod_.userTypeBubbleElement.classList.remove('bubble-shown');
      }
    },

    /**
     * Handler of keydown event.
     * @param {Event} e KeyDown Event object.
     */
    handleKeyDown: function(e) {
      if (this.disabled)
        return;
      var editing = e.target.tagName == 'INPUT' && e.target.value;
      switch (e.key) {
        case 'ArrowLeft':
          if (!editing) {
            if (this.focusedPod_ && this.focusedPod_.previousElementSibling)
              this.focusPod(this.focusedPod_.previousElementSibling);
            else
              this.focusPod(this.lastElementChild);

            e.stopPropagation();
          }
          break;
        case 'ArrowRight':
          if (!editing) {
            if (this.focusedPod_ && this.focusedPod_.nextElementSibling)
              this.focusPod(this.focusedPod_.nextElementSibling);
            else
              this.focusPod(this.firstElementChild);

            e.stopPropagation();
          }
          break;
        case 'Enter':
          if (this.focusedPod_) {
            var targetTag = e.target.tagName;
            if (e.target == this.focusedPod_.passwordElement ||
                (this.focusedPod_.pinKeyboard &&
                 e.target == this.focusedPod_.pinKeyboard.inputElement) ||
                (targetTag != 'INPUT' &&
                 targetTag != 'BUTTON' &&
                 targetTag != 'A')) {
              this.setActivatedPod(this.focusedPod_, e);
              e.stopPropagation();
            }
          }
          break;
        case 'Escape':
          if (!this.alwaysFocusSinglePod)
            this.focusPod();
          break;
      }
    },

    /**
     * Called right after the pod row is shown.
     */
    handleAfterShow: function() {
      var focusedPod = this.focusedPod_;

      // Without timeout changes in pods positions will be animated even though
      // it happened when 'flying-pods' class was disabled.
      setTimeout(function() {
        Oobe.getInstance().toggleClass('flying-pods', true);
        if (focusedPod)
          ensureTransitionEndEvent(focusedPod);
      }, 0);

      // Force input focus for user pod on show and once transition ends.
      if (focusedPod) {
        var screen = this.parentNode;
        var self = this;
        focusedPod.addEventListener('transitionend', function f(e) {
          focusedPod.removeEventListener('transitionend', f);
          focusedPod.reset(true);
          // Notify screen that it is ready.
          screen.onShow();
        });
      }
    },

    /**
     * Called right before the pod row is shown.
     */
    handleBeforeShow: function() {
      Oobe.getInstance().toggleClass('flying-pods', false);
      for (var event in this.listeners_) {
        this.ownerDocument.addEventListener(
            event, this.listeners_[event][0], this.listeners_[event][1]);
      }
      $('login-header-bar').buttonsTabIndex = UserPodTabOrder.HEADER_BAR;

      if (this.podPlacementPostponed_) {
        this.podPlacementPostponed_ = false;
        this.placePods_();
        this.maybePreselectPod();
      }
    },

    /**
     * Called when the element is hidden.
     */
    handleHide: function() {
      for (var event in this.listeners_) {
        this.ownerDocument.removeEventListener(
            event, this.listeners_[event][0], this.listeners_[event][1]);
      }
      $('login-header-bar').buttonsTabIndex = 0;
    },

    /**
     * Called when a pod's user image finishes loading.
     */
    handlePodImageLoad: function(pod) {
      var index = this.podsWithPendingImages_.indexOf(pod);
      if (index == -1) {
        return;
      }

      this.podsWithPendingImages_.splice(index, 1);
      if (this.podsWithPendingImages_.length == 0) {
        this.classList.remove('images-loading');
      }
    },

    /**
     * Preselects pod, if needed.
     */
     maybePreselectPod: function() {
       var pod = this.preselectedPod;
       this.focusPod(pod);

       // Hide user-type-bubble in case all user pods are disabled and we focus
       // first pod.
       if (pod && pod.multiProfilesPolicyApplied) {
         pod.userTypeBubbleElement.classList.remove('bubble-shown');
       }
     }
  };

  return {
    PodRow: PodRow
  };
});



cr.define('cr.ui', function() {
  const DisplayManager = cr.ui.login.DisplayManager;

  /**
   * Maximum possible height of the #login-header-bar, including the padding
   * and the border.
   * @type {number}
   */
  const MAX_LOGIN_HEADER_BAR_HEIGHT = 57;

  /**
   * Manages initialization of screens, transitions, and error messages.
   * @constructor
   * @extends {DisplayManager}
   */
  function UserManager() {}

  cr.addSingletonGetter(UserManager);

  UserManager.prototype = {
    __proto__: DisplayManager.prototype,

    /**
     * Indicates that this is the Material Design Desktop User Manager.
     * @type {boolean}
     */
    newDesktopUserManager: true,

    /**
     * Indicates whether the user pods page is visible.
     * @type {boolean}
     */
    userPodsPageVisible: true,

    /**
     * @override
     * Overrides clientAreaSize in DisplayManager. When a new profile is created
     * the user pods page may not be visible yet, so user-pods cannot be
     * placed correctly. Therefore, we use dimensions of the #animated-pages.
     * @type {{width: number, height: number}}
     */
    get clientAreaSize() {
      const userManagerPages = document.querySelector('user-manager-pages');
      const width = userManagerPages.offsetWidth;
      // Deduct the maximum possible height of the #login-header-bar from the
      // height of #animated-pages. Result is the remaining visible height.
      const height =
          userManagerPages.offsetHeight - MAX_LOGIN_HEADER_BAR_HEIGHT;
      return {width: width, height: height};
    }
  };

  /**
   * Listens for the page change event to see if the user pods page is visible.
   * Updates userPodsPageVisible property accordingly and if the page is visible
   * re-arranges the user pods.
   * @param {!Event} event The event containing ID of the selected page.
   */
  UserManager.onPageChanged_ = function(event) {
    const userPodsPageVisible = event.detail.page == 'user-pods-page';
    cr.ui.UserManager.getInstance().userPodsPageVisible = userPodsPageVisible;
    if (userPodsPageVisible) {
      $('pod-row').rebuildPods();
    }
  };

  /**
   * Initializes the UserManager.
   */
  UserManager.initialize = function() {
    cr.ui.login.DisplayManager.initialize();
    login.AccountPickerScreen.register();
    cr.ui.Bubble.decorate($('bubble'));

    signin.ProfileBrowserProxyImpl.getInstance().initializeUserManager(
        window.location.hash);
    cr.addWebUIListener('show-error-dialog', cr.ui.UserManager.showErrorDialog);
  };

  /**
   * Shows the given screen.
   * @param {boolean} showGuest True if 'Browse as Guest' button should be
   *     displayed.
   * @param {boolean} showAddPerson True if 'Add Person' button should be
   *     displayed.
   */
  UserManager.showUserManagerScreen = function(showGuest, showAddPerson) {
    UserManager.getInstance().showScreen(
        {id: 'account-picker', data: {disableAddUser: false}});
    // Hide control options if the user does not have the right permissions.
    const controlBar = document.querySelector('control-bar');
    controlBar.showGuest = showGuest;
    controlBar.showAddPerson = showAddPerson;

    // Disable the context menu, as the Print/Inspect element items don't
    // make sense when displayed as a widget.
    document.addEventListener('contextmenu', function(e) {
      e.preventDefault();
    });

    if (window.location.hash == '#tutorial') {
      document.querySelector('user-manager-tutorial').startTutorial();
    } else if (window.location.hash == '#create-user') {
      document.querySelector('user-manager-pages')
          .setSelectedPage('create-user-page');
    }
  };

  /**
   * Open a new browser for the given profile.
   * @param {string} profilePath The profile's path.
   */
  UserManager.launchUser = function(profilePath) {
    signin.ProfileBrowserProxyImpl.getInstance().launchUser(profilePath);
  };

  /**
   * Disables signin UI.
   */
  UserManager.disableSigninUI = function() {
    DisplayManager.disableSigninUI();
  };

  /**
   * Shows signin UI.
   * @param {string=} opt_email An optional email for signin UI.
   */
  UserManager.showSigninUI = function(opt_email) {
    DisplayManager.showSigninUI(opt_email);
  };

  /**
   * Shows sign-in error bubble.
   * @param {number} loginAttempts Number of login attempts tried.
   * @param {string} message Error message to show.
   * @param {string} link Text to use for help link.
   * @param {number} helpId Help topic Id associated with help link.
   */
  UserManager.showSignInError = function(loginAttempts, message, link, helpId) {
    DisplayManager.showSignInError(loginAttempts, message, link, helpId);
  };

  /**
   * Clears error bubble as well as optional menus that could be open.
   */
  UserManager.clearErrors = function() {
    DisplayManager.clearErrors();
  };

  /**
   * Shows the error dialog populated with the given message.
   * @param {string} message Error message to show.
   */
  UserManager.showErrorDialog = function(message) {
    document.querySelector('error-dialog').show(message);
  };

  // Export
  return {UserManager: UserManager};
});

// Alias to Oobe for use in src/ui/login/account_picker/user_pod_row.js
const Oobe = cr.ui.UserManager;

// Allow selection events on components with editable text (password field)
// bug (http://code.google.com/p/chromium/issues/detail?id=125863)
disableTextSelectAndDrag(function(e) {
  const src = e.target;
  return src instanceof HTMLTextAreaElement ||
      src instanceof HTMLInputElement && /text|password|search/.test(src.type);
});

document.addEventListener('DOMContentLoaded', cr.ui.UserManager.initialize);

document.addEventListener('change-page', cr.ui.UserManager.onPageChanged_);
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="/create_profile.html">
<link rel="import" href="chrome://resources/cr_elements/cr_view_manager/cr_view_manager.html">

<dom-module id="user-manager-pages">
  <template>
    <style>
      cr-view-manager {
        display: block;
        height: 100%;
      }

      div.active[slot='view'],
      div.closing[slot='view'] {
        align-items: center;
        display: flex;
        justify-content: center;
      }
    </style>
    <cr-view-manager id="animatedPages" role="main">
      <div id="create-user-page" slot="view" on-keydown="stopPropagation_">
        <template is="dom-if" if="[[shouldShowCreateProfile_(selectedPage_)]]"
            restamp>
          <create-profile></create-profile>
        </template>
      </div>
      <div id="user-pods-page" slot="view">
          <slot></slot>
      </div>
    </cr-view-manager>
  </template>
  <script src="user_manager_pages.js"></script>
</dom-module>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview 'user-manager-pages' is the element that controls paging in the
 * user manager screen.
 */
Polymer({
  is: 'user-manager-pages',

  properties: {
    /**
     * ID of the currently selected page.
     * @private
     */
    selectedPage_: String,

    /**
     * Data passed to the currently selected page.
     * @private {?Object}
     */
    pageData_: {type: Object, value: null}
  },

  listeners: {'change-page': 'onChangePage_'},

  /** @override */
  attached: function() {
    this.setSelectedPage('user-pods-page');
  },

  /**
   * Handler for the change-page event.
   * @param {Event} e The event containing ID of the page that is to be selected
   *     and the optional data to be passed to the page.
   * @private
   */
  onChangePage_: function(e) {
    this.setSelectedPage(e.detail.page, e.detail.data);
  },

  /**
   * Sets the selected page.
   * @param {string} pageId ID of the page that is to be selected.
   * @param {Object=} opt_pageData Optional data to be passed to the page.
   */
  setSelectedPage: function(pageId, opt_pageData) {
    this.pageData_ = opt_pageData || null;
    this.selectedPage_ = pageId;
    /** @type {CrViewManagerElement} */ (this.$.animatedPages)
        .switchView(this.selectedPage_);
  },

  /**
   * This is to prevent events from propagating to the document element, which
   * erroneously triggers user-pod selections.
   *
   * TODO(scottchen): re-examine if its necessary for user_pod_row.js to bind
   * listeners on the entire document element.
   *
   * @param {!Event} e
   * @private
   */
  stopPropagation_: function(e) {
    e.stopPropagation();
  },

  /** @return {boolean} */
  shouldShowCreateProfile_: function() {
    return this.selectedPage_ == 'create-user-page';
  }
});
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">

<dom-module id="shared-styles">
  <template>
    <style include="paper-button-style">
      :root {
        --error-color: var(--google-red-700);
        --page-width: 624px;
        --title-icon-color: var(--paper-grey-500);
        --user-manager-separator-line: 1px solid rgba(0, 0, 0, .12);
      }

      a,
      a:active,
      a:hover,
      a:visited {
        color: var(--google-blue-700);
        cursor: pointer;
        text-decoration: none;
      }

      .product-logo {
        content: -webkit-image-set(
            url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGEAAAAWCAYAAADQIfLaAAAI90lEQVR4Xu3Ya4we5X2H4ft5Zt7Dno822BhsE2MXkjaYAkFtKXaElMoEJYrSGMgBpHA0iUNSaONQBam0IW1KA0lwW6omUIyCkOsWoRwIpyiOQ+RianAN2MVgDF7Ah/Xafnf3fd+Zef79fXik3Xe3K0EjVD7sLV2SZ+aZ552ZZ6TR2l1w9VOEYFTbq/R2t5GRkCQO51x3ltmlRbBVjdzOCIEBA+/Mjiap2+PhiTRx3zdnQ2ZQ5BDMqNWNRg7eEYO2/tPY87MbGPqP7zG92VJiJs5B6hxZwZ80s+Kv6lmoFAU4B2aCMuspMk5xuJWJd7dWy259pexuCs7GCPwmzS6CExwDjaz48WiDc1HeOzwQiBkEcWJAXhjHxmxNJeOP2yv+Aud5wXinzeaLIqcoCpz3g2P14te18exc74zEu7gwohziaCnxIvWGzamNF8943JmO37iyLJZ23hs5WSadvEulpXKFkOfkWfZgwC9JcGABi0/cOygCeuMDeYD2akKaOO0zgoGJOWO0adXC7CGNOUtjDzsHDrBQELoSkkovb7MFsl5ulS38/3ee/Kv8tdzJu1D6vg/+Fm1l/8Vdzzy/cnS0TntHlRAM7wznPS8NZTgKPrCwTDmF/95XY2Q0MG+wSslDVhhmRiL1MTulUknuOPe06meTxKF5SNJ2ksoRHtq/mbeZSS6B90ZvyCbZybtUWvZUOvs7/mz+4nn819YXqbRX8QSyzPHC63UuuaCTtR8fYKC3gvPQHKuz+em3eOCJYeb0lejsKJOkKYLzCaVy8pmTTmj/Wy3CsyEYHV29HBjay/1DW3mbBWny3mmvfIF3MR/wq4+PZCedsGgBg3O7OHbwMD5NeH7vKOs+1csda5fw6Cs9XLsh4cp7Eu7Y0stFq07nW19aStfAIAsWnsgpp57IyQvncsrCQU6c10dI2y4LaSdW6qT7hCo/f+QBmo1xpvRR+Y7cLVdJuyi8jMtIHPMD+aacyUQr5Xzpk9vkTukWxaq4fbesjWOYdGy5zCP+dtynWCLflu/L5ZKIokMuk0Wi+ISsoLVl8jlRDMhqaYv77pObpVcUV8o98Z6WCt58cn4oCpo5LP7tpSRFk92vjHDxeV18afUiLl3f4NaNYwwdLjh4tOCHm8c4e90Ype5+PvnhQUaaZVxSQvNgSYJLy/hS+cNpOcGnKZ290N7F1P5c1snL8pR8XO6XNjkqB+Qa+SN5TPriA1oqirNljdwii+V1OSY3yNflNfmlrIwPtV8UH4rH/1R2yatynVwrX5U35Wm5etLb3xYXc5kQF+QjtHZGvF7itX5GbpfT5WdyltwY7/kP5BGZK38nK9LE87tmMH58nJ45fcxfcjIvPL6LNR9bxn2/hi0v5vzeaZ56DphmW+jZvs+4+cEG//C5hGf3eUhSSqnDnMOJOsN7+ittpeGDb8D2p37FpC6KrpHnRPFT+Wa80d0yT/bIzaJ4QO6VT8RxL8mq+MHcKIoL5RK5XrYJcWHvka/Fh/CKnCf/Iv8piqvkujjmp6I4FB/kXVKL59WEuMAHaO247BXFmFjc/htRbJH18d6uEMXDcp9ckIZgnd57MGPseMGcUxfz/n1v0dPu+OXWggX90MjBDJB6BosG4aU3jf0jsGh+iT0HEiqJYQbBDNUWAv1pieFDbw6ze8dTTOpCeVyem/Lxu1wUC6USH0iMIj74XlH0x+2NTPQR+blsm3LeP8lXpEs6ZWdcgBiHZIc8xkT7JJNuqYlnIsf0XKRIxKbMt18OyqNMVJMhKdJgKOUczUaTUkcbi04/leZ4HbMeAjEDIyJmImaGBWsZmxWBZgZZHphSh+xi5pwUMk5rXpqiKE0/Tq88y/QOiEnvDB/9ijQkZ6JEguQzXl9rxfTjNKb8hpM6rXkJHqhhhhngHMV4g7HyHJL2ds5ZlPHaIUc5AedQUC0ZrxyEU+c4Th6AoSPoOFjrazJuwYYtgJmBMbm35HdozcnJoijidjJtzERh+nFelw8wvaWTjpfEMz1Pa46Zq0hCaz2T5jDxM1y/Z3rO54VtQ2EWFSSJ59+fq3LVyoIPvQ827zaGR42jY8a2l6Gt5PjGatj1huPwqKeUGEYMh5ntNJ2C8t6TpGUm9aCcLZ8nFrc3yR/KIfHiZrqJGY5vlA/K1Uy0TG6UJ8SkQzyxmeaK+Sm/m4piv6yQvkmLfJkcnjLe0dLM+3zIi80GRARzzO0OPLoDNm31bPoy3HQRDHZBXwdc8vsJW27x1EbqPPZ8Qn8HBCMW5wj2pMMYH62zcOkAKy6+kkntkFvl03Kv3CXfkn+TX8iAnCAVWuuLFN0yh9Z2xnlXywb5rvyjPBn/TZy7n9Y64lyOiapyonhRzJVOUfyzNGVDvPYvyzPSI07SeG6ZiXyco53WBqXX583GAyHY63iPgYjBwjnGXY/CnT9xXHG+Z8M1jh+u8az7KNz7o8P8/ePGvMEyzhmGUg6HmRFCuN+AoijIGvD+c1YwpYflCnlEtsUb+YYohuP2Dlr7XqR4UP6S6f1YLpcfxY/vTXILE90tt9PaT+IYIxbP/YrUJJMbZasohuQ6uUeeldvinN8WkzdkrexmolH5qmyhtb+Qu92nbz9EWk6/WG2vfqcoAjG8Q8Frw1DysGy+o1J2PLF1mN5qzvWfXMCRWk4RrOX/wou82IDZZ3EORaWtqn1H+MLFizh25BjTm80XeU69NvrdZiP7hU9TFBgU0YI+6O+CVw87drwa6C5nXHphP/UCsnzSAnhPnhf7QhFuwDliJAnUjhU064H/vdk8GDjH+OjYp/Jmc69LUgJgJlIE8EBfhycbH2P5kgqDg+0crWV4Dxh47wl5Uc+z7GM4d9g53kGzecE5h4O3xo+Pnqu/D7Z7n+CcBwNDOThWD3SVc85c1sNILeAB7xzOe7IsP9BsNJfj3PZ3vgCzeWLOe9TBeq22vD469rWiKDLtw4tPS9SO1znrtCpd3VWajUDiPHkRaNQb62Ux8KLD8c6bLWVSLr7ZRZ7dJuu9Ty5PS+mq0cyfMb8r71lyUqcdHG6O6M3fE4I9WeT5D8Dtd86jc/m/Ndv/AOSYkBCb8OyBAAAAAElFTkSuQmCC) 1x,
            url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAAAsCAYAAAA3r2fDAAAVTElEQVR4Xu2dCZBd1Xnnf9859229t7YWWtCCFiyQMQG8QAIYJ4CN8CSxEyeOK9hkHJcTe8bO1MTrTMapTHkh47JxDQ5ObA/jZcbLTNUElAA2i3EgEGzMKlZZC5JarVa3Wnr99nvONy70Vc3r1uvXTwWmxdT7VX119a7Ou/cs3/9837nndrec974naCYqDOZS8hnI5bKoOKoNxYmQzzryOcexUkBV6e/xOYFLG0HfkAY9N0RWq7JShAKAKiGqHhbYl0lkh3fyYCPoPzVSfS5GiEDiIA1KLusoVwMZ7zhWDtQbinOcFOISMoXFPP6dbRT3308ndOmiqiSdFwYA7yCfdRc30vjuci2+pd7QkTQoaVQAYgC18iIg6JDABkQudV7IeMh4+ZFP5FsifDMNWonKgtKlS0IHRIWsh8TLZZVa/Hi1Ht9UT5VGqubsgncCgBcTTrOA7JgGPT7TwyWJd5fksvKX3vOFXCKfVQXlFKVLVwiqkE3oz2fdl0rVeE21HkEU74TEy0xnBxBAaYkXcPadNCq1clye8fKZQs5dm0/4N1LjtoWIDl26uHYCUIVCVi518HSxEq6ppUrihcQ5XixOIPFCUDhaCpuOleKt2cR9LptAjCw8XbpCUAWb8a8t18Jdv7DTNCh+VmkR5kROUhDlaqRUDf9ehFsSD+FlDA1dujhEMENEUASAfFY+WK2lXy1VUrwDxBTyS8GiQ1Amp8NVPXl3byEnL5sYunRxGiPHTQkxgio9OfcHtUa8vlqPtghWIKKqdIpy8jgnaIRyLV441JvcWch5GkHpGI2Iy+B8jpeYPuBVwFnAMlrR5TXAbwNDvAJxlSMTvGCT40wfPsxQpvJq7/SbpVrEOQUUjYCCLRxQFF7iACFgYoAYoVSNbyxk5YbECZ0GBnEZQr1IozLBS8wm4K+A64ArmU2Xi4G/AK4FPgEM8wojGVnay3EETeuSceH2Si3gAY0goiAYgqItFwfaMhR0XkZRaBJDPVVEeH9fwW0/Vg7bEWE+XKaH2vR+qpPP8hKTAseAOlBjNl1+DagCTwBbgS3AvbyCSDZtXY8A4hMypH+742fPjNQbKblsMiMVUkBEUUBUTtgnECAi1NPjewVRwXshkzi8E+IsITS7flTsXqBNQinVlELefTdJGCpXQ8M7oR0qfVSPjqKxwUuMAsEsMpsuDwMXmghGgZ28wkhSyRGikkPPHFg6/EeLlw2z+9l9ZJcsQWNERREEcE3OGgEBEZwTqg1ldKKBhsDSQc+Sfo8TqNRSJqdqlMop/X2ZF0zVUi1DAQdoVBATmCooOIVYk56Cl8+RhA8LwlwoSn9vQmnqMVQjLytdtltEOAO4FTjIK4yEGJGoJEnyxVIlsmLDGiYOjFE+VqRnoB/ViDkniAICCs4pimP3wTqFTOStr+vl0nN6OWtNjlVLEhIHU6XAntEqO3Ye5cHHJ9k7OsWSRXl6ch4FxAkiDhFBBOzJFc674+YcqkI26z/U21/4KxU30W5hMrK6wA0//ikLQpc7zF6RJIQ6ucStS1zm8lq1Tt9gnlWb1vHEA4+SFnL4JINGRRygiqriPdRSYddohTe9Js+H376Mczb1AQkQCCGSBli82P3CBvmVs5fzrm0Vbr7nELf98zg+4xkeyBBVMMcnyXic93h//Oic4MSZ7pR8LvNh590nNdKSfM8gabXIM4/cxcnSpUvivcdnkvcpDkekXKyzbM0qxvcd5OCBwwwuWwbOE23hLE6pp7BrtMr73jLEJ9+zGkg4NFXjfz/Y4PH9MF6ENEB/HtYthUtfBZdsyXL1G9ewcU0/X7t5lGM1z5LhHM45XJKYABwigioIICKWN0Gq8t6MuE9GoQXK4NKE++94kGNHj9ABI8BGYBGQASrAfuCRk3wtZR1wJtAL1IAx4CEgneN7/YC3skU7v9xy6xxQsjpMMpOlwCZgsdW3aunHDqBCa7J2PwHKZgCbzApWh6eBXZzIZmC9ta1uuf+DtMYDA4Cztk1j2PfzgNr9GsxNv9U7AseAAGB908dxyk1tfpWNY87K7wCe50S22FgVrH4HgBmpQxIVcO53oyoAhECIcPqZG5g8NEm1WCTX1w/eo6oIys79Nd775sFfiGAtEPjOfRVuvAsOHoX+AvRmAYGxY/Dgbvjeg3D5WXU+9bYGZ64f5P1vc/z3O4okhRz5rEMxBAQBQJwJwT47J8uc9xeJ515mEaPQPwwP33cz89AL/D5wLjBkTiXW4VUTw/8B/qXNgO/jOO8HXgsMAqlZNAe9CXiMmawE/tyc+e+AHwLvAN5kDuBsoD7SJIQc8E7gPKuv9SzRBvQQcBewnRM5B/gTu8angGeADwLn2/3qQDSnuhf4b0Cw+1xr3+8DAmbmZF8G9jKT5VbvRcCPgRsxgN8ErrT7/BcT3ly82/p0HPiMtQ8798cmpk8CB60t5zYJNdg97ga+gU0g1pazgZ5Zbfk5cINdi0TFbxSRdWpCQIRqqcrA0iFWnnE6P39yF5lsFsnmcEnC82N1Xrspx1/869OByA23N/j8rbByEZy5AmKEaJfSHCzug0YKf/8zeG5M+fof11i3qpc3XwD/8FCNQl4QBBFQOzoBnCAiiAoWHvCJ3+a8u1cjMyj05hndU+aBu77PnNhg2bFqM9O4HQds1loB/Dtz5H/gRIrmKO8B3mYzy04TyDBQMWF8zJ6rP4vR5OiJ/fsK4F3AtNVhCfAo8BSAOdVHgdNtFgw2aFWgz2yROc8ZwPUtRNsDVOz/LwN+C3jOZveCtbsEbLPj7cCHTCzjFimctbkKrLC2fQKYbNG2HhNrMxk7b+XakrWyeRO8QWLnJywKvB24yvp3P9Bj4q7YuEwB99nEcxYw1twWK7fO/OE/AsUkm0suRkGbtwcEqtXwwsL58Og41UqNHJCqkIbIx945AmS5/eEyX7gNNiyHQgZCBFVmEBW8g7NXwRMH4BPfU/7mj1Jee2aWpw4Exkue/rxgIsQJTa98YCJxIOC8vM47QYUZLF0O2799B5OH9jEHPdYpw0DZHOpWc4oaMGKzziU2wO+24/3M5IiVWQv8yMSyB/DmbG81ITSA3wX+M0bT7HsUeB2wBhi3AdsNDNlRgazVd7kJ5Yg56ZPmsMM2G/6GOcevWbmvYQDByo6Z6FYD3wXutJm2167xFmCPtX+LOdojwN9b/wiw1kSkJtirgZtatK0M1JlJoymdibSnbmWrdi+D1Np32ES7EviWjcGETQoXWDt32RhdYM7+E+BmO2/jZG2BVdb+7ySqulVFTtgprr+wcC6wcsMannroSTKFLGOHSvzqq4e4YOsQ1VqNL98JSwagkMH2AubePEsjbF4OP3gCbvlJZNv5nrNPz/DDJ5QkcSiCsyiAmUUKUyiIsAXBzexQJVeAfbsfow1vt84rWni/zjrcYNKc7KDN9oPA7wE/M6EYiDnCU8BnZw36mM1Q/8ny1XXmQLuZSWpO6WwWf5gT+U3Lz4+a0/61icHgiIX2x20GP2zpx0MtrueszncDX551jX1AYo4xbvXab/ebwLA6HAD+AzBlYsktwOait9TyH4GvzmrL8xZJLgcmre932VgXZ43TYYsG0zZOJImTjSEqIkIzIkJ5usHImlWM7x9jYqJIsey4cEsPkOGHj5d57hCcMTK/COyAoPTl4JZHYdv5yoYRx0/3AD4hceBMAAYgiChRMaEyojACjGKIOOo1mBibMxosBl5vnRWAzwNlWnObzdTYzBlahPnUcss6JzIO3GtOCbCqhRC8pRE3ziGCfuAiq69aXn2E1jxtUeCDNuNe3uKaBXPqr9Caey2yiLXve1Z+NvuAHRZFBiyK7uXlpdcE+VVa80/AG5smrW+bCGbzjNlrbDxwaRp6vPe0IoYUnGP1xnUQI/lE2LymB1AeeR6cA9qIYDZRYVEf/PwQHDqiDAwKi/o9AY/3DvFupg4wETThhEVOwIwkyVApwvM754wIZ1va0WuzYpH2fMXsOSBlJoOWNhxgbkatcwXIzeHoz9qgtWKLibcA3ANM0p4HLUKltp5YykyG7AlJldZM2yw/YHV/iLmZBBKzPC8/g9beSGuKFkUHLN17ZJ62ZAAH4NKmHV1lJiJCpVRj+LQlLFu5HAlVlg5nAWVyGnIJxHlEoNjR1JJJYLoG+22Oy2ebrqGKKm0JkXyI8P9MCQreZ9pFBIAAPMOLI9fBrmnaFEniHOuVffMs6h2gJph5sXbl7NorWkSgCeZGzXJWrjJfWbPIy48DDtOeaCI93GEdFSDRljN6M5F6Q1m5cQ1794zTqDXMZ2elPh2IQM1Qs3nQFifSGGlGJZJGD8JcJNYhVaDIi6BDB3C8OPJ2jzowTWcUAbF79zAT7aC+0uGoOH65KC8OMdMOyxpYdqOYnSh9EGrlKv3D/QyvOI0DY9OAY1EfVFNAOhOBQdqAvhysGAKAegpOsLLMj2oVVWZa26ZHq6UHMrx4HC8Onecaoam+CZ2RaeqBlBMROkMW2NG1gzq4X0ZbEpf4ctSAgWqLmolQq6b0L1/BoekpoM45q4Vv36+grQUAtHh7FSam4Q0bYWQxTBfhWFXI+Jb3bXlCRCYx7DMioChzUALEcu7TgKc5tZmyY9bSpMeYnxUmoDowyamFdB5NKQCBBSAJIT6bcQ6lPbFRZ3CowO6SAlV+fWuWDT9SDh2FkUGI2k4EdoxQrMG2cwSA3RNQrDkGC8p8iAghxoMh6JgIBohCCJCmDebA9gpI7WnM3bRnIzAM/AsLw7OWp6s97foB7Rmwpx8Ny4v3cmphEZk8UGBuFgHrgWkWABdVHrMMoz0iDGQDj41m2bHbU8jBn1wmHCpCpQEiwFxrAsALPDUKv7EFrj5fICrPHXJkvACdRQNVnlTVqKqYERp1enph9fqz2znWc0ACbAbeOs/O5odtR/fjQD8vP3uaFr8bgN+iPe8F8iaIh4DGKRjhHKDA+fPs9fQBdRaAJG2k9yQ+QZxD51GDE0WBb9zv+PTayJXnwp+NwXW3wqphZXEfhDjTmZ1AI4UnD8KWFfDpdzhAeWSXsv+oZ6DQSRJp4tJ4v226zTifK8CiZatpw/eBT1na8NtA1naFyxjmdH/QtFeQA+osDP/LZvmjwL+yuvyjfTZYac6zFYjAfmvTqcYO68cpi8j77D0rbZp8rrY9kIOAsgA4DemzGnWXCPOiCssH4ZE98LU7BYAPXAmf/h1wAjsOwOhROFqF6SpMFOHZg7B3Aq4+F/7nB4TFA46de6rcu1Mo5ByCdrR8iqqocos4AcEMxAn1Gqxafw5teBr4OrDMZsxtNuO/B/hDiwJ/Bqxuerz510CNhWEn8LfAYhPllfaOz3utvh8A/tzEIoACXwTKnHrsBh6wzcVjwDutLdeYfcTatcP2Q3oXRggIaRq+I3SGAqcNwfd/AjfdLQC88yL47p8KH7pCuGAdLOuH4R7YuBze8Tq44Rrh+ms8/T1Z7vnpFDfd06Cvr0DWR7SDlAgEVcaA+1CYbVMTcPYFF9PbP0wbbgO+BNSb0o63mCheb+uCHhuQv5z1qDVvIlkDDNGePuB0K9s3K+1aZecXMz93AV8AKnb/tcDlVt+LTdR5E+2nWuxg9zTVY4C5ccBpVnaE9iyy6622PjTIACvbtO0m4FG7h70+zVX2gtyFwOMm5AngHLtWgmHisLa0TVc9sMLKLaU9i61PR2wfIZLWw40hm3xUvEdjRNrk7KqQSWBkEP7HA7B3QnjXr8K6EeUDlwMI1QqkAfp6AXGAEEPkyzdPcsfPSmx74ypyXqk3OnuupqrEEG5kDkrH6qxcN8DGrRfx8H230IYf2YBcAqw3p06afpbgEeCfOZG9wH+1sk/TnidsUMUG2GDcdqxz5rSdcJ9d41LgDBOr1ZdxE+3dtOY5E763Os1FDfimiWW8A3Hutag6OmuX9u+AwhyL9bJNLm8GtjT1e9H68xarx5MWiYvNaaCdvx5w8+wWT5vo+qx+7bjdIu9BAPnDLx0lRiWT8bdmc5krYox0iiocmIKBPFy4Cc5bC+uXKiMDIA6KFWHXociju+rc/XjK/Y8e4d1XLeVVG4Y5PFXDicwtAjuJCCEENOpi7/2koi2FsnZznm98/m/4+nXvp3PI2oBUgcipTxbwFtUCr1xy1o7yKfNr4RVBnNCoNz7kvTx5PCoonbJqGKoNuO1R+MFjsLhPGCiAc1BpCKNjNY4VG1QqNa44v5ezNgwyfrTRkQhUAFVi1M8niZ8UEVohKpSLsOW8X+ckqZu9Uqjz/wc1TjGSeqkEAjHoUyJ8raev99pAoFOiQjY5vm6IEeopHDwKKoIn0pdTck5Is4FXb170gjhQBZlHBIAgNNK07EQ+KiJtn2oVj8KKtWtZtGyV/VxC53TpIr933Vjzr7/2hf7ew5lcbiiGQHva7waLc8RGg7RW4+ChEq8/M8cbfmWEQ0fquE5E4ITQCIQQt2Vzme3zPtr1GYaWCB/9/cvY8dBddOlyUqmROA+ACIQQQ7VcvdL75H7xjhgi0uF7QDr7QwTVyLFSg6X9ytaNgxwrB6QTEYgQQySEcEMmm9lOB2hMKfRkWL1h60kLoUuXJMn3YOAFNMYHKqXy+/I9hRvtKRKz0Y4UocSglKerXHRePz19ecan6jiZXwSqSr3WuDPJ+D8VJx2tWTRGMhkYXLSck6VLl0ScYCCAJgm1cvhKZXp6Uc/AwKctMnQYDgwRFGXySJV1Iwmb1g8wWUw7EgFAo964L5NN3uRPZuEuQoxQr1U4Wbp0cahihtrReU8M4TPlY8V/GxoB5z0z0GY78TQi1BsRbVQ5Z3M/+IQQQutr2MHZKx6VUuUW591FSZKgqiwoXbp/Osp5T5qG6yvF4ra0Wpty4hBxoBgtfRpEEIHJyRKbV2c5fWU/Uy9EA2kdQew33TUaKfVq/XOqXG2iYKHp0hWCicEBbK+USpur5fL3YwiI9+AcCmYzEYFKJaXg6rx64wDVBqB6omJEEO+IMVIt156uVWpXOO8+kiT+1BNBl+5f1RQRRNyhRr3xO6GRXuWzmY8n2eyFPvGgoKooCmoqQDhypMQFZ+RZsqSH8SMNnACKXUtQIIRAWktHY4hfBD57XHSCamRB6dIVQifRIa3Xtqe12pUuSd6VyWbfKt73izjEOUSE4nSd5YPC1k0DlGpC4h0AqkoIkRAjIQ13a4zfUuWbPnFV7zyNNOWUp0tXCM1rh9BIb21Ua7fGNAyLyGXi3OtF3GsU1pWLlWXnnplFVJmamg5O5HBUfV5Vd8QYfyIiP3YiO8U5vBPUFukLSZcu/xd8CDPlW+bFZAAAAABJRU5ErkJggg==) 2x);
        height: 22px;
      }
    </style>
  </template>
</dom-module>
<link rel="import" href="chrome://resources/html/load_time_data.html">
<script src="/strings.js"></script>
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="/shared_styles.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">

<dom-module id="user-manager-tutorial">
  <template>
    <style include="shared-styles">
      .tutorial-slide {
        @apply --cr-card-elevation;
        -webkit-transition: opacity 200ms ease-in-out;
        background-color: white;
        border-radius: var(--cr-card-border-radius);
        bottom: 0;
        height: 408px;
        left: 0;
        margin: auto;
        position: absolute;
        right: 0;
        top: 0;
        width: 320px;
        z-index: 100;
      }

      :host.single-pod #yourChrome,
      :host.single-pod #complete {
        margin-inline-start: 30px;
      }

      #guests {
        bottom: 20px;
        left: auto;
        margin: 0;
        right: 100px;
        top: auto;
      }

      :host-context([dir='rtl']) #guests {
        left: 100px;
        right: auto;
      }

      #friends,
      #notYou {
        bottom: 20px;
        left: auto;
        margin: 0;
        right: 20px;
        top: auto;
      }

      :host-context([dir='rtl']) #friends,
      :host-context([dir='rtl']) #notYou {
        left: 20px;
        right: auto;
      }

      #notYou {
        height: 100px;
        width: 240px;
      }

      .slide-contents {
        color: var(--cr-primary-text-color);
        padding: 0 20px;
        text-align: center;
      }

      .slide-title {
        font-size: 20px;
        line-height: 20px;
        margin: 30px 0;
      }

      .slide-text {
        font-size: 15px;
        line-height: 20px;
      }

      .slide-buttons {
        bottom: 20px;
        position: absolute;
        text-align: center;
        width: 100%;
      }

      .slide-buttons [is='action-link'] {
        width: 100%;
      }

      .slide-buttons button {
        bottom: 0;
        height: 35px;
        padding: 0 15px;
        width: 138px;
      }

      .arrow-down {
        border-bottom: 10px solid white;
        border-left: 10px solid white;
        border-right: 10px solid transparent;
        border-top: 10px solid transparent;
        bottom: -10px;
        box-shadow: rgba(60, 64, 67, .4) -1px 1px 1px 0,
            rgba(60, 64, 67, .15) -2px 2px 2px 0;
        height: 0;
        position: absolute;
        right: 40px;
        transform: rotate(-45deg);
        width: 0;
      }

      :host-context([dir='rtl']) .arrow-down {
        left: 40px;
        right: auto;
      }

      #guests .arrow-down {
        right: 110px;
      }

      :host-context([dir='rtl']) #guests .arrow-down {
        left: 110px;
        right: auto;
      }

      .slide-image {
        border-radius:
            var(--cr-card-border-radius) var(--cr-card-border-radius) 0 0;
        height: 182px;
      }

      #yourChrome .slide-image {
        background-color: rgb(241, 202, 58);
        background-image:
            url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_YOUR_CHROME);
      }

      #guests .slide-image {
        background-color: rgb(90, 196, 144);
        background-image: url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_GUESTS);
      }

      #friends .slide-image {
        background-color: var(--paper-light-blue-100);
        background-image:
            url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_FRIENDS);
      }

      #complete .slide-image {
        background-color: white;
        background-image:
            url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_COMPLETE);
      }

      #notYou #dismiss {
        cursor: pointer;
        position: absolute;
        right: 5px;
        top: 5px;
      }

      #notYou #slide-add-user {
        margin-top: 10px;
      }

      :host-context([dir='rtl']) #notYou #dismiss {
        left: 5px;
        right: auto;
      }
    </style>
    <template is="dom-if" if="[[!hidden_]]">
      <template is="dom-if"
          if="[[!isStepHidden_(currentStep_, steps_.YOUR_CHROME)]]">
        <div class="tutorial-slide" id="[[steps_.YOUR_CHROME]]">
          <div class="slide-image"></div>
          <div class="slide-contents">
            <div class="slide-title">$i18n{slideYourChromeTitle}</div>
            <div class="slide-text">$i18n{slideYourChromeText}</div>
          </div>
          <div class="slide-buttons">
            <paper-button on-tap="onNextTap_" data-next$="[[steps_.GUESTS]]">
              $i18n{tutorialNext}
            </paper-button>
          </div>
        </div>
      </template>
      <template is="dom-if"
          if="[[!isStepHidden_(currentStep_, steps_.GUESTS)]]">
        <div class="tutorial-slide" id="[[steps_.GUESTS]]">
          <div class="slide-image"></div>
          <div class="slide-contents">
            <div class="slide-title">$i18n{slideGuestsTitle}</div>
            <div class="slide-text">$i18n{slideGuestsText}</div>
          </div>
          <div class="slide-buttons">
            <paper-button on-tap="onNextTap_" data-next$="[[steps_.FRIENDS]]">
              $i18n{tutorialNext}
            </paper-button>
          </div>
          <div class="arrow-down"></div>
        </div>
      </template>
      <template is="dom-if"
          if="[[!isStepHidden_(currentStep_, steps_.FRIENDS)]]">
        <div class="tutorial-slide" id="[[steps_.FRIENDS]]">
          <div class="slide-image"></div>
          <div class="slide-contents">
            <div class="slide-title">$i18n{slideFriendsTitle}</div>
            <div class="slide-text">$i18n{slideFriendsText}</div>
          </div>
          <div class="slide-buttons">
            <paper-button on-tap="onNextTap_" data-next$="[[steps_.COMPLETE]]">
              $i18n{tutorialNext}
            </paper-button>
          </div>
          <div class="arrow-down"></div>
        </div>
      </template>
      <template is="dom-if"
          if="[[!isStepHidden_(currentStep_, steps_.COMPLETE)]]">
        <div class="tutorial-slide" id="[[steps_.COMPLETE]]">
          <div class="slide-image"></div>
          <div class="slide-contents">
            <div class="slide-title">$i18n{slideCompleteTitle}</div>
            <div class="slide-text">$i18n{slideCompleteText}</div>
          </div>
          <div class="slide-buttons">
            <paper-button on-tap="onNextTap_" data-next$="[[steps_.NOT_YOU]]">
              $i18n{tutorialDone}
            </paper-button>
          </div>
        </div>
      </template>
      <template is="dom-if" if="[[!isStepHidden_(currentStep_, 'notYou')]]">
        <div class="tutorial-slide" id="notYou">
          <iron-icon id="dismiss" icon="cr:close"
              on-tap="onDissmissTap_">
          </iron-icon>
          <div class="slide-buttons">
            <div class="slide-text">
              $i18n{slideCompleteUserNotFound}
            </div>
            <div id="slide-add-user">
              <a id="addUser" is="action-link" on-tap="onAddUserTap_">
                $i18n{slideCompleteAddUser}
              </a>
            </div>
          </div>
          <div class="arrow-down"></div>
        </div>
      </template>
    </template>
  </template>
  <script src="user_manager_tutorial.js"></script>
</dom-module>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/** @enum {string} */
const TutorialSteps = {
  YOUR_CHROME: 'yourChrome',
  FRIENDS: 'friends',
  GUESTS: 'guests',
  COMPLETE: 'complete',
  NOT_YOU: 'notYou'
};

/**
 * @fileoverview 'user-manager-tutorial' is the element that controls the
 * tutorial steps for the user manager page.
 */
(function() {
Polymer({
  is: 'user-manager-tutorial',

  properties: {
    /**
     * True if the tutorial is currently hidden.
     * @private {boolean}
     */
    hidden_: {type: Boolean, value: true},

    /**
     * Current tutorial step ID.
     * @type {string}
     */
    currentStep_: {type: String, value: ''},

    /**
     * Enum values for the step IDs.
     * @private {TutorialSteps}
     */
    steps_: {readOnly: true, type: Object, value: TutorialSteps}
  },

  /**
   * Determines whether a given step is displaying.
   * @param {string} currentStep Index of the current step
   * @param {string} step Name of the given step
   * @return {boolean}
   * @private
   */
  isStepHidden_: function(currentStep, step) {
    return currentStep != step;
  },

  /**
   * Navigates to the next step.
   * @param {!Event} event
   * @private
   */
  onNextTap_: function(event) {
    const element = Polymer.dom(event).rootTarget;
    this.currentStep_ = element.dataset.next;
  },

  /**
   * Handler for the link in the last step. Takes user to the create-profile
   * page in order to add a new profile.
   * @param {!Event} event
   * @private
   */
  onAddUserTap_: function(event) {
    this.onDissmissTap_();
    // Event is caught by user-manager-pages.
    this.fire('change-page', {page: 'create-user-page'});
  },

  /**
   * Starts the tutorial.
   */
  startTutorial: function() {
    this.currentStep_ = TutorialSteps.YOUR_CHROME;
    this.hidden_ = false;

    // If there's only one pod, show the steps to the side of the pod.
    // Otherwise, center the steps and disable interacting with the pods
    // while the tutorial is showing.
    const podRow = /** @type {{focusPod: !function(), pods: !Array}} */
        ($('pod-row'));

    this.classList.toggle('single-pod', podRow.pods.length == 1);

    podRow.focusPod();  // No focused pods.
    $('inner-container').classList.add('disabled');
  },

  /**
   * Ends the tutorial.
   * @private
   */
  onDissmissTap_: function() {
    $('inner-container').classList.remove('disabled');
    this.hidden_ = true;
  }
});
})();
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>$i18n{tokenCacheHeader}</title>
  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  <link rel="stylesheet" href="identity_internals.css">
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/cr/ui.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="strings.js"></script>
  <script src="identity_internals.js"></script>
</head>
<body>
  <h2 class="header">$i18n{tokenCacheHeader}</h2>
  <div id="token-list"></div>
</body>
</html>
/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.header {
  color: rgb(74, 142, 230);
  font-size: 100%;
  margin-bottom: 0;
}

#token-list {
  width: 100%;
}

tr:nth-child(odd) {
  background: rgb(239, 243, 255);
}

td.label {
  font-weight: bold;
  vertical-align: top;
}

td.token-actions {
  text-align: center;
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('identity_internals', function() {
  'use strict';

  /**
   * Creates an identity token item.
   * @param {!Object} tokenInfo Object containing token information.
   * @constructor
   */
  function TokenListItem(tokenInfo) {
    const el = cr.doc.createElement('div');
    el.data_ = tokenInfo;
    el.__proto__ = TokenListItem.prototype;
    el.decorate();
    return el;
  }

  TokenListItem.prototype = {
    __proto__: HTMLDivElement.prototype,

    /** @override */
    decorate: function() {
      this.textContent = '';
      this.id = this.data_.accessToken;

      const table = this.ownerDocument.createElement('table');
      const tbody = this.ownerDocument.createElement('tbody');
      tbody.appendChild(this.createEntry_(
          'accessToken', this.data_.accessToken, 'access-token'));
      tbody.appendChild(this.createEntry_(
          'extensionName', this.data_.extensionName, 'extension-name'));
      tbody.appendChild(this.createEntry_(
          'extensionId', this.data_.extensionId, 'extension-id'));
      tbody.appendChild(
          this.createEntry_('tokenStatus', this.data_.status, 'token-status'));
      tbody.appendChild(this.createEntry_(
          'expirationTime', this.data_.expirationTime, 'expiration-time'));
      tbody.appendChild(this.createEntryForScopes_());
      table.appendChild(tbody);
      const tfoot = this.ownerDocument.createElement('tfoot');
      tfoot.appendChild(this.createButtons_());
      table.appendChild(tfoot);
      this.appendChild(table);
    },

    /**
     * Creates an entry for a single property of the token.
     * @param {string} label An i18n label of the token's property name.
     * @param {string} value A value of the token property.
     * @param {string} accessor Additional class to tag the field for testing.
     * @return {HTMLElement} An HTML element with the property name and value.
     */
    createEntry_: function(label, value, accessor) {
      const row = this.ownerDocument.createElement('tr');
      const labelField = this.ownerDocument.createElement('td');
      labelField.classList.add('label');
      labelField.textContent = loadTimeData.getString(label);
      row.appendChild(labelField);
      const valueField = this.ownerDocument.createElement('td');
      valueField.classList.add('value');
      valueField.classList.add(accessor);
      valueField.textContent = value;
      row.appendChild(valueField);
      return row;
    },

    /**
     * Creates an entry for a list of token scopes.
     * @return {!HTMLElement} An HTML element with scopes.
     */
    createEntryForScopes_: function() {
      const row = this.ownerDocument.createElement('tr');
      const labelField = this.ownerDocument.createElement('td');
      labelField.classList.add('label');
      labelField.textContent = loadTimeData.getString('scopes');
      row.appendChild(labelField);
      const valueField = this.ownerDocument.createElement('td');
      valueField.classList.add('value');
      valueField.classList.add('scope-list');
      this.data_.scopes.forEach(function(scope) {
        valueField.appendChild(this.ownerDocument.createTextNode(scope));
        valueField.appendChild(this.ownerDocument.createElement('br'));
      }, this);
      row.appendChild(valueField);
      return row;
    },

    /**
     * Creates buttons for the token.
     * @return {HTMLElement} An HTML element with actionable buttons for the
     *     token.
     */
    createButtons_: function() {
      const row = this.ownerDocument.createElement('tr');
      const buttonHolder = this.ownerDocument.createElement('td');
      buttonHolder.colSpan = 2;
      buttonHolder.classList.add('token-actions');
      buttonHolder.appendChild(this.createRevokeButton_());
      row.appendChild(buttonHolder);
      return row;
    },

    /**
     * Creates a revoke button with an event sending a revoke token message
     * to the controller.
     * @return {!HTMLButtonElement} The created revoke button.
     * @private
     */
    createRevokeButton_: function() {
      const revokeButton = this.ownerDocument.createElement('button');
      revokeButton.classList.add('revoke-button');
      revokeButton.addEventListener('click', function() {
        chrome.send(
            'identityInternalsRevokeToken',
            [this.data_.extensionId, this.data_.accessToken]);
      }.bind(this));
      revokeButton.textContent = loadTimeData.getString('revoke');
      return revokeButton;
    },
  };

  /**
   * Creates a new list of identity tokens.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {cr.ui.div}
   */
  const TokenList = cr.ui.define('div');

  TokenList.prototype = {
    __proto__: HTMLDivElement.prototype,

    /** @override */
    decorate: function() {
      this.textContent = '';
      this.showTokenNodes_();
    },

    /**
     * Populates the list of tokens.
     */
    showTokenNodes_: function() {
      this.data_.forEach(function(tokenInfo) {
        this.appendChild(new TokenListItem(tokenInfo));
      }, this);
    },

    /**
     * Removes a token node related to the specifed token ID from both the
     * internals data source as well as the user internface.
     * @param {string} accessToken The id of the token to remove.
     * @private
     */
    removeTokenNode_: function(accessToken) {
      let tokenIndex;
      for (let index = 0; index < this.data_.length; index++) {
        if (this.data_[index].accessToken == accessToken) {
          tokenIndex = index;
          break;
        }
      }

      // Remove from the data_ source if token found.
      if (tokenIndex) {
        this.data_.splice(tokenIndex, 1);
      }

      // Remove from the user interface.
      const tokenNode = $(accessToken);
      if (tokenNode) {
        this.removeChild(tokenNode);
      }
    },
  };

  let tokenList;

  /**
   * Initializes the UI by asking the contoller for list of identity tokens.
   */
  function initialize() {
    chrome.send('identityInternalsGetTokens');
    tokenList = $('token-list');
    tokenList.data_ = [];
    tokenList.__proto__ = TokenList.prototype;
    tokenList.decorate();
  }

  /**
   * Callback function accepting a list of tokens to be displayed.
   * @param {!Token[]} tokens A list of tokens to be displayed
   */
  function returnTokens(tokens) {
    tokenList.data_ = tokens;
    tokenList.showTokenNodes_();
  }

  /**
   * Callback function that removes a token from UI once it has been revoked.
   * @param {!Array<string>} accessTokens Array with a single element, which is
   * an access token to be removed.
   */
  function tokenRevokeDone(accessTokens) {
    assert(accessTokens.length > 0);
    tokenList.removeTokenNode_(accessTokens[0]);
  }

  // Return an object with all of the exports.
  return {
    initialize: initialize,
    returnTokens: returnTokens,
    tokenRevokeDone: tokenRevokeDone,
  };
});

document.addEventListener('DOMContentLoaded', identity_internals.initialize);
     ;o0
݂Dʐ:EZgdPbLyC~haBM'$wӯg?I+yU?{FBxC?V;J$SZ; 0~EHd阱uNnh\@L^Lb0y,8rR%1 +jq+v HIghۢ8s?;qX1GbMsڙljX3dׯ,]r'le*R֚oI<Ze+!$yu+~j!rĘCCZ$P>RPfYILc!juhRCC玴}`%Aޜ$x5>6i43z|2p0FJpCKRb{P=bp:yyw^[dy^	uvw=`UnYx$dכ˟}Xk-Xuc9ς)Yل0BPzm?И;M!3M#??ױk|'6v-@\	       WKs6WlNH9tz68v9\h(A9{wM4$2vyxSm\~:z3\X,VpRX<$+`txr rU!TTk)F0߀gf $2ĔL,"9*dJgӋ),dh47פzEFWho2}aQ	K򣭋D-!5&r2
tupoYc!H)=J)t
_zw>Dz$6AN)ҿNm^c_iVh<+$a ==xVB3\ݢnHE\}Qz<IJ]5\ [A J&ῷMd?՘fɺ"\nN&ʢ.yb;dWY{LLLs3#Wx`QbR~$4r(<292AXJҰ#E)[$t2pBNT{RWӯ߸"K-x[ΔrYPQtǪH>,c&$]W\Y^6n&w#\}y_|G=OI0F8
vkh>bك U+¥tӉm[G7Ac'Lc^z[M<vʆuɐr+qi퍚&'mů?|H0"XY㗮F0AA'f\1_42;rW!z߸ø$xZ5H2:'ZK7)$_2f,u,Jٟa:eQb"]*gmV+^	TU%-hBl6H0]xϞɦwd+$IcZTt͂mbmىUۺI2:lTp/Qํ1G<DX9hD!Ֆ};
$u$۬^ѫ#};~Vc\1B(LSxH%So+sA, p]eI{IB~3-bZ$kpB;?Nr4KCLml.PoxYL#u$2@kDTQ.tm&e	Z/rV^MG/;˝ɘ׿>Yzt(r5&sJ=j廲i&`DL':m9-P=8K/y5(GjU	VS\; 97k еFdtY<;`ZU|Ҙ2Ӿ59Wj5]HI
s͎뽛kU+MլC@A=Q`t]l.D%6BYJV-1T&R_S<v2Q	Ƨ@ꎅ_zc{;f6eaR       n0zmP9}J
$} JI)ŎZ;HK5gfxq7V5yqy-MkS[nZC9nP28jr(
"mP A#hUa7
0PbTS0a;ݷP+38Ȳw~e -2pYV,+ID*k1,bC|RY"tYNFHZm
z8Y삁XKzD*;ޖWdP״e%WFIF._(q{U	))5Z&=|32}2K;'ogpwԌM@dx{۔#~>FʪGp'ybB ai<EK/T=?E4/UG\/*lK4/iO;OǋA~!g˝
G͓|k?Yq,&'c#=ZafofjFki7/JE[p")ugq6hT$Jb8>=&?nfi1f?ʌ® A%>N'eOh`a  /* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

:host > * {
  --dialog-padding-end: 26px;
  --dialog-padding-start: 16px;
  --dialog-width: 340px;
  --navigation-icon-button-size: 36px;
  --non-navigation-icon-size: 16px;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  font-family: 'Roboto', 'Noto', sans-serif;
}

.button {
  color: var(--paper-blue-700);
  cursor: pointer;
  text-align: center;
}

[hidden] {
  display: none !important;
}

.ellipsis {
  overflow: hidden;
  padding: 0 1%;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html {
  /* Remove 300ms delay for 'click' event, when using touch interface. */
  touch-action: manipulation;
}

body {
  font-size: 0.75em;
  margin: 0;
}

#media-router-container {
  background-color: white;
  box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14),
              0 1px 8px 0 rgba(0, 0, 0, 0.12),
              0 3px 3px -2px rgba(0, 0, 0, 0.4);
  display: flex;
  flex-direction: column;
  margin-bottom: 1px;
  width: calc(var(--dialog-width) - 1px);
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Any strings used here will already be localized. Values such as
// CastMode.type or IDs will be defined elsewhere and determined later.

cr.exportPath('media_router');

/**
 * This corresponds to the C++ MediaCastMode, with the exception of AUTO.
 * See below for details. Note to support fast bitset operations, the values
 * here are (1 << [corresponding value in MR]).
 * @enum {number}
 */
media_router.CastModeType = {
  // Note: AUTO mode is only used to configure the sink list container to show
  // all sinks. Individual sinks are configured with a specific cast mode
  // (PRESENTATION, TAB_MIRROR, DESKTOP_MIRROR).
  AUTO: -1,
  PRESENTATION: 0x1,
  TAB_MIRROR: 0x2,
  DESKTOP_MIRROR: 0x4,
  LOCAL_FILE: 0x8,
};

/**
 * The ESC key maps to KeyboardEvent.key value 'Escape'.
 * @const {string}
 */
media_router.KEY_ESC = 'Escape';

/**
 * This corresponds to the C++ MediaRouterMetrics
 * MediaRouterRouteCreationOutcome.
 * @enum {number}
 */
media_router.MediaRouterRouteCreationOutcome = {
  SUCCESS: 0,
  FAILURE_NO_ROUTE: 1,
  FAILURE_INVALID_SINK: 2,
};

/**
 * This corresponds to the C++ MediaRouterMetrics MediaRouterUserAction.
 * @enum {number}
 */
media_router.MediaRouterUserAction = {
  CHANGE_MODE: 0,
  START_LOCAL: 1,
  STOP_LOCAL: 2,
  CLOSE: 3,
  STATUS_REMOTE: 4,
  REPLACE_LOCAL_ROUTE: 5,
};

/**
 * The possible states of the Media Router dialog. Used to determine which
 * components to show.
 * @enum {string}
 */
media_router.MediaRouterView = {
  CAST_MODE_LIST: 'cast-mode-list',
  FILTER: 'filter',
  ISSUE: 'issue',
  ROUTE_DETAILS: 'route-details',
  SINK_LIST: 'sink-list',
};

/**
 * The minimum number of sinks to have to enable the search input strictly for
 * filtering (i.e. the Media Router doesn't support search so the search input
 * only filters existing sinks).
 * @const {number}
 */
media_router.MINIMUM_SINKS_FOR_SEARCH = 20;

/**
 * The states that media can be in.
 * @enum {number}
 */
media_router.PlayState = {
  PLAYING: 0,
  PAUSED: 1,
  BUFFERING: 2,
};

/**
 * This corresponds to the C++ MediaSink IconType, and the order must stay in
 * sync.
 * @enum {number}
 */
media_router.SinkIconType = {
  CAST: 0,
  CAST_AUDIO_GROUP: 1,
  CAST_AUDIO: 2,
  MEETING: 3,
  HANGOUT: 4,
  EDUCATION: 5,
  WIRED_DISPLAY: 6,
  GENERIC: 7,
};

/**
 * @enum {string}
 */
media_router.SinkStatus = {
  IDLE: 'idle',
  ACTIVE: 'active',
  REQUEST_PENDING: 'request_pending'
};

cr.define('media_router', function() {
  'use strict';

  /**
   * @param {number} type The type of cast mode.
   * @param {string} description The description of the cast mode.
   * @param {?string} host The hostname of the site to cast.
   * @param {boolean} isForced True if the mode is forced.
   * @constructor
   * @struct
   */
  var CastMode = function(type, description, host, isForced) {
    /** @type {number} */
    this.type = type;

    /** @type {string} */
    this.description = description;

    /** @type {?string} */
    this.host = host || null;

    /** @type {boolean} */
    this.isForced = isForced;
  };

  /**
   * Placeholder object for AUTO cast mode. See comment in CastModeType.
   * @const {!media_router.CastMode}
   */
  var AUTO_CAST_MODE = new CastMode(
      media_router.CastModeType.AUTO, loadTimeData.getString('autoCastMode'),
      null, false);

  /**
   * @param {number} id The ID of this issue.
   * @param {string} title The issue title.
   * @param {string} message The issue message.
   * @param {number} defaultActionType The type of default action.
   * @param {number|undefined} secondaryActionType The type of optional action.
   * @param {?string} routeId The route ID to which this issue
   *                  pertains. If not set, this is a global issue.
   * @param {boolean} isBlocking True if this issue blocks other UI.
   * @param {?number} helpPageId The numeric help center ID.
   * @constructor
   * @struct
   */
  var Issue = function(
      id, title, message, defaultActionType, secondaryActionType, routeId,
      isBlocking, helpPageId) {
    /** @type {number} */
    this.id = id;

    /** @type {string} */
    this.title = title;

    /** @type {string} */
    this.message = message;

    /** @type {number} */
    this.defaultActionType = defaultActionType;

    /** @type {number|undefined} */
    this.secondaryActionType = secondaryActionType;

    /** @type {?string} */
    this.routeId = routeId;

    /** @type {boolean} */
    this.isBlocking = isBlocking;

    /** @type {?number} */
    this.helpPageId = helpPageId;
  };

  /**
   * @param {string} id The media route ID.
   * @param {string} sinkId The ID of the media sink running this route.
   * @param {string} description The short description of this route.
   * @param {?number} tabId The ID of the tab in which web app is running and
   *                  accessing the route.
   * @param {boolean} isLocal True if this is a locally created route.
   * @param {boolean} canJoin True if this route can be joined.
   * @param {?string} customControllerPath non-empty if this route has custom
   *                  controller.
   * @constructor
   * @struct
   */
  var Route = function(
      id, sinkId, description, tabId, isLocal, canJoin, customControllerPath) {
    /** @type {string} */
    this.id = id;

    /** @type {string} */
    this.sinkId = sinkId;

    /** @type {string} */
    this.description = description;

    /** @type {?number} */
    this.tabId = tabId;

    /** @type {boolean} */
    this.isLocal = isLocal;

    /** @type {boolean} */
    this.canJoin = canJoin;

    /** @type {number|undefined} */
    this.currentCastMode = undefined;

    /** @type {?string} */
    this.customControllerPath = customControllerPath;

    /** @type {boolean} */
    this.supportsWebUiController = false;
  };

  /**
   * @param {string} title The title of the route.
   * @param {boolean} canPlayPause Whether the route can be played/paused.
   * @param {boolean} canMute Whether the route can be muted/unmuted.
   * @param {boolean} canSetVolume Whether the route volume can be changed.
   * @param {boolean} canSeek Whether the route's playback position can be
   *     changed.
   * @param {boolean} isPaused Whether the route is paused.
   * @param {boolean} isMuted Whether the route is muted.
   * @param {number} volume The route's volume, between 0 and 1.
   * @param {number} duration The route's duration in seconds.
   * @param {number} currentTime The route's current position in seconds.
   *     Must not be greater than |duration|.
   * @param {!{mediaRemotingEnabled: boolean}=} mirroringExtraData Only set for
   *     mirroring routes.
   * @param {!{localPresent: boolean}=} hangoutsExtraData Only set for Hangouts
   *     routes.
   * @constructor
   * @struct
   */
  var RouteStatus = function(
      title = '', canPlayPause = false, canMute = false, canSetVolume = false,
      canSeek = false, playState = media_router.PlayState.PLAYING,
      isPaused = false, isMuted = false, volume = 0, duration = 0,
      currentTime = 0, hangoutsExtraData = undefined,
      mirroringExtraData = undefined) {

    /** @type {string} */
    this.title = title;

    /** @type {boolean} */
    this.canPlayPause = canPlayPause;

    /** @type {boolean} */
    this.canMute = canMute;

    /** @type {boolean} */
    this.canSetVolume = canSetVolume;

    /** @type {boolean} */
    this.canSeek = canSeek;

    /** @type {media_router.PlayState} */
    this.playState = playState;

    /** @type {boolean} */
    this.isMuted = isMuted;

    /** @type {number} */
    this.volume = volume;

    /** @type {number} */
    this.duration = duration;

    /** @type {number} */
    this.currentTime = currentTime;

    /** @type {!{localPresent: boolean}|undefined} */
    this.hangoutsExtraData = hangoutsExtraData;

    /** @type {!{mediaRemotingEnabled: boolean}|undefined} */
    this.mirroringExtraData = mirroringExtraData;
  };

  /**
   * @param {string} id The ID of the media sink.
   * @param {string} name The name of the sink.
   * @param {?string} description Optional description of the sink.
   * @param {?string} domain Optional domain of the sink.
   * @param {media_router.SinkIconType} iconType the type of icon for the sink.
   * @param {media_router.SinkStatus} status The readiness state of the sink.
   * @param {number} castModes Bitset of cast modes compatible with the sink.
   * @constructor
   * @struct
   */
  var Sink = function(
      id, name, description, domain, iconType, status, castModes) {
    /** @type {string} */
    this.id = id;

    /** @type {string} */
    this.name = name;

    /** @type {?string} */
    this.description = description;

    /** @type {?string} */
    this.domain = domain;

    /** @type {!media_router.SinkIconType} */
    this.iconType = iconType;

    /** @type {!media_router.SinkStatus} */
    this.status = status;

    /** @type {number} */
    this.castModes = castModes;

    /** @type {boolean} */
    this.isPseudoSink = false;
  };

  /**
   * @param {number} tabId The current tab ID.
   * @param {string} domain The domain of the current tab.
   * @constructor
   * @struct
   */
  var TabInfo = function(tabId, domain) {
    /** @type {number} */
    this.tabId = tabId;

    /** @type {string} */
    this.domain = domain;
  };

  return {
    AUTO_CAST_MODE: AUTO_CAST_MODE,
    CastMode: CastMode,
    Issue: Issue,
    Route: Route,
    RouteStatus: RouteStatus,
    Sink: Sink,
    TabInfo: TabInfo,
  };
});
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// API invoked by this UI to communicate with the browser WebUI message handler.
cr.define('media_router.browserApi', function() {
  'use strict';

  /**
   * Indicates that the user has acknowledged the first run flow.
   *
   * @param {boolean} optedIntoCloudServices Whether or not the user opted into
   *                  cloud services.
   */
  function acknowledgeFirstRunFlow(optedIntoCloudServices) {
    chrome.send('acknowledgeFirstRunFlow', [optedIntoCloudServices]);
  }

  /**
   * Acts on the given issue.
   *
   * @param {number} issueId
   * @param {number} actionType Type of action that the user clicked.
   * @param {?number} helpPageId The numeric help center ID.
   */
  function actOnIssue(issueId, actionType, helpPageId) {
    chrome.send(
        'actOnIssue',
        [{issueId: issueId, actionType: actionType, helpPageId: helpPageId}]);
  }

  /**
   * Modifies |route| by changing its source to the one identified by
   * |selectedCastMode|.
   *
   * @param {!media_router.Route} route The route being modified.
   * @param {number} selectedCastMode The value of the cast mode the user
   *   selected.
   */
  function changeRouteSource(route, selectedCastMode) {
    chrome.send(
        'requestRoute',
        [{sinkId: route.sinkId, selectedCastMode: selectedCastMode}]);
  }

  /**
   * Closes the dialog.
   *
   * @param {boolean} pressEscToClose Whether the user pressed ESC to close the
   *                  dialog.
   */
  function closeDialog(pressEscToClose) {
    chrome.send('closeDialog', [pressEscToClose]);
  }

  /**
   * Closes the given route.
   *
   * @param {!media_router.Route} route
   */
  function closeRoute(route) {
    chrome.send('closeRoute', [{routeId: route.id, isLocal: route.isLocal}]);
  }

  /**
   * Joins the given route.
   *
   * @param {!media_router.Route} route
   */
  function joinRoute(route) {
    chrome.send('joinRoute', [{sinkId: route.sinkId, routeId: route.id}]);
  }

  /**
   * Indicates that the initial data has been received.
   */
  function onInitialDataReceived() {
    chrome.send('onInitialDataReceived');
  }

  /**
   * Reports that the route details view was closed.
   */
  function onMediaControllerClosed() {
    chrome.send('onMediaControllerClosed');
  }

  /**
   * Reports that the route details view was opened for |routeId|.
   *
   * @param {string} routeId
   */
  function onMediaControllerAvailable(routeId) {
    chrome.send('onMediaControllerAvailable', [{routeId: routeId}]);
  }

  /**
   * Sends a command to pause the route shown in the route details view.
   */
  function pauseCurrentMedia() {
    chrome.send('pauseCurrentMedia');
  }

  /**
   * Sends a command to play the route shown in the route details view.
   */
  function playCurrentMedia() {
    chrome.send('playCurrentMedia');
  }

  /**
   * Reports when the user clicks outside the dialog.
   */
  function reportBlur() {
    chrome.send('reportBlur');
  }

  /**
   * Reports the index of the selected sink.
   *
   * @param {number} sinkIndex
   */
  function reportClickedSinkIndex(sinkIndex) {
    chrome.send('reportClickedSinkIndex', [sinkIndex]);
  }

  /**
   * Reports that the user used the filter input.
   */
  function reportFilter() {
    chrome.send('reportFilter');
  }

  /**
   * Reports the initial dialog view.
   *
   * @param {string} view
   */
  function reportInitialState(view) {
    chrome.send('reportInitialState', [view]);
  }

  /**
   * Reports the initial action the user took.
   *
   * @param {number} action
   */
  function reportInitialAction(action) {
    chrome.send('reportInitialAction', [action]);
  }

  /**
   * Reports the navigation to the specified view.
   *
   * @param {string} view
   */
  function reportNavigateToView(view) {
    chrome.send('reportNavigateToView', [view]);
  }

  /**
   * Reports whether or not a route was created successfully.
   *
   * @param {boolean} success
   */
  function reportRouteCreation(success) {
    chrome.send('reportRouteCreation', [success]);
  }

  /**
   * Reports the outcome of a create route response.
   *
   * @param {number} outcome
   */
  function reportRouteCreationOutcome(outcome) {
    chrome.send('reportRouteCreationOutcome', [outcome]);
  }

  /**
   * Reports the cast mode that the user selected.
   *
   * @param {number} castModeType
   */
  function reportSelectedCastMode(castModeType) {
    chrome.send('reportSelectedCastMode', [castModeType]);
  }

  /**
   * Reports the current number of sinks.
   *
   * @param {number} sinkCount
   */
  function reportSinkCount(sinkCount) {
    chrome.send('reportSinkCount', [sinkCount]);
  }

  /**
   * Reports the time it took for the user to select a sink after the sink list
   * is populated and shown.
   *
   * @param {number} timeMs
   */
  function reportTimeToClickSink(timeMs) {
    chrome.send('reportTimeToClickSink', [timeMs]);
  }

  /**
   * Reports the time, in ms, it took for the user to close the dialog without
   * taking any other action.
   *
   * @param {number} timeMs
   */
  function reportTimeToInitialActionClose(timeMs) {
    chrome.send('reportTimeToInitialActionClose', [timeMs]);
  }

  /**
   * Reports the time, in ms, it took the WebUI route controller to load media
   * status info.
   *
   * @param {number} timeMs
   */
  function reportWebUIRouteControllerLoaded(timeMs) {
    chrome.send('reportWebUIRouteControllerLoaded', [timeMs]);
  }

  /**
   * Requests data to initialize the WebUI with.
   * The data will be returned via media_router.ui.setInitialData.
   */
  function requestInitialData() {
    chrome.send('requestInitialData');
  }

  /**
   * Requests that a media route be started with the given sink.
   *
   * @param {string} sinkId The sink ID.
   * @param {number} selectedCastMode The value of the cast mode the user
   *   selected.
   */
  function requestRoute(sinkId, selectedCastMode) {
    chrome.send(
        'requestRoute', [{sinkId: sinkId, selectedCastMode: selectedCastMode}]);
  }

  /**
   * Requests that the media router search all providers for a sink matching
   * |searchCriteria| that can be used with the media source associated with the
   * cast mode |selectedCastMode|. If such a sink is found, a route is also
   * created between the sink and the media source.
   *
   * @param {string} sinkId Sink ID of the pseudo sink generating the request.
   * @param {string} searchCriteria Search criteria for the route providers.
   * @param {string} domain User's current hosted domain.
   * @param {number} selectedCastMode The value of the cast mode to be used with
   *   the sink.
   */
  function searchSinksAndCreateRoute(
      sinkId, searchCriteria, domain, selectedCastMode) {
    chrome.send('searchSinksAndCreateRoute', [{
                  sinkId: sinkId,
                  searchCriteria: searchCriteria,
                  domain: domain,
                  selectedCastMode: selectedCastMode
                }]);
  }

  /**
   * Sends a command to seek the route shown in the route details view.
   *
   * @param {number} time The new current time in seconds.
   */
  function seekCurrentMedia(time) {
    chrome.send('seekCurrentMedia', [{time: time}]);
  }

  /**
   * Sends a command to open a file dialog and allow the user to choose a local
   * media file.
   */
  function selectLocalMediaFile() {
    chrome.send('selectLocalMediaFile');
  }

  /**
   * Sends a command to mute or unmute the route shown in the route details
   * view.
   *
   * @param {boolean} mute Mute the route if true, unmute it if false.
   */
  function setCurrentMediaMute(mute) {
    chrome.send('setCurrentMediaMute', [{mute: mute}]);
  }

  /**
   * Sends a command to change the volume of the route shown in the route
   * details view.
   *
   * @param {number} volume The volume between 0 and 1.
   */
  function setCurrentMediaVolume(volume) {
    chrome.send('setCurrentMediaVolume', [{volume: volume}]);
  }

  /**
   * Sets the local present mode of the Hangouts associated with the current
   * route.
   * @param {boolean} localPresent
   */
  function setHangoutsLocalPresent(localPresent) {
    chrome.send('hangouts.setLocalPresent', [localPresent]);
  }

  /**
   * Sends a command to change the Media Remoting enabled value associated with
   * current route.
   * @param {boolean} enabled
   */
  function setMediaRemotingEnabled(enabled) {
    chrome.send('setMediaRemotingEnabled', [enabled]);
  }

  return {
    acknowledgeFirstRunFlow: acknowledgeFirstRunFlow,
    actOnIssue: actOnIssue,
    changeRouteSource: changeRouteSource,
    closeDialog: closeDialog,
    closeRoute: closeRoute,
    joinRoute: joinRoute,
    onInitialDataReceived: onInitialDataReceived,
    onMediaControllerClosed: onMediaControllerClosed,
    onMediaControllerAvailable: onMediaControllerAvailable,
    pauseCurrentMedia: pauseCurrentMedia,
    playCurrentMedia: playCurrentMedia,
    reportBlur: reportBlur,
    reportClickedSinkIndex: reportClickedSinkIndex,
    reportFilter: reportFilter,
    reportInitialAction: reportInitialAction,
    reportInitialState: reportInitialState,
    reportNavigateToView: reportNavigateToView,
    reportRouteCreation: reportRouteCreation,
    reportRouteCreationOutcome: reportRouteCreationOutcome,
    reportSelectedCastMode: reportSelectedCastMode,
    reportSinkCount: reportSinkCount,
    reportTimeToClickSink: reportTimeToClickSink,
    reportTimeToInitialActionClose: reportTimeToInitialActionClose,
    reportWebUIRouteControllerLoaded: reportWebUIRouteControllerLoaded,
    requestInitialData: requestInitialData,
    requestRoute: requestRoute,
    searchSinksAndCreateRoute: searchSinksAndCreateRoute,
    seekCurrentMedia: seekCurrentMedia,
    selectLocalMediaFile: selectLocalMediaFile,
    setCurrentMediaMute: setCurrentMediaMute,
    setCurrentMediaVolume: setCurrentMediaVolume,
    setHangoutsLocalPresent: setHangoutsLocalPresent,
    setMediaRemotingEnabled: setMediaRemotingEnabled
  };
});

// // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Any strings used here will already be localized. Values such as
// CastMode.type or IDs will be defined elsewhere and determined later.

cr.exportPath('media_router');

/**
 * This corresponds to the C++ MediaCastMode, with the exception of AUTO.
 * See below for details. Note to support fast bitset operations, the values
 * here are (1 << [corresponding value in MR]).
 * @enum {number}
 */
media_router.CastModeType = {
  // Note: AUTO mode is only used to configure the sink list container to show
  // all sinks. Individual sinks are configured with a specific cast mode
  // (PRESENTATION, TAB_MIRROR, DESKTOP_MIRROR).
  AUTO: -1,
  PRESENTATION: 0x1,
  TAB_MIRROR: 0x2,
  DESKTOP_MIRROR: 0x4,
  LOCAL_FILE: 0x8,
};

/**
 * The ESC key maps to KeyboardEvent.key value 'Escape'.
 * @const {string}
 */
media_router.KEY_ESC = 'Escape';

/**
 * This corresponds to the C++ MediaRouterMetrics
 * MediaRouterRouteCreationOutcome.
 * @enum {number}
 */
media_router.MediaRouterRouteCreationOutcome = {
  SUCCESS: 0,
  FAILURE_NO_ROUTE: 1,
  FAILURE_INVALID_SINK: 2,
};

/**
 * This corresponds to the C++ MediaRouterMetrics MediaRouterUserAction.
 * @enum {number}
 */
media_router.MediaRouterUserAction = {
  CHANGE_MODE: 0,
  START_LOCAL: 1,
  STOP_LOCAL: 2,
  CLOSE: 3,
  STATUS_REMOTE: 4,
  REPLACE_LOCAL_ROUTE: 5,
};

/**
 * The possible states of the Media Router dialog. Used to determine which
 * components to show.
 * @enum {string}
 */
media_router.MediaRouterView = {
  CAST_MODE_LIST: 'cast-mode-list',
  FILTER: 'filter',
  ISSUE: 'issue',
  ROUTE_DETAILS: 'route-details',
  SINK_LIST: 'sink-list',
};

/**
 * The minimum number of sinks to have to enable the search input strictly for
 * filtering (i.e. the Media Router doesn't support search so the search input
 * only filters existing sinks).
 * @const {number}
 */
media_router.MINIMUM_SINKS_FOR_SEARCH = 20;

/**
 * The states that media can be in.
 * @enum {number}
 */
media_router.PlayState = {
  PLAYING: 0,
  PAUSED: 1,
  BUFFERING: 2,
};

/**
 * This corresponds to the C++ MediaSink IconType, and the order must stay in
 * sync.
 * @enum {number}
 */
media_router.SinkIconType = {
  CAST: 0,
  CAST_AUDIO_GROUP: 1,
  CAST_AUDIO: 2,
  MEETING: 3,
  HANGOUT: 4,
  EDUCATION: 5,
  WIRED_DISPLAY: 6,
  GENERIC: 7,
};

/**
 * @enum {string}
 */
media_router.SinkStatus = {
  IDLE: 'idle',
  ACTIVE: 'active',
  REQUEST_PENDING: 'request_pending'
};

cr.define('media_router', function() {
  'use strict';

  /**
   * @param {number} type The type of cast mode.
   * @param {string} description The description of the cast mode.
   * @param {?string} host The hostname of the site to cast.
   * @param {boolean} isForced True if the mode is forced.
   * @constructor
   * @struct
   */
  var CastMode = function(type, description, host, isForced) {
    /** @type {number} */
    this.type = type;

    /** @type {string} */
    this.description = description;

    /** @type {?string} */
    this.host = host || null;

    /** @type {boolean} */
    this.isForced = isForced;
  };

  /**
   * Placeholder object for AUTO cast mode. See comment in CastModeType.
   * @const {!media_router.CastMode}
   */
  var AUTO_CAST_MODE = new CastMode(
      media_router.CastModeType.AUTO, loadTimeData.getString('autoCastMode'),
      null, false);

  /**
   * @param {number} id The ID of this issue.
   * @param {string} title The issue title.
   * @param {string} message The issue message.
   * @param {number} defaultActionType The type of default action.
   * @param {number|undefined} secondaryActionType The type of optional action.
   * @param {?string} routeId The route ID to which this issue
   *                  pertains. If not set, this is a global issue.
   * @param {boolean} isBlocking True if this issue blocks other UI.
   * @param {?number} helpPageId The numeric help center ID.
   * @constructor
   * @struct
   */
  var Issue = function(
      id, title, message, defaultActionType, secondaryActionType, routeId,
      isBlocking, helpPageId) {
    /** @type {number} */
    this.id = id;

    /** @type {string} */
    this.title = title;

    /** @type {string} */
    this.message = message;

    /** @type {number} */
    this.defaultActionType = defaultActionType;

    /** @type {number|undefined} */
    this.secondaryActionType = secondaryActionType;

    /** @type {?string} */
    this.routeId = routeId;

    /** @type {boolean} */
    this.isBlocking = isBlocking;

    /** @type {?number} */
    this.helpPageId = helpPageId;
  };

  /**
   * @param {string} id The media route ID.
   * @param {string} sinkId The ID of the media sink running this route.
   * @param {string} description The short description of this route.
   * @param {?number} tabId The ID of the tab in which web app is running and
   *                  accessing the route.
   * @param {boolean} isLocal True if this is a locally created route.
   * @param {boolean} canJoin True if this route can be joined.
   * @param {?string} customControllerPath non-empty if this route has custom
   *                  controller.
   * @constructor
   * @struct
   */
  var Route = function(
      id, sinkId, description, tabId, isLocal, canJoin, customControllerPath) {
    /** @type {string} */
    this.id = id;

    /** @type {string} */
    this.sinkId = sinkId;

    /** @type {string} */
    this.description = description;

    /** @type {?number} */
    this.tabId = tabId;

    /** @type {boolean} */
    this.isLocal = isLocal;

    /** @type {boolean} */
    this.canJoin = canJoin;

    /** @type {number|undefined} */
    this.currentCastMode = undefined;

    /** @type {?string} */
    this.customControllerPath = customControllerPath;

    /** @type {boolean} */
    this.supportsWebUiController = false;
  };

  /**
   * @param {string} title The title of the route.
   * @param {boolean} canPlayPause Whether the route can be played/paused.
   * @param {boolean} canMute Whether the route can be muted/unmuted.
   * @param {boolean} canSetVolume Whether the route volume can be changed.
   * @param {boolean} canSeek Whether the route's playback position can be
   *     changed.
   * @param {boolean} isPaused Whether the route is paused.
   * @param {boolean} isMuted Whether the route is muted.
   * @param {number} volume The route's volume, between 0 and 1.
   * @param {number} duration The route's duration in seconds.
   * @param {number} currentTime The route's current position in seconds.
   *     Must not be greater than |duration|.
   * @param {!{mediaRemotingEnabled: boolean}=} mirroringExtraData Only set for
   *     mirroring routes.
   * @param {!{localPresent: boolean}=} hangoutsExtraData Only set for Hangouts
   *     routes.
   * @constructor
   * @struct
   */
  var RouteStatus = function(
      title = '', canPlayPause = false, canMute = false, canSetVolume = false,
      canSeek = false, playState = media_router.PlayState.PLAYING,
      isPaused = false, isMuted = false, volume = 0, duration = 0,
      currentTime = 0, hangoutsExtraData = undefined,
      mirroringExtraData = undefined) {

    /** @type {string} */
    this.title = title;

    /** @type {boolean} */
    this.canPlayPause = canPlayPause;

    /** @type {boolean} */
    this.canMute = canMute;

    /** @type {boolean} */
    this.canSetVolume = canSetVolume;

    /** @type {boolean} */
    this.canSeek = canSeek;

    /** @type {media_router.PlayState} */
    this.playState = playState;

    /** @type {boolean} */
    this.isMuted = isMuted;

    /** @type {number} */
    this.volume = volume;

    /** @type {number} */
    this.duration = duration;

    /** @type {number} */
    this.currentTime = currentTime;

    /** @type {!{localPresent: boolean}|undefined} */
    this.hangoutsExtraData = hangoutsExtraData;

    /** @type {!{mediaRemotingEnabled: boolean}|undefined} */
    this.mirroringExtraData = mirroringExtraData;
  };

  /**
   * @param {string} id The ID of the media sink.
   * @param {string} name The name of the sink.
   * @param {?string} description Optional description of the sink.
   * @param {?string} domain Optional domain of the sink.
   * @param {media_router.SinkIconType} iconType the type of icon for the sink.
   * @param {media_router.SinkStatus} status The readiness state of the sink.
   * @param {number} castModes Bitset of cast modes compatible with the sink.
   * @constructor
   * @struct
   */
  var Sink = function(
      id, name, description, domain, iconType, status, castModes) {
    /** @type {string} */
    this.id = id;

    /** @type {string} */
    this.name = name;

    /** @type {?string} */
    this.description = description;

    /** @type {?string} */
    this.domain = domain;

    /** @type {!media_router.SinkIconType} */
    this.iconType = iconType;

    /** @type {!media_router.SinkStatus} */
    this.status = status;

    /** @type {number} */
    this.castModes = castModes;

    /** @type {boolean} */
    this.isPseudoSink = false;
  };

  /**
   * @param {number} tabId The current tab ID.
   * @param {string} domain The domain of the current tab.
   * @constructor
   * @struct
   */
  var TabInfo = function(tabId, domain) {
    /** @type {number} */
    this.tabId = tabId;

    /** @type {string} */
    this.domain = domain;
  };

  return {
    AUTO_CAST_MODE: AUTO_CAST_MODE,
    CastMode: CastMode,
    Issue: Issue,
    Route: Route,
    RouteStatus: RouteStatus,
    Sink: Sink,
    TabInfo: TabInfo,
  };
});

// // Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// API invoked by the browser MediaRouterWebUIMessageHandler to communicate
// with this UI.
cr.define('media_router.ui', function() {
  'use strict';

  // The media-router-container element.
  var container = null;

  // The media-router-header element.
  var header = null;

  // The route-controls element. Is null if the route details view isn't open.
  var routeControls = null;

  // The initial height for |container|.
  var initialMaxHeight = 0;

  /**
   * Handles response of previous create route attempt.
   *
   * @param {string} sinkId The ID of the sink to which the Media Route was
   *     creating a route.
   * @param {?media_router.Route} route The newly created route that
   *     corresponds to the sink if route creation succeeded; null otherwise.
   * @param {boolean} isForDisplay Whether or not |route| is for display.
   */
  function onCreateRouteResponseReceived(sinkId, route, isForDisplay) {
    container.onCreateRouteResponseReceived(sinkId, route, isForDisplay);
  }

  /**
   * Called when the route controller for the route that is currently selected
   * is invalidated.
   */
  function onRouteControllerInvalidated() {
    container.onRouteControllerInvalidated();
  }

  /**
   * Handles the search response by forwarding |sinkId| to the container.
   *
   * @param {string} sinkId The ID of the sink found by search.
   */
  function receiveSearchResult(sinkId) {
    container.onReceiveSearchResult(sinkId);
  }

  /**
   * Sets the cast mode list.
   *
   * @param {!Array<!media_router.CastMode>} castModeList
   */
  function setCastModeList(castModeList) {
    container.castModeList = castModeList;
  }

  /**
   * Sets |container| and |header|.
   *
   * @param {!MediaRouterContainerInterface} mediaRouterContainer
   * @param {!MediaRouterHeaderElement} mediaRouterHeader
   */
  function setElements(mediaRouterContainer, mediaRouterHeader) {
    container = mediaRouterContainer;
    header = mediaRouterHeader;

    if (initialMaxHeight) {
      container.updateMaxDialogHeight(initialMaxHeight);
      initialMaxHeight = 0;
    }
  }

  /**
   * Populates the WebUI with data obtained about the first run flow.
   *
   * @param {{firstRunFlowCloudPrefLearnMoreUrl: string,
   *          firstRunFlowLearnMoreUrl: string,
   *          wasFirstRunFlowAcknowledged: boolean,
   *          showFirstRunFlowCloudPref: boolean}} data
   * Parameters in data:
   *   firstRunFlowCloudPrefLearnMoreUrl - url to open when the cloud services
   *       pref learn more link is clicked.
   *   firstRunFlowLearnMoreUrl - url to open when the first run flow learn
   *       more link is clicked.
   *   wasFirstRunFlowAcknowledged - true if first run flow was previously
   *       acknowledged by user.
   *   showFirstRunFlowCloudPref - true if the cloud pref option should be
   *       shown.
   */
  function setFirstRunFlowData(data) {
    container.firstRunFlowCloudPrefLearnMoreUrl =
        data['firstRunFlowCloudPrefLearnMoreUrl'];
    container.firstRunFlowLearnMoreUrl = data['firstRunFlowLearnMoreUrl'];
    container.showFirstRunFlowCloudPref = data['showFirstRunFlowCloudPref'];
    // Some users acknowledged the first run flow before the cloud prefs
    // setting was implemented. These users will see the first run flow
    // again.
    container.showFirstRunFlow = !data['wasFirstRunFlowAcknowledged'] ||
        container.showFirstRunFlowCloudPref;
  }

  /**
   * Populates the WebUI with data obtained from Media Router.
   *
   * @param {{deviceMissingUrl: string,
   *          sinksAndIdentity: {
   *            sinks: !Array<!media_router.Sink>,
   *            showEmail: boolean,
   *            userEmail: string,
   *            showDomain: boolean
   *          },
   *          routes: !Array<!media_router.Route>,
   *          castModes: !Array<!media_router.CastMode>,
   *          useTabMirroring: boolean}} data
   * Parameters in data:
   *   deviceMissingUrl - url to be opened on "Device missing?" clicked.
   *   sinksAndIdentity - list of sinks to be displayed and user identity.
   *   useWebUiRouteControls - whether new WebUI route controls should be used.
   *   routes - list of routes that are associated with the sinks.
   *   castModes - list of available cast modes.
   *   useTabMirroring - whether the cast mode should be set to TAB_MIRROR.
   */
  function setInitialData(data) {
    container.deviceMissingUrl = data['deviceMissingUrl'];
    container.castModeList = data['castModes'];
    this.setSinkListAndIdentity(data['sinksAndIdentity']);
    container.routeList = data['routes'];
    container.maybeShowRouteDetailsOnOpen();
    if (data['useTabMirroring']) {
      container.selectCastMode(media_router.CastModeType.TAB_MIRROR);
    }
    media_router.browserApi.onInitialDataReceived();
  }

  /**
   * Sets current issue to |issue|, or clears the current issue if |issue| is
   * null.
   *
   * @param {?media_router.Issue} issue
   */
  function setIssue(issue) {
    container.issue = issue;
  }

  /**
   * Sets |routeControls|. The argument may be null if the route details view is
   * getting closed.
   *
   * @param {?RouteControlsInterface} mediaRouterRouteControls
   */
  function setRouteControls(mediaRouterRouteControls) {
    routeControls = mediaRouterRouteControls;
  }

  /**
   * Sets the list of currently active routes.
   *
   * @param {!Array<!media_router.Route>} routeList
   */
  function setRouteList(routeList) {
    container.routeList = routeList;
  }

  /**
   * Sets the list of discovered sinks along with properties of whether to hide
   * identity of the user email and domain.
   *
   * @param {{sinks: !Array<!media_router.Sink>,
   *          showEmail: boolean,
   *          userEmail: string,
   *          showDomain: boolean}} data
   * Parameters in data:
   *   sinks - list of sinks to be displayed.
   *   showEmail - true if the user email should be shown.
   *   userEmail - email of the user if the user is signed in.
   *   showDomain - true if the user domain should be shown.
   */
  function setSinkListAndIdentity(data) {
    container.showDomain = data['showDomain'];
    container.allSinks = data['sinks'];
    header.userEmail = data['userEmail'];
    header.showEmail = data['showEmail'];
  }

  /**
   * Updates the max height of the dialog
   *
   * @param {number} height
   */
  function updateMaxHeight(height) {
    if (container) {
      container.updateMaxDialogHeight(height);
    } else {
      // Update the max height once |container| gets set.
      initialMaxHeight = height;
    }
  }

  /**
   * Updates the route status shown in the route controls.
   *
   * @param {!media_router.RouteStatus} status
   */
  function updateRouteStatus(status) {
    if (routeControls) {
      routeControls.routeStatus = status;
    }
  }

  function userSelectedLocalMediaFile(fileName) {
    container.onFileDialogSuccess(fileName);
  }

  return {
    onCreateRouteResponseReceived: onCreateRouteResponseReceived,
    onRouteControllerInvalidated: onRouteControllerInvalidated,
    receiveSearchResult: receiveSearchResult,
    setCastModeList: setCastModeList,
    setElements: setElements,
    setFirstRunFlowData: setFirstRunFlowData,
    setInitialData: setInitialData,
    setIssue: setIssue,
    setRouteControls: setRouteControls,
    setRouteList: setRouteList,
    setSinkListAndIdentity: setSinkListAndIdentity,
    updateMaxHeight: updateMaxHeight,
    updateRouteStatus: updateRouteStatus,
    userSelectedLocalMediaFile: userSelectedLocalMediaFile,
  };
});


// Handles user events for the Media Router UI.
cr.define('media_router', function() {
  'use strict';

  /**
   * The media-router-container element. Initialized after polymer is ready.
   * @type {?MediaRouterContainerInterface}
   */
  var container = null;

  /**
   * Initializes the Media Router WebUI and requests initial media
   * router content, such as the media sink and media route lists.
   */
  function initialize() {
    // For non-Mac platforms, request data immediately after initialization.
    if (!cr.isMac) {
      onRequestInitialData();
    }

    container = /** @type {!MediaRouterContainerInterface} */
        ($('media-router-container'));

    media_router.ui.setElements(container, container.header);

    container.addEventListener(
        'acknowledge-first-run-flow', onAcknowledgeFirstRunFlow);
    container.addEventListener('back-click', onNavigateToSinkList);
    container.addEventListener('cast-mode-selected', onCastModeSelected);
    container.addEventListener(
        'change-route-source-click', onChangeRouteSourceClick);
    container.addEventListener('close-dialog', onCloseDialog);
    container.addEventListener('close-route', onCloseRoute);
    container.addEventListener('create-route', onCreateRoute);
    container.addEventListener('issue-action-click', onIssueActionClick);
    container.addEventListener('join-route-click', onJoinRouteClick);
    container.addEventListener(
        'navigate-sink-list-to-details', onNavigateToDetails);
    container.addEventListener(
        'navigate-to-cast-mode-list', onNavigateToCastMode);
    container.addEventListener(
        'select-local-media-file', onSelectLocalMediaFile);
    container.addEventListener('report-filter', onFilter);
    container.addEventListener('report-initial-action', onInitialAction);
    container.addEventListener(
        'report-initial-action-close', onInitialActionClose);
    container.addEventListener('report-route-creation', onReportRouteCreation);
    container.addEventListener(
        'report-sink-click-time', onSinkClickTimeReported);
    container.addEventListener('report-sink-count', onSinkCountReported);
    container.addEventListener(
        'report-resolved-route', onReportRouteCreationOutcome);
    container.addEventListener('request-initial-data', onRequestInitialData);
    container.addEventListener(
        'search-sinks-and-create-route', onSearchSinksAndCreateRoute);
    container.addEventListener('show-initial-state', onShowInitialState);
    container.addEventListener('sink-click', onSinkClick);

    window.addEventListener('blur', onWindowBlur);
  }

  /**
   * Requests that the Media Router searches for a sink with criteria
   * |event.detail.name|.
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   id - id of the pseudo sink generating the request.
   *   name - sink search criteria.
   *   domain - user's current domain.
   *   selectedCastMode - type of cast mode selected by the user.
   */
  function onSearchSinksAndCreateRoute(event) {
    /** @type {{id: string, domain: string, name: string,
     *          selectedCastMode: number}} */
    var detail = event.detail;
    media_router.browserApi.searchSinksAndCreateRoute(
        detail.id, detail.name, detail.domain, detail.selectedCastMode);
  }

  /**
   * Reports the selected cast mode.
   * Called when the user selects a cast mode from the picker.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   castModeType - type of cast mode selected by the user.
   */
  function onCastModeSelected(event) {
    /** @type {{castModeType: number}} */
    var detail = event.detail;
    media_router.browserApi.reportSelectedCastMode(detail.castModeType);
  }

  /**
   * Reports the route for which the users wants to replace the source and the
   * cast mode that should be used for the new source.
   *
   * @param {!Event} event The event object.
   * Parameters in |event|.detail:
   *   route - route to modify.
   *   selectedCastMode - type of cast mode selected by the user.
   */
  function onChangeRouteSourceClick(event) {
    /** @type {{route: !media_router.Route, selectedCastMode: number}} */
    var detail = event.detail;
    media_router.browserApi.changeRouteSource(
        detail.route, detail.selectedCastMode);
  }

  /**
   * Sends a request to the browser to select a local file.
   */
  function onSelectLocalMediaFile() {
    media_router.browserApi.selectLocalMediaFile();
  }

  /**
   * Updates the preference that the user has seen the first run flow.
   * Called when the user clicks on the acknowledgement button on the first run
   * flow.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   optedIntoCloudServices - whether or not the user opted into cloud
   *                            services.
   */
  function onAcknowledgeFirstRunFlow(event) {
    /** @type {{optedIntoCloudServices: boolean}} */
    var detail = event.detail;
    media_router.browserApi.acknowledgeFirstRunFlow(
        detail.optedIntoCloudServices);
  }

  /**
   * Closes the dialog.
   * Called when the user clicks the close button on the dialog. Reports
   * whether the user closed the dialog via the ESC key.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   pressEscToClose - whether or not the user pressed ESC to close the
   *                     dialog.
   */
  function onCloseDialog(event) {
    /** @type {{pressEscToClose: boolean}} */
    var detail = event.detail;
    container.maybeReportUserFirstAction(
        media_router.MediaRouterUserAction.CLOSE);
    media_router.browserApi.closeDialog(detail.pressEscToClose);
  }

  /**
   * Reports when the user uses the filter input to filter the sink list. This
   * is reported at most once each time the user enters the filter view, and
   * only if text is actually entered in the filter input.
   */
  function onFilter() {
    media_router.browserApi.reportFilter();
  }

  /**
   * Reports the first action the user takes after opening the dialog.
   * Called when the user explicitly interacts with the dialog to perform an
   * action.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   action - the first action taken by the user.
   */
  function onInitialAction(event) {
    /** @type {{action: number}} */
    var detail = event.detail;
    media_router.browserApi.reportInitialAction(detail.action);
  }

  /**
   * Reports the time it took for the user to close the dialog if that was the
   * first action the user took after opening the dialog.
   * Called when the user closes the dialog without taking any other action.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   timeMs - time in ms for the user to close the dialog.
   */
  function onInitialActionClose(event) {
    /** @type {{timeMs: number}} */
    var detail = event.detail;
    media_router.browserApi.reportTimeToInitialActionClose(detail.timeMs);
  }

  /**
   * Acts on an issue and dismisses it from the UI.
   * Called when the user performs an action on an issue.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   id - issue ID.
   *   actionType - type of action performed by the user.
   *   helpPageId - the numeric help center ID.
   */
  function onIssueActionClick(event) {
    /** @type {{id: number, actionType: number, helpPageId: number}} */
    var detail = event.detail;
    media_router.browserApi.actOnIssue(
        detail.id, detail.actionType, detail.helpPageId);
    container.issue = null;
  }

  /**
   * Creates a media route.
   * Called when the user requests to create a media route.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   sinkId - sink ID selected by the user.
   *   selectedCastModeValue - cast mode selected by the user.
   */
  function onCreateRoute(event) {
    /** @type {{sinkId: string, selectedCastModeValue: number}} */
    var detail = event.detail;
    media_router.browserApi.requestRoute(
        detail.sinkId, detail.selectedCastModeValue);
  }

  /**
   * Stops a route.
   * Called when the user requests to stop a media route.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   route - The route to close.
   */
  function onCloseRoute(event) {
    /** @type {{route: !media_router.Route}} */
    var detail = event.detail;
    media_router.browserApi.closeRoute(detail.route);
  }

  /**
   * Starts casting to an existing route.
   * Called when the user requests to start casting to a media route that is
   * joinable.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   route - The route to connect to if possible.
   */
  function onJoinRouteClick(event) {
    /** @type {{route: !media_router.Route}} */
    var detail = event.detail;
    media_router.browserApi.joinRoute(detail.route);
  }

  /**
   * Reports the user navigation to the cast mode view.
   * Called when the user clicks the drop arrow to navigate to the cast mode
   * view on the dialog.
   */
  function onNavigateToCastMode() {
    media_router.browserApi.reportNavigateToView(
        media_router.MediaRouterView.CAST_MODE_LIST);
  }

  /**
   * Reports the user navigation the route details view.
   * Called when the user clicks on a sink to navigate to the route details
   * view.
   */
  function onNavigateToDetails() {
    media_router.browserApi.reportNavigateToView(
        media_router.MediaRouterView.ROUTE_DETAILS);
  }

  /**
   * Reports the user navigation the sink list view.
   * Called when the user clicks on the back button from the route details view
   * to the sink list view.
   */
  function onNavigateToSinkList() {
    media_router.browserApi.reportNavigateToView(
        media_router.MediaRouterView.SINK_LIST);
  }

  /**
   * Reports whether or not the route creation was successful.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   success - whether or not the route creation was successful.
   */
  function onReportRouteCreation(event) {
    /** @type {{success: boolean}} */
    var detail = event.detail;
    media_router.browserApi.reportRouteCreation(detail.success);
  }

  /**
   * Reports success or the type of failure for route creation response.
   * Called when the route is resolved; either the route creation was a success
   * or if there was no route or the route's corresponding sink is invalid;
   * either the sink does not exist or was not the sink we were looking for.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   outcome - the outcome of a create route response.
   *
   */
  function onReportRouteCreationOutcome(event) {
    /** @type {{outcome: number}} */
    var detail = event.detail;
    media_router.browserApi.reportRouteCreationOutcome(detail.outcome);
  }

  /**
   * Requests for initial data to load into the dialog.
   */
  function onRequestInitialData() {
    media_router.browserApi.requestInitialData();
  }

  /**
   * Reports the initial state of the dialog after it is opened.
   * Called after initial data is populated.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   currentView - the current dialog's current view.
   */
  function onShowInitialState(event) {
    /** @type {{currentView: string}} */
    var detail = event.detail;
    media_router.browserApi.reportInitialState(detail.currentView);
  }

  /**
   * Reports the index of the sink that was clicked.
   * Called when the user selects a sink on the sink list.
   *
   * @param {!Event} event
   * Paramters in |event|.detail:
   *   index - the index of the clicked sink.
   */
  function onSinkClick(event) {
    /** @type {{index: number}} */
    var detail = event.detail;
    media_router.browserApi.reportClickedSinkIndex(detail.index);
  }

  /**
   * Reports the time it took for the user to select a sink to create a route
   * after the list was popuated and shown.
   *
   * @param {!Event} event
   * Paramters in |event|.detail:
   *   timeMs - the time it took for the user to select a sink.
   */
  function onSinkClickTimeReported(event) {
    /** @type {{timeMs: number}} */
    var detail = event.detail;
    media_router.browserApi.reportTimeToClickSink(detail.timeMs);
  }

  /**
   * Reports the current sink count.
   * Called 3 seconds after the dialog is initially opened.
   *
   * @param {!Event} event
   * Parameters in |event|.detail:
   *   sinkCount - the number of sinks.
   */
  function onSinkCountReported(event) {
    /** @type {{sinkCount: number}} */
    var detail = event.detail;
    media_router.browserApi.reportSinkCount(detail.sinkCount);
  }

  /**
   * Reports when the user clicks outside the dialog.
   */
  function onWindowBlur() {
    media_router.browserApi.reportBlur();
  }

  return {
    initialize: initialize,
  };
});

window.addEventListener('load', media_router.initialize);
<!DOCTYPE HTML>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>$i18n{mediaRouterTitle}</title>

  <link rel="stylesheet" href="chrome://resources/css/roboto.css">
  <link rel="stylesheet" href="media_router_common.css">
  <link rel="stylesheet" href="media_router.css">
  <link rel="import" href="chrome://resources/html/cr.html">
  <link rel="import" href="chrome://resources/html/load_time_data.html">
  <link rel="import" href="chrome://resources/html/util.html">
  <script src="chrome://media-router/strings.js"></script>
  <script src="chrome://media-router/media_router.js"></script>
  <link rel="import" href="chrome://media-router/elements/media_router_container/media_router_container.html">
</head>
<body>
  <media-router-container id="media-router-container"></media-router-container>
  <link rel="import" href="chrome://resources/html/i18n_template.html">
</body>
</html>
<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="media_router_internals.css">
  <link rel="import" href="chrome://resources/html/cr.html">
  <link rel="import" href="chrome://resources/html/util.html">
  <script src="media_router_internals.js"></script>
</head>
<body>
  <div id="sink-status-div"></div>
</body>
</html>
/* Copyright 2018 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

#sink-status-div {
  white-space: pre-wrap;
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Handles user events for the Media Router Internals UI.
cr.define('media_router_internals', function() {
  'use strict';

  /**
   * Initializes the Media Router Internals WebUI
   */
  function initialize() {
    // Notify the browser that the page has loaded, causing it to send media
    // router status.
    chrome.send('initialized');
  }

  function setStatus(status) {
    const jsonStatus = JSON.stringify(status, null, /* spacing level = */ 2);
    $('sink-status-div').textContent = jsonStatus;
  }

  return {
    initialize: initialize,
    setStatus: setStatus,
  };
});

document.addEventListener(
    'DOMContentLoaded', media_router_internals.initialize);
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// API invoked by the browser MediaRouterWebUIMessageHandler to communicate
// with this UI.
cr.define('media_router.ui', function() {
  'use strict';

  // The media-router-container element.
  var container = null;

  // The media-router-header element.
  var header = null;

  // The route-controls element. Is null if the route details view isn't open.
  var routeControls = null;

  // The initial height for |container|.
  var initialMaxHeight = 0;

  /**
   * Handles response of previous create route attempt.
   *
   * @param {string} sinkId The ID of the sink to which the Media Route was
   *     creating a route.
   * @param {?media_router.Route} route The newly created route that
   *     corresponds to the sink if route creation succeeded; null otherwise.
   * @param {boolean} isForDisplay Whether or not |route| is for display.
   */
  function onCreateRouteResponseReceived(sinkId, route, isForDisplay) {
    container.onCreateRouteResponseReceived(sinkId, route, isForDisplay);
  }

  /**
   * Called when the route controller for the route that is currently selected
   * is invalidated.
   */
  function onRouteControllerInvalidated() {
    container.onRouteControllerInvalidated();
  }

  /**
   * Handles the search response by forwarding |sinkId| to the container.
   *
   * @param {string} sinkId The ID of the sink found by search.
   */
  function receiveSearchResult(sinkId) {
    container.onReceiveSearchResult(sinkId);
  }

  /**
   * Sets the cast mode list.
   *
   * @param {!Array<!media_router.CastMode>} castModeList
   */
  function setCastModeList(castModeList) {
    container.castModeList = castModeList;
  }

  /**
   * Sets |container| and |header|.
   *
   * @param {!MediaRouterContainerInterface} mediaRouterContainer
   * @param {!MediaRouterHeaderElement} mediaRouterHeader
   */
  function setElements(mediaRouterContainer, mediaRouterHeader) {
    container = mediaRouterContainer;
    header = mediaRouterHeader;

    if (initialMaxHeight) {
      container.updateMaxDialogHeight(initialMaxHeight);
      initialMaxHeight = 0;
    }
  }

  /**
   * Populates the WebUI with data obtained about the first run flow.
   *
   * @param {{firstRunFlowCloudPrefLearnMoreUrl: string,
   *          firstRunFlowLearnMoreUrl: string,
   *          wasFirstRunFlowAcknowledged: boolean,
   *          showFirstRunFlowCloudPref: boolean}} data
   * Parameters in data:
   *   firstRunFlowCloudPrefLearnMoreUrl - url to open when the cloud services
   *       pref learn more link is clicked.
   *   firstRunFlowLearnMoreUrl - url to open when the first run flow learn
   *       more link is clicked.
   *   wasFirstRunFlowAcknowledged - true if first run flow was previously
   *       acknowledged by user.
   *   showFirstRunFlowCloudPref - true if the cloud pref option should be
   *       shown.
   */
  function setFirstRunFlowData(data) {
    container.firstRunFlowCloudPrefLearnMoreUrl =
        data['firstRunFlowCloudPrefLearnMoreUrl'];
    container.firstRunFlowLearnMoreUrl = data['firstRunFlowLearnMoreUrl'];
    container.showFirstRunFlowCloudPref = data['showFirstRunFlowCloudPref'];
    // Some users acknowledged the first run flow before the cloud prefs
    // setting was implemented. These users will see the first run flow
    // again.
    container.showFirstRunFlow = !data['wasFirstRunFlowAcknowledged'] ||
        container.showFirstRunFlowCloudPref;
  }

  /**
   * Populates the WebUI with data obtained from Media Router.
   *
   * @param {{deviceMissingUrl: string,
   *          sinksAndIdentity: {
   *            sinks: !Array<!media_router.Sink>,
   *            showEmail: boolean,
   *            userEmail: string,
   *            showDomain: boolean
   *          },
   *          routes: !Array<!media_router.Route>,
   *          castModes: !Array<!media_router.CastMode>,
   *          useTabMirroring: boolean}} data
   * Parameters in data:
   *   deviceMissingUrl - url to be opened on "Device missing?" clicked.
   *   sinksAndIdentity - list of sinks to be displayed and user identity.
   *   useWebUiRouteControls - whether new WebUI route controls should be used.
   *   routes - list of routes that are associated with the sinks.
   *   castModes - list of available cast modes.
   *   useTabMirroring - whether the cast mode should be set to TAB_MIRROR.
   */
  function setInitialData(data) {
    container.deviceMissingUrl = data['deviceMissingUrl'];
    container.castModeList = data['castModes'];
    this.setSinkListAndIdentity(data['sinksAndIdentity']);
    container.routeList = data['routes'];
    container.maybeShowRouteDetailsOnOpen();
    if (data['useTabMirroring']) {
      container.selectCastMode(media_router.CastModeType.TAB_MIRROR);
    }
    media_router.browserApi.onInitialDataReceived();
  }

  /**
   * Sets current issue to |issue|, or clears the current issue if |issue| is
   * null.
   *
   * @param {?media_router.Issue} issue
   */
  function setIssue(issue) {
    container.issue = issue;
  }

  /**
   * Sets |routeControls|. The argument may be null if the route details view is
   * getting closed.
   *
   * @param {?RouteControlsInterface} mediaRouterRouteControls
   */
  function setRouteControls(mediaRouterRouteControls) {
    routeControls = mediaRouterRouteControls;
  }

  /**
   * Sets the list of currently active routes.
   *
   * @param {!Array<!media_router.Route>} routeList
   */
  function setRouteList(routeList) {
    container.routeList = routeList;
  }

  /**
   * Sets the list of discovered sinks along with properties of whether to hide
   * identity of the user email and domain.
   *
   * @param {{sinks: !Array<!media_router.Sink>,
   *          showEmail: boolean,
   *          userEmail: string,
   *          showDomain: boolean}} data
   * Parameters in data:
   *   sinks - list of sinks to be displayed.
   *   showEmail - true if the user email should be shown.
   *   userEmail - email of the user if the user is signed in.
   *   showDomain - true if the user domain should be shown.
   */
  function setSinkListAndIdentity(data) {
    container.showDomain = data['showDomain'];
    container.allSinks = data['sinks'];
    header.userEmail = data['userEmail'];
    header.showEmail = data['showEmail'];
  }

  /**
   * Updates the max height of the dialog
   *
   * @param {number} height
   */
  function updateMaxHeight(height) {
    if (container) {
      container.updateMaxDialogHeight(height);
    } else {
      // Update the max height once |container| gets set.
      initialMaxHeight = height;
    }
  }

  /**
   * Updates the route status shown in the route controls.
   *
   * @param {!media_router.RouteStatus} status
   */
  function updateRouteStatus(status) {
    if (routeControls) {
      routeControls.routeStatus = status;
    }
  }

  function userSelectedLocalMediaFile(fileName) {
    container.onFileDialogSuccess(fileName);
  }

  return {
    onCreateRouteResponseReceived: onCreateRouteResponseReceived,
    onRouteControllerInvalidated: onRouteControllerInvalidated,
    receiveSearchResult: receiveSearchResult,
    setCastModeList: setCastModeList,
    setElements: setElements,
    setFirstRunFlowData: setFirstRunFlowData,
    setInitialData: setInitialData,
    setIssue: setIssue,
    setRouteControls: setRouteControls,
    setRouteList: setRouteList,
    setSinkListAndIdentity: setSinkListAndIdentity,
    updateMaxHeight: updateMaxHeight,
    updateRouteStatus: updateRouteStatus,
    userSelectedLocalMediaFile: userSelectedLocalMediaFile,
  };
});
<!-- The following icons are duplicated to avoid pulling in unused icons,
     e.g. the entire cr_elements/icons.html file. -->
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
<iron-iconset-svg name="media-router" size="24">
<svg><defs>
  <!-- third_party/polymer/v1_0/components-chromium/iron-icons/iron-icons.html -->
  <g id="folder"><path d="M0 0h24v24H0z" fill="none"></path><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g>
  <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
  <g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g>

  <!-- third_party/polymer/v1_0/components-chromium/iron-icons/av-icons.html -->
  <g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"></path></g>

  <!-- third_party/polymer/v1_0/components-chromium/iron-icons/hardware-icons.html -->
  <g id="laptop"><path d="M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"></path></g>
  <g id="speaker"><path d="M17 2H7c-1.1 0-2 .9-2 2v16c0 1.1.9 1.99 2 1.99L17 22c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 2c1.1 0 2 .9 2 2s-.9 2-2 2c-1.11 0-2-.9-2-2s.89-2 2-2zm0 16c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"></path></g>
  <g id="speaker-group"><path d="M18.2 1H9.8C8.81 1 8 1.81 8 2.8v14.4c0 .99.81 1.79 1.8 1.79l8.4.01c.99 0 1.8-.81 1.8-1.8V2.8c0-.99-.81-1.8-1.8-1.8zM14 3c1.1 0 2 .89 2 2s-.9 2-2 2-2-.89-2-2 .9-2 2-2zm0 13.5c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"></path><circle cx="14" cy="12.5" r="2.5"></circle><path d="M6 5H4v16c0 1.1.89 2 2 2h10v-2H6V5z"></path></g>
  <g id="tv"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z"></path></g>

  <!-- Icons below are swapped out in branded builds. -->
  <!-- copy of third_party/polymer/v1_0/components-chromium/iron-icons/hardware-icons.html hardware:tv icon -->
  <g id="chromecast"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z"></path></g>
  <g id="education"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z"></path></g>
  <!-- copy of third_party/polymer/v1_0/components-chromium/iron-icons/hardware-icons.html communication:message icon -->
  <g id="hangout"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path></g>
  <g id="meeting"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path></g>
</defs></svg>
</iron-iconset-svg>
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<dom-module id="issue-banner">
  <link rel="import" type="css" href="../../media_router_common.css">
  <link rel="import" type="css" href="issue_banner.css">
  <template>
    <div class$="[[computeIssueClass_(issue)]]">
      <div>
        <div hidden$="[[computeIsBlockingIssueHidden_(issue)]]">
          <iron-icon icon="cr:error-outline" id="blocking-icon">
          </iron-icon>
        </div>
        <div id="title" aria-live="polite" tabindex="0">[[issue.title]]</div>
      </div>
      <div id="buttons">
        <paper-button flat id="opt-button" class="button"
            on-tap="onClickOptAction_"
            hidden$="[[computeOptionalActionHidden_(issue)]]">
          <span>[[secondaryActionButtonText_]]</span>
        </paper-button>
        <paper-button flat id="default-button"
            class="button action" on-tap="onClickDefaultAction_">
          <span>[[defaultActionButtonText_]]</span>
        </paper-button>
      </div>
    </div>
  </template>
<script src="issue_banner.js"></script>
</dom-module>
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This Polymer element is used to show information about issues related
// to casting.
Polymer({
  is: 'issue-banner',

  properties: {
    /**
     * Maps an issue action type to the resource identifier of the text shown
     * in the action button.
     * This is a property of issue-banner because it is used in tests. This
     * property should always be set before |issue| is set or updated.
     * @private {!Array<string>}
     */
    actionTypeToButtonTextResource_: {
      type: Array,
      readOnly: true,
      value: function() {
        return ['dismissButton', 'learnMoreText'];
      },
    },

    /**
     * The text shown in the default action button.
     * @private {string|undefined}
     */
    defaultActionButtonText_: {
      type: String,
    },

    /**
     * The issue to show.
     * @type {?media_router.Issue|undefined}
     */
    issue: {
      type: Object,
      observer: 'updateActionButtonText_',
    },

    /**
     * The text shown in the secondary action button.
     * @private {string|undefined}
     */
    secondaryActionButtonText_: {
      type: String,
    },
  },

  behaviors: [
    I18nBehavior,
  ],

  /**
   * @param {?media_router.Issue} issue
   * @return {boolean} Whether or not to hide the blocking issue UI.
   * @private
   */
  computeIsBlockingIssueHidden_: function(issue) {
    return !issue || !issue.isBlocking;
  },

  /**
   * @param {?media_router.Issue} issue The current issue.
   * @return {string} The class for the overall issue-banner.
   * @private
   */
  computeIssueClass_: function(issue) {
    if (!issue) {
      return '';
    }

    return issue.isBlocking ? 'blocking' : 'non-blocking';
  },

  /**
   * @param {?media_router.Issue} issue
   * @return {boolean} Whether or not to hide the non-blocking issue UI.
   * @private
   */
  computeOptionalActionHidden_: function(issue) {
    return !issue || issue.secondaryActionType === undefined;
  },

  /**
   * Fires an issue-action-click event.
   *
   * @param {number} actionType The type of issue action.
   * @private
   */
  fireIssueActionClick_: function(actionType) {
    this.fire('issue-action-click', {
      id: this.issue.id,
      actionType: actionType,
      helpPageId: this.issue.helpPageId
    });
  },

  /**
   * Called when a default issue action is clicked.
   *
   * @param {!Event} event The event object.
   * @private
   */
  onClickDefaultAction_: function(event) {
    this.fireIssueActionClick_(this.issue.defaultActionType);
  },

  /**
   * Called when an optional issue action is clicked.
   *
   * @param {!Event} event The event object.
   * @private
   */
  onClickOptAction_: function(event) {
    this.fireIssueActionClick_(
        /** @type {number} */ (this.issue.secondaryActionType));
  },

  /**
   * Called when |issue| is updated. This updates the default and secondary
   * action button text.
   *
   * @private
   */
  updateActionButtonText_: function() {
    var defaultText = '';
    var secondaryText = '';
    if (this.issue) {
      defaultText = this.i18n(
          this.actionTypeToButtonTextResource_[this.issue.defaultActionType]);

      if (this.issue.secondaryActionType !== undefined) {
        secondaryText = this.i18n(
            this.actionTypeToButtonTextResource_[this.issue
                                                     .secondaryActionType]);
      }
    }

    this.defaultActionButtonText_ = defaultText;
    this.secondaryActionButtonText_ = secondaryText;
  },
});
/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.blocking {
  background-color: white;
  overflow: hidden;
  position: relative;
  text-align: center;
}

.blocking > #buttons {
  padding-bottom: 24px;
  padding-top: 20px;
}

.blocking > div > #title {
  color: rgba(0, 0, 0, 0.87);
  line-height: 1.125em;
  padding: 10px;
  vertical-align: middle;
}

#blocking-icon {
  color: var(--google-red-500);
  height: 75px;
  padding-top: 24px;
  width: 75px;
}

.non-blocking {
  background-color: var(--paper-grey-800);
  padding: 16px;
  width: inherit;
}

.non-blocking > #buttons {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  width: 100%;
}

.non-blocking > #buttons > .button {
  color: var(--paper-blue-300);
}

.non-blocking > #buttons > #default-button {
  margin-inline-end: 24px;
}

.non-blocking > div > #title {
  color: rgba(255, 255, 255, 0.87);
  margin-inline-end: 12px;
  overflow: hidden;
  padding-inline-end: 12px;
}

paper-button {
  margin: 0;
}
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
<link rel="import" href="../media_router_header/media_router_header.html">
<link rel="import" href="../route_details/route_details.html">
<link rel="import" href="../../icons/media_router_icons.html">
<dom-module id="media-router-container">
  <link rel="import" type="css" href="../../media_router_common.css">
  <link rel="import" type="css" href="media_router_container.css">
  <template>
    <div id="focus-placeholder" tabindex="0"></div>
    <template is="dom-if"
        if="[[computeShowFirstRunFlow_(showFirstRunFlow, currentView_)]]">
      <div id="first-run-flow">
        <div id="first-run-title">[[i18n('firstRunFlowTitle')]]</div>
        <div id="first-run-text">
          <span>[[i18n('firstRunFlowText')]]</span>
          <a href="[[firstRunFlowLearnMoreUrl]]" class="first-run-learn-more"
              target="_blank">
            [[i18n('learnMoreText')]]
          </a>
        </div>
        <div id="first-run-flow-cloud-pref"
            hidden$="[[!showFirstRunFlowCloudPref]]">
          <cr-checkbox checked id="first-run-cloud-checkbox">
            <span>[[getFirstRunFlowCloudPrefText_()]]</span>
            <a href="[[firstRunFlowCloudPrefLearnMoreUrl]]"
                class="first-run-learn-more" target="_blank">
              [[i18n('learnMoreText')]]
            </a>
          </cr-checkbox>
        </div>
        <div id="first-run-button-container">
          <paper-button id="first-run-button" class="button"
              on-tap="acknowledgeFirstRunFlow_">
            <span>[[i18n('firstRunFlowButtonText')]]</span>
          </paper-button>
        </div>
      </div>
    </template>
    <media-router-header id="container-header"
        class$="[[currentView_]]" view="[[currentView_]]"
        heading-text="[[computeHeaderText_(currentView_, headerText)]]"
        arrow-drop-icon-disabled="[[computeIsLaunching_(currentLaunchingSinkId_)]]"
        tooltip="[[computeHeaderTooltip_(currentView_, headerTextTooltip)]]"
        on-back-click="showSinkList_">
    </media-router-header>
    <div id="content">
      <template is="dom-if" if="[[!computeCastModeListHidden_(currentView_)]]">
        <iron-selector id="cast-mode-list" role="presentation"
            selectable=".selectable-item"
            selected="{{selectedCastModeMenuItem_}}">
          <template is="dom-repeat" id="presentationCastModeList"
              items="[[computePresentationCastModeList_(castModeList)]]">
            <button class="selectable-item" on-click="onCastModeClick_">
              <iron-icon class="cast-mode-icon"
                  icon="[[computeCastModeIcon_(item)]]">
              </iron-icon>
              <div><span>[[item.host]]</span></div>
            </button>
          </template>
          <div id="share-screen-text" class="subheading-text"
              hidden$="[[computeShareScreenSubheadingHidden_(castModeList)]]">
            <span>[[i18n('shareYourScreenSubheadingText')]]</span>
          </div>
          <template is="dom-repeat" id="shareScreenCastModeList"
              items="[[computeShareScreenCastModeList_(castModeList)]]">
            <button class="selectable-item" on-click="onCastModeClick_">
              <iron-icon class="cast-mode-icon"
                  icon="[[computeCastModeIcon_(item)]]">
              </iron-icon>
              <div><span>[[item.description]]</span></div>
            </button>
          </template>
          <div id="cast-local-media-text" class="subheading-text"
              hidden$="[[computeLocalMediaSubheadingHidden_(castModeList)]]">
            <span>[[i18n('castLocalMediaSubheadingText')]]</span>
          </div>
          <template is="dom-repeat" id="localMediaCastModeList"
              items="[[computeLocalMediaCastModeList_(castModeList)]]">
            <button class="selectable-item" on-click="onCastModeClick_">
              <iron-icon class="cast-mode-icon"
                  icon="[[computeCastModeIcon_(item)]]">
              </iron-icon>
              <div><span>[[item.description]]</span></div>
            </button>
          </template>
        </iron-selector>
      </template>
      <template is="dom-if"
          if="[[!computeRouteDetailsHidden_(currentView_, issue)]]">
        <route-details id="route-details" route="[[currentRoute_]]"
            shown-cast-mode-value="[[shownCastModeValue_]]"
            sink="[[getSinkForRoute_(currentRoute_)]]"
            is-any-sink-currently-launching=
                "[[computeIsLaunching_(currentLaunchingSinkId_)]]"
            on-change-route-source-click="onChangeRouteSourceClick_"
            on-close-route="onCloseRoute_">
        </route-details>
      </template>
      <div id="sink-list-view"
          hidden$="[[computeSinkListViewHidden_(currentView_, issue)]]">
        <div id="device-missing"
             hidden$="[[computeDeviceMissingHidden_(sinksToShow_)]]">
          <paper-spinner-lite id="searching-devices-spinner" active
              hidden$="[[computeSpinnerHidden_(justOpened_)]]">
          </paper-spinner-lite>
          <a href="[[deviceMissingUrl]]" target="_blank"
              hidden$="[[!computeSpinnerHidden_(justOpened_)]]">
            [[i18n('destinationMissingText')]]
          </a>
        </div>
        <template is="dom-if" if="[[!computeSinkListHidden_(sinksToShow_)]]">
          <div id="sink-list" hidden$="[[hideSinkListForAnimation_]]">
            <iron-selector id="sink-list-paper-menu" role="presentation"
                selectable=".selectable-item">
              <template is="dom-repeat" id="sinkList" items="[[sinksToShow_]]">
                <button class="selectable-item" on-click="onSinkClick_">
                  <div class="sink-content">
                    <div>
                      <iron-icon icon="[[computeSinkIcon_(item)]]"
                          hidden$="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.id)]]"
                          class$="[[computeSinkIconClass_(item.id, sinkToRouteMap_)]]">
                      </iron-icon>
                      <template is="dom-if"
                          if="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.id)]]">
                        <paper-spinner-lite class="sink-icon" active>
                        </paper-spinner-lite>
                      </template>
                    </div>
                    <div>
                      <div class="sink-text">
                        <span dir="auto" class="sink-name" title="[[item.name]]">
                          [[item.name]]
                        </span>
                        <template is="dom-if"
                            if="[[!computeSinkDomainHidden_(item)]]">
                          <span class="sink-domain" title="[[item.domain]]">
                            [[item.domain]]
                          </span>
                        </template>
                      </div>
                      <template is="dom-if"
                          if="[[!computeSinkSubtextHidden_(item, sinkToRouteMap_)]]">
                        <div class="sink-text sink-subtext">
                          <span>[[computeSinkSubtext_(item, sinkToRouteMap_)]]</span>
                        </div>
                      </template>
                    </div>
                  </div>
                </button>
              </template>
            </iron-selector>
          </div>
        </template>
        <template is="dom-if" if="[[searchEnabled_]]">
          <div id="sink-search">
            <div class="sink-content">
              <paper-icon-button id="sink-search-icon"
                  icon="media-router:search" on-tap="searchButtonClick_"
                  title="[[i18n('searchButtonTitle')]]">
              </paper-icon-button>
              <cr-input id="sink-search-input" value="{{searchInputText_}}"
                  placeholder="[[i18n('searchInputLabel')]]">
              </cr-input>
            </div>
          </div>
        </template>
        <template is="dom-if" if="[[!isSearchListHidden_]]">
          <div id="search-results-container">
            <div id="no-search-matches"
                hidden$="[[computeNoMatchesHidden_(searchResultsToShow_, isSearchListHidden_)]]">
              <span>[[i18n('searchNoMatchesText')]]</span>
            </div>
            <div id="search-results"
                hidden$="[[computeSearchResultsHidden_(searchResultsToShow_, isSearchListHidden_)]]">
              <iron-selector id="search-results-paper-menu" selected="0"
                  role="presentation" selectable=".selectable-item">
                <template is="dom-repeat" id="searchResults"
                    items="[[searchResultsToShow_]]">
                  <button class="search-item selectable-item"
                      on-click="onSinkClick_">
                    <div class="sink-content">
                      <div>
                        <iron-icon icon="[[computeSinkIcon_(item.sinkItem)]]"
                            hidden$="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.sinkItem.id)]]"
                            class$="[[computeSinkIconClass_(item.sinkItem.id, sinkToRouteMap_)]]">
                        </iron-icon>
                        <template is="dom-if"
                            if="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.sinkItem.id)]]">
                          <paper-spinner-lite class="sink-icon" active>
                          </paper-spinner-lite>
                        </template>
                      </div>
                      <div>
                        <div class="sink-text">
                          <media-router-search-highlighter class="sink-name"
                              data="[[computeSinkMatchingText_(item)]]"
                              title="[[item.sinkItem.name]]">
                          </media-router-search-highlighter>
                          <template is="dom-if"
                              if="[[!computeSinkDomainHidden_(item.sinkItem)]]">
                            <span class="sink-domain" title="[[item.sinkItem.domain]]">
                              [[item.sinkItem.domain]]
                            </span>
                          </template>
                        </div>
                        <template is="dom-if"
                            if="[[!computeSinkSubtextHidden_(item.sinkItem, sinkToRouteMap_)]]">
                          <div class="sink-text sink-subtext">
                            <span>
                              [[computeSinkSubtext_(item.sinkItem, sinkToRouteMap_)]]
                            </span>
                          </div>
                        </template>
                      </div>
                    </div>
                  </button>
                </template>
              </iron-selector>
            </div>
          </div>
        </template>
      </div>
      <template is="dom-if"
          if="[[computeIssueBannerShown_(currentView_, issue)]]">
        <issue-banner id="issue-banner" issue="[[issue]]"
            class$="[[computeIssueBannerClass_(issue)]]">
        </issue-banner>
      </template>
    </div>
  </template>
  <script src="pseudo_sink_search_state.js"></script>
  <script src="media_router_container.js"></script>
</dom-module>
/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.active-sink {
  color: var(--paper-blue-700);
}

.cast-mode-icon,
.sink-icon {
  height: var(--non-navigation-icon-size);
  padding-inline-end: 12px;
  padding-inline-start: var(--dialog-padding-start);
  width: var(--non-navigation-icon-size);
}

#container-header {
  position: fixed;
  width: 100%;
}

#content {
  position: relative;
}

#device-missing {
  align-items: center;
  background-color: white;
  display: flex;
  justify-content: center;
  padding: 60px 0;
}

#device-missing a {
  color: var(--paper-blue-700);
  margin: 8px 0;
  text-align: center;
  text-decoration: none;
}

#first-run-button {
  background-color: white;
}

#first-run-button-container {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
}

#first-run-cloud-checkbox,
#first-run-flow-cloud-pref,
#first-run-text {
  font-size: 1.0em;
  line-height: 1.5em;
}

#first-run-cloud-checkbox,
#first-run-text,
#first-run-title {
  color: white;
  padding-bottom: 24px;
}

#first-run-cloud-checkbox::shadow #checkboxLabel {
  padding-inline-start: var(-dialog-padding-start);
}

#first-run-flow {
  background-color: var(--paper-blue-700);
  box-sizing: border-box;
  padding: 24px 16px 4px 16px;
  position: fixed;
  width: 100%;
}

#first-run-flow a {
  color: white;
  text-decoration: none;
}

#first-run-flow-cloud-pref {
  color: white;
  display: flex;
}

.first-run-learn-more {
  font-weight: bold;
  text-transform: uppercase;
}

#first-run-title {
  font-size: 1.25em;
}

#issue-banner {
  width: 100%;
}

#issue-banner.non-blocking {
  bottom: 0;
  display: block;
  margin-top: 0;
}

#no-search-matches {
  color: rgb(112, 112, 112);
  display: block;
  font-size: 1.2 em;
  padding-bottom: 20px;
  padding-top: 20px;
  text-align: center;
}

cr-checkbox {
  --cr-checkbox-checked-box-color: white;
  --cr-checkbox-label-color: white;
  --cr-checkbox-mark-color: var(--paper-blue-700);
  --cr-checkbox-ripple-checked-color: white;
  --cr-checkbox-ripple-unchecked-color: white;
  --cr-checkbox-unchecked-box-color: white;
  --cr-checkbox-ripple-opacity: 0.25;
}

.selectable-item {
  -webkit-appearance: none;
  align-items: center;
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  font-family: inherit;
  font-size: 1.0em;
  line-height: 0;
  min-height: 0;
  outline: 0;
  padding: 12px 0;
  text-align: initial;
  width: 100%;
}

.selectable-item:hover,
.selectable-item:focus {
  background-color: rgb(238, 238, 238);
  border: 0;
}

.selectable-item.iron-selected {
  font-weight: bold;
}

iron-selector {
  color: rgba(0, 0, 0, 0.87);
  display: block;
  overflow-x: hidden;
  overflow-y: auto;
  padding-bottom: 0;
  padding-top: 4px;
  user-select: none;
}

iron-selector#cast-mode-list {
  padding-bottom: 12px;
  padding-top: 4px;
}

#search-input-container {
  flex-grow: 1;
}

#search-results {
  overflow-x: hidden;
  overflow-y: auto;
}

#search-results-container {
  bottom: 0;
  left: 0;
  overflow-x: hidden;
  overflow-y: hidden;
  position: absolute;
  right: 0;
  top: 100%;
}

#searching-devices-spinner {
  height: 30px;
  width: 30px;
}

.subheading-text {
  color: var(--paper-grey-600);
  cursor: default;
  font-weight: normal;
  padding-bottom: 4px;
  padding-inline-start: var(--dialog-padding-start);
  padding-top: 12px;
}

#share-screen-text::after {
  background-color: white;
  font-weight: normal;
}

.sink-content {
  display: flex;
  flex-direction: row;
  font-weight: normal;
}

.sink-domain {
  color: var(--paper-grey-600);
  padding-inline-start: 6px;
  /* TODO(crbug/589697): Handle overflow of very long domain names. */
}

#sink-list {
  overflow-x: hidden;
  overflow-y: auto;
}

#sink-list-view {
  margin-bottom: 12px;
  position: relative;
}

.sink-name {
  min-width: 10%;
}

#search-input-container {
  flex-grow: 1;
}

#sink-search {
  padding-bottom: 0;
  padding-top: 4px;
  position: absolute;
  top: 100%;
  width: 100%;
  z-index: 1;
}

/* Separate icon class is a consequence of box-sizing: border-box set by
 * paper-icon-button. This should achieve the same dimensions as .sink-icon. */
#sink-search-icon {
  margin-inline-start: 4px;
  padding-inline-end: 12px;
  padding-inline-start: 12px;
}

#sink-search-input {
  --cr-input-background-color: white;
  --cr-input-container: {
    border-radius: 0;
  }
  --cr-input-error-display: none;
  --cr-input-input: {
    border-bottom: 1px solid var(--paper-grey-800);
  }
  --cr-input-padding-end: 0;
  --cr-input-padding-start: 0;
  --cr-input-padding-bottom: 2px;
  --cr-input-padding-top: 2px;
  align-self: center;
  flex-grow: 1;
  font-size: 12px;
  margin-inline-end: 31px;
}

.sink-subtext {
  color: var(--paper-grey-600);
  padding-top: 8px;
}

.sink-text {
  flex-flow: row nowrap;
  line-height: normal;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 275px;
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * This Polymer element contains the entire media router interface. It handles
 * hiding and showing specific components.
 * @implements {MediaRouterContainerInterface}
 */
Polymer({
  is: 'media-router-container',

  properties: {
    /**
     * The list of available sinks.
     * @type {!Array<!media_router.Sink>}
     */
    allSinks: {
      type: Array,
      value: [],
      observer: 'reindexSinksAndRebuildSinksToShow_',
    },

    /**
     * The last promise in a chain that will be fulfilled when the current
     * animation has finished. It does not return a value; it is strictly a
     * synchronization mechanism.
     * @private {!Promise}
     */
    animationPromise_: {
      type: Object,
      value: function() {
        return Promise.resolve();
      },
    },

    /**
     * The list of CastModes to show.
     * @type {!Array<!media_router.CastMode>|undefined}
     */
    castModeList: {
      type: Array,
      observer: 'checkCurrentCastMode_',
    },

    /**
     * The ID of the Sink currently being launched.
     * @private {string}
     * TODO(crbug.com/616604): Use per-sink route creation state.
     */
    currentLaunchingSinkId_: {
      type: String,
      value: '',
    },

    /**
     * The current route.
     * @private {?media_router.Route|undefined}
     */
    currentRoute_: {
      type: Object,
    },

    /**
     * The current view to be shown.
     * @private {?media_router.MediaRouterView|undefined}
     */
    currentView_: {
      type: String,
      observer: 'currentViewChanged_',
    },

    /**
     * The URL to open when the device missing link is clicked.
     * @type {string|undefined}
     */
    deviceMissingUrl: {
      type: String,
    },

    /**
     * The height of the dialog.
     * @private {number}
     */
    dialogHeight_: {
      type: Number,
      value: 330,
    },

    /**
     * The time |this| element calls ready().
     * @private {number|undefined}
     */
    elementReadyTimeMs_: {
      type: Number,
    },

    /**
     * Animation player used for running filter transition animations.
     * @private {?Animation}
     */
    filterTransitionPlayer_: {
      type: Object,
      value: null,
    },

    /**
     * The URL to open when the cloud services pref learn more link is clicked.
     * @type {string|undefined}
     */
    firstRunFlowCloudPrefLearnMoreUrl: {
      type: String,
    },

    /**
     * The URL to open when the first run flow learn more link is clicked.
     * @type {string|undefined}
     */
    firstRunFlowLearnMoreUrl: {
      type: String,
    },

    /**
     * The header text for the sink list.
     * @type {string|undefined}
     */
    headerText: {
      type: String,
    },

    /**
     * The header text tooltip. This would be descriptive of the
     * source origin, whether a host name, tab URL, etc.
     * @type {string|undefined}
     */
    headerTextTooltip: {
      type: String,
    },

    /**
     * An animation player that is used for running dialog height adjustments.
     * @private {?Animation}
     */
    heightAdjustmentPlayer_: {
      type: Object,
      value: null,
    },

    /**
     * Whether the sink list is being hidden for animation purposes.
     * @private {boolean}
     */
    hideSinkListForAnimation_: {
      type: Boolean,
      value: false,
    },

    /**
     * Records whether the search input is focused when a window blur event is
     * received. This is used to handle search focus edge cases. See
     * |setSearchFocusHandlers_| for details.
     * @private {boolean}
     */
    isSearchFocusedOnWindowBlur_: {
      type: Boolean,
      value: false,
    },

    /**
     * Whether the search list is currently hidden.
     * @private {boolean}
     */
    isSearchListHidden_: {
      type: Boolean,
      value: true,
    },

    /**
     * The issue to show.
     * @type {?media_router.Issue}
     */
    issue: {
      type: Object,
      value: null,
      observer: 'maybeShowIssueView_',
    },

    /**
     * Whether the MR UI was just opened.
     * @private {boolean}
     */
    justOpened_: {
      type: Boolean,
      value: true,
    },

    /**
     * Whether the user's mouse is positioned over the dialog.
     * @private {boolean|undefined}
     */
    mouseIsPositionedOverDialog_: {
      type: Boolean,
    },

    /**
     * The ID of the route that is currently being created. This is set when
     * route creation is resolved but not ready for its controls to be
     * displayed.
     * @private {string|undefined}
     */
    pendingCreatedRouteId_: {
      type: String,
    },

    /**
     * The time the sink list was shown and populated with at least one sink.
     * This is reset whenever the user switches views or there are no sinks
     * available for display.
     * @private {number}
     */
    populatedSinkListSeenTimeMs_: {
      type: Number,
      value: -1,
    },

    /**
     * Pseudo sinks from MRPs that represent their ability to accept sink search
     * requests.
     * @private {!Array<!media_router.Sink>}
     */
    pseudoSinks_: {
      type: Array,
      value: [],
    },

    /**
     * Helps manage the state of creating a sink and a route from a pseudo sink.
     * @private {PseudoSinkSearchState|undefined}
     */
    pseudoSinkSearchState_: {
      type: Object,
    },

    /**
     * Whether the next character input should cause a filter action metric to
     * be sent.
     * @type {boolean}
     * @private
     */
    reportFilterOnInput_: {
      type: Boolean,
      value: false,
    },

    /**
     * The list of current routes.
     * @type {!Array<!media_router.Route>|undefined}
     */
    routeList: {
      type: Array,
      observer: 'rebuildRouteMaps_',
    },

    /**
     * Maps media_router.Route.id to corresponding media_router.Route.
     * @private {!Object<!string, !media_router.Route>|undefined}
     */
    routeMap_: {
      type: Object,
    },

    /**
     * Whether the search feature is enabled and we should show the search
     * input.
     * @private {boolean}
     */
    searchEnabled_: {
      type: Boolean,
      value: false,
      observer: 'searchEnabledChanged_',
    },

    /**
     * Search text entered by the user into the sink search input.
     * @private {string}
     */
    searchInputText_: {
      type: String,
      value: '',
      observer: 'searchInputTextChanged_',
    },

    /**
     * Sinks to display that match |searchInputText_|.
     * @private {!Array<!{sinkItem: !media_router.Sink,
     *                    substrings: Array<!Array<number>>}>|undefined}
     */
    searchResultsToShow_: {
      type: Array,
    },

    /**
     * The selected cast mode menu item. The item with this index is bolded in
     * the cast mode menu.
     * @private {number|undefined}
     */
    selectedCastModeMenuItem_: {
      type: Number,
      observer: 'updateSelectedCastModeMenuItem_',
    },

    /**
     * Whether to show the user domain of sinks associated with identity.
     * @type {boolean|undefined}
     */
    showDomain: {
      type: Boolean,
    },

    /**
     * Whether to show the first run flow.
     * @type {boolean|undefined}
     */
    showFirstRunFlow: {
      type: Boolean,
      observer: 'updateElementPositioning_',
    },

    /**
     * Whether to show the cloud preference setting in the first run flow.
     * @type {boolean|undefined}
     */
    showFirstRunFlowCloudPref: {
      type: Boolean,
    },

    /**
     * The cast mode shown to the user. Initially populated within
     * |rebuildSinksToShow_()|.
     * This value may be changed in one of the following ways:
     * 1) The user explicitly selected a cast mode.
     * 2) The user selected cast mode is no longer available for the associated
     *    WebContents. In this case, the container will reset to auto mode. Note
     *    that |userHasSelectedCastMode_| will switch back to false.
     * 3) The sink list changed, and the user had not explicitly selected a cast
     *    mode. If the sinks support exactly 1 cast mode, the container will
     *    switch to that cast mode. Otherwise, the container will reset to auto
     *    mode.
     * @private {number}
     */
    shownCastModeValue_: Number,

    /**
     * Max height for the sink list.
     * @private {number}
     */
    sinkListMaxHeight_: {
      type: Number,
      value: 0,
    },

    /**
     * Maps media_router.Sink.id to corresponding media_router.Sink.
     * @private {!Object<!string, !media_router.Sink>|undefined}
     */
    sinkMap_: {
      type: Object,
    },

    /**
     * Maps media_router.Sink.id to corresponding media_router.Route.
     * @private {!Object<!string, !media_router.Route>}
     */
    sinkToRouteMap_: {
      type: Object,
      value: {},
    },

    /**
     * Sinks to show for the currently selected cast mode.
     * @private {!Array<!media_router.Sink>|undefined}
     */
    sinksToShow_: {
      type: Array,
      observer: 'updateElementPositioning_',
    },

    /**
     * Whether the user has explicitly selected a cast mode.
     * @private {boolean}
     */
    userHasSelectedCastMode_: {
      type: Boolean,
      value: false,
    },

    /**
     * Whether the user has already taken an action.
     * @type {boolean}
     */
    userHasTakenInitialAction_: {
      type: Boolean,
      value: false,
    },
  },

  behaviors: [
    I18nBehavior,
  ],

  observers: [
    'maybeUpdateStartSinkDisplayStartTime_(currentView_, sinksToShow_)',
  ],

  ready: function() {
    this.elementReadyTimeMs_ = window.performance.now();
    this.showSinkList_();

    Polymer.RenderStatus.afterNextRender(this, function() {
      // Import the elements that aren't needed at startup. This reduces
      // initial load time. Delayed loading interferes with getting the
      // offsetHeight of the first-run-flow element in updateElementPositioning_
      // though, so we also make sure it is called after the last load.
      var that = this;
      var loadsRemaining = 3;
      var onload = function() {
        loadsRemaining--;
        if (loadsRemaining > 0) {
          return;
        }
        that.updateElementPositioning_();
        if (that.currentView_ == media_router.MediaRouterView.SINK_LIST) {
          that.putSearchAtBottom_();
        }
      };
      this.importHref(
          'chrome://resources/polymer/v1_0/neon-animation/' +
              'web-animations.html',
          onload);
      this.importHref(
          this.resolveUrl('../issue_banner/issue_banner.html'), onload);
      this.importHref(
          this.resolveUrl(
              '../media_router_search_highlighter/' +
              'media_router_search_highlighter.html'),
          onload);

      // If this is not on a Mac platform, remove the placeholder. See
      // onFocus_() for more details. ready() is only called once, so no need
      // to check if the placeholder exist before removing.
      if (!cr.isMac) {
        this.$$('#focus-placeholder').remove();
      }

      document.addEventListener('keydown', this.onKeydown_.bind(this), true);
      this.listen(this, 'focus', 'onFocus_');
      this.listen(this, 'header-height-changed', 'updateElementPositioning_');
      this.listen(this, 'header-or-arrow-click', 'toggleCastModeHidden_');
      this.listen(this, 'mouseleave', 'onMouseLeave_');
      this.listen(this, 'mouseenter', 'onMouseEnter_');

      // Turn off the spinner after 3 seconds, then report the current number of
      // sinks.
      this.async(function() {
        this.justOpened_ = false;
        // |pseudoSinks_| does not contain pseudo sinks without a domain, so it
        // cannot be used for calculating the number of real sinks.
        var realSinks = this.allSinks.filter(function(sink) {
          return !sink.isPseudoSink;
        });
        this.fire('report-sink-count', {
          sinkCount: realSinks.length,
        });
      }, 3000 /* 3 seconds */);

      // For Mac platforms, request data after a short delay after load. This
      // appears to speed up initial data load time on Mac.
      if (cr.isMac) {
        this.async(function() {
          this.fire('request-initial-data');
        }, 25 /* 0.025 seconds */);
      }
    });
  },

  /**
   * Fires an acknowledge-first-run-flow event and hides the first run flow.
   * This is call when the first run flow button is clicked.
   *
   * @private
   */
  acknowledgeFirstRunFlow_: function() {
    // Only set |userOptedIntoCloudServices| if the user was shown the cloud
    // services preferences option.
    var userOptedIntoCloudServices = this.showFirstRunFlowCloudPref ?
        this.$$('#first-run-cloud-checkbox').checked :
        undefined;
    this.fire('acknowledge-first-run-flow', {
      optedIntoCloudServices: userOptedIntoCloudServices,
    });

    this.showFirstRunFlow = false;
    this.showFirstRunFlowCloudPref = false;
  },

  /**
   * Fires a 'report-initial-action' event when the user takes their first
   * action after the dialog opens. Also fires a 'report-initial-action-close'
   * event if that initial action is to close the dialog.
   * @param {!media_router.MediaRouterUserAction} initialAction
   */
  maybeReportUserFirstAction: function(initialAction) {
    if (this.userHasTakenInitialAction_) {
      return;
    }

    this.fire('report-initial-action', {
      action: initialAction,
    });

    if (initialAction == media_router.MediaRouterUserAction.CLOSE) {
      var timeToClose = window.performance.now() - this.elementReadyTimeMs_;
      this.fire('report-initial-action-close', {
        timeMs: timeToClose,
      });
    }

    this.userHasTakenInitialAction_ = true;
  },

  get header() {
    return this.$['container-header'];
  },

  /**
   * Calls all the functions to set the UI to a given cast mode.
   * @param {!media_router.CastMode} castMode The cast mode to set things to.
   * @private
   */
  castModeSelected_(castMode) {
    this.selectCastMode(castMode.type);
    this.fire('cast-mode-selected', {castModeType: castMode.type});
    this.showSinkList_();
    this.maybeReportUserFirstAction(
        media_router.MediaRouterUserAction.CHANGE_MODE);
  },

  /**
   * Checks that the currently selected cast mode is still in the
   * updated list of available cast modes. If not, then update the selected
   * cast mode to the first available cast mode on the list.
   */
  checkCurrentCastMode_: function() {
    if (!this.castModeList.length) {
      return;
    }

    // If there is a forced mode make sure it is shown.
    if (this.findForcedCastMode_()) {
      this.rebuildSinksToShow_();
    }

    // If we are currently showing auto mode, then nothing needs to be done.
    // Otherwise, if the cast mode currently shown no longer exists (regardless
    // of whether it was selected by user), then switch back to auto cast mode.
    if (this.shownCastModeValue_ != media_router.CastModeType.AUTO &&
        !this.findCastModeByType_(this.shownCastModeValue_)) {
      this.setShownCastMode_(media_router.AUTO_CAST_MODE);
      this.rebuildSinksToShow_();
    }
  },

  /**
   * Compares two search match objects for sorting. Earlier and longer matches
   * are prioritized.
   *
   * @param {!{sinkItem: !media_router.Sink,
   *           substrings: Array<!Array<number>>}} resultA
   * Parameters in |resultA|:
   *   sinkItem - sink object.
   *   substrings - start-end index pairs of substring matches.
   * @param {!{sinkItem: !media_router.Sink,
   *           substrings: Array<!Array<number>>}} resultB
   * Parameters in |resultB|:
   *   sinkItem - sink object.
   *   substrings - start-end index pairs of substring matches.
   * @return {number} -1 if |resultA| should come before |resultB|, 1 if
   *     |resultB| should come before |resultA|, and 0 if they are considered
   *     equal.
   */
  compareSearchMatches_: function(resultA, resultB) {
    var substringsA = resultA.substrings;
    var substringsB = resultB.substrings;
    var numberSubstringsA = substringsA.length;
    var numberSubstringsB = substringsB.length;

    if (numberSubstringsA == 0 && numberSubstringsB == 0) {
      return 0;
    } else if (numberSubstringsA == 0) {
      return 1;
    } else if (numberSubstringsB == 0) {
      return -1;
    }

    var loopMax = Math.min(numberSubstringsA, numberSubstringsB);
    for (var i = 0; i < loopMax; ++i) {
      var [matchStartA, matchEndA] = substringsA[i];
      var [matchStartB, matchEndB] = substringsB[i];

      if (matchStartA < matchStartB) {
        return -1;
      } else if (matchStartA > matchStartB) {
        return 1;
      }

      if (matchEndA > matchEndB) {
        return -1;
      } else if (matchEndA < matchEndB) {
        return 1;
      }
    }

    if (numberSubstringsA > numberSubstringsB) {
      return -1;
    } else if (numberSubstringsA < numberSubstringsB) {
      return 1;
    }
    return 0;
  },

  /**
   * Returns a duration in ms from a distance in pixels using a default speed of
   * 1000 pixels per second.
   * @param {number} distance Number of pixels that will be traveled.
   * @private
   */
  computeAnimationDuration_: function(distance) {
    // The duration of the animation can be found by abs(distance)/speed, where
    // speed is fixed at 1000 pixels per second, or 1 pixel per millisecond.
    return Math.abs(distance);
  },

  /**
   * If there is a forced cast mode, returns that cast mode.  If |allSinks|
   * supports only a single cast mode, returns that cast mode.  Otherwise,
   * returns AUTO_MODE. Only called if |userHasSelectedCastMode_| is |false|.
   *
   * @return {!media_router.CastMode} The single cast mode supported by
   *                                  |allSinks|, or AUTO_MODE.
   */
  computeCastMode_: function() {
    /** @const */ var forcedMode = this.findForcedCastMode_();
    if (forcedMode) {
      return forcedMode;
    }

    var allCastModes = this.allSinks.reduce(function(castModesSoFar, sink) {
      // Ignore pseudo sinks in the cast mode computation.
      return castModesSoFar | (sink.isPseudoSink ? 0 : sink.castModes);
    }, 0);

    // This checks whether |castModes| does not consist of exactly 1 cast mode.
    if (!allCastModes || allCastModes & (allCastModes - 1)) {
      return media_router.AUTO_CAST_MODE;
    }

    var castMode = this.findCastModeByType_(allCastModes);
    if (castMode) {
      return castMode;
    }

    console.error('Cast mode ' + allCastModes + ' not in castModeList');
    return media_router.AUTO_CAST_MODE;
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @return {boolean} Whether or not to hide the cast mode list.
   * @private
   */
  computeCastModeListHidden_: function(view) {
    return view != media_router.MediaRouterView.CAST_MODE_LIST;
  },

  /**
   * @param {!media_router.CastMode} castMode The cast mode to determine an
   *     icon for.
   * @return {string} The icon to use.
   * @private
   */
  computeCastModeIcon_: function(castMode) {
    switch (castMode.type) {
      case media_router.CastModeType.PRESENTATION:
        return 'media-router:web';
      case media_router.CastModeType.TAB_MIRROR:
        return 'media-router:tab';
      case media_router.CastModeType.DESKTOP_MIRROR:
        return 'media-router:laptop';
      case media_router.CastModeType.LOCAL_FILE:
        return 'media-router:folder';
      default:
        return '';
    }
  },

  /**
   * @param {!Array<!media_router.CastMode>} castModeList The current list of
   *     cast modes.
   * @return {!Array<!media_router.CastMode>} The list of PRESENTATION cast
   *     modes.
   * @private
   */
  computePresentationCastModeList_: function(castModeList) {
    return castModeList.filter(function(mode) {
      return mode.type == media_router.CastModeType.PRESENTATION;
    });
  },

  /**
   * @param {!Array<!media_router.Sink>} sinksToShow The list of sinks.
   * @return {boolean} Whether or not to hide the 'devices missing' message.
   * @private
   */
  computeDeviceMissingHidden_: function(sinksToShow) {
    return sinksToShow.length != 0;
  },

  /**
   * @param {?Element} element Element to compute padding for.
   * @return {number} Computes the amount of vertical padding (top + bottom) on
   *     |element|.
   * @private
   */
  computeElementVerticalPadding_: function(element) {
    var paddingBottom, paddingTop;
    [paddingBottom, paddingTop] = this.getElementVerticalPadding_(element);
    return paddingBottom + paddingTop;
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @param {?media_router.Issue} issue The current issue.
   * @return {boolean} Whether or not to hide the header.
   * @private
   */
  computeHeaderHidden_: function(view, issue) {
    return view == media_router.MediaRouterView.ROUTE_DETAILS ||
        (view == media_router.MediaRouterView.SINK_LIST && !!issue &&
         issue.isBlocking);
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @param {string} headerText The header text for the sink list.
   * @return {string|undefined} The text for the header.
   * @private
   */
  computeHeaderText_: function(view, headerText) {
    switch (view) {
      case media_router.MediaRouterView.CAST_MODE_LIST:
        return this.i18n('selectCastModeHeaderText');
      case media_router.MediaRouterView.ISSUE:
        return this.i18n('issueHeaderText');
      case media_router.MediaRouterView.ROUTE_DETAILS:
        return this.currentRoute_ && this.sinkMap_[this.currentRoute_.sinkId] ?
            this.sinkMap_[this.currentRoute_.sinkId].name :
            '';
      case media_router.MediaRouterView.SINK_LIST:
      case media_router.MediaRouterView.FILTER:
        return this.headerText;
      default:
        return '';
    }
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @param {string} headerTooltip The tooltip for the header for the sink
   *     list.
   * @return {string} The tooltip for the header.
   * @private
   */
  computeHeaderTooltip_: function(view, headerTooltip) {
    return view == media_router.MediaRouterView.SINK_LIST ? headerTooltip : '';
  },

  /**
   * @param {string} currentLaunchingSinkId ID of the sink that is currently
   *     launching, or empty string if none exists.
   * @private
   */
  computeIsLaunching_: function(currentLaunchingSinkId) {
    return currentLaunchingSinkId != '';
  },

  /**
   * @param {?media_router.Issue} issue The current issue.
   * @return {string} The class for the issue banner.
   * @private
   */
  computeIssueBannerClass_: function(issue) {
    return !!issue && !issue.isBlocking ? 'non-blocking' : '';
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @param {?media_router.Issue} issue The current issue.
   * @return {boolean} Whether or not to show the issue banner.
   * @private
   */
  computeIssueBannerShown_: function(view, issue) {
    return !!issue &&
        (view == media_router.MediaRouterView.CAST_MODE_LIST ||
         view == media_router.MediaRouterView.SINK_LIST ||
         view == media_router.MediaRouterView.FILTER ||
         view == media_router.MediaRouterView.ISSUE);
  },

  /**
   * @param {!Array<!{sinkItem: !media_router.Sink,
   *                  substrings: Array<!Array<number>>}>} searchResultsToShow
   *     The sinks currently matching the search text.
   * @param {boolean} isSearchListHidden Whether the search list is hidden.
   * @return {boolean} Whether or not the 'no matches' message is hidden.
   * @private
   */
  computeNoMatchesHidden_: function(searchResultsToShow, isSearchListHidden) {
    return isSearchListHidden || this.searchInputText_.length == 0 ||
        searchResultsToShow.length != 0;
  },

  /**
   * @param {!Array<!media_router.CastMode>} castModeList The current list of
   *     cast modes.
   * @return {!Array<!media_router.CastMode>} The list of non-PRESENTATION cast
   *     modes. Also excludes LOCAL_FILE.
   * @private
   */
  computeShareScreenCastModeList_: function(castModeList) {
    return castModeList.filter(function(mode) {
      return mode.type == media_router.CastModeType.DESKTOP_MIRROR ||
          mode.type == media_router.CastModeType.TAB_MIRROR;
    });
  },

  /**
   * @param {!Array<!media_router.CastMode>} castModeList The current list of
   *     cast modes.
   * @return {!Array<!media_router.CastMode>} The list of local media cast
   *     modes.
   * @private
   */
  computeLocalMediaCastModeList_: function(castModeList) {
    return castModeList.filter(function(mode) {
      return mode.type == media_router.CastModeType.LOCAL_FILE;
    });
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @param {?media_router.Issue} issue The current issue.
   * @return {boolean} Whether or not to hide the route details.
   * @private
   */
  computeRouteDetailsHidden_: function(view, issue) {
    return view != media_router.MediaRouterView.ROUTE_DETAILS ||
        (!!issue && issue.isBlocking);
  },

  /**
   * Computes an array of substring indices that mark where substrings of
   * |searchString| occur in |sinkName|.
   *
   * @param {string} searchString Search string entered by user.
   * @param {string} sinkName Sink name being filtered.
   * @return {Array<!Array<number>>} Array of substring start-end (inclusive)
   *     index pairs if every character in |searchString| was matched, in order,
   *     in |sinkName|. Otherwise it returns null.
   * @private
   */
  computeSearchMatches_: function(searchString, sinkName) {
    var i = 0;
    var matchStart = -1;
    var matchEnd = -1;
    var matchPairs = [];
    for (var j = 0; i < searchString.length && j < sinkName.length; ++j) {
      if (searchString[i].toLocaleLowerCase() ==
          sinkName[j].toLocaleLowerCase()) {
        if (matchStart == -1) {
          matchStart = j;
        }
        ++i;
      } else if (matchStart != -1) {
        matchEnd = j - 1;
        matchPairs.push([matchStart, matchEnd]);
        matchStart = -1;
      }
    }
    if (matchStart != -1) {
      matchEnd = j - 1;
      matchPairs.push([matchStart, matchEnd]);
    }
    return (i == searchString.length) ? matchPairs : null;
  },

  /**
   * Computes whether the search results list should be hidden.
   * @param {!Array<!{sinkItem: !media_router.Sink,
   *                  substrings: Array<!Array<number>>}>} searchResultsToShow
   *     The sinks currently matching the search text.
   * @param {boolean} isSearchListHidden Whether the search list is hidden.
   * @return {boolean} Whether the search results list should be hidden.
   * @private
   */
  computeSearchResultsHidden_: function(
      searchResultsToShow, isSearchListHidden) {
    return isSearchListHidden || searchResultsToShow.length == 0;
  },

  /**
   * @param {!Array<!media_router.CastMode>} castModeList The current list of
   *     cast modes.
   * @return {boolean} Whether or not to hide the share screen subheading text.
   * @private
   */
  computeShareScreenSubheadingHidden_: function(castModeList) {
    return this.computeShareScreenCastModeList_(castModeList).length == 0;
  },

  /**
   * @param {!Array<!media_router.CastMode>} castModeList The current list of
   *     cast modes.
   * @return {boolean} Whether or not to hide the local media subheading text.
   * @private
   */
  computeLocalMediaSubheadingHidden_: function(castModeList) {
    return this.computeLocalMediaCastModeList_(castModeList).length == 0;
  },

  /**
   * @param {boolean} showFirstRunFlow Whether or not to show the first run
   *     flow.
   * @param {?media_router.MediaRouterView} currentView The current view.
   * @private
   */
  computeShowFirstRunFlow_: function(showFirstRunFlow, currentView) {
    return showFirstRunFlow &&
        currentView == media_router.MediaRouterView.SINK_LIST;
  },

  /**
   * @param {!media_router.Sink} sink The sink to determine an icon for.
   * @return {string} The icon to use.
   * @private
   */
  computeSinkIcon_: function(sink) {
    switch (sink.iconType) {
      case media_router.SinkIconType.CAST:
        return 'media-router:chromecast';
      case media_router.SinkIconType.CAST_AUDIO_GROUP:
        return 'media-router:speaker-group';
      case media_router.SinkIconType.CAST_AUDIO:
        return 'media-router:speaker';
      case media_router.SinkIconType.MEETING:
        return 'media-router:meeting';
      case media_router.SinkIconType.HANGOUT:
        return 'media-router:hangout';
      case media_router.SinkIconType.EDUCATION:
        return 'media-router:education';
      case media_router.SinkIconType.WIRED_DISPLAY:
        return 'media-router:tv';
      case media_router.SinkIconType.GENERIC:
        return 'media-router:tv';
      default:
        return 'media-router:tv';
    }
  },

  /**
   * @param {!string} sinkId A sink ID.
   * @param {!Object<!string, ?media_router.Route>} sinkToRouteMap
   *     Maps media_router.Sink.id to corresponding media_router.Route.
   * @return {string} The class for the sink icon.
   * @private
   */
  computeSinkIconClass_: function(sinkId, sinkToRouteMap) {
    return sinkToRouteMap[sinkId] ? 'sink-icon active-sink' : 'sink-icon';
  },

  /**
   * @param {!string} currentLaunchingSinkId The ID of the sink that is
   *     currently launching.
   * @param {!string} sinkId A sink ID.
   * @return {boolean} |true| if given sink is currently launching.
   * @private
   */
  computeSinkIsLaunching_: function(currentLaunchingSinkId, sinkId) {
    return currentLaunchingSinkId == sinkId;
  },

  /**
   * @param {!Array<!media_router.Sink>} sinksToShow The list of sinks.
   * @return {boolean} Whether or not to hide the sink list.
   * @private
   */
  computeSinkListHidden_: function(sinksToShow) {
    return sinksToShow.length == 0;
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @param {?media_router.Issue} issue The current issue.
   * @return {boolean} Whether or not to hide entire the sink list view.
   * @private
   */
  computeSinkListViewHidden_: function(view, issue) {
    return (view != media_router.MediaRouterView.SINK_LIST &&
            view != media_router.MediaRouterView.FILTER) ||
        (!!issue && issue.isBlocking);
  },

  /**
   * Returns whether the sink domain for |sink| should be hidden.
   * @param {!media_router.Sink} sink
   * @return {boolean} |true| if the domain should be hidden.
   * @private
   */
  computeSinkDomainHidden_: function(sink) {
    return !this.showDomain || this.isEmptyOrWhitespace_(sink.domain);
  },

  /**
   * Computes which portions of a sink name, if any, should be highlighted when
   * displayed in the filter view. Any substrings matching the search text
   * should be highlighted.
   *
   * The order the strings are combined is plainText[0] highlightedText[0]
   * plainText[1] highlightedText[1] etc.
   *
   * @param {!{sinkItem: !media_router.Sink,
   *           substrings: !Array<!Array<number>>}} matchedItem
   * Parameters in matchedItem:
   *   sinkItem - Original !media_router.Sink from the sink list.
   *   substrings - List of index pairs denoting substrings of sinkItem.name
   *       that match |searchInputText_|.
   * @return {!{highlightedText: !Array<string>, plainText: !Array<string>}}
   *   highlightedText - Array of strings that should be displayed highlighted.
   *   plainText - Array of strings that should be displayed normally.
   * @private
   */
  computeSinkMatchingText_: function(matchedItem) {
    if (!matchedItem.substrings) {
      return {highlightedText: [null], plainText: [matchedItem.sinkItem.name]};
    }
    var lastMatchIndex = -1;
    var nameIndex = 0;
    var sinkName = matchedItem.sinkItem.name;
    var highlightedText = [];
    var plainText = [];
    for (var i = 0; i < matchedItem.substrings.length; ++i) {
      var [matchStart, matchEnd] = matchedItem.substrings[i];
      if (lastMatchIndex + 1 < matchStart) {
        plainText.push(sinkName.substring(lastMatchIndex + 1, matchStart));
      } else {
        plainText.push(null);
      }
      highlightedText.push(sinkName.substring(matchStart, matchEnd + 1));
      lastMatchIndex = matchEnd;
    }
    if (lastMatchIndex + 1 < sinkName.length) {
      highlightedText.push(null);
      plainText.push(sinkName.substring(lastMatchIndex + 1));
    }
    return {highlightedText: highlightedText, plainText: plainText};
  },

  /**
   * Returns the subtext to be shown for |sink|. Only called if
   * |computeSinkSubtextHidden_| returns false for the same |sink| and
   * |sinkToRouteMap|.
   * @param {!media_router.Sink} sink
   * @param {!Object<!string, ?media_router.Route>} sinkToRouteMap
   * @return {?string} The subtext to be shown.
   * @private
   */
  computeSinkSubtext_: function(sink, sinkToRouteMap) {
    var route = sinkToRouteMap[sink.id];
    if (route && !this.isEmptyOrWhitespace_(route.description)) {
      return route.description;
    }

    return sink.description;
  },

  /**
   * Returns whether the sink subtext for |sink| should be hidden.
   * @param {!media_router.Sink} sink
   * @param {!Object<!string, ?media_router.Route>} sinkToRouteMap
   * @return {boolean} |true| if the subtext should be hidden.
   * @private
   */
  computeSinkSubtextHidden_: function(sink, sinkToRouteMap) {
    if (!this.isEmptyOrWhitespace_(sink.description)) {
      return false;
    }

    var route = sinkToRouteMap[sink.id];
    return !route || this.isEmptyOrWhitespace_(route.description);
  },

  /**
   * @param {boolean} justOpened Whether the MR UI was just opened.
   * @return {boolean} Whether or not to hide the spinner.
   * @private
   */
  computeSpinnerHidden_: function(justOpened) {
    return !justOpened;
  },

  /**
   * Computes the height of the sink list view element when search results are
   * being shown.
   *
   * @param {?Element} deviceMissing No devices message element.
   * @param {?Element} noMatches No search matches element.
   * @param {?Element} results Search results list element.
   * @param {number} searchOffsetHeight Search input container element height.
   * @param {number} maxHeight Max height of the list elements.
   * @return {number} The height of the sink list view when search results are
   *     being shown.
   * @private
   */
  computeTotalSearchHeight_: function(
      deviceMissing, noMatches, results, searchOffsetHeight, maxHeight) {
    var contentHeight = deviceMissing.offsetHeight +
        ((noMatches.hasAttribute('hidden')) ? results.offsetHeight :
                                              noMatches.offsetHeight);
    return Math.min(contentHeight, maxHeight) + searchOffsetHeight;
  },

  /**
   * Updates element positioning when the view changes and possibly triggers
   * reporting of a user filter action. If there is no filter text, it defers
   * the reporting until some text is entered, but otherwise it reports the
   * filter action here.
   * @param {?media_router.MediaRouterView} currentView The current view of the
   *     dialog.
   * @param {?media_router.MediaRouterView} previousView The previous
   *     |currentView|.
   * @private
   */
  currentViewChanged_: function(currentView, previousView) {
    if (currentView == media_router.MediaRouterView.FILTER) {
      this.reportFilterOnInput_ = true;
      this.maybeReportFilter_();
    }
    this.updateElementPositioning_();

    if (previousView == media_router.MediaRouterView.ROUTE_DETAILS) {
      media_router.browserApi.onMediaControllerClosed();
      if (this.$$('route-details')) {
        this.$$('route-details').onClosed();
      }
    }
  },

  /**
   * Filters all sinks based on fuzzy matching to the currently entered search
   * text.
   * @param {string} searchInputText The currently entered search text.
   * @private
   */
  filterSinks_: function(searchInputText) {
    if (searchInputText.length == 0) {
      this.searchResultsToShow_ = this.sinksToShow_.map(function(item) {
        return {sinkItem: item, substrings: null};
      });
      return;
    }

    var searchResultsToShow = [];
    for (var i = 0; i < this.sinksToShow_.length; ++i) {
      var matchSubstrings = this.computeSearchMatches_(
          searchInputText, this.sinksToShow_[i].name);
      if (!matchSubstrings) {
        continue;
      }
      searchResultsToShow.push(
          {sinkItem: this.sinksToShow_[i], substrings: matchSubstrings});
    }
    searchResultsToShow.sort(this.compareSearchMatches_);

    var pendingPseudoSink = (this.pseudoSinkSearchState_) ?
        this.pseudoSinkSearchState_.getPseudoSink() :
        null;
    // We may need to add pseudo sinks to the filter results. A pseudo sink will
    // be shown if there is no real sink with the same icon and name exactly
    // matching the filter text. The map() call transforms any pseudo sink
    // objects that will be shown to the search result format, where we know
    // that the entire sink name will be a match.
    //
    // The exception to this is when there is a pending pseudo sink search. Then
    // the pseudo sink for the search will be treated like a real sink because
    // it will actually be in |sinksToShow_| until a real sink is returned by
    // search. So the filter here shouldn't treat it like a pseudo sink.
    searchResultsToShow =
        this.pseudoSinks_
            .filter(function(pseudoSink) {
              return (!pendingPseudoSink ||
                      pseudoSink.id != pendingPseudoSink.id) &&
                  !searchResultsToShow.find(function(searchResult) {
                    return searchResult.sinkItem.name == searchInputText &&
                        searchResult.sinkItem.iconType == pseudoSink.iconType;
                  });
            })
            .map(function(pseudoSink) {
              pseudoSink.name = searchInputText;
              return {
                sinkItem: pseudoSink,
                substrings: [[0, searchInputText.length - 1]]
              };
            })
            .concat(searchResultsToShow);
    this.searchResultsToShow_ = searchResultsToShow;
  },

  /**
   * Helper function to locate the CastMode object with the given type in
   * castModeList.
   *
   * @param {number} castModeType Type of cast mode to look for.
   * @return {media_router.CastMode|undefined} CastMode object with the given
   *     type in castModeList, or undefined if not found.
   * @private
   */
  findCastModeByType_: function(castModeType) {
    return this.castModeList.find(function(element, index, array) {
      return element.type == castModeType;
    });
  },

  /**
   * Helper function to locate the position in the |castModeList| of the
   * CastMode object with the given type.
   *
   * @param {number} castModeType Type of cast mode to look for.
   * @return {number} index of the given type, or -1 if not found.
   * @private
   */
  findCastModeIndexByType_: function(castModeType) {
    return this.castModeList
        .map(function(element) {
          return element.type;
        })
        .indexOf(castModeType);
  },


  /**
   * Helper function to return a forced CastMode, if any.
   *
   * @return {media_router.CastMode|undefined} CastMode object with
   *     isForced = true, or undefined if not found.
   * @private
   */
  findForcedCastMode_: function() {
    return this.castModeList &&
        this.castModeList.find(element => element.isForced);
  },

  /**
   * @param {?Element} element Element to compute padding for.
   * @return {!Array<number>} Array containing the element's bottom padding
   *     value and the element's top padding value, in that order.
   * @private
   */
  getElementVerticalPadding_: function(element) {
    var style = window.getComputedStyle(element);
    return [
      parseInt(style.getPropertyValue('padding-bottom'), 10) || 0,
      parseInt(style.getPropertyValue('padding-top'), 10) || 0
    ];
  },

  /**
   * Retrieves the first run flow cloud preferences text, if it exists. On
   * non-officially branded builds, the string is not defined.
   *
   * @return {string} Cloud preferences text.
   */
  getFirstRunFlowCloudPrefText_: function() {
    return loadTimeData.valueExists('firstRunFlowCloudPrefText') ?
        this.i18n('firstRunFlowCloudPrefText') :
        '';
  },

  /**
   * @param {?media_router.Route} route Route to get the sink for.
   * @return {?media_router.Sink} Sink associated with |route| or
   *     undefined if we don't have data for the sink.
   */
  getSinkForRoute_: function(route) {
    return route ? this.sinkMap_[route.sinkId] : null;
  },

  /**
   * @param {?Element} element Conditionally-templated element to check.
   * @return {boolean} Whether |element| is considered present in the document
   *     as a conditionally-templated element. This does not check the |hidden|
   *     attribute.
   */
  hasConditionalElement_: function(element) {
    return !!element &&
        (!element.style.display || element.style.display != 'none');
  },

  /**
   * Returns whether given string is undefined, null, empty, or whitespace only.
   * @param {?string} str String to be tested.
   * @return {boolean} |true| if the string is undefined, null, empty, or
   *     whitespace.
   * @private
   */
  isEmptyOrWhitespace_: function(str) {
    return str === undefined || str === null || (/^\s*$/).test(str);
  },

  /**
   * Reports a user filter action if |searchInputText_| is not empty and the
   * filter action hasn't been reported since the view changed to the filter
   * view.
   * @private
   */
  maybeReportFilter_: function() {
    if (this.reportFilterOnInput_ && this.searchInputText_.length != 0) {
      this.reportFilterOnInput_ = false;
      this.fire('report-filter');
    }
  },

  /**
   * Updates |currentView_| if the dialog had just opened and there's
   * only one local route.
   */
  maybeShowRouteDetailsOnOpen: function() {
    var localRoute = null;
    for (var i = 0; i < this.routeList.length; i++) {
      var route = this.routeList[i];
      if (!route.isLocal) {
        continue;
      }
      if (!localRoute) {
        localRoute = route;
      } else {
        // Don't show route details if there are more than one local route.
        localRoute = null;
        break;
      }
    }

    if (localRoute) {
      this.showRouteDetails_(localRoute);
    }
    this.fire('show-initial-state', {currentView: this.currentView_});
  },

  /**
   * Updates |currentView_| if there is a new blocking issue or a blocking
   * issue is resolved. Clears any pending route creation properties if the
   * issue corresponds with |pendingCreatedRouteId_|.
   *
   * @param {?media_router.Issue} issue The new issue, or null if the
   *                              blocking issue was resolved.
   * @private
   */
  maybeShowIssueView_: function(issue) {
    if (!!issue) {
      if (issue.isBlocking) {
        this.currentView_ = media_router.MediaRouterView.ISSUE;
      } else if (this.currentView_ == media_router.MediaRouterView.SINK_LIST) {
        // Make space for the non-blocking issue in the sink list.
        this.updateElementPositioning_();
      }
    } else if (this.currentView_ == media_router.MediaRouterView.ISSUE) {
      // Switch back to the sink list if the issue was cleared and it was
      // showing an issue. It is expected that the only way to clear an issue is
      // by user action; the IssueManager (C++ side) does not clear issues in
      // the UI.
      this.showSinkList_();
    }

    if (!!this.pendingCreatedRouteId_ && !!issue &&
        issue.routeId == this.pendingCreatedRouteId_) {
      this.resetRouteCreationProperties_(false);
    }
  },

  /**
   * If an element in the search results list has keyboard focus when we are
   * transitioning from the filter view to the sink list view, give focus to the
   * same sink in the sink list. Otherwise we leave the keyboard focus where it
   * is.
   * @private
   */
  maybeUpdateFocusOnFilterViewExit_: function() {
    var searchSinks =
        this.$$('#search-results').querySelectorAll('.selectable-item');
    var focusedElem = Array.prototype.find.call(searchSinks, function(sink) {
      return sink.matches(':focus');
    });
    if (!focusedElem) {
      return;
    }
    var focusedSink =
        this.$$('#searchResults').itemForElement(focusedElem).sinkItem;
    setTimeout(function() {
      var sinkListPaperMenu = this.$$('#sink-list-paper-menu');
      var sinks = sinkListPaperMenu.children;
      var sinkList = this.$$('#sinkList');
      for (var i = 0; i < sinks.length; i++) {
        if (sinkList.itemForElement(sinks[i]).id == focusedSink.id) {
          sinkListPaperMenu.selectIndex(i);
          break;
        }
      }
    }.bind(this));
  },

  /**
   * May update |populatedSinkListSeenTimeMs_| depending on |currentView| and
   * |sinksToShow|.
   * Called when |currentView_| or |sinksToShow_| is updated.
   *
   * @param {?media_router.MediaRouterView} currentView The current view of the
   *                                        dialog.
   * @param {!Array<!media_router.Sink>} sinksToShow The sinks to display.
   * @private
   */
  maybeUpdateStartSinkDisplayStartTime_: function(currentView, sinksToShow) {
    if (currentView == media_router.MediaRouterView.SINK_LIST &&
        sinksToShow.length != 0) {
      // Only set |populatedSinkListSeenTimeMs_| if it has not already been set.
      if (this.populatedSinkListSeenTimeMs_ == -1) {
        this.populatedSinkListSeenTimeMs_ = window.performance.now();
      }
    } else {
      // Reset |populatedSinkListLastSeen_| if the sink list isn't being shown
      // or if there aren't any sinks available for display.
      this.populatedSinkListSeenTimeMs_ = -1;
    }
  },

  /**
   * Animates the transition from the filter view, where the search field is at
   * the top of the list, to the sink list view, where the search field is at
   * the bottom of the list.
   *
   * If this is called while another animation is in progress, it queues itself
   * to be run at the end of the current animation.
   *
   * @param {!function()} resolve Resolves the animation promise that is waiting
   *     on this animation.
   * @private
   */
  moveSearchToBottom_: function(resolve) {
    var deviceMissing = this.$['device-missing'];
    var list = this.$$('#sink-list');
    var resultsContainer = this.$$('#search-results-container');
    var search = this.$$('#sink-search');
    var view = this.$['sink-list-view'];

    var hasList = this.hasConditionalElement_(list);
    var initialHeight = view.offsetHeight;
    // Force the view height to be max dialog height.
    view.style['overflow'] = 'hidden';

    var searchInitialOffsetHeight = search.offsetHeight;
    var searchInitialPaddingBottom, searchInitialPaddingTop;
    [searchInitialPaddingBottom, searchInitialPaddingTop] =
        this.getElementVerticalPadding_(search);
    var searchPadding = searchInitialPaddingBottom + searchInitialPaddingTop;
    var searchHeight = search.offsetHeight - searchPadding;
    var searchFinalPaddingBottom, searchFinalPaddingTop;
    [searchFinalPaddingBottom, searchFinalPaddingTop] =
        this.getElementVerticalPadding_(search);
    var searchFinalOffsetHeight =
        searchHeight + searchFinalPaddingBottom + searchFinalPaddingTop;

    var resultsInitialTop = 0;
    var finalHeight = 0;
    // Get final view height ahead of animation.
    if (hasList) {
      list.style['position'] = 'absolute';
      list.style['opacity'] = '0';
      this.hideSinkListForAnimation_ = false;
      finalHeight += list.offsetHeight;
      list.style['position'] = 'relative';
    } else {
      resultsInitialTop +=
          deviceMissing.offsetHeight + searchInitialOffsetHeight;
      finalHeight += deviceMissing.offsetHeight;
    }

    var searchInitialTop = hasList ? 0 : deviceMissing.offsetHeight;
    var searchFinalTop = hasList ? list.offsetHeight - search.offsetHeight :
                                   deviceMissing.offsetHeight;
    resultsContainer.style['position'] = 'absolute';

    var duration =
        this.computeAnimationDuration_(searchFinalTop - searchInitialTop);
    var timing = {duration: duration, easing: 'ease-in-out', fill: 'forwards'};

    // This GroupEffect does the reverse of |moveSearchToTop_|. It fades the
    // sink list in while sliding the search input and search results list down.
    // The dialog height is also adjusted smoothly to the sink list height.
    var deviceMissingEffect = new KeyframeEffect(
        deviceMissing,
        [
          {'marginBottom': searchInitialOffsetHeight},
          {'marginBottom': searchFinalOffsetHeight}
        ],
        timing);
    var listEffect =
        new KeyframeEffect(list, [{'opacity': '0'}, {'opacity': '1'}], timing);
    var resultsEffect = new KeyframeEffect(
        resultsContainer,
        [
          {
            'top': resultsInitialTop + 'px',
            'paddingTop': resultsContainer.style['padding-top']
          },
          {'top': '100%', 'paddingTop': '0px'}
        ],
        timing);
    var searchEffect = new KeyframeEffect(
        search,
        [
          {
            'top': searchInitialTop + 'px',
            'marginTop': '0px',
            'paddingBottom': searchInitialPaddingBottom + 'px',
            'paddingTop': searchInitialPaddingTop + 'px'
          },
          {
            'top': '100%',
            'marginTop': '-' + searchFinalOffsetHeight + 'px',
            'paddingBottom': searchFinalPaddingBottom + 'px',
            'paddingTop': searchFinalPaddingTop + 'px'
          }
        ],
        timing);
    var viewEffect = new KeyframeEffect(
        view,
        [
          {'height': initialHeight + 'px', 'paddingBottom': '0px'}, {
            'height': finalHeight + 'px',
            'paddingBottom': searchFinalOffsetHeight + 'px'
          }
        ],
        timing);
    var player = document.timeline.play(new GroupEffect(
        hasList ?
            [listEffect, resultsEffect, searchEffect, viewEffect] :
            [deviceMissingEffect, resultsEffect, searchEffect, viewEffect]));

    var that = this;
    var finalizeAnimation = function() {
      view.style['overflow'] = '';
      that.putSearchAtBottom_();
      that.filterTransitionPlayer_.cancel();
      that.filterTransitionPlayer_ = null;
      that.isSearchListHidden_ = true;
      resolve();
    };

    player.finished.then(finalizeAnimation);
    this.filterTransitionPlayer_ = player;
  },

  /**
   * Animates the transition from the sink list view, where the search field is
   * at the bottom of the list, to the filter view, where the search field is at
   * the top of the list.
   *
   * If this is called while another animation is in progress, it queues itself
   * to be run at the end of the current animation.
   *
   * @param {!function()} resolve Resolves the animation promise that is waiting
   *     on this animation.
   * @private
   */
  moveSearchToTop_: function(resolve) {
    var deviceMissing = this.$['device-missing'];
    var list = this.$$('#sink-list');
    var noMatches = this.$$('#no-search-matches');
    var results = this.$$('#search-results');
    var resultsContainer = this.$$('#search-results-container');
    var search = this.$$('#sink-search');
    var view = this.$['sink-list-view'];

    // Set the max height for the results list before it's shown.
    results.style.maxHeight = this.sinkListMaxHeight_ + 'px';

    // Saves current search container |offsetHeight| which includes bottom
    // padding.
    var searchInitialOffsetHeight = search.offsetHeight;
    var hasList = this.hasConditionalElement_(list);
    var searchInitialTop = hasList ?
        list.offsetHeight - searchInitialOffsetHeight :
        deviceMissing.offsetHeight;
    var searchFinalTop = hasList ? 0 : deviceMissing.offsetHeight;
    var searchInitialPaddingBottom, searchInitialPaddingTop;
    [searchInitialPaddingBottom, searchInitialPaddingTop] =
        this.getElementVerticalPadding_(search);
    var searchPadding = searchInitialPaddingBottom + searchInitialPaddingTop;
    var searchHeight = search.offsetHeight - searchPadding;
    var searchFinalPaddingBottom, searchFinalPaddingTop;
    [searchFinalPaddingBottom, searchFinalPaddingTop] =
        this.getElementVerticalPadding_(search);
    var searchFinalOffsetHeight =
        searchHeight + searchFinalPaddingBottom + searchFinalPaddingTop;

    // Omitting |search.offsetHeight| because it is handled by view animation
    // separately.
    var initialHeight =
        hasList ? list.offsetHeight : deviceMissing.offsetHeight;
    view.style['overflow'] = 'hidden';

    var resultsPadding = this.computeElementVerticalPadding_(results);
    var finalHeight = this.computeTotalSearchHeight_(
        deviceMissing, noMatches, results, searchFinalOffsetHeight,
        this.sinkListMaxHeight_ + resultsPadding);

    var duration =
        this.computeAnimationDuration_(searchFinalTop - searchInitialTop);
    var timing = {duration: duration, easing: 'ease-in-out', fill: 'forwards'};

    // This GroupEffect will cause the sink list to fade out while the search
    // input and search results list slide up. The dialog will also resize
    // smoothly to the new search result list height.
    var deviceMissingEffect = new KeyframeEffect(
        deviceMissing,
        [
          {'marginBottom': searchInitialOffsetHeight},
          {'marginBottom': searchFinalOffsetHeight}
        ],
        timing);
    var listEffect =
        new KeyframeEffect(list, [{'opacity': '1'}, {'opacity': '0'}], timing);
    var resultsEffect = new KeyframeEffect(
        resultsContainer,
        [
          {'top': '100%', 'paddingTop': '0px'}, {
            'top': searchFinalTop + 'px',
            'paddingTop': searchFinalOffsetHeight + 'px'
          }
        ],
        timing);
    var searchEffect = new KeyframeEffect(
        search,
        [
          {
            'top': '100%',
            'marginTop': '-' + searchInitialOffsetHeight + 'px',
            'paddingBottom': searchInitialPaddingBottom + 'px',
            'paddingTop': searchInitialPaddingTop + 'px'
          },
          {
            'top': searchFinalTop + 'px',
            'marginTop': '0px',
            'paddingBottom': searchFinalPaddingBottom + 'px',
            'paddingTop': searchFinalPaddingTop + 'px'
          }
        ],
        timing);
    var viewEffect = new KeyframeEffect(
        view,
        [
          {
            'height': initialHeight + 'px',
            'paddingBottom': searchInitialOffsetHeight + 'px'
          },
          {'height': finalHeight + 'px', 'paddingBottom': '0px'}
        ],
        timing);
    var player = document.timeline.play(new GroupEffect(
        hasList ?
            [listEffect, resultsEffect, searchEffect, viewEffect] :
            [deviceMissingEffect, resultsEffect, searchEffect, viewEffect]));

    var that = this;
    var finalizeAnimation = function() {
      // When we are moving the search results up into view, the user may type
      // more text or delete text which may change the height of the search
      // results list. In this case, the dialog height that the animation ends
      // on will now be wrong. In order to correct this smoothly,
      // |putSearchAtTop_| will queue another animation just to adjust the
      // dialog height.
      //
      // The |filterTransitionPlayer_| will hold all of the animated elements in
      // their final keyframe state until it is canceled or another player
      // overrides it because we used |fill: 'forwards'| in all of the effects.
      // So unlike |moveSearchToBottom_|, we don't know for sure whether we want
      // to cancel |filterTransitionPlayer_| after |putSearchAtTop_| because
      // another animation may have been run to correct the dialog height.
      //
      // If |putSearchAtTop_| has to adjust the dialog height, it also queues
      // itself to run again when that animation is finished. When the height is
      // finally correct at the end of an animation, it will cancel
      // |filterTransitionPlayer_| itself.
      that.putSearchAtTop_(resolve);
    };

    player.finished.then(finalizeAnimation);
    this.filterTransitionPlayer_ = player;
  },

  /**
   * Handles a cast mode selection. Updates |headerText|, |headerTextTooltip|,
   * and |shownCastModeValue_|.
   *
   * @param {!Event} event The event object.
   * @private
   */
  onCastModeClick_: function(event) {
    // The clicked cast mode can come from one of three lists,
    // presentationCastModeList, shareScreenCastModeList, and
    // localMediaCastModeList.
    var clickedMode =
        this.$$('#presentationCastModeList').itemForElement(event.target) ||
        this.$$('#shareScreenCastModeList').itemForElement(event.target) ||
        this.$$('#localMediaCastModeList').itemForElement(event.target);

    if (!clickedMode) {
      return;
    }

    // If the user selects LOCAL_FILE, some additional steps are required
    // (selecting the file), before the cast mode has been officially
    // selected.
    if (clickedMode.type == media_router.CastModeType.LOCAL_FILE) {
      this.selectLocalMediaFile_();
    } else {
      this.castModeSelected_(clickedMode);
    }
  },

  /**
   * Handles a change-route-source-click event. Sets the currently launching
   * sink to be the current route's sink and shows the sink list.
   *
   * @param {!Event} event The event object.
   * Parameters in |event|.detail:
   *   route - route to modify.
   *   selectedCastMode - cast mode to use for the new source.
   * @private
   */
  onChangeRouteSourceClick_: function(event) {
    /** @type {{route: !media_router.Route, selectedCastMode: number}} */
    var detail = event.detail;
    this.currentLaunchingSinkId_ = detail.route.sinkId;
    var sink = this.sinkMap_[detail.route.sinkId];
    this.showSinkList_();
    this.maybeReportUserFirstAction(
        media_router.MediaRouterUserAction.REPLACE_LOCAL_ROUTE);
  },

  /**
   * Handles a close-route event. Shows the sink list and starts a timer to
   * close the dialog if there is no click within three seconds.
   *
   * @param {!Event} event The event object.
   * Parameters in |event|.detail:
   *   route - route to close.
   * @private
   */
  onCloseRoute_: function(event) {
    /** @type {{route: media_router.Route}} */
    var detail = event.detail;
    this.showSinkList_();
    this.startTapTimer_();

    if (detail.route.isLocal) {
      this.maybeReportUserFirstAction(
          media_router.MediaRouterUserAction.STOP_LOCAL);
    }
  },

  /**
   * Handles response of previous create route attempt.
   *
   * @param {string} sinkId The ID of the sink to which the Media Route was
   *     creating a route.
   * @param {?media_router.Route} route The newly created route that
   *     corresponds to the sink if route creation succeeded; null otherwise.
   * @param {boolean} isForDisplay Whether or not |route| is for display.
   */
  onCreateRouteResponseReceived: function(sinkId, route, isForDisplay) {
    // The provider will handle sending an issue for a failed route request.
    if (!route) {
      this.resetRouteCreationProperties_(false);
      this.fire('report-resolved-route', {
        outcome: media_router.MediaRouterRouteCreationOutcome.FAILURE_NO_ROUTE
      });
      return;
    }

    // Check that |sinkId| exists and corresponds to |currentLaunchingSinkId_|.
    if (!this.sinkMap_[sinkId] || this.currentLaunchingSinkId_ != sinkId) {
      this.fire('report-resolved-route', {
        outcome:
            media_router.MediaRouterRouteCreationOutcome.FAILURE_INVALID_SINK
      });
      return;
    }

    // Regardless of whether the route is for display, it was resolved
    // successfully.
    this.fire(
        'report-resolved-route',
        {outcome: media_router.MediaRouterRouteCreationOutcome.SUCCESS});

    if (isForDisplay) {
      this.showRouteDetails_(route);
      this.startTapTimer_();
      this.resetRouteCreationProperties_(true);
    } else {
      this.pendingCreatedRouteId_ = route.id;
    }
  },

  /**
   * Sets up the LOCAL_FILE cast mode for display after a specific file has been
   * selected.
   *
   * @param {string} fileName The name of the file that has been selected.
   */
  onFileDialogSuccess(fileName) {
    /** @const */ var mode =
        this.findCastModeByType_(media_router.CastModeType.LOCAL_FILE);

    if (!mode) {
      return;
    }

    this.castModeSelected_(mode);
    this.headerText =
        loadTimeData.getStringF('castLocalMediaSelectedFileTitle', fileName);

    this.updateSelectedCastModeMenuItem_();
  },

  /**
   * Called when a focus event is triggered.
   *
   * @param {!Event} event The event object.
   * @private
   */
  onFocus_: function(event) {
    // If the focus event was automatically fired by Polymer, remove focus from
    // the element. This prevents unexpected focusing when the dialog is
    // initially loaded. This only happens on mac.
    if (cr.isMac && !event.sourceCapabilities) {
      // Adding a focus placeholder element is part of the workaround for
      // handling unexpected focusing, which only happens once on dialog open.
      // Since the placeholder is focus-enabled as denoted by its tabindex
      // value, the focus will not appear in other elements.
      var placeholder = this.$$('#focus-placeholder');
      // Check that the placeholder is the currently focused element. In some
      // tests, other elements are non-user-triggered focused.
      if (placeholder && this.shadowRoot.activeElement == placeholder) {
        event.path[0].blur();
        // Remove the placeholder since we have no more use for it.
        placeholder.remove();
      }
    }
  },

  /**
   * Called when a keydown event is fired.
   * @param {!Event} e Keydown event object for the event.
   */
  onKeydown_: function(e) {
    // The ESC key may be pressed with a combination of other keys. It is
    // handled on the C++ side instead of the JS side on non-mac platforms,
    // which uses toolkit-views. Handle the expected behavior on all platforms
    // here.
    if (e.key == media_router.KEY_ESC && !e.shiftKey && !e.ctrlKey &&
        !e.altKey && !e.metaKey) {
      // When searching, allow ESC as a mechanism to leave the filter view.
      if (this.currentView_ == media_router.MediaRouterView.FILTER) {
        // If the user tabbed to an item in the search results, or otherwise has
        // an item in the list focused, focus will seem to vanish when we
        // transition back to the sink list. Instead we should move focus to the
        // appropriate item in the sink list.
        this.maybeUpdateFocusOnFilterViewExit_();
        this.showSinkList_();
        e.preventDefault();
      } else {
        this.fire('close-dialog', {
          pressEscToClose: true,
        });
      }
    }
  },

  /**
   * Called when a mouseleave event is triggered.
   *
   * @private
   */
  onMouseLeave_: function() {
    this.mouseIsPositionedOverDialog_ = false;
  },

  /**
   * Called when a mouseenter event is triggered.
   *
   * @private
   */
  onMouseEnter_: function() {
    this.mouseIsPositionedOverDialog_ = true;
  },

  /**
   * Called when a search has completed up to route creation. |sinkId|
   * identifies the sink that should be in |allSinks|, if a sink was found.
   *
   * @param {string} sinkId The ID of the sink that is the result of the
   *     currently pending search.
   */
  onReceiveSearchResult: function(sinkId) {
    this.pseudoSinkSearchState_.receiveSinkResponse(sinkId);
    this.currentLaunchingSinkId_ =
        this.pseudoSinkSearchState_.checkForRealSink(this.allSinks);
    this.rebuildSinksToShow_();
    // If we're in filter view, make sure the |sinksToShow_| change is picked
    // up.
    if (this.currentView_ == media_router.MediaRouterView.FILTER) {
      this.filterSinks_(this.searchInputText_);
    }
  },

  /**
   * Called when the connection to the route controller is invalidated. Switches
   * from route details view to the sink list view.
   */
  onRouteControllerInvalidated: function() {
    if (this.currentView_ == media_router.MediaRouterView.ROUTE_DETAILS) {
      this.currentRoute_ = null;
      this.showSinkList_();
    }
  },

  /**
   * Called when a sink is clicked.
   *
   * @param {!Event} event The event object.
   * @private
   */
  onSinkClick_: function(event) {
    var clickedSink =
        (this.currentView_ == media_router.MediaRouterView.FILTER) ?
        this.$$('#searchResults').itemForElement(event.target).sinkItem :
        this.$$('#sinkList').itemForElement(event.target);
    this.showOrCreateRoute_(clickedSink);
    this.fire('sink-click', {index: event['model'].index});
  },

  /**
   * Sets the positioning of the sink list, search input, and search results so
   * that everything is in the correct state for the sink list view.
   *
   * @private
   */
  putSearchAtBottom_: function() {
    var search = this.$$('#sink-search');
    if (!this.hasConditionalElement_(search)) {
      return;
    }
    var deviceMissing = this.$['device-missing'];
    var list = this.$$('#sink-list');
    var resultsContainer = this.$$('#search-results-container');
    var view = this.$['sink-list-view'];
    search.style['top'] = '';
    if (resultsContainer) {
      resultsContainer.style['position'] = '';
      resultsContainer.style['padding-top'] = '';
      resultsContainer.style['top'] = '';
    }
    this.hideSinkListForAnimation_ = false;
    var hasList = this.hasConditionalElement_(list);
    if (hasList) {
      search.style['margin-top'] = '-' + search.offsetHeight + 'px';
      view.style['padding-bottom'] = search.offsetHeight + 'px';
      list.style['opacity'] = '';
    } else {
      var bottomMargin = 12;
      deviceMissing.style['margin-bottom'] =
          (search.offsetHeight + bottomMargin) + 'px';
      search.style['margin-top'] = '';
      view.style['padding-bottom'] = '';
    }
  },

  /**
   * Sets the positioning of the sink list, search input, and search results so
   * that everything is in the correct state for the filter view.
   *
   * If the user was searching while the |moveSearchToTop_| animation was
   * happening then the dialog height that animation ends at could be different
   * than the current height of the search results. If this is the case, this
   * function first spawns a new animation that smoothly corrects the height
   * problem. This is iterative, but once we enter a call where the heights
   * match up, the elements will become static again.
   *
   * @param {!function()} resolve Resolves the animation promise that is waiting
   *     on this animation.
   * @private
   */
  putSearchAtTop_: function(resolve) {
    var deviceMissing = this.$['device-missing'];
    var list = this.$$('#sink-list');
    var noMatches = this.$$('#no-search-matches');
    var results = this.$$('#search-results');
    var resultsContainer = this.$$('#search-results-container');
    var search = this.$$('#sink-search');
    var view = this.$['sink-list-view'];

    // Set the max height for the results list before it's shown.
    results.style.maxHeight = this.sinkListMaxHeight_ + 'px';

    // If there is a height mismatch between where the animation calculated the
    // height should be and where it is now because the search results changed
    // during the animation, correct it with... another animation.
    var resultsPadding = this.computeElementVerticalPadding_(results);
    var finalHeight = this.computeTotalSearchHeight_(
        deviceMissing, noMatches, results, search.offsetHeight,
        this.sinkListMaxHeight_ + resultsPadding);
    if (finalHeight != view.offsetHeight) {
      var viewEffect = new KeyframeEffect(
          view,
          [
            {'height': view.offsetHeight + 'px'},
            {'height': finalHeight + 'px'}
          ],
          {
            duration:
                this.computeAnimationDuration_(finalHeight - view.offsetHeight),
            easing: 'ease-in-out',
            fill: 'forwards'
          });
      var player = document.timeline.play(viewEffect);
      if (this.heightAdjustmentPlayer_) {
        this.heightAdjustmentPlayer_.cancel();
      }
      this.heightAdjustmentPlayer_ = player;
      player.finished.then(this.putSearchAtTop_.bind(this, resolve));
      return;
    }

    var hasList = this.hasConditionalElement_(list);
    search.style['margin-top'] = '';
    deviceMissing.style['margin-bottom'] = search.offsetHeight + 'px';
    var searchFinalTop = hasList ? 0 : deviceMissing.offsetHeight;
    var resultsPaddingTop = hasList ? search.offsetHeight + 'px' : '0px';
    search.style['top'] = searchFinalTop + 'px';
    this.hideSinkListForAnimation_ = true;
    resultsContainer.style['position'] = 'relative';
    resultsContainer.style['padding-top'] = resultsPaddingTop;
    resultsContainer.style['top'] = '';

    view.style['overflow'] = '';
    view.style['padding-bottom'] = '';
    if (this.filterTransitionPlayer_) {
      this.filterTransitionPlayer_.cancel();
      this.filterTransitionPlayer_ = null;
    }

    if (this.heightAdjustmentPlayer_) {
      this.heightAdjustmentPlayer_.cancel();
      this.heightAdjustmentPlayer_ = null;
    }

    resolve();
  },

  /**
   * Queues a call to |moveSearchToBottom_| by adding it as a continuation to
   * |animationPromise_| and updating |animationPromise_|.
   */
  queueMoveSearchToBottom_: function() {
    var oldPromise = this.animationPromise_;
    var that = this;
    this.animationPromise_ = new Promise(function(resolve) {
      oldPromise.then(that.moveSearchToBottom_.bind(that, resolve));
    });
  },

  /**
   * Queues a call to |moveSearchToTop_| by adding it as a continuation to
   * |animationPromise_| and updating |animationPromise_|. The new promise will
   * not resolve until |putSearchAtTop_| is finished, including any potential
   * dialog height adjustment animations.
   */
  queueMoveSearchToTop_: function() {
    var oldPromise = this.animationPromise_;
    var that = this;
    this.animationPromise_ = new Promise(function(resolve) {
      oldPromise.then(function() {
        that.isSearchListHidden_ = false;
        setTimeout(that.moveSearchToTop_.bind(that, resolve));
      });
    });
  },

  /**
   * Queues a call to |putSearchAtTop_| by adding it as a continuation to
   * |animationPromise_| and updating |animationPromise_|.
   */
  queuePutSearchAtTop_: function() {
    var that = this;
    var oldPromise = this.animationPromise_;
    this.animationPromise_ = new Promise(function(resolve) {
      oldPromise.then(that.putSearchAtTop_.bind(that, resolve));
    });
  },

  /**
   * Called when |routeList| is updated. Rebuilds |routeMap_| and
   * |sinkToRouteMap_|.
   *
   * @private
   */
  rebuildRouteMaps_: function() {
    this.routeMap_ = {};

    // Rebuild |sinkToRouteMap_| with a temporary map to avoid firing the
    // computed functions prematurely.
    var tempSinkToRouteMap = {};

    // We expect that each route in |routeList| maps to a unique sink.
    this.routeList.forEach(function(route) {
      this.routeMap_[route.id] = route;
      tempSinkToRouteMap[route.sinkId] = route;
    }, this);

    // If there is route creation in progress, check if any of the route ids
    // correspond to |pendingCreatedRouteId_|. If so, the newly created route
    // is ready to be displayed; switch to route details view.
    if (this.currentLaunchingSinkId_ != '' &&
        this.pendingCreatedRouteId_ != '') {
      var route = tempSinkToRouteMap[this.currentLaunchingSinkId_];
      if (route && this.pendingCreatedRouteId_ == route.id) {
        this.showRouteDetails_(route);
        this.startTapTimer_();
        this.resetRouteCreationProperties_(true);
      }
    } else {
      // If |currentRoute_| is no longer active, clear |currentRoute_|. Also
      // switch back to the SINK_PICKER view if the user is currently in the
      // ROUTE_DETAILS view.
      if (this.currentRoute_) {
        this.currentRoute_ = this.routeMap_[this.currentRoute_.id] || null;
      }
      if (!this.currentRoute_ &&
          this.currentView_ == media_router.MediaRouterView.ROUTE_DETAILS) {
        this.showSinkList_();
      }
    }

    this.sinkToRouteMap_ = tempSinkToRouteMap;
    this.rebuildSinksToShow_();
  },

  /**
   * Rebuilds the list of sinks to be shown for the current cast mode.
   * A sink should be shown if it is compatible with the current cast mode, or
   * if the sink is associated with a route.  The resulting list is sorted by
   * name.
   */
  rebuildSinksToShow_: function() {
    var updatedSinkList = this.allSinks.filter(function(sink) {
      return !sink.isPseudoSink;
    }, this);

    if (this.pseudoSinkSearchState_) {
      var pendingPseudoSink = this.pseudoSinkSearchState_.getPseudoSink();
      // Here we will treat the pseudo sink that launched the search as a real
      // sink until one is returned by search. This way it isn't possible to
      // ever reach a UI state where there is no spinner being shown in the sink
      // list but |currentLaunchingSinkId_| is non-empty (thereby preventing any
      // other sink from launching).
      if (pendingPseudoSink.id == this.currentLaunchingSinkId_) {
        updatedSinkList.unshift(pendingPseudoSink);
      }
    }
    // If user did not select a cast mode, then:
    // - If there is a forced cast mode, it is shown.
    // - If all sinks support only a single cast mode, then the cast mode is
    //   switched to that mode.
    // - Otherwise, the cast mode becomes AUTO mode.
    if (!this.userHasSelectedCastMode_) {
      this.setShownCastMode_(this.computeCastMode_());
    }

    // Non-AUTO modes may show a subset of sinks based on compatibility with the
    // shown value.
    if (this.shownCastModeValue_ != media_router.CastModeType.AUTO) {
      updatedSinkList = updatedSinkList.filter(function(element) {
        return (element.castModes & this.shownCastModeValue_) ||
            this.sinkToRouteMap_[element.id];
      }, this);
    }

    // When there's an updated list of sinks, append any new sinks to the end
    // of the existing list. This prevents sinks randomly jumping around the
    // dialog, which can surprise users / lead to inadvertently casting to the
    // wrong sink.
    if (this.sinksToShow_) {
      for (var i = this.sinksToShow_.length - 1; i >= 0; i--) {
        var index = updatedSinkList.findIndex(function(updatedSink) {
          return this.sinksToShow_[i].id == updatedSink.id;
        }.bind(this));
        if (index < 0) {
          // Remove any sinks that are no longer discovered.
          this.sinksToShow_.splice(i, 1);
        } else {
          // If the sink exists, move it from |updatedSinkList| to
          // |sinksToShow_| in the same position, as the cast modes or other
          // fields may have been updated.
          this.sinksToShow_[i] = updatedSinkList[index];
          updatedSinkList.splice(index, 1);
        }
      }

      updatedSinkList = this.sinksToShow_.concat(updatedSinkList);
    }
    this.sinksToShow_ = updatedSinkList;
  },

  /**
   * Called when |allSinks| is updated.
   *
   * @private
   */
  reindexSinksAndRebuildSinksToShow_: function() {
    this.sinkMap_ = {};

    this.allSinks.forEach(function(sink) {
      if (!sink.isPseudoSink) {
        this.sinkMap_[sink.id] = sink;
      }
    }, this);

    if (this.pseudoSinkSearchState_) {
      this.currentLaunchingSinkId_ =
          this.pseudoSinkSearchState_.checkForRealSink(this.allSinks);
    }
    this.pseudoSinks_ = this.allSinks.filter(function(sink) {
      return sink.isPseudoSink && !!sink.domain;
    });
    this.rebuildSinksToShow_();
    this.searchEnabled_ = this.searchEnabled_ || this.pseudoSinks_.length > 0 ||
        this.sinksToShow_.length >= media_router.MINIMUM_SINKS_FOR_SEARCH;
    this.filterSinks_(this.searchInputText_ || '');
    if (this.currentView_ != media_router.MediaRouterView.FILTER) {
      // This code is in the unique position of seeing |animationPromise_| as
      // null on startup. |allSinks| is initialized before |animationPromise_|
      // and this listener runs when |allSinks| is initialized.
      if (this.animationPromise_) {
        this.animationPromise_ =
            this.animationPromise_.then(this.putSearchAtBottom_.bind(this));
      } else {
        this.putSearchAtBottom_();
      }
    } else {
      this.queuePutSearchAtTop_();
    }
  },

  /**
   * Resets the properties relevant to creating a new route. Fires an event
   * indicating whether or not route creation was successful.
   * Clearing |currentLaunchingSinkId_| hides the spinner indicating there is
   * a route creation in progress and show the device icon instead.
   * @param {boolean} creationSuccess Whether route creation succeeded.
   *
   * @private
   */
  resetRouteCreationProperties_: function(creationSuccess) {
    this.pseudoSinkSearchState_ = null;
    this.currentLaunchingSinkId_ = '';
    this.pendingCreatedRouteId_ = '';
    // If it was a search that failed we need to refresh the filtered sinks now
    // that |pseudoSinkSearchState_| is null.
    if (!creationSuccess &&
        this.currentView_ == media_router.MediaRouterView.FILTER) {
      this.filterSinks_(this.searchInputText_);
    }

    this.fire('report-route-creation', {success: creationSuccess});
  },

  /**
   * Responds to a click on the search button by toggling sink filtering.
   */
  searchButtonClick_: function() {
    // Redundancy needed because focus() only fires event if input is not
    // already focused. In the case that user typed text, hit escape, then
    // clicks the search button, a focus event will not fire and so its event
    // handler from ready() will not run.
    this.showSearchResults_();
    this.$$('#sink-search-input').focus();
  },

  /**
   * Initializes the position of the search input if search becomes enabled.
   * @param {boolean} searchEnabled The new value of |searchEnabled_|.
   * @private
   */
  searchEnabledChanged_: function(searchEnabled) {
    if (searchEnabled) {
      this.async(function() {
        this.setSearchFocusHandlers_();
        this.putSearchAtBottom_();
      });
    }
  },

  /**
   * Filters the sink list when the input text changes and shows the search
   * results if |searchInputText| is not empty.
   * @param {string} searchInputText The currently entered search text.
   * @private
   */
  searchInputTextChanged_: function(searchInputText) {
    this.filterSinks_(searchInputText);
    if (searchInputText.length != 0) {
      this.showSearchResults_();
      this.maybeReportFilter_();
    }
  },

  /**
   * Sets the selected cast mode to the one associated with |castModeType|,
   * and rebuilds sinks to reflect the change.
   * @param {number} castModeType The type of the selected cast mode.
   */
  selectCastMode: function(castModeType) {
    var castMode = this.findCastModeByType_(castModeType);
    if (castMode && castModeType != this.shownCastModeValue_) {
      this.setShownCastMode_(castMode);
      this.userHasSelectedCastMode_ = true;
      this.rebuildSinksToShow_();
    }
  },

  /**
   * Fires the command to open a file dialog.
   *
   * @private
   */
  selectLocalMediaFile_() {
    this.fire('select-local-media-file');
  },

  /**
   * Sets various focus and blur event handlers to handle showing search results
   * when the search input is focused.
   * @private
   */
  setSearchFocusHandlers_: function() {
    var searchInput = this.$$('#sink-search-input');
    var that = this;

    // The window can see a blur event for two important cases: the window is
    // actually losing focus or keyboard focus is wrapping from the end of the
    // document to the beginning. To handle both cases, we save whether the
    // search input was focused during the window blur event.
    //
    // When the search input receives focus, it could be as part of window
    // focus. If the search input was also focused on window blur, it shouldn't
    // show search results if they aren't already being shown. Otherwise,
    // focusing the search input should activate the FILTER view by calling
    // |showSearchResults_()|.
    window.addEventListener('blur', function() {
      that.isSearchFocusedOnWindowBlur_ =
          that.shadowRoot.activeElement == searchInput;
    });
    searchInput.addEventListener('focus', function() {
      if (!that.isSearchFocusedOnWindowBlur_) {
        that.showSearchResults_();
      }
    });
  },

  /**
   * Updates the shown cast mode, and updates the header text fields
   * according to the cast mode. If |castMode| type is AUTO, then set
   * |userHasSelectedCastMode_| to false.
   *
   * @param {!media_router.CastMode} castMode
   */
  setShownCastMode_: function(castMode) {
    if (this.shownCastModeValue_ == castMode.type) {
      return;
    }

    this.shownCastModeValue_ = castMode.type;
    this.headerText = castMode.description;
    this.headerTextTooltip = castMode.host || '';
    if (castMode.type == media_router.CastModeType.AUTO) {
      this.userHasSelectedCastMode_ = false;
    }
  },

  /**
   * Shows the cast mode list.
   *
   * @private
   */
  showCastModeList_: function() {
    this.currentView_ = media_router.MediaRouterView.CAST_MODE_LIST;
  },

  /**
   * Creates a new route if there is no route to the |sink| . Otherwise,
   * shows the route details.
   *
   * @param {!media_router.Sink} sink The sink to use.
   * @private
   */
  showOrCreateRoute_: function(sink) {
    var route = this.sinkToRouteMap_[sink.id];
    if (route) {
      this.showRouteDetails_(route);
      this.fire('navigate-sink-list-to-details');
      this.maybeReportUserFirstAction(
          media_router.MediaRouterUserAction.STATUS_REMOTE);
    } else if (this.currentLaunchingSinkId_ == '') {
      // Allow one launch at a time.
      var selectedCastModeValue =
          this.shownCastModeValue_ == media_router.CastModeType.AUTO ?
          sink.castModes & -sink.castModes :
          this.shownCastModeValue_;
      if (sink.isPseudoSink) {
        this.pseudoSinkSearchState_ = new PseudoSinkSearchState(sink);
        this.fire('search-sinks-and-create-route', {
          id: sink.id,
          name: sink.name,
          domain: sink.domain,
          selectedCastMode: selectedCastModeValue
        });
      } else {
        this.fire('create-route', {
          sinkId: sink.id,
          // If user selected a cast mode, then we will create a route using
          // that cast mode. Otherwise, the UI is in "auto" cast mode and will
          // use the preferred cast mode compatible with the sink. The preferred
          // cast mode value is the least significant bit on the bitset.
          selectedCastModeValue: selectedCastModeValue
        });

        var timeToSelectSink =
            window.performance.now() - this.populatedSinkListSeenTimeMs_;
        this.fire('report-sink-click-time', {timeMs: timeToSelectSink});
      }
      this.currentLaunchingSinkId_ = sink.id;
      if (sink.isPseudoSink) {
        this.rebuildSinksToShow_();
      }

      this.maybeReportUserFirstAction(
          media_router.MediaRouterUserAction.START_LOCAL);
    }
  },

  /**
   * Shows the route details.
   *
   * @param {!media_router.Route} route The route to show.
   * @private
   */
  showRouteDetails_: function(route) {
    this.currentRoute_ = route;
    this.currentView_ = media_router.MediaRouterView.ROUTE_DETAILS;
    if (route.supportsWebUiController) {
      media_router.browserApi.onMediaControllerAvailable(route.id);
    }
    if (this.$$('route-details')) {
      this.$$('route-details').onOpened();
    }
  },

  /**
   * Shows the search results.
   *
   * @private
   */
  showSearchResults_: function() {
    if (this.currentView_ != media_router.MediaRouterView.FILTER) {
      this.currentView_ = media_router.MediaRouterView.FILTER;
      this.queueMoveSearchToTop_();
    }
  },

  /**
   * Shows the sink list.
   *
   * @private
   */
  showSinkList_: function() {
    if (this.currentView_ == media_router.MediaRouterView.FILTER) {
      this.queueMoveSearchToBottom_();
      this.currentView_ = media_router.MediaRouterView.SINK_LIST;
    } else {
      this.currentView_ = media_router.MediaRouterView.SINK_LIST;
      this.putSearchAtBottom_();
    }
  },

  /**
   * Starts a timer which fires a close-dialog event if the user's mouse is
   * not positioned over the dialog after three seconds.
   *
   * @private
   */
  startTapTimer_: function() {
    var id = setTimeout(function() {
      if (!this.mouseIsPositionedOverDialog_) {
        this.fire('close-dialog', {
          pressEscToClose: false,
        });
      }
    }.bind(this), 3000 /* 3 seconds */);
  },

  /**
   * Toggles |currentView_| between CAST_MODE_LIST and SINK_LIST.
   *
   * @private
   */
  toggleCastModeHidden_: function() {
    if (this.currentView_ == media_router.MediaRouterView.CAST_MODE_LIST) {
      this.showSinkList_();
    } else if (this.currentView_ == media_router.MediaRouterView.SINK_LIST) {
      this.showCastModeList_();
      this.fire('navigate-to-cast-mode-list');
    }
  },

  /**
   * Update the position-related styling of some elements.
   *
   * @private
   */
  updateElementPositioning_: function() {
    // Ensures that conditionally templated elements have finished stamping.
    this.async(function() {
      var headerHeight = this.header.offsetHeight;
      // Unlike the other elements whose heights are fixed, the first-run-flow
      // element can have a fractional height. So we use getBoundingClientRect()
      // to avoid rounding errors.
      var firstRunFlowHeight = this.$$('#first-run-flow') &&
              this.$$('#first-run-flow').style.display != 'none' ?
          this.$$('#first-run-flow').getBoundingClientRect().height :
          0;
      var issueHeight = this.$$('#issue-banner') &&
              this.$$('#issue-banner').style.display != 'none' ?
          this.$$('#issue-banner').offsetHeight :
          0;
      var search = this.$$('#sink-search');
      var hasSearch = this.hasConditionalElement_(search);
      var searchHeight = hasSearch ? search.offsetHeight : 0;
      var searchPadding =
          hasSearch ? this.computeElementVerticalPadding_(search) : 0;

      this.header.style.marginTop = firstRunFlowHeight + 'px';
      this.$['content'].style.marginTop =
          firstRunFlowHeight + headerHeight + 'px';

      var sinkList = this.$$('#sink-list');
      var sinkListPadding =
          sinkList ? this.computeElementVerticalPadding_(sinkList) : 0;

      this.sinkListMaxHeight_ = this.dialogHeight_ - headerHeight -
          firstRunFlowHeight - issueHeight - searchHeight + searchPadding -
          sinkListPadding;

      // Limit the height of the dialog to ten items, including search.
      var sinkItemHeight = 41;
      var maxSinkItems = hasSearch ? 9 : 10;
      this.sinkListMaxHeight_ =
          Math.min(sinkItemHeight * maxSinkItems, this.sinkListMaxHeight_);
      if (sinkList) {
        sinkList.style.maxHeight = this.sinkListMaxHeight_ + 'px';
      }
    });
  },

  /**
   * Update the max dialog height and update the positioning of the elements.
   *
   * @param {number} height The max height of the Media Router dialog.
   */
  updateMaxDialogHeight: function(height) {
    this.dialogHeight_ = height;
    this.updateElementPositioning_();
  },

  /**
   * Sets the selected cast mode menu item to be in sync with the current cast
   * mode.
   * @private
   */
  updateSelectedCastModeMenuItem_: function() {
    /** @const */ var curIndex =
        this.findCastModeIndexByType_(this.shownCastModeValue_);
    if (this.selectedCastModeMenuItem_ != curIndex) {
      this.selectedCastModeMenuItem_ = curIndex;
    }
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../icons/media_router_icons.html">
<dom-module id="media-router-header">
  <link rel="import" type="css" href="../../media_router_common.css">
  <link rel="import" type="css" href="media_router_header.css">
  <template>
    <div id="header" class$="[[view]]">
      <div id="main-container">
        <template is="dom-if" if="[[computeBackButtonShown_(view)]]">
          <div id="back-button-container">
            <paper-icon-button id="back-button" icon="[[arrowDropIcon_]]"
                on-tap="onBackButtonClick_" title="[[i18n('backButtonTitle')]]">
            </paper-icon-button>
          </div>
        </template>
        <div id="header-and-arrow-container" on-tap="onHeaderOrArrowClick_">
          <span id="header-text" title="[[tooltip]]">
              [[headingText]]</span>
          <div id="arrow-drop-container">
            <paper-icon-button icon="[[computeArrowDropIcon_(view)]]"
                id="arrow-drop-icon" disabled$="[[arrowDropIconDisabled]]"
                hidden$="[[computeArrowDropIconHidden_(view)]]"
                title="[[computeArrowDropTitle_(view)]]">
            </paper-icon-button>
          </div>
        </div>
        <div id="close-button-container">
          <paper-icon-button icon="cr:close" id="close-button"
              on-tap="onCloseButtonClick_" title="[[i18n('closeButtonTitle')]]">
          </paper-icon-button>
        </div>
      </div>
      <template is="dom-if" if="[[showEmail]]">
        <div id="user-email-container">[[userEmail]]</div>
      </template>
    </div>
  </template>
<script src="media_router_header.js"></script>
</dom-module>
/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

#arrow-drop-container {
  flex-grow: 1;
}

#arrow-drop-icon {
  height: var(--navigation-icon-button-size);
  width: var(--navigation-icon-button-size);
}

#back-button {
  height: var(--navigation-icon-button-size);
  width: var(--navigation-icon-button-size);
}

#back-button-container {
  padding-inline-end: 4px;
}

#close-button {
  height: 31px;
  margin-inline-start: auto;
  width: 31px;
}

#close-button-container {
  margin-inline-start: auto;
  padding-inline-end: 16px;
  padding-inline-start: 24px;
}

#header {
  align-items: center;
  color: white;
  padding-inline-start: 8px;
}

#header-and-arrow-container {
  display: flex;
  overflow: hidden;
  white-space: nowrap;
}

#header-text {
  font-size: 1.175em;
  line-height: 36px;
  margin: 0 8px;
  overflow: hidden;
  padding-inline-end: 4px;
  text-overflow: ellipsis;
}

.issue {
  background-color: var(--paper-red-700);
}

paper-icon-button {
  display: inline-block;
}

#main-container {
  display: flex;
  padding-top: 10px;
}

.cast-mode-list,
.filter,
.route-details,
.sink-list {
  background-color: var(--paper-blue-700);
}

#user-email-container {
  bottom: 0;
  font-size: 0.917em;
  left: auto;
  padding-bottom: 12px;
  padding-inline-start: 8px;
  position: absolute;
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This Polymer element is used as a header for the media router interface.
Polymer({
  is: 'media-router-header',

  properties: {
    /**
     * The name of the icon used as the back button. This is set once, when
     * the |this| is ready.
     * @private {string|undefined}
     */
    arrowDropIcon_: {
      type: String,
    },

    /**
     * Whether or not the arrow drop icon should be disabled.
     * @type {boolean}
     */
    arrowDropIconDisabled: {
      type: Boolean,
      value: false,
    },

    /**
     * The header text to show.
     * @type {string|undefined}
     */
    headingText: {
      type: String,
    },

    /**
     * The height of the header when it shows the user email.
     * @private {number}
     */
    headerWithEmailHeight_: {
      type: Number,
      readOnly: true,
      value: 62,
    },

    /**
     * The height of the header when it doesn't show the user email.
     * @private {number}
     */
    headerWithoutEmailHeight_: {
      type: Number,
      readOnly: true,
      value: 52,
    },

    /**
     * Whether to show the user email in the header.
     * @type {boolean|undefined}
     */
    showEmail: {
      type: Boolean,
      observer: 'maybeChangeHeaderHeight_',
    },

    /**
     * The text to show in the tooltip.
     * @type {string|undefined}
     */
    tooltip: {
      type: String,
    },

    /**
     * The user email if they are signed in.
     * @type {string|undefined}
     */
    userEmail: {
      type: String,
    },

    /**
     * The current view that this header should reflect.
     * @type {?media_router.MediaRouterView|undefined}
     */
    view: {
      type: String,
      observer: 'updateHeaderCursorStyle_',
    },
  },

  behaviors: [
    I18nBehavior,
  ],

  ready: function() {
    this.$$('#header').style.height = this.headerWithoutEmailHeight_ + 'px';
  },

  attached: function() {
    // isRTL() only works after i18n_template.js runs to set <html dir>.
    // Set the back button icon based on text direction.
    this.arrowDropIcon_ = isRTL() ? 'cr:arrow-forward' : 'cr:arrow-back';
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @return {string} The icon to use.
   * @private
   */
  computeArrowDropIcon_: function(view) {
    return view == media_router.MediaRouterView.CAST_MODE_LIST ?
        'cr:arrow-drop-up' :
        'cr:arrow-drop-down';
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @return {boolean} Whether or not the arrow drop icon should be hidden.
   * @private
   */
  computeArrowDropIconHidden_: function(view) {
    return view != media_router.MediaRouterView.SINK_LIST &&
        view != media_router.MediaRouterView.CAST_MODE_LIST;
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @return {string} The title text for the arrow drop button.
   * @private
   */
  computeArrowDropTitle_: function(view) {
    return view == media_router.MediaRouterView.CAST_MODE_LIST ?
        this.i18n('viewDeviceListButtonTitle') :
        this.i18n('viewCastModeListButtonTitle');
  },

  /**
   * @param {?media_router.MediaRouterView} view The current view.
   * @return {boolean} Whether or not the back button should be shown.
   * @private
   */
  computeBackButtonShown_: function(view) {
    return view == media_router.MediaRouterView.ROUTE_DETAILS ||
        view == media_router.MediaRouterView.FILTER;
  },

  /**
   * Returns whether given string is undefined, null, empty, or whitespace only.
   * @param {?string} str String to be tested.
   * @return {boolean} |true| if the string is undefined, null, empty, or
   *     whitespace.
   * @private
   */
  isEmptyOrWhitespace_: function(str) {
    return str === undefined || str === null || (/^\s*$/).test(str);
  },

  /**
   * Handles a click on the back button by firing a back-click event.
   *
   * @private
   */
  onBackButtonClick_: function() {
    this.fire('back-click');
  },

  /**
   * Handles a click on the close button by firing a close-button-click event.
   *
   * @private
   */
  onCloseButtonClick_: function() {
    this.fire('close-dialog', {
      pressEscToClose: false,
    });
  },

  /**
   * Handles a click on the arrow button by firing an arrow-click event.
   *
   * @private
   */
  onHeaderOrArrowClick_: function() {
    if (this.view == media_router.MediaRouterView.SINK_LIST ||
        this.view == media_router.MediaRouterView.CAST_MODE_LIST) {
      this.fire('header-or-arrow-click');
    }
  },

  /**
   * Updates header height to accomodate email text. This is called on changes
   * to |showEmail| and will return early if the value has not changed.
   *
   * @param {boolean} newValue The new value of |showEmail|.
   * @param {boolean} oldValue The previous value of |showEmail|.
   * @private
   */
  maybeChangeHeaderHeight_: function(newValue, oldValue) {
    if (oldValue == newValue) {
      return;
    }

    // Ensures conditional templates are stamped.
    this.async(function() {
      var currentHeight = this.offsetHeight;

      this.$$('#header').style.height =
          this.showEmail && !this.isEmptyOrWhitespace_(this.userEmail) ?
          this.headerWithEmailHeight_ + 'px' :
          this.headerWithoutEmailHeight_ + 'px';

      // Only fire if height actually changed.
      if (currentHeight != this.offsetHeight) {
        this.fire('header-height-changed');
      }
    });
  },

  /**
   * Updates the cursor style for the header text when the view changes. When
   * the drop arrow is also shown, the header text is also clickable.
   *
   * @param {?media_router.MediaRouterView} view The current view.
   * @private
   */
  updateHeaderCursorStyle_: function(view) {
    this.$$('#header-text').style.cursor =
        view == media_router.MediaRouterView.SINK_LIST ||
            view == media_router.MediaRouterView.CAST_MODE_LIST ?
        'pointer' :
        'auto';
  },
});
/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.highlight {
  font-weight: bold;
}
<link rel="import" href="chrome://resources/html/polymer.html">
<dom-module id="media-router-search-highlighter">
  <link rel="import" type="css" href="media_router_search_highlighter.css">
  <template>
    <span id="text" dir="auto"></span>
  </template>
</dom-module>
<script src="media_router_search_highlighter.js"></script>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This Polymer element displays text that needs sections of it highlighted.
// This is useful, for example, for displaying which portions of a string were
// matched by some filter text.
Polymer({
  is: 'media-router-search-highlighter',

  properties: {
    /**
     * The text that this element should display, split it into highlighted and
     * normal text. The displayed text will alternate between plainText and
     * highlightedText.
     *
     * Example: You have a sink with the name 'living room'.
     * When your seach text is 'living', the resulting arrays will be:
     *     plainText: [null, ' room'], highlightedText: ['living', null]
     *
     * When your search text is 'room', the resulting arrays will be:
     *     plainText: ['living ', null], highlightedText: [null, 'room']
     *
     * null corresponds to an empty string when the arrays are being combined.
     * So both examples reproduce the text 'living room', but with different
     * words highlighted.
     * @type {{highlightedText: !Array<?string>,
     *         plainText: !Array<?string>}|undefined}
     */
    data: {
      type: Object,
      observer: 'dataChanged_',
    },

    /**
     * The text that this element is displaying as a plain string. The primary
     * purpose for this property is to make getting this element's textContent
     * easy for testing.
     * @type {string|undefined}
     */
    text: {
      type: String,
      readOnly: true,
      notify: false,
    },
  },

  /**
   * Update the element text if |data| changes.
   *
   * The order the strings are combined is plainText[0] highlightedText[0]
   * plainText[1] highlightedText[1] etc.
   *
   * @param {{highlightedText: !Array<?string>, plainText: !Array<?string>}}
   *    data
   * Parameters in |data|:
   *   highlightedText - Array of strings that should be displayed highlighted.
   *   plainText - Array of strings that should be displayed normally.
   */
  dataChanged_: function(data) {
    if (!data || !data.highlightedText || !data.plainText) {
      return;
    }

    var text = '';
    for (var i = 0; i < data.highlightedText.length; ++i) {
      if (data.plainText[i]) {
        text += HTMLEscape(/** @type {!string} */ (data.plainText[i]));
      }
      if (data.highlightedText[i]) {
        text += '<span class="highlight">' +
            HTMLEscape(/** @type {!string} */ (data.highlightedText[i])) +
            '</span>';
      }
    }
    this.$.text.innerHTML = text;
    this._setText(this.$.text.textContent);
  },
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
<link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">

<iron-iconset-svg name="route-controls" size="24">
<svg><defs>
  <g id="play-arrow"><path d="M8 5v14l11-7z"></path></g>
  <g id="pause"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"></path></g>
  <g id="volume-off"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"></path></g>
  <g id="volume-up"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"></path></g>
</defs></svg>
</iron-iconset-svg>

<dom-module id="route-controls">
  <link rel="import" type="css" href="../../media_router_common.css">
  <link rel="import" type="css" href="route_controls.css">
  <template>
    <style include="md-select"></style>
    <div id="media-controls">
      <div class="ellipsis" id="route-description"
           title="[[routeDescription_]]">
        [[routeDescription_]]
      </div>
      <div class="ellipsis" id="route-title" title="[[routeStatus.title]]"
           hidden$="[[!shouldShowRouteStatusTitle_]]">
        [[routeStatus.title]]
      </div>
      <div>
        <div id="route-time-controls" hidden="[[!routeStatus.canSeek]]">
          <cr-slider
              aria-valuetext$="[[getTimeSliderValueText_(displayedCurrentTime_)]]"
              dir="ltr"
              id="route-time-slider"
              on-dragging-changed="onSeekingChanged_"
              on-cr-slider-value-changed="onSeekSliderValueChanged_"
              min="0" max="[[routeStatus.duration]]"
              title="[[i18n('seekTitle')]]"
              value="[[displayedCurrentTime_]]"></cr-slider>
          <div id="timeline">
            <span id="current-time"
                  aria-label$="[[getCurrentTimeLabel_(displayedCurrentTime_)]]">
              [[getFormattedTime_(displayedCurrentTime_)]]
            </span>
            <span id="duration"
                  aria-label$="[[getDurationLabel_(routeStatus.duration)]]">
              [[getFormattedTime_(routeStatus.duration)]]
            </span>
          </div>
        </div>
        <div id="play-pause-volume-hangouts-controls">
          <span id="button-holder" dir="ltr">
            <paper-icon-button
                id="route-play-pause-button"
                hidden="[[!routeStatus.canPlayPause]]"
                disabled="[[!routeStatus.canPlayPause]]"
                icon="[[getPlayPauseIcon_(routeStatus)]]"
                title="[[getPlayPauseTitle_(routeStatus)]]"
                on-click="onPlayPause_"></paper-icon-button>
            <paper-icon-button
                id="route-volume-button"
                hidden="[[!routeStatus.canMute]]"
                disabled="[[!routeStatus.canMute]]"
                icon="[[getMuteUnmuteIcon_(routeStatus)]]"
                title="[[getMuteUnmuteTitle_(routeStatus)]]"
                on-click="onMuteUnmute_"></paper-icon-button>
          </span>
          <span id="volume-holder" hidden="[[!routeStatus.canSetVolume]]">
            <cr-slider
                aria-valuetext$="[[getVolumeSliderValueText_(displayedVolume_)]]"
                id="route-volume-slider"
                disabled="[[!routeStatus.canSetVolume]]"
                on-cr-slider-value-changed="onVolumeChanged_"
                on-dragging-changed="onVolumeDraggingChanged_"
                title="[[i18n('volumeTitle')]]"></cr-slider>
          </span>
          <div id="hangouts-local-present-controls"
               hidden="[[!routeStatus.hangoutsExtraData]]">
            <cr-checkbox
                checked="[[hangoutsLocalPresent_]]"
                id="hangouts-local-present-checkbox"
                on-change="onHangoutsLocalPresentChange_"
                tabindex="0">
              <span id='hangouts-local-present-checkbox-title'>
                [[i18n('hangoutsLocalPresentTitle')]]
              </span>
              <span id="hangouts-local-present-checkbox-subtitle">
                [[i18n('hangoutsLocalPresentSubtitle')]]
              </span>
            </cr-checkbox>
          </div>
        </div>
        <div id="mirroring-fullscreen-video-controls"
            hidden="[[!routeStatus.mirroringExtraData]]">
          [[i18n('fullscreenVideosDropdownTitle')]]
          <select class="md-select"
              id="mirroring-fullscreen-video-dropdown"
              on-change="onFullscreenVideoDropdownChange_">
            <option value="[[FullscreenVideoOption_.REMOTE_SCREEN]]">
              [[i18n('fullscreenVideosRemoteScreen')]]
            </option>
            <option value="[[FullscreenVideoOption_.BOTH_SCREENS]]">
              [[i18n('fullscreenVideosBothScreens')]]
            </option>
          </select>
        </div>
      </div>
    </div>
  </template>
<script src="route_controls.js"></script>
</dom-module>
/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

#button-holder {
  float: left;
}

#current-time {
  left: 20px;
  position: absolute;
}

#duration {
  position: absolute;
  right: 20px;
}

:host-context([dir='rtl']) #play-pause-volume-hangouts-controls {
  transform: scaleX(-1);
}

:host-context([dir='rtl']) #route-play-pause-button {
  transform: scaleX(-1);
}

:host-context([dir='rtl']) #volume-holder {
  transform: scaleX(-1);
}

#media-controls {
  font-size: 1.25em;
  margin: 0 8px;
}

#play-pause-volume-hangouts-controls {
  display: block;
  margin-top: 13px;
  overflow: hidden;
}

#route-description {
  margin: 15px 8px 3px 8px;
  width: 90%;
}

#route-time-controls {
  display: block;
  margin-top: 3px;
  overflow: hidden;
}

#route-time-slider {
  --cr-slider-active-color: rgb(16, 16, 16);
  --cr-slider-container-color: rgba(16, 16, 16, .24);
  --cr-slider-knob-color: rgb(16, 16, 16);
  width: 100%;
}

#route-title {
  color: rgb(125, 125, 125);
  margin: 3px 8px;
}

#route-volume-slider {
  --cr-slider-active-color: rgb(33, 150, 243);
  --cr-slider-container-color: rgba(16, 16, 16, .24);
  --cr-slider-knob-color: rgb(16, 16, 16);
  width: 100%;
}

#timeline {
  font-size: 0.75em;
}

#volume-holder {
  display: block;
  overflow: hidden;
  padding: 0.3em 0;
}

#hangouts-local-present-controls {
  cursor: pointer;
  display: inline-block;
  float: right;
  padding-top: 10.5px;
  white-space: nowrap;
}

#hangouts-local-present-checkbox {
  --cr-checkbox-label-container: {
    padding-inline-start: 14px;
  }
  align-items: start;
}

#hangouts-local-present-checkbox-subtitle {
  display: block;
  font-size: 0.8em;
  margin-top: 2px;
  width: 249px;
}

#mirroring-fullscreen-video-controls {
  display: inline-block;
  font-size: 0.8em;
  margin: 15px 8px 3px 8px;
  vertical-align: middle;
}

#mirroring-fullscreen-video-dropdown {
  margin-inline-start: 8px;
  width: auto;
}
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * This Polymer element shows media controls for a route that is currently cast
 * to a device.
 * @implements {RouteControlsInterface}
 */
Polymer({
  is: 'route-controls',

  properties: {
    /**
     * Set of possible options for playing fullscreen videos when mirroring.
     * @private {!Object}
     */
    FullscreenVideoOption_: {
      type: Object,
      value: {
        // Play on remote screen only.
        REMOTE_SCREEN: 'remote_screen',
        // Play on both remote and local screens.
        BOTH_SCREENS: 'both_screens'
      }
    },

    /**
     * The current time displayed in seconds, before formatting.
     * @private {number}
     */
    displayedCurrentTime_: {
      type: Number,
      value: 0,
    },

    /**
     * The volume shown in the volume control, between 0 and 1.
     * @private {number}
     */
    displayedVolume_: {
      type: Number,
      value: 0,
    },

    /**
     * True if the Hangouts route is currently using local present mode.
     * Valid for Hangouts routes only.
     * @private {boolean}
     */
    hangoutsLocalPresent_: {
      type: Boolean,
      value: false,
    },

    /**
     * The timestamp for when the initial media status was loaded.
     * @private {number}
     */
    initialLoadTime_: {
      type: Number,
      value: 0,
    },

    /**
     * Set to true when the user is dragging the seek bar. Updates for the
     * current time from the browser will be ignored when set to true.
     * @private {boolean}
     */
    isSeeking_: {
      type: Boolean,
      value: false,
    },

    /**
     * Set to true when the user is dragging the volume bar. Volume updates from
     * the browser will be ignored when set to true.
     * @private
     */
    isVolumeChanging_: {
      type: Boolean,
      value: false,
    },

    /**
     * The timestamp for when the controller last submitted a seek request.
     * @private
     */
    lastSeekByUser_: {
      type: Number,
      value: 0,
    },

    /**
     * The timestamp for when |routeStatus| was last updated.
     * @private
     */
    lastStatusUpdate_: {
      type: Number,
      value: 0,
    },

    /**
     * The timestamp for when the controller last submitted a volume change
     * request.
     * @private
     */
    lastVolumeChangeByUser_: {
      type: Number,
      value: 0,
    },

    /**
     * Keep in sync with media remoting individual user setting.
     * @private
     */
    mediaRemotingEnabled_: {
      type: Boolean,
      value: true,
    },

    /**
     * The route currently associated with this controller.
     * @type {?media_router.Route|undefined}
     */
    route: {
      type: Object,
      observer: 'onRouteUpdated_',
    },

    /**
     * The route description to display. Uses the media route description if
     * none is provided by the media route status object.
     * @private {string}
     */
    routeDescription_: {
      type: String,
      value: '',
    },

    /**
     * The timestamp for when the route details view was opened.
     * @type {number}
     */
    routeDetailsOpenTime: {
      type: Number,
      value: 0,
    },

    /**
     * The status of the media route shown.
     * @type {!media_router.RouteStatus}
     */
    routeStatus: {
      type: Object,
      observer: 'onRouteStatusChange_',
      value: new media_router.RouteStatus(),
    },

    /**
     * The ID of the timer currently set to increment the current time of the
     * media, or 0 if the current time is not being incremented.
     * @private {number}
     */
    timeIncrementsTimeoutId_: {
      type: Number,
      value: 0,
    },

    /**
     * Whether the controls should show the media title.
     * @private {boolean}
     */
    shouldShowRouteStatusTitle_: {
      type: Boolean,
      value: false,
    },
  },

  behaviors: [
    I18nBehavior,
  ],

  /**
   * Called by Polymer when the element loads. Registers the element to be
   * notified of route status updates.
   */
  ready: function() {
    media_router.ui.setRouteControls(
        /** @type {RouteControlsInterface} */ (this));
  },

  /**
   * Current time can be incremented if the media is playing, and either the
   * duration is 0 or current time is less than the duration.
   * @return {boolean}
   * @private
   */
  canIncrementCurrentTime_: function() {
    return !this.isSeeking_ &&
        this.routeStatus.playState === media_router.PlayState.PLAYING &&
        (this.routeStatus.duration === 0 ||
         this.displayedCurrentTime_ < this.routeStatus.duration);
  },

  /**
   * Creates an accessibility label for the element showing the media's current
   * time.
   * @param {number} displayedCurrentTime
   * @return {string}
   * @private
   */
  getCurrentTimeLabel_: function(displayedCurrentTime) {
    return `${
              this.i18n('currentTimeLabel')
            } ${this.getFormattedTime_(displayedCurrentTime)}`;
  },

  /**
   * Creates an accessibility label for the element showing the media's
   * duration.
   * @param {number} duration
   * @return {string}
   * @private
   */
  getDurationLabel_: function(duration) {
    return `${this.i18n('durationLabel')} ${this.getFormattedTime_(duration)}`;
  },

  /**
   * Converts a number representing an interval of seconds to a string with
   * HH:MM:SS format.
   * @param {number} timeInSec Must be non-negative. Intervals longer than 100
   *     hours get truncated silently.
   * @return {string}
   * @private
   */
  getFormattedTime_: function(timeInSec) {
    if (timeInSec < 0) {
      return '';
    }
    var hours = Math.floor(timeInSec / 3600);
    var minutes = Math.floor(timeInSec / 60) % 60;
    var seconds = Math.floor(timeInSec) % 60;
    // Show the hours only if it is nonzero.
    return (hours ? ('0' + hours).substr(-2) + ':' : '') +
        ('0' + minutes).substr(-2) + ':' + ('0' + seconds).substr(-2);
  },

  /**
   * @param {!media_router.RouteStatus} routeStatus
   * @return {string} The value for the icon attribute of the mute/unmute
   *     button.
   * @private
   */
  getMuteUnmuteIcon_: function(routeStatus) {
    return routeStatus.isMuted ? 'route-controls:volume-off' :
                                 'route-controls:volume-up';
  },

  /**
   * @param {!media_router.RouteStatus} routeStatus
   * @return {string} Localized title for the mute/unmute button.
   * @private
   */
  getMuteUnmuteTitle_: function(routeStatus) {
    return routeStatus.isMuted ? this.i18n('unmuteTitle') :
                                 this.i18n('muteTitle');
  },

  /**
   * @param {!media_router.RouteStatus} routeStatus
   * @return {string}The value for the icon attribute of the play/pause button.
   * @private
   */
  getPlayPauseIcon_: function(routeStatus) {
    return routeStatus.playState === media_router.PlayState.PAUSED ?
        'route-controls:play-arrow' :
        'route-controls:pause';
  },

  /**
   * @param {!media_router.RouteStatus} routeStatus
   * @return {string} Localized title for the play/pause button.
   * @private
   */
  getPlayPauseTitle_: function(routeStatus) {
    return routeStatus.playState === media_router.PlayState.PAUSED ?
        this.i18n('playTitle') :
        this.i18n('pauseTitle');
  },

  /**
   * @return {string} Text representing the current position on the seek slider.
   * @private
   */
  getTimeSliderValueText_: function(displayedCurrentTime) {
    if (!this.routeStatus) {
      return '';
    }
    return `${
              this.getFormattedTime_(displayedCurrentTime)
            } / ${this.getFormattedTime_(this.routeStatus.duration)}`;
  },

  /**
   * @param {number} volume
   * @return {string} The volume as a percentage.
   * @private
   */
  getVolumeSliderValueText_: function(volume) {
    return String(Math.round(volume * 100)) + '%';
  },

  /**
   * Checks whether the media is still playing, and if so, sends a media status
   * update incrementing the current time and schedules another call for a
   * second later.
   * @private
   */
  maybeIncrementCurrentTime_: function() {
    if (this.canIncrementCurrentTime_()) {
      var updatedCurrentTime = this.routeStatus.currentTime +
          Math.floor((Date.now() - this.lastStatusUpdate_) / 1000);
      this.displayedCurrentTime_ = this.routeStatus.duration === 0 ?
          updatedCurrentTime :
          Math.min(updatedCurrentTime, this.routeStatus.duration);
      if (this.routeStatus.duration === 0 ||
          this.displayedCurrentTime_ < this.routeStatus.duration) {
        this.timeIncrementsTimeoutId_ =
            setTimeout(() => this.maybeIncrementCurrentTime_(), 1000);
      }
    } else {
      this.timeIncrementsTimeoutId_ = 0;
    }
  },

  /**
   * Called when the "smooth motion" box for Hangouts is changed by the user.
   * @param {!{target: !HTMLElement}} e
   * @private
   */
  onHangoutsLocalPresentChange_: function(e) {
    media_router.browserApi.setHangoutsLocalPresent(e.target.checked);
  },

  /**
   * Called when the user toggles the mute status of the media. Sends a mute or
   * unmute command to the browser.
   * @private
   */
  onMuteUnmute_: function() {
    media_router.browserApi.setCurrentMediaMute(!this.routeStatus.isMuted);
  },

  /**
   * Called when the user toggles between playing and pausing the media. Sends a
   * play or pause command to the browser.
   * @private
   */
  onPlayPause_: function() {
    if (this.routeStatus.playState === media_router.PlayState.PAUSED) {
      media_router.browserApi.playCurrentMedia();
    } else {
      media_router.browserApi.pauseCurrentMedia();
    }
  },

  /**
   * Updates seek and volume bars if the user is not currently dragging on
   * them.
   * @param {!media_router.RouteStatus} newRouteStatus
   * @private
   */
  onRouteStatusChange_: function(newRouteStatus) {
    this.lastStatusUpdate_ = Date.now();
    if (this.shouldAcceptCurrentTimeUpdates_()) {
      this.displayedCurrentTime_ = newRouteStatus.currentTime;
    }
    if (this.shouldAcceptVolumeUpdates_()) {
      const volume = Math.round(newRouteStatus.volume * 100);
      this.$['route-volume-slider'].value = volume;
      this.displayedVolume_ = volume / 100;
    }
    if (!this.initialLoadTime_) {
      this.initialLoadTime_ = Date.now();
      media_router.browserApi.reportWebUIRouteControllerLoaded(
          this.initialLoadTime_ - this.routeDetailsOpenTime);
    }
    this.stopIncrementingCurrentTime_();
    if (this.canIncrementCurrentTime_()) {
      this.timeIncrementsTimeoutId_ =
          setTimeout(() => this.maybeIncrementCurrentTime_(), 1000);
    }
    this.hangoutsLocalPresent_ = !!newRouteStatus.hangoutsExtraData &&
        newRouteStatus.hangoutsExtraData.localPresent;
    if (newRouteStatus.mirroringExtraData) {
      // Manually update the selected value on the
      // mirroring-fullscreen-video-dropdown dropbox.
      // TODO(imcheng): Avoid doing this by wrapping the dropbox in a Polymer
      // template, or introduce <paper-dropdown-menu> to the Polymer library.
      this.$['mirroring-fullscreen-video-dropdown'].value =
          newRouteStatus.mirroringExtraData.mediaRemotingEnabled ?
          this.FullscreenVideoOption_.REMOTE_SCREEN :
          this.FullscreenVideoOption_.BOTH_SCREENS;
    }
    this.shouldShowRouteStatusTitle_ = !!newRouteStatus.title &&
        newRouteStatus.title != '' &&
        newRouteStatus.title != this.routeDescription_;
  },

  /**
   * Called when the route is updated. Updates the description shown if it has
   * not been provided by status updates.
   * @param {?media_router.Route} route
   * @private
   */
  onRouteUpdated_: function(route) {
    if (!route) {
      this.stopIncrementingCurrentTime_();
    }
    if (route) {
      this.routeDescription_ = route.description;
    }
  },

  /** @private */
  updateTime_: function() {
    this.stopIncrementingCurrentTime_();
    this.displayedCurrentTime_ = this.$['route-time-slider'].value;
    if (!this.isSeeking_) {
      media_router.browserApi.seekCurrentMedia(this.displayedCurrentTime_);
      this.lastSeekByUser_ = Date.now();
    }
  },

  /**
   * @param {!{detail: {value: boolean}}} e
   * @private
   */
  onSeekingChanged_: function(e) {
    this.isSeeking_ = e.detail.value;
    this.updateTime_();
  },

  /** @private */
  onSeekSliderValueChanged_: function() {
    this.updateTime_();
  },

  /** @private */
  updateVolume_: function() {
    this.lastVolumeChangeByUser_ = Date.now();
    const volume = this.$['route-volume-slider'].value / 100;
    if (volume == this.displayedVolume_) {
      return;
    }
    this.displayedVolume_ = volume;
    media_router.browserApi.setCurrentMediaVolume(volume);
  },

  /**
   * Called when the user updates volume with the slider.
   * @private
   */
  onVolumeChanged_: function() {
    /** @const */ var currentTime = Date.now();
    // We limit the frequency of volume change requests during dragging to
    // limit the number of Mojo calls to the component extension.
    if (currentTime - this.lastVolumeChangeByUser_ < 300) {
      return;
    }
    this.updateVolume_();
  },

  /**
   * @param {!{detail: {value: boolean}}} e
   * @private
   */
  onVolumeDraggingChanged_: function(e) {
    if (!!this.isVolumeChanging_ == !!e.detail.value) {
      return;
    }
    this.isVolumeChanging_ = e.detail.value;
    if (!this.isVolumeChanging_) {
      this.updateVolume_();
    }
  },

  /**
   * Called when the value on the mirroring-fullscreen-video-dropdown dropdown
   * menu changes.
   * @param {!Event} e
   * @private
   */
  onFullscreenVideoDropdownChange_: function(e) {
    /** @const */ var dropdownValue =
        this.$['mirroring-fullscreen-video-dropdown'].value;
    media_router.browserApi.setMediaRemotingEnabled(
        dropdownValue == this.FullscreenVideoOption_.REMOTE_SCREEN);
  },

  /**
   * Resets the route controls. Called when the route details view is closed.
   */
  reset: function() {
    this.routeStatus = new media_router.RouteStatus();
    media_router.ui.setRouteControls(null);
  },

  /**
   * @return {boolean} Whether external current time updates should be reflected
   *     on the seek slider.
   * @private
   */
  shouldAcceptCurrentTimeUpdates_: function() {
    // Ignore external updates immediately after internal updates, because it's
    // likely to just be internal updates coming back from the device, and could
    // make the slider knob jump around.
    return !this.isSeeking_ && Date.now() - this.lastSeekByUser_ > 1000;
  },

  /**
   * @return {boolean} Whether external volume updates should be reflected on
   *     the volume slider.
   * @private
   */
  shouldAcceptVolumeUpdates_: function() {
    // Ignore external updates immediately after internal updates, because it's
    // likely to just be internal updates coming back from the device, and could
    // make the slider knob jump around.
    return !this.isVolumeChanging_ &&
        Date.now() - this.lastVolumeChangeByUser_ > 1000;
  },

  /**
   * If it is currently incrementing the current time shown, then stops doing
   * so.
   * @private
   */
  stopIncrementingCurrentTime_: function() {
    if (this.timeIncrementsTimeoutId_) {
      clearTimeout(this.timeIncrementsTimeoutId_);
      this.timeIncrementsTimeoutId_ = 0;
    }
  }
});
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="../route_controls/route_controls.html">
<dom-module id="route-details">
  <link rel="import" type="css" href="../../media_router_common.css">
  <link rel="import" type="css" href="route_details.css">
  <template>
    <div class="ellipsis" id="route-description"
         title="[[routeDescription_]]"
         hidden$="[[shouldShowWebUiControls_(route)]]">
      [[routeDescription_]]
    </div>
    <template is="dom-if" if="[[shouldShowWebUiControls_(route)]]">
      <route-controls id="route-controls"
          route-details-open-time="[[openTime_]]"
          route="[[route]]"></route-controls>
    </template>
    <div id="route-action-buttons" class="layout">
      <paper-button flat class="route-button button"
          id="start-casting-to-route-button"
          hidden$="[[computeCastButtonHidden_(route, changeRouteSourceAvailable_)]]"
          on-tap="startCastingToRoute_">
        <span>[[i18n('startCastingButtonText')]]</span>
      </paper-button>
      <paper-button flat class="route-button button"
          id="close-route-button"
          on-tap="closeRoute_">
        <span>[[i18n('stopCastingButtonText')]]</span>
      </paper-button>
    <div>
  </template>
<script src="route_details.js"></script>
</dom-module>
/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

#route-action-buttons {
  @apply --layout-horizontal;
  @apply --layout-end-justified;
  margin: 0 10px;
  padding: 0;
  white-space: nowrap;
}

.route-button {
  background-color: white;
  line-height: 12px;
  margin: 12px 0;
  text-align: end;
}

#route-description {
  font-size: 1.2em;
  line-height: 1.5em;
  margin-top: 16px;
  padding-inline-end: var(--dialog-padding-end);
  padding-inline-start: 44px;
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This Polymer element shows information from media that is currently cast
// to a device.
Polymer({
  is: 'route-details',

  properties: {
    /**
     * Description of the current casting activity, e.g. "Casting YouTube".
     * @private {string|undefined}
     */
    routeDescription_: {
      type: String,
    },

    /**
     * Whether the external container will accept change-route-source-click
     * events.
     * @private {boolean}
     */
    changeRouteSourceAvailable_: {
      type: Boolean,
      computed: 'computeChangeRouteSourceAvailable_(route, sink,' +
          'isAnySinkCurrentlyLaunching, shownCastModeValue)',
    },

    /**
     * Whether a sink is currently launching in the container.
     * @type {boolean}
     */
    isAnySinkCurrentlyLaunching: {
      type: Boolean,
      value: false,
    },

    /**
     * The timestamp for when the route details view was opened. We initialize
     * the value in a function so that the value is set when the element is
     * loaded, rather than at page load.
     * @private {number}
     */
    openTime_: {
      type: Number,
      value: function() {
        return Date.now();
      },
    },

    /**
     * The route to show.
     * @type {?media_router.Route|undefined}
     */
    route: {
      type: Object,
      observer: 'onRouteChange_',
    },

    /**
     * The cast mode shown to the user. Initially set to auto mode. (See
     * media_router.CastMode documentation for details on auto mode.)
     * @type {number}
     */
    shownCastModeValue: {
      type: Number,
      value: media_router.AUTO_CAST_MODE.type,
    },

    /**
     * Sink associated with |route|.
     * @type {?media_router.Sink}
     */
    sink: {
      type: Object,
      value: null,
    },
  },

  behaviors: [
    I18nBehavior,
  ],

  /**
   * Fires a close-route event. This is called when the button to close
   * the current route is clicked.
   *
   * @private
   */
  closeRoute_: function() {
    this.fire('close-route', {route: this.route});
  },

  /**
   * @param {?media_router.Route|undefined} route
   * @param {boolean} changeRouteSourceAvailable
   * @return {boolean} Whether to show the button that allows casting to the
   *     current route or the current route's sink.
   */
  computeCastButtonHidden_: function(route, changeRouteSourceAvailable) {
    if (route === undefined || changeRouteSourceAvailable === undefined) {
      return false;
    }

    return !((route && route.canJoin) || changeRouteSourceAvailable);
  },

  /**
   * @param {?media_router.Route|undefined} route The current route for the
   *     route details view.
   * @param {?media_router.Sink|undefined} sink Sink associated with |route|.
   * @param {boolean} isAnySinkCurrentlyLaunching Whether a sink is launching
   *     now.
   * @param {number} shownCastModeValue Currently selected cast mode value or
   *     AUTO if no value has been explicitly selected.
   * @return {boolean} Whether the change route source function should be
   *     available when displaying |currentRoute| in the route details view.
   *     Changing the route source should not be available when the currently
   *     selected source that would be cast is the same as the route's current
   *     source.
   * @private
   */
  computeChangeRouteSourceAvailable_: function(
      route, sink, isAnySinkCurrentlyLaunching, shownCastModeValue) {
    if (isAnySinkCurrentlyLaunching || !route || !sink) {
      return false;
    }
    if (!route.currentCastMode) {
      return true;
    }
    var selectedCastMode =
        this.computeSelectedCastMode_(shownCastModeValue, sink);
    return (selectedCastMode != 0) &&
        (selectedCastMode != route.currentCastMode);
  },

  /**
   * @param {number} castMode User selected cast mode or AUTO.
   * @param {?media_router.Sink} sink Sink to which we will cast.
   * @return {number} The selected cast mode when |castMode| is selected in the
   *     dialog and casting to |sink|.  Returning 0 means there is no cast mode
   *     available to |sink| and therefore the start-casting-to-route button
   *     will not be shown.
   */
  computeSelectedCastMode_: function(castMode, sink) {
    // |sink| can be null when there is a local route, which is shown in the
    // dialog, but the sink to which it is connected isn't in the current set of
    // sinks known to the dialog.  This can happen, for example, with DIAL
    // devices.  A route is created to a DIAL device, but opening the dialog on
    // a tab that only supports mirroring will not show the DIAL device.  The
    // route will be shown in route details if it is the only local route, so
    // you arrive at this function with a null |sink|.
    if (!sink) {
      return 0;
    }
    if (castMode == media_router.CastModeType.AUTO) {
      return sink.castModes & -sink.castModes;
    }
    return castMode & sink.castModes;
  },

  /**
   * Called when the route details view is closed. Resets route-controls.
   */
  onClosed: function() {
    if (this.$$('route-controls')) {
      this.$$('route-controls').reset();
    }
  },

  /**
   * Called when the route details view is opened.
   */
  onOpened: function() {
    if (this.$$('route-controls')) {
      media_router.ui.setRouteControls(
          /** @type {RouteControlsInterface} */ (this.$$('route-controls')));
    }
  },

  /**
   * Updates |routeDescription_| for the default view.
   * @param {?media_router.Route} route
   * @private
   */
  onRouteChange_: function(route) {
    this.routeDescription_ = route ? route.description : '';
  },

  /**
   * @param {?media_router.Route} route
   * @return {boolean} Whether the WebUI route controller should be shown
   *     instead of the default route description element.
   * @private
   */
  shouldShowWebUiControls_: function(route) {
    return !!route && !!route.supportsWebUiController;
  },

  /**
   * Fires a join-route-click event if the current route is joinable, otherwise
   * it fires a change-route-source-click event, which changes the source of the
   * current route. This may cause the current route to be closed and a new
   * route to be started. This is called when the button to start casting to the
   * current route is clicked.
   *
   * @private
   */
  startCastingToRoute_: function() {
    if (this.route.canJoin) {
      this.fire('join-route-click', {route: this.route});
    } else {
      this.fire('change-route-source-click', {
        route: this.route,
        selectedCastMode:
            this.computeSelectedCastMode_(this.shownCastModeValue, this.sink)
      });
    }
  },
});
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * This class holds state that is relevant to the search process from the UI's
 * perspective. It primarily handles the spinner logic while waiting for a
 * search to complete. The spinner first needs to start on the pseudo sink, but
 * when a real sink arrives to replace it the spinner should transfer to the
 * real sink.
 *
 * Additionally, this class provides a method for
 * onCreateRouteResponseReceived() that maps the pseudo sink ID that started the
 * search to the real sink that was produced by the search. This helps check
 * whether a received route is valid.
 *
 * @param {!media_router.Sink} pseudoSink Pseudo sink that started the search.
 * @constructor
 */
var PseudoSinkSearchState = function(pseudoSink) {
  /**
   * Pseudo sink that started the search.
   * @private {!media_router.Sink}
   */
  this.pseudoSink_ = pseudoSink;

  /**
   * The ID of the sink that is found by search.
   * @private {string}
   */
  this.realSinkId_ = '';

  /**
   * Whether we have received a sink in the sink list with ID |realSinkId_|.
   * @private {boolean}
   */
  this.hasRealSink_ = false;
};

/**
 * Record the real sink ID returned from the Media Router.
 * @param {string} sinkId Real sink ID that is the result of the search.
 */
PseudoSinkSearchState.prototype.receiveSinkResponse = function(sinkId) {
  this.realSinkId_ = sinkId;
};

/**
 * Checks whether we have a sink in |sinkList| that is our search result then
 * computes the value for |currentLaunchingSinkId_| based on the state of the
 * search. It should be the pseudo sink ID until the real sink arrives, then the
 * real sink ID.
 * @param {!Array<!media_router.Sink>} sinkList List of all sinks to check.
 * @return {string} New value for |currentLaunchingSinkId_|.
 */
PseudoSinkSearchState.prototype.checkForRealSink = function(sinkList) {
  if (!this.hasRealSink_) {
    this.hasRealSink_ = !!this.realSinkId_ && sinkList.some(function(sink) {
      return (sink.id == this.realSinkId_);
    }, this);
    return !this.hasRealSink_ ? this.pseudoSink_.id : this.realSinkId_;
  }
  return this.realSinkId_;
};

/**
 * Returns the pseudo sink for the current search. This is used to enforce
 * freezing its name in filter view and displaying it in the sink list view.
 * @return {!media_router.Sink}
 */
PseudoSinkSearchState.prototype.getPseudoSink = function() {
  return this.pseudoSink_;
};
<!DOCTYPE HTML>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>Google Cast</title>
  <link rel="stylesheet" href="cast.css">
  <link rel="shortcut icon" href="cast_favicon.ico">
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="strings.js"></script>
  <script src="cast.js"></script>
</head>
<body>
  <extensionview></extensionview>
</body>
</html>
/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body,
extensionview,
html  {
  border: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}

extensionview {
  overflow: hidden;
  position: absolute;
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

window.addEventListener('load', function init() {
  const extensionView = document.querySelector('extensionview');

  /**
   * @param {string} str
   * @return {!Array<string>}
   */
  const splitUrlOnHash = function(str) {
    str = str || '';
    const pos = str.indexOf('#');
    return (pos !== -1) ? [str.substr(0, pos), str.substr(pos + 1)] : [str, ''];
  };

  new MutationObserver(function() {
    const newHash = splitUrlOnHash(extensionView.getAttribute('src'))[1];
    const oldHash = window.location.hash.substr(1);
    if (newHash !== oldHash) {
      window.location.hash = newHash;
    }
  }).observe(extensionView, {attributes: true});

  window.addEventListener('hashchange', function() {
    const newHash = window.location.hash.substr(1);
    const extensionViewSrcParts =
        splitUrlOnHash(extensionView.getAttribute('src'));
    if (newHash !== extensionViewSrcParts[1] && newHash.startsWith('offers')) {
      extensionView.load(extensionViewSrcParts[0] + '#' + newHash);
    }
  });

  extensionView.load(
      'chrome-extension://' + loadTimeData.getString('extensionId') +
          '/cast_setup/index.html#offers');
});
    @@     (@  F          (  n@       (	  P       (  Y  (   @                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ۶yΆ$̀ ـٳfٳ٦Yٌ̀ٙ3̌̌3  ٙٌٙٙ    Հ                  ժ3Pacbbbcc⹀bؓ'cՂ bۏbmbbbbbbbbخbXbb݊
b<b˔bbbbbbbbˊb/b b b
b
b
b
b
b
b
bbbbbbbbbbcbR5 ے        K{ړ$ׂ ڒ ߵpתUߑތߤ?˗ǅ-  


M   տ?w! $zްVFՠъ/  


		A؝ di/ʇޫQNڨӈ/  


		f,|̧ۧNێڌ?ʔϘCSԨ{+  


		~-1ܸږ0ڇڏXҫǈ6	_ղ޽q'  


	22ȦڤN׋نۗ+zr$%pٱf" 


	32Ի޳lٓ ؅ڍNʞկYߐ5ÇӤY
		31yۘ1هׅޜ3}˖?ߐސJ̒͡H
		21ͭݶtۛ4ى
ׅ ڑbѯw'ݍ ޔc׹}4
			21Լګ[ٖ'؇ׄ ڑީUȝҥQߔ܍ߞ/ݾg"
			2˜1͝Ι̖⾅ܭd؞=א؆ׇڏިSƖ~,݌ݒRΤԩR





		2աD1HE?ݛ1؎Շ	Յ؋ܙ-\ǙХQܐۉ ߛ+{Ɏ=
	




		2Ї1ݍ
؈Պْ!ݡCtΩۿsߛ)ډ ێN̢ڻp*




				2Ї1ߏ$ݜ3ݥKlÒ׾ċ<ی	ډݛ-|͜P



				2ۡN1VYdo㾀ȝּ̟Sۏم ے\Ь{3


				2˧1ի׮߸Ϩ^۔ ؄ ؊ޤGƔѨW	


				21Щfە$׆׈ۚ3~5


		21ͤaە&ׅ ֆژ.qԸСT 

		21ȔZە#؆ׅٓ&gѯs-




		21԰Gېׅ׆	ڗ-fΩ͑E

				21ֶŐaݜ6ًׄ׉ژ2mϬէ]#



		

21Ьޯfڝ?֌ԃӂ֌۠DzӴںo-


			


21ҳʣܳu٦Y՚>Ҍ#Ђ|πӎ*٤V῎Ń<	



		2x1~}uܫbأSՙ?ю*΄}̀ϊ%ԚGگtǤȍH



		2Ѝ$1ۑ(ݔ()ߓ%щχ΃~͂Ћ(ԙF٭mտ̔O



				2x 1~ׁ݆څ΁΅Љ"ю-ԗ>֢U۰tӻ̔R



				2ˇ$1ב*ܓ-2ߛ9ԘA՞N٧aܲx࿐̩ˑQ 	

				2ձx1廁ĊƏƟίܿȈM

				21װwC




		21Мh5



		21֮ƀP*	



		21ط̐d;	



		21ذˎhD&
	



		21ۼңɆeE)		



		21ۼլϘǂlT<'



			2Ь1߱КʏƄwdO:+




			2S1TSVRIC=6*



			22



			32



			32

						2ݟ-}

							
~-ޜ!!f fے$#B""#"!!  A+&P##$$$""""N    $ا'ޥ&6(R'a'b'a%a%a%a%a%a%a%a%a%a%a%a%a"a"a"a"a a a a a a a a a a aaaaaaaaaaaaaaaaaaaaaaaabaR١6ߪ ۶$                ժ@636666666666666((((((((((((666666(((((((((((((((((((۞$ס(ժ+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (       @                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ()ڢK)̟((((Ɔ(f((((߿(P    ȶݤHΦĂmڶPAܜ/ٻs}ڮPĞڈSɗϕNٖ'ۉ Nͬۙ.؄ ݧT˕ݎ C޷rNpۢJ׉وݥO<܋ǕՀ N ڋژ/Ểۉޠ8ņ⺀Nʎˢѫېٌͥ=NҮڕ#׆uʕNŎےׅ߭b/NЪߧOׇ
׉qbѱN۶řݳtԗ<΃zѐ2Ûǋy Nق|΂Ғ7ݸ͙՝KNW٨cݷϳʐNmNӦ=NҟQN׵̔a7PP    PP                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (      0                                                                                                                                                                                                                                                                                                                                  ;YYΩYׁ YԲYYYdYߒYYYY(YY	Y	Y	YYYY<    HΣa)
IݤMݗ#@9
|ւ 佁ߔo۹		{zܺګ^ׄ ިRÃ܍ָɈ
	{Ӆ{؏wݒߧIF
	{ŗ{ۯߤDً׶


	{{ߦJׄǚL
	{{Ǘړ#׈ƘΓ
		{ཇ{ǈڨ]ъ#}ԘBսٷ

		{~{ߍҐ1٧`˪ڻ!
	{{Ϛ

	{{[
	{{ҡ[
		{K{N<%
		{
		"L ! J    ->(Y(Y(Y%Y%Y%Y"Y"Y Y Y YYYYYYYYYYޣ=                                                                                                                                                                                                                                                                                                    (                                                                                                                                                                     .ۙ.ظ@͞c 	.*=c ٚ3n';	ڝ=.iYa
	̧۔$p 
dٓ$

	٤VNҏ.٦[0
	߻Ԫ3
	~
	~P
	%0$"  /                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      PNG

   IHDR         J~s   aIDATx=
@Dۥ݋ٴRkIcΰXY`+^4[ x	5;H|P"J<JoF|A\~1~    IENDB`PNG

   IHDR         J~s   cIDATxһ@щpu9 @r l3kcsur ^X4ǓPwO!`DH|PWk>|5/.z@U;    IENDB`RIFFzp  WEBPVP8Lmp  /ÕHlI$(=(:"??ٽQGd"CdIz2 	! ~\*x.QFC[mS-~6xsڰxM9N|&3AR@/oN|?^=k~ 8}qՙv䀹szG׌.U1iAi,IRF0rkEk	.sIPd&moؙZtKQNEQZe:$IR\|y)aHH
ÆZ܁O@?Q @	ئI)a !Q#Q)"c٨/\ Ù@@ .NH]RJU-}ry`  p	 @DS~Y<6YJL86l6-i.	|?RG:P|Q&袿}i:}oz:/KL tVi=i*6[Yxٖؔz壴NҦmZ;n&!mHi6<GE9IBH< zŴmgFۙ6$N3ɩ$i:H5:$e+~	;$!0xIl9>@<.~:6,cE_CαSVu6 b7ը	: FW7`ضOF?QznՁɆ?̿sPˢAt11\m6Irٿ׈Q)eș&x! 3vl]}E& ( OMHRd1fβyߟfpǬ)@`7Y܍Ӱ95> ԋ	l6mQjH=[h'87 5>$~2 Cm&mϟ3Im8Ohz?$I"=xٷ?l1`%M.$fVa@@Xck {( m#Adqm$=_bvI$Y*YU"^gaw~.ց|EI!y:u0 A۶iH {$Iu<i&1s Fѧ
ӂ?ZՁo!7tB:p:mۆ,HۦOL^޳S|#;Wx=7wnM9>oL}m:֫Nlk]1#%I?l:nɽ T>p{3_><8lxd,z&?OjB\2Y/Mkwek)ё8/?ux:ܣ]>t|sl]x,Qxz%q;?;&|~7ڮ-EcQ{O	D]5!/uʱԎJ\KyC$#CmyM{^zaڂx:g?q੡OM
IuжsVch2"j!?Dy2$/󍏧|~>粫,f 2B'$ hn_ԩcGh` P+A; &G[[mS("&O~n|~kmӑfHnɳPہO=+BRWĥwaՋ"G)aEO]ϭEFPG$ς<O3H긶!jq8I~ <hMo׿_׿_M?	E~ڿ=yqVw_?_ӿ?E%68|	8;Ff̌?Ͽ_ɳ&	S[33׿__?O?))_Y;o?bXu8W)rgy?u=ϿW?GGD?li<3OS)Bs>?g[O	___d_YHoA?i_|ipR/rr/%?}p}vO#?|4s[ϪP$-'m.CG=?{{s>>؉P\oYZ=q~oecǶ%o|:{ZNlی0k>-q3{0ϙ:8=y6m-B.f~l^5ɧ|m#f37g 9n<7_ׂ|¨SY6aホDHi1c[6.̩ȃwlch'gǁ7FuB$gfB$g2چ}
r`N)2c3ø8w^kS`[;^(3uvOccg	BiI֐l:tmP4xZ=0($(IL^6~$Ԡ!S{kL<mXLk8{6Պy 3IhEqzżǖv4ĶcoKR+۹c3$.bԲ)yN:ť0mw)e6Frb˱nͼRAFL^lvoB	0\ˢ2kmvư{()J^5fkYeIY93Z۵cs֘ك}U҇zسپ*EgvsZ;1Z&qׄ[KrYw{˳lc]mYh7w6f7J)Rǵ{4l>LM?Ύs` JR*kذ7ym̤5ϝo9aD.U+Fg/ZYXiac̼TʣZCk:̾jeFk4f>WK*W<4y#3l[sb|zdmlKGǝcư/]J'b_ΗhZJOaힻ뤫1㹷p))ǵ̷fbB3M{+O3;ی3ØBU6;f13Y|,RŭBl.8sa`Haaf(^n[	y1pv؎amf^RT|3:g{J>81jΰ59"Q%Re?rDu;]n%,8cck^YBbgs%ʳ%mmGjƛqIX9eH^UBg̶<Jۼa컈e7́9Coۭ#aaelM$$Yf3NrݺJtg1{`wx҉q:-*-"Ǽ0ck67Ǭa\19^()`{coɶk_SZ)Roey族F1`q6!.KE6Q53eBg]!(DУf["QyaE061@RGo0xݯl`/PJ|9R>v60.'z!B"zis5bƚf0K 9Y͐8͸svM64a!5d-=qqr0Bc,glqe9̣7Dt޹mG۬-3br99YB{,wί1]Ȏ:/vکף;͉.$O׉=}kG|j9/?hru`?~>y/!.`H 4ʰ|Q΄.,} @ HAq! a1&/C6N4^,@f Bt<!NAdIdB``%,Dy菔"SPۚ d#I?)-^ʜP0Teang`jn!2jDB|Tψ r87#dnmޫfĻr$ }F2g۪=T\}fqۉm$đ;mXn/d>"zM>[V+JzY8K3w?+KsCw@gi=tC5>K93Q?tdEy==+6Nѵܩmims泵Zf,n1'L&~').\n%X>GG:-EeumC=:}Xj'eL1>k -8['۴v<ڹܬB |V|NL~_b#:1>h>;fsܦ'5iC{n}ގMZ-58TRo>\QPpp\۷>'$ W32#vkU!.; &*CZ:qket 坾rq=O=򱗙GxE vUS	Hruݜ-أ  qUGz:z%z%v*5`i~ٙkDx`v(o]8uゥ'*3*Ȝ׵͐xF`hm3e뱇yD-@25MAqOCN|4xL^bFػ_5kXi[A4;m	f7][|m(ؐ<	ǦCL;u4)4Hg$IGY0	uʵz`';M6tbaا`PB 5lGv;mR l.˔YK)f<bRp﵃ÑuhM]kxp_sZaay$U 0ktǄ~cXz EJCsrU~VWSa9 㿙&!H'fv̩cfzy.HL"3֙' 	ӊȘAGiQdq UęNqx˕=
rXc$kȍixOg#XfP14!W`_@'ǍyTOB@az`=`-v<
@jCĭ%ɶ4q>d=6c̼~l,030	$M8 mKi).}۬jm>{kg*SR Y!<sΉ\ƵO3ΖL0cHRIEZ&YS9K7j
5/ âf@ TP?rU6]ϯcփ}8̎c̵b:3uvٖXjK63ۘH3jA0~M
`ՔA.w(q$z$  s ~Alc465Uǭ+ҬeGq(%R6Ǧ=`ۜETy
h n
]Ic0e
`@6#4QjlrjP_׹ At+8ό1DMfa΅>mmǂVc6#Z<g$ǻ3l pI	Q7L!+3(+ۺZ֟>N/Q
wzi'!ub8<p,FÞ$.z!0O{;Dqd$BL]fB`/|]^C'x0c%bc(5&fOgu-9szjnr0|)@<y~J=mxOBPH=lt lṮgksO2=d ilwY/lagk-P[L<NK I{,#1&P|xQ~̊( %`jOgWH&G'W,$IBIR&1n	`+5uy&6jooq.  `x oZG!)@Z0psB!$,na\ZIlLvkvM;yx4K	®uVh	E*d@F6le=HH9%{?M$$ЙH\ڣND ;=0䏋@ԥ,:ըUyHU>p( ^}K,c"$tui"|]4D+f HҫL>&SʹN\Te H  Z
xH( -t*59I(vKE C|:9M 3JTl_DBZ؎8Ma[Y?kZe1Aל/<vM>G®@$thfQ mD[
bVxxX zxaAnƌ˕qee4Zn}QQ- A<9&6`jx>PXPnjq()E1+kU :G\>#.ut[c1cL>3=J	ZV:*עLC:+J%B7
sQ1ƈ
VgDoZ>/|[[yO3Oߟb4q[djǪ)ds0`#QQ2ّcAlj2SǑ;0yoQp݌Qʥ?~+ZSE0Nj6+S݌11o61jieZ_WSk߅f9**WYFfiez0)ՇyleN#ą2Қs;bk>`PT#fܰ9ͽag}hсK(ribɐ5-_n'sy6FYҏz*y|_?PVʝYM=ڠr_adhFfrf%l޳K̴brq`qRqg:^2wV6=JA1[h]]~><pejϣ>t촥(d\(c3,HQ(@Ĉ#^/XveIihm	m`i2sT%)Vz:*@٧`hؐF,0*:p?8lke{yCY;\NMc`R*זŐE3ɴz>op'_ϺGcDCkC%d8dB.1s,e3EnʱkW4mqARdZFkiǮa2kKo=Zg @_ǂh*ǤnP&Ĥo7)YfQx>Ƚ]3?w8D.u-Ӵֲ=6/ְv`TrRRsm=NC*뷐藶VӦ:"tr)t&2&W]ԧSe0sm*im#tRf6&՛z#irj?ֱHrGP$@t f:(EBRH̕,):m[fw("͞D8^ttߵnwX3Gџh<TJ80"z2F!Oi9@l	#kb3d.涞M;MJ3lHuzG
==ի^B
[q|TN@(-=R:Rr6Yezߖ0(mЮ>Z`vE%E*o8n6xb=6	WqSA)òc5Af30 鋍ʥW5eA)*y4FB2?j~.=Tlǡnq鑢&Д:SB	531̝K.}36,Z#Azw$z(Wac親Ԡ#P풦yl7ŪgßuKӉ@)/	
sMv1#O1s)Klf `yP<5z?ڎoPp[l"$"IY&p.N[|CkE/ #"*nqYPBXޕ.I{\x `/ĎsB=01QPT9Ts!787 Ѵ  AŅ}V!)%ZBҷ,S9A#= lH#`j0Ea&mT	3L.	ǫ趏9˼η!sp\֬yDfIU
|UB|,=,x`@g*Յi%~ٷ<'UL2kGAQ8j0/	nD!"c,v
9$ wR@m @<3[X>z 
 +	ѴP +_=W4_*ARpH	 ʙNlcٸS DD+mg蠧ׯG%2 a JxU*G@AG90l&M:<h>{g_lv}uy{Nd%,g0'<øؿ꯮=dkr4	hTPΒ1|gkb.͟ٸy1]/_kΙzX?R //k5{ՆiT_aVJ4\!>E?:ho#	_V[IypwOvsOq	>rlge[Y,dVtmHt4}?0s+?÷-LcD{ԻSEP>xO,5w|@{>_9KOlغPt,y%Qaz߷3RǬ>iƪ] Vnke6N>G،LfGG}!qOYOc\v֝Wv\XW=n.)dJ~H?sh|f;'}d@yb$bUWvfu`+l`QY9whpO'+r	~t_͕hv5[17,5f}\Dmm
"/|UX[ 9Zk4.<@gX}UAXjdQA]{BH\g,sK*vyjCyOXV`QTheQc buk?&R+}[W""@lt2M hU(Y"R
-:3[	ȍpaِQq.0* NP@²ʚB>9J^O%=·0Ԇi^_O=gZrYOh''^jB-J %hJ<!P[ҟᴶ_zzieKD)7Y:svx@3!eua]Ȥ+Y@45{+/. nu]i=Zg"kS.<gaŭ J%gVq"| @ptJwcz:la*4p>{'L@CVt,P WyCC# 0깦qi])kzCWX	 	') >޲/7^%/? %gtzxqq}2у @H(/V.qe~^Jt/"P.@:ZX aaR9@\g٥ӹm=Ԣ5B{L\$K}bJ[B;[56a Ex[8ݝ@\tWO+@YJAw&졈Cq?ĎB]r4w^m)\pFY5ka^/=]!0)Ke#,j=JG:YNW!U[,~DN5+8 Yr@ܫ}(>N]2蚜dP*mdN>$>j	ex,͘x6Eb-[(Acۢ6Pk<
iAҌˣ4cf p9S3K"vDѕՅ5ܯ^ķ"3/Dj?anvhFrSjqfH^@e-5lH.T˞-
nqɪ(>fMOtNר.JAUW`gCI\9Q%ǒ]\/J&ytV,Bx(jİ̭uTla1-omPc\__Ք<6XvlMgkuT)2cKIߥċ>z).Cp]uuأ~Zz|s܇453xd7Nn)|T6% l9Spzsk]jy+tJ
7c};WaD45&vĬЇ,}|M>ƈ[,ESetį>Eed}-yYPͳi^e@趈LAy$jD^ǽ	0KStCA[S*	,Λp1))*#Cu&Ȫ>!s0` 6<QB,=T>r~̫@&r
?xD>`k':jHp@B#-%da,VKyA[LC֢rFpZF_&{YbN B6j[@,2 &}ۊED泰u9u,DBčZl)gks+I+_?ζ< |%u~<ɿ&wM|?~W7yG?BѶϱs3<鍱39ggy3~vk;`mfcc~thϬGRoA;`ND{4?{89cҶ3~~ӟ3c^w'c8g?Kv^m?Lێ3۷9?K3>%f?K6^y3C?Jǘ|6;Yt<y0&;XY:6`d}f0}g>.?̛Gwyc~7^m+uߊQ3EP·II,W@T@ HA[4@@մ_F3B#fdYk$qS`AcQ*\|L$x@+K$6F1߈ɆYhLD ?@9 ԿVJ<(H$+-)k g»-X;\I8+ģ4;tDUlF5`fvf3;qC4!  =D%##Kli7q&sr>JPj!lEY@/k6(m$+W^>T1E#|,$p(g140
X &,ffq!㈶5i iXq	*@7&dOh X
 @H623!f@\j+ЁdVuu!,:q
UrF)X[QBڂ@ӡ0iXX1'*;<b{>8;# &QJX@OZlg@7ca@̘{{a$fWT; V@ عxP"hyK_6RX7 .\[h)gIY0U#63bXjq*ĥ !!ibL"q-H	*%KxA	0K@Di4c2>FR׭QñJ<Guen?a?ohQh :Be!"QHǅʴH\d=Y2p5p[~TAY~R znۀև^5vѠ!ULA@<;;Oj*Ph8&ӕA4!Ygs:̫LeiL&=?x\ZB`֣Xp	WEv=2UP7忉8 K0!7@V,OXT@Kt)ǦWZz~l X`afRThsg.\+4a*aAŅH@uӕzjhtHEsVRс
V2K~f6YX4汿nZM2ʩ\ཱུw`c<x<3ˆɅL[w5?XX[X5v42Feγaƀ?,i\qE/hdߘH{cVYE0JڅxuB:;7b"Fy'X8[PF{o<)jy/ؿnDg</0,O2zƻ1 |dW,O߉" [ZgC)/Ec5Bp*-I;9%3;ZSeaSٝـ<@h̝SS&bca)5w3}=	d;)(WfVz<~qv|ebo
WfdUKfؾaZQ3 `?8[#P@9{84q1hu~0!ʀFkTT1=  iMfo224`F؏T6*	T]h9]7q/6PcB 4 Aq6&+jbQ4.Ӕ>r`Xb<7e6^#̚ܥiLWf@UL:R4foW?[Pks'5qϚj a?Шp&4(yog6e
cސ5O>MxSeLs:ڞ&0TI샗*4Nm;\Q6	@e	Eaq93Rf㹩2d\A\ \%0 Sx[*{w&=c_kILVVN-WZ23R4xsug^NɱX4_kxlBH0-hcsZ3N,'xcTzf(82&uvTmRY#M) xvc*O NfI  PFfRْvj w.?v5e),@ޙoH	Y=Lٻ)X{U".R@a[@  4m '	]Z̨f{eLxխnrQ3"(Q -[TPTsv|!\8W]~޲>i<lKQK"幖R/%GO(xr]k4fnZ[l!Dp)ɶ h6 XURW5EŝD5h`  A:0~^dR!'r*p _V̓#kQ{Na1\. 8릜"]($b]H<WnQpSؐ. ?sa 66KiʠK!S|A91Q
Lx)R2Ԙq_=LRD2xHE8cP^JKPJqy`K)Ճ?VJdL$bpbf2_J4PpZ	(OL~ΉTNưѭqnb1QQ d ;KY,sR2'fFR/2eH!ed+S]Xb:ī	'8L|e2NE8!V^+[DKp _:05|*Fj/cמV[uu`@h<I\Ã:ֆ3Z^S;3kSb$@!
F4
 v#e]i$#])lukH
17 (剧S :`q1xEĥ ت<zj")XQ*cmu	PJmi~Vkn
~nb6 @H[7HH&%PS<EcC^T,Ĥ8/ h'%018]{N@X[QJtι%79#/0ڤߩ6udaaAY9KJKJ ̀ة%@40oj+
6!  (UPxMJZ(a/,B@(% t J{NPYa
!rg |qFJDRRkaǂmI<B	%l"v b 10䍃du1F͖f2 je-9|JB e85	.G	})$YMv%$J ڂ[2rF 4Clڌf82:T!֘A2]Ɵ3BlKf),#rr O2bg! @F*b J1Kn@YAk؄HBP\Q 80X<fPse)tkri˸1W0ĤH@	(d9̾aQktI Ypvƥ6	6bWȞ5υ
<#.Vʪ@zNsO 4ګ4گ<tgĿה`ay\eY
92BtDr2?OrhC^3r-D4!%Ez^.as?n~+ 68[>?G?͹xsno/|;~>yg_w ebW9Q}XF,Sِ/no|ꮹt{?<\`>(ogpsإܐvsGGo!mu>,?EI72,[>9ԔZ9΍%:]m~96[tj.tgkуȔ0~L9]/.$__5kxϸ>q?/s"%hPe|6٧~Üg>e^g_v0f?'zk)-ߘ9(g`dו؀g/>1a栅ryn^gt3'ۢf1aN,#w"xas }ΙY20丬im;3\嵟h68,h`1P.pY"f1Ì"mq93fd`i98evw^TPLݞ0f}E1J@Ό.%ocHa7F乱$$
c3GTJ.0b?'t0M߾g!hYgf	^
il@lƝ//%mY͘MmA3sT$of09է:MsBa3f8YBnv" ~k-^6 QY/
}C1:h3Vu73S͘o^/e_5ހ6f&$.(ʛތ&f`Fyg7Z浾٘eƽ\<aZ}mUol.cyhG`MX/湙6)اuY>vٰ_ւ9d|lx.Wσyp(Gv׹kiͲ8\\.m^6y\{f-2ح`d;cԵG{i6{:qq]1zp8>2̆{k}c{雰fr#^ca~NX:a][^wgqnbf;cZnCK0ps=h&CC筸\}yE<.]{y_uo1!k9s1kX"ö1#)WH:c6˥8lfys=wY+^Z'rÞϥϞ|Ǳq{etҬP.nw-6OGŅqz.{y<*a}c׹`vw-s
ׁ86{q]㰡px׹u2sK^_k]u\˶]qUb/{Øy\Eapl[&[9eVr^7{ul#Jp8㘽:ZwkM}*ίw6l?;kzvl3zy=&R^m6GlĴ<T`_r|.uf1[3bNZLDΰ`Ycvci/Wێx}ra0
zߛ=mLc!qoo~l
a_udm,Mkp4JrRʗc>s`sdd-F~i(J%a9lދl61:D򢜭dރN/p.=xݧ#86q5hFhR׽\{B=ǘX&h-$FuܣP?2D\^g8P.חiQ/u!ٚ]S+뺮zl{qvZuS[J
L˹6ZCL/(̶ARJ"aưGom6a#,7ݵD5^|NȘ}i^|۲lV{0^_o%J).cϗic˷؇;zol|9uRHJrys]\3llyK$<`o!Izm{8_4暵NL0DGH>lr̷qlZC|}RFƽjW_l(76l>\\\c|xri^kFb؛ۇT}6pOhq(Dy]+}|ss~JfL$Ioӝ.=l}qtE/d/Hq,|AB3|;|b033roqPln$$,`{+b=ci0ow^IcoEI0ƌ/}Gx%b^D>Diڧ$QHf[uz_{a}"t1o狈a0sM;ʌ3mf噗}Ey5m>p0=fy_k#g1e|qoYvD:AMEaؼ%^.UIVKVmc;buzDs)Xr5Y~X0fX3f߽.\6c!KryvXZqwt7sC`d}A>'d9ǶgTHgpQ1q͇	rP˧~EoAp3ی#P&}cOIJs*3bay>e<-nk-ۮ2.̅NK-?;3qR.^\v$ߞ6]Z+{v?`n͕ٙ9lcc1Uh3$9{Ѹ5scp!yÜFmac{EvK[_{粉}^D'͵>M.#79Ҷټ^x}H:z6%{箙8]'h^on#kl6,\Ksl^ߗ]]28kw=^K~paFrݍ~cpfOoX/[umRw5p<Kz]Rȳ31R~Q-'K}|>柲>f9Jѐ([6\_<_m=5=8խ|&99Qt{yvgs1CqG|//Rvr޽"88.zk6{e3^zyF6gnkMlfifvUݺ1De۲XMnC8s2/$ہ9jbd*2{uE?N'31SP\m868^[u/TWh;_&fisAzy{u/3ɴV\\ύŋ9O|uU3ptåcsc\$bp6tbT.\$%]W6sP(.ы=6>9c^gB_@U#Iw ֮^Dll6AJ}$Mi-W
fFHQ>rB_AGD3wG[ޓ_:1`H(_҆Z|&ydy=H>Dϰ(zv^4C Ԟ^)EﵦVb~Îȯ׋|
T,JQ[ S@sG^#K7el:掮c}1<،EDGAVD^=/.|JVy +aH:(?-uenK^d frZi׃?}߿sKxC	=裚lH!@^ A~xScN.KدOݥR=o>ʇGN,<؟[2J ݃,%{"mƟ|\GsW}yX8Q
aLSb' T]eK,9KBO	l5^cˊ%?.{P'`6rC&iYX]j5L{a/=z\>Yr]f|c4[Vҵk?,v4=ut`() #ZB{z8><\-0s={M܄6):-.hlDH`IWoqzMōmxJ{B}R{?>\rU?F5T*{i)'F;y!}<.6vo)H.lqmE\>KWHMь!th{< S[ v0.[o1"7W?<|tHVMP҇xDq0DHqE"Fa\̏GṘbIAOG5!̶dg(nԃBI,1FssV_}$DCkFniTxnbٛocr1?5y@ĩ!*epkt >nBK :7$2W~E̏77oʢ[[-Ch(*exhCE#AD ?+Gם[:l[a&BZ[ϔ4b& c!ne),Pn:"8J_ayk~h&J^f;W23%|Ϊ03~r^2LHPm̗s$Du&ӵVҏs#xBg~ciH W$,߀M1ZlQ`ν}W'o[Q-v㿘gtA(ByxAZGQ;M50km"Y#;UK!7޽quha#!tv-!Z	 v! eY5"cxd63?dv
8*9͉X~1	Zknu˦F[_ok˲e4S#1KoKTG\*"k9nv?ug EdciUͮl|!ʬ$;6Rrmvn@+wh:ﵪ;py1[!pᑃ?~:{kzjPnJo"9ѱj]! ;3zvf0P[E<Ch]+0>@b?>6ԵGd@_-!NQe 4=(ܝb ()t\Gă;$vB(qz{koۯېX_%ʃjZgA qW^.-tMޢ:8G9a^<ǨO?.<ҿ\z<)cD[s6\\B3cvA],q ^g	7[+;޻awOYMh^0' rG#ٜ</(m]!@we=:Eq	.Mm@[lbyK>n[ΰml/4>ZP!M\FN^"K]*5bSU$Zc`G۞h+i-<4&)Q?7;XMhbg^@|% 4G\|7;]7%X4pAr?v{\R;h9MtiXY4Fwd-O6iBؒ ĮUx-ٕPESo|ccZs{sα,òBܵ+!)w$fg BteMwS{%AL[:9"¿5(nո-Sk؛[@WK$A $ѥ)
օ
hԷqF\p@[vݏ)2,kT hX@ҴвͶm22FΒ`4*3_BR]	ltY~1>Zq^ALYF%5Hb^oႽy߇onzϝ [7}$!$[g|1W!APOxB$؂'d&nLu؄1lzT
cP|}yCPHgWַ;Җ'	(xe3t 6+j q'/ p{_xIYıG
@B 0hV-@cpkCoW~Mnwk aROHnr@BW@4OX@	ƥ<ͻ9PT!,C<c{@ā2dN_vnZ#8sRD!t0{+\S	(Ah<
j+hvxkݜq!rAY>2))
[͚sK3.ądC!A௰hb5 o]$Qf&
|[%NYZIweӸDy< Fa.2oh%[GֵF8cԌwqr B?<ٞ8I`2Q3N%Y\Kp]l@qL,dvj(0!Q!@'rhJl<AS"-CHdF+7?_JafML[%b
K=|E 1O2dH>A@LiCH  7@4CM|T{;vYl4HljwCv¸Ac~'i32QU,XS&d$|&	$ ja `'.S'̕lنِS)4dguŒV[H>q`/rV'7Z2&dG#@)L'@r
- h$A	@@3皂0pA _yYGIZWFtFBHYlMUHMDhÅ4ZB`P5I@h	!rȔ*."x.ǔM~F|;0a=о7@&j$Ḏ%< Pvf>HiܔjHG  d%E0vE咠P|@P$iya wAqCHÇBC Z$d@2!`YHnNww<w?W6oyW7Gv8¸@5 @HIe0J[6uX%4cEZguoyfx )3Zr`&,XQzpgdPmDݥQ-ǻbrWEG#Aڿr8t3 xL.LV@'v,PHlée		X|~<?g]JD65_껧_*[ [D ٻvY	;YYJ#]IzDA$ ~bRVOCqTFct3 7l  "830[nb76&dtM!/$Z;|RW&`a*}g`F 1TvYL7ۖ)eDV?(qЮR~ogW@/iv,;u5e1%mo#9̵̣%"N$<[M}Ο;#?Nnj(HaB *(v_l۝L|]NSCS7A mFmXkxf4G.@pj6 .L/.ǗE#~ư8v鬈/(XCqP
3??@{Έ$ Kշwq$˔G?<&EzZ4NHsg43\H-Ӟ\zf]b(K/1/D1jU%n"RG[n5oԟ#.wvf|^9kkeQaٗ.3j^\QTٜom>]HpE\WJ/P^~bߒi6ǥx7[9PVlc1eZo]o˩ZRgVƧS^cz+"(gujOgFxm^Ҿ@$?*G5KhfnwL])w
êq.k>RJ>#7/ΕĖ<Qb =
`b,c~qv5^DG6o	ٯ=_t':14PhJ:Ah}
f[\zdg.B7̱ZYak8r'9r=JXN\Om$+#n浐-GݝDةaA`$I[US^_{A҇: }JeaQ*GhU `('oQϽ&2),r[h ݂vjC8l;5iVk2A:e/_{=mͯ'P/9A7vY5r87/4)5,!`oZoP=[6xQ 
Bk{Sݰ@&Ӓe9'zk11TP=#*,"*97]Wa4;Ņhʲ
Љq}~F3R_ZbUI-z^sU?Tջs=f>،9g`QE|a	t59'`m0s(n)վ#@\h2mi*ijFk]`00_eNo(C<$M	ܚ {4[e$i޷cZVjbg>H:i:mНrGNl7qGvOUu%ޖ>^Xhk۟L/S)4tYz L\-&[h{iч1B6{m'USXŲxӷD^ɬʵ2v[suWYf	=fFLS3`y;'h;\J8)^`[2A>g{W{HUS$7@rzAfv4¬lTmǗ9Bm`+f0v[ctÛluwKDv;Q(U#_f͕,nObv2bme;rt
Meҧ7	XPrm+7mwie򺌌5=lEq 0ZvJpUjbךgsgk;FVvPx1![(v7-Xf?[em#ZZkӵr_#5]ĭ+1ZL Qhߍotjh[;'ܘ	Y^hSs:{'wA^䪴AXI)5hMtHF;?ޖ0h9e'AN:{stTut/l<ndħVhԬv:Jqs$5eU3yDAn? RO/[!zc?;sEv_ X2~uӵ.QXoRvu[bkW(ybhdMNw}̏sY/֣߉пMAļҡp'i
=ikN:p=0AV $G𶄡ٝ/.#83Rv8])g:o9=C}QKi"7ALPtjh+˲RR| f$ﻞ.yֻ!yi[q>Q~	Gvpi(|MIh;ETA8HVv[@5Ղ*sZtWknW7oVQE,4=!ZYHS%;f{P
ܠkZ>_ljL;-l4w-hщíK7jXҵ/@:)c"3
ҸXgd&H.5ruzSBhq;0❀EsvQ~t?Qf@nL2yjE$сj-n&dDuϳy;5Эyo[4M{tZhNvRTآukaf)$uMXk	  t1+6tA/8xޘn'zc:r4F8y6 њ~<ޒȚ]k>  v
eym	X>F0k+lΚ. S֑pqujmvH0b] g3oPu2`12[ܥ0WGLMƺjs^V;s
-s쮖mߘ޶m<W쎻`ϳjS2jCse.KklM{!,èaw֦ۅ	s o/BLݝ4=6-CwЅ=զ{5pYhu?o0Ѡ)TB+⏁-_h?J޷U7E}QHW>e]/_>EHGw(>h,	}$_;?28mfgNIE];Go;(/]^>WeV&C6z̧})zrF[AG[Gi#mFNƶ٧~ǜjG摮NK,DbBc9m/d݉LQhh0ܿ+~HH-ǲlg7-&+_hjl`rB
x0Bm6~HvtN,0ǿyYM|}Գ-䗗qG߷u:&yAَ{s7{v%4?SLir<f_DQ^$nou*|yFAscmz&9k<?ri76ϥDc%k_;(y	#4eY]}թd67eLofvC책~"ʛW21̝M6M43#cesLcζ&Tg[9wd-chZg>Pd~ۥ0fn%4j̸qyΗͩC1lǽt|ζ|GeYEr8'J&22MڍӋ&MwAϥAkXX,sNt6sWZoɶԐirZk`-3m[>lwJhy2tӚn9`;<jZl6LM0¼fkpYMc2>%$Sn0jĜZήYd	wElgʍQ3e2ڷ|Sy?w'+'vh>'Rr˗C#[cv5Y߯5BAurDQcͭB/`:dDbC|$Zc¾sX̳i7!0WsuXZN3}swӠXtXkv:6)F˶6"C>f/uDI%g̳Y-b?3_!h|0&߄ɬ51H>.EDwS/C;wAZZ.vj>`Y/T4ֱ}0aX,F76kG_툡enNtDGJZ.[P;@t#0{cre]oFlZҐ|ʐm[\Gk
OA,--=TIԧcYk޾|h_2zY/<׈B:7#]]>Uݙ]'5eA/J<7sӼZ;כݩ"I-L:®׻uou%wٻAB}H,3EG,y,u)kݵx~d5{|Ic-#N/b*}ahhtsa\rsJliٿ%ޛ`鄉ek/1ͲV{dhE~Ѧcn(oV[5r¼gbњm:-H2fqC#O޴&qʰ3s'YM%&%},Z2ۆG1d/XtB͂e(/Z4MmyjSL\l3'b,ʹzh\e'sW?~||#sA;]2*).gh;Mnmn!h*saevgr5߉3ϵ{ѦsJ ѹYj/n0sV^]h\ks`B7r i4ƚl5,q8e?1Yhna6c{'\z,Ȍ4ی["ȸf̘a7D(57'鱭aR\Ѡk`mfXȥVKЉgB3IѮ%vxf17-\%Dew,'Ǭi ny0cAD+^/Te0)JKzjl{3i!ƭ{4;
	rܵ Q68=6dfLkoBp&ܟos`\̓ta5̋89{ZGQPsm M[>p[,/<JgCib;5dU%-N̩mZA9K8̽m(*oDGQyN3ly`>mR	)'yMZMn)-[#yi4L̯wDُxxj
O<NōWD"tG|2:c}Lk"p)=1cJr<bG10~#㢈^ trs0{<d(a!*k^f_b}!$*k=ZP`(yiN%=e
u~B> RIFF  WEBPVP8    * X>m0I"!p9inPZ3g^t{m7>F꺜U4/<֝Jye";۲5y.kR	Uua9;fˍ)_ѥëE2/<Z{iXb
C~$s[rTHեaJ!ԜD+iNit%cp76Ut
94q:+íIXIPf*tN|E)Nfu< cvta|N?ьV_+	R5EZz$,5 iK%O4sK\8̄^	,? XuyX÷K;ۿ74~t|φ]A_;U
&=oqx',S{zoɷzrsvjه=1IR;sҚ=נuJ|u4%ד,1w{UbƐ	
7W$y6Ob[z%BuHآ	!qSIAh74|d(& 9I_9Pj1*e֗UL ]z{9zG8QN&d86ojb+G1aG9h &I$#k4>uŅi=5´jBa#~ ,GO^,ŴR=23Y$Ĵ`#2G%#&͚Ņڌ	e%,QH=OX?EPh|[@܍df,(a#9:M0gEs(;?4x_o|x.K[g%!;+ۧ_o3C:jE.uY1ֻ~IȪ7]"h٥S?UQ]ywAn &,t_w_N{?:cD\c& KX76BQ1}v(
U؞QeQ[5h2ξ|y KNY]9|7b`9Sx3gB%!a>k\t1:#x&dgb0LJ0 Z{mLx}4{
(ՆqZ>
kOQ5(MbШ/u}"od;!oc?cn\^u^mgcJz.zD;-Xf'LPk5i:&l/6qR,O@IH\+G1aFY{(b&vnvZ_^jdC-=؇Roej4(Zum3i٠i-kD)hfZ!KC0f
Z6ֈRлD%ajSsZG65?'q/{PtA҃.pCvoN|pw~loѻqI EՆ$qCd}}9;R@5Ӗ,A3S!(zKg)v=Ȃ,~	6qK8Vl|c8	E.wHPvy)
%ַ68q/hSan WƖѺ/sf̵ZHMbAD?]d,X1UGZ;]eMtIT[olςY~{>C'FF a`=+u&}}?w$M'4q5Ն14!+#$_#gWA̕I>\]?ŅuH2P6V.(4hcGzek.NOu, ƼP}?;CTa><+vAF^EPV
 Td-dl Hm3+|
D"!hYA-N_!(#SG Sy9>1ӷtSVW AM¢?ff[ĢQ	};(@SZ]	e:$#Np3o)tvcfQ$,i  s$87
u3cdCML7i4o3u. =>
`i3Am[I?-.lgIZvVyn.ZU#(UR"rQ_9wWhQh86m%2M4 d'\;`oCOǿ˝ٟ/W$ʌik-{}Bᥱaxsa<2UCΝB"dӑ4>:~r[TfIT`9H3,B\3$omnt[%~sw֓6&4VOtC}YfYD)t .k9b0癮x${ޯK)absorQ0I]eɓ"SbvZIAC1zP3~ױlUF׷$ЂI{cH' l?Aܖ>Y-` Cʍ4PlOIP#-E"2T'W07o'm8  2[nc	USP0r"ΐfXsQ1"ժJ9We׬eHf trn"yМRB31E)`inO{T aܽ-#2)h|GNQ>W^OSwWLPQ'<h݂ا>+"o]n4\`pVf<Ҷ'̈́=Cw{8jůd~c}W٠
Jݹ	s!X#Y%3uedQړƍq墪&ފC^`o=V~&1V"j#eviaR$j+Zm-ޥ0%`ͧTՓNz˿k ?QJ֯0D'qj.]d!f5p'eWd[y*< *І5ˊT((z!(]C"ڋv:4JMmE25-8\k_%Z@fP*5$%\wX(	Ur,;ܿHA?;9LᬣT&f1iS[P7ǚ$v{Hv0LimSU~~f>"x{SL	J7J2`C ecOy)SeupqT$~O*<VwN+6}dl6xm.lɈ$ˢLbPُdsa͊ʒcKᛖIa>cy!2y|Tu.i+DiՅeJG#|VUtXɗfހU)2JOKpB-A>!J?:`??	KKᑨ.'&Æ|Kd)w,NH_<Cg9l4r^.D|  O;'PlBe.T}/	τvpsNP3C#a%M)Pi'953KƽdCv\}\hAޯ`ӱ4h+80RcSWN<07-uu39Z|mє0 S%j:2`˶Q\ԧ]}ܛj s(#  XxER>_a\f+갬I__&P2&. [5쮖	{hTʑ0nbo@\i]f)#z4f
\
z 7y\6*)Mn3 ~V~I2""3"8-dKjX`&6()C]²BB"V>ɻPɻ`Roa|/a@~Zlhs	oi'YP%QWkI6FJfoT@/ErjsyT{3?{< vj+4A9j.z LT$Mw<IH@b~)sj5}{1~]G!^ft-)^FzE>6gA>cn6UHgk3Ǹրx?.AH/Ri1-!ITe gM웨`ؙeC'NM0TóBr`)1(iouԧ2O{PPc?2	Uj8/Y@w($bA\2#6oK0Ϲc?yN`r=q$|Ѯ\       Xn6SpE"i
W10V통0td1D<J{=Ȯ4{,QRe;!Ϗ~W%s9?
X\zPxvx2?b,D ]
n9 gqƵ*Lw^!Eq4KJ cҋ3r*	bc%$JЊc2%2㽒&խDba&$Nj$AI]Q[rH:m\tѽ1@q@.Xײ=BM6tngaocJVT<r5cǿH:>aǟݷٛr:r*:(|Dt<С#~!09ʶr}qqђ<7˗u7XdM=5<[hUɌEb:}s¦˖5QdLD>cXoJS0yad}_=ðVFZӭHl1HB)!:MIbԆ8lhH",
+˼ nGCWS>D`Ģy{avnULKR@XqC(+<
qLDQ92E$vJ0KU\ؔ9{;)3}6k雌'aNr3>GӷZUH	ݸ7}=
p^{rn}b&TjuEgCl6)T)	?]PBB]!lQVSj W>V#=0psGhPݘ=-ڽz*Wt$U9?׉7eF	k|!C"T=-η ^e?t23ݡ5&$~/BϺ10YbݨwL^te+yJ3z.T0 <BHf:WCYN}PkA9.V1wV_;X]zIxT/AOڵ/9Gսu#uQkC6J7&)EuLrrײ>ofbਞ`AsG(!Y}5JAcp~";[|_4^kHN(H}ba0+#ۮ2zW(+kQ!5G՚Cǰn3oEY;wJ#W@_`<ø˒ކ,	KDEI(M!Fj>]`3ic]!AK8rzUljIވl0ك}H]F<My3utCcc+ ^&HK:;a pϋVs&~?f/w.tݜ\T7<vUzau4ՙH_?       YYs8~ׯ@db7e1[[<@$$bL ߧ Os_,}u7K&"_I>O49&L)XB'B)1DH|`q8%w1#:(QȈHČ׹x`2c1%7'cW)#)Xl:D4#Sfb3XglrzysJf<eh@GH%Y .rH.N͔V;d(!K )l/ԕ9#	U2HF`1es ZLiS")mUt͔H-ؒ\+WpT&\yF<"g]lHC[ه/Q4)ũ5HCʳh-'ӔxWBk  oeHiiz	<D,/UJWS+؛O1}zD^dpLU<CHˊF4J?9tA>PV$Ƣ'rg6N|*#0ϯ>^Fցlb;6\64['8SMȃW1QACgꆥ,BBn-?}
5{KNo(F,,d((Z9!*Ul߆isau[U8v~ܦ	ݥ8`ˆxRE|;?'0+yjqv U6<Cڹ JLyg]_CL	,$4RTдGZWi5gEM&pzuI+9R%?:=6&?GݽXD
"rw/̎kC(*Td82*X9Đg	x^SUc fJPvX& CuB'9CeX}CyY<7C0*@Ef?΄bZΛXER-@J(s+s2A^IBF-XL\Xw2}2Rf\Z3[_ȭ$P<^"GpTsH+DXO3P
kp5nGK(Fyy> (>6`k؂2-R`86W%RޒzA;}
P|Ks㠱`Mz24u	4zyCTYӭ5ˀ.@[Qn7$BII  Bc߻T#B>KyVP {-Ҵna+1B bZQ/wuÌc%wVCC={9f5Ndy].N0Y,Yx9߲V.nU9$<}wi. oR`vPńe XX&P=Ƶ5vMU]ezuR&8À*(oy!]]#=^ KZ@.vsX!GN7Xs%Y*y|JI2`^RpM˄kr 꿥`cH*g\dYĂ-Cb$';$ΤPʤ\<Z=oLBe-m2CF+gB	[ kvu3jr 3t|Tנi͠y$}U຋vsFcPXNaiGR+UjG5	_1yX3j&	H]d#4{ANYlꛖ7Ztp8/fƑ%|NӶIQ0	}bS|2Ad>\;v5r#o.=JUYno͛YeUI>c*oC={Ͱ9iI4̇&n>+/DK.>,>erF#VBM_.tX\ㆁ21HBfrm<-p3E&K	x%̔f&ұ%Jj/v{k @ a߿K0vڛ78>O=)A%Y㥫4
2ɁJu#1-4=fV]ZHP'8^5bKabMEto8ICAH}<#CVF&P.S庚"1@\JJJwHHu]>ի4>P<s_3"`,2_AXq-]~Ɨf8X|C$:M5g!Z%
</9$"uGMb N.}OJIN1&;fY
p(aT<V.oLk+鋑yig",zsTS>\ڗRo       mS8{~ns9(YwLKv?t:űO$GrdL[YϫWYva:h<!`s>N 8teSpI0@CtC>a f( HCqzQCp9>xs~wL1qO@'2L4KB%t'ǧ`2:dm9,	H&p#0Mӓ샵q/QzC9]00c8	AE)n p7/JߏcWߦ~CGr9i@MpJQ18Nod̙bsX0bͨH4xIaA}u>>2q2*RT1N'0|c,c5yڏ')Z f\qO}*/tt⿂\v
+E`=?#)SM#8rtr2:GsG0  #Y_5[׽ost1Hǅ͝3;Pf`9e1"GpS+ʿ"t\ Jz7C)I|utJ>$ɩ$cďs@p(_|u0_؟_UbcN:CiNq*,.cXG$E4)8p'cX)5(r\KsnVK"VU]Q>$e"9J>~0GMrDdn1%(w.-`"(@)1,ED2
8ŋH, Aykp/%ROߟ/-3D0lQ^=0Swn	_-
4mɓҼZU݂ro.YS!bCPm}Bqsk?ʥzLF&N_#JTCnW0),Û. 9^B~$4<DDW:[y"inrm8-W`ң4\,rI	RYJ5U)|zUX2GW0p+	(n4'qhl!IZh"Z`0Xlk"́G90*kg׀i/j\}@tehKTqZ.00{Wt-!Rvn+`o[!(5Kmoev:Z.ߺʷ EgS5>BU(<oĜ7mh;:w k~I4GCBĞ
'+#3DpMt*眥qgJ|@q qX}ͪgebNxƕ(uSg4	_}͞մ}7:E㷹%ih_SX6jSB֠I-H7Ka߬3%f0	\l^TPlYm9ٮGS]((8v:m+
RSc-^4n4kQvy9
ޱQ64NZxiC.4O/E		Q9f~U.;2Ax6Uy\nwDH3V {ku!qoHj]ȟ>-P;݋s+h)K[YOl}4e-eteqieUz ,M0|Oz;JF]ֹcI4Yɍ̀yYbe~1/}0xFIMݎ?~QJVo݊o4ilk9Fy"N1[okʶVPݽwq uHz)0[C%;Vd<^v\Yvv pc7 19]<Bo%CE{DjWkW=,j<Ȧ
lo6\H?ol{uAOgOރZ.&g| s	(eO;QىyP<^<ܯR# #EMjX*sQ
xh`"if4^\0¹##kGCgo(>w`tH'AV-Ƶ	0Tƴ
,;Ҙ׆K3X<Pf+NLR"EWwb3N/?A5IN2,)5މr(A̠FN|㤣ԮgT'X&]* Uk4^z]I}DY<qY{~9HB.CvG&0q͡2(/uMF~nXS˕"*_:!a2Ou'D,&*8yD3[yЅldDʅ<ƪz(kNᢑ|8Z-i[ԸCcR57;;^jDO;FZֶ$tB1V^EiQۖxy4
-)dsS$wsÆK,D+#U\dY"é<;foLcJe)"Ԕ[81lSLDȮRMrR˹&wzJI\|4$fDW6'JM#L?2ɑ定Bۆ*7+"FزTdGd|
r˴~^{oM#yyEbl<Si(*սt4AP".VacxG-y:3G]xp'uxǰ
謷V=85a"KEp|>7W7G
PM2'N5}>S<Owr=6+Y(w,qPqM" ^50vތz\m[9 ;˃7EݻC.#wշ%RPo{w=qg\\FU^Fb$Fq!uQ̲DzF͏8X֎G4#R:Qq89=d  <!-- TODO(calamity): Remove this once manifest URL installs are implemented. -->
<!-- See https://crbug.com/896575 for details -->
<html>
<head>
  <link rel="manifest" href="manifest.json">
</head>
</html>
     Wn8}Wp]4-B]\;I;X,}[,ZKL$Q );nP.v)67K33CrK ɳǫ \W/_!6BdHZ}XY`S4WzGrXz[R*X
	n%/(#L}>,f(li@ *,8U2y(вR1 :*T7WQ.+VeFr>&&ǳ@V젔>ۗw#j䨠jq*`ZmXQ'\5$WkQpQ$BA3Bʈ0̪dZ⾝1׈6[DE^GB6XTo0'dCm>\k]ωUi-ٜRam5I4Qwaa8ن"ωk9[*w-Bl:tX9'kZr4[,)$5ho[Oee,F<fU@glH0@s2)_zϋ3otݱXJ4$,MfD7n'3b@d|!iO(VhayC6e\$s\"k&@]OnHԉQi ^!8_{P&ߩ.6fdYO-\:Ze-I|_u${CY|{um}VVqz;{eC>YUoӍ
/pg9jT9ɛ
ErtޞR,dy*?	{6%2לPm(	GH<.fɈ
īɖTX#x4	Nf
1bg\0r= ugI}&e`;O'`Xa_0YJ]YCc:E)D6):W*K#6	s]OgN?(ql+.D4un:Ҁ[ca4ucŖKo5Ƣ #5׀70{ۮtn +^K%0LW,c~w;	Z*ڶTt4T\o"hF[o;       uR]O0}8FmiBJ0\x$vgu}vhaH(9ש
Lz]\7i]g'=7·'m)ߐ.
	&;!oIclxZF7ŊRzaliDQ	ّ"q~ȍ\*o~HƷklkx
:6JkUY**6#<];uU"]9.[bf?965i
ǰ/9*(Wk(tO-h< N)pl>*av~Z4mlN{X"'S6JR&M`L>Sq>8}'vOP?8sRF/gأ=j       RF_}+4{x B'$&}dY:7Zuwf$lhg锜|r%WgkZq!W)Hp F)$DG@"%AL[뷿M4U(IfdR,&4C8gg$)Ѹ@|!9x>yIEɏ!w!'kcrDƑ6(鴠,\k	 uBhB<LaPAgagY9A3PM3o연4e-XKE*iVtbFg'?8ȂgrC~%aA
:r`TE4t#(EVrswaJP2bq)灂Q<#uy|Txfq
wPrsp-< ̯byR+n<k
ip{W' L2͡5oԭuډ9=e~U<V?*VdWU5%nyozZ6	Hw:87AVJIZ" S{Ątp[?eE*As|8ldHUxJ/ǝdd+U~ϿeP*_cOȔKb%6*OT۩Ez@ax^x#ȯs/a$g:AϵvtbqPO*hg.Z/vWG[ɕJ?^,aޑKn\{⟲LrlX\OjEt矶8#=qǕJUWK;1 8QӸTSu2 CңT}Y~o 8M5Ռ5l!88D@ңg7=_z	gr6Luy\K5|Y!.N;T$UHn_qOXB|V_^̞U,Vh{dt'Ά5c18$8eUcX.4r洚Z),1g7W -/^ vZKjcĎ\O?]Aьu"6TF+k=T!Y!nEFs~LifPyZ Zmڳ:^f5ϓ0F銿\!r2mrK흉apWGaun9R#|\ՕB|"uMZ_ψAGa&JlS=օ]w[y֠|d7=
U֨{_r+ez=];ᠱ닚B=z˔taMku{ڠ5 'mY߼d11*&N.Yؾi<2B*\o;8ɺ̶uv%nzrc!Ӛ}(  6
MouseEventCount#  ?  HA LD XE ME NFG*
KeyEventCount   ?  A xC D E;
NavigationEntryCount#  @  @  @  HA  A  A  FB\
MRUIndexP  ?   @  @  A  A  A  B  B C C xC @C @C C @C D
TouchEventCount
   @ 4F7
NumReactivationBefore   ?  ?  `@  @  A  A!
TopDomain_1080024851943145123M#
TopDomain_15689501676488870256"
TopDomain_15061790812729663598~#
TopDomain_17805263144043282746"
TopDomain_15183327860286992060
MouseEventCount_6#
TopDomain_17609869936025638318
Type_1"
TopDomain_10119661862724640164G

MRUIndex_9"
TopDomain_3206887100623121722"
TopDomain_10043033701369158400E!
TopDomain_959275671374652467 
TopDomain_87712541284966463"
TopDomain_1572676409482578135

MRUIndex_8"
TopDomain_2684509497774788840"
TopDomain_3871863902853417076"
TopDomain_13201593719927070652k
IsPinned#
TopDomain_17665177956735407683#
TopDomain_15894589896585942567"
TopDomain_11085224173626070834S
SiteEngagementScore_70B!
TopDomain_1388128116188258854t
NumReactivationBefore_6/#
TopDomain_15460036257622057721"
TopDomain_5161051873882288304"
TopDomain_7427709185199481811"
TopDomain_13012715934034554483h
TouchEventCount_1"
TopDomain_2064774450264892649
SiteEngagementScore_0:#
TopDomain_15847248848374708081
NavigationEntryCount_0 #
TopDomain_17348514064360434852#
TopDomain_15288598938443330327#
TopDomain_17454475692079618781"
TopDomain_4498139696238849296"
TopDomain_9594404622941547504"
TopDomain_9204579900384785527"
TopDomain_12525798276078776067f#
TopDomain_15655412894497687330"
TopDomain_9685155330727019174"
TopDomain_11018654186523614761Q"
TopDomain_6035613466181606704
NavigationEntryCount_2"#
TopDomain_17796737512117080128"
TopDomain_6045732738424972004"
TopDomain_11227683057626966116V
NumReactivationBefore_0)
TopDomain_11632560942001414[
SiteEngagementScore_50@"
TopDomain_5941799794948841680"
TopDomain_5841942723928569023!
TopDomain_196963497794912993
MouseEventCount_2"
TopDomain_2851264494900985422
PageTransitionIsRedirect5!
TopDomain_843676498139257074"
TopDomain_4294201111699280567"
TopDomain_9606618426864857338!
TopDomain_1153398345655265072Z"
TopDomain_10895494351168426693N"
TopDomain_10169506825395800337H"
TopDomain_13235606415688235361n"
TopDomain_7449205003113069198"
TopDomain_12138507100907984281c"
TopDomain_12128704406167545479b
NumReactivationBefore_1*"
TopDomain_4369365699833920337#
TopDomain_18429447622638145680
SiteEngagementScore_30>"
TopDomain_4804837807085259619
ShowState_16!
TopDomain_698916636646710575"
TopDomain_11164683519288964730U

MRUIndex_2#
TopDomain_17580878206960980545"
TopDomain_6935756648522340603
SiteEngagementScore_60A"
TopDomain_14596851351072705470y"
TopDomain_10921456545786979211P
NumReactivationBefore_3,"
TopDomain_1804284032727006986"
TopDomain_5203230528484920842"
TopDomain_12335924279508075969d
KeyEventCount_0
KeyEventCount_4#
TopDomain_15741269190621693221
WasRecentlyAudible
NavigationEntryCount_7'"
TopDomain_6508721319432249974!
TopDomain_236703431990620330#
TopDomain_17390321984555611993"
TopDomain_2957965146093936771"
TopDomain_8632220210146641000"
TopDomain_13208729640320280584l"
TopDomain_12386390640692202738e#
TopDomain_17811530796309643159#
TopDomain_16768701066384376478"
TopDomain_6163045271141768870"
TopDomain_2672907030994913228"
TopDomain_13115516086556974343j!
TopDomain_878847704185202492"
TopDomain_7088684986110897678"
TopDomain_4009933873399061218!
TopDomain_341490971205980837
MouseEventCount_1"
TopDomain_4764263413547323863"
TopDomain_2440596079597823666"
TopDomain_8555518466344315990"
TopDomain_8316249495056507568#
TopDomain_15966429509789767021!
TopDomain_1448229354234554080x#
TopDomain_16366079186907057253
NavigationEntryCount_3##
TopDomain_18378977400083720013"
TopDomain_8501429689397503793"
TopDomain_6337103823310205182
PageTransitionCoreType_21"
TopDomain_10187093199053808570I
KeyEventCount_3
MRUIndex_15"
TopDomain_5338723781413972714"
TopDomain_4760987115333628632
NavigationEntryCount_5%"
TopDomain_8144375594159422697#
TopDomain_15262276248633613016#
TopDomain_18300295044313409868"
TopDomain_5160451677974969231"
TopDomain_9664280485523735114!
TopDomain_1368146020981450700p!
TopDomain_876199788100362630
KeyEventCount_5	
MouseEventCount_3"
TopDomain_2968749863868578542"
TopDomain_8723982126215208982"
TopDomain_14157691472982757617u

MRUIndex_5"
TopDomain_7304754882072794192!
TopDomain_324364537650936070
MouseEventCount_5#
TopDomain_15387739340581110685"
TopDomain_3860317998083780863"
TopDomain_7350763718700977478#
TopDomain_17318491964161906161"
TopDomain_7063227438872759949"
TopDomain_1946495666138444138
SiteEngagementScore_10;#
TopDomain_15819600267779402594
PageTransitionCoreType_83
HasBeforeUnloadHandler "
TopDomain_10758121499324064194L
ShowState_27"
TopDomain_13717026609825930643q
MouseEventCount_7"
TopDomain_9605309396967163933
NumReactivationBefore_4- 
TopDomain_33819408664442396

MRUIndex_7"
TopDomain_7049109217806271285"
TopDomain_13473667061284296256o"
TopDomain_8256838480345576948
MRUIndex_12"
TopDomain_11281394909307332136X"
TopDomain_9646924245674468055"
TopDomain_13771742413608550493r
SiteEngagementScore_80C"
TopDomain_14625437354194983248z
NavigationEntryCount_6&"
TopDomain_13834769092094238000s
SiteEngagementScore_40?
NumReactivationBefore_2+"
TopDomain_12558476351114645767g#
TopDomain_16812564669986576421

MRUIndex_3"
TopDomain_11912199775964982622_
MRUIndex_10
MouseEventCount_0#
TopDomain_16079275975660711115#
TopDomain_17705640974703232252
TouchEventCount_2
MouseEventCount_4"
TopDomain_10740419527460090491K#
TopDomain_17999381730064795300#
TopDomain_16369899265487396589
IsActive#
TopDomain_16341703993826111523
SiteEngagementScore_20=#
TopDomain_18245469667301336119#
TopDomain_15921862757681270712"
TopDomain_11738965776604256531\"
TopDomain_8720606896994407571"
TopDomain_11389434805263954430Y!
TopDomain_1304085646556006376i"
TopDomain_15005136786217271573|"
TopDomain_1874056532838985632#
TopDomain_17950719759682742338"
TopDomain_7114699737129879665#
TopDomain_18337490325837093757"
TopDomain_8079398500111676442"
TopDomain_9499668011696157315"
TopDomain_14233941029653936165v#
TopDomain_17251037843225226770"
TopDomain_10901531562134450126O

MRUIndex_0
"
TopDomain_8429031694230093054#
TopDomain_17093041278158597643

MRUIndex_4"
TopDomain_9791677860763157788"
TopDomain_8494204192682713966"
TopDomain_10072413688749279773F#
TopDomain_16437285489292541054
NormalizedMRUIndex("
TopDomain_9020261517444911033
KeyEventCount_2#
TopDomain_15870042273117884100#
TopDomain_17045289118324886784!
TopDomain_510821771540594083"
TopDomain_15045547456553872263} 
PageTransitionFromAddressBar4
KeyEventCount_1!
TopDomain_1035925084514834068J"
TopDomain_3110799877618283806
ShowState_38!
TopDomain_651058769554286351
NavigationEntryCount_1!#
TopDomain_16751120787332825022#
TopDomain_16199790386872945279
HasFormEntry
MRUIndex_16"
TopDomain_5436730130443146323"
TopDomain_11954853327857560706`
TouchEventCount_0"
TopDomain_11796274831969683171]#
TopDomain_17631324395650738667!
TopDomain_752537756789258043
Type_2
PageTransitionCoreType_72
NumReactivationBefore_5.
ShowState_49
SiteEngagementScore_90D
PageTransitionCoreType_00
NavigationEntryCount_4$

MRUIndex_6"
TopDomain_2345074716881772422"
TopDomain_3177707200991458183#
TopDomain_16411198922429453306"
TopDomain_2495968728959269770"
TopDomain_12094168201145311450a"
TopDomain_2928222190293398513"
TopDomain_11873006736009776549^"
TopDomain_8944327742448415689"
TopDomain_5352397048417326769"
TopDomain_14986263851399781883{"
TopDomain_14429980498988674617w"
TopDomain_1621665845362371393"
TopDomain_9195558766026703544"
TopDomain_5011259669684447045"
TopDomain_11082551044701230453R"
TopDomain_3968615742235786342!
TopDomain_726059442646517786"
TopDomain_13216356480294047299m#
TopDomain_15487345791713004722#
TopDomain_15516523711153697558"
TopDomain_11279037034026214503W"
TopDomain_2023368772508865927

MRUIndex_1#
TopDomain_17349310390648753489
SiteEngagementScore_100<"
TopDomain_7746553357405203507"
TopDomain_11149338271801532545T#
TopDomain_15449547182571591448"
TopDomain_2311961509270792991*Type*PageTransitionCoreType*SiteEngagementScore*	ShowState<!doctype html>
<html dir="$i18n{textdirection}"
      hascustombackground="$i18n{hasCustomBackground}"
      bookmarkbarattached="$i18n{bookmarkbarattached}"
      lang="$i18n{language}"
      class="md">
<head>
<meta charset="utf-8">
<title>$i18n{title}</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  -webkit-font-smoothing: antialiased;
  font-size: 100%;
  margin: 0;
}

/** Typography -------------------------------------------------------------- */

.content {
  /* This is identical to the default background color. It's necessary to set it
     for the case when a theme with a background image is installed. */
  background-color: rgb(50, 54, 57);
  color: rgb(189, 193, 198);
  font-size: calc(100% - 2px);
  line-height: calc(100% + 6px);
  min-width: 240px;
}

h1 {
  color: rgb(218, 220, 224);
  font-size: calc(100% + 8px);
  font-weight: 400;
  line-height: calc(100% + 8px);
}

em {
  color: white;
  font-style: normal;
}

.learn-more-button {
  color: rgb(138, 180, 248);
  text-decoration: none;
}

/* Small font on small screens. */
@media (max-width: 240px),
       (max-height: 320px) {
  .content {
    font-size: calc(100% - 4px);
    line-height: calc(100% + 6px);
  }

  h1 {
    font-size: calc(100% + 4px);
    line-height: calc(100% + 4px);
  }
}

/** Icon -------------------------------------------------------------------- */

.icon {
  content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNDAgMjQwIj48ZyBvcGFjaXR5PSIuOCIgZmlsbD0iI0ZGRiI+PHBhdGggZD0iTTEyMSAwQzUzLjktLjYtLjYgNTMuOSAwIDEyMWMuNiA2NS4yIDUzLjggMTE4LjQgMTE5IDExOSA2Ny4xLjYgMTIxLjYtNTMuOSAxMjEtMTIxQzIzOS40IDUzLjggMTg2LjIuNiAxMjEgMHpNOTAuNSA1OWMuMy0uOSAxLTEuNSAyLjItMS4yIDIuMi41IDE5LjkgNC4zIDE5LjkgNC4zczM2LjgtNS42IDM4LjEtNS45YzEuMS0uMiAxLjkuNCAyLjEgMS40LjEuNCA2LjMgMjEuMyAxMS43IDM5LjVINzguM0M4My45IDc5LjYgOTAuMSA2MCA5MC41IDU5em04NS45IDEwMy4zYy0uOCAxMi4yLTEwLjcgMjIuMS0yMi45IDIyLjktMTQuMy45LTI2LjEtMTAuNC0yNi4xLTI0LjUgMC0uNyAwLTEuNC4xLTIuMS0yLS43LTQuMi0xLTYuNC0xLTIuMyAwLTQuNS40LTYuNyAxLjEuMS43LjEgMS4zLjEgMiAwIDE0LjEtMTEuOCAyNS40LTI2LjEgMjQuNS0xMi4yLS44LTIyLjEtMTAuNy0yMi45LTIyLjktLjgtMTQuMiAxMC41LTI2LjEgMjQuNS0yNi4xIDEwLjIgMCAxOSA2LjMgMjIuNyAxNS4yIDIuNy0uOCA1LjUtMS4zIDguNC0xLjMgMi44IDAgNS41LjQgOC4xIDEuMiAzLjctOC45IDEyLjQtMTUuMSAyMi43LTE1LjEgMTQuMSAwIDI1LjQgMTEuOSAyNC41IDI2LjF6bTIzLjQtMzQuM0g0Mi40Yy0uMiAwLS4zLS4zLS4xLS40IDUuMi0yLjcgMzUuNC0xNy42IDc5LTE3LjYgNDMuNyAwIDczLjUgMTQuOCA3OC42IDE3LjYuMi4xLjEuNC0uMS40eiIvPjxjaXJjbGUgY3g9IjE1MS45IiBjeT0iMTYwLjgiIHI9IjE3LjQiLz48Y2lyY2xlIGN4PSI5MC4xIiBjeT0iMTYwLjgiIHI9IjE3LjQiLz48L2c+PC9zdmc+);
  height: 120px;
  width: 120px;
}

/* Medium-sized icon on medium-sized screens. */
@media (max-height: 480px),
       (max-width: 720px) {
  .icon {
    height: 72px;
    width: 72px;
  }
}

/* Very small icon on very small screens. */
@media (max-width: 720px) {
  @media (max-width: 240px),
         (max-height: 480px) {
    .icon {
      height: 48px;
      width: 48px;
    }
  }
}

/** The "Learn more" link --------------------------------------------------- */

/* By default, we only show the inline "Learn more" link. */
.content > .learn-more-button {
  display: none;
}

/* On narrow screens, we show the standalone "Learn more" link. */
@media (max-width: 720px) {
  #subtitle > .learn-more-button {
    display: none;
  }

  .content > .learn-more-button {
    display: block;
  }
}

/** Layout ------------------------------------------------------------------ */

/* Align the content, icon, and title to to the center. */
.content {
  margin-left: auto;
  margin-right: auto;
  max-width: 600px;
}

.icon {
  margin-left: auto;
  margin-right: auto;
}

h1 {
  text-align: center;
}

/* Align the two columns of bulletpoints next to each other. */
.bulletpoints {
  float: left;
}

html[dir=rtl] .bulletpoints {
  float: right;
}

.bulletpoints + .bulletpoints {
  clear: right;
}

html[dir=rtl] .bulletpoints + .bulletpoints {
  clear: left;
}

.clearer {
  clear: both;
}

/* On narrow screens, align everything to the left. */
@media (max-width: 720px) {
  .content {
    max-width: 600px !important;  /* must override the rule set by JS which
                                   * is only valid for width > 720px cases. */
    text-align: start;
  }

  .icon {
    margin-inline-start: 0;
  }

  h1 {
    text-align: start;
  }

  .bulletpoints + .bulletpoints,
  html[dir=rtl] .bulletpoints + .bulletpoints {
    clear: both;
  }
}

/** Paddings and margins ---------------------------------------------------- */

.bulletpoints ul {
  margin: 4px 0 0;
  padding-inline-start: 16px;
}

/* Margins of floating elements don't collapse. The margin for bulletpoints
 * will usually be provided by a neighboring element. */
.bulletpoints {
  margin: 0;
}

.bulletpoints + .bulletpoints {
  margin-inline-start: 40px;
}

.bulletpoints + .bulletpoints.too-wide {
  margin-inline-start: 0;
  margin-top: 1.5rem;
}

/* Wide screens. */
@media (min-width: 720px) {
  .icon,
  h1,
  #subtitle,
  .learn-more-button {
    margin-bottom: 1.5rem;
    margin-top: 1.5rem;
  }

  .content {
    margin-top: 40px;
    min-width: 240px;
    padding: 8px 48px 24px;
  }

  /* Snap the content box to the whole height on short screens. */
  @media (max-height: 480px) {
    html,
    body,
    .content {
      height: 100%;
    }

    .content {
      margin-bottom: 0;
      margin-top: 0;
      padding-bottom: 0;
      padding-top: 0;
    }

    .icon {
      margin-top: 0;
      padding-top: 32px;  /* Define the top offset through the icon's padding,
                           * otherwise the screen height would be 100% + 32px */
    }
  }

  /* Smaller vertical margins on very short screens. */
  @media (max-height: 320px) {
    h1,
    #subtitle,
    .learn-more-button {
      margin-bottom: 16px;
      margin-top: 16px;
    }

    .icon {
      margin-bottom: 16px;
    }
  }
}

/* Narrow screens */
@media (max-width: 720px) {
  .content {
    padding: 72px 32px;
    min-width: 176px;
  }

  .icon,
  h1,
  #subtitle,
  .learn-more-button {
    margin-bottom: 1.5rem;
    margin-top: 1.5rem;
  }

  /* The two columns of bulletpoints are moved under each other. */
  .bulletpoints + .bulletpoints {
    margin-inline-start: 0;
    margin-top: 1.5rem;
  }

  /* Smaller offsets on smaller screens. */
  @media (max-height: 600px) {
    .content {
      padding-top: 48px;
    }

    .icon,
    h1,
    #subtitle,
    .learn-more-button {
      margin-bottom: 1rem;
      margin-top: 1rem;
    }

    .bulletpoints + .bulletpoints {
      margin-top: 1rem;
    }
  }

  /* Small top offset on very small screens. */
  @media (max-height: 480px) {
    .content {
      padding-top: 32px;
    }
  }

  /* Undo the first and last elements margins. */
  .icon {
    margin-top: 0;
  }

  .learn-more-button {
    margin-bottom: 0;
  }
}

/* Very narrow screens. */
@media (max-width: 240px) {
  .content {
    min-width: 192px;
    padding-left: 24px;
    padding-right: 24px;
  }
}
</style>
<script>
// Until themes can clear the cache, force-reload the theme stylesheet.
document.write('<link id="incognitothemecss" rel="stylesheet" ' +
               'href="chrome://theme/css/incognito_new_tab_theme.css?' +
               Date.now() + '">');
</script>
</head>
<body>
<div class="content">
  <div class="icon" role="presentation" alt=""></div>
  <h1>$i18n{incognitoTabHeading}</h1>
  <p id="subtitle">
    <span>$i18n{incognitoTabDescription}</span>
    <a class="learn-more-button"
        href="$i18n{learnMoreLink}">$i18n{learnMore}</a>
  </p>
  <div>
    <div class="bulletpoints">$i18nRaw{incognitoTabFeatures}</div>
    <div class="bulletpoints">$i18nRaw{incognitoTabWarning}</div>
    <div class="clearer"></div>
  </div>
  <a class="learn-more-button" href="$i18n{learnMoreLink}">$i18n{learnMore}</a>
</div>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Let the width of two lists of bulletpoints in a horizontal alignment
// determine the maximum content width.
function recomputeLayoutWidth() {
  const bulletpoints = document.querySelectorAll('.bulletpoints');
  const content = document.querySelector('.content');

  // Unless this is the first load of the Incognito NTP in this session and
  // with this font size, we already have the maximum content width determined.
  const fontSize = window.getComputedStyle(document.body).fontSize;
  let maxWidth = localStorage[fontSize] ||
      (bulletpoints[0].offsetWidth + bulletpoints[1].offsetWidth +
       40 /* margin */ + 2 /* offsetWidths may be rounded down */);

  // Save the data for quicker access when the NTP is reloaded. Note that since
  // we're in the Incognito mode, the local storage is ephemeral and the data
  // will be discarded when the session ends.
  localStorage[fontSize] = maxWidth;

  // Limit the maximum width to 600px. That might force the two lists
  // of bulletpoints under each other, in which case we must swap the left
  // and right margin.
  const MAX_ALLOWED_WIDTH = 600;
  const tooWide = maxWidth > MAX_ALLOWED_WIDTH;
  bulletpoints[1].classList.toggle('too-wide', tooWide);
  if (tooWide) {
    maxWidth = MAX_ALLOWED_WIDTH;
  }

  content.style.maxWidth = maxWidth + 'px';
}

window.addEventListener('load', recomputeLayoutWidth);

// Handle the bookmark bar, theme, and font size change requests
// from the C++ side.
const ntp = {
  /** @param {string} attached */
  setBookmarkBarAttached: function(attached) {
    document.documentElement.setAttribute('bookmarkbarattached', attached);
  },

  /** @param {!{hasCustomBackground: boolean}} themeData */
  themeChanged: function(themeData) {
    document.documentElement.setAttribute(
        'hascustombackground', themeData.hasCustomBackground);
    $('incognitothemecss').href =
        'chrome://theme/css/incognito_new_tab_theme.css?' + Date.now();
  },

  defaultFontSizeChanged: function() {
    setTimeout(recomputeLayoutWidth, 100);
  }
};
</script>
</body>
</html>
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<title>$i18n{title}</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Incognito and guest mode NTP shared CSS. */

body {
  -webkit-font-smoothing: antialiased;
  font-size: 85%;
}

h1 {
  font-size: 200%;
  font-weight: 400;
  margin-bottom: .77em;
}

p {
  line-height: 1.5;
  margin: .588em 0;
  text-align: start;
}

a {
  color: rgb(51, 103, 214);
}

a:hover {
  text-decoration: underline;
}

/* 'Learn More' button styled like a Material Design text button.
 * TODO(edwardjung): Switch styled links to actual text buttons. */
.learn-more-button {
  color: rgb(66, 133, 244);
  display: inline-block;
  font-size: 92.8%;
  font-weight: 500;
  margin-top: 1.98em;
  padding: 10.5px 12px;
  text-decoration: none;
  text-transform: uppercase;
}

.content {
  box-sizing: border-box;
  margin: 3.5em auto 0;
  max-width: 480px;
  min-width: 240px;
  padding: 30px 35px;
  text-align: center;
}

html[hascustombackground='true'] .content {
  border-radius: 2px;
  box-shadow: 0 4px 6px 1px rgba(0, 0, 0, 0.4);
}

.content > span {
  display: block;
}

@media (max-width:700px) {
  body {
    margin: 1em 2em 2em;
  }
}

@media (max-width:400px) {
  body {
    margin: 3em 1.5em 2em;
  }

  /* Adjustment for narrow screen to prevent horizontal scrollbar. */
  .content {
    padding: 16px 8px;
  }
}

@media (max-height:480px) and (max-width:400px) {
  .content {
    margin: auto;
  }
}
</style>
</head>
<body>
<div class="content">
  <h1>$i18n{guestTabHeading}</h1>
  <p>$i18n{guestTabDescription}</p>
  <a class="learn-more-button" href="$i18n{learnMoreLink}">$i18n{learnMore}</a>
</div>
</body>
</html>
/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html {
  background-attachment: fixed;
  background-color: $i18n{colorBackground};
  background-position: $i18n{backgroundBarDetached};
  background-repeat: $i18n{backgroundTiling};
  height: 100%;
  overflow: auto;
}

html[hascustombackground='true'] {
  background-image: url(chrome://theme/IDR_THEME_NTP_BACKGROUND?$i18n{themeId});
}

html[bookmarkbarattached='true'] {
  background-position: $i18n{backgroundBarAttached};
}

#attribution-img {
  content: url(chrome://theme/IDR_THEME_NTP_ATTRIBUTION?$i18n{themeId});
}
<!doctype html>
<html class="starting-up" dir="$i18n{textdirection}"
    bookmarkbarattached="$i18n{bookmarkbarattached}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<title>$i18n{title}</title>
<!-- Don't scale the viewport in either portrait or landscape mode.
     Note that this means apps will be reflowed when rotated (like iPad).
     If we wanted to maintain position we could remove 'maximum-scale' so
     that we'd zoom out in portrait mode, but then there would be a bunch
     of unusable space at the bottom.
-->
<meta name="viewport"
      content="user-scalable=no, width=device-width, maximum-scale=1.0">

<!-- It's important that this be the first script loaded. -->
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview
 * Logging info for benchmarking purposes. Should be the first js file included.
 */

/* Stack of events that has been logged. */
const eventLog = [];

/**
 * Logs an event.
 * @param {string} name The name of the event (can be any string).
 * @param {boolean=} opt_shouldLogTime If true, the event is used for
 *     benchmarking and the time is logged. Otherwise, just push the event on
 *     the event stack.
 */
function logEvent(name, opt_shouldLogTime) {
  if (opt_shouldLogTime) {
    chrome.send('metricsHandler:logEventTime', [name]);
  }
  eventLog.push([name, Date.now()]);
}

logEvent('Tab.NewTabScriptStart', true);
window.addEventListener('load', function(e) {
  logEvent('Tab.NewTabOnload', true);
});
document.addEventListener('DOMContentLoaded', function(e) {
  logEvent('Tab.NewTabDOMContentLoaded', true);
});
</script>

<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.bubble {
  position: absolute;
  white-space: normal;
  /* Height is dynamic, width fixed. */
  width: 300px;
  z-index: 9999;
}

.bubble-content {
  color: black;
  line-height: 150%;
  margin: 1px;
  padding: 8px 11px 12px;
  position: relative;
  z-index: 3;
}

/* When the close button is there, we need more padding on the right of the
 * bubble. */
.bubble-close:not([hidden]) ~ .bubble-content {
  padding-inline-end: 22px;
}

.bubble-close {
  height: 16px;
  position: absolute;
  right: 6px;
  top: 6px;
  width: 16px;
  z-index: 4;
}

html[dir='rtl'] .bubble-close {
  left: 6px;
  right: auto;
}

.bubble-close {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg==) 1x);
}

.bubble-close:hover {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqUlEQVR4XqWRMQqEMBBF/1E8Ra6x6V3FRnS9QbCxtJg6Z7CzE9lTiIXXyUb3C8EULixDIMM8Zt4kcDfxM5A45U+cgeXnC1tREgkzAgob3hiq3CUHvGLG4FTQoSgxQGDrzN8WTLBGnx2IVDksen9GH7Z9hA5E6uxABMJyCHDMCEGHzugLQPPlBCBNGq+5YtpnGw1Bv+te15ypljTpVzdak5Opy+z+qf//zQ+Lg+07ay5KsgAAAABJRU5ErkJggg==) 1x);
}

.bubble-close:active {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAQklEQVR4AWP4TwBSTQGDHcMZIIYAKA9VwRkwtINJgyCaCTAlCBaKAoQ+hFmoCqBKENKkK8C0gpAjCXuTyICiQ2QBAPSwyG3ByZlCAAAAAElFTkSuQmCC) 1x);
}

.bubble-shadow {
  bottom: 0;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 1;
}

.bubble-arrow {
  box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.15);
  height: 15px;
  position: absolute;
  transform: rotate(45deg);
  width: 15px;
  z-index: 2;
}

.bubble-content,
.bubble-arrow {
  background: white;
}

.bubble-shadow,
.bubble-arrow {
  border: 1px solid rgba(0, 0, 0, 0.3);
}

.bubble-shadow,
.bubble-content {
  border-radius: 6px;
  box-sizing: border-box;
}

.auto-close-bubble {
  position: fixed;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.expandable-bubble {
  -webkit-border-image: url(chrome://theme/IDR_APP_NOTIFICATION_SMALL_BUBBLE)
                        5 5 7 6 stretch;
  -webkit-box-sizing: border-box;
  border-width: 5px 5px 7px 6px;
  color: #444;
  cursor: pointer;
  display: inline-block;
  font-size: 12px;
  position: absolute;
  user-select: none;
  z-index: 1;
}

.expandable-bubble::after {
  bottom: -1px;
  content: url(chrome://theme/IDR_APP_NOTIFICATION_NUB);
  display: block;
  height: 7px;
  position: absolute;
  right: 5px;  /* TODO(finnur): Need to handle RTL properly. */
  width: 9px;
}

.expandable-bubble > .expandable-bubble-contents > .expandable-bubble-title {
  display: inline-block;
  margin-left: 1px;
  margin-top : -3px;
  overflow: hidden;
  white-space: nowrap;
}

.expandable-bubble[masked] > .expandable-bubble-contents >
    .expandable-bubble-title::after {
  content: url(chrome://theme/IDR_APP_NOTIFICATION_NUB_MASK);
  display: block;
  height: 15px;
  overflow: hidden;
  position: absolute;
  right: 0;
  top: 0;
  width: 12px;
}

.expandable-bubble[expanded] > .expandable-bubble-contents >
    .expandable-bubble-title {
  font-size: 13px;
  margin-bottom: 3px;
  margin-left: 0;
}

.expandable-bubble-close {
  height: 16px;
  position: absolute;
  right: 0;
  top: 0;
  width: 16px;
  z-index: 2;
}

.expandable-bubble[expanded] {
  padding: 3px;
  z-index: 3;  /* One higher then the close button on an unexpanded bubble. */
}

.expandable-bubble[expanded] > .expandable-bubble-close {
  z-index: 4;
}

.expandable-bubble-close {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg==) 1x);
}

.expandable-bubble-close:hover {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqUlEQVR4XqWRMQqEMBBF/1E8Ra6x6V3FRnS9QbCxtJg6Z7CzE9lTiIXXyUb3C8EULixDIMM8Zt4kcDfxM5A45U+cgeXnC1tREgkzAgob3hiq3CUHvGLG4FTQoSgxQGDrzN8WTLBGnx2IVDksen9GH7Z9hA5E6uxABMJyCHDMCEGHzugLQPPlBCBNGq+5YtpnGw1Bv+te15ypljTpVzdak5Opy+z+qf//zQ+Lg+07ay5KsgAAAABJRU5ErkJggg==) 1x);
}

.expandable-bubble-close:active {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAQklEQVR4AWP4TwBSTQGDHcMZIIYAKA9VwRkwtINJgyCaCTAlCBaKAoQ+hFmoCqBKENKkK8C0gpAjCXuTyICiQ2QBAPSwyG3ByZlCAAAAAElFTkSuQmCC) 1x);
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

cr-menu {
  -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, .50);
  background: white;
  border-radius: 2px;
  color: black;
  cursor: default;
  left: 0;
  margin: 0;
  outline: 1px solid rgba(0, 0, 0, 0.2);
  padding: 8px 0;
  position: fixed;
  white-space: nowrap;
  z-index: 3;
}

cr-menu:not(.decorated) {
  display: none;
}

cr-menu > * {
  box-sizing: border-box;
  display: block;
  margin: 0;
  text-align: start;
  width: 100%;
}

cr-menu > :not(hr) {
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: black;
  font: inherit;
  line-height: 18px;
  outline: none;
  overflow: hidden;
  padding: 0 19px;
  text-overflow: ellipsis;
}

cr-menu > hr {
  background: -webkit-linear-gradient(left,
                                      rgba(0, 0, 0, .10),
                                      rgba(0, 0, 0, .02) 96%);
  border: 0;
  height: 1px;
  margin: 8px 0;
}

cr-menu > [disabled] {
  color: rgba(0, 0, 0, .3);
}

cr-menu > [hidden] {
  display: none;
}

cr-menu > :not(hr):-webkit-any([selected], :active) {
  background-color: rgba(0, 0, 0, .06);
}

cr-menu > [checked]::before {
  content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAPUlEQVR4AWNAA8YMgugC7xiUGICixkgC/0FCSkCGMVzgHUijEphRDhGA6BAEc/5DBRBmIAQQgneRBP5jQAAe7CCchpa/PQAAAABJRU5ErkJggg==);
  display: inline-block;
  height: 9px;
  margin: 0 5px;
  width: 9px;
}

cr-menu > [checked] {
  padding-inline-start: 0;
}

cr-menu > [selected][checked]:active::before {
  content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAQklEQVR4Xl3LQQ0AIAwDwFmYBSxMHGqxgIVSmjSEpZ/ulgb+FLLDxggkywNcGixlICZJZQr05FAHDCRPDCLhEph6DuGWaFS/FhbPAAAAAElFTkSuQmCC);
}

/* TODO(zvorygin) menu > [shortcutText]::after - this selector is much better,
 * but it's buggy in current webkit revision, so I have to use [showShortcuts].
 */
cr-menu[showShortcuts] > ::after {
  color: #999;
  content: attr(shortcutText);
  float: right;
  padding-inline-start: 30px;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* NOTE: If you are using the drop-down style, you must first call
 * MenuButton.createDropDownArrows() to initialize the CSS canvases that
 * contain the arrow images. */

button.menu-button.drop-down {
  background: white url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNjMGMzYzYiIHdpZHRoPSI2IiBoZWlnaHQ9IjMiIHZpZXdib3g9IjAgMCA2IDMiPgogIDxwYXRoIGQ9Ik0wIDAgTDYgMCBMMyAzIiB3aWR0aD0iNiIgaGVpZ2h0PSIzIi8+Cjwvc3ZnPgo=) no-repeat center 4px;
  border: 1px solid rgb(192, 195, 198);
  border-radius: 2px;
  height: 12px;
  margin: 0 5px;
  padding: 0;
  position: relative;
  top: 1px;
  width: 12px;
}

button.menu-button.drop-down:hover {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiMwMDAiIHdpZHRoPSI2IiBoZWlnaHQ9IjMiIHZpZXdib3g9IjAgMCA2IDMiPgogIDxwYXRoIGQ9Ik0wIDAgTDYgMCBMMyAzIiB3aWR0aD0iNiIgaGVpZ2h0PSIzIi8+Cjwvc3ZnPgo=);
  border-color: rgb(48, 57, 66);
}

button.menu-button.drop-down[menu-shown],
button.menu-button.drop-down:focus {
  background-color: rgb(48, 57, 66);
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHdpZHRoPSI2IiBoZWlnaHQ9IjMiIHZpZXdib3g9IjAgMCA2IDMiPgogIDxwYXRoIGQ9Ik0wIDAgTDYgMCBMMyAzIiB3aWR0aD0iNiIgaGVpZ2h0PSIzIi8+Cjwvc3ZnPgo=);
  border-color: rgb(48, 57, 66);
}

button.menu-button.using-mouse {
  outline: none;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.trash {
  -webkit-appearance: none;
  background: none;
  border: none;
  cursor: pointer;
  display: inline-block;
  outline: none;
  padding: 0;
  position: relative;
  width: 30px;
}

.trash > span {
  display: inline-block;
}

.trash > .can,
.trash > .lid {
  background: url(chrome://resources/images/trash.png) 0 0 no-repeat;
  left: 8px;
  position: absolute;
  right: 8px;
  top: 2px;
}

.trash > .lid {
  height: 6px;
  transform-origin: -7% 100%;
  transition: transform 150ms;
  width: 14px;
}

html[dir='rtl'] .trash > .lid {
  transform-origin: 107% 100%;
}

.trash:-webkit-any(:focus, :hover, .open) > .lid {
  transform: rotate(-45deg);
  transition: transform 250ms;
}

html[dir='rtl'] .trash:-webkit-any(:focus, :hover, .open) > .lid {
  transform: rotate(45deg);
}

.trash > .can {
  background-position: -1px -4px;
  height: 12px;
  /* The margins match the background position offsets. */
  margin-left: 1px;
  /* The right margin is one greater due to a shadow on the trash image. */
  margin-right: 2px;
  margin-top: 4px;
  width: 11px;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* This file defines styles for form controls. The order of rule blocks is
 * important as there are some rules with equal specificity that rely on order
 * as a tiebreaker. These are marked with OVERRIDE. */

/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

[is='action-link'] {
  cursor: pointer;
  display: inline-block;
  text-decoration: none;
}

[is='action-link']:hover {
  text-decoration: underline;
}

[is='action-link']:active {
  color: rgb(5, 37, 119);
  text-decoration: underline;
}

[is='action-link'][disabled] {
  color: #999;
  cursor: default;
  pointer-events: none;
  text-decoration: none;
}

[is='action-link'].no-outline {
  outline: none;
}


/* Default state **************************************************************/

:-webkit-any(button,
             input[type='button'],
             input[type='submit']):not(.custom-appearance),
select,
input[type='checkbox'],
input[type='radio'] {
  -webkit-appearance: none;
  background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 2px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
      inset 0 1px 2px rgba(255, 255, 255, 0.75);
  color: #444;
  font: inherit;
  margin: 0 1px 0 0;
  outline: none;
  text-shadow: 0 1px 0 rgb(240, 240, 240);
  user-select: none;
}

:-webkit-any(button,
             input[type='button'],
             input[type='submit']):not(.custom-appearance),
select {
  min-height: 2em;
  min-width: 4em;
  padding-bottom: 1px;

  /* The following platform-specific rule is necessary to get adjacent
   * buttons, text inputs, and so forth to align on their borders while also
   * aligning on the text's baselines. */
  padding-bottom: 2px;

  padding-top: 1px;
}

:-webkit-any(button,
             input[type='button'],
             input[type='submit']):not(.custom-appearance) {
  padding-inline-end: 10px;
  padding-inline-start: 10px;
}

select {
  -webkit-appearance: none;
  /* OVERRIDE */
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUUlEQVR4AWP4TxREZkYxpKHAKKzKEhOZvyG4zN8SE7Eq+6+wYCHbTwiT7eeChf8VsFsKVQhTxIDDbVCFfF8ginApgyp82wRShEcZVJIVzoJDAGqrgIJGRl20AAAAAElFTkSuQmCC),
      -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
  background-position: right center;
  background-repeat: no-repeat;
  padding-inline-end: 24px;
  padding-inline-start: 10px;
}

html[dir='rtl'] select {
  background-position: center left;
}

input[type='checkbox'] {
  height: 13px;
  position: relative;
  vertical-align: middle;
  width: 13px;
}

input[type='radio'] {
  /* OVERRIDE */
  border-radius: 100%;
  height: 15px;
  position: relative;
  vertical-align: middle;
  width: 15px;
}

/* TODO(estade): add more types here? */
input[type='number'],
input[type='password'],
input[type='search'],
input[type='text'],
input[type='url'],
input:not([type]),
textarea {
  border: 1px solid #bfbfbf;
  border-radius: 2px;
  box-sizing: border-box;
  color: #444;
  font: inherit;
  margin: 0;
  /* Use min-height to accommodate addditional padding for touch as needed. */
  min-height: 2em;
  outline: none;
  padding: 3px;

  /* For better alignment between adjacent buttons and inputs. */
  padding-bottom: 4px;

}

input[type='search'] {
  -webkit-appearance: textfield;
  /* NOTE: Keep a relatively high min-width for this so we don't obscure the end
   * of the default text in relatively spacious languages (i.e. German). */
  min-width: 160px;
}

/* Checked ********************************************************************/

input[type='checkbox']:checked::before {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAQAAAADpb+tAAAAZ0lEQVR4AWNAA2xAiAXEM8xiMEAXVGJYz7AZCFEkmBi6wYKtEC4/gxqY9gILrmYQhwiXMWxkiAVyVoOFfSCCpkAmCK4Fk+1QA4GqekECUAMkka0KY9gIFvZDd5oawwyGBqACdIDqOwAQzBnTWnnU+gAAAABJRU5ErkJggg==);
  background-size: 100% 100%;
  content: '';
  display: block;
  height: 100%;
  user-select: none;
  width: 100%;
}

input[type='radio']:checked::before {
  background-color: #666;
  border-radius: 100%;
  bottom: 3px;
  content: '';
  display: block;
  left: 3px;
  position: absolute;
  right: 3px;
  top: 3px;
}


/* Hover **********************************************************************/

:enabled:hover:-webkit-any(
    select,
    input[type='checkbox'],
    input[type='radio'],
    :-webkit-any(
        button,
        input[type='button'],
        input[type='submit']):not(.custom-appearance)) {
  background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
  border-color: rgba(0, 0, 0, 0.3);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12),
      inset 0 1px 2px rgba(255, 255, 255, 0.95);
  color: black;
}

:enabled:hover:-webkit-any(select) {
  /* OVERRIDE */
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUUlEQVR4AWP4TxREZkYxpKHAKKzKEhOZvyG4zN8SE7Eq+6+wYCHbTwiT7eeChf8VsFsKVQhTxIDDbVCFfF8ginApgyp82wRShEcZVJIVzoJDAGqrgIJGRl20AAAAAElFTkSuQmCC),
      -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
}


/* Active *********************************************************************/

:enabled:active:-webkit-any(
    select,
    input[type='checkbox'],
    input[type='radio'],
    :-webkit-any(
        button,
        input[type='button'],
        input[type='submit']):not(.custom-appearance)) {
  background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
  box-shadow: none;
  text-shadow: none;
}

:enabled:active:-webkit-any(select) {
  /* OVERRIDE */
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUUlEQVR4AWP4TxREZkYxpKHAKKzKEhOZvyG4zN8SE7Eq+6+wYCHbTwiT7eeChf8VsFsKVQhTxIDDbVCFfF8ginApgyp82wRShEcZVJIVzoJDAGqrgIJGRl20AAAAAElFTkSuQmCC),
      -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
}

/* Disabled *******************************************************************/

:disabled:-webkit-any(
    button,
    input[type='button'],
    input[type='submit']):not(.custom-appearance),
select:disabled {
  background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);
  border-color: rgba(80, 80, 80, 0.2);
  box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08),
      inset 0 1px 2px rgba(255, 255, 255, 0.75);
  color: #aaa;
}

select:disabled {
  /* OVERRIDE */
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAASUlEQVR4AWP4TxREZkYxpKHAKKzKEhMb/iPDxESsyv4rLFiIULRg4X8F7JaCFSIUMeBwG1QhTBEuZVCFb5tAivAog0qywllwCAAavoiLhz+UlAAAAABJRU5ErkJggg==),
      -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);
}

input:disabled:-webkit-any([type='checkbox'],
                           [type='radio']) {
  opacity: .75;
}

input:disabled:-webkit-any([type='password'],
                           [type='search'],
                           [type='text'],
                           [type='url'],
                           :not([type])) {
  color: #999;
}

/* Focus **********************************************************************/

:enabled:focus:-webkit-any(
    select,
    input[type='checkbox'],
    input[type='number'],
    input[type='password'],
    input[type='radio'],
    input[type='search'],
    input[type='text'],
    input[type='url'],
    input:not([type]),
    :-webkit-any(
         button,
         input[type='button'],
         input[type='submit']):not(.custom-appearance)) {
  /* We use border color because it follows the border radius (unlike outline).
   * This is particularly noticeable on mac. */
  border-color: rgb(77, 144, 254);
  outline: none;
  /* OVERRIDE */
  transition: border-color 200ms;
}

/* Checkbox/radio helpers ******************************************************
 *
 * .checkbox and .radio classes wrap labels. Checkboxes and radios should use
 * these classes with the markup structure:
 *
 *   <div class="checkbox">
 *     <label>
 *       <input type="checkbox">
 *       <span>
 *     </label>
 *   </div>
 */

:-webkit-any(.checkbox, .radio) label {
  /* Don't expand horizontally: <http://crbug.com/112091>. */
  align-items: center;
  display: inline-flex;
  padding-bottom: 7px;
  padding-top: 7px;
  user-select: none;
}

:-webkit-any(.checkbox, .radio) label input {
  flex-shrink: 0;
}

:-webkit-any(.checkbox, .radio) label input ~ span {
  /* Make sure long spans wrap at the same horizontal position they start. */
  display: block;
  margin-inline-start: 0.6em;
}

:-webkit-any(.checkbox, .radio) label:hover {
  color: black;
}

label > input:disabled:-webkit-any([type='checkbox'], [type='radio']) ~ span {
  color: #999;
}

extensionview {
  display: inline-block;
  height: 300px;
  width: 300px;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.app {
  outline: none;
  position: absolute;
  text-align: center;
}

.app-contents {
  transition: transform 100ms;
}

.app-contents:active:not(.suppress-active),
.app:not(.click-focus):focus .app-contents:not(.suppress-active),
.drag-representation:not(.placing) .app-contents {
  transform: scale(1.1);
}

/* Don't animate the initial scaling.  */
.app-contents:active:not(.suppress-active),
/* Active gets applied right before .suppress-active, so to avoid flicker
 * we need to make the scale go back to normal without an animation. */
.app-contents.suppress-active {
  transition-duration: 0ms;
}

.app-contents > span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-img-container {
  /* -webkit-mask-image set by JavaScript to the image source. */
  -webkit-mask-size: 100% 100%;
  margin-left: auto;
  margin-right: auto;
}

.app-img-container > * {
  height: 100%;
  width: 100%;
}

.app-icon-div {
  -webkit-box-align: center;
  -webkit-box-pack: center;
  background-color: white;
  border: 1px solid #d5d5d5;
  border-radius: 5px;
  display: -webkit-box;
  margin-left: auto;
  margin-right: auto;
  position: relative;
  vertical-align: middle;
  z-index: 0;
}

.app-icon-div .app-img-container {
  bottom: 10px;
  left: 10px;
  position: absolute;
}

.app-icon-div .color-stripe {
  border-bottom-left-radius: 5px 5px;
  border-bottom-right-radius: 5px 5px;
  bottom: 0;
  height: 3px;
  opacity: 1.0;
  position: absolute;
  width: 100%;
  z-index: 100;
}

.app-context-menu > button:first-child {
  font-weight: bold;
}

.app-context-menu {
  z-index: 1000;
}

.app-context-menu > [checked]::before {
  height: 5px;
}

.launch-click-target {
  cursor: pointer;
}

.app-img-container > img:first-child {
  display: block;
}

.app .invisible {
  visibility: hidden;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* TODO(estade): handle overflow better? I tried overflow-x: hidden and
 * overflow-y: visible (for the new dot animation), but this makes a scroll
 * bar appear */
#dot-list {
  /* Expand to take up all available horizontal space.  */
  -webkit-box-flex: 1;
  /* Center child dots. */
  -webkit-box-pack: center;
  display: -webkit-flex;
  height: 100%;
  list-style-type: none;
  margin: 0;
  padding: 0;
}

html.starting-up #dot-list {
  display: none;
}

.dot {
  box-sizing: border-box;
  cursor: pointer;
  /* max-width: Set in new_tab.js. See measureNavDots() */
  margin-inline-end: 10px;
  outline: none;
  padding-inline-start: 2px;
  text-align: left;
  transition: margin-inline-end 250ms, max-width 250ms, opacity 250ms;
}

.dot:last-child {
  margin-inline-end: 0;
}

.dot:only-of-type {
  cursor: default;
  opacity: 0;
  pointer-events: none;
}

.dot.small {
  margin-inline-end: 0;
  max-width: 0;
}

.dot .selection-bar {
  border-bottom: 5px solid;
  border-color: rgba(0, 0, 0, 0.1);
  height: 10px;
  transition: border-color 200ms;
}

.dot input {
  -webkit-appearance: caret;
  background-color: transparent;
  cursor: inherit;
  font: inherit;
  height: auto;
  margin-inline-start: 2px;
  margin-top: 2px;
  padding: 1px 0;
  transition: color 200ms;
  width: 90%;
}

.dot input:focus {
  cursor: auto;
}

/* Everything below here should be themed but we don't have appropriate colors
 * yet. */
.dot input {
  color: #b2b2b2;
}

.dot:focus input,
.dot:hover input,
.dot.selected input {
  color: #7f7f7f;
}

.dot:focus .selection-bar,
.dot:hover .selection-bar,
.dot.drag-target .selection-bar {
  border-color: #b2b2b2;
}

.dot.selected .selection-bar {
  border-color: #7f7f7f;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html {
  /* It's necessary to put this here instead of in body in order to get the
     background-size of 100% to work properly */
  height: 100%;
  overflow: hidden;
}

body {
  /* Don't highlight links when they're tapped. Safari has bugs here that
     show up as flicker when dragging in some situations */
  -webkit-tap-highlight-color: transparent;
  background-size: auto 100%;
  margin: 0;
  /* Don't allow selecting text - can occur when dragging */
  user-select: none;
}

/* [hidden] does display:none, but its priority is too low in some cases. */
[hidden] {
  display: none !important;
}

.close-button {
  background: no-repeat;
  background-color: transparent;
  /* TODO(estade): this should animate between states. */
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg==) 1x);
  border: 0;
  cursor: default;
  display: inline-block;
  height: 16px;
  padding: 0;
  width: 16px;
}

.close-button:hover,
.close-button:focus {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqUlEQVR4XqWRMQqEMBBF/1E8Ra6x6V3FRnS9QbCxtJg6Z7CzE9lTiIXXyUb3C8EULixDIMM8Zt4kcDfxM5A45U+cgeXnC1tREgkzAgob3hiq3CUHvGLG4FTQoSgxQGDrzN8WTLBGnx2IVDksen9GH7Z9hA5E6uxABMJyCHDMCEGHzugLQPPlBCBNGq+5YtpnGw1Bv+te15ypljTpVzdak5Opy+z+qf//zQ+Lg+07ay5KsgAAAABJRU5ErkJggg==) 1x);
}

.close-button:active {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAQklEQVR4AWP4TwBSTQGDHcMZIIYAKA9VwRkwtINJgyCaCTAlCBaKAoQ+hFmoCqBKENKkK8C0gpAjCXuTyICiQ2QBAPSwyG3ByZlCAAAAAElFTkSuQmCC)
          1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAA/ElEQVR4Xu3UsWrCUBiG4efGlIBoIMFbcnYolYJ3pg4iKGrGYFTRwaUFhYAekiDt0EG++X2W83N8/3J/DbwBMJJSsdQItcDY1VlCOImzq3Ed8OmicHASB3ns5KBw8VUNpDJrW7uAiJ3sbK1l0mqArpmFTUlQ5jYWZrrUAUSmT0SZm4qoA56JvVhs/5g3A7RLolA85A1ASOTye65NMxASK6syfxGITMzvMxG9CvRkliWwlOm9AsSOcitzU1NzK7mjuBkQvHtLK7iLBiB5PhttJSGpB8I8vM6kDuiHeUjoVwMfYR4SRtUAw1veIZzOjRhSBzCoyKFjgH/3K7+BHzg+Cgw0eSW3AAAAAElFTkSuQmCC)
          2x);
}

[is='action-link'] {
  margin-inline-start: 0.5em;
}

#card-slider-frame {
  /* Must match #footer height. */
  bottom: 50px;
  overflow: hidden;
  /* We want this to fill the window except for the region used
   * by footer. */
  position: fixed;
  top: 0;
  width: 100%;
}

#page-list {
  /* fill the apps-frame */
  display: -webkit-box;
  height: 100%;
}

#attribution {
  bottom: 0;
  margin-left: 8px;
  /* Leave room for the scrollbar. */
  margin-right: 13px;
  position: absolute;
  z-index: -5;
}

html[dir='rtl'] #attribution {
  left: 0;
  right: auto;
  text-align: right;
}

#attribution > span {
  display: block;
}

#footer {
  background-image: linear-gradient(
      rgba(242, 242, 242, 0.9), rgba(222, 222, 222, 0.9));
  bottom: 0;
  color: #7F7F7F;
  font-size: 0.9em;
  font-weight: bold;
  overflow: hidden;
  position: fixed;
  width: 100%;
  z-index: 5;
}

/* TODO(estade): remove this border hack and replace with a webkit-gradient
 * border-image on #footer once WebKit supports border-image-slice.
 * See https://bugs.webkit.org/show_bug.cgi?id=20127 */
#footer-border {
  height: 1px;
}

#footer-content {
  -webkit-align-items: center;
  -webkit-justify-content: space-between;
  display: -webkit-flex;
  height: 49px;
}

#footer-content > * {
  margin: 0 9px;
}

#logo-img {
  display: inline-block;
  margin-top: 4px;
  overflow: hidden;
  position: relative;
}

.starting-up * {
  transition: none !important;
}

/* Login Status. **************************************************************/

#login-container {
  background: transparent none;
  border: none;
  box-shadow: none;
  color: inherit;
  font: inherit;
  /* Leave room for the scrollbar. */
  margin-left: 13px;
  margin-right: 13px;
  margin-top: 5px;
  padding: 0;
  position: fixed;
  right: 0;
  text-align: right;
  top: 0;
  z-index: 10;
}

#login-container:not(.signed-in) {
  cursor: pointer;
}

html[dir='rtl'] #login-container {
  left: 0;
  right: auto;
}

#login-container [is='action-link'] {
  margin-inline-start: 0;
}

.login-status-icon {
  background-position: right center;
  background-repeat: no-repeat;
  min-height: 27px;
  padding-inline-end: 37px;
}

html[dir='rtl'] .login-status-icon {
  background-position-x: left;
}

#login-status-bubble-contents {
  font-size: 1.1em;
}

#login-status-message-container {
  margin-bottom: 13px;
}

#login-status-learn-more {
  display: inline-block;
}

.login-status-row {
  -webkit-box-align: center;
  -webkit-box-orient: horizontal;
  -webkit-box-pack: end;
  display: -webkit-box;
}

#login-status-advanced-container {
  -webkit-box-flex: 1;
}

#login-status-dismiss {
  min-width: 6em;
}

/* Trash. *********************************************************************/

#trash {
  color: #222;
  height: 100%;
  opacity: 0;
  padding-inline-start: 10px;
  position: absolute;
  right: 0;
  top: 50px;
  transition: top 200ms, opacity 0ms;
  transition-delay: 0ms, 200ms;
  width: auto;
}

html[dir='rtl'] #trash {
  left: 0;
  right: auto;
}

#footer.showing-trash-mode #trash {
  opacity: 0.75;
  top: 0;
  transition-delay: 0ms, 0ms;
  transition-duration: 0ms, 200ms;
}

#footer.showing-trash-mode #trash.drag-target {
  opacity: 1;
}

#trash > .trash-text {
  border: 1px dashed #7f7f7f;
  border-radius: 4px;
  display: inline-block;
  padding-bottom: 9px;
  padding-inline-end: 7px;
  padding-inline-start: 30px;
  padding-top: 10px;
  position: relative;
  top: 7px;
}

#trash > .lid,
#trash > .can {
  left: 18px;
  top: 18px;
}

html[dir='rtl'] #trash > .lid,
html[dir='rtl'] #trash > .can {
  right: 18px;
}

#footer.showing-trash-mode #trash.drag-target .lid {
  transform: rotate(-45deg);
}

html[dir='rtl'] #footer.showing-trash-mode #trash.drag-target .lid {
  transform: rotate(45deg);
}

#fontMeasuringDiv {
  /* The font attributes match the nav inputs. */
  font-size: 0.9em;
  font-weight: bold;
  pointer-events: none;
  position: absolute;
  visibility: hidden;
}

/* Page switcher buttons. *****************************************************/

.page-switcher {
  background-color: transparent;
  border: none;
  bottom: 0;
  font-size: 40px;
  margin: 0;
  max-width: 150px;
  min-width: 90px;
  outline: none;
  padding: 0;
  position: absolute;
  top: 0;
  transition: width 150ms, right 150ms, background-color 150ms;
  z-index: 5;
}

/* Footer buttons. ************************************************************/

#chrome-web-store-link {
  -webkit-order: 3;
  color: inherit;
  cursor: pointer;
  display: inline-block;
  margin: 0;
  padding-inline-end: 12px;
  text-decoration: none;
  transition-delay: 100ms;
  white-space: nowrap;
}

#chrome-web-store-title {
  background: url(chrome://theme/IDR_WEBSTORE_ICON_24) right 50% no-repeat;
  display: inline-block;
  line-height: 49px;
  padding-inline-end: 36px;
  padding-inline-start: 15px;
}

#chrome-web-store-link:hover {
  color: #666;
}

html[dir='rtl'] #chrome-web-store-title {
  background-position-x: left;
}

/* In trash mode, hide the menus and web store link. */
#footer.showing-trash-mode .menu-container {
  opacity: 0;
  transition-delay: 0ms;
  visibility: hidden;
}

#footer .menu-container {
  -webkit-align-items: center;
  -webkit-flex-direction: row;
  -webkit-justify-content: flex-end;
  /* Put menus in a box so the order can easily be swapped. */
  display: -webkit-flex;
  height: 100%;
  margin: 0;
  min-width: -webkit-min-content;
}

#other-sessions-menu-button {
  -webkit-order: 0;
}

.other-sessions-promo-message {
  display: none;
  padding: 0;
}

.other-sessions-promo-message:only-child {
  display: block;
}

.other-sessions-promo-message p {
  margin: 0;
}
</style>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.tile-page {
  -webkit-box-orient: vertical;
  display: -webkit-box;
  height: 100%;
  position: relative;
  width: 100%;
}

.tile-page-scrollbar {
  -webkit-box-sizing: border-box;
  margin: 0 4px;
  pointer-events: none;
  position: absolute;
  right: 0;
  width: 5px;
  z-index: 5;
}

.tile-page-content {
  -webkit-box-flex: 1;
  /* Don't apply clip mask to padding. */
  -webkit-mask-clip: content-box;
  /* TODO(estade): this mask is disabled for technical reasons. It negatively
   * impacts performance of page switching, also it causes problems with Mac
   * text: http://crbug.com/86955
  -webkit-mask-image: -webkit-linear-gradient(bottom, transparent, black 30px);
  */
  /* The following four properties are necessary so that the mask won't clip
   * the scrollbar. */
  box-sizing: border-box;
  overflow-y: scroll;
  /* Scrollbar width(13px) + balance right padding.  */
  padding-left: 93px;
  padding-right: 80px;
  /* This value is mirrored in TilePage.updateTopMargin_ */
  padding-top: 60px;
  position: relative;
  text-align: center;
  width: 100%;
}

.top-margin {
  /* The only reason height is set to 1px, rather than left at 0, is that
   * otherwise webkit collapses the top and bottom margins. */
  height: 1px;
}

.tile-grid {
  position: relative;
  width: 100%;
}

.tile {
  -webkit-print-color-adjust: exact;
  /* Don't offer the context menu on long-press. */
  -webkit-touch-callout: none;
  -webkit-user-drag: element;
  display: inline-block;
  position: absolute;
}

/* NOTE: Dopplegangers nest themselves inside of other tiles, so don't
 * accidentally double apply font-size to them. */
.tile:not(.doppleganger) {
  font-size: 1.2em;
}

/* Not real but not a doppleganger: show nothing. This state exists for a
 * webstore tile that's on the same page as a [+]. */
.tile:not(.real):not(.doppleganger) {
  display: none;
}

/* I don't know why this is necessary. -webkit-user-drag: element on .tile
 * should be enough. If we don't do this, we get 2 drag representations for
 * the image. */
.tile img {
  -webkit-user-drag: none;
}

.doppleganger {
  left: 0 !important;
  right: 0 !important;
  top: 0 !important;
}

.tile.dragging {
  opacity: 0;
}

.tile.drag-representation {
  pointer-events: none;
  position: fixed;
  transition: opacity 200ms;
  z-index: 3;
}

.tile.drag-representation.placing > * {
  transition: transform 200ms;
}

/* When a drag finishes while we're not showing the page where the tile
 * belongs, the tile shrinks to a dot. */
.tile.drag-representation.dropped-on-other-page > * {
   transform: scale(0) rotate(0);
}

.tile.drag-representation.deleting > * {
  transform: scale(0) rotate(360deg);
  transition: transform 600ms;
}

.animating-tile-page .tile,
.tile.drag-representation.placing {
  transition: left 200ms, right 200ms, top 200ms;
}

.hovering-on-trash {
  opacity: 0.6;
}

.animating-tile-page .top-margin {
  transition: margin-bottom 200ms;
}

@keyframes bounce {
  0% {
    transform: scale(0, 0);
  }

  60% {
    transform: scale(1.2, 1.2);
  }

  100% {
    transform: scale(1, 1);
  }
}

.tile > .new-tile-contents {
  animation: bounce 500ms ease-in-out;
}

@keyframes blipout {
  0% {
    transform: scale(1, 1);
  }

  60% {
    animation-timing-function: ease-in;
    opacity: 1;
    transform: scale(1.3, 0.02);
  }

  90% {
    opacity: 0.7;
    transform: scale(0.3, 0.02);
  }

  100% {
    animation-timing-function: linear;
    opacity: 0;
    transform: scale(0.3, 0.02);
  }
}

.tile > .removing-tile-contents {
  animation: blipout 300ms;
  animation-fill-mode: forwards;
  pointer-events: none;
}

.tile-page:not(.selected-card) * {
  transition: none !important;
}

/** Scrollbars ****************************************************************/

.tile-page-content::-webkit-scrollbar {
  width: 13px;
}

.tile-page-content::-webkit-scrollbar-button {
  display: none;
}
</style>
<script>
// Until themes can clear the cache, force-reload the theme stylesheet.
document.write('<link id="themecss" rel="stylesheet" ' +
               'href="chrome://theme/css/new_tab_theme.css?' + Date.now() + '">');
</script>
<script>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Action links are elements that are used to perform an in-page navigation or
// action (e.g. showing a dialog).
//
// They look like normal anchor (<a>) tags as their text color is blue. However,
// they're subtly different as they're not initially underlined (giving users a
// clue that underlined links navigate while action links don't).
//
// Action links look very similar to normal links when hovered (hand cursor,
// underlined). This gives the user an idea that clicking this link will do
// something similar to navigation but in the same page.
//
// They can be created in JavaScript like this:
//
//   var link = document.createElement('a', 'action-link');  // Note second arg.
//
// or with a constructor like this:
//
//   var link = new ActionLink();
//
// They can be used easily from HTML as well, like so:
//
//   <a is="action-link">Click me!</a>
//
// NOTE: <action-link> and document.createElement('action-link') don't work.

class ActionLink extends HTMLAnchorElement {
  connectedCallback() {
    // Action links can start disabled (e.g. <a is="action-link" disabled>).
    this.tabIndex = this.disabled ? -1 : 0;

    if (!this.hasAttribute('role')) {
      this.setAttribute('role', 'link');
    }

    this.addEventListener('keydown', function(e) {
      if (!this.disabled && e.key == 'Enter' && !this.href) {
        // Schedule a click asynchronously because other 'keydown' handlers
        // may still run later (e.g. document.addEventListener('keydown')).
        // Specifically options dialogs break when this timeout isn't here.
        // NOTE: this affects the "trusted" state of the ensuing click. I
        // haven't found anything that breaks because of this (yet).
        window.setTimeout(this.click.bind(this), 0);
      }
    });

    function preventDefault(e) {
      e.preventDefault();
    }

    function removePreventDefault() {
      document.removeEventListener('selectstart', preventDefault);
      document.removeEventListener('mouseup', removePreventDefault);
    }

    this.addEventListener('mousedown', function() {
      // This handlers strives to match the behavior of <a href="...">.

      // While the mouse is down, prevent text selection from dragging.
      document.addEventListener('selectstart', preventDefault);
      document.addEventListener('mouseup', removePreventDefault);

      // If focus started via mouse press, don't show an outline.
      if (document.activeElement != this) {
        this.classList.add('no-outline');
      }
    });

    this.addEventListener('blur', function() {
      this.classList.remove('no-outline');
    });
  }

  /** @param {boolean} disabled */
  set disabled(disabled) {
    if (disabled) {
      HTMLAnchorElement.prototype.setAttribute.call(this, 'disabled', '');
    } else {
      HTMLAnchorElement.prototype.removeAttribute.call(this, 'disabled');
    }
    this.tabIndex = disabled ? -1 : 0;
  }

  get disabled() {
    return this.hasAttribute('disabled');
  }

  /** @override */
  setAttribute(attr, val) {
    if (attr.toLowerCase() == 'disabled') {
      this.disabled = true;
    } else {
      HTMLAnchorElement.prototype.setAttribute.apply(this, arguments);
    }
  }

  /** @override */
  removeAttribute(attr) {
    if (attr.toLowerCase() == 'disabled') {
      this.disabled = false;
    } else {
      HTMLAnchorElement.prototype.removeAttribute.apply(this, arguments);
    }
  }
}
customElements.define('action-link', ActionLink, {extends: 'a'});
</script>
<script>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview EventTracker is a simple class that manages the addition and
 * removal of DOM event listeners. In particular, it keeps track of all
 * listeners that have been added and makes it easy to remove some or all of
 * them without requiring all the information again. This is particularly handy
 * when the listener is a generated function such as a lambda or the result of
 * calling Function.bind.
 */

/**
 * The type of the internal tracking entry. TODO(dbeam): move this back to
 * EventTracker.Entry when https://github.com/google/closure-compiler/issues/544
 * is fixed.
 * @typedef {{target: !EventTarget,
 *            eventType: string,
 *            listener: (EventListener|Function),
 *            capture: boolean}}
 */
// eslint-disable-next-line no-var
var EventTrackerEntry;

/**
 * Create an EventTracker to track a set of events.
 * EventTracker instances are typically tied 1:1 with other objects or
 * DOM elements whose listeners should be removed when the object is disposed
 * or the corresponding elements are removed from the DOM.
 * @constructor
 */
function EventTracker() {
  /**
   * @type {Array<EventTrackerEntry>}
   * @private
   */
  this.listeners_ = [];
}

EventTracker.prototype = {
  /**
   * Add an event listener - replacement for EventTarget.addEventListener.
   * @param {!EventTarget} target The DOM target to add a listener to.
   * @param {string} eventType The type of event to subscribe to.
   * @param {EventListener|Function} listener The listener to add.
   * @param {boolean=} opt_capture Whether to invoke during the capture phase.
   */
  add: function(target, eventType, listener, opt_capture) {
    const capture = !!opt_capture;
    const h = {
      target: target,
      eventType: eventType,
      listener: listener,
      capture: capture,
    };
    this.listeners_.push(h);
    target.addEventListener(eventType, listener, capture);
  },

  /**
   * Remove any specified event listeners added with this EventTracker.
   * @param {!EventTarget} target The DOM target to remove a listener from.
   * @param {?string} eventType The type of event to remove.
   */
  remove: function(target, eventType) {
    this.listeners_ = this.listeners_.filter(function(h) {
      if (h.target == target && (!eventType || (h.eventType == eventType))) {
        EventTracker.removeEventListener_(h);
        return false;
      }
      return true;
    });
  },

  /**
   * Remove all event listeners added with this EventTracker.
   */
  removeAll: function() {
    this.listeners_.forEach(EventTracker.removeEventListener_);
    this.listeners_ = [];
  }
};

/**
 * Remove a single event listener given it's tracking entry. It's up to the
 * caller to ensure the entry is removed from listeners_.
 * @param {EventTrackerEntry} h The entry describing the listener to remove.
 * @private
 */
EventTracker.removeEventListener_ = function(h) {
  h.target.removeEventListener(h.eventType, h.listener, h.capture);
};
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Assertion support.
 */

/**
 * Verify |condition| is truthy and return |condition| if so.
 * @template T
 * @param {T} condition A condition to check for truthiness.  Note that this
 *     may be used to test whether a value is defined or not, and we don't want
 *     to force a cast to Boolean.
 * @param {string=} opt_message A message to show on failure.
 * @return {T} A non-null |condition|.
 */
function assert(condition, opt_message) {
  if (!condition) {
    let message = 'Assertion failed';
    if (opt_message) {
      message = message + ': ' + opt_message;
    }
    const error = new Error(message);
    const global = function() {
      /** @type {boolean} */
      this.traceAssertionsForTesting;
      return this;
    }();
    if (global.traceAssertionsForTesting) {
      console.warn(error.stack);
    }
    throw error;
  }
  return condition;
}

/**
 * Call this from places in the code that should never be reached.
 *
 * For example, handling all the values of enum with a switch() like this:
 *
 *   function getValueFromEnum(enum) {
 *     switch (enum) {
 *       case ENUM_FIRST_OF_TWO:
 *         return first
 *       case ENUM_LAST_OF_TWO:
 *         return last;
 *     }
 *     assertNotReached();
 *     return document;
 *   }
 *
 * This code should only be hit in the case of serious programmer error or
 * unexpected input.
 *
 * @param {string=} opt_message A message to show when this is hit.
 */
function assertNotReached(opt_message) {
  assert(false, opt_message || 'Unreachable code hit');
}

/**
 * @param {*} value The value to check.
 * @param {function(new: T, ...)} type A user-defined constructor.
 * @param {string=} opt_message A message to show when this is hit.
 * @return {T}
 * @template T
 */
function assertInstanceof(value, type, opt_message) {
  // We don't use assert immediately here so that we avoid constructing an error
  // message if we don't have to.
  if (!(value instanceof type)) {
    assertNotReached(
        opt_message ||
        'Value ' + value + ' is not a[n] ' + (type.name || typeof type));
  }
  return value;
}


/**
 * Alias for document.getElementById. Found elements must be HTMLElements.
 * @param {string} id The ID of the element to find.
 * @return {HTMLElement} The found element or null if not found.
 */
function $(id) {
  // Disable getElementById restriction here, since we are instructing other
  // places to re-use the $() that is defined here.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, HTMLElement) : null;
}

// TODO(devlin): This should return SVGElement, but closure compiler is missing
// those externs.
/**
 * Alias for document.getElementById. Found elements must be SVGElements.
 * @param {string} id The ID of the element to find.
 * @return {Element} The found element or null if not found.
 */
function getSVGElement(id) {
  // Disable getElementById restriction here, since it is not suitable for SVG
  // elements.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, Element) : null;
}

/**
 * @return {?Element} The currently focused element (including elements that are
 *     behind a shadow root), or null if nothing is focused.
 */
function getDeepActiveElement() {
  let a = document.activeElement;
  while (a && a.shadowRoot && a.shadowRoot.activeElement) {
    a = a.shadowRoot.activeElement;
  }
  return a;
}

/**
 * Add an accessible message to the page that will be announced to
 * users who have spoken feedback on, but will be invisible to all
 * other users. It's removed right away so it doesn't clutter the DOM.
 * @param {string} msg The text to be pronounced.
 */
function announceAccessibleMessage(msg) {
  const element = document.createElement('div');
  element.setAttribute('aria-live', 'polite');
  element.style.position = 'fixed';
  element.style.left = '-9999px';
  element.style.height = '0px';
  element.innerText = msg;
  document.body.appendChild(element);
  window.setTimeout(function() {
    document.body.removeChild(element);
  }, 0);
}

/**
 * Generates a CSS url string.
 * @param {string} s The URL to generate the CSS url for.
 * @return {string} The CSS url string.
 */
function getUrlForCss(s) {
  // http://www.w3.org/TR/css3-values/#uris
  // Parentheses, commas, whitespace characters, single quotes (') and double
  // quotes (") appearing in a URI must be escaped with a backslash
  let s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
  // WebKit has a bug when it comes to URLs that end with \
  // https://bugs.webkit.org/show_bug.cgi?id=28885
  if (/\\\\$/.test(s2)) {
    // Add a space to work around the WebKit bug.
    s2 += ' ';
  }
  return 'url("' + s2 + '")';
}

/**
 * Parses query parameters from Location.
 * @param {Location} location The URL to generate the CSS url for.
 * @return {Object} Dictionary containing name value pairs for URL
 */
function parseQueryParams(location) {
  const params = {};
  const query = unescape(location.search.substring(1));
  const vars = query.split('&');
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split('=');
    params[pair[0]] = pair[1];
  }
  return params;
}

/**
 * Creates a new URL by appending or replacing the given query key and value.
 * Not supporting URL with username and password.
 * @param {Location} location The original URL.
 * @param {string} key The query parameter name.
 * @param {string} value The query parameter value.
 * @return {string} The constructed new URL.
 */
function setQueryParam(location, key, value) {
  const query = parseQueryParams(location);
  query[encodeURIComponent(key)] = encodeURIComponent(value);

  let newQuery = '';
  for (const q in query) {
    newQuery += (newQuery ? '&' : '?') + q + '=' + query[q];
  }

  return location.origin + location.pathname + newQuery + location.hash;
}

/**
 * @param {Node} el A node to search for ancestors with |className|.
 * @param {string} className A class to search for.
 * @return {Element} A node with class of |className| or null if none is found.
 */
function findAncestorByClass(el, className) {
  return /** @type {Element} */ (findAncestor(el, function(el) {
    return el.classList && el.classList.contains(className);
  }));
}

/**
 * Return the first ancestor for which the {@code predicate} returns true.
 * @param {Node} node The node to check.
 * @param {function(Node):boolean} predicate The function that tests the
 *     nodes.
 * @return {Node} The found ancestor or null if not found.
 */
function findAncestor(node, predicate) {
  let last = false;
  while (node != null && !(last = predicate(node))) {
    node = node.parentNode;
  }
  return last ? node : null;
}

function swapDomNodes(a, b) {
  const afterA = a.nextSibling;
  if (afterA == b) {
    swapDomNodes(b, a);
    return;
  }
  const aParent = a.parentNode;
  b.parentNode.replaceChild(a, b);
  aParent.insertBefore(b, afterA);
}

/**
 * Disables text selection and dragging, with optional whitelist callbacks.
 * @param {function(Event):boolean=} opt_allowSelectStart Unless this function
 *    is defined and returns true, the onselectionstart event will be
 *    surpressed.
 * @param {function(Event):boolean=} opt_allowDragStart Unless this function
 *    is defined and returns true, the ondragstart event will be surpressed.
 */
function disableTextSelectAndDrag(opt_allowSelectStart, opt_allowDragStart) {
  // Disable text selection.
  document.onselectstart = function(e) {
    if (!(opt_allowSelectStart && opt_allowSelectStart.call(this, e))) {
      e.preventDefault();
    }
  };

  // Disable dragging.
  document.ondragstart = function(e) {
    if (!(opt_allowDragStart && opt_allowDragStart.call(this, e))) {
      e.preventDefault();
    }
  };
}

/**
 * Check the directionality of the page.
 * @return {boolean} True if Chrome is running an RTL UI.
 */
function isRTL() {
  return document.documentElement.dir == 'rtl';
}

/**
 * Get an element that's known to exist by its ID. We use this instead of just
 * calling getElementById and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} id The identifier name.
 * @return {!HTMLElement} the Element.
 */
function getRequiredElement(id) {
  return assertInstanceof(
      $(id), HTMLElement, 'Missing required element: ' + id);
}

/**
 * Query an element that's known to exist by a selector. We use this instead of
 * just calling querySelector and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} selectors CSS selectors to query the element.
 * @param {(!Document|!DocumentFragment|!Element)=} opt_context An optional
 *     context object for querySelector.
 * @return {!HTMLElement} the Element.
 */
function queryRequiredElement(selectors, opt_context) {
  const element = (opt_context || document).querySelector(selectors);
  return assertInstanceof(
      element, HTMLElement, 'Missing required element: ' + selectors);
}

// Handle click on a link. If the link points to a chrome: or file: url, then
// call into the browser to do the navigation.
['click', 'auxclick'].forEach(function(eventName) {
  document.addEventListener(eventName, function(e) {
    if (e.button > 1) {
      return;
    }  // Ignore buttons other than left and middle.
    if (e.defaultPrevented) {
      return;
    }

    const eventPath = e.path;
    let anchor = null;
    if (eventPath) {
      for (let i = 0; i < eventPath.length; i++) {
        const element = eventPath[i];
        if (element.tagName === 'A' && element.href) {
          anchor = element;
          break;
        }
      }
    }

    // Fallback if Event.path is not available.
    let el = e.target;
    if (!anchor && el.nodeType == Node.ELEMENT_NODE &&
        el.webkitMatchesSelector('A, A *')) {
      while (el.tagName != 'A') {
        el = el.parentElement;
      }
      anchor = el;
    }

    if (!anchor) {
      return;
    }

    anchor = /** @type {!HTMLAnchorElement} */ (anchor);
    if ((anchor.protocol == 'file:' || anchor.protocol == 'about:') &&
        (e.button == 0 || e.button == 1)) {
      chrome.send('navigateToUrl', [
        anchor.href, anchor.target, e.button, e.altKey, e.ctrlKey, e.metaKey,
        e.shiftKey
      ]);
      e.preventDefault();
    }
  });
});

/**
 * Creates a new URL which is the old URL with a GET param of key=value.
 * @param {string} url The base URL. There is not sanity checking on the URL so
 *     it must be passed in a proper format.
 * @param {string} key The key of the param.
 * @param {string} value The value of the param.
 * @return {string} The new URL.
 */
function appendParam(url, key, value) {
  const param = encodeURIComponent(key) + '=' + encodeURIComponent(value);

  if (url.indexOf('?') == -1) {
    return url + '?' + param;
  }
  return url + '&' + param;
}

/**
 * Creates an element of a specified type with a specified class name.
 * @param {string} type The node type.
 * @param {string} className The class name to use.
 * @return {Element} The created element.
 */
function createElementWithClassName(type, className) {
  const elm = document.createElement(type);
  elm.className = className;
  return elm;
}

/**
 * transitionend does not always fire (e.g. when animation is aborted
 * or when no paint happens during the animation). This function sets up
 * a timer and emulate the event if it is not fired when the timer expires.
 * @param {!HTMLElement} el The element to watch for transitionend.
 * @param {number=} opt_timeOut The maximum wait time in milliseconds for the
 *     transitionend to happen. If not specified, it is fetched from |el|
 *     using the transitionDuration style value.
 */
function ensureTransitionEndEvent(el, opt_timeOut) {
  if (opt_timeOut === undefined) {
    const style = getComputedStyle(el);
    opt_timeOut = parseFloat(style.transitionDuration) * 1000;

    // Give an additional 50ms buffer for the animation to complete.
    opt_timeOut += 50;
  }

  let fired = false;
  el.addEventListener('transitionend', function f(e) {
    el.removeEventListener('transitionend', f);
    fired = true;
  });
  window.setTimeout(function() {
    if (!fired) {
      cr.dispatchSimpleEvent(el, 'transitionend', true);
    }
  }, opt_timeOut);
}

/**
 * Alias for document.scrollTop getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The Y document scroll offset.
 */
function scrollTopForDocument(doc) {
  return doc.documentElement.scrollTop || doc.body.scrollTop;
}

/**
 * Alias for document.scrollTop setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target Y scroll offset.
 */
function setScrollTopForDocument(doc, value) {
  doc.documentElement.scrollTop = doc.body.scrollTop = value;
}

/**
 * Alias for document.scrollLeft getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The X document scroll offset.
 */
function scrollLeftForDocument(doc) {
  return doc.documentElement.scrollLeft || doc.body.scrollLeft;
}

/**
 * Alias for document.scrollLeft setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target X scroll offset.
 */
function setScrollLeftForDocument(doc, value) {
  doc.documentElement.scrollLeft = doc.body.scrollLeft = value;
}

/**
 * Replaces '&', '<', '>', '"', and ''' characters with their HTML encoding.
 * @param {string} original The original string.
 * @return {string} The string with all the characters mentioned above replaced.
 */
function HTMLEscape(original) {
  return original.replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
}

/**
 * Shortens the provided string (if necessary) to a string of length at most
 * |maxLength|.
 * @param {string} original The original string.
 * @param {number} maxLength The maximum length allowed for the string.
 * @return {string} The original string if its length does not exceed
 *     |maxLength|. Otherwise the first |maxLength| - 1 characters with '...'
 *     appended.
 */
function elide(original, maxLength) {
  if (original.length <= maxLength) {
    return original;
  }
  return original.substring(0, maxLength - 1) + '\u2026';
}

/**
 * Quote a string so it can be used in a regular expression.
 * @param {string} str The source string.
 * @return {string} The escaped string.
 */
function quoteString(str) {
  return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
}

/**
 * Calls |callback| and stops listening the first time any event in |eventNames|
 * is triggered on |target|.
 * @param {!EventTarget} target
 * @param {!Array<string>|string} eventNames Array or space-delimited string of
 *     event names to listen to (e.g. 'click mousedown').
 * @param {function(!Event)} callback Called at most once. The
 *     optional return value is passed on by the listener.
 */
function listenOnce(target, eventNames, callback) {
  if (!Array.isArray(eventNames)) {
    eventNames = eventNames.split(/ +/);
  }

  const removeAllAndCallCallback = function(event) {
    eventNames.forEach(function(eventName) {
      target.removeEventListener(eventName, removeAllAndCallCallback, false);
    });
    return callback(event);
  };

  eventNames.forEach(function(eventName) {
    target.addEventListener(eventName, removeAllAndCallCallback, false);
  });
}

//   /* is_ios */

/**
 * @param {!Event} e
 * @return {boolean} Whether a modifier key was down when processing |e|.
 */
function hasKeyModifiers(e) {
  return !!(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey);
}
</script>

<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/** @typedef {{eventName: string, uid: number}} */
// eslint-disable-next-line no-var
var WebUIListener;

/** Platform, package, object property, and Event support. **/
// eslint-disable-next-line no-var
var cr = cr || function(global) {
  'use strict';

  /**
   * Builds an object structure for the provided namespace path,
   * ensuring that names that already exist are not overwritten. For
   * example:
   * "a.b.c" -> a = {};a.b={};a.b.c={};
   * @param {string} name Name of the object that this file defines.
   * @param {*=} opt_object The object to expose at the end of the path.
   * @param {Object=} opt_objectToExportTo The object to add the path to;
   *     default is {@code global}.
   * @return {!Object} The last object exported (i.e. exportPath('cr.ui')
   *     returns a reference to the ui property of window.cr).
   * @private
   */
  function exportPath(name, opt_object, opt_objectToExportTo) {
    const parts = name.split('.');
    let cur = opt_objectToExportTo || global;

    for (let part; parts.length && (part = parts.shift());) {
      if (!parts.length && opt_object !== undefined) {
        // last part and we have an object; use it
        cur[part] = opt_object;
      } else if (part in cur) {
        cur = cur[part];
      } else {
        cur = cur[part] = {};
      }
    }
    return cur;
  }

  /**
   * Fires a property change event on the target.
   * @param {EventTarget} target The target to dispatch the event on.
   * @param {string} propertyName The name of the property that changed.
   * @param {*} newValue The new value for the property.
   * @param {*} oldValue The old value for the property.
   */
  function dispatchPropertyChange(target, propertyName, newValue, oldValue) {
    const e = new Event(propertyName + 'Change');
    e.propertyName = propertyName;
    e.newValue = newValue;
    e.oldValue = oldValue;
    target.dispatchEvent(e);
  }

  /**
   * Converts a camelCase javascript property name to a hyphenated-lower-case
   * attribute name.
   * @param {string} jsName The javascript camelCase property name.
   * @return {string} The equivalent hyphenated-lower-case attribute name.
   */
  function getAttributeName(jsName) {
    return jsName.replace(/([A-Z])/g, '-$1').toLowerCase();
  }

  /**
   * The kind of property to define in {@code defineProperty}.
   * @enum {string}
   * @const
   */
  const PropertyKind = {
    /**
     * Plain old JS property where the backing data is stored as a "private"
     * field on the object.
     * Use for properties of any type. Type will not be checked.
     */
    JS: 'js',

    /**
     * The property backing data is stored as an attribute on an element.
     * Use only for properties of type {string}.
     */
    ATTR: 'attr',

    /**
     * The property backing data is stored as an attribute on an element. If the
     * element has the attribute then the value is true.
     * Use only for properties of type {boolean}.
     */
    BOOL_ATTR: 'boolAttr'
  };

  /**
   * Helper function for defineProperty that returns the getter to use for the
   * property.
   * @param {string} name The name of the property.
   * @param {PropertyKind} kind The kind of the property.
   * @return {function():*} The getter for the property.
   */
  function getGetter(name, kind) {
    let attributeName;
    switch (kind) {
      case PropertyKind.JS:
        const privateName = name + '_';
        return function() {
          return this[privateName];
        };
      case PropertyKind.ATTR:
        attributeName = getAttributeName(name);
        return function() {
          return this.getAttribute(attributeName);
        };
      case PropertyKind.BOOL_ATTR:
        attributeName = getAttributeName(name);
        return function() {
          return this.hasAttribute(attributeName);
        };
    }

    // TODO(dbeam): replace with assertNotReached() in assert.js when I can coax
    // the browser/unit tests to preprocess this file through grit.
    throw 'not reached';
  }

  /**
   * Helper function for defineProperty that returns the setter of the right
   * kind.
   * @param {string} name The name of the property we are defining the setter
   *     for.
   * @param {PropertyKind} kind The kind of property we are getting the
   *     setter for.
   * @param {function(*, *):void=} opt_setHook A function to run after the
   *     property is set, but before the propertyChange event is fired.
   * @return {function(*):void} The function to use as a setter.
   */
  function getSetter(name, kind, opt_setHook) {
    let attributeName;
    switch (kind) {
      case PropertyKind.JS:
        const privateName = name + '_';
        return function(value) {
          const oldValue = this[name];
          if (value !== oldValue) {
            this[privateName] = value;
            if (opt_setHook) {
              opt_setHook.call(this, value, oldValue);
            }
            dispatchPropertyChange(this, name, value, oldValue);
          }
        };

      case PropertyKind.ATTR:
        attributeName = getAttributeName(name);
        return function(value) {
          const oldValue = this[name];
          if (value !== oldValue) {
            if (value == undefined) {
              this.removeAttribute(attributeName);
            } else {
              this.setAttribute(attributeName, value);
            }
            if (opt_setHook) {
              opt_setHook.call(this, value, oldValue);
            }
            dispatchPropertyChange(this, name, value, oldValue);
          }
        };

      case PropertyKind.BOOL_ATTR:
        attributeName = getAttributeName(name);
        return function(value) {
          const oldValue = this[name];
          if (value !== oldValue) {
            if (value) {
              this.setAttribute(attributeName, name);
            } else {
              this.removeAttribute(attributeName);
            }
            if (opt_setHook) {
              opt_setHook.call(this, value, oldValue);
            }
            dispatchPropertyChange(this, name, value, oldValue);
          }
        };
    }

    // TODO(dbeam): replace with assertNotReached() in assert.js when I can coax
    // the browser/unit tests to preprocess this file through grit.
    throw 'not reached';
  }

  /**
   * Defines a property on an object. When the setter changes the value a
   * property change event with the type {@code name + 'Change'} is fired.
   * @param {!Object} obj The object to define the property for.
   * @param {string} name The name of the property.
   * @param {PropertyKind=} opt_kind What kind of underlying storage to use.
   * @param {function(*, *):void=} opt_setHook A function to run after the
   *     property is set, but before the propertyChange event is fired.
   */
  function defineProperty(obj, name, opt_kind, opt_setHook) {
    if (typeof obj == 'function') {
      obj = obj.prototype;
    }

    const kind = /** @type {PropertyKind} */ (opt_kind || PropertyKind.JS);

    if (!obj.__lookupGetter__(name)) {
      obj.__defineGetter__(name, getGetter(name, kind));
    }

    if (!obj.__lookupSetter__(name)) {
      obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));
    }
  }

  /**
   * Counter for use with createUid
   */
  let uidCounter = 1;

  /**
   * @return {number} A new unique ID.
   */
  function createUid() {
    return uidCounter++;
  }

  /**
   * Returns a unique ID for the item. This mutates the item so it needs to be
   * an object
   * @param {!Object} item The item to get the unique ID for.
   * @return {number} The unique ID for the item.
   */
  function getUid(item) {
    if (item.hasOwnProperty('uid')) {
      return item.uid;
    }
    return item.uid = createUid();
  }

  /**
   * Dispatches a simple event on an event target.
   * @param {!EventTarget} target The event target to dispatch the event on.
   * @param {string} type The type of the event.
   * @param {boolean=} opt_bubbles Whether the event bubbles or not.
   * @param {boolean=} opt_cancelable Whether the default action of the event
   *     can be prevented. Default is true.
   * @return {boolean} If any of the listeners called {@code preventDefault}
   *     during the dispatch this will return false.
   */
  function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) {
    const e = new Event(type, {
      bubbles: opt_bubbles,
      cancelable: opt_cancelable === undefined || opt_cancelable
    });
    return target.dispatchEvent(e);
  }

  /**
   * Calls |fun| and adds all the fields of the returned object to the object
   * named by |name|. For example, cr.define('cr.ui', function() {
   *   function List() {
   *     ...
   *   }
   *   function ListItem() {
   *     ...
   *   }
   *   return {
   *     List: List,
   *     ListItem: ListItem,
   *   };
   * });
   * defines the functions cr.ui.List and cr.ui.ListItem.
   * @param {string} name The name of the object that we are adding fields to.
   * @param {!Function} fun The function that will return an object containing
   *     the names and values of the new fields.
   */
  function define(name, fun) {
    const obj = exportPath(name);
    const exports = fun();
    for (const propertyName in exports) {
      // Maybe we should check the prototype chain here? The current usage
      // pattern is always using an object literal so we only care about own
      // properties.
      const propertyDescriptor =
          Object.getOwnPropertyDescriptor(exports, propertyName);
      if (propertyDescriptor) {
        Object.defineProperty(obj, propertyName, propertyDescriptor);
      }
    }
  }

  /**
   * Adds a {@code getInstance} static method that always return the same
   * instance object.
   * @param {!Function} ctor The constructor for the class to add the static
   *     method to.
   */
  function addSingletonGetter(ctor) {
    ctor.getInstance = function() {
      return ctor.instance_ || (ctor.instance_ = new ctor());
    };
  }

  /**
   * Forwards public APIs to private implementations.
   * @param {Function} ctor Constructor that have private implementations in its
   *     prototype.
   * @param {Array<string>} methods List of public method names that have their
   *     underscored counterparts in constructor's prototype.
   * @param {string=} opt_target Selector for target node.
   */
  function makePublic(ctor, methods, opt_target) {
    methods.forEach(function(method) {
      ctor[method] = function() {
        const target = opt_target ?
            // Disable document.getElementById restriction since cr.js should
            // not depend on util.js.
            // eslint-disable-next-line no-restricted-properties
            document.getElementById(opt_target) :
            ctor.getInstance();
        return target[method + '_'].apply(target, arguments);
      };
    });
  }

  /**
   * The mapping used by the sendWithPromise mechanism to tie the Promise
   * returned to callers with the corresponding WebUI response. The mapping is
   * from ID to the PromiseResolver helper; the ID is generated by
   * sendWithPromise and is unique across all invocations of said method.
   * @type {!Object<!PromiseResolver>}
   */
  const chromeSendResolverMap = {};

  /**
   * The named method the WebUI handler calls directly in response to a
   * chrome.send call that expects a response. The handler requires no knowledge
   * of the specific name of this method, as the name is passed to the handler
   * as the first argument in the arguments list of chrome.send. The handler
   * must pass the ID, also sent via the chrome.send arguments list, as the
   * first argument of the JS invocation; additionally, the handler may
   * supply any number of other arguments that will be included in the response.
   * @param {string} id The unique ID identifying the Promise this response is
   *     tied to.
   * @param {boolean} isSuccess Whether the request was successful.
   * @param {*} response The response as sent from C++.
   */
  function webUIResponse(id, isSuccess, response) {
    const resolver = chromeSendResolverMap[id];
    delete chromeSendResolverMap[id];

    if (isSuccess) {
      resolver.resolve(response);
    } else {
      resolver.reject(response);
    }
  }

  /**
   * A variation of chrome.send, suitable for messages that expect a single
   * response from C++.
   * @param {string} methodName The name of the WebUI handler API.
   * @param {...*} var_args Variable number of arguments to be forwarded to the
   *     C++ call.
   * @return {!Promise}
   */
  function sendWithPromise(methodName, var_args) {
    const args = Array.prototype.slice.call(arguments, 1);
    const promiseResolver = new PromiseResolver();
    const id = methodName + '_' + createUid();
    chromeSendResolverMap[id] = promiseResolver;
    chrome.send(methodName, [id].concat(args));
    return promiseResolver.promise;
  }

  /**
   * A map of maps associating event names with listeners. The 2nd level map
   * associates a listener ID with the callback function, such that individual
   * listeners can be removed from an event without affecting other listeners of
   * the same event.
   * @type {!Object<!Object<!Function>>}
   */
  const webUIListenerMap = {};

  /**
   * The named method the WebUI handler calls directly when an event occurs.
   * The WebUI handler must supply the name of the event as the first argument
   * of the JS invocation; additionally, the handler may supply any number of
   * other arguments that will be forwarded to the listener callbacks.
   * @param {string} event The name of the event that has occurred.
   * @param {...*} var_args Additional arguments passed from C++.
   */
  function webUIListenerCallback(event, var_args) {
    const eventListenersMap = webUIListenerMap[event];
    if (!eventListenersMap) {
      // C++ event sent for an event that has no listeners.
      // TODO(dpapad): Should a warning be displayed here?
      return;
    }

    const args = Array.prototype.slice.call(arguments, 1);
    for (const listenerId in eventListenersMap) {
      eventListenersMap[listenerId].apply(null, args);
    }
  }

  /**
   * Registers a listener for an event fired from WebUI handlers. Any number of
   * listeners may register for a single event.
   * @param {string} eventName The event to listen to.
   * @param {!Function} callback The callback run when the event is fired.
   * @return {!WebUIListener} An object to be used for removing a listener via
   *     cr.removeWebUIListener. Should be treated as read-only.
   */
  function addWebUIListener(eventName, callback) {
    webUIListenerMap[eventName] = webUIListenerMap[eventName] || {};
    const uid = createUid();
    webUIListenerMap[eventName][uid] = callback;
    return {eventName: eventName, uid: uid};
  }

  /**
   * Removes a listener. Does nothing if the specified listener is not found.
   * @param {!WebUIListener} listener The listener to be removed (as returned by
   *     addWebUIListener).
   * @return {boolean} Whether the given listener was found and actually
   *     removed.
   */
  function removeWebUIListener(listener) {
    const listenerExists = webUIListenerMap[listener.eventName] &&
        webUIListenerMap[listener.eventName][listener.uid];
    if (listenerExists) {
      delete webUIListenerMap[listener.eventName][listener.uid];
      return true;
    }
    return false;
  }

  return {
    addSingletonGetter: addSingletonGetter,
    createUid: createUid,
    define: define,
    defineProperty: defineProperty,
    dispatchPropertyChange: dispatchPropertyChange,
    dispatchSimpleEvent: dispatchSimpleEvent,
    exportPath: exportPath,
    getUid: getUid,
    makePublic: makePublic,
    PropertyKind: PropertyKind,

    // C++ <-> JS communication related methods.
    addWebUIListener: addWebUIListener,
    removeWebUIListener: removeWebUIListener,
    sendWithPromise: sendWithPromise,
    webUIListenerCallback: webUIListenerCallback,
    webUIResponse: webUIResponse,

    get doc() {
      return document;
    },

    /** Whether we are using a Mac or not. */
    get isMac() {
      return /Mac/.test(navigator.platform);
    },

    /** Whether this is on the Windows platform or not. */
    get isWindows() {
      return /Win/.test(navigator.platform);
    },

    /** Whether this is on chromeOS or not. */
    get isChromeOS() {
      return /CrOS/.test(navigator.userAgent);
    },

    /** Whether this is on vanilla Linux (not chromeOS). */
    get isLinux() {
      return /Linux/.test(navigator.userAgent);
    },

    /** Whether this is on Android. */
    get isAndroid() {
      return /Android/.test(navigator.userAgent);
    },

    /** Whether this is on iOS. */
    get isIOS() {
      return /iPad|iPhone|iPod/.test(navigator.platform);
    }
  };
}(this);
</script>
<script>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview This contains an implementation of the EventTarget interface
 * as defined by DOM Level 2 Events.
 */

/**
 * @typedef {EventListener|function(!Event):*}
 */
// eslint-disable-next-line no-var
var EventListenerType;

cr.define('cr', function() {

  /**
   * Creates a new EventTarget. This class implements the DOM level 2
   * EventTarget interface and can be used wherever those are used.
   * @constructor
   * @implements {EventTarget}
   */
  function EventTarget() {}

  EventTarget.prototype = {
    /**
     * Adds an event listener to the target.
     * @param {string} type The name of the event.
     * @param {EventListenerType} handler The handler for the event. This is
     *     called when the event is dispatched.
     */
    addEventListener: function(type, handler) {
      if (!this.listeners_) {
        this.listeners_ = Object.create(null);
      }
      if (!(type in this.listeners_)) {
        this.listeners_[type] = [handler];
      } else {
        const handlers = this.listeners_[type];
        if (handlers.indexOf(handler) < 0) {
          handlers.push(handler);
        }
      }
    },

    /**
     * Removes an event listener from the target.
     * @param {string} type The name of the event.
     * @param {EventListenerType} handler The handler for the event.
     */
    removeEventListener: function(type, handler) {
      if (!this.listeners_) {
        return;
      }
      if (type in this.listeners_) {
        const handlers = this.listeners_[type];
        const index = handlers.indexOf(handler);
        if (index >= 0) {
          // Clean up if this was the last listener.
          if (handlers.length == 1) {
            delete this.listeners_[type];
          } else {
            handlers.splice(index, 1);
          }
        }
      }
    },

    /**
     * Dispatches an event and calls all the listeners that are listening to
     * the type of the event.
     * @param {!Event} event The event to dispatch.
     * @return {boolean} Whether the default action was prevented. If someone
     *     calls preventDefault on the event object then this returns false.
     */
    dispatchEvent: function(event) {
      if (!this.listeners_) {
        return true;
      }

      // Since we are using DOM Event objects we need to override some of the
      // properties and methods so that we can emulate this correctly.
      const self = this;
      event.__defineGetter__('target', function() {
        return self;
      });

      const type = event.type;
      let prevented = 0;
      if (type in this.listeners_) {
        // Clone to prevent removal during dispatch
        const handlers = this.listeners_[type].concat();
        for (let i = 0, handler; handler = handlers[i]; i++) {
          if (handler.handleEvent) {
            prevented |= handler.handleEvent.call(handler, event) === false;
          } else {
            prevented |= handler.call(this, event) === false;
          }
        }
      }

      return !prevented && !event.defaultPrevented;
    }
  };

  // Export
  return {EventTarget: EventTarget};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('cr.ui', function() {

  /**
   * Decorates elements as an instance of a class.
   * @param {string|!Element} source The way to find the element(s) to decorate.
   *     If this is a string then {@code querySeletorAll} is used to find the
   *     elements to decorate.
   * @param {!Function} constr The constructor to decorate with. The constr
   *     needs to have a {@code decorate} function.
   */
  function decorate(source, constr) {
    let elements;
    if (typeof source == 'string') {
      elements = cr.doc.querySelectorAll(source);
    } else {
      elements = [source];
    }

    for (let i = 0, el; el = elements[i]; i++) {
      if (!(el instanceof constr)) {
        constr.decorate(el);
      }
    }
  }

  /**
   * Helper function for creating new element for define.
   */
  function createElementHelper(tagName, opt_bag) {
    // Allow passing in ownerDocument to create in a different document.
    let doc;
    if (opt_bag && opt_bag.ownerDocument) {
      doc = opt_bag.ownerDocument;
    } else {
      doc = cr.doc;
    }
    return doc.createElement(tagName);
  }

  /**
   * Creates the constructor for a UI element class.
   *
   * Usage:
   * <pre>
   * var List = cr.ui.define('list');
   * List.prototype = {
   *   __proto__: HTMLUListElement.prototype,
   *   decorate: function() {
   *     ...
   *   },
   *   ...
   * };
   * </pre>
   *
   * @param {string|Function} tagNameOrFunction The tagName or
   *     function to use for newly created elements. If this is a function it
   *     needs to return a new element when called.
   * @return {function(Object=):Element} The constructor function which takes
   *     an optional property bag. The function also has a static
   *     {@code decorate} method added to it.
   */
  function define(tagNameOrFunction) {
    let createFunction, tagName;
    if (typeof tagNameOrFunction == 'function') {
      createFunction = tagNameOrFunction;
      tagName = '';
    } else {
      createFunction = createElementHelper;
      tagName = tagNameOrFunction;
    }

    /**
     * Creates a new UI element constructor.
     * @param {Object=} opt_propertyBag Optional bag of properties to set on the
     *     object after created. The property {@code ownerDocument} is special
     *     cased and it allows you to create the element in a different
     *     document than the default.
     * @constructor
     */
    function f(opt_propertyBag) {
      const el = createFunction(tagName, opt_propertyBag);
      f.decorate(el);
      for (const propertyName in opt_propertyBag) {
        el[propertyName] = opt_propertyBag[propertyName];
      }
      return el;
    }

    /**
     * Decorates an element as a UI element class.
     * @param {!Element} el The element to decorate.
     */
    f.decorate = function(el) {
      el.__proto__ = f.prototype;
      el.decorate();
    };

    return f;
  }

  /**
   * Input elements do not grow and shrink with their content. This is a simple
   * (and not very efficient) way of handling shrinking to content with support
   * for min width and limited by the width of the parent element.
   * @param {!HTMLElement} el The element to limit the width for.
   * @param {!HTMLElement} parentEl The parent element that should limit the
   *     size.
   * @param {number} min The minimum width.
   * @param {number=} opt_scale Optional scale factor to apply to the width.
   */
  function limitInputWidth(el, parentEl, min, opt_scale) {
    // Needs a size larger than borders
    el.style.width = '10px';
    const doc = el.ownerDocument;
    const win = doc.defaultView;
    const computedStyle = win.getComputedStyle(el);
    const parentComputedStyle = win.getComputedStyle(parentEl);
    const rtl = computedStyle.direction == 'rtl';

    // To get the max width we get the width of the treeItem minus the position
    // of the input.
    const inputRect = el.getBoundingClientRect();  // box-sizing
    const parentRect = parentEl.getBoundingClientRect();
    const startPos = rtl ? parentRect.right - inputRect.right :
                           inputRect.left - parentRect.left;

    // Add up border and padding of the input.
    const inner = parseInt(computedStyle.borderLeftWidth, 10) +
        parseInt(computedStyle.paddingLeft, 10) +
        parseInt(computedStyle.paddingRight, 10) +
        parseInt(computedStyle.borderRightWidth, 10);

    // We also need to subtract the padding of parent to prevent it to overflow.
    const parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) :
                                parseInt(parentComputedStyle.paddingRight, 10);

    let max = parentEl.clientWidth - startPos - inner - parentPadding;
    if (opt_scale) {
      max *= opt_scale;
    }

    function limit() {
      if (el.scrollWidth > max) {
        el.style.width = max + 'px';
      } else {
        el.style.width = 0;
        const sw = el.scrollWidth;
        if (sw < min) {
          el.style.width = min + 'px';
        } else {
          el.style.width = sw + 'px';
        }
      }
    }

    el.addEventListener('input', limit);
    limit();
  }

  /**
   * Takes a number and spits out a value CSS will be happy with. To avoid
   * subpixel layout issues, the value is rounded to the nearest integral value.
   * @param {number} pixels The number of pixels.
   * @return {string} e.g. '16px'.
   */
  function toCssPx(pixels) {
    if (!window.isFinite(pixels)) {
      console.error('Pixel value is not a number: ' + pixels);
    }
    return Math.round(pixels) + 'px';
  }

  /**
   * Users complain they occasionaly use doubleclicks instead of clicks
   * (http://crbug.com/140364). To fix it we freeze click handling for
   * the doubleclick time interval.
   * @param {MouseEvent} e Initial click event.
   */
  function swallowDoubleClick(e) {
    const doc = e.target.ownerDocument;
    let counter = Math.min(1, e.detail);
    function swallow(e) {
      e.stopPropagation();
      e.preventDefault();
    }
    function onclick(e) {
      if (e.detail > counter) {
        counter = e.detail;
        // Swallow the click since it's a click inside the doubleclick timeout.
        swallow(e);
      } else {
        // Stop tracking clicks and let regular handling.
        doc.removeEventListener('dblclick', swallow, true);
        doc.removeEventListener('click', onclick, true);
      }
    }
    // The following 'click' event (if e.type == 'mouseup') mustn't be taken
    // into account (it mustn't stop tracking clicks). Start event listening
    // after zero timeout.
    setTimeout(function() {
      doc.addEventListener('click', onclick, true);
      doc.addEventListener('dblclick', swallow, true);
    }, 0);
  }

  return {
    decorate: decorate,
    define: define,
    limitInputWidth: limitInputWidth,
    toCssPx: toCssPx,
    swallowDoubleClick: swallowDoubleClick
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// require: event_tracker.js

// TODO(vitalyp): Inline the enums below into cr.ui definition function, remove
// cr.exportPath() call and remove exportPath from exports in cr.js when this
// issue will be fixed:
// https://github.com/google/closure-compiler/issues/544
cr.exportPath('cr.ui');

/**
 * The arrow location specifies how the arrow and bubble are positioned in
 * relation to the anchor node.
 * @enum {string}
 */
cr.ui.ArrowLocation = {
  // The arrow is positioned at the top and the start of the bubble. In left
  // to right mode this is the top left. The entire bubble is positioned below
  // the anchor node.
  TOP_START: 'top-start',
  // The arrow is positioned at the top and the end of the bubble. In left to
  // right mode this is the top right. The entire bubble is positioned below
  // the anchor node.
  TOP_END: 'top-end',
  // The arrow is positioned at the bottom and the start of the bubble. In
  // left to right mode this is the bottom left. The entire bubble is
  // positioned above the anchor node.
  BOTTOM_START: 'bottom-start',
  // The arrow is positioned at the bottom and the end of the bubble. In
  // left to right mode this is the bottom right. The entire bubble is
  // positioned above the anchor node.
  BOTTOM_END: 'bottom-end'
};

/**
 * The bubble alignment specifies the position of the bubble in relation to
 * the anchor node.
 * @enum {string}
 */
cr.ui.BubbleAlignment = {
  // The bubble is positioned just above or below the anchor node (as
  // specified by the arrow location) so that the arrow points at the midpoint
  // of the anchor.
  ARROW_TO_MID_ANCHOR: 'arrow-to-mid-anchor',
  // The bubble is positioned just above or below the anchor node (as
  // specified by the arrow location) so that its reference edge lines up with
  // the edge of the anchor.
  BUBBLE_EDGE_TO_ANCHOR_EDGE: 'bubble-edge-anchor-edge',
  // The bubble is positioned so that it is entirely within view and does not
  // obstruct the anchor element, if possible. The specified arrow location is
  // taken into account as the preferred alignment but may be overruled if
  // there is insufficient space (see BubbleBase.reposition for the exact
  // placement algorithm).
  ENTIRELY_VISIBLE: 'entirely-visible'
};

cr.define('cr.ui', function() {
  /**
   * Abstract base class that provides common functionality for implementing
   * free-floating informational bubbles with a triangular arrow pointing at an
   * anchor node.
   * @constructor
   * @extends {HTMLDivElement}
   * @implements {EventListener}
   */
  const BubbleBase = cr.ui.define('div');

  /**
   * The horizontal distance between the tip of the arrow and the reference edge
   * of the bubble (as specified by the arrow location). In pixels.
   * @type {number}
   * @const
   */
  BubbleBase.ARROW_OFFSET = 30;

  /**
   * Minimum horizontal spacing between edge of bubble and edge of viewport
   * (when using the ENTIRELY_VISIBLE alignment). In pixels.
   * @type {number}
   * @const
   */
  BubbleBase.MIN_VIEWPORT_EDGE_MARGIN = 2;

  BubbleBase.prototype = {
    // Set up the prototype chain.
    __proto__: HTMLDivElement.prototype,

    /**
     * @type {Node}
     * @private
     */
    anchorNode_: null,

    /**
     * Initialization function for the cr.ui framework.
     */
    decorate: function() {
      this.className = 'bubble';
      this.innerHTML = '<div class="bubble-content"></div>' +
          '<div class="bubble-shadow"></div>' +
          '<div class="bubble-arrow"></div>';
      this.hidden = true;
      this.bubbleAlignment = cr.ui.BubbleAlignment.ENTIRELY_VISIBLE;
    },

    /**
     * Set the anchor node, i.e. the node that this bubble points at. Only
     * available when the bubble is not being shown.
     * @param {HTMLElement} node The new anchor node.
     */
    set anchorNode(node) {
      if (!this.hidden) {
        return;
      }

      this.anchorNode_ = node;
    },

    /**
     * Set the conent of the bubble. Only available when the bubble is not being
     * shown.
     * @param {HTMLElement} node The root node of the new content.
     */
    set content(node) {
      if (!this.hidden) {
        return;
      }

      const bubbleContent = this.querySelector('.bubble-content');
      bubbleContent.innerHTML = '';
      bubbleContent.appendChild(node);
    },

    /**
     * Set the arrow location. Only available when the bubble is not being
     * shown.
     * @param {cr.ui.ArrowLocation} location The new arrow location.
     */
    set arrowLocation(location) {
      if (!this.hidden) {
        return;
      }

      this.arrowAtRight_ = location == cr.ui.ArrowLocation.TOP_END ||
          location == cr.ui.ArrowLocation.BOTTOM_END;
      if (document.documentElement.dir == 'rtl') {
        this.arrowAtRight_ = !this.arrowAtRight_;
      }
      this.arrowAtTop_ = location == cr.ui.ArrowLocation.TOP_START ||
          location == cr.ui.ArrowLocation.TOP_END;
    },

    /**
     * Set the bubble alignment. Only available when the bubble is not being
     * shown.
     * @param {cr.ui.BubbleAlignment} alignment The new bubble alignment.
     */
    set bubbleAlignment(alignment) {
      if (!this.hidden) {
        return;
      }

      this.bubbleAlignment_ = alignment;
    },

    /**
     * Update the position of the bubble. Whenever the layout may have changed,
     * the bubble should either be repositioned by calling this function or
     * hidden so that it does not point to a nonsensical location on the page.
     */
    reposition: function() {
      const documentWidth = document.documentElement.clientWidth;
      const documentHeight = document.documentElement.clientHeight;
      const anchor = this.anchorNode_.getBoundingClientRect();
      const anchorMid = (anchor.left + anchor.right) / 2;
      const bubble = this.getBoundingClientRect();
      const arrow = this.querySelector('.bubble-arrow').getBoundingClientRect();

      let left;
      let top;
      if (this.bubbleAlignment_ == cr.ui.BubbleAlignment.ENTIRELY_VISIBLE) {
        // Work out horizontal placement. The bubble is initially positioned so
        // that the arrow tip points toward the midpoint of the anchor and is
        // BubbleBase.ARROW_OFFSET pixels from the reference edge and (as
        // specified by the arrow location). If the bubble is not entirely
        // within view, it is then shifted, preserving the arrow tip position.
        left = this.arrowAtRight_ ?
            anchorMid + BubbleBase.ARROW_OFFSET - bubble.width :
            anchorMid - BubbleBase.ARROW_OFFSET;
        const maxLeftPos =
            documentWidth - bubble.width - BubbleBase.MIN_VIEWPORT_EDGE_MARGIN;
        const minLeftPos = BubbleBase.MIN_VIEWPORT_EDGE_MARGIN;
        if (document.documentElement.dir == 'rtl') {
          left = Math.min(Math.max(left, minLeftPos), maxLeftPos);
        } else {
          left = Math.max(Math.min(left, maxLeftPos), minLeftPos);
        }
        const arrowTip = Math.min(
            Math.max(
                arrow.width / 2,
                this.arrowAtRight_ ? left + bubble.width - anchorMid :
                                     anchorMid - left),
            bubble.width - arrow.width / 2);

        // Work out the vertical placement, attempting to fit the bubble
        // entirely into view. The following placements are considered in
        // decreasing order of preference:
        // * Outside the anchor, arrow tip touching the anchor (arrow at
        //   top/bottom as specified by the arrow location).
        // * Outside the anchor, arrow tip touching the anchor (arrow at
        //   bottom/top, opposite the specified arrow location).
        // * Outside the anchor, arrow tip overlapping the anchor (arrow at
        //   top/bottom as specified by the arrow location).
        // * Outside the anchor, arrow tip overlapping the anchor (arrow at
        //   bottom/top, opposite the specified arrow location).
        // * Overlapping the anchor.
        const offsetTop = Math.min(
            documentHeight - anchor.bottom - bubble.height, arrow.height / 2);
        const offsetBottom =
            Math.min(anchor.top - bubble.height, arrow.height / 2);
        if (offsetTop < 0 && offsetBottom < 0) {
          top = 0;
          this.updateArrowPosition_(false, false, arrowTip);
        } else if (
            offsetTop > offsetBottom ||
            offsetTop == offsetBottom && this.arrowAtTop_) {
          top = anchor.bottom + offsetTop;
          this.updateArrowPosition_(true, true, arrowTip);
        } else {
          top = anchor.top - bubble.height - offsetBottom;
          this.updateArrowPosition_(true, false, arrowTip);
        }
      } else {
        if (this.bubbleAlignment_ ==
            cr.ui.BubbleAlignment.BUBBLE_EDGE_TO_ANCHOR_EDGE) {
          left = this.arrowAtRight_ ? anchor.right - bubble.width : anchor.left;
        } else {
          left = this.arrowAtRight_ ?
              anchorMid - this.clientWidth + BubbleBase.ARROW_OFFSET :
              anchorMid - BubbleBase.ARROW_OFFSET;
        }
        top = this.arrowAtTop_ ?
            anchor.bottom + arrow.height / 2 :
            anchor.top - this.clientHeight - arrow.height / 2;
        this.updateArrowPosition_(
            true, this.arrowAtTop_, BubbleBase.ARROW_OFFSET);
      }

      this.style.left = left + 'px';
      this.style.top = top + 'px';
    },

    /**
     * Show the bubble.
     */
    show: function() {
      if (!this.hidden) {
        return;
      }

      this.attachToDOM_();
      this.hidden = false;
      this.reposition();

      const doc = assert(this.ownerDocument);
      this.eventTracker_ = new EventTracker;
      this.eventTracker_.add(doc, 'keydown', this, true);
      this.eventTracker_.add(doc, 'mousedown', this, true);
    },

    /**
     * Hide the bubble.
     */
    hide: function() {
      if (this.hidden) {
        return;
      }

      this.eventTracker_.removeAll();
      this.hidden = true;
      this.parentNode.removeChild(this);
    },

    /**
     * Handle keyboard events, dismissing the bubble if necessary.
     * @param {Event} event The event.
     */
    handleEvent: function(event) {
      // Close the bubble when the user presses <Esc>.
      if (event.type == 'keydown' && event.keyCode == 27) {
        this.hide();
        event.preventDefault();
        event.stopPropagation();
      }
    },

    /**
     * Attach the bubble to the document's DOM.
     * @private
     */
    attachToDOM_: function() {
      document.body.appendChild(this);
    },

    /**
     * Update the arrow so that it appears at the correct position.
     * @param {boolean} visible Whether the arrow should be visible.
     * @param {boolean} atTop Whether the arrow should be at the top of the
     * bubble.
     * @param {number} tipOffset The horizontal distance between the tip of the
     * arrow and the reference edge of the bubble (as specified by the arrow
     * location).
     * @private
     */
    updateArrowPosition_: function(visible, atTop, tipOffset) {
      const bubbleArrow = this.querySelector('.bubble-arrow');
      bubbleArrow.hidden = !visible;
      if (!visible) {
        return;
      }

      let edgeOffset = (-bubbleArrow.clientHeight / 2) + 'px';
      bubbleArrow.style.top = atTop ? edgeOffset : 'auto';
      bubbleArrow.style.bottom = atTop ? 'auto' : edgeOffset;

      edgeOffset = (tipOffset - bubbleArrow.offsetWidth / 2) + 'px';
      bubbleArrow.style.left = this.arrowAtRight_ ? 'auto' : edgeOffset;
      bubbleArrow.style.right = this.arrowAtRight_ ? edgeOffset : 'auto';
    },
  };

  /**
   * A bubble that remains open until the user explicitly dismisses it or clicks
   * outside the bubble after it has been shown for at least the specified
   * amount of time (making it less likely that the user will unintentionally
   * dismiss the bubble). The bubble repositions itself on layout changes.
   * @constructor
   * @extends {cr.ui.BubbleBase}
   */
  const Bubble = cr.ui.define('div');

  Bubble.prototype = {
    // Set up the prototype chain.
    __proto__: BubbleBase.prototype,

    /**
     * Initialization function for the cr.ui framework.
     */
    decorate: function() {
      BubbleBase.prototype.decorate.call(this);

      const close = document.createElement('div');
      close.className = 'bubble-close';
      this.insertBefore(close, this.querySelector('.bubble-content'));

      this.handleCloseEvent = this.hide;
      this.deactivateToDismissDelay_ = 0;
      this.bubbleAlignment = cr.ui.BubbleAlignment.ARROW_TO_MID_ANCHOR;
    },

    /**
     * Handler for close events triggered when the close button is clicked. By
     * default, set to this.hide. Only available when the bubble is not being
     * shown.
     * @param {function(): *} handler The new handler, a function with no
     *     parameters.
     */
    set handleCloseEvent(handler) {
      if (!this.hidden) {
        return;
      }

      this.handleCloseEvent_ = handler;
    },

    /**
     * Set the delay before the user is allowed to click outside the bubble to
     * dismiss it. Using a delay makes it less likely that the user will
     * unintentionally dismiss the bubble.
     * @param {number} delay The delay in milliseconds.
     */
    set deactivateToDismissDelay(delay) {
      this.deactivateToDismissDelay_ = delay;
    },

    /**
     * Hide or show the close button.
     * @param {boolean} isVisible True if the close button should be visible.
     */
    set closeButtonVisible(isVisible) {
      this.querySelector('.bubble-close').hidden = !isVisible;
    },

    /**
     * Show the bubble.
     */
    show: function() {
      if (!this.hidden) {
        return;
      }

      BubbleBase.prototype.show.call(this);

      this.showTime_ = Date.now();
      this.eventTracker_.add(window, 'resize', this.reposition.bind(this));
    },

    /**
     * Handle keyboard and mouse events, dismissing the bubble if necessary.
     * @param {Event} event The event.
     * @suppress {checkTypes}
     * TODO(vitalyp): remove suppression when the extern
     * Node.prototype.contains() will be fixed.
     */
    handleEvent: function(event) {
      BubbleBase.prototype.handleEvent.call(this, event);

      if (event.type == 'mousedown') {
        // Dismiss the bubble when the user clicks on the close button.
        if (event.target == this.querySelector('.bubble-close')) {
          this.handleCloseEvent_();
          // Dismiss the bubble when the user clicks outside it after the
          // specified delay has passed.
        } else if (
            !this.contains(event.target) &&
            Date.now() - this.showTime_ >= this.deactivateToDismissDelay_) {
          this.hide();
        }
      }
    },
  };

  /**
   * A bubble that closes automatically when the user clicks or moves the focus
   * outside the bubble and its target element, scrolls the underlying document
   * or resizes the window.
   * @constructor
   * @extends {cr.ui.BubbleBase}
   */
  const AutoCloseBubble = cr.ui.define('div');

  AutoCloseBubble.prototype = {
    // Set up the prototype chain.
    __proto__: BubbleBase.prototype,

    /**
     * Initialization function for the cr.ui framework.
     */
    decorate: function() {
      BubbleBase.prototype.decorate.call(this);
      this.classList.add('auto-close-bubble');
    },

    /**
     * Set the DOM sibling node, i.e. the node as whose sibling the bubble
     * should join the DOM to ensure that focusable elements inside the bubble
     * follow the target element in the document's tab order. Only available
     * when the bubble is not being shown.
     * @param {HTMLElement} node The new DOM sibling node.
     */
    set domSibling(node) {
      if (!this.hidden) {
        return;
      }

      this.domSibling_ = node;
    },

    /**
     * Show the bubble.
     */
    show: function() {
      if (!this.hidden) {
        return;
      }

      BubbleBase.prototype.show.call(this);
      this.domSibling_.showingBubble = true;

      const doc = this.ownerDocument;
      this.eventTracker_.add(doc, 'click', this, true);
      this.eventTracker_.add(doc, 'mousewheel', this, true);
      this.eventTracker_.add(doc, 'scroll', this, true);
      this.eventTracker_.add(doc, 'elementFocused', this, true);
      this.eventTracker_.add(window, 'resize', this);
    },

    /**
     * Hide the bubble.
     */
    hide: function() {
      BubbleBase.prototype.hide.call(this);
      this.domSibling_.showingBubble = false;
    },

    /**
     * Handle events, closing the bubble when the user clicks or moves the focus
     * outside the bubble and its target element, scrolls the underlying
     * document or resizes the window.
     * @param {Event} event The event.
     * @suppress {checkTypes}
     * TODO(vitalyp): remove suppression when the extern
     * Node.prototype.contains() will be fixed.
     */
    handleEvent: function(event) {
      BubbleBase.prototype.handleEvent.call(this, event);

      let target;
      switch (event.type) {
        // Close the bubble when the user clicks outside it, except if it is a
        // left-click on the bubble's target element (allowing the target to
        // handle the event and close the bubble itself).
        case 'mousedown':
        case 'click':
          target = assertInstanceof(event.target, Node);
          if (event.button == 0 && this.anchorNode_.contains(target)) {
            break;
          }
        // Close the bubble when the underlying document is scrolled.
        case 'mousewheel':
        case 'scroll':
          target = assertInstanceof(event.target, Node);
          if (this.contains(target)) {
            break;
          }
        // Close the bubble when the window is resized.
        case 'resize':
          this.hide();
          break;
        // Close the bubble when the focus moves to an element that is not the
        // bubble target and is not inside the bubble.
        case 'elementFocused':
          target = assertInstanceof(event.target, Node);
          if (!this.anchorNode_.contains(target) && !this.contains(target)) {
            this.hide();
          }
          break;
      }
    },

    /**
     * Attach the bubble to the document's DOM, making it a sibling of the
     * |domSibling_| so that focusable elements inside the bubble follow the
     * target element in the document's tab order.
     * @private
     */
    attachToDOM_: function() {
      const parent = this.domSibling_.parentNode;
      parent.insertBefore(this, this.domSibling_.nextSibling);
    },
  };


  return {
    BubbleBase: BubbleBase,
    Bubble: Bubble,
    AutoCloseBubble: AutoCloseBubble
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Card slider implementation. Allows you to create interactions
 * that have items that can slide left to right to reveal additional items.
 * Works by adding the necessary event handlers to a specific DOM structure
 * including a frame, container and cards.
 * - The frame defines the boundary of one item. Each card will be expanded to
 *   fill the width of the frame. This element is also overflow hidden so that
 *   the additional items left / right do not trigger horizontal scrolling.
 * - The container is what all the touch events are attached to. This element
 *   will be expanded to be the width of all cards.
 * - The cards are the individual viewable items. There should be one card for
 *   each item in the list. Only one card will be visible at a time. Two cards
 *   will be visible while you are transitioning between cards.
 *
 * This class is designed to work well on any hardware-accelerated touch device.
 * It should still work on pre-hardware accelerated devices it just won't feel
 * very good. It should also work well with a mouse.
 */

// Use an anonymous function to enable strict mode just for this file (which
// will be concatenated with other files when embedded in Chrome
cr.define('cr.ui', function() {
  'use strict';

  /**
   * @constructor
   * @param {!Element} frame The bounding rectangle that cards are visible in.
   * @param {!Element} container The surrounding element that will have event
   *     listeners attached to it.
   * @param {number} cardWidth The width of each card should have.
   */
  function CardSlider(frame, container, cardWidth) {
    /**
     * @type {!Element}
     * @private
     */
    this.frame_ = frame;

    /**
     * @type {!Element}
     * @private
     */
    this.container_ = container;

    /**
     * Array of card elements.
     * @type {!Array<!Element>}
     * @private
     */
    this.cards_ = [];

    /**
     * Index of currently shown card.
     * @type {number}
     * @private
     */
    this.currentCard_ = -1;

    /**
     * @type {number}
     * @private
     */
    this.cardWidth_ = cardWidth;

    /**
     * @type {!cr.ui.TouchHandler}
     * @private
     */
    this.touchHandler_ = new cr.ui.TouchHandler(this.container_);
  }


  /**
   * The time to transition between cards when animating. Measured in ms.
   * @type {number}
   * @private
   * @const
   */
  CardSlider.TRANSITION_TIME_ = 200;


  /**
   * The minimum velocity required to transition cards if they did not drag past
   * the halfway point between cards. Measured in pixels / ms.
   * @type {number}
   * @private
   * @const
   */
  CardSlider.TRANSITION_VELOCITY_THRESHOLD_ = 0.2;


  CardSlider.prototype = {
    /**
     * The current left offset of the container relative to the frame. This
     * position does not include deltas from active drag operations, and
     * always aligns with a frame boundary.
     * @type {number}
     * @private
     */
    currentLeft_: 0,

    /**
     * Current offset relative to |currentLeft_| due to an active drag
     * operation.
     * @type {number}
     * @private
     */
    deltaX_: 0,

    /**
     * Initialize all elements and event handlers. Must call after construction
     * and before usage.
     * @param {boolean} ignoreMouseWheelEvents If true, horizontal mouse wheel
     *     events will be ignored, rather than flipping between pages.
     */
    initialize: function(ignoreMouseWheelEvents) {
      const view = this.container_.ownerDocument.defaultView;
      assert(
          view.getComputedStyle(this.container_).display == '-webkit-box',
          'Container should be display -webkit-box.');
      assert(
          view.getComputedStyle(this.frame_).overflow == 'hidden',
          'Frame should be overflow hidden.');
      assert(
          view.getComputedStyle(this.container_).position == 'static',
          'Container should be position static.');

      this.updateCardWidths_();

      this.mouseWheelScrollAmount_ = 0;
      this.mouseWheelCardSelected_ = false;
      this.mouseWheelIsContinuous_ = false;
      this.scrollClearTimeout_ = null;
      if (!ignoreMouseWheelEvents) {
        this.frame_.addEventListener(
            'mousewheel', this.onMouseWheel_.bind(this));
      }
      this.container_.addEventListener(
          'transitionend', this.onTransitionEnd_.bind(this));

      // Also support touch events in case a touch screen happens to be
      // available.  Note that this has minimal impact in the common case of
      // no touch events (eg. we're mainly just adding listeners for events that
      // will never trigger).
      const TouchHandler = cr.ui.TouchHandler;
      this.container_.addEventListener(
          TouchHandler.EventType.TOUCH_START, this.onTouchStart_.bind(this));
      this.container_.addEventListener(
          TouchHandler.EventType.DRAG_START, this.onDragStart_.bind(this));
      this.container_.addEventListener(
          TouchHandler.EventType.DRAG_MOVE, this.onDragMove_.bind(this));
      this.container_.addEventListener(
          TouchHandler.EventType.DRAG_END, this.onDragEnd_.bind(this));

      this.touchHandler_.enable(/* opt_capture */ false);
    },

    /**
     * Use in cases where the width of the frame has changed in order to update
     * the width of cards. For example should be used when orientation changes
     * in full width sliders.
     * @param {number} newCardWidth Width all cards should have, in pixels.
     */
    resize: function(newCardWidth) {
      if (newCardWidth != this.cardWidth_) {
        this.cardWidth_ = newCardWidth;

        this.updateCardWidths_();

        // Must upate the transform on the container to show the correct card.
        this.transformToCurrentCard_();
      }
    },

    /**
     * Sets the cards used. Can be called more than once to switch card sets.
     * @param {!Array<!Element>} cards The individual viewable cards.
     * @param {number} index Index of the card to in the new set of cards to
     *     navigate to.
     */
    setCards: function(cards, index) {
      assert(
          index >= 0 && index < cards.length,
          'Invalid index in CardSlider#setCards');
      this.cards_ = cards;

      this.updateCardWidths_();
      this.updateSelectedCardAttributes_();

      // Jump to the given card index.
      this.selectCard(index, false, false, true);
    },

    /**
     * Ensures that for all cards:
     * - if the card is the current card, then it has 'selected-card' in its
     *   classList, and is visible for accessibility
     * - if the card is not the selected card, then it does not have
     *   'selected-card' in its classList, and is invisible for accessibility.
     * @private
     */
    updateSelectedCardAttributes_: function() {
      for (let i = 0; i < this.cards_.length; i++) {
        if (i == this.currentCard_) {
          this.cards_[i].classList.add('selected-card');
          this.cards_[i].removeAttribute('aria-hidden');
        } else {
          this.cards_[i].classList.remove('selected-card');
          this.cards_[i].setAttribute('aria-hidden', true);
        }
      }
    },

    /**
     * Updates the width of each card.
     * @private
     */
    updateCardWidths_: function() {
      for (let i = 0, card; card = this.cards_[i]; i++) {
        card.style.width = this.cardWidth_ + 'px';
      }
    },

    /**
     * Returns the index of the current card.
     * @return {number} index of the current card.
     */
    get currentCard() {
      return this.currentCard_;
    },

    /**
     * Allows setting the current card index.
     * @param {number} index A new index to set the current index to.
     * @return {number} The new index after having been set.
     */
    set currentCard(index) {
      return (this.currentCard_ = index);
    },

    /**
     * Returns the number of cards.
     * @return {number} number of cards.
     */
    get cardCount() {
      return this.cards_.length;
    },

    /**
     * Returns the current card itself.
     * @return {!Element} the currently shown card.
     */
    get currentCardValue() {
      return this.cards_[this.currentCard_];
    },

    /**
     * Returns the frame holding the cards.
     * @return {Element} The frame used to position the cards.
     */
    get frame() {
      return this.frame_;
    },

    /**
     * Handle horizontal scrolls to flip between pages.
     * @private
     */
    onMouseWheel_: function(e) {
      if (e.wheelDeltaX == 0) {
        return;
      }

      // Continuous devices such as an Apple Touchpad or Apple MagicMouse will
      // send arbitrary delta values. Conversly, standard mousewheels will
      // send delta values in increments of 120.  (There is of course a small
      // chance we mistake a continuous device for a non-continuous device.
      // Unfortunately there isn't a better way to do this until real touch
      // events are available to desktop clients.)
      const DISCRETE_DELTA = 120;
      if (e.wheelDeltaX % DISCRETE_DELTA) {
        this.mouseWheelIsContinuous_ = true;
      }

      if (this.mouseWheelIsContinuous_) {
        // For continuous devices, detect a page swipe when the accumulated
        // delta matches a pre-defined threshhold.  After changing the page,
        // ignore wheel events for a short time before repeating this process.
        if (this.mouseWheelCardSelected_) {
          return;
        }
        this.mouseWheelScrollAmount_ += e.wheelDeltaX;
        if (Math.abs(this.mouseWheelScrollAmount_) >= 600) {
          let pagesToScroll = this.mouseWheelScrollAmount_ > 0 ? 1 : -1;
          if (!isRTL()) {
            pagesToScroll *= -1;
          }
          let newCardIndex = this.currentCard + pagesToScroll;
          newCardIndex =
              Math.min(this.cards_.length - 1, Math.max(0, newCardIndex));
          this.selectCard(newCardIndex, true);
          this.mouseWheelCardSelected_ = true;
        }
      } else {
        // For discrete devices, consider each wheel tick a page change.
        let pagesToScroll = e.wheelDeltaX / DISCRETE_DELTA;
        if (!isRTL()) {
          pagesToScroll *= -1;
        }
        let newCardIndex = this.currentCard + pagesToScroll;
        newCardIndex =
            Math.min(this.cards_.length - 1, Math.max(0, newCardIndex));
        this.selectCard(newCardIndex, true);
      }

      // We got a mouse wheel event, so cancel any pending scroll wheel timeout.
      if (this.scrollClearTimeout_ != null) {
        clearTimeout(this.scrollClearTimeout_);
      }
      // If we didn't use up all the scroll, hold onto it for a little bit, but
      // drop it after a delay.
      if (this.mouseWheelScrollAmount_ != 0) {
        this.scrollClearTimeout_ =
            setTimeout(this.clearMouseWheelScroll_.bind(this), 500);
      }
    },

    /**
     * Resets the amount of horizontal scroll we've seen to 0. See
     * onMouseWheel_.
     * @private
     */
    clearMouseWheelScroll_: function() {
      this.mouseWheelScrollAmount_ = 0;
      this.mouseWheelCardSelected_ = false;
    },

    /**
     * Handles the ends of transitions on transform (animated
     * card switches).
     * @param {Event} e The transitionend event.
     * @private
     */
    onTransitionEnd_: function(e) {
      // Ignore irrelevant transitions that might bubble up.
      if (e.target !== this.container_ || e.propertyName != 'transform') {
        return;
      }
      this.fireChangeEndedEvent_(true);
    },

    /**
     * Dispatches a simple event to tell subscribers we're done moving to the
     * newly selected card.
     * @param {boolean} wasAnimated whether or not the change was animated.
     * @private
     */
    fireChangeEndedEvent_: function(wasAnimated) {
      const e = document.createEvent('Event');
      e.initEvent('cardSlider:card_change_ended', true, true);
      e.cardSlider = this;
      e.changedTo = this.currentCard_;
      e.wasAnimated = wasAnimated;
      this.container_.dispatchEvent(e);
    },

    /**
     * Add a card to the card slider at a particular index. If the card being
     * added is inserted in front of the current card, cardSlider.currentCard
     * will be adjusted accordingly (to current card + 1).
     * @param {!Node} card A card that will be added to the card slider.
     * @param {number} index An index at which the given |card| should be
     *     inserted. Must be positive and less than the number of cards.
     */
    addCardAtIndex: function(card, index) {
      assert(card instanceof Node, '|card| isn\'t a Node');
      this.assertValidIndex_(index);
      this.cards_ = Array.prototype.concat.call(
          this.cards_.slice(0, index), card, this.cards_.slice(index));

      this.updateSelectedCardAttributes_();

      if (this.currentCard_ == -1) {
        this.currentCard_ = 0;
      } else if (index <= this.currentCard_) {
        this.selectCard(this.currentCard_ + 1, false, true, true);
      }

      this.fireAddedEvent_(card, index);
    },

    /**
     * Append a card to the end of the list.
     * @param {!Element} card A card to add at the end of the card slider.
     */
    appendCard: function(card) {
      this.cards_.push(assertInstanceof(card, Element));
      this.fireAddedEvent_(card, this.cards_.length - 1);
    },

    /**
     * Dispatches a simple event to tell interested subscribers that a card was
     * added to this card slider.
     * @param {Node} card The recently added card.
     * @param {number} index The position of the newly added card.
     * @private
     */
    fireAddedEvent_: function(card, index) {
      this.assertValidIndex_(index);
      const e = document.createEvent('Event');
      e.initEvent('cardSlider:card_added', true, true);
      e.addedIndex = index;
      e.addedCard = card;
      this.container_.dispatchEvent(e);
    },

    /**
     * Returns the card at a particular index.
     * @param {number} index The index of the card to return.
     * @return {!Element} The card at the given index.
     */
    getCardAtIndex: function(index) {
      this.assertValidIndex_(index);
      return this.cards_[index];
    },

    /**
     * Removes a card by index from the card slider. If the card to be removed
     * is the current card or in front of the current card, the current card
     * will be updated (to current card - 1).
     * @param {!Element} card A card to be removed.
     */
    removeCard: function(card) {
      this.removeCardAtIndex(
          this.cards_.indexOf(assertInstanceof(card, Element)));
    },

    /**
     * Removes a card by index from the card slider. If the card to be removed
     * is the current card or in front of the current card, the current card
     * will be updated (to current card - 1).
     * @param {number} index The index of the tile that should be removed.
     */
    removeCardAtIndex: function(index) {
      this.assertValidIndex_(index);
      const removed = this.cards_.splice(index, 1).pop();

      if (this.cards_.length == 0) {
        this.currentCard_ = -1;
      } else if (index < this.currentCard_) {
        this.selectCard(this.currentCard_ - 1, false, true);
      }

      this.fireRemovedEvent_(removed, index);
    },

    /**
     * Dispatches a cardSlider:card_removed event so interested subscribers know
     * when a card was removed from this card slider.
     * @param {Node} card The recently removed card.
     * @param {number} index The index of the card before it was removed.
     * @private
     */
    fireRemovedEvent_: function(card, index) {
      const e = document.createEvent('Event');
      e.initEvent('cardSlider:card_removed', true, true);
      e.removedCard = card;
      e.removedIndex = index;
      this.container_.dispatchEvent(e);
    },

    /**
     * This re-syncs the transform that's used to position the frame in
     * the likely event it needs to be updated by a card being inserted or
     * removed in the flow.
     */
    repositionFrame: function() {
      this.transformToCurrentCard_();
    },

    /**
     * Checks the the given |index| exists in this.cards_.
     * @param {number} index An index to check.
     * @private
     */
    assertValidIndex_: function(index) {
      assert(index >= 0 && index < this.cards_.length);
    },

    /**
     * Selects a new card, ensuring that it is a valid index, transforming the
     * view and possibly calling the change card callback.
     * @param {number} newCardIndex Index of card to show.
     * @param {boolean=} opt_animate If true will animate transition from
     *     current position to new position.
     * @param {boolean=} opt_dontNotify If true, don't tell subscribers that
     *     we've changed cards.
     * @param {boolean=} opt_forceChange If true, ignore if the card already
     *     selected.
     */
    selectCard: function(
        newCardIndex, opt_animate, opt_dontNotify, opt_forceChange) {
      this.assertValidIndex_(newCardIndex);

      const previousCard = this.currentCardValue;
      let isChangingCard =
          !this.cards_[newCardIndex].classList.contains('selected-card');

      if (typeof opt_forceChange != 'undefined' && opt_forceChange) {
        isChangingCard = true;
      }

      if (isChangingCard) {
        this.currentCard_ = newCardIndex;
        this.updateSelectedCardAttributes_();
      }

      const willTransitionHappen = this.transformToCurrentCard_(opt_animate);

      if (isChangingCard && !opt_dontNotify) {
        const event = document.createEvent('Event');
        event.initEvent('cardSlider:card_changed', true, true);
        event.cardSlider = this;
        event.wasAnimated = !!opt_animate;
        this.container_.dispatchEvent(event);

        // We also dispatch an event on the cards themselves.
        if (previousCard) {
          cr.dispatchSimpleEvent(previousCard, 'carddeselected', true, true);
        }
        cr.dispatchSimpleEvent(
            this.currentCardValue, 'cardselected', true, true);
      }

      // If we're not changing, animated, or transitioning, fire a
      // cardSlider:card_change_ended event right away.
      if ((!isChangingCard || !opt_animate || !willTransitionHappen) &&
          !opt_dontNotify) {
        this.fireChangeEndedEvent_(false);
      }
    },

    /**
     * Selects a card from the stack. Passes through to selectCard.
     * @param {!Element} newCard The card that should be selected.
     * @param {boolean=} opt_animate Whether to animate.
     */
    selectCardByValue: function(newCard, opt_animate) {
      const i = this.cards_.indexOf(newCard);
      assert(i != -1);
      this.selectCard(i, opt_animate);
    },

    /**
     * Centers the view on the card denoted by this.currentCard. Can either
     * animate to that card or snap to it.
     * @param {boolean=} opt_animate If true will animate transition from
     *     current position to new position.
     * @return {boolean} Whether or not a transformation was necessary.
     * @private
     */
    transformToCurrentCard_: function(opt_animate) {
      const prevLeft = this.currentLeft_;
      this.currentLeft_ = -this.cardWidth_ *
          (isRTL() ? this.cards_.length - this.currentCard - 1 :
                     this.currentCard);

      // If there's no change, return something to let the caller know there
      // won't be a transition occuring.
      if (prevLeft == this.currentLeft_ && this.deltaX_ == 0) {
        return false;
      }

      // Animate to the current card, which will either transition if the
      // current card is new, or reset the existing card if we didn't drag
      // enough to change cards.
      let transition = '';
      if (opt_animate) {
        transition =
            'transform ' + CardSlider.TRANSITION_TIME_ + 'ms ease-in-out';
      }
      this.container_.style.transition = transition;
      this.translateTo_(this.currentLeft_);

      return true;
    },

    /**
     * Moves the view to the specified position.
     * @param {number} x Horizontal position to move to.
     * @private
     */
    translateTo_: function(x) {
      // We use a transform to slide because this is GPU accelerated on
      // Chrome and iOS.  Once Chrome does GPU acceleration on the position
      // fixed-layout elements we could simply set the element's position to
      // fixed and modify 'left' instead.
      this.deltaX_ = x - this.currentLeft_;
      this.container_.style.transform = 'translate3d(' + x + 'px, 0, 0)';
    },

    /* Touch ******************************************************************/

    /**
     * Clear any transition that is in progress and enable dragging for the
     * touch.
     * @param {!Event} e The TouchHandler event.
     * @private
     */
    onTouchStart_: function(e) {
      e = /** @type {!cr.ui.TouchHandler.Event} */ (e);
      this.container_.style.transition = '';
      e.enableDrag = true;
    },

    /**
     * Tell the TouchHandler that dragging is acceptable when the user begins by
     * scrolling horizontally and there is more than one card to slide.
     * @param {!Event} e The TouchHandler event.
     * @private
     */
    onDragStart_: function(e) {
      e = /** @type {!cr.ui.TouchHandler.Event} */ (e);
      e.enableDrag =
          this.cardCount > 1 && Math.abs(e.dragDeltaX) > Math.abs(e.dragDeltaY);
    },

    /**
     * On each drag move event reposition the container appropriately so the
     * cards look like they are sliding.
     * @param {!Event} e The TouchHandler event.
     * @private
     */
    onDragMove_: function(e) {
      e = /** @type {!cr.ui.TouchHandler.Event} */ (e);
      let deltaX = e.dragDeltaX;
      // If dragging beyond the first or last card then apply a backoff so the
      // dragging feels stickier than usual.
      if (!this.currentCard && deltaX > 0 ||
          this.currentCard == (this.cards_.length - 1) && deltaX < 0) {
        deltaX /= 2;
      }
      this.translateTo_(this.currentLeft_ + deltaX);
    },

    /**
     * On drag end events we may want to transition to another card, depending
     * on the ending position of the drag and the velocity of the drag.
     * @param {!Event} e The TouchHandler event.
     * @private
     */
    onDragEnd_: function(e) {
      e = /** @type {!cr.ui.TouchHandler.Event} */ (e);
      const deltaX = e.dragDeltaX;
      const velocity = this.touchHandler_.getEndVelocity().x;
      const newX = this.currentLeft_ + deltaX;
      let newCardIndex = Math.round(-newX / this.cardWidth_);

      if (newCardIndex == this.currentCard &&
          Math.abs(velocity) > CardSlider.TRANSITION_VELOCITY_THRESHOLD_) {
        // The drag wasn't far enough to change cards but the velocity was
        // high enough to transition anyways. If the velocity is to the left
        // (negative) then the user wishes to go right (card + 1).
        newCardIndex += velocity > 0 ? -1 : 1;
      }
      // Ensure that the new card index is valid.  The new card index could be
      // invalid if a swipe suggests scrolling off the end of the list of
      // cards.
      if (newCardIndex < 0) {
        newCardIndex = 0;
      } else if (newCardIndex >= this.cardCount) {
        newCardIndex = this.cardCount - 1;
      }
      this.selectCard(newCardIndex, /* animate */ true);
    },

    /**
     * Cancel any current touch/slide as if we saw a touch end
     */
    cancelTouch: function() {
      // Stop listening to any current touch
      this.touchHandler_.cancelTouch();

      // Ensure we're at a card bounary
      this.transformToCurrentCard_(true);
    },
  };

  return {CardSlider: CardSlider};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// require: event_target.js

cr.define('cr.ui', function() {
  /** @const */ const EventTarget = cr.EventTarget;
  /** @const */ const Menu = cr.ui.Menu;

  /**
   * Handles context menus.
   * @constructor
   * @extends {cr.EventTarget}
   * @implements {EventListener}
   */
  function ContextMenuHandler() {
    /** @private {!EventTracker} */
    this.showingEvents_ = new EventTracker();
  }

  ContextMenuHandler.prototype = {
    __proto__: EventTarget.prototype,

    /**
     * The menu that we are currently showing.
     * @type {cr.ui.Menu}
     */
    menu_: null,
    get menu() {
      return this.menu_;
    },

    /**
     * Shows a menu as a context menu.
     * @param {!Event} e The event triggering the show (usually a contextmenu
     *     event).
     * @param {!cr.ui.Menu} menu The menu to show.
     */
    showMenu: function(e, menu) {
      menu.updateCommands(assertInstanceof(e.currentTarget, Node));
      if (!menu.hasVisibleItems()) {
        return;
      }

      this.menu_ = menu;
      menu.classList.remove('hide-delayed');
      menu.show({x: e.screenX, y: e.screenY});
      menu.contextElement = e.currentTarget;

      // When the menu is shown we steal a lot of events.
      const doc = menu.ownerDocument;
      const win = /** @type {!Window} */ (doc.defaultView);
      this.showingEvents_.add(doc, 'keydown', this, true);
      this.showingEvents_.add(doc, 'mousedown', this, true);
      this.showingEvents_.add(doc, 'touchstart', this, true);
      this.showingEvents_.add(doc, 'focus', this);
      this.showingEvents_.add(win, 'popstate', this);
      this.showingEvents_.add(win, 'resize', this);
      this.showingEvents_.add(win, 'blur', this);
      this.showingEvents_.add(menu, 'contextmenu', this);
      this.showingEvents_.add(menu, 'activate', this);
      this.positionMenu_(e, menu);

      const ev = new Event('show');
      ev.element = menu.contextElement;
      ev.menu = menu;
      this.dispatchEvent(ev);
    },

    /**
     * Hide the currently shown menu.
     * @param {cr.ui.HideType=} opt_hideType Type of hide.
     *     default: cr.ui.HideType.INSTANT.
     */
    hideMenu: function(opt_hideType) {
      const menu = this.menu;
      if (!menu) {
        return;
      }

      if (opt_hideType == cr.ui.HideType.DELAYED) {
        menu.classList.add('hide-delayed');
      } else {
        menu.classList.remove('hide-delayed');
      }
      menu.hide();
      const originalContextElement = menu.contextElement;
      menu.contextElement = null;
      this.showingEvents_.removeAll();
      menu.selectedIndex = -1;
      this.menu_ = null;

      // On windows we might hide the menu in a right mouse button up and if
      // that is the case we wait some short period before we allow the menu
      // to be shown again.
      this.hideTimestamp_ = cr.isWindows ? Date.now() : 0;

      const ev = new Event('hide');
      ev.element = originalContextElement;
      ev.menu = menu;
      this.dispatchEvent(ev);
    },

    /**
     * Positions the menu
     * @param {!Event} e The event object triggering the showing.
     * @param {!cr.ui.Menu} menu The menu to position.
     * @private
     */
    positionMenu_: function(e, menu) {
      // TODO(arv): Handle scrolled documents when needed.

      const element = e.currentTarget;
      let x, y;
      // When the user presses the context menu key (on the keyboard) we need
      // to detect this.
      if (this.keyIsDown_) {
        const rect = element.getRectForContextMenu ?
            element.getRectForContextMenu() :
            element.getBoundingClientRect();
        const offset = Math.min(rect.width, rect.height) / 2;
        x = rect.left + offset;
        y = rect.top + offset;
      } else {
        x = e.clientX;
        y = e.clientY;
      }

      cr.ui.positionPopupAtPoint(x, y, menu);
    },

    /**
     * Handles event callbacks.
     * @param {!Event} e The event object.
     */
    handleEvent: function(e) {
      // Keep track of keydown state so that we can use that to determine the
      // reason for the contextmenu event.
      switch (e.type) {
        case 'keydown':
          this.keyIsDown_ = !e.ctrlKey && !e.altKey &&
              // context menu key or Shift-F10
              (e.keyCode == 93 && !e.shiftKey || e.key == 'F10' && e.shiftKey);
          break;

        case 'keyup':
          this.keyIsDown_ = false;
          break;
      }

      // Context menu is handled even when we have no menu.
      if (e.type != 'contextmenu' && !this.menu) {
        return;
      }

      switch (e.type) {
        case 'mousedown':
          if (!this.menu.contains(e.target)) {
            this.hideMenu();
            if (e.button == 0 /* Left button */ && (cr.isLinux || cr.isMac)) {
              // Emulate Mac and Linux, which swallow native 'mousedown' events
              // that close menus.
              e.preventDefault();
              e.stopPropagation();
            }
          } else {
            e.preventDefault();
          }
          break;

        case 'touchstart':
          if (!this.menu.contains(e.target)) {
            this.hideMenu();
          }
          break;

        case 'keydown':
          if (e.key == 'Escape') {
            this.hideMenu();
            e.stopPropagation();
            e.preventDefault();

            // If the menu is visible we let it handle all the keyboard events.
          } else if (this.menu) {
            this.menu.handleKeyDown(e);
            e.preventDefault();
            e.stopPropagation();
          }
          break;

        case 'activate':
          const hideDelayed =
              e.target instanceof cr.ui.MenuItem && e.target.checkable;
          this.hideMenu(
              hideDelayed ? cr.ui.HideType.DELAYED : cr.ui.HideType.INSTANT);
          break;

        case 'focus':
          if (!this.menu.contains(e.target)) {
            this.hideMenu();
          }
          break;

        case 'blur':
          this.hideMenu();
          break;

        case 'popstate':
        case 'resize':
          this.hideMenu();
          break;

        case 'contextmenu':
          if ((!this.menu || !this.menu.contains(e.target)) &&
              (!this.hideTimestamp_ || Date.now() - this.hideTimestamp_ > 50)) {
            this.showMenu(e, e.currentTarget.contextMenu);
          }
          e.preventDefault();
          // Don't allow elements further up in the DOM to show their menus.
          e.stopPropagation();
          break;
      }
    },

    /**
     * Adds a contextMenu property to an element or element class.
     * @param {!Element|!Function} elementOrClass The element or class to add
     *     the contextMenu property to.
     */
    addContextMenuProperty: function(elementOrClass) {
      const target = typeof elementOrClass == 'function' ?
          elementOrClass.prototype :
          elementOrClass;

      target.__defineGetter__('contextMenu', function() {
        return this.contextMenu_;
      });
      target.__defineSetter__('contextMenu', function(menu) {
        const oldContextMenu = this.contextMenu;

        if (typeof menu == 'string' && menu[0] == '#') {
          menu = this.ownerDocument.getElementById(menu.slice(1));
          cr.ui.decorate(menu, Menu);
        }

        if (menu === oldContextMenu) {
          return;
        }

        if (oldContextMenu && !menu) {
          this.removeEventListener('contextmenu', contextMenuHandler);
          this.removeEventListener('keydown', contextMenuHandler);
          this.removeEventListener('keyup', contextMenuHandler);
        }
        if (menu && !oldContextMenu) {
          this.addEventListener('contextmenu', contextMenuHandler);
          this.addEventListener('keydown', contextMenuHandler);
          this.addEventListener('keyup', contextMenuHandler);
        }

        this.contextMenu_ = menu;

        if (menu && menu.id) {
          this.setAttribute('contextmenu', '#' + menu.id);
        }

        cr.dispatchPropertyChange(this, 'contextMenu', menu, oldContextMenu);
      });

      if (!target.getRectForContextMenu) {
        /**
         * @return {!ClientRect} The rect to use for positioning the context
         *     menu when the context menu is not opened using a mouse position.
         */
        target.getRectForContextMenu = function() {
          return this.getBoundingClientRect();
        };
      }
    },

    /**
     * Sets the given contextMenu to the given element. A contextMenu property
     * would be added if necessary.
     * @param {!Element} element The element or class to set the contextMenu to.
     * @param {!cr.ui.Menu} contextMenu The contextMenu property to be set.
     */
    setContextMenu: function(element, contextMenu) {
      if (!element.contextMenu) {
        this.addContextMenuProperty(element);
      }
      element.contextMenu = contextMenu;
    }
  };

  /**
   * The singleton context menu handler.
   * @type {!ContextMenuHandler}
   */
  const contextMenuHandler = new ContextMenuHandler;

  // Export
  return {
    contextMenuHandler: contextMenuHandler,
  };
});
</script>
<script>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview DragWrapper
 * A class for simplifying HTML5 drag and drop. Classes should use this to
 * handle the nitty gritty of nested drag enters and leaves.
 */
cr.define('cr.ui', function() {
  /** @interface */
  const DragWrapperDelegate = function() {};

  // TODO(devlin): The only method this "delegate" actually needs is
  // shouldAcceptDrag(); the rest can be events emitted by the DragWrapper.
  DragWrapperDelegate.prototype = {
    /**
     * @param {MouseEvent} e The event for the drag.
     * @return {boolean} Whether the drag should be accepted. If false,
     *     subsequent methods (doDrag*) will not be called.
     */
    shouldAcceptDrag: assertNotReached,

    /** @param {MouseEvent} e */
    doDragEnter: assertNotReached,

    /** @param {MouseEvent} e */
    doDragLeave: assertNotReached,

    /** @param {MouseEvent} e */
    doDragOver: assertNotReached,

    /** @param {MouseEvent} e */
    doDrop: assertNotReached,
  };

  /**
   * Creates a DragWrapper which listens for drag target events on |target| and
   * delegates event handling to |delegate|.
   * @param {!Element} target
   * @param {!cr.ui.DragWrapperDelegate} delegate
   * @constructor
   */
  function DragWrapper(target, delegate) {
    this.initialize(target, delegate);
  }

  DragWrapper.prototype = {
    initialize: function(target, delegate) {
      target.addEventListener('dragenter', this.onDragEnter_.bind(this));
      target.addEventListener('dragover', this.onDragOver_.bind(this));
      target.addEventListener('drop', this.onDrop_.bind(this));
      target.addEventListener('dragleave', this.onDragLeave_.bind(this));

      this.target_ = target;
      this.delegate_ = delegate;
    },

    /**
     * The number of un-paired dragenter events that have fired on |this|. This
     * is incremented by |onDragEnter_| and decremented by |onDragLeave_|. This
     * is necessary because dragging over child widgets will fire additional
     * enter and leave events on |this|. A non-zero value does not necessarily
     * indicate that |isCurrentDragTarget()| is true.
     * @type {number}
     * @private
     */
    dragEnters_: 0,

    /**
     * Whether the tile page is currently being dragged over with data it can
     * accept.
     * @type {boolean}
     */
    get isCurrentDragTarget() {
      return this.target_.classList.contains('drag-target');
    },

    /**
     * Delegate for dragenter events fired on |target_|.
     * @param {MouseEvent} e A MouseEvent for the drag.
     * @private
     */
    onDragEnter_: function(e) {
      if (++this.dragEnters_ == 1) {
        if (this.delegate_.shouldAcceptDrag(e)) {
          this.target_.classList.add('drag-target');
          this.delegate_.doDragEnter(e);
        }
      } else {
        // Sometimes we'll get an enter event over a child element without an
        // over event following it. In this case we have to still call the
        // drag over delegate so that we make the necessary updates (one visible
        // symptom of not doing this is that the cursor's drag state will
        // flicker during drags).
        this.onDragOver_(e);
      }
    },

    /**
     * Thunk for dragover events fired on |target_|.
     * @param {Event} e A MouseEvent for the drag.
     * @private
     */
    onDragOver_: function(e) {
      if (!this.target_.classList.contains('drag-target')) {
        return;
      }
      this.delegate_.doDragOver(e);
    },

    /**
     * Thunk for drop events fired on |target_|.
     * @param {Event} e A MouseEvent for the drag.
     * @private
     */
    onDrop_: function(e) {
      this.dragEnters_ = 0;
      if (!this.target_.classList.contains('drag-target')) {
        return;
      }
      this.target_.classList.remove('drag-target');
      this.delegate_.doDrop(e);
    },

    /**
     * Thunk for dragleave events fired on |target_|.
     * @param {Event} e A MouseEvent for the drag.
     * @private
     */
    onDragLeave_: function(e) {
      if (--this.dragEnters_ > 0) {
        return;
      }

      this.target_.classList.remove('drag-target');
      this.delegate_.doDragLeave(e);
    },
  };

  return {
    DragWrapper: DragWrapper,
    DragWrapperDelegate: DragWrapperDelegate,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// require: event_tracker.js

cr.define('cr.ui', function() {
  'use strict';

  /**
   * ExpandableBubble is a free-floating compact informational bubble with an
   * arrow that points at a place of interest on the page. When clicked, the
   * bubble expands to show more of its content. Width of the bubble is the
   * width of the node it is overlapping when unexpanded. Expanded, it is of a
   * fixed width, but variable height. Currently the arrow is always positioned
   * at the bottom right and points down.
   * @constructor
   * @extends {HTMLDivElement}
   * @implements {EventListener}
   */
  const ExpandableBubble = cr.ui.define('div');

  ExpandableBubble.prototype = {
    __proto__: HTMLDivElement.prototype,

    decorate: function() {
      this.className = 'expandable-bubble';
      this.innerHTML = '<div class="expandable-bubble-contents">' +
          '<div class="expandable-bubble-title"></div>' +
          '<div class="expandable-bubble-main" hidden></div>' +
          '</div>' +
          '<div class="expandable-bubble-close" hidden></div>';

      this.hidden = true;
      this.bubbleSuppressed = false;
      this.handleCloseEvent = this.hide;
    },

    /**
     * Sets the title of the bubble. The title is always visible when the
     * bubble is visible.
     * @param {Node} node An HTML element to set as the title.
     */
    set contentTitle(node) {
      const bubbleTitle = this.querySelector('.expandable-bubble-title');
      bubbleTitle.textContent = '';
      bubbleTitle.appendChild(node);
    },

    /**
     * Sets the content node of the bubble. The content node is only visible
     * when the bubble is expanded.
     * @param {Node} node An HTML element.
     */
    set content(node) {
      const bubbleMain = this.querySelector('.expandable-bubble-main');
      bubbleMain.textContent = '';
      bubbleMain.appendChild(node);
    },

    /**
     * Sets the anchor node, i.e. the node that this bubble points at and
     * partially overlaps.
     * @param {HTMLElement} node The new anchor node.
     */
    set anchorNode(node) {
      this.anchorNode_ = node;

      if (!this.hidden) {
        this.resizeAndReposition();
      }
    },

    /**
     * Handles the close event which is triggered when the close button
     * is clicked. By default is set to this.hide.
     * @param {Function} func A function with no parameters.
     */
    set handleCloseEvent(func) {
      this.handleCloseEvent_ = func;
    },

    /**
     * Temporarily suppresses the bubble from view (and toggles it back).
     * 'Suppressed' and 'hidden' are two bubble states that both indicate that
     * the bubble should not be visible, but when you 'un-suppress' a bubble,
     * only a suppressed bubble becomes visible. This can be handy, for example,
     * if the user switches away from the app card (then we need to know which
     * bubbles to show (only the suppressed ones, not the hidden ones). Hiding
     * and un-hiding a bubble overrides the suppressed state (a bubble cannot
     * be suppressed but not hidden).
     */
    set suppressed(suppress) {
      if (suppress) {
        // If the bubble is already hidden, then we don't need to suppress it.
        if (this.hidden) {
          return;
        }

        this.hidden = true;
      } else if (this.bubbleSuppressed) {
        this.hidden = false;
      }
      this.bubbleSuppressed = suppress;
      this.resizeAndReposition();
    },

    /**
     * Updates the position of the bubble.
     * @private
     */
    reposition_: function() {
      const clientRect = this.anchorNode_.getBoundingClientRect();

      // Center bubble in collapsed mode (if it doesn't take up all the room we
      // have).
      let offset = 0;
      if (!this.expanded) {
        offset = (clientRect.width - parseInt(this.style.width, 10)) / 2;
      }
      this.style.left = this.style.right = clientRect.left + offset + 'px';

      const top = Math.max(0, clientRect.top - 4);
      this.style.top = this.expanded ?
          (top - this.offsetHeight + this.unexpandedHeight) + 'px' :
          top + 'px';
    },

    /**
     * Resizes the bubble and then repositions it.
     * @private
     */
    resizeAndReposition: function() {
      const clientRect = this.anchorNode_.getBoundingClientRect();
      let width = clientRect.width;

      const bubbleTitle = this.querySelector('.expandable-bubble-title');
      const closeElement = this.querySelector('.expandable-bubble-close');
      const closeWidth = this.expanded ? closeElement.clientWidth : 0;
      const margin = 15;

      // Suppress the width style so we can get it to calculate its width.
      // We'll set the right width again when we are done.
      bubbleTitle.style.width = '';

      if (this.expanded) {
        // We always show the full title but never show less width than 250
        // pixels.
        const expandedWidth =
            Math.max(250, bubbleTitle.scrollWidth + closeWidth + margin);
        this.style.marginLeft = (width - expandedWidth) + 'px';
        width = expandedWidth;
      } else {
        const newWidth = Math.min(bubbleTitle.scrollWidth + margin, width);
        // If we've maxed out in width then apply the mask.
        this.masked = newWidth == width;
        width = newWidth;
        this.style.marginLeft = '0';
      }

      // Width is determined by the width of the title (when not expanded) but
      // capped to the width of the anchor node.
      this.style.width = width + 'px';
      bubbleTitle.style.width = Math.max(0, width - margin - closeWidth) + 'px';

      // Also reposition the bubble -- dimensions have potentially changed.
      this.reposition_();
    },

    /**
     * Expand the bubble (bringing the full content into view).
     * @private
     */
    expandBubble_: function() {
      this.querySelector('.expandable-bubble-main').hidden = false;
      this.querySelector('.expandable-bubble-close').hidden = false;
      this.expanded = true;
      this.resizeAndReposition();
    },

    /**
     * Collapse the bubble, hiding the main content and the close button.
     * This is automatically called when the window is resized.
     * @private
     */
    collapseBubble_: function() {
      this.querySelector('.expandable-bubble-main').hidden = true;
      this.querySelector('.expandable-bubble-close').hidden = true;
      this.expanded = false;
      this.resizeAndReposition();
    },

    /**
     * The onclick handler for the notification (expands the bubble).
     * @param {Event} e The event.
     * @private
     * @suppress {checkTypes}
     * TODO(vitalyp): remove suppression when the extern
     * Node.prototype.contains() will be fixed.
     */
    onNotificationClick_: function(e) {
      if (!this.contains(/** @type {!Node} */ (e.target))) {
        return;
      }

      if (!this.expanded) {
        // Save the height of the unexpanded bubble, so we can make sure to
        // position it correctly (arrow points in the same location) after
        // we expand it.
        this.unexpandedHeight = this.offsetHeight;
      }

      this.expandBubble_();
    },

    /**
     * Shows the bubble. The bubble will start collapsed and expand when
     * clicked.
     */
    show: function() {
      if (!this.hidden) {
        return;
      }

      document.body.appendChild(this);
      this.hidden = false;
      this.resizeAndReposition();

      this.eventTracker_ = new EventTracker;
      this.eventTracker_.add(
          window, 'load', this.resizeAndReposition.bind(this));
      this.eventTracker_.add(
          window, 'resize', this.resizeAndReposition.bind(this));
      this.eventTracker_.add(this, 'click', this.onNotificationClick_);

      const doc = this.ownerDocument;
      this.eventTracker_.add(assert(doc), 'keydown', this, true);
      this.eventTracker_.add(assert(doc), 'mousedown', this, true);
    },

    /**
     * Hides the bubble from view.
     */
    hide: function() {
      this.hidden = true;
      this.bubbleSuppressed = false;
      this.eventTracker_.removeAll();
      this.parentNode.removeChild(this);
    },

    /**
     * Handles keydown and mousedown events, dismissing the bubble if
     * necessary.
     * @param {Event} e The event.
     * @private
     * @suppress {checkTypes}
     * TODO(vitalyp): remove suppression when the extern
     * Node.prototype.contains() will be fixed.
     */
    handleEvent: function(e) {
      let handled = false;
      switch (e.type) {
        case 'keydown':
          if (e.keyCode == 27) {  // Esc.
            if (this.expanded) {
              this.collapseBubble_();
              handled = true;
            }
          }
          break;

        case 'mousedown':
          if (e.target == this.querySelector('.expandable-bubble-close')) {
            this.handleCloseEvent_();
            handled = true;
          } else if (!this.contains(/** @type {!Node} */ (e.target))) {
            if (this.expanded) {
              this.collapseBubble_();
              handled = true;
            }
          }
          break;
      }

      if (handled) {
        // The bubble emulates a focus grab when expanded, so when we've
        // collapsed/hide the bubble we consider the event handles and don't
        // need to propagate it further.
        e.stopPropagation();
        e.preventDefault();
      }
    },
  };

  /**
   * Whether the bubble is expanded or not.
   */
  cr.defineProperty(ExpandableBubble, 'expanded', cr.PropertyKind.BOOL_ATTR);

  /**
   * Whether the title needs to be masked out towards the right, which indicates
   * to the user that part of the text is clipped. This is only used when the
   * bubble is collapsed and the title doesn't fit because it is maxed out in
   * width within the anchored node.
   */
  cr.defineProperty(ExpandableBubble, 'masked', cr.PropertyKind.BOOL_ATTR);

  return {ExpandableBubble: ExpandableBubble};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('cr.ui', function() {
  /**
   * Constructor for FocusManager singleton. Checks focus of elements to ensure
   * that elements in "background" pages (i.e., those in a dialog that is not
   * the topmost overlay) do not receive focus.
   * @constructor
   */
  function FocusManager() {}

  FocusManager.prototype = {
    /**
     * Whether focus is being transferred backward or forward through the DOM.
     * @type {boolean}
     * @private
     */
    focusDirBackwards_: false,

    /**
     * Determines whether the |child| is a descendant of |parent| in the page's
     * DOM.
     * @param {Node} parent The parent element to test.
     * @param {Node} child The child element to test.
     * @return {boolean} True if |child| is a descendant of |parent|.
     * @private
     */
    isDescendantOf_: function(parent, child) {
      return !!parent && !(parent === child) && parent.contains(child);
    },

    /**
     * Returns the parent element containing all elements which should be
     * allowed to receive focus.
     * @return {Element} The element containing focusable elements.
     */
    getFocusParent: function() {
      return document.body;
    },

    /**
     * Returns the elements on the page capable of receiving focus.
     * @return {Array<Element>} The focusable elements.
     */
    getFocusableElements_: function() {
      const focusableDiv = this.getFocusParent();

      // Create a TreeWalker object to traverse the DOM from |focusableDiv|.
      const treeWalker = document.createTreeWalker(
          focusableDiv, NodeFilter.SHOW_ELEMENT,
          /** @type {NodeFilter} */
          ({
            acceptNode: function(node) {
              const style = window.getComputedStyle(node);
              // Reject all hidden nodes. FILTER_REJECT also rejects these
              // nodes' children, so non-hidden elements that are descendants of
              // hidden <div>s will correctly be rejected.
              if (node.hidden || style.display == 'none' ||
                  style.visibility == 'hidden') {
                return NodeFilter.FILTER_REJECT;
              }

              // Skip nodes that cannot receive focus. FILTER_SKIP does not
              // cause this node's children also to be skipped.
              if (node.disabled || node.tabIndex < 0) {
                return NodeFilter.FILTER_SKIP;
              }

              // Accept nodes that are non-hidden and focusable.
              return NodeFilter.FILTER_ACCEPT;
            }
          }),
          false);

      const focusable = [];
      while (treeWalker.nextNode()) {
        focusable.push(treeWalker.currentNode);
      }

      return focusable;
    },

    /**
     * Dispatches an 'elementFocused' event to notify an element that it has
     * received focus. When focus wraps around within the a page, only the
     * element that has focus after the wrapping receives an 'elementFocused'
     * event. This differs from the native 'focus' event which is received by
     * an element outside the page first, followed by a 'focus' on an element
     * within the page after the FocusManager has intervened.
     * @param {EventTarget} element The element that has received focus.
     * @private
     */
    dispatchFocusEvent_: function(element) {
      cr.dispatchSimpleEvent(element, 'elementFocused', true, false);
    },

    /**
     * Attempts to focus the appropriate element in the current dialog.
     * @private
     */
    setFocus_: function() {
      const element = this.selectFocusableElement_();
      if (element) {
        element.focus();
        this.dispatchFocusEvent_(element);
      }
    },

    /**
     * Selects first appropriate focusable element according to the
     * current focus direction and element type.  If it is a radio button,
     * checked one is selected from the group.
     * @private
     */
    selectFocusableElement_: function() {
      // If |this.focusDirBackwards_| is true, the user has pressed "Shift+Tab"
      // and has caused the focus to be transferred backward, outside of the
      // current dialog. In this case, loop around and try to focus the last
      // element of the dialog; otherwise, try to focus the first element of the
      // dialog.
      const focusableElements = this.getFocusableElements_();
      let element = this.focusDirBackwards_ ? focusableElements.pop() :
                                              focusableElements.shift();
      if (!element) {
        return null;
      }
      if (element.tagName != 'INPUT' || element.type != 'radio' ||
          element.name == '') {
        return element;
      }
      if (!element.checked) {
        for (let i = 0; i < focusableElements.length; i++) {
          const e = focusableElements[i];
          if (e && e.tagName == 'INPUT' && e.type == 'radio' &&
              e.name == element.name && e.checked) {
            element = e;
            break;
          }
        }
      }
      return element;
    },

    /**
     * Handler for focus events on the page.
     * @param {Event} event The focus event.
     * @private
     */
    onDocumentFocus_: function(event) {
      // If the element being focused is a descendant of the currently visible
      // page, focus is valid.
      const targetNode = /** @type {Node} */ (event.target);
      if (this.isDescendantOf_(this.getFocusParent(), targetNode)) {
        this.dispatchFocusEvent_(event.target);
        return;
      }

      // Focus event handlers for descendant elements might dispatch another
      // focus event.
      event.stopPropagation();

      // The target of the focus event is not in the topmost visible page and
      // should not be focused.
      event.target.blur();

      // Attempt to wrap around focus within the current page.
      this.setFocus_();
    },

    /**
     * Handler for keydown events on the page.
     * @param {Event} event The keydown event.
     * @private
     */
    onDocumentKeyDown_: function(event) {
      /** @const */ const tabKeyCode = 9;

      if (event.keyCode == tabKeyCode) {
        // If the "Shift" key is held, focus is being transferred backward in
        // the page.
        this.focusDirBackwards_ = event.shiftKey ? true : false;
      }
    },

    /**
     * Initializes the FocusManager by listening for events in the document.
     */
    initialize: function() {
      document.addEventListener(
          'focus', this.onDocumentFocus_.bind(this), true);
      document.addEventListener(
          'keydown', this.onDocumentKeyDown_.bind(this), true);
    },
  };

  return {
    FocusManager: FocusManager,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('cr.ui', function() {
  /** @const */ const Command = cr.ui.Command;

  /**
   * Creates a new menu item element.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {HTMLElement}
   * @implements {EventListener}
   */
  const MenuItem = cr.ui.define('cr-menu-item');

  /**
   * Creates a new menu separator element.
   * @return {cr.ui.MenuItem} The new separator element.
   */
  MenuItem.createSeparator = function() {
    const el = cr.doc.createElement('hr');
    MenuItem.decorate(el);
    return el;
  };

  MenuItem.prototype = {
    __proto__: HTMLElement.prototype,

    /**
     * Initializes the menu item.
     */
    decorate: function() {
      let commandId;
      if ((commandId = this.getAttribute('command'))) {
        this.command = commandId;
      }

      this.addEventListener('mouseup', this.handleMouseUp_);

      // Adding the 'custom-appearance' class prevents widgets.css from changing
      // the appearance of this element.
      this.classList.add('custom-appearance');

      // Enable Text to Speech on the menu. Additionaly, ID has to be set, since
      // it is used in element's aria-activedescendant attribute.
      if (!this.isSeparator()) {
        this.setAttribute('role', 'menuitem');
      }

      let iconUrl;
      if ((iconUrl = this.getAttribute('icon'))) {
        this.iconUrl = iconUrl;
      }
    },

    /**
     * The command associated with this menu item. If this is set to a string
     * of the form "#element-id" then the element is looked up in the document
     * of the command.
     * @type {cr.ui.Command}
     */
    command_: null,
    get command() {
      return this.command_;
    },
    set command(command) {
      if (this.command_) {
        this.command_.removeEventListener('labelChange', this);
        this.command_.removeEventListener('disabledChange', this);
        this.command_.removeEventListener('hiddenChange', this);
        this.command_.removeEventListener('checkedChange', this);
      }

      if (typeof command == 'string' && command[0] == '#') {
        command = assert(this.ownerDocument.getElementById(command.slice(1)));
        cr.ui.decorate(command, Command);
      }

      this.command_ = command;
      if (command) {
        if (command.id) {
          this.setAttribute('command', '#' + command.id);
        }

        if (typeof command.label === 'string') {
          this.label = command.label;
        }
        this.disabled = command.disabled;
        this.hidden = command.hidden;
        this.checked = command.checked;

        this.command_.addEventListener('labelChange', this);
        this.command_.addEventListener('disabledChange', this);
        this.command_.addEventListener('hiddenChange', this);
        this.command_.addEventListener('checkedChange', this);
      }

      this.updateShortcut_();
    },

    /**
     * The text label.
     * @type {string}
     */
    get label() {
      return this.textContent;
    },
    set label(label) {
      this.textContent = label;
    },

    /**
     * Menu icon.
     * @type {string}
     */
    get iconUrl() {
      return this.style.backgroundImage;
    },
    set iconUrl(url) {
      this.style.backgroundImage = 'url(' + url + ')';
    },

    /**
     * @return {boolean} Whether the menu item is a separator.
     */
    isSeparator: function() {
      return this.tagName == 'HR';
    },

    /**
     * Updates shortcut text according to associated command. If command has
     * multiple shortcuts, only first one is displayed.
     */
    updateShortcut_: function() {
      this.removeAttribute('shortcutText');

      if (!this.command_ || !this.command_.shortcut ||
          this.command_.hideShortcutText) {
        return;
      }

      const shortcuts = this.command_.shortcut.split(/\s+/);

      if (shortcuts.length == 0) {
        return;
      }

      const shortcut = shortcuts[0];
      const mods = {};
      let ident = '';
      shortcut.split('|').forEach(function(part) {
        const partUc = part.toUpperCase();
        switch (partUc) {
          case 'CTRL':
          case 'ALT':
          case 'SHIFT':
          case 'META':
            mods[partUc] = true;
            break;
          default:
            console.assert(!ident, 'Shortcut has two non-modifier keys');
            ident = part;
        }
      });

      let shortcutText = '';

      ['CTRL', 'ALT', 'SHIFT', 'META'].forEach(function(mod) {
        if (mods[mod]) {
          shortcutText += loadTimeData.getString('SHORTCUT_' + mod) + '+';
        }
      });

      if (ident == ' ') {
        ident = 'Space';
      }

      if (ident.length != 1) {
        shortcutText +=
            loadTimeData.getString('SHORTCUT_' + ident.toUpperCase());
      } else {
        shortcutText += ident.toUpperCase();
      }

      this.setAttribute('shortcutText', shortcutText);
    },

    /**
     * Handles mouseup events. This dispatches an activate event; if there is an
     * associated command, that command is executed.
     * @param {!Event} e The mouseup event object.
     * @private
     */
    handleMouseUp_: function(e) {
      e = /** @type {!MouseEvent} */ (e);
      // Only dispatch an activate event for left or middle click.
      if (e.button > 1) {
        return;
      }

      if (!this.disabled && !this.isSeparator() && this.selected) {
        // Store |contextElement| since it'll be removed by {Menu} on handling
        // 'activate' event.
        const contextElement =
            /** @type {{contextElement: Element}} */ (this.parentNode)
                .contextElement;
        const activationEvent = cr.doc.createEvent('Event');
        activationEvent.initEvent('activate', true, true);
        activationEvent.originalEvent = e;
        // Dispatch command event followed by executing the command object.
        if (this.dispatchEvent(activationEvent)) {
          const command = this.command;
          if (command) {
            command.execute(contextElement);
            cr.ui.swallowDoubleClick(e);
          }
        }
      }
    },

    /**
     * Updates command according to the node on which this menu was invoked.
     * @param {Node=} opt_node Node on which menu was opened.
     */
    updateCommand: function(opt_node) {
      if (this.command_) {
        this.command_.canExecuteChange(opt_node);
      }
    },

    /**
     * Handles changes to the associated command.
     * @param {Event} e The event object.
     */
    handleEvent: function(e) {
      switch (e.type) {
        case 'disabledChange':
          this.disabled = this.command.disabled;
          break;
        case 'hiddenChange':
          this.hidden = this.command.hidden;
          break;
        case 'labelChange':
          this.label = this.command.label;
          break;
        case 'checkedChange':
          this.checked = this.command.checked;
          break;
      }
    }
  };

  /**
   * Whether the menu item is disabled or not.
   */
  cr.defineProperty(MenuItem, 'disabled', cr.PropertyKind.BOOL_ATTR);

  /**
   * Whether the menu item is hidden or not.
   */
  cr.defineProperty(MenuItem, 'hidden', cr.PropertyKind.BOOL_ATTR);

  /**
   * Whether the menu item is selected or not.
   */
  cr.defineProperty(MenuItem, 'selected', cr.PropertyKind.BOOL_ATTR);

  /**
   * Whether the menu item is checked or not.
   */
  cr.defineProperty(MenuItem, 'checked', cr.PropertyKind.BOOL_ATTR);

  /**
   * Whether the menu item is checkable or not.
   */
  cr.defineProperty(MenuItem, 'checkable', cr.PropertyKind.BOOL_ATTR);

  // Export
  return {MenuItem: MenuItem};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('cr.ui', function() {
  /** @const */ const MenuItem = cr.ui.MenuItem;

  /**
   * Creates a new menu element. Menu dispatches all commands on the element it
   * was shown for.
   *
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {HTMLElement}
   */
  const Menu = cr.ui.define('cr-menu');

  Menu.prototype = {
    __proto__: HTMLElement.prototype,

    selectedIndex_: -1,

    /**
     * Element for which menu is being shown.
     */
    contextElement: null,

    /**
     * Initializes the menu element.
     */
    decorate: function() {
      this.addEventListener('mouseover', this.handleMouseOver_);
      this.addEventListener('mouseout', this.handleMouseOut_);
      this.addEventListener('mouseup', this.handleMouseUp_, true);

      this.classList.add('decorated');
      this.setAttribute('role', 'menu');
      this.hidden = true;  // Hide the menu by default.

      // Decorate the children as menu items.
      const menuItems = this.menuItems;
      for (let i = 0, menuItem; menuItem = menuItems[i]; i++) {
        cr.ui.decorate(menuItem, MenuItem);
      }
    },

    /**
     * Adds menu item at the end of the list.
     * @param {Object} item Menu item properties.
     * @return {cr.ui.MenuItem} The created menu item.
     */
    addMenuItem: function(item) {
      const menuItem = this.ownerDocument.createElement('cr-menu-item');
      this.appendChild(menuItem);

      cr.ui.decorate(menuItem, MenuItem);

      if (item.label) {
        menuItem.label = item.label;
      }

      if (item.iconUrl) {
        menuItem.iconUrl = item.iconUrl;
      }

      return menuItem;
    },

    /**
     * Adds separator at the end of the list.
     */
    addSeparator: function() {
      const separator = this.ownerDocument.createElement('hr');
      cr.ui.decorate(separator, MenuItem);
      this.appendChild(separator);
    },

    /**
     * Clears menu.
     */
    clear: function() {
      this.selectedItem = null;
      this.textContent = '';
    },

    /**
     * Walks up the ancestors of |node| until a menu item belonging to this menu
     * is found.
     * @param {Node} node The node to start searching from.
     * @return {cr.ui.MenuItem} The found menu item or null.
     * @private
     */
    findMenuItem_: function(node) {
      while (node && node.parentNode != this && !(node instanceof MenuItem)) {
        node = node.parentNode;
      }
      return node ? assertInstanceof(node, MenuItem) : null;
    },

    /**
     * Handles mouseover events and selects the hovered item.
     * @param {Event} e The mouseover event.
     * @private
     */
    handleMouseOver_: function(e) {
      const overItem = this.findMenuItem_(/** @type {Element} */ (e.target));
      this.selectedItem = overItem;
    },

    /**
     * Handles mouseout events and deselects any selected item.
     * @param {Event} e The mouseout event.
     * @private
     */
    handleMouseOut_: function(e) {
      this.selectedItem = null;
    },

    /**
     * If there's a mouseup that happens quickly in about the same position,
     * stop it from propagating to items. This is to prevent accidentally
     * selecting a menu item that's created under the mouse cursor.
     * @param {Event} e A mouseup event on the menu (in capturing phase).
     * @private
     */
    handleMouseUp_: function(e) {
      assert(this.contains(/** @type {Element} */ (e.target)));

      if (!this.trustEvent_(e) || Date.now() - this.shown_.time > 200) {
        return;
      }

      const pos = this.shown_.mouseDownPos;
      if (!pos ||
          Math.abs(pos.x - e.screenX) + Math.abs(pos.y - e.screenY) > 4) {
        return;
      }

      e.preventDefault();
      e.stopPropagation();
    },

    /**
     * @param {!Event} e
     * @return {boolean} Whether |e| can be trusted.
     * @private
     * @suppress {checkTypes}
     */
    trustEvent_: function(e) {
      return e.isTrusted || e.isTrustedForTesting;
    },

    get menuItems() {
      return this.querySelectorAll(this.menuItemSelector || '*');
    },

    /**
     * The selected menu item or null if none.
     * @type {cr.ui.MenuItem}
     */
    get selectedItem() {
      return this.menuItems[this.selectedIndex];
    },
    set selectedItem(item) {
      const index = Array.prototype.indexOf.call(this.menuItems, item);
      this.selectedIndex = index;
    },

    /**
     * Focuses the selected item. If selectedIndex is invalid, set it to 0
     * first.
     */
    focusSelectedItem: function() {
      if (this.selectedIndex < 0 ||
          this.selectedIndex > this.menuItems.length) {
        this.selectedIndex = 0;
      }

      if (this.selectedItem) {
        this.selectedItem.focus();
        this.setAttribute('aria-activedescendant', this.selectedItem.id);
      }
    },

    /**
     * Menu length
     */
    get length() {
      return this.menuItems.length;
    },

    /**
     * Returns whether the given menu item is visible.
     * @param {!cr.ui.MenuItem} menuItem
     * @return {boolean}
     * @private
     */
    isItemVisible_: function(menuItem) {
      if (menuItem.hidden) {
        return false;
      }
      if (!!menuItem.offsetParent) {
        return true;
      }
      // A "position: fixed" element won't have an offsetParent, so we have to
      // do the full style computation.
      return window.getComputedStyle(menuItem).display != 'none';
    },

    /**
     * Returns whether the menu has any visible items.
     * @return {boolean} True if the menu has visible item. Otherwise, false.
     */
    hasVisibleItems: function() {
      // Inspect items in reverse order to determine if the separator above each
      // set of items is required.
      for (const menuItem of this.menuItems) {
        if (this.isItemVisible_(menuItem)) {
          return true;
        }
      }
      return false;
    },

    /**
     * This is the function that handles keyboard navigation. This is usually
     * called by the element responsible for managing the menu.
     * @param {Event} e The keydown event object.
     * @return {boolean} Whether the event was handled be the menu.
     */
    handleKeyDown: function(e) {
      let item = this.selectedItem;

      const self = this;
      const selectNextAvailable = function(m) {
        const menuItems = self.menuItems;
        const len = menuItems.length;
        if (!len) {
          // Edge case when there are no items.
          return;
        }
        let i = self.selectedIndex;
        if (i == -1 && m == -1) {
          // Edge case when needed to go the last item first.
          i = 0;
        }

        // "i" may be negative(-1), so modulus operation and cycle below
        // wouldn't work as assumed. This trick makes startPosition positive
        // without altering it's modulo.
        const startPosition = (i + len) % len;

        while (true) {
          i = (i + m + len) % len;

          // Check not to enter into infinite loop if all items are hidden or
          // disabled.
          if (i == startPosition) {
            break;
          }

          item = menuItems[i];
          if (item && !item.isSeparator() && !item.disabled &&
              this.isItemVisible_(item)) {
            break;
          }
        }
        if (item && !item.disabled) {
          self.selectedIndex = i;
        }
      }.bind(this);

      switch (e.key) {
        case 'ArrowDown':
          selectNextAvailable(1);
          this.focusSelectedItem();
          return true;
        case 'ArrowUp':
          selectNextAvailable(-1);
          this.focusSelectedItem();
          return true;
        case 'Enter':
        case ' ':
          if (item) {
            // Store |contextElement| since it'll be removed when handling the
            // 'activate' event.
            const contextElement = this.contextElement;
            const activationEvent = cr.doc.createEvent('Event');
            activationEvent.initEvent('activate', true, true);
            activationEvent.originalEvent = e;
            if (item.dispatchEvent(activationEvent)) {
              if (item.command) {
                item.command.execute(contextElement);
              }
            }
          }
          return true;
      }

      return false;
    },

    hide: function() {
      this.hidden = true;
      delete this.shown_;
    },

    /** @param {{x: number, y: number}=} opt_mouseDownPos */
    show: function(opt_mouseDownPos) {
      this.shown_ = {mouseDownPos: opt_mouseDownPos, time: Date.now()};
      this.hidden = false;
    },

    /**
     * Updates menu items command according to context.
     * @param {Node=} node Node for which to actuate commands state.
     */
    updateCommands: function(node) {
      const menuItems = this.menuItems;

      for (const menuItem of menuItems) {
        if (!menuItem.isSeparator()) {
          menuItem.updateCommand(node);
        }
      }

      let separatorRequired = false;
      let lastSeparator = null;
      // Hide any separators without a visible item between them and the next
      // separator or the end of the menu.
      for (const menuItem of menuItems) {
        if (menuItem.isSeparator()) {
          if (separatorRequired) {
            lastSeparator = menuItem;
          }
          menuItem.hidden = true;
          separatorRequired = false;
          continue;
        }
        if (this.isItemVisible_(menuItem)) {
          if (lastSeparator) {
            lastSeparator.hidden = false;
          }
          separatorRequired = true;
        }
      }
    }
  };

  function selectedIndexChanged(selectedIndex, oldSelectedIndex) {
    const oldSelectedItem = this.menuItems[oldSelectedIndex];
    if (oldSelectedItem) {
      oldSelectedItem.selected = false;
      oldSelectedItem.blur();
    }
    const item = this.selectedItem;
    if (item) {
      item.selected = true;
    }
  }

  /**
   * The selected menu item.
   * type {number}
   */
  cr.defineProperty(
      Menu, 'selectedIndex', cr.PropertyKind.JS, selectedIndexChanged);

  /**
   * Selector for children which are menu items.
   */
  cr.defineProperty(Menu, 'menuItemSelector', cr.PropertyKind.ATTR);

  // Export
  return {Menu: Menu};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview This file provides utility functions for position popups.
 */

cr.exportPath('cr.ui');

/**
 * Type def for rects as returned by getBoundingClientRect.
 * @typedef {{left: number, top: number, width: number, height: number,
 *            right: number, bottom: number}}
 */
cr.ui.Rect;

/**
 * Enum for defining how to anchor a popup to an anchor element.
 * @enum {number}
 */
cr.ui.AnchorType = {
  /**
   * The popup's right edge is aligned with the left edge of the anchor.
   * The popup's top edge is aligned with the top edge of the anchor.
   */
  BEFORE: 1,  // p: right, a: left, p: top, a: top

  /**
   * The popop's left edge is aligned with the right edge of the anchor.
   * The popup's top edge is aligned with the top edge of the anchor.
   */
  AFTER: 2,  // p: left a: right, p: top, a: top

  /**
   * The popop's bottom edge is aligned with the top edge of the anchor.
   * The popup's left edge is aligned with the left edge of the anchor.
   */
  ABOVE: 3,  // p: bottom, a: top, p: left, a: left

  /**
   * The popop's top edge is aligned with the bottom edge of the anchor.
   * The popup's left edge is aligned with the left edge of the anchor.
   */
  BELOW: 4  // p: top, a: bottom, p: left, a: left
};

cr.define('cr.ui', function() {
  /** @const */
  const AnchorType = cr.ui.AnchorType;

  /**
   * Helper function for positionPopupAroundElement and positionPopupAroundRect.
   * @param {!cr.ui.Rect} anchorRect The rect for the anchor.
   * @param {!HTMLElement} popupElement The element used for the popup.
   * @param {cr.ui.AnchorType} type The type of anchoring to do.
   * @param {boolean=} opt_invertLeftRight Whether to invert the right/left
   *     alignment.
   */
  function positionPopupAroundRect(
      anchorRect, popupElement, type, opt_invertLeftRight) {
    const popupRect = popupElement.getBoundingClientRect();
    let availRect;
    const ownerDoc = popupElement.ownerDocument;
    const cs = ownerDoc.defaultView.getComputedStyle(popupElement);
    const docElement = ownerDoc.documentElement;

    if (cs.position == 'fixed') {
      // For 'fixed' positioned popups, the available rectangle should be based
      // on the viewport rather than the document.
      availRect = {
        height: docElement.clientHeight,
        width: docElement.clientWidth,
        top: 0,
        bottom: docElement.clientHeight,
        left: 0,
        right: docElement.clientWidth
      };
    } else {
      availRect = popupElement.offsetParent.getBoundingClientRect();
    }

    if (cs.direction == 'rtl') {
      opt_invertLeftRight = !opt_invertLeftRight;
    }

    // Flip BEFORE, AFTER based on alignment.
    if (opt_invertLeftRight) {
      if (type == AnchorType.BEFORE) {
        type = AnchorType.AFTER;
      } else if (type == AnchorType.AFTER) {
        type = AnchorType.BEFORE;
      }
    }

    // Flip type based on available size
    switch (type) {
      case AnchorType.BELOW:
        if (anchorRect.bottom + popupRect.height > availRect.height &&
            popupRect.height <= anchorRect.top) {
          type = AnchorType.ABOVE;
        }
        break;
      case AnchorType.ABOVE:
        if (popupRect.height > anchorRect.top &&
            anchorRect.bottom + popupRect.height <= availRect.height) {
          type = AnchorType.BELOW;
        }
        break;
      case AnchorType.AFTER:
        if (anchorRect.right + popupRect.width > availRect.width &&
            popupRect.width <= anchorRect.left) {
          type = AnchorType.BEFORE;
        }
        break;
      case AnchorType.BEFORE:
        if (popupRect.width > anchorRect.left &&
            anchorRect.right + popupRect.width <= availRect.width) {
          type = AnchorType.AFTER;
        }
        break;
    }
    // flipping done

    const style = popupElement.style;
    // Reset all directions.
    style.left = style.right = style.top = style.bottom = 'auto';

    // Primary direction
    switch (type) {
      case AnchorType.BELOW:
        if (anchorRect.bottom + popupRect.height <= availRect.height) {
          style.top = anchorRect.bottom + 'px';
        } else {
          style.bottom = '0';
        }
        break;
      case AnchorType.ABOVE:
        if (availRect.height - anchorRect.top >= 0) {
          style.bottom = availRect.height - anchorRect.top + 'px';
        } else {
          style.top = '0';
        }
        break;
      case AnchorType.AFTER:
        if (anchorRect.right + popupRect.width <= availRect.width) {
          style.left = anchorRect.right + 'px';
        } else {
          style.right = '0';
        }
        break;
      case AnchorType.BEFORE:
        if (availRect.width - anchorRect.left >= 0) {
          style.right = availRect.width - anchorRect.left + 'px';
        } else {
          style.left = '0';
        }
        break;
    }

    // Secondary direction
    switch (type) {
      case AnchorType.BELOW:
      case AnchorType.ABOVE:
        if (opt_invertLeftRight) {
          // align right edges
          if (anchorRect.right - popupRect.width >= 0) {
            style.right = availRect.width - anchorRect.right + 'px';

            // align left edges
          } else if (anchorRect.left + popupRect.width <= availRect.width) {
            style.left = anchorRect.left + 'px';

            // not enough room on either side
          } else {
            style.right = '0';
          }
        } else {
          // align left edges
          if (anchorRect.left + popupRect.width <= availRect.width) {
            style.left = anchorRect.left + 'px';

            // align right edges
          } else if (anchorRect.right - popupRect.width >= 0) {
            style.right = availRect.width - anchorRect.right + 'px';

            // not enough room on either side
          } else {
            style.left = '0';
          }
        }
        break;

      case AnchorType.AFTER:
      case AnchorType.BEFORE:
        // align top edges
        if (anchorRect.top + popupRect.height <= availRect.height) {
          style.top = anchorRect.top + 'px';

          // align bottom edges
        } else if (anchorRect.bottom - popupRect.height >= 0) {
          style.bottom = availRect.height - anchorRect.bottom + 'px';

          // not enough room on either side
        } else {
          style.top = '0';
        }
        break;
    }
  }

  /**
   * Positions a popup element relative to an anchor element. The popup element
   * should have position set to absolute and it should be a child of the body
   * element.
   * @param {!HTMLElement} anchorElement The element that the popup is anchored
   *     to.
   * @param {!HTMLElement} popupElement The popup element we are positioning.
   * @param {cr.ui.AnchorType} type The type of anchoring we want.
   * @param {boolean=} opt_invertLeftRight Whether to invert the right/left
   *     alignment.
   */
  function positionPopupAroundElement(
      anchorElement, popupElement, type, opt_invertLeftRight) {
    const anchorRect = anchorElement.getBoundingClientRect();
    positionPopupAroundRect(
        anchorRect, popupElement, type, !!opt_invertLeftRight);
  }

  /**
   * Positions a popup around a point.
   * @param {number} x The client x position.
   * @param {number} y The client y position.
   * @param {!HTMLElement} popupElement The popup element we are positioning.
   * @param {cr.ui.AnchorType=} opt_anchorType The type of anchoring we want.
   */
  function positionPopupAtPoint(x, y, popupElement, opt_anchorType) {
    const rect = {left: x, top: y, width: 0, height: 0, right: x, bottom: y};

    const anchorType = opt_anchorType || AnchorType.BELOW;
    positionPopupAroundRect(rect, popupElement, anchorType);
  }

  // Export
  return {
    positionPopupAroundElement: positionPopupAroundElement,
    positionPopupAtPoint: positionPopupAtPoint
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Assertion support.
 */

/**
 * Verify |condition| is truthy and return |condition| if so.
 * @template T
 * @param {T} condition A condition to check for truthiness.  Note that this
 *     may be used to test whether a value is defined or not, and we don't want
 *     to force a cast to Boolean.
 * @param {string=} opt_message A message to show on failure.
 * @return {T} A non-null |condition|.
 */
function assert(condition, opt_message) {
  if (!condition) {
    let message = 'Assertion failed';
    if (opt_message) {
      message = message + ': ' + opt_message;
    }
    const error = new Error(message);
    const global = function() {
      /** @type {boolean} */
      this.traceAssertionsForTesting;
      return this;
    }();
    if (global.traceAssertionsForTesting) {
      console.warn(error.stack);
    }
    throw error;
  }
  return condition;
}

/**
 * Call this from places in the code that should never be reached.
 *
 * For example, handling all the values of enum with a switch() like this:
 *
 *   function getValueFromEnum(enum) {
 *     switch (enum) {
 *       case ENUM_FIRST_OF_TWO:
 *         return first
 *       case ENUM_LAST_OF_TWO:
 *         return last;
 *     }
 *     assertNotReached();
 *     return document;
 *   }
 *
 * This code should only be hit in the case of serious programmer error or
 * unexpected input.
 *
 * @param {string=} opt_message A message to show when this is hit.
 */
function assertNotReached(opt_message) {
  assert(false, opt_message || 'Unreachable code hit');
}

/**
 * @param {*} value The value to check.
 * @param {function(new: T, ...)} type A user-defined constructor.
 * @param {string=} opt_message A message to show when this is hit.
 * @return {T}
 * @template T
 */
function assertInstanceof(value, type, opt_message) {
  // We don't use assert immediately here so that we avoid constructing an error
  // message if we don't have to.
  if (!(value instanceof type)) {
    assertNotReached(
        opt_message ||
        'Value ' + value + ' is not a[n] ' + (type.name || typeof type));
  }
  return value;
}


cr.exportPath('cr.ui');

/**
 * Enum for type of hide. Delayed is used when called by clicking on a
 * checkable menu item.
 * @enum {number}
 */
cr.ui.HideType = {
  INSTANT: 0,
  DELAYED: 1
};

cr.define('cr.ui', function() {
  /** @const */
  const Menu = cr.ui.Menu;

  /** @const */
  const HideType = cr.ui.HideType;

  /** @const */
  const positionPopupAroundElement = cr.ui.positionPopupAroundElement;

  /**
   * Creates a new menu button element.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {HTMLButtonElement}
   * @implements {EventListener}
   */
  const MenuButton = cr.ui.define('button');

  MenuButton.prototype = {
    __proto__: HTMLButtonElement.prototype,

    /**
     * Initializes the menu button.
     */
    decorate: function() {
      // Listen to the touch events on the document so that we can handle it
      // before cancelled by other UI components.
      this.ownerDocument.addEventListener('touchstart', this);
      this.addEventListener('mousedown', this);
      this.addEventListener('keydown', this);
      this.addEventListener('dblclick', this);
      this.addEventListener('blur', this);

      // Adding the 'custom-appearance' class prevents widgets.css from changing
      // the appearance of this element.
      this.classList.add('custom-appearance');
      this.classList.add('menu-button');  // For styles in menu_button.css.

      let menu;
      if ((menu = this.getAttribute('menu'))) {
        this.menu = menu;
      }

      // An event tracker for events we only connect to while the menu is
      // displayed.
      this.showingEvents_ = new EventTracker();

      this.anchorType = cr.ui.AnchorType.BELOW;
      this.invertLeftRight = false;
    },

    /**
     * The menu associated with the menu button.
     * @type {cr.ui.Menu}
     */
    get menu() {
      return this.menu_;
    },
    set menu(menu) {
      if (typeof menu == 'string' && menu[0] == '#') {
        menu = assert(this.ownerDocument.getElementById(menu.slice(1)));
        cr.ui.decorate(menu, Menu);
      }

      this.menu_ = menu;
      if (menu) {
        if (menu.id) {
          this.setAttribute('menu', '#' + menu.id);
        }
      }
    },

    /**
     * Whether to show the menu on press of the Up or Down arrow keys.
     */
    respondToArrowKeys: true,

    /**
     * Checks if the menu should be closed based on the target of a mouse click
     * or a touch event target.
     * @param {Event} e The event object.
     * @return {boolean}
     * @private
     */
    shouldDismissMenu_: function(e) {
      // The menu is dismissed when clicking outside the menu.
      // The button is excluded here because it should toggle show/hide the
      // menu and handled separately.
      return e.target instanceof Node && !this.contains(e.target) &&
          !this.menu.contains(e.target);
    },

    /**
     * Handles event callbacks.
     * @param {Event} e The event object.
     */
    handleEvent: function(e) {
      if (!this.menu) {
        return;
      }

      switch (e.type) {
        case 'touchstart':
          // Touch on the menu button itself is ignored to avoid that the menu
          // opened again by the mousedown event following the touch events.
          if (this.shouldDismissMenu_(e)) {
            this.hideMenuWithoutTakingFocus_();
          }
          break;
        case 'mousedown':
          if (e.currentTarget == this.ownerDocument) {
            if (this.shouldDismissMenu_(e)) {
              this.hideMenuWithoutTakingFocus_();
            } else {
              e.preventDefault();
            }
          } else {
            if (this.isMenuShown()) {
              this.hideMenuWithoutTakingFocus_();
            } else if (e.button == 0) {  // Only show the menu when using left
                                         // mouse button.
              this.showMenu(false, {x: e.screenX, y: e.screenY});

              // Prevent the button from stealing focus on mousedown.
              e.preventDefault();
            }
          }

          // Hide the focus ring on mouse click.
          this.classList.add('using-mouse');
          break;
        case 'keydown':
          this.handleKeyDown(e);
          // If the menu is visible we let it handle all the keyboard events.
          if (this.isMenuShown() && e.currentTarget == this.ownerDocument) {
            this.menu.handleKeyDown(e);
            e.preventDefault();
            e.stopPropagation();
          }

          // Show the focus ring on keypress.
          this.classList.remove('using-mouse');
          break;
        case 'focus':
          if (this.shouldDismissMenu_(e)) {
            this.hideMenu();
            // Show the focus ring on focus - if it's come from a mouse event,
            // the focus ring will be hidden in the mousedown event handler,
            // executed after this.
            this.classList.remove('using-mouse');
          }
          break;
        case 'blur':
          // No need to hide the focus ring anymore, without having focus.
          this.classList.remove('using-mouse');
          break;
        case 'activate':
          const hideDelayed =
              e.target instanceof cr.ui.MenuItem && e.target.checkable;
          const hideType = hideDelayed ? HideType.DELAYED : HideType.INSTANT;
          if (e.originalEvent instanceof MouseEvent ||
              e.originalEvent instanceof TouchEvent) {
            this.hideMenuWithoutTakingFocus_(hideType);
          } else {
            // Keyboard. Take focus to continue keyboard operation.
            this.hideMenu(hideType);
          }
          break;
        case 'scroll':
          if (!(e.target == this.menu || this.menu.contains(e.target))) {
            this.hideMenu();
          }
          break;
        case 'popstate':
        case 'resize':
          this.hideMenu();
          break;
        case 'contextmenu':
          if ((!this.menu || !this.menu.contains(e.target)) &&
              (!this.hideTimestamp_ || Date.now() - this.hideTimestamp_ > 50)) {
            this.showMenu(true, {x: e.screenX, y: e.screenY});
          }
          e.preventDefault();
          // Don't allow elements further up in the DOM to show their menus.
          e.stopPropagation();
          break;
        case 'dblclick':
          // Don't allow double click events to propagate.
          e.preventDefault();
          e.stopPropagation();
          break;
      }
    },

    /**
     * Shows the menu.
     * @param {boolean} shouldSetFocus Whether to set focus on the
     *     selected menu item.
     * @param {{x: number, y: number}=} opt_mousePos The position of the mouse
     *     when shown (in screen coordinates).
     */
    showMenu: function(shouldSetFocus, opt_mousePos) {
      this.hideMenu();

      this.menu.updateCommands(this);

      const event = new UIEvent(
          'menushow', {bubbles: true, cancelable: true, view: window});
      if (!this.dispatchEvent(event)) {
        return;
      }

      this.menu.show(opt_mousePos);

      this.setAttribute('menu-shown', '');

      // When the menu is shown we steal all keyboard events.
      const doc = this.ownerDocument;
      const win = doc.defaultView;
      this.showingEvents_.add(doc, 'keydown', this, true);
      this.showingEvents_.add(doc, 'mousedown', this, true);
      this.showingEvents_.add(doc, 'focus', this, true);
      this.showingEvents_.add(doc, 'scroll', this, true);
      this.showingEvents_.add(win, 'popstate', this);
      this.showingEvents_.add(win, 'resize', this);
      this.showingEvents_.add(this.menu, 'contextmenu', this);
      this.showingEvents_.add(this.menu, 'activate', this);
      this.positionMenu_();

      if (shouldSetFocus) {
        this.menu.focusSelectedItem();
      }
    },

    /**
     * Hides the menu. If your menu can go out of scope, make sure to call this
     * first.
     * @param {cr.ui.HideType=} opt_hideType Type of hide.
     *     default: cr.ui.HideType.INSTANT.
     */
    hideMenu: function(opt_hideType) {
      this.hideMenuInternal_(true, opt_hideType);
    },

    /**
     * Hides the menu. If your menu can go out of scope, make sure to call this
     * first.
     * @param {cr.ui.HideType=} opt_hideType Type of hide.
     *     default: cr.ui.HideType.INSTANT.
     */
    hideMenuWithoutTakingFocus_: function(opt_hideType) {
      this.hideMenuInternal_(false, opt_hideType);
    },

    /**
     * Hides the menu. If your menu can go out of scope, make sure to call this
     * first.
     * @param {boolean} shouldTakeFocus Moves the focus to the button if true.
     * @param {cr.ui.HideType=} opt_hideType Type of hide.
     *     default: cr.ui.HideType.INSTANT.
     */
    hideMenuInternal_: function(shouldTakeFocus, opt_hideType) {
      if (!this.isMenuShown()) {
        return;
      }

      this.removeAttribute('menu-shown');
      if (opt_hideType == HideType.DELAYED) {
        this.menu.classList.add('hide-delayed');
      } else {
        this.menu.classList.remove('hide-delayed');
      }
      this.menu.hide();

      this.showingEvents_.removeAll();
      if (shouldTakeFocus) {
        this.focus();
      }

      const event = new UIEvent(
          'menuhide', {bubbles: true, cancelable: false, view: window});
      this.dispatchEvent(event);

      // On windows we might hide the menu in a right mouse button up and if
      // that is the case we wait some short period before we allow the menu
      // to be shown again.
      this.hideTimestamp_ = cr.isWindows ? Date.now() : 0;
    },

    /**
     * Whether the menu is shown.
     */
    isMenuShown: function() {
      return this.hasAttribute('menu-shown');
    },

    /**
     * Positions the menu below the menu button. At this point we do not use any
     * advanced positioning logic to ensure the menu fits in the viewport.
     * @private
     */
    positionMenu_: function() {
      positionPopupAroundElement(
          this, this.menu, this.anchorType, this.invertLeftRight);
    },

    /**
     * Handles the keydown event for the menu button.
     */
    handleKeyDown: function(e) {
      switch (e.key) {
        case 'ArrowDown':
        case 'ArrowUp':
          if (!this.respondToArrowKeys) {
            break;
          }
        case 'Enter':
        case ' ':
          if (!this.isMenuShown()) {
            this.showMenu(true);
          }
          e.preventDefault();
          break;
        case 'Escape':
        case 'Tab':
          this.hideMenu();
          break;
      }
    }
  };

  // Export
  return {
    MenuButton: MenuButton,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview This implements a special button that is useful for showing a
 * context menu.
 */

cr.define('cr.ui', function() {
  /** @const */ const MenuButton = cr.ui.MenuButton;

  /**
   * Helper function for ContextMenuButton to find the first ancestor of the
   * button that has a context menu.
   * @param {!cr.ui.MenuButton} button The button to start the search from.
   * @return {HTMLElement} The found element or null if not found.
   */
  function getContextMenuTarget(button) {
    let el = button;
    do {
      el = el.parentNode;
    } while (el && !('contextMenu' in el));
    return el ? assertInstanceof(el, HTMLElement) : null;
  }

  /**
   * Creates a new menu button which is used to show the context menu for an
   * ancestor that has a {@code contextMenu} property.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {cr.ui.MenuButton}
   */
  const ContextMenuButton = cr.ui.define('button');

  ContextMenuButton.prototype = {
    __proto__: MenuButton.prototype,

    /**
     * Override to return the contextMenu for the ancestor.
     * @override
     * @type {cr.ui.Menu}
     */
    get menu() {
      const target = getContextMenuTarget(this);
      return target && target.contextMenu;
    },

    /** @override */
    decorate: function() {
      this.tabIndex = -1;
      this.addEventListener('mouseup', this);
      MenuButton.prototype.decorate.call(this);
    },

    /** @override */
    handleEvent: function(e) {
      switch (e.type) {
        case 'mousedown':
          // Menu buttons prevent focus changes.
          const target = getContextMenuTarget(this);
          if (target) {
            target.focus();
          }
          break;
        case 'mouseup':
          // Stop mouseup to prevent selection changes.
          e.stopPropagation();
          break;
      }
      MenuButton.prototype.handleEvent.call(this, e);
    },

    /**
     * Override MenuButton showMenu to allow the mousedown to be fully handled
     * before the menu is shown. This is important in case the mousedown
     * triggers command changes.
     * @param {boolean} shouldSetFocus Whether the menu should be focused after
     *     the menu is shown.
     * @param {{x: number, y: number}=} opt_mousePos The position of the mouse
     *     when shown (in screen coordinates).
     * @override
     */
    showMenu: function(shouldSetFocus, opt_mousePos) {
      const self = this;
      window.setTimeout(function() {
        MenuButton.prototype.showMenu.call(self, shouldSetFocus, opt_mousePos);
      }, 0);
    }
  };

  // Export
  return {ContextMenuButton: ContextMenuButton};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Touch Handler. Class that handles all touch events and
 * uses them to interpret higher level gestures and behaviors. TouchEvent is a
 * built in mobile safari type:
 * http://developer.apple.com/safari/library/documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html.
 * This class is intended to work with all webkit browsers, tested on Chrome and
 * iOS.
 *
 * The following types of gestures are currently supported.  See the definition
 * of TouchHandler.EventType for details.
 *
 * Single Touch:
 *      This provides simple single-touch events.  Any secondary touch is
 *      ignored.
 *
 * Drag:
 *      A single touch followed by some movement. This behavior will handle all
 *      of the required events and report the properties of the drag to you
 *      while the touch is happening and at the end of the drag sequence. This
 *      behavior will NOT perform the actual dragging (redrawing the element)
 *      for you, this responsibility is left to the client code.
 *
 * Long press:
 *     When your element is touched and held without any drag occuring, the
 *     LONG_PRESS event will fire.
 */

// Use an anonymous function to enable strict mode just for this file (which
// will be concatenated with other files when embedded in Chrome)
cr.define('cr.ui', function() {
  'use strict';

  /**
   * A TouchHandler attaches to an Element, listents for low-level touch (or
   * mouse) events and dispatching higher-level events on the element.
   * @param {!Element} element The element to listen on and fire events
   * for.
   * @constructor
   */
  function TouchHandler(element) {
    /**
     * @type {!Element}
     * @private
     */
    this.element_ = element;

    /**
     * The absolute sum of all touch y deltas.
     * @type {number}
     * @private
     */
    this.totalMoveY_ = 0;

    /**
     * The absolute sum of all touch x deltas.
     * @type {number}
     * @private
     */
    this.totalMoveX_ = 0;

    /**
     * An array of tuples where the first item is the horizontal component of a
     * recent relevant touch and the second item is the touch's time stamp. Old
     * touches are removed based on the max tracking time and when direction
     * changes.
     * @type {!Array<number>}
     * @private
     */
    this.recentTouchesX_ = [];

    /**
     * An array of tuples where the first item is the vertical component of a
     * recent relevant touch and the second item is the touch's time stamp. Old
     * touches are removed based on the max tracking time and when direction
     * changes.
     * @type {!Array<number>}
     * @private
     */
    this.recentTouchesY_ = [];

    /**
     * Used to keep track of all events we subscribe to so we can easily clean
     * up
     * @type {EventTracker}
     * @private
     */
    this.events_ = new EventTracker();
  }


  /**
   * DOM Events that may be fired by the TouchHandler at the element
   */
  TouchHandler.EventType = {
    // Fired whenever the element is touched as the only touch to the device.
    // enableDrag defaults to false, set to true to permit dragging.
    TOUCH_START: 'touchHandler:touch_start',

    // Fired when an element is held for a period of time.  Prevents dragging
    // from occuring (even if enableDrag was set to true).
    LONG_PRESS: 'touchHandler:long_press',

    // If enableDrag was set to true at TOUCH_START, DRAG_START will fire when
    // the touch first moves sufficient distance.  enableDrag is set to true but
    // can be reset to false to cancel the drag.
    DRAG_START: 'touchHandler:drag_start',

    // If enableDrag was true after DRAG_START, DRAG_MOVE will fire whenever the
    // touch is moved.
    DRAG_MOVE: 'touchHandler:drag_move',

    // Fired just before TOUCH_END when a drag is released.  Correlates 1:1 with
    // a DRAG_START.
    DRAG_END: 'touchHandler:drag_end',

    // Fired whenever a touch that is being tracked has been released.
    // Correlates 1:1 with a TOUCH_START.
    TOUCH_END: 'touchHandler:touch_end',

    // Fired whenever the element is tapped in a short time and no dragging is
    // detected.
    TAP: 'touchHandler:tap'
  };


  /**
   * The type of event sent by TouchHandler
   * @constructor
   * @extends {Event}
   * @param {string} type The type of event (one of cr.ui.Grabber.EventType).
   * @param {boolean} bubbles Whether or not the event should bubble.
   * @param {number} clientX The X location of the touch.
   * @param {number} clientY The Y location of the touch.
   * @param {!Element} touchedElement The element at the current location of the
   *        touch.
   */
  TouchHandler.Event = function(
      type, bubbles, clientX, clientY, touchedElement) {
    const event = document.createEvent('Event');
    event.initEvent(type, bubbles, true);
    event.__proto__ = TouchHandler.Event.prototype;

    /**
     * The X location of the touch affected
     * @type {number}
     */
    event.clientX = clientX;

    /**
     * The Y location of the touch affected
     * @type {number}
     */
    event.clientY = clientY;

    /**
     * The element at the current location of the touch.
     * @type {!Element}
     */
    event.touchedElement = touchedElement;

    return event;
  };

  TouchHandler.Event.prototype = {
    __proto__: Event.prototype,

    /**
     * For TOUCH_START and DRAG START events, set to true to enable dragging or
     * false to disable dragging.
     * @type {boolean|undefined}
     */
    enableDrag: undefined,

    /**
     * For DRAG events, provides the horizontal component of the
     * drag delta. Drag delta is defined as the delta of the start touch
     * position and the current drag position.
     * @type {number|undefined}
     */
    dragDeltaX: undefined,

    /**
     * For DRAG events, provides the vertical component of the
     * drag delta.
     * @type {number|undefined}
     */
    dragDeltaY: undefined
  };

  /**
   * Maximum movement of touch required to be considered a tap.
   * @type {number}
   * @private
   */
  TouchHandler.MAX_TRACKING_FOR_TAP_ = 8;

  /**
   * The maximum number of ms to track a touch event. After an event is older
   * than this value, it will be ignored in velocity calculations.
   * @type {number}
   * @private
   */
  TouchHandler.MAX_TRACKING_TIME_ = 250;

  /**
   * The maximum number of touches to track.
   * @type {number}
   * @private
   */
  TouchHandler.MAX_TRACKING_TOUCHES_ = 5;

  /**
   * The maximum velocity to return, in pixels per millisecond, that is used
   * to guard against errors in calculating end velocity of a drag. This is a
   * very fast drag velocity.
   * @type {number}
   * @private
   */
  TouchHandler.MAXIMUM_VELOCITY_ = 5;

  /**
   * The velocity to return, in pixel per millisecond, when the time stamps on
   * the events are erroneous. The browser can return bad time stamps if the
   * thread is blocked for the duration of the drag. This is a low velocity to
   * prevent the content from moving quickly after a slow drag. It is less
   * jarring if the content moves slowly after a fast drag.
   * @type {number}
   * @private
   */
  TouchHandler.VELOCITY_FOR_INCORRECT_EVENTS_ = 1;

  /**
   * The time, in milliseconds, that a touch must be held to be considered
   * 'long'.
   * @type {number}
   * @private
   */
  TouchHandler.TIME_FOR_LONG_PRESS_ = 500;

  TouchHandler.prototype = {
    /**
     * If defined, the identifer of the single touch that is active.  Note that
     * 0 is a valid touch identifier - it should not be treated equivalently to
     * undefined.
     * @type {number|undefined}
     * @private
     */
    activeTouch_: undefined,

    /**
     * @type {boolean|undefined}
     * @private
     */
    tracking_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    startTouchX_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    startTouchY_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    endTouchX_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    endTouchY_: undefined,

    /**
     * Time of the touchstart event.
     * @type {number|undefined}
     * @private
     */
    startTime_: undefined,

    /**
     * The time of the touchend event.
     * @type {number|undefined}
     * @private
     */
    endTime_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    lastTouchX_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    lastTouchY_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    lastMoveX_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    lastMoveY_: undefined,

    /**
     * @type {number|undefined}
     * @private
     */
    longPressTimeout_: undefined,

    /**
     * If defined and true, the next click event should be swallowed
     * @type {boolean|undefined}
     * @private
     */
    swallowNextClick_: undefined,

    /**
     * @type {boolean}
     * @private
     */
    draggingEnabled_: false,

    /**
     * Start listenting for events.
     * @param {boolean=} opt_capture True if the TouchHandler should listen to
     *      during the capture phase.
     * @param {boolean=} opt_mouse True if the TouchHandler should generate
     *      events for mouse input (in addition to touch input).
     */
    enable: function(opt_capture, opt_mouse) {
      const capture = !!opt_capture;

      // Just listen to start events for now. When a touch is occuring we'll
      // want to be subscribed to move and end events on the document, but we
      // don't want to incur the cost of lots of no-op handlers on the document.
      this.events_.add(
          this.element_, 'touchstart', this.onStart_.bind(this), capture);
      if (opt_mouse) {
        this.events_.add(
            this.element_, 'mousedown',
            this.mouseToTouchCallback_(this.onStart_.bind(this)), capture);
      }

      // If the element is long-pressed, we may need to swallow a click
      this.events_.add(this.element_, 'click', this.onClick_.bind(this), true);
    },

    /**
     * Stop listening to all events.
     */
    disable: function() {
      this.stopTouching_();
      this.events_.removeAll();
    },

    /**
     * Wraps a callback with translations of mouse events to touch events.
     * NOTE: These types really should be function(Event) but then we couldn't
     * use this with bind (which operates on any type of function).  Doesn't
     * JSDoc support some sort of polymorphic types?
     * @param {Function} callback The event callback.
     * @return {Function} The wrapping callback.
     * @private
     */
    mouseToTouchCallback_: function(callback) {
      return function(e) {
        // Note that there may be synthesizes mouse events caused by touch
        // events (a mouseDown after a touch-click).  We leave it up to the
        // client to worry about this if it matters to them (typically a short
        // mouseDown/mouseUp without a click is no big problem and it's not
        // obvious how we identify such synthesized events in a general way).
        const touch = {
          // any fixed value will do for the identifier - there will only
          // ever be a single active 'touch' when using the mouse.
          identifier: 0,
          clientX: e.clientX,
          clientY: e.clientY,
          target: e.target
        };
        e.touches = [];
        e.targetTouches = [];
        e.changedTouches = [touch];
        if (e.type != 'mouseup') {
          e.touches[0] = touch;
          e.targetTouches[0] = touch;
        }
        callback(e);
      };
    },

    /**
     * Begin tracking the touchable element, it is eligible for dragging.
     * @private
     */
    beginTracking_: function() {
      this.tracking_ = true;
    },

    /**
     * Stop tracking the touchable element, it is no longer dragging.
     * @private
     */
    endTracking_: function() {
      this.tracking_ = false;
      this.dragging_ = false;
      this.totalMoveY_ = 0;
      this.totalMoveX_ = 0;
    },

    /**
     * Reset the touchable element as if we never saw the touchStart
     * Doesn't dispatch any end events - be careful of existing listeners.
     */
    cancelTouch: function() {
      this.stopTouching_();
      this.endTracking_();
      // If clients needed to be aware of this, we could fire a cancel event
      // here.
    },

    /**
     * Record that touching has stopped
     * @private
     */
    stopTouching_: function() {
      // Mark as no longer being touched
      this.activeTouch_ = undefined;

      // If we're waiting for a long press, stop
      window.clearTimeout(this.longPressTimeout_);

      // Stop listening for move/end events until there's another touch.
      // We don't want to leave handlers piled up on the document.
      // Note that there's no harm in removing handlers that weren't added, so
      // rather than track whether we're using mouse or touch we do both.
      this.events_.remove(document, 'touchmove');
      this.events_.remove(document, 'touchend');
      this.events_.remove(document, 'touchcancel');
      this.events_.remove(document, 'mousemove');
      this.events_.remove(document, 'mouseup');
    },

    /**
     * Touch start handler.
     * @param {!TouchEvent} e The touchstart event.
     * @private
     */
    onStart_: function(e) {
      // Only process single touches.  If there is already a touch happening, or
      // two simultaneous touches then just ignore them.
      if (e.touches.length > 1) {
        // Note that we could cancel an active touch here.  That would make
        // simultaneous touch behave similar to near-simultaneous. However, if
        // the user is dragging something, an accidental second touch could be
        // quite disruptive if it cancelled their drag.  Better to just ignore
        // it.
        return;
      }

      // It's still possible there could be an active "touch" if the user is
      // simultaneously using a mouse and a touch input.
      if (this.activeTouch_ !== undefined) {
        return;
      }

      const touch = e.targetTouches[0];
      this.activeTouch_ = touch.identifier;

      // We've just started touching so shouldn't swallow any upcoming click
      if (this.swallowNextClick_) {
        this.swallowNextClick_ = false;
      }

      this.disableTap_ = false;

      // Sign up for end/cancel notifications for this touch.
      // Note that we do this on the document so that even if the user drags
      // their finger off the element, we'll still know what they're doing.
      if (e.type == 'mousedown') {
        this.events_.add(
            document, 'mouseup',
            this.mouseToTouchCallback_(this.onEnd_.bind(this)), false);
      } else {
        this.events_.add(document, 'touchend', this.onEnd_.bind(this), false);
        this.events_.add(
            document, 'touchcancel', this.onEnd_.bind(this), false);
      }

      // This timeout is cleared on touchEnd and onDrag
      // If we invoke the function then we have a real long press
      window.clearTimeout(this.longPressTimeout_);
      this.longPressTimeout_ = window.setTimeout(
          this.onLongPress_.bind(this), TouchHandler.TIME_FOR_LONG_PRESS_);

      // Dispatch the TOUCH_START event
      this.draggingEnabled_ =
          !!this.dispatchEvent_(TouchHandler.EventType.TOUCH_START, touch);

      // We want dragging notifications
      if (e.type == 'mousedown') {
        this.events_.add(
            document, 'mousemove',
            this.mouseToTouchCallback_(this.onMove_.bind(this)), false);
      } else {
        this.events_.add(document, 'touchmove', this.onMove_.bind(this), false);
      }

      this.startTouchX_ = this.lastTouchX_ = touch.clientX;
      this.startTouchY_ = this.lastTouchY_ = touch.clientY;
      this.startTime_ = e.timeStamp;

      this.recentTouchesX_ = [];
      this.recentTouchesY_ = [];
      this.recentTouchesX_.push(touch.clientX, e.timeStamp);
      this.recentTouchesY_.push(touch.clientY, e.timeStamp);

      this.beginTracking_();
    },

    /**
     * Given a list of Touches, find the one matching our activeTouch
     * identifier. Note that Chrome currently always uses 0 as the identifier.
     * In that case we'll end up always choosing the first element in the list.
     * @param {TouchList} touches The list of Touch objects to search.
     * @return {!Touch|undefined} The touch matching our active ID if any.
     * @private
     */
    findActiveTouch_: function(touches) {
      assert(this.activeTouch_ !== undefined, 'Expecting an active touch');
      // A TouchList isn't actually an array, so we shouldn't use
      // Array.prototype.filter/some, etc.
      for (let i = 0; i < touches.length; i++) {
        if (touches[i].identifier == this.activeTouch_) {
          return touches[i];
        }
      }
      return undefined;
    },

    /**
     * Touch move handler.
     * @param {!TouchEvent} e The touchmove event.
     * @private
     */
    onMove_: function(e) {
      if (!this.tracking_) {
        return;
      }

      // Our active touch should always be in the list of touches still active
      assert(this.findActiveTouch_(e.touches), 'Missing touchEnd');

      const that = this;
      const touch = this.findActiveTouch_(e.changedTouches);
      if (!touch) {
        return;
      }

      const clientX = touch.clientX;
      const clientY = touch.clientY;

      const moveX = this.lastTouchX_ - clientX;
      const moveY = this.lastTouchY_ - clientY;
      this.totalMoveX_ += Math.abs(moveX);
      this.totalMoveY_ += Math.abs(moveY);
      this.lastTouchX_ = clientX;
      this.lastTouchY_ = clientY;

      const couldBeTap =
          this.totalMoveY_ <= TouchHandler.MAX_TRACKING_FOR_TAP_ ||
          this.totalMoveX_ <= TouchHandler.MAX_TRACKING_FOR_TAP_;

      if (!couldBeTap) {
        this.disableTap_ = true;
      }

      if (this.draggingEnabled_ && !this.dragging_ && !couldBeTap) {
        // If we're waiting for a long press, stop
        window.clearTimeout(this.longPressTimeout_);

        // Dispatch the DRAG_START event and record whether dragging should be
        // allowed or not.  Note that this relies on the current value of
        // startTouchX/Y - handlers may use the initial drag delta to determine
        // if dragging should be permitted.
        this.dragging_ =
            this.dispatchEvent_(TouchHandler.EventType.DRAG_START, touch);

        if (this.dragging_) {
          // Update the start position here so that drag deltas have better
          // values but don't touch the recent positions so that velocity
          // calculations can still use touchstart position in the time and
          // distance delta.
          this.startTouchX_ = clientX;
          this.startTouchY_ = clientY;
          this.startTime_ = e.timeStamp;
        } else {
          this.endTracking_();
        }
      }

      if (this.dragging_) {
        this.dispatchEvent_(TouchHandler.EventType.DRAG_MOVE, touch);

        this.removeTouchesInWrongDirection_(
            this.recentTouchesX_, this.lastMoveX_, moveX);
        this.removeTouchesInWrongDirection_(
            this.recentTouchesY_, this.lastMoveY_, moveY);
        this.removeOldTouches_(this.recentTouchesX_, e.timeStamp);
        this.removeOldTouches_(this.recentTouchesY_, e.timeStamp);
        this.recentTouchesX_.push(clientX, e.timeStamp);
        this.recentTouchesY_.push(clientY, e.timeStamp);
      }

      this.lastMoveX_ = moveX;
      this.lastMoveY_ = moveY;
    },

    /**
     * Filters the provided recent touches array to remove all touches except
     * the last if the move direction has changed.
     * @param {!Array<number>} recentTouches An array of tuples where the first
     *     item is the x or y component of the recent touch and the second item
     *     is the touch time stamp.
     * @param {number|undefined} lastMove The x or y component of the previous
     *     move.
     * @param {number} recentMove The x or y component of the most recent move.
     * @private
     */
    removeTouchesInWrongDirection_: function(
        recentTouches, lastMove, recentMove) {
      if (lastMove && recentMove && recentTouches.length > 2 &&
          (lastMove > 0 ^ recentMove > 0)) {
        recentTouches.splice(0, recentTouches.length - 2);
      }
    },

    /**
     * Filters the provided recent touches array to remove all touches older
     * than the max tracking time or the 5th most recent touch.
     * @param {!Array<number>} recentTouches An array of tuples where the first
     *     item is the x or y component of the recent touch and the second item
     *     is the touch time stamp.
     * @param {number} recentTime The time of the most recent event.
     * @private
     */
    removeOldTouches_: function(recentTouches, recentTime) {
      while (recentTouches.length &&
                 recentTime - recentTouches[1] >
                     TouchHandler.MAX_TRACKING_TIME_ ||
             recentTouches.length > TouchHandler.MAX_TRACKING_TOUCHES_ * 2) {
        recentTouches.splice(0, 2);
      }
    },

    /**
     * Touch end handler.
     * @param {!TouchEvent} e The touchend event.
     * @private
     */
    onEnd_: function(e) {
      const that = this;
      assert(this.activeTouch_ !== undefined, 'Expect to already be touching');

      // If the touch we're tracking isn't changing here, ignore this touch end.
      const touch = this.findActiveTouch_(e.changedTouches);
      if (!touch) {
        // In most cases, our active touch will be in the 'touches' collection,
        // but we can't assert that because occasionally two touchend events can
        // occur at almost the same time with both having empty 'touches' lists.
        // I.e., 'touches' seems like it can be a bit more up to date than the
        // current event.
        return;
      }

      // This is touchEnd for the touch we're monitoring
      assert(
          !this.findActiveTouch_(e.touches), 'Touch ended also still active');

      // Indicate that touching has finished
      this.stopTouching_();

      if (this.tracking_) {
        const clientX = touch.clientX;
        const clientY = touch.clientY;

        if (this.dragging_) {
          this.endTime_ = e.timeStamp;
          this.endTouchX_ = clientX;
          this.endTouchY_ = clientY;

          this.removeOldTouches_(this.recentTouchesX_, e.timeStamp);
          this.removeOldTouches_(this.recentTouchesY_, e.timeStamp);

          this.dispatchEvent_(TouchHandler.EventType.DRAG_END, touch);

          // Note that in some situations we can get a click event here as well.
          // For now this isn't a problem, but we may want to consider having
          // some logic that hides clicks that appear to be caused by a touchEnd
          // used for dragging.
        }

        this.endTracking_();
      }
      this.draggingEnabled_ = false;

      // Note that we dispatch the touchEnd event last so that events at
      // different levels of semantics nest nicely (similar to how DOM
      // drag-and-drop events are nested inside of the mouse events that trigger
      // them).
      this.dispatchEvent_(TouchHandler.EventType.TOUCH_END, touch);
      if (!this.disableTap_) {
        this.dispatchEvent_(TouchHandler.EventType.TAP, touch);
      }
    },

    /**
     * Get end velocity of the drag. This method is specific to drag behavior,
     * so if touch behavior and drag behavior is split then this should go with
     * drag behavior. End velocity is defined as deltaXY / deltaTime where
     * deltaXY is the difference between endPosition and the oldest recent
     * position, and deltaTime is the difference between endTime and the oldest
     * recent time stamp.
     * @return {Object} The x and y velocity.
     */
    getEndVelocity: function() {
      // Note that we could move velocity to just be an end-event parameter.
      let velocityX = this.recentTouchesX_.length ?
          (this.endTouchX_ - this.recentTouchesX_[0]) /
              (this.endTime_ - this.recentTouchesX_[1]) :
          0;
      let velocityY = this.recentTouchesY_.length ?
          (this.endTouchY_ - this.recentTouchesY_[0]) /
              (this.endTime_ - this.recentTouchesY_[1]) :
          0;

      velocityX = this.correctVelocity_(velocityX);
      velocityY = this.correctVelocity_(velocityY);

      return {x: velocityX, y: velocityY};
    },

    /**
     * Correct erroneous velocities by capping the velocity if we think it's too
     * high, or setting it to a default velocity if know that the event data is
     * bad.
     * @param {number} velocity The x or y velocity component.
     * @return {number} The corrected velocity.
     * @private
     */
    correctVelocity_: function(velocity) {
      let absVelocity = Math.abs(velocity);

      // We add to recent touches for each touchstart and touchmove. If we have
      // fewer than 3 touches (6 entries), we assume that the thread was blocked
      // for the duration of the drag and we received events in quick succession
      // with the wrong time stamps.
      if (absVelocity > TouchHandler.MAXIMUM_VELOCITY_) {
        absVelocity = this.recentTouchesY_.length < 3 ?
            TouchHandler.VELOCITY_FOR_INCORRECT_EVENTS_ :
            TouchHandler.MAXIMUM_VELOCITY_;
      }
      return absVelocity * (velocity < 0 ? -1 : 1);
    },

    /**
     * Handler when an element has been pressed for a long time
     * @private
     */
    onLongPress_: function() {
      // Swallow any click that occurs on this element without an intervening
      // touch start event.  This simple click-busting technique should be
      // sufficient here since a real click should have a touchstart first.
      this.swallowNextClick_ = true;
      this.disableTap_ = true;

      // Dispatch to the LONG_PRESS
      assert(typeof this.startTouchX_ == 'number');
      assert(typeof this.startTouchY_ == 'number');
      this.dispatchEventXY_(
          TouchHandler.EventType.LONG_PRESS, this.element_,
          /** @type {number} */ (this.startTouchX_),
          /** @type {number} */ (this.startTouchY_));
    },

    /**
     * Click handler - used to swallow clicks after a long-press
     * @param {!Event} e The click event.
     * @private
     */
    onClick_: function(e) {
      if (this.swallowNextClick_) {
        e.preventDefault();
        e.stopPropagation();
        this.swallowNextClick_ = false;
      }
    },

    /**
     * Dispatch a TouchHandler event to the element
     * @param {string} eventType The event to dispatch.
     * @param {Touch} touch The touch triggering this event.
     * @return {boolean|undefined} The value of enableDrag after dispatching
     *         the event.
     * @private
     */
    dispatchEvent_: function(eventType, touch) {

      // Determine which element was touched.  For mouse events, this is always
      // the event/touch target.  But for touch events, the target is always the
      // target of the touchstart (and it's unlikely we can change this
      // since the common implementation of touch dragging relies on it). Since
      // touch is our primary scenario (which we want to emulate with mouse),
      // we'll treat both cases the same and not depend on the target.
      /** @type {Element} */
      let touchedElement;
      if (eventType == TouchHandler.EventType.TOUCH_START) {
        touchedElement = assertInstanceof(touch.target, Element);
      } else {
        touchedElement = assert(this.element_.ownerDocument.elementFromPoint(
            touch.clientX, touch.clientY));
      }

      return this.dispatchEventXY_(
          eventType, touchedElement, touch.clientX, touch.clientY);
    },

    /**
     * Dispatch a TouchHandler event to the element
     * @param {string} eventType The event to dispatch.
     * @param {!Element} touchedElement
     * @param {number} clientX The X location for the event.
     * @param {number} clientY The Y location for the event.
     * @return {boolean|undefined} The value of enableDrag after dispatching
     *         the event.
     * @private
     */
    dispatchEventXY_: function(eventType, touchedElement, clientX, clientY) {
      const isDrag =
          (eventType == TouchHandler.EventType.DRAG_START ||
           eventType == TouchHandler.EventType.DRAG_MOVE ||
           eventType == TouchHandler.EventType.DRAG_END);

      // Drag events don't bubble - we're really just dragging the element,
      // not affecting its parent at all.
      const bubbles = !isDrag;

      const event = new TouchHandler.Event(
          eventType, bubbles, clientX, clientY, touchedElement);

      // Set enableDrag when it can be overridden
      if (eventType == TouchHandler.EventType.TOUCH_START) {
        event.enableDrag = false;
      } else if (eventType == TouchHandler.EventType.DRAG_START) {
        event.enableDrag = true;
      }

      if (isDrag) {
        event.dragDeltaX = clientX - this.startTouchX_;
        event.dragDeltaY = clientY - this.startTouchY_;
      }

      this.element_.dispatchEvent(event);
      return event.enableDrag;
    }
  };

  return {TouchHandler: TouchHandler};
});
</script>

<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('ntp', function() {
  'use strict';

  // We can't pass the currently dragging tile via dataTransfer because of
  // http://crbug.com/31037
  let currentlyDraggingTile = null;
  function getCurrentlyDraggingTile() {
    return currentlyDraggingTile;
  }
  function setCurrentlyDraggingTile(tile) {
    currentlyDraggingTile = tile;
    if (tile) {
      ntp.enterRearrangeMode();
    } else {
      ntp.leaveRearrangeMode();
    }
  }

  /**
   * Changes the current dropEffect of a drag. This modifies the native cursor
   * and serves as an indicator of what we should do at the end of the drag as
   * well as give indication to the user if a drop would succeed if they let go.
   * @param {DataTransfer} dataTransfer A dataTransfer object from a drag event.
   * @param {string} effect A drop effect to change to (i.e. copy, move, none).
   */
  function setCurrentDropEffect(dataTransfer, effect) {
    dataTransfer.dropEffect = effect;
    if (currentlyDraggingTile) {
      currentlyDraggingTile.lastDropEffect = dataTransfer.dropEffect;
    }
  }

  /**
   * Creates a new Tile object. Tiles wrap content on a TilePage, providing
   * some styling and drag functionality.
   * @constructor
   * @extends {HTMLDivElement}
   */
  function Tile(contents) {
    const tile = cr.doc.createElement('div');
    tile.__proto__ = Tile.prototype;
    tile.initialize(contents);

    return tile;
  }

  Tile.prototype = {
    __proto__: HTMLDivElement.prototype,

    initialize: function(contents) {
      // 'real' as opposed to doppleganger.
      this.className = 'tile real';
      this.appendChild(contents);
      contents.tile = this;

      this.addEventListener('dragstart', this.onDragStart_);
      this.addEventListener('drag', this.onDragMove_);
      this.addEventListener('dragend', this.onDragEnd_);

      this.firstChild.addEventListener(
          'animationend', this.onContentsAnimationEnd_.bind(this));

      this.eventTracker = new EventTracker();
    },

    get index() {
      return Array.prototype.indexOf.call(this.tilePage.tileElements_, this);
    },

    get tilePage() {
      return findAncestorByClass(this, 'tile-page');
    },

    /**
     * Position the tile at |x, y|, and store this as the grid location, i.e.
     * where the tile 'belongs' when it's not being dragged.
     * @param {number} x The x coordinate, in pixels.
     * @param {number} y The y coordinate, in pixels.
     */
    setGridPosition: function(x, y) {
      this.gridX = x;
      this.gridY = y;
      this.moveTo(x, y);
    },

    /**
     * Position the tile at |x, y|.
     * @param {number} x The x coordinate, in pixels.
     * @param {number} y The y coordinate, in pixels.
     */
    moveTo: function(x, y) {
      // left overrides right in LTR, and right takes precedence in RTL.
      this.style.left = toCssPx(x);
      this.style.right = toCssPx(x);
      this.style.top = toCssPx(y);
    },

    /**
     * The handler for dragstart events fired on |this|.
     * @param {Event} e The event for the drag.
     * @private
     */
    onDragStart_: function(e) {
      // The user may start dragging again during a previous drag's finishing
      // animation.
      if (this.classList.contains('dragging')) {
        this.finalizeDrag_();
      }

      setCurrentlyDraggingTile(this);

      e.dataTransfer.effectAllowed = 'copyMove';
      /** @type {!ntp.App} */ (this.firstChild).setDragData(e.dataTransfer);

      // The drag clone is the node we use as a representation during the drag.
      // It's attached to the top level document element so that it floats above
      // image masks.
      this.dragClone = this.cloneNode(true);
      this.dragClone.style.right = '';
      this.dragClone.classList.add('drag-representation');
      $('card-slider-frame').appendChild(this.dragClone);
      this.eventTracker.add(
          this.dragClone, 'transitionend',
          this.onDragCloneTransitionEnd_.bind(this));

      this.classList.add('dragging');
      // offsetLeft is mirrored in RTL. Un-mirror it.
      const offsetLeft = isRTL() ?
          this.parentNode.clientWidth - this.offsetLeft :
          this.offsetLeft;
      this.dragOffsetX = e.x - offsetLeft - this.parentNode.offsetLeft;
      this.dragOffsetY = e.y - this.offsetTop -
          // Unlike offsetTop, this value takes scroll position into account.
          this.parentNode.getBoundingClientRect().top;

      this.onDragMove_(e);
    },

    /**
     * The handler for drag events fired on |this|.
     * @param {Event} e The event for the drag.
     * @private
     */
    onDragMove_: function(e) {
      if (e.view != window || (e.x == 0 && e.y == 0)) {
        this.dragClone.hidden = true;
        return;
      }

      this.dragClone.hidden = false;
      this.dragClone.style.left = toCssPx(e.x - this.dragOffsetX);
      this.dragClone.style.top = toCssPx(e.y - this.dragOffsetY);
    },

    /**
     * The handler for dragend events fired on |this|.
     * @param {Event} e The event for the drag.
     * @private
     */
    onDragEnd_: function(e) {
      this.dragClone.hidden = false;
      this.dragClone.classList.add('placing');

      setCurrentlyDraggingTile(null);

      // tilePage will be null if we've already been removed.
      const tilePage = this.tilePage;
      if (tilePage) {
        tilePage.positionTile_(this.index);
      }

      // Take an appropriate action with the drag clone.
      if (this.landedOnTrash) {
        this.dragClone.classList.add('deleting');
      } else if (tilePage) {
        // TODO(dbeam): Until we fix dropEffect to the correct behavior it will
        // differ on windows - crbug.com/39399.  That's why we use the custom
        // this.lastDropEffect instead of e.dataTransfer.dropEffect.
        if (tilePage.selected && this.lastDropEffect != 'copy') {
          // The drag clone can still be hidden from the last drag move event.
          this.dragClone.hidden = false;
          // The tile's contents may have moved following the respositioning;
          // adjust for that.
          const contentDiffX =
              this.dragClone.firstChild.offsetLeft - this.firstChild.offsetLeft;
          const contentDiffY =
              this.dragClone.firstChild.offsetTop - this.firstChild.offsetTop;
          this.dragClone.style.left =
              toCssPx(this.gridX + this.parentNode.offsetLeft - contentDiffX);
          this.dragClone.style.top = toCssPx(
              this.gridY + this.parentNode.getBoundingClientRect().top -
              contentDiffY);
        } else if (this.dragClone.hidden) {
          this.finalizeDrag_();
        } else {
          // The CSS3 transitions spec intentionally leaves it up to individual
          // user agents to determine when styles should be applied. On some
          // platforms (at the moment, Windows), when you apply both classes
          // immediately a transition may not occur correctly. That's why we're
          // using a setTimeout here to queue adding the class until the
          // previous class (currently: .placing) sets up a transition.
          // http://dev.w3.org/csswg/css3-transitions/#starting
          window.setTimeout(function() {
            if (this.dragClone) {
              this.dragClone.classList.add('dropped-on-other-page');
            }
          }.bind(this), 0);
        }
      }

      delete this.lastDropEffect;
      this.landedOnTrash = false;
    },

    /**
     * Creates a clone of this node offset by the coordinates. Used for the
     * dragging effect where a tile appears to float off one side of the grid
     * and re-appear on the other.
     * @param {number} x x-axis offset, in pixels.
     * @param {number} y y-axis offset, in pixels.
     */
    showDoppleganger: function(x, y) {
      // We always have to clear the previous doppleganger to make sure we get
      // style updates for the contents of this tile.
      this.clearDoppleganger();

      const clone = this.cloneNode(true);
      clone.classList.remove('real');
      clone.classList.add('doppleganger');
      const clonelets = clone.querySelectorAll('.real');
      for (let i = 0; i < clonelets.length; i++) {
        clonelets[i].classList.remove('real');
      }

      this.appendChild(clone);
      this.doppleganger_ = clone;

      if (isRTL()) {
        x *= -1;
      }

      this.doppleganger_.style.transform =
          'translate(' + x + 'px, ' + y + 'px)';
    },

    /**
     * Destroys the current doppleganger.
     */
    clearDoppleganger: function() {
      if (this.doppleganger_) {
        this.removeChild(this.doppleganger_);
        this.doppleganger_ = null;
      }
    },

    /**
     * Returns status of doppleganger.
     * @return {boolean} True if there is a doppleganger showing for |this|.
     */
    hasDoppleganger: function() {
      return !!this.doppleganger_;
    },

    /**
     * Cleans up after the drag is over. This is either called when the
     * drag representation finishes animating to the final position, or when
     * the next drag starts (if the user starts a 2nd drag very quickly).
     * @private
     */
    finalizeDrag_: function() {
      assert(this.classList.contains('dragging'));

      const clone = this.dragClone;
      this.dragClone = null;

      clone.parentNode.removeChild(clone);
      this.eventTracker.remove(clone, 'transitionend');
      this.classList.remove('dragging');
      if (this.firstChild.finalizeDrag) {
        this.firstChild.finalizeDrag();
      }
    },

    /**
     * Called when the drag representation node is done migrating to its final
     * resting spot.
     * @param {Event} e The transition end event.
     */
    onDragCloneTransitionEnd_: function(e) {
      if (this.classList.contains('dragging') &&
          (e.propertyName == 'left' || e.propertyName == 'top' ||
           e.propertyName == 'transform')) {
        this.finalizeDrag_();
      }
    },

    /**
     * Called when an app is removed from Chrome. Animates its disappearance.
     * @param {boolean=} opt_animate Whether the animation should be animated.
     */
    doRemove: function(opt_animate) {
      if (opt_animate) {
        this.firstChild.classList.add('removing-tile-contents');
      } else {
        this.tilePage.removeTile(this, false);
      }
    },

    /**
     * Callback for the animationend event on the tile's contents.
     * @param {Event} e The event object.
     */
    onContentsAnimationEnd_: function(e) {
      if (this.firstChild.classList.contains('new-tile-contents')) {
        this.firstChild.classList.remove('new-tile-contents');
      }
      if (this.firstChild.classList.contains('removing-tile-contents')) {
        this.tilePage.removeTile(this, true);
      }
    },
  };

  /**
   * Gives the proportion of the row width that is devoted to a single icon.
   * @param {number} rowTileCount The number of tiles in a row.
   * @param {number} tileSpacingFraction The proportion of the tile width which
   *     will be used as spacing between tiles.
   * @return {number} The ratio between icon width and row width.
   */
  function tileWidthFraction(rowTileCount, tileSpacingFraction) {
    return rowTileCount + (rowTileCount - 1) * tileSpacingFraction;
  }

  /**
   * Calculates an assortment of tile-related values for a grid with the
   * given dimensions.
   * @param {number} width The pixel width of the grid.
   * @param {number} numRowTiles The number of tiles in a row.
   * @param {number} tileSpacingFraction The proportion of the tile width which
   *     will be used as spacing between tiles.
   * @return {Object} A mapping of pixel values.
   */
  function tileValuesForGrid(width, numRowTiles, tileSpacingFraction) {
    const tileWidth =
        width / tileWidthFraction(numRowTiles, tileSpacingFraction);
    const offsetX = tileWidth * (1 + tileSpacingFraction);
    const interTileSpacing = offsetX - tileWidth;

    return {
      tileWidth: tileWidth,
      offsetX: offsetX,
      interTileSpacing: interTileSpacing,
    };
  }

  // The smallest amount of horizontal blank space to display on the sides when
  // displaying a wide arrangement. There is an additional 26px of margin from
  // the tile page padding.
  const MIN_WIDE_MARGIN = 18;

  /**
   * Creates a new TilePage object. This object contains tiles and controls
   * their layout.
   * @param {Object} gridValues Pixel values that define the size and layout
   *     of the tile grid.
   * @constructor
   * @extends {HTMLDivElement}
   * @implements {cr.ui.DragWrapperDelegate}
   */
  function TilePage(gridValues) {
    const el = cr.doc.createElement('div');
    el.gridValues_ = gridValues;
    el.__proto__ = TilePage.prototype;
    el.initialize();

    return el;
  }

  /**
   * Takes a collection of grid layout pixel values and updates them with
   * additional tiling values that are calculated from TilePage constants.
   * @param {Object} grid The grid layout pixel values to update.
   */
  TilePage.initGridValues = function(grid) {
    // The amount of space we need to display a narrow grid (all narrow grids
    // are this size).
    grid.narrowWidth = grid.minTileWidth *
        tileWidthFraction(grid.minColCount, grid.tileSpacingFraction);
    // The minimum amount of space we need to display a wide grid.
    grid.minWideWidth = grid.minTileWidth *
        tileWidthFraction(grid.maxColCount, grid.tileSpacingFraction);
    // The largest we will ever display a wide grid.
    grid.maxWideWidth = grid.maxTileWidth *
        tileWidthFraction(grid.maxColCount, grid.tileSpacingFraction);
    // Tile-related pixel values for the narrow display.
    grid.narrowTileValues = tileValuesForGrid(
        grid.narrowWidth, grid.minColCount, grid.tileSpacingFraction);
    // Tile-related pixel values for the minimum narrow display.
    grid.wideTileValues = tileValuesForGrid(
        grid.minWideWidth, grid.maxColCount, grid.tileSpacingFraction);
  };

  TilePage.prototype = {
    __proto__: HTMLDivElement.prototype,

    initialize: function() {
      this.className = 'tile-page';

      // Div that acts as a custom scrollbar. The scrollbar has to live
      // outside the content div so it doesn't flicker when scrolling (due to
      // repainting after the scroll, then repainting again when moved in the
      // onScroll handler). |scrollbar_| is only aesthetic, and it only
      // represents the thumb. Actual events are still handled by the invisible
      // native scrollbars. This div gives us more flexibility with the visuals.
      this.scrollbar_ = this.ownerDocument.createElement('div');
      this.scrollbar_.className = 'tile-page-scrollbar';
      this.scrollbar_.hidden = true;
      this.appendChild(this.scrollbar_);

      // This contains everything but the scrollbar.
      this.content_ = this.ownerDocument.createElement('div');
      this.content_.className = 'tile-page-content';
      this.appendChild(this.content_);

      // Div that sets the vertical position of the tile grid.
      this.topMargin_ = this.ownerDocument.createElement('div');
      this.topMargin_.className = 'top-margin';
      this.content_.appendChild(this.topMargin_);

      // Div that holds the tiles.
      this.tileGrid_ = this.ownerDocument.createElement('div');
      this.tileGrid_.className = 'tile-grid';
      this.tileGrid_.style.minWidth = this.gridValues_.narrowWidth + 'px';
      this.tileGrid_.setAttribute('role', 'menu');
      this.tileGrid_.setAttribute(
          'aria-label',
          loadTimeData.getString(
              'tile_grid_screenreader_accessible_description'));

      this.content_.appendChild(this.tileGrid_);

      // Ordered list of our tiles.
      this.tileElements_ = this.tileGrid_.getElementsByClassName('tile real');
      // Ordered list of the elements which want to accept keyboard focus. These
      // elements will not be a part of the normal tab order; the tile grid
      // initially gets focused and then these elements can be focused via the
      // arrow keys.
      this.focusableElements_ =
          this.tileGrid_.getElementsByClassName('focusable');

      // These are properties used in updateTopMargin.
      this.animatedTopMarginPx_ = 0;
      this.topMarginPx_ = 0;

      this.eventTracker = new EventTracker();
      this.eventTracker.add(window, 'resize', this.onResize_.bind(this));

      this.addEventListener(
          'DOMNodeInsertedIntoDocument', this.onNodeInsertedIntoDocument_);

      this.content_.addEventListener('scroll', this.onScroll_.bind(this));

      this.dragWrapper_ = new cr.ui.DragWrapper(this.tileGrid_, this);

      this.addEventListener('cardselected', this.handleCardSelection_);
      this.addEventListener('carddeselected', this.handleCardDeselection_);
      this.addEventListener('focus', this.handleFocus_);
      this.addEventListener('keydown', this.handleKeyDown_);
      this.addEventListener('mousedown', this.handleMouseDown_);

      this.focusElementIndex_ = -1;
    },

    get tiles() {
      return this.tileElements_;
    },

    get tileCount() {
      return this.tileElements_.length;
    },

    get selected() {
      return Array.prototype.indexOf.call(this.parentNode.children, this) ==
          ntp.getCardSlider().currentCard;
    },

    /**
     * The size of the margin (unused space) on the sides of the tile grid, in
     * pixels.
     * @type {number}
     */
    get sideMargin() {
      return this.layoutValues_.leftMargin;
    },

    /**
     * Returns the width of the scrollbar, in pixels, if it is active, or 0
     * otherwise.
     * @type {number}
     */
    get scrollbarWidth() {
      return this.scrollbar_.hidden ? 0 : 13;
    },

    /**
     * Fetches the size, in pixels, of the padding-top of the tile contents.
     * @type {number}
     */
    get contentPadding() {
      if (typeof this.contentPadding_ == 'undefined') {
        this.contentPadding_ =
            parseInt(window.getComputedStyle(this.content_).paddingTop, 10);
      }
      return this.contentPadding_;
    },

    /**
     * Removes the tilePage from the DOM and cleans up event handlers.
     *
     * TODO(dbeam): this method now conflicts with HTMLElement#remove(). Rename.
     */
    remove: function() {
      // This checks arguments.length as most remove functions have a boolean
      // |opt_animate| argument, but that's not necesarilly applicable to
      // removing a tilePage. Selecting a different card in an animated way and
      // deleting the card afterward is probably a better choice.
      assert(
          typeof arguments[0] != 'boolean',
          'This function takes no |opt_animate| argument.');
      this.tearDown_();
      this.parentNode.removeChild(this);
    },

    /**
     * Cleans up resources that are no longer needed after this TilePage
     * instance is removed from the DOM.
     * @private
     */
    tearDown_: function() {
      this.eventTracker.removeAll();
    },

    /**
     * Appends a tile to the end of the tile grid.
     * @param {HTMLElement} tileElement The contents of the tile.
     * @param {boolean} animate If true, the append will be animated.
     * @protected
     */
    appendTile: function(tileElement, animate) {
      this.addTileAt(tileElement, this.tileElements_.length, animate);
    },

    /**
     * Adds the given element to the tile grid.
     * @param {Node} tileElement The tile object/node to insert.
     * @param {number} index The location in the tile grid to insert it at.
     * @param {boolean} animate If true, the tile in question will be
     *     animated (other tiles, if they must reposition, do not animate).
     * @protected
     */
    addTileAt: function(tileElement, index, animate) {
      this.classList.remove('animating-tile-page');
      if (animate) {
        tileElement.classList.add('new-tile-contents');
      }

      // Make sure the index is positive and either in the the bounds of
      // this.tileElements_ or at the end (meaning append).
      assert(index >= 0 && index <= this.tileElements_.length);

      const wrapperDiv = new Tile(tileElement);
      // If is out of the bounds of the tile element list, .insertBefore() will
      // act just like appendChild().
      this.tileGrid_.insertBefore(wrapperDiv, this.tileElements_[index]);
      this.calculateLayoutValues_();
      this.heightChanged_();

      this.repositionTiles_();

      // If this is the first tile being added, make it focusable after add.
      if (this.focusableElements_.length == 1) {
        this.updateFocusableElement();
      }
      this.fireAddedEvent(wrapperDiv, index, animate);
    },

    /**
     * Notify interested subscribers that a tile has been removed from this
     * page.
     * @param {ntp.Tile} tile The newly added tile.
     * @param {number} index The index of the tile that was added.
     * @param {boolean} wasAnimated Whether the removal was animated.
     */
    fireAddedEvent: function(tile, index, wasAnimated) {
      const e = document.createEvent('Event');
      e.initEvent('tilePage:tile_added', true, true);
      e.addedIndex = index;
      e.addedTile = tile;
      e.wasAnimated = wasAnimated;
      this.dispatchEvent(e);
    },

    /**
     * Removes the given tile and animates the repositioning of the other tiles.
     * @param {boolean=} opt_animate Whether the removal should be animated.
     * @param {boolean=} opt_dontNotify Whether a page should be removed if the
     *     last tile is removed from it.
     */
    removeTile: function(tile, opt_animate, opt_dontNotify) {
      if (opt_animate) {
        this.classList.add('animating-tile-page');
      }

      const index = tile.index;
      tile.parentNode.removeChild(tile);
      this.calculateLayoutValues_();
      this.cleanupDrag();
      this.updateFocusableElement();

      if (!opt_dontNotify) {
        this.fireRemovedEvent(tile, index, !!opt_animate);
      }
    },

    /**
     * Notify interested subscribers that a tile has been removed from this
     * page.
     * @param {ntp.Tile} tile The tile that was removed.
     * @param {number} oldIndex Where the tile was positioned before removal.
     * @param {boolean} wasAnimated Whether the removal was animated.
     */
    fireRemovedEvent: function(tile, oldIndex, wasAnimated) {
      const e = document.createEvent('Event');
      e.initEvent('tilePage:tile_removed', true, true);
      e.removedIndex = oldIndex;
      e.removedTile = tile;
      e.wasAnimated = wasAnimated;
      this.dispatchEvent(e);
    },

    /**
     * Removes all tiles from the page.
     */
    removeAllTiles: function() {
      this.tileGrid_.innerHTML = '';
    },

    /**
     * Called when the page is selected (in the card selector).
     * @param {Event} e A custom cardselected event.
     * @private
     */
    handleCardSelection_: function(e) {
      this.updateFocusableElement();

      // When we are selected, we re-calculate the layout values. (See comment
      // in doDrop.)
      this.calculateLayoutValues_();
    },

    /**
     * Called when the page loses selection (in the card selector).
     * @param {Event} e A custom carddeselected event.
     * @private
     */
    handleCardDeselection_: function(e) {
      if (this.currentFocusElement_) {
        this.currentFocusElement_.tabIndex = -1;
      }
    },

    /**
     * When we get focus, pass it on to the focus element.
     * @param {Event} e The focus event.
     * @private
     */
    handleFocus_: function(e) {
      if (this.focusableElements_.length == 0) {
        return;
      }

      this.updateFocusElement_();
    },

    /**
     * Since we are doing custom focus handling, we have to manually
     * set focusability on click (as well as keyboard nav above).
     * @param {Event} e The focus event.
     * @private
     */
    handleMouseDown_: function(e) {
      const focusable =
          findAncestorByClass(/** @type {Element} */ (e.target), 'focusable');
      if (focusable) {
        this.focusElementIndex_ =
            Array.prototype.indexOf.call(this.focusableElements_, focusable);
        this.updateFocusElement_();
      }
    },

    /**
     * Handle arrow key focus nav.
     * @param {Event} e The focus event.
     * @private
     */
    handleKeyDown_: function(e) {
      // We only handle up, down, left, right without control keys.
      if (e.metaKey || e.shiftKey || e.altKey || e.ctrlKey) {
        return;
      }

      // Wrap the given index to |this.focusableElements_|.
      const wrap = function(idx) {
        return (idx + this.focusableElements_.length) %
            this.focusableElements_.length;
      }.bind(this);

      let direction;
      switch (e.key) {
        case 'ArrowRight':
        case 'ArrowLeft':
          direction = e.key == 'ArrowRight' ? 1 : -1;
          this.focusElementIndex_ = wrap(this.focusElementIndex_ + direction);
          break;
        case 'ArrowUp':
        case 'ArrowDown':
          // Look through all focusable elements. Find the first one that is
          // in the same column.
          direction = e.key == 'ArrowUp' ? -1 : 1;
          const currentIndex = Array.prototype.indexOf.call(
              this.focusableElements_, this.currentFocusElement_);
          let newFocusIdx = wrap(currentIndex + direction);
          const tile = this.currentFocusElement_.parentNode;
          for (;; newFocusIdx = wrap(newFocusIdx + direction)) {
            const newTile = this.focusableElements_[newFocusIdx].parentNode;
            const rowTiles = this.layoutValues_.numRowTiles;
            if ((newTile.index - tile.index) % rowTiles == 0) {
              break;
            }
          }

          this.focusElementIndex_ = newFocusIdx;
          break;

        default:
          return;
      }

      this.updateFocusElement_();

      e.preventDefault();
      e.stopPropagation();
    },

    /**
     * Ensure 0 <= this.focusElementIndex_ < this.focusableElements_.length,
     * make the focusable element at this.focusElementIndex_ (if any) eligible
     * for tab focus, and the previously-focused element not eligible.
     * @protected
     */
    updateFocusableElement: function() {
      if (this.focusableElements_.length == 0 || !this.selected) {
        this.focusElementIndex_ = -1;
        return;
      }

      this.focusElementIndex_ =
          Math.min(this.focusableElements_.length - 1, this.focusElementIndex_);
      this.focusElementIndex_ = Math.max(0, this.focusElementIndex_);

      const newFocusElement = this.focusableElements_[this.focusElementIndex_];
      const lastFocusElement = this.currentFocusElement_;
      if (lastFocusElement && lastFocusElement != newFocusElement) {
        lastFocusElement.tabIndex = -1;
      }

      newFocusElement.tabIndex = 1;
    },

    /**
     * Focuses the element at |this.focusElementIndex_|. Makes the previous
     * focus element, if any, no longer eligible for tab focus.
     * @private
     */
    updateFocusElement_: function() {
      this.updateFocusableElement();
      if (this.focusElementIndex_ >= 0) {
        this.focusableElements_[this.focusElementIndex_].focus();
      }
    },

    /**
     * The current focus element is that element which is eligible for focus.
     * @type {HTMLElement} The node.
     * @private
     */
    get currentFocusElement_() {
      return this.querySelector('.focusable[tabindex="1"]');
    },

    /**
     * Makes some calculations for tile layout. These change depending on
     * height, width, and the number of tiles.
     * TODO(estade): optimize calls to this function. Do nothing if the page is
     * hidden, but call before being shown.
     * @private
     */
    calculateLayoutValues_: function() {
      const grid = this.gridValues_;
      const availableSpace = this.tileGrid_.clientWidth - 2 * MIN_WIDE_MARGIN;
      const wide = availableSpace >= grid.minWideWidth;
      const numRowTiles = wide ? grid.maxColCount : grid.minColCount;

      const effectiveGridWidth = wide ?
          Math.min(
              Math.max(availableSpace, grid.minWideWidth), grid.maxWideWidth) :
          grid.narrowWidth;
      const realTileValues = tileValuesForGrid(
          effectiveGridWidth, numRowTiles, grid.tileSpacingFraction);

      // leftMargin centers the grid within the avaiable space.
      const minMargin = wide ? MIN_WIDE_MARGIN : 0;
      const leftMargin = Math.max(
          minMargin, (this.tileGrid_.clientWidth - effectiveGridWidth) / 2);

      const rowHeight = this.heightForWidth(realTileValues.tileWidth) +
          realTileValues.interTileSpacing;

      this.layoutValues_ = {
        colWidth: realTileValues.offsetX,
        gridWidth: effectiveGridWidth,
        leftMargin: leftMargin,
        numRowTiles: numRowTiles,
        rowHeight: rowHeight,
        tileWidth: realTileValues.tileWidth,
        wide: wide,
      };

      // We need to update the top margin as well.
      this.updateTopMargin_();

      this.firePageLayoutEvent_();
    },

    /**
     * Dispatches the custom pagelayout event.
     * @private
     */
    firePageLayoutEvent_: function() {
      cr.dispatchSimpleEvent(this, 'pagelayout', true, true);
    },

    /**
     * @return {number} The amount of margin that should be animated (in pixels)
     *     for the current grid layout.
     */
    getAnimatedLeftMargin_: function() {
      if (this.layoutValues_.wide) {
        return 0;
      }

      const grid = this.gridValues_;
      return (grid.minWideWidth - MIN_WIDE_MARGIN - grid.narrowWidth) / 2;
    },

    /**
     * Calculates the x/y coordinates for an element and moves it there.
     * @param {number} index The index of the element to be positioned.
     * @param {number=} opt_indexOffset If provided, this is added to |index|
     *     when positioning the tile. The effect is that the tile will be
     *     positioned in a non-default location.
     * @private
     */
    positionTile_: function(index, opt_indexOffset) {
      const grid = this.gridValues_;
      const layout = this.layoutValues_;

      const indexOffset = opt_indexOffset || 0;
      // Add the offset _after_ the modulus division. We might want to show the
      // tile off the side of the grid.
      const col = index % layout.numRowTiles + indexOffset;
      const row = Math.floor(index / layout.numRowTiles);
      // Calculate the final on-screen position for the tile.
      const realX = col * layout.colWidth + layout.leftMargin;
      const realY = row * layout.rowHeight;

      // Calculate the portion of the tile's position that should be animated.
      const animatedTileValues =
          layout.wide ? grid.wideTileValues : grid.narrowTileValues;
      // Animate the difference between three-wide and six-wide.
      const animatedLeftMargin = this.getAnimatedLeftMargin_();
      const animatedX = col * animatedTileValues.offsetX + animatedLeftMargin;
      const animatedY = row *
          (this.heightForWidth(animatedTileValues.tileWidth) +
           animatedTileValues.interTileSpacing);

      const tile = this.tileElements_[index];
      tile.setGridPosition(animatedX, animatedY);
      tile.firstChild.setBounds(
          layout.tileWidth, realX - animatedX, realY - animatedY);

      // This code calculates whether the tile needs to show a clone of itself
      // wrapped around the other side of the tile grid.
      const offTheRight = col == layout.numRowTiles ||
          (col == layout.numRowTiles - 1 && tile.hasDoppleganger());
      const offTheLeft = col == -1 || (col == 0 && tile.hasDoppleganger());
      if (this.isCurrentDragTarget && (offTheRight || offTheLeft)) {
        const sign = offTheRight ? 1 : -1;
        tile.showDoppleganger(
            -layout.numRowTiles * layout.colWidth * sign,
            layout.rowHeight * sign);
      } else {
        tile.clearDoppleganger();
      }

      if (index == this.tileElements_.length - 1) {
        this.tileGrid_.style.height = (realY + layout.rowHeight) + 'px';
        this.queueUpdateScrollbars_();
      }
    },

    /**
     * Gets the index of the tile that should occupy coordinate (x, y). Note
     * that this function doesn't care where the tiles actually are, and will
     * return an index even for the space between two tiles. This function is
     * effectively the inverse of |positionTile_|.
     * @param {number} x The x coordinate, in pixels, relative to the left of
     *     |this|.
     * @param {number} y The y coordinate, in pixels, relative to the top of
     *     |this|.
     * @return {number}
     * @private
     */
    getWouldBeIndexForPoint_: function(x, y) {
      const grid = this.gridValues_;
      const layout = this.layoutValues_;

      const gridClientRect = this.tileGrid_.getBoundingClientRect();
      let col = Math.floor(
          (x - gridClientRect.left - layout.leftMargin) / layout.colWidth);
      if (col < 0 || col >= layout.numRowTiles) {
        return -1;
      }

      if (isRTL()) {
        col = layout.numRowTiles - 1 - col;
      }

      const row = Math.floor((y - gridClientRect.top) / layout.rowHeight);
      return row * layout.numRowTiles + col;
    },

    /**
     * Window resize event handler. Window resizes may trigger re-layouts.
     * @param {Object} e The resize event.
     */
    onResize_: function(e) {
      if (this.lastWidth_ == this.clientWidth &&
          this.lastHeight_ == this.clientHeight) {
        return;
      }

      this.calculateLayoutValues_();

      this.lastWidth_ = this.clientWidth;
      this.lastHeight_ = this.clientHeight;
      this.classList.add('animating-tile-page');
      this.heightChanged_();

      this.repositionTiles_();
    },

    /**
     * The tile grid has an image mask which fades at the edges. We only show
     * the mask when there is an active drag; it obscures doppleganger tiles
     * as they enter or exit the grid.
     * @private
     */
    updateMask_: function() {
      if (!this.isCurrentDragTarget) {
        this.tileGrid_.style.WebkitMaskBoxImage = '';
        return;
      }

      const leftMargin = this.layoutValues_.leftMargin;
      // The fade distance is the space between tiles.
      let fadeDistance =
          (this.gridValues_.tileSpacingFraction * this.layoutValues_.tileWidth);
      fadeDistance = Math.min(leftMargin, fadeDistance);
      // On Skia we don't use any fade because it works very poorly. See
      // http://crbug.com/99373
      if (!cr.isMac) {
        fadeDistance = 1;
      }
      const gradient = '-webkit-linear-gradient(left,' +
          'transparent, ' +
          'transparent ' + (leftMargin - fadeDistance) + 'px, ' +
          'black ' + leftMargin + 'px, ' +
          'black ' + (this.tileGrid_.clientWidth - leftMargin) + 'px, ' +
          'transparent ' +
          (this.tileGrid_.clientWidth - leftMargin + fadeDistance) + 'px, ' +
          'transparent)';
      this.tileGrid_.style.WebkitMaskBoxImage = gradient;
    },

    updateTopMargin_: function() {
      const layout = this.layoutValues_;

      // The top margin is set so that the vertical midpoint of the grid will
      // be 1/3 down the page.
      const numTiles = this.tileCount +
          (this.isCurrentDragTarget && !this.withinPageDrag_ ? 1 : 0);
      const numRows = Math.max(1, Math.ceil(numTiles / layout.numRowTiles));
      const usedHeight = layout.rowHeight * numRows;
      let newMargin = document.documentElement.clientHeight / 3 -
          usedHeight / 3 - this.contentPadding;
      // The 'height' style attribute of topMargin is non-zero to work around
      // webkit's collapsing margin behavior, so we have to factor that into
      // our calculations here.
      newMargin = Math.max(newMargin, 0) - this.topMargin_.offsetHeight;

      // |newMargin| is the final margin we actually want to show. However,
      // part of that should be animated and part should not (for the same
      // reason as with leftMargin). The approach is to consider differences
      // when the layout changes from wide to narrow or vice versa as
      // 'animatable'. These differences accumulate in animatedTopMarginPx_,
      // while topMarginPx_ caches the real (total) margin. Either of these
      // calculations may come out to be negative, so we use margins as the
      // css property.

      if (typeof this.topMarginIsForWide_ == 'undefined') {
        this.topMarginIsForWide_ = layout.wide;
      }
      if (this.topMarginIsForWide_ != layout.wide) {
        this.animatedTopMarginPx_ += newMargin - this.topMarginPx_;
        this.topMargin_.style.marginBottom = toCssPx(this.animatedTopMarginPx_);
      }

      this.topMarginIsForWide_ = layout.wide;
      this.topMarginPx_ = newMargin;
      this.topMargin_.style.marginTop =
          toCssPx(this.topMarginPx_ - this.animatedTopMarginPx_);
    },

    /**
     * Handles final setup that can only happen after |this| is inserted into
     * the page.
     * @private
     */
    onNodeInsertedIntoDocument_: function(e) {
      this.calculateLayoutValues_();
      this.heightChanged_();
    },

    /**
     * Called when the height of |this| has changed: update the size of
     * tileGrid.
     * @private
     */
    heightChanged_: function() {
      // The tile grid will expand to the bottom footer, or enough to hold all
      // the tiles, whichever is greater. It would be nicer if tilePage were
      // a flex box, and the tile grid could be box-flex: 1, but this exposes a
      // bug where repositioning tiles will cause the scroll position to reset.
      this.tileGrid_.style.minHeight = this.clientHeight -
          this.tileGrid_.offsetTop - this.content_.offsetTop + 'px';
    },

    /**
     * Scrolls the page in response to an mousewheel event, although the event
     * may have been triggered on a different element. Return true if the
     * event triggered scrolling, and false otherwise.
     * This is called explicitly, which allows a consistent experience whether
     * the user scrolls on the page or on the page switcher, because this
     * function provides a common conversion factor between wheel delta and
     * scroll delta.
     * @param {Event} e The mousewheel event.
     */
    handleMouseWheel: function(e) {
      // The ctrl-wheel should triggle the zoom in/out actions in Chromium for
      // all pages.
      if (e.wheelDeltaY == 0 || e.ctrlKey) {
        return false;
      }

      this.content_.scrollTop -= e.wheelDeltaY / 3;
      return true;
    },

    /**
     * Handler for the 'scroll' event on |content_|.
     * @param {Event} e The scroll event.
     * @private
     */
    onScroll_: function(e) {
      this.queueUpdateScrollbars_();
    },

    /**
     * ID of scrollbar update timer. If 0, there's no scrollbar re-calc queued.
     * @private
     */
    scrollbarUpdate_: 0,

    /**
     * Queues an update on the custom scrollbar. Used for two reasons: first,
     * coalescing of multiple updates, and second, because action like
     * repositioning a tile can require a delay before they affect values
     * like clientHeight.
     * @private
     */
    queueUpdateScrollbars_: function() {
      if (this.scrollbarUpdate_) {
        return;
      }

      this.scrollbarUpdate_ =
          window.setTimeout(this.doUpdateScrollbars_.bind(this), 0);
    },

    /**
     * Does the work of calculating the visibility, height and position of the
     * scrollbar thumb (there is no track or buttons).
     * @private
     */
    doUpdateScrollbars_: function() {
      this.scrollbarUpdate_ = 0;

      const content = this.content_;

      // Adjust scroll-height to account for possible header-bar.
      const adjustedScrollHeight = content.scrollHeight - content.offsetTop;

      if (adjustedScrollHeight <= content.clientHeight) {
        this.scrollbar_.hidden = true;
        return;
      } else {
        this.scrollbar_.hidden = false;
      }

      const thumbTop = content.offsetTop +
          content.scrollTop / adjustedScrollHeight * content.clientHeight;
      const thumbHeight =
          content.clientHeight / adjustedScrollHeight * this.clientHeight;

      this.scrollbar_.style.top = thumbTop + 'px';
      this.scrollbar_.style.height = thumbHeight + 'px';
      this.firePageLayoutEvent_();
    },

    /**
     * Get the height for a tile of a certain width. Override this function to
     * get non-square tiles.
     * @param {number} width The pixel width of a tile.
     * @return {number} The height for |width|.
     */
    heightForWidth: function(width) {
      return width;
    },

    /** Dragging **/

    get isCurrentDragTarget() {
      return this.dragWrapper_.isCurrentDragTarget;
    },

    /** @override */
    doDragLeave: function(e) {
      this.cleanupDrag();
    },

    /** @override */
    doDragEnter: function(e) {
      // Applies the mask so doppleganger tiles disappear into the fog.
      this.updateMask_();

      this.classList.add('animating-tile-page');
      this.withinPageDrag_ = this.contains(currentlyDraggingTile);
      this.dragItemIndex_ = this.withinPageDrag_ ? currentlyDraggingTile.index :
                                                   this.tileElements_.length;
      this.currentDropIndex_ = this.dragItemIndex_;

      // The new tile may change the number of rows, hence the top margin
      // will change.
      if (!this.withinPageDrag_) {
        this.updateTopMargin_();
      }

      this.doDragOver(e);
    },

    /** @override */
    doDragOver: function(e) {
      e.preventDefault();

      this.setDropEffect(e.dataTransfer);
      let newDragIndex = this.getWouldBeIndexForPoint_(e.pageX, e.pageY);
      if (newDragIndex < 0 || newDragIndex >= this.tileElements_.length) {
        newDragIndex = this.dragItemIndex_;
      }
      this.updateDropIndicator_(newDragIndex);
    },

    /** @override */
    doDrop: function(e) {
      e.stopPropagation();
      e.preventDefault();

      const index = this.currentDropIndex_;
      // Only change data if this was not a 'null drag'.
      if (!((index == this.dragItemIndex_) && this.withinPageDrag_)) {
        const adjustedIndex =
            this.currentDropIndex_ + (index > this.dragItemIndex_ ? 1 : 0);
        if (this.withinPageDrag_) {
          this.tileGrid_.insertBefore(
              currentlyDraggingTile, this.tileElements_[adjustedIndex]);
          this.tileMoved(currentlyDraggingTile, this.dragItemIndex_);
        } else {
          const originalPage =
              currentlyDraggingTile ? currentlyDraggingTile.tilePage : null;
          this.addDragData(e.dataTransfer, adjustedIndex);
          if (originalPage) {
            originalPage.cleanupDrag();
          }
        }

        // Dropping the icon may cause topMargin to change, but changing it
        // now would cause everything to move (annoying), so we leave it
        // alone. The top margin will be re-calculated next time the window is
        // resized or the page is selected.
      }

      this.classList.remove('animating-tile-page');
      this.cleanupDrag();
    },

    /**
     * Appends the currently dragged tile to the end of the page. Called
     * from outside the page, e.g. when dropping on a nav dot.
     */
    appendDraggingTile: function() {
      const originalPage = currentlyDraggingTile.tilePage;
      if (originalPage == this) {
        return;
      }

      this.addDragData(null, this.tileElements_.length);
      if (originalPage) {
        originalPage.cleanupDrag();
      }
    },

    /**
     * Makes sure all the tiles are in the right place after a drag is over.
     */
    cleanupDrag: function() {
      this.repositionTiles_(currentlyDraggingTile);
      // Remove the drag mask.
      this.updateMask_();
    },

    /**
     * Reposition all the tiles (possibly ignoring one).
     * @param {Node=} opt_ignoreNode An optional node to ignore.
     * @private
     */
    repositionTiles_: function(opt_ignoreNode) {
      for (let i = 0; i < this.tileElements_.length; i++) {
        if (!opt_ignoreNode || opt_ignoreNode !== this.tileElements_[i]) {
          this.positionTile_(i);
        }
      }
    },

    /**
     * Updates the visual indicator for the drop location for the active drag.
     * @param {number} newDragIndex
     * @private
     */
    updateDropIndicator_: function(newDragIndex) {
      const oldDragIndex = this.currentDropIndex_;
      if (newDragIndex == oldDragIndex) {
        return;
      }

      const repositionStart = Math.min(newDragIndex, oldDragIndex);
      const repositionEnd = Math.max(newDragIndex, oldDragIndex);

      for (let i = repositionStart; i <= repositionEnd; i++) {
        if (i == this.dragItemIndex_) {
          continue;
        }

        const adjustment = i > this.dragItemIndex_ ?
            i <= newDragIndex ? -1 : 0 :
            i >= newDragIndex ? 1 : 0;
        this.positionTile_(i, adjustment);
      }
      this.currentDropIndex_ = newDragIndex;
    },

    /**
     * Checks if a page can accept a drag with the given data.
     * @param {Event} e The drag event if the drag object. Implementations will
     *     likely want to check |e.dataTransfer|.
     * @return {boolean} True if this page can handle the drag.
     */
    shouldAcceptDrag: function(e) {
      return false;
    },

    /**
     * Called to accept a drag drop. Will not be called for in-page drops.
     * @param {Object} dataTransfer The data transfer object that holds the drop
     *     data. This should only be used if currentlyDraggingTile is null.
     * @param {number} index The tile index at which the drop occurred.
     */
    addDragData: function(dataTransfer, index) {
      assertNotReached();
    },

    /**
     * Called when a tile has been moved (via dragging). Override this to make
     * backend updates.
     * @param {Node} draggedTile The tile that was dropped.
     * @param {number} prevIndex The previous index of the tile.
     */
    tileMoved: function(draggedTile, prevIndex) {},

    /**
     * Sets the drop effect on |dataTransfer| to the desired value (e.g.
     * 'copy').
     * @param {DataTransfer} dataTransfer The drag event dataTransfer object.
     */
    setDropEffect: function(dataTransfer) {
      assertNotReached();
    },
  };

  return {
    getCurrentlyDraggingTile: getCurrentlyDraggingTile,
    setCurrentDropEffect: setCurrentDropEffect,
    // Not used outside, just for usage in JSDoc inside this file.
    Tile: Tile,
    TilePage: TilePage,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('ntp', function() {
  'use strict';

  const APP_LAUNCH = {
    // The histogram buckets (keep in sync with extension_constants.h).
    NTP_APPS_MAXIMIZED: 0,
    NTP_APPS_COLLAPSED: 1,
    NTP_APPS_MENU: 2,
    NTP_MOST_VISITED: 3,
    NTP_APP_RE_ENABLE: 16,
    NTP_WEBSTORE_FOOTER: 18,
    NTP_WEBSTORE_PLUS_ICON: 19,
  };

  // Histogram buckets for UMA tracking of where a DnD drop came from.
  const DRAG_SOURCE = {
    SAME_APPS_PANE: 0,
    OTHER_APPS_PANE: 1,
    MOST_VISITED_PANE: 2,  // Deprecated.
    BOOKMARKS_PANE: 3,     // Deprecated.
    OUTSIDE_NTP: 4
  };
  const DRAG_SOURCE_LIMIT = DRAG_SOURCE.OUTSIDE_NTP + 1;

  // The fraction of the app tile size that the icon uses.
  const APP_IMG_SIZE_FRACTION = 4 / 5;

  /**
   * App context menu. The class is designed to be used as a singleton with
   * the app that is currently showing a context menu stored in this.app_.
   * @constructor
   */
  function AppContextMenu() {
    this.__proto__ = AppContextMenu.prototype;
    this.initialize();
  }
  cr.addSingletonGetter(AppContextMenu);

  AppContextMenu.prototype = {
    initialize: function() {
      const menu = new cr.ui.Menu;
      cr.ui.decorate(menu, cr.ui.Menu);
      menu.classList.add('app-context-menu');
      this.menu = menu;

      this.launch_ = this.appendMenuItem_();
      this.launch_.addEventListener('activate', this.onActivate_.bind(this));

      menu.appendChild(cr.ui.MenuItem.createSeparator());
      this.launchRegularTab_ = this.appendMenuItem_('applaunchtyperegular');
      this.launchPinnedTab_ = this.appendMenuItem_('applaunchtypepinned');
      if (loadTimeData.getBoolean('canHostedAppsOpenInWindows')) {
        this.launchNewWindow_ = this.appendMenuItem_('applaunchtypewindow');
      }
      this.launchFullscreen_ = this.appendMenuItem_('applaunchtypefullscreen');

      const self = this;
      this.forAllLaunchTypes_(function(launchTypeButton, id) {
        launchTypeButton.addEventListener(
            'activate', self.onLaunchTypeChanged_.bind(self));
      });

      this.launchTypeMenuSeparator_ = cr.ui.MenuItem.createSeparator();
      menu.appendChild(this.launchTypeMenuSeparator_);
      this.options_ = this.appendMenuItem_('appoptions');
      this.uninstall_ = this.appendMenuItem_('appuninstall');

      if (loadTimeData.getBoolean('canShowAppInfoDialog')) {
        this.appinfo_ = this.appendMenuItem_('appinfodialog');
        this.appinfo_.addEventListener(
            'activate', this.onShowAppInfo_.bind(this));
      } else {
        this.details_ = this.appendMenuItem_('appdetails');
        this.details_.addEventListener(
            'activate', this.onShowDetails_.bind(this));
      }

      this.options_.addEventListener(
          'activate', this.onShowOptions_.bind(this));
      this.uninstall_.addEventListener(
          'activate', this.onUninstall_.bind(this));

      this.createShortcutSeparator_ =
          menu.appendChild(cr.ui.MenuItem.createSeparator());
      this.createShortcut_ = this.appendMenuItem_('appcreateshortcut');
      this.createShortcut_.addEventListener(
          'activate', this.onCreateShortcut_.bind(this));

      document.body.appendChild(menu);
    },

    /**
     * Appends a menu item to |this.menu|.
     * @param {string=} opt_textId If defined, the ID for the localized string
     *     that acts as the item's label.
     * @private
     */
    appendMenuItem_: function(opt_textId) {
      const button = cr.doc.createElement('button');
      this.menu.appendChild(button);
      cr.ui.decorate(button, cr.ui.MenuItem);
      if (opt_textId) {
        button.textContent = loadTimeData.getString(opt_textId);
      }
      return button;
    },

    /**
     * Iterates over all the launch type menu items.
     * @param {function(cr.ui.MenuItem, number)} f The function to call for each
     *     menu item. The parameters to the function include the menu item and
     *     the associated launch ID.
     * @private
     */
    forAllLaunchTypes_: function(f) {
      // Order matters: index matches launchType id.
      const launchTypes = [
        this.launchPinnedTab_, this.launchRegularTab_, this.launchFullscreen_,
        this.launchNewWindow_
      ];

      for (let i = 0; i < launchTypes.length; ++i) {
        if (!launchTypes[i]) {
          continue;
        }

        f(launchTypes[i], i);
      }
    },

    /**
     * Does all the necessary setup to show the menu for the given app.
     * @param {ntp.App} app The App object that will be showing a context menu.
     */
    setupForApp: function(app) {
      this.app_ = app;

      this.launch_.textContent = app.appData.title;

      const launchTypeWindow = this.launchNewWindow_;
      let hasLaunchType = false;
      this.forAllLaunchTypes_(function(launchTypeButton, id) {
        launchTypeButton.disabled = false;
        launchTypeButton.checked = app.appData.launch_type == id;
        // There are three cases when a launch type is hidden:
        //  1. if the launch type can't be changed.
        //  2. canHostedAppsOpenInWindows is false and type is launchTypeWindow
        //  3. enableNewBookmarkApps is true and type is anything except
        //     launchTypeWindow
        launchTypeButton.hidden = !app.appData.mayChangeLaunchType ||
            (!loadTimeData.getBoolean('canHostedAppsOpenInWindows') &&
             launchTypeButton == launchTypeWindow) ||
            (loadTimeData.getBoolean('enableNewBookmarkApps') &&
             launchTypeButton != launchTypeWindow);
        if (!launchTypeButton.hidden) {
          hasLaunchType = true;
        }
      });

      this.launchTypeMenuSeparator_.hidden =
          !app.appData.mayChangeLaunchType || !hasLaunchType;

      this.options_.disabled = !app.appData.optionsUrl || !app.appData.enabled;
      if (this.details_) {
        this.details_.disabled = !app.appData.detailsUrl;
      }
      this.uninstall_.disabled = !app.appData.mayDisable;
      if (this.appinfo_) {
        this.appinfo_.hidden = !app.appData.isLocallyInstalled;
      }

      this.createShortcutSeparator_.hidden = this.createShortcut_.hidden =
          !app.appData.mayCreateShortcuts;
    },

    /** @private */
    onActivate_: function() {
      chrome.send('launchApp', [this.app_.appId, APP_LAUNCH.NTP_APPS_MENU]);
    },

    /**
     * @param {Event} e
     * @private
     */
    onLaunchTypeChanged_: function(e) {
      const pressed = e.currentTarget;
      const app = this.app_;
      let targetLaunchType = pressed;
      // When bookmark apps are enabled, hosted apps can only toggle between
      // open as window and open as tab.
      if (loadTimeData.getBoolean('enableNewBookmarkApps')) {
        targetLaunchType = this.launchNewWindow_.checked ?
            this.launchRegularTab_ :
            this.launchNewWindow_;
      }
      this.forAllLaunchTypes_(function(launchTypeButton, id) {
        if (launchTypeButton == targetLaunchType) {
          chrome.send('setLaunchType', [app.appId, id]);
          // Manually update the launch type. We will only get
          // appsPrefChangeCallback calls after changes to other NTP instances.
          app.appData.launch_type = id;
        }
      });
    },

    /** @private */
    onShowOptions_: function() {
      window.location = this.app_.appData.optionsUrl;
    },

    /** @private */
    onShowDetails_: function() {
      let url = this.app_.appData.detailsUrl;
      url = appendParam(url, 'utm_source', 'chrome-ntp-launcher');
      window.location = url;
    },

    /** @private */
    onUninstall_: function() {
      chrome.send('uninstallApp', [this.app_.appData.id]);
    },

    /** @private */
    onCreateShortcut_: function() {
      chrome.send('createAppShortcut', [this.app_.appData.id]);
    },

    /** @private */
    onShowAppInfo_: function() {
      chrome.send('showAppInfo', [this.app_.appData.id]);
    }
  };

  /**
   * Creates a new App object.
   * @param {Object} appData The data object that describes the app.
   * @constructor
   * @extends {HTMLDivElement}
   */
  function App(appData) {
    const el = cr.doc.createElement('div');
    el.__proto__ = App.prototype;
    el.initialize(appData);

    return el;
  }

  App.prototype = {
    __proto__: HTMLDivElement.prototype,

    /**
     * Initialize the app object.
     * @param {Object} appData The data object that describes the app.
     */
    initialize: function(appData) {
      this.appData = appData;
      assert(this.appData_.id, 'Got an app without an ID');
      this.id = this.appData_.id;
      this.setAttribute('role', 'menuitem');

      this.className = 'app focusable';

      if (!this.appData_.icon_big_exists && this.appData_.icon_small_exists) {
        this.useSmallIcon_ = true;
      }

      this.appContents_ = (this.useSmallIcon_ ? $('app-small-icon-template') :
                                                $('app-large-icon-template'))
                              .cloneNode(true);
      this.appContents_.id = '';
      this.appendChild(this.appContents_);

      this.appImgContainer_ =
          /** @type {HTMLElement} */ (this.querySelector('.app-img-container'));
      this.appImg_ = this.appImgContainer_.querySelector('img');
      this.setIcon();

      if (this.useSmallIcon_) {
        this.imgDiv_ =
            /** @type {HTMLElement} */ (this.querySelector('.app-icon-div'));
        this.addLaunchClickTarget_(this.imgDiv_);
        this.imgDiv_.title = this.appData_.full_name;
        chrome.send('getAppIconDominantColor', [this.id]);
      } else {
        this.addLaunchClickTarget_(this.appImgContainer_);
        this.appImgContainer_.title = this.appData_.full_name;
      }

      // The app's full name is shown in the tooltip, whereas the short name
      // is used for the label.
      const appSpan = /** @type {HTMLElement} */ (
          this.appContents_.querySelector('.title'));
      appSpan.textContent = this.appData_.title;
      appSpan.title = this.appData_.full_name;
      this.addLaunchClickTarget_(appSpan);

      this.addEventListener('keydown', cr.ui.contextMenuHandler);
      this.addEventListener('keyup', cr.ui.contextMenuHandler);

      // This hack is here so that appContents.contextMenu will be the same as
      // this.contextMenu.
      const self = this;
      this.appContents_.__defineGetter__('contextMenu', function() {
        return self.contextMenu;
      });

      if (!this.appData_.kioskMode) {
        this.appContents_.addEventListener(
            'contextmenu', cr.ui.contextMenuHandler);
      }

      this.addEventListener('mousedown', this.onMousedown_, true);
      this.addEventListener('keydown', this.onKeydown_);
      this.addEventListener('blur', this.onBlur_);
    },

    /**
     * Sets the color of the favicon dominant color bar.
     * @param {string} color The css-parsable value for the color.
     */
    set stripeColor(color) {
      this.querySelector('.color-stripe').style.backgroundColor = color;
    },

    /**
     * Removes the app tile from the page. Should be called after the app has
     * been uninstalled.
     *
     * TODO(dbeam): this method now conflicts with HTMLElement#remove(), which
     * is why the param is optional. Rename.
     *
     * @param {boolean=} opt_animate Whether the removal should be animated.
     */
    remove: function(opt_animate) {
      // Unset the ID immediately, because the app is already gone. But leave
      // the tile on the page as it animates out.
      this.id = '';
      this.tile.doRemove(opt_animate);
    },

    /**
     * Set the URL of the icon from |appData_|. This won't actually show the
     * icon until loadIcon() is called (for performance reasons; we don't want
     * to load icons until we have to).
     */
    setIcon: function() {
      let src = this.useSmallIcon_ ? this.appData_.icon_small :
                                     this.appData_.icon_big;
      if (!this.appData_.enabled || !this.appData_.isLocallyInstalled ||
          (!this.appData_.offlineEnabled && !navigator.onLine)) {
        src += '?grayscale=true';
      }

      this.appImgSrc_ = src;
      this.classList.add('icon-loading');
    },

    /**
     * Shows the icon for the app. That is, it causes chrome to load the app
     * icon resource.
     */
    loadIcon: function() {
      if (this.appImgSrc_) {
        this.appImg_.src = this.appImgSrc_;
        this.appImg_.classList.remove('invisible');
        this.appImgSrc_ = null;
      }

      this.classList.remove('icon-loading');
    },

    /**
     * Set the size and position of the app tile.
     * @param {number} size The total size of |this|.
     * @param {number} x The x-position.
     * @param {number} y The y-position.
     *     animate.
     */
    setBounds: function(size, x, y) {
      const imgSize = size * APP_IMG_SIZE_FRACTION;
      this.appImgContainer_.style.width = this.appImgContainer_.style.height =
          toCssPx(this.useSmallIcon_ ? 16 : imgSize);
      if (this.useSmallIcon_) {
        // 3/4 is the ratio of 96px to 128px (the used height and full height
        // of icons in apps).
        const iconSize = imgSize * 3 / 4;
        // The -2 is for the div border to improve the visual alignment for the
        // icon div.
        this.imgDiv_.style.width = this.imgDiv_.style.height =
            toCssPx(iconSize - 2);
        // Margins set to get the icon placement right and the text to line up.
        this.imgDiv_.style.marginTop = this.imgDiv_.style.marginBottom =
            toCssPx((imgSize - iconSize) / 2);
      }

      this.style.width = this.style.height = toCssPx(size);
      this.style.left = toCssPx(x);
      this.style.right = toCssPx(x);
      this.style.top = toCssPx(y);
    },

    /** @private */
    onBlur_: function() {
      this.classList.remove('click-focus');
      this.appContents_.classList.remove('suppress-active');
    },

    /**
     * Invoked when an app is clicked.
     * @param {Event} e The click/auxclick event.
     * @private
     */
    onClick_: function(e) {
      if (/** @type {MouseEvent} */ (e).button > 1) {
        return;
      }

      chrome.send('launchApp', [
        this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, 'chrome-ntp-icon', e.button,
        e.altKey, e.ctrlKey, e.metaKey, e.shiftKey
      ]);

      // Don't allow the click to trigger a link or anything
      e.preventDefault();
    },

    /**
     * Invoked when the user presses a key while the app is focused.
     * @param {Event} e The key event.
     * @private
     */
    onKeydown_: function(e) {
      if (e.key == 'Enter') {
        chrome.send('launchApp', [
          this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, '', 0, e.altKey, e.ctrlKey,
          e.metaKey, e.shiftKey
        ]);
        e.preventDefault();
        e.stopPropagation();
      }
    },

    /**
     * Adds a node to the list of targets that will launch the app. This list
     * is also used in onMousedown to determine whether the app contents should
     * be shown as active (if we don't do this, then clicking anywhere in
     * appContents, even a part that is outside the ideally clickable region,
     * will cause the app icon to look active).
     * @param {HTMLElement} node The node that should be clickable.
     * @private
     */
    addLaunchClickTarget_: function(node) {
      node.classList.add('launch-click-target');
      node.addEventListener('click', this.onClick_.bind(this));
      node.addEventListener('auxclick', this.onClick_.bind(this));
    },

    /**
     * Handler for mousedown on the App. Adds a class that allows us to
     * not display as :active for right clicks (specifically, don't pulse on
     * these occasions). Also, we don't pulse for clicks that aren't within the
     * clickable regions.
     * @param {Event} e The mousedown event.
     * @private
     */
    onMousedown_: function(e) {
      // If the current platform uses middle click to autoscroll and this
      // mousedown isn't handled, onClick_() will never fire. crbug.com/142939
      if (e.button == 1) {
        e.preventDefault();
      }

      if (e.button == 2 ||
          !findAncestorByClass(
              /** @type {Element} */ (e.target), 'launch-click-target')) {
        this.appContents_.classList.add('suppress-active');
      } else {
        this.appContents_.classList.remove('suppress-active');
      }

      // This class is here so we don't show the focus state for apps that
      // gain keyboard focus via mouse clicking.
      this.classList.add('click-focus');
    },

    /**
     * Change the appData and update the appearance of the app.
     * @param {AppInfo} appData The new data object that describes the app.
     */
    replaceAppData: function(appData) {
      this.appData_ = appData;
      this.setIcon();
      this.loadIcon();
    },

    /**
     * The data and preferences for this app.
     * @type {Object}
     */
    set appData(data) {
      this.appData_ = data;
    },
    get appData() {
      return this.appData_;
    },

    /** @type {string} */
    get appId() {
      return this.appData_.id;
    },

    /**
     * Returns a pointer to the context menu for this app. All apps share the
     * singleton AppContextMenu. This function is called by the
     * ContextMenuHandler in response to the 'contextmenu' event.
     * @type {cr.ui.Menu}
     */
    get contextMenu() {
      const menu = AppContextMenu.getInstance();
      menu.setupForApp(this);
      return menu.menu;
    },

    /**
     * Returns whether this element can be 'removed' from chrome (i.e. whether
     * the user can drag it onto the trash and expect something to happen).
     * @return {boolean} True if the app can be uninstalled.
     */
    canBeRemoved: function() {
      return this.appData_.mayDisable;
    },

    /**
     * Uninstalls the app after it's been dropped on the trash.
     */
    removeFromChrome: function() {
      chrome.send('uninstallApp', [this.appData_.id, true]);
      this.tile.tilePage.removeTile(this.tile, true);
    },

    /**
     * Called when a drag is starting on the tile. Updates dataTransfer with
     * data for this tile.
     */
    setDragData: function(dataTransfer) {
      dataTransfer.setData('Text', this.appData_.title);
      dataTransfer.setData('URL', this.appData_.url);
    },
  };

  const TilePage = ntp.TilePage;

  const appsPageGridValues = {
    // The fewest tiles we will show in a row.
    minColCount: 3,
    // The most tiles we will show in a row.
    maxColCount: 6,

    // The smallest a tile can be.
    minTileWidth: 64 / APP_IMG_SIZE_FRACTION,
    // The biggest a tile can be.
    maxTileWidth: 128 / APP_IMG_SIZE_FRACTION,

    // The padding between tiles, as a fraction of the tile width.
    tileSpacingFraction: 1 / 8,
  };
  TilePage.initGridValues(appsPageGridValues);

  /**
   * Creates a new AppsPage object.
   * @constructor
   * @extends {ntp.TilePage}
   */
  function AppsPage() {
    const el = new TilePage(appsPageGridValues);
    el.__proto__ = AppsPage.prototype;
    el.initialize();

    return el;
  }

  AppsPage.prototype = {
    __proto__: TilePage.prototype,

    initialize: function() {
      this.classList.add('apps-page');

      this.addEventListener('cardselected', this.onCardSelected_);

      this.addEventListener('tilePage:tile_added', this.onTileAdded_);

      this.content_.addEventListener('scroll', this.onScroll_.bind(this));
    },

    /**
     * Highlight a newly installed app as it's added to the NTP.
     * @param {AppInfo} appData The data object that describes the app.
     */
    insertAndHighlightApp: function(appData) {
      ntp.getCardSlider().selectCardByValue(this);
      this.content_.scrollTop = this.content_.scrollHeight;
      this.insertApp(appData, true);
    },

    /**
     * Similar to appendApp, but it respects the app_launch_ordinal field of
     * |appData|.
     * @param {Object} appData The data that describes the app.
     * @param {boolean} animate Whether to animate the insertion.
     */
    insertApp: function(appData, animate) {
      let index = this.tileElements_.length;
      for (let i = 0; i < this.tileElements_.length; i++) {
        if (appData.app_launch_ordinal <
            this.tileElements_[i].firstChild.appData.app_launch_ordinal) {
          index = i;
          break;
        }
      }

      this.addTileAt(new App(appData), index, animate);
    },

    /**
     * Handler for 'cardselected' event, fired when |this| is selected. The
     * first time this is called, we load all the app icons.
     * @private
     */
    onCardSelected_: function() {
      const apps = /** @type {NodeList<ntp.App>} */ (
          this.querySelectorAll('.app.icon-loading'));
      for (let i = 0; i < apps.length; i++) {
        apps[i].loadIcon();
      }
    },

    /**
     * Handler for tile additions to this page.
     * @param {Event} e The tilePage:tile_added event.
     * @private
     */
    onTileAdded_: function(e) {
      assert(e.currentTarget == this);
      assert(e.addedTile.firstChild instanceof App);
      if (this.classList.contains('selected-card')) {
        e.addedTile.firstChild.loadIcon();
      }
    },

    /**
     * A handler for when the apps page is scrolled (then we need to reposition
     * the bubbles.
     * @private
     */
    onScroll_: function() {
      if (!this.selected) {
        return;
      }
      for (let i = 0; i < this.tileElements_.length; i++) {
        const app = this.tileElements_[i].firstChild;
        assert(app instanceof App);
      }
    },

    /** @override */
    doDragOver: function(e) {
      // Only animatedly re-arrange if the user is currently dragging an app.
      const tile = ntp.getCurrentlyDraggingTile();
      if (tile && tile.querySelector('.app')) {
        TilePage.prototype.doDragOver.call(this, e);
      } else {
        e.preventDefault();
        this.setDropEffect(e.dataTransfer);
      }
    },

    /** @override */
    shouldAcceptDrag: function(e) {
      if (ntp.getCurrentlyDraggingTile()) {
        return true;
      }
      if (!e.dataTransfer || !e.dataTransfer.types) {
        return false;
      }
      return Array.prototype.indexOf.call(
                 e.dataTransfer.types, 'text/uri-list') != -1;
    },

    /** @override */
    addDragData: function(dataTransfer, index) {
      let sourceId = -1;
      const currentlyDraggingTile = ntp.getCurrentlyDraggingTile();
      if (currentlyDraggingTile) {
        const tileContents = currentlyDraggingTile.firstChild;
        if (tileContents.classList.contains('app')) {
          const originalPage = currentlyDraggingTile.tilePage;
          const samePageDrag = originalPage == this;
          sourceId = samePageDrag ? DRAG_SOURCE.SAME_APPS_PANE :
                                    DRAG_SOURCE.OTHER_APPS_PANE;
          this.tileGrid_.insertBefore(
              currentlyDraggingTile, this.tileElements_[index]);
          this.tileMoved(currentlyDraggingTile);
          if (!samePageDrag) {
            originalPage.fireRemovedEvent(currentlyDraggingTile, index, true);
            this.fireAddedEvent(currentlyDraggingTile, index, true);
          }
        }
      } else {
        this.addOutsideData_(dataTransfer);
        sourceId = DRAG_SOURCE.OUTSIDE_NTP;
      }

      assert(sourceId != -1);
      chrome.send(
          'metricsHandler:recordInHistogram',
          ['NewTabPage.AppsPageDragSource', sourceId, DRAG_SOURCE_LIMIT]);
    },

    /**
     * Adds drag data that has been dropped from a source that is not a tile.
     * @param {Object} dataTransfer The data transfer object that holds drop
     *     data.
     * @private
     */
    addOutsideData_: function(dataTransfer) {
      const url = dataTransfer.getData('url');
      assert(url);

      // If the dataTransfer has html data, use that html's text contents as the
      // title of the new link.
      const html = dataTransfer.getData('text/html');
      let title;
      if (html) {
        // It's important that we don't attach this node to the document
        // because it might contain scripts.
        const doc = document.implementation.createHTMLDocument();
        doc.body.innerHTML = html;
        title = doc.body.textContent;
      }

      // Make sure title is >=1 and <=45 characters for Chrome app limits.
      if (!title) {
        title = url;
      }
      if (title.length > 45) {
        title = title.substring(0, 45);
      }
      const data = {url: url, title: title};

      // Synthesize an app.
      this.generateAppForLink(data);
    },

    /**
     * Creates a new crx-less app manifest and installs it.
     * @param {Object} data The data object describing the link. Must have |url|
     *     and |title| members.
     */
    generateAppForLink: function(data) {
      assert(data.url != undefined);
      assert(data.title != undefined);
      const pageIndex = ntp.getAppsPageIndex(this);
      chrome.send('generateAppForLink', [data.url, data.title, pageIndex]);
    },

    /** @override */
    tileMoved: function(draggedTile) {
      if (!(draggedTile.firstChild instanceof App)) {
        return;
      }

      const pageIndex = ntp.getAppsPageIndex(this);
      chrome.send('setPageIndex', [draggedTile.firstChild.appId, pageIndex]);

      const appIds = [];
      for (let i = 0; i < this.tileElements_.length; i++) {
        const tileContents = this.tileElements_[i].firstChild;
        if (tileContents instanceof App) {
          appIds.push(tileContents.appId);
        }
      }

      chrome.send('reorderApps', [draggedTile.firstChild.appId, appIds]);
    },

    /** @override */
    setDropEffect: function(dataTransfer) {
      const tile = ntp.getCurrentlyDraggingTile();
      if (tile && tile.querySelector('.app')) {
        ntp.setCurrentDropEffect(dataTransfer, 'move');
      } else {
        ntp.setCurrentDropEffect(dataTransfer, 'copy');
      }
    },
  };

  /**
   * Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE
   * histogram. This should only be invoked from the AppLauncherHandler.
   * @param {string} appId The ID of the app.
   */
  function launchAppAfterEnable(appId) {
    chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]);
  }

  return {
    APP_LAUNCH: APP_LAUNCH,
    App: App,
    AppsPage: AppsPage,
    launchAppAfterEnable: launchAppAfterEnable,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview DotList implementation
 */

cr.define('ntp', function() {
  'use strict';

  /**
   * Live list of the navigation dots.
   * @type {!NodeList|undefined}
   */
  let navDots;

  /**
   * Creates a new DotList object.
   * @constructor
   * @extends {HTMLUListElement}
   */
  const DotList = cr.ui.define('ul');

  DotList.prototype = {
    __proto__: HTMLUListElement.prototype,

    decorate: function() {
      this.addEventListener('keydown', this.onKeyDown_.bind(this));
      navDots = this.getElementsByClassName('dot');
    },

    /**
     * Live list of the navigation dots.
     * @type {!NodeList|undefined}
     */
    get dots() {
      return navDots;
    },

    /**
     * Handler for key events on the dot list. These keys will change the focus
     * element.
     * @param {!Event} e The KeyboardEvent.
     */
    onKeyDown_: function(e) {
      if (hasKeyModifiers(e)) {
        return;
      }

      let direction = 0;
      if (e.key == 'ArrowLeft') {
        direction = -1;
      } else if (e.key == 'ArrowRight') {
        direction = 1;
      } else {
        return;
      }

      const focusDot = this.querySelector('.dot:focus');
      if (!focusDot) {
        return;
      }
      const focusIndex = Array.prototype.indexOf.call(navDots, focusDot);
      let newFocusIndex = focusIndex + direction;
      if (focusIndex == newFocusIndex) {
        return;
      }

      newFocusIndex = (newFocusIndex + navDots.length) % navDots.length;
      navDots[newFocusIndex].tabIndex = 3;
      navDots[newFocusIndex].focus();
      focusDot.tabIndex = -1;

      e.stopPropagation();
      e.preventDefault();
    }
  };

  return {DotList: DotList};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Trash
 * This is the class for the trash can that appears when dragging an app.
 */

cr.define('ntp', function() {
  'use strict';

  /**
   * @constructor
   * @extends {HTMLDivElement}
   * @implements {cr.ui.DragWrapperDelegate}
   */
  function Trash(trash) {
    trash.__proto__ = Trash.prototype;
    trash.initialize();
    return trash;
  }

  Trash.prototype = {
    __proto__: HTMLDivElement.prototype,

    initialize: function(element) {
      this.dragWrapper_ = new cr.ui.DragWrapper(this, this);
    },

    /**
     * Determines whether we are interested in the drag data for |e|.
     * @param {Event} e The event from drag enter.
     * @return {boolean} True if we are interested in the drag data for |e|.
     */
    shouldAcceptDrag: function(e) {
      const tile = ntp.getCurrentlyDraggingTile();
      if (!tile) {
        return false;
      }

      return tile.firstChild.canBeRemoved();
    },

    /** @override */
    doDragOver: function(e) {
      ntp.getCurrentlyDraggingTile().dragClone.classList.add(
          'hovering-on-trash');
      ntp.setCurrentDropEffect(e.dataTransfer, 'move');
      e.preventDefault();
    },

    /** @override */
    doDragEnter: function(e) {
      this.doDragOver(e);
    },

    /** @override */
    doDrop: function(e) {
      e.preventDefault();

      const tile = ntp.getCurrentlyDraggingTile();
      tile.firstChild.removeFromChrome();
      tile.landedOnTrash = true;
    },

    /** @override */
    doDragLeave: function(e) {
      ntp.getCurrentlyDraggingTile().dragClone.classList.remove(
          'hovering-on-trash');
    },
  };

  return {
    Trash: Trash,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview PageListView implementation.
 * PageListView manages page list, dot list, switcher buttons and handles apps
 * pages callbacks from backend.
 *
 * Note that you need to have AppLauncherHandler in your WebUI to use this code.
 */

/**
 * @typedef {{app_launch_ordinal: string,
 *            description: string,
 *            detailsUrl: string,
 *            direction: string,
 *            enabled: boolean,
 *            full_name: string,
 *            full_name_direction: string,
 *            homepageUrl: string,
 *            icon_big: string,
 *            icon_big_exists: boolean,
 *            icon_small: string,
 *            icon_small_exists: boolean,
 *            id: string,
 *            is_component: boolean,
 *            is_webstore: boolean,
 *            isLocallyInstalled: boolean,
 *            kioskEnabled: boolean,
 *            kioskMode: boolean,
 *            kioskOnly: boolean,
 *            launch_container: number,
 *            launch_type: number,
 *            mayChangeLaunchType: boolean,
 *            mayCreateShortcuts: boolean,
 *            mayDisable: boolean,
 *            name: string,
 *            offlineEnabled: boolean,
 *            optionsUrl: string,
 *            packagedApp: boolean,
 *            page_index: number,
 *            title: string,
 *            url: string,
 *            version: string}}
 * @see chrome/browser/ui/webui/ntp/app_launcher_handler.cc
 */
let AppInfo;

cr.define('ntp', function() {
  'use strict';

  /**
   * Creates a PageListView object.
   * @constructor
   * @extends {Object}
   */
  function PageListView() {}

  PageListView.prototype = {
    /**
     * The CardSlider object to use for changing app pages.
     * @type {cr.ui.CardSlider|undefined}
     */
    cardSlider: undefined,

    /**
     * The frame div for this.cardSlider.
     * @type {!Element|undefined}
     */
    sliderFrame: undefined,

    /**
     * The 'page-list' element.
     * @type {!Element|undefined}
     */
    pageList: undefined,

    /**
     * A list of all 'tile-page' elements.
     * @type {!NodeList|undefined}
     */
    tilePages: undefined,

    /**
     * A list of all 'apps-page' elements.
     * @type {!NodeList|undefined}
     */
    appsPages: undefined,

    /**
     * The 'dots-list' element.
     * @type {!ntp.DotList|undefined}
     */
    dotList: undefined,

    /**
     * The left and right paging buttons.
     * @type {!ntp.PageSwitcher|undefined}
     */
    pageSwitcherStart: undefined,
    pageSwitcherEnd: undefined,

    /**
     * The 'trash' element.  Note that technically this is unnecessary,
     * JavaScript creates the object for us based on the id.  But I don't want
     * to rely on the ID being the same, and JSCompiler doesn't know about it.
     * @type {!Element|undefined}
     */
    trash: undefined,

    /**
     * The index of the page that is currently shown. For example if the third
     * page is showing, this will be 2.
     * @type {number}
     */
    shownPageIndex: 0,

    /**
     * EventTracker for managing event listeners for page events.
     * @type {!EventTracker}
     */
    eventTracker: new EventTracker,

    /**
     * If non-null, this is the ID of the app to highlight to the user the next
     * time getAppsCallback runs. "Highlight" in this case means to switch to
     * the page and run the new tile animation.
     * @type {?string}
     */
    highlightAppId: null,

    /**
     * Initializes page list view.
     * @param {!Element} pageList A DIV element to host all pages.
     * @param {!Element} dotList An UL element to host nav dots. Each dot
     *     represents a page.
     * @param {!Element} cardSliderFrame The card slider frame that hosts
     *     pageList and switcher buttons.
     * @param {!Element|undefined} opt_trash Optional trash element.
     * @param {!ntp.PageSwitcher|undefined} opt_pageSwitcherStart Optional start
     *     page switcher button.
     * @param {!ntp.PageSwitcher|undefined} opt_pageSwitcherEnd Optional end
     *     page switcher button.
     */
    initialize: function(
        pageList, dotList, cardSliderFrame, opt_trash, opt_pageSwitcherStart,
        opt_pageSwitcherEnd) {
      this.pageList = pageList;

      this.dotList = /** @type {!ntp.DotList} */ (dotList);
      cr.ui.decorate(this.dotList, ntp.DotList);

      this.trash = opt_trash;
      if (this.trash) {
        new ntp.Trash(this.trash);
      }

      this.pageSwitcherStart = opt_pageSwitcherStart;
      if (this.pageSwitcherStart) {
        ntp.initializePageSwitcher(this.pageSwitcherStart);
      }

      this.pageSwitcherEnd = opt_pageSwitcherEnd;
      if (this.pageSwitcherEnd) {
        ntp.initializePageSwitcher(this.pageSwitcherEnd);
      }

      this.shownPageIndex = loadTimeData.getInteger('shown_page_index');

      // Request data on the apps so we can fill them in.
      // Note that this is kicked off asynchronously.  'getAppsCallback' will
      // be invoked at some point after this function returns.
      chrome.send('getApps');

      document.addEventListener('keydown', this.onDocKeyDown_.bind(this));

      this.tilePages = this.pageList.getElementsByClassName('tile-page');
      this.appsPages = this.pageList.getElementsByClassName('apps-page');

      // Initialize the cardSlider without any cards at the moment.
      this.sliderFrame = cardSliderFrame;
      this.cardSlider = new cr.ui.CardSlider(
          this.sliderFrame, this.pageList, this.sliderFrame.offsetWidth);

      // Prevent touch events from triggering any sort of native scrolling if
      // there are multiple cards in the slider frame.
      const cardSlider = this.cardSlider;
      cardSliderFrame.addEventListener('touchmove', function(e) {
        if (cardSlider.cardCount <= 1) {
          return;
        }
        e.preventDefault();
      }, true);

      // Handle mousewheel events anywhere in the card slider, so that wheel
      // events on the page switchers will still scroll the page.
      // This listener must be added before the card slider is initialized,
      // because it needs to be called before the card slider's handler.
      cardSliderFrame.addEventListener('mousewheel', function(e) {
        if (/** @type {!ntp.TilePage} */ (cardSlider.currentCardValue)
                .handleMouseWheel(e)) {
          e.preventDefault();            // Prevent default scroll behavior.
          e.stopImmediatePropagation();  // Prevent horizontal card flipping.
        }
      });

      this.cardSlider.initialize(
          loadTimeData.getBoolean('isSwipeTrackingFromScrollEventsEnabled'));

      // Handle events from the card slider.
      this.pageList.addEventListener(
          'cardSlider:card_changed', this.onCardChanged_.bind(this));
      this.pageList.addEventListener(
          'cardSlider:card_added', this.onCardAdded_.bind(this));
      this.pageList.addEventListener(
          'cardSlider:card_removed', this.onCardRemoved_.bind(this));

      // Ensure the slider is resized appropriately with the window.
      window.addEventListener('resize', this.onWindowResize_.bind(this));

      // Update apps when online state changes.
      window.addEventListener(
          'online', this.updateOfflineEnabledApps_.bind(this));
      window.addEventListener(
          'offline', this.updateOfflineEnabledApps_.bind(this));
    },

    /**
     * Appends a tile page.
     *
     * @param {!ntp.TilePage} page The page element.
     * @param {string} title The title of the tile page.
     * @param {boolean} titleIsEditable If true, the title can be changed.
     * @param {ntp.TilePage=} opt_refNode Optional reference node to insert in
     *     front of.
     * When opt_refNode is falsey, |page| will just be appended to the end of
     * the page list.
     */
    appendTilePage: function(page, title, titleIsEditable, opt_refNode) {
      if (opt_refNode) {
        const refIndex = this.getTilePageIndex(opt_refNode);
        this.cardSlider.addCardAtIndex(page, refIndex);
      } else {
        this.cardSlider.appendCard(page);
      }

      // If we're appending an AppsPage and it's a temporary page, animate it.
      const animate =
          page instanceof ntp.AppsPage && page.classList.contains('temporary');
      // Make a deep copy of the dot template to add a new one.
      const newDot = new ntp.NavDot(page, title, titleIsEditable, animate);
      page.navigationDot = newDot;
      this.dotList.insertBefore(
          newDot, opt_refNode ? opt_refNode.navigationDot : null);
      // Set a tab index on the first dot.
      if (this.dotList.dots.length == 1) {
        newDot.tabIndex = 3;
      }

      this.eventTracker.add(page, 'pagelayout', this.onPageLayout_.bind(this));
    },

    /**
     * Called by chrome when an app has changed positions.
     * @param {AppInfo} appData The data for the app. This contains page and
     *     position indices.
     */
    appMoved: function(appData) {
      const app = /** @type {ntp.App} */ ($(appData.id));
      assert(app, 'trying to move an app that doesn\'t exist');
      app.remove(false);

      this.appsPages[appData.page_index].insertApp(appData, false);
    },

    /**
     * Called by chrome when an existing app has been disabled or
     * removed/uninstalled from chrome.
     * @param {AppInfo} appData A data structure full of relevant information
     *     for the app.
     * @param {boolean} isUninstall True if the app is being uninstalled;
     *     false if the app is being disabled.
     * @param {boolean} fromPage True if the removal was from the current page.
     */
    appRemoved: function(appData, isUninstall, fromPage) {
      const app = /** @type {ntp.App} */ ($(appData.id));
      assert(app, 'trying to remove an app that doesn\'t exist');

      if (!isUninstall) {
        app.replaceAppData(appData);
      } else {
        app.remove(!!fromPage);
      }
    },

    /**
     * @return {boolean} If the page is still starting up.
     * @private
     */
    isStartingUp_: function() {
      return document.documentElement.classList.contains('starting-up');
    },

    /**
     * Tracks whether apps have been loaded at least once.
     * @type {boolean}
     * @private
     */
    appsLoaded_: false,

    /**
     * Callback invoked by chrome with the apps available.
     *
     * Note that calls to this function can occur at any time, not just in
     * response to a getApps request. For example, when a user
     * installs/uninstalls an app on another synchronized devices.
     * @param {{apps: Array<AppInfo>, appPageNames: Array<string>}} data
     *     An object with all the data on available applications.
     */
    getAppsCallback: function(data) {
      const startTime = Date.now();

      // Remember this to select the correct card when done rebuilding.
      const prevCurrentCard = this.cardSlider.currentCard;

      // Make removal of pages and dots as quick as possible with less DOM
      // operations, reflows, or repaints. We set currentCard = 0 and remove
      // from the end to not encounter any auto-magic card selections in the
      // process and we hide the card slider throughout.
      this.cardSlider.currentCard = 0;

      // Clear any existing apps pages and dots.
      // TODO(rbyers): It might be nice to preserve animation of dots after an
      // uninstall. Could we re-use the existing page and dot elements?  It
      // seems unfortunate to have Chrome send us the entire apps list after an
      // uninstall.
      while (this.appsPages.length > 0) {
        this.removeTilePageAndDot_(this.appsPages[this.appsPages.length - 1]);
      }

      // Get the array of apps and add any special synthesized entries
      const apps = data.apps;

      // Get a list of page names
      const pageNames = data.appPageNames;

      function stringListIsEmpty(list) {
        for (let i = 0; i < list.length; i++) {
          if (list[i]) {
            return false;
          }
        }
        return true;
      }

      // Sort by launch ordinal
      apps.sort(function(a, b) {
        return a.app_launch_ordinal > b.app_launch_ordinal ?
            1 :
            a.app_launch_ordinal < b.app_launch_ordinal ? -1 : 0;
      });

      // An app to animate (in case it was just installed).
      let highlightApp;

      // If there are any pages after the apps, add new pages before them.
      const lastAppsPage = (this.appsPages.length > 0) ?
          this.appsPages[this.appsPages.length - 1] :
          null;
      const lastAppsPageIndex = (lastAppsPage != null) ?
          Array.prototype.indexOf.call(this.tilePages, lastAppsPage) :
          -1;
      const nextPageAfterApps = lastAppsPageIndex != -1 ?
          this.tilePages[lastAppsPageIndex + 1] :
          null;

      // Add the apps, creating pages as necessary
      for (let i = 0; i < apps.length; i++) {
        const app = apps[i];
        const pageIndex = app.page_index || 0;
        while (pageIndex >= this.appsPages.length) {
          let pageName = loadTimeData.getString('appDefaultPageName');
          if (this.appsPages.length < pageNames.length) {
            pageName = pageNames[this.appsPages.length];
          }

          const origPageCount = this.appsPages.length;
          this.appendTilePage(
              new ntp.AppsPage(), pageName, true, nextPageAfterApps);
          // Confirm that appsPages is a live object, updated when a new page is
          // added (otherwise we'd have an infinite loop)
          assert(
              this.appsPages.length == origPageCount + 1, 'expected new page');
        }

        if (app.id == this.highlightAppId) {
          highlightApp = app;
        } else {
          this.appsPages[pageIndex].insertApp(app, false);
        }
      }

      this.cardSlider.currentCard = prevCurrentCard;

      if (highlightApp) {
        this.appAdded(highlightApp, true);
      }

      logEvent('apps.layout: ' + (Date.now() - startTime));

      // Tell the slider about the pages and mark the current page.
      this.updateSliderCards();
      this.cardSlider.currentCardValue.navigationDot.classList.add('selected');

      if (!this.appsLoaded_) {
        this.appsLoaded_ = true;
        cr.dispatchSimpleEvent(document, 'sectionready', true, true);
      }
    },

    /**
     * Called by chrome when a new app has been added to chrome or has been
     * enabled if previously disabled.
     * @param {AppInfo} appData A data structure full of relevant information
     *     for the app.
     * @param {boolean=} opt_highlight Whether the app about to be added should
     *     be highlighted.
     */
    appAdded: function(appData, opt_highlight) {
      if (appData.id == this.highlightAppId) {
        opt_highlight = true;
        this.highlightAppId = null;
      }

      const pageIndex = appData.page_index || 0;

      if (pageIndex >= this.appsPages.length) {
        while (pageIndex >= this.appsPages.length) {
          this.appendTilePage(
              new ntp.AppsPage(), loadTimeData.getString('appDefaultPageName'),
              true);
        }
        this.updateSliderCards();
      }

      const page = this.appsPages[pageIndex];
      const app = /** @type {?ntp.App} */ ($(appData.id));
      if (app) {
        app.replaceAppData(appData);
      } else if (opt_highlight) {
        page.insertAndHighlightApp(appData);
        this.setShownPage_(appData.page_index);
      } else {
        page.insertApp(appData, false);
      }
    },

    /**
     * Callback invoked by chrome whenever an app preference changes.
     * @param {Object} data An object with all the data on available
     *     applications.
     */
    appsPrefChangedCallback: function(data) {
      for (let i = 0; i < data.apps.length; ++i) {
        $(data.apps[i].id).appData = data.apps[i];
      }

      // Set the App dot names.
      const dots = this.dotList.getElementsByClassName('dot');
      for (let i = 0; i < dots.length; ++i) {
        dots[i].displayTitle = data.appPageNames[i] || '';
      }
    },

    /**
     * Invoked whenever the pages in apps-page-list have changed so that
     * the Slider knows about the new elements.
     */
    updateSliderCards: function() {
      const pageNo = Math.max(
          0, Math.min(this.cardSlider.currentCard, this.tilePages.length - 1));
      this.cardSlider.setCards(
          Array.prototype.slice.call(this.tilePages), pageNo);
      this.cardSlider.selectCardByValue(this.appsPages[Math.min(
          this.shownPageIndex, this.appsPages.length - 1)]);
    },

    /**
     * Called whenever tiles should be re-arranging themselves out of the way
     * of a moving or insert tile.
     */
    enterRearrangeMode: function() {
      const tempPage = new ntp.AppsPage();
      tempPage.classList.add('temporary');
      const pageName = loadTimeData.getString('appDefaultPageName');
      this.appendTilePage(tempPage, pageName, true);

      if (ntp.getCurrentlyDraggingTile().firstChild.canBeRemoved()) {
        $('footer').classList.add('showing-trash-mode');
        $('footer-menu-container').style.minWidth = $('trash').offsetWidth -
            $('chrome-web-store-link').offsetWidth + 'px';
      }

      document.documentElement.classList.add('dragging-mode');
    },

    /**
     * Invoked whenever some app is released
     */
    leaveRearrangeMode: function() {
      const tempPage = /** @type {ntp.AppsPage} */ (
          document.querySelector('.tile-page.temporary'));
      if (tempPage) {
        const dot = tempPage.navigationDot;
        if (!tempPage.tileCount &&
            tempPage != this.cardSlider.currentCardValue) {
          this.removeTilePageAndDot_(tempPage, true);
        } else {
          tempPage.classList.remove('temporary');
          this.saveAppPageName(
              tempPage, loadTimeData.getString('appDefaultPageName'));
        }
      }

      $('footer').classList.remove('showing-trash-mode');
      $('footer-menu-container').style.minWidth = '';
      document.documentElement.classList.remove('dragging-mode');
    },

    /**
     * Callback for the 'pagelayout' event.
     * @param {Event} e The event.
     */
    onPageLayout_: function(e) {
      if (Array.prototype.indexOf.call(this.tilePages, e.currentTarget) !=
          this.cardSlider.currentCard) {
        return;
      }

      this.updatePageSwitchers();
    },

    /**
     * Adjusts the size and position of the page switchers according to the
     * layout of the current card, and updates the aria-label attributes of
     * the page switchers.
     */
    updatePageSwitchers: function() {
      if (!this.pageSwitcherStart || !this.pageSwitcherEnd) {
        return;
      }

      const page =
          /** @type {?ntp.TilePage} */ (this.cardSlider.currentCardValue);

      this.pageSwitcherStart.hidden =
          !page || (this.cardSlider.currentCard == 0);
      this.pageSwitcherEnd.hidden = !page ||
          (this.cardSlider.currentCard == this.cardSlider.cardCount - 1);

      if (!page) {
        return;
      }

      const pageSwitcherLeft =
          isRTL() ? this.pageSwitcherEnd : this.pageSwitcherStart;
      const pageSwitcherRight =
          isRTL() ? this.pageSwitcherStart : this.pageSwitcherEnd;
      const scrollbarWidth = page.scrollbarWidth;
      pageSwitcherLeft.style.width = (page.sideMargin + 13) + 'px';
      pageSwitcherLeft.style.left = '0';
      pageSwitcherRight.style.width =
          (page.sideMargin - scrollbarWidth + 13) + 'px';
      pageSwitcherRight.style.right = scrollbarWidth + 'px';

      const offsetTop =
          page.querySelector('.tile-page-content').offsetTop + 'px';
      pageSwitcherLeft.style.top = offsetTop;
      pageSwitcherRight.style.top = offsetTop;
      pageSwitcherLeft.style.paddingBottom = offsetTop;
      pageSwitcherRight.style.paddingBottom = offsetTop;

      // Update the aria-label attributes of the two page switchers.
      this.pageSwitcherStart.updateButtonAccessibleLabel(this.dotList.dots);
      this.pageSwitcherEnd.updateButtonAccessibleLabel(this.dotList.dots);
    },

    /**
     * Returns the index of the given apps page.
     * @param {ntp.AppsPage} page The AppsPage we wish to find.
     * @return {number} The index of |page| or -1 if it is not in the
     *    collection.
     */
    getAppsPageIndex: function(page) {
      return Array.prototype.indexOf.call(this.appsPages, page);
    },

    /**
     * Handler for cardSlider:card_changed events from this.cardSlider.
     * @param {Event} e The cardSlider:card_changed event.
     * @private
     */
    onCardChanged_: function(e) {
      const page = e.cardSlider.currentCardValue;

      // Don't change shownPage until startup is done (and page changes actually
      // reflect user actions).
      if (!this.isStartingUp_()) {
        // TODO(dbeam): is this ever false?
        if (page.classList.contains('apps-page')) {
          this.setShownPage_(this.getAppsPageIndex(page));
        } else {
          console.error('unknown page selected');
        }
      }

      // Update the active dot
      const curDot = this.dotList.getElementsByClassName('selected')[0];
      if (curDot) {
        curDot.classList.remove('selected');
      }
      page.navigationDot.classList.add('selected');
      this.updatePageSwitchers();
    },

    /**
     * Saves/updates the newly selected page to open when first loading the NTP.
     * @param {number} shownPageIndex The new shown page index.
     * @private
     */
    setShownPage_: function(shownPageIndex) {
      assert(shownPageIndex >= 0);
      this.shownPageIndex = shownPageIndex;
      chrome.send('pageSelected', [this.shownPageIndex]);
    },

    /**
     * Listen for card additions to update the page switchers or the current
     * card accordingly.
     * @param {Event} e A card removed or added event.
     */
    onCardAdded_: function(e) {
      // When the second arg passed to insertBefore is falsey, it acts just like
      // appendChild.
      this.pageList.insertBefore(e.addedCard, this.tilePages[e.addedIndex]);
      this.onCardAddedOrRemoved_();
    },

    /**
     * Listen for card removals to update the page switchers or the current card
     * accordingly.
     * @param {Event} e A card removed or added event.
     */
    onCardRemoved_: function(e) {
      e.removedCard.parentNode.removeChild(e.removedCard);
      this.onCardAddedOrRemoved_();
    },

    /**
     * Called when a card is removed or added.
     * @private
     */
    onCardAddedOrRemoved_: function() {
      if (this.isStartingUp_()) {
        return;
      }

      // Without repositioning there were issues - http://crbug.com/133457.
      this.cardSlider.repositionFrame();
      this.updatePageSwitchers();
    },

    /**
     * Save the name of an apps page.
     * Store the apps page name into the preferences store.
     * @param {ntp.AppsPage} appPage The app page for which we wish to save.
     * @param {string} name The name of the page.
     */
    saveAppPageName: function(appPage, name) {
      const index = this.getAppsPageIndex(appPage);
      assert(index != -1);
      chrome.send('saveAppPageName', [name, index]);
    },

    /**
     * Window resize handler.
     * @private
     */
    onWindowResize_: function(e) {
      this.cardSlider.resize(this.sliderFrame.offsetWidth);
      this.updatePageSwitchers();
    },

    /**
     * Listener for offline status change events. Updates apps that are
     * not offline-enabled to be grayscale if the browser is offline.
     * @private
     */
    updateOfflineEnabledApps_: function() {
      const apps = /** @type {!NodeList<!ntp.App>} */ (
          document.querySelectorAll('.app'));
      for (let i = 0; i < apps.length; ++i) {
        if (apps[i].appData.enabled && !apps[i].appData.offlineEnabled) {
          apps[i].setIcon();
          apps[i].loadIcon();
        }
      }
    },

    /**
     * Handler for key events on the page. Ctrl-Arrow will switch the visible
     * page.
     * @param {Event} e The KeyboardEvent.
     * @private
     */
    onDocKeyDown_: function(e) {
      if (!e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) {
        return;
      }

      let direction = 0;
      if (e.key == 'ArrowLeft') {
        direction = -1;
      } else if (e.key == 'ArrowRight') {
        direction = 1;
      } else {
        return;
      }

      const cardIndex = (this.cardSlider.currentCard + direction +
                         this.cardSlider.cardCount) %
          this.cardSlider.cardCount;
      this.cardSlider.selectCard(cardIndex, true);

      e.stopPropagation();
    },

    /**
     * Returns the index of a given tile page.
     * @param {ntp.TilePage} page The TilePage we wish to find.
     * @return {number} The index of |page| or -1 if it is not in the
     *    collection.
     */
    getTilePageIndex: function(page) {
      return Array.prototype.indexOf.call(this.tilePages, page);
    },

    /**
     * Removes a page and navigation dot (if the navdot exists).
     * @param {ntp.TilePage} page The page to be removed.
     * @param {boolean=} opt_animate If the removal should be animated.
     */
    removeTilePageAndDot_: function(page, opt_animate) {
      if (page.navigationDot) {
        page.navigationDot.remove(opt_animate);
      }
      this.cardSlider.removeCard(page);
    },
  };

  return {PageListView: PageListView};
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Page switcher
 * This is the class for the left and right navigation arrows that switch
 * between pages.
 */
cr.define('ntp', function() {

  /**
   * @constructor
   * @extends {HTMLButtonElement}
   */
  function PageSwitcher() {}

  PageSwitcher.prototype = {
    __proto__: HTMLButtonElement.prototype,

    decorate: function(el) {
      el.__proto__ = PageSwitcher.prototype;

      el.addEventListener('click', el.activate_);

      el.direction_ = el.id == 'page-switcher-start' ? -1 : 1;

      el.dragWrapper_ = new cr.ui.DragWrapper(el, el);
    },

    /**
     * Activate the switcher (go to the next card).
     * @private
     */
    activate_: function() {
      ntp.getCardSlider().selectCard(this.nextCardIndex_(), true);
    },

    /**
     * Calculate the index of the card that this button will switch to.
     * @private
     */
    nextCardIndex_: function() {
      const cardSlider = ntp.getCardSlider();
      const index = cardSlider.currentCard + this.direction_;
      const numCards = cardSlider.cardCount - 1;
      return Math.max(0, Math.min(index, numCards));
    },

    /**
     * Update the accessible label attribute of this button, based on the
     * current position in the card slider and the names of the cards.
     * @param {NodeList} dots The dot elements which display the names of the
     *     cards.
     */
    updateButtonAccessibleLabel: function(dots) {
      const currentIndex = ntp.getCardSlider().currentCard;
      const nextCardIndex = this.nextCardIndex_();
      if (nextCardIndex == currentIndex) {
        this.setAttribute('aria-label', '');  // No next card.
        return;
      }

      const currentDot = dots[currentIndex];
      const nextDot = dots[nextCardIndex];
      if (!currentDot || !nextDot) {
        this.setAttribute('aria-label', '');  // Dots not initialised yet.
        return;
      }

      const currentPageTitle = currentDot.displayTitle;
      const nextPageTitle = nextDot.displayTitle;
      const msgName = (currentPageTitle == nextPageTitle) ?
          'page_switcher_same_title' :
          'page_switcher_change_title';
      const ariaLabel = loadTimeData.getStringF(msgName, nextPageTitle);
      this.setAttribute('aria-label', ariaLabel);
    },

    shouldAcceptDrag: function(e) {
      // Only allow page switching when a drop could happen on the page being
      // switched to.
      const nextPage =
          ntp.getCardSlider().getCardAtIndex(this.nextCardIndex_());
      return nextPage.shouldAcceptDrag(e);
    },

    doDragEnter: function(e) {
      this.scheduleDelayedSwitch_(e);
      this.doDragOver(e);
    },

    doDragLeave: function(e) {
      this.cancelDelayedSwitch_();
    },

    doDragOver: function(e) {
      e.preventDefault();
      const targetPage = ntp.getCardSlider().currentCardValue;
      if (targetPage.shouldAcceptDrag(e)) {
        targetPage.setDropEffect(e.dataTransfer);
      }
    },

    doDrop: function(e) {
      e.stopPropagation();
      this.cancelDelayedSwitch_();

      const tile = ntp.getCurrentlyDraggingTile();
      if (!tile) {
        return;
      }

      const sourcePage = tile.tilePage;
      const targetPage = ntp.getCardSlider().currentCardValue;
      if (targetPage == sourcePage || !targetPage.shouldAcceptDrag(e)) {
        return;
      }

      targetPage.appendDraggingTile();
    },

    /**
     * Starts a timer to activate the switcher. The timer repeats until
     * cancelled by cancelDelayedSwitch_.
     * @private
     */
    scheduleDelayedSwitch_: function(e) {
      // Stop switching when the next page can't be dropped onto.
      const nextPage =
          ntp.getCardSlider().getCardAtIndex(this.nextCardIndex_());
      if (!nextPage.shouldAcceptDrag(e)) {
        return;
      }

      const self = this;
      function navPageClearTimeout() {
        self.activate_();
        self.dragNavTimeout_ = null;
        self.scheduleDelayedSwitch_(e);
      }
      this.dragNavTimeout_ = window.setTimeout(navPageClearTimeout, 500);
    },

    /**
     * Cancels the timer that activates the switcher while dragging.
     * @private
     */
    cancelDelayedSwitch_: function() {
      if (this.dragNavTimeout_) {
        window.clearTimeout(this.dragNavTimeout_);
        this.dragNavTimeout_ = null;
      }
    },

  };

  /** @const */
  const initializePageSwitcher = PageSwitcher.prototype.decorate;

  return {
    initializePageSwitcher: initializePageSwitcher,
    PageSwitcher: PageSwitcher
  };
});
</script>

<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Nav dot
 * This is the class for the navigation controls that appear along the bottom
 * of the NTP.
 */

cr.define('ntp', function() {
  'use strict';

  /**
   * Creates a new navigation dot.
   * @param {ntp.TilePage} page The associated TilePage.
   * @param {string} title The title of the navigation dot.
   * @param {boolean} titleIsEditable If true, the title can be changed.
   * @param {boolean} animate If true, animates into existence.
   * @constructor
   * @extends {HTMLLIElement}
   * @implements {cr.ui.DragWrapperDelegate}
   */
  function NavDot(page, title, titleIsEditable, animate) {
    const dot = cr.doc.createElement('li');
    dot.__proto__ = NavDot.prototype;
    dot.initialize(page, title, titleIsEditable, animate);

    return dot;
  }

  NavDot.prototype = {
    __proto__: HTMLLIElement.prototype,

    initialize: function(page, title, titleIsEditable, animate) {
      this.className = 'dot';
      this.setAttribute('role', 'button');

      this.page_ = page;

      const selectionBar = this.ownerDocument.createElement('div');
      selectionBar.className = 'selection-bar';
      this.appendChild(selectionBar);

      // TODO(estade): should there be some limit to the number of characters?
      this.input_ = this.ownerDocument.createElement('input');
      this.input_.setAttribute('spellcheck', false);
      this.input_.value = title;
      // Take the input out of the tab-traversal focus order.
      this.input_.disabled = true;
      this.appendChild(this.input_);

      this.displayTitle = title;
      this.titleIsEditable_ = titleIsEditable;

      this.addEventListener('keydown', this.onKeyDown_);
      this.addEventListener('click', this.onClick_);
      this.addEventListener('dblclick', this.onDoubleClick_);
      this.dragWrapper_ = new cr.ui.DragWrapper(this, this);
      this.addEventListener('transitionend', this.onTransitionEnd_);

      this.input_.addEventListener('blur', this.onInputBlur_.bind(this));
      this.input_.addEventListener(
          'mousedown', this.onInputMouseDown_.bind(this));
      this.input_.addEventListener('keydown', this.onInputKeyDown_.bind(this));

      if (animate) {
        this.classList.add('small');
        const self = this;
        window.setTimeout(function() {
          self.classList.remove('small');
        }, 0);
      }
    },

    /**
     * @return {ntp.TilePage} The associated TilePage.
     */
    get page() {
      return this.page_;
    },

    /**
     * Sets/gets the display title.
     * @type {string} title The display name for this nav dot.
     */
    get displayTitle() {
      return this.title;
    },
    set displayTitle(title) {
      this.title = this.input_.value = title;
    },

    /**
     * Removes the dot from the page. If |opt_animate| is truthy, we first
     * transition the element to 0 width.
     * @param {boolean=} opt_animate Whether to animate the removal or not.
     */
    remove: function(opt_animate) {
      if (opt_animate) {
        this.classList.add('small');
      } else {
        this.parentNode.removeChild(this);
      }
    },

    /**
     * Navigates the card slider to the page for this dot.
     */
    switchToPage: function() {
      ntp.getCardSlider().selectCardByValue(this.page_, true);
    },

    /**
     * Handler for keydown event on the dot.
     * @param {Event} e The KeyboardEvent.
     */
    onKeyDown_: function(e) {
      if (e.key == 'Enter') {
        this.onClick_(e);
        e.stopPropagation();
      }
    },

    /**
     * Clicking causes the associated page to show.
     * @param {Event} e The click event.
     * @private
     */
    onClick_: function(e) {
      this.switchToPage();
      // The explicit focus call is necessary because of overriding the default
      // handling in onInputMouseDown_.
      if (this.ownerDocument.activeElement != this.input_) {
        this.focus();
      }

      e.stopPropagation();
    },

    /**
     * Double clicks allow the user to edit the page title.
     * @param {Event} e The click event.
     * @private
     */
    onDoubleClick_: function(e) {
      if (this.titleIsEditable_) {
        this.input_.disabled = false;
        this.input_.focus();
        this.input_.select();
      }
    },

    /**
     * Prevent mouse down on the input from selecting it.
     * @param {Event} e The click event.
     * @private
     */
    onInputMouseDown_: function(e) {
      if (this.ownerDocument.activeElement != this.input_) {
        e.preventDefault();
      }
    },

    /**
     * Handle keypresses on the input.
     * @param {Event} e The click event.
     * @private
     */
    onInputKeyDown_: function(e) {
      switch (e.key) {
        case 'Escape':  // Escape cancels edits.
          this.input_.value = this.displayTitle;
        case 'Enter':  // Fall through.
          this.input_.blur();
          break;
      }
    },

    /**
     * When the input blurs, commit the edited changes.
     * @param {Event} e The blur event.
     * @private
     */
    onInputBlur_: function(e) {
      window.getSelection().removeAllRanges();
      this.displayTitle = this.input_.value;
      ntp.saveAppPageName(this.page_, this.displayTitle);
      this.input_.disabled = true;
    },

    shouldAcceptDrag: function(e) {
      return this.page_.shouldAcceptDrag(e);
    },

    /** @override */
    doDragEnter: function(e) {
      const self = this;
      function navPageClearTimeout() {
        self.switchToPage();
        self.dragNavTimeout = null;
      }
      this.dragNavTimeout = window.setTimeout(navPageClearTimeout, 500);

      this.doDragOver(e);
    },

    /** @override */
    doDragOver: function(e) {
      // Prevent default handling so the <input> won't act as a drag target.
      e.preventDefault();

      if (!this.dragWrapper_.isCurrentDragTarget) {
        ntp.setCurrentDropEffect(e.dataTransfer, 'none');
      } else {
        this.page_.setDropEffect(e.dataTransfer);
      }
    },

    /** @override */
    doDrop: function(e) {
      e.stopPropagation();
      const tile = ntp.getCurrentlyDraggingTile();
      if (tile && tile.tilePage != this.page_) {
        this.page_.appendDraggingTile();
      }
      // TODO(estade): handle non-tile drags.

      this.cancelDelayedSwitch_();
    },

    /** @override */
    doDragLeave: function(e) {
      this.cancelDelayedSwitch_();
    },

    /**
     * Cancels the timer for page switching.
     * @private
     */
    cancelDelayedSwitch_: function() {
      if (this.dragNavTimeout) {
        window.clearTimeout(this.dragNavTimeout);
        this.dragNavTimeout = null;
      }
    },

    /**
     * A transition has ended.
     * @param {Event} e The transition end event.
     * @private
     */
    onTransitionEnd_: function(e) {
      if (e.propertyName === 'max-width' && this.classList.contains('small')) {
        this.parentNode.removeChild(this);
      }
    },
  };

  return {
    NavDot: NavDot,
  };
});
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview New tab page 4
 * This is the main code for a previous version of the Chrome NTP ("NTP4").
 * Some parts of this are still used for the chrome://apps page.
 */

// Use an anonymous function to enable strict mode just for this file (which
// will be concatenated with other files when embedded in Chrome
cr.define('ntp', function() {
  'use strict';

  /**
   * NewTabView instance.
   * @type {!Object|undefined}
   */
  let newTabView;

  /**
   * If non-null, an bubble confirming that the user has signed into sync. It
   * points at the login status at the top of the page.
   * @type {!cr.ui.Bubble|undefined}
   */
  let loginBubble;

  /**
   * true if |loginBubble| should be shown.
   * @type {boolean}
   */
  let shouldShowLoginBubble = false;

  /**
   * The time when all sections are ready.
   * @type {number|undefined}
   * @private
   */
  let startTime;

  /**
   * The number of sections to wait on.
   * @type {number}
   */
  let sectionsToWaitFor = -1;

  /**
   * The time in milliseconds for most transitions.  This should match what's
   * in new_tab.css.  Unfortunately there's no better way to try to time
   * something to occur until after a transition has completed.
   * @type {number}
   * @const
   */
  const DEFAULT_TRANSITION_TIME = 500;

  /**
   * Creates a NewTabView object. NewTabView extends PageListView with
   * new tab UI specific logics.
   * @constructor
   * @extends {ntp.PageListView}
   */
  function NewTabView() {
    const pageSwitcherStart = /** @type {!ntp.PageSwitcher} */ (
        getRequiredElement('page-switcher-start'));
    const pageSwitcherEnd = /** @type {!ntp.PageSwitcher} */ (
        getRequiredElement('page-switcher-end'));
    this.initialize(
        getRequiredElement('page-list'), getRequiredElement('dot-list'),
        getRequiredElement('card-slider-frame'), getRequiredElement('trash'),
        pageSwitcherStart, pageSwitcherEnd);
  }

  // TODO(dbeam): NewTabView is now the only extender of PageListView; these
  // classes should be merged.
  NewTabView.prototype = {__proto__: ntp.PageListView.prototype};

  /**
   * Invoked at startup once the DOM is available to initialize the app.
   */
  function onLoad() {
    sectionsToWaitFor = 1;
    measureNavDots();

    newTabView = new NewTabView();

    if (!loadTimeData.getBoolean('showWebStoreIcon')) {
      const webStoreIcon = $('chrome-web-store-link');
      // Not all versions of the NTP have a footer, so this may not exist.
      if (webStoreIcon) {
        webStoreIcon.hidden = true;
      }
    } else {
      const webStoreLink = loadTimeData.getString('webStoreLink');
      const url =
          appendParam(webStoreLink, 'utm_source', 'chrome-ntp-launcher');
      $('chrome-web-store-link').href = url;
      $('chrome-web-store-link')
          .addEventListener('auxclick', onChromeWebStoreButtonClick);
      $('chrome-web-store-link')
          .addEventListener('click', onChromeWebStoreButtonClick);
    }

    // We need to wait for all the footer menu setup to be completed before
    // we can compute its layout.
    layoutFooter();

    if (loadTimeData.getString('login_status_message')) {
      loginBubble = new cr.ui.Bubble;
      loginBubble.anchorNode = $('login-container');
      loginBubble.arrowLocation = cr.ui.ArrowLocation.TOP_END;
      loginBubble.bubbleAlignment =
          cr.ui.BubbleAlignment.BUBBLE_EDGE_TO_ANCHOR_EDGE;
      loginBubble.deactivateToDismissDelay = 2000;
      loginBubble.closeButtonVisible = false;

      $('login-status-advanced').onclick = function() {
        chrome.send('showAdvancedLoginUI');
      };
      $('login-status-dismiss').onclick = loginBubble.hide.bind(loginBubble);

      const bubbleContent = $('login-status-bubble-contents');
      loginBubble.content = bubbleContent;

      // The anchor node won't be updated until updateLogin is called so don't
      // show the bubble yet.
      shouldShowLoginBubble = true;
    }

    $('login-container').addEventListener('click', showSyncLoginUI);
    if (loadTimeData.getBoolean('shouldShowSyncLogin')) {
      chrome.send('initializeSyncLogin');
    }

    doWhenAllSectionsReady(function() {
      // Tell the slider about the pages.
      newTabView.updateSliderCards();
      // Mark the current page.
      newTabView.cardSlider.currentCardValue.navigationDot.classList.add(
          'selected');

      cr.dispatchSimpleEvent(document, 'ntpLoaded', true, true);
      document.documentElement.classList.remove('starting-up');

      startTime = Date.now();
    });
  }

  /**
   * Launches the chrome web store app with the chrome-ntp-launcher
   * source.
   * @param {Event} e The click/auxclick event.
   */
  function onChromeWebStoreButtonClick(e) {
    if (e.button > 1) {
      return;
    }  // Ignore buttons other than left and middle.
    chrome.send(
        'recordAppLaunchByURL',
        [encodeURIComponent(this.href), ntp.APP_LAUNCH.NTP_WEBSTORE_FOOTER]);
  }

  /**
   * Queued callbacks which lie in wait for all sections to be ready.
   * @type {Array}
   */
  const readyCallbacks = [];

  /**
   * Fired as each section of pages becomes ready.
   */
  document.addEventListener('sectionready', function(e) {
    if (--sectionsToWaitFor <= 0) {
      while (readyCallbacks.length) {
        readyCallbacks.shift()();
      }
    }
  });

  /**
   * This is used to simulate a fire-once event (i.e. $(document).ready() in
   * jQuery or Y.on('domready') in YUI. If all sections are ready, the callback
   * is fired right away. If all pages are not ready yet, the function is queued
   * for later execution.
   * @param {Function} callback The work to be done when ready.
   */
  function doWhenAllSectionsReady(callback) {
    assert(typeof callback == 'function');
    if (sectionsToWaitFor > 0) {
      readyCallbacks.push(callback);
    } else {
      window.setTimeout(callback, 0);
    }  // Do soon after, but asynchronously.
  }

  /**
   * Measure the width of a nav dot with a given title.
   * @param {string} id The loadTimeData ID of the desired title.
   * @return {number} The width of the nav dot.
   */
  function measureNavDot(id) {
    const measuringDiv = $('fontMeasuringDiv');
    measuringDiv.textContent = loadTimeData.getString(id);
    // The 4 is for border and padding.
    return Math.max(measuringDiv.clientWidth * 1.15 + 4, 80);
  }

  /**
   * Fills in an invisible div with the longest dot title string so that
   * its length may be measured and the nav dots sized accordingly.
   */
  function measureNavDots() {
    const styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    // max-width is used because if we run out of space, the nav dots will be
    // shrunk.
    const pxWidth = measureNavDot('appDefaultPageName');
    styleElement.textContent = '.dot { max-width: ' + pxWidth + 'px; }';
    document.querySelector('head').appendChild(styleElement);
  }

  /**
   * Layout the footer so that the nav dots stay centered.
   */
  function layoutFooter() {
    // We need the image to be loaded.
    const logo = $('logo-img');
    const logoImg = logo.querySelector('img');

    // Only compare the width after the footer image successfully loaded.
    if (!logoImg.complete || logoImg.width === 0) {
      logoImg.onload = layoutFooter;
      return;
    }

    const menu = $('footer-menu-container');
    if (menu.clientWidth > logoImg.width) {
      logo.style.WebkitFlex = '0 1 ' + menu.clientWidth + 'px';
    } else {
      menu.style.WebkitFlex = '0 1 ' + logoImg.width + 'px';
    }
  }

  /**
   * Called when the theme has changed.
   * @param {Object=} opt_themeData Not used; only exists to match equivalent
   *     function in incognito NTP.
   */
  function themeChanged(opt_themeData) {
    $('themecss').href = 'chrome://theme/css/new_tab_theme.css?' + Date.now();
  }

  function setBookmarkBarAttached(attached) {
    document.documentElement.setAttribute('bookmarkbarattached', attached);
  }

  /**
   * Set the dominant color for a node. This will be called in response to
   * getFaviconDominantColor. The node represented by |id| better have a setter
   * for stripeColor.
   * @param {string} id The ID of a node.
   * @param {string} color The color represented as a CSS string.
   */
  function setFaviconDominantColor(id, color) {
    const node = $(id);
    if (node) {
      node.stripeColor = color;
    }
  }

  /**
   * Updates the text displayed in the login container. If there is no text then
   * the login container is hidden.
   * @param {string} loginHeader The first line of text.
   * @param {string} loginSubHeader The second line of text.
   * @param {string} iconURL The url for the login status icon. If this is null
        then the login status icon is hidden.
   * @param {boolean} isUserSignedIn Indicates if the user is signed in or not.
   */
  function updateLogin(loginHeader, loginSubHeader, iconURL, isUserSignedIn) {
    /** @const */ const showLogin = loginHeader || loginSubHeader;

    $('login-container').hidden = !showLogin;
    $('login-container').classList.toggle('signed-in', isUserSignedIn);
    $('card-slider-frame').classList.toggle('showing-login-area', !!showLogin);

    if (showLogin) {
      // TODO(dbeam): we should use .textContent instead to mitigate XSS.
      $('login-status-header').innerHTML = loginHeader;
      $('login-status-sub-header').innerHTML = loginSubHeader;

      const headerContainer = $('login-status-header-container');
      headerContainer.classList.toggle('login-status-icon', !!iconURL);
      headerContainer.style.backgroundImage =
          iconURL ? getUrlForCss(iconURL) : 'none';
    }

    if (shouldShowLoginBubble) {
      window.setTimeout(loginBubble.show.bind(loginBubble), 0);
      chrome.send('loginMessageSeen');
      shouldShowLoginBubble = false;
    } else if (loginBubble) {
      loginBubble.reposition();
    }
  }

  /**
   * Show the sync login UI.
   * @param {Event} e The click event.
   */
  function showSyncLoginUI(e) {
    const rect = e.currentTarget.getBoundingClientRect();
    chrome.send(
        'showSyncLoginUI', [rect.left, rect.top, rect.width, rect.height]);
  }

  /**
   * Wrappers to forward the callback to corresponding PageListView member.
   */

  /**
   * Called by chrome when a new app has been added to chrome or has been
   * enabled if previously disabled.
   * @param {Object} appData A data structure full of relevant information for
   *     the app.
   * @param {boolean=} opt_highlight Whether the app about to be added should
   *     be highlighted.
   */
  function appAdded(appData, opt_highlight) {
    newTabView.appAdded(appData, opt_highlight);
  }

  /**
   * Called by chrome when an app has changed positions.
   * @param {Object} appData The data for the app. This contains page and
   *     position indices.
   */
  function appMoved(appData) {
    newTabView.appMoved(appData);
  }

  /**
   * Called by chrome when an existing app has been disabled or
   * removed/uninstalled from chrome.
   * @param {Object} appData A data structure full of relevant information for
   *     the app.
   * @param {boolean} isUninstall True if the app is being uninstalled;
   *     false if the app is being disabled.
   * @param {boolean} fromPage True if the removal was from the current page.
   */
  function appRemoved(appData, isUninstall, fromPage) {
    newTabView.appRemoved(appData, isUninstall, fromPage);
  }

  /**
   * Callback invoked by chrome whenever an app preference changes.
   * @param {Object} data An object with all the data on available
   *     applications.
   */
  function appsPrefChangeCallback(data) {
    newTabView.appsPrefChangedCallback(data);
  }

  /**
   * Callback invoked by chrome whenever the app launcher promo pref changes.
   * @param {boolean} show Identifies if we should show or hide the promo.
   */
  function appLauncherPromoPrefChangeCallback(show) {
    newTabView.appLauncherPromoPrefChangeCallback(show);
  }

  /**
   * Called whenever tiles should be re-arranging themselves out of the way
   * of a moving or insert tile.
   */
  function enterRearrangeMode() {
    newTabView.enterRearrangeMode();
  }

  /**
   * Callback invoked by chrome with the apps available.
   *
   * Note that calls to this function can occur at any time, not just in
   * response to a getApps request. For example, when a user
   * installs/uninstalls an app on another synchronized devices.
   * @param {Object} data An object with all the data on available
   *        applications.
   */
  function getAppsCallback(data) {
    newTabView.getAppsCallback(data);
  }

  /**
   * Return the index of the given apps page.
   * @param {ntp.AppsPage} page The AppsPage we wish to find.
   * @return {number} The index of |page| or -1 if it is not in the collection.
   */
  function getAppsPageIndex(page) {
    return newTabView.getAppsPageIndex(page);
  }

  function getCardSlider() {
    return newTabView.cardSlider;
  }

  /**
   * Invoked whenever some app is released
   */
  function leaveRearrangeMode() {
    newTabView.leaveRearrangeMode();
  }

  /**
   * Save the name of an apps page.
   * Store the apps page name into the preferences store.
   * @param {ntp.AppsPage} appPage The app page for which we wish to save.
   * @param {string} name The name of the page.
   */
  function saveAppPageName(appPage, name) {
    newTabView.saveAppPageName(appPage, name);
  }

  function setAppToBeHighlighted(appId) {
    newTabView.highlightAppId = appId;
  }

  // Return an object with all the exports
  return {
    appAdded: appAdded,
    appMoved: appMoved,
    appRemoved: appRemoved,
    appsPrefChangeCallback: appsPrefChangeCallback,
    appLauncherPromoPrefChangeCallback: appLauncherPromoPrefChangeCallback,
    enterRearrangeMode: enterRearrangeMode,
    getAppsCallback: getAppsCallback,
    getAppsPageIndex: getAppsPageIndex,
    getCardSlider: getCardSlider,
    onLoad: onLoad,
    leaveRearrangeMode: leaveRearrangeMode,
    saveAppPageName: saveAppPageName,
    setAppToBeHighlighted: setAppToBeHighlighted,
    setBookmarkBarAttached: setBookmarkBarAttached,
    setFaviconDominantColor: setFaviconDominantColor,
    themeChanged: themeChanged,
    updateLogin: updateLogin
  };
});

document.addEventListener('DOMContentLoaded', ntp.onLoad);

const toCssPx = cr.ui.toCssPx;
</script>
</head>

<body>
  <div id="card-slider-frame">
    <button id="page-switcher-start" class="page-switcher custom-appearance"
        tabindex="2" hidden>‹
    </button>
    <div id="page-list"></div>
    <button id="page-switcher-end" class="page-switcher custom-appearance"
        tabindex="2" hidden>›
    </button>
    <div id="attribution">
      <span>$i18n{attributionintro}</span>
      <img id="attribution-img">
    </div>
  </div>

  <div id="footer">
    <div id="footer-border"></div>
    <div id="footer-content">
      <div id="logo-img">
        <img alt="" src="chrome://theme/IDR_PRODUCT_LOGO">
      </div>

      <ul id="dot-list">
      </ul>

      <div id="footer-menu-container" class="menu-container">
        <a id="chrome-web-store-link">
          <span id="chrome-web-store-title">$i18n{webStoreTitleShort}</span>
        </a>
      </div>

      <div id="trash" class="trash">
        <span class="lid"></span>
        <span class="can"></span>
        <span class="trash-text">$i18n{appuninstall}</span>
      </div>
    </div>
  </div>

  <div id="login-container" hidden>
    <div id="login-status-header-container" class="login-status-row">
      <div id="login-status-header"></div>
    </div>
    <div id="login-status-sub-header"></div>
  </div>
</body>

<!-- A div to hold all the templates, and in the darkness bind them. -->
<div hidden>

<!-- Login status bubble -->
<div id="login-status-bubble-contents">
  <div id="login-status-message-container">
    <span>$i18n{login_status_message}</span>
    <a id="login-status-learn-more" href="$i18nRaw{login_status_url}"
        target="_blank">$i18n{learn_more}</a>
  </div>
  <div class="login-status-row">
    <div id="login-status-advanced-container">
      <a is="action-link" id="login-status-advanced">
        $i18n{login_status_advanced}
      </a>
    </div>
    <button id="login-status-dismiss">$i18n{login_status_dismiss}</button>
  </div>
</div>

<!-- App Contents w/ Large Icon -->
<div id="app-large-icon-template" class="app-contents">
  <div class="app-img-container" aria-hidden="true">
    <img class="invisible" alt="">
  </div>
  <span class="title"></span>
</div>

<!-- App Contents w/ Small Icon -->
<div id="app-small-icon-template" class="app-contents">
  <div class="app-icon-div" aria-hidden="true">
    <div class="app-img-container">
      <img class="invisible" alt="">
    </div>
    <div class="color-stripe"></div>
  </div>
  <span class="title"></span>
</div>

</div>

<!-- This is used to measure text in the current locale. It is not visible. -->
<div id="fontMeasuringDiv"></div>

</html>
/* Copyright 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html {
  background-attachment: fixed;
  background-color: $i18n{colorBackground};
  background-image: url(chrome://theme/IDR_THEME_NTP_BACKGROUND?$i18n{themeId});
  background-position: $i18n{backgroundBarDetached};
  background-repeat: $i18n{backgroundTiling};
}

#attribution {
  left: $i18n{leftAlignAttribution};
  right: $i18n{rightAlignAttribution};
  text-align: $i18n{textAlignAttribution};
  display: $i18n{displayAttribution};
}

#attribution-img {
  content: url(chrome://theme/IDR_THEME_NTP_ATTRIBUTION?$i18n{themeId});
}

html[bookmarkbarattached='true'] {
  background-position: $i18n{backgroundBarAttached};
}

body {
  color: $i18n{colorTextRgba};
  height: 100%;
  overflow: auto;
}

#attribution,
[is='action-link'] {
  color: $i18n{colorTextLight};
}

[is='action-link']:active {
  color: $i18n{colorTextRgba};
}

.page-switcher {
  color: rgba($i18n{colorText}, 0.5);
}

.page-switcher:hover,
.page-switcher:focus,
.page-switcher.drag-target {
  background-color: rgba($i18n{colorText}, 0.06);
}

/* Only change the background to a gradient when a promo is showing. */
.showing-login-area #page-switcher-end:hover,
.showing-login-area #page-switcher-end:focus,
.showing-login-area #page-switcher-end.drag-target {
  background: linear-gradient(
      rgba($i18n{colorText}, 0) 0,
      rgba($i18n{colorText}, .01) 60px,
      rgba($i18n{colorText}, .06) 183px);
}

.tile-page-scrollbar {
  background-color: $i18n{colorTextLight};
}

/* Footer *********************************************************************/

#footer-border {
  background: linear-gradient(to left,
      rgba($i18n{colorSectionBorder}, 0.2),
      rgba($i18n{colorSectionBorder}, 0.3) 20%,
      rgba($i18n{colorSectionBorder}, 0.3) 80%,
      rgba($i18n{colorSectionBorder}, 0.2));
}

.dot input:focus {
  background-color: $i18n{colorBackground};
}

.filler .thumbnail {
  border-color: $i18n{colorBackground};
}
<!-- Common styles for signin-related tab modal dialogs. -->
<dom-module id="signin-dialog-shared">
  <template>
    <style>
      a {
        color: var(--google-blue-700);
        text-decoration: none;
      }

      body {
        margin: 0;
        padding: 0;
      }

      .container {
        background-color: white;
        color: #333;
        width: 448px;
      }

      .top-title-bar {
        align-items: center;
        border-bottom: 1px solid var(--paper-grey-300);
        display: flex;
        font-size: 16px;
        height: 52px;
        padding: 0 24px;
      }

      .action-container {
        display: flex;
        justify-content: flex-end;
        padding: 16px;
      }



    </style>
  </template>
</dom-module>
/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  align-items: center;
  box-sizing: border-box;
  color: var(--paper-grey-900);
  display: flex;
  flex-direction: column;
  font-size: 100%;
  justify-content: center;
  margin: 0;
  min-height: 100vh;
  padding: 8px;
}

.watermark {
  -webkit-mask-image: url(chrome://resources/images/google_logo.svg);
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 100%;
  animation: fadeIn 1s cubic-bezier(0, 0, .2, 1) both;
  background: var(--paper-grey-400);
  bottom: 24px;
  height: 24px;
  position: absolute;
  width: 74px;
}

@media(max-height: 608px) {
  .watermark {
    display: none;
  }
}
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>$i18n{headerText}</title>

  <link rel="import" href="chrome://resources/html/polymer.html">

  <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
  <link rel="import" href="chrome://resources/html/cr.html">
  <link rel="import" href="chrome://resources/html/util.html">
  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
  <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">

  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
  <link rel="stylesheet" href="chrome://welcome/welcome.css">

  <dom-module id="welcome-app">
    <template>
      <style include="paper-button-style">
        @keyframes slideUpContent {
          from {
            transform: translateY(186px);
          }
        }

        @keyframes fadeIn {
          from {
            opacity: 0;
          }
        }

        @keyframes fadeOut {
          to {
            opacity: 0;
          }
        }


        @keyframes fadeInAndSlideUp {
          from {
            opacity: 0;
            transform: translateY(8px);
          }
        }

        @keyframes spin {
          from {
            transform: rotate(1440deg) scale(0.8);
          }
        }

        @keyframes fadeInAndSlideDownShadow {
          from {
            opacity: .6;
            top: 0;
          }
        }

        @keyframes scaleUp {
          0% {
            transform: scale(.8);
          }
        }

        @keyframes colorize {
          from {
            filter: grayscale(100%) brightness(128%) contrast(20%) brightness(161%);
            opacity: .6;
          }
        }

        @keyframes bounce {
          0% {
            transform: matrix3d(0.8, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          7.61% {
            transform: matrix3d(0.907, 0, 0, 0, 0, 0.907, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          11.41% {
            transform: matrix3d(0.948, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          15.12% {
            transform: matrix3d(0.976, 0, 0, 0, 0, 0.976, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          18.92% {
            transform: matrix3d(0.996, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          22.72% {
            transform: matrix3d(1.008, 0, 0, 0, 0, 1.008, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          30.23% {
            transform: matrix3d(1.014, 0, 0, 0, 0, 1.014, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          50.25% {
            transform: matrix3d(1.003, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          70.27% {
            transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
          100% {
            transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
          }
        }

        .content {
          height: 100%;
          overflow-y: hidden;
        }

        .slider {
          align-items: center;
          animation: slideUpContent 600ms 1.8s cubic-bezier(.4, .2, 0, 1) both;
          display: flex;
          flex: 1;
          flex-direction: column;
          justify-content: center;
          max-width: 500px;
        }

        .heading {
          animation: fadeInAndSlideUp 600ms 1.9s cubic-bezier(.4, .2, 0, 1) both;
          font-size: 2.125em;
          margin-bottom: .25em;
          margin-top: 1.5em;
          text-align: center;
        }

        .subheading {
          animation: fadeInAndSlideUp 600ms 1.9s cubic-bezier(.4, .2, 0, 1) both;
          color: #939393;
          font-size: 1em;
          font-weight: 500;
          margin-top: .25em;
          text-align: center;
        }

        .logo {
          animation: fadeIn 600ms both, bounce 1s 600ms linear both;
          height: 96px;
          position: relative;
          width: 96px;
        }

        .logo-icon {
          animation: spin 2.4s cubic-bezier(.4, .2, 0, 1) both,
                     colorize 300ms 700ms linear both;
          background-image: -webkit-image-set(url(chrome://welcome/logo.png) 1x,
                                              url(chrome://welcome/logo2x.png) 2x);
          background-size: 100%;
          height: 96px;
          width: 96px;
        }

        .logo-shadow {
          animation: fadeInAndSlideDownShadow 300ms 600ms both;
          background: rgba(0, 0, 0, .2);
          border-radius: 50%;
          filter: blur(16px);
          height: 96px;
          position: absolute;
          top: 16px;
          width: 96px;
          z-index: -1;
        }

        .signin {
          animation: fadeInAndSlideUp 600ms 2s cubic-bezier(.4, .2, 0, 1) both;
          margin-top: 3em;
          text-align: left;
        }

        .signin-description {
          font-size: .875em;
          line-height: 1.725em;
          max-width: 344px;
        }

        .signin-buttons {
          align-items: center;
          display: flex;
          flex-direction: column;
          margin: auto;
          margin-top: 2em;
          width: fit-content;
        }

        paper-button {
          font-size: .8125em;
          /* Makes sure the two paper-buttons are the same width since they're
             placed vertically. Requires parent to be "width: fit-content;". */
          width: 100%;
        }

        #cancel {
          margin-bottom: 2px;  /* Prevent focus ring from being chopped. */
          margin-top: 1.5em;
        }
      </style>
      <div class="content">
        <div class="slider">
          <div class="logo">
            <div class="logo-icon" on-click="onLogoTap_"></div>
            <div class="logo-shadow"></div>
          </div>
          <div class="heading">$i18n{headerText}</div>
    
          <div class="signin">
            <div class="signin-description">$i18n{descriptionText}</div>
            <div class="signin-buttons">
              <paper-button class="action-button" on-tap="onAccept_">
                $i18n{acceptText}
              </paper-button>
              <paper-button id="cancel" on-tap="onDecline_">
                $i18n{declineText}
              </paper-button>
            </div>
          </div>
        </div>
      </div>
    </template>
    <script src="welcome.js"></script>
  </dom-module>
</head>
<body>
  <welcome-app></welcome-app>
  <div class="watermark"></div>
</body>
</html>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'welcome-app',

  /** @private */
  onAccept_: function() {
    chrome.send('handleActivateSignIn');
  },

  /** @private */
  onDecline_: function() {
    chrome.send('handleUserDecline');
  },

  /** @private */
  onLogoTap_: function() {
    this.$$('.logo-icon')
        .animate(
            {
              transform: ['none', 'rotate(-10turn)'],
            },
            /** @type {!KeyframeEffectOptions} */ ({
              duration: 500,
              easing: 'cubic-bezier(1, 0, 0, 1)',
            }));
  },
});
/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  align-items: center;
  color: var(--google-grey-700);
  display: flex;
  flex-direction: column;
  font-size: 100%;
  justify-content: center;
  margin: 0;
  min-height: 100vh;
  text-align: center;
}

.watermark {
  -webkit-mask-image: url(chrome://resources/images/google_logo.svg);
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 100%;
  animation: fadeIn 1s cubic-bezier(0, 0, .2, 1) both;
  background: var(--paper-grey-400);
  bottom: 24px;
  height: 24px;
  position: absolute;
  width: 74px;
}

@media(max-height: 608px) {
  .watermark {
    display: none;
  }
}
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
  <head>
    <meta charset="utf-8">
    <title>$i18n{headerText}</title>

    <link rel="import" href="chrome://resources/html/polymer.html">
    <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
    <link rel="import" href="welcome_app.html">

    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
    <link rel="stylesheet" href="chrome://welcome/welcome.css">
  </head>
  <body>
    <welcome-app></welcome-app>
    <div class="watermark"></div>
  </body>
</html>
<link rel="import" href="chrome://resources/html/cr.html">
<script src="welcome_browser_proxy.js"></script>
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview A helper object used by the welcome page to interact with
 * the browser.
 */

cr.define('welcome', function() {

  /** @interface */
  class WelcomeBrowserProxy {
    handleActivateSignIn() {}
    handleUserDecline() {}
  }

  /** @implements {welcome.WelcomeBrowserProxy} */
  class WelcomeBrowserProxyImpl {
    /** @override */
    handleActivateSignIn() {
      chrome.send('handleActivateSignIn');
    }

    /** @override */
    handleUserDecline() {
      chrome.send('handleUserDecline');
    }
  }

  cr.addSingletonGetter(WelcomeBrowserProxyImpl);

  return {
    WelcomeBrowserProxy: WelcomeBrowserProxy,
    WelcomeBrowserProxyImpl: WelcomeBrowserProxyImpl,
  };
});
<link rel="import" href="chrome://resources/html/polymer.html">

<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="welcome_browser_proxy.html">

<dom-module id="welcome-app">
  <template>
    <style include="paper-button-style">
      @keyframes slideUpContent {
        from {
          transform: translateY(120px);
        }
      }

      @keyframes fadeIn {
        from {
          opacity: 0;
        }
      }

      @keyframes fadeInAndSlideUp {
        from {
          opacity: 0;
          transform: translateY(8px);
        }
      }

      @keyframes fadeOutAndSlideUp {
        to {
          height: 0;
          opacity: 0;
          transform: translateY(-8px);
        }
      }

      @keyframes spin {
        from {
          transform: rotate(1440deg) scale(0.8);
        }
      }

      @keyframes colorize {
        from {
          filter: grayscale(100%) brightness(128%) contrast(20%) brightness(161%);
          opacity: .6;
        }
      }

      @keyframes bounce {
        0% {
          transform: matrix3d(0.8, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        7.61% {
          transform: matrix3d(0.907, 0, 0, 0, 0, 0.907, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        11.41% {
          transform: matrix3d(0.948, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        15.12% {
          transform: matrix3d(0.976, 0, 0, 0, 0, 0.976, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        18.92% {
          transform: matrix3d(0.996, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        22.72% {
          transform: matrix3d(1.008, 0, 0, 0, 0, 1.008, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        30.23% {
          transform: matrix3d(1.014, 0, 0, 0, 0, 1.014, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        50.25% {
          transform: matrix3d(1.003, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        70.27% {
          transform: matrix3d(0.999, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
        100% {
          transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
        }
      }

      .slider {
        align-items: center;
        animation: slideUpContent 600ms 2.5s cubic-bezier(.4, .2, 0, 1) both;
        display: flex;
        flex: 1;
        flex-direction: column;
        justify-content: center;
        max-width: 500px;
      }

      .heading-container {
        animation: fadeInAndSlideUp 1s 400ms cubic-bezier(.4, .2, 0, 1) both;
        color: var(--paper-grey-800);
        font-size: 2.5em;
        line-height: 1em;
        margin-bottom: 0.25em;
        margin-top: 1.5em;
        position: relative;
      }

      .heading {
        animation: fadeOutAndSlideUp 600ms 2.1s cubic-bezier(.4, .2, 0, 1) forwards;
        /* Makes sure fading-in/out doesn't impact the logo position. */
        position: absolute;
      }

      .second-heading {
        animation: fadeInAndSlideUp 600ms 2.5s cubic-bezier(.4, .2, 0, 1) both;
        font-size: 0.6em;
      }

      #logoWrapper {
        animation: fadeIn 600ms both, bounce 1s 600ms linear both;
        height: 96px;
        position: relative;
        width: 96px;
      }

      #logo {
        animation: spin 2.4s cubic-bezier(.4, .2, 0, 1) both,
                   colorize 300ms 700ms linear both;
        background-image: -webkit-image-set(url(chrome://welcome/logo.png) 1x,
                                            url(chrome://welcome/logo2x.png) 2x);
        background-size: 100%;
        height: 96px;
        width: 96px;
      }

      .signin {
        animation: fadeInAndSlideUp 600ms 2.5s cubic-bezier(.4, .2, 0, 1) both;
      }

      .signin-description {
        font-size: 1em;
        line-height: 1.725em;
        max-width: 344px;
      }

      .signin-buttons {
        align-items: center;
        display: flex;
        font-size: .8125em;
        justify-content: space-between;
        margin-top: 2.5em;
      }

      paper-button {
        min-width: 92px;
      }
    </style>
    <div class="slider">
      <div id="logoWrapper">
        <div id="logo" on-tap="onLogoTap_"></div>
      </div>
      <div class="heading-container">
        <div class="heading">$i18n{headerText}</div>
        <div class="second-heading">$i18n{secondHeaderText}</div>
      </div>
      <div class="signin">
        <div class="signin-description">$i18n{descriptionText}</div>
        <div class="signin-buttons">
          <paper-button on-tap="onDecline_">
            $i18n{declineText}
          </paper-button>
          <paper-button class="action-button" on-tap="onAccept_">
            $i18n{acceptText}
          </paper-button>
        </div>
      </div>
    </div>
  </template>
  <script src="welcome_app.js"></script>
</dom-module>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'welcome-app',

  welcomeBrowserProxy_: null,

  /** @override */
  ready: function() {
    this.welcomeBrowserProxy_ = welcome.WelcomeBrowserProxyImpl.getInstance();
  },

  /** @private */
  onAccept_: function() {
    this.welcomeBrowserProxy_.handleActivateSignIn();
  },

  /** @private */
  onDecline_: function() {
    this.welcomeBrowserProxy_.handleUserDecline();
  },

  /** @private */
  onLogoTap_: function() {
    this.$.logo.animate(
        {
          transform: ['none', 'rotate(-10turn)'],
        },
        /** @type {!KeyframeEffectOptions} */ ({
          duration: 500,
          easing: 'cubic-bezier(1, 0, 0, 1)',
        }));
  },
});
/* Copyright 2016 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  align-items: center;
  box-sizing: border-box;
  color: var(--paper-grey-900);
  display: flex;
  flex-direction: column;
  font-size: 100%;
  justify-content: center;
  margin: 0;
  min-height: 100vh;
}
<!DOCTYPE html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <title>$i18n{headerText}</title>

  <link rel="import" href="chrome://resources/html/polymer.html">

  <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
  <link rel="import" href="chrome://resources/cr_elements/icons.html">
  <link rel="import" href="chrome://resources/html/cr.html">
  <link rel="import" href="chrome://resources/html/load_time_data.html">
  <link rel="import" href="chrome://resources/html/util.html">

  <link rel="import" href="chrome://resources/html/action_link.html">
  <link rel="import" href="chrome://resources/html/action_link_css.html">

  <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
  <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">

  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
  <link rel="stylesheet" href="/welcome_win10.css">

  <script src="strings.js"></script>

  <dom-module id="welcome-win10">
    <template>
      <style include="action-link paper-button-style">
        :host {
          align-items: flex-start;
          display: inline-flex;
          flex-direction: column;
          opacity: 0;
          padding: 4em 1.5em 1.5em 1.5em;
          transition: opacity 300ms;
        }

        :host .section {
          --expandable-section-height: 28.375em;
        }

        :host([is-accelerated]) .section {
          --expandable-section-height: 26.375em;
        }

        a {
          color: var(--google-blue-500);
          text-decoration: none;
        }

        ol {
          margin: 0;
          overflow: auto;
          padding: 0;
        }

        strong {
          font-weight: 500;
        }

        .header-logo {
          content: url(chrome://welcome-win10/logo-large.png);
          height: 3.125em;
          margin: 0 -0.0625em;
        }

        h1 {
          font-size: 2.125em;
          font-weight: normal;
          margin: 0;
          padding-bottom: 2rem;
          padding-top: 1rem;
        }

        .sections {
          margin-bottom: 2em;
        }

        .section.expandable:first-child {
          border-top: 1px solid var(--google-grey-300);
        }

        .section.expandable {
          border-bottom: 1px solid var(--google-grey-300);
        }

        .section.expandable .section-heading {
          color: var(--google-blue-500);
          cursor: pointer;
        }

        .section-heading {
          align-items: center;
          display: flex;
          padding: 1.5em 0;
        }

        .section-heading-text {
          flex: 1;
          font-weight: 500;
        }

        .section.expandable .section-heading-text {
          font-weight: normal;
        }

        .section.expandable.expanded .section-heading-text {
          font-weight: 500;
        }

        .section-heading-expand {
          height: 1.25em;
          transition: transform 150ms cubic-bezier(.4, .2, 0, 1) 50ms;
          width: 1.25em;
        }

        .section.expandable.expanded .section-heading-expand {
          transform: rotate(180deg);
          transition-delay: 150ms;
        }

        .section-steps {
          overflow: hidden;
        }

        .section-steps li {
          margin-bottom: 1em;
          margin-inline-start: 1.25em;
          padding-inline-start: 1em;
        }

        .section-steps li:last-child {
          margin-bottom: 1em;
        }

        .section.expandable .section-steps {
          height: var(--expandable-section-height);
          max-height: 0;
          opacity: 0;
          transition: max-height 300ms cubic-bezier(.4, .2, 0, 1) 50ms,
                      opacity 150ms;
          visibility: hidden;
        }

        .section.expandable.expanded .section-steps {
          max-height: var(--expandable-section-height);
          opacity: 1;
          transition: max-height 300ms cubic-bezier(.4, .2, 0, 1) 50ms,
                      opacity 150ms 250ms;
          visibility: visible;
        }

        paper-button {
          font-size: .8125em;
        }

        .logo-small {
          content: url(chrome://welcome-win10/logo-small.png);
          display: inline;
          height: 1.25em;
          vertical-align: top;
          width: 1.25em;
        }

        .screenshot {
          display: block;
          height: 440px;
          margin: 0 auto;
          max-width: 100%;
          position: relative;
          top: -96px;
          width: 720px;
        }

        .screenshot-image {
          box-shadow: 0 0 0 1px rgba(0, 0, 0, .12), 0 1px 2px
                      rgba(0, 0, 0, .24);
          height: 48vw;
          margin: 1em 0;
          max-height: 300px;
          max-width: 400px;
          min-height: 150px;
          min-width: 200px;
          position: relative;
          width: 64vw;
        }

        #default-image {
          background: url(chrome://welcome-win10/default.webp);
          background-repeat: no-repeat;
          background-size: cover;
        }

        #taskbar-image {
          background: url(chrome://welcome-win10/pin.webp);
          background-repeat: no-repeat;
          background-size: cover;
        }

        .screenshot-overlay {
          box-sizing: border-box;
          line-height: 0;
          position: absolute;
          user-select: none;
        }

        .screenshot-overlay div {
          cursor: default;
        }

        #taskbar-overlay {
          left: 31%;
          top: 73%;
        }

        #taskbar-overlay div {
          color: #ccc;
          font-family: Tahoma, Verdana, Segoe, sans-serif;
          font-weight: 500;
        }

        #switch-anyway-overlay {
          left: 38%;
          top: 83%;
        }

        #switch-anyway-overlay div {
          color: rgb(0, 117, 218);
          font-family: Segoe UI;
        }

        #icon-overlay {
          background-image: url(chrome://welcome-win10/logo-small.png);
          background-size: cover;
          height: 8%;
          left: 46%;
          top: 90%;
          width: 6%;
        }

        /* These values are precisely set so that the text over the screenshot
         * starts scaling at the same time the image starts scaling too. */
        @media (max-width: 626px) {
          #taskbar-overlay {
            font-size: 1.95vw;
          }

          #switch-anyway-overlay {
            font-size: 1.92vw;
          }
        }

        /* Font-sizes used when the screenshot exactly reaches its max size. */
        @media (min-width: 626px) {
          #taskbar-overlay {
            font-size: 12.2px;
          }

          #switch-anyway-overlay {
            font-size: 12px;
          }
        }
      </style>
      <div class="header-logo" role="presentation"></div>
      <h1>$i18n{headerText}</h1>
      <div class="sections">
        <div class$="[[computeClasses(isCombined)]]">
          <template is="dom-if" if="[[isCombined]]">
            <div role="heading" aria-level="2">
              <a id="tab1" is="action-link" class="section-heading"
                  on-tap="onToggle" role="button" aria-controls="panel1"
                  aria-expanded="true">
                <div class="section-heading-text" role="presentation">
                  $i18n{defaultBrowserSubheaderText}
                </div>
                <iron-icon class="section-heading-expand" icon="cr:expand-more"
                    role="presentation">
                </iron-icon>
              </a>
            </div>
          </template>
          <template is="dom-if" if="[[!isCombined]]">
            <div class="section-heading" role="text">
              <div class="section-heading-text" role="presentation">
                $i18n{defaultBrowserSubheaderText}
              </div>
            </div>
          </template>
          <ol id="panel1" class="section-steps" aria-labelledby="tab1">
            <li>
              <a is="action-link" on-tap="onOpenSettings">
                $i18n{openSettingsText}
              </a>
            </li>
            <template is="dom-if" if="[[!isAccelerated]]">
              <li>
                <div role="presentation">$i18nRaw{clickEdgeText}</div>
              </li>
            </template>
            <li>
              <div role="presentation">$i18nRaw{clickSelectChrome}</div>
            </li>
            <li>
              <div role="presentation">$i18nRaw{clickSwitchAnywayText}</div>
              <div class="screenshot-image" id="default-image"
                  role="presentation">
                <div class="screenshot-overlay" id="switch-anyway-overlay">
                  <div aria-hidden="true">$i18n{switchAnywayLabel}</div>
                </div>
              </div>
            </li>
          </ol>
        </div>
        <template is="dom-if" if="[[isCombined]]">
          <div class="section expandable">
            <div role="heading" aria-level="2">
              <a id="tab2" is="action-link" class="section-heading"
                  on-tap="onToggle" role="button" aria-controls="panel2"
                  aria-expanded="false">
                <div class="section-heading-text" role="presentation">
                  $i18n{pinSubheaderText}
                </div>
                <iron-icon class="section-heading-expand" icon="cr:expand-more"
                    role="presentation">
                </iron-icon>
              </a>
            </div>
            <ol id="panel2" class="section-steps" aria-labelledby="tab2">
              <li>$i18nRaw{rightClickText}</li>
              <li>
                <div role="presentation">$i18nRaw{pinInstructionText}</div>
                <div class="screenshot-image" id="taskbar-image"
                    role="presentation">
                  <div class="screenshot-overlay" id="taskbar-overlay">
                    <div aria-hidden="true">$i18n{pinToTaskbarLabel}</div>
                  </div>
                  <div class="screenshot-overlay" id="icon-overlay">
                  </div>
                </div>
              </li>
            </ol>
          </div>
        </template>
      </div>
      <paper-button class="action-button" on-tap="onContinue">
        $i18n{continueText}
      </paper-button>
    </template>
    <script src="/welcome_win10.js"></script>
  </dom-module>
</head>
<body>
  <welcome-win10></welcome-win10>
</body>
</html>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Polymer({
  is: 'welcome-win10',

  properties: {
    // Determines if the combined variant should be displayed. The combined
    // variant includes instructions on how to pin Chrome to the taskbar.
    isCombined: {
      type: Boolean,
      value: false,
    },

    // Indicates if the accelerated flow is enabled.
    isAccelerated: {
      type: Boolean,
      value: function() {
        return loadTimeData.getBoolean('acceleratedFlowEnabled');
      },
      reflectToAttribute: true,
    },
  },

  receivePinnedState_: function(isPinnedToTaskbar) {
    // Allow overriding of the result via a query parameter.
    // TODO(pmonette): Remove these checks when they are no longer needed.
    const VARIANT_KEY = 'variant';
    const VARIANT_TYPE_MAP = {'defaultonly': false, 'combined': true};
    const params = new URLSearchParams(location.search);
    if (params.has(VARIANT_KEY) &&
        params.get(VARIANT_KEY) in VARIANT_TYPE_MAP) {
      this.isCombined = VARIANT_TYPE_MAP[params.get(VARIANT_KEY)];
    } else {
      this.isCombined = !isPinnedToTaskbar;
    }

    // Show the module.
    this.style.opacity = 1;
  },

  ready: function() {
    // The accelerated flow can be overridden with a query parameter.
    const FLOWTYPE_KEY = 'flowtype';
    const FLOW_TYPE_MAP = {'regular': false, 'accelerated': true};
    const params = new URLSearchParams(location.search);
    if (params.has(FLOWTYPE_KEY)) {
      if (params.get(FLOWTYPE_KEY) in FLOW_TYPE_MAP) {
        this.isAccelerated = FLOW_TYPE_MAP[params.get(FLOWTYPE_KEY)];
      } else {
        console.error(
            'Found invalid value for the \'flowtype\' parameter: %s',
            params.get(FLOWTYPE_KEY));
      }
    }

    // Asynchronously check if Chrome is pinned to the taskbar.
    cr.sendWithPromise('getPinnedToTaskbarState')
        .then(this.receivePinnedState_.bind(this));
  },

  computeClasses: function(isCombined) {
    return isCombined ? 'section expandable expanded' : 'section';
  },

  onContinue: function() {
    chrome.send('handleContinue');
  },

  onOpenSettings: function() {
    chrome.send('handleSetDefaultBrowser');
  },

  onToggle: function() {
    if (!this.isCombined) {
      return;
    }
    const sections = this.shadowRoot.querySelectorAll('.section.expandable');
    sections.forEach(function(section) {
      const isExpanded = section.classList.toggle('expanded');
      section.querySelector('[role~="button"]')
          .setAttribute('aria-expanded', isExpanded);
    });
  }
});
     Zms6_2s3%;:L=MS_]?y Q՛,@R$%[p8@`]Г8}{`,_L+-e[vvh2cK(mc20-"~294̨RGE*_^\lb<4v
H8fnYs6*}<r}2ANMcE	FӠzع_ZV/ʸ3Oe`*g.dkj9ip/ŲP!"mr{/GSZӐӓ񑣴OdVfS$vKwqz8DȔh1?"FEƌx2f0a\J{<]za$LAXD)]yug!478z:ua`CSDƱ?0~WZig\9
B湁\:bc<S1cVdݐ i˽GEZI_N8P$4/z.#ahG;㰑Ɲ9b]ɫC$V,=kP|XmvC_vX<&"Bu&'wvf\/d^Y;<%za,La*]	D7*1Ӌ٫U?IX"1b9'Y-MWW[uܓ;i0z2~M9Jm?TE4PMakrA"4-.5/2/Q^ȑJ{{pK(!RN
F*S>͕v*8+9
655*\s|O޷9b V/d_xW&$<h!aHv*M;Y5&y{,,3:ZV~1tj	{aR[+3qsJyjFO5ldjO}50'ѦN `:!i_yfZ59aVͧxNMM-d/N-%s0fꂾT<"BceW,1-Nf'
JGS'6؈mM,NF|J{'RƱLA;dkQÅR
,lџGG#O֫6yPM5u8]vҕV|'2/JZ4<-ї(B^VG>Aބ'+NL( 6VvV
)~xws.ňGYCιA=&06T)ʵw0OKTX;SX\mcݖA(lfJh`	AFw!ǆ5PlR1A%WNm5Ѵ>L~Vh~v)m8 m>FȓQ>j^Q]a0ڒhRO5@U.+oGW].
0Pfƞܷ1qOEn$zP,P>(1$4	עy=nˆai/"^(P1P/:>-#n4:F͖p1{Rύ+Dzb封}PZ|z3=yp~Ƞ'~UX+w`A^$Xw	HK^-|P󹌨2p~[=+.xR00i$	dTE
BZv8wƝdxLkCP4s`DRx4<+RWk8t|&R%:dSΪs])teq!}uјyk>-"`:.b~
ow)T.G@xk߆ӮqP0A*8e*h'"Н~d+YUZզ"i`ioYYRRX	+4ã#(ds(6KGsXiLjnIP:65}ԇ_)08AE%ۼ#p=䩴B`ઁ[/ŏNӏ*z7zB&(ϑiؒ{FW6ð{Po'"oX> 7qGGCu@ v<FAvv-h`mtmhX78uwCwGQ}__ǹ0:߫9Cb9.l5h`\
ߝ=DNX^Ѧ@i>9 m.CJPP$YHǞ+,${E0V|=d&r*6W&Z3D:S<,ك;5x$N`Ϊ'HEi>5
^m\ݥ{ytN=,k*@e[$$U5}8Kz䉸4R53Ȍ"6׮V2w pѯД:^7۴%ئ7[f@8EHmWQ3Ԏ:Ig{9q:BhegP.,tI-Fk/W,MPN}x},Qo[F?ɍ=Vԇb}&ҴL>uT>ׁ3ߨ"{L/*DoqFi'-#:ڟwΔ'PwfoQ`$$I/vvoO,%       }ksFw
IZUuvet"K:"-C1	pP6'0 AIMΦR	Ekzz?M_Ί;~|`8,Kj쭊Y`o>ad"ٕz[ϟiP<U6$D ^W"KDo0x;8͋D$ЭE0	`,4]%Q''~0碷?? l	ǟ㨘]hy	qp>H`62Eb1?o7}E\(j17;Be585]%"4 uqy;}+`=F+w 1뭻g1f/a>W	pH$T
	$7EK",<B`<7qMv+2T?,ZTROm;X3\$aod?9qomα~I<mEYbs&ww~a@}	5),&|9o|4
#n4=tWA'm2L//BgLas'kSߓ❋b%V")Àhd͟x/rIu舄@JY/OCGxvԈ,s_yۂᑩ|Àpʹ3f}1` UnuHFΠk&gN$/3iKA] %\.EyED,m!DD\{6Z 08FRA%84OǿQqK!T%2|iSSY#4V m:=M,f{6?Ȧ?d}.oUm8!K9v^<%EY* 梀MaaQUaRDE&`N\x'sL
PQHMz5XOfb&-,/Mp>&(8(Cqb,Q_	љd=@MgQ"Ӏ faO1h1gYuCSC*01'O8|h6,]#ll`	rd"`QNU=Б
-CzlՀ>vيe-l &hYA[:NO螾sFX"* U,~|UXcc9c!v)u_,)Y(&(ȮQs^5|=m\ĥ`2KDKcA%FsWNqL3
ދ% (<ɈYQd74]t8ML\H']k5Ri?٪f$(M~Tp_[]h3xNL)i7ejْhERZIX^Fa1TWnGjJ@
jw{{	vH;>Xu.Dt$gvmWJgvuY~ު$L=qU
M"]	s J*rJ2vxFqP.IĮ"'
N0^S0'0@w A hPaX<3h A)q-NZē<0}aBVY0$3wLH)S*hBGE'Wm6H`<9c)(OyI }E6|$#mbRLi<)	49RRjJ:rrqA%˕$)R APp8S;	Dce=\B1(`pK:_ǹ8Y{"[Ɛ/)t*aq#Uh; ՘)bBH~d+h{j[)
@Cy?m_dX
v>Uo7n_EhWT Ȥ`oX`xQ͸	(ȶ_oK	NKbh?1z1lwE7A S25;JTn)9ƺIir[%6^:RԿX:1M虜\5d^}l/т)wF#<WJ4^dfX^hY*eqQ^@Gٛؼ8Vך	B7{f_	7;Q+7v;c	Rԑ2:ĠQkd/-'<jx&Ɯ`TrTt\;4r	!@ ը?pQ?$-(꣭wBtv:fCPf6e%m8	˚
JУ['ebAiX#UM1kMCHee8̘s,TQj"G^ZV te
haLpuÁȩc޸9Eʧ%pO"p/CRYZ?MC`s-Z2<ScṦe[똣drL۸P=oKk.ZED˓ʡw,ȏ2$ihF_&.[?Ŭf>"QwzVN%Qs1o-JN fFf
>ꛩWWBe~L,7˴,:'T=H=@n -R(]tն=?(-y\l43tvN+=nWc@?T#S)=82%hԧL:]i`̢4J%%$3!?|xW4=VÎVhϗs##uL ?>Pŵ	Jℨ)!p<"eÆxF'=ROV&*oT.bBit8RKyOD2!dBlXLus=%x	Ȅdtǔ?\6A)X_OyގơyqUMV,FibfK%3>cX:0`m
tGЧ^U(߭Qr!Spaw+g7XᒗG*79h̎W<	 *NmDjm`
]^)?q$`Yh퉨#S	\DsJG+^:3||rTH \9vb..4.0>A}ߵ¶{,dH_ߢ pWN 3Gc4Gge0́Tt?{,&7p!'Pgbn$eŘ(%L53FlOXhb.Ws+/
ȢXtw+O?1fE20'nisbHlvi;j]]^ pb,*'̎f#iD=yn{z#nNnR5YwVE[3a_,:Wk)66̷u&;I(Y6H{1FQ$m``b$+qRŒSLg,@FO41۠0?UQN~@NCM%N9]IMWW:M<\$^݈M7J)#4.BDU+,ܔ%l.]ЭY[\ȔyBS]	Iv9ou,p,y=&B]:\R(_pHOZHPftxl7qBc侐*#hJIeŃJVJo2i9mS2C|2G0YCdkQG<4=^ՠlDcB55>KAj"]:IR𰣹Rty
Gz+"tR`'nOg*?oBw]3kgrR|.UE>G$kRflcf뱍pXaGZ6꺁^ayH `W]BL(_)hA}kت(7KI JC;)mp|5U 7J[A
wq]_RHUl] pGTsdVv"" %jG#^&vTثce?2Wqʁ r8kOmqSP.JZ0w<
ܟOH:-Jؒ#Œt8K
5ZfF<9+{'4 b7JȔ2bsVW^ap0
óA0xe0$_`$0wre8xZᷜMzYXz<W~/.EYc)]q;itڒGqD/4CbJ͊y[bq
F}*uy@\X\C:cv-u}M@񞧅;xޞӊԈ!
q,W[̵attrv!JFGѠ ;8h wZA(_JPhD/!tU ,` n;C{pkuSm	Y8k "6H#NχuQ*LZ͇ꟼ;=/fN헠bvAl2ay68N?JyJ[*j}on$|5^ąJRO}@i䤩;>z$y /%#>&f۠c
(R<8T:=n8a|h@r$U9T67rFZ$Te	ｵ7BŻ"%N<#(nW%F(pV˯c !{.gx"
jXRƨ	NY%Wޕ}8R/[h*?WwIg`F#Z `q
0.x"'ut:"fr61)BʡsLHusQ-a-P늎w.d0(W+rn7j+6F^sȲ,`Ԓ5\1xmhS] Tbl	dEe'Xe(7]@d!J-Ni=,85bH.flZ5Gq(oʰ·ـ2R tG@k{;cg6L7o-k oI<hܖ7Eխf7sogq}XG}{kcJأYi`[9*WWw+;y1 EJG%3v!,
 ɏWa8nϋ*}S#RժA>=< prR-u} :lJVj{3L4sCph#GJ"1Q=`{qN5y@6t\tk #g_0NO(oA'M9^xFqӻ~hkH>u'Za	G 6?r:{>1m>[]2w8W8?,npVoʏe- 7W@q1,y~^~^?6/?#istZ:_anFntv_?r@3:Bj%|,Wc#Xp=۠
뤉%8r= I~2nH.ٳ\k *=%(OV-rO[`bJŃ[Y;3Ϩ,J$7Vra8ȳ**lLȊʒ rձ	UR1fE09Q'Іƽ_TwJjs̿zXQ1foxI[%z
l;-ngmsW 0V;_Nݎ+ul͈
w٤xmoM<UtVeC>ik*Z}lO˞Eql 9R^8G<&<~.; 5 iڊ=(;DئPvi-!r$`7Q]uԯ-֣#ʮ8M&ٴ*6,'q@lQĪmehm]JSi^q:vcԉk+C`Smv$ آ^'8q܀: H"+ OxY[?0hxI[ua4c~.xlҭu'/VIt*ūW@~`=+$W`AIFO(XJwnN/.nr_NN?t ),bcH5zHKgYY).3ۻV0u]VYn5 NT6E1"]]6|"76+LUϟo,*ƒatѥxJjk.Sם2# *'Y,0_-U->;36N+-XOPOpZƔ`se93rޢ_E)Ob;X0E}&"xuy^6W"a35Fi|Wh!UxNkaj%BF/;r͹-'ڿІ]PbUwx+Y'V5dpLnߔ%J;d21])xKǢ4I@e]f0Z3/u.|D	U-=GT&) T}pd.ʳ0 0kNSt;l?D+^>0
#j	>rO5PCcڱ vj7	J]AxKtoà`4l"' (A:,mwU>:R2x3Z搌(<Fp  Q]+q4Ythu &/;tޕt9E-jAS7,}~R/_`QVri<6>=ݦOJ^ק
[U;jsB!j&e"~;sRߍd&qiƠN[̤ΧiG]'BeDk4y^Sj)Um<bYsyKb'htV 1x >UYFUA~bWY⑏4U^r+H%UZڔ_iA'sQ
ܦ	:rﴭ'G>, ~(@ZBBۍҊ`FDEL~ MPaMLTi0]OZ $,^"y0%s/9^Z-Ԩ7j(U4Dao>'	|uC/P`'A( :[p|7KSY3edE+~o<8/O"$eZfVL,9wݘp5iJb>zPyaY+>Tv1/k/{"fp%ldmHG%8T&ԯf&ʯڪ ?:aa(ߵ2{k4)W*OT:6@,S?(2Yl{.(`!k׳²Дu8:^׷QT5%V:uKji\o]E6lFMg7dI&1oq;킋^ݨ5.èIm$E!8$Y6_#P]2^5sU
eYr{O-5kֹٝXU+qJ TTS>ֵ#jקOV5-I5tYu+xڞ`)r[_,4|bnp{<~A!&?n¯.!u7ł۵Yrllئ:p^4MCK"໚*t	I%`UӕKmm6(|2%Uq%ˉs1u.zdY,+[Xs˱]mf$A:ގR"r*Sbֈx:,$$UTɥs~4{{ uڡemXu{CwP9tPP->T~SD++fZrfXE-%wkRҔaesyʍ|`fs%S]}<]WڮGaі`cKdUNT:R ڣuTufd:ܯۓ7
PY$*=mlkta9'	|5"	ؑŠ45lsc؂E|q$GVhB|:vLJG'ӳ$\,@GKъypp^W*,v*Ս5hߍyz
6
O=yFʹ1T7UYgԭ.=U6\Lkwsd~3'n]`KZRok҉kր)S^%bi؞^7sa٭ͅ+;g_?_?249PM%6aqLznE)D~
)'\d%&\C.;htBmࣔZg L+X=BDEM$An*g1/,bӃsw'E7]TԓrT]?OP8z~۪,^Au{`]ǗƆObiݩ3G~JEW]9V+MAۦYJJ=UCnWE.e.wv\O߮`͌OIhjq|OO1λ{ßNniUzLHm<T~Ӆ
c:I%RB3_AbNWb]ƪ?R+_3V:C
*,T"T,XSFym6ɲ OL̗&  %\Zv LycC*ΩQ#_c	F
cYU_Oe`jIv|w0:>y?:8?=z,(KPTNl <2'TQfoA`zT2pH.	WN	|>n.KI.|hf~ 	\jt=%YZ~[?˰pr<COxv뭞	x;'9DQb^ũԅ3%$ 
r^|u\	=؇KdNL:@qr.!S庞 0z#fyKo` ~C,M9n_tEhaY3ʂ	' ƿą~ ]b1`H	>pR?U5OJcNе*z`ө {ȊT)׋&2sNEA1>'OIQ0S.lM/_{|i'/fqT}SGi/r'`^_p%VӋH9?[WLTH)>)wڙH,3~|S.}C[tm]N6(;6Q+/	;M2_hoK_~59/H1iZ|QD1cیds4jqHIlz}&&2wcG-yv~ϣ` W&1h2/j~ƥҶu]@MMXއj4D	`[md݌z L/
:]c,iD.U +leQĲRG<X4[y}-zRej	2tØX3dంKH-P_X+%+7V{Fo ^8lm׹t.
@1jye{~Ť沍v)Wo,y zǢpͣxLI0!&ڨzf~)}gdʈl#,]:,9^M{zAkuӓ}l[cx	X!DF}4)7=XȡIBϞxJ_ԙ㬔
@7箽!Vi怬ﭰy'fN/{ϱÐӱvoP/]yAB*
I!3AIڔ'Oq'.(4Y2}%!bpJCjByJĚ/~N\ټXrMc15t[zffNx7ig>H޶!nӔ*o\{1	3>#`ȇcN&͒2tEDچTzVkA C.ޙYJmbΧH(UL"](TS1U3	Diw4ȣoɍt-5fVw@K,"6C&a'80DG̈́l݋w?ĸL%gZ<uJgi`5y^j@t_ʊzVoWy%gk1
/*fFg,.Lǽ#[X͍ NTvsqd S+"T&V6JU1de
2lP<hVݧxc"ߘMhEiFE?:追ْâ@.P6Ud)<@P/_2^<){	T⑊/[7TӣZQ!p7F{)Nwvh`*psB{iBWXȾ[fAUMGݜwD^N՗-EQyqw,E֔@$wt'?=.ĭrC7{jȖ+YF&1}FZKj@]~dA c\C֘V­}ѻ{"H`]ߩ?<쟟􇏊<\"?>8;T$&b>_ì-a~i;IQGODx/sT#jٕDJJV.	K'P9d+o/Atɾ+QX`[&kG.=%R4x|+*9K<]UksRIEY,(3CAv_My}}O%(ݗ-{pߔ4Cc-nS:P'gyP-M&n7kV;vG*D3;;o\]6ݮӡڝ4.	]րh@ɋcTaX.ڴKmh}e6N5l zҀTשzCsЦ,*v,unXV8ԌQږҫ2MpLՋl. ٰBF{ ƙA  // Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This features file defines extension APIs implemented under src/chrome.
// See chrome/common/extensions/api/_features.md to understand this file, as
// well as feature.h, simple_feature.h, and feature_provider.h.
//
// Note that specifying "web_page", "blessed_web_page", or "all" as a context
// type will require manually updating chrome/renderer/resources/dispatcher.cc.

{
  "accessibilityFeatures": [{
    "dependencies": ["permission:accessibilityFeatures.modify"],
    "contexts": ["blessed_extension"]
  }, {
    "dependencies": ["permission:accessibilityFeatures.read"],
    "contexts": ["blessed_extension"]
  }],
  "accessibilityPrivate": {
    "dependencies": ["permission:accessibilityPrivate"],
    "contexts": ["blessed_extension"]
  },
  "accessibilityPrivate.onTwoFingerTouchStart": {
    "channel": "stable",
    "contexts": ["blessed_extension"],
    "dependencies": [],
    "extension_types": ["platform_app"],
    "session_types": ["kiosk"],
    "whitelist": [
       "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB",  // http://crbug.com/717501
       "A3BC37E2148AC4E99BE4B16AF9D42DD1E592BBBE",  // http://crbug.com/717501
       "1C93BD3CF875F4A73C0B2A163BB8FBDA8B8B3D80",  // http://crbug.com/717501
       "307E96539209F95A1A8740C713E6998A73657D96",  // http://crbug.com/717501
       "4F25792AF1AA7483936DE29C07806F203C7170A0",  // http://crbug.com/717501
       "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9",  // http://crbug.com/717501
       "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB",  // http://crbug.com/717501
       "81986D4F846CEDDDB962643FA501D1780DD441BB",  // http://crbug.com/717501
       "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7"   // http://crbug.com/839189
    ]
  },
  "accessibilityPrivate.onTwoFingerTouchStop": {
    "channel": "stable",
    "contexts": ["blessed_extension"],
    "dependencies": [],
    "extension_types": ["platform_app"],
    "session_types": ["kiosk"],
    "whitelist": [
       "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB",  // http://crbug.com/717501
       "A3BC37E2148AC4E99BE4B16AF9D42DD1E592BBBE",  // http://crbug.com/717501
       "1C93BD3CF875F4A73C0B2A163BB8FBDA8B8B3D80",  // http://crbug.com/717501
       "307E96539209F95A1A8740C713E6998A73657D96",  // http://crbug.com/717501
       "4F25792AF1AA7483936DE29C07806F203C7170A0",  // http://crbug.com/717501
       "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9",  // http://crbug.com/717501
       "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB",  // http://crbug.com/717501
       "81986D4F846CEDDDB962643FA501D1780DD441BB",  // http://crbug.com/717501
       "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7"   // http://crbug.com/839189
    ]
  },
  "action": {
    "dependencies": ["manifest:action"],
    "contexts": ["blessed_extension"]
  },
  "activityLogPrivate": [{
    "dependencies": ["permission:activityLogPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://extensions/*"
    ]
  }],
  "app": {
    "blacklist": [
      "2FC374607C2DF285634B67C64A2E356C607091C3",  // Quickoffice
      "3727DD3E564B6055387425027AD74C58784ACC15",  // Quickoffice internal
      "12E618C3C6E97495AAECF2AC12DEB082353241C6",  // QO component extension
      "06BE211D5F014BAB34BC22D9DDA09C63A81D828E",  // Official xkb extension
      "F94EE6AB36D6C6588670B2B01EB65212D9C64E33",  // Open source xkb extension
      "B9EF10DDFEA11EF77873CC5009809E5037FC4C7A"   // Google input tools
    ],
    "channel": "stable",
    "extension_types": ["hosted_app", "extension", "legacy_packaged_app"],
    "contexts": [
      "blessed_extension",
      "unblessed_extension",
      "content_script",
      "web_page",
      "blessed_web_page"
    ],
    // Any webpage can use the app API.
    "matches": ["<all_urls>"]
  },
  "appviewTag": {
    "internal": true,
    "dependencies": ["permission:appview"],
    "contexts": ["blessed_extension"]
  },
  "autofillPrivate": [{
    "dependencies": ["permission:autofillPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://settings/*"
    ]
  }],
  "automationInternal": {
    "internal": true,
    "dependencies": ["manifest:automation"],
    "contexts": ["blessed_extension"]
  },
  "automation": {
    "dependencies": ["manifest:automation"],
    "contexts": ["blessed_extension"]
  },
  "autotestPrivate": {
    "dependencies": ["permission:autotestPrivate"],
    "contexts": ["blessed_extension"]
  },
  "bookmarkManagerPrivate": [{
    "dependencies": ["permission:bookmarkManagerPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://bookmarks/*"
    ]
  }],
  "bookmarks": [{
    "dependencies": ["permission:bookmarks"],
    "contexts": ["blessed_extension"],
    "default_parent": true
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://bookmarks/*",
      "chrome://welcome/*"
    ]
  }],
  "bookmarks.export": [{
    "whitelist": [
      "D5736E4B5CF695CB93A2FB57E4FDC6E5AFAB6FE2", // http://crbug.com/312900
      "D57DE394F36DC1C3220E7604C575D29C51A6C495", // http://crbug.com/319444
      "3F65507A3B39259B38C8173C6FFA3D12DF64CCE9"  // http://crbug.com/371562
    ]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "dependencies": [],
    "matches": [
      "chrome://bookmarks/*"
    ]
  }],
  "bookmarks.import": [{
    "whitelist": [
      "D5736E4B5CF695CB93A2FB57E4FDC6E5AFAB6FE2", // http://crbug.com/312900
      "D57DE394F36DC1C3220E7604C575D29C51A6C495", // http://crbug.com/319444
      "3F65507A3B39259B38C8173C6FFA3D12DF64CCE9"  // http://crbug.com/371562
    ]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "dependencies": [],
    "matches": [
      "chrome://bookmarks/*"
    ]
  }],
  "brailleDisplayPrivate": {
    "dependencies": ["permission:brailleDisplayPrivate"],
    "contexts": ["blessed_extension"]
  },
  "browserAction": {
    "dependencies": ["manifest:browser_action"],
    "contexts": ["blessed_extension"]
  },
  // This API is whitelisted on stable and should not be enabled for a wider
  // audience without resolving security issues raised in API proposal and
  // review (https://codereview.chromium.org/25305002).
  "browserAction.openPopup": [{
    "channel": "dev",
    "dependencies": ["manifest:browser_action"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "dependencies": ["manifest:browser_action"],
    "whitelist": [
      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // Dev
      // The extensions below here only use openPopup on a user action,
      // so are safe, and can be removed when the whitelist on that
      // capability is lifted. See crbug.com/436489 for context.
      "A4577D8C2AF4CF26F40CBCA83FFA4251D6F6C8F8",  // http://crbug.com/497301
      "A8208CCC87F8261AFAEB6B85D5E8D47372DDEA6B",  // http://crbug.com/497301
      "EFCF5358672FEE04789FD2EC3638A67ADEDB6C8C"   // http://crbug.com/514696
    ],
    "contexts": ["blessed_extension"]
  }],
  "browsingData": {
    "dependencies": ["permission:browsingData"],
    "contexts": ["blessed_extension"]
  },
  "cast.channel": {
    "dependencies": ["permission:cast"],
    "contexts": ["blessed_extension"]
  },
  "cast.streaming.rtpStream": {
    "dependencies": ["permission:cast.streaming"],
    "contexts": ["blessed_extension"]
  },
  "cast.streaming.receiverSession": {
    "dependencies": ["permission:cast.streaming"],
    "contexts": ["blessed_extension"]
  },
  "cast.streaming.session": {
    "dependencies": ["permission:cast.streaming"],
    "contexts": ["blessed_extension"]
  },
  "cast.streaming.udpTransport": {
    "dependencies": ["permission:cast.streaming"],
    "contexts": ["blessed_extension"]
  },
  "certificateProvider": {
    "dependencies": ["permission:certificateProvider"],
    "contexts": ["blessed_extension"]
  },
  "certificateProviderInternal": {
    "internal": true,
    "dependencies": ["permission:certificateProvider"],
    "contexts": ["blessed_extension"]
  },
  "chromeosInfoPrivate": [{
    "dependencies": ["permission:chromeosInfoPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://version/*"
    ],
    "platforms": ["chromeos"]
  }],
  "chromeWebViewInternal": [{
    "internal": true,
    "dependencies": ["permission:webview"],
    "contexts": ["blessed_extension"]
  }, {
    "internal": true,
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://chrome-signin/*",
      "chrome://discards/*",
      "chrome://hats/*",
      "chrome://media-router/*",
      "chrome://mobilesetup/*",
      "chrome://oobe/*",
      "chrome://assistant-optin/*"
    ]
  }],
  "cloudPrintPrivate": {
    "dependencies": ["permission:cloudPrintPrivate"],
    "contexts": ["blessed_extension"]
  },
  "commandLinePrivate": {
    "dependencies": ["permission:commandLinePrivate"],
    "contexts": ["blessed_extension"]
  },
  "commands": {
    "dependencies": ["manifest:commands"],
    "contexts": ["blessed_extension"]
  },
  "contentSettings": {
    "dependencies": ["permission:contentSettings"],
    "contexts": ["blessed_extension"]
  },
  "contextMenus": {
    "dependencies": ["permission:contextMenus"],
    "contexts": ["blessed_extension"]
  },
  "contextMenusInternal": {
    "internal": true,
    "channel": "stable",
    "contexts": ["blessed_extension"]
  },
  "cookies": {
    "dependencies": ["permission:cookies"],
    "contexts": ["blessed_extension"]
  },
  "cryptotokenPrivate": {
    "dependencies": ["permission:cryptotokenPrivate"],
    "contexts": ["blessed_extension"]
  },
  "dashboardPrivate": [{
    "channel": "stable",
    "contexts": ["blessed_web_page", "web_page"],
    "matches": ["https://chrome.google.com/webstore/*"]
  }, {
    "channel": "stable",
    "contexts": ["blessed_extension"],
    "whitelist": [
      "B44D08FD98F1523ED5837D78D0A606EA9D6206E5"  // Web Store
    ]
  }],
  "dataReductionProxy": {
    "dependencies": ["permission:dataReductionProxy"],
    "contexts": ["blessed_extension"]
  },
  "debugger": {
    "dependencies": ["permission:debugger"],
    "contexts": ["blessed_extension"]
  },
  "declarativeContent": {
    "dependencies": ["permission:declarativeContent"],
    "contexts": ["blessed_extension"]
  },
  "desktopCapture": [{
    "dependencies": ["permission:desktopCapture"],
    "contexts": ["blessed_extension"]
  }, {
    "dependencies": ["permission:desktopCapturePrivate"],
    "whitelist": [
      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // Media Router Dev
      "226CF815E39A363090A1E547D53063472B8279FA"   // Media Router Stable
    ],
    "contexts": ["blessed_extension"]
  }],
  "developerPrivate": [{
    "dependencies": ["permission:developerPrivate", "permission:management"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://extensions/*",
      "chrome://extensions-frame/*",
      "chrome://chrome/extensions/*"
    ]
  }],
  // All devtools APIs are implemented by hand, so don't compile them.
  "devtools.inspectedWindow": {
    "nocompile": true,
    "dependencies": ["manifest:devtools_page"],
    "contexts": ["blessed_extension"]
  },
  "devtools.network": {
    "nocompile": true,
    "dependencies": ["manifest:devtools_page"],
    "contexts": ["blessed_extension"]
  },
  "devtools.panels": {
    "nocompile": true,
    "dependencies": ["manifest:devtools_page"],
    "contexts": ["blessed_extension"]
  },
  "downloads": {
    "dependencies": ["permission:downloads"],
    "contexts": ["blessed_extension"]
  },
  "downloadsInternal": {
    "internal": true,
    "channel": "stable",
    "contexts": ["blessed_extension"]
  },
  "echoPrivate": {
    "dependencies": ["permission:echoPrivate"],
    "contexts": ["blessed_extension"]
  },
  "enterprise.hardwarePlatform": {
    "dependencies": ["permission:enterprise.hardwarePlatform"],
    "contexts": ["blessed_extension"]
  },
  "enterprise.deviceAttributes": {
    "dependencies": ["permission:enterprise.deviceAttributes"],
    "contexts": ["blessed_extension"]
  },
  "enterprise.platformKeys": {
    "dependencies": ["permission:enterprise.platformKeys"],
    "contexts": ["blessed_extension"]
  },
  "enterprise.platformKeysInternal": {
    "dependencies": ["permission:enterprise.platformKeys"],
    "internal": true,
    "contexts": ["blessed_extension"]
  },
  "enterprise.platformKeysPrivate": {
    "dependencies": ["permission:enterprise.platformKeysPrivate"],
    "contexts": ["blessed_extension"]
  },
  "enterprise.reportingPrivate": {
    "dependencies": ["permission:enterprise.reportingPrivate"],
    "contexts": ["blessed_extension"]
  },
  "experimental.devtools.audits": {
    "nocompile": true,
    "dependencies": ["permission:experimental", "manifest:devtools_page"],
    "contexts": ["blessed_extension"]
  },
  "experimental.devtools.console": {
    "nocompile": true,
    "dependencies": ["permission:experimental", "manifest:devtools_page"],
    "contexts": ["blessed_extension"]
  },
  "extension": {
    "channel": "stable",
    "extension_types": ["extension", "legacy_packaged_app"],
    "contexts": ["blessed_extension"]
  },
  "extension.getURL": {
    "contexts": ["blessed_extension", "unblessed_extension", "content_script", "extension_service_worker"]
  },
  "extension.getViews": [
    {
      "channel": "stable",
      "contexts": ["blessed_extension"],
      "extension_types": ["extension", "legacy_packaged_app"]
    },
    {
      // TODO(yoz): Eliminate this usage.
      "channel": "stable",
      "contexts": ["blessed_extension"],
      "extension_types": ["platform_app"],
      "whitelist": [
        "A948368FC53BE437A55FEB414106E207925482F5"  // File manager
      ]
    }
  ],
  "extension.inIncognitoContext": {
    "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
  },
  "extension.lastError": {
    "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
  },
  "extension.onRequest": {
    "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
  },
  "extension.sendRequest": {
    "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
  },
  "extensionOptionsInternal": [{
    "internal": true,
    "contexts": ["blessed_extension"],
    "dependencies": ["permission:embeddedExtensionOptions"]
  }, {
    "internal": true,
    "channel": "stable",
    "contexts": ["webui"],
    "matches": ["chrome://extensions-frame/*", "chrome://extensions/*"]
  }],
  // This is not a real API, only here for documentation purposes.
  // See http://crbug.com/275944 for background.
  "extensionsManifestTypes": {
    "internal": true,
    "channel": "stable",
    "contexts": ["blessed_extension"]
  },
  "fileBrowserHandler": {
    "dependencies": ["permission:fileBrowserHandler"],
    "contexts": ["blessed_extension"]
  },
  "fileBrowserHandlerInternal": {
    "internal": true,
    "dependencies": ["permission:fileBrowserHandler"],
    "contexts": ["blessed_extension"]
  },
  "fileManagerPrivate": {
    "dependencies": ["permission:fileManagerPrivate"],
    "contexts": ["blessed_extension"]
  },
  "fileManagerPrivateInternal": {
    "internal": true,
    "dependencies": ["permission:fileManagerPrivate"],
    "contexts": ["blessed_extension"]
  },
  "fileSystemProvider": {
    "dependencies": ["permission:fileSystemProvider"],
    "contexts": ["blessed_extension"]
  },
  "fileSystemProviderInternal": {
    "internal": true,
    "dependencies": ["permission:fileSystemProvider"],
    "contexts": ["blessed_extension"]
  },
  "firstRunPrivate": {
    "dependencies": ["permission:firstRunPrivate"],
    "contexts": ["blessed_extension"]
  },
  "fontSettings": {
    "dependencies": ["permission:fontSettings"],
    "contexts": ["blessed_extension"]
  },
  "gcm": {
    "dependencies": ["permission:gcm"],
    "contexts": ["blessed_extension"]
  },
  "history": {
    "dependencies": ["permission:history"],
    "contexts": ["blessed_extension"]
  },
  "i18n": {
    "channel": "stable",
    "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
    "contexts": ["blessed_extension", "unblessed_extension", "content_script",
                 "lock_screen_extension"]
  },
  "identity": {
    "dependencies": ["permission:identity"],
    "contexts": ["blessed_extension"]
  },
  "identity.getAccounts": {
    "channel": "dev",
    "dependencies": ["permission:identity"],
    "contexts": ["blessed_extension"]
  },
  "identityPrivate": {
    "dependencies": ["permission:identityPrivate"],
    "contexts": ["blessed_extension"]
  },
  "idltest": {
    "dependencies": ["permission:idltest"],
    "contexts": ["blessed_extension"]
  },
  "input.ime": {
    "dependencies": ["permission:input"],
    "contexts": ["blessed_extension"]
  },
  "inputMethodPrivate": [{
    "dependencies": ["permission:inputMethodPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://settings/*"
    ]
  }],
  "instanceID": {
    "dependencies": ["permission:gcm"],
    "contexts": ["blessed_extension"]
  },
  "languageSettingsPrivate": [{
    "dependencies": ["permission:languageSettingsPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://settings/*"
    ]
  }],
  "launcherSearchProvider": {
    "dependencies": ["permission:launcherSearchProvider"],
    "contexts": ["blessed_extension"]
  },
  "webcamPrivate": {
    "dependencies": ["permission:webcamPrivate"],
    "contexts": ["blessed_extension"]
  },
  // This is not a real API, only here for documentation purposes.
  // See http://crbug.com/275944 for background.
  "manifestTypes": {
    "internal": true,
    "channel": "stable",
    "contexts": ["blessed_extension"]
  },
  "mediaPlayerPrivate": {
    "dependencies": ["permission:mediaPlayerPrivate"],
    "contexts": ["blessed_extension"]
  },
  "mdns": {
    "dependencies": ["permission:mdns"],
    "contexts": ["blessed_extension"]
  },
  "mimeHandlerViewGuestInternal": {
    "internal": true,
    "contexts": "all",
    "channel": "stable",
    "matches": ["<all_urls>"]
  },
  "networking.castPrivate": {
    "channel": "stable",
    "contexts": ["blessed_extension"],
    "dependencies": ["permission:networking.castPrivate"]
  },
  "notifications": {
    "dependencies": ["permission:notifications"],
    "contexts": ["blessed_extension"]
  },
  "omnibox": {
    "dependencies": ["manifest:omnibox"],
    "contexts": ["blessed_extension"]
  },
  "pageAction": {
    "dependencies": ["manifest:page_action"],
    "contexts": ["blessed_extension"]
  },
  "pageCapture": {
    "dependencies": ["permission:pageCapture"],
    "contexts": ["blessed_extension"]
  },
  "passwordsPrivate": [{
    "dependencies": ["permission:passwordsPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://settings/*"
    ]
  }],
  "permissions": {
    "channel": "stable",
    "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
    "contexts": ["blessed_extension"]
  },
  "platformKeys": {
    "dependencies": ["permission:platformKeys"],
    "contexts": ["blessed_extension"]
  },
  "platformKeysInternal": [{
    "dependencies": ["permission:platformKeys"],
    "internal": true,
    "contexts": ["blessed_extension"]
  },{
    "dependencies": ["permission:enterprise.platformKeys"],
    "internal": true,
    "contexts": ["blessed_extension"]
  }],
  "preferencesPrivate": {
    "dependencies": ["permission:preferencesPrivate"],
    "contexts": ["blessed_extension"]
  },
  "privacy": {
    "dependencies": ["permission:privacy"],
    "contexts": ["blessed_extension"]
  },
  "processes": {
    "dependencies": ["permission:processes"],
    "contexts": ["blessed_extension"]
  },
  "proxy": {
    "dependencies": ["permission:proxy"],
    "contexts": ["blessed_extension"]
  },
  "imageWriterPrivate": {
    "dependencies": ["permission:imageWriterPrivate"],
    "contexts": ["blessed_extension"]
  },
  "quickUnlockPrivate": {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://multidevice-setup/*",
      "chrome://settings/*",
      "chrome://oobe/*"
    ],
    "platforms": ["chromeos"]
  },
  "resourcesPrivate": [{
    "dependencies": ["permission:resourcesPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://print/*"
    ]
  }],
  "rtcPrivate": {
    "dependencies": ["permission:rtcPrivate"],
    "contexts": ["blessed_extension"]
  },
  "safeBrowsingPrivate": {
    "dependencies": ["permission:safeBrowsingPrivate"],
    "contexts": ["blessed_extension"]
  },
  "sessions": {
    "dependencies": ["permission:sessions"],
    "contexts": ["blessed_extension"]
  },
  "settingsPrivate": [{
    "dependencies": ["permission:settingsPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://settings/*"
    ]
  }],
  "signedInDevices": {
    "dependencies": ["permission:signedInDevices"],
    "contexts": ["blessed_extension"]
  },
  "systemIndicator": {
    "dependencies": ["manifest:system_indicator"],
    "contexts": ["blessed_extension"]
  },
  "systemPrivate": {
    "dependencies": ["permission:systemPrivate"],
    "contexts": ["blessed_extension"]
  },
  "tabCapture": {
    "dependencies": ["permission:tabCapture"],
    "contexts": ["blessed_extension"]
  },
  "tabs": [{
    "channel": "stable",
    "extension_types": ["extension", "legacy_packaged_app"],
    "contexts": ["blessed_extension", "extension_service_worker"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://bookmarks/*"
    ]
  }],
  "terminalPrivate": {
    "dependencies": ["permission:terminalPrivate"],
    "contexts": ["blessed_extension"]
  },
  "topSites": {
    "dependencies": ["permission:topSites"],
    "contexts": ["blessed_extension"]
  },
  "tts": {
    "dependencies": ["permission:tts"],
    "contexts": ["blessed_extension"]
  },
  "ttsEngine": {
    "dependencies": ["permission:ttsEngine"],
    "contexts": ["blessed_extension"]
  },
  "usersPrivate": [{
    "dependencies": ["permission:usersPrivate"],
    "contexts": ["blessed_extension"],
    "platforms": ["chromeos"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://settings/*"
    ]
  }],
  "virtualKeyboardPrivate": {
    "dependencies": ["permission:virtualKeyboardPrivate"],
    "contexts": ["blessed_extension"]
  },
  "wallpaper": {
    "dependencies": ["permission:wallpaper"],
    "contexts": ["blessed_extension"]
  },
  "wallpaperPrivate": {
    "dependencies": ["permission:wallpaperPrivate"],
    "contexts": ["blessed_extension"]
  },
  "webNavigation": {
    "dependencies": ["permission:webNavigation"],
    "contexts": ["blessed_extension", "extension_service_worker"]
  },
  "webrtcAudioPrivate": {
    "dependencies": ["permission:webrtcAudioPrivate"],
    "contexts": ["blessed_extension"]
  },
  "webrtcDesktopCapturePrivate": {
    "dependencies": ["permission:webrtcDesktopCapturePrivate"],
    "contexts": ["blessed_extension"]
  },
  "webrtcLoggingPrivate": {
    "dependencies": ["permission:webrtcLoggingPrivate"],
    "contexts": ["blessed_extension"]
  },
  "webrtcLoggingPrivate.getLogsDirectory": {
    "component_extensions_auto_granted": false,
    "whitelist": [
      // Extension used for API test.
      "ADFA45434ABA2F1A4647E673F53FF37F8F6047A3",
      "4F25792AF1AA7483936DE29C07806F203C7170A0",  // http://crbug.com/775961
      "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9",  // http://crbug.com/775961
      "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB",  // http://crbug.com/775961
      "81986D4F846CEDDDB962643FA501D1780DD441BB"   // http://crbug.com/775961
    ]
  },
  "webstorePrivate": {
    "dependencies": ["permission:webstorePrivate"],
    // NOTE: even though this is only used by the webstore hosted app, which
    // normally would mean blessed_web_page, component hosted apps are actually
    // given the blessed_extension denomination. Confusing.
    "contexts": ["blessed_extension"]
  },
  "webviewTag": {
    "internal": true,
    "channel": "stable",
    "dependencies": ["permission:webview"],
    "contexts": ["blessed_extension"]
  },
  "windows": [{
    "dependencies": ["api:tabs"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://bookmarks/*"
    ]
  }]
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This features file defines Chrome Apps APIs implemented under src/chrome.
// See chrome/common/extensions/api/_features.md to understand this file, as
// well as feature.h, simple_feature.h, and feature_provider.h.

{
  "arcAppsPrivate": {
    "dependencies": ["permission:arcAppsPrivate"],
    "contexts": ["blessed_extension"]
  },
  "browser": {
    "dependencies": ["permission:browser"],
    "contexts": ["blessed_extension"]
  },
  "mediaGalleries": {
    "dependencies": ["permission:mediaGalleries"],
    "contexts": ["blessed_extension"]
  },
  "musicManagerPrivate": {
    "dependencies": ["permission:musicManagerPrivate"],
    "contexts": ["blessed_extension"]
  },
  "syncFileSystem": {
    "dependencies": ["permission:syncFileSystem"],
    "contexts": ["blessed_extension"]
  },
  "webstoreWidgetPrivate": {
    "dependencies": ["permission:webstoreWidgetPrivate"],
    "contexts": ["blessed_extension"]
  }
}
C 5xj@ Mʱ]d扶υl1nwN3Qj5<jjY| UhIaNIzFFFkANZid탾5}Ξ)B2CҪRVgZ(gaGNZo6K{6i3'{RXIL%PIQݢJk>HSPҳ;.=ݥ(=0/-.B}`ҹS{i
GtrV۵AHRE^aF;3bHWwOyY&CMʄ<P-?|3BO	/l%ƮnK؝Λ9?9;!7.P?k+yK5!
пZg~zޞHG)ia)Pr!.=)nԪ40}$kLDPb^mXDg|[gyRҰῥɈ$j%y]<1jh؅Jpv!]2&!x ?[n%gwS}j9pzvVBӂ &83ܯ=E'j+|U};(0i ~<P2Ӕ<%}As'gb@4n^&q*-kjE5E.PβԖ0^(t7_|~fb}QP~c_:!ntHK  uϗrS	40lRU.ᓯ(3ǬTA@rf",&tӺdfUmԟnb~a	H[VWUKd	fzܚ[P#9fsݙnnfp7Cy@ ؝Tg{Gxx 0+W bf	EZ5YƙZ{{2	P2[(+fXֳ]YR5Hq|팈̶2#sZ)h]`[%>?oɐ*PnFwvzn?~d)3e z݄F#dg +PUО|?l˺uתuW
c7'C͛+P?\VmVZ[T
:Up"0xњ`kIڐ[صMACMns@ LI&j[\Nj5|%b*_C ُO$ii?qqQ73CU8.ױ#Jm*VIw aZ+<|H:KewxɲwP~b J̞#e=!W]EtBe̱ǍJh^,t`ѯPNMU#IbdhIxA/cٷ3u.]#$A+<R33 t$ey=3-b6&Z?}/q뚨%jfk+E$4(̐ ^7*=FpluBiebpxЅ 8FtMDVcb*FKʷֆ%@ic,iz\FJ"<6+bkVQBNWi[/'Z\1J:pM-:]EVor!^7)[*Ǌ9ٳP2?y߽Юo
::h_96>~weu<9=Q&dW^cy~n.NPг$,{tC.KH_w	iy̳I3W]#VVQ>_ʎ:na<-IZK׹)w뛓|6̔Jp-hVuכ{ycTNu~dZ;OaU>_i[abQvڿ
Chg?>5OʿG#ʯ2|?FЅ251R;7AI7HFմ|z0}~#v4m"@p4@>t:^6##cYop!No*XQ:kq,5 +-ˮoWw䑶pw2IdA;wAVeUEn&0W$(.L4pe>g8>0ZłL!8^p 1⨱/\y?a=IdA{O2obhawƪ$$B$)vº@a7[UZ
ԟs0N9Qy@".ҟ5B-ۆu}ROH߇&_%H^({W)|!myʄ1pv+B"*Z(1hb?{$اTH=@2
X͊+,|2 x1Je&W`V;:Fa1JM&9pm0:
H8nٍbƕ dlk+kMoF٠/WDzKAnBp]1AQ9FPsrrצ$`$3,7o{{kǭ4B5<.Yu:`  4XHZJ,I](7˟99ջ̷v%*hYgpS(n&&lέթJ1XfnNf5WZ7)ˡ.c7O1j{8 H،%VB2$5=4?F kHte[1j~KC
t[܆d	s#<,e_kS)	RjuT58G-$( ̽Y҈4+OG>k5^&NbϢ!a_(۩UCu3,8mהy!E+S+1 ^X6!5EDE|D;[,X@R\{	;(bW4,"b#4q>C.׫?"ϱ5нh͍K0ss%23.`hX_%ƱV=_VX`VOI;G~DyjQ}x#Ea7TBqsr0 +aM0_\BEDfՐ.!^Z5j,m2W3\xXPy=\fKigpS:`wMAP	ayk
5t7&԰m)JvG:A{L?(mIgym WsцU{zk+\-sYZDov(kfp*uFD _8S㌱IFP>dﳯ1eJpeҧK&Rc/5!< pS2vFz[]ܭ9(ֳbxXA7"J%jP[3[s0x-/1`תa3
e >Wr[QJ+%;]A\ҕf2Fhc/͎7
YJ@Q^hV3QywzVc7Qd6Nƪ$?CoZC]A?nm2}ЏfA'M.y pE^,ڄ/u>bPXF 8<Q-apjZ'x"̣aa|hs4q`L4;xӡ=j(=ZSGĳY]6,RUc_U[Z%pȉXP,Mhl֑N1 G۸wG1 jx{[͙QcOS; *iOJ<ͶEYs(OHpZDX(#)?Bx?z$Ur*5TAY&bWK´k0LGjtN)f7% Ң	%LhGdiK(6$%2KVgiJܹ(6c7G	i+ٔwp+w֦Ú->,{ee1A9*,O6vs{h.BPX_UdYj,ќh:f4v37R5tV"9t}5fv&oe.ya:T
e-Y|VQe]BžAa}_ڀ	޷}\6qƗ2Y'⮾5_z:	|F-~,CJ1?g\ڤ
X6(ðLjfZۇ
ΜЦ4@,RʨNT!ߣ1Ⱦ;n1MK9Ud^fyOY|j^#29;,kAÚ;γDWYEEd`_,#xTU7g&o7t:|/XBBTUn? !`e6D>lLh4f%eHefcE#()
Pe!@2&6	0zJT.-+epȳlJ(j{h.
H6L48UWfm\T8ɨ'!n|IUInЛ;hd[-CXBB<Tm6e/KB0:dBד$U°\6pRbD1FebXTq36𓃻򦱪˟fz!$![nAR3?Zq4:MO(d>Ju:E#0A#JͼiK$C%^}-$}5IPlZ9}ࢼ-cw_(]21qTGX̬T_F$FrԉRNԛm1v({ѫ`: ˱jE{yo}wL;VeZZoۆʢ#ӧL
82-ݦ+ꓛ4Gft3PY\(ea}/9CBWܦs?姊; a+ze4{ER#%EܱzL(/}@>܋93n*ͫbUџ'^@fϕo ?;Vz^k?o1L~;x^BsՋ \?3Jfz=_¬>?n3ƈ\C-mkLF,?kPjV@] qW}/ӂ򜊽I|w.WSΕnʎ[ޥ*FIF/DD~h|3dG<@	wq]ȫj:u(	ϸ	SYZ̙r=0#cטaeeYǲJ).ADnύJe-G\7?AЭQ_K>N@.12'<ŇoRL)}Po\.~\Mw Y24F/-o<)WܽOV	
cwyGY'%ck: i\h>"?qN@nQâ`45YXxփasNs,SɿI+WgtS[߱ Y	;˅4$U^&ڳMѵyq$tedA*DN~#o'1:@9ji6WHP1#	QĬ$L\N`(p4%O	]$Z,W@/͘rnV¨[4D_Mԃ;y:|aauV[߯'vT_uN*'*
hu^/[6<n=X>t30n
,wR핥z{!ކfWj^ZƜdq
?Uc>AIK-99Zqy[|cu nEc6FR}%_w޹Q 3fC?<:Ћ;W ?iZv#.3\?MJ7PUb6-T$r_;DkzDՇ^r#./%p>^bK%1(@XM>bH78Ӽ	3Zr*ZEA쟩|ggvB0# Sٲj4jeaei}#ʧɪpÙV RI-{ȕ!i	^viw\CRR>sdi_!L XK)XJBB(4v5Oڦ&lq5hAoBw#0JZIsUuXg?-!Z)@e\`!gLVꫂ	9j{-j3q-t
H᳃Dӳl_FbI=N?=-GoG_Qe˝d+2) wC]ܫ3v=s!@mV\TX4v~ MOFTq "5A|/Y۵{|[;Gʂ2k6!Z% v_Sr: ;e3{|my嵙<%fI%>mwh2?S15TBѪZuvTӶ~S6b	`-5[@Mf)]l0z"p2HZ)DBܴDQt)βH͠W
(34Yܻ&78uR&oy6p,$sؙ*;n-],(C#O%|r\GG:-ȬNBL#eA1Ϗ`r|BX!=5uy;M1O!z][j'@nOy_z7')fjT->]h܁cAINbMnq!2rrD`a
 0!LA	b耀*ڽOѰhT9a+Aa8E}+ApQ+d`&c`x`t@"BqJP>N1tʞ`g;ͼBN-@]E!pEf	X\Dc]3R6LThxc6Ch{?u4M6,yDB
L7Y_S1V$hloJbuXϓ"Cs=k*NX\=׃=RaZLPl4戝K$,j6YJZK/kz
PJT H1o3I+}'.,VT_*~ÝЃ3dqО3L5KMIjew4dpͲu*6ԩCACk4TCwe& UR~|җzYaNQٶa5~+8Oo;	gó(E O6',"![2謀4{{݋<l,dWV-F^ڏ<axFa5%,Tڏ<݂'& ߊ	|
9P_U+ Tȷhc߷nk,nK0ɔ]Q-ߥ,|9YaBPl} U4yNf"D劰o+gQ]޷pe~Sz+Zao k,9V^XdDoF7i 'Q͔9v5,~8$sw#
hreAF"JATOn;QC&H(U((ov{
LJ%OFz%x:xVH/zmPޔ؉HQpmf\C]T#3}x72"2f
Ȗh@:rّo=2 \{yDqk( YmwzģDlWQ`jʬڳ
7P=JoU&oySU7/⊁,i>FF:wPP]5]t*k~b)P">/ "vz붗.`P
#RaV/%#qI@B[oVc7&S#ނp%O`nU)Ea q3zuz$CaRY =!1B}f
:m!<@Jwȓٙ 0LDuOh&TYly?/b6LnغCѤOo g:ɘG8\ulcQ߹ZfO2u%,-nAlG'vTN|VÚAb5zz\=gKw(qGa[Lå ^*#IwV>Su=\u~CdUkVa_{î!98<4ei	3^bRTACP)L<6yPbu+m>W͝9lnfҲ>`;ZEԹq$r2E`0yeL_~Ei
Û9mjW( Ĉ#H?vd4(ݮ6Jz7Vmjǃ1TAB99=oOgw츧x
eÏU"d]0zCAvp* `Uj웠@lH~гyJ>qc[-k
[c;o3, S@VEddPK!Q9
^F}S(ʘܖ>og~XEG[S9F16:,ǎzvn[]o/eTERb]XݠR򏺚__3#Wޞ%1>h`ԋ\t)deO 3gY}W"|鐲~ZU_OyfX)5',}.Պbfd%B:p;	:	.xL&g^+MQ\wl
Ye	Cޫm$MPv,
fSxiMYtUMwM̾a^̎z.\j$EVRvg_`M'<>Dr_/T{Njq_=
FSro'!:|^!$d8''ƚX:Lj'ߓR"v^/U$WDo\tIԈrs?c>*|0-S/T4<uTgc&*tRp_2ЁS(oQT~>>Yq!!q {qptji*gV"(@<}B(ZgG6/`e#A/쳍FE~ǐB:=֓l"K_dǰ?)kxe}j9Ʉt|·wkeW1E0nt)tdTe?W?UؑW6#"MweE\n ?OX\X{qRTi[Te&?Sm><-ͪL(>kx<YfvdLH*8!frklrBi@'a!y$2dh3ٙIoٙ9Y#{="飘Bɭl1ֆɞSSt<v)D-IVP'.+/qVWfoCo߾1:up)*FR{KXk=M_5Gc'zUфiVk=h1U%A߱⌥ncRՈnYCvr #MrrOɫGi!/f$Ipd:_Iy`ᖈNUPMTlj5 η%qlj/cGASShcutAr;ahI4V=I%Gצ2+غS셒YPC`9, qӍρyisVG8Ƅ;[UVzvwg5aJtenKe|KԆbFlE_mvEVYz
	ZᕪK4CpM0h|W;Q9\$mf	Åu4];"@m*FC}8^2`FH1cdσEb!L}!	!a϶AlЬ.6ܖh\	&0ݛ%=fR)k|!-OE\~	&[Ҟ#aY2]@n{/ͼ@yUV32{3$=!nG=XjmmJ@K6,0xݴ:slZW"İg[$arQ|Hŕhrg1*d~Kڟ Dh%џ71#4\YQ;"6f]jbxC_جMb?-$Xuih8FC3.Je?;{&kF! se)PhTEh?=ur=<t?Vq+gdG_IjRnmWDg?3gt#K*rn^:b>HEouZl<]{K4a!&/x7>_h{p~܌@m-ݲ)c[[5浭@G4`2\M$g6!VIVX#;v"N檱cZ$ﾺ]|JO?±efs놮,-0"Q:9]rm6+ ZwZ앎Έ'0thlo$+lN;EzKa݋Վ+]ΌKy0E*JmLz&`8Z.7rI7*+tBy*rdvcG/'HRf2M	sMA2u{n~cu7tA9з˻fu~WܶWRr~p_):2>ʲsc=[>S#Vj!M;CEBWN^HQ2|9,/mQ,$`pƠK܌"gLa1NːVB{	 Ps鹸tGIUq0_Nz!HǑq<aj*%_bJZDdN#TgBgbCj^('k9.p&4mqkYK=	`O:E:\%Ux>F	(igTͪ
9d#;Tu)?<\S3M7ԚܿV;NC\
K5 ɇ:Acl#8M{05)z͔ܲHYb>3V< W'hkw/8AO=E*ʒј.ޕR<BI
pԥۖ`=ǔn쥟 |TK)߬*8M>eR]̕ېĎ'uL}[_C:sБbLS İ&'GHXJ,Xq!0ni&+]xc@Xz҃źi,^/i=?DŗWo`"g[%֧Aepz+^羢/M6x^4 l\FcbtȅOm'?H5CPl4LW?|~$1b#jO%	|N!_Dzw4.y'cO
.уj9 Uz1Xz2$oo1~ɣEXEl)"'ό/tt!#.pDQ.7"
Y=1x=b@"7
O(SBThn,+/} f''+;?r@K>ПbHiދ%$-$^RE1f ߣ7Ҵ_tSK>\6Ы<^w]iy-x9$V1J  ̵}a<W/KJ [tc?fsksID}{̫`8Xf{m[II%wg[N#w,c  K ?g$tIo#d91T΋3"tl̌x5fW*_C|~p&7OL6(
&E+Z$vdC_0԰4Db*ȨL"}AM.cfrGi,ȿsh/zWڼ	NXs~PY総t_̯<5BvMH~]7Y6ȺoMX98XW3>Q@rcx>#A}C2p46Lx^5@m
 n&TwK61HS[+_n{'p w[5w1ЉU%9(ek͆czuԝL>`slQ2l' 4+,@((~A^B:Vd݉S/\g3J<3=ޞ}?T9/C7ൃ:Ԇ(qtm(Noܡ6Q6q_IoV:bZk6s_|nm>3j"dY$.يS~Y-l0G:*;y>ۗN=IKB^7|ܼIZeP(6byk4sAM년nw SH=l=}/UL:a4:pW;7y/7)L!#6P˻6=5\W=z]A'{` `ஊ$i3xp+^7r%́ gHӄV$Zf9NH]@lQG=fnQrg]nQ;AA"-5Qk0B\A]umGȱչ-Nda\E鋄}p{F˶.ʨLHnNVYkQr(*=ސ/(lEh]&EP'>JKV`Uܑ3Grt(κ	{Ra؟u`Q͢曛Q~ݢ{]uC,1:7 T\A.fP-r"RqLhc?$>QZ=nC"B h2;t*|@m6A _s+PFT'sV	.9'dZkb;7}nCESŴ-}߷]m>Iwp:]P*m1uf[mrUB)tĆ]SPS+^EFG.|]s` $LH˱7q>;vrt 
(r(p1]|m||Tر}!w犺0McWrJ^ -?QƎ[0>~iQ]0}PP>9~𿑼`W!X^RBlθE4޿ShssP=$P$4|LwʿC#nISZ+ ;;m2Zh
v%L<]Y#(	굄>۩yZ% z+FG)PGph'8h_FD5i2[C!FKNS5U9]Of0ע(	g$+yaGcE^N,2y֛/SIadg
+v1D!˦(ҦwC~N4лWhEYg{xm	h^tXEhf@EPq^x̰Vg#y8R(2fکjbmz*曏Ghq,w+\FTnx~X@ӑB!Qn|x1,O_{f2r#T,O8mc	2d|;k|#W(bRh+)`̊ߑNHA㉫䰚Ec\>4 aaبGÅaAK)[_XǺV7%L,* R*nG?=Rbxrݭyί65fMS`ga)B*vî8t!GY	"%@b^CbvƗvc1v/Τ~<JF8?X)P
E]zDG&3b.B~aQu7_s+P5I;
UIoLAtnĘZk?bųVo֤{;pXL}`!0Eho`d1/>` {E^mzqXsm&0%?[墩W&+{5q&䜟8X̜E۟{}H)qbvp3#BIo2K C+H=
F
}os Ln7A騚quZib@5V9Vю0}NJ,T	ʥY^L,gF <͡$ja7\c6AY+崩7KZ3s|D);6vuC]I
P{% ¹ TQT?8wT\njȀ86n7@A;;6ñ:gzȚU+\uwԙqWC0ƲuaY;AZ^b-Â_mA<!DxFkdzCD,`zJk4n<T^ Q=]ZhҖ
,13h\˧/a>EgV!T Cx-c/p/CX0	Y4]oLrgvddZ@kpz>UBå	6@D|Ny.QS4ɶh;Dr2FA8>-_wE uM'ZA.+DP 1K>Gc#3!U
ax? Ɩ^DLdK1zDX F_C`+'E)Қ1X/sy?ҁÊe?@A1.oa*굛^7>32"+dt7h ʴ2S⇪Dy(k ȟIkt ]<RhDC" 0WU)sԊ@30KG]IoCOLzaQLpYF!@gllq<).:a"Aq|% TwmQJh:&C(a<q#"vq7@<w:@IYb~)K ݆d_ x,A8.MLNI3nD3èKpMzhrY~3U@\2;uYlg@fEM>r޽y	> Tf R)r,'R xWܢꀿ@ 
V4f	U{.bdd0UXJ7rf	3HHRa]CKM*uۧ
hCJ\ &[8fRe{qq (A0qM+7	"6|ƣE6I&lLJb9
[).NGX8	W	*qhܥE;X3EyLsSF&_31(*K80)e6{cvozr`a%DM^UtCC[_:%21W<(SR;ir-N\ l07?I}؃ FǤp[kqT77ΈϗVTd"c'0	1DDWGof rj@k$w_tQ@]8wq!eQ<iy]%A7ặ'wVЭbTߪ?{a0{+.Qg*$ 0Qfa&c5:-SOqf%2͚2v2ѧ|;'?9nQ<7@j@P[).sOa8y|L. +4i¤C ~<lalUJ01S߀~c&:+PaFs5s7W0o=xkC~#jHhc'Šv!2G?Nv(.lihQFq}RkdYEZ}u%1mc}jUnk	JuV=J/Cvn
6	A+MAύ
+-pbt`)Dt9?*
OR $ye-.$坋"N:Ь4x P)Ge충/6WM="gA_gD~FavĪEz\+D!~qDnT3*!E
<X/uޢ_1Z!A0U=YN⡿VjAEg2}PW;σr`6ZI~cWfḋ:aJ8v@rHy1?~%6bܺ(,E<g&06(ځO5f	.-Z	RӐ᥮Dם%!1&pRX2~> dKfĀ?j]8bmtURս*ڄ<G4P	S ϾsT@k<V&&K0V[=N(*Y2FQ1Fٸ'Xs빮K&Heg*KaW2vɼ!fB·~دYc3x,D, tŌnR\q^"W=G?5
&`2MW)"~*oU(@q]|h`s7FR79Q
X_j}t$D]@l9=cgmed8v 9P˪qKe?\sy`Sܮ-%rd0x!yMO>:C.M`B;]NWO5b^.pZX#t^B(Fh]<3U6y*jX0"Q&Vj}*c+^88 FPfAL?<84rP=FnCXj5y#ĴѤ[5EvTh +(1Lő+r{_P~Q.<t-7(sz0(iiOE#w:Qs`O2{]Nq-chx%)۰(~xo@">NL/Q49==T	L4q4~;9D3d)4g֢e>|$/ 4J$0F 	L&f8<^?<:TbX<Jx"tP+x<PyxQ.p<! HIx<x0Tbc3;㉠Php4@
gx*x<j%9V&6ZUEx4Mdv-k dTW~_WZgD{(|.EwQ;Rwuh5k᠘cRc0ǥwvb"<ϠB}3 isjCI@OL)CtKP~EHXǡs=t!3'IBGOAFujo}ULlD0[z**QvR@hPsV+3k״SMS-l֯Db"S茑{Et<-D3aB0rLğ) Vnc%4ZxT̆:F6u[Xd酞iG<5 5o}eh"5lK6|/GACQPqo|Bm-h`XMVdk);ZLZMFUm6:^	FͨA?S=Ã jN,aCEN[WY Mඤ	O|( = bTZ34h qQK.̩dqCg4?7vo@,zbyczG`?uJ,?9Nr
:W7Rޝx6ܾ=}4R2q+HUDXI#1z'J$Ie#7SZodD 8B %j\!w@N:EvVZ#6]l-r dk^uqR?.^7vXMV!D#FNyk0̠	hZeǿk][	kddVz,Obb(Izy.#^K>Az13b\O5 4M%?ܙV:=֩CVLh|v٤
y}@.fϭtAGAxN@fj]jWxCיa6'`^0!V=:M;vhK]s_-_^Hoɤb4U{TX]Ϟw-j}]HjG<-ZcAS]S0D-%XHn|>BBJ/t¾|$B¥vk#	s1@P-.ܕB[_d5W|a]/{aesѱо"qD>Bl--*Bh|,xC+$d۝ z/y*Qֵ9jS1*'#E#,V<]*^A+F{J@wI	v^,㨴/w$F{{6	"D9,dzےL۔Hʋg(IiP^}/`Tӎrn3B`%TK۩֧`	`dK(nԈsIH]bجC`#Ҕ6JF*}e٬q=PmmA_	l#QX w	hBKI]f4ty^yi ʈt4𕴥ȅ|~{F6 !9dUb:W{*CGeEÛA>	J]1Њm-B ѯۋRq[VT0^
*G7{~~Pk'du680-e_ |]sЙ~3 }Rt
 ?E"wȵ963	p6_usta^Cq	ߵGDPRp`Kw/uPlrPit4-'q[sZUE	LWYi[4q=ˑLF;Kl^";SxyXҰNFU)~56L(Ï&(sտxcr[fP؞
64tjYB;YPEZ=2' b3Rp
HF8/gxЀWeOg>nyFF2i5nA1^wgx)wFĦqFu*ʷ+n}ώRL,Π#Z$
0#WtJ<!|1~QIzS*F߭U{0qgcАfh+c?8KYKb܎L,t2v9ok3fpnq8\ctK%z@wjTLSCx43+bq#hR$0=> $PçŲ?tv<n#u#5	Ux@4EEV#b8nbהdm@O16Z3}ժ^^@Lݎ \,9qnbӑ:89`Bf{#YFЀ""ؐefzY[q-hco|awڼתtuͅQ| eg:2bs+T_YXrv71/b);[[{F-Ϻ(ّ KN@0$C5C6N,1(v$¸;ݻ,nd-B(Gm5v%8K6X)t@jNXbGL+U#;$+MK2b8K0-<bip#ܶz3+ŭa]QCgqF9`٠+n^u?;5Z2Uyڲ\A@"Ƅ:i~yU.Mz='t3[tP~ᗜ4
{;9$V[O6Vo5n*@%UU2a7U$DX	+OD,blWf=Cddrdr4aTL3IWkVRqWAʌwtD.x4(.pt=`h6q"fD)@sWU(Nj'QX p-`P\@3DΤ"lgY
M#M8OQT#&[*]$gBĚG[e$t1qȕ ӱ:V_f0@=[8TׯG׶eL"H`&Vw}u)\CPba|ddjZ8:*{CxU|E
&g"r߶NLc&]	XDAlHv(aET Br<x&VvL"cݣ|bӢa@hH+ZK)uŉ	tTHfxOCv\Rpr_,RE*D0ls8
&vrib'*`4Fɚy,L$4I3\eiZy189u
)1o
^O^Hu0?`-ﴹy?W/|dqA7%#L!{bEj@zd1#Rh>u06н+4=sBH6?Zh#	 <aE(׸ቴaQ˃~CP(YE/p9bkdֈr./p g=Tp"Q'tNN}u#QKyNX;;qOM?kOCf>B$0I@zH]m˟OWK/N`SK_FQDL{p#ci"#f,z .L]<<
1=%783y97xQl/b<z~z?bNL,15L@GlKcR*\Ub=EWd
ℚfP*ج^vҲ5o=&aCuӁ_eH97JmX腫wNPIg>H\C!75{}P2a<і8Wfe^ 9IG+cVa`;{7:d7%y̗z2f;Лq^O`?6o=mR
Y\jvwf8 +FB|nNJw|'J_
xIJȍ7[heeS7>g+Cg1о%fq(ű6Bǈ=JbI3v2mp2pY
x\F|2Ґ<Wo<v='={WrQԔr\,ͧa&(\+x(4їj3`+\e4
9d>`䞥O30l2fM"+gyY){?*8r5'9Mʂ7@ubVkQ@n^tk][B@_`-1)2<6W.Y:.BL>rLzD猢\X096[ G\0Tlo\g`+["kO3eONmCf˽̺ҰMxfauhQ]JkXe^8*_I@.iw{ă:%r$~[fѓ#:v&c]?ܚ\?	6Iytˍ^Х,St&-tg6f,ß}0_KVZO3 ỻ<΢Z˿HܳDdˎo#Df.#Ѩ'Nl'܈<nQweb?]skb@]~	AP>@oSܩY}_fP5A׺gYY5\eSNLmuI-.nKL=uǶ:_Fqa?9{;'ERlQT*ǎ^Btu3b`yR\>G
#"2\~A~o+&?7cS6e^`V\⦲љM#H
a
E戫[(?:B7Rц5,@3P{ƿ=0w` L3)sߣ̓KJ) ŨGr`1GaR1S n%c'19IMGR-T,P((Kr (7L
eƙrO"̄gR͸>s#9ZR'8$LWE%R01x3E3oB};jO>^=}ȥ=w2rt> Q'ˑ\hĜiDQ;>gх-]FG2 VLm/(-^z|d <,Rj[ʕu-ξqCRp{i8+մ5Pmc<ĭb<s!.8rFu?/"j߈QJ-↿7jFj8>(K87#ƸMW?1Xk`nM[y[nS7]j7ޗjJ!vH
{pQ8AzzPd@k !k%Ή;v.>ΧNd#RW%ٷi\MR8'~"
y!Oֳ!-2WuG~A;8% )A!^	7r()&k
|S8|罺c>AiA$b7oAd:|#͉r{Z	(OVѐk-įrOC`?"żtb3^d2,5JP:'0?	v&7cjox0t/!RtFXt@#Eex{]eȣ9g3}dT ddӖbm%ǻ)⮧cut+__ FAwR)Jl(<'aG	AXO8%c@!zZ9!*N'cL%X2kĕhθgqa29j? 59\#΃P;p&rx޾rr\7-A`7z&CLwʪRateYD9T@[<K a^(P<<F4 MA%Pח3q' Dzsrz#>|O a̱ypiٷg#Pw	ngGJUܗSk6,\D0$$RF6*"8'-EN/8ứ<1K_Q#?1$^řL<C  LW9UrwWEʄ	&/蛴9'-|XahGP+s5F^ak6\akMIH.b>biAў*xwI}ߎ)vPxTȒ+=FzcNo:.-*cB^[;"ȗ=pk/@<KÍu->
s7Mh\xr`yZTEpp*t;(2}
#+
jGVJb̝܉8G޾ăf@nvgҷ0SJJ'[QKGo̓e&{%58DnN;~ܯIKLMB$ez
:>2+I%KV+pG1Ӽ$-bP3
x(<ߴ "ȘezN;fC_'lيˬ4Jwܫ!(yZWR&k쭰Pu}9"sɫ傻eUMsa)5WsSd}<_*~-t1E9D@	t#$K>/Xr $=JL!bY=۰dy(:pzG:-e}fk6+Tr$&+oT܆_WĆnj_>oz,h,Oښ%۟c5vQE`<kBiLH	|}!y=dEjCF9 w|Sī#twS>Nh*RhkB4'"Ex\5[@/]=>PwE~UGT \1AP8g	 	DWpӘ7sbKxi9GL%#cEC*>${/	56""VO"1h H
KGQ/*P_KbK6iڝ|o}-Y@hU Y%ro̖_Í7,hctv0=h 1 H8g"li&eHF+TdmL+\zkJCGI if$2UGBs,z!9kFgͬolj=[Y*N|vwT	DzT4L{z3%e Ӥm lV0w[{w;@e4 LC4E?#f
9?RY۲6d3N)dN@T;lij9϶9E=L}?IC4!v8N;nst<["Aջ[*<TNGXYxMmRCȌpdey-E?;	͜6pB43-OD'K!+c{m#/o\f0TF$a^o;&KK RiI=+so;n 7YDÕ$9ƞ~&YS,s9 ӛ9:4g\i3m7.zfoVFmu7*GR)A`.þ[gшn'Շ9 [&'RSQs^#+}Zv9+䜰cQsZSyc[z=h\aPeo{B {$on{E7?EZ<jp>!9Γ^0љ)z	(XJn4)`2eKӼGD1$" sy;Ha{,	Sg+w"nV.9!Gnz+ԍ"sHO9W}FO4JzU
=wO_r8NF-	xD=t{)-h"?+4\f<;>g<cG|pPYq#;dJ"'4"48#J#%CTaD?)ctpzJ-8m P#dI|E%-]bgMoY}׷׳%-2?Adf瑪ʎ2&P RFA|8VA"JeP4;rП@sYTy	u~e4Cn4f;K&;G9:FՋnb'\Ѐ5;qؓ/6LTPHȪ׸&u8JCu#]i>bF=v*kfF(vQSK+m\L7<Lfv[ә	?nL|Ŕ5Ƚr%^w@Q'uy(doƢBE3hW{-D=`UP lNrq7Knj7ΛȚ2W#,E}:=*FV,:<Fr;8Ve,َQJoekx;1Hɾ6U;Û`Ӭd*5#G]Rg>{m3Ć(w+yH$SC;hcB.iI#J|
9JjW]X(fb~ՊƄL#:dU
$qPҼߏOx|!E T(Y:vPQxȸW~X 1*P%*14<3bi	!%ޥtrW:`-M8	V'KT	\9	*Z1OLo@3"-Eϒ|	XO}+W \8	'O/ia1qUI<4([s.gО%9ٔ|Wk62Uh{ȰcgC"TܺT/e=Ĕpx{=_9a׫I%Y
AZI
ط	IÜ5ML;^2K)8$P󫩩Ba'cL'	mbcxaW7^ZXM?-n
6#8P)*)P u @x&٦"PhN	B]y<38bbPuy[@c؁ln\HpYMSYe~0lLܔ5nP{>J!arCѤ0pבUwڸ ONDbN!`%?u*{KOyܟ^54\0Q)Lvֺxz\/=r5'-݉K0St)L4~tu鮺\ a!2s^鮸Z -q.|/ߴ.X/ɶl/4G_ޔN
<Muy6<HEγ$,ʓj$gKL/Jޏu} u>@D@fsy$""7Ŵ~f[Ou%q1[$reYŅ$Vis|F< ,ӄgnHJv|:*)k.~F2!w@hyj$j3BjTܕlG.@QrtqzZjp{̔"Δ\Eu<Oy$	4+f \ }o++"?ۖ	UPFᖷ@`Q`x+XXa9qL]|+OoO5vk2n4"wy.W}8HePkLvMp!qd`TMT<QT괇"74(C_NJrCe!ͬ 4_v+bb̨
[l"gLKg4mzRqKZtT6;A9.xCoy5h.&(	 K˽p!9);DRm)h}}=JuM'|'%2'B0a1~=ury9T$OFε,hE<u'6	v7cflsEht|cH"~Yc\$CXTł** Y܋`l-;
R/~̪A	{Ci9A? pxq*]I*n
kwr[4d==LNې$nǀx;9f7΁eNTdPfD=rxh
0!V
E aCesca.Zv'HAql\,QֵA]Ĺ߶l3ߘM4Ckl)UDTȒ2mPON}C#9\cx녹Ny9dе[a`@Mjsk\xX푾	p](%s,U=Ehe;>Ȗ^31%pdetUIxD>ntӦB%"bNfHcv#Iqj7ثQϫg`<aw.hVdrXq&)l}!b֘,/Py%ϑ&mU5O<Oki̓	edM?d/ɳ8 yƎR\L\jϧ$a=Rz)
SNFsANqԳE݉]&\l_cq0%jBe \sL&r\syRv]tb[Sۤ>`Y-	A"=P٧ٻ@F.K3
>/P-uqtf`<S@Qc>#c"ӌ%/]圽z
iq9媟 O̈}QA oOt^`fIj=L09ʁ̮InD3rg{k홇adUREYs"<%)Syע-+ۦcwt8=2s&*IHpՊ&VZ$<0oF96cnxoG{C!`\ERU%
YΧD.nU7VF=E?nQ)ܘPP1`7aɍ!h@.G -'`'E"J&lC'La,V܈@G嶫
'x?~@汲􈼇o/BIfPezoWH5'PY),]hNW<,4w 2oa[[ǥSCyfdS~}SmzgiS%ŨWXS7<FŊ|	`k-}ql	$ta4KOhvnX,ńd kY9T1,\]wVE -,1.&cIrϜqdjT*Dz?aLK_uK@4-7"^DwxΏF+wli<e$C\2HUQ9"y*I(bڒ-\pܮMFٺq"Chi2[5"QUlutҫ7˺4ц!*<b#Gh=PwK_',B~1s|W~d](&hޡ-[]:xN2ن![L5i_(mТ)+;YtvX}Hd: W%'u7؝5=BHMvfpapC=9g,!0MRgaVULҺ1:>"O碖VBNw܊p,_8j6Eo[zE1ou\C(E?-<7CRN-r0v<)J81(^XCH٤78uDVoEWM`_5Ln[8T:P۱хy2uBo,LE>6Ner^_ QUVD|y@aϱx"
5U*Je"5֐J<^VMlclce%`Hb̒YI'#)4CZdb_Iu Ṣ^B8RqeE v[=\[6pqHWFǂֲB]"Dg,vo)0tJ.*lGGҢ&̡6ÀEby>fEMGkWynmQOԢܿj6aCr[YO_ wS
hFwRc
wWEܱ.pAclZqtLaA4}[6Z7==T}^baƚ{d} +4GآȒߑ[D$#ahVx&&%$LXE iZSviďhOuQ{,ݫKeVRKFdǟ%j*y*E%-rA}PXIjW!@&gҦz <nmǭDnԼ\~#@Ҋo'6õXPɰ<34$0E% @X4~<5ɏqvJdd)>`>V"P-Vʙ2h`&qg )R6)!Veg:'(:a>Ǒ3\3sQ8e 3#Wl8PŏzX 9
lBUgxH4rSaW<tۄbS|νZ=;utP"kwbL=Q>1Efy1@RTG-c⩙Ypa[0ؑH9t=RxxGvQ`T};D1Qv]K#Thu0TqI{/Rb:.UB1rZ]OMxKXZb䵅J<q+疒b`cL"R\@H6nViGe J>m)fYx!ļzZ`LATJĥ%1k"Fs"=~r4XhSGCisiuQE8Q%u'78"DTLZY	791PiTbeԃ.%"kZXh)J}M`#;)i9ꮔz06&i{QDX(b%VQLg"m6c/qJF&bq˂
8,@LG|fD	i9%ڑěf"u%XiŰKvhR &R;iL&ɀ!}XF*ߏ2dCH6FnRq-5_D'\ǝz>ъ_A*yG(Y#r	   CɆ#إwz苩ty޳2{g*{̗ӥ|58u	KMQfHQZ+ddreqwJh2Gt3d0(B=?usmE8nHLhKgߝ)ΐxiI"%D*w=mElW!ވYLCʰk2:K\-SΖHYu:O5"YЂp<S7
KOr2~Q.>8:U("^J ]*579j[J!)P\[H;fIH]wcDE)nnCc4:)؛u-H7#lI`QR`ԑTTґh7;ڶX/RL0RA!EJU,EjbpQB.?ȅɤ e5
R2PQT{_.jܓA=.G,(N&
*Q_vxN QGXQT~E_rG@PtMn:
ġpP4l(4""Bl&B5,

xBB<K_)<[O-E:nЅO9ٟi+aaiq$	zwCk&2Idx$٪x	0b+9]BoH$J:NGC̳%jFi2l{=/)~^k̨qDH\`4efEZFߪuh:޳(|[E;G@6TJ!v@'=Afz|"p[ uaOX돳IR\qo5jDV]FĨuXuߪ:7?Egx&?MbHm6`FYvkxN 
	 vhUgm)#mH穝nzX/O1(-}ԑNR78ndAu--}bV,fNɨM]	AEA&>*'h}Y6'1 amǖ(y#ۍQYhg:7܊7%{z'
B⎐fT&g70׼p3{YG23A"Q:u|T>AA0%k1"-N뉟T/KW XK*v9v4?{:d&7+5qVJ8cT؞Zǖ@Um~7Q{O!OP]1_=Ja aZJox+~^ɯXnʆ 	̘ұa&䡖Ϗk~8?y"0^좹~R^.?]ymVPWNmA <<:/,=.w,Ll3wx<@뷠yOTh}y岻M֯w._ݟvJ<cwo%oF_gu~+^ \eR_&c?;V-Ew"DyCuQt]5N~5Hnɓ0~yOoGUe?p_>{>㌉8{	d#??s'#j#xT<4pz}fyc ebJG:bӛq(zR	iOBcÑ+XUCZx8-HOP9BMFb -:C1QrG@댏׽`h7U5(h4`I=uC^7΁aj08zFs\v.]gQ$Εc٦]MT670[⫇Ge%;#V_M_{/tfbG́|_1q?mS輸K>K2faT^e'#_rב0 F"ah3HiD&:%P7._}#ɻ\voηugćS!f,aڛIk,bb$!}F/ 7<"8'e)c;@A`~:HcS.9pL/#ۂ(_YxU$Zqw0GD]=^p4rW0j@J-ȕ"yے/,'O;-th(eX	Cb9ֆ|cYO&aQk8C3%@)a%"\h9gjoY4@X(dr$rw_h=+e[ m~a@'880։lȀN
{55'EX^u0"i>ЛHGq0؟LcL79)[SMSfĪK*;ӥ&@q ed%*toN8eN5Zi~ϊ>J2Pe|?sL[.\'\~#
%ޫIz)Hsϧժji
"mYjp¸TLEQv9+6fLFYW6nO.?+3YwC/}6`Sbj#S\/|=@ĀuDm'!`jA}o4g(2>n']Aiy;Ь?pGco(\?F[8Gl)uƅ 㧓!ҷZ}
Lq78א6?<0ZCfW|K˅Gak{zuEP^pɦ]2 ̬#Z  ? \ՐHnPMzUEAUGihwM ei~#'d hVvo\t~9]x(l+I[14oyɷ*?dE3	mqlԲyOP?_7Oj&5gHLd@iރ/el2.&70*&f#a{vIԼN3>F-|e6}:ٌ}qk%G2(būtJ	cK;5'%GٓS2O7O
7b
_uWzHtRjHP>Nzh&]ckdG	mj;OL@Yq.{R; 210=9U;/ka6ZBX"FxDy&E=؅_Ƭ"g#kbԺPy!6yb"^w?ciH!:=t[Ҙwmrz63?L3x[pX@FLt:>`Wo?Z|C8qw|JjH/逾4j!}_4DFL Q)QSoCٱC!o2}L؇x9
=[L}	'}X^w": {  RIsjwMl~ydiRhXN5g:>kXGï^`!o.>KӃylpry	,͸dDqS犲j=g 6ZKM05zet`ĊzLffun]b*j컩ti k L}&tٮ3fr?F
jAzY^ߏu+YΓi؏+iۭvc،ujV{-զ]8^Z*}goPuS/PsS=-1v
G5cY\!JCk/L2cuı)M_.jmdEd'SsP Րhop]lυW'CEο3ætȍ:=Sώ p=nz֥%/0MzĂEYwR7:H$9Wؒ^Fvn9ڱ&+pfa6:P3.iG)'j{[O܃oY鸢%[k/^&>?}yv!/m%\qMorAIJyԒF]KZ]j3mM{W+-UZd|@)&>](tV)C]_{IgU(P,<hKm|5TZ,ƕ[-'_HNtӐ&8O;^3258=ګvfJvfUPCZH楼ݤR#Ol8
{H]sf6pCMRQt[{MON
P(ۼI첺лW[0ٕ+A6l7 	ýL(`O SDKܴm/Flp$J]xmO^P3ymV,T+&C}ʛĎnmabfc:;>bpF߫wh[VLa}{P,fg)ziaOе]Ye~~nqm*sK!_/VRtS7<i~?x=F<׾bMކPQl6Y>s2g\䙳pCpzҮјurXb'A;-ЖKٖ37rBLMH`歂w|&_ Oݧ	*tCn~!T޶AkzYS}wK U}?}I.<d_ *'XqocE6KF`aѫ]Ѯ_35QfdE1κ/d8IIN8y]p228 c3Vp+C^O)@faYUb;	xY]Ԕ}evWr8-#r_y[H=r%j>۬C|~F4h}JuwbZl3- !1ƼY  TPʀP"|F\z(Jo@zԧwO7vXE >P&3w|8jE]LoGm_8YWX"BP_'0aY~@&4Hj{'׍<	BcnY7|!-泃% 2;CG] a;>ibz_$xw;l|s@Ⲃ6A'R-5f*"F7jgp
"s7B#&1jcUDh}Z̈́A0Irsģ -8Q1Qh;5\R8ӽ}qCMrnXuJz&ɦ{?!?	P5:_~
S@\_g4abwײ\UY}T̰*1Ihus6iTj"荗*i*9pj6&D$)4ĕ:Me8GX_:I|,
Z
lr]`iRõToS$ٜmM\Qo( 훚BW_w$KK7yTQehjSekn{ F;ĐU%{ˀ̵ L eHJM[6ORhFZ'l[3<0¸XYXZ872AG"r^̓@)q!euJYKkdAҌog,[+t.v@3Bl\3[a58&R)?(:"ibr) c /)DiP)7u[?anLC F7#Eج0gv-s1.<\ZlqMA#畮Sn:o̚f8<i+Rw5D!`cɸD$b5&1$'/-l>O*BҲpPTu*NI0;!m
kjUaKV(8 _z&UǹFv9ZfN@!KzSxrkje]M= l%@quZk.q$DA(dQԽO)+|%dUqBrSٽ5ϠZ{ݼbkN㰃wdڦWPkq )؜gƐ`o,D<KAq|P#[$`nf0%K=<t[ϠS8c$WtNXl7<Vq~t)iQ⮧c3&ad2wx{>tiF1Ȗ4|쵩u@pmƷUԊEuh
yd71]]7FaIEc	WՌTD>q!D ƆS7B>'+/,.wϑK6Ryݏb<fn 8`\QEIM0	l+Zf(ph6 	'_	tR0JnwSkŖa4naVR:L3'G<4%׳$tHH}g\-tp5K$$Aj{0"fZ}Ű!JndCⷈl5nR DX}ō)Qkzatȶm4#5A@E0h~o^!d@h4Au&	y$wԮ7I,;3 *\REjEn2F(q1q> /+KzYnvCxMK)Tzy1&E	nvYm	L.eT 'qݸlI3Sn~~B<+߄hb'lVr0qL`t.f!bҁGdn,.6Mw/E1	JQo3zcȘTgupUr (I[7Z>f@WBn|:Q)O@iZ|J	dP<beȏ!͙LVS*y#@MڇpVm1#qDC|wwieM`@")wp]@^νe.5yo
O~<?T)ktNWI)-5M;88Rs֫ X5#Uo\PG~%W@N	쨕uqG/<%j#yn-ꘞ"=
zz<Z,>r˭L%.QgKFc;Jt.KMF"e芘Q;LQ4094=׈6NYP)9
'7꧐a.Yi{H+MMNGOwOǌIcVSD9A%!uf]'DD\)ﬆ}bAXH"rZIt!;<~gw5;5p-KUAG<Xk=dx-4US<'ίFϺH>%C	gJ Z-/ZyPF5:1<g]T{ޠ~/> i3m닖#EpE@f(T!誦aRwQS;:e<]w/^Fn;}h)IT!ksɆN괛SP"UĠeRmyy¨+$0nRz^>;;nN\<tf/A;h/JU$i)3%Ej6}ò*e3!-cdi8/fm8%^im	rbt~ӑybY?Em+&.N<z$( I3
ʮsӧdiZ8 BlGCdhʇbQh8z9{P]y,k6ұO쟬?"[ri[]Y	e\+A rilE:u'w`v]0K[
c4j8͘z+G^*Ę]+{
ǅ锩t<Sr>h^as h-ȯG&9yC\$w %; &Q#j_CHGHmll'wż♱FMޮE;J[A9%Sf'A)aѥsʐ2t[7ZQ@ F0>θtfAv(UJ;N{3x=rN{D]^"ţ1idBK]0b{LTҐ
v\ ]-LS;ۮWK4oۃa>9ȊC~UmpRyɒYeEDXtS/09G/%[4#4zcyꆴ1ޏlM|;9媈?6&diy)hA:zXqÒ_zN)٭Z#R$J]	FM>Dϓ* HRY	DMC"*},zy2n1MFu#ǀ%) _	))JBthh.mϭfar:r"Aۨ/:(ЁTc$pf]:62r/!ѿ@@k`YG\ğ R)RR5O0	53)I>ԑoRrĄlRAР9،">8DM)
iDwjA/"p3CyhL)*~m}YiYH0&p'UЖA"J
6-xޫ SFYXɯjw*I3ڧem L^>ǅUHhCvkbe,f#)f$1!z	Gq')E_$dXr!6t+G:tD|W_o5ْ(J&,N-I#!veH(z`2rT6L[){..H*Έ;-B;ޠU#"zŁvkZZ']=MAjֺR65\)	sTsJ%+f<}Y@-kLJM<Fr6<I_N%	p7>mYda!t 2Ŵ3dr>:)iX@C@&BWmi#ߎc+ɮsׂ]}9JO5P8l'-O?N^\op$-;O,	
O&@E1Knۖ
JڀݟLGq5 ׿a_+mo@DVu 4lC~?گ!H![g^!$MQƗ̯89n Y?RݤeeumĆua7K ` 9"jm4E+YXՂOi|&|Z{ؿ~Ar"Rg49h^Q=NήCpl&vj("?R&s<kMrRPr2Xjy`vIg+~אu j,,Ёp#9A=vO2SB1اoW@RS尋 5Hn̾˾0:DY	Ә1~b_ϹT~5"h_YW_DAͼVMWW+w%ENVUؾ[c>NxnFV||{CpSeիhM`5Sm唹	U#KKD0YhjFP<H?3W|xV42$ҙe{lqRsC빇|,9jq,+hOJvI!(==![斓Ȼ+U%*=t.w'Cŷm%DC4Ee;\8/׃ +C81BϤ)(mew[ϾƧu)t[YSYf>έώ	_ č}N	Fu[5fwc>PX>S3OMٝEmviۉ
E%v".N$O',WSȡK>Tވ_a\m=ռ8ф<(ٜ_0.,T5A,ZG3?\$l uOIk2?M.^HUM=qx(OD,HW Ys4WOYtmRK3_|ވNtFʓmؾMbth!<S!q-;	{4)|lKقqVfpܵ9/R^ɋS	.Ε$nTH`9BeKMЅL)eԎI_f{WszxQ REzO9iEHG=ȈPV5?SAaCE\8+%CxmUuvߗnڋmƳPTnC2K:.ڰd&x8a)+X͵ӬxN^F?'Rd87o¢]z_ggCp#]=	ē"#bXN?]IE!&W7j:I,NXl/(_V-/+&;Yʙ(/5QH]<IQ{BHG(cr8ZbF1	S2uwc xAPW]P?N*keC74d>fNq{\
,SsxePkjnǱP#D#i6Mpx'_!{RaqV:K! %LRRGSw%qW{<Ƨi'j{)`IWY:LWM9ѩ{LtаP^**Ue9Qokd]8?PƠIl%J="`CvGœsrj#ns45TJ(1`$=]ܹmFVOkoUX;ViLgnj}hTq)]ŪQ/	a,+zˀͱ,JM$wCթFj@FLX;t[|k
NpM
Y|hZL `홧&lƚ4QfGip[>	Q>"p3HNEJ >V׮r9q\`ѥFkFqͶ6]Ex?Qd)en%^4![UXO!⛸xb:Pyl],#y!|F!7kQW`a`=9('H_a۽ei
l2
D3,϶*:tʳ Md\Cƹr]9qTz^=pZ%j.ű9h6
6vm-v7S$/Qhhd>ޞմqyf|s/j.H(r@KO6S	~/8p0y(0Sĭ VMIts6LD[=2o`2hs?-f?<9amcכ I_,8~5ޞkyyc~xv`ǃo' ;3_hpVsQi'?4UTti3&OC{@ jnvXVQv.òObtZiǘx'ա(zRN$2tG`p<F[s[d" ):>Ќ?pځP:9Ǔao^7#T 	'xR	ȡa&y~K"-yIKk*\M
{g Hpv J7 8Oԯ3YCv ;HStmQ8A^_3u&r S߂1+]Yz_=D?=*W	$b;r(u$υtf/QD)rPqc1vRF+.|4s&WT qW	^>g3wfr
#:h-dkNpA3{/V.#&72h;iGmsړ yWnI.Mb;/d8
.7K$xaVFMuMfL%{93Ҁ	t_~YHQ%qFnL*'<,DM`zz8^i57EL!Q
Vn1
N.92fya9Pps.g@ǌgx 왶z:R'$<BLHe;-re54}qPw\V/p2XMM|8&xmр&IB=]ܶ6lh~%#rH]sޥ{kTTM)%6{ࠅHY-SZA/$֨x9oug+nO$^uAsDAYt4o!v26)j:mws-#1~nM4LHh$^_Rc"e|Ө-鞋rv6$<-*'iA[ڤWej~dcC_Y 7ipGkФS+5И{7@tjz]ȇp7l졕XV|2QSOOЀP?HfyOt]YCg@if͵yyb<ӑ\3̏zyaDϦ޾91Iq=>$~O>12;\>I95dT+k=<	mO5J4?_fܔqZW5vP/[et']fhvG7:^6hU6ޓ{ʭ!SJ(8Ww!xfre`JN$5>ȲI'`FGIw{j\8DkX\I5e2<.i:׳ML9Qߔ:VL!}6p:aqD%i(u{k8>+G>+u<'jL|o`˛P[|!pʆsZ{l%uIBԭ!AĬCZ[=w?ş;}ŷI!6EQ$NrG4AvGFv=5fkXg"LWP*7 rrZ6oi֩5oI "Z"Wk;.(l(87zc<:+fc缔S/'pM))m Z{,ɐ4#|{F%1c=Ȥ(Oq9:ywNQ@_)Vf `ӉR݃x<D@ʞvRfz	TW܃uB1,Zwԑ-x].&ࣶNz"T/㥻ù=k	Vc2/i"NO(	X}k_QxR
;=jUOewJW5iT"<tYb/YGAƕsDXr.XڲP(FRw&U5GmT&UASՔ$j`>b$Ҋ4gJO~p%<jky$)[6x>RATc%xӹ{pX ,DSŁ] 9-As¸ H#KѴk3V>I"㰏_`?-*
o QOw EEhs
(`Rp0eNޚr e&]
]5vmtLL'*o-T:oH%%+5_3z~Z\VmP#1MBT2>IFIήV/\^x#.0W­N{4gSXm{Khe]~Nz KFkH3/}hOy{W\tU#;癖u_zΫ]MԓƗ7q
*}7TɳJ{/mHY-ȫ=ZY8VVW4W$Ŀυ?ռω=7*q	[W&?P3t~m*H_1E5D_[^nӯ*Q|)zVϝ;نaDa;]׉#UqgliyȺEx=6rs$R^$ķԷr>[=_2dfOm=ӆqRs}1-\?էaci79ktBXp-K{$IB8 v-<"XMޗ3{u*	0C5DRA[h<]zM2e9&%3FMXg٪ E*qR ds<ߵMiRKdH:7)?^K,&/Q6?=,d#{)Xf
mhK`$t&pxl@7Se.Z*qwX+#KtE7e8[!q%ގ3d3OгkB_z3IM=
c};M6&2yVC/jɇĎZGyO^9Jb" ?nevU+>Tϸe\C}S݀f-cWZ	hA*4vsw6mtԟc X9HM06ݘ$mU%oKf->,Ppе='M)-sS5V2J
ӭ&YK?YtW/e(d eYo<\nBx$XkeJc';nAhrZ2YJZȮB",ɺe
VsצɜlyhVֈBeOxjBk({1YP.f	EFk(I|g"t .]ջ,
5|vQ(x:i#&A>/y	*9P9NJ.mHµK ^|)Bl3݁k]!\>۷UG2}Uad@)Ƕ`M,}sXuqnbP	z"j9T_ lFٞN5`U:~k66]Fr}}jKaƲߒLAV;,<ZVERXHUrOٞ:d@,;=ՌX$ϛJYXF\A͙筜0_{<Cwxv"`_͢W!<1E_#;c%lK˒Z?bLjl]?|tZtO:Sdx"]3S52cLaeX U52Pyz1L$`w	bm5(R!S./zCp#SR`ì?
M1ۧY?B$m"NTҺL4<s4\Lnڒ5)(k<x_QACQ
oxfwj(]YcIM+?t}%,Ȳu3@JuZs3޿LNЬzNu	iq9t""KsM(EDrbȟ2;|},'-/<wbj6G8ac^5%/HLg
CBpi{AL3{"6	;;ix&ľ`E/=0/FgLkYH(_ټB_e23[Fg:?[ի
N%ճPFPo@xMO|o7Ͷx*ߖbTU-  s=Hp֖
d<<{@{vcC^?v_ƌnq6P;0\&t+e3YNll-Dzj/XUCdHk&N-n\-\&CBE*u[:6ۡ[G;0C5rލ0ڄx )!bt_؛,LwnäN~FgoįUX !AqA(2dBr[YNIt`iKp:0z/fS6}lQh?\brb]m<LzeM_mt8.ȡl7<I/1_[OZF T5`8]Ϯa tJ3UC(H>7Ic\>:eX/R1Or4O9,+ݏﰲ`ke>j3LYN/A]Uy3?|m;lϙz]fno_kwxSH?XU9wmuhTݤGvڢ0[&&|YEl5+&;f/y;<o~N=y>mO`)^{`]2S;mcymmiȬ琋b4UY 1OHZ@w^Myg!1|C14l{BW8mI ,ܫkeeDX`
w?AQDts@*9hP|cy˛d;<C>%L=+蠌6Zn*/z(K_I6f8憢fo1Bm?)_cAm&AOJ.V*S}quBMFs'ˌ~_FB#t3.8 uȉL_bPlP$2OEyp@+)\>gTzQI)m~KdȋRι4LJbG (U@,jRW>fqMLicAxX <3uKH[)}斶_%!q=)3ޘ#n;?ڳ,;c32I⚥
2jed6A}iƢ!h&B#L"18Ua}p%H 菬BfPBhUmhTHO	#I5պtm , 9N7{ԇrqiqz4im<U亄o=<
W9,e6+7ۮ&ҶThm蓱y$YxGf)uO'[UoaU8oԻGw'@~V>Ű0(	(.qt*Py=d(YLz8H!'uK=x˼WR7~Hs߃&sO㒭Yes p?Cgl2hqQ>͎ΰr3YAqFm?1`Is>|C]-;[-ߕ꒪s޾r#}E7=`J-XvޫU.*|+b?m8Ia.Zàm [1O_Q>"'q$`|ص	|tZB/ȤX3k|`4I?vfN)[ʄIyG5lc/WPs1Ր)^5׺YWφjYRFxtJb%V{Ʀڼ"Z/FV7_#"1,f7Oȡvz4FCr@xmm\Qa71Yy;1_czO>e\x:OyIW9-,Y	)7ZfIלr,.!Ot!V*2Ǉ<?8rՎJt>ɞJvlc>k0lV-Q&K2-v |M150[dThZ^ل
qmmM:bA`NEZ.<c`3YK`&iA{,׸6mt(ĝյ0>]4
5HUq\VVERczbBA*sڰ@llۂ~-9"޹R^8pdn];M%rEe\c^n5%$`̬!X[j#+_	HN*;Mapo	+XQ xÚqbjb:?_@?@yIe.:&u$'W]oĪQɏhUĽ!5W8j㑌`}A(,VG<Nbmul/{tZT>qrY'b,5OxR:8L4oY Lq<;$ONZbˣ3q3#TSӾ29Ϭ	ʦ8FDWy_5\Swsn F}04m(0~s2~K*)峭(|vGt+-Kv.bvaI,Úv6)Uz8,$%;l+T$lx<v<hg 3}PCɏy/bƬXI 3{c-]o&j9j|KNN276p2:Oo7DlY(d ;NY@&AA4]s{.)FYR)vT*W&51Ądnp6`<:k4zן-cEV2)!4)p BVXE MĬ3$mX4ox"mxbpȼ]׳8VF1ʂR1jur޾'NsY,T9Ih¼xuv
C$
;q!Ҹ.OpXߨrB~y(/Wň:i)k6O3غk2؊:KR60suA	jatW`_"C(#Y<r^՚3}4f(ԇ_D`@gØvw7V)2|cҵy3bI>a_m	 +{piM֣ucI)EQך.JI7qQz@PiݮzCNaYd..bE$k7o{=Mq
y+@Z5Fy,س6#ONwf)ygI!Utnd*ѹvGYt1fy61)c|`C4]QDix:{*n5T{QEfB3<~pyCq2
լ߁
'[8~zd9F.Cڑ=;habGߜsw\yL{փkEyp\|ijktZvGk>+R.lx5RimW;V*l%}eΒOQs]Vzd|O㩀&[Z"7xkylC}::짞sP"Em&s>>6gi+R~Í.Ͱun
foIb߄*b7lmNo9ߤ).R;daT mexTgP(+G㺀ݯG(o˾7?l6^~MyIEps=Y@ _Ċ~~!5p] I
OA?@e@dx_{~	u7_@r^Yq{ ݟא_m~q ?f~e~?Iϯ	'9k1a
J	<<<ށA./+?.+ PO+(?l' a,TNɯ# 
&p/!!O{K;qT>Vp">_!&/)ƈ\h俬T俼@@Y _^ /)/h7*ߨ׎xAEk?lKx?b0cE]}_c%k#?6/JBHП񄅂,>GWFV,dld絅?"XI=(]7J(=gpg	䚼HI**Œ#27^yAYBĮ]l"ր%#'/:Hzʊn,WzUalRI1`3;R_fHcף	&/+r^WUPXnn*d%@_[h#f_T	JgjlWgM_P\Gސ3SEJwAP}:.)ǥ#ŏ]@<iФ]w5))k>?,{r3\_+PŲOfeŝRҡ.M,T=|^ޛȢ|5}.ї8E`yGViEJn忸h}.iZBj11X.k['тy؃kOQ"b5r냕'ph7=M	W_iP1>r>:	s~Mf|9#C!W.D%ǂѿ
u%8>R#X^i'偈Qe|Se8cU9;`́B-!ǔS}ԅ v޹1^A	40vM/簳ˎER23K&LЧi{SaTF2a+:jACs넕-vww]@F9x`2ޭp1팗}Ν 
S]ö`leh B֧6{xЍ7x_B%hD{#¯{<Y>lwS#),1ˁqSZH?=Tn#zs	gxެ/7v5/>P>v4}
艦/Imˏ=dIͯ@iVVB#$XKgrAᕛ8jGZ涛rfĵahb85 RlH&/D"N
yIѴg%}a+?BUKe|SG61k93$l>ZHlH'BsMEFcU9dl[A?^t8|ri.~$xP@q=O';ԯQT//o\	 XK yQsNVxJDg@v%L۶MS\Խ#ǹsݳ2Ztx\Y)<m-;kf0sjB¹fe31.n@DXV-y:8KР^]
A8FWk&bRPSBPly I돋P~j}2C ňIx5
4@RbLM!Q> ǽy梞%f;d$K{u#	,%39c5G5q=iQLSf6IAI6VMSlwffkzxNT䯎:4ʈCU-GշN' S~TPLC2IxXa%?LGr:xE(E	v?#!iq'&
?`1 o)TRTumBxM_`q{&s.Yºy	a"nR*h:
cOQ?[uk  ;0W852@*^]*+u|=\mYw2i;9S~I殺Mm-T-u9MDŅ)EwRUWA|vPFFV7i dW>a	ϵlvכ
WS5eAzAC[V$:֟]x7M1p'j3:54Q_s~$:I1z/	PgRܱu3<#m?W-Od$|h]vZTOj-&p?->_RSfSUWr/O+yBH4^.7G&A $ucu]ؙH'bDW-\EuyӐyYѷ5=`L5Ku\Y܁\s:4ћ'N>p/	U o\ӫ-BX]<
%3LI'q"KF[kv{wHg"֠;jHy+y2L=</U2-G	I/DÐtDMOb>RP>0p4s[HtN6bZ@:h~Xf}!-S⽃Ƽ>gH>ޓ =m{}2ft%H ,V4~lfidh3]Xk(aGck%]eNe4/Ee幺_d;jfWPhV̰Rw ckr^H!zĿX*V&`N!aIs'OU#l"O3r0/<P逅vFkA`gF5QXy G$+'W]|ҟ6@b)xGѓkEyζVu2-v©dNZ`טN!5ʕpf<5}(Q'Ѽ@mNV^c	I}<>*,xVz	^N`/;7-V}_U$GS՛p$ߴ	)y%_P<Wn-+u2APW8'E2G4 P6>:nu^Tյ/Q/g\QХM[5+ym/u`^P$_o'5gEh6XEm:c<5"z5Nt	ѰjÜ)X]
|jn/顾a-[T3Oki"dd(h@\xpErn*8֑Ma%E5F"tD%g	3Kxs|NS:VP(*b|w%*rf#c9dLtu%#ʰ1~ž<?Kd))=1- !?# ԛv,XfR.P	<[K=cMB*~6(p|Wɋ対#zk7mg$. ]}ҐtNZ"J]Ft/ilDM؉ҙjUxq|fJ[)ް:7VL5uN>H.R㭩wG"8ybZ4$6h>ڱz\3%7~,Dľ`A Wq%"%{f抸}LjIÿ<%ʣZvњVCԖq㲗RBSB!P _rVB+1(+=ىJ$;{;C
UO#Rs)Pn <Gb1䠈űMomBCF壻W @Rc%*Kjz[\hN$ֻNx.km\+Z[*u;m(cOwE|
87<NtJ`*aZ\Ѧ

(1PpԨt̃ܐ]|>W+aOFl0 Sp%`I;Y4%uc4(?R*W`Gq0@߭*?=Cϲ&b1gVoTONw`*:u"jl^5n(KJepihҫ:n\1C;u4AēY4pb.EqB@Id@ ]}6x4R7@Se*(&|v3-YM(KF˗qCc'
bhK2R1f۞U` X9JVVCg!J\*C"+NAԬX'EJvOŃIco*'虪ULtT#dL(s8lDpbJ ;pϚ8W[Kc3!xGTJF-jk=>5"^t(8G:a<:.##?86)N4B<) \LA;SW9Y$QG(?P`>_75R\\:>X=~B uBUj!Y+ 2!qKiCc]<gpF	K<i_	2FpRhJ0sMF6'*B#*'{*#T]@j~HНH5ġ;7ߎw,5j
mR\;Js·xnRlZgGmr+cZ|KƵvt("bT CB2'ލIl7S	TA.cZ`棓T^lEcI1yIN8(=)U{F^\0^P2ZdR8.ֈ,RW-M('kz͊sN7u^,lzިb8<rp̮r(\&ީ=&z>Lβ~_ 
 j#I_}Ղ6]<$DIuxjOfq[].B&ƤFȜM:# "KKٷc3˃MlHPf(WJJ0),FgR<<_PxjICKnK`<ODsMa,{N)_!
;tTr!E2G0kfm XҲ_S \-ʺ!cHYXtx/D{!X8%/L.'FvO[*XKW<LqN[6f[+qLՕ\B\X`	ऊDKK:HhsnoH30IXG1GB-QjMlDɎIJ2)cXIiЬ~(*.'KniXEז!~9"j|:*ɕz&ȞMOJSrOWXDSjw
PVק;?+[ΓS)I0l3b`|o>1FSۓs)/J*x=JHJ| kg̖{.V`
/M0š=K4xC|ŁK1lKzoBvJI4A*G)`;+fK ea'j"4߉s|E;2jG*tz<>*u3KQ|Bio3  -YjH&j@E]#béZi"Zԉ}3!Y7Wo19:mNan"^k74_)hOIL.3˰<6zM(]$OV'NzI]=C0	3veh;0hGCi~&nMh c5_zm"،.mAU*˿{J- PRm"7g I`[jQed>4YLv1 ?1_x4ΓCj/>ae3	T
`j g]tÊw	7B%U!iC0,EC#O8sb槙D^~ۻj7f5ܓzz -<ߔ lYfP@2s֜#Ѧ
K(rqÂ"Ddb\G$XLWH88ğz"͈lg]3,aAa?pU%n#fglgq{!m\PNcXˊbƒoEs!8뜺'a"Kyvrc(ݱy@rD' As:*DDh]{QmSo{q[POŘb2Ӝ$ц"j.9&x5-R5Yp8.x-xMdy].p-d'
x{)B"T0]XI5kڿQ	IS7H]'uК`d\&J(D,ټ|@)?V*4W,(u{M$DJ,{8Sز]k[
%w<ur645vNu4L>2n_;zeVd+mw׵=MeF%,Q'oE/˃M'sf%ntqr胫-'ӹ};t$ִqVqZzv-
y3hY֚ W7:@mr'{L0ilMus7taxWǾv4uր)`cѥ%"GιM 7C*w7zDQ3m6$4fH1%}2ex\pLYxZ8WXja+&e^`'@L{&v3\An/9嗰8?ʇ&+Ťz]r%R<j\G˻B7(C2 '`mrLػzIEO&~{}NIRF_$#igIiNt0̐T,}LDPxYTXR
R^m.|/	-$ܹ%eK9TS1S:)->G,<N=Z,1 o:3_kQG*xΊ&pN?sLA.̰uM2&4*9fbcUk#l*I`IÓN_65R`h47B$ֵQJOOϞAX²Y[D9h4#%rI/i~yB/[38M
74Tv<"hZX-ْ]XkZ:ZZveU9M_̬F=\=S[=Ky%a{$'"#AvxrOmy1!ftMީ4o7>[ٺXܞx
ckdÞ4Q<1? ZX,^Ȝ
ŕ*mgKZ!NA3~oUzZ.e9#yHnwPÔc3$SEEݼĞNF	s!7ROO.Kݤ]8@O=h&|
9;ܣ 04mLrk`e=no@f7]y$6hkk$$y}Ǎ|nbWהP0vȍ;ϵ=«0ZxصmkY/KR(HyI!X_æ:i~\6&y]X8TnO3wv8SFob8sq4Zo  CX58f6@.K{.rw q{?RGck4 v|O\<,L,`	~C74]?.օֿqjEb=#s-ȂnO%>9\UR-u244^(Ub~wpBԩ&Amb;l}`%˛C( O{yP;=׀l77_cNqO5Cnъxڼ5Z;s9H_mǻ2,<w/1ɴ=U"'	/%=p%>r>IwrGZ};`Be	As*icbpna{Hw;w@95`_[PLu)](؅k'9e&%~za
_#Mܽ44mrsC͆ckK<]l&ׅ:lg\=clm0n?Z 1*ҰNj'9Ni
J%mDLM_K,Ul_ZeTu,΄πt(v;=g\{R$&.`um$3cѦ9dDjvF~r+`%!a	r~(Lf'S[rx\VЅBߞG~DW%BuYaguasUB˿-9:Һs)}~8T!zy!LHNdj_ynFs5J1Њ1dA}n.5,3i~ *؂nssx3l1}gͲe h7j< Zz5}

s1mSWcH42VDo'Ghyl"z3'_z'DPbڊjqqN<+!1`<DP<NmȷgMK7VT/?oItQ8{4)qɅ:1Ukљ1~qg}@DJ͋zl
gwG	+uj:gƷ'=utnk8/<(agqCjXZ(#)l^N_ݶs-MIUP(>~RLy#=dkjN}NDLP%4,N鐈I/ jSv5;Z$ 6V@wJ3'/(MQsj]~0.2: U	@] <jhBUmBF	B,Nv%?SIIPݠz)lF aD,} _vJ	TxJAWjytrk=B?~ UGһr?J^qÓLrK}Jau~l!u_+Mq*d"ӼiݷZeV._o^6[ƹpalϐMi#~3;~. 
|DNC$j,7_!WH*bN\},jUGUԂ<\=%dhZ[@^sGHwO{_$6#B>H\<RAw+ $	yǄ,&vז&-[fxf -7+̩%W_#\)껞,3X"bc-fl0n~.#v(X\jD;R
̏I^8\8ao~GOz݋x;>j1pլ'[6_]PyN:b~2yVٷ#{S@dSNR^ukhݳ0Uƨ];t6hgsgOTkĎk0uLNi:+#+PWtHS y9ŌF9rlSk`,NI\SN׊ÙLc(j@,ѳf[ħ	`6\v#zls2z6{|fU[F(ĖQes(d,/ >ju߈yWz\7>!oMh:\7<YnFՅsŖ6DZMn"}fu0<Dv3ܰٷ<]OUώxA/_L+2~ulش8]Uf,Qsttj/xH4>8(V@Ol "W-U+֙_zqlEF_o~/JaXeqU}XIӡjhBW !1TzJVduDWXJ-\|@ƨ.bJ fWf;IOO<wj
 &"DOu͞p~Q3u)M鿼\g-(zLo2\Y	vCܺ)5>'O&TPxoiuc2)F7U~gpzxC9.a[2z@4em^1u&ݙ(ݿ{~cuo~[f6nS()'jPgglUDj{9띖j۬(4wsW-\<fٷ՛.̶;˽n޽$k}M,Bsa*5uhrSGҕ8snNןU%M9|!#:M >1o\/`A{Wc!CCxahoxN6ϊ_a8(jjK;w:"?dz%^~]Th^nݥ:}xĝKbs̮IzI,~?Dr_)˨I;y?	PK.ngE?La+=;)Whǆ9}N<6μ3oE;:M8~ +Dv1~Hc<}f͟__F*3?_3?jVeşjb83%:W>.bO?O43åH؇>.Ű\)z+= SV}JS]sqEv@ꀠZMb/zp;}O]+0-n łne`swSSVT`؍/SOiޡ-yɑe3'%b2,z&Aj!mBڏUQN_o$=,h\6Ԧ24~] w"5=Lja
JJ5cpF<u֔6O^$DlfĪju c}
Ƙ	[Ww¸#ϰ;Z3FAXgcDc0~H	CÅ-sO.c`NhEZu*xpKAP:RBߋcsQ|v\|4jmDC%f[.a&(	Ѫ}?S)(qhoBQ}<s;83Ukه~oh>e\c\X/j}ź.2ÖH'VNMP;>e5]I;Ͳlg\a2}LE[Z7^8 52ȅRq  ^T~+$[m|kpM>rqQ  n  utȢ:j?\*LӁg>L>^r(046+M|`gq=4n/܌Mb|tor;Jnrf_~#FҘflj)Ѭ6Wpz?WL6-SMyRN?=9 r^FT//;~ٿRčTmpٴ @u0jGo<84kUb)Fu5pN۠۱@^t(0uXL }>* U`AҔ.-3Rc5Cg/L^y~zjzsb=bO
(xˈhƗŲmWnhs`G4
UFz'("6bJzē#蚑BIěYoX}{8y|Ij!VD1{wU)>1qDq}Or`8!s6,g,h	W4rտBh1䶚滟=f/Roҭ~Nf~ ɜŨK%e.s⍦G;}\BM?5d]Gnk(KƼGp/δTlZ0UM|fmA[&W%4Z0\u!nhN7aNBW5WK.jDT*0'0ϐc\apZ^MeO"DVdʔ˃Q$;u'_-2m%ewT'H9յ=ga<ۿ 8&@Nqce17jWS0H
]Ts֜k腸DO&+yB`dPcnY6\)nm2'yqS?o;ۿAğ\BA's3}hZO@ oԭkMxNF?vЕK܅SFsMB!ȇĕ<`)xd1$[qǅ^P'pB̌daѿiְ{ D?x1{}q|vM]S?huVK&d\yWo,2g[q"OUW	v/	E@#S<Ճq	kMAuQuXlq~Je&秭9s6ir}7QJX8N-Nt`?CuZ-GS;:G+ǽedر}1I1Z0ov w4m=ꥳ9D$U()Z1^R/1s[U|L$6u]/[V5N;ʒbPkY)7?lDR|lCY8}fnl1̕wؠr]kZ^%;I({2yBB;&~S%jOV馗 5Teɂ[$\:y\,_I2Pgܩm< E!:ۋhbd>C%IM!M
!S,wT#l# +AկHͣ0\lVGoBz`i)\KBg:PKrrD΍\nGp]Z6_D{V$Dl,K֏y\3ܩb^Y_2a{)Lg,Ki"Lw^|gY$	D&A7ik=SCh_\VTvOsMiS!	3ʽ}Q}:-oOş&Iݵc)ggEx=tN>cbY	Ö"yEC]ʗz;^P
b%a( BƹڳjQѮ8ǚ?|S(՗Ma(Nn1*gmoW4;<h^s0auLaA4OFMeZZh/hA/WH.hm3c*n Zgfϵaz:oY6Gϗ=~ف*4܅d)M?7WciI[Ỿ00ާYw¶"X_8khֿ Ʃr:@7h7-%`{6,GcΊlQn]"ÆC^唳Ig R:p~fz-Z5<)>:W̸#E%Ա	9D[99ȘB٭SJBSi]SGXlO%"1uXf(tA:EdS&Vz;g;pK	ǐD$<>PyuN[_&d<wF-*R)/}bw9Ú8ris:e%>iuDP!ٞ׃eq\E`\.R`Wg9|@Fr<X8nf,;y:33vO 1+{Ķ4&#x̷7^/D3wfhkS#lo66NZ$LML6dk\1cCtZ^Gh3.ne~9FHȇ3%.! .KkcC?[.;mq+:#E.xEj<٢LS=ضQM
a\[mDLdͭse0rFRGǤG%?!9G°<hJܞWvνDvYw3DKAvp!.XĘ+?t1eDih@ ͒7=_  hJ< X /ȡٸ tGcUq @`  1*b	Sp=f]P*sG7㭘iGbE d>vbml99]hbp}We	2"q<h,7C x:`#lxYXMG"b^k$<炟ɇeA9L7!1^7K[-]v.a,A=!+ESt8pfܛໟ ԋ/(,Zs˹Kf`mfz'|$mőQ>8qOYv,4xk't<8h' 'iG-{fQqؖx: Gz12JMe5ǐ}'>p^Sר	B6QI/wM{ڡplo?#ic=P|8&רX]l#㡔IK[
9Lځ@zf-۴~tְn/q|\
[~X\,̖dT~S18lNTXͺ3`B H#no:(4knlJKz>JL:ua';1ܔ[X|`&nLXW<>.05sBSҜX74QQ?{%5"=`=KWYOXOUbGپ,e7J}QcFt7gdxpׂb~7ٮ^]x@L:&j/ah-=qjfdKR1zao+)حF&z$2c¶1D`Ԃqgrphu\TaSK4$|s3(Z<$* $o'uR~9"_i]RОf(h;TFO.tb_xO`)g@|w$=4\<TO{gY#xu"#bY?V' xٞB=<u
+Ub|%.Ϩ ~-Q,i⁺uVpﲜuWOS]Z-lY͞`\Vq,]tzQT:G\C!#JSjXÅpg/yI0 XD2F3$ϥʎ"w#'(KeNۭ$	+wQ#r!xݫ5~vZKzaQ#x+!$ (j۪S\B+OOAD?tqa8y- U6L>Q2XAb?/DA9/c&\
9~?\%$/KHڑ_0=J)eZf5TC7+LX1YW<fS9*]`='
RЈKפN䰱&z<.+\|"yc՘O!	9[j#.oahyxf#Z&¢gBR_Vي1T%.L^9+ck`% !LVM#O4=-
#\oV[uYPm F[|TO:%cb پ*;nq+=\^q*	{g<	PK7C|D. FЙUEU(	vp46E @PPWsaxr3PJlqD!1ϼPSW:8T%eH5`-b5,cKAPx EbZ1*u# I6p̌|BuJ0[jm5'td+䡸fqkMd8+F/%bG"XufJA)(UPSϊ:diyayF	ҫA
RǺYrm+]Њ<[y^f%f@\QzXC%&pwmߙk^CԚ_[=
"!W77 /9Ne9s_xmY)/
y7F!߾xz{^:͉|Fo~E@|2ǩ2d'$6Q~T,?$7zi#4(]
Ie/ƕC\
P#^]rO..k:%l0\RWɟny%b%Vk%vN!iN8n^R|#ugVwTrsLjjo%rVftk]ԍIG}A(-i2?'w`,'Pjo5r`UnKjƐ݌7WmMh Ha0tx=)/scH}٧ow<]l)ed3Tx%cظ|La<LE%FL B;Hd5Rc(BH	TfooտWmH׫nF.&=_sy8	,ZSo45nE)5n:ju]ί6@AF/+À߄!>[hϾ,o$Qxd!X#5%7pnG97i[7_iLW~قbۭzGe-^yR>HJ.Cl1*^H F1T/G!.(eAMT_-~*N5!6_#OlDS~4[C<	v*RT&e7/\N[<!}ǭ'_Өs eOGtKlc  cql<2.g)6AH	~M
@/<"d}]V'\-V%W;S|Dx2ȥ^hܐ7nj{sSP'ix4?3,ΏHZeTtu|bҠ#.UϦ8Nh7+JC@\|b`kEpߨ)7ʹoh!(dޠYН'@[Ƒ	xs)~S=YAGuI:My>4REX}w܏t_<&6Ϲ\?bSA(4zp,	Ks_yMXnVSUH
IJU<.nH)uMqjxS[hFYH6,i"SQL5V[Bj;n@>^;nHhQzU:G{u&YlۍSNu)ZX5pPl1ob9RӨ8X
rs{PK.?2kZq+5՗nd-	۪?2jRL`P|[Ս+f?e4	J.SV VUo~jF\)[bYH_bvkhH/1W'epqL/oݾ+3T|mǝ)-7FnP"\p]-Z:"_j\m" bUVV$HQWj}p{Ƈj#rl1?J# k;'!<XZi`KtNc%w1AwN«YK^5~&"9nH&HfM{gꂢO~7Ȟ8u`^F,'0}iv-T[q^m$i46衂XtQP_kATeLӝz}Ҏ@ϴ`{6?|<aI\QS$ }ENXruF-uR3Gsl'4\4*YE<D1hQ 'IÏLsDnUt,<Sz8Ú|"nEqѝNSTVe-sNY;)dmØ4s1A:16𠕹՜_@)_AqO5p x`3N;| E_pZah.a)Yqm5B}^k$V=A_(M%8K|UA/(]c~m;LC@S⻛R)Y~TL1d,a]T]楷ᘽB-ÿGUTILTMyC!]|G)
TܰYo@˓{-W ;0«$Ǫ6Ft"t,hbzQH,Hma
<jcjՀ-zm5Y,đRhǹ̿xJ|#bc\#L!z, IA[:g+>¤9$l+zxBxy;jCkcb9 "J^Ψv>
-N3HcF5>ذ:nm]'1M#́mI#QPLa,Q#ߙ jz?jo GG$!]mUؒƹ(cM宅Ȟʯ+)	<:ui*{S	؉T	,d颤2 2l'v"`Sxf (c#W!8B:$<OE,_l \֍*6fz`\%@]eh%s^^dplYL!	WNcɦ)Q\PԤ>MGV&`lt9FA*2e<<߆dNTp 2k;
%1ԕ^O&~&;C	u
҈1?:>V3 E_I3EDpx]J$0-? %rA!"w:JB{dPyP+X9(vR]5 Hъt-*FMPA+x|N:eWm<Io&Óƺ/v>c:幷ܱEQ' FQ޷?i9tgLADѲb~d/:_]e3C\\{{ks_{{@"8p oMYMx)~B  A`sP7E AUM
D@nθVh)%ʃ5& (JZ^=;;%T9ٹ5g.tfɓT4VgrGWu8J	Z<kCǆ]]q ;)?i("/ԕUq:|5H*c
6'y	VMj?Z:I!\SH<#H9mQg ?SnYQG:z/aր,nWɼ_ZҜUDA<H Ɏ`ܩꂺ%2(]pPxjԪaJ&$ײn?>8_csY5GqiŻ1|P~ӣE%]f0-d-yvʀQS`y8gJl 	F>5Y+Pu7kx=(b9 +wNd;h9^;^G+٭?}U -V	suQiG]s)!$
Hߚ:<crO^n{NxfmN]I7	4s)z'Vᳬ)p]+='H0haRQ-yR}=2}^w>2{"Ws2%W7V>9X531`	?Q0ܵll%RBFq.^r?6K-{f'T4*&bp7yؔۢ:BGVE E*@rק&?S9	[*4^.XOcK~KɣG;>NZDNx5럷o*ą2氵>fxx콻?M`f{%~U_4Fw+Hr`%mM6WBU$CK
!sU1"*ynRЏr%gp<~k s ..D(Bz{E*8#ix!n8\x8VzR>xt#?tugk	 O#1?$)7D8yo31ʝQX=ʐz,EMD)T
X҂d-'ڈff.P|QFMq9Expq42xՒ))iv͸b2Ih(DqRynT(uԍr8PZ=y񚧢_^ɁA7+AAKN&gݠ&``3seuٍߢn}r3^شs°0㠦,^ռZ<5c!,e	*gTw=VҝKi-)}ҥ?Lc笶t16nT[gq]lI
(NSFV̊[~+D>9/V_lds|;k8+$͠K>Fm>AHdQTch(od,Mo՟pB.~uJ\GXpiTJQ¥*Q//~/BuB.+D-Bd7QfXYمtVEl))s)@Whg,ѫ~rKVpp;o=/D-8Y:iKӻ~ϓ5:6bk?>,/Kʉ{es!ߝm)P4Wىnߕz(:=՝^$|r0Da}L^UOJZdOl[F;|Br:@-|?J|-|K"ai^Q~5ŧϛw?(?H]Sp]Lu͏U@#
n5 6eyXݘ#MІt,<):8_-Rbʁ0L)ψ,@}+k(`~u&+-/M$o?s<g7w:$[F	qIɝ|4ng"RG㤭e#8H2ld[`d:v=Ȼo[-+QbrV8 b2#biˌ	-BLkhDsn%+7d7a.4բshueGAވvd!Y_R8UyRϻ{uD1 ,h%ÿqDR҅{cAʰaވQ傔$"jjϮ@rڗ(geh bPz>q=h6|K~gȡm4k$=u!;*ħPK&k>YA z: !Iw.E\:2	%BfqǰFvxI 2D =_Vja{Rl{أs qSA)`뛳+xȐ~WUA9uU٢6. وRo,UN3u3sXzp57P\;4WPƬHmbv(8Ĕ(Hc%51qXthd"@_q3(D=fKD=:;.jk#\8V6w0ōܻzsg!kPֆjO0l,x<7}^]`!\3CnCdѶX5w_]E_P|b"t)l8*AYY?[:%`]yPg^X).@iY:t.|H8L$j߳ q|JcDLCk᪗dGrx8wC*cѩ?qgwsEM28.VLr 'aWbiozKǑxC_okАSa׺ s\aluG[+> Z]mbȮzT3wߞ.v/5$ty9,x%E oBH,fz1%~)z̪/Qeҙ/n ݕ46_JLDX$DB-#ң34MLO-,:!:Kf`Fjx?1Pj/f&9.+W$P)OW@:,N"'	m"vyE%xPN,HkDD\;~:u	%;e:Dʀ=0b(0e*Yk6~9Yά6fIgNa=䥁5UJkCX-(EZPlrM|ϰv1}nB'D쫋׈7x=@Ƃ$  AR24#8NJ@#r&hnoP,Ek&";\J\ UѶzB*B.
a(`@AL'Iu wڢ3
plmP9VeܼѶՒzid餹 9vgcڿP9B[$g|f/͎/RMWZEh,)	=}HJ/ۄ|*qzޏ^+ X(k|Y~Xܚr@zZ,P3:mz4PډvDqU@!WNᰟ,c[cARn[]Y.zN3PtGd]srhiTOXrJ`o*TLYnjaN$~Z*/$ds#>uІBnoU>6zHCnb_t2&xu\װpn8Ϋr LdJb2[bt^2TYVK
&OLokc{q;-\drQDg;k	UCըzjp7Ic_G
{^vUGzg&S	Γq5|Ι譸#d`Z3}&̳K.`7ܣdwL沟[\؈BEA9((wF3Xw:w,+pnZ2p	A-5c(@rF|2%hɿ\7j@y`BS2Q\ Vdy[/6
%+ M%ϭfQٚ(	k?cE5,W\Ө<ܬ(VB[
lKZzzcEswc)2:3ة<ݶ|`7]@ѧڸv(SY%?'viaP%y0酠XA@
o]_h$!ٻTI=ڍy/AN(cCKW~hDw}Urr9pYd`"k_1xRhMݣǝ+MnJFP_Զ~DlXҋ要zжNT~hͦ	ȖoU-p#wz(f'}|׉Z#͎EHS)XC0Yt^fpZ#3s@5q7T/ؗFv!\H?W->LtD'̪V&&9rY2?\gGoV؏HOaՑϘ_i'4Еr]uP1D1JRUK1/Y zhBüX:b5-B4 8:H6sm`eGhsH~@.eO"wIhe=&v[f]_=t7fSuycзnpTM~ʱ#c 8RSJ3I>Lv)7qŦ1\Ť^2:~ZU铦@t  MWC?iszi[Es{`hV_IBq2_ z$me	$#T _x)VYYGz&7Xtebĝc.۹Qt>#KE#.UnHMyQ>Xv,=5|b9U .jcJbٱE"P[Do!1IլbxD`$^\ [Ͼt@X͛^:HpPק^2l[f/f-ҟ0h%Vũ̕; q\w0#WR錵vBum4	Zhm?c$.P}muS.atHd>^m>:XZO#Z0TF8g޶QDx[Oܦ[ZKk-Kjwa(O~oQfɱJ7'V԰Ɏ~.3<A&QGN~t6U@Bo/ tܷK-^JK5mV-̈́n	'j_M)CcwHTjgޗ+$H.u{G/c_bʋA
AU $2}1,D	XK2aJ z^ JK'2 d$f̡M.T%1}{k	VJIEe]sXвWG**&ʃA)S@8k,qRB3crj<,ڪRNm-1wY`#3ixZv03 iqp@cXYËRF#P<4-֌޵wp~嬿6V׷盍^QÛyuHL=\tHf4E hg"0ẈQx=EО
~v]eрYh$F*PdAdA roxlsS*7q0oM+8)Dp#$sv.TMz~@(CCGFI	X,Q>W9~:ZObxJ/4y:~"GOҊN+%Kbe<40ACT%S&j:!_Z T}h@HXId53}1=K#prVMkVOt	k-UOgk@xZ.E$"Q=tjxMCZV\8Y-uM_H\yю!Q1NVwYk
de+'WCcB!dR4xpyr@=p7ßоm,1fq)~ًF>S32ZB.dV(CM!;4HL<H#AhёmIз'r^<<>tW͸AFR#m[]37G` VXx2Ĵ*誜>MDŕXm%~2v0_ w5<'i~uƔ+E D#Њ|7q?ﱓ;Mao_? P)a5iɡ?nt^!kF\	$b +IZmQUZpm 6*Y7>SeYFuY.o0qUx$_Ǚx%TƠ}lVՙ4?&1|T'hbvZgE1"F5Kr
-v}6];}BD89
ı1pƍޓ=Dn5Pc#a骚BPÎAq[9HQ O:Ҹ=uUƁ6>.*K}u"4*تĘ/`rZuĳ՚t1մ%+扪]37|:/Kʽ(Aelԣ6Qv_0=*3򠂌u}LE/l9]r+g>iS 1@&mhqE&>hMR-kS4 dM"ȗ(VXb@gDDkH1 N L;$΋U+mkKOw֏NC[nxC3n?`۱0=3WNj&;=aw<Elmkl{07n=>;AY!_W4Ӂ⿞7xCއ{ib=[ q \'JAEUB9i;xP)p8S?0ִbVUJu
[9ԥ=*CBZw5CL2sЎD$?&` iH<.Έn'Vr3BI!Դxi/Ѵa.
)tQAD7m6~!l6É,sEm[iJ{z%BFDP@)GN%֌+{TIN(dVkdc)|:5C }kôp9,򼊄5PMeNnT>50pxm3k Nj"̋p`Mj&"Wt4r-MwtbTӬdu#6!PxWbT],]xSQMsZw/3,6{B'u+myA	tҗ@Q@N8zPK;m7߹.K,!<NI+بL;B0Sc$}

u߀ \uJ|+ӎҡf_O]c8vlٗz4Acty[d0MY-e,VN9}/[wg7$S^؜vQfJR<}|5*}RQxX|)-$+IOf0 n'ٺUfo/bHȇD7x3Q7lË/i\N=z.0܎S'`/jр[	`TJ4X}XuWӾ nqqG0'Zp
Gk)xj
YoC+uG-ZMIqHBuZsk7j8W]a6	LBToum0oQ9}#:-/Qb"jNv<tiQ~Aok1qYEx ,Iw3Һ*X{cxI≦.SV|;J+34$r0bѵ|f;֩P{M#O)ξ	DryZx1ÐJW{5Iw
Lw1P
\L92K-#YZMݹs"HK! -Eyi-]Y i	m13XX yh? ֌p/p~z؂l.5bª[LY>bTJL
{6e0=X,SJ>?SŔ]SSvi٩N9y6ln2ց#7JzcaZ3(Ģ
q8<C/UD:Rn@	{4&nV	.x61蹓4.KM	zTۂLZ='ANb{!xdaiaUPa]q-]-Mu]$LٹHAZJ8wST7(i ٬Фf:ۊ<	w:satuwTYV4 !$Vyw٤#%:@su??i3ofoÛdqM=1_8hxplF[#W5GcJR`ƞwXհY$Mcǘ%wAVE^kBNtuԧe㌏Xb.c@GgL%Έ(Gg򸲅yr219{$<p摔}JúJ(_(B,^Ղ5[Fcɪ]YKq! KՊ0xy2ul)bq	S]gAdHhFgR50\24-lQϣ	c.>}Qwtm,_BFvמ}ay&[#	D]Rk3EMx&,A{qm	zAK|(YU34`Zt|Ȕ]&R|L]org^Mu/~?xZ;dN9dp~PQ#4pj^KML5hϡmN )Ndvaد`ZQ9ӠkS,?9t {{9!+^FzzZ*o5';ΔCz?k&8CIR΁;HjeFĊoat"%"JhS0[r	Fwj+SŞT3?!c%qZ7.d%S3ULY#7bndcH>S 89þ-"xRL68F	p_&96 .["U?ȃS|	_a7ثXAi5%twڌM}M.'5EH:MΦx*8UN?uv@rN~!t1Nqˁ ϶w8920CrfS*n*é ZvNuMszB5cS@5,yli=m|C=0ؚ&u1M&A=X	jᓩâX*E|٤E!k!No~@\EmbH0nU+4)"!zM?gԂI|.uUv }rya۪hgNֻ8n]-F8m[B]}<]E*].?[?sE֔]x&Ұ$b(ue4bDסйi3rw<.da~Q%[d_l3[4P:Co3MjߕYT魏+&6WI'?Pr8s|}dZkݍо5&	4V3גSQhu]Z1dUuTIԇhlp҅m$\~rXUun;JG$FF5im=3Yej`8i_4ȀK[x)MAE	:3
(h(A=;oMhQ"a@G=>yA
=66w\	?d3J<GH*	sr8=j清5О-Rx/)T1NMoͽJ(.FLߎVJ(Z)ϪjDMuořlg:0[U0^L=,^M {X:sa=NO/4_jH>!(\zn09d%/S7`>Lq9ZZܬ
hU$EuAtJy
3P,@Wja?O;f/$x>lEy9f;gܽ|3t->TN%ZĵF^fu怼SnVp2l6	ےDg=&תtKsK!C$SÛ!iȸ8!/ ns֐#4bJzBɖ( AM{"oh%H#vBS	N:HwA@<|!|v]`0h88E@V@GC~;ana.vKc^7Ru#ThA[Kx;Asi?`t́ib}-Ш+voo:+Y))`i@wdr+ݳPW +ROeLi@eIhtbgX㸏G ɏ@L52J)jTxX0E]-JcɃE+l]v!U#phOevԺseQAp[OF׍pĀaWq΄ 	V#q_It۵WʑEVd)h/rf+gf/Ci!IIuE%4iaz?3Z8[*r75i_dSEmBt-]>_mDS!@|Su𗋃TmU%Waze(6AְJq)GƠA
es^u;{Plbjڑ`maҦ汮	Z u%aČZ/Q3APzgmefs $G0>xƖ1_t6.NKZȂъc EڕbUGX<y{?_Z+rF	J״8Ɇ$1ilDS% g¡kҷk5um;̹p_`a[YɍtVltV_AVf'#ԤW罝]G~ꚱIu(lØb ƊX
'f,0UUΜA:;!q^ǪMC P}mI[ܡ2,u>JR0o[F.ܠ&>3f,̰QY]BPYdP^ŏd-I *7~Π s Пte&4ğqxO}H?Q33d/s!C)wAOa.2atA:xuh2Nk$aE6u@{8~Q<ಬ0&FtV))ݤ'_WGF'JY
B΅yXI+?r*=:zɯ2|ja\u.)̙i̡`a4r`MGJ8#|椄#ϙ*3?!'z}Z)%7s%2C/Q]?Q}5/G>~:6h0$bqMv#mxO$8vO綒;_FglyW;/ij^~/bY^7uUyQV#:)0RCH$!6E>RzOQ$ЀB >TudgeԉB"d_|{ė8,`
(	ÍF hAs/I:<z X`|
犵,nJ&SL:B'/{-,O5鍧׉M,R`Gnz73`@`ڠ>J~RBSuacæ.WA*.~VƱR#mܴW8  X>wa5c%* ~03ydWpۯ;@nsѭE &]6"j'K
C-VwD>Iv_׋Ml^G42 6Q|/d-sF$-S73$@qj`g]g1a5k%9	39yQMz۪m>=AmpF:{oi-qVǿ*.>لՆZ&[&w(IXnN"] HmqBeڙYK<aC c:ףB>$h|ۥ<ms,5/bז^xT l~+1qO"#p/Eb_Jwh=NA%yɢ23~S\ŕEB(ŐqDPN e@t( IAvc<Qb:mC0W}1pPІPMm F64nK8RfGf^g.kA?ZnX~[[%*H/>ID6WM#C#;P$juzjOܧ.'dJ4c>? RCJWZY#,fvt'fjw 	MfpdS(7Ks	N94Gj7M[!4t(`!`&{2x/Z"ZgY<7Enm<3A,Qި?%D|v
G))Kei0oXƧ0lk=bZ׽AȪC+KǅXӢTT%j5f3]^#'#.u
md=*)I_b^4d{ѹؗ}k\p|7yL73u>[WZv47lo\vls)K5Ro
riA%ճ>z9me`i+7Eh6)	G?LGI=!7	%hKz^q{ĝtB3̸GmfxHe(,2Bk{򇝈j	IЃ@utL=? :2zc.QV{>J$h&7Mꔋ,FV
?0̺JId6l==j3bWJEBLoYΦ>1mk-)QҥExР\݄|Ò-.Nxn򏜄֖SZkٷR7JνJjy?<[覆zJ"j,pUbnh`#T@nh'
şX%$3]кbO4KBkh/kA1} "K:]M^y20	jANLqS:nNb:iyt q<+g5RoNyHqH:C>`+\Sdn]Y)E8+Ks6ff}SRE+ɡ5tl5Y22!ʰZKie!=ndMTRcȓYjU/bf9aH	g{`iRɬ7Nq ackqdXN쒧b<-DZm©5!#FB0zQ3M6i,2\KOcC/-&QE欧cf7m6NqGpn]qJz
Xj>n߲ʅ-GkK2V*&ma@X3{A5aD7ǫp8h1qQՐ[BkqNl#i ޿SqmVZ*MUl$[ġ{8id+?sy}l@<Lpc8򿼧uu+no[dbޤTJ&yO;~Y|43Etm>@e=^'Xħ}8kc4w#|@<uޜއqi,Ae/Bi?uM	|M~-}]	Չ9
B[i}  }VS2ZW iFcv1bV#|!yW<GW9ӌNG?2Ǩ-i#Wԫ1]ED%7+MsT_y<pjP-~JiGcLˋ4s:upOco҆]qvaH}aKKZ5LO9AyI ~C=Y;K\={TEcU62. B:E7i<ď[0+ۜtjyzj,/V!<͋LN&2][觖oD~&Ss$M76%̜z#.2b̊aotۆ(zT"@ԩtB}K޷=Nͼ(, :QʫNVs2=Te$M+lhNcJ/?U+Ku@DS}ZQh-3|l}bm|)"8.ii<ňScg\9Nw865󄤅LQ<F?NiL#9h)7 3%ڃ7o?椳boqI.x	ǛA[żFK@2$&T@.K:am1z溇re4!+	b+ā<FA\.O}-M\+&`(dг|F_YT``߁}7<ݸxM$aK{ĕ*gA@-#کӃV7m9
5|єCd>t %#L 4Q'ښwMVpRIaT0f$dC3}&=l2dCf>4Ӛ0)
oG 7Mh iDA4K2_&iP#4|2 ]1כ$H!H($\yJ=m-:
W0,њ.&!v5yQ9@?ʛ#i4}v3A *$iR:1}H^M{+EKX><\<E[Y:o#ESl\JUoMn[_76ax&S''Xsr'٬eyJYe_|-;?"?WU8EE%ͥӗ*oaJ_ǳ
xqK$Me4͖ӲN<jniNBmRo::MLQ-=ji*aBd1QQOkl[QY\HN}izej먁5B5,h(YГN7r6`spS%:O]E!Є'"dĉQ	p('GTDOSjQH#2+`F"4c;OB0
S?ۄ8F!0U	ёQ8珍NM:%TMOS'`bjQ֗R#)M|X֛SzZrB#% IRڏ4I cqfūGbc813gyEJfxE8t2ǖř!DU}JhŲ.c΅c|s@ZeD錹Db"m4hYHiHDM,[ʺ}*o᥮N̑Bc2M!"d
:*IY8)uh:mBXYJe*^V#e09hXh8>}DcZ${JOF	BC$PN2xC$ML1b(+HcY9T>)d">^*Az<)T噿q#6*IpIM+wG}r62++wMdk|Ԍ4B.gQǧWn:P6-" -{z!'1m9C!j<i.oƿ=9~1]Z둷hs71/koALa	dPhD	ēX
F"gFL$m W%;*ngڳs_qN9SxG=G+gwA?}EB
 <reɅۘKjףAޙ.>9ɼ§Y#9p@)/ݴS|̨a0ti}Cx 7
+"AHo@M[sTveiFovFM;wr}[#=hu\p klP@&yjqE)q<,@mtIjJgms#Ŗz:eī
}TC2=Lu +!>}ZBEZ,9;gM$0= {.s czMmt~	5F-S>d=(j-PqvXivQ3&Z?|K11a@8=*wW
~~>-=.'Ǧ䨬v$O\)!ǿ#YKq۔gmM9˃.c8&{[- ?",<@ID<N,UVBj%r@	Bڏ9&9WVӑ[}k\!2l4%ުC#D\/_sYb:GPP0CRnNuhhlG^.,^UL"i^BЖU N$#\\#N
8:w!o LmÄIabk3W~*Kd)	
X` i1gwͧ_xN}"I~89CRl^1\[Eu+pͦ&cu94NPkR^o7ڎE& fHKT/
 m{lFT[g-rI0I8npԈwͤΣ82o¡
=%?-r"JtgbCyUyF:cNo^aMӍ1_|dhtZᮺ&;M'[nR6&+x`*Ǭs!e+8c QD3\okR8g<CNca,	EqKd|L{n(;`C{:0p$w	r($:`pbNu#}]wQ>FvYJW 2o1U*T*x,lɫb\5.sUX!7<Q-t" '/<q潶#/>nϺΏpNm3d+Fx]MnػK>,	$Y@h%3/ɲƋK֧և&gkrE"dsۛu%Pmgs,v.qu]/kzImZ]Ǎ?BU( 4c J7IIk5;H(E
"kd~KZJڍ##
Ӳokh'5AjVZØQu'kMυwJ<GEOfs(ke'VP磏a
hBTbQ=5Q	[J/uM8a3Z\-
}Ur<N6h/kV^dҟ6\tY}ޯHd=,3&Ț۽Bs05:0OlsjR95/^&a;h#N7oz	V-\Y>uMD	tynB<-l6~}뗾@6U*[u쬥FxR$`
bwѺ96ja	Kt#Y=	7M 6Jq+ּvXHffWqe5)IQ4jR[XyqW\Bec#MXZtڷ`[SfC(ʺՖCP˥tF*y\=,W6n|pv)dF{hu;:GS0r.}xjk-|n풇_9,̾5RM]IϮw-ҫϝ_|Eˬ	S5{$[Fkҟ|3*sNu%9@B< \:%28DnύLc:Ϙ;-?@zٔ7Z0[+s6Ukh
TQsAň`wySB[*rZ2E @./:HN֡4BjԒУmDP)-JHڮ(%RH?lXzvD iA= įb(Hg=(r'?%%# zSȇ>*`mv$NC(R*D4fU Q$>.\`xOp:rKrFJ-{Z+7
cm
C3;led+Cdb9wJUՔ8?pQtHDVnD*g JCJDW=ETkǄ[pBcLk8ٶῙN$[߼Ү")){b?}=)D(n0+}Y;`Ll*?ql[ho>0]dNCo,RJPŧkkd-q 4"p8YfV"_ lw:>+vA	"GVDz"{+Mg0Xw ?W%=WV+LD3|xs @K U c&ˏFq  ?re{rJ7.j|t*$Ӣt7 ,[0CRE%,$N*WQ
lUC1{4sXǋ^E*VȚb^[Йgʉ(gh$*Z<ϖn'"\z҃vGȂ>0&V} h,{UlccN5) ݶ!dD2+|L\>6l 'I&HH 1I;2Ex
  Ix}f߶i35<inwnv[)]P0N]b~2SQunzHtc|nݔSS1ihI؎ɊLS8"T?*D+N?-=Vߤv^+3#xQ-I?2h_*_KV#ɦ,h|)y3j|ċ#:|d+ʟw!RF-Y_/]<#sfn6Kl? @⥉[<QdlҤEp֓c-eۭ`>1J^,f 93QmH"k^~ĪMIw>3 ٍtҟϣj2/Rm-^H#Υu\
f]׿u'NIBo#=Fs*IL'	DN#%Q?"*i1_lыYqO" eIܰJDUcGAjK="m%% ;X041㝈<>}]XISḷK d(0WBs)WKR /0;Azd{o^zUt˒|m}s3&og7/3( 9K|-w/[/HpC\^% L''Ψ/X,u,.#>npKìNJzoܪi}^Nt [BGkr+N]VJ cK~H}3պ^4ZE|q<hgK/T-mݪyBS:h 62DU1PDʑoǻOrq~uGs4`KԮ͚*A, ~$yKD TQ5gԈ|<@*D<YFJ?_@WWbHV@ ?̭`})5 *׋o|_:ǽv3彦OXEÌ0z%Kd>>ߓa<H#}'.gXb$|6B$b=/qH`AҕijWmprTu\{.}4uӀ_R?t##K85j+9n6\id'u57#YO??.$7r|T#^$/*D0^{ y*^{W	!L|7O%H7/=*83~7 R+L0)gVQ[]ezB*fxHJmPŋF|nEC-2Zߝ5?b,#K_R=;IJɸd3P27}5#SŖf\~vhI[p.;uW:CVZm9hFbƒ!'pJ ٵ؂l'~3FtC|}ǡ\Xm	(3fjJ'uLld:[/%@6l7ɺtq;k}-l)coOaqu,UR˯'gʟ-5ע=8!8{:8j]BW?'.F5D=bX*  	.5ֱKú>Qx&/aee5f,$UeJ_!Tt|hOV2Ŭ``iۓthdG1Cɾ6WMf,vD;cD6UaŠLWl&%ЂۣrBծ (?_x͖vc*ZwHf:fr 1y1w+,(0%Pɛi+C5=0LWQ03h o1.{ca-jE푀!ܤ1;r<'N%Wzh u6ÿ^sSYnm?KRf+ɑ#c~YbsE4H>C/Hnߦ;KHW,q@6񶸘)kB ]<@yP,M".;兾~]lʧ?]lK2nRhcx?	ڍ<eSF W_>'{baZfmc4&OŔ?gzSյ[>>$`qcZ;.LPα $IO3H.RƮj~^$q`òK]߮lKb8MG!N}.[FV3)S1дKU %f["ol_3u t{РA1v:/Me?V멻e)kU)ˎ9~#f^EC@9-kM::?W	;Q-7yBlt_ec<Vjg(\umɩ-%t⦾x1u\Mz@}R)70,ZSf}̻}hFE])gW.gȮƯTK쨣pe^E {RW<S$E7sE@gL;:P"_XGxMn?O-U|0.uό`dLSC	*kv^jIu8	~;ulG,/eksOLmI`VS;RU
xsF~/v;'619jhJL8Q}v\,Vf1UbYIz'N?^&>	ke!REΤʳU(?li"~Kz')F	TYBHb<\TMUS Q6kiK/<iވys	MsW<{QÿX*qC
SbC˕j2WX*NHT܇a	\u7/; ь6fHsѺ
Sk	\*I r>}FwP1]0|M.vGlu|Ыxx5B"/ըO!),EX'IMv U0P-JHYbq<:VЎO@\C-^⣹ܻdα!ǄfLuqі!ǟ~C?П|c"wЁث؞5LL/IvN'P>$~+z~ķkMh88aq1:0DZ%Vf4?	˶E+Bj2z9<ra2.@9~}zoPD3KNv'i^4"eeT`|p
zqsRK`Bl*xQ }ZD-Nl&ٴW+/kܭ$)N8 88cԾo侸-%7!cՁOu}=\}1ܡqb?k;e	w({T43ɉHz_0Gtk8|֡HmF; 85]ŔbHĨ]	iwnI.PP"?mèWw?,ףb1uKħ`ۨЊ$n΋UUG꼣iz`a##4}f3Ȕ&vg<11G(%TX/4M(_sΟ駪죙f炆9xEA&W s	RU& {~I+k*d9ߑspe46<$V-ya-+1zpyFv-o7獃J6eaj"e׹~c/+fϔckݿe}9{1X2ߝ*1ou,25˪O=/ieCW}PU@g$x;h#R%>(<u!@
2y2x7pEb?5`nܯx)F묇#2"~3W!R/w#Jg9 X_9=6t`p 4ЦXp@;ܿe'T}tRci)w|~afqOb_t1:0ƪfΥ$	O"e.(HǪ'qP&[$yG\0UKt/,^4,^~_C#&'SGDFӰr*Gw?q;'M6fdQOÐȸ#Ϳ|7D  U	NfUXx~U S 9?lyi7N5|rfj:Zٿ<ZC;5|d+TivjUkZ67A`E	(6NLHJe6 t1c/U=礼hhQШkt]iHշB
M&rkpWEyY\&aogD']Q۴6:'k3s3x=y;${ـYl
L^^ыa<I>=k9_drTא+דIStG1qaM2Nm-}¢L5{Y{TC4}{e!rۻeFQg#.#j)V@L#9TSu%96HrC/^A]֙MEτJR u?c%& ;V%y?Y: bNEnȫԗRdJrA!l	W>?VǏ	'0Qח-h&*:kZ/[,d)ns1}-%>%Ddٛ7uwg.#qE;Z	'Qqo	i	/ {1"*OGD0YNH|p&{tooZkkcT`'!ډ5zCxH/#Bh7j	"gT5[P\ERjg0]6U`Qьc/x) 9QCcשּׂ;Ix%?U/Y
Kj#Y2uLKVw.{1"`Y'.2 TVIlcW@E^~Ug]ҌTm6bq稛(Nz	hG~.*#pmGPfe"Bo5mԛhZ^eԽ9΅$vj"Xp};mD?KCsp Quސ&$=!w:ǎ|ءUδk\(jG?t!{z6 a Di/TNe.?9~L!ew7g'z6lI?]$:U^uͶj
Iqu50\#PYӗG_#G3d^|ंxK3X Ohbz\\Si&zPx4&RNUي<B8t$K1G/=wX`gZTB,3ή?D{"2O5YQ_sL9mB;1j$c?i	x^uG:uy%/[.msj꙳6e F>}/>o=:TkQ0$:oRٰBH"<3z[T@^PoN5?gr\klnYw2ro@YiŹYa?t^vtv"<EmU1s4oXy#A
j2jhg6(zeJsk6|2{!<OtC<.gn?ͽ:aʟ?nWoy +ybtʅL[kk<ǟE}t2~:c:PLLEEn"ۿtOz_KL|GNs͍[?7+dNtAunV̲b/齺jd[%Dx?.q;6-*7!zUODŧJ_(W0vx7H|C
!dvqz h0gʝ'dk!8~o<?O3O;u,Doku
nh{کo"PTlz\A~T>1Г6P8]M๐8?a5Zv WrR@Sc_8GGtLxYH`&h]R.[`oU~%U(\ҫH~"ٯ\>.Ժ=8m:	d@n}po%
๺ۄd8nWs$y.(+6*q^+bUҽw*ut.>0$/KLC-iAA>:,OjXN:-=͟scmɊ+tAl4xgFMDP߃i3BL=Mq@saTgI+[xeQ/"9YW3^Gۀ0:\Q6,Z7H?䭇7hSQ#}״~C캜|cB9Յ/^u-2O\1`-%.)ݠ{y ˮ9+$rUY|Qa CdzGU쵂;eoafRumaZȼ2"ylUeQuZvc:(;(PMZFy3mY*yey-X	8;1fH=@6r-Fl6,՟,-m'LpVEOf;oU3w2yx<'8ݢ`]lAG!J.ղ!ͶA@^(@q3}{+8R*I$j&}ʌb;Z WncaGbuu,D}zY%3E}%h 6<iPPWk5̠)8~D-kXF,DkѣھqE5 r<GCqI.PsN4_Y/yZGKSET'chރAkX"ӕ,ۑ4Ux.}݌B@@ҵ9x(fn/z'[ pE{|Ɯk9j)94	3*nĠ;2ךELhyTql701,tILg12YCxUj&Bt4p}%-{P>Z6H%bq/j$n0w&MybN F8IDFω{xX\mr?	}j^?}Vo+>*3\1lQ}t^,5frL@t,nsݷCĨBeBt,5fV+zE$c1}nϘO[Ζ8|P?T
M<eZU6|K68	=UFD CxN)zx2o{lbZĒ̤jw"K+wҧLG6AvOt0}EF0g	 U?b}z*EX/^]$\:"$QIspAP*ĻYo|؜u^*_}㐪9(kccUخqut3sҞ:S?Fsm͢>XJXvnnYdB[QPO_K5%a2jB5r!*{pC1Sޘ}}o4i"fsfdSY<
qǜ,=񗿥.\:z(\A7U 582x[S7WO
g!<:Rxʯ>6g۷v^|9}߹m_܎|]z1㪯מVB4-~k*.=KUa֐B\SI58ޤEtQߢ*vQksS/Cs-5ENbO݀>cx wX6$B?59J>5"U<BD䓄rQٱw0aW0mZRTizv /GCHQ<*࢑=Qc02֩Ib		vˍ	߹N2vn־؁ooR_;ncA
ªaY1j}hf3R@<B8t;d]c}:]/(mx|eN4lj¸#R]I:ϴzJ?-ƑlgBSN6Fk=vmLGK/7rKsrgՏru|ΫG:XB3PH	I6Aܱ1l;Mw~S~xof~3+}/ݿļa%7@~[yy6eyp][D챖xw_4VOqE4C&|mbRk٫_|*SEHVEV, 6/=7`4̣	AbvKc
޽C
\}#l{#pmQ8,iI$ճŚo)%z_[e=IH9i|j,czf U6&
/vfb!Ǫo:%7;RKi|>fP \"gGh\r^,t; 6Z"X?qΊ_KzkW##³Xg*%	t',rk88W>4L	<h	<eӋMډE-8uOz>`_!q8Uӱ ]uZwZ-!=>+Tm\w	{6b[ܘ?w1l֠w=>g>B7aWD#;?靱v<s0	'MU>LL;n]nk[BKT~kmPф*?LRʣRQއ'c ႓_^]pUoQ]t{ӛzc/ɏ|;㏵lc>ͳE˔r3l$IZt)bU^e$˪ @V RzC շT*J숌a;RV0%Z.'2dї˓gXog>~Q-PQ@1C܅r2Npä
Wp	:Q`d/Hm@fd_&Ўy"&*j*'8 DnH- !|NfBh=tDI/wpw<	d~輈12/)E'Cϗ0 ĕTɰ]K-R2xfRUb0r沶]/,`|XǠI.
IfT+{V	  C?| Gfpm:|K$DGf^!UWq{?J5%^yrI
Nx'dQ32Ke>$_JYq/)EUE,zUy,0d4KDerv>CVS*s;i>,k͘D6QwQv8jVDiڛQ?('`v-ހ'M"2MYWK[EJ3(h(6n*$.

A;k˟܇' 74nJЉu4;0}}N\c)` L;2"?	r"*Jrj.wt;hSk0=ʠޞe=v2" fg,^£"?)]1WAVhb?VZ5y"FJGx멸@CEv7oZu6[k:϶E0k\{tڱyônm+Uwl:}Y/+6?mw!_kQ`(uEb-}%emϧ\?1^RcL4v%PwjLàk<3t}wOm0#0٘MdU	{M Y|r E֗jd*uyHrӞ-  V " m(^,zz! KAaz
FÐS+RA)b985x3).!<°׃VE UJX(f\[W/w Z*?0+ՠT{U q?gsZjr/y#85Cv[$JKQC>t2
qAD+Z\-^dMd7؅h [.5TL%"nBy̛tB̺CϼkD:fB'Ԯ7pUDvyt>\v@l]Rr՜L	rKy#\.{rfl霸܌- wuPϻ3}*	҇NR.&.CC|P_o*:\Mj<s(2An
>E~C=7ۅkhW6-[<~،;ǥ$s^oV*<LM#]ƹ}MmלA&^/ʪc"Zs!F Y2nO0IB ơ(SW )Hn  BX8!z0E`F 8br9FAb9@'@Q0a@7C@z߻u A|끻 bMGm@VRQg2ysTFX,:[w
8G')s_?Aߍ~εYGӃ?<zD>l^: VϠ9,*Fl*zUb&Y*cSן'c>~4~pq&4ĵJk+J}j,!BB`i4A\?6Eu}+ěy9
aGɽE _ಟ^'1eWb2;ypeZn/`D6wREͲdD3[;LL
8!Z-lThu&r*%B( oWWªbrO}b(oHmFfd%9w2l҈^8ˁTNM#I(A.`֠rw-Ωؚ,Z(4dn*XXXILeL8i?os۸G

O*"J0	.6$'KGpٓSYd:Ç%fWiYD<%Ԟ]#r9snx+@|=BrSM8j
jkO¸|h)`e/
T1RnE8L*g-&3߮5.٨}`k8QύA8E`#)̚je)GU!5QXwVW'Ng֩UtKK*WCBE2M[2aPY"Lp<m5lM?mWF90F<h{akȀre\FE-lW-y]v}aNu$uZ"+uLVmc糬Cˀ3 yqirA5vnD
yH +|27>)d<6!7/U=F]n kO)
=:1)/lՊgvH'~bVXRfyc5o-GfJ'ٞh}ǫ#ّ HtD>(ץ "+ل7қpߴ@Q^أYhHٴ 3_uvWPq!-4Ζ7YCmoHPe&o
k6XYL`%Tӣ<QkV`TCcn޺~eO2!DTײ#!@F%bCNgHшP)hAN׶4k8ZXR5+ģb;Ž^ˍ`;Koy'e埆秅<f" J8bvF}̐a[K| jmeayU+35cZ#uNk`CנڜwI\^+pvB[VjtsZ|r0ŕ*;Wr0`cT0ɨ72U,&Bۇ(8~qh#^Ey7:{ڊ[=.(=[ц#StPR%OL
i++dε;&G
b
	lZ72Ai؆z?n	<i::5<A_%_q􅝈twfqdԘ
q0Kѻ3ZqUmV/=:8y+G]ËtҨw=lC={;uBdOWoC4ql
P:e|T|Zbn>e1W(M@>Ή|3Pw$ssm@h)WUL<Fֺ Q5o= 2
hh9c|VcOȕL& <q\`Q@SPo(4
Z>
Wz8rTJKgaMXaE`_,/*y)iqv!l/A%ql!J_qVx%\[c?_+KʐDʹ[y/	'ɹsPwǈ}	c6 Y6[UxY.k># E
mJvPJH0Uߚw8\mb\׺~2h>N4G.}
-+DOkϱWue<eL
uy6+1~x,d1J=1w^֔,/h'8Y|Y b*=8V#f+J>zyH"(t6"sӬQ~["9[ɟhV$1lf7
o1b2ef{URK#~~K_n٢7< R V_`r29shGf*Xnۖa%0ɮ\Ѷorھ4PS/Ȳ]i*\nqוX8_ҝʵi/n
6,u\Ê/& \I)T؄.A&6&bGRѪiOH71}2Hy|Zf~Ζ`Sf.u);!P+XL])^_3W3{(Џ~U$+Rck:YUV[קsoׯH:[(#MI'9c
}J4,FizAS!"gch 6;Yp;
-jѐ4
@!I';-S=^QPmJ qs,|~f۫/	7F tMVoo+4
pѵ>_9=}z'kr<qXa7Jht2)`	ҡ+k]Rn}L
;Ym'F6hndኣ'bBp~6HAC@Ϋc G0oH7hj1|#?F
g$pw npCQ.еH3(96`>5qX[.R-$P6!R"'CDT4&Z2#x\y>?ѳ68[ZNU[) -\[ ۯ6Y2/軡`S2áNfe:i?CPDqD/5щBsrL(6|Mc\\iEp('!MȈ +*kb} )}m[n76#V>BjY%l"ܒաMy|݃`	Vsg+`sFWF5X'3!bi\(XV@s@O"wx[܄I)S-"Cۧ"G,<)~pQXm)D̿80Vc(V f%3}BiĄ$eɋSˬ9%T%'TFF9Ӻ*r;Toy=ba7Ev0pp]8I1N!'=/kAʙH'~rg䕖T㆔*ŁƁʍѡy'8ݶ8sBSx7"=y^@s_sX0Zhx&3	 Gc÷62ȻRf.t~t@Afa0P#WyV"7wCt8
h0nBuqSsf(|ll ^ 5+Ƙ0Yw/TAX1Nрl,~_~!d'Q}~Eې$hW-k`@	$3oI NEpx)4!vܹ?u2^Ko.˿
U; hH[Gg-DJwv"n4=$_tW4	>֢Ҷ:^~4E&bAmsD2k0mVweido&6Eέ?{̽r(Q(6QX[4	2"K7ohn*!=iܫ\"o_lFO@<ZldQ7<\OFϊ~͇'e.2FU&Î`	`clm=,3p]j9"<YG|U+h|c4Hֲ|jwSl9sFژzߔÉ:HjTal[46݊P0l|d+a('aW\ˤ9FBRFI'R3ۈ ӟ6MRMR`ոU4޵WH#qT
G<AnWJwq1W:ne9H.qzЮrJrǮvH=֧W'C7rinB[DHW<)Qx.3%9QAzh2܁F3 G])8hT濝w\})' Ei?%
QRSニ^:%ήQf84OHw{z Ur[JtJ&ZSlH
m7yb>zwDiHp7hCGX\W`7XdϽXX\JV9HX\+N&pwz)k nF")Z\x '%5hmlFa߬)kF6%& 0o!i</k'kl M ,PÉ3JQΆ0R[dyJPfςզIm4 ,]߼ϟ~Rkoeg^2 $
}9Z9"mRypW1bkN{x ғW%% @"N{Q S Ǖ 8T q+y{q+49Z:5^o:61X~F 	Ttٚ0l1qEJ4?p7q|FجxS(v)Cc<̋n2k@>$Fv
>aTgp}\?3_g}WΫ~8,+<~{	OP\NuV&݀CJ.:'W>{N*ˍ4A]R6M!ubzl.ZȎG-RNC5n1[EsxH5-1(W[q~7TWha7$Ame),Pknha%kٰ
QN |^`q7h30yzIYlOܴĿ$m/5NmѿB9[s<Wm0Qyt#)&ӊ~ݫy)&pAZ@BIکrd(0ĄLK euuiӺ6N<#Bi|apLN7ElUրz[
l/e#>"!<x$MOP/
*0ߒ?l$G!C|~Id!t׸!R9m\r(r98P9[{s_xOS~A>U_[ x,m	ǊA[{9wK	h*Εi[q%ziQazzdŵ5YfzE?=>Wk:xZϋdBy
' *+Hg;/l~,lD"uVA@rQ
I+W+a5/1Rјt_pgcpDkiփ$D4C`u&ͳqb{HAB]z>~d|s>#iNYaBfl~%
Ni~ćV-b-rU0))X6"XDYǱZn|a;B|!SO8BA/?yG>O`ּ({s!ث]*l8򖂈O-* 
Ǯ˽c[	fePʷZy#=d#R2 %;(Y[R)E6qf峿>NՑRO˜5mgV5[;)Ow`J:O%01~/Vd6o%qR{> <VSA`bkd?B. Xmd"BPN]gȆ]_)/#6Ss?I(s~W^/9H[萊Кy/3'w|ѭ)|l1k8t:?8pK^sDDSP\ДW>_.!(8*6^jx̿H'YKF[1;g	E`Ɍs_X"P?Yx(	1Gś@
io!XirKÇֵI!#NllpQ}ph%
7C1bg
 У5IZ [#y)n  #5,ٿ7@?n@?wchȀ3)J?ӀT֒/L^t</HnH~Ay.'#wHkP0נh9)aeSo}I"ǇKђV̧')oQoF]D?'p&YnD6ArDTE>{A狀BOGT$m&
S=_j:r?=ɖ+u%fdXYj"szB.$;C	sP˶9y5)Xd2_7ʴ_>gXKT?fP#:W59TS1^lG8|\ܠovsfyc p3SnM =xǇɲ8c|xV޾c,jV9^<C̅9Sy{}gӭy\
dL4w)|椌J~tQdJ>u,?Y,Sj6m	{oZk0(Ǒdt"?L23#$].%:_'	DW.+N,ræN/6?g3#"1& KXp!tА~FFME-){Xz}Щ|=k֍nkwy?}SKI0GۛhZv'	^{]o盰ƯkMD3WxMA/ld~0.0x=4#j;#OFϻg]AOΩܪ!wN9t@H"m\?asLYIFuבJFB.ŔJdkJVv[Zw{3drҮ{krjȶ,(=laIwqx{'Oɗ?Pawڶt@>.(I] r<n җ~!SSI|Q?c\*z/1(鸰4ܷf@K^@
^2=~"|&Jv{iſ'\m_w~mdɎvD>NjwlhZl9On
ݐ@哬,'$Rezk(M:3zGȺz ,mUpSA>r-L[~ɻSL"?8j@=V|~h3Y	Bi_%JZvgUׇF֒._ya&w G'Eq-Q*Z L&qb6hGLXϧ,ޖ*ao*|02Z@~UGB?xg^ۤ8GP=U:b(?vt8
HSa|qq/'noo.G!D#ަaKm_SHhHBK`:8֬C%\8V'](B@wv9y0n;V\drdf<֞/z^_Ř/ci1fMLh_i?L~ t^s@:"9%[Z}e30}/Jʨ'=A_}g)SH&C	/%gM6ݵdGu.o4Ss^k9{jGHxP.ف佅*?в@CxQ2oSk:ƦNf4 |Ƈ[cފ˵IГ3+LWA3V,ӑcg	T!|I]@E+vK&--c+>	_keslbmL~MɱÓWfNogP^ܞx\,lv5"BbkS-D2q43A]}YZ2>,z|]ͷ}ք}~AApC]8ErYqQ0r=\m7%pXq<<=-wÂ^9-`"98<%q/Eҿ4y
;M&1ӂjo0PG1sg";KXd9ro"	Fd1'(;ɻWJ9{->i`̪rEYe H"G`٨ޥ.New 1McGTp՞kK$&]M7e!`#'W`$㵶p,J;m[j1V{;CھP]C+fEvhrlS:P̸[6ph0n-$p393?6dࠀ3a~eq"b;='^'7q߃&#'Aby\{%=\) ̼dQA-IQTfr0+`%í/dz'Fik;aiUvM7ǒ}f{mc }m]u?:h_+驶uǶAl\{:0gQr7<:ןck cR/'3?lZ`⠉6eZ|1Z߂R߲O cKLɷYWm!A\WTdIb94$ɒ(
gJq[l0DH8Co$H~H	ThOjP>W9΍%mlVz8Dy6ǘ3͜W"0K\Vgn*CrzNFRޱ
'%+&,G?~~șeGv$b+X@ |CN 3br:V2A SnDq-#ZVete'N.RH?c%n.1s,6c{opE \uc~@^:_]jG5|V\';T}7悓R}ܞE+xUW˯^̤#3,7)s.{#~9B1s63b[=G5.-[wi7CnʪUqY:$F^NT?
p'h.~0MB{w;-~dZO0K_ڱ|zV	&^z?y<$ku{] `-P0	D_}$cdO4v4B~$c:?n$&P9w.Q~OF6UV"\?H%=S+[I*Qk*x!>%>/#):=![)X	F֫BR`L@1ڰg3NLm7!߳\CCb[ߋ@j=skx蛝XQ%ȑQv+[֬pW7HXyO=ّ>z2r%1s_
{- 7 3.L~tZ!zՄyt$#͇)>BpnZƍ|Λ>lLژ>[aܶҦ:kGPt
_b@^r_Vf(8`1%x7zaS<vҪ-%\:&nVp,~ڌupVvpƂs'"w[de[~DAX&K}iaApIU0GmܿxAs_Hɫ&O\ZFNkd쇃y3Ie (~/́o/U=7]w// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/* eslint-disable no-restricted-properties */
function $(id) {
  return document.getElementById(id);
}
/* eslint-enable no-restricted-properties */

document.addEventListener('DOMContentLoaded', function() {
  if (cr.isChromeOS) {
    var keyboardUtils = document.createElement('script');
    keyboardUtils.src = 'chrome://credits/keyboard_utils.js';
    document.body.appendChild(keyboardUtils);
  }

  $('print-link').hidden = false;
  $('print-link').onclick = function() {
    window.print();
    return false;
  };

  document.addEventListener('keypress', function(e) {
    // Make the license show/hide toggle when the Enter is pressed.
    if (e.keyCode == 0x0d && e.target.tagName == 'LABEL') {
      e.target.previousElementSibling.click();
    }
  });
});
     V{s8O#י$-HH=̥<MF-"[Kw\/KzoDjQ䫀_YS]ѥ-usqz[^'أyH1!q,j5-|>O1EXT5QXZ	Ŕ7R8!ȏ鴙wX^,T$v,R5GB8J%VKF<o#ռ(V1|d%}:KJ/byZTPoI9%g9tn$Eb$\"W`9CJBGBqԔrq-MEBS4:%2Ni1sY >:sϹ_Ju*DzǪ>VBvX( o%1?&Xz/ʹ~?4VsLܵppb>(2YU:wwnZS[eVDkq5?;{у߮Xm$U-oìC5+Ν]y³ZXal0k}gc*>]5cF9=<}k04ʁt5:Gmo~+Yg猌`l{c,N7ސ`|YIVm|ִ>ﰖwon>'}O Wf;*I|W0[߅Xo5	pf-^[=u;tmo<\ziiޝ1˰Z<<b0ֹhx7-еoeu叫>wf#!nCuT0cQER"TP¥iA#Gpyz=PJB+lJD_Ɗ6ՐҎRm4>w1{αY~@f?U#K	n)ZBጠ#q~p
1&, /xEU6mzB~9EKs=}сU9@қ_5[:s,U''Yzඟ0zm0No;ө,UJPyrxo".09 elXcÍYWGLq:R:T5G[,$_j/Sk>j+CCԈ^" =S!-pŲo3RX%f<#Z
0f>wA;bi3$P2a>5c>D(7 co<gƋ8R0/@ķ1͍HI\NȦRVq-+SPyynj)3ۤl
KPzT48V-5<[GW\Oep{(
       Yo۶5&9u{}/8Y-6YH*ߖݑD9vڑww>btf Nv[q̔rK3J'>
jP\sí '`fBJ92NW`ǣ=mV9\ef1'MYs8?^Na"rt:]8PBQ,Xi"	BT1m~灩^TthO;$؅k{5쓊Z!0Ac4;Ej,І];pq DhPPDcm{4;;,mBq)!=#,Sl9+l?8)@x)ʐ1N^rlUH=JYv*nV4gEE."7PWLq bJc	ŵQG,$+쭞mNp7Q/3i1ʛ5YYWm;Q*&a00pd1'̰dng\JzgD=bO徜S3K<)˹Sw1WQ&+8nGfy&>YIڻ:w3E_U_Ik6f3btzy;/Rey#"
S%-ƅ֭9t@%ġp:B9BڕuB_(T<8XU#A3&-?b^v9D'оpLrʍ;ev;A
BKQ$iIQIR$Q=f5&	WhU
m[I3",xlg~teriV*O㜈Vq~vc{dk˰W߇lR1bms(Ι֤XT9Vrm;;])[R;Ni,mXzZeݩ}_d.iY*rۿVi-_3!o0΄
i./՚ ՒgY[:sz~LRO˛/b_VgM*^t5EKMUةz'p}Eؑq92p%KK?$-usK#jl,Kl&	mno~qT쥑.b_,^''#n&^wsUqLR<;؊
7KFڮ}bW۶#?B#ӦͦM7F'0[hBIo%1kxn!ş!\o`O|n>tyJ-Xǝ8}0-n* mcTڮmzV|An=~-n#Lfx2u*OȲ.gc<D/Ld{r<BFPYVL1X1L^aL'Ba Rvl<03f}<7:I}7j_粐/[[?Hw";z~WYVL9]"R˽L3C;0=.+?=ŕHLT)^7¬PW01jU:j7Hs]^m*zEczsCaWAsv8g}~GLnn][ş"[Dr3Yh1B+1`wO'hˮzI͚|t_y/jŢu/?E/ܕjR
Zm-Bm6У/L!i?w+ܕwKU_űiךMy
Too7U:ѩ퉴KGRU>cH]Ne=2@\įEk_V[`ۥ	.њ@lašg6O,G"wC.M$* V>xO`oMJֺPpF)OYgGا75ã^k.R3^
ΎpV{BiN}èC	uh\"2TC u<5evD]3Zb"TƥiNF|<7ӭ&x7JLrVq?L'ixٲ`|td?ۈoce?|}>Xv>)?OOwչm29}O}␶A4ݕ  <!DOCTYPE HTML>
<!--
Copyright 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<html>
<head>
  <meta charset="utf-8">
  <title>$i18n{domDistillerTitle}</title>
  <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
  <link rel="stylesheet" href="chrome://resources/css/overlay.css">
  <style>/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

a:visited {
  color: orange;
}

.hidden {
  visibility: hidden;
}
</style>

  
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/cr/ui/overlay.js"></script>
  <script src="about_dom_distiller.js"></script>
  <script src="strings.js"></script>
</head>
<body>
  <div id="mainContent">
    <div id="list-section">
    <header>
      <h1 id="listTitle">$i18n{domDistillerTitle}</h1>
    </header>
      <div id="add-entry">
        <label for="article_url">$i18n{addArticleUrl}</label>
        <input type="text" id="article_url" />
        <br/>
        <button id="addbutton">$i18n{addArticleAddButtonLabel}</button>
        <button id="viewbutton">$i18n{viewUrlButtonLabel}</button>
        <span id="add-entry-error">$i18n{addArticleFailedLabel}</span>
        <span id="view-url-error">$i18n{viewUrlFailedLabel}</span>
      </div>
      <div id="update-list">
        <form>
          <button id="refreshbutton">$i18n{refreshButtonLabel}</button>
          <span id="entries-list-loading">$i18n{loadingEntries}</span>
        </form>
      </div>
      <ul id="entries-list">
      </ul>
    </div>
  </div>
  <script src="chrome://resources/js/i18n_template.js"></script>
</body>
</html>
/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

a:visited {
  color: orange;
}

.hidden {
  visibility: hidden;
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var domDistiller = {
  /**
   * Callback from the backend with the list of entries to display.
   * This call will build the entries section of the DOM distiller page, or hide
   * that section if there are none to display.
   * @param {!Array<string>} entries The entries.
   */
  onReceivedEntries: function(entries) {
    $('entries-list-loading').classList.add('hidden');
    if (!entries.length) $('entries-list').classList.add('hidden');

    var list = $('entries-list');
    domDistiller.removeAllChildren(list);
    for (var i = 0; i < entries.length; i++) {
      var listItem = document.createElement('li');
      var link = document.createElement('a');
      var entry_id = entries[i].entry_id;
      link.setAttribute('id', 'entry-' + entry_id);
      link.setAttribute('href', '#');
      link.innerText = entries[i].title;
      link.addEventListener('click', function(event) {
        domDistiller.onSelectArticle(event.target.id.substr("entry-".length));
      }, true);
      listItem.appendChild(link);
      list.appendChild(listItem);
    }
  },

  /**
   * Callback from the backend when adding an article failed.
   */
  onArticleAddFailed: function() {
    $('add-entry-error').classList.remove('hidden');
  },

  /**
   * Callback from the backend when viewing a URL failed.
   */
  onViewUrlFailed: function() {
    $('view-url-error').classList.remove('hidden');
  },

  removeAllChildren: function(root) {
    while(root.firstChild) {
      root.removeChild(root.firstChild);
    }
  },

  /**
   * Sends a request to the browser process to add the URL specified to the list
   * of articles.
   */
  onAddArticle: function() {
    $('add-entry-error').classList.add('hidden');
    var url = $('article_url').value;
    chrome.send('addArticle', [url]);
  },

  /**
   * Sends a request to the browser process to view a distilled version of the
   * URL specified.
   */
  onViewUrl: function() {
    $('view-url-error').classList.add('hidden');
    var url = $('article_url').value;
    chrome.send('viewUrl', [url]);
  },

  /**
   * Sends a request to the browser process to view a distilled version of the
   * selected article.
   */
  onSelectArticle: function(articleId) {
    chrome.send('selectArticle', [articleId]);
  },

  /* All the work we do on load. */
  onLoadWork: function() {
    $('list-section').classList.remove('hidden');
    $('entries-list-loading').classList.add('hidden');
    $('add-entry-error').classList.add('hidden');
    $('view-url-error').classList.add('hidden');

    $('refreshbutton').addEventListener('click', function(event) {
      domDistiller.onRequestEntries();
    }, false);
    $('addbutton').addEventListener('click', function(event) {
      domDistiller.onAddArticle();
    }, false);
    $('viewbutton').addEventListener('click', function(event) {
      domDistiller.onViewUrl();
    }, false);
    domDistiller.onRequestEntries();
  },

  onRequestEntries: function() {
    $('entries-list-loading').classList.remove('hidden');
    chrome.send('requestEntries');
  },
}

document.addEventListener('DOMContentLoaded', domDistiller.onLoadWork);
<!DOCTYPE HTML>
<!--
Copyright 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
  <meta name="theme-color" id="theme-color">
  <title>$1</title>
  <!-- Placeholder for CSS. -->
  $2
</head>
<body class="$3">
  <div id="contentWrap">
    <div id="mainContent">
      <article>
        <header id="articleHeader">
          <div id="titleCollapse">
            <div class="verticalCenterOuter">
              <div class="verticalCenterInner">
                <h1 id="titleHolder"><noscript>$4</noscript></h1>
              </div>
            </div>
          </div>
        </header>
        <div id="content"><noscript>$5</noscript></div>
      </article>
      <div id="loadingIndicator" class="visible">
        <!-- SVG material loading spinner. -->
        $6
      </div>
    </div>
    <a data-original-url="$7" id="closeReaderView">$8</a>
  </div>
  <div id="feedbackContainer" class="footerFeedback hidden">
    <div class="feedbackContent">
      <div id="feedbackQuestion"></div>
      <div class="feedbackButtonWrap">
        <a class="feedbackButton" id="feedbackNo"></a>
        <a class="feedbackButton" id="feedbackYes"></a>
      </div>
    </div>
    <div class="clear"></div>
  </div>
</body>
</html>
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// On iOS, |distiller_on_ios| was set to true before this script.
var distiller_on_ios;
if (typeof distiller_on_ios === 'undefined') {distiller_on_ios = false;}

function addToPage(html) {
  var div = document.createElement('div');
  div.innerHTML = html;
  document.getElementById('content').appendChild(div);
  fillYouTubePlaceholders();
}

function fillYouTubePlaceholders() {
  var placeholders = document.getElementsByClassName('embed-placeholder');
  for (var i = 0; i < placeholders.length; i++) {
    if (!placeholders[i].hasAttribute('data-type') ||
        placeholders[i].getAttribute('data-type') != 'youtube' ||
        !placeholders[i].hasAttribute('data-id')) {
      continue;
    }
    var embed = document.createElement('iframe');
    var url = 'http://www.youtube.com/embed/' +
        placeholders[i].getAttribute('data-id');
    embed.setAttribute('class', 'youtubeIframe');
    embed.setAttribute('src', url);
    embed.setAttribute('type', 'text/html');
    embed.setAttribute('frameborder', '0');

    var parent = placeholders[i].parentElement;
    var container = document.createElement('div');
    container.setAttribute('class', 'youtubeContainer');
    container.appendChild(embed);

    parent.replaceChild(container, placeholders[i]);
  }
}

function showLoadingIndicator(isLastPage) {
  document.getElementById('loadingIndicator').className =
      isLastPage ? 'hidden' : 'visible';
}

// Sets the title.
function setTitle(title) {
  var holder = document.getElementById('titleHolder');

  holder.textContent = title;
  document.title = title;
}

// Set the text direction of the document ('ltr', 'rtl', or 'auto').
function setTextDirection(direction) {
  document.body.setAttribute('dir', direction);
}

// Maps JS Font Family to CSS class and then changes body class name.
// CSS classes must agree with distilledpage.css.
function useFontFamily(fontFamily) {
  var cssClass;
  if (fontFamily == "serif") {
    cssClass = "serif";
  } else if (fontFamily == "monospace") {
    cssClass = "monospace";
  } else {
    cssClass = "sans-serif";
  }
  // Relies on the classname order of the body being Theme class, then Font
  // Family class.
  var themeClass = document.body.className.split(" ")[0];
  document.body.className = themeClass + " " + cssClass;
}

// Maps JS theme to CSS class and then changes body class name.
// CSS classes must agree with distilledpage.css.
function useTheme(theme) {
  var cssClass;
  if (theme == "sepia") {
    cssClass = "sepia";
  } else if (theme == "dark") {
    cssClass = "dark";
  } else {
    cssClass = "light";
  }
  // Relies on the classname order of the body being Theme class, then Font
  // Family class.
  var fontFamilyClass = document.body.className.split(" ")[1];
  document.body.className = cssClass + " " + fontFamilyClass;

  updateToolbarColor();
}

function updateToolbarColor() {
  // Relies on the classname order of the body being Theme class, then Font
  // Family class.
  var themeClass = document.body.className.split(" ")[0];

  var toolbarColor;
  if (themeClass == "sepia") {
    toolbarColor = "#BF9A73";
  } else if (themeClass == "dark") {
    toolbarColor = "#1A1A1A";
  } else {
    toolbarColor = "#F5F5F5";
  }
  document.getElementById('theme-color').content = toolbarColor;
}

function useFontScaling(scaling) {
  pincher.useFontScaling(scaling);
}

function maybeSetWebFont() {
  // On iOS, the web fonts block the rendering until the resources are
  // fetched, which can take a long time on slow networks.
  // In Blink, it times out after 3 seconds and uses fallback fonts.
  // See crbug.com/711650
  if (distiller_on_ios) return;

  var e = document.createElement('link');
  e.href = 'https://fonts.googleapis.com/css?family=Roboto';
  e.rel = 'stylesheet';
  e.type = 'text/css';
  document.head.appendChild(e);
}

// Add a listener to the "View Original" link to report opt-outs.
document.getElementById('closeReaderView').addEventListener('click',
    function(e) {
      if (distiller) {
        distiller.closePanel(true);
      }
    }, true);

updateToolbarColor();
maybeSetWebFont();

var pincher = (function() {
  'use strict';
  // When users pinch in Reader Mode, the page would zoom in or out as if it
  // is a normal web page allowing user-zoom. At the end of pinch gesture, the
  // page would do text reflow. These pinch-to-zoom and text reflow effects
  // are not native, but are emulated using CSS and JavaScript.
  //
  // In order to achieve near-native zooming and panning frame rate, fake 3D
  // transform is used so that the layer doesn't repaint for each frame.
  //
  // After the text reflow, the web content shown in the viewport should
  // roughly be the same paragraph before zooming.
  //
  // The control point of font size is the html element, so that both "em" and
  // "rem" are adjusted.
  //
  // TODO(wychen): Improve scroll position when elementFromPoint is body.

  var pinching = false;
  var fontSizeAnchor = 1.0;

  var focusElement = null;
  var focusPos = 0;
  var initClientMid;

  var clampedScale = 1;

  var lastSpan;
  var lastClientMid;

  var scale = 1;
  var shiftX;
  var shiftY;

  // The zooming speed relative to pinching speed.
  var FONT_SCALE_MULTIPLIER = 0.5;

  var MIN_SPAN_LENGTH = 20;

  // The font size is guaranteed to be in px.
  var baseSize =
      parseFloat(getComputedStyle(document.documentElement).fontSize);

  var refreshTransform = function() {
    var slowedScale = Math.exp(Math.log(scale) * FONT_SCALE_MULTIPLIER);
    clampedScale = Math.max(0.5, Math.min(2.0, fontSizeAnchor * slowedScale));

    // Use "fake" 3D transform so that the layer is not repainted.
    // With 2D transform, the frame rate would be much lower.
    document.body.style.transform =
        'translate3d(' + shiftX + 'px,' +
                         shiftY + 'px, 0px)' +
        'scale(' + clampedScale/fontSizeAnchor + ')';
  };

  function saveCenter(clientMid) {
    // Try to preserve the pinching center after text reflow.
    // This is accurate to the HTML element level.
    focusElement = document.elementFromPoint(clientMid.x, clientMid.y);
    var rect = focusElement.getBoundingClientRect();
    initClientMid = clientMid;
    focusPos = (initClientMid.y - rect.top) / (rect.bottom - rect.top);
  }

  function restoreCenter() {
    var rect = focusElement.getBoundingClientRect();
    var targetTop = focusPos * (rect.bottom - rect.top) + rect.top +
        document.scrollingElement.scrollTop - (initClientMid.y + shiftY);
    document.scrollingElement.scrollTop = targetTop;
  }

  function endPinch() {
    pinching = false;

    document.body.style.transformOrigin = '';
    document.body.style.transform = '';
    document.documentElement.style.fontSize = clampedScale * baseSize + "px";

    restoreCenter();

    var img = document.getElementById('fontscaling-img');
    if (!img) {
      img = document.createElement('img');
      img.id = 'fontscaling-img';
      img.style.display = 'none';
      document.body.appendChild(img);
    }
    img.src = "/savefontscaling/" + clampedScale;
  }

  function touchSpan(e) {
    var count = e.touches.length;
    var mid = touchClientMid(e);
    var sum = 0;
    for (var i = 0; i < count; i++) {
      var dx = (e.touches[i].clientX - mid.x);
      var dy = (e.touches[i].clientY - mid.y);
      sum += Math.hypot(dx, dy);
    }
    // Avoid very small span.
    return Math.max(MIN_SPAN_LENGTH, sum/count);
  }

  function touchClientMid(e) {
    var count = e.touches.length;
    var sumX = 0;
    var sumY = 0;
    for (var i = 0; i < count; i++) {
      sumX += e.touches[i].clientX;
      sumY += e.touches[i].clientY;
    }
    return {x: sumX/count, y: sumY/count};
  }

  function touchPageMid(e) {
    var clientMid = touchClientMid(e);
    return {x: clientMid.x - e.touches[0].clientX + e.touches[0].pageX,
            y: clientMid.y - e.touches[0].clientY + e.touches[0].pageY};
  }

  return {
    handleTouchStart: function(e) {
      if (e.touches.length < 2) return;
      e.preventDefault();

      var span = touchSpan(e);
      var clientMid = touchClientMid(e);

      if (e.touches.length > 2) {
        lastSpan = span;
        lastClientMid = clientMid;
        refreshTransform();
        return;
      }

      scale = 1;
      shiftX = 0;
      shiftY = 0;

      pinching = true;
      fontSizeAnchor =
          parseFloat(getComputedStyle(document.documentElement).fontSize) /
          baseSize;

      var pinchOrigin = touchPageMid(e);
      document.body.style.transformOrigin =
          pinchOrigin.x + 'px ' + pinchOrigin.y  + 'px';

      saveCenter(clientMid);

      lastSpan = span;
      lastClientMid = clientMid;

      refreshTransform();
    },

    handleTouchMove: function(e) {
      if (!pinching) return;
      if (e.touches.length < 2) return;
      e.preventDefault();

      var span = touchSpan(e);
      var clientMid = touchClientMid(e);

      scale *= touchSpan(e) / lastSpan;
      shiftX += clientMid.x - lastClientMid.x;
      shiftY += clientMid.y - lastClientMid.y;

      refreshTransform();

      lastSpan = span;
      lastClientMid = clientMid;
    },

    handleTouchEnd: function(e) {
      if (!pinching) return;
      e.preventDefault();

      var span = touchSpan(e);
      var clientMid = touchClientMid(e);

      if (e.touches.length >= 2) {
        lastSpan = span;
        lastClientMid = clientMid;
        refreshTransform();
        return;
      }

      endPinch();
    },

    handleTouchCancel: function(e) {
      if (!pinching) return;
      endPinch();
    },

    reset: function() {
      scale = 1;
      shiftX = 0;
      shiftY = 0;
      clampedScale = 1;
      document.documentElement.style.fontSize = clampedScale * baseSize + "px";
    },

    status: function() {
      return {
        scale: scale,
        clampedScale: clampedScale,
        shiftX: shiftX,
        shiftY: shiftY
      };
    },

    useFontScaling: function(scaling) {
      saveCenter({x: window.innerWidth/2, y: window.innerHeight/2});
      shiftX = 0;
      shiftY = 0;
      document.documentElement.style.fontSize = scaling * baseSize + "px";
      clampedScale = scaling;
      restoreCenter();
    }
  };
}());

window.addEventListener(
  'touchstart', pincher.handleTouchStart, {passive: false});
window.addEventListener(
  'touchmove', pincher.handleTouchMove, {passive: false});
window.addEventListener(
  'touchend', pincher.handleTouchEnd, {passive: false});
window.addEventListener(
  'touchcancel', pincher.handleTouchCancel, {passive: false});
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Applies DomDistillerJs to the content of the page and returns a
// DomDistillerResults (as a javascript object/dict).
(function(options, stringify_output) {
  try {
    function initialize() {
      // This include will be processed at build time by grit.
      // Note: this <include> is not behind a single-line comment because the
      // first line of the file is source code (so the first line would be
      // skipped) instead of a licence header.
      // clang-format off
      (function () {var $gwt_version = "2.7.0";var $wnd = window;var $doc = $wnd.document;var $moduleName, $moduleBase;var $stats = $wnd.__gwtStatsEvent ? function(a) {$wnd.__gwtStatsEvent(a)} : null;var $strongName = '5878C8F52195FB04C55ADFF5C3802008';var aa=2147483647,ba={3:1,12:1},ca={3:1,15:1,12:1},da={3:1,4:1},ea={3:1,5:1,6:1,4:1},ga={10:1,18:1,3:1,11:1,9:1},h={3:1,5:1,14:1,6:1,4:1,13:1},ha={46:1},ka={25:1},la={3:1,31:1},ma={3:1,11:1,9:1,29:1},na={3:1,5:1,4:1},_,oa,pa={};function qa(){}function ra(a){function b(){}b.prototype=a||{};return new b}function k(){}
function n(a,b,c){var d=pa[a],e=d instanceof Array?d[0]:null;d&&!e?_=d:(_=pa[a]=b?ra(pa[b]):{},_.cM=c,_.constructor=_,!b&&(_.tM=qa));for(d=3;d<arguments.length;++d)arguments[d].prototype=_;e&&(_.cZ=e)}function sa(){}function ua(a,b){return va(a)?a===b:xa(a)?a.eQ(b):(ya(a),a===b)}function za(a){return va(a)?p:xa(a)?a.cZ:ya(a)?a.cZ:Fa}
function Ga(a){if(va(a)){Ha();var b=":"+a,c=Ia[b];if(null!=c)a=c;else{c=Oa[b];if(null==c){var d,e,f;d=0;e=a.length;f=e-4;for(c=0;c<f;)d=a.charCodeAt(c+3)+31*(a.charCodeAt(c+2)+31*(a.charCodeAt(c+1)+31*(a.charCodeAt(c)+31*d))),d=~~d,c+=4;for(;c<e;)d*=31,f=c++,f=a.charCodeAt(f),d+=f;c=~~d}256==Ra&&(Oa=Ia,Ia={},Ra=0);++Ra;a=Ia[b]=c}}else a=xa(a)?a.hC():(ya(a),a.$H||(a.$H=++Sa));return a}n(1,null,{},sa);_.eQ=function(a){return this===a};_.gC=function(){return this.cZ};
_.hC=function(){return this.$H||(this.$H=++Sa)};_.tS=function(){var a=Ta(za(this))+"@",b;b=(Ga(this)>>>0).toString(16);return a+b};_.toString=function(){return this.tS()};Ua={3:1,220:1,11:1,2:1};!Array.isArray&&(Array.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)});function Va(a){return a.toString?a.toString():"[JavaScriptObject]"}function xa(a){return!Array.isArray(a)&&a.tM===qa}function r(a,b){return null!=a&&(va(a)&&!!Ua[b]||a.cM&&!!a.cM[b])}
function ya(a){return Array.isArray(a)&&a.tM===qa}function va(a){return"string"===typeof a}function s(a){return null==a?null:a}function Wa(a){return~~Math.max(Math.min(a,aa),-2147483648)}var Ua;function Xa(a){if(null==a.n)if(a.B()){var b=a.c;b.C()?a.n="["+b.k:b.B()?a.n="["+b.w():a.n="[L"+b.w()+";";a.b=b.v()+"[]";a.j=b.A()+"[]"}else{var b=a.g,c=a.d,c=c.split("/");a.n=Ya(".",[b,Ya("$",c)]);a.b=Ya(".",[b,Ya(".",c)]);a.j=c[c.length-1]}}function Ta(a){Xa(a);return a.n}function Za(a){Xa(a);return a.j}
function $a(){this.i=jb++;this.a=this.k=this.b=this.d=this.g=this.j=this.n=null}function kb(a){var b;b=new $a;b.n="Class$"+(a?"S"+a:""+b.i);b.b=b.n;b.j=b.n;return b}function t(a){var b;b=kb(a);lb(a,b);return b}function u(a,b){var c;c=kb(a);lb(a,c);c.f=b?8:0;c.e=b;return c}function mb(){var a;a=kb(null);a.f=2;return a}function w(a,b){var c=a.a=a.a||[];return c[b]||(c[b]=a.u(b))}function Ya(a,b){for(var c=0;!b[c]||""==b[c];)c++;for(var d=b[c++];c<b.length;c++)b[c]&&""!=b[c]&&(d+=a+b[c]);return d}
function lb(a,b){if(a){b.k=a;var c=b.C()?null:pa[b.k];c?c.cZ=b:pa[a]=[b]}}n(76,1,{},$a);_.u=function(a){var b;b=new $a;b.f=4;1<a?b.c=w(this,a-1):b.c=this;return b};_.v=function(){Xa(this);return this.b};_.w=function(){return Ta(this)};_.A=function(){return Za(this)};_.B=function(){return 0!=(this.f&4)};_.C=function(){return 0!=(this.f&1)};_.tS=function(){return(0!=(this.f&2)?"interface ":0!=(this.f&1)?"":"class ")+(Xa(this),this.n)};_.f=0;_.i=0;var jb=1,nb=t(1),Fa=t(0);t(76);n(12,1,ba);_.q=function(){return this.e};
_.tS=function(){var a,b;a=Ta(this.cZ);b=this.q();return null!=b?a+": "+b:a};t(12);function ob(a){this.e=a;cc(this,this.e)}n(15,12,ca,ob);t(15);n(19,15,ca);t(19);n(101,19,ca);t(101);function dc(){dc=k;ec=new sa}function fc(a){dc();this.e=null;this.a="";this.b=a;this.a=""}n(39,101,{39:1,3:1,15:1,12:1},fc);
_.q=function(){var a;null==this.c&&(a=s(this.b)===s(ec)?null:this.b,this.d=null==a?"null":null==a||va(a)||a.tM===qa?va(a)?"String":Ta(za(a)):null==a?null:a.name,this.a=this.a+": "+(null==a||va(a)||a.tM===qa?a+"":null==a?null:a.message),this.c="("+this.d+") "+this.a);return this.c};_.r=function(){return s(this.b)===s(ec)?null:this.b};var ec;t(39);n(196,1,{});t(196);function gc(a){$wnd.setTimeout(function(){throw a;},0)}function hc(){0!=ic&&(ic=0);jc=-1}var ic=0,Sa=0,kc=0,jc=-1;
function lc(){lc=k;mc=new vc}function vc(){}function Bc(a,b){var c,d,e;d=0;for(e=a.length;d<e;d++){c=a[d];try{if(c[1]){if(c[0].Ib()){var f=b;!f&&(f=[]);f[f.length]=c;b=f}}else c[0].Ib()}catch(g){if(g=Cc(g),r(g,12))c=g,gc(r(c,39)?c.r():c);else throw Dc(g);}}return b}n(145,196,{},vc);var mc;t(145);function Ec(){Ec=k;var a,b;b=!(Error.stackTraceLimit||"stack"in Error());a=new Fc;Gc=b?new Hc:a}function cc(a,b){Ec();Gc.s(a,b)}var Gc;n(208,1,{});t(208);function Hc(){}n(111,208,{},Hc);
_.s=function(a,b){var c={};a.fnStack=[];for(var d=arguments.callee.caller;d;){Ec();var e;if(!(e=d.name)){e=d;var f=/function(?:\s+([\w$]+))?\s*\(/.exec(d.toString());e=e.name=f&&f[1]||"anonymous"}a.fnStack.push(e);e=":"+e;if(f=c[e]){var g,l;g=0;for(l=f.length;g<l;g++)if(f[g]===d)return}(f||(c[e]=[])).push(d);d=d.caller}};t(111);function Ic(){Ic=k;Error.stackTraceLimit=64}n(209,208,{});
_.s=function(a,b){function c(a){if(!("stack"in a))try{throw a;}catch(b){}return a}var d;"string"==typeof b?d=c(Error(b)):b instanceof Object&&"stack"in b?d=b:d=c(Error());a.__gwt$backingJsError=d};t(209);function Fc(){Ic()}n(112,209,{},Fc);t(112);function Jc(a,b){if(!a)throw new Kc(""+b);}function y(a){if(!a)throw new Lc;}function z(a,b){if(0>a||a>=b)throw new Mc("Index: "+a+", Size: "+b);}function Nc(a){if(null==a)throw new Oc;}
function Pc(a,b){if(0>a||a>b)throw new Mc("Index: "+a+", Size: "+b);}function Qc(a,b){var c,d,e,f;a=""+a;c=new Rc;for(d=f=0;d<b.length;){e=a.indexOf("%s",f);if(-1==e)break;f=a.substr(f,e-f);c.a+=f;f=b[d++];c.a+=f;f=e+2}e=a.substr(f,a.length-f);c.a+=e;if(d<b.length){c.a+=" [";e=b[d++];for(c.a+=e;d<b.length;)c.a+=", ",e=b[d++],c.a+=e;c.a+="]"}return c.a}function Sc(a,b){return null==a[b]?null:String(a[b])}function A(a,b){return a.getAttribute(b)||""}
function B(a){(a=a.parentNode)&&1==a.nodeType||(a=null);return a}function C(a,b){this.a=a;this.b=b}n(9,1,{3:1,11:1,9:1});_.t=function(a){return this.b-a.b};_.eQ=function(a){return this===a};_.hC=function(){return this.$H||(this.$H=++Sa)};_.tS=function(){return null!=this.a?this.a:""+this.b};_.b=0;t(9);
function Tc(){Tc=k;Uc=new Vc;dd=new gd;od=new vd;wd=new xd;yd=new zd;Ad=new Bd;Cd=new Dd;Ed=new Fd;Gd=new Hd;Id=new Jd;Kd=new Ld;Md=new Nd;Od=new Pd;Qd=new Rd;Sd=new Td;Ud=new le;te=new Ae;De=new Ee}function Fe(){Tc();return D(w(Ge,1),ea,10,0,[Uc,dd,od,wd,yd,Ad,Cd,Ed,Gd,Id,Kd,Md,Od,Qd,Sd,Ud,te,De])}n(10,9,ga);var dd,te,od,Uc,Ad,Ud,yd,Cd,Ed,Gd,wd,De,Id,Kd,Md,Qd,Sd,Od,Ge=u(10,Fe);function Vc(){C.call(this,"DEFAULT",0)}n(160,10,ga,Vc);u(160,null);function Jd(){C.call(this,"SE_RESIZE",9)}
n(169,10,ga,Jd);u(169,null);function Ld(){C.call(this,"SW_RESIZE",10)}n(170,10,ga,Ld);u(170,null);function Nd(){C.call(this,"S_RESIZE",11)}n(171,10,ga,Nd);u(171,null);function Pd(){C.call(this,"W_RESIZE",12)}n(172,10,ga,Pd);u(172,null);function Rd(){C.call(this,"TEXT",13)}n(173,10,ga,Rd);u(173,null);function Td(){C.call(this,"WAIT",14)}n(174,10,ga,Td);u(174,null);function le(){C.call(this,"HELP",15)}n(175,10,ga,le);u(175,null);function Ae(){C.call(this,"COL_RESIZE",16)}n(176,10,ga,Ae);u(176,null);
function Ee(){C.call(this,"ROW_RESIZE",17)}n(177,10,ga,Ee);u(177,null);function gd(){C.call(this,"AUTO",1)}n(161,10,ga,gd);u(161,null);function vd(){C.call(this,"CROSSHAIR",2)}n(162,10,ga,vd);u(162,null);function xd(){C.call(this,"POINTER",3)}n(163,10,ga,xd);u(163,null);function zd(){C.call(this,"MOVE",4)}n(164,10,ga,zd);u(164,null);function Bd(){C.call(this,"E_RESIZE",5)}n(165,10,ga,Bd);u(165,null);function Dd(){C.call(this,"NE_RESIZE",6)}n(166,10,ga,Dd);u(166,null);
function Fd(){C.call(this,"NW_RESIZE",7)}n(167,10,ga,Fd);u(167,null);function Hd(){C.call(this,"N_RESIZE",8)}n(168,10,ga,Hd);u(168,null);function He(){He=k;var a=Fe(),b,c,d,e;b={};d=0;for(e=a.length;d<e;++d)c=a[d],b[":"+(null!=c.a?c.a:""+c.b)]=c;Ie=b}var Ie;function Je(a,b){var c;c=a.slice(0,b);D(za(a),a.cM,a.__elementTypeId$,a.__elementTypeCategory$,c);return c}function Ke(a,b){var c;c=Le(0,b);D(za(a),a.cM,a.__elementTypeId$,a.__elementTypeCategory$,c);return c}
function E(a,b,c,d,e){d=Le(e,d);D(w(a,1),b,c,e,d);return d}function Me(a){return Ne(p,[na,h],[13,2],4,a,0,2)}function Ne(a,b,c,d,e,f,g){var l,m,q,v;q=e[f];l=(m=f==g-1)?d:0;v=Le(l,q);D(w(a,g-f),b[f],c[f],l,v);if(!m)for(++f,l=0;l<q;++l)v[l]=Ne(a,b,c,d,e,f,g);return v}function D(a,b,c,d,e){e.cZ=a;e.cM=b;e.tM=qa;e.__elementTypeId$=c;e.__elementTypeCategory$=d;return e}
function Le(a,b){var c=Array(b),d;switch(a){case 6:d={l:0,m:0,h:0};break;case 7:d=0;break;case 8:d=!1;break;default:return c}for(var e=0;e<b;++e)c[e]=d;return c}function Oe(a,b,c,d,e,f){a===c&&(a=a.slice(b,b+e),b=0);var g=b;for(b+=e;g<b;){var l=Math.min(g+1E4,b);e=l-g;Array.prototype.splice.apply(c,[d,f?e:0].concat(a.slice(g,l)));g=l;d+=e}}function Dc(a){return r(a,39)&&s(a.b)!==s((dc(),ec))?s(a.b)===s(ec)?null:a.b:a}
function Cc(a){var b;if(r(a,12))return a;b=a&&a.__gwt$exception;if(!b&&(b=new fc(a),cc(b,a),a&&"object"==typeof a))try{a.__gwt$exception=b}catch(c){}return b}function Pe(){var a;a=navigator.userAgent.toLowerCase();var b=$doc.documentMode;a=-1!=a.indexOf("webkit")?"safari":-1!=a.indexOf("msie")&&10<=b&&11>b?"ie10":-1!=a.indexOf("msie")&&9<=b&&11>b?"ie9":-1!=a.indexOf("msie")&&8<=b&&11>b?"ie8":-1!=a.indexOf("gecko")||11<=b?"gecko1_8":"unknown";if("safari"!==a)throw new Qe(a);}n(59,12,ba);t(59);
n(22,59,ba);t(22);function Qe(a){this.e=""+("Possible problem with your *.gwt.xml module file.\nThe compile time user.agent value (safari) does not match the runtime user.agent value ("+a+").\nExpect more errors.");cc(this,this.e)}n(100,22,ba,Qe);t(100);n(60,1,{});_.tS=function(){return this.a};t(60);function Re(){cc(this,this.e)}function Mc(a){ob.call(this,a)}n(30,19,ca,Re,Mc);t(30);function Se(){cc(this,this.e)}n(180,30,ca,Se);t(180);function Kc(a){ob.call(this,a)}n(36,19,ca,Kc);t(36);
function Te(){Te=k;Ue=new Ve(!1);We=new Ve(!0)}function Ve(a){this.a=a}n(47,1,{3:1,47:1,11:1},Ve);_.t=function(a){var b=this.a;return b==a.a?0:b?1:-1};_.eQ=function(a){return r(a,47)&&a.a==this.a};_.hC=function(){return this.a?1231:1237};_.tS=function(){return""+this.a};_.a=!1;var Ue,We;t(47);function Xe(a){this.a=a}n(37,1,{3:1,37:1,11:1},Xe);_.t=function(a){return this.a-a.a};_.eQ=function(a){return r(a,37)&&a.a==this.a};_.hC=function(){return this.a};_.tS=function(){return String.fromCharCode(this.a)};
_.a=0;var Ye=t(37);function Ze(){Ze=k;$e=E(Ye,ea,37,128,0)}var $e;n(75,1,{3:1,75:1});t(75);function af(a){ob.call(this,a)}n(23,19,{3:1,15:1,23:1,12:1},af);t(23);function bf(){cc(this,this.e)}n(181,19,ca,bf);t(181);function cf(a){this.a=a}function df(a){var b,c;return-129<a&&128>a?(b=a+128,c=(ef(),ff)[b],!c&&(c=ff[b]=new cf(a)),c):new cf(a)}n(38,75,{3:1,11:1,38:1,75:1},cf);_.t=function(a){var b=this.a;a=a.a;return b<a?-1:b>a?1:0};_.eQ=function(a){return r(a,38)&&a.a==this.a};_.hC=function(){return this.a};
_.tS=function(){return""+this.a};_.a=0;var gf=t(38);function ef(){ef=k;ff=E(gf,ea,38,256,0)}var ff;function hf(a,b){return a<b?a:b}function Oc(){cc(this,this.e)}function jf(a){ob.call(this,a)}n(53,19,ca,Oc,jf);t(53);function kf(a,b){var c;c=b.length;return a.substr(a.length-c,c)===b}function F(a,b){return null==b?!1:a==b?!0:a.length==b.length&&a.toLowerCase()==b.toLowerCase()}function lf(a){return!a.length}
function qf(a,b,c){var d;65536<=b?(d=56320+(b-65536&1023)&65535,b=String.fromCharCode(55296+(b-65536>>10&1023)&65535)+String.fromCharCode(d)):b=String.fromCharCode(b&65535);return a.lastIndexOf(b,c)}function sf(a,b,c,d,e){if(null==c)throw new Oc;if(0>b||0>d||0>=e||b+e>a.length||d+e>c.length)return!1;a=a.substr(b,e);c=c.substr(d,e);return a===c}function zf(a){var b=(160).toString(16),b="\\u"+"0000".substring(b.length)+b;return a.replace(RegExp(b,"g"),String.fromCharCode(32))}
function Af(a,b){var c;c=Xf("");return a.replace(RegExp(b,"g"),c)}function Yf(a,b){var c;c=Xf("");return a.replace(RegExp(b),c)}
function lg(a,b){for(var c=RegExp(b,"g"),d=[],e=0,f=a,g=null;;){var l=c.exec(f);if(null==l||""==f){d[e]=f;break}else d[e]=f.substring(0,l.index),f=f.substring(l.index+l[0].length,f.length),c.lastIndex=0,g==f&&(d[e]=f.substring(0,1),f=f.substring(1)),g=f,e++}if(0<a.length){for(c=d.length;0<c&&""==d[c-1];)--c;c<d.length&&d.splice(c,d.length-c)}c=E(p,h,2,d.length,4);for(e=0;e<d.length;++e)c[e]=d[e];return c}function og(a,b){return a.substr(0,b.length)===b}
function pg(a,b){return a.substr(b,a.length-b)}function tg(a,b,c){return a.substr(b,c-b)}function ug(a){return 0==a.length||" "<a[0]&&" "<a[a.length-1]?a:a.replace(/^[\u0000-\u0020]*|[\u0000-\u0020]*$/g,"")}function Xf(a){var b;for(b=0;0<=(b=a.indexOf("\\",b));)36==a.charCodeAt(b+1)?a=a.substr(0,b)+"$"+pg(a,++b):a=a.substr(0,b)+pg(a,++b);return a}var p=t(2);function Ha(){Ha=k;Oa={};Ia={}}var Oa,Ra=0,Ia;function Tg(){this.a=""}function Rc(){this.a=""}function Ug(a){this.a=a}n(40,60,{220:1},Tg,Rc,Ug);
t(40);function Vg(a){ob.call(this,a)}n(54,19,ca,Vg);t(54);function Wg(a,b){var c,d,e;Nc(b);c=!1;for(e=b.D();e.Q();)d=e.R(),c|=a.F(d);return c}function Xg(a){var b,c,d,e;e=new Ug("[");b=!1;for(d=a.D();d.Q();)c=d.R(),b?e.a+=", ":b=!0,e.a+=c===a?"(this Collection)":""+c;e.a+="]";return e.a}n(211,1,{});_.F=function(){throw new Vg("Add not supported on this collection");};_.G=function(a){return Wg(this,a)};
_.H=function(a){a:{var b,c;for(c=this.D();c.Q();)if(b=c.R(),s(a)===s(b)||null!=a&&ua(a,b)){a=!0;break a}a=!1}return a};_.I=function(){return 0==this.J()};_.K=function(){return this.L(E(nb,da,1,this.J(),3))};_.L=function(a){var b,c,d;d=this.J();a.length<d&&(a=Ke(a,d));c=this.D();for(b=0;b<d;++b)a[b]=c.R();a.length>d&&(a[d]=null);return a};_.tS=function(){return Xg(this)};t(211);function Yg(a,b){var c,d,e;c=b.W();e=b.X();d=a.P(c);return!(s(e)===s(d)||null!=e&&ua(e,d))||null==d&&!a.N(c)?!1:!0}
function Zg(a,b){var c,d,e;for(d=a.O().D();d.Q();)if(c=d.R(),e=c.W(),s(b)===s(e)||null!=b&&ua(b,e))return c;return null}function $g(a,b){return b===a?"(this Map)":""+b}function ah(a){return a?a.X():null}n(210,1,ha);_.M=function(a){return Yg(this,a)};_.N=function(a){return!!Zg(this,a)};_.eQ=function(a){var b;if(a===this)return!0;if(!r(a,46)||this.J()!=a.J())return!1;for(b=a.O().D();b.Q();)if(a=b.R(),!this.M(a))return!1;return!0};_.P=function(a){return ah(Zg(this,a))};_.hC=function(){return bh(this.O())};
_.J=function(){return this.O().J()};_.tS=function(){var a,b,c,d;d=new Ug("{");a=!1;for(c=this.O().D();c.Q();)b=c.R(),a?d.a+=", ":a=!0,d.a+=$g(this,b.W()),d.a+="\x3d",d.a+=$g(this,b.X());d.a+="}";return d.a};t(210);function ch(a,b){return va(b)?G(a,b):!!dh(a.a,b)}function eh(a,b){return va(b)?H(a,b):ah(dh(a.a,b))}function H(a,b){return null==b?ah(dh(a.a,null)):a.c.eb(b)}function G(a,b){return null==b?!!dh(a.a,null):void 0!==a.c.eb(b)}function fh(a,b,c){return va(b)?L(a,b,c):gh(a.a,b,c)}
function L(a,b,c){return null==b?gh(a.a,null,c):a.c.hb(b,c)}function hh(a){ih();a.a=jh.bb();a.a.b=a;a.c=jh.cb();a.c.b=a;a.b=0;kh(a)}n(113,210,ha);_.N=function(a){return ch(this,a)};_.O=function(){return new lh(this)};_.P=function(a){return eh(this,a)};_.J=function(){return this.b};_.b=0;t(113);n(212,211,ka);_.eQ=function(a){if(a===this)a=!0;else if(r(a,25)&&a.J()==this.J())a:{var b;Nc(a);for(b=a.D();b.Q();)if(a=b.R(),!this.H(a)){a=!1;break a}a=!0}else a=!1;return a};_.hC=function(){return bh(this)};
t(212);function lh(a){this.a=a}n(63,212,ka,lh);_.H=function(a){return r(a,24)?Yg(this.a,a):!1};_.D=function(){return new mh(this.a)};_.J=function(){return this.a.b};t(63);function nh(a){if(a.a.Q())return!0;if(a.a!=a.b)return!1;a.a=a.c.a._();return a.a.Q()}function oh(a){if(a._gwt_modCount!=a.c._gwt_modCount)throw new ph;return y(nh(a)),a.a.R()}function mh(a){this.c=a;this.a=this.b=this.c.c._();this._gwt_modCount=a._gwt_modCount}n(64,1,{},mh);_.Q=function(){return nh(this)};_.R=function(){return oh(this)};
t(64);n(213,211,{31:1});_.S=function(){throw new Vg("Add not supported on this list");};_.F=function(a){this.S(this.J(),a);return!0};_.eQ=function(a){var b,c,d;if(a===this)return!0;if(!r(a,31)||this.J()!=a.J())return!1;d=a.D();for(b=this.D();b.Q();)if(a=b.R(),c=d.R(),!(s(a)===s(c)||null!=a&&ua(a,c)))return!1;return!0};_.hC=function(){var a,b,c;c=1;for(b=this.D();b.Q();)a=b.R(),c=31*c+(null!=a?Ga(a):0),c=~~c;return c};_.D=function(){return new M(this)};
_.U=function(){throw new Vg("Remove not supported on this list");};t(213);function qh(a){if(-1==a.c)throw new bf;a.d.U(a.c);a.b=a.c;a.c=-1}function M(a){this.d=a}n(7,1,{},M);_.Q=function(){return this.b<this.d.J()};_.R=function(){return y(this.b<this.d.J()),this.d.T(this.c=this.b++)};_.V=function(){qh(this)};_.b=0;_.c=-1;t(7);function rh(a,b){this.d=this.a=a;Pc(b,a.b.length);this.b=b}n(43,7,{},rh);t(43);function sh(a,b){z(b,a.b);return N(a.c,a.a+b)}
function th(a,b,c){var d=a.b.length;if(0>b)throw new Mc("fromIndex: "+b+" \x3c 0");if(c>d)throw new Mc("toIndex: "+c+" \x3e size "+d);if(b>c)throw new af("fromIndex: "+b+" \x3e toIndex: "+c);this.c=a;this.a=b;this.b=c-b}n(50,213,{31:1},th);_.S=function(a,b){Pc(a,this.b);uh(this.c,this.a+a,b);++this.b};_.T=function(a){return sh(this,a)};_.U=function(a){z(a,this.b);a=this.c.U(this.a+a);--this.b;return a};_.J=function(){return this.b};_.a=0;_.b=0;t(50);
function vh(a){a=new mh((new lh(a.a)).a);return new wh(a)}function xh(a){this.a=a}n(65,212,ka,xh);_.H=function(a){return ch(this.a,a)};_.D=function(){return vh(this)};_.J=function(){return this.a.b};t(65);function wh(a){this.a=a}n(114,1,{},wh);_.Q=function(){return nh(this.a)};_.R=function(){return oh(this.a).W()};t(114);function yh(a,b){var c;c=a.d;a.d=b;return c}n(48,1,{48:1,24:1});_.eQ=function(a){return r(a,24)?zh(this.c,a.W())&&zh(this.d,a.X()):!1};_.W=function(){return this.c};_.X=function(){return this.d};
_.hC=function(){return Ah(this.c)^Ah(this.d)};_.Y=function(a){return yh(this,a)};_.tS=function(){return this.c+"\x3d"+this.d};t(48);function Bh(a,b){this.c=a;this.d=b}n(49,48,{48:1,49:1,24:1},Bh);t(49);n(216,1,{24:1});_.eQ=function(a){return r(a,24)?zh(this.W(),a.W())&&zh(this.X(),a.X()):!1};_.hC=function(){return Ah(this.W())^Ah(this.X())};_.tS=function(){return this.W()+"\x3d"+this.X()};t(216);function Ch(a,b){var c;c=Dh(a,b.W());return!!c&&zh(c.d,b.X())}n(218,210,ha);
_.M=function(a){return Ch(this,a)};_.N=function(a){return!!Dh(this,a)};_.O=function(){return new Eh(this)};_.P=function(a){return ah(Dh(this,a))};t(218);function Eh(a){this.a=a}n(97,212,ka,Eh);_.H=function(a){return r(a,24)&&Ch(this.a,a)};_.D=function(){return new Fh(this.a)};_.J=function(){return this.a.c};t(97);function Gh(a){a=new Fh((new Hh(a.a)).a);return new Ih(a)}function Jh(a){this.a=a}n(192,212,ka,Jh);_.H=function(a){return!!Dh(this.a,a)};_.D=function(){return Gh(this)};_.J=function(){return this.a.c};
t(192);function Ih(a){this.a=a}n(193,1,{},Ih);_.Q=function(){return this.a.a.Q()};_.R=function(){return this.a.a.R().W()};t(193);function Kh(a,b){var c;c=Lh(a,b);try{return y(c.b!=c.d.c),c.c=c.b,c.b=c.b.a,++c.a,c.c.c}catch(d){d=Cc(d);if(r(d,55))throw new Mc("Can't get element "+b);throw Dc(d);}}n(214,213,{31:1});_.S=function(a,b){var c;c=Lh(this,a);Mh(c.d,b,c.b.b,c.b);++c.a;c.c=null};_.T=function(a){return Kh(this,a)};_.D=function(){return Lh(this,0)};
_.U=function(a){var b,c;b=Lh(this,a);try{return c=(y(b.b!=b.d.c),b.c=b.b,b.b=b.b.a,++b.a,b.c.c),Nh(b),c}catch(d){d=Cc(d);if(r(d,55))throw new Mc("Can't remove element "+a);throw Dc(d);}};t(214);function Oh(a){a.b=E(nb,da,1,0,3)}function uh(a,b,c){Pc(b,a.b.length);a.b.splice(b,0,c)}function P(a,b){a.b[a.b.length]=b;return!0}function Ph(a,b){var c;c=b.K();if(0==c.length)return!1;Oe(c,0,a.b,a.b.length,c.length,!1);return!0}function N(a,b){z(b,a.b.length);return a.b[b]}
function Qh(a,b){for(var c=0;c<a.b.length;++c)if(zh(b,a.b[c]))return c;return-1}function Rh(a,b){var c;c=(z(b,a.b.length),a.b[b]);a.b.splice(b,1);return c}function Sh(a,b,c){z(b,a.b.length);a.b[b]=c}function Th(a,b){var c,d;d=a.b.length;b.length<d&&(b=Ke(b,d));for(c=0;c<d;++c)b[c]=a.b[c];b.length>d&&(b[d]=null);return b}function Q(){Oh(this)}function Uh(a){Oh(this);a=Je(a.b,a.b.length);Oe(a,0,this.b,0,a.length,!1)}n(8,213,la,Q,Uh);_.S=function(a,b){uh(this,a,b)};_.F=function(a){return P(this,a)};
_.G=function(a){return Ph(this,a)};_.H=function(a){return-1!=Qh(this,a)};_.T=function(a){return N(this,a)};_.I=function(){return 0==this.b.length};_.U=function(a){return Rh(this,a)};_.J=function(){return this.b.length};_.K=function(){return Je(this.b,this.b.length)};_.L=function(a){return Th(this,a)};t(8);
function Vh(a,b,c,d,e,f){var g,l,m;if(7>d-c)for(a=c,g=a+1;g<d;++g)for(m=g;m>a&&0<f.Z(b[m-1],b[m]);--m)c=b[m],b[m]=b[m-1],b[m-1]=c;else if(l=c+e,g=d+e,m=l+(g-l>>1),Vh(b,a,l,m,-e,f),Vh(b,a,m,g,-e,f),0>=f.Z(a[m-1],a[m]))for(;c<d;)b[c++]=a[l++];else for(e=l,l=m;c<d;)l>=g||e<m&&0>=f.Z(a[e],a[l])?b[c++]=a[e++]:b[c++]=a[l++]}function bh(a){var b,c;c=0;for(b=a.D();b.Q();)a=b.R(),c+=null!=a?Ga(a):0,c=~~c;return c}function Wh(){Wh=k;Xh=new Yh}var Xh;
function Zh(a,b){Nc(a);Nc(b);return va(a)?a==b?0:a<b?-1:1:a.t(b)}function Yh(){}n(187,1,{},Yh);_.Z=function(a,b){return Zh(a,b)};t(187);function kh(a){a._gwt_modCount=(a._gwt_modCount|0)+1}function ph(){cc(this,this.e)}n(194,19,ca,ph);t(194);function $h(){cc(this,this.e)}n(88,19,ca,$h);t(88);function ai(a,b){return bi(a.a,b)?a.b[b.b]:null}function ci(a,b,c){di(a.a,b);ei(a,b.b,c)}function ei(a,b,c){var d;d=a.b[b];a.b[b]=c;return d}
function fi(a){var b;this.a=(b=a.e&&a.e(),new gi(b,Ke(b,b.length)));this.b=E(nb,da,1,this.a.a.length,3)}n(185,210,ha,fi);_.N=function(a){return bi(this.a,a)};_.O=function(){return new hi(this)};_.P=function(a){return ai(this,a)};_.J=function(){return this.a.c};t(185);function hi(a){this.a=a}n(92,212,ka,hi);_.H=function(a){return r(a,24)?Yg(this.a,a):!1};_.D=function(){return new ii(this.a)};_.J=function(){return this.a.a.c};t(92);function ii(a){this.c=a;this.a=new ji(this.c.a)}n(93,1,{},ii);_.Q=function(){return ki(this.a)};
_.R=function(){return this.b=ni(this.a),new ti(this.c,this.b)};t(93);function ti(a,b){this.b=a;this.a=b}n(94,216,{24:1},ti);_.W=function(){return this.a};_.X=function(){return this.b.b[this.a.b]};_.Y=function(a){return ei(this.b,this.a.b,a)};t(94);n(219,212,ka);t(219);function di(a,b){var c;Nc(b);c=b.b;return a.b[c]?!1:(a.b[c]=b,++a.c,!0)}function bi(a,b){return r(b,9)&&!!b&&a.b[b.b]==b}function gi(a,b){this.a=a;this.b=b;this.c=0}n(195,219,ka,gi);_.F=function(a){return di(this,a)};
_.H=function(a){return bi(this,a)};_.D=function(){return new ji(this)};_.J=function(){return this.c};_.c=0;t(195);function vi(a){var b;++a.a;for(b=a.c.a.length;a.a<b&&!a.c.b[a.a];++a.a);}function ki(a){return a.a<a.c.a.length}function ni(a){return y(a.a<a.c.a.length),a.b=a.a,vi(a),a.c.b[a.b]}function ji(a){this.c=a;vi(this)}n(99,1,{},ji);_.Q=function(){return ki(this)};_.R=function(){return ni(this)};_.a=-1;_.b=-1;t(99);function Wi(a,b){return s(a)===s(b)||null!=a&&ua(a,b)}
function Yi(){hh(this)}n(20,113,{3:1,46:1},Yi);t(20);function R(a,b){return null==fh(a.a,b,a)}function S(a,b){return ch(a.a,b)}function Zi(){this.a=new Yi}n(17,212,{3:1,25:1},Zi);_.F=function(a){return R(this,a)};_.H=function(a){return S(this,a)};_.I=function(){return 0==this.a.b};_.D=function(){return vh(new xh(this.a))};_.J=function(){return this.a.b};_.tS=function(){return Xg(new xh(this.a))};t(17);
function dh(a,b){var c,d,e,f;c=null==b?"0":""+~~Ga(b);d=a.a[c]||[];e=0;for(f=d.length;e<f;++e)if(c=d[e],Wi(b,c.W()))return c;return null}function gh(a,b,c){var d,e,f,g;d=null==b?"0":""+~~Ga(b);e=a.a;d=e[d]||(e[d]=[]);f=0;for(g=d.length;f<g;++f)if(e=d[f],Wi(b,e.W()))return e.Y(c);d[d.length]=new Bh(b,c);a=a.b;++a.b;kh(a);return null}function ej(){this.a=this.$()}n(89,1,{},ej);_.$=function(){return Object.create(null)};_._=function(){return new fj(this)};t(89);
function gj(a){if(a.c<a.a.length)return!0;if(a.b<a.d.length-1){var b=a.d[++a.b];a.a=a.f.a[b];a.c=0;return!0}return!1}function fj(a){this.f=a;this.d=Object.getOwnPropertyNames(this.f.a);this.a=E(hj,da,24,0,0)}n(144,1,{},fj);_.Q=function(){return gj(this)};_.R=function(){return y(gj(this)),this.e=this.a[this.c++],this.e};_.b=-1;_.c=0;_.e=null;t(144);function lj(){ej.call(this)}n(142,89,{},lj);_.$=function(){return{}};
_._=function(){var a=this.ab(),b=this.a,c;for(c in b)if(c==parseInt(c,10))for(var d=b[c],e=0,f=d.length;e<f;++e)a.F(d[e]);return a.D()};_.ab=function(){return new vj(this)};t(142);function vj(a){this.a=a;Oh(this)}n(143,8,la,vj);_.U=function(a){a=Rh(this,a);a:{var b=this.a,c=a.W(),d,e,f,g;f=null==c?"0":""+~~Ga(c);d=b.a[f]||[];for(g=0;g<d.length;g++)if(e=d[g],Wi(c,e.W())){1==d.length?delete b.a[f]:d.splice(g,1);b=b.b;--b.b;kh(b);break a}}return a};t(143);function wj(){}n(139,1,{},wj);_.bb=function(){return new ej};
_.cb=function(){return new xj};t(139);function ih(){ih=k;var a,b;if(b=Object.create&&Object.getOwnPropertyNames)b=Object.create(null),void 0!==b.__proto__||0!=Object.getOwnPropertyNames(b).length?b=!1:(b.__proto__=42,b=42!==b.__proto__?!1:!0);jh=b?(a=Object.create(null),a.__proto__=42,0==Object.getOwnPropertyNames(a).length)?new Kj:new wj:new Lj}var jh;function Kj(){}n(141,139,{},Kj);_.cb=function(){return new Wj};t(141);function Lj(){}n(140,139,{},Lj);_.bb=function(){return new lj};_.cb=function(){return new Xj};
t(140);function Yj(a,b,c){var d;d=a.a[b];if(void 0===d){var e=a.b;++e.b;kh(e)}a.a[b]=void 0===c?null:c;return d}function Zj(a,b){var c;c=a.a[b];if(void 0!==c){delete a.a[b];var d=a.b;--d.b;kh(d)}return c}function xj(){this.a=this.db()}n(71,1,{},xj);_.db=function(){return Object.create(null)};_._=function(){var a;a=this.fb();return new ak(this,a)};_.eb=function(a){return this.a[a]};_.fb=function(){return Object.getOwnPropertyNames(this.a)};_.gb=function(a){return new bk(this,a)};
_.hb=function(a,b){return Yj(this,a,b)};_.ib=function(a){return Zj(this,a)};t(71);function ak(a,b){this.b=a;this.c=b}n(131,1,{},ak);_.Q=function(){return this.a<this.c.length};_.R=function(){return y(this.a<this.c.length),new bk(this.b,this.c[this.a++])};_.a=0;t(131);function bk(a,b){this.a=a;this.b=b}n(83,216,{24:1},bk);_.W=function(){return this.b};_.X=function(){return this.a.eb(this.b)};_.Y=function(a){return this.a.hb(this.b,a)};t(83);function Xj(){xj.call(this)}n(128,71,{},Xj);_.db=function(){return{}};
_._=function(){var a=this.jb(),b;for(b in this.a)if(58==b.charCodeAt(0)){var c=this.gb(b.substring(1));a.F(c)}return a.D()};_.eb=function(a){return this.a[":"+a]};_.jb=function(){return new ck(this)};_.hb=function(a,b){return Yj(this,":"+a,b)};_.ib=function(a){return Zj(this,":"+a)};t(128);function ck(a){this.a=a;Oh(this)}n(130,8,la,ck);_.U=function(a){var b;return b=Rh(this,a),Zj(this.a,":"+b.W()),b};t(130);function Wj(){xj.call(this)}n(129,71,{},Wj);
_.fb=function(){var a;a=Object.getOwnPropertyNames(this.a);void 0!==this.a.__proto__&&(a[a.length]="__proto__");return a};t(129);function dk(a,b){Mh(a,b,a.c.b,a.c);return!0}function Mh(a,b,c,d){var e;e=new ek;e.c=b;e.b=c;e.a=d;d.b=c.a=e;++a.b}function Lh(a,b){var c,d;Pc(b,a.b);if(b>=a.b>>1)for(d=a.c,c=a.b;c>b;--c)d=d.b;else for(d=a.a.a,c=0;c<b;++c)d=d.a;return new fk(a,b,d)}function gk(){this.a=new ek;this.c=new ek;this.a.a=this.c;this.c.b=this.a;this.a.b=this.c.a=null;this.b=0}n(80,214,la,gk);
_.F=function(a){return dk(this,a)};_.J=function(){return this.b};_.b=0;t(80);function Nh(a){var b;if(!a.c)throw new bf;b=a.c.a;var c=a.d,d=a.c;d.a.b=d.b;d.b.a=d.a;d.a=d.b=null;d.c=null;--c.b;a.b==a.c?a.b=b:--a.a;a.c=null}function fk(a,b,c){this.d=a;this.b=c;this.a=b}n(115,1,{},fk);_.Q=function(){return this.b!=this.d.c};_.R=function(){return y(this.b!=this.d.c),this.c=this.b,this.b=this.b.a,++this.a,this.c.c};_.V=function(){Nh(this)};_.a=0;_.c=null;t(115);function ek(){}n(66,1,{},ek);t(66);
var hj=mb();function Lc(){cc(this,this.e)}n(55,19,{3:1,15:1,12:1,55:1},Lc);t(55);function zh(a,b){return s(a)===s(b)||null!=a&&ua(a,b)}function Ah(a){return null!=a?Ga(a):0}function hk(a,b){if(0>a||a>=b)throw new Se;}n(124,213,la);_.S=function(a,b){hk(a,this.a.b.length+1);uh(this.a,a,b)};_.F=function(a){return P(this.a,a)};_.G=function(a){return Ph(this.a,a)};_.H=function(a){return-1!=Qh(this.a,a)};_.T=function(a){return hk(a,this.a.b.length),N(this.a,a)};_.I=function(){return 0==this.a.b.length};
_.D=function(){return new M(this.a)};_.U=function(a){return hk(a,this.a.b.length),this.a.U(a)};_.J=function(){return this.a.b.length};_.K=function(){var a=this.a;return Je(a.b,a.b.length)};_.L=function(a){return Th(this.a,a)};_.tS=function(){return Xg(this.a)};t(124);function ik(a){var b;b=a.a.b.length;if(0<b)return hk(b-1,a.a.b.length),a.a.U(b-1);throw new $h;}function jk(){this.a=new Q}n(67,124,la,jk);t(67);
function Dh(a,b){var c,d;for(d=a.b;d;){c=Zh(b,d.c);if(0==c)return d;c=0>c?0:1;d=d.a[c]}return null}function kk(a,b,c,d,e,f,g,l){var m;if(d){(m=d.a[0])&&kk(a,b,c,m,e,f,g,l);m=d.c;var q,v;c.kb()&&(q=Zh(m,e),0>q||!f&&0==q)||c.lb()&&(v=Zh(m,g),0<v||!l&&0==v)||b.F(d);(d=d.a[1])&&kk(a,b,c,d,e,f,g,l)}}
function lk(a,b,c,d){var e,f;if(b){e=Zh(c.c,b.c);if(0==e)return d.d=yh(b,c.d),d.b=!0,b;e=0>e?0:1;b.a[e]=lk(a,b.a[e],c,d);mk(b.a[e])&&(mk(b.a[1-e])?(b.b=!0,b.a[0].b=!1,b.a[1].b=!1):mk(b.a[e].a[e])?b=nk(b,1-e):mk(b.a[e].a[1-e])&&(b=(f=1-(1-e),b.a[f]=nk(b.a[f],f),nk(b,1-e))))}else return c;return b}function mk(a){return!!a&&a.b}function nk(a,b){var c,d;c=1-b;d=a.a[c];a.a[c]=d.a[b];d.a[b]=a;a.b=!0;d.b=!1;return d}function ok(){var a=null;this.b=null;!a&&(a=(Wh(),Wh(),Xh));this.a=a}
n(96,218,{3:1,46:1},ok);_.O=function(){return new Hh(this)};_.J=function(){return this.c};_.c=0;t(96);function Fh(a){var b=(pk(),qk),c;c=new Q;kk(a,c,b,a.b,null,!1,null,!1);this.a=new rh(c,0)}n(74,1,{},Fh);_.Q=function(){return this.a.Q()};_.R=function(){return this.a.R()};t(74);function Hh(a){this.a=a}n(98,97,ka,Hh);t(98);function rk(a,b){Bh.call(this,a,b);this.a=E(sk,da,58,2,0);this.b=!0}n(58,49,{48:1,49:1,24:1,58:1},rk);_.b=!1;var sk=t(58);function tk(){}n(188,1,{},tk);
_.tS=function(){return"State: mv\x3d"+this.c+" value\x3d"+this.d+" done\x3d"+this.a+" found\x3d"+this.b};_.a=!1;_.b=!1;_.c=!1;t(188);function pk(){pk=k;qk=new uk("All",0);vk=new wk;xk=new yk;zk=new Ak}function uk(a,b){C.call(this,a,b)}n(29,9,ma,uk);_.kb=function(){return!1};_.lb=function(){return!1};var qk,vk,xk,zk,Bk=u(29,function(){pk();return D(w(Bk,1),ea,29,0,[qk,vk,xk,zk])});function wk(){C.call(this,"Head",1)}n(189,29,ma,wk);_.lb=function(){return!0};u(189,null);
function yk(){C.call(this,"Range",2)}n(190,29,ma,yk);_.kb=function(){return!0};_.lb=function(){return!0};u(190,null);function Ak(){C.call(this,"Tail",3)}n(191,29,ma,Ak);_.kb=function(){return!0};u(191,null);function Ck(a){this.a=new ok;Wg(this,a)}n(90,212,{3:1,25:1},Ck);_.F=function(a){var b=this.a,c=(Te(),Ue);a=new rk(a,c);c=new tk;b.b=lk(b,b.b,a,c);c.b||++b.c;b.b.b=!1;return null==c.d};_.H=function(a){return!!Dh(this.a,a)};_.D=function(){return Gh(new Jh(this.a))};_.J=function(){return this.a.c};
t(90);
function Dk(a){var b;if(!(0<a.a.b)){b=Ek(a.f);!b.length||dk(a.a,b);b=a.a;var c;var d=$doc.title,e=$doc.documentElement,f;c=f="";p==p?f=c=d:e&&(d=e.getElementsByTagName("TITLE"),0<d.length&&(f=c=d[0].textContent));if(f.length){U();if(/ [\|\-] /i.test(f))f=c.replace(RegExp("(.*)[\\|\\-] .*","gi"),"$1"),3>Fk.Bb(f)&&(f=c.replace(RegExp("[^\\|\\-]*[\\|\\-](.*)","gi"),"$1"));else if(-1!=f.indexOf(": "))f=c.replace(RegExp(".*:(.*)","gi"),"$1"),3>Fk.Bb(f)&&(f=c.replace(RegExp("[^:]*[:](.*)","gi"),"$1"));else if(e&&
(150<f.length||15>f.length)){f=e.getElementsByTagName("H1");e="";for(d=0;d<f.length&&!e.length;d++)e=f[d].innerText;f=e;!f.length&&(f=c)}f=Gk(f);4>=Fk.Bb(f)&&(f=c);c=f}else c="";dk(b,c);p==p&&dk(a.a,$doc.title)}}function Hk(a){var b,c;this.b=a;this.a=new gk;this.e=(b={},b[6]=[],b);this.d=(c={},c);b=V();this.f=new Ik(a,this.e);a=V()-b;if(void 0==a)throw new TypeError;this.e[1]=a;this.g=""}n(102,1,{},Hk);t(102);function Jk(){}n(103,1,{},Jk);t(103);
function Kk(a){var b,c,d,e,f,g,l,m,q,v,I,pb,Aa,li,ln,mi,ia,mf,nf,mn,nn;v=V();var on=$doc.documentElement.textContent,pn,qn;U();Fk=(pn=RegExp("[\\u3040-\\uA4CF]","g"),qn=RegExp("[\\uAC00-\\uD7AF]","g"),pn.test(on)?new Lk:qn.test(on)?new Mk:new Nk);m=(li={},li[10]=[],li);c=new Hk($doc.documentElement);var tn=(Dk(c),Kh(c.a,0));if(void 0==tn)throw new TypeError;m[1]=tn;var oi;if(void 0!=a[2]){if(void 0===a[2])throw new TypeError;oi=a[2]}else oi=0;Ok=oi;W("DomDistiller debug level: "+Ok);b=(ln={},ln);
var pi;if(pi=void 0!=a[1]){if(void 0===a[1])throw new TypeError;pi=a[1]}var un=pi,nc,Vd,qi,Wd,Wc,ri,Xd,vn,of,Xc;Wc=V();ri=new Jk;Xd=new Pk;vn=c.b.querySelectorAll('meta[name\x3d"viewport"][content*\x3d"width\x3ddevice-width"]');of=new Qk(Xd);of.i=0<vn.length;var si;var yn=c.b,pf,oc;pf=yn.getElementsByTagName("ARTICLE");oc=Rk(pf);1==oc.b.length?si=(z(0,oc.b.length),oc.b[0]):(pf=yn.querySelectorAll('[itemscope][itemtype*\x3d"Article"],[itemscope][itemtype*\x3d"Posting"]'),oc=Rk(pf),si=0<oc.b.length?
Sk(oc):null);nc=(Xc=si,of.d=!!Xc,Xc?1<=Ok&&W("Extracted article element: "+Xc):Xc=c.b,Tk(new Uk(of),Xc),ri.a=(Vk(Xd,Xd.d),Xd.b),Dk(c),ri);var Bn=V()-Wc;if(void 0==Bn)throw new TypeError;c.e[2]=Bn;Wc=V();var Ba=nc.a,J;var Yd,rf,ta,ui,Yc;Yc=new Q;b:{var Zd;for(Zd=0;Zd<Ba.a.b.length;Zd++)if(r(N(Ba.a,Zd),35)){ta=Zd;break b}ta=Ba.a.b.length}if(ta!=Ba.a.b.length){ui=rf=N(Ba.a,ta).d;Yd=new Wk(Ba.a,ta);for(++ta;ta<Ba.a.b.length;ta++)r(N(Ba.a,ta),35)&&(rf=N(Ba.a,ta).d,rf==ui?Xk(Yd,new Wk(Ba.a,ta)):(Yc.b[Yc.b.length]=
Yd,ui=rf,Yd=new Wk(Ba.a,ta)));Yc.b[Yc.b.length]=Yd}J=new Yk(Yc);var hr=c.a,O;Zk(J,!0,"Start");var ir=($k(),J),wi,qb;for(qb=new M(ir.a);qb.b<qb.d.J();){wi=(y(qb.b<qb.d.J()),qb.d.T(qb.c=qb.b++));var xi;var yi=wi,$d=void 0;14<yi.d?xi=!1:($d=Gk(yi.g),xi=8<=$d.length?al.test($d):1==yi.c?"Comment"===$d:"Shares"===$d?!0:!1);xi&&R(wi.b,"STRICTLY_NOT_CONTENT")}var zi=new bl(hr),tf,rb,Ca;if(zi.a)for(rb=new M(J.a);rb.b<rb.d.J();)tf=(y(rb.b<rb.d.J()),rb.d.T(rb.c=rb.b++)),Ca=tf.g,Ca=zf(Ca),Ca=Af(Ca,"'"),Ca=ug(Ca).toLowerCase(),
S(zi.a,Ca)&&R(tf.b,"de.l3s.boilerpipe/TITLE"),Ca=ug(Ca.replace(cl,"")),S(zi.a,Ca)&&R(tf.b,"de.l3s.boilerpipe/TITLE");var ae,uf,Da,be,ce,Ja,ab;Ja=J.a;if(0==Ja.b.length)O=!1;else{uf=!1;for(Da=0;Da<Ja.b.length;Da++)ce=0==Da?null:(z(Da-1,Ja.b.length),Ja.b[Da-1]),ae=(z(Da,Ja.b.length),Ja.b[Da]),be=Da+1==Ja.b.length?null:(z(Da+1,Ja.b.length),Ja.b[Da+1]),uf|=(0.333333>=ae.c?!ce||0.555556>=ce.c?16>=ae.d?!be||15>=be.d?!ce||4>=ce.d?ab=!1:ab=!0:ab=!0:ab=!0:40>=ae.d?!be||17>=be.d?ab=!1:ab=!0:ab=!0:ab=!1,dl(ae,
ab));O=uf}Zk(J,O,"Classification Complete");var jr=(el(),fl),Ai,Jn,Bi,vf,Kn,wf,sb;Ai=!1;sb=new M(J.a);a:for(;sb.b<sb.d.J();)if(wf=(y(sb.b<sb.d.J()),sb.d.T(sb.c=sb.b++)),wf.a)for(Bi=jr.a,vf=0,Kn=Bi.length;vf<Kn;++vf)if(Jn=Bi[vf],S(wf.b,Jn)){dl(wf,!1);Ai=!0;continue a}O=Ai;Zk(J,O,"Ignore Strictly Not Content blocks");var Ci=gl();Ci.e=0.5;Ci.d=10;O=hl(il(Ci),J);Zk(J,O,"SimilarSiblingContentExpansion: Cross headings");var xf=gl();xf.c=!0;xf.e=0;xf.d=10;O=hl(il(xf),J);Zk(J,O,"SimilarSiblingContentExpansion: Mixed tags");
var yf,tb,On,de,Ea,Di;Di=J.a;if(2>Di.b.length)O=!1;else{yf=!1;de=new rh(Di,0);for(tb=de.R();de.Q();)if(Ea=tb,tb=de.R(),S(Ea.b,"de.l3s.boilerpipe/HEADING")&&!(S(Ea.b,"STRICTLY_NOT_CONTENT")||S(tb.b,"STRICTLY_NOT_CONTENT")||S(Ea.b,"de.l3s.boilerpipe/TITLE")||S(tb.b,"de.l3s.boilerpipe/TITLE")))if(tb.a){yf=!0;On=Ea.a;Xk(Ea,tb);tb=Ea;de.V();var Pn=Ea;S(Pn.b,"de.l3s.boilerpipe/HEADING")&&Pn.b.a.c.ib("de.l3s.boilerpipe/HEADING");On||R(Ea.b,"BOILERPLATE_HEADING_FUSED")}else Ea.a&&(yf=!0,dl(Ea,!1));O=yf}Zk(J,
O,"HeadingFusion");O=jl((kl(),ll),J);Zk(J,O,"BlockProximityFusion: Distance 1");var kr=(ml(),nl),Ei,bb,Fi,Vn;Vn=J.a;Ei=!1;for(bb=new M(Vn);bb.b<bb.d.J();)Fi=(y(bb.b<bb.d.J()),bb.d.T(bb.c=bb.b++)),Fi.a||null!=kr.a&&S(Fi.b,"de.l3s.boilerpipe/TITLE")||(qh(bb),Ei=!0);O=Ei;Zk(J,O,"BlockFilter");O=jl(ol,J);Zk(J,O,"BlockProximityFusion: Same level content-only");var lr=(pl(),ql),Gi,ub,ee,Hi,Ii,Ka,vb,wb,Zc;Zc=J.a;if(2>Zc.b.length)O=!1;else{Hi=-1;ub=null;Gi=0;ee=-1;for(wb=new M(Zc);wb.b<wb.d.J();)Ka=(y(wb.b<
wb.d.J()),wb.d.T(wb.c=wb.b++)),Ka.a&&(Ii=Ka.d,Ii>Hi&&(ub=Ka,Hi=Ii,ee=Gi)),++Gi;for(vb=new M(Zc);vb.b<vb.d.J();)Ka=(y(vb.b<vb.d.J()),vb.d.T(vb.c=vb.b++)),Ka==ub?(dl(Ka,!0),R(Ka.b,"de.l3s.boilerpipe/VERY_LIKELY_CONTENT")):(dl(Ka,!1),R(Ka.b,"de.l3s.boilerpipe/MIGHT_BE_CONTENT"));if(lr.a&&-1!=ee){var mr=ee,xb,Zn,Ji,Ki;Ki=B(rl(N(ub.j,N(ub.i,ub.i.b.length-1).a)));for(Ji=new rh(Zc,mr+1);Ji.Q();)xb=Ji.R(),Zn=B(sl(N(xb.j,N(xb.i,0).a))),B(Ki)==B(Zn)&&(dl(xb,!0),R(xb.b,"SIBLING_OF_MAIN_CONTENT"),Ki=B(rl(N(xb.j,
N(xb.i,xb.i.b.length-1).a))));var nr=ee,yb,$n,Li,$c;Li=B(sl(N(ub.j,N(ub.i,0).a)));for($c=new rh(Zc,nr);0<$c.b;)yb=(y(0<$c.b),N($c.a,$c.c=--$c.b)),$n=B(rl(N(yb.j,N(yb.i,yb.i.b.length-1).a))),B(Li)==B($n)&&(dl(yb,!0),R(yb.b,"SIBLING_OF_MAIN_CONTENT"),Li=B(sl(N(yb.j,N(yb.i,0).a))))}O=!0}Zk(J,O,"Keep Largest Block");var Bf,pc,Cf,ad,zb,Ab,fe;Cf=0;pc=fe=-1;for(Ab=new M(J.a);Ab.b<Ab.d.J();)ad=(y(Ab.b<Ab.d.J()),Ab.d.T(Ab.c=Ab.b++)),-1==pc&&S(ad.b,"de.l3s.boilerpipe/TITLE")&&(fe=Cf,pc=-1),-1==pc&&ad.a&&(pc=
Cf),++Cf;if(pc<=fe||-1==fe)O=!1;else{Bf=!1;for(zb=new M(new th(J.a,fe,pc));zb.b<zb.d.J();)ad=(y(zb.b<zb.d.J()),zb.d.T(zb.c=zb.b++)),S(ad.b,"de.l3s.boilerpipe/MIGHT_BE_CONTENT")&&(Bf|=dl(ad,!0));O=Bf}Zk(J,O,"Expand Title to Content");var Mi,Df,cb,Bb,Cb;Mi=!1;Df=-1;for(Cb=new M(J.a);Cb.b<Cb.d.J();)if(cb=(y(Cb.b<Cb.d.J()),Cb.d.T(Cb.c=Cb.b++)),cb.a&&S(cb.b,"de.l3s.boilerpipe/VERY_LIKELY_CONTENT")){Df=cb.f;break}if(-1==Df)O=!1;else{for(Bb=new M(J.a);Bb.b<Bb.d.J();)cb=(y(Bb.b<Bb.d.J()),Bb.d.T(Bb.c=Bb.b++)),
!cb.a&&100<=cb.d&&cb.f==Df&&(dl(cb,!0),Mi=!0);O=Mi}Zk(J,O,"Largest Block Same Tag Level -\x3e Content");var Ni,Ef,db,Db;Ni=!1;Ef=aa;for(Db=new M(J.a);Db.b<Db.d.J();)db=(y(Db.b<Db.d.J()),Db.d.T(Db.c=Db.b++)),db.a&&S(db.b,"de.l3s.boilerpipe/VERY_LIKELY_CONTENT")?Ef=db.f:db.f>Ef&&S(db.b,"de.l3s.boilerpipe/MIGHT_BE_CONTENT")&&S(db.b,"de.l3s.boilerpipe/LI")&&0==db.c?(dl(db,!0),Ni=!0):Ef=aa;O=Ni;Zk(J,O,"List at end filter");var or=c.d,Oi,Ff,Pi,Eb;Ff=0;for(Eb=new M(J.a);Eb.b<Eb.d.J();)Pi=(y(Eb.b<Eb.d.J()),
Eb.d.T(Eb.c=Eb.b++)),Pi.a&&(Ff+=Pi.d);Oi=Ff;if(void 0==Oi)throw new TypeError;or[1]=Oi;var pr,Fb;for(Fb=new M(J.a);Fb.b<Fb.d.J();){var Gf=pr=(y(Fb.b<Fb.d.J()),Fb.d.T(Fb.c=Fb.b++)),ao=void 0,Gb=void 0,Qi=void 0;if(Gf.a)for(Gb=new M(Gf.i);Gb.b<Gb.d.J();)ao=(y(Gb.b<Gb.d.J()),Gb.d.T(Gb.c=Gb.b++)),Qi=N(Gf.j,ao.a),Qi.p=!0,S(Gf.b,"de.l3s.boilerpipe/TITLE")&&R(Qi.e,"de.l3s.boilerpipe/TITLE")}var Hf,Hb,If;If=!1;for(Hb=new M(nc.a.a);Hb.b<Hb.d.J();)Hf=(y(Hb.b<Hb.d.J()),Hb.d.T(Hb.c=Hb.b++)),Hf.p?If=!0:r(Hf,35)?
If=!1:If&&(Hf.p=!0);var bo=nc.a,Jf,La,Ib,Jb,bd,co,Kf;Jf=new Q;Kf=bd=null;for(Jb=new M(bo.a);Jb.b<Jb.d.J();)La=(y(Jb.b<Jb.d.J()),Jb.d.T(Jb.c=Jb.b++)),r(La,35)&&La.p&&(!bd&&(bd=La),Kf=La);if(Kf){for(Ib=new M(bo.a);Ib.b<Ib.d.J()&&!(La=(y(Ib.b<Ib.d.J()),Ib.d.T(Ib.c=Ib.b++)),(co=r(La,32))&&La.p||La==Kf);)co&&P(Jf,La);var ge,Ri,Si,he,eo,Lf,Kb,cd;if(0!=Jf.b.length){Si=null;bd&&(Si=N(bd.a,bd.c));eo=(cd=new Q,P(cd,new tl),P(cd,new ul),P(cd,new vl(Si)),P(cd,new wl),cd);ge=null;Ri=0;for(Kb=new M(Jf);Kb.b<Kb.d.J();){Lf=
(y(Kb.b<Kb.d.J()),Kb.d.T(Kb.c=Kb.b++));var Mf=void 0,jo=void 0,Lb=void 0,ie=void 0;if(Lf){ie=0;Mf=Lf.d;for(Lb=new M(eo);Lb.b<Lb.d.J();)jo=(y(Lb.b<Lb.d.J()),Lb.d.T(Lb.c=Lb.b++)),ie+=jo.Gb(Mf);2>Ok||(Mf?W("FINAL SCORE: "+ie+" : "+A(Mf,"src")):W("Null image attempting to be scored!"));he=ie}else he=0;26<=he&&(!ge||Ri<he)&&(ge=Lf,Ri=he)}ge&&(ge.p=!0)}}var qr=nc.a,Nf,Mb,Ma,je,Ti,Ui,ko,ke;Ma=!1;Ti=-1;je=new jk;for(Mb=new M(qr.a);Mb.b<Mb.d.J();)Nf=(y(Mb.b<Mb.d.J()),Mb.d.T(Mb.c=Mb.b++)),r(Nf,51)?(ke=Nf,ke.b==
(xl(),yl)?(ke.p=Ma,P(je.a,ke),Ma=!1):(Ui=ik(je),(Ma|=Ti>=je.a.b.length)&&(Ti=je.a.b.length-1),ko=Ui.p,Ui.p=Ma,ke.p=Ma,Ma=ko)):Ma||(Ma=Nf.p);var lo=V()-Wc;if(void 0==lo)throw new TypeError;c.e[3]=lo;Wc=V();var Vi,Nb,ed;ed=new Tg;for(Nb=new M(nc.a.a);Nb.b<Nb.d.J();)if(Vi=(y(Nb.b<Nb.d.J()),Nb.d.T(Nb.c=Nb.b++)),Vi.p){var rr=Vi.Eb(un);ed.a+=rr;un&&(ed.a+="\n")}qi=ed.a;var mo=V()-Wc;if(void 0==mo)throw new TypeError;c.e[4]=mo;var sr=nc.a,Na,Ob,Of,Pf;Of=new Q;for(Ob=new M(sr.a);Ob.b<Ob.d.J();)if(Na=(y(Ob.b<
Ob.d.J()),Ob.d.T(Ob.c=Ob.b++)),Na.p)if(r(Na,32))Ph(Of,(!Na.b&&zl(Na),Pf=new Q,!Na.e.length||P(Pf,Na.e),Ph(Pf,Al(Na.b)),Pf));else if(r(Na,68)){var tr=Of,Qf=Na,Rf=void 0,Sf=void 0,Tf=void 0,Xi=void 0;!Qf.a&&(Qf.a=Bl(Cl(Qf.b)));Tf=new Q;Xi=Qf.a.querySelectorAll("IMG, SOURCE");for(Rf=0;Rf<Xi.length;Rf++)Sf=Xi[Rf],!Sf.src.length||P(Tf,Sf.src),Ph(Tf,Al(Sf));Ph(tr,Tf)}c.c=Of;if(4<=Ok){for(Wd=0;Wd<c.e[6].length;Wd++){var oo=c.e;if(Wd>=oo[6].length)throw new RangeError;Vd=oo[6][Wd];if(void 0===Vd[1])throw new TypeError;
var ur="Timing: "+Vd[1]+" \x3d ";if(void 0===Vd[2])throw new TypeError;W(ur+Vd[2])}var po=c.e;if(void 0===po[1])throw new TypeError;var vr="Timing: MarkupParsingTime \x3d "+po[1]+"\nTiming: DocumentConstructionTime \x3d ",qo=c.e;if(void 0===qo[2])throw new TypeError;var wr=vr+qo[2]+"\nTiming: ArticleProcessingTime \x3d ",ro=c.e;if(void 0===ro[3])throw new TypeError;var xr=wr+ro[3]+"\nTiming: FormattingTime \x3d ",so=c.e;if(void 0===so[4])throw new TypeError;W(xr+so[4])}if(void 0==qi)throw new TypeError;
b[1]=qi;if(void 0==b)throw new TypeError;m[2]=b;var to=((null==c.g||!c.g.length)&&(c.g="auto"),c.g);if(void 0==to)throw new TypeError;m[9]=to;for(Aa=new M(c.c);Aa.b<Aa.d.J();){pb=(y(Aa.b<Aa.d.J()),Aa.d.T(Aa.c=Aa.b++));var yr=(mi={},m[10].push(mi),mi);if(void 0==pb)throw new TypeError;yr[1]=pb}var $i;if(void 0!=a[3]){if(void 0===a[3])throw new TypeError;$i=a[3]}else $i=$doc.URL;g=$i;I=c.e;q=V();var aj;if(void 0!=a[4]){if(void 0===a[4])throw new TypeError;aj=a[4]}else aj="next";if("pagenum"===aj){Dl();
ia=new El(I);var bj;var wo=$doc.documentElement,cj,dj,fd,Uf,Vf,xo,Wf;Wf=V();ia.b=g.replace(Fl,"");ia.d=Gl(ia.b);if(ia.d){dj=Hl(Il(wo,g));cj=wo.getElementsByTagName("A");for(fd=0;fd<cj.length;)Vf=cj[fd],(xo=Jl(ia,Vf,dj))?(Kl(ia.a),Ll(ia,Vf,!1,!0,null),Ml(ia.a,xo.a),ia.c=0,Ll(ia,Vf,!1,!1,dj),fd+=1+ia.c):++fd;var me=ia.a;0!=me.a.b.length&&0==N(me.a,me.a.b.length-1).b.b.length&&me.a.U(me.a.b.length-1);Nl(Wf,ia.e,"PageParameterParser");Wf=V();var zr=ia.a,Ao=ia.b,hd,qc,Zf,Pb,$f,ag;if($f=Gl(Ao)){$f.d.username=
"";$f.d.password="";qc=new Ol;for(Pb=new M(zr.a);Pb.b<Pb.d.J();)if(Zf=(y(Pb.b<Pb.d.J()),Pb.d.T(Pb.c=Pb.b++)),!(2>Zf.b.b.length)){for(var T=Zf.b,Ar=0>Zf.a,bg=$f,Br=qc.a?qc.a.d:"",id=void 0,Bo=void 0,Qb=void 0,id=0,Qb=new M(T);Qb.b<Qb.d.J();)Bo=(y(Qb.b<Qb.d.J()),Qb.d.T(Qb.c=Qb.b++)),!Bo.b.length||++id;if(0==id)ag=null;else{if(Ar)for(var jd=void 0,kd=void 0,Co=void 0,kd=0,jd=T.b.length-1;kd<jd;++kd,--jd)Co=(z(kd,T.b.length),T.b[kd]),Sh(T,kd,(z(jd,T.b.length),T.b[jd])),Sh(T,jd,Co);2==T.b.length&&1==id&&
1==(z(0,T.b.length),T.b[0]).a&&2==(z(1,T.b.length),T.b[1]).a&&(lf((z(0,T.b.length),T.b[0]).b)?Sh(T,0,new Pl(1,Va(bg.d))):Sh(T,1,new Pl(2,Va(bg.d))),++id);var cg=void 0;if(2<=id){for(var rc=void 0,ij=void 0,ld=void 0,dg=void 0,jj=void 0,Rb=void 0,sc=void 0,md=void 0,Sb=void 0,ne=void 0,Pa=void 0,eg=void 0,Do=void 0,fg=void 0,oe=void 0,Eo=void 0,Tb=void 0,pe=void 0,pe=0,Tb=new M(T);Tb.b<Tb.d.J();)Eo=(y(Tb.b<Tb.d.J()),Tb.d.T(Tb.c=Tb.b++)),Eo.a==pe+1&&++pe;if(28<=pe&&31>=pe)cg=null;else{jj="";ne=new Ql;
eg=E(Rl,da,69,T.b.length,0);for(sc=0;sc<T.b.length;sc++)if(Sb=(z(sc,T.b.length),T.b[sc]),Sb.b.length&&(oe=Gl(Sb.b),eg[sc]=oe)){oe.d.username="";oe.d.password="";var Ub=oe,Dr=Sb.a,Er=sc,Fr=ne,qe=void 0,kj=void 0,re=void 0,gg=void 0,hg=void 0,nd=void 0,ig=void 0,jg=void 0;if(null==Ub.b)if(jg=Ub.d.search,jg.length)for(hg=(U(),lg(jg.substr(1,jg.length-1),"\\\x26")),Ub.b=Me([hg.length,2]),nd=0;nd<hg.length;nd++)ig=lg(hg[nd],"\x3d"),Ub.b[nd][0]=ig[0],Ub.b[nd][1]=1<ig.length?ig[1]:"";else Ub.b=Me([0,2]);
gg=Ub.b;if(0!=gg.length)for(qe=0;qe<gg.length;qe++){kj=gg[qe];try{re=new Sl(Ub,0==qe,kj[0],kj[1])}catch(kg){if(kg=Cc(kg),r(kg,23))re=null;else throw Dc(kg);}re&&Tl(Fr,re,new Ul(Dr,re.a,Er))}1==Sb.a&&(jj=Sb.b)}if(0==ne.a.b)for(Rb=0;Rb<T.b.length;Rb++)if(Sb=(z(Rb,T.b.length),T.b[Rb]),eg[Rb]){var tc=eg[Rb],Gr=Sb.a,Hr=Rb,Ir=ne,mj=void 0,nj=void 0,Io=void 0,oj=void 0,pj=void 0,se=void 0,Jo=void 0,oj=(null==tc.c&&(tc.c=Vl(tc.d)),tc.c);if(oj.length&&Wl(oj))for(Jo=Va(tc.d),pj=tc.d.origin.length,!Xl&&(Xl=
RegExp("(\\d+)","gi")),Xl.lastIndex=pj;;){mj=Xl.exec(Jo);if(!mj)break;nj=Xl.lastIndex;Io=nj-mj[1].length;try{se=new Yl(tc,pj,Io,nj)}catch(mg){if(mg=Cc(mg),r(mg,23))se=null;else throw Dc(mg);}se&&Tl(Ir,se,new Ul(Gr,se.a,Hr))}}fg=new Ol;for(ld=new mh((new lh(ne.a)).a);nh(ld);){if(ld._gwt_modCount!=ld.c._gwt_modCount)throw new ph;ij=(y(nh(ld)),ld.a.R());Do=ij.W();md=ij.X();if(!(Do===Br||100<md.a.b.length)&&md.b.Ab(bg)){e:{var qj=md.b,uc=md.a,Vb=T,rj=jj,eb=void 0,sj=void 0,ue=void 0,Mo=void 0,tj=void 0,
Wb=void 0,Qa=void 0,No=void 0,ve=void 0,uj=void 0;if(2<=uc.b.length)if(ve=Zl(uc,Vb),ve.a&&ve.b&&$l(Vb,ve)){Mo=am(uc);eb=new Q;for(Wb=new M(uc);Wb.b<Wb.d.J();)tj=(y(Wb.b<Wb.d.J()),Wb.d.T(Wb.c=Wb.b++)),P(eb,new Pl(tj.a,N(Vb,tj.c).b));Pa=new bm((cm(),dm),qj.tS(),eb,Mo,ve.c)}else Pa=null;else{if(1==uc.b.length&&rj.length&&(Qa=(z(0,uc.b.length),uc.b[0]),No=2==Qa.a&&1==Qa.c,uj=3==Qa.a&&2==Qa.c&&2==(z(1,Vb.b.length),Vb.b[1]).a,1==(z(0,Vb.b.length),Vb.b[0]).a&&(No||uj)&&qj.zb(rj))){ue=Qa.b-Qa.a;0==ue||1==
ue?sj=1:(sj=Qa.b,ue=0);eb=new Q;P(eb,new Pl(1,rj));P(eb,new Pl(Qa.a,N(Vb,Qa.c).b));Pa=new bm((cm(),dm),qj.tS(),eb,new em(sj,ue),uj?(z(1,eb.b.length),eb.b[1]).b:"");break e}Pa=null}}if(Pa){var rc=(!fm&&(fm=/\/$/),bg.d.href.replace(fm,"")),we;e:{var pd=Pa,yj=rc,Mr=T,qd=void 0,ng=void 0,Xb=void 0;if(2>pd.a.b.length||1==N(pd.a,0).a||yj.length>=N(pd.a,0).b.length)we=!1;else{for(qd=0;qd<pd.a.b.length;qd++){var zj;(zj=N(pd.a,qd).a!=qd+2)||(zj=N(pd.a,qd).b===yj);if(zj){we=!1;break e}}for(Xb=new M(Mr);Xb.b<
Xb.d.J();)if(ng=(y(Xb.b<Xb.d.J()),Xb.d.T(Xb.c=Xb.b++)),1==ng.a&&ng.b.length&&ng.b!==yj){we=!1;break e}we=!0}}we?uh(Pa.a,0,new Pl(1,rc)):md.b.zb(rc)&&(dg=N(Pa.a,0),2==dg.a&&dg.b!==rc&&rc.length<dg.b.length&&uh(Pa.a,0,new Pl(1,rc)));gm(fg,new hm(Pa))}}}cg=fg.a?fg:null}}else cg=null;ag=cg}ag&&gm(qc,ag)}if(qc.a){qc.b&&3<=Ok&&W("Detected multiple page patterns");hd=qc.a;var Aj,Bj,Yb;if(!hd.c.length&&0!=hd.a.b.length)for(Aj=!1,Yb=new M(hd.a);Yb.b<Yb.d.J();){Bj=(y(Yb.b<Yb.d.J()),Yb.d.T(Yb.c=Yb.b++));if(Aj){hd.c=
Bj.b;break}Bj.b===Ao&&(Aj=!0)}Uf=hd}else Uf=new im}else Uf=new im;Nl(Wf,ia.e,"PageParameterDetector");bj=Uf}else bj=new im;l=bj;e={};f=l.c;if(f.length){if(void 0==f)throw new TypeError;e[1]=f}if(void 0==e)throw new TypeError;m[3]=e;3<=Ok&&W("paging by pagenum: "+jm(l))}else{3<=Ok&&W("paging by next");km();mf={};var Ro=$doc.documentElement,wc,Cj,Dj,Ej,Fj,fb,Gj,xe,K,Zb,ja,Hj,x,$b,rd,qg,ye,Ij,sd,td,ud,rg,sg,So,gb,Jj,To,Uo;3<=Ok&&hh(lm);fb=(U(),g.replace(RegExp("\\/[^/]*$","gi"),""));To=g.replace(RegExp("\\/$",
"gi"),"");wc=Ro.getElementsByTagName("A");sg=new Zi;Dj=new Zi;Ej=Hl(Il(Ro,g));var Nr=lg(g,":\\/\\/")[0]+"://",Vo,ze=g,ze=(U(),lg(ze,":\\/\\/"))[1];Vo=-1==ze.indexOf("/")?ze:lg(ze,"\\/")[0];Cj=Nr+Vo+"/";var Or="^"+Cj.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$\x26")+".*\\d";So=RegExp(Or,"i");for(xe=0;xe<wc.length;xe++)if(K=wc[xe],Uo=A(K,"href"),Ej.setAttribute("href",Uo),ja=Ej.href,So.test(ja))if(Jj=(K.offsetWidth||0)|0,Gj=(K.offsetHeight||0)|0,0==Jj||0==Gj)X(K,"ignored: sz\x3d"+Jj+"x"+Gj);else if(mm(K))if(ja=
ja.replace(nm,""),X(K,"-\x3e "+ja),F(ja,To)||F(ja,fb))X(K,"ignored: same as current or folder url "+fb);else if($b=K.innerText,25<$b.length)X(K,"ignored: link text too long");else if(om.test($b))X(K,"ignored: one of extra"),R(Dj,ja);else if(Hj=ja,ja.substr(0,fb.length)===fb&&(Hj=pg(ja,fb.length)),pm.test(Hj)){x=new qm(xe,$b,ja);R(sg,x);0!=ja.indexOf(fb)&&(x.d-=25,X(K,"score\x3d"+x.d+": not part of folder url "+fb));Zb=$b+" "+A(K,"class")+" "+K.id;X(K,"txt+class+id\x3d"+Zb);rm.test(Zb)&&(x.d+=50,X(K,
"score\x3d"+x.d+": has next"));sm.test(Zb)&&(x.d+=25,X(K,"score\x3d"+x.d+": has pag* word"));tm.test(Zb)&&!rm.test(x.c)&&(x.d-=65,X(K,"score\x3d"+x.d+": has first|last but no next regex"));if(um.test(Zb)||om.test(Zb))x.d-=50,X(K,"score\x3d"+x.d+": has neg or extra regex");vm.test(Zb)&&(x.d-=200,X(K,"score\x3d"+x.d+": has opp of next regex"));qg=rg=!1;for(td=B(K);td&&(!rg||!qg);)ud=A(td,"class")+" "+td.id,!rg&&sm.test(ud)&&(x.d+=25,rg=!0,X(K,"score\x3d"+x.d+": posParent - "+ud)),qg||!um.test(ud)||
wm.test(ud)||(x.d-=25,qg=!0,X(K,"score\x3d"+x.d+": negParent - "+ud)),td=B(td);if(xm.test(ja)||sm.test(ja))x.d+=25,X(K,"score\x3d"+x.d+": has paging info");om.test(ja)&&(x.d-=15,X(K,"score\x3d"+x.d+": has extra regex"));10<$b.length&&(x.d-=$b.length,X(K,"score\x3d"+x.d+": text too long"));rd=ym($b);0<rd&&(1==rd?x.d-=10:x.d+=0>10-rd?0:10-rd,X(K,"score\x3d"+x.d+": linktxt is a num ("+rd+")"));for(var hb=g,ib=ja,cp=K,Pr=Cj.length,xc=void 0,vg=void 0,wg=void 0,hb=zm(hb),ib=zm(ib),xc=Pr;xc<hf(hb.length,
ib.length)&&hb.charCodeAt(xc)==ib.charCodeAt(xc);xc++);hb=tg(hb,xc,hb.length);ib=tg(ib,xc,ib.length);X(cp,"remains: "+hb+", "+ib);vg=ym(ib);wg=ym(hb);X(cp,"remains: "+wg+", "+vg);(Fj=0<wg&&0<vg?df(vg-wg):null)&&1==Fj.a&&(x.d+=25,X(K,"score\x3d"+x.d+": diff \x3d "+Fj))}else X(K,"ignored: no number beyond folder url "+fb);else X(K,"ignored: invisible");else X(K,"ignored: not prefix + num");gb=null;if(0!=sg.a.b)for(Ij=vh(new xh(sg.a));nh(Ij.a);)ye=oh(Ij.a).W(),S(Dj,ye.a)||50<=ye.d&&(!gb||gb.d<ye.d)&&
(gb=ye);sd=null;if(gb){var Qr=gb.a;U();sd=Qr.replace(RegExp("\\/$","gi"),"");X(wc[gb.b],"found: score\x3d"+gb.d+", txt\x3d["+gb.c+"], "+sd)}if(3<=Ok){var Be,xg,ac,Ce,yg;W("numLinks\x3d"+wc.length+", found next: "+(null!=sd?sd:"null"));for(Be=0;Be<wc.length;Be++){xg=wc[Be];ac=xg.innerText;yg=(U(),lg(ac,"\\s+"));ac="";for(Ce=0;Ce<yg.length;Ce++)ac+=yg[Ce],Ce<yg.length-1&&(ac+=" ");W(Be+")"+xg.href+", txt\x3d["+ac+"], dbg\x3d["+eh(lm,xg)+"]")}}nf=sd;if(null!=nf){if(void 0==nf)throw new TypeError;mf[1]=
nf}if(void 0==mf)throw new TypeError;m[3]=mf}Nl(q,I,"Pagination");var fa=c.f,yc,bc,zg,Ag,zc,Ac,Mj,wa,Nj,Oj,Pj;wa=(Nj={},Nj[9]=[],Nj);var Bg,Cg;Cg=!1;for(Bg=0;Bg<fa.a.b.length&&!Cg;Bg++)Cg=N(fa.a,Bg).xb();if(!Cg){var ep=Ek(fa);if(void 0==ep)throw new TypeError;wa[1]=ep;var Qj,Dg,Eg;Eg="";for(Dg=0;Dg<fa.a.b.length&&!Eg.length;Dg++)Eg=N(fa.a,Dg).vb();Qj=Eg;if(void 0==Qj)throw new TypeError;wa[2]=Qj;var Rj,Fg,Gg;Gg="";for(Fg=0;Fg<fa.a.b.length&&!Gg.length;Fg++)Gg=N(fa.a,Fg).wb();Rj=Gg;if(void 0==Rj)throw new TypeError;
wa[3]=Rj;var Sj,Hg,Ig;Hg="";for(Ig=0;Ig<fa.a.b.length&&!Hg.length;Ig++)Hg=N(fa.a,Ig).rb();Sj=Hg;if(void 0==Sj)throw new TypeError;wa[4]=Sj;var Tj,Jg,Kg;Kg="";for(Jg=0;Jg<fa.a.b.length&&!Kg.length;Jg++)Kg=N(fa.a,Jg).tb();Tj=Kg;if(void 0==Tj)throw new TypeError;wa[5]=Tj;var Uj,Lg,Mg;Lg="";for(Mg=0;Mg<fa.a.b.length&&!Lg.length;Mg++)Lg=N(fa.a,Mg).qb();Uj=Lg;if(void 0==Uj)throw new TypeError;wa[6]=Uj;var Vj,Ng,Og;Ng="";for(Og=0;Og<fa.a.b.length&&!Ng.length;Og++)Ng=N(fa.a,Og).pb();Vj=Ng;if(void 0==Vj)throw new TypeError;
wa[7]=Vj;var Pg,Qg;Pg=null;for(Qg=0;Qg<fa.a.b.length&&!Pg;Qg++)Pg=N(fa.a,Qg).ob();if(yc=Pg){bc=(Oj={},Oj[5]=[],Oj);var fp=yc.d;if(void 0==fp)throw new TypeError;bc[1]=fp;var gp=yc.c;if(void 0==gp)throw new TypeError;bc[2]=gp;var hp=yc.b;if(void 0==hp)throw new TypeError;bc[3]=hp;var ip=yc.e;if(void 0==ip)throw new TypeError;bc[4]=ip;for(Ag=0;Ag<yc.a.length;Ag++)bc[5].push(yc.a[Ag]);if(void 0==bc)throw new TypeError;wa[8]=bc}var Rg,Sg;Sg=null;for(Rg=0;Rg<fa.a.b.length&&!(Sg=N(fa.a,Rg).sb(),0<Sg.length);Rg++);
Mj=Sg;for(zg=0;zg<Mj.length;zg++){zc=Mj[zg];Ac=(Pj={},wa[9].push(Pj),Pj);var jp=zc.e;if(void 0==jp)throw new TypeError;Ac[1]=jp;var kp=zc.c;if(void 0==kp)throw new TypeError;Ac[2]=kp;var lp=zc.d;if(void 0==lp)throw new TypeError;Ac[3]=lp;var mp=zc.a;if(void 0==mp)throw new TypeError;Ac[4]=mp;var np=zc.f;if(void 0==np)throw new TypeError;Ac[5]=np;var op=zc.b;if(void 0==op)throw new TypeError;Ac[6]=op}}if(void 0==wa)throw new TypeError;m[5]=wa;var pp=V()-v;if(void 0==pp)throw new TypeError;I[5]=pp;
if(void 0==I)throw new TypeError;m[6]=I;var qp=c.d;if(void 0==qp)throw new TypeError;m[8]=qp;d=(mn={},mn);var rp=(nn=Am,Am="",nn);if(void 0==rp)throw new TypeError;d[1]=rp;if(void 0==d)throw new TypeError;m[7]=d;return m}n(207,1,{},function(){});t(207);
function Bl(a){var b;if(0==a.b.length)return null;b=new Bm(a);var c=(z(0,a.b.length),a.b[0]),d;for(d=c.parentNode;d&&9!=d.nodeType;c=d,d=d.parentNode);Tk(new Uk(b),c);b=b.c;for(a=(z(0,a.b.length),a.b[0]);1==b.a.b&&b.b!=a&&3!=Kh(b.a,0).b.nodeType;)b=Kh(b.a,0);a=Cm(b);if(1!=a.nodeType)return null;Dm(a,"ID",D(w(p,1),h,2,4,["*"]));Em(a);Dm(a,"TARGET",D(w(p,1),h,2,4,["A"]));Dm(a,"COLOR",D(w(p,1),h,2,4,["FONT"]));Dm(a,"BGCOLOR",D(w(p,1),h,2,4,["TABLE","TR","TD","TH"]));Dm(a,"STYLE",D(w(p,1),h,2,4,["*"]));
1==a.nodeType&&"IMG"===a.tagName&&Fm(a);c=a.querySelectorAll("IMG");for(b=0;b<c.length;b++)Fm(c[b]);return a}function Al(a){var b,c;c=new Q;a.hasAttribute("srcset")&&Ph(c,Gm(a));a=a.querySelectorAll("[SRCSET]");for(b=0;b<a.length;b++)Ph(c,Gm(a[b]));return c}function Hm(a){return a?((a.offsetHeight||0)|0)*((a.offsetWidth||0)|0):0}function Im(a,b){var c;c=a.getElementsByTagName(b);return 0<c.length?c[0]:null}function Jm(a,b){var c;for(c=a;c&&!c.contains(b);)c=c.parentNode;return c}
function Sk(a){var b,c;if(0==a.J())return null;c=a.T(0);for(b=1;b<a.J();b++)c=Jm(c,a.T(b));return c}function Cl(a){var b;b=new Q;Tk(new Uk(new Km(b)),a);return b}function Lm(a){var b;for(b=new Q;a;)b.b[b.b.length]=a,a=a.parentNode;return b}function Gm(a){var b,c,d;c=new Q;a=A(a,"srcset");if(!a.length)return c;d=Mm(a);for(a=0;a<d.length;a++)b=Gk(d[a]),b.length&&(b=lg(b," "),P(c,b[0]));return c}function Nm(a){var b;$doc.body.appendChild(a);b=a.innerText;$doc.body.removeChild(a);return b}
function V(){return"undefined"!==typeof distiller_on_ios&&distiller_on_ios||!window.performance?Date.now():window.performance.now()}function Rk(a){var b,c,d;d=new Q;for(c=0;c<a.length;c++)b=a[c],mm(b)&&(b.offsetParent||0!=((b.offsetHeight||0)|0)||0!=((b.offsetWidth||0)|0))&&0<Hm(b)&&(d.b[d.b.length]=b);return d}function Om(a,b){var c;if(null==a)return!1;c=$doc.createElement("a");c.href=a;return kf("."+Sc(c,"host"),"."+b)}
function mm(a){var b;b=getComputedStyle(a,null);a=parseFloat(b.opacity);return!("none"===b.display||"hidden"===b.visibility||0==a)}function Em(a){var b,c,d;"A"===a.tagName&&(d=a,d.href.length&&(d.href=d.href));b=a.getElementsByTagName("A");for(c=0;c<b.length;c++)d=b[c],d.href.length&&(d.href=d.href);"VIDEO"===a.tagName&&(c=a,c.poster.length&&(c.poster=c.poster));d=a.getElementsByTagName("VIDEO");for(b=0;b<d.length;b++)c=d[b],c.poster.length&&(c.poster=c.poster);Pm(a);Qm(a)}
function Pm(a){("IMG"==a.tagName||"SOURCE"==a.tagName||"TRACK"==a.tagName||"VIDEO"==a.tagName)&&a.src&&(a.src=a.src);a=a.querySelectorAll("img,source,track,video");for(var b in a)a[b].src&&(a[b].src=a[b].src)}function Qm(a){var b;a.hasAttribute("srcset")&&Rm(a);a=a.querySelectorAll("[SRCSET]");for(b=0;b<a.length;b++)Rm(a[b])}
function Rm(a){var b,c,d,e;d=A(a,"srcset");if(d.length){c=$doc.createElement("img");e=Mm(d);for(d=0;d<e.length;d++)b=Gk(e[d]),b.length&&(b=lg(b," "),c.src=b[0],b[0]=c.src,e[d]=Sm(b," "));c=Sm(e,", ");a.setAttribute("srcset",c)}else a.removeAttribute("srcset")}
function Tm(a){var b,c,d,e;if(null==a||!a.length)return new Yi;e=new Yi;a=lg(a,"\x26");for(c=0;c<a.length;c++);c=0;for(d=a.length;c<d;++c)if(b=a[c],b=lg(b,"\x3d"),1<b.length){var f=e,g=b[0];if(null==b[1])throw new jf("encodedURL cannot be null");L(f,g,decodeURI(b[1]))}return e}function Dm(a,b,c){var d,e,f;e=0;for(f=c.length;e<f;++e)d=c[e],a.tagName!==d&&"*"!==d||a.removeAttribute(b);d=0;for(e=c.length;d<e;++d);c=Sm(c,", ");c=a.querySelectorAll(c);for(a=0;a<c.length;a++)c[a].removeAttribute(b)}
function Fm(a){var b,c,d;b=a.attributes;for(c=0;c<b.length;)d=b[c].nodeName,"src"===d||"alt"===d||"srcset"===d||"dir"===d||"width"===d||"height"===d||"title"===d?++c:a.removeAttribute(d)}function Km(a){this.a=a}n(105,1,{},Km);_.mb=function(){};_.nb=function(a){switch(a.nodeType){case 3:return P(this.a,a),!1;case 1:if(!mm(a))return!1;P(this.a,a);return!0;default:return!1}};t(105);
function Tk(a,b){var c,d;if(a.a.nb(b)){if(d=b.firstChild)for(;d!=b;){c=!1;if(a.a.nb(d)){if(c=d.firstChild){d=c;continue}c=!0}for(;d!=b;){c&&a.a.mb(d);if(c=d.nextSibling){d=c;break}d=d.parentNode;c=!0}}a.a.mb(b)}}function Uk(a){this.a=a}n(61,1,{},Uk);t(61);function Um(a){var b;a.b="";(b=a.j.querySelector(".byline-name"))&&(a.b=b.textContent)}function Vm(a){this.j=a}n(121,1,{},Vm);
_.ob=function(){var a,b;a=new Wm;if(null==this.d){var c;!this.a&&(this.a=this.j.getElementsByTagName("META"));this.d="";if(b=this.j.querySelector(".dateline"))this.d=b.textContent;else for(b=0;b<this.a.length;b++)if(c=this.a[b],F(c.name,"displaydate")){this.d=c.content;break}}a.d=this.d;b=(null==this.b&&Um(this),this.b);a.a=b.length?D(w(p,1),h,2,4,[b]):E(p,h,2,0,4);return a};_.pb=function(){return null==this.b&&Um(this),this.b};
_.qb=function(){if(null==this.c){var a,b;!this.a&&(this.a=this.j.getElementsByTagName("META"));this.c="";for(a=0;a<this.a.length;a++)if(b=this.a[a],F(b.name,"copyright")){this.c=b.content;break}}return this.c};_.rb=function(){return""};
_.sb=function(){if(!this.f){var a,b,c,d,e;this.f=new Q;a=this.j.getElementsByTagName("IMG");for(c=0;c<a.length;c++){e=a[c];var f=d=b=void 0,g=void 0;b=void 0;b=B(e);if(F("FIGURE",b.tagName)){if(d=b.getElementsByTagName("FIGCAPTION"),g=d.length,b="",0<g&&2>=g)for(f=0;f<g&&!b.length;f++)b=d[f].innerText}else b="";(d=null!=b&&b.length)||(d=d=void 0,d=e.width,400>d?d=!1:(d/=e.height,d=1.3<=d&&3>=d));d&&(d=new Xm,d.e=e.src,d.a=b,d.f=e.width,d.b=e.height,P(this.f,d))}}return Th(this.f,E(Ym,da,27,this.f.b.length,
0))};_.tb=function(){if(null==this.i){var a,b,c;this.i="";a=this.j.getElementsByTagName("*");for(c=0;c<a.length&&!this.i.length;c++)b=a[c],this.i=A(b,"publisher"),!this.i.length&&(this.i=A(b,"source_organization"))}return this.i};_.ub=function(){if(null==this.k){var a,b;!this.a&&(this.a=this.j.getElementsByTagName("META"));this.k="";if(0!=this.a.length&&(a=this.j.getElementsByTagName("TITLE"),0!=a.length))for(a=0;a<this.a.length;a++)if(b=this.a[a],F(b.name,"title")){this.k=b.content;break}}return this.k};
_.vb=function(){return""};_.wb=function(){return""};_.xb=function(){if(!this.e){var a,b;!this.a&&(this.a=this.j.getElementsByTagName("META"));this.e=!0;for(a=0;a<this.a.length;a++)if(b=this.a[a],F(b.name,"IE_RM_OFF")){this.g=F(b.content,"true");break}}return this.g};_.a=null;_.b=null;_.c=null;_.d=null;_.e=!1;_.f=null;_.g=!1;_.i=null;_.j=null;_.k=null;t(121);function ym(a){return parseInt(a,10)|0}
function Nl(a,b,c){var d;if(b){b=(d={},b[6].push(d),d);if(void 0==c)throw new TypeError;b[1]=c;a=V()-a;if(void 0==a)throw new TypeError;b[2]=a}}function W(a){null==a&&(a="");-1==a.indexOf("[0;")&&-1==a.indexOf("[1;")||(a+="\u001b[0m");Zm||null==$wnd.console||"function"!=typeof $wnd.console.log&&"object"!=typeof $wnd.console.log||$wnd.console.log(a);Am+=a+"\n"}var Ok=0,Am="",Zm=!1;function Ek(a){var b,c;c="";for(b=0;b<a.a.b.length&&!c.length;b++)c=N(a.a,b).ub();return c}
function Ik(a,b){var c;this.b=b;this.a=new Q;c=V();P(this.a,new $m(a,this.b));Nl(c,this.b,"OpenGraphProtocolParser");c=V();P(this.a,new an(a,this.b));Nl(c,this.b,"SchemaOrgParserAccessor");c=V();P(this.a,new Vm(a));Nl(c,this.b,"IEReadingViewParser")}n(110,1,{},Ik);t(110);function Wm(){}n(62,1,{},Wm);_.a=null;_.b="";_.c="";_.d="";_.e="";t(62);function Xm(){}n(27,1,{27:1},Xm);_.a="";_.b=0;_.c="";_.d="";_.e="";_.f=0;var Ym=t(27);
function Kl(a){if(0==a.a.b.length||0!=N(a.a,a.a.b.length-1).b.b.length)P(a.a,new bn),a.b=null}function Ml(a,b){var c,d,e;d=N(a.a,a.a.b.length-1);0==d.b.b.length?(P(d.b,b),a.b=b):(c=b.a-a.b.a,c=0==c?0:0>c?-1:1,c!=d.a?0!=d.a&&(d=(e=new bn,P(a.a,e),e),0!=c&&P(d.b,a.b)):0==c&&(d.b.b=E(nb,da,1,0,3)),P(d.b,b),a.b=b,d.a=c)}function cn(){this.a=new Q}n(125,1,{},cn);_.b=null;t(125);function bn(){this.b=new Q}n(82,1,{},bn);_.a=0;t(82);function Bm(a){this.b=new dn(a);this.a=new Q;this.d=new Q}n(182,1,{},Bm);
_.mb=function(){this.a.U(this.a.b.length-1);this.d.U(this.d.b.length-1)};_.nb=function(a){if(!this.b.a)return!1;P(this.a,a);P(this.d,null);1==this.d.b.length&&(this.c=new en(a),Sh(this.d,0,this.c));if(fn(this.b,a))for(a=0;a<this.a.b.length;a++)if(null==N(this.d,a)){Sh(this.d,a,new en(N(this.a,a)));var b=N(this.d,a-1),c=N(this.d,a);dk(b.a,c)}return!0};t(182);
function gn(a){var b,c;c=a.b.cloneNode(!1);for(a=Lh(a.a,0);a.b!=a.d.c;)b=(y(a.b!=a.d.c),a.c=a.b,a.b=a.b.a,++a.a,a.c.c),b=gn(b),c.appendChild(b);return c}function Cm(a){var b,c;c=a.b.cloneNode(!1);1==a.b.nodeType&&(b=getComputedStyle(a.b,null).direction,!b.length&&(b="auto"),c.setAttribute("dir",b));for(a=Lh(a.a,0);a.b!=a.d.c;)b=(y(a.b!=a.d.c),a.c=a.b,a.b=a.b.a,++a.a,a.c.c),b=Cm(b),c.appendChild(b);return c}function en(a){this.b=a;this.a=new gk}n(73,1,{},en);t(73);
function hn(){hn=k;jn=RegExp("((\\w+):\\s+(http:\\/\\/ogp.me\\/ns(\\/\\w+)*#))\\s*","gi");kn=/^xmlns:(\w+)/i;rn=/^http:\/\/ogp.me\/ns(\/\w+)*#/i}function sn(a,b){return G(a.f,b)?H(a.f,b):""}function wn(a,b,c){null!=c&&c.length?(c=c.substr(1,c.length-1),"profile"===c?ci(a.c,(xn(),zn),b):"article"===c&&ci(a.c,(xn(),An),b)):ci(a.c,(xn(),Cn),b)}
function Dn(a,b){var c,d;this.b=new En;this.d=new Fn;this.a=new Gn;this.e=D(w(Hn,1),da,21,0,[new In("title",(xn(),Cn),null),new In("type",Cn,null),new In("url",Cn,null),new In("description",Cn,null),new In("site_name",Cn,null),new In("image",Cn,this.b),new In("image:",Cn,this.b),new In("first_name",zn,this.d),new In("last_name",zn,this.d),new In("section",An,this.a),new In("published_time",An,this.a),new In("modified_time",An,this.a),new In("expiration_time",An,this.a),new In("author",An,this.a)]);
this.f=new Yi;this.c=new fi(Ln);this.g=b;d=V();var e,f,g;c="";F("HTML",a.tagName)&&(c=A(a,"prefix"));c.length||(g=a.getElementsByTagName("HEAD"),1==g.length&&(c=A(g[0],"prefix")));if(c.length)for(jn.lastIndex=0;;){g=jn.exec(c);if(!g)break;wn(this,g[2],g[4])}else for(c=a.attributes,g=0;g<c.length;g++)if(f=c[g],e=f.nodeName.toLowerCase(),e=kn.exec(e))f=f.nodeValue,(f=rn.exec(f))&&wn(this,e[1],f[1]);null==ai(this.c,(xn(),Cn))&&ci(this.c,Cn,"og");null==ai(this.c,zn)&&ci(this.c,zn,"profile");null==ai(this.c,
An)&&ci(this.c,An,"article");Nl(d,this.g,"OpenGraphProtocolParser.findPrefixes");d=V();var l,m;e="";for(g=new ii((new hi(this.c)).a);ki(g.a);)c=(g.b=ni(g.a),new ti(g.c,g.b)),e+='meta[property^\x3d"'+c.b.b[c.a.b]+'"],';e=tg(e,0,e.length-1);c=a.querySelectorAll(e);for(g=0;g<c.length;g++)for(f=c[g],m=A(f,"property").toLowerCase(),e=0;e<this.e.length;e++)l=ai(this.c,this.e[e].c)+":",og(m,l+this.e[e].a)&&(m=pg(m,l.length),l=!0,this.e[e].b&&(l=this.e[e].b.yb(m,f.content,this.f)),l&&L(this.f,this.e[e].a,
f.content));Nl(d,this.g,"OpenGraphProtocolParser.parseMetaTags");d=V();c=this.b;if(0!=c.a.b.length)for(g=c.a.b.length-1;0<=g;g--)e=N(c.a,g)[0],null!=e&&e.length||c.a.U(g);Nl(d,this.g,"OpenGraphProtocolParser.imageParser.verify");d=V();c=ai(this.c,Cn)+":";if(!(G(this.f,"title")?H(this.f,"title"):"").length)throw new ob('Required "'+c+'title" property is missing.');if(!(G(this.f,"type")?H(this.f,"type"):"").length)throw new ob('Required "'+c+'type" property is missing.');if(!(G(this.f,"url")?H(this.f,
"url"):"").length)throw new ob('Required "'+c+'url" property is missing.');if(0==Mn(this.b).length)throw new ob('Required "'+c+'image" property is missing.');Nl(d,this.g,"OpenGraphProtocolParser.checkRequired")}n(146,1,{},Dn);var kn,rn,jn;t(146);function Gn(){this.b=!1;this.a=new Q}n(149,1,{},Gn);_.yb=function(a,b,c){this.b||(c=c.c.eb("type"),this.b=null!=c&&F(c,"article"));return this.b?"author"===a?(P(this.a,b),!1):!0:!1};_.b=!1;t(149);
function Mn(a){var b,c,d,e;e=E(Ym,da,27,a.a.b.length,0);for(b=0;b<a.a.b.length;b++)c=N(a.a,b),d=new Xm,e[b]=d,d.e=null!=c[1]&&c[1].length?c[1]:c[0],null!=c[2]&&(d.c=c[2]),null!=c[3]&&(d.d=c[3]),null!=c[4]&&(d.f=ym(c[4])),null!=c[5]&&(d.b=ym(c[5]));return e}function En(){this.b=D(w(p,1),h,2,4,"image image:url image:secure_url image:type image:width image:height".split(" "));this.a=new Q}n(147,1,{},En);
_.yb=function(a,b){var c,d;if("image"===a)d=E(p,h,2,this.b.length,4),d[0]=b,P(this.a,d);else for(0==this.a.b.length?(d=E(p,h,2,this.b.length,4),P(this.a,d)):d=N(this.a,this.a.b.length-1),c=1;c<this.b.length;c++)if(a===this.b[c]){d[c]=b;break}return!1};t(147);function xn(){xn=k;Cn=new Nn("OG",0);zn=new Nn("PROFILE",1);An=new Nn("ARTICLE",2)}function Nn(a,b){C.call(this,a,b)}n(44,9,{3:1,11:1,9:1,44:1},Nn);var An,Cn,zn,Ln=u(44,function(){xn();return D(w(Ln,1),ea,44,0,[Cn,zn,An])});
function Fn(){this.b=this.a=!1}n(148,1,{},Fn);_.yb=function(a,b,c){this.a||(a=c.c.eb("type"),this.b=null!=a&&F(a,"profile"),this.a=!0);return this.b};_.a=!1;_.b=!1;t(148);function In(a,b,c){this.a=a;this.c=b;this.b=c}n(21,1,{21:1},In);_.a=null;_.b=null;var Hn=t(21);function Qn(a){if(!a.a){var b;var c=a.c,d=a.d;hn();var e,f;try{f=V(),e=new Dn(c,d),Nl(f,d,"OpenGraphProtocolParser.parse"),b=e}catch(g){if(g=Cc(g),r(g,15))b=null;else throw Dc(g);}a.b=b;a.a=!0}return!!a.b}
function $m(a,b){this.c=a;this.d=b;this.a=!1}n(118,1,{},$m);_.ob=function(){var a;if(Qn(this)){a=new Wm;a.d=sn(this.b,"published_time");a.c=sn(this.b,"modified_time");a.b=sn(this.b,"expiration_time");a.e=sn(this.b,"section");var b;b=this.b.a;b=Th(b.a,E(p,h,2,b.a.b.length,4));a.a=b;return a.e.length||a.d.length||a.c.length||a.b.length||0!=a.a.length?a:null}return null};
_.pb=function(){var a;if(Qn(this)){var b=this.b;a=b.f;b.d.b?(b=a.c.eb("first_name"),null==b&&(b=""),a=a.c.eb("last_name"),null!=a&&b.length&&a.length&&(b+=" "),a=b+a):a=""}else a="";return a};_.qb=function(){return""};_.rb=function(){return Qn(this)?sn(this.b,"description"):""};_.sb=function(){return Qn(this)?Mn(this.b.b):E(Ym,da,27,0,0)};_.tb=function(){return Qn(this)?sn(this.b,"site_name"):""};_.ub=function(){return Qn(this)?sn(this.b,"title"):""};
_.vb=function(){var a;a=Qn(this)?sn(this.b,"type"):"";return F(a,"article")?"Article":""};_.wb=function(){return Qn(this)?sn(this.b,"url"):""};_.xb=function(){return!1};_.a=!1;t(118);function fn(a,b){if(b!=a.a)return!1;a.a=a.b.Q()?a.b.R():null;return!0}function dn(a){this.b=a.D();a.I()||(this.a=this.b.R())}n(95,1,{},dn);t(95);function Ul(a,b,c){this.a=a;this.b=b;this.c=c}n(91,1,{},Ul);_.a=0;_.b=0;_.c=0;t(91);
function jm(a){var b,c,d;d="Type: "+a.e+"\nPageInfo: "+a.a.b.length;d+="\npattern: "+a.d;for(c=new M(a.a);c.b<c.d.J();)b=(y(c.b<c.d.J()),c.d.T(c.c=c.b++)),d+="\n  "+("pg"+b.a+": "+b.b);return d+="\nformula: "+(a.b?Rn(a.b):"null")+"\nnextPagingUrl: "+a.c}function im(){this.e=(cm(),Sn);this.a=new Q}function bm(a,b,c,d,e){this.e=(cm(),Sn);this.e=a;this.d=b;this.a=c;this.b=d;this.c=e}
function am(a){var b,c,d,e;if(2>a.b.length)return null;c=(z(0,a.b.length),a.b[0]);b=(z(1,a.b.length),a.b[1]);if(d=2==a.b.length)d=c.a,e=b.a,d=4<(d>e?d:e);if(d)return null;d=b.a-c.a;if(0==d)return null;b=~~((b.b-c.b)/d);if(0==b)return null;c=c.b-b*c.a;if(0!=c&&c!=-b)return null;for(d=2;d<a.b.length;d++)if(e=(z(d,a.b.length),a.b[d]),e.b!=b*e.a+c)return null;return new em(b,c)}
function Zl(a,b){var c,d,e,f,g,l,m,q;q=new Tn;f=c=e=-1;m=new Zi;for(l=new M(a);l.b<l.d.J();){g=(y(l.b<l.d.J()),l.d.T(l.c=l.b++));d=g.c;if(-1==c)e=d;else if(d!=c+1){if(d<=c||d!=c+2||-1!=f)return q;f=d-1}if(!R(m,df(g.b)))return q;c=d}q.a=!0;if(-1!=f){if(0>=f||f>=b.b.length-1)return q;c=(z(f,b.b.length),b.b[f]).a;(z(f-1,b.b.length),b.b[f-1]).a==c-1&&(z(f+1,b.b.length),b.b[f+1]).a==c+1&&(q.b=!0,q.c=(z(f+1,b.b.length),b.b[f+1]).b);return q}if((0==e||1==e)&&1==(z(0,b.b.length),b.b[0]).a&&2==(z(1,b.b.length),
b.b[1]).a||2==e&&3==(z(2,b.b.length),b.b[2]).a&&lf((z(1,b.b.length),b.b[1]).b)&&!lf((z(0,b.b.length),b.b[0]).b))return q.b=!0,q;f=b.b.length;if((c==f-1||c==f-2)&&(z(f-2,b.b.length),b.b[f-2]).a+1==(z(f-1,b.b.length),b.b[f-1]).a)return q.b=!0,q;for(e+=1;e<c;e++)if((z(e-1,b.b.length),b.b[e-1]).a+2==(z(e+1,b.b.length),b.b[e+1]).a){q.b=!0;break}return q}
function $l(a,b){var c,d,e,f;if(1>=a.b.length)return!1;c=(z(0,a.b.length),a.b[0]);if(1!=c.a&&!c.b.length)return!1;d=!1;for(f=new M(a);f.b<f.d.J();)if(e=(y(f.b<f.d.J()),f.d.T(f.c=f.b++)),e.b.length)d&&!b.c.length&&(b.c=e.b);else{if(d)return!1;d=!0}if(2==a.b.length)return c.a+1==(z(1,a.b.length),a.b[1]).a;for(d=1;d<a.b.length;d++)if(c=(z(d,a.b.length),a.b[d]),e=(z(d-1,a.b.length),a.b[d-1]),1!=c.a-e.a&&(1!=d&&d!=a.b.length-1||!c.b.length||!e.b.length))return!1;return!0}n(41,1,{},im,bm);_.tS=function(){return jm(this)};
_.b=null;_.c="";_.d="";t(41);function Rn(a){return"coefficient\x3d"+a.a+", delta\x3d"+a.b}function em(a,b){this.a=a;this.b=b}n(77,1,{},em);_.tS=function(){return Rn(this)};_.a=0;_.b=0;t(77);function Pl(a,b){this.a=a;this.b=b}n(26,1,{},Pl);_.tS=function(){return"pg"+this.a+": "+this.b};_.a=0;t(26);function Tn(){}n(104,1,{},Tn);_.a=!1;_.b=!1;_.c="";t(104);function cm(){cm=k;Sn=new Un("UNSET",0);dm=new Un("PAGE_NUMBER",1);Wn=new Un("UNKNOWN",2)}function Un(a,b){C.call(this,a,b)}
n(42,9,{3:1,11:1,9:1,42:1},Un);var dm,Wn,Sn,Xn=u(42,function(){cm();return D(w(Xn,1),ea,42,0,[Sn,dm,Wn])});
function Yn(){Y||(Y=new Zi,R(Y,"baixar-gratis"),R(Y,"category"),R(Y,"content"),R(Y,"day"),R(Y,"date"),R(Y,"definition"),R(Y,"etiket"),R(Y,"film-seyret"),R(Y,"key"),R(Y,"keys"),R(Y,"keyword"),R(Y,"label"),R(Y,"news"),R(Y,"q"),R(Y,"query"),R(Y,"rating"),R(Y,"s"),R(Y,"search"),R(Y,"seasons"),R(Y,"search_keyword"),R(Y,"search_query"),R(Y,"sortby"),R(Y,"subscriptions"),R(Y,"tag"),R(Y,"tags"),R(Y,"video"),R(Y,"videos"),R(Y,"w"),R(Y,"wiki"))}var Y=null,Xl=null;
function gm(a,b){var c;if(a.a){c=a.a;var d=b.a;c=c.b&&!d.b?1:!c.b&&d.b?-1:c.e==d.e?0:c.e==(cm(),dm)?1:d.e==dm?-1:0;-1==c?(a.a=b.a,a.b=b.b):0==c&&(a.b=!0)}else a.a=b.a,a.b=b.b}function Ol(){}function hm(a){this.a=a}n(70,1,{},Ol,hm);_.a=null;_.b=!1;t(70);function Tl(a,b,c){var d;d=b.tS();G(a.a,d)?P(H(a.a,d).a,c):L(a.a,d,new fo(b,c))}function Ql(){this.a=new Yi}n(126,1,{},Ql);t(126);function fo(a,b){this.b=a;this.a=new Q;P(this.a,b)}n(127,1,{},fo);t(127);function Dl(){Dl=k;Fl=/\/$/}
function Ll(a,b,c,d,e){var f;f=c?b:d?b.previousSibling:b.nextSibling;if(!f)return f=b.parentNode,!go&&(go=/(BODY)|(HTML)/),go.test(f.nodeName)?!1:Ll(a,f,!1,d,e);c=!1;switch(f.nodeType){case 3:b=f.nodeValue;if(!b.length||(U(),0==Fk.Bb(b)))break;b=f.nodeValue;var g,l,m;if(Wl(b)){ho?ho.lastIndex=0:ho=RegExp("(\\S*[\\w\u00c0-\u1fff\u2c00-\ud7ff]\\S*)","gi");!io&&(io=/^[\W_]*(\d+)[\W_]*$/i);for(g=!1;;){l=ho.exec(b);if(!l)break;1>=l.length||(l=l[1],m=io.exec(l),l=-1,m&&1<m.length&&(l=no(m[1])),0<=l&&100>=
l?(Ml(a.a,new Pl(l,"")),g=!0):Kl(a.a))}b=g}else Kl(a.a),b=!1;if(d||!b)return!1;break;case 1:if(b=f,F("A",b.tagName)){if(d)return!1;++a.c;(b=Jl(a,b,e))?(Ml(a.a,b.a),b=!0):(Kl(a.a),b=!1);if(!b)return!1;break}default:if(!f.hasChildNodes())break;c=!0;d?f=f.lastChild:f=f.firstChild}return Ll(a,f,c,d,e)}
function Jl(a,b,c){var d,e,f,g;if(!mm(b))return null;g=Gk(b.innerText);g=Af(g,"[()\\[\\]{}]");g=ug(g);g=no(g);if(!(0<=g&&100>=g))return null;d=A(b,"href");d.length?(c.setAttribute("href",d),f=c.href):f="";d=!f.length;e=!1;c=null;if(!d){e="javascript:"===f.substr(0,11);c=Gl(f);if(!c||!e&&!F(c.d.host,a.d.d.host))return null;c.d.hash=""}if(!(a=d||e)){b=getComputedStyle(b,null);b=b.cursor.toUpperCase();Tc();a=(He(),Ie);Nc(b);a=a[":"+b];b=D(w(nb,1),da,1,3,[b]);if(!a)throw new af(Qc("Enum constant undefined: %s",
b));a=a==(Tc(),Qd)}return a?new uo(g,""):new uo(g,Va(c.d).replace(Fl,""))}function El(a){this.a=new cn;this.e=a}n(108,1,{},El);_.b="";_.c=0;_.d=null;var Fl,go=null,io=null,ho=null;t(108);function uo(a,b){this.a=new Pl(a,b)}n(79,1,{},uo);t(79);
function km(){km=k;rm=RegExp("(next|weiter|continue|\x3e([^\\|]|$)|\u00bb([^\\|]|$))","i");vm=RegExp("(prev|early|old|new|\x3c|\u00ab)","i");wm=/article|body|content|entry|hentry|main|page|pagination|post|text|blog|story/i;um=RegExp("combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|shoutbox|sidebar|sponsor|shopping|tags|tool|widget","i");om=RegExp("print|archive|comment|discuss|e[\\-]?mail|share|reply|all|login|sign|single|as one|article|post|\u7bc7","i");
sm=/pag(e|ing|inat)/i;xm=/p(a|g|ag)?(e|ing|ination)?(=|\/)[0-9]{1,2}$/i;tm=/(first|last)/i;nm=/\/?(#.*)?$/;pm=/\d/;lm=new Yi}function X(a,b){var c;3>Ok||(c="",ch(lm,a)&&(c=eh(lm,a)),!c.length||(c+="; "),fh(lm,a,c+b))}function Hl(a){km();var b,c;c=$doc.implementation.createHTMLDocument();b=c.createElement("base");b.href=a;(c.head||c.getElementsByTagName("head")[0]).appendChild(b);a=c.createElement("a");c.body.appendChild(a);return a}
function Il(a,b){km();var c,d;d=a.getElementsByTagName("BASE");if(0==d.length)return b;c=Hl(b);d=A(d[0],"href");c.setAttribute("href",d);return c.href}var om,tm,nm,xm,um,rm,pm,sm,wm,vm,lm;function qm(a,b,c){this.b=a;this.d=0;this.c=b;this.a=c}n(109,1,{},qm);_.b=-1;_.d=0;t(109);function vo(a){var b;null==a.a&&(b=(null==a.c&&(a.c=Vl(a.d)),a.c),b.length?a.a=(U(),lg(b,"\\/")):a.a=E(p,h,2,0,4));return a.a}function yo(a){this.d=a}
function Gl(a){var b;try{b=new URL(a)}catch(c){b=null}return b?new yo(b):null}n(69,1,{69:1},yo);_.tS=function(){return Va(this.d)};_.a=null;_.b=null;var fm=_.c=null,Rl=t(69);function Vl(a){a=a.pathname.replace(/;.*$/,"");a=a.replace(/^\//,"");return a.replace(/\/$/,"")}function zo(a){var b,c;if(2>a.b)return!1;c=vo(a.g);if(4!=c[a.b].length)return!1;b=no(c[a.b-1]);return 0<b&&12>=b&&(a=no(c[a.b-2]),1970<a&&3E3>a)?!0:!1}
function Fo(a,b){var c,d,e,f;f=b.length;e=f-a.f.length;if(!og(b,a.e))return!1;c=a.c;for(d=hf(a.d,e);c<d&&b.charCodeAt(c)==a.i.charCodeAt(c);c++);if(c==e){if(d=c+1==a.d)d=a.i.charCodeAt(c),128>d?(e=(Ze(),$e)[d],!e&&(e=$e[d]=new Xe(d)),d=e):d=new Xe(d),d=/[-_;,]/.test(d);if(d||c+a.f.length==f)return!0}else if(c==a.d&&0<=no(b.substr(c,e-c)))return!0;return!1}
function Yl(a,b,c,d){var e;a=Va(a.d);a:{if(47==a.charCodeAt(c-1)&&b<c-1&&(e=a.substr(d,a.length-d).toLowerCase(),!Go&&(Go=/(.s?html?)?$/i),Go.test(e)&&(!Ho&&(Ho=/([^/]*)\/$/i),b=a.substr(b+1,c-(b+1)),(b=Ho.exec(b))&&1<b.length&&(Yn(),S(Y,b[1].toLowerCase()))))){b=!0;break a}b=!1}if(b)throw new af("Bad last numeric path component");e=a.substr(c,d-c);b=no(e);if(0>b)throw new af("Value in path component is an invalid number: "+e);d=a.substr(0,c)+"[*!]"+a.substr(d,a.length-d);this.g=Gl(d);if(!this.g)throw new af("Invalid URL: "+
d);this.i=d;this.a=b;this.d=c;this.c=qf(this.i,47,this.d);c=vo(this.g);for(this.b=0;this.b<c.length&&-1==c[this.b].indexOf("[*!]");this.b++);this.e=tg(this.i,0,this.c);d=this.i.length;c=d-this.d-4;0!=c&&(this.f=pg(this.i,d-c))}n(184,1,{},Yl);
_.zb=function(a){if(this.f.length&&!kf(a,this.f))a=!1;else if(47==this.i.charCodeAt(this.d-1))a:{var b,c,d,e;e=a.length;c=this.f.length;d=a.length-c;b=qf(this.g.d.pathname,47,this.c-1-this.g.d.origin.length);if(-1!=b&&(b+=this.g.d.origin.length,b+c==e)){a=sf(a,0,this.i,0,b);break a}og(a,this.e)?(b=this.c+c,a=b==e?!0:b>e||47!=a.charCodeAt(this.c)?!1:0<=no(tg(a,this.c+1,d))):a=!1}else a=Fo(this,a);return a};
_.Ab=function(a){var b,c;b=vo(a).length;c=vo(this.g).length;if(b>c)return!1;if(1==b&&1==c){c=vo(a)[0];a=vo(this.g)[0];var d;if(c.length&&a.length)for(d=hf(c.length,a.length),b=0;b<d&&c.charCodeAt(b)==a.charCodeAt(b);b++);else b=0;d=b;var e,f,g;e=0;f=c.length-1;for(g=a.length-1;f>d&&g>d&&c.charCodeAt(f)==a.charCodeAt(g);--f,--g,e++);return 2*(e+b)>=c.length}a:{e=vo(a);d=vo(this.g);b=!1;for(c=a=0;a<e.length&&c<d.length;++a,c++)if(a==this.b&&!b)b=!0,e.length<d.length&&--a;else if(!F(e[a],d[c])){a=!1;
break a}a=!0}return!a||zo(this)?!1:!0};_.tS=function(){return this.i};_.a=0;_.b=-1;_.c=0;_.d=0;_.f="";var Go=null,Ho=null;t(184);
function Sl(a,b,c,d){var e;if(!c.length)throw new af("Empty query name");if(!d.length)throw new af("Empty query value");if(!Ko(d))throw new af("Query value has non-digits: "+d);Yn();if(S(Y,c.toLowerCase()))throw new af("Query name is bad page param name: "+c);e=no(d);if(0>e)throw new af("Query value is an invalid number: "+d);b=(b?"?":"\x26")+c+"\x3d";a=a.d.href.replace(b+d,b+"[*!]");this.i=Gl(a);if(!this.i)throw new af("Invalid URL: "+a);this.j=a;this.a=e;this.c=a.indexOf("[*!]");this.e=qf(this.j,
63,this.c-1);this.b=qf(this.j,38,this.c-1);-1==this.b&&(this.b=this.e);!Lo&&(Lo=/\/$/);this.d=tg(this.j,0,this.b).replace(Lo,"");e=this.j.length;this.g=e-this.c-4;0!=this.g&&(this.f=pg(this.j,e-this.g+1))}n(183,1,{},Sl);
_.zb=function(a){var b,c;if(0!=this.g&&!kf(a,this.f))return!1;c=a.length-this.g;if(!og(a,this.d))return!1;if(this.b==c||c==this.b-1&&47==this.j.charCodeAt(c))return!0;b=tg(a,this.b,c).toLowerCase();!Oo&&(Oo=/^\/|(.html?)$/i);return Oo.test(b)?!0:sf(a,this.b,this.j,this.b,this.c-this.b)?0<=no(tg(a,this.c,c)):!1};_.Ab=function(a){a=(null==a.c&&(a.c=Vl(a.d)),a.c);var b=this.i;null==b.c&&(b.c=Vl(b.d));return F(a,b.c)};_.tS=function(){return this.j};_.a=0;_.b=0;_.c=0;_.e=0;_.f="";_.g=0;
var Lo=null,Oo=null;t(183);
function Po(){Po=k;Qo=new Yi;L(Qo,"http://schema.org/ImageObject",(Wo(),Xo));L(Qo,"http://schema.org/Article",Yo);L(Qo,"http://schema.org/BlogPosting",Yo);L(Qo,"http://schema.org/NewsArticle",Yo);L(Qo,"http://schema.org/ScholarlyArticle",Yo);L(Qo,"http://schema.org/TechArticle",Yo);L(Qo,"http://schema.org/Person",Zo);L(Qo,"http://schema.org/Organization",$o);L(Qo,"http://schema.org/Corporation",$o);L(Qo,"http://schema.org/EducationalOrganization",$o);L(Qo,"http://schema.org/GovernmentOrganization",$o);
L(Qo,"http://schema.org/NGO",$o);ap=new Yi;L(ap,"IMG","SRC");L(ap,"AUDIO","SRC");L(ap,"EMBED","SRC");L(ap,"IFRAME","SRC");L(ap,"SOURCE","SRC");L(ap,"TRACK","SRC");L(ap,"VIDEO","SRC");L(ap,"A","HREF");L(ap,"LINK","HREF");L(ap,"AREA","HREF");L(ap,"META","CONTENT");L(ap,"TIME","DATETIME");L(ap,"OBJECT","DATA");L(ap,"DATA","VALUE");L(ap,"METER","VALUE")}function bp(a){var b,c,d;b=new Q;for(c=0;c<a.c.b.length;c++)d=N(a.c,c),d.d==(Wo(),Yo)&&P(b,d);return b}
function dp(a,b,c){var d,e,f,g,l;e=null;d=b.hasAttribute("ITEMSCOPE")&&b.hasAttribute("ITEMTYPE");if(c){var m;f=A(b,"ITEMPROP");f.length?(m=(U(),lg(f,"\\s+")),f=0<m.length?m:D(w(p,1),h,2,4,[f])):f=E(p,h,2,0,4)}else f=E(p,h,2,0,4);if(d){a:{var q;switch((q=A(b,"ITEMTYPE"),G(Qo,q)?H(Qo,q):(Wo(),sp)).b){case 0:e=new tp(b);break;case 1:e=new up(b);break;case 2:e=new vp(b);break;case 3:e=new wp(b);break;case 4:e=new xp(b);break;default:e=null;break a}}!e||e.d==(Wo(),sp)||c&&c.d==(Wo(),sp)&&0!=f.length||
(P(a.c,e),fh(a.b,b,e))}if(0<f.length&&c.d!=(Wo(),sp)&&(!e||e.d!=(Wo(),sp)))for(a=0;a<f.length;a++)e?G(c.b,f[a])&&L(c.b,f[a],e):(d=c,q=f[a],m=(g="",l=b.tagName,G(ap,l)&&(g=A(b,H(ap,l))),!g.length&&(g=b.textContent),g),G(d.c,q)&&!H(d.c,q).length&&L(d.c,q,m))}
function yp(a,b){Po();var c;this.c=new Q;this.b=new Yi;this.d=b;c=V();var d,e,f,g,l;d=a.querySelectorAll("[ITEMPROP],[ITEMSCOPE]");dp(this,a,null);for(f=0;f<d.length;f++){for(var m=e=d[f],q=void 0,v=void 0,v=null,q=e;q;){q=B(q);if(!q)break;if(q.hasAttribute("ITEMSCOPE")&&q.hasAttribute("ITEMTYPE")){ch(this.b,q)&&(v=eh(this.b,q));break}}dp(this,m,v)}d=a.querySelectorAll("A[rel\x3dauthor],LINK[rel\x3dauthor]");for(f=0;f<d.length;f++)e=d[f],!this.a.length&&(this.a=(g="",l=e.tagName,(F(l,"A")||F(l,"LINK"))&&
F(A(e,"REL"),"author")&&(g=e.textContent),g));Nl(c,this.d,"SchemaOrgParser.parse")}function zp(a,b){Po();var c;c=a;a.length&&b.length&&(c+=" ");return c+b}n(28,1,{},yp);_.a="";var ap,Qo;t(28);function Ap(a,b){return G(a.c,b)?H(a.c,b):""}function Bp(a,b){this.a=b;this.d=a;this.c=new Yi;this.b=new Yi;L(this.c,"name","");L(this.c,"url","");L(this.c,"description","");L(this.c,"image","")}n(45,1,{});t(45);
function Cp(a,b){var c,d,e,f;c=G(a.c,b)?H(a.c,b):"";if(c.length)return c;(d=G(a.b,b)?H(a.b,b):null)&&(d.d==(Wo(),Zo)?c=(e=G(d.c,"name")?H(d.c,"name"):"",e.length?e:zp(G(d.c,"givenName")?H(d.c,"givenName"):"",G(d.c,"familyName")?H(d.c,"familyName"):"")):d.d==$o&&(c=(f=G(d.c,"name")?H(d.c,"name"):"",f.length?f:G(d.c,"legalName")?H(d.c,"legalName"):"")));return c}
function up(a){Bp.call(this,(Wo(),Yo),a);L(this.c,"headline","");L(this.c,"publisher","");L(this.c,"copyrightHolder","");L(this.c,"copyrightYear","");L(this.c,"dateModified","");L(this.c,"datePublished","");L(this.c,"author","");L(this.c,"creator","");L(this.c,"articleSection","");fh(this.b,"publisher",null);fh(this.b,"copyrightHolder",null);fh(this.b,"author",null);fh(this.b,"creator",null);fh(this.b,"associatedMedia",null);fh(this.b,"encoding",null)}n(151,45,{},up);t(151);
function tp(a){Bp.call(this,(Wo(),Xo),a);L(this.c,"contentUrl","");L(this.c,"encodingFormat","");L(this.c,"caption","");L(this.c,"representativeOfPage","");L(this.c,"width","");L(this.c,"height","")}n(150,45,{},tp);t(150);function wp(a){Bp.call(this,(Wo(),$o),a);L(this.c,"legalName","")}n(153,45,{},wp);t(153);function vp(a){Bp.call(this,(Wo(),Zo),a);L(this.c,"familyName","");L(this.c,"givenName","")}n(152,45,{},vp);t(152);
function Wo(){Wo=k;Xo=new Dp("IMAGE",0);Yo=new Dp("ARTICLE",1);Zo=new Dp("PERSON",2);$o=new Dp("ORGANIZATION",3);sp=new Dp("UNSUPPORTED",4)}function Dp(a,b){C.call(this,a,b)}n(33,9,{3:1,11:1,9:1,33:1},Dp);var Yo,Xo,$o,Zo,sp,Ep=u(33,function(){Wo();return D(w(Ep,1),ea,33,0,[Xo,Yo,Zo,$o,sp])});function xp(a){Bp.call(this,(Wo(),sp),a)}n(154,45,{},xp);t(154);function an(a,b){this.b=a;this.c=b}n(119,1,{},an);
_.ob=function(){var a;!this.a&&(this.a=new yp(this.b,this.c));a=bp(this.a);if(0==a.b.length)a=null;else{a=(z(0,a.b.length),a.b[0]);var b,c;b=new Wm;b.d=G(a.c,"datePublished")?H(a.c,"datePublished"):"";b.c=G(a.c,"dateModified")?H(a.c,"dateModified"):"";b.e=G(a.c,"articleSection")?H(a.c,"articleSection"):"";c=Cp(a,"author");!c.length&&(c=Cp(a,"creator"));b.a=c.length?D(w(p,1),h,2,4,[c]):E(p,h,2,0,4);a=b}return a};
_.pb=function(){var a,b;!this.a&&(this.a=new yp(this.b,this.c));b="";a=bp(this.a);0!=a.b.length&&(a=(z(0,a.b.length),a.b[0]),b=Cp(a,"author"),!b.length&&(b=Cp(a,"creator")));return b.length?b:this.a.a};_.qb=function(){var a;!this.a&&(this.a=new yp(this.b,this.c));a=bp(this.a);0==a.b.length?a="":(a=(z(0,a.b.length),a.b[0]),a=zp(G(a.c,"copyrightYear")?H(a.c,"copyrightYear"):"",Cp(a,"copyrightHolder")),a=a.length?"Copyright "+a:a);return a};
_.rb=function(){var a;!this.a&&(this.a=new yp(this.b,this.c));a=bp(this.a);return 0==a.b.length?"":Ap((z(0,a.b.length),a.b[0]),"description")};
_.sb=function(){var a,b,c,d,e,f,g,l;!this.a&&(this.a=new yp(this.b,this.c));g=new Q;b=bp(this.a);c=null;for(d=0;d<b.b.length;d++){a=(z(d,b.b.length),b.b[d]);if(!c&&(c=(e=G(a.b,"associatedMedia")?H(a.b,"associatedMedia"):null,!e&&(e=G(a.b,"encoding")?H(a.b,"encoding"):null),e&&e.d==(Wo(),Xo)?e:null)))continue;var m=f=void 0,m=G(a.c,"image")?H(a.c,"image"):"";m.length?(f=new Xm,f.e=m,a=f):a=null;a&&(g.b[g.b.length]=a)}d=this.a;b=new Q;for(a=0;a<d.c.b.length;a++)e=N(d.c,a),e.d==(Wo(),Xo)&&P(b,e);d=!1;
for(e=0;e<b.b.length;e++)f=(z(e,b.b.length),b.b[e]),a=(l=new Xm,l.e=G(f.c,"contentUrl")?H(f.c,"contentUrl"):"",!l.e.length&&(l.e=G(f.c,"url")?H(f.c,"url"):""),l.d=G(f.c,"encodingFormat")?H(f.c,"encodingFormat"):"",l.a=G(f.c,"caption")?H(f.c,"caption"):"",l.f=ym(G(f.c,"width")?H(f.c,"width"):""),l.b=ym(G(f.c,"height")?H(f.c,"height"):""),l),f==c||!d&&F(G(f.c,"representativeOfPage")?H(f.c,"representativeOfPage"):"","true")?(d=!0,Pc(0,g.b.length),g.b.splice(0,0,a)):g.b[g.b.length]=a;return Th(g,E(Ym,
da,27,g.b.length,0))};_.tb=function(){var a,b;!this.a&&(this.a=new yp(this.b,this.c));b="";a=bp(this.a);0!=a.b.length&&(a=(z(0,a.b.length),a.b[0]),b=Cp(a,"publisher"),!b.length&&(b=Cp(a,"copyrightHolder")));return b};
_.ub=function(){var a,b,c;!this.a&&(this.a=new yp(this.b,this.c));c="";var d=bp(this.a),d=new Uh(d),e=new Fp;a=Je(d.b,d.b.length);b=a.length;var f,g;!e&&(e=(Wh(),Wh(),Xh));f=b-0;g=D(w(nb,1),da,1,3,[df(0),df(b)]);if(!(0<=f))throw new af(Qc("%s \x3e %s",g));g=Ke(a,f);var l=hf(a.length-0,f),m=f=0,q,v,I,pb,Aa;if(null==a)throw new jf("src");if(null==g)throw new jf("dest");pb=za(a);v=za(g);Jc(0!=(pb.f&4),"srcType is not an array");Jc(0!=(v.f&4),"destType is not an array");I=pb.c;q=v.c;Jc(0!=(I.f&1)?I==
q:0==(q.f&1),"Array types don't match");Aa=a.length;q=g.length;if(0>f||0>m||0>l||f+l>Aa||m+l>q)throw new Re;if(0!=(I.f&1)&&0==(I.f&4)||pb==v)0<l&&Oe(a,f,g,m,l,!0);else if(s(a)===s(g)&&f<m)for(f+=l,l=m+l;l-- >m;)g[l]=a[--f];else for(l=m+l;m<l;)g[m++]=a[f++];Vh(g,a,0,b,-0,e);e=d.b.length;for(b=0;b<e;b++)Sh(d,b,a[b]);for(a=0;a<d.b.length&&!c.length;a++)b=(z(a,d.b.length),d.b[a]),c=G(b.c,"headline")?H(b.c,"headline"):"",!c.length&&(c=G(b.c,"name")?H(b.c,"name"):"");return c};
_.vb=function(){!this.a&&(this.a=new yp(this.b,this.c));return 0==bp(this.a).b.length?"":"Article"};_.wb=function(){var a;!this.a&&(this.a=new yp(this.b,this.c));a=bp(this.a);return 0==a.b.length?"":Ap((z(0,a.b.length),a.b[0]),"url")};_.xb=function(){return!1};t(119);function Fp(){}n(120,1,{},Fp);_.Z=function(a,b){var c,d;c=Hm(a.a);d=Hm(b.a);return c>d?-1:c<d?1:0};t(120);function U(){U=k;Fk=new Lk}function Wl(a){U();return/\d/.test(a)}function zm(a){U();return decodeURIComponent(a)}
function Ko(a){U();return/^\d+$/.test(a)}function Gp(a){U();return!/\S/.test(a)}function Sm(a,b){U();return a.join(b)}function Mm(a){U();return a.split(",")}function Gk(a){U();return a.trim()}function no(a){U();return a.length&&Ko(a)?ym(a):-1}var Fk;function Nk(){}n(107,1,{},Nk);_.Bb=function(a){return(a=a.match(/(\S*[\w\u00C0-\u1FFF]\S*)/g))?a.length:0};t(107);function Lk(){}n(78,1,{},Lk);
_.Bb=function(a){var b=a.match(/(\S*[\w\u00C0-\u1FFF\uAC00-\uD7AF]\S*)/g),c=b?b.length:0,b=a.match(/([\u3040-\uA4CF])/g);return c+=Math.ceil(0.55*(b?b.length:0))};t(78);function Mk(){}n(106,1,{},Mk);_.Bb=function(a){return(a=a.match(/(\S*[\w\u00C0-\u1FFF\uAC00-\uD7AF]\S*)/g))?a.length:0};t(106);
function Hp(){Hp=k;Ip=new Yi;L(Ip,"COLGROUP",(Te(),Ue));L(Ip,"COL",Ue);L(Ip,"TH",We);Jp=new Yi;L(Jp,"EMBED",Ue);L(Jp,"OBJECT",Ue);L(Jp,"APPLET",Ue);L(Jp,"IFRAME",Ue);Kp=new Zi;R(Kp,"grid");R(Kp,"treegrid");Lp=new Zi;R(Lp,"gridcell");R(Lp,"columnheader");R(Lp,"row");R(Lp,"rowgroup");R(Lp,"rowheader");Mp=new Zi;R(Mp,"application");R(Mp,"banner");R(Mp,"complementary");R(Mp,"contentinfo");R(Mp,"form");R(Mp,"main");R(Mp,"navigation");R(Mp,"search")}
function Np(a,b){var c,d,e;for(d=new M(a);d.b<d.d.J();)if(c=(y(d.b<d.d.J()),d.d.T(d.c=d.b++)),e=c.tagName,null==e?dh(b.a,null):void 0!==b.c.eb(e))return!(null==e?ah(dh(b.a,null)):b.c.eb(e)).a||Op(c);return!1}function Op(a){a=a.innerText;return!!a.length&&!Gp(a)}function Pp(a,b,c){2<=Ok&&W(a+b+" -\x3e "+c);return c}
function Qp(a){Hp();var b,c,d,e,f,g,l,m;Rp();for(f=B(a);f;){if(F("INPUT",f.tagName)||F(A(f,"contenteditable"),"true"))return Pp(Sp,"",(Z(),Tp));f=B(f)}f=A(a,"role").toLowerCase();if("presentation"===f)return Pp(Up,"_"+f,(Z(),Tp));if(S(Kp,f)||S(Mp,f))return Pp(Up,"_"+f,(Z(),Vp));f=new Q;g=a.getElementsByTagName("*");if(0<a.getElementsByTagName("TABLE").length)for(e=0;e<g.length;e++)for(c=g[e],d=B(c);d;){if(F("TABLE",d.tagName)){d==a&&(f.b[f.b.length]=c);break}d=B(d)}else for(e=0;e<g.length;e++)P(f,
g[e]);for(g=new M(f);g.b<g.d.J();)if(b=(y(g.b<g.d.J()),g.d.T(g.c=g.b++)),c=A(b,"role").toLowerCase(),S(Lp,c)||S(Mp,c))return Pp(Wp,"_"+c,(Z(),Vp));if("0"===A(a,"datatable"))return Pp(Xp,"",(Z(),Tp));if(0<a.getElementsByTagName("TABLE").length)return Pp(Yp,"",(Z(),Tp));g=a.rows;if(1>=g.length)return Pp(Zp,"",(Z(),Tp));c=null;for(d=b=0;d<g.length;d++)e=g[d].cells,e.length>b&&(b=e.length,c=e);d=c;if(!d||1>=d.length)return Pp($p,"",(Z(),Tp));if((c=a.caption)&&Op(c)||a.tHead||a.tFoot||Np(f,Ip))return Pp(aq,
"",(Z(),Vp));c=new Q;for(e=new M(f);e.b<e.d.J();)b=(y(e.b<e.d.J()),e.d.T(e.c=e.b++)),F("TD",b.tagName)&&(c.b[c.b.length]=b);for(e=new M(c);e.b<e.d.J();){b=(y(e.b<e.d.J()),e.d.T(e.c=e.b++));if(b.hasAttribute("abbr")||b.hasAttribute("headers")||b.hasAttribute("scope"))return Pp(bq,"",(Z(),Vp));b=b.getElementsByTagName("*");if(1==b.length&&F("ABBR",b[0].tagName))return Pp(cq,"",(Z(),Vp))}e=a.ownerDocument.documentElement;b=(e.offsetWidth||0)|0;if(0<b&&((a.offsetWidth||0)|0)>0.95*b){m=!1;b=e.getElementsByTagName("META");
for(l=0;l<b.length&&!m;l++)m=b[l],m=F(m.name,"viewport");if(!m)return Pp(dq,"",(Z(),Tp))}if(a.hasAttribute("summary"))return Pp(eq,"",(Z(),Vp));if(5<=d.length)return Pp(fq,"",(Z(),Vp));for(d=new M(c);d.b<d.d.J();)if(b=(y(d.b<d.d.J()),d.d.T(d.c=d.b++)),b=getComputedStyle(b,null).borderStyle,b.length&&"none"!==b&&"hidden"!==b)return Pp(gq,"_"+b,(Z(),Vp));l=null;for(b=0;b<g.length;b++)if(d=getComputedStyle(g[b],null).backgroundColor,null==l)l=d;else if(!F(l,d))return Pp(hq,"",(Z(),Vp));if(20<=g.length)return Pp(iq,
"",(Z(),Vp));if(10>=c.b.length)return Pp(jq,"",(Z(),Tp));if(Np(f,Jp))return Pp(kq,"",(Z(),Tp));f=(e.offsetHeight||0)|0;return 0<f&&((a.offsetHeight||0)|0)>0.9*f?Pp(lq,"",(Z(),Tp)):Pp(mq,"",(Z(),Vp))}var Mp,Lp,Kp,Ip,Jp;
function Rp(){Rp=k;Sp=new nq("INSIDE_EDITABLE_AREA",0);Up=new nq("ROLE_TABLE",1);Wp=new nq("ROLE_DESCENDANT",2);Xp=new nq("DATATABLE_0",3);aq=new nq("CAPTION_THEAD_TFOOT_COLGROUP_COL_TH",4);bq=new nq("ABBR_HEADERS_SCOPE",5);cq=new nq("ONLY_HAS_ABBR",6);dq=new nq("MORE_95_PERCENT_DOC_WIDTH",7);eq=new nq("SUMMARY",8);Yp=new nq("NESTED_TABLE",9);Zp=new nq("LESS_EQ_1_ROW",10);$p=new nq("LESS_EQ_1_COL",11);fq=new nq("MORE_EQ_5_COLS",12);gq=new nq("CELLS_HAVE_BORDER",13);hq=new nq("DIFFERENTLY_COLORED_ROWS",
14);iq=new nq("MORE_EQ_20_ROWS",15);jq=new nq("LESS_EQ_10_CELLS",16);kq=new nq("EMBED_OBJECT_APPLET_IFRAME",17);lq=new nq("MORE_90_PERCENT_DOC_HEIGHT",18);mq=new nq("DEFAULT",19);oq=new nq("UNKNOWN",20)}function nq(a,b){C.call(this,a,b)}n(16,9,{3:1,11:1,9:1,16:1},nq);var bq,aq,gq,Xp,mq,hq,kq,Sp,jq,$p,Zp,lq,dq,iq,fq,Yp,cq,Wp,Up,eq,oq,pq=u(16,function(){Rp();return D(w(pq,1),ea,16,0,[Sp,Up,Wp,Xp,aq,bq,cq,dq,eq,Yp,Zp,$p,fq,gq,hq,iq,jq,kq,lq,mq,oq])});
function Z(){Z=k;Vp=new qq("DATA",0);Tp=new qq("LAYOUT",1)}function qq(a,b){C.call(this,a,b)}n(56,9,{3:1,11:1,9:1,56:1},qq);var Vp,Tp,rq=u(56,function(){Z();return D(w(rq,1),ea,56,0,[Vp,Tp])});function sq(a,b){var c;c=tq(b);a.appendChild(c);return c}function tq(a){var b;b=a.cloneNode(!1);1==a.nodeType&&(a=getComputedStyle(a,null).direction,!a.length&&(a="auto"),b.setAttribute("dir",a));return b}function uq(a,b){var c;c=a.parentNode;c||(c=tq(b),c.appendChild(a));return c}
function vq(a){return sl(N(a.j,N(a.i,0).a))}function wq(a,b){return S(a.b,b)}function Xk(a,b){a.g+="\n";a.g+=b.g;a.d+=b.d;a.e+=b.e;a.c=0==a.d?0:a.e/a.d;a.a|=b.a;Ph(a.i,b.i);a.b.G(b.b);a.f=hf(a.f,b.f)}function dl(a,b){if(b==a.a)return!1;a.a=b;return!0}
function xq(a){var b;b="["+(N(a.j,N(a.i,0).a).j+"-"+N(a.j,N(a.i,a.i.b.length-1).a).j+";");b+="tl\x3d"+a.f+";";b+="nw\x3d"+a.d+";";b+="ld\x3d"+a.c+";";b=b+"]\t"+((a.a?"\u001b[0;32mCONTENT":"\u001b[0;35mboilerplate")+"\u001b[0m,");b+="\u001b[1;30m"+Xg(new Ck(a.b))+"\u001b[0m";return b+="\n"+a.g}function Wk(a,b){var c,d;this.j=a;this.i=new Q;P(this.i,df(b));c=N(this.j,b);this.b=(d=c.e,c.e=new Zi,d);this.d=c.i;this.e=c.g;this.f=c.n;this.g=c.o;this.c=0==this.d?0:this.e/this.d}n(72,1,{},Wk);_.tS=function(){return xq(this)};
_.a=!1;_.c=0;_.d=0;_.e=0;_.f=0;t(72);function Yk(a){this.a=a}n(81,1,{},Yk);t(81);function yq(){yq=k;zq=new Zi;R(zq,"IMG");R(zq,"PICTURE");R(zq,"FIGURE");R(zq,"SPAN");Aq=D(w(p,1),h,2,4,["data-src","data-original","datasrc","data-url"])}function Bq(a){var b;b=$doc.createElement("FIGCAPTION");a=Gk(a.innerText);b.textContent=a||"";return b}
function Cq(a,b){var c,d,e;if(!S(zq,b.tagName))return null;a.b="";c="IMG"==b.tagName?b:Im(b,"IMG");if("FIGURE"===b.tagName){d=Im(b,"PICTURE");!d&&(d=Im(b,"IMG"));if(!d)return null;Dq(a,c);(c=Im(b,"FIGCAPTION"))?(e=c.querySelectorAll("A[HREF]"),c=0<e.length?c:Bq(c)):c=Bq(b);return new Eq(d,a.c,a.a,a.b,c)}if("SPAN"===b.tagName){if(-1==A(b,"class").indexOf("lazy-image-placeholder"))return null;c=$doc.createElement("img");a.b=A(b,"data-src");a.c=ym(A(b,"data-width"));a.a=ym(A(b,"data-height"));d=A(b,
"data-srcset");c.setAttribute("srcset",d);return new Fq(c,a.c,a.a,a.b)}Dq(a,c);return new Fq(b,a.c,a.a,a.b)}function Dq(a,b){var c,d,e,f;d=Aq;e=0;for(f=d.length;e<f&&(c=d[e],a.b=A(b,c),!a.b.length);++e);a.b.length?(a.c=0,a.a=0):(a.b=b.src,a.c=b.width,a.a=b.height);2<=Ok&&W("Extracted WebImage: "+a.b)}function Gq(){yq()}n(132,1,{},Gq);_.Cb=function(a){return Cq(this,a)};_.Db=function(){return zq};_.a=0;_.c=0;var Aq,zq;t(132);function Hq(){Hq=k;Iq=new Zi;R(Iq,"BLOCKQUOTE");R(Iq,"IFRAME")}
function Jq(a){var b;if(-1==A(a,"class").indexOf("twitter-tweet"))return null;b=a.getElementsByTagName("a");if(0==b.length)return null;b=b[b.length-1];if(!Om(b.href,"twitter.com"))return null;a:{var c;c=lg(Sc(b,"pathname"),"/");for(b=c.length-1;0<=b;b--)if(0<c[b].length){b=c[b];break a}b=null}return null==b?null:new Kq(a,"twitter",b,null)}
function Lq(a){var b;if("IFRAME"!==a.tagName||a.src.length)return null;b=a.contentWindow.document;if(!b)return null;b=b.getElementsByTagName("blockquote");if(1>b.length)return null;b=A(b[0],"data-tweet-id");return b.length?new Kq(a,"twitter",b,null):null}function Mq(){Hq()}n(133,1,{},Mq);_.Cb=function(a){var b;a&&S(Iq,a.tagName)?(b=null,"BLOCKQUOTE"===a.tagName?b=Jq(a):"IFRAME"===a.tagName&&(b=Lq(a)),b&&2<=Ok&&(W("Twitter embed extracted:"),W("    ID: "+b.b)),a=b):a=null;return a};_.Db=function(){return Iq};
var Iq;t(133);function Nq(){Nq=k;Oq=new Zi;R(Oq,"IFRAME")}function Pq(a){var b,c;if(!a||!S(Oq,a.tagName))return null;c=a.src;if(!Om(c,"player.vimeo.com"))return null;b=$doc.createElement("a");b.href=c;c=Sc(b,"pathname");b=Tm(pg(Sc(b,"search"),1));a:{var d;d=lg(c,"/");for(c=d.length-1;0<=c&&"video"!==d[c];c--)if(0<d[c].length){c=d[c];break a}c=null}if(null==c)return null;2<=Ok&&(W("Vimeo embed extracted:"),W("    ID:    "+c));return new Kq(a,"vimeo",c,b)}function Qq(){Nq()}n(134,1,{},Qq);_.Cb=function(a){return Pq(a)};
_.Db=function(){return Oq};var Oq;t(134);function Rq(){Rq=k;Sq=new Zi;R(Sq,"IFRAME");R(Sq,"OBJECT")}
function Tq(a){var b,c,d;if(!a||!S(Sq,a.tagName))return null;d=null;"IFRAME"===a.tagName?d=a.src:"OBJECT"===a.tagName&&("application/x-shockwave-flash"===A(a,"type")?d=A(a,"data"):(b=a.querySelectorAll('param[name\x3d"movie"]'),1==b.length&&(d=A(b[0],"value"))));if(null==d||!Om(d,"youtube.com"))return null;c=d.indexOf("?");0>c&&(c=d.indexOf("\x26"));0>c&&(c=d.length);b=d.substr(0,c);d=Tm(d.substr(c+1,d.length-(c+1)));a:{c=lg(b,"/");for(b=c.length-1;0<=b&&"embed"!==c[b];b--)if(0<c[b].length){b=c[b];
break a}b=null}if(null==b)return null;2<=Ok&&(W("YouTube embed extracted:"),W("    ID:    "+b));return new Kq(a,"youtube",b,d)}function Uq(){Rq()}n(135,1,{},Uq);_.Cb=function(a){return Tq(a)};_.Db=function(){return Sq};var Sq;t(135);
function Zk(a,b,c){if(!(1>Ok))if(b){W("\u001b[0;34m\x3c\x3c\x3c\x3c\x3c "+c+" \x3e\x3e\x3e\x3e\x3e");if(!(1>Ok)){b="";for(c=new M(a.a);c.b<c.d.J();)a=(y(c.b<c.d.J()),c.d.T(c.c=c.b++)),b+=xq(a)+"\n";W(b)}W("\u001b[0;34m\x3c\x3c\x3c\x3c\x3c                \x3e\x3e\x3e\x3e\x3e")}else W("\u001b[0;31m~~~~~ No Changes: "+c+" ~~~~~")}
function $k(){$k=k;al=RegExp("(^(comments|\u00a9 reuters|please rate this|post a comment|\\d+\\s+(comments|users responded in))|what you think\\.\\.\\.|add your comment|add comment|reader views|have your say|reader comments|r\u00e4tta artikeln|^thanks for your comments - this feedback is now closed$)","i")}var al;function kl(){kl=k;ll=new Vq(!1);ol=new Vq(!0)}
function jl(a,b){var c,d,e,f,g;c=b.a;if(2>c.b.length)return!1;d=!1;g=(z(0,c.b.length),c.b[0]);for(f=new rh(c,1);f.b<f.d.J();)c=(y(f.b<f.d.J()),f.d.T(f.c=f.b++)),c.a&&g.a?(e=N(c.j,N(c.i,0).a).j-N(g.j,N(g.i,g.i.b.length-1).a).j-1,1>=e?(e=!0,a.a?g.f!=c.f&&(e=!1):S(c.b,"BOILERPLATE_HEADING_FUSED")&&(e=!1),S(g.b,"STRICTLY_NOT_CONTENT")!=S(c.b,"STRICTLY_NOT_CONTENT")&&(e=!1),S(g.b,"de.l3s.boilerpipe/TITLE")!=S(c.b,"de.l3s.boilerpipe/TITLE")&&(e=!1),!g.a&&S(g.b,"de.l3s.boilerpipe/LI")&&!S(c.b,"de.l3s.boilerpipe/LI")&&
(e=!1),e?(Xk(g,c),qh(f),d=!0):g=c):g=c):g=c;return d}function Vq(a){this.a=a}n(85,1,{},Vq);_.tS=function(){return Xa(Wq),Wq.n+": postFiltering\x3d"+this.a};_.a=!1;var ol,ll,Wq=t(85);function Xq(){Xq=k;cl=RegExp("[\\?\\!\\.\\-\\:]+","g")}function Yq(a,b,c){var d,e;e=lg(b,c);if(1!=e.length)for(b=0;b<e.length;b++)d=e[b],-1==d.indexOf(".com")&&(c=(U(),Fk.Bb(d)),4<=c&&R(a,d))}
function Zq(a,b){var c,d,e,f,g,l;l=lg(a,b);if(1==l.length)return null;d=0;e="";for(c=0;c<l.length;c++)if(g=l[c],-1==g.indexOf(".com")&&(f=(U(),Fk.Bb(g)),f>d||g.length>e.length))d=f,e=g;return 0==e.length?null:ug(e)}
function bl(a){Xq();var b;if(a)for(this.a=new Zi,a=Lh(a,0);a.b!=a.d.c;){b=(y(a.b!=a.d.c),a.c=a.b,a.b=a.b.a,++a.a,a.c.c);var c=void 0;b=zf(b);b=Af(b,"'");b=ug(b).toLowerCase();0!=b.length&&R(this.a,b)&&(c=Zq(b,"[ ]*[\\|\u00bb|-][ ]*"),null!=c&&R(this.a,c),c=Zq(b,"[ ]*[\\|\u00bb|:][ ]*"),null!=c&&R(this.a,c),c=Zq(b,"[ ]*[\\|\u00bb|:\\(\\)][ ]*"),null!=c&&R(this.a,c),c=Zq(b,"[ ]*[\\|\u00bb|:\\(\\)\\-][ ]*"),null!=c&&R(this.a,c),c=Zq(b,"[ ]*[\\|\u00bb|,|:\\(\\)\\-][ ]*"),null!=c&&R(this.a,c),c=Zq(b,"[ ]*[\\|\u00bb|,|:\\(\\)\\-\u00a0][ ]*"),
null!=c&&R(this.a,c),Yq(this.a,b,"[ ]+[\\|][ ]+"),Yq(this.a,b,"[ ]+[\\-][ ]+"),R(this.a,Yf(b," - [^\\-]+$")),R(this.a,Yf(b,"^[^\\-]+ - ")))}else this.a=null}n(136,1,{},bl);var cl;t(136);function pl(){pl=k;ql=new $q(!0)}function $q(a){this.a=a}n(87,1,{},$q);_.a=!1;var ql;t(87);function ar(a,b,c){b=N(a.d,b);c=N(a.d,c);return a.c||(b.nodeType!=c.nodeType?0:1!=b.nodeType||b.nodeName===c.nodeName)?b.parentNode==c.parentNode:!1}
function hl(a,b){var c,d,e,f,g,l,m,q,v,I;a.g=b.a;if(2>a.g.b.length)return!1;d=a.g;e=$doc.documentElement;l=new Q;for(f=0;f<d.b.length;++f){g=f+1==d.b.length?e:vq((z(f+1,d.b.length),d.b[f+1]));0==f?m=e:(m=(z(f-1,d.b.length),d.b[f-1]),m=rl(N(m.j,N(m.i,m.i.b.length-1).a)));v=m;m=vq((z(f,d.b.length),d.b[f]));for(q=m.parentNode;!q.contains(v)&&!q.contains(g);)m=q,q=q.parentNode;l.b[l.b.length]=m}a.d=l;l=E(br,{3:1},0,a.g.b.length,7);q=m=0;d=E(br,{3:1},0,a.g.b.length,7);f=e=0;g=!1;for(v=0;v<a.g.b.length;v++)if(!a.b&&
wq(N(a.g,v),"de.l3s.boilerpipe/TITLE")||!a.a&&wq(N(a.g,v),"de.l3s.boilerpipe/HEADING"))m=q,e=f;else if(N(a.g,v).a&&!wq(N(a.g,v),"STRICTLY_NOT_CONTENT")&&!wq(N(a.g,v),"de.l3s.boilerpipe/TITLE"))for(l[q++]=v,I=e;I<f;I++)c=d[I],v-c>a.e?I==e&&++e:ar(a,v,c)&&(g=!0,dl(N(a.g,c),!0),d[I]=d[e++]);else if(N(a.g,v).c<=a.f&&!N(a.g,v).a&&!wq(N(a.g,v),"STRICTLY_NOT_CONTENT")&&!wq(N(a.g,v),"de.l3s.boilerpipe/TITLE")){for(I=m;I<q;I++)if(c=l[I],v-c>a.e)I==m&&++m;else if(ar(a,v,c)){g=!0;dl(N(a.g,v),!0);l[I]=l[m++];
break}I==q?d[f++]=v:l[q++]=v}return g}function cr(a,b,c,d,e){this.b=a;this.a=b;this.c=c;this.f=d;this.e=e}n(138,1,{},cr);_.a=!1;_.b=!1;_.c=!1;_.e=0;_.f=0;t(138);function gl(){var a=new dr;a.a=!0;return a}function il(a){return new cr(a.b,a.a,a.c,a.e,a.d)}function dr(){this.c=this.a=this.b=!1;this.d=this.e=0}n(84,1,{},dr);_.a=!1;_.b=!1;_.c=!1;_.d=0;_.e=0;t(84);function ml(){ml=k;nl=new er("de.l3s.boilerpipe/TITLE")}function er(a){this.a=a}n(86,1,{},er);var nl;t(86);
function el(){el=k;fl=new fr(D(w(p,1),h,2,4,["STRICTLY_NOT_CONTENT"]))}function fr(a){this.a=a}n(137,1,{},fr);var fl;t(137);
function gr(a,b){var c,d,e,f,g,l,m;m=mm(b);g=l=!1;m||(a.i&&a.d&&(a.f||(g=b.classList.contains("hidden")),(a.f||g)&&(l=!0)),a.i&&(-1!=A(b,"class").indexOf("continue")&&(l=!0),"false"===A(b,"aria-expanded")&&(l=!0)));var q=m||l,v;2>Ok||(v=getComputedStyle(b,null),W((q?"KEEP ":"SKIP ")+b.tagName+": id\x3d"+b.id+", dsp\x3d"+v.display+", vis\x3d"+v.visibility+", opaq\x3d"+v.opacity));if(!m&&!l)return R(a.e,b),!1;try{if(S(a.b,b.tagName))for(f=new M(a.c);f.b<f.d.J();)if(e=(y(f.b<f.d.J()),f.d.T(f.c=f.b++)),
d=e.Cb(b))return c=a.a,Vk(c,c.d),P(c.b.a,d),!1}catch(I){if(I=Cc(I),r(I,15))c=I,W("Exception happened in EmbedExtractors: "+c.q());else throw Dc(I);}c=A(b,"class");d=A(b,"data-component");if("sharing"===c||"socialArea"===c||"share"===d)return!1;Cr(b.tagName)&&(d=a.a,e=new Jr(b.tagName,(xl(),yl)),Vk(d,d.d),P(d.b.a,e));switch(b.tagName){case "A":if(c=-1!=b.href.indexOf("action\x3dedit\x26section\x3d"))return!1;break;case "SPAN":if("mw-editsection"===c)return!1;break;case "BR":return g=a.a,g.c&&(Vk(g,
g.d),++g.d,g.c=!1),g=g.g,g.j+="\n",P(g.a,b),!1;case "TABLE":c=Qp(b);2>Ok||(d=B(b),W("TABLE: "+c+", id\x3d"+b.id+", class\x3d"+A(b,"class")+", parent\x3d["+d.tagName+", id\x3d"+d.id+", class\x3d"+A(d,"class")+"]"));if(c==(Z(),Vp))return g=a.a,Vk(g,g.d),P(g.b.a,new Kr(b)),!1;break;case "VIDEO":return g=a.a,c=new Lr(b),Vk(g,g.d),P(g.b.a,c),!1;case "OPTION":case "OBJECT":case "EMBED":case "APPLET":return a.a.c=!0,!1;case "HEAD":case "STYLE":case "SCRIPT":case "LINK":case "NOSCRIPT":case "IFRAME":case "svg":return!1}c=
a.a;Rr();f=getComputedStyle(b,null);d=new Sr;e=b.tagName;switch(f.display){case "inline":break;case "inline-block":case "inline-flex":d.a=!0;break;case "block":if("none"!==f["float"]&&"SPAN"===e)break;default:d.b=!0,d.a=!0}if("HTML"!==e&&"BODY"!==e&&"ARTICLE"!==e)switch(l=A(b,"class"),f=b.classList.length,m=A(b,"id"),(Tr.test(l)||Tr.test(m))&&2>=f&&(f=d.d,f[f.length]="STRICTLY_NOT_CONTENT"),e){case "ASIDE":case "NAV":e=d.d;e[e.length]="STRICTLY_NOT_CONTENT";break;case "LI":e=d.d;e[e.length]="de.l3s.boilerpipe/LI";
break;case "H1":e=d.d;e[e.length]="de.l3s.boilerpipe/H1";e=d.d;e[e.length]="de.l3s.boilerpipe/HEADING";break;case "H2":e=d.d;e[e.length]="de.l3s.boilerpipe/H2";e=d.d;e[e.length]="de.l3s.boilerpipe/HEADING";break;case "H3":e=d.d;e[e.length]="de.l3s.boilerpipe/H3";e=d.d;e[e.length]="de.l3s.boilerpipe/HEADING";break;case "H4":case "H5":case "H6":e=d.d;e[e.length]="de.l3s.boilerpipe/HEADING";break;case "A":d.a=!0,b.hasAttribute("href")&&(d.c=!0)}P(c.a.a,d);d.a&&++c.f;d.c&&(e=c.g,e.e=!0,e.j+=" ");c.c|=
d.b;c=(Te(),a.f?We:Ue);P(a.g.a,c);a.f|=g;return!0}function Qk(a){var b;this.g=new jk;this.e=new Zi;this.a=a;this.c=new Q;P(this.c,new Gq);P(this.c,new Mq);P(this.c,new Qq);P(this.c,new Uq);this.b=new Zi;for(b=new M(this.c);b.b<b.d.J();)a=(y(b.b<b.d.J()),b.d.T(b.c=b.b++)),Wg(this.b,a.Db())}n(123,1,{},Qk);
_.mb=function(a){if(1==a.nodeType&&Cr(a.tagName)){var b=this.a;a=new Jr(a.tagName,(xl(),Ur));Vk(b,b.d);P(b.b.a,a)}b=this.a;a=b.a;var c;c=a.a.b.length;if(0<c)a=(hk(c-1,a.a.b.length),N(a.a,c-1));else throw new $h;a.a&&--b.f;if(b.c||a.b)Vk(b,b.d),++b.d;a.c&&(a=b.g,a.e=!1,a.j+=" ");ik(b.a);this.f=ik(this.g).a};
_.nb=function(a){switch(a.nodeType){case 3:var b=this.a;b.c&&(Vk(b,b.d),++b.d,b.c=!1);var c=b.g,b=b.f,d;d=a.data;d.length&&(c.j+=d,P(c.a,a),Gp(d)||(a=(U(),Fk.Bb(d)),c.i+=a,c.e&&(c.g+=a),c.f=c.a.b.length-1,c.d<c.c&&(c.d=c.f),-1==c.b&&(c.b=b)));return!1;case 1:return gr(this,a);default:return!1}};_.d=!1;_.f=!1;_.i=!1;t(123);function Rr(){Rr=k;Tr=/\bcomments?\b/}function Sr(){this.d=[]}n(179,1,{},Sr);_.a=!1;_.b=!1;_.c=!1;var Tr;t(179);function Vr(){this.a=new Q}n(116,1,{},Vr);t(116);
function Vk(a,b){var c;c=a.g;var d=a.e;c.c==c.a.b.length?c=null:c.d<c.c?(Wr(c),c=null):(d=new Xr(c.j,c.a,c.c,c.a.b.length,c.d,c.f,c.i,c.g,c.b,d),Wr(c),c=d);if(c){c.d=b;++a.e;var e,f;for(e=new M(a.a.a);e.b<e.d.J();)for(d=(y(e.b<e.d.J()),e.d.T(e.c=e.b++)),f=0;f<d.d.length;f++)R(c.e,d.d[f]);P(a.b.a,c)}}function Pk(){this.b=new Vr;this.a=new jk;this.g=new Yr;this.d=0}n(122,1,{},Pk);_.c=!1;_.d=0;_.e=0;_.f=0;t(122);n(215,1,{});_.p=!1;t(215);
function Kq(a,b,c,d){this.a=new Q;this.b=c;P(this.a,a);this.c=b;!d&&new Yi}n(57,215,{},Kq);_.Eb=function(a){if(a)return"";a=$doc.createElement("div");a.className="embed-placeholder";a.setAttribute("data-type",this.c);a.setAttribute("data-id",this.b);return a.outerHTML};t(57);function Zr(){Zr=k;$r=D(w(p,1),h,2,4,["data-srcset"])}
function zl(a){var b,c,d,e,f,g,l,m;f=a.d.cloneNode(!0);c="IMG"==f.tagName?f:Im(f,"IMG");a.e.length&&(c.src=a.e,a.e=c.src);0<a.f&&0<a.c&&(c.width=a.f,c.height=a.c);Fm(c);m=f.getElementsByTagName("SOURCE");for(g=0;g<m.length;g++)for(l=m[g],c=$r,d=0,e=c.length;d<e;++d)if(b=c[d],b=A(l,b),b.length){l.setAttribute("srcset",b);break}Pm(f);Qm(f);a.b=f}function Fq(a,b,c,d){Zr();this.d=a;this.f=b;this.c=c;this.e=d;null==this.e&&(this.e="")}n(32,215,{32:1},Fq);
_.Eb=function(a){if(a)return"";!this.b&&zl(this);return this.b.outerHTML};_.c=0;_.f=0;var $r;t(32);function Eq(a,b,c,d,e){Zr();Fq.call(this,a,b,c,d);this.a=e}n(186,32,{32:1},Eq);_.Eb=function(a){var b;b=Bl(Cl(this.a));if(a)return Nm(b);a=$doc.createElement("FIGURE");var c=(!this.b&&zl(this),this.b);a.appendChild(c);!this.a.innerHTML.length||a.appendChild(b);return a.outerHTML};t(186);function Kr(a){this.b=a}n(68,215,{68:1},Kr);
_.Eb=function(a){!this.a&&(this.a=Bl(Cl(this.b)));return a?Nm(this.a):this.a.outerHTML};t(68);function as(){as=k;bs=new Zi;R(bs,"UL");R(bs,"OL");R(bs,"LI");R(bs,"BLOCKQUOTE");R(bs,"PRE")}function Jr(a,b){as();this.a=a;this.b=b}function Cr(a){as();return S(bs,a)}n(51,215,{51:1},Jr);_.Eb=function(a){return a?"":"\x3c"+(this.b==(xl(),yl)?"":"/")+this.a+"\x3e"};var bs;t(51);function xl(){xl=k;yl=new cs("START",0);Ur=new cs("END",1)}function cs(a,b){C.call(this,a,b)}n(52,9,{3:1,11:1,9:1,52:1},cs);
var Ur,yl,ds=u(52,function(){xl();return D(w(ds,1),ea,52,0,[yl,Ur])});function sl(a){return N(a.a,a.c)}function es(){$||($=new Zi,R($,"B"),R($,"BIG"),R($,"I"),R($,"SMALL"),R($,"TT"),R($,"ABBR"),R($,"ACRONYM"),R($,"CITE"),R($,"CODE"),R($,"DFN"),R($,"EM"),R($,"KBD"),R($,"STRONG"),R($,"SAMP"),R($,"TIME"),R($,"VAR"),R($,"A"),R($,"BDO"),R($,"IMG"),R($,"MAP"),R($,"Q"),R($,"SPAN"),R($,"SUB"),R($,"SUP"),R($,"BUTTON"),R($,"INPUT"),R($,"LABEL"),R($,"SELECT"),R($,"TEXTAREA"));return $}
function rl(a){return N(a.a,a.f)}function Xr(a,b,c,d,e,f,g,l,m,q){this.o=a;this.a=b;this.k=c;this.b=d;this.c=e;this.f=f;this.i=g;this.g=l;this.e=new Zi;this.n=m;this.j=q}n(35,215,{35:1},Xr);
_.Eb=function(a){var b,c,d;if(S(this.e,"de.l3s.boilerpipe/TITLE"))return"";d=new th(this.a,this.k,this.b);var e;if(1==d.b)b=gn(new en((z(0,d.b),N(d.c,d.a))));else{c=(z(0,d.b),N(d.c,d.a));b=c.cloneNode(!1);for(d=new dn(d);d.a;)if(fn(d,c)){if(!d.a)break;for(;;){for(e=c.nextSibling;e&&!e.contains(d.a);)e=e.nextSibling;if(e){b=uq(b,c.parentNode);b=sq(b,e);c=e;break}c=c.parentNode;b=uq(b,c)}}else{for(c=c.firstChild;!c.contains(d.a);)c=c.nextSibling;b=sq(b,c)}for(;b.parentNode;)b=b.parentNode}1!=b.nodeType&&
(c=B(sh(new th(this.a,this.k,this.b),0)).cloneNode(!1),c.appendChild(b),b=c);"BODY"===b.tagName&&(c=$doc.createElement("div"),c.innerHTML=b.innerHTML||"",b=c);for(d=null;S(es(),b.tagName);){d||(d=Sk(new th(this.a,this.k,this.b)),1!=d.nodeType&&(d=B(d)));d=B(d);if("BODY"===d.tagName)break;c=d.cloneNode(!1);c.appendChild(b);b=c}Em(b);Dm(b,"TARGET",D(w(p,1),h,2,4,["A"]));Dm(b,"ID",D(w(p,1),h,2,4,["*"]));c=b;1==c.nodeType&&c.hasAttribute("class")&&(-1!=A(c,"class").indexOf("caption")?c.className="caption":
c.removeAttribute("class"));c=c.querySelectorAll("[class]");for(d=0;d<c.length;d++)-1!=A(c[d],"class").indexOf("caption")?c[d].className="caption":c[d].removeAttribute("class");Dm(b,"COLOR",D(w(p,1),h,2,4,["FONT"]));Dm(b,"STYLE",D(w(p,1),h,2,4,["*"]));return a?Nm(b):Cr(b.tagName)?b.innerHTML:b.outerHTML};_.b=0;_.c=0;_.d=0;_.f=0;_.g=0;_.i=0;_.j=0;_.k=0;_.n=0;var $=null;t(35);function Wr(a){a.j="";a.i=0;a.g=0;a.c=a.a.b.length;a.b=-1}function Yr(){this.a=new Q}n(155,1,{},Yr);_.b=-1;_.c=0;_.d=-1;
_.e=!1;_.f=0;_.g=0;_.i=0;_.j="";t(155);function Lr(a){this.a=a}n(178,215,{},Lr);_.Eb=function(a){var b,c;if(a)return"";c=this.a.cloneNode(!1);for(a=0;a<this.a.childNodes.length;a++)b=this.a.childNodes[a],1!=b.nodeType||"SOURCE"!==b.tagName&&"TRACK"!==b.tagName||(b=b.cloneNode(!1),c.appendChild(b));c.poster.length&&(c.poster=c.poster);Pm(c);Dm(c,"ID",D(w(p,1),h,2,4,["*"]));return c.outerHTML};t(178);n(217,1,{});
_.Gb=function(a){var b;b=0;a&&(b=this.Fb(a));2<=Ok&&W(Za(this.cZ)+": "+b+"/"+this.Hb());return hf(b,this.Hb())};t(217);function tl(){this.b=25;this.c=75E3;this.a=2E5}n(156,217,{},tl);_.Fb=function(a){a=((a.offsetWidth||0)|0)*((a.offsetHeight||0)|0);if(a<this.c)return 0;a=Wa((a-this.c)/(this.a-this.c)*this.b);return hf(a,this.b)};_.Hb=function(){return this.b};_.a=0;_.b=0;_.c=0;t(156);function ul(){this.a=25}n(157,217,{},ul);
_.Fb=function(a){var b,c;b=(a.offsetHeight||0)|0;if(0>=b)return 0;c=(a.offsetWidth||0)|0;a=0;b=c/b;1.4500000476837158<b&&1.7999999523162842>b?a=1:1.2999999523162842<b&&2.200000047683716>b&&(a=0.4000000059604645);return Wa(this.a*a)};_.Hb=function(){return this.a};_.a=0;t(157);function vl(a){this.b=25;this.a=a}n(158,217,{},vl);
_.Fb=function(a){var b;if(!this.a)return 0;a=Lm(this.a).b.length-1-(Lm(Jm(this.a,a)).b.length-1);b=0;4>a?b=1:6>a?b=0.6000000238418579:8>a&&(b=0.20000000298023224);return Wa(this.b*b)};_.Hb=function(){return this.b};_.b=0;t(158);function wl(){this.a=15}n(159,217,{},wl);_.Fb=function(a){var b;a=Lm(a);for(b=new M(a);b.b<b.d.J();)if(a=(y(b.b<b.d.J()),b.d.T(b.c=b.b++)),1==a.nodeType&&"FIGURE"===a.tagName)return this.a;return 0};_.Hb=function(){return this.a};_.a=0;t(159);var br,fs;fs=kb("I");fs.k="I";
fs.f=1;br=fs;t(198);t(200);t(null);t(203);hj=mb();_=function(a){var b=this;if("$wnd"==a)return $wnd;if(""===a)return b;"$wnd."==a.substring(0,5)&&(b=$wnd,a=a.substring(5));a=a.split(".");a[0]in b||!b.execScript||b.execScript("var "+a[0]);for(var c;a.length&&(c=a.shift());)b[c]?b=b[c]:b=b[c]={};return b}("org.chromium.distiller.DomDistiller");_.apply=function(){var a;return Kk((a={},a))};_.applyWithOptions=Kk;
function gs(a){return function(){var b;a:{var c=arguments,d;0!=ic&&(d=Date.now?Date.now():(new Date).getTime(),2E3<d-kc&&(kc=d,jc=$wnd.setTimeout(hc,10)));if(0==ic++){d=(lc(),mc);var e,f;if(d.a){f=null;do e=d.a,d.a=null,f=Bc(e,f);while(d.a);d.a=f}d=!0}else d=!1;try{b=a.apply(this,c);break a}finally{if(c=d)if(d=(lc(),mc),d.b){f=null;do e=d.b,d.b=null,f=Bc(e,f);while(d.b);d.b=f}--ic;c&&-1!=jc&&($wnd.clearTimeout(jc),jc=-1)}b=void 0}return b}}
var gwtOnLoad=gwtOnLoad=function(a,b,c){function d(){for(var a=0;a<e.length;a++)e[a]()}null==oa&&(oa=[]);var e=oa;$moduleName=b;$moduleBase=c;if(a)try{gs(d)()}catch(f){a(b,f)}else gs(d)()};(function(){null==oa&&(oa=[]);for(var a=oa,b=0;b<arguments.length;b++)a.push(arguments[b])})(function(){$wnd.setTimeout(gs(Pe));var a,b,c;b=$doc.compatMode;a=D(w(p,1),h,2,4,["CSS1Compat"]);for(c=0;c<a.length&&a[c]!==b;c++);});var hs=[[["locale","default"],["user.agent","safari"]]];
"object"===typeof window&&"object"===typeof window.$gwt&&(window.$gwt.permProps=hs);window.gwtOnLoad=gwtOnLoad;gwtOnLoad(undefined, "domdistiller", "", 0);})();
      // clang-format on
    }
    window.setTimeout = function() {};
    window.clearTimeout = function() {};
    initialize();

    // The OPTIONS placeholder will be replaced with the DomDistillerOptions at
    // runtime.
    var distiller = window.org.chromium.distiller.DomDistiller;
    var res = distiller.applyWithOptions(options);

    if (stringify_output) {
      return JSON.stringify(res);
    }
    return res;
  } catch (e) {
    window.console.error("Error during distillation: " + e);
    if (e.stack != undefined) window.console.error(e.stack);
  }
  return undefined;
})($$OPTIONS, $$STRINGIFY)
/* Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* Set the global 'box-sizing' state to 'border-box'.
 * *::after and *::before used to select pseudo-elements not selectable by *. */

*,
*::after,
*::before {
  box-sizing: border-box;
}

/* Remove all margins and padding from certain element and add word wrap. */

blockquote,
body,
caption,
dd,
dl,
fieldset,
figure,
form,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
legend,
ol,
p,
pre,
ul,
table,
td,
th {
  margin: 0;
  padding: 0;
  word-wrap: break-word;
}

/* Prevent 'sub' and 'sup' affecting 'line-height'. */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sup {
  top: -0.5em;
}

sub {
  bottom: -0.25em;
}

/* Remove most spacing between table cells. */

table {
  border-collapse: collapse;
  border-spacing: 0;
  display: block;
  overflow-x: auto;
}

td,
th {
  padding: 0.5rem;
}

/* Base typography. */

html {
  font-size: 14px;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  line-height: 1.714;
  margin: 0px auto;
  text-rendering: optimizeLegibility;
  transition-property: color, background-color;
  transition-duration: 0.5s;
  transition-timing-function: ease;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}

/* Classes for light, dark and sepia themes.
 * Must agree with classes returned by useTheme() in dom_distiller_viewer.js
 * and with CSS class constants in viewer.cc */

.light {
  color: #424242;
  background-color: #FAFAFA;
}

.dark {
  color: #E0E0E0;
  background-color: #212121;
}

.sepia {
  color: #000;
  background-color: rgb(203, 173, 141);
}

.light a:link,
.sepia a:link {
  color: #55F;
}

.dark a:link {
  color: #88F;
}

.light a:visited,
.sepia a:visited {
  color: #902290;
}

.dark a:visited {
  color: #D872D8;
}

.light code,
.light pre {
  background-color: #EEE;
  border-color: #AAA;
}

.sepia code,
.sepia pre {
  background-color: rgb(217, 196, 175);
  border-color: rgb(147, 125, 102);
}

.dark code,
.dark pre {
  background-color: #333;
  border-color: #555;
}

.light tbody tr:nth-child(odd) {
  background-color: #EEE;
}

.light th, .light td {
  border-left: 1px solid #AAA;
}

.sepia tbody tr:nth-child(odd) {
  background-color: rgb(217, 196, 175);
}

.sepia th, .sepia td {
  border-left: 1px solid rgb(147, 125, 102);
}

.dark tbody tr:nth-child(odd) {
  background-color: #333;
}

.dark th, .dark td {
  border-left: 1px solid #555;
}

/* #contentWrap is added to be more specific than the color theme rules */
#contentWrap th:first-child { border-left: none; }
#contentWrap td:first-child { border-left: none; }


/* Font settings */

.serif {
  font-family: serif;
}

.sans-serif {
  font-family: 'Roboto', sans-serif;
}

.monospace {
  font-family: monospace;
}

/* Define vertical rhythm (baseline grid of 4px). */

blockquote,
caption,
code,
dd,
dl,
fieldset,
figure,
form,
hr,
legend,
ol,
p,
pre,
q,
table,
td,
th,
ul {
  margin-bottom: 1.143rem;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  line-height: 1.417;
  margin: 1em 0;
}

/* Content. */

#loadingIndicator {
  width: 100%;
  padding-bottom: 2em;
}

#loadingIndicator > img, #loadingIndicator > svg {
  display: block;
  height: 2.5em;
  margin: auto;
  width: 2.5em;
}

/* Margins for Show Original link. */

.light #closeReaderView {
  border-top: 1px solid #E0E0E0;
  color: #4285F4;
}

.dark #closeReaderView {
  border-top: 1px solid #555;
  color: #3adaff;
}

.sepia #closeReaderView {
  border-top: 1px solid rgb(147, 125, 102);
  color: #55F;
}

video::-webkit-media-controls-fullscreen-button {
  display: none;
}

#closeReaderView {
  /*
  TODO(mdjones): Remove the "display: none;" style when the Reader Mode bar
                 behaves like the toolbar when scrolling.
  */
  display: none;
  flex: 0 0 auto;
  font-family: 'Roboto', sans-serif;
  font-weight: 700;
  line-height: 14px;
  padding: 24px 16px;
  font-size: 14px;
  text-align: right;
  text-decoration: none;
  text-transform: uppercase;
  width: 100%;
}

#content {
  margin: 24px 16px 24px 16px;
}

#mainContent {
  flex: 1 1 auto;
  margin: 0px auto;
  width: 100%;
}

@media screen {
  #mainContent {
    max-width: 35em;
  }
}

#articleHeader {
  margin-top: 24px;
  width: 100%;
}

#titleHolder {
  font-size: 1.714rem;
  line-height: 1.417;
  margin: 0 16px;
}

blockquote {
  border-left: 4px solid #888;
  padding-left: 1em;
}

cite {
  opacity: .8;
  font-style: italic;
}

hr {
  opacity: .5;
  border-style: solid;
  height: 1px 0 0 0;
  width: 75%;
}


q {
  opacity: .8;
  display:block;
  font-style: italic;
  font-weight: 600;
}

embed,
img,
object,
video {
  max-width: 100%;
}

/* TODO(sunangel): make images zoomable. */

img {
  display: block;
  height: auto;
  margin: 0.6rem auto 0.4rem auto;
}

/* TODO(nyquist): set these classes directly in the dom distiller. */

embed+[class*='caption'],
figcaption,
img+[class*='caption'],
object+[class*='caption'],
video+[class*='caption'] {
  opacity: .8;
  display: table;
  margin-bottom: 1rem;
  font-size: 0.857rem;
  line-height: 1.667;
}

ol,
ul {
  margin-left: 1.296rem;
}

code, pre {
  border: 1px solid;
  border-radius: 2px;
}

pre code {
  border: none;
}

pre {
  line-height: 1.642;
  padding: .5em;
  white-space: pre-wrap;
}

body .hidden {
  display: none;
}

.clear {
  clear: both;
}

/* Iframe sizing. */
.youtubeContainer {
  height: 0px;
  /* This is the perecnt height of a standard HD video. */
  padding-bottom: 56.25%;
  position: relative;
  width: 100%;
}

.youtubeIframe {
  height: 100%;
  left: 0px;
  position: absolute;
  top: 0px;
  width: 100%;
}

/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* The following are iOS specific rules for rendering on WebKit instead of
 * Blink. */

#mainContent {
  -webkit-flex: 1 1 auto;
}

#closeReaderView {
  -webkit-flex: 0 0 auto;
}

#contentWrap {
  -webkit-flex-flow: column;
  display: -webkit-flex;
}
<svg version="1" xmlns="http://www.w3.org/2000/svg"
                 xmlns:xlink="http://www.w3.org/1999/xlink"
     width="16px" height="16px" viewBox="0 0 28 28">
  <!-- 28= RADIUS*2 + STROKEWIDTH -->

  <title>Material design circular activity spinner with CSS3 animation</title>
  <style type="text/css">
      /**************************/
      /* STYLES FOR THE SPINNER */
      /**************************/

      /*
       * Constants:
       *      RADIUS      = 12.5
       *      STROKEWIDTH = 3
       *      ARCSIZE     = 270 degrees (amount of circle the arc takes up)
       *      ARCTIME     = 1333ms (time it takes to expand and contract arc)
       *      ARCSTARTROT = 216 degrees (how much the start location of the arc
       *                                should rotate each time, 216 gives us a
       *                                5 pointed star shape (it's 360/5 * 2).
       *                                For a 7 pointed star, we might do
       *                                360/7 * 3 = 154.286)
       *
       *      SHRINK_TIME = 400ms
       */

      .qp-circular-loader {
        width:28px;  /* 2*RADIUS + STROKEWIDTH */
        height:28px; /* 2*RADIUS + STROKEWIDTH */
      }
      .qp-circular-loader-path {
        stroke-dasharray: 58.9;  /* 2*RADIUS*PI * ARCSIZE/360 */
        stroke-dashoffset: 58.9; /* 2*RADIUS*PI * ARCSIZE/360 */
                                 /* hides things initially */
      }

      /* SVG elements seem to have a different default origin */
      .qp-circular-loader, .qp-circular-loader * {
        -webkit-transform-origin: 50% 50%;
      }

      /* Rotating the whole thing */
      @-webkit-keyframes rotate {
        from {-webkit-transform: rotate(0deg);}
        to {-webkit-transform: rotate(360deg);}
      }
      .qp-circular-loader {
        -webkit-animation-name: rotate;
        -webkit-animation-duration: 1568.63ms; /* 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */
        -webkit-animation-iteration-count: infinite;
        -webkit-animation-timing-function: linear;
      }

      /* Filling and unfilling the arc */
      @-webkit-keyframes fillunfill {
        from {
          stroke-dashoffset: 58.8 /* 2*RADIUS*PI * ARCSIZE/360 - 0.1 */
                                  /* 0.1 a bit of a magic constant here */
        }
        50% {
          stroke-dashoffset: 0;
        }
        to {
          stroke-dashoffset: -58.4 /* -(2*RADIUS*PI * ARCSIZE/360 - 0.5) */
                                   /* 0.5 a bit of a magic constant here */
        }
      }
      @-webkit-keyframes rot {
        from {
          -webkit-transform: rotate(0deg);
        }
        to {
          -webkit-transform: rotate(-360deg);
        }
      }
      @-webkit-keyframes colors {
        from {
          stroke: #4285f4;
        }
        to {
          stroke: #4285f4;
        }
      }
      .qp-circular-loader-path {
        -webkit-animation-name: fillunfill, rot, colors;
        -webkit-animation-duration: 1333ms, 5332ms, 5332ms; /* ARCTIME, 4*ARCTIME, 4*ARCTIME */
        -webkit-animation-iteration-count: infinite, infinite, infinite;
        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1), steps(4), linear;
        -webkit-animation-play-state: running, running, running;
        -webkit-animation-fill-mode: forwards;
      }

  </style>

  <!-- 3= STROKEWIDTH -->
  <!-- 14= RADIUS + STROKEWIDTH/2 -->
  <!-- 12.5= RADIUS -->
  <!-- 1.5=  STROKEWIDTH/2 -->
  <!-- ARCSIZE would affect the 1.5,14 part of this... 1.5,14 is specific to
       270 degress -->
  <g class="qp-circular-loader">
    <path class="qp-circular-loader-path" fill="none" 
          d="M 14,1.5 A 12.5,12.5 0 1 1 1.5,14" stroke-width="3"
          stroke-linecap="round"></path>
  </g>
</svg>

// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

(function() {
  function hasOGArticle() {
    var elems = document.head.querySelectorAll(
        'meta[property="og:type"],meta[name="og:type"]');
    for (var i in elems) {
      if (elems[i].content && elems[i].content.toUpperCase() == 'ARTICLE') {
        return true;
      }
    }
    return false;
  }

  var body = document.body;
  if (!body) {
    return false;
  }
  return JSON.stringify({
     'opengraph': hasOGArticle(),
     'url': document.location.href,
     'numElements': body.querySelectorAll('*').length,
     'numAnchors': body.querySelectorAll('a').length,
     'numForms': body.querySelectorAll('form').length,
     'innerText': body.innerText,
     'textContent': body.textContent,
     'innerHTML': body.innerHTML,
  });
})()
d	     A@kHUfJ?      |@q]
W?      ?Y[]?      @͇;п       ?
?	     @@@F_ȿ      /@z+pN?   C@Z?	     @@@b ƿ    gE@FG=   Z<@}qU?    ?@M¿      #@p	$?     B@C4,㵿    rW@":?    gE@y7mr      @>"2z	     Q@I$Ĺ?      @Xct   G@Q{Ho?   `@?G4?   `*C?AЪs5   ?9Wr?   `ƃ?Ul9     C@vk{      @y       ?8.2?	     ;@&	     Q@4%l?      @!      @OC=?      @Kut泿    a?济Ȗ豿     ;@?~3?     z@s(ǰ      ]@F]n?     0b@.      @?      ?ngp      N@jEhԲ?      !@s     C@$_      @ebJ   ?WQ?   ?R     x@V33r(?     l@     ]@hD6?     `W@o{!      ?8}O=?      @^     ]@e.-?     v@BĀꩿ     hs@71FJ?   pګ?uS';    @+!믿   0>`@R7V8?      @/LeA     U@x9     ;@h&x?     z@h-	      /@0x)Ы?     @D@\^˅	     N@x?	     B@݄諿      ?S6[?      ?:X,      @>8X?   `@?Qv.?    ?Pa-hƭ   PT?b?   0
?H~    K?F%X?   06{?el     @D@\?     U@/n      ?eG:o     x@:]?     l@=C     `@!?   p8H@Q   59@ʮ?     @K@eGG   @G wa?     @G@zHF   59@Myi.5?     @K@dj     ;@)c?    a?}橿    @rH	     Q@|1@|Rk?   PT?<2?   0
?53dZ   `@?(#?    ?NS=w   PT?./.?   0
?,jrHH禿   {?,l?      @,X	My    a?uRdbd   0@@2; )?     ?@X6?       ?0"?     @?q ?   }NY@&/X?      ?#\^z3?    %e@@>!ϰگ     @A{O}?     @Vcி      @ Z,@N?	      %@Rii?     @@@`qI     P@K~5?     p@}|#o?   `@@LJ㬿   H@{?   p6d@ցzx   ߺ?ď㓥     @(x8?     0n@z3{   `-g?:\a>?   `_V]@\o=q?	     1@F\?      ?oWVT	     @I@^      @?     @]~A?   `@@St*   E@3|?   `@@ܹ}:z͠     $@
1?   `
@j.̢   PC?;짿     hv@P?	      !@X?      ?ʈhDf?     D@dֳ     w@4D(?     @T\6     t@_iI?     @(.➿   Ь$@k?      W@7$`     8r@|?   ߺ?ۀj   #?(?   ?B6"z   1g@@     @/&k?   `=d@Cs     R@zQX?      @]20c?     ;@F\    %e@@qQQC   E@bN?      @V?	     <@#	     2@
0?      ?#O?    ڶ@:)
z   `-g?~}c?   p45?.&      |@a5~?     O@As?	     @J@      @<?     .@ cg읿      W@a=Q	      @?     w@6[?     @ڳ9i㚿     C@7`?   0>?	     `@.?     |@}&?   @:Q@jetĚ      @YE>?    y&6@x   M@`<Ǘ?   1g@.     R@D@?     O@X:     t@e^?     n@     pc@W!gԖ?     (@!On     Xv@|ZNV?      R@Ҋ:W     @?D?    IYT@ҷc     $@.˼?    %e@@j(     ^@07:?   `=d@/#b      ?7zA   ?4z?   p45?CY   |?y꧖?    c]?(P   `-g?.s?     <ks8+v̘#+sLruHH*>$S`@$Aޙ-F'oG9#h7^AGApj̫{BE8Y{0A.[ "uɁ,e[M9;h	q׻!0ZqNLj$gЏ;vD6y~9uD6^
;?
$"[3j4[j	"t9ur9!`\#MܐȽt#u/X1WSKlK8փeфFĦ24cρ8#'g32r9v66#g8dLHמsx~0 1<M=0i(?z,33@)A>|upGܷopd'=טpp4HcwVe>ˡ5U0ҭ6Q> 9 vr:TPr=ˏ`;5dw.
6I}̙51 6iu:	\	pk0V3kuK2 S=V`FtrGG~:wnlàa|T`T@P$i@"PJswr}Nl
ut!*P`MVNb>K
T}%dN	VJN{_:)꺅vC]{B	K!x=G֣"8WlE}	[1IZ<+d|
vA'LRW,)P7Jx_ PFnF=q\fSqԐ7 ^Wpס3 }%̺ECI57H)8g(Q?hp?ġȟɜ8 +_NberD|8%'3ٷ(x}c9橀8쉑}ub.{`2Af@#w!<hJJ2~Fo94=wFl'\!ċ7qg6.}avVv]3{џ-'/ힿq_|_'ckkH;3Ν;myC36KcK{Oo[__ٯ?MWo'kxs|nοG_?jO;{Wzr|u<<GS;<i)~>o;k^L?ܞ.]ۂۋ٭|#׺G wcw#]v秃*KƮwWg,LaHwG
殜遟v>/axpzxxqc7ytg}Xst@sbj,GMu)!{ӕso|t|<]A:@U!^+=Ys֜Z@7{-W-NxݚFڻ怑VXɈ	vE)4m
x8O~ori>cOCxwN|lq<
xVoOn1X>糕}t;4n;ZvW}+s.A>ʞ/d'"`ޥ/sw]fyuJj$/_vY@sj
n!Y,@U rސ[Ә>LޜjZn4C$e5Oϣ*
fY^'E:*K,<n&PU*Rۑ}_CR4ʪ0^K6X\oѤc5ֻIna#fwLIx+=e/^T{{H[Ig7pȦyUVWzV[li,8<=[t:MqV`-E:Ȫݬg9լZP'(:y5D\}Po!w@t9
WD]7hԡ<։
ndO@M:FBWeYK_C.wƾ8轨d&h k$$D\3K8ӵyWF}Fk6bh+7jc̒E.,(YY2i$3l2h];Q-|i(W*gQVbpE7TH?˸X>],|RyzΚf@Nv9>;Hx
=o	%7eKDmfl?$MBlA[̕aఠy22S薥z>JrV3lbmWю!澛( Mv]v5"FVGTf^baP$ʯ,.HZ,TzqV/T5C6Қ@
oGi&,sYKV*4RzhY&ww2Ų VX*-(Z\tXX*!q3dd@G4ah$6Q#1愘ab\15n%f^K,#|Ib/|pi>^Z&LZHK jNff5Qt%h{ǺԎ5%3\NtV-{(oW#lI\2Vl:Mum9KsGbɺ׹uď;wJy"+8W=fx׹^91ɇ*c{ZU]Wj.e3*
b*#4ΘR]4AQ٢&?t)Jz鮻K ˰)mA)5J]NmZI+Kn|&TOW^%>=GKkoczV8FKkՊ-VT
J.&<-hs~lpi z.ꍒӭͺһgkL7g(}b|drnc>;֛)J_GG[בJЁYvQ2W-7H2i*M1yJ1^%W+@׷6 ]7tuT;)ͪ|v+qUdЍq^&ٻ4x'mgGU{ܑO6ī<$l㓾iG.O!AAD.$ ِY2O&@ z՜P5kF69]x($S#P؈֬l>>Ej$V7@%!)Ph`7I:Bvw7J6ЦX#>"(M"g)=:})IC'}^OqbX!HW)Jb_fI+,D,+A{[I	jy6w WRZ~dB>ˡɈb/x'2b09:Z!KlC&ab ~@{w +P!CqP&93sy
RapWmX/y.q]Y+̞Pc֐EVƈs%!2}N<O3\p8;K^;Ohg.\;+l$=W@7FK'@˝WGsP(w3#A&=zI]PHSPgM.`> 8\p75hNd6EJؿ&P3\N..cĲ e`i(yI	% *n4uG7}12WodSIzd3#cVjOSݦJV#ee$D6KAT@=YC,!ex`!,PHϜML0&m=C6Ae[]EO+D΂Ēk
sLu[:_BM61Э<2y]7q'^Ș4ҀQxJךfѐ<4)ZQ]JVsIB/ZJkAmnI*LgZQԖ4YR D}s捣	-nYr"_&:)̱D徑&JR#NB\/_Eќ}0sm&kG32rGpd 	hKr5WsJͬ6(HK|1&xFLBҕt/'GAC䭧rJK:R*`r$͈1C%aV	=ҟ	ҟ	ҟ	ҟ	=A#G>9p3GEvH¤D	9qWwd,r_7\L<'i|"{yIkt#xR(pR\A=C17Xh"~sʭˌ[;\: 4s׵9FԞ>>'~T[!_'ɼsC^jȾ,#38.{i_OpU8jb]l7˽~RL'0Ëk|_r-nHfE{ Y6\)ʇ;շ/?2Nc4k*܍o6ko<^dJO>[P1SJ       ;ksȑ+ƾ\U]I\dՕ޲U9*ɑ@  xkc$r`@OwOgxp fij]Q8|r-lUnIY\$jK-;{⃖"]biRi$|]w2Od$[7S]lc)baDL˴L"x.۳狹XX{{' ]`xtaQDl-o(ˍL
RC-|TMDt!!lix+4+`53.etiPaYY _1+kAlJ.@!`"% K%sX b\1uō{X#>%"YQm$.n#X;ڢKF`wbh{,Y&(T8;5R¶aecAyKI֎[LBd~i<n,~̉lEn@
6NSڈVdᗣDދ I!a[>-x|ܜDX"cE$بahM~<+d,ҫ2m%yf;6rլM5q)@Pe*Gb_D$WVZM,0; Z\f\}:f}fKFgbekvgC4Rk0'=r`	XGH3Ģ?us僽@Xxg
+it1%*)@k)?sEEYiMvoe'Ƥ`)%`}Tb?k 9- A -]&2yĹ7U%k]IePŨRJEU,\j wEZŰAP}"c+WEFS֒q(!]s`6^EP^ec'*YP
SQm+"=0aQ{$%<#i}VR[i"2KkG&4bԖJjF*|v7YL7n,@TP\Cc^.KBQh 2cPM||A_Up:f@U^wUEUTUyZiH|\z틏R$ -<X$S+Aq|Jޏ`ZDZwvYd, mQ&E,dިSD˱!ϵ G^}߶Ai@X9(k\ZxZ6DKBƎqS*#/82F8kAX~B<kq.76]X[#<7x6 d	TLMDL7h+`j=3wN&MDG7$dJ\*MXH]Z^m'3šO-W}O\!@C殆ڣJnOojjL}A؃9X@K*svC	Nqe`4ZHH@NpOOK72%^#l>%<SȂ1PZB6U.nϝd=&;BATr.uU36ܦߤ&vϰĠY
Q.>1#Ă`5t 59HپC&m7X8Z1Þ%oz2C͎teioOFAY5PxfX3 	o₷k 1Y5 	x3ʆd"LF`w#
Fd@H Q4䇄!fm4 1L[8bM%6^eVA h軣>{yzLhrv~j,74 lު|WP>0siaYٙ6`snkH3`ʒʻ瀽Fc'=_sf_D}bb"3.z c}f&TQ; 	V[@ȯ. 
"`[g"z=H,wp_Y4Vb}6nSu{~=`-5o/ݴk<Gse$IL;;(se b8"qWG2	4k]jj0UMybr
mz	xH8Q63t0!B"{<rm$TkUaըgSPP^X<&9)]YkrZ+dS>MU$f8[h6c-qlK#-3>VSX|c˱z81ciWd;럿ኡM|-*M]%^xCQߎNm0i`:ݺW`'zgh"P˭w)hG}}c-~6kFZGIs7Q0 nB}"C<f#Wmf#!Y4CKr?/m'6ig|YrPnQ;Cĕ+Jr=d
yuwc3JܮRTz#Qe?u	6oG ٗv|1/x?93mXn N6/yb.ˊh
,1ԓ3Vf}-샂0㝳v|ɝ֬Vf<
g6,:Ǜ:tWO$!30Y82+8WAS 橌-jnQC n#znE.se|~~ͻ?חg?_UÒXB7ahdbebI@a.?p:Ntg}A*;7Q"KtMU34(c[x$f6umnM@+Nqڡ,^Gw`ΧHQFz$Ai T0]"64d!_u/ԶPj>[

y Zyx«jV<jI6.G):i6H=}=sa$8Dk 8>ɺk٢h-z.#@X.3\"=ȸ:<ϧ6zhˡu}9f﬽s ȝ4ǲowPy9˓65:Mx%G"QƹLКW$>w}&zSɞg]Pйh"c0C\8h6R!> G5O¡so,dL-@F8M9'w[Qf8/8m])Sx lR:׎d<UVb|7;0LHb?Uzi	F1HX	^Gg\8x\љA#FJlUU->B(xe-JTk%	GfShH~u˃OiJp{?Uh-կyGHߦ2A}j-m̱x! >n^r73R:k|b1ٍ*O?d+7[ɡxpv#K;"	rF=zeD4vB/0d8IƹwWB8@LxR_0=^lx]O3W*-.:;Wl]KhmJbH!8s\sۘYmylkEƿԃiZ{,a3 y  h;<֥SD7DSmYix6#ro}sވs+}1֚Ĉ8]%wnҚQzo蛱Q>[۪Z:&"`~iE~;ңAQFsuHu¾ّ^U>5.Ӊ?L+UPfo1%HMM]'u5Em@s1H7*9('HF#472D{
*ZB BשljnNy
DxSo<CO}cru'"snStzND5iEo!?Wضp=}oj㽡vCJFA|[m~۬=jaxpTIW#TӫG*']:[._K8{M81kG-C=5îfÚ
rl36d*G\!֞#jsb㏢өv1oe<P*سeTNa)Fd_Яz:.P;r:~h&s	*Jb-UQƺ3M",t_TϨ^-4qDtP;3w&\hĭ1O53Vw6!>OJ? 8o>       Xr6)Lv&-n3*Wv:I2m=P @L>R_iId:HrqEPiuR\{{.?Y
%?GP29Ys36ϑ3DƳ@:E /6hO#
[b5dI Nh,O#c%FPhFyIѨ$1Jk$	X>KPU-&QCMlfM!tzہAPc0@!W5h~<=$"GIf`r&anIBś4t|"sU*= =tzgg7ez" ܢb9ϝ޼WAq^(ڈ&9 '濎3/~<"W{Sc%m{Sl1 '67G;m&Nk8#m6ͬU6PQ,XՐ`,$ofXqY)&:RMbF&VsLxLH]!aÇTerYkQY0:XDt=Yzl?R1~e8>;:ά(N]iOĲˬIUH\զDNsZKaFԘ"ކ4	7r]D٥eۥKyLǔH]7iB.R2E?;YM1ߧ!^qw]IK7h$mT,s=$ޮZђ. (FJ6aţvPt~urP#-ab<XEt#=yٰIMcЊ58a)P=vع7;=ڲ?qD*)xyclه+fB@v3׫>=Q׏'Ġ#YUQw4;uch%85CGp}3jA]ܐUӎi?s//4Տ_#;ӍfҸO&a9(?Ҝj._X6XdC(mŜ*u]|No<¿~;iFo(7c#Q7eWJJan2,ҟ>WkDlaIBP!Zv)Tp0ZX4_NVlAnQxA83-	cl5_Yvu|= SPoL6cW~tO]Yŵy
       }Rj0+rIȱ]o.mK5T+٥+if3̓6sinFiv{Zؗh&,`/4ynap
!; [TП@/A04eAZ11n
:·O06EkU@$7;੿C6м>ƻlUJf)g"_|<׹AAQNi q%ش(C\~_	shykm⹄|9:+&;QY{YG<uOq^G.DVKn		؇Iƨ+s AHCSe)&dÛr#bGJxrԓdKańa       X[o8~ϯ`촱YS=6dvɴ3I-[YԐ] }sH|k
C"sRLz{?S|֬̕t׵ύu.
HNX],9:%B\;LmS%R)ץY+[L̷B?LJ:U%|.He)8-L]fB8WnvV,t&ZRGtuWz0]E]^r|.>bTV~4=ZZRc3].ŕXPM#}ܣ^._Z-X].4_$V҉ʚJYV
<{YzX'RZѻ7Eݙᖈ ڍi !FVI`JZ0RĻZst\Uܒ^*:G2|KoD6[~λ1	w2ilv%~wS|"%0 'J 8KD+)l]v%:p)&"&XdvvTw b{4{b$eeQ4qG}*NSºݏ%nf2IAY&ܖr^zMT|=I3+4׻(S>|٥׎rgǉѥb'	с^.KG
c-a
,W]$ǩJ^_@eʪ캪2*έ*ě;2VzeE`L{8AʄDj"%k
ܵL6@bF|yO4Sg(ET^~Bf*5yJDvNЙw3P	i`Mca\в,l[n aZ A')΁S5s1:ee֣l{7m%@h<I΁ƍn.<nOO
U.}>o"Jd&Y`x-bD|D=v-kB|TlJ!WUһ~↶ڈ IOۧ?Aɋdn'~kϠqG.sgt:#s|t裁XwPzm?L47Z4t
\ӛty^}@hBi7SR8#yp>诇糖m8ANEwC[TGyHMEk0Kw@T.z[-rӥZ-h	|SL@LDN o5VY,##1
˺<H}#wz
#4kȓa(aLo+JDQV:#{b Kc2T:\JNsΙTshnWTDjΠ*)^jNVM=M9a(a7MuFE+(b_&Y>^pKZC
	NSYk0nЃ{V܊Vx3?@~<\c%gn$fXxX+,_0PROoe9wջq	3gbuԂL52ns~pȇ@Zܯ8nۜ;ܤvI/KM{UmNsKu$FÛ7ðw4Pc?9i;ީPv>q-饫cbȬ"M@AkKnKSUP6/lo|>nog[y{q;1v_>.[=hg{xCLnBji~Ӹ$k?TZsFrػ;Da|[)ZO߇*V|x.CYV|B=lȢ< "96S].\lBh~_0l؝_4;n;tHӳg5{'52|-F}N:U ˈˍ       Yr۸0Ӊ]wɕ3H (YWi\U2#
o?5~ĬKb27_R0H24Ӡ2`2N/hId(Reѯ:_u0GɧJ')Єx_Jem?)xq
iZM N֑{sU!V{zsY_dCxu|--^pVL*=3!m_Zb:KI#9kB"SKTٻб,ɘ4U/hazy~~vs.Xk hcaB#woh%gj`fyx&QS9W<5;c,:]U"WQJ.[ 2{)I-[ZaM%"ݐo,Myx!OdD
Fox}Ţ*g/}X9-CR.Z0KoZ׭v늩
0qehwkLNpYU,d&\QwM撂\sYH]k2HJf"}Bzi)x
YlmḶ#y6lt3n=Tw0pI;7W8i}Go{ 8ZOg+*L aƦWy	WXÒkSƊ\ρ	_.mP!ّtYW;N~T2VkY*Of_/m4X+)4i+>OiVČ)]۞T
cqǾ
zZ4LfNiqT$iM29aĝϱo0WNʈ֒j,ZrTZWy̌)5fao(""OAR%!z^aJ=:h	҇d[؎6h2CtzXs.ZrI*B6rFqZwbxӄa9'Wn.:Uˢ9y0q]t&+z0ZZ:RI&Kè#JH:FbZEYJބK)3
vrOrzOAudח?\ܾ;9M)f5x䁹ܚ+};kRxu4yY3r$8j`w%Xغ[5ܗ;_n.f{TVl8qSF[|L=ϩ`&8q@=yᔤV5{EqȜm:xk+
U!xNU'=~FOl,+]OPʲ9p34 K
;'ޝ+.fz?rɊiԈHEk
+6(xɰ)| \#vdEw'y-0)[B;qI%VԌQЍXN]*V7=Gn鹖NXNoQInȂ`­_鄊vyDRwknQ?b?y GZQjf4>A.c:{9jV:7rޑdW)~Ǉd<ՇۛnZ+Zl3CBnd1,6]G~3ZP۱%/$<]AGf%@^OAEr3Hkz灳Q!"9<vhot,uݷ+6^m~c#ޢ}z>OP?`Hͷ{KYv`A,L{MO#@"FQT4A8PQnpYHB͡t{)Ztk}WPm5];ۑߎ)7VI(gvy\訉[{%K2v7wk{۲87q
:\:@R#pO`f
i9ɕ}8kjYG*vMPB,R59z	bt$_^lluQE:]wn
>]	[*+[mjI)kWǛUpTpfZzr^
xT.~֣V&^hwB5#gE6X0jH!U}'Xx߮[G?+tuJ6Ē;EN9QOI&U^j#(0:`1+-A,\"AWWL;Qwd|Q`m_OLtYc>Qsw_'.}Jsޓf :x!ˁlԿxnw%~?SRyL       ZoۼQr+O}JamR4
(Zm.Q]A))|Eߑ9>fTr2,Jf+ޭZjTft7Yhbɴ(ވ4R0`f%KVJ'%*Tsq|R]&X&2%<gsS&sr-d&{ɮ8|;V(,TZV`+^L5d/*OT9Lh0v-Bi)Ri^`Z^1OӋRFBGw*78FیhXY:C$/K'O3QZxVL64epJ/3aTnẫ:;cQ}BwQ-Fu'Z<L[88\HglTI&{s{K0E;7}so*
_sqBVk/Z=U7beۙk5HRœ	#{;^J+,aOO
YK!]ܒ"0>?>^)-.es;<0~|yd!EQb[w2
||d2O,tſn!1yQ\w}	F&`o|UbcA"8	(K@ȏHrebG0t7E@ZTlFi(ka(
-ƑJQ-Wo܎c`M1_D癸_$8^1% QWY|[Ca tVb2B<g*kg4&30a)7]EsoXr8v;ZRbU( I0`4dgnJݭC4A_sgC
"X8vD 977<3l*trO0Pes@fWZ𼕗+(ki	@*XVzs-*Q~4ghׂnWbNpu)C7QW^$,M:׎['YrvtĈ"n
P/h:Ax__j?jtr0.$vD8쇳*M@KU8%Q73UZmUJ"ۍ)TZF-I>u0 @Bg$crd_<pkQW<QM}Dٙy)QH<y@*CB9|ZE*:=,-G+BX=-V$-5\Zgl(pm4PV%ĭJlrϋs6d]ZuZlW"	:LRti+, qBN&אv@~d:a(jL@#h6%eAd;Lm7vʶ2B1r)0(:C	`|l'/:A?c̎dh*b
Uq}7=rb}81BG*^!hP7RU%9߈ ]5M1tPXY%	#a`͇`: +w+ai^K{;'OwSCub'P"QؐHq"foE#4!1'qWc,1^njjVHpI@@I]49v|a.kd7Oo&P52jdZ6gN[VMslH2,av@N["9(M~<o(L;pNC՟_6j L8/5Ihm@#s{M_y 먎.|6`[LĹkhnӅ.Fs@gsP{+ZZ AĤ
D-2t.\m4yV-G+q~HZHk	8Щy )@
ʭ44>gNx)بu૟U\"55CR=[u"?d|J4aU~6)<$^kAq$KNd^YԤ䯝ґ噦{rpݜD
&N ʇUe!rbHxileQl~aeiLm
x[	2Ie?mjʄ}8$ duT0u$aQ?;PNZ"=⮤sYyF}"µp#	H^J46-:
fFſ<AХHcrwZ_cρ@ZDNk.˲`["JXc`j瀽p
9Sȝa!cA-h#K9BK	LA;,L"DTb!چ5h
>{>:ƺc>'cp-ƫV9"x5ِmyz,4-g:$nid/'qҊw\)_6k
TK!ǠɜVKcD}빎Rǭ疷/x^{g<'gqjݸ7Z1LoV$XCK?Y> 'e_cdo@]@H[4'Z݇ྯ=m.T{|T3f)5[⸧g33ڣg}z(C0@}u#x 	jg?3	ZTU|Ad#9קԳJX
NGP+1><"Zp>)KGh8SwO)XМ@ tuBdt:۩`gW]鉉0Aj wA:߽t2dqUU"Y?\퍎"q-͵nm>>MdTMϩ9pds3iՁۨi:WqoM\p uFI_xnϭ[R8^4hpo
>{:}6MH륭"+o)`_"G}3怾r[*TtFUԿxs<1ogf	\v~tc+hb/'  <!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <meta name="theme-color" content="#fff">
  <meta name="viewport" content="width=device-width, initial-scale=1.0,
                                 maximum-scale=1.0, user-scalable=no">
  <title>$i18n{title}</title>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

a {
  color: rgb(88, 88, 88);
}

body {
  --google-blue-600: rgb(26, 115, 232);
  --google-blue-700: rgb(25, 103, 210);
  --google-gray-50: rgb(248, 249, 250);
  --google-gray-300: rgb(218, 220, 224);
  --google-gray-500: rgb(154, 160, 166);
  --google-gray-600: rgb(128, 134, 139);
  --google-gray-700: rgb(95, 99, 104);
  background-color: #fff;
  color: var(--google-gray-700);
  word-wrap: break-word;
}

.nav-wrapper .secondary-button {
  background: #fff;
  border: 1px solid var(--google-gray-500);
  color: var(--google-gray-700);
  float: none;
  margin: 0;
  padding: 8px 16px;
}

.hidden {
  display: none;
}

html {
  -webkit-text-size-adjust: 100%;
  font-size: 125%;
}

.icon {
  background-repeat: no-repeat;
  background-size: 100%;
}
</style>
  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
   Use of this source code is governed by a BSD-style license that can be
   found in the LICENSE file. */

button {
  border: 0;
  border-radius: 4px;
  box-sizing: border-box;
  color: #fff;
  cursor: pointer;
  float: right;
  font-size: .875em;
  margin: 0;
  padding: 8px 16px;
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

[dir='rtl'] button {
  float: left;
}

.bad-clock button,
.captive-portal button,
.main-frame-blocked button,
.neterror button,
.offline button,
.pdf button,
.ssl button,
.safe-browsing-billing button {
  background: var(--google-blue-600);
}

button:active {
  background: var(--google-blue-700);
  outline: 0;
}

#debugging {
  display: inline;
  overflow: auto;
}

.debugging-content {
  line-height: 1em;
  margin-bottom: 0;
  margin-top: 1em;
}

.debugging-content-fixed-width {
  display: block;
  font-family: monospace;
  font-size: 1.2em;
  margin-top: 0.5em;
}

.debugging-title {
  font-weight: bold;
}

#details {
  margin: 0 0 50px;
}

#details p:not(:first-of-type) {
  margin-top: 20px;
}

.secondary-button:active {
  border-color: white;
  box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .3),
      0 2px 6px 2px rgba(60, 64, 67, .15);
}

.secondary-button:hover {
  background: var(--google-gray-50);
  border-color: var(--google-gray-600);
  text-decoration: none;
}

.error-code {
  color: #646464;
  font-size: .86667em;
  text-transform: uppercase;
  margin-top: 12px;
}

#error-debugging-info {
  font-size: 0.8em;
}

h1 {
  color: var(--google-gray-900);
  font-size: 1.6em;
  font-weight: normal;
  line-height: 1.25em;
  margin-bottom: 16px;
}

h2 {
  font-size: 1.2em;
  font-weight: normal;
}

.icon {
  height: 72px;
  margin: 0 0 40px;
  width: 72px;
}

input[type=checkbox] {
  opacity: 0;
}

input[type=checkbox]:focus ~ .checkbox {
  outline: -webkit-focus-ring-color auto 5px;
}

.interstitial-wrapper {
  box-sizing: border-box;
  font-size: 1em;
  line-height: 1.6em;
  margin: 14vh auto 0;
  max-width: 600px;
  width: 100%;
}

#main-message > p {
  display: inline;
}

#extended-reporting-opt-in {
  font-size: .875em;
  margin-top: 39px;
}

#extended-reporting-opt-in label {
  position: relative;
  display: flex;
  align-items: flex-start;
}

.nav-wrapper {
  margin-top: 51px;
}

.nav-wrapper::after {
  clear: both;
  content: '';
  display: table;
  width: 100%;
}

.small-link {
  color: #696969;
  font-size: .875em;
}

.checkboxes {
  flex: 0 0 24px;
}

.checkbox {
  background: transparent;
  border: 1px solid white;
  border-radius: 2px;
  display: block;
  height: 14px;
  left: 0;
  position: absolute;
  right: 0;
  top: 3px;
  width: 14px;
}

.checkbox::before {
  background: transparent;
  border: 2px solid white;
  border-right-width: 0;
  border-top-width: 0;
  content: '';
  height: 4px;
  left: 2px;
  opacity: 0;
  position: absolute;
  top: 3px;
  transform: rotate(-45deg);
  width: 9px;
}

input[type=checkbox]:checked ~ .checkbox::before {
  opacity: 1;
}

#recurrent-error-message {
  background: #ededed;
  border-radius: 4px;
  padding: 12px 16px;
  margin-top: 12px;
  margin-bottom: 16px;
}

.showing-recurrent-error-message #extended-reporting-opt-in {
  margin-top: 16px;
}

@media (max-width: 700px) {
  .interstitial-wrapper {
    padding: 0 10%;
  }

  #error-debugging-info {
    overflow: auto;
  }
}

@media (max-width: 420px) {
  button,
  [dir='rtl'] button,
  .small-link {
    float: none;
    font-size: .825em;
    font-weight: 500;
    margin: 0;
    width: 100%;
  }

  button {
    padding: 16px 24px;
  }

  #details {
    margin: 20px 0 20px 0;
  }

  #details p:not(:first-of-type) {
    margin-top: 10px;
  }

  .secondary-button:not(.hidden) {
    display: block;
    margin-top: 20px;
    text-align: center;
    width: 100%;
  }

  .interstitial-wrapper {
    padding: 0 5%;
  }

  #extended-reporting-opt-in {
    margin-top: 24px;
  }

  .nav-wrapper {
    margin-top: 30px;
  }
}

/**
 * Mobile specific styling.
 * Navigation buttons are anchored to the bottom of the screen.
 * Details message replaces the top content in its own scrollable area.
 */

@media (max-width: 420px) {
  .nav-wrapper .secondary-button {
    border: 0;
    margin: 16px 0 0;
    margin-inline-end: 0;
    padding-bottom: 16px;
    padding-top: 16px;
  }
}

/* Fixed nav. */
@media (min-width: 240px) and (max-width: 420px) and
       (min-height: 401px),
       (min-width: 421px) and (min-height: 240px) and
       (max-height: 560px) {
  body .nav-wrapper {
    background: #fff;
    bottom: 0;
    box-shadow: 0 -22px 40px #fff;
    left: 0;
    margin: 0 auto;
    max-width: 736px;
    padding-left: 24px;
    padding-right: 24px;
    position: fixed;
    right: 0;
    width: 100%;
    z-index: 2;
  }

  .interstitial-wrapper {
    max-width: 736px;
  }

  #details,
  #main-content {
    padding-bottom: 40px;
  }

  #details {
    padding-top: 5.5vh;
  }

  button.small-link {
    color: var(--google-blue-600);
  }
}

@media (max-width: 420px) and (orientation: portrait),
       (max-height: 560px) {
  body {
    margin: 0 auto;
  }

  button,
  [dir='rtl'] button,
  button.small-link {
    font-family: Roboto-Regular,Helvetica;
    font-size: .933em;
    margin: 6px 0;
    transform: translatez(0);
  }

  .nav-wrapper {
    box-sizing: border-box;
    padding-bottom: 8px;
    width: 100%;
  }

  #details {
    box-sizing: border-box;
    height: auto;
    margin: 0;
    opacity: 1;
    transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  #details.hidden,
  #main-content.hidden {
    display: block;
    height: 0;
    opacity: 0;
    overflow: hidden;
    padding-bottom: 0;
    transition: none;
  }

  h1 {
    font-size: 1.5em;
    margin-bottom: 8px;
  }

  .icon {
    margin-bottom: 5.69vh;
  }

  .interstitial-wrapper {
    box-sizing: border-box;
    margin: 7vh auto 12px;
    padding: 0 24px;
    position: relative;
  }

  .interstitial-wrapper p {
    font-size: .95em;
    line-height: 1.61em;
    margin-top: 8px;
  }

  #main-content {
    margin: 0;
    transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  .small-link {
    border: 0;
  }

  .suggested-left > #control-buttons,
  .suggested-right > #control-buttons {
    float: none;
    margin: 0;
  }
}

@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
  .interstitial-wrapper {
    margin-top: 10vh;
  }
}

@media (min-height: 400px) and (orientation:portrait) {
  .interstitial-wrapper {
    margin-bottom: 145px;
  }
}

@media (min-height: 299px) {
  .nav-wrapper {
    padding-bottom: 16px;
  }
}

@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and
       (orientation: portrait) {
  .interstitial-wrapper {
    margin-top: 7vh;
  }
}

@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
  .interstitial-wrapper {
    margin-top: 10vh;
  }
}

/* Small mobile screens. No fixed nav. */
@media (max-height: 400px) and (orientation: portrait),
       (max-height: 239px) and (orientation: landscape),
       (max-width: 419px) and (max-height: 399px) {
  .interstitial-wrapper {
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
  }

  #details {
    flex: 1 1 auto;
    order: 0;
  }

  #main-content {
    flex: 1 1 auto;
    order: 0;
  }

  .nav-wrapper {
    flex: 0 1 auto;
    margin-top: 8px;
    order: 1;
    padding-left: 0;
    padding-right: 0;
    position: relative;
    width: 100%;
  }

  button {
    padding: 16px 24px;
  }

  button.small-link {
    color: var(--google-blue-600);
  }
}

@media (max-width: 239px) and (orientation: portrait) {
  .nav-wrapper {
    padding-left: 0;
    padding-right: 0;
  }
}
</style>
  <style>/* Copyright 2013 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

/* Don't use the main frame div when the error is in a subframe. */
html[subframe] #main-frame-error {
  display: none;
}

/* Don't use the subframe error div when the error is in a main frame. */
html:not([subframe]) #sub-frame-error {
  display: none;
}

#diagnose-button {
  float: none;
  margin-bottom: 10px;
  margin-inline-start: 0;
  margin-top: 20px;
}

h1 {
  margin-top: 0;
  word-wrap: break-word;
}

h1 span {
  font-weight: 500;
}

h2 {
  color: #666;
  font-size: 1.2em;
  font-weight: normal;
  margin: 10px 0;
}

a {
  color: rgb(17, 85, 204);
  text-decoration: none;
}

.icon {
  -webkit-user-select: none;
  display: inline-block;
}

.icon-generic {
  /**
   * Can't access chrome://theme/IDR_ERROR_NETWORK_GENERIC from an untrusted
   * renderer process, so embed the resource manually.
   */
  content: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAENJREFUeF7tzbEJACEQRNGBLeAasBCza2lLEGx0CxFGG9hBMDDxRy/72O9FMnIFapGylsu1fgoBdkXfUHLrQgdfrlJN1BdYBjQQm3UAAAAASUVORK5CYII=) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQAQMAAADdiHD7AAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAFJJREFUeF7t0cENgDAMQ9FwYgxG6WjpaIzCCAxQxVggFuDiCvlLOeRdHR9yzjncHVoq3npu+wQUrUuJHylSTmBaespJyJQoObUeyxDQb3bEm5Au81c0pSCD8HYAAAAASUVORK5CYII=) 2x);
}

.icon-offline {
  content: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAGxJREFUeF7tyMEJwkAQRuFf5ipMKxYQiJ3Z2nSwrWwBA0+DQZcdxEOueaePp9+dQZFB7GpUcURSVU66yVNFj6LFICatThZB6r/ko/pbRpUgilY0Cbw5sNmb9txGXUKyuH7eV25x39DtJXUNPQGJtWFV+BT/QAAAAABJRU5ErkJggg==) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQBAMAAAAVaP+LAAAAGFBMVEUAAABTU1NNTU1TU1NPT09SUlJSUlJTU1O8B7DEAAAAB3RSTlMAoArVKvVgBuEdKgAAAJ1JREFUeF7t1TEOwyAMQNG0Q6/UE+RMXD9d/tC6womIFSL9P+MnAYOXeTIzMzMzMzMzaz8J9Ri6HoITmuHXhISE8nEh9yxDh55aCEUoTGbbQwjqHwIkRAEiIaG0+0AA9VBMaE89Rogeoww936MQrWdBr4GN/z0IAdQ6nQ/FIpRXDwHcA+JIJcQowQAlFUA0MfQpXLlVQfkzR4igS6ENjknm/wiaGhsAAAAASUVORK5CYII=) 2x);
  position: relative;
}

.icon-disabled {
  content: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABICAMAAAAZF4G5AAAABlBMVEVMaXFTU1OXUj8tAAAAAXRSTlMAQObYZgAAASZJREFUeAHd11Fq7jAMRGGf/W/6PoWB67YMqv5DybwG/CFjRuR8JBw3+ByiRjgV9W/TJ31P0tBfC6+cj1haUFXKHmVJo5wP98WwQ0ZCbfUc6LQ6VuUBz31ikADkLMkDrfUC4rR6QGW+gF6rx7NaHWCj1Y/W6lf4L7utvgBSt3rBFSS/XBMPUILcJINHCBWYUfpWn4NBi1ZfudIc3rf6/NGEvEA+AsYTJozmXemjXeLZAov+mnkN2HfzXpMSVQDnGw++57qNJ4D1xitA2sJ+VAWMygSEaYf2mYPTjZfk2K8wmP7HLIH5Mg4/pP+PEcDzUvDMvYbs/2NWwPO5vBdMZE4EE5UTQLiBFDaUlTDPBRoJ9HdAYIkIo06og3BNXtCzy7zA1aXk5x+tJARq63eAygAAAABJRU5ErkJggg==) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOAAAACQAQMAAAArwfVjAAAABlBMVEVMaXFTU1OXUj8tAAAAAXRSTlMAQObYZgAAAYdJREFUeF7F1EFqwzAUBNARAmVj0FZe5QoBH6BX+dn4GlY2PYNzGx/A0CvkCIJuvIraKJKbgBvzf2g62weDGD7CYggpfFReis4J0ey9EGFIiEQQojFSlA9kSIiqd0KkFjKsewgRbStEN19mxUPTtmW9HQ/h6tyqNQ8NlSMZdzyE6qkoE0trVYGFm0n1WYeBhduzwbwBC7voS+vIxfeMjeaiLxsMMtQNwMPtuew+DjzcTHk8YMfDknEcIUOtf2lVfgVH3K4Xv5PRYAXRVMtItIJ3rfaCIVn9DsTH2NxisAVRex2Hh3hX+/mRUR08bAwPEYsI51ZxWH4Q0SpicQRXeyEaIug48FEdegARfMz/tADVsRciwTAxW308ehmC2gLraC+YCbV3QoTZexa+zegAEW5PhhgYfmbvJgcRqngGByOSXdFJcLk2JeDPEN0kxe1JhIt5FiFA+w+ItMELsUyPF2IaJ4aILqb4FbxPwhImwj6JauKgDUCYaxmYIsd4KXdMjIC9ItB5Bn4BNRwsG0XM2nwAAAAASUVORK5CYII=) 2x);
  width: 112px;
}

.error-code {
  display: block;
  font-size: .8em;
}

#content-top {
  margin: 20px;
}

#help-box-inner {
  background-color: #f9f9f9;
  border-top: 1px solid #EEE;
  color: #444;
  padding: 20px;
  text-align: start;
}

.hidden {
  display: none;
}

#suggestion {
  margin-top: 15px;
}

#suggestions-list p {
  margin-block-end: 0;
}

#suggestions-list ul {
  margin-top: 0;
}

.single-suggestion {
  list-style-type: none;
  padding-left: 0;
}

#short-suggestion {
  margin-top: 5px;
}

#error-information-button {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiLz4KICAgIDxwYXRoIGQ9Ik0xMSAxOGgydi0yaC0ydjJ6bTEtMTZDNi40OCAyIDIgNi40OCAyIDEyczQuNDggMTAgMTAgMTAgMTAtNC40OCAxMC0xMFMxNy41MiAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4em0wLTE0Yy0yLjIxIDAtNCAxLjc5LTQgNGgyYzAtMS4xLjktMiAyLTJzMiAuOSAyIDJjMCAyLTMgMS43NS0zIDVoMmMwLTIuMjUgMy0yLjUgMy01IDAtMi4yMS0xLjc5LTQtNC00eiIvPgo8L3N2Zz4K);
  height: 24px;
  vertical-align: -.15em;
  width: 24px;
}

.use-popup-container#error-information-popup-container
  #error-information-popup {
  align-items: center;
  background-color: rgba(0,0,0,.65);
  display: flex;
  height: 100%;
  left: 0;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 100;
}

.use-popup-container#error-information-popup-container
  #error-information-popup-content > p {
  margin-bottom: 11px;
  margin-inline-start: 20px;
}

.use-popup-container#error-information-popup-container #suggestions-list ul {
  margin-inline-start: 15px;
}

.use-popup-container#error-information-popup-container
  #error-information-popup-box {
  background-color: white;
  left: 5%;
  padding-bottom: 15px;
  padding-top: 15px;
  position: fixed;
  width: 90%;
  z-index: 101;
}

.use-popup-container#error-information-popup-container div.error-code {
  margin-inline-start: 20px;
}

.use-popup-container#error-information-popup-container #suggestions-list p {
  margin-inline-start: 20px;
}

:not(.use-popup-container)#error-information-popup-container
  #error-information-popup-close {
  display: none;
}

#error-information-popup-close {
  margin-bottom: 0px;
  margin-inline-end: 35px;
  margin-top: 15px;
  text-align: end;
}

.link-button {
  color: rgb(66, 133, 244);
  display: inline-block;
  font-weight: bold;
  text-transform: uppercase;
}

#sub-frame-error-details {

  color: #8F8F8F;

  /* Not done on mobile for performance reasons. */
  text-shadow: 0 1px 0 rgba(255,255,255,0.3);

}

[jscontent=hostName],
[jscontent=failedUrl] {
  overflow-wrap: break-word;
}

#search-container {
  /* Prevents a space between controls. */
  display: flex;
  margin-top: 20px;
}

#search-box {
  border: 1px solid #cdcdcd;
  flex-grow: 1;
  font-size: 1em;
  height: 26px;
  margin-right: 0;
  padding: 1px 9px;
}

#search-box:focus {
  border: 1px solid rgb(93, 154, 255);
  outline: none;
}

#search-button {
  border: none;
  border-bottom-left-radius: 0;
  border-top-left-radius: 0;
  box-shadow: none;
  display: flex;
  height: 30px;
  margin: 0;
  padding: 0;
  width: 60px;
}

#search-image {
  content:
      -webkit-image-set(
          url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAPCAQAAAB+HTb/AAAArElEQVR4Xn3NsUoCUBzG0XvB3U0chR4geo5qihpt6gkCx0bXFsMERWj2KWqIanAvmlUUoQapwU6g4l8H5bd9Z/iSPS0hu/RqZqrncBuzLl7U3Rn4cSpQFTeroejJl1Lgs7f4ceDPdeBMXYp86gaONYJkY83AnqHiGk9wHnjk16PKgo5N9BUCkzPf5j6M0PfuVg5MymoetFwoaKAlB26WdXAvJ7u5mezitqtkT//7Sv/u96CaLQAAAABJRU5ErkJggg==) 1x,
          url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAeCAQAAACVzLYUAAABYElEQVR4Xr3VMUuVURzH8XO98jgkGikENkRD0KRGDUVDQy0h2SiC4IuIiktL4AvQt1CDBJUJwo1KXXS6cWdHw7tcjWwoC5Hrx+UZgnNO5CXiO/75jD/+QZf9MzjskVU7DrU1zRv9G9ir5hsA4Nii83+GA9ZI1nI1D6tWAE1TRlQMuuuFDthzMQefgo4nKr+f3dIGDdUUHPYD1ISoMQdgJgUfgqaKEOcxWE/BVTArJBvwC0cGY7gNLgiZNsD1GP4EPVn4EtyLYRuczcJ34HYMP4E7GdajDS7FcB48z8AJ8FmI4TjouBkzZ2yBuRQMlsButIZ+dfDVUBqOaIHvavpLVHXfFmAqv45r9gEHNr3y3hcAfLSgSMPgiiZR+6Z9AMuKNAwqpjUcA2h55pxgAfBWkYRlQ254YMJloaxPHbCkiGCymL5RlLA7GnRDXyuC7uhicLoKdRyaDE5Pl00K//93nABqPgBDK8sfWgAAAABJRU5ErkJggg==) 2x);
  margin: auto;
}

.secondary-button {
  background: #d9d9d9;
  color: #696969;
  margin-inline-end: 16px;
}

.snackbar {
  background: #323232;
  border-radius: 2px;
  bottom: 24px;
  box-sizing: border-box;
  color: #fff;
  font-size: .87em;
  left: 24px;
  max-width: 568px;
  min-width: 288px;
  opacity: 0;
  padding: 16px 24px 12px;
  position: fixed;
  transform: translateY(90px);
  will-change: opacity, transform;
  z-index: 999;
}

.snackbar-show {
  -webkit-animation:
    show-snackbar .25s cubic-bezier(0.0, 0.0, 0.2, 1) forwards,
    hide-snackbar .25s cubic-bezier(0.4, 0.0, 1, 1) forwards 5s;
}

@-webkit-keyframes show-snackbar {
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

@-webkit-keyframes hide-snackbar {
  0% {
    opacity: 1;
    transform: translateY(0);
  }
  100% {
    opacity: 0;
    transform: translateY(90px);
  }
}

.suggestions {
  margin-top: 18px;
}

.suggestion-header {
  font-weight: bold;
  margin-bottom: 4px;
}

.suggestion-body {
  color: #777;
}

/* Increase line height at higher resolutions. */
@media (min-width: 641px) and (min-height: 641px) {
  #help-box-inner {
    line-height: 18px;
  }
}

/* Decrease padding at low sizes. */
@media (max-width: 640px), (max-height: 640px) {
  h1 {
    margin: 0 0 15px;
  }
  #content-top {
    margin: 15px;
  }
  #help-box-inner {
    padding: 20px;
  }
  .suggestions {
    margin-top: 10px;
  }
  .suggestion-header {
    margin-bottom: 0;
  }
}

#download-link, #download-link-clicked {
  margin-bottom: 30px;
  margin-top: 30px;
}

#download-link-clicked {
  color: #BBB;
}

#download-link:before, #download-link-clicked:before {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxLjJlbSIgaGVpZ2h0PSIxLjJlbSIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik01LDIwSDE5VjE4SDVNMTksOUgxNVYzSDlWOUg1TDEyLDE2TDE5LDlaIiBmaWxsPSJyZ2IoNjYsIDEzMywgMjQ0KSIgLz4KPC9zdmc+);
  display: inline-block;
  margin-inline-end: 4px;
  vertical-align: -webkit-baseline-middle;
}

#download-link-clicked:before {
  width: 0px;
  opacity: 0;
}

#offline-content-list-visibility-card {
  border: 1px solid white;
  border-radius: 8px;
  display: flex;
  font-size: .8em;
  justify-content: space-between;
  line-height: 1;
}

#offline-content-list.list-hidden #offline-content-list-visibility-card {
  border-color: rgb(218, 220, 224);
}

#offline-content-list-visibility-card > div {
  padding: 1em;
}

#offline-content-list-title {
  color: var(--google-gray-700);
}

#offline-content-list-show-text, #offline-content-list-hide-text {
  color: rgb(66, 133, 244);
}

/* Hides the "hide" text div when the offline content list is collapsed/hidden
 * and, alternatively, hides the "show" text div when the offline content list
 * is expanded/shown.
 */
#offline-content-list.list-hidden #offline-content-list-hide-text,
#offline-content-list:not(.list-hidden) #offline-content-list-show-text {
  display: none;
}

/* Controls the animation of the offline content list when it is expanded/shown.
 */
#offline-content-suggestions {
  /* Max-height has to be set for the height animation to work. The chosen value
   * is a little greater than the maximum height the list will have, when all
   * suggestions have images, so that it is never clamped. This makes so that
   * when the actual height is smaller then the animation is not as smooth.
   */
  max-height: 27em;
  transition: max-height 0.2s ease-in, visibility 0s 0.2s,
              opacity 0.2s 0.2s linear;
}

/* Controls the animation of the offline content list when it is
 * collapsed/hidden.
 */
#offline-content-list.list-hidden #offline-content-suggestions {
  max-height: 0;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s linear, visibility 0s 0.2s,
              max-height 0.2s 0.2s ease-out;
}

#offline-content-list {
  margin-inline-start: -5%;
  width: 110%;
}

/* The selectors below adjust the "overflow" of the suggestion cards contents
 * based on the same screen size based strategy used for the main frame, which
 * is applied by the `interstitial-wrapper` class. */
@media (max-width: 420px)  {
  #offline-content-list {
    margin-inline-start: -2.5%;
    width: 105%;
  }
}
@media (max-width: 420px) and (orientation: portrait),
       (max-height: 560px) {
  #offline-content-list {
    margin-inline-start: -12px;
    width: calc(100% + 24px);
  }
}

.suggestion-with-image .offline-content-suggestion-visual {
  flex-basis: 8.2em;
  flex-shrink: 0;
}

.suggestion-with-image .offline-content-suggestion-visual > img {
  height: 100%;
  width: 100%;
}

#offline-content-list:not(.is-rtl) .suggestion-with-image
.offline-content-suggestion-visual > img {
  border-bottom-right-radius: 7px;
  border-top-right-radius: 7px;
}

#offline-content-list.is-rtl .suggestion-with-image
.offline-content-suggestion-visual > img {
  border-bottom-left-radius: 7px;
  border-top-left-radius: 7px;
}

.suggestion-with-icon .offline-content-suggestion-visual {
  align-items: center;
  display: flex;
  justify-content: center;
  min-height: 4.2em;
  min-width: 4.2em;
}

.suggestion-with-icon .offline-content-suggestion-visual > div {
  align-items: center;
  background-color: rgb(241, 243, 244);
  border-radius: 50%;
  display: flex;
  height: 2.3em;
  justify-content: center;
  width: 2.3em;
}

.suggestion-with-icon .offline-content-suggestion-visual > div > img {
  height: 1.45em;
  width: 1.45em;
}

.image-video {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik0xNywxMC41VjdBMSwxIDAgMCwwIDE2LDZINEExLDEgMCAwLDAgMyw3VjE3QTEsMSAwIDAsMCA0LDE4SDE2QTEsMSAwIDAsMCAxNywxN1YxMy41TDIxLDE3LjVWNi41TDE3LDEwLjVaIiBmaWxsPSIjM0M0MDQzIiAvPgo8L3N2Zz4=);
}

.image-music-note {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik0xMiwzVjEyLjI2QzExLjUsMTIuMDkgMTEsMTIgMTAuNSwxMkM4LDEyIDYsMTQgNiwxNi41QzYsMTkgOCwyMSAxMC41LDIxQzEzLDIxIDE1LDE5IDE1LDE2LjVWNkgxOVYzSDEyWiIgZmlsbD0iIzNDNDA0MyIgLz4KPC9zdmc+);
}

.image-earth {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8cGF0aCBkPSJNMTIsMiBDMTcuNTIsMiAyMiw2LjQ4IDIyLDEyIEMyMiwxNy41MiAxNy41MiwyMiAxMiwyMiBDNi40OCwyMiAyLDE3LjUyIDIsMTIgQzIsNi40OCA2LjQ4LDIgMTIsMiBaIE00LDEyIEw4LjM5OTY1NzM4LDEyIEMxMS44MDY5NTY0LDEyLjAyMTY3MDMgMTMuMzIxNTEyNywxMy43MzA2ODgxIDEyLjk0MzMyNjMsMTcuMTI3MDUzMyBMOS40ODc3OTI5NywxNy4xMjcwNTMzIEw5LjQ4Nzc5Mjk3LDE5LjU5Njk2NzcgQzEwLjI3Nzk4MTIsMTkuODU4NDUzMyAxMS4xMjI1ODYyLDIwIDEyLDIwIEMxNi40MTU0MzA1LDIwIDIwLDE2LjQxNTQzMDUgMjAsMTIgQzIwLDExLjgzNjk2ODkgMTkuOTk1MTEzMSwxMS42NzUwNzA1IDE5Ljk4NTQ3OCwxMS41MTQ0NDM1IEMxOS4zMjg0OTI3LDEyLjUwNDgxNDUgMTguMzMzMzMzMywxMyAxNywxMyBDMTQuODYyNTcwOSwxMyAxMy43OTM4NTY0LDEyLjA4MzU3NTEgMTMuNzkzODU2NCwxMC4yNTA3MjUyIEwxMC4wNDU2OTYyLDEwLjI1MDcyNTIgQzkuNzcxODkzODEsNy41MjI0MzE3NyAxMC43Mjg1MTc1LDYuMTU4Mjg1MDcgMTIuOTE1NTY3Miw2LjE1ODI4NTA3IEMxMi45MTU1NjcyLDUuMTgzMDg2OTIgMTMuMjQzMDA2Myw0LjU2MTQ2MTg1IDEzLjcyNzI1NTUsNC4xODcyNjgyIEMxMy4xNzA5MzQsNC4wNjQ2NDU4IDEyLjU5Mjk1OSw0IDEyLDQgQzcuNTg0NTY5NSw0IDQsNy41ODQ1Njk1IDQsMTIgWiIgaWQ9IkNvbWJpbmVkLVNoYXBlIiBmaWxsPSIjM0M0MDQzIiBmaWxsLXJ1bGU9Im5vbnplcm8iPjwvcGF0aD4KPC9zdmc+);
}

.image-file {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik0xMyw5VjMuNUwxOC41LDlNNiwyQzQuODksMiA0LDIuODkgNCw0VjIwQTIsMiAwIDAsMCA2LDIySDE4QTIsMiAwIDAsMCAyMCwyMFY4TDE0LDJINloiIGZpbGw9IiMzQzQwNDMiIC8+Cjwvc3ZnPg==);
}

.offline-content-suggestion-texts {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  line-height: 1.3;
  padding: .9em;
  width: 100%;
}

.offline-content-suggestion-title {
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  color: rgb(32, 33, 36);
  display: -webkit-box;
  font-size: 1.1em;
  overflow: hidden;
  text-overflow: ellipsis;
}

div.offline-content-suggestion {
  align-items: stretch;
  border: 1px solid rgb(218, 220, 224);
  border-radius: 8px;
  display: flex;
  justify-content: space-between;
  margin-bottom: .8em;
}

.suggestion-with-image {
  flex-direction: row;
  height: 8.2em;
  max-height: 8.2em;
}

.suggestion-with-icon {
  flex-direction: row-reverse;
  height: 4.2em;
  max-height: 4.2em;
}

.suggestion-with-icon .offline-content-suggestion-title {
  -webkit-line-clamp: 1;
  word-break: break-all;
}

.suggestion-with-icon .offline-content-suggestion-texts {
  padding-inline-start: 0px;
}

.offline-content-suggestion-attribution-freshness {
  color: rgb(95, 99, 104);
  display: flex;
  font-size: .8em;
}

.offline-content-suggestion-attribution {
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  display: -webkit-box;
  flex-shrink: 1;
  overflow-wrap: break-word;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-all;
}

.no-attribution .offline-content-suggestion-attribution {
  display: none;
}

.offline-content-suggestion-freshness:before {
  content: '-';
  display: inline-block;
  flex-shrink: 0;
  margin-inline-end: .1em;
  margin-inline-start: .1em;
}

.no-attribution .offline-content-suggestion-freshness:before {
  display: none;
}

.offline-content-suggestion-freshness {
  flex-shrink: 0;
}

.suggestion-with-image .offline-content-suggestion-pin-spacer {
  flex-shrink: 1;
  flex-grow: 100;
}

.suggestion-with-image .offline-content-suggestion-pin {
  content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+CiAgICA8ZGVmcz4KICAgICAgICA8cGF0aCBpZD0iYSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+CiAgICA8L2RlZnM+CiAgICA8Y2xpcFBhdGggaWQ9ImIiPgogICAgICAgIDx1c2UgeGxpbms6aHJlZj0iI2EiIG92ZXJmbG93PSJ2aXNpYmxlIi8+CiAgICA8L2NsaXBQYXRoPgogICAgPHBhdGggY2xpcC1wYXRoPSJ1cmwoI2IpIiBkPSJNMTIgMkM2LjUgMiAyIDYuNSAyIDEyczQuNSAxMCAxMCAxMCAxMC00LjUgMTAtMTBTMTcuNSAyIDEyIDJ6bTUgMTZIN3YtMmgxMHYyem0tNi43LTRMNyAxMC43bDEuNC0xLjQgMS45IDEuOSA1LjMtNS4zTDE3IDcuMyAxMC4zIDE0eiIgZmlsbD0icmdiKDE1NCwgMTYwLCAxNjYpIi8+Cjwvc3ZnPgo=);
  flex-shrink: 0;
  height: 1.4em;
  margin-inline-start: .4em;
  width: 1.4em;
}

/* Controls the animation (and a bit more) of the launch-downloads-home action
 * button when the offline content list is expanded/shown.
 */
#offline-content-list-action {
  text-align: center;
  transition: visibility 0s 0.2s, opacity 0.2s 0.2s linear;
}

/* Controls the animation of the launch-downloads-home action button when the
 * offline content list is collapsed/hidden.
 */
#offline-content-list.list-hidden #offline-content-list-action {
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s linear, visibility 0s 0.2s;
}


#offline-content-summary {
  border: 1px solid var(--google-gray-300);
  border-radius: 12px;
  padding: 12px;
  text-align: center;
}

.offline-content-summary-image-truncate {
  width: 45px;
}

.offline-content-summary-images {
  direction: ltr;
  display: flex;
  margin-top: 10px;
  justify-content: center;
  padding-bottom: 12px;
}

.offline-content-summary-images img {
  background: rgb(241, 243, 244);
  border-radius: 50%;
  box-shadow:
    0px 1px 2px 0px rgb(155, 155, 155),
    0px 1px 3px 0px rgb(155, 155, 155);
  padding: 12px;
  width: 32px;
}

.offline-content-summary-description {
  border-top: 1px solid var(--google-gray-300);
  padding-top: 12px;
}

.offline-content-summary-action {
  padding-top: 12px;
}

#cancel-save-page-button {
  border: 1px solid var(--google-gray-300);
  border-radius: 5px;
  color: var(--google-gray-700);
  padding: 16px;
  text-align: center;
}

#save-page-for-later-button {
  display: flex;
  justify-content: center;
}

.hidden#save-page-for-later-button {
  display: none;
}

/* Don't allow overflow when in a subframe. */
html[subframe] body {
  overflow: hidden;
}

#sub-frame-error {
  -webkit-align-items: center;
  background-color: #DDD;
  display: -webkit-flex;
  -webkit-flex-flow: column;
  height: 100%;
  -webkit-justify-content: center;
  left: 0;
  position: absolute;
  text-align: center;
  top: 0;
  transition: background-color .2s ease-in-out;
  width: 100%;
}

#sub-frame-error:hover {
  background-color: #EEE;
}

#sub-frame-error .icon-generic {
  margin: 0 0 16px;
}

#sub-frame-error-details {
  margin: 0 10px;
  text-align: center;
  visibility: hidden;
}

/* Show details only when hovering. */
#sub-frame-error:hover #sub-frame-error-details {
  visibility: visible;
}

/* If the iframe is too small, always hide the error code. */
/* TODO(mmenke): See if overflow: no-display works better, once supported. */
@media (max-width: 200px), (max-height: 95px) {
  #sub-frame-error-details {
    display: none;
  }
}

/* Adjust icon for small embedded frames in apps. */
@media (max-height: 100px) {
  #sub-frame-error .icon-generic {
    height: auto;
    margin: 0;
    padding-top: 0;
    width: 25px;
  }
}

/* details-button is special; it's a <button> element that looks like a link. */
#details-button {
  box-shadow: none;
  min-width: 0;
}

/* Styles for platform dependent separation of controls and details button. */
.suggested-left > #control-buttons,
.suggested-left #stale-load-button,
.suggested-right > #details-button {
  float: left;
}

.suggested-right > #control-buttons,
.suggested-right #stale-load-button,
.suggested-left > #details-button {
  float: right;
}

.suggested-left .secondary-button {
  margin-inline-end: 0px;
  margin-inline-start: 16px;
}

#details-button.singular {
  float: none;
}

/* download-button shows both icon and text. */
#download-button {
  padding-bottom: 4px;
  padding-top: 4px;
  position: relative;
}

#download-button:before {
  background: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAO0lEQVQ4y2NgGArgPxIY1YChsOE/LtBAmpYG0mxpIOSDBpKUo2lpIDZxNJCkHKqlYZAla3RAHQ1DFgAARRroHyLNTwwAAAAASUVORK5CYII=) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAAZElEQVRYw+3Ruw3AMAwDUY3OzZUmRRD4E9iim9wNwAdbEURHyk4AAAAATiCVK8lLyPsKeT9K3lsownnunfkPxO78hKiYHxBV8x2icr5BVM+/CMf8g3DN34Rzns6ViwHUAUQ/6wIAd5Km7l6c8AAAAABJRU5ErkJggg==) 2x)
    no-repeat;
  content: '';
  display: inline-block;
  width: 24px;
  height: 24px;
  margin-inline-end: 4px;
  margin-inline-start: -4px;
  vertical-align: middle;
}

#download-button:disabled {
  background: rgb(180, 206, 249);
  color: rgb(255, 255, 255);
}

/*
TODO(https://crbug.com/852872): UI for offline suggested content is incomplete.
*/
.suggested-thumbnail {
  width: 25vw;
  height: 25vw;
}

/* Alternate dino page button styles */
#control-buttons .reload-button-alternate:disabled {
  background: #ccc;
  color: #fff;
  font-size: 14px;
  height: 48px;
}

#buttons::after {
  clear: both;
  content: '';
  display: block;
  width: 100%;
}

/* Offline page */
.offline {
  transition: -webkit-filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1),
              background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
  will-change: -webkit-filter, background-color;
}

.offline #main-message > p {
  display: none;
}

.offline.inverted {
  -webkit-filter: invert(100%);
  background-color: #000;
}

.offline .interstitial-wrapper {
  color: #2b2b2b;
  font-size: 1em;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 600px;
  padding-top: 100px;
  width: 100%;
}

.offline .runner-container {
  direction: ltr;
  height: 150px;
  max-width: 600px;
  overflow: hidden;
  position: absolute;
  top: 35px;
  width: 44px;
}

.offline .runner-canvas {
  height: 150px;
  max-width: 600px;
  opacity: 1;
  overflow: hidden;
  position: absolute;
  top: 0;
  z-index: 10;
}

.offline .controller {
  background: rgba(247,247,247, .1);
  height: 100vh;
  left: 0;
  position: absolute;
  top: 0;
  width: 100vw;
  z-index: 9;
}

#offline-resources {
  display: none;
}

@media (max-width: 420px) {
  #download-button {
    padding-bottom: 12px;
    padding-top: 12px;
  }

  .suggested-left > #control-buttons,
  .suggested-right > #control-buttons {
    float: none;
  }

  .snackbar {
    left: 0;
    bottom: 0;
    width: 100%;
    border-radius: 0;
  }
}

@media (max-height: 350px) {
  h1 {
    margin: 0 0 15px;
  }

  .icon-offline {
    margin: 0 0 10px;
  }

  .interstitial-wrapper {
    margin-top: 5%;
  }

  .nav-wrapper {
    margin-top: 30px;
  }
}

@media (min-width: 420px) and (max-width: 736px) and
       (min-height: 240px) and (max-height: 420px) and
       (orientation:landscape) {
  .interstitial-wrapper {
    margin-bottom: 100px;
  }
}

@media (max-width: 360px) and (max-height: 480px) {
  .offline .interstitial-wrapper {
    padding-top: 60px;
  }

  .offline .runner-container {
    top: 8px;
  }
}

@media (min-height: 240px) and (orientation: landscape) {
  .offline .interstitial-wrapper {
    margin-bottom: 90px;
  }

  .icon-offline {
    margin-bottom: 20px;
  }
}

@media (max-height: 320px) and (orientation: landscape) {
  .icon-offline {
    margin-bottom: 0;
  }

  .offline .runner-container {
    top: 10px;
  }
}

@media (max-width: 240px) {
  button {
    padding-left: 12px;
    padding-right: 12px;
  }

  .interstitial-wrapper {
    overflow: inherit;
    padding: 0 8px;
  }
}

@media (max-width: 120px) {
  button {
    width: auto;
  }
}

.arcade-mode,
.arcade-mode .runner-container,
.arcade-mode .runner-canvas {
  image-rendering: pixelated;
  max-width: 100%;
  overflow: hidden;
}

.arcade-mode #buttons,
.arcade-mode #main-content {
  opacity: 0;
  overflow: hidden;
}

.arcade-mode .interstitial-wrapper {
  height: 100vh;
  max-width: 100%;
  overflow: hidden;
}

.arcade-mode .runner-container {
  left: 0;
  margin: auto;
  right: 0;
  transform-origin: top center;
  transition: transform 250ms cubic-bezier(0.4, 0.0, 1, 1) .4s;
  z-index: 2;
}
</style>
  <script>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is the shared code for security interstitials. It is used for both SSL
// interstitials and Safe Browsing interstitials.

// Should match security_interstitials::SecurityInterstitialCommand
/** @enum| {string} */
var SecurityInterstitialCommandId = {
  CMD_DONT_PROCEED: 0,
  CMD_PROCEED: 1,
  // Ways for user to get more information
  CMD_SHOW_MORE_SECTION: 2,
  CMD_OPEN_HELP_CENTER: 3,
  CMD_OPEN_DIAGNOSTIC: 4,
  // Primary button actions
  CMD_RELOAD: 5,
  CMD_OPEN_DATE_SETTINGS: 6,
  CMD_OPEN_LOGIN: 7,
  // Safe Browsing Extended Reporting
  CMD_DO_REPORT: 8,
  CMD_DONT_REPORT: 9,
  CMD_OPEN_REPORTING_PRIVACY: 10,
  CMD_OPEN_WHITEPAPER: 11,
  // Report a phishing error.
  CMD_REPORT_PHISHING_ERROR: 12
};

var HIDDEN_CLASS = 'hidden';

/**
 * A convenience method for sending commands to the parent page.
 * @param {string} cmd  The command to send.
 */
function sendCommand(cmd) {
  if (window.certificateErrorPageController) {
    switch (cmd) {
      case SecurityInterstitialCommandId.CMD_DONT_PROCEED:
        certificateErrorPageController.dontProceed();
        break;
      case SecurityInterstitialCommandId.CMD_PROCEED:
        certificateErrorPageController.proceed();
        break;
      case SecurityInterstitialCommandId.CMD_SHOW_MORE_SECTION:
        certificateErrorPageController.showMoreSection();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_HELP_CENTER:
        certificateErrorPageController.openHelpCenter();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_DIAGNOSTIC:
        certificateErrorPageController.openDiagnostic();
        break;
      case SecurityInterstitialCommandId.CMD_RELOAD:
        certificateErrorPageController.reload();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_DATE_SETTINGS:
        certificateErrorPageController.openDateSettings();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_LOGIN:
        certificateErrorPageController.openLogin();
        break;
      case SecurityInterstitialCommandId.CMD_DO_REPORT:
        certificateErrorPageController.doReport();
        break;
      case SecurityInterstitialCommandId.CMD_DONT_REPORT:
        certificateErrorPageController.dontReport();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_REPORTING_PRIVACY:
        certificateErrorPageController.openReportingPrivacy();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_WHITEPAPER:
        certificateErrorPageController.openWhitepaper();
        break;
      case SecurityInterstitialCommandId.CMD_REPORT_PHISHING_ERROR:
        certificateErrorPageController.reportPhishingError();
        break;
    }
    return;
  }
// 
  window.domAutomationController.send(cmd);
// 
// 
}

/**
 * Call this to stop clicks on <a href="#"> links from scrolling to the top of
 * the page (and possibly showing a # in the link).
 */
function preventDefaultOnPoundLinkClicks() {
  document.addEventListener('click', function(e) {
    var anchor = findAncestor(/** @type {Node} */ (e.target), function(el) {
      return el.tagName == 'A';
    });
    // Use getAttribute() to prevent URL normalization.
    if (anchor && anchor.getAttribute('href') == '#')
      e.preventDefault();
  });
}
</script>
  <script>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var mobileNav = false;

/**
 * For small screen mobile the navigation buttons are moved
 * below the advanced text.
 */
function onResize() {
  var helpOuterBox = document.querySelector('#details');
  var mainContent = document.querySelector('#main-content');
  var mediaQuery = '(min-width: 240px) and (max-width: 420px) and ' +
      '(min-height: 401px), ' +
      '(max-height: 560px) and (min-height: 240px) and ' +
      '(min-width: 421px)';

  var detailsHidden = helpOuterBox.classList.contains(HIDDEN_CLASS);
  var runnerContainer = document.querySelector('.runner-container');

  // Check for change in nav status.
  if (mobileNav != window.matchMedia(mediaQuery).matches) {
    mobileNav = !mobileNav;

    // Handle showing the top content / details sections according to state.
    if (mobileNav) {
      mainContent.classList.toggle(HIDDEN_CLASS, !detailsHidden);
      helpOuterBox.classList.toggle(HIDDEN_CLASS, detailsHidden);
      if (runnerContainer) {
        runnerContainer.classList.toggle(HIDDEN_CLASS, !detailsHidden);
      }
    } else if (!detailsHidden) {
      // Non mobile nav with visible details.
      mainContent.classList.remove(HIDDEN_CLASS);
      helpOuterBox.classList.remove(HIDDEN_CLASS);
      if (runnerContainer) {
        runnerContainer.classList.remove(HIDDEN_CLASS);
      }
    }
  }
}

function setupMobileNav() {
  window.addEventListener('resize', onResize);
  onResize();
}

document.addEventListener('DOMContentLoaded', setupMobileNav);
</script>
  <script>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Decodes a UTF16 string that is encoded as base64.
function decodeUTF16Base64ToString(encoded_text) {
  var data = atob(encoded_text);
  var result = '';
  for (var i = 0; i < data.length; i += 2) {
    result +=
        String.fromCharCode(data.charCodeAt(i) * 256 + data.charCodeAt(i + 1));
  }
  return result;
}

function toggleHelpBox() {
  var helpBoxOuter = document.getElementById('details');
  helpBoxOuter.classList.toggle(HIDDEN_CLASS);
  var detailsButton = document.getElementById('details-button');
  if (helpBoxOuter.classList.contains(HIDDEN_CLASS))
    detailsButton.innerText = detailsButton.detailsText;
  else
    detailsButton.innerText = detailsButton.hideDetailsText;

  // Details appears over the main content on small screens.
  if (mobileNav) {
    document.getElementById('main-content').classList.toggle(HIDDEN_CLASS);
    var runnerContainer = document.querySelector('.runner-container');
    if (runnerContainer) {
      runnerContainer.classList.toggle(HIDDEN_CLASS);
    }
  }
}

function diagnoseErrors() {
// 
    if (window.errorPageController)
      errorPageController.diagnoseErrorsButtonClick();
// 
// 
}

// Subframes use a different layout but the same html file.  This is to make it
// easier to support platforms that load the error page via different
// mechanisms (Currently just iOS).
if (window.top.location != window.location)
  document.documentElement.setAttribute('subframe', '');

// Re-renders the error page using |strings| as the dictionary of values.
// Used by NetErrorTabHelper to update DNS error pages with probe results.
function updateForDnsProbe(strings) {
  var context = new JsEvalContext(strings);
  jstProcess(context, document.getElementById('t'));
}

// Given the classList property of an element, adds an icon class to the list
// and removes the previously-
function updateIconClass(classList, newClass) {
  var oldClass;

  if (classList.hasOwnProperty('last_icon_class')) {
    oldClass = classList['last_icon_class'];
    if (oldClass == newClass)
      return;
  }

  classList.add(newClass);
  if (oldClass !== undefined)
    classList.remove(oldClass);

  classList['last_icon_class'] = newClass;

  if (newClass == 'icon-offline') {
    document.body.classList.add('offline');
    new Runner('.interstitial-wrapper');
  } else {
    document.body.classList.add('neterror');
  }
}

// Does a search using |baseSearchUrl| and the text in the search box.
function search(baseSearchUrl) {
  var searchTextNode = document.getElementById('search-box');
  document.location = baseSearchUrl + searchTextNode.value;
  return false;
}

// Use to track clicks on elements generated by the navigation correction
// service.  If |trackingId| is negative, the element does not come from the
// correction service.
function trackClick(trackingId) {
  // This can't be done with XHRs because XHRs are cancelled on navigation
  // start, and because these are cross-site requests.
  if (trackingId >= 0 && errorPageController)
    errorPageController.trackClick(trackingId);
}

// Called when an <a> tag generated by the navigation correction service is
// clicked.  Separate function from trackClick so the resources don't have to
// be updated if new data is added to jstdata.
function linkClicked(jstdata) {
  trackClick(jstdata.trackingId);
}

// Implements button clicks.  This function is needed during the transition
// between implementing these in trunk chromium and implementing them in
// iOS.
function reloadButtonClick(url) {
  if (window.errorPageController) {
    errorPageController.reloadButtonClick();
  } else {
    location = url;
  }
}

function showSavedCopyButtonClick() {
  if (window.errorPageController) {
    errorPageController.showSavedCopyButtonClick();
  }
}

function downloadButtonClick() {
  if (window.errorPageController) {
    errorPageController.downloadButtonClick();
    var downloadButton = document.getElementById('download-button');
    downloadButton.disabled = true;
    downloadButton.textContent = downloadButton.disabledText;

    document.getElementById('download-link-wrapper')
        .classList.add(HIDDEN_CLASS);
    document.getElementById('download-link-clicked-wrapper')
        .classList.remove(HIDDEN_CLASS);
  }
}

function detailsButtonClick() {
  if (window.errorPageController)
    errorPageController.detailsButtonClick();
}

/**
 * Replace the reload button with the Google cached copy suggestion.
 */
function setUpCachedButton(buttonStrings) {
  var reloadButton = document.getElementById('reload-button');

  reloadButton.textContent = buttonStrings.msg;
  var url = buttonStrings.cacheUrl;
  var trackingId = buttonStrings.trackingId;
  reloadButton.onclick = function(e) {
    e.preventDefault();
    trackClick(trackingId);
    if (window.errorPageController) {
      errorPageController.trackCachedCopyButtonClick();
    }
    location = url;
  };
  reloadButton.style.display = '';
  document.getElementById('control-buttons').hidden = false;
}

var primaryControlOnLeft = true;
// 

function setAutoFetchState(scheduled, can_schedule) {
  document.getElementById('cancel-save-page-button')
      .classList.toggle(HIDDEN_CLASS, !scheduled);
  document.getElementById('save-page-for-later-button')
      .classList.toggle(HIDDEN_CLASS, scheduled || !can_schedule);
}

function savePageLaterClick() {
  errorPageController.savePageForLater();
  // savePageForLater will eventually trigger a call to setAutoFetchState() when
  // it completes.
}

function cancelSavePageClick() {
  errorPageController.cancelSavePage();
  // setAutoFetchState is not called in response to cancelSavePage(), so do it
  // now.
  setAutoFetchState(false, true);
}

function toggleErrorInformationPopup() {
  document.getElementById('error-information-popup-container')
      .classList.toggle(HIDDEN_CLASS);
}

function launchOfflineItem(itemID, name_space) {
  errorPageController.launchOfflineItem(itemID, name_space);
}

function launchDownloadsPage() {
  errorPageController.launchDownloadsPage();
}

// Populates a summary of suggested offline content.
function offlineContentSummaryAvailable(summary) {
  // Note: See AvailableContentSummaryToValue in
  // available_offline_content_helper.cc for the data contained in |summary|.
  if (!summary || summary.total_items == 0 ||
      !loadTimeData.valueExists('offlineContentSummary')) {
    return;
  }
  // TODO(https://crbug.com/852872): Customize presented icons based on the
  // types of available offline content.
  document.getElementById('offline-content-summary').hidden = false;
}

function getIconForSuggestedItem(item) {
  // Note: |item.content_type| contains the enum values from
  // chrome::mojom::AvailableContentType.
  switch (item.content_type) {
    case 1:  // kVideo
      return 'image-video';
    case 2:  // kAudio
      return 'image-music-note';
    case 0:  // kPrefetchedPage
    case 3:  // kOtherPage
      return 'image-earth';
  }
  return 'image-file';
}

function getSuggestedContentDiv(item, index) {
  // Note: See AvailableContentToValue in available_offline_content_helper.cc
  // for the data contained in an |item|.
  // TODO(carlosk): Present |snippet_base64| when that content becomes
  // available.
  var visual = '';
  var extraContainerClasses = [];
  // html_inline.py will try to replace src attributes with data URIs using a
  // simple regex. The following is obfuscated slightly to avoid that.
  var src = 'src';
  if (item.thumbnail_data_uri) {
    extraContainerClasses.push('suggestion-with-image');
    visual = `<img ${src}="${item.thumbnail_data_uri}">`;
  } else {
    extraContainerClasses.push('suggestion-with-icon');
    iconClass = getIconForSuggestedItem(item);
    visual = `<div><img class="${iconClass}"></div>`;
  }

  if (!item.attribution_base64)
    extraContainerClasses.push('no-attribution');

  return `
  <div class="offline-content-suggestion ${extraContainerClasses.join(' ')}"
    onclick="launchOfflineItem('${item.ID}', '${item.name_space}')">
      <div class="offline-content-suggestion-texts">
        <div id="offline-content-suggestion-title-${index}"
             class="offline-content-suggestion-title">
        </div>
        <div class="offline-content-suggestion-attribution-freshness">
          <div id="offline-content-suggestion-attribution-${index}"
               class="offline-content-suggestion-attribution">
          </div>
          <div class="offline-content-suggestion-freshness">
            ${item.date_modified}
          </div>
          <div class="offline-content-suggestion-pin-spacer"></div>
          <div class="offline-content-suggestion-pin"></div>
        </div>
      </div>
      <div class="offline-content-suggestion-visual">
        ${visual}
      </div>
  </div>`;
}

// Populates a list of suggested offline content.
// Note: For security reasons all content downloaded from the web is considered
// unsafe and must be securely handled to be presented on the dino page. Images
// have already been safely re-encoded but textual content -- like title and
// attribution -- must be properly handled here.
function offlineContentAvailable(isShown, suggestions) {
  if (!suggestions || !loadTimeData.valueExists('offlineContentList'))
    return;

  var suggestionsHTML = [];
  for (var index = 0; index < suggestions.length; index++)
    suggestionsHTML.push(getSuggestedContentDiv(suggestions[index], index));

  document.getElementById('offline-content-suggestions').innerHTML =
      suggestionsHTML.join('\n');

  // Sets textual web content using |textContent| to make sure it's handled as
  // plain text.
  for (var index = 0; index < suggestions.length; index++) {
    document.getElementById(`offline-content-suggestion-title-${index}`)
        .textContent =
        decodeUTF16Base64ToString(suggestions[index].title_base64);
    document.getElementById(`offline-content-suggestion-attribution-${index}`)
        .textContent =
        decodeUTF16Base64ToString(suggestions[index].attribution_base64);
  }

  var contentListElement = document.getElementById('offline-content-list');
  if (document.dir == 'rtl')
    contentListElement.classList.add('is-rtl');
  contentListElement.hidden = false;
  // The list is configured as hidden by default. Show it if needed.
  if (isShown)
    toggleOfflineContentListVisibility(false);
}

function toggleOfflineContentListVisibility(updatePref) {
  if (!loadTimeData.valueExists('offlineContentList'))
    return;

  var contentListElement = document.getElementById('offline-content-list');
  var isVisible = !contentListElement.classList.toggle('list-hidden');

  if (updatePref && window.errorPageController) {
    errorPageController.listVisibilityChanged(isVisible);
  }
}

function onDocumentLoad() {
  var controlButtonDiv = document.getElementById('control-buttons');
  var reloadButton = document.getElementById('reload-button');
  var detailsButton = document.getElementById('details-button');
  var showSavedCopyButton = document.getElementById('show-saved-copy-button');
  var downloadButton = document.getElementById('download-button');

  var reloadButtonVisible = loadTimeData.valueExists('reloadButton') &&
      loadTimeData.getValue('reloadButton').msg;
  var showSavedCopyButtonVisible =
      loadTimeData.valueExists('showSavedCopyButton') &&
      loadTimeData.getValue('showSavedCopyButton').msg;
  var downloadButtonVisible = loadTimeData.valueExists('downloadButton') &&
      loadTimeData.getValue('downloadButton').msg;

  // If offline content suggestions will be visible, the usual buttons will not
  // be presented.
  var offlineContentVisible =
      loadTimeData.valueExists('suggestedOfflineContentPresentationMode');
  if (offlineContentVisible) {
    document.querySelector('.nav-wrapper').classList.add(HIDDEN_CLASS);
    detailsButton.classList.add(HIDDEN_CLASS);

    if (downloadButtonVisible)
      document.getElementById('download-link').hidden = false;

    document.getElementById('download-links-wrapper')
        .classList.remove(HIDDEN_CLASS);
    document.getElementById('error-information-popup-container')
        .classList.add('use-popup-container', HIDDEN_CLASS)
    document.getElementById('error-information-button')
        .classList.remove(HIDDEN_CLASS);

    return;
  }

  var primaryButton, secondaryButton;
  if (showSavedCopyButton.primary) {
    primaryButton = showSavedCopyButton;
    secondaryButton = reloadButton;
  } else {
    primaryButton = reloadButton;
    secondaryButton = showSavedCopyButton;
  }

  // Sets up the proper button layout for the current platform.
  if (primaryControlOnLeft) {
    buttons.classList.add('suggested-left');
    controlButtonDiv.insertBefore(secondaryButton, primaryButton);
  } else {
    buttons.classList.add('suggested-right');
    controlButtonDiv.insertBefore(primaryButton, secondaryButton);
  }

  // Check for Google cached copy suggestion.
  if (loadTimeData.valueExists('cacheButton')) {
    setUpCachedButton(loadTimeData.getValue('cacheButton'));
  }

  if (reloadButton.style.display == 'none' &&
      showSavedCopyButton.style.display == 'none' &&
      downloadButton.style.display == 'none') {
    detailsButton.classList.add('singular');
  }

  var attemptAutoFetch = loadTimeData.valueExists('attemptAutoFetch') &&
      loadTimeData.getValue('attemptAutoFetch');

  // Show control buttons.
  if (reloadButtonVisible || showSavedCopyButtonVisible ||
      downloadButtonVisible || attemptAutoFetch) {
    controlButtonDiv.hidden = false;

    // Set the secondary button state in the cases of two call to actions.
    if ((reloadButtonVisible || downloadButtonVisible) &&
        showSavedCopyButtonVisible) {
      secondaryButton.classList.add('secondary-button');
    }
  }
}

document.addEventListener('DOMContentLoaded', onDocumentLoad);
</script>
  <script>// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function() {
'use strict';
/**
 * T-Rex runner.
 * @param {string} outerContainerId Outer containing element id.
 * @param {Object} opt_config
 * @constructor
 * @export
 */
function Runner(outerContainerId, opt_config) {
  // Singleton
  if (Runner.instance_) {
    return Runner.instance_;
  }
  Runner.instance_ = this;

  this.outerContainerEl = document.querySelector(outerContainerId);
  this.containerEl = null;
  this.snackbarEl = null;
  // A div to intercept touch events. Only set while (playing && useTouch).
  this.touchController = null;

  this.config = opt_config || Runner.config;
  // Logical dimensions of the container.
  this.dimensions = Runner.defaultDimensions;

  this.canvas = null;
  this.canvasCtx = null;

  this.tRex = null;

  this.distanceMeter = null;
  this.distanceRan = 0;

  this.highestScore = 0;
  this.syncHighestScore = false;

  this.time = 0;
  this.runningTime = 0;
  this.msPerFrame = 1000 / FPS;
  this.currentSpeed = this.config.SPEED;

  this.obstacles = [];

  this.activated = false; // Whether the easter egg has been activated.
  this.playing = false; // Whether the game is currently in play state.
  this.crashed = false;
  this.paused = false;
  this.inverted = false;
  this.invertTimer = 0;
  this.resizeTimerId_ = null;

  this.playCount = 0;

  // Sound FX.
  this.audioBuffer = null;
  this.soundFx = {};

  // Global web audio context for playing sounds.
  this.audioContext = null;

  // Images.
  this.images = {};
  this.imagesLoaded = 0;

  if (this.isDisabled()) {
    this.setupDisabledRunner();
  } else {
    this.loadImages();

    window['initializeEasterEggHighScore'] =
        this.initializeHighScore.bind(this);
  }
}
window['Runner'] = Runner;

/**
 * Default game width.
 * @const
 */
var DEFAULT_WIDTH = 600;

/**
 * Frames per second.
 * @const
 */
var FPS = 60;

/** @const */
var IS_HIDPI = window.devicePixelRatio > 1;

/** @const */
var IS_IOS = /iPad|iPhone|iPod/.test(window.navigator.platform);

/** @const */
var IS_MOBILE = /Android/.test(window.navigator.userAgent) || IS_IOS;

/** @const */
var ARCADE_MODE_URL = 'chrome://dino/';

/**
 * Default game configuration.
 * @enum {number}
 */
Runner.config = {
  ACCELERATION: 0.001,
  BG_CLOUD_SPEED: 0.2,
  BOTTOM_PAD: 10,
  // Scroll Y threshold at which the game can be activated.
  CANVAS_IN_VIEW_OFFSET: -10,
  CLEAR_TIME: 3000,
  CLOUD_FREQUENCY: 0.5,
  GAMEOVER_CLEAR_TIME: 750,
  GAP_COEFFICIENT: 0.6,
  GRAVITY: 0.6,
  INITIAL_JUMP_VELOCITY: 12,
  INVERT_FADE_DURATION: 12000,
  INVERT_DISTANCE: 700,
  MAX_BLINK_COUNT: 3,
  MAX_CLOUDS: 6,
  MAX_OBSTACLE_LENGTH: 3,
  MAX_OBSTACLE_DUPLICATION: 2,
  MAX_SPEED: 13,
  MIN_JUMP_HEIGHT: 35,
  MOBILE_SPEED_COEFFICIENT: 1.2,
  RESOURCE_TEMPLATE_ID: 'audio-resources',
  SPEED: 6,
  SPEED_DROP_COEFFICIENT: 3,
  ARCADE_MODE_INITIAL_TOP_POSITION: 35,
  ARCADE_MODE_TOP_POSITION_PERCENT: 0.1
};


/**
 * Default dimensions.
 * @enum {string}
 */
Runner.defaultDimensions = {
  WIDTH: DEFAULT_WIDTH,
  HEIGHT: 150
};


/**
 * CSS class names.
 * @enum {string}
 */
Runner.classes = {
  ARCADE_MODE: 'arcade-mode',
  CANVAS: 'runner-canvas',
  CONTAINER: 'runner-container',
  CRASHED: 'crashed',
  ICON: 'icon-offline',
  INVERTED: 'inverted',
  SNACKBAR: 'snackbar',
  SNACKBAR_SHOW: 'snackbar-show',
  TOUCH_CONTROLLER: 'controller'
};


/**
 * Sprite definition layout of the spritesheet.
 * @enum {Object}
 */
Runner.spriteDefinition = {
  LDPI: {
    CACTUS_LARGE: {x: 332, y: 2},
    CACTUS_SMALL: {x: 228, y: 2},
    CLOUD: {x: 86, y: 2},
    HORIZON: {x: 2, y: 54},
    MOON: {x: 484, y: 2},
    PTERODACTYL: {x: 134, y: 2},
    RESTART: {x: 2, y: 2},
    TEXT_SPRITE: {x: 655, y: 2},
    TREX: {x: 848, y: 2},
    STAR: {x: 645, y: 2}
  },
  HDPI: {
    CACTUS_LARGE: {x: 652, y: 2},
    CACTUS_SMALL: {x: 446, y: 2},
    CLOUD: {x: 166, y: 2},
    HORIZON: {x: 2, y: 104},
    MOON: {x: 954, y: 2},
    PTERODACTYL: {x: 260, y: 2},
    RESTART: {x: 2, y: 2},
    TEXT_SPRITE: {x: 1294, y: 2},
    TREX: {x: 1678, y: 2},
    STAR: {x: 1276, y: 2}
  }
};


/**
 * Sound FX. Reference to the ID of the audio tag on interstitial page.
 * @enum {string}
 */
Runner.sounds = {
  BUTTON_PRESS: 'offline-sound-press',
  HIT: 'offline-sound-hit',
  SCORE: 'offline-sound-reached'
};


/**
 * Key code mapping.
 * @enum {Object}
 */
Runner.keycodes = {
  JUMP: {'38': 1, '32': 1},  // Up, spacebar
  DUCK: {'40': 1},  // Down
  RESTART: {'13': 1}  // Enter
};


/**
 * Runner event names.
 * @enum {string}
 */
Runner.events = {
  ANIM_END: 'webkitAnimationEnd',
  CLICK: 'click',
  KEYDOWN: 'keydown',
  KEYUP: 'keyup',
  POINTERDOWN: 'pointerdown',
  POINTERUP: 'pointerup',
  RESIZE: 'resize',
  TOUCHEND: 'touchend',
  TOUCHSTART: 'touchstart',
  VISIBILITY: 'visibilitychange',
  BLUR: 'blur',
  FOCUS: 'focus',
  LOAD: 'load'
};

Runner.prototype = {
  /**
   * Whether the easter egg has been disabled. CrOS enterprise enrolled devices.
   * @return {boolean}
   */
  isDisabled: function() {
    return loadTimeData && loadTimeData.valueExists('disabledEasterEgg');
  },

  /**
   * For disabled instances, set up a snackbar with the disabled message.
   */
  setupDisabledRunner: function() {
    this.containerEl = document.createElement('div');
    this.containerEl.className = Runner.classes.SNACKBAR;
    this.containerEl.textContent = loadTimeData.getValue('disabledEasterEgg');
    this.outerContainerEl.appendChild(this.containerEl);

    // Show notification when the activation key is pressed.
    document.addEventListener(Runner.events.KEYDOWN, function(e) {
      if (Runner.keycodes.JUMP[e.keyCode]) {
        this.containerEl.classList.add(Runner.classes.SNACKBAR_SHOW);
        document.querySelector('.icon').classList.add('icon-disabled');
      }
    }.bind(this));
  },

  /**
   * Setting individual settings for debugging.
   * @param {string} setting
   * @param {*} value
   */
  updateConfigSetting: function(setting, value) {
    if (setting in this.config && value != undefined) {
      this.config[setting] = value;

      switch (setting) {
        case 'GRAVITY':
        case 'MIN_JUMP_HEIGHT':
        case 'SPEED_DROP_COEFFICIENT':
          this.tRex.config[setting] = value;
          break;
        case 'INITIAL_JUMP_VELOCITY':
          this.tRex.setJumpVelocity(value);
          break;
        case 'SPEED':
          this.setSpeed(value);
          break;
      }
    }
  },

  /**
   * Cache the appropriate image sprite from the page and get the sprite sheet
   * definition.
   */
  loadImages: function() {
    if (IS_HIDPI) {
      Runner.imageSprite = document.getElementById('offline-resources-2x');
      this.spriteDef = Runner.spriteDefinition.HDPI;
    } else {
      Runner.imageSprite = document.getElementById('offline-resources-1x');
      this.spriteDef = Runner.spriteDefinition.LDPI;
    }

    if (Runner.imageSprite.complete) {
      this.init();
    } else {
      // If the images are not yet loaded, add a listener.
      Runner.imageSprite.addEventListener(Runner.events.LOAD,
          this.init.bind(this));
    }
  },

  /**
   * Load and decode base 64 encoded sounds.
   */
  loadSounds: function() {
    if (!IS_IOS) {
      this.audioContext = new AudioContext();

      var resourceTemplate =
          document.getElementById(this.config.RESOURCE_TEMPLATE_ID).content;

      for (var sound in Runner.sounds) {
        var soundSrc =
            resourceTemplate.getElementById(Runner.sounds[sound]).src;
        soundSrc = soundSrc.substr(soundSrc.indexOf(',') + 1);
        var buffer = decodeBase64ToArrayBuffer(soundSrc);

        // Async, so no guarantee of order in array.
        this.audioContext.decodeAudioData(buffer, function(index, audioData) {
            this.soundFx[index] = audioData;
          }.bind(this, sound));
      }
    }
  },

  /**
   * Sets the game speed. Adjust the speed accordingly if on a smaller screen.
   * @param {number} opt_speed
   */
  setSpeed: function(opt_speed) {
    var speed = opt_speed || this.currentSpeed;

    // Reduce the speed on smaller mobile screens.
    if (this.dimensions.WIDTH < DEFAULT_WIDTH) {
      var mobileSpeed = speed * this.dimensions.WIDTH / DEFAULT_WIDTH *
          this.config.MOBILE_SPEED_COEFFICIENT;
      this.currentSpeed = mobileSpeed > speed ? speed : mobileSpeed;
    } else if (opt_speed) {
      this.currentSpeed = opt_speed;
    }
  },

  /**
   * Game initialiser.
   */
  init: function() {
    // Hide the static icon.
    document.querySelector('.' + Runner.classes.ICON).style.visibility =
        'hidden';

    this.adjustDimensions();
    this.setSpeed();

    this.containerEl = document.createElement('div');
    this.containerEl.className = Runner.classes.CONTAINER;

    // Player canvas container.
    this.canvas = createCanvas(this.containerEl, this.dimensions.WIDTH,
        this.dimensions.HEIGHT, Runner.classes.PLAYER);

    this.canvasCtx = this.canvas.getContext('2d');
    this.canvasCtx.fillStyle = '#f7f7f7';
    this.canvasCtx.fill();
    Runner.updateCanvasScaling(this.canvas);

    // Horizon contains clouds, obstacles and the ground.
    this.horizon = new Horizon(this.canvas, this.spriteDef, this.dimensions,
        this.config.GAP_COEFFICIENT);

    // Distance meter
    this.distanceMeter = new DistanceMeter(this.canvas,
          this.spriteDef.TEXT_SPRITE, this.dimensions.WIDTH);

    // Draw t-rex
    this.tRex = new Trex(this.canvas, this.spriteDef.TREX);

    this.outerContainerEl.appendChild(this.containerEl);

    this.startListening();
    this.update();

    window.addEventListener(Runner.events.RESIZE,
        this.debounceResize.bind(this));
  },

  /**
   * Create the touch controller. A div that covers whole screen.
   */
  createTouchController: function() {
    this.touchController = document.createElement('div');
    this.touchController.className = Runner.classes.TOUCH_CONTROLLER;
    this.touchController.addEventListener(Runner.events.TOUCHSTART, this);
    this.touchController.addEventListener(Runner.events.TOUCHEND, this);
    this.outerContainerEl.appendChild(this.touchController);
  },

  /**
   * Debounce the resize event.
   */
  debounceResize: function() {
    if (!this.resizeTimerId_) {
      this.resizeTimerId_ =
          setInterval(this.adjustDimensions.bind(this), 250);
    }
  },

  /**
   * Adjust game space dimensions on resize.
   */
  adjustDimensions: function() {
    clearInterval(this.resizeTimerId_);
    this.resizeTimerId_ = null;

    var boxStyles = window.getComputedStyle(this.outerContainerEl);
    var padding = Number(boxStyles.paddingLeft.substr(0,
        boxStyles.paddingLeft.length - 2));

    this.dimensions.WIDTH = this.outerContainerEl.offsetWidth - padding * 2;
    if (this.isArcadeMode()) {
      this.dimensions.WIDTH = Math.min(DEFAULT_WIDTH, this.dimensions.WIDTH);
      if (this.activated) {
        this.setArcadeModeContainerScale();
      }
    }

    // Redraw the elements back onto the canvas.
    if (this.canvas) {
      this.canvas.width = this.dimensions.WIDTH;
      this.canvas.height = this.dimensions.HEIGHT;

      Runner.updateCanvasScaling(this.canvas);

      this.distanceMeter.calcXPos(this.dimensions.WIDTH);
      this.clearCanvas();
      this.horizon.update(0, 0, true);
      this.tRex.update(0);

      // Outer container and distance meter.
      if (this.playing || this.crashed || this.paused) {
        this.containerEl.style.width = this.dimensions.WIDTH + 'px';
        this.containerEl.style.height = this.dimensions.HEIGHT + 'px';
        this.distanceMeter.update(0, Math.ceil(this.distanceRan));
        this.stop();
      } else {
        this.tRex.draw(0, 0);
      }

      // Game over panel.
      if (this.crashed && this.gameOverPanel) {
        this.gameOverPanel.updateDimensions(this.dimensions.WIDTH);
        this.gameOverPanel.draw();
      }
    }
  },

  /**
   * Play the game intro.
   * Canvas container width expands out to the full width.
   */
  playIntro: function() {
    if (!this.activated && !this.crashed) {
      this.playingIntro = true;
      this.tRex.playingIntro = true;

      // CSS animation definition.
      var keyframes = '@-webkit-keyframes intro { ' +
            'from { width:' + Trex.config.WIDTH + 'px }' +
            'to { width: ' + this.dimensions.WIDTH + 'px }' +
          '}';
      document.styleSheets[0].insertRule(keyframes, 0);

      this.containerEl.addEventListener(Runner.events.ANIM_END,
          this.startGame.bind(this));

      this.containerEl.style.webkitAnimation = 'intro .4s ease-out 1 both';
      this.containerEl.style.width = this.dimensions.WIDTH + 'px';

      this.setPlayStatus(true);
      this.activated = true;
    } else if (this.crashed) {
      this.restart();
    }
  },


  /**
   * Update the game status to started.
   */
  startGame: function() {
    if (this.isArcadeMode()) {
      this.setArcadeMode();
    }
    this.runningTime = 0;
    this.playingIntro = false;
    this.tRex.playingIntro = false;
    this.containerEl.style.webkitAnimation = '';
    this.playCount++;

    // Handle tabbing off the page. Pause the current game.
    document.addEventListener(Runner.events.VISIBILITY,
          this.onVisibilityChange.bind(this));

    window.addEventListener(Runner.events.BLUR,
          this.onVisibilityChange.bind(this));

    window.addEventListener(Runner.events.FOCUS,
          this.onVisibilityChange.bind(this));
  },

  clearCanvas: function() {
    this.canvasCtx.clearRect(0, 0, this.dimensions.WIDTH,
        this.dimensions.HEIGHT);
  },

  /**
   * Checks whether the canvas area is in the viewport of the browser
   * through the current scroll position.
   * @return boolean.
   */
  isCanvasInView: function() {
    return this.containerEl.getBoundingClientRect().top >
        Runner.config.CANVAS_IN_VIEW_OFFSET;
  },

  /**
   * Update the game frame and schedules the next one.
   */
  update: function() {
    this.updatePending = false;

    var now = getTimeStamp();
    var deltaTime = now - (this.time || now);

    this.time = now;

    if (this.playing) {
      this.clearCanvas();

      if (this.tRex.jumping) {
        this.tRex.updateJump(deltaTime);
      }

      this.runningTime += deltaTime;
      var hasObstacles = this.runningTime > this.config.CLEAR_TIME;

      // First jump triggers the intro.
      if (this.tRex.jumpCount == 1 && !this.playingIntro) {
        this.playIntro();
      }

      // The horizon doesn't move until the intro is over.
      if (this.playingIntro) {
        this.horizon.update(0, this.currentSpeed, hasObstacles);
      } else {
        deltaTime = !this.activated ? 0 : deltaTime;
        this.horizon.update(deltaTime, this.currentSpeed, hasObstacles,
            this.inverted);
      }

      // Check for collisions.
      var collision = hasObstacles &&
          checkForCollision(this.horizon.obstacles[0], this.tRex);

      if (!collision) {
        this.distanceRan += this.currentSpeed * deltaTime / this.msPerFrame;

        if (this.currentSpeed < this.config.MAX_SPEED) {
          this.currentSpeed += this.config.ACCELERATION;
        }
      } else {
        this.gameOver();
      }

      var playAchievementSound = this.distanceMeter.update(deltaTime,
          Math.ceil(this.distanceRan));

      if (playAchievementSound) {
        this.playSound(this.soundFx.SCORE);
      }

      // Night mode.
      if (this.invertTimer > this.config.INVERT_FADE_DURATION) {
        this.invertTimer = 0;
        this.invertTrigger = false;
        this.invert();
      } else if (this.invertTimer) {
        this.invertTimer += deltaTime;
      } else {
        var actualDistance =
            this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan));

        if (actualDistance > 0) {
          this.invertTrigger = !(actualDistance %
              this.config.INVERT_DISTANCE);

          if (this.invertTrigger && this.invertTimer === 0) {
            this.invertTimer += deltaTime;
            this.invert();
          }
        }
      }
    }

    if (this.playing || (!this.activated &&
        this.tRex.blinkCount < Runner.config.MAX_BLINK_COUNT)) {
      this.tRex.update(deltaTime);
      this.scheduleNextUpdate();
    }
  },

  /**
   * Event handler.
   */
  handleEvent: function(e) {
    return (function(evtType, events) {
      switch (evtType) {
        case events.KEYDOWN:
        case events.TOUCHSTART:
        case events.POINTERDOWN:
          this.onKeyDown(e);
          break;
        case events.KEYUP:
        case events.TOUCHEND:
        case events.POINTERUP:
          this.onKeyUp(e);
          break;
      }
    }.bind(this))(e.type, Runner.events);
  },

  /**
   * Bind relevant key / mouse / touch listeners.
   */
  startListening: function() {
    // Keys.
    document.addEventListener(Runner.events.KEYDOWN, this);
    document.addEventListener(Runner.events.KEYUP, this);

    // Touch / pointer.
    this.containerEl.addEventListener(Runner.events.TOUCHSTART, this);
    document.addEventListener(Runner.events.POINTERDOWN, this);
    document.addEventListener(Runner.events.POINTERUP, this);
  },

  /**
   * Remove all listeners.
   */
  stopListening: function() {
    document.removeEventListener(Runner.events.KEYDOWN, this);
    document.removeEventListener(Runner.events.KEYUP, this);

    if (this.touchController) {
      this.touchController.removeEventListener(Runner.events.TOUCHSTART, this);
      this.touchController.removeEventListener(Runner.events.TOUCHEND, this);
    }

    this.containerEl.removeEventListener(Runner.events.TOUCHSTART, this);
    document.removeEventListener(Runner.events.POINTERDOWN, this);
    document.removeEventListener(Runner.events.POINTERUP, this);
  },

  /**
   * Process keydown.
   * @param {Event} e
   */
  onKeyDown: function(e) {
    // Prevent native page scrolling whilst tapping on mobile.
    if (IS_MOBILE && this.playing) {
      e.preventDefault();
    }

    if (this.isCanvasInView()) {
      if (!this.crashed && !this.paused) {
        if (Runner.keycodes.JUMP[e.keyCode] ||
            e.type == Runner.events.TOUCHSTART) {
          e.preventDefault();
          // Starting the game for the first time.
          if (!this.playing) {
            // Started by touch so create a touch controller.
            if (!this.touchController && e.type == Runner.events.TOUCHSTART) {
              this.createTouchController();
            }
            this.loadSounds();
            this.setPlayStatus(true);
            this.update();
            if (window.errorPageController) {
              errorPageController.trackEasterEgg();
            }
          }
          // Start jump.
          if (!this.tRex.jumping && !this.tRex.ducking) {
            this.playSound(this.soundFx.BUTTON_PRESS);
            this.tRex.startJump(this.currentSpeed);
          }
        } else if (this.playing && Runner.keycodes.DUCK[e.keyCode]) {
          e.preventDefault();
          if (this.tRex.jumping) {
            // Speed drop, activated only when jump key is not pressed.
            this.tRex.setSpeedDrop();
          } else if (!this.tRex.jumping && !this.tRex.ducking) {
            // Duck.
            this.tRex.setDuck(true);
          }
        }
      // iOS only triggers touchstart and no pointer events.
      } else if (IS_IOS && this.crashed && e.type == Runner.events.TOUCHSTART &&
          e.currentTarget == this.containerEl) {
        this.handleGameOverClicks(e);
      }
    }
  },

  /**
   * Process key up.
   * @param {Event} e
   */
  onKeyUp: function(e) {
    var keyCode = String(e.keyCode);
    var isjumpKey = Runner.keycodes.JUMP[keyCode] ||
       e.type == Runner.events.TOUCHEND ||
       e.type == Runner.events.POINTERUP;

    if (this.isRunning() && isjumpKey) {
      this.tRex.endJump();
    } else if (Runner.keycodes.DUCK[keyCode]) {
      this.tRex.speedDrop = false;
      this.tRex.setDuck(false);
    } else if (this.crashed) {
      // Check that enough time has elapsed before allowing jump key to restart.
      var deltaTime = getTimeStamp() - this.time;

      if (this.isCanvasInView() &&
          (Runner.keycodes.RESTART[keyCode] || this.isLeftClickOnCanvas(e) ||
          (deltaTime >= this.config.GAMEOVER_CLEAR_TIME &&
          Runner.keycodes.JUMP[keyCode]))) {
        this.handleGameOverClicks(e);
      }
    } else if (this.paused && isjumpKey) {
      // Reset the jump state
      this.tRex.reset();
      this.play();
    }
  },

  /**
   * Handle interactions on the game over screen state.
   * A user is able to tap the high score twice to reset it.
   * @param {Event} e
   */
  handleGameOverClicks: function(e) {
    e.preventDefault();
    if (this.distanceMeter.hasClickedOnHighScore(e) && this.highestScore) {
      if (this.distanceMeter.isHighScoreFlashing()) {
        // Subsequent click, reset the high score.
        this.saveHighScore(0, true);
        this.distanceMeter.resetHighScore();
      } else {
        // First click, flash the high score.
        this.distanceMeter.startHighScoreFlashing();
      }
    } else {
      this.distanceMeter.cancelHighScoreFlashing();
      this.restart();
    }
  },

  /**
   * Returns whether the event was a left click on canvas.
   * On Windows right click is registered as a click.
   * @param {Event} e
   * @return {boolean}
   */
  isLeftClickOnCanvas: function(e) {
    return e.button != null && e.button < 2 &&
        e.type == Runner.events.POINTERUP && e.target == this.canvas;
  },

  /**
   * RequestAnimationFrame wrapper.
   */
  scheduleNextUpdate: function() {
    if (!this.updatePending) {
      this.updatePending = true;
      this.raqId = requestAnimationFrame(this.update.bind(this));
    }
  },

  /**
   * Whether the game is running.
   * @return {boolean}
   */
  isRunning: function() {
    return !!this.raqId;
  },

  /**
   * Set the initial high score as stored in the user's profile.
   * @param {integer} highScore
   */
  initializeHighScore: function(highScore) {
    this.syncHighestScore = true;
    highScore = Math.ceil(highScore);
    if (highScore < this.highestScore) {
      if (window.errorPageController) {
        errorPageController.updateEasterEggHighScore(this.highestScore);
      }
      return;
    }
    this.highestScore = highScore;
    this.distanceMeter.setHighScore(this.highestScore);
  },

  /**
   * Sets the current high score and saves to the profile if available.
   * @param {number} distanceRan Total distance ran.
   * @param {boolean} opt_resetScore Whether to reset the score.
   */
  saveHighScore: function(distanceRan, opt_resetScore) {
    this.highestScore = Math.ceil(distanceRan);
    this.distanceMeter.setHighScore(this.highestScore);

    // Store the new high score in the profile.
    if (this.syncHighestScore && window.errorPageController) {
      if (opt_resetScore) {
        errorPageController.resetEasterEggHighScore();
      } else {
        errorPageController.updateEasterEggHighScore(this.highestScore);
      }
    }
  },

  /**
   * Game over state.
   */
  gameOver: function() {
    this.playSound(this.soundFx.HIT);
    vibrate(200);

    this.stop();
    this.crashed = true;
    this.distanceMeter.achievement = false;

    this.tRex.update(100, Trex.status.CRASHED);

    // Game over panel.
    if (!this.gameOverPanel) {
      this.gameOverPanel = new GameOverPanel(this.canvas,
          this.spriteDef.TEXT_SPRITE, this.spriteDef.RESTART,
          this.dimensions);
    } else {
      this.gameOverPanel.draw();
    }

    // Update the high score.
    if (this.distanceRan > this.highestScore) {
      this.saveHighScore(this.distanceRan);
    }

    // Reset the time clock.
    this.time = getTimeStamp();
  },

  stop: function() {
    this.setPlayStatus(false);
    this.paused = true;
    cancelAnimationFrame(this.raqId);
    this.raqId = 0;
  },

  play: function() {
    if (!this.crashed) {
      this.setPlayStatus(true);
      this.paused = false;
      this.tRex.update(0, Trex.status.RUNNING);
      this.time = getTimeStamp();
      this.update();
    }
  },

  restart: function() {
    if (!this.raqId) {
      this.playCount++;
      this.runningTime = 0;
      this.setPlayStatus(true);
      this.paused = false;
      this.crashed = false;
      this.distanceRan = 0;
      this.setSpeed(this.config.SPEED);
      this.time = getTimeStamp();
      this.containerEl.classList.remove(Runner.classes.CRASHED);
      this.clearCanvas();
      this.distanceMeter.reset(this.highestScore);
      this.horizon.reset();
      this.tRex.reset();
      this.playSound(this.soundFx.BUTTON_PRESS);
      this.invert(true);
      this.bdayFlashTimer = null;
      this.update();
    }
  },

  setPlayStatus: function(isPlaying) {
    if (this.touchController)
      this.touchController.classList.toggle(HIDDEN_CLASS, !isPlaying);
    this.playing = isPlaying;
  },

  /**
   * Whether the game should go into arcade mode.
   * @return {boolean}
   */
  isArcadeMode: function() {
    return document.title == ARCADE_MODE_URL;
  },

  /**
   * Hides offline messaging for a fullscreen game only experience.
   */
  setArcadeMode: function() {
    document.body.classList.add(Runner.classes.ARCADE_MODE);
    this.setArcadeModeContainerScale();
  },

  /**
   * Sets the scaling for arcade mode.
   */
  setArcadeModeContainerScale: function() {
    var windowHeight = window.innerHeight;
    var scaleHeight = windowHeight / this.dimensions.HEIGHT;
    var scaleWidth = window.innerWidth / this.dimensions.WIDTH;
    var scale = Math.max(1, Math.min(scaleHeight, scaleWidth));
    var scaledCanvasHeight = this.dimensions.HEIGHT * scale;
    // Positions the game container at 10% of the available vertical window
    // height minus the game container height.
    var translateY = Math.ceil(Math.max(0, (windowHeight - scaledCanvasHeight -
        Runner.config.ARCADE_MODE_INITIAL_TOP_POSITION) *
        Runner.config.ARCADE_MODE_TOP_POSITION_PERCENT)) *
        window.devicePixelRatio;
    this.containerEl.style.transform = 'scale(' + scale + ') translateY(' +
        translateY + 'px)';
  },

  /**
   * Pause the game if the tab is not in focus.
   */
  onVisibilityChange: function(e) {
    if (document.hidden || document.webkitHidden || e.type == 'blur' ||
      document.visibilityState != 'visible') {
      this.stop();
    } else if (!this.crashed) {
      this.tRex.reset();
      this.play();
    }
  },

  /**
   * Play a sound.
   * @param {SoundBuffer} soundBuffer
   */
  playSound: function(soundBuffer) {
    if (soundBuffer) {
      var sourceNode = this.audioContext.createBufferSource();
      sourceNode.buffer = soundBuffer;
      sourceNode.connect(this.audioContext.destination);
      sourceNode.start(0);
    }
  },

  /**
   * Inverts the current page / canvas colors.
   * @param {boolean} Whether to reset colors.
   */
  invert: function(reset) {
    if (reset) {
      document.body.classList.toggle(Runner.classes.INVERTED, false);
      this.invertTimer = 0;
      this.inverted = false;
    } else {
      this.inverted = document.body.classList.toggle(Runner.classes.INVERTED,
          this.invertTrigger);
    }
  }
};


/**
 * Updates the canvas size taking into
 * account the backing store pixel ratio and
 * the device pixel ratio.
 *
 * See article by Paul Lewis:
 * http://www.html5rocks.com/en/tutorials/canvas/hidpi/
 *
 * @param {HTMLCanvasElement} canvas
 * @param {number} opt_width
 * @param {number} opt_height
 * @return {boolean} Whether the canvas was scaled.
 */
Runner.updateCanvasScaling = function(canvas, opt_width, opt_height) {
  var context = canvas.getContext('2d');

  // Query the various pixel ratios
  var devicePixelRatio = Math.floor(window.devicePixelRatio) || 1;
  var backingStoreRatio = Math.floor(context.webkitBackingStorePixelRatio) || 1;
  var ratio = devicePixelRatio / backingStoreRatio;

  // Upscale the canvas if the two ratios don't match
  if (devicePixelRatio !== backingStoreRatio) {
    var oldWidth = opt_width || canvas.width;
    var oldHeight = opt_height || canvas.height;

    canvas.width = oldWidth * ratio;
    canvas.height = oldHeight * ratio;

    canvas.style.width = oldWidth + 'px';
    canvas.style.height = oldHeight + 'px';

    // Scale the context to counter the fact that we've manually scaled
    // our canvas element.
    context.scale(ratio, ratio);
    return true;
  } else if (devicePixelRatio == 1) {
    // Reset the canvas width / height. Fixes scaling bug when the page is
    // zoomed and the devicePixelRatio changes accordingly.
    canvas.style.width = canvas.width + 'px';
    canvas.style.height = canvas.height + 'px';
  }
  return false;
};


/**
 * Get random number.
 * @param {number} min
 * @param {number} max
 * @param {number}
 */
function getRandomNum(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}


/**
 * Vibrate on mobile devices.
 * @param {number} duration Duration of the vibration in milliseconds.
 */
function vibrate(duration) {
  if (IS_MOBILE && window.navigator.vibrate) {
    window.navigator.vibrate(duration);
  }
}


/**
 * Create canvas element.
 * @param {HTMLElement} container Element to append canvas to.
 * @param {number} width
 * @param {number} height
 * @param {string} opt_classname
 * @return {HTMLCanvasElement}
 */
function createCanvas(container, width, height, opt_classname) {
  var canvas = document.createElement('canvas');
  canvas.className = opt_classname ? Runner.classes.CANVAS + ' ' +
      opt_classname : Runner.classes.CANVAS;
  canvas.width = width;
  canvas.height = height;
  container.appendChild(canvas);

  return canvas;
}


/**
 * Decodes the base 64 audio to ArrayBuffer used by Web Audio.
 * @param {string} base64String
 */
function decodeBase64ToArrayBuffer(base64String) {
  var len = (base64String.length / 4) * 3;
  var str = atob(base64String);
  var arrayBuffer = new ArrayBuffer(len);
  var bytes = new Uint8Array(arrayBuffer);

  for (var i = 0; i < len; i++) {
    bytes[i] = str.charCodeAt(i);
  }
  return bytes.buffer;
}


/**
 * Return the current timestamp.
 * @return {number}
 */
function getTimeStamp() {
  return IS_IOS ? new Date().getTime() : performance.now();
}


//******************************************************************************


/**
 * Game over panel.
 * @param {!HTMLCanvasElement} canvas
 * @param {Object} textImgPos
 * @param {Object} restartImgPos
 * @param {!Object} dimensions Canvas dimensions.
 * @constructor
 */
function GameOverPanel(canvas, textImgPos, restartImgPos, dimensions) {
  this.canvas = canvas;
  this.canvasCtx = canvas.getContext('2d');
  this.canvasDimensions = dimensions;
  this.textImgPos = textImgPos;
  this.restartImgPos = restartImgPos;
  this.draw();
};


/**
 * Dimensions used in the panel.
 * @enum {number}
 */
GameOverPanel.dimensions = {
  TEXT_X: 0,
  TEXT_Y: 13,
  TEXT_WIDTH: 191,
  TEXT_HEIGHT: 11,
  RESTART_WIDTH: 36,
  RESTART_HEIGHT: 32
};


GameOverPanel.prototype = {
  /**
   * Update the panel dimensions.
   * @param {number} width New canvas width.
   * @param {number} opt_height Optional new canvas height.
   */
  updateDimensions: function(width, opt_height) {
    this.canvasDimensions.WIDTH = width;
    if (opt_height) {
      this.canvasDimensions.HEIGHT = opt_height;
    }
  },

  /**
   * Draw the panel.
   */
  draw: function() {
    var dimensions = GameOverPanel.dimensions;

    var centerX = this.canvasDimensions.WIDTH / 2;

    // Game over text.
    var textSourceX = dimensions.TEXT_X;
    var textSourceY = dimensions.TEXT_Y;
    var textSourceWidth = dimensions.TEXT_WIDTH;
    var textSourceHeight = dimensions.TEXT_HEIGHT;

    var textTargetX = Math.round(centerX - (dimensions.TEXT_WIDTH / 2));
    var textTargetY = Math.round((this.canvasDimensions.HEIGHT - 25) / 3);
    var textTargetWidth = dimensions.TEXT_WIDTH;
    var textTargetHeight = dimensions.TEXT_HEIGHT;

    var restartSourceWidth = dimensions.RESTART_WIDTH;
    var restartSourceHeight = dimensions.RESTART_HEIGHT;
    var restartTargetX = centerX - (dimensions.RESTART_WIDTH / 2);
    var restartTargetY = this.canvasDimensions.HEIGHT / 2;

    if (IS_HIDPI) {
      textSourceY *= 2;
      textSourceX *= 2;
      textSourceWidth *= 2;
      textSourceHeight *= 2;
      restartSourceWidth *= 2;
      restartSourceHeight *= 2;
    }

    textSourceX += this.textImgPos.x;
    textSourceY += this.textImgPos.y;

    // Game over text from sprite.
    this.canvasCtx.drawImage(Runner.imageSprite,
        textSourceX, textSourceY, textSourceWidth, textSourceHeight,
        textTargetX, textTargetY, textTargetWidth, textTargetHeight);

    // Restart button.
    this.canvasCtx.drawImage(Runner.imageSprite,
        this.restartImgPos.x, this.restartImgPos.y,
        restartSourceWidth, restartSourceHeight,
        restartTargetX, restartTargetY, dimensions.RESTART_WIDTH,
        dimensions.RESTART_HEIGHT);
  }
};


//******************************************************************************

/**
 * Check for a collision.
 * @param {!Obstacle} obstacle
 * @param {!Trex} tRex T-rex object.
 * @param {HTMLCanvasContext} opt_canvasCtx Optional canvas context for drawing
 *    collision boxes.
 * @return {Array<CollisionBox>}
 */
function checkForCollision(obstacle, tRex, opt_canvasCtx) {
  var obstacleBoxXPos = Runner.defaultDimensions.WIDTH + obstacle.xPos;

  // Adjustments are made to the bounding box as there is a 1 pixel white
  // border around the t-rex and obstacles.
  var tRexBox = new CollisionBox(
      tRex.xPos + 1,
      tRex.yPos + 1,
      tRex.config.WIDTH - 2,
      tRex.config.HEIGHT - 2);

  var obstacleBox = new CollisionBox(
      obstacle.xPos + 1,
      obstacle.yPos + 1,
      obstacle.typeConfig.width * obstacle.size - 2,
      obstacle.typeConfig.height - 2);

  // Debug outer box
  if (opt_canvasCtx) {
    drawCollisionBoxes(opt_canvasCtx, tRexBox, obstacleBox);
  }

  // Simple outer bounds check.
  if (boxCompare(tRexBox, obstacleBox)) {
    var collisionBoxes = obstacle.collisionBoxes;
    var tRexCollisionBoxes = tRex.ducking ?
        Trex.collisionBoxes.DUCKING : Trex.collisionBoxes.RUNNING;

    // Detailed axis aligned box check.
    for (var t = 0; t < tRexCollisionBoxes.length; t++) {
      for (var i = 0; i < collisionBoxes.length; i++) {
        // Adjust the box to actual positions.
        var adjTrexBox =
            createAdjustedCollisionBox(tRexCollisionBoxes[t], tRexBox);
        var adjObstacleBox =
            createAdjustedCollisionBox(collisionBoxes[i], obstacleBox);
        var crashed = boxCompare(adjTrexBox, adjObstacleBox);

        // Draw boxes for debug.
        if (opt_canvasCtx) {
          drawCollisionBoxes(opt_canvasCtx, adjTrexBox, adjObstacleBox);
        }

        if (crashed) {
          return [adjTrexBox, adjObstacleBox];
        }
      }
    }
  }
  return false;
};


/**
 * Adjust the collision box.
 * @param {!CollisionBox} box The original box.
 * @param {!CollisionBox} adjustment Adjustment box.
 * @return {CollisionBox} The adjusted collision box object.
 */
function createAdjustedCollisionBox(box, adjustment) {
  return new CollisionBox(
      box.x + adjustment.x,
      box.y + adjustment.y,
      box.width,
      box.height);
};


/**
 * Draw the collision boxes for debug.
 */
function drawCollisionBoxes(canvasCtx, tRexBox, obstacleBox) {
  canvasCtx.save();
  canvasCtx.strokeStyle = '#f00';
  canvasCtx.strokeRect(tRexBox.x, tRexBox.y, tRexBox.width, tRexBox.height);

  canvasCtx.strokeStyle = '#0f0';
  canvasCtx.strokeRect(obstacleBox.x, obstacleBox.y,
      obstacleBox.width, obstacleBox.height);
  canvasCtx.restore();
};


/**
 * Compare two collision boxes for a collision.
 * @param {CollisionBox} tRexBox
 * @param {CollisionBox} obstacleBox
 * @return {boolean} Whether the boxes intersected.
 */
function boxCompare(tRexBox, obstacleBox) {
  var crashed = false;
  var tRexBoxX = tRexBox.x;
  var tRexBoxY = tRexBox.y;

  var obstacleBoxX = obstacleBox.x;
  var obstacleBoxY = obstacleBox.y;

  // Axis-Aligned Bounding Box method.
  if (tRexBox.x < obstacleBoxX + obstacleBox.width &&
      tRexBox.x + tRexBox.width > obstacleBoxX &&
      tRexBox.y < obstacleBox.y + obstacleBox.height &&
      tRexBox.height + tRexBox.y > obstacleBox.y) {
    crashed = true;
  }

  return crashed;
};


//******************************************************************************

/**
 * Collision box object.
 * @param {number} x X position.
 * @param {number} y Y Position.
 * @param {number} w Width.
 * @param {number} h Height.
 */
function CollisionBox(x, y, w, h) {
  this.x = x;
  this.y = y;
  this.width = w;
  this.height = h;
};


//******************************************************************************

/**
 * Obstacle.
 * @param {HTMLCanvasCtx} canvasCtx
 * @param {Obstacle.type} type
 * @param {Object} spritePos Obstacle position in sprite.
 * @param {Object} dimensions
 * @param {number} gapCoefficient Mutipler in determining the gap.
 * @param {number} speed
 * @param {number} opt_xOffset
 */
function Obstacle(canvasCtx, type, spriteImgPos, dimensions,
    gapCoefficient, speed, opt_xOffset) {

  this.canvasCtx = canvasCtx;
  this.spritePos = spriteImgPos;
  this.typeConfig = type;
  this.gapCoefficient = gapCoefficient;
  this.size = getRandomNum(1, Obstacle.MAX_OBSTACLE_LENGTH);
  this.dimensions = dimensions;
  this.remove = false;
  this.xPos = dimensions.WIDTH + (opt_xOffset || 0);
  this.yPos = 0;
  this.width = 0;
  this.collisionBoxes = [];
  this.gap = 0;
  this.speedOffset = 0;

  // For animated obstacles.
  this.currentFrame = 0;
  this.timer = 0;

  this.init(speed);
};

/**
 * Coefficient for calculating the maximum gap.
 * @const
 */
Obstacle.MAX_GAP_COEFFICIENT = 1.5;

/**
 * Maximum obstacle grouping count.
 * @const
 */
Obstacle.MAX_OBSTACLE_LENGTH = 3,


Obstacle.prototype = {
  /**
   * Initialise the DOM for the obstacle.
   * @param {number} speed
   */
  init: function(speed) {
    this.cloneCollisionBoxes();

    // Only allow sizing if we're at the right speed.
    if (this.size > 1 && this.typeConfig.multipleSpeed > speed) {
      this.size = 1;
    }

    this.width = this.typeConfig.width * this.size;

    // Check if obstacle can be positioned at various heights.
    if (Array.isArray(this.typeConfig.yPos))  {
      var yPosConfig = IS_MOBILE ? this.typeConfig.yPosMobile :
          this.typeConfig.yPos;
      this.yPos = yPosConfig[getRandomNum(0, yPosConfig.length - 1)];
    } else {
      this.yPos = this.typeConfig.yPos;
    }

    this.draw();

    // Make collision box adjustments,
    // Central box is adjusted to the size as one box.
    //      ____        ______        ________
    //    _|   |-|    _|     |-|    _|       |-|
    //   | |<->| |   | |<--->| |   | |<----->| |
    //   | | 1 | |   | |  2  | |   | |   3   | |
    //   |_|___|_|   |_|_____|_|   |_|_______|_|
    //
    if (this.size > 1) {
      this.collisionBoxes[1].width = this.width - this.collisionBoxes[0].width -
          this.collisionBoxes[2].width;
      this.collisionBoxes[2].x = this.width - this.collisionBoxes[2].width;
    }

    // For obstacles that go at a different speed from the horizon.
    if (this.typeConfig.speedOffset) {
      this.speedOffset = Math.random() > 0.5 ? this.typeConfig.speedOffset :
          -this.typeConfig.speedOffset;
    }

    this.gap = this.getGap(this.gapCoefficient, speed);
  },

  /**
   * Draw and crop based on size.
   */
  draw: function() {
    var sourceWidth = this.typeConfig.width;
    var sourceHeight = this.typeConfig.height;

    if (IS_HIDPI) {
      sourceWidth = sourceWidth * 2;
      sourceHeight = sourceHeight * 2;
    }

    // X position in sprite.
    var sourceX = (sourceWidth * this.size) * (0.5 * (this.size - 1)) +
        this.spritePos.x;

    // Animation frames.
    if (this.currentFrame > 0) {
      sourceX += sourceWidth * this.currentFrame;
    }

    this.canvasCtx.drawImage(Runner.imageSprite,
      sourceX, this.spritePos.y,
      sourceWidth * this.size, sourceHeight,
      this.xPos, this.yPos,
      this.typeConfig.width * this.size, this.typeConfig.height);
  },

  /**
   * Obstacle frame update.
   * @param {number} deltaTime
   * @param {number} speed
   */
  update: function(deltaTime, speed) {
    if (!this.remove) {
      if (this.typeConfig.speedOffset) {
        speed += this.speedOffset;
      }
      this.xPos -= Math.floor((speed * FPS / 1000) * deltaTime);

      // Update frame
      if (this.typeConfig.numFrames) {
        this.timer += deltaTime;
        if (this.timer >= this.typeConfig.frameRate) {
          this.currentFrame =
              this.currentFrame == this.typeConfig.numFrames - 1 ?
              0 : this.currentFrame + 1;
          this.timer = 0;
        }
      }
      this.draw();

      if (!this.isVisible()) {
        this.remove = true;
      }
    }
  },

  /**
   * Calculate a random gap size.
   * - Minimum gap gets wider as speed increses
   * @param {number} gapCoefficient
   * @param {number} speed
   * @return {number} The gap size.
   */
  getGap: function(gapCoefficient, speed) {
    var minGap = Math.round(this.width * speed +
          this.typeConfig.minGap * gapCoefficient);
    var maxGap = Math.round(minGap * Obstacle.MAX_GAP_COEFFICIENT);
    return getRandomNum(minGap, maxGap);
  },

  /**
   * Check if obstacle is visible.
   * @return {boolean} Whether the obstacle is in the game area.
   */
  isVisible: function() {
    return this.xPos + this.width > 0;
  },

  /**
   * Make a copy of the collision boxes, since these will change based on
   * obstacle type and size.
   */
  cloneCollisionBoxes: function() {
    var collisionBoxes = this.typeConfig.collisionBoxes;

    for (var i = collisionBoxes.length - 1; i >= 0; i--) {
      this.collisionBoxes[i] = new CollisionBox(collisionBoxes[i].x,
          collisionBoxes[i].y, collisionBoxes[i].width,
          collisionBoxes[i].height);
    }
  }
};


/**
 * Obstacle definitions.
 * minGap: minimum pixel space betweeen obstacles.
 * multipleSpeed: Speed at which multiples are allowed.
 * speedOffset: speed faster / slower than the horizon.
 * minSpeed: Minimum speed which the obstacle can make an appearance.
 */
Obstacle.types = [
  {
    type: 'CACTUS_SMALL',
    width: 17,
    height: 35,
    yPos: 105,
    multipleSpeed: 4,
    minGap: 120,
    minSpeed: 0,
    collisionBoxes: [
      new CollisionBox(0, 7, 5, 27),
      new CollisionBox(4, 0, 6, 34),
      new CollisionBox(10, 4, 7, 14)
    ]
  },
  {
    type: 'CACTUS_LARGE',
    width: 25,
    height: 50,
    yPos: 90,
    multipleSpeed: 7,
    minGap: 120,
    minSpeed: 0,
    collisionBoxes: [
      new CollisionBox(0, 12, 7, 38),
      new CollisionBox(8, 0, 7, 49),
      new CollisionBox(13, 10, 10, 38)
    ]
  },
  {
    type: 'PTERODACTYL',
    width: 46,
    height: 40,
    yPos: [ 100, 75, 50 ], // Variable height.
    yPosMobile: [ 100, 50 ], // Variable height mobile.
    multipleSpeed: 999,
    minSpeed: 8.5,
    minGap: 150,
    collisionBoxes: [
      new CollisionBox(15, 15, 16, 5),
      new CollisionBox(18, 21, 24, 6),
      new CollisionBox(2, 14, 4, 3),
      new CollisionBox(6, 10, 4, 7),
      new CollisionBox(10, 8, 6, 9)
    ],
    numFrames: 2,
    frameRate: 1000/6,
    speedOffset: .8
  }
];


//******************************************************************************
/**
 * T-rex game character.
 * @param {HTMLCanvas} canvas
 * @param {Object} spritePos Positioning within image sprite.
 * @constructor
 */
function Trex(canvas, spritePos) {
  this.canvas = canvas;
  this.canvasCtx = canvas.getContext('2d');
  this.spritePos = spritePos;
  this.xPos = 0;
  this.yPos = 0;
  // Position when on the ground.
  this.groundYPos = 0;
  this.currentFrame = 0;
  this.currentAnimFrames = [];
  this.blinkDelay = 0;
  this.blinkCount = 0;
  this.animStartTime = 0;
  this.timer = 0;
  this.msPerFrame = 1000 / FPS;
  this.config = Trex.config;
  // Current status.
  this.status = Trex.status.WAITING;

  this.jumping = false;
  this.ducking = false;
  this.jumpVelocity = 0;
  this.reachedMinHeight = false;
  this.speedDrop = false;
  this.jumpCount = 0;
  this.jumpspotX = 0;

  this.init();
};


/**
 * T-rex player config.
 * @enum {number}
 */
Trex.config = {
  DROP_VELOCITY: -5,
  GRAVITY: 0.6,
  HEIGHT: 47,
  HEIGHT_DUCK: 25,
  INIITAL_JUMP_VELOCITY: -10,
  INTRO_DURATION: 1500,
  MAX_JUMP_HEIGHT: 30,
  MIN_JUMP_HEIGHT: 30,
  SPEED_DROP_COEFFICIENT: 3,
  SPRITE_WIDTH: 262,
  START_X_POS: 50,
  WIDTH: 44,
  WIDTH_DUCK: 59
};


/**
 * Used in collision detection.
 * @type {Array<CollisionBox>}
 */
Trex.collisionBoxes = {
  DUCKING: [
    new CollisionBox(1, 18, 55, 25)
  ],
  RUNNING: [
    new CollisionBox(22, 0, 17, 16),
    new CollisionBox(1, 18, 30, 9),
    new CollisionBox(10, 35, 14, 8),
    new CollisionBox(1, 24, 29, 5),
    new CollisionBox(5, 30, 21, 4),
    new CollisionBox(9, 34, 15, 4)
  ]
};


/**
 * Animation states.
 * @enum {string}
 */
Trex.status = {
  CRASHED: 'CRASHED',
  DUCKING: 'DUCKING',
  JUMPING: 'JUMPING',
  RUNNING: 'RUNNING',
  WAITING: 'WAITING'
};

/**
 * Blinking coefficient.
 * @const
 */
Trex.BLINK_TIMING = 7000;


/**
 * Animation config for different states.
 * @enum {Object}
 */
Trex.animFrames = {
  WAITING: {
    frames: [44, 0],
    msPerFrame: 1000 / 3
  },
  RUNNING: {
    frames: [88, 132],
    msPerFrame: 1000 / 12
  },
  CRASHED: {
    frames: [220],
    msPerFrame: 1000 / 60
  },
  JUMPING: {
    frames: [0],
    msPerFrame: 1000 / 60
  },
  DUCKING: {
    frames: [264, 323],
    msPerFrame: 1000 / 8
  }
};


Trex.prototype = {
  /**
   * T-rex player initaliser.
   * Sets the t-rex to blink at random intervals.
   */
  init: function() {
    this.groundYPos = Runner.defaultDimensions.HEIGHT - this.config.HEIGHT -
        Runner.config.BOTTOM_PAD;
    this.yPos = this.groundYPos;
    this.minJumpHeight = this.groundYPos - this.config.MIN_JUMP_HEIGHT;

    this.draw(0, 0);
    this.update(0, Trex.status.WAITING);
  },

  /**
   * Setter for the jump velocity.
   * The approriate drop velocity is also set.
   */
  setJumpVelocity: function(setting) {
    this.config.INIITAL_JUMP_VELOCITY = -setting;
    this.config.DROP_VELOCITY = -setting / 2;
  },

  /**
   * Set the animation status.
   * @param {!number} deltaTime
   * @param {Trex.status} status Optional status to switch to.
   */
  update: function(deltaTime, opt_status) {
    this.timer += deltaTime;

    // Update the status.
    if (opt_status) {
      this.status = opt_status;
      this.currentFrame = 0;
      this.msPerFrame = Trex.animFrames[opt_status].msPerFrame;
      this.currentAnimFrames = Trex.animFrames[opt_status].frames;

      if (opt_status == Trex.status.WAITING) {
        this.animStartTime = getTimeStamp();
        this.setBlinkDelay();
      }
    }

    // Game intro animation, T-rex moves in from the left.
    if (this.playingIntro && this.xPos < this.config.START_X_POS) {
      this.xPos += Math.round((this.config.START_X_POS /
          this.config.INTRO_DURATION) * deltaTime);
    }

    if (this.status == Trex.status.WAITING) {
      this.blink(getTimeStamp());
    } else {
      this.draw(this.currentAnimFrames[this.currentFrame], 0);
    }

    // Update the frame position.
    if (this.timer >= this.msPerFrame) {
      this.currentFrame = this.currentFrame ==
          this.currentAnimFrames.length - 1 ? 0 : this.currentFrame + 1;
      this.timer = 0;
    }

    // Speed drop becomes duck if the down key is still being pressed.
    if (this.speedDrop && this.yPos == this.groundYPos) {
      this.speedDrop = false;
      this.setDuck(true);
    }
  },

  /**
   * Draw the t-rex to a particular position.
   * @param {number} x
   * @param {number} y
   */
  draw: function(x, y) {
    var sourceX = x;
    var sourceY = y;
    var sourceWidth = this.ducking && this.status != Trex.status.CRASHED ?
        this.config.WIDTH_DUCK : this.config.WIDTH;
    var sourceHeight = this.config.HEIGHT;
    var outputHeight = sourceHeight;

    if (IS_HIDPI) {
      sourceX *= 2;
      sourceY *= 2;
      sourceWidth *= 2;
      sourceHeight *= 2;
    }

    // Adjustments for sprite sheet position.
    sourceX += this.spritePos.x;
    sourceY += this.spritePos.y;

    // Ducking.
    if (this.ducking && this.status != Trex.status.CRASHED) {
      this.canvasCtx.drawImage(Runner.imageSprite, sourceX, sourceY,
          sourceWidth, sourceHeight,
          this.xPos, this.yPos,
          this.config.WIDTH_DUCK, outputHeight);
    } else {
      // Crashed whilst ducking. Trex is standing up so needs adjustment.
      if (this.ducking && this.status == Trex.status.CRASHED) {
        this.xPos++;
      }
      // Standing / running
      this.canvasCtx.drawImage(Runner.imageSprite, sourceX, sourceY,
          sourceWidth, sourceHeight,
          this.xPos, this.yPos,
          this.config.WIDTH, outputHeight);
    }
    this.canvasCtx.globalAlpha = 1;
  },

  /**
   * Sets a random time for the blink to happen.
   */
  setBlinkDelay: function() {
    this.blinkDelay = Math.ceil(Math.random() * Trex.BLINK_TIMING);
  },

  /**
   * Make t-rex blink at random intervals.
   * @param {number} time Current time in milliseconds.
   */
  blink: function(time) {
    var deltaTime = time - this.animStartTime;

    if (deltaTime >= this.blinkDelay) {
      this.draw(this.currentAnimFrames[this.currentFrame], 0);

      if (this.currentFrame == 1) {
        // Set new random delay to blink.
        this.setBlinkDelay();
        this.animStartTime = time;
        this.blinkCount++;
      }
    }
  },

  /**
   * Initialise a jump.
   * @param {number} speed
   */
  startJump: function(speed) {
    if (!this.jumping) {
      this.update(0, Trex.status.JUMPING);
      // Tweak the jump velocity based on the speed.
      this.jumpVelocity = this.config.INIITAL_JUMP_VELOCITY - (speed / 10);
      this.jumping = true;
      this.reachedMinHeight = false;
      this.speedDrop = false;
    }
  },

  /**
   * Jump is complete, falling down.
   */
  endJump: function() {
    if (this.reachedMinHeight &&
        this.jumpVelocity < this.config.DROP_VELOCITY) {
      this.jumpVelocity = this.config.DROP_VELOCITY;
    }
  },

  /**
   * Update frame for a jump.
   * @param {number} deltaTime
   * @param {number} speed
   */
  updateJump: function(deltaTime, speed) {
    var msPerFrame = Trex.animFrames[this.status].msPerFrame;
    var framesElapsed = deltaTime / msPerFrame;

    // Speed drop makes Trex fall faster.
    if (this.speedDrop) {
      this.yPos += Math.round(this.jumpVelocity *
          this.config.SPEED_DROP_COEFFICIENT * framesElapsed);
    } else {
      this.yPos += Math.round(this.jumpVelocity * framesElapsed);
    }

    this.jumpVelocity += this.config.GRAVITY * framesElapsed;

    // Minimum height has been reached.
    if (this.yPos < this.minJumpHeight || this.speedDrop) {
      this.reachedMinHeight = true;
    }

    // Reached max height
    if (this.yPos < this.config.MAX_JUMP_HEIGHT || this.speedDrop) {
      this.endJump();
    }

    // Back down at ground level. Jump completed.
    if (this.yPos > this.groundYPos) {
      this.reset();
      this.jumpCount++;
    }
  },

  /**
   * Set the speed drop. Immediately cancels the current jump.
   */
  setSpeedDrop: function() {
    this.speedDrop = true;
    this.jumpVelocity = 1;
  },

  /**
   * @param {boolean} isDucking.
   */
  setDuck: function(isDucking) {
    if (isDucking && this.status != Trex.status.DUCKING) {
      this.update(0, Trex.status.DUCKING);
      this.ducking = true;
    } else if (this.status == Trex.status.DUCKING) {
      this.update(0, Trex.status.RUNNING);
      this.ducking = false;
    }
  },

  /**
   * Reset the t-rex to running at start of game.
   */
  reset: function() {
    this.yPos = this.groundYPos;
    this.jumpVelocity = 0;
    this.jumping = false;
    this.ducking = false;
    this.update(0, Trex.status.RUNNING);
    this.midair = false;
    this.speedDrop = false;
    this.jumpCount = 0;
  }
};


//******************************************************************************

/**
 * Handles displaying the distance meter.
 * @param {!HTMLCanvasElement} canvas
 * @param {Object} spritePos Image position in sprite.
 * @param {number} canvasWidth
 * @constructor
 */
function DistanceMeter(canvas, spritePos, canvasWidth) {
  this.canvas = canvas;
  this.canvasCtx = canvas.getContext('2d');
  this.image = Runner.imageSprite;
  this.spritePos = spritePos;
  this.x = 0;
  this.y = 5;

  this.currentDistance = 0;
  this.maxScore = 0;
  this.highScore = 0;
  this.container = null;

  this.digits = [];
  this.achievement = false;
  this.defaultString = '';
  this.flashTimer = 0;
  this.flashIterations = 0;
  this.invertTrigger = false;
  this.flashingRafId = null;
  this.highScoreBounds = {};
  this.highScoreFlashing = false;

  this.config = DistanceMeter.config;
  this.maxScoreUnits = this.config.MAX_DISTANCE_UNITS;
  this.init(canvasWidth);
};


/**
 * @enum {number}
 */
DistanceMeter.dimensions = {
  WIDTH: 10,
  HEIGHT: 13,
  DEST_WIDTH: 11
};


/**
 * Y positioning of the digits in the sprite sheet.
 * X position is always 0.
 * @type {Array<number>}
 */
DistanceMeter.yPos = [0, 13, 27, 40, 53, 67, 80, 93, 107, 120];


/**
 * Distance meter config.
 * @enum {number}
 */
DistanceMeter.config = {
  // Number of digits.
  MAX_DISTANCE_UNITS: 5,

  // Distance that causes achievement animation.
  ACHIEVEMENT_DISTANCE: 100,

  // Used for conversion from pixel distance to a scaled unit.
  COEFFICIENT: 0.025,

  // Flash duration in milliseconds.
  FLASH_DURATION: 1000 / 4,

  // Flash iterations for achievement animation.
  FLASH_ITERATIONS: 3,

  // Padding around the high score hit area.
  HIGH_SCORE_HIT_AREA_PADDING: 4
};


DistanceMeter.prototype = {
  /**
   * Initialise the distance meter to '00000'.
   * @param {number} width Canvas width in px.
   */
  init: function(width) {
    var maxDistanceStr = '';

    this.calcXPos(width);
    this.maxScore = this.maxScoreUnits;
    for (var i = 0; i < this.maxScoreUnits; i++) {
      this.draw(i, 0);
      this.defaultString += '0';
      maxDistanceStr += '9';
    }

    this.maxScore = parseInt(maxDistanceStr);
  },

  /**
   * Calculate the xPos in the canvas.
   * @param {number} canvasWidth
   */
  calcXPos: function(canvasWidth) {
    this.x = canvasWidth - (DistanceMeter.dimensions.DEST_WIDTH *
        (this.maxScoreUnits + 1));
  },

  /**
   * Draw a digit to canvas.
   * @param {number} digitPos Position of the digit.
   * @param {number} value Digit value 0-9.
   * @param {boolean} opt_highScore Whether drawing the high score.
   */
  draw: function(digitPos, value, opt_highScore) {
    var sourceWidth = DistanceMeter.dimensions.WIDTH;
    var sourceHeight = DistanceMeter.dimensions.HEIGHT;
    var sourceX = DistanceMeter.dimensions.WIDTH * value;
    var sourceY = 0;

    var targetX = digitPos * DistanceMeter.dimensions.DEST_WIDTH;
    var targetY = this.y;
    var targetWidth = DistanceMeter.dimensions.WIDTH;
    var targetHeight = DistanceMeter.dimensions.HEIGHT;

    // For high DPI we 2x source values.
    if (IS_HIDPI) {
      sourceWidth *= 2;
      sourceHeight *= 2;
      sourceX *= 2;
    }

    sourceX += this.spritePos.x;
    sourceY += this.spritePos.y;

    this.canvasCtx.save();

    if (opt_highScore) {
      // Left of the current score.
      var highScoreX = this.x - (this.maxScoreUnits * 2) *
          DistanceMeter.dimensions.WIDTH;
      this.canvasCtx.translate(highScoreX, this.y);
    } else {
      this.canvasCtx.translate(this.x, this.y);
    }

    this.canvasCtx.drawImage(this.image, sourceX, sourceY,
        sourceWidth, sourceHeight,
        targetX, targetY,
        targetWidth, targetHeight
      );

    this.canvasCtx.restore();
  },

  /**
   * Covert pixel distance to a 'real' distance.
   * @param {number} distance Pixel distance ran.
   * @return {number} The 'real' distance ran.
   */
  getActualDistance: function(distance) {
    return distance ? Math.round(distance * this.config.COEFFICIENT) : 0;
  },

  /**
   * Update the distance meter.
   * @param {number} distance
   * @param {number} deltaTime
   * @return {boolean} Whether the acheivement sound fx should be played.
   */
  update: function(deltaTime, distance) {
    var paint = true;
    var playSound = false;

    if (!this.achievement) {
      distance = this.getActualDistance(distance);
      // Score has gone beyond the initial digit count.
      if (distance > this.maxScore && this.maxScoreUnits ==
        this.config.MAX_DISTANCE_UNITS) {
        this.maxScoreUnits++;
        this.maxScore = parseInt(this.maxScore + '9');
      } else {
        this.distance = 0;
      }

      if (distance > 0) {
        // Acheivement unlocked
        if (distance % this.config.ACHIEVEMENT_DISTANCE == 0) {
          // Flash score and play sound.
          this.achievement = true;
          this.flashTimer = 0;
          playSound = true;
        }

        // Create a string representation of the distance with leading 0.
        var distanceStr = (this.defaultString +
            distance).substr(-this.maxScoreUnits);
        this.digits = distanceStr.split('');
      } else {
        this.digits = this.defaultString.split('');
      }
    } else {
      // Control flashing of the score on reaching acheivement.
      if (this.flashIterations <= this.config.FLASH_ITERATIONS) {
        this.flashTimer += deltaTime;

        if (this.flashTimer < this.config.FLASH_DURATION) {
          paint = false;
        } else if (this.flashTimer >
            this.config.FLASH_DURATION * 2) {
          this.flashTimer = 0;
          this.flashIterations++;
        }
      } else {
        this.achievement = false;
        this.flashIterations = 0;
        this.flashTimer = 0;
      }
    }

    // Draw the digits if not flashing.
    if (paint) {
      for (var i = this.digits.length - 1; i >= 0; i--) {
        this.draw(i, parseInt(this.digits[i]));
      }
    }

    this.drawHighScore();
    return playSound;
  },

  /**
   * Draw the high score.
   */
  drawHighScore: function() {
    this.canvasCtx.save();
    this.canvasCtx.globalAlpha = .8;
    for (var i = this.highScore.length - 1; i >= 0; i--) {
      this.draw(i, parseInt(this.highScore[i], 10), true);
    }
    this.canvasCtx.restore();
  },

  /**
   * Set the highscore as a array string.
   * Position of char in the sprite: H - 10, I - 11.
   * @param {number} distance Distance ran in pixels.
   */
  setHighScore: function(distance) {
    distance = this.getActualDistance(distance);
    var highScoreStr = (this.defaultString +
        distance).substr(-this.maxScoreUnits);

    this.highScore = ['10', '11', ''].concat(highScoreStr.split(''));
  },


  /**
   * Whether a clicked is in the high score area.
   * @param {TouchEvent|ClickEvent} e Event object.
   * @return {boolean} Whether the click was in the high score bounds.
   */
  hasClickedOnHighScore: function(e) {
    var x = 0;
    var y = 0;

    if (e.touches) {
      // Bounds for touch differ from pointer.
      var canvasBounds = this.canvas.getBoundingClientRect();
      x = e.touches[0].clientX - canvasBounds.left;
      y = e.touches[0].clientY - canvasBounds.top;
    } else {
      x = e.offsetX;
      y = e.offsetY;
    }

    this.highScoreBounds = this.getHighScoreBounds();
    return x >= this.highScoreBounds.x && x <=
        this.highScoreBounds.x + this.highScoreBounds.width &&
        y >= this.highScoreBounds.y && y <=
        this.highScoreBounds.y + this.highScoreBounds.height;
  },

  /**
   * Get the bounding box for the high score.
   * @return {Object} Object with x, y, width and height properties.
   */
  getHighScoreBounds: function() {
    return {
      x: (this.x - (this.maxScoreUnits * 2) *
          DistanceMeter.dimensions.WIDTH) -
          DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING,
      y: this.y,
      width: DistanceMeter.dimensions.WIDTH * (this.highScore.length + 1) +
          DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING,
      height: DistanceMeter.dimensions.HEIGHT +
          (DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING * 2)
    };
  },

  /**
   * Animate flashing the high score to indicate ready for resetting.
   * The flashing stops following this.config.FLASH_ITERATIONS x 2 flashes.
   */
  flashHighScore: function() {
    var now = getTimeStamp();
    var deltaTime = now - (this.frameTimeStamp || now);
    var paint = true;
    this.frameTimeStamp = now;

    // Reached the max number of flashes.
    if (this.flashIterations > this.config.FLASH_ITERATIONS * 2) {
      this.cancelHighScoreFlashing();
      return;
    }

    this.flashTimer += deltaTime;

    if (this.flashTimer < this.config.FLASH_DURATION) {
      paint = false;
    } else if (this.flashTimer > this.config.FLASH_DURATION * 2) {
      this.flashTimer = 0;
      this.flashIterations++;
    }

    if (paint) {
      this.drawHighScore();
    } else {
      this.clearHighScoreBounds();
    }
    // Frame update.
    this.flashingRafId =
        requestAnimationFrame(this.flashHighScore.bind(this));
  },

  /**
   * Draw empty rectangle over high score.
   */
  clearHighScoreBounds: function() {
    this.canvasCtx.save();
    this.canvasCtx.fillStyle = '#fff';
    this.canvasCtx.rect(this.highScoreBounds.x, this.highScoreBounds.y,
        this.highScoreBounds.width, this.highScoreBounds.height);
    this.canvasCtx.fill();
    this.canvasCtx.restore();
  },

  /**
   * Starts the flashing of the high score.
   */
  startHighScoreFlashing() {
    this.highScoreFlashing = true;
    this.flashHighScore();
  },

  /**
   * Whether high score is flashing.
   * @return {boolean}
   */
  isHighScoreFlashing() {
    return this.highScoreFlashing;
  },

  /**
   * Stop flashing the high score.
   */
  cancelHighScoreFlashing: function() {
    cancelAnimationFrame(this.flashingRafId);
    this.flashIterations = 0;
    this.flashTimer = 0;
    this.highScoreFlashing = false;
    this.clearHighScoreBounds();
    this.drawHighScore();
  },

  /**
   * Clear the high score.
   */
  resetHighScore: function() {
    this.setHighScore(0);
    this.cancelHighScoreFlashing();
  },

  /**
   * Reset the distance meter back to '00000'.
   */
  reset: function() {
    this.update(0);
    this.achievement = false;
  }
};


//******************************************************************************

/**
 * Cloud background item.
 * Similar to an obstacle object but without collision boxes.
 * @param {HTMLCanvasElement} canvas Canvas element.
 * @param {Object} spritePos Position of image in sprite.
 * @param {number} containerWidth
 */
function Cloud(canvas, spritePos, containerWidth) {
  this.canvas = canvas;
  this.canvasCtx = this.canvas.getContext('2d');
  this.spritePos = spritePos;
  this.containerWidth = containerWidth;
  this.xPos = containerWidth;
  this.yPos = 0;
  this.remove = false;
  this.cloudGap = getRandomNum(Cloud.config.MIN_CLOUD_GAP,
      Cloud.config.MAX_CLOUD_GAP);

  this.init();
};


/**
 * Cloud object config.
 * @enum {number}
 */
Cloud.config = {
  HEIGHT: 14,
  MAX_CLOUD_GAP: 400,
  MAX_SKY_LEVEL: 30,
  MIN_CLOUD_GAP: 100,
  MIN_SKY_LEVEL: 71,
  WIDTH: 46
};


Cloud.prototype = {
  /**
   * Initialise the cloud. Sets the Cloud height.
   */
  init: function() {
    this.yPos = getRandomNum(Cloud.config.MAX_SKY_LEVEL,
        Cloud.config.MIN_SKY_LEVEL);
    this.draw();
  },

  /**
   * Draw the cloud.
   */
  draw: function() {
    this.canvasCtx.save();
    var sourceWidth = Cloud.config.WIDTH;
    var sourceHeight = Cloud.config.HEIGHT;
    var outputWidth = sourceWidth;
    var outputHeight = sourceHeight;
    if (IS_HIDPI) {
      sourceWidth = sourceWidth * 2;
      sourceHeight = sourceHeight * 2;
    }

    this.canvasCtx.drawImage(Runner.imageSprite, this.spritePos.x,
        this.spritePos.y,
        sourceWidth, sourceHeight,
        this.xPos, this.yPos,
        outputWidth, outputHeight);

    this.canvasCtx.restore();
  },

  /**
   * Update the cloud position.
   * @param {number} speed
   */
  update: function(speed) {
    if (!this.remove) {
      this.xPos -= Math.ceil(speed);
      this.draw();

      // Mark as removeable if no longer in the canvas.
      if (!this.isVisible()) {
        this.remove = true;
      }
    }
  },

  /**
   * Check if the cloud is visible on the stage.
   * @return {boolean}
   */
  isVisible: function() {
    return this.xPos + Cloud.config.WIDTH > 0;
  }
};


//******************************************************************************

/**
 * Nightmode shows a moon and stars on the horizon.
 */
function NightMode(canvas, spritePos, containerWidth) {
  this.spritePos = spritePos;
  this.canvas = canvas;
  this.canvasCtx = canvas.getContext('2d');
  this.xPos = containerWidth - 50;
  this.yPos = 30;
  this.currentPhase = 0;
  this.opacity = 0;
  this.containerWidth = containerWidth;
  this.stars = [];
  this.drawStars = false;
  this.placeStars();
};

/**
 * @enum {number}
 */
NightMode.config = {
  FADE_SPEED: 0.035,
  HEIGHT: 40,
  MOON_SPEED: 0.25,
  NUM_STARS: 2,
  STAR_SIZE: 9,
  STAR_SPEED: 0.3,
  STAR_MAX_Y: 70,
  WIDTH: 20
};

NightMode.phases = [140, 120, 100, 60, 40, 20, 0];

NightMode.prototype = {
  /**
   * Update moving moon, changing phases.
   * @param {boolean} activated Whether night mode is activated.
   * @param {number} delta
   */
  update: function(activated, delta) {
    // Moon phase.
    if (activated && this.opacity == 0) {
      this.currentPhase++;

      if (this.currentPhase >= NightMode.phases.length) {
        this.currentPhase = 0;
      }
    }

    // Fade in / out.
    if (activated && (this.opacity < 1 || this.opacity == 0)) {
      this.opacity += NightMode.config.FADE_SPEED;
    } else if (this.opacity > 0) {
      this.opacity -= NightMode.config.FADE_SPEED;
    }

    // Set moon positioning.
    if (this.opacity > 0) {
      this.xPos = this.updateXPos(this.xPos, NightMode.config.MOON_SPEED);

      // Update stars.
      if (this.drawStars) {
         for (var i = 0; i < NightMode.config.NUM_STARS; i++) {
            this.stars[i].x = this.updateXPos(this.stars[i].x,
                NightMode.config.STAR_SPEED);
         }
      }
      this.draw();
    } else {
      this.opacity = 0;
      this.placeStars();
    }
    this.drawStars = true;
  },

  updateXPos: function(currentPos, speed) {
    if (currentPos < -NightMode.config.WIDTH) {
      currentPos = this.containerWidth;
    } else {
      currentPos -= speed;
    }
    return currentPos;
  },

  draw: function() {
    var moonSourceWidth = this.currentPhase == 3 ? NightMode.config.WIDTH * 2 :
         NightMode.config.WIDTH;
    var moonSourceHeight = NightMode.config.HEIGHT;
    var moonSourceX = this.spritePos.x + NightMode.phases[this.currentPhase];
    var moonOutputWidth = moonSourceWidth;
    var starSize = NightMode.config.STAR_SIZE;
    var starSourceX = Runner.spriteDefinition.LDPI.STAR.x;

    if (IS_HIDPI) {
      moonSourceWidth *= 2;
      moonSourceHeight *= 2;
      moonSourceX = this.spritePos.x +
          (NightMode.phases[this.currentPhase] * 2);
      starSize *= 2;
      starSourceX = Runner.spriteDefinition.HDPI.STAR.x;
    }

    this.canvasCtx.save();
    this.canvasCtx.globalAlpha = this.opacity;

    // Stars.
    if (this.drawStars) {
      for (var i = 0; i < NightMode.config.NUM_STARS; i++) {
        this.canvasCtx.drawImage(Runner.imageSprite,
            starSourceX, this.stars[i].sourceY, starSize, starSize,
            Math.round(this.stars[i].x), this.stars[i].y,
            NightMode.config.STAR_SIZE, NightMode.config.STAR_SIZE);
      }
    }

    // Moon.
    this.canvasCtx.drawImage(Runner.imageSprite, moonSourceX,
        this.spritePos.y, moonSourceWidth, moonSourceHeight,
        Math.round(this.xPos), this.yPos,
        moonOutputWidth, NightMode.config.HEIGHT);

    this.canvasCtx.globalAlpha = 1;
    this.canvasCtx.restore();
  },

  // Do star placement.
  placeStars: function() {
    var segmentSize = Math.round(this.containerWidth /
        NightMode.config.NUM_STARS);

    for (var i = 0; i < NightMode.config.NUM_STARS; i++) {
      this.stars[i] = {};
      this.stars[i].x = getRandomNum(segmentSize * i, segmentSize * (i + 1));
      this.stars[i].y = getRandomNum(0, NightMode.config.STAR_MAX_Y);

      if (IS_HIDPI) {
        this.stars[i].sourceY = Runner.spriteDefinition.HDPI.STAR.y +
            NightMode.config.STAR_SIZE * 2 * i;
      } else {
        this.stars[i].sourceY = Runner.spriteDefinition.LDPI.STAR.y +
            NightMode.config.STAR_SIZE * i;
      }
    }
  },

  reset: function() {
    this.currentPhase = 0;
    this.opacity = 0;
    this.update(false);
  }

};


//******************************************************************************

/**
 * Horizon Line.
 * Consists of two connecting lines. Randomly assigns a flat / bumpy horizon.
 * @param {HTMLCanvasElement} canvas
 * @param {Object} spritePos Horizon position in sprite.
 * @constructor
 */
function HorizonLine(canvas, spritePos) {
  this.spritePos = spritePos;
  this.canvas = canvas;
  this.canvasCtx = canvas.getContext('2d');
  this.sourceDimensions = {};
  this.dimensions = HorizonLine.dimensions;
  this.sourceXPos = [this.spritePos.x, this.spritePos.x +
      this.dimensions.WIDTH];
  this.xPos = [];
  this.yPos = 0;
  this.bumpThreshold = 0.5;

  this.setSourceDimensions();
  this.draw();
};


/**
 * Horizon line dimensions.
 * @enum {number}
 */
HorizonLine.dimensions = {
  WIDTH: 600,
  HEIGHT: 12,
  YPOS: 127
};


HorizonLine.prototype = {
  /**
   * Set the source dimensions of the horizon line.
   */
  setSourceDimensions: function() {

    for (var dimension in HorizonLine.dimensions) {
      if (IS_HIDPI) {
        if (dimension != 'YPOS') {
          this.sourceDimensions[dimension] =
              HorizonLine.dimensions[dimension] * 2;
        }
      } else {
        this.sourceDimensions[dimension] =
            HorizonLine.dimensions[dimension];
      }
      this.dimensions[dimension] = HorizonLine.dimensions[dimension];
    }

    this.xPos = [0, HorizonLine.dimensions.WIDTH];
    this.yPos = HorizonLine.dimensions.YPOS;
  },

  /**
   * Return the crop x position of a type.
   */
  getRandomType: function() {
    return Math.random() > this.bumpThreshold ? this.dimensions.WIDTH : 0;
  },

  /**
   * Draw the horizon line.
   */
  draw: function() {
    this.canvasCtx.drawImage(Runner.imageSprite, this.sourceXPos[0],
        this.spritePos.y,
        this.sourceDimensions.WIDTH, this.sourceDimensions.HEIGHT,
        this.xPos[0], this.yPos,
        this.dimensions.WIDTH, this.dimensions.HEIGHT);

    this.canvasCtx.drawImage(Runner.imageSprite, this.sourceXPos[1],
        this.spritePos.y,
        this.sourceDimensions.WIDTH, this.sourceDimensions.HEIGHT,
        this.xPos[1], this.yPos,
        this.dimensions.WIDTH, this.dimensions.HEIGHT);
  },

  /**
   * Update the x position of an indivdual piece of the line.
   * @param {number} pos Line position.
   * @param {number} increment
   */
  updateXPos: function(pos, increment) {
    var line1 = pos;
    var line2 = pos == 0 ? 1 : 0;

    this.xPos[line1] -= increment;
    this.xPos[line2] = this.xPos[line1] + this.dimensions.WIDTH;

    if (this.xPos[line1] <= -this.dimensions.WIDTH) {
      this.xPos[line1] += this.dimensions.WIDTH * 2;
      this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH;
      this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x;
    }
  },

  /**
   * Update the horizon line.
   * @param {number} deltaTime
   * @param {number} speed
   */
  update: function(deltaTime, speed) {
    var increment = Math.floor(speed * (FPS / 1000) * deltaTime);

    if (this.xPos[0] <= 0) {
      this.updateXPos(0, increment);
    } else {
      this.updateXPos(1, increment);
    }
    this.draw();
  },

  /**
   * Reset horizon to the starting position.
   */
  reset: function() {
    this.xPos[0] = 0;
    this.xPos[1] = HorizonLine.dimensions.WIDTH;
  }
};


//******************************************************************************

/**
 * Horizon background class.
 * @param {HTMLCanvasElement} canvas
 * @param {Object} spritePos Sprite positioning.
 * @param {Object} dimensions Canvas dimensions.
 * @param {number} gapCoefficient
 * @constructor
 */
function Horizon(canvas, spritePos, dimensions, gapCoefficient) {
  this.canvas = canvas;
  this.canvasCtx = this.canvas.getContext('2d');
  this.config = Horizon.config;
  this.dimensions = dimensions;
  this.gapCoefficient = gapCoefficient;
  this.obstacles = [];
  this.obstacleHistory = [];
  this.horizonOffsets = [0, 0];
  this.cloudFrequency = this.config.CLOUD_FREQUENCY;
  this.spritePos = spritePos;
  this.nightMode = null;

  // Cloud
  this.clouds = [];
  this.cloudSpeed = this.config.BG_CLOUD_SPEED;

  // Horizon
  this.horizonLine = null;
  this.init();
};


/**
 * Horizon config.
 * @enum {number}
 */
Horizon.config = {
  BG_CLOUD_SPEED: 0.2,
  BUMPY_THRESHOLD: .3,
  CLOUD_FREQUENCY: .5,
  HORIZON_HEIGHT: 16,
  MAX_CLOUDS: 6
};


Horizon.prototype = {
  /**
   * Initialise the horizon. Just add the line and a cloud. No obstacles.
   */
  init: function() {
    this.addCloud();
    this.horizonLine = new HorizonLine(this.canvas, this.spritePos.HORIZON);
    this.nightMode = new NightMode(this.canvas, this.spritePos.MOON,
        this.dimensions.WIDTH);
  },

  /**
   * @param {number} deltaTime
   * @param {number} currentSpeed
   * @param {boolean} updateObstacles Used as an override to prevent
   *     the obstacles from being updated / added. This happens in the
   *     ease in section.
   * @param {boolean} showNightMode Night mode activated.
   */
  update: function(deltaTime, currentSpeed, updateObstacles, showNightMode) {
    this.runningTime += deltaTime;
    this.horizonLine.update(deltaTime, currentSpeed);
    this.nightMode.update(showNightMode);
    this.updateClouds(deltaTime, currentSpeed);

    if (updateObstacles) {
      this.updateObstacles(deltaTime, currentSpeed);
    }
  },

  /**
   * Update the cloud positions.
   * @param {number} deltaTime
   * @param {number} currentSpeed
   */
  updateClouds: function(deltaTime, speed) {
    var cloudSpeed = this.cloudSpeed / 1000 * deltaTime * speed;
    var numClouds = this.clouds.length;

    if (numClouds) {
      for (var i = numClouds - 1; i >= 0; i--) {
        this.clouds[i].update(cloudSpeed);
      }

      var lastCloud = this.clouds[numClouds - 1];

      // Check for adding a new cloud.
      if (numClouds < this.config.MAX_CLOUDS &&
          (this.dimensions.WIDTH - lastCloud.xPos) > lastCloud.cloudGap &&
          this.cloudFrequency > Math.random()) {
        this.addCloud();
      }

      // Remove expired clouds.
      this.clouds = this.clouds.filter(function(obj) {
        return !obj.remove;
      });
    } else {
      this.addCloud();
    }
  },

  /**
   * Update the obstacle positions.
   * @param {number} deltaTime
   * @param {number} currentSpeed
   */
  updateObstacles: function(deltaTime, currentSpeed) {
    // Obstacles, move to Horizon layer.
    var updatedObstacles = this.obstacles.slice(0);

    for (var i = 0; i < this.obstacles.length; i++) {
      var obstacle = this.obstacles[i];
      obstacle.update(deltaTime, currentSpeed);

      // Clean up existing obstacles.
      if (obstacle.remove) {
        updatedObstacles.shift();
      }
    }
    this.obstacles = updatedObstacles;

    if (this.obstacles.length > 0) {
      var lastObstacle = this.obstacles[this.obstacles.length - 1];

      if (lastObstacle && !lastObstacle.followingObstacleCreated &&
          lastObstacle.isVisible() &&
          (lastObstacle.xPos + lastObstacle.width + lastObstacle.gap) <
          this.dimensions.WIDTH) {
        this.addNewObstacle(currentSpeed);
        lastObstacle.followingObstacleCreated = true;
      }
    } else {
      // Create new obstacles.
      this.addNewObstacle(currentSpeed);
    }
  },

  removeFirstObstacle: function() {
    this.obstacles.shift();
  },

  /**
   * Add a new obstacle.
   * @param {number} currentSpeed
   */
  addNewObstacle: function(currentSpeed) {
    var obstacleTypeIndex = getRandomNum(0, Obstacle.types.length - 1);
    var obstacleType = Obstacle.types[obstacleTypeIndex];

    // Check for multiples of the same type of obstacle.
    // Also check obstacle is available at current speed.
    if (this.duplicateObstacleCheck(obstacleType.type) ||
        currentSpeed < obstacleType.minSpeed) {
      this.addNewObstacle(currentSpeed);
    } else {
      var obstacleSpritePos = this.spritePos[obstacleType.type];

      this.obstacles.push(new Obstacle(this.canvasCtx, obstacleType,
          obstacleSpritePos, this.dimensions,
          this.gapCoefficient, currentSpeed, obstacleType.width));

      this.obstacleHistory.unshift(obstacleType.type);

      if (this.obstacleHistory.length > 1) {
        this.obstacleHistory.splice(Runner.config.MAX_OBSTACLE_DUPLICATION);
      }
    }
  },

  /**
   * Returns whether the previous two obstacles are the same as the next one.
   * Maximum duplication is set in config value MAX_OBSTACLE_DUPLICATION.
   * @return {boolean}
   */
  duplicateObstacleCheck: function(nextObstacleType) {
    var duplicateCount = 0;

    for (var i = 0; i < this.obstacleHistory.length; i++) {
      duplicateCount = this.obstacleHistory[i] == nextObstacleType ?
          duplicateCount + 1 : 0;
    }
    return duplicateCount >= Runner.config.MAX_OBSTACLE_DUPLICATION;
  },

  /**
   * Reset the horizon layer.
   * Remove existing obstacles and reposition the horizon line.
   */
  reset: function() {
    this.obstacles = [];
    this.horizonLine.reset();
    this.nightMode.reset();
  },

  /**
   * Update the canvas width and scaling.
   * @param {number} width Canvas width.
   * @param {number} height Canvas height.
   */
  resize: function(width, height) {
    this.canvas.width = width;
    this.canvas.height = height;
  },

  /**
   * Add a new cloud to the horizon.
   */
  addCloud: function() {
    this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD,
        this.dimensions.WIDTH));
  }
};
})();
</script>
</head>
<body id="t" style="font-family: $i18n{fontfamily}; font-size: $i18n{fontsize}">
  <div id="main-frame-error" class="interstitial-wrapper">
    <div id="main-content">
      <div class="icon"
          jseval="updateIconClass(this.classList, iconClass)" alt=""></div>
      <div id="main-message">
        <h1>
          <span jsselect="heading" jsvalues=".innerHTML:msg"></span>
          <a id="error-information-button" class="hidden" onclick="toggleErrorInformationPopup();"></a>
        </h1>
        <p jsselect="summary" jsvalues=".innerHTML:msg"></p>
        <!--The suggestion list and error code are normally presented inline,
          in which case error-information-popup-* divs have no effect. When
          error-information-popup-container has the use-popup-container class, this
          information is provided in a popup instead.-->
        <div id="error-information-popup-container">
          <div id="error-information-popup">
            <div id="error-information-popup-box">
              <div id="error-information-popup-content">
                <div id="suggestions-list" style="display:none"
                    jsdisplay="(suggestionsSummaryList && suggestionsSummaryList.length)">
                  <p jsvalues=".innerHTML:suggestionsSummaryListHeader"></p>
                  <ul jsvalues=".className:suggestionsSummaryList.length == 1 ? 'single-suggestion' : ''">
                    <li jsselect="suggestionsSummaryList" jsvalues=".innerHTML:summary"></li>
                  </ul>
                </div>
                <div class="error-code" jscontent="errorCode"></div>
                <p id="error-information-popup-close">
                  <a class="link-button" jscontent="closeDescriptionPopup" onclick="toggleErrorInformationPopup();"></a>
                </p>
              </div>
            </div>
          </div>
        </div>
        <div id="diagnose-frame" class="hidden"></div>
        <div id="download-links-wrapper" class="hidden">
          <div id="download-link-wrapper">
            <a id="download-link" class="link-button"
                onclick="downloadButtonClick()" jsselect="downloadButton"
                jscontent="msg" jsvalues=".disabledText:disabledMsg">
            </a>
          </div>
          <div id="download-link-clicked-wrapper" class="hidden">
            <div id="download-link-clicked" class="link-button"
                jsselect="downloadButton" jscontent="disabledMsg">
            </div>
          </div>
        </div>
        <div id="offline-content-list" class="list-hidden" hidden>
          <div id="offline-content-list-visibility-card"
              onclick="toggleOfflineContentListVisibility(true)">
            <div id="offline-content-list-title"
                jsselect="offlineContentList" jscontent="title">
            </div>
            <div>
              <div id="offline-content-list-show-text"
                  jsselect="offlineContentList" jscontent="showText">
              </div>
              <div id="offline-content-list-hide-text"
                  jsselect="offlineContentList" jscontent="hideText">
              </div>
            </div>
          </div>
          <div id="offline-content-suggestions"></div>
          <div id="offline-content-list-action">
            <a class="link-button" onclick="launchDownloadsPage()"
                jsselect="offlineContentList" jscontent="actionText">
            </a>
          </div>
        </div>
        <div id="offline-content-summary" onclick="launchDownloadsPage()" hidden>
          <div class="offline-content-summary-images">
            <div class="offline-content-summary-image-truncate">
              <img id="earth" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8cGF0aCBkPSJNMTIsMiBDMTcuNTIsMiAyMiw2LjQ4IDIyLDEyIEMyMiwxNy41MiAxNy41MiwyMiAxMiwyMiBDNi40OCwyMiAyLDE3LjUyIDIsMTIgQzIsNi40OCA2LjQ4LDIgMTIsMiBaIE00LDEyIEw4LjM5OTY1NzM4LDEyIEMxMS44MDY5NTY0LDEyLjAyMTY3MDMgMTMuMzIxNTEyNywxMy43MzA2ODgxIDEyLjk0MzMyNjMsMTcuMTI3MDUzMyBMOS40ODc3OTI5NywxNy4xMjcwNTMzIEw5LjQ4Nzc5Mjk3LDE5LjU5Njk2NzcgQzEwLjI3Nzk4MTIsMTkuODU4NDUzMyAxMS4xMjI1ODYyLDIwIDEyLDIwIEMxNi40MTU0MzA1LDIwIDIwLDE2LjQxNTQzMDUgMjAsMTIgQzIwLDExLjgzNjk2ODkgMTkuOTk1MTEzMSwxMS42NzUwNzA1IDE5Ljk4NTQ3OCwxMS41MTQ0NDM1IEMxOS4zMjg0OTI3LDEyLjUwNDgxNDUgMTguMzMzMzMzMywxMyAxNywxMyBDMTQuODYyNTcwOSwxMyAxMy43OTM4NTY0LDEyLjA4MzU3NTEgMTMuNzkzODU2NCwxMC4yNTA3MjUyIEwxMC4wNDU2OTYyLDEwLjI1MDcyNTIgQzkuNzcxODkzODEsNy41MjI0MzE3NyAxMC43Mjg1MTc1LDYuMTU4Mjg1MDcgMTIuOTE1NTY3Miw2LjE1ODI4NTA3IEMxMi45MTU1NjcyLDUuMTgzMDg2OTIgMTMuMjQzMDA2Myw0LjU2MTQ2MTg1IDEzLjcyNzI1NTUsNC4xODcyNjgyIEMxMy4xNzA5MzQsNC4wNjQ2NDU4IDEyLjU5Mjk1OSw0IDEyLDQgQzcuNTg0NTY5NSw0IDQsNy41ODQ1Njk1IDQsMTIgWiIgaWQ9IkNvbWJpbmVkLVNoYXBlIiBmaWxsPSIjM0M0MDQzIiBmaWxsLXJ1bGU9Im5vbnplcm8iPjwvcGF0aD4KPC9zdmc+">
            </div>
            <div class="offline-content-summary-image-truncate">
              <img id="music-note" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik0xMiwzVjEyLjI2QzExLjUsMTIuMDkgMTEsMTIgMTAuNSwxMkM4LDEyIDYsMTQgNiwxNi41QzYsMTkgOCwyMSAxMC41LDIxQzEzLDIxIDE1LDE5IDE1LDE2LjVWNkgxOVYzSDEyWiIgZmlsbD0iIzNDNDA0MyIgLz4KPC9zdmc+">
            </div>
            <div class="offline-content-summary-image-truncate">
              <img id="video" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik0xNywxMC41VjdBMSwxIDAgMCwwIDE2LDZINEExLDEgMCAwLDAgMyw3VjE3QTEsMSAwIDAsMCA0LDE4SDE2QTEsMSAwIDAsMCAxNywxN1YxMy41TDIxLDE3LjVWNi41TDE3LDEwLjVaIiBmaWxsPSIjM0M0MDQzIiAvPgo8L3N2Zz4=">
            </div>
            <div>
              <img id="image" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGQ9Ik04LjUsMTMuNUwxMSwxNi41TDE0LjUsMTJMMTksMThINU0yMSwxOVY1QzIxLDMuODkgMjAuMSwzIDE5LDNINUEyLDIgMCAwLDAgMyw1VjE5QTIsMiAwIDAsMCA1LDIxSDE5QTIsMiAwIDAsMCAyMSwxOVoiIGZpbGw9IiMzQzQwNDMiIC8+Cjwvc3ZnPg==">
            </div>
          </div>
          <div class="offline-content-summary-description"
              jsselect="offlineContentSummary" jscontent="description">
          </div>
          <a class="offline-content-summary-action link-button"
              jsselect="offlineContentSummary" jscontent="actionText">
          </a>
        </div>
      </div>
    </div>
    <div id="buttons" class="nav-wrapper">
      <div id="control-buttons" hidden>
        <button id="reload-button"
            class="blue-button text-button"
            onclick="trackClick(this.trackingId);
                     reloadButtonClick(this.url);"
            jsselect="reloadButton"
            jsvalues=".url:reloadUrl; .trackingId:reloadTrackingId"
            jscontent="msg"></button>
        <button id="show-saved-copy-button"
            class="blue-button text-button"
            onclick="showSavedCopyButtonClick()"
            jsselect="showSavedCopyButton"
            jscontent="msg" jsvalues="title:title; .primary:primary">
        </button>
        <button id="download-button"
            class="blue-button text-button"
            onclick="downloadButtonClick()"
            jsselect="downloadButton"
            jscontent="msg" jsvalues=".disabledText:disabledMsg">
        </button>
        <div id="save-page-for-later-button" class="hidden">
          <a class="link-button" onclick="savePageLaterClick()"
            jsselect="savePageLater"
            jscontent="savePageMsg">
          </a>
        </div>
        <div id="cancel-save-page-button" class="hidden"
          onclick="cancelSavePageClick()"
          jsselect="savePageLater"
          jsvalues=".innerHTML:cancelMsg">
        </div>
      </div>
      <button id="details-button" class="secondary-button text-button small-link"
         onclick="detailsButtonClick(); toggleHelpBox()" jscontent="details"
         jsdisplay="(suggestionsDetails && suggestionsDetails.length > 0) || diagnose"
         jsvalues=".detailsText:details; .hideDetailsText:hideDetails;"></button>
    </div>
    <div id="details" class="hidden">
      <div class="suggestions" jsselect="suggestionsDetails">
        <div class="suggestion-header" jsvalues=".innerHTML:header"></div>
        <div class="suggestion-body" jsvalues=".innerHTML:body"></div>
      </div>
    </div>
  </div>
  <div id="sub-frame-error">
    <!-- Show details when hovering over the icon, in case the details are
         hidden because they're too large. -->
    <div class="icon"
        jseval="updateIconClass(this.classList, iconClass)"></div>
    <div id="sub-frame-error-details" jsselect="summary" jsvalues=".innerHTML:msg"></div>
  </div>

  <div id="offline-resources">
    <img id="offline-resources-1x" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABNEAAABEBAMAAABdZr6uAAAAGFBMVEUAAAD////a2tr/9/e6urpTU1P39/e5ubkY2m5RAAAAAXRSTlMAQObYZgAACRdJREFUeAHt3cFuo0gQBuDCvWiu1IG7lSdAQtxzmAcAWbVvkJzntq+/cfPDFHGB29gdcNK/Zj3tKgIJ+bYBJ2boeyUlJSUl40kKCsnh5UiBYWuTGHARUkDquhrHrq7pagOxGy8vL8ujqwvQkFciyqU9P7ZEItKSfMQXc/80l34kJIJFcqFcsNxt4TExqxFSyiQdXQl2czA1tjZZ9J6kCyggTuREQxqR6moDsRv4/NdKo8NUGkB5VAJB8OXhQVquRj9NWiafUlzd+uHo9zoFhYWNTXYD8iKoACqjFSfQtdRwNSHTBsgcL0bnQNEQ1UBHj7Q0grReENE4k1H/xDe8r3YcCVHe3g5NEI5bRQR54JSGdNe2fsC3I560AoVsrTTUqwVphjmtCLE6n9fxz2+iiRvBSFppMYmRz3nUhktL0m46VWMRtqQVgJUR8adC1kFaWfjCOmkOI0savBhTGkYBkxph9Psjr8pN/vfA2epj5nDapmrrpMkYjl8lGRNNmr11JQ27ep20rAOsssiEp4XSF/xJWl9YAFVXq6Qd6T5pGBtzmkcGadRfJkCa7/rBvdL4Bj18S5UtacwPlfbvnDRCmT8fNI5AhyWZrDCz+lglrZTCb5vPw25a0NJ8YV6ak1OANFejgUDXJbQjRirgZVE7YPSqpMHS4EswGhegXNX2Jq3sLGmoPkzaW6C0w9F8sSOCtOKKNBSrJWkOH1pFl9bCDaa0QVoupjQ0tjt6bijtPeToiR2ucpw9RqJ8Sa2AtGwqTRVwOH2AtKbCCA2DF0aQhpEKdC1cHrz2J/stpLWkLkAvpOnG1tI2OHq+f+QN2hakYT7TeTneKi3rIK0slLRpgX2B75bm5GRKO9Ld0tSk9oeI8un5l4i0HhSJ4AHEziM8w+tpP+iK4IPYOR9/vV2RRpc5YjlLGguk6ebUEaShcF1aXf0F5SpIQ2Mbab/oz69AaUna+zCnvS9JOxxfDGuHL5XW0wGo5lRBGhqKoC3N1RfQjhhBGkY6kKZe1tXUMKdFyLeUhiPnv4vSXojsbwQWY3uf4PE+aXgxw8sariQdnk8aIDgjrZHq8dJ+/Uc3JEl7uyptLvdLk2vSnFcyyqpsabphSjsPHi7tv4/8oclxUKTFKBf/H8Z6mbG0uCTGxl71ub+6gTSZl8Y+16AJ97ko4697pGlQtXJT2Y1FaXBivrBxxGgaOpgveeADMacFSkvSZDtp2ZNLw7Wn9pPLOJT8rxmaBrrM8cUy7+/WDwiZY1R1lLMI0uytL0DT4cUypImazajU0jDEo6yV5qqvkuavPS0bkCZJ2rbSugywCsoGWCiM0sr10hrPqv6qOS26tHfx0jJWhxkiFo5SJSFEK/MtK1hDcas0e+vz4T4yBM/JLI/SCkjrxt+R46EwSCv6+hpptf8j8hXSxp97SvAZl20yN5bEmncqLeMhhSGNx2worWPqpXExSOvGwiiNGLPeemkVVfGlLemiNr8+pxlXB6TKLUEacznuTCI4iVAl9aUoaX2bFS81LDvmQtljU9oYSDO3jtx7EMXJGSayggjDYigoaYRZb0lavSTtRO7kpdXxpL2+vv5QaeOHScespSGCMOufRvm8xZeGCQxbHqV1PBQAb5TGxbI0H1vaqa4IL7JJPGn//O5xzJ1xBUojkdaURiJnaYLvHQIncaokYrzCwaIWBq/JsFP2xJQm70iPwNx6ODXgnC2rszMlTRdKLa2gBWluWRpRfGn+d26JRMTWFfB6GgJoekkQlp1KK2UcG9JkDKRNE19axj0s4nIqDQWQkxBp1ARIoyb+nBZf2uR7x3ASqUoioqDRKO0iXamkXYSXpVlbD5eGsF3n4PdG+dJ1aW5ZmvNzGhaKeJ4WOzGlJWlFiDRqFqU1H43q/CBRrz2/Rhqiz+cjVUkmoT4wYaZjk1qANBXmYGn2R7AqB0vrWBWGS8waoGrpHyoih4YpzcmpkVpOrq6j/YQ9SXt2aTSRhgDTMCZCEw0QvJBG5AabEaTRBtLIhyNVLWnL1Loi4/JuaRQWnn2ZlxGi+6VVTo0hTTegzpAGm1tIS9LsuyXsThqcgEqjxl4anrhGc7SlVRHeRxA9BgmOXCVTmk0N0miBGs/dAYbXSQtYdp00aAIVB2d1BWmqgRaGWhoa30Max66SCW29NPOuVsbWt5cGRHWtJzGkUQ0QxFBLQyPCu/A2oMbRq2RKM6l1cGNTYx+aC6+UxhRJGtX13zfb4UqSENUAQQyVtKjvYU/S9iYt/l2tFMHm+0gzru3jV0lDs6jh5VoMCqLP1JjHQdhX9XhpxFwMB+6wwop7DblaSwu7AwyGGhpILdwBZhtpSVq8rLqrFa4Wot3VahNqzHGriAHNa5q+tNGnQFdTY2Ik9KsKDQvTzqThdC3anfp+sDTmsuM5aR2z8I+S5pt1Ffnuo/GjjlwswhxaZRzYdJWD1gBqdCmtxC8IeWkGG2w1WI7aenCY9ifNNVKpRoQ7Kv8saRlDWpGVWLe51TA6OJ3D1gV5TmmkpUW6S3z86DNhFg6v4sA2pRa4hl7ZpTR/f4uC5qQxETM4r/uq4ie+tAj5YdIoG6VN1o1AWh9K0p5XGuMhrGqEmUPXQEKWNGYuu4LmpAHYTdKYkrTZJGmILS08Iknabo+ewqFVO4FrIBE8GAfQInDVK7+q7aU5DapabFjSKtp7krScto1zHlTjrVT972qfLhrk0DCkofHMGd8ZHlo1s7SGgOAMbWHV4RExtr5xmkbGqcudBDOUbvQE0XBamm7ET5L23HGu/khFAHXOpwYIwldFbnwXnmqEJCXFaStNpRuK4Lnh8M9+NpWrdSMoKSmaigtoqDGePFtSUlJSUlJSRIT2nFykNcbPlpS8Pf/ZcYSoNcZPlpRciEhov8E/eKvHz5gUweM+A1h4FFV5SOTrktJiZhuCZ/uJMtHe54NS9jaFCKWkxE4/d6TkcuvybeBJ5/pgI/ETvrm0r4I3JxK2IkKEwiJzK0Da0CPMRdqgb7C0K2jk2CIWCNxXaV/tMnnYEisiKz6DDfdS2lf53OckcuP/S0HTd4stYPE4EVqTNu2r4AQeOmXVYaLd3TkjPu/2wfu2Tfvqhn313ZOSkpLyPyeERVeEgd/fAAAAAElFTkSuQmCC">
    <img id="offline-resources-2x" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACY4AAACCBAMAAAAZXNPFAAAAJFBMVEX////////a2tr/9/e5ubn39/dTU1P29vbv7+/+/v74+Pjw8PCvMVmIAAAAAXRSTlMAQObYZgAAC3pJREFUeAHs3cFx6soSxnGt7r5TcAqTAgF4Q3n7VkrBIZytQ3AWJ703HBn/yyOaUcMga9D33VO26OmWkQt+VegKPCiKoiiKoii/H7uaoVlectrf94VH+NACSacMpP0CCU68/MutNdJir+TwOn3/bxzH/503p61c+SqOXxloHFk9laYafSx+9+UvUy+Nv/DE6rJXjskxOSbH5NgKsfFqjo0Iy/n3fVXHOEJ7YIGk8RQsab5AwhP87ld1jMgxOSbH5NgzO/YNDaJNX8/asIpKU2hhYtqij1qex8p65FjnjJHj/YfNA3ho6pjZOJotO0J7ZAFJsOQxCylRqU0QCKrXyjJFUi5Gdr4XxyxnLGLWey8pe3fmGJtyTI69Hf58yDE59jjGiN152Dx2O3XMvML6jiVKUccCtjm4kaUz1ftxOBxeEagwZipRA6RpAdEIq3Ksea8cI3LsK3Ls7f09O/bn/V2OddArxwbS3rGqZJBjFwtmlQ4b6cgpCramY4lawDFMCb2qpNbglSVFaodzntSx8ULMeu4ldJB9OZYjx6oLcoxzYWxdODWGaIV3bOXQJ8fkWOCwN+iY4RCF0w272mEjHefF+UhYpZTSio4N5Lcco+6cH3tKx8we443Zo3rNljpG7x4dGwYe4XJMjn22dkyOybFj0LFhqPyKeCxXHbOc6EWG/NSqYwZEUwGPqh2OY4wEHKOSGjnmkggoSxQj1K6EppBk1Lh+7LJjWIRZ51BjlrNfQy79R1/g/JgcG8fljtG7O8e+b8ixBzkmx+SYHDu2dYyH7JM4Zg0cA6TbHaNeI1GO6f9XNnNMjrmXEskxOTYx9PMcF88MpOImNcexcmJfjsmxY5vz/Dyyq44FztmX3XXJrHTMqo7ZFcdstE04luq7qotV1Ai1q6EtfoWsHNtmb/A8vxzLkWNyTI617ZVjx3Pw7HbHfMDWdWxyB3LKAo75HSVbG3AssVJzDDQ24Bhl9/PH5tdJTDXggbliC8eoDWw85vPHdB2sHKNrj47JsbeP7Fj+Ksda9cqxI/m6dZdjQ8yxmkeEbhxzJx2DHMfoaOBYSmlwFsCnnNiZY4fX6Z8ck2MdOkb27Zgc+zwhlr92ETnWgWNH8n3zdsfkGNLMF1ICn8oE8gUcg0SXEerUCLVKnGF2W5Ps5NgWI8fk2MtL/rfQspe9OibH+DzYhpFjcoxvp6zpGPuqS1Z2+5MrOla8NQinLi6wXplAvpBjLG/bMT7vYmuRY3KMR+1LPTt2TI7xebCNI8fk2LhDx8Z7HUv4MXcq1R2rTwQcg8SNO3Y45+kdM2Jb7iVyLB45Jsf4GLEiTrG4Kp+6sx+Sp6bct0/qcmyDjo23OGbEbleMfZFqd3HrdxxzKXEWUnWiiWMYEnw3OLUlkgXfQc4C58fkmByTY3KsZ8c+5VjTXjlG9uPYYHLstxzj+jH0INQvmTPVyyk6Sd3Aer2+H8tZ9Gd4eut14hsmx+TYzhzj/ZVybI1eORY87LhiTsxu6Cb+S0eOzcpFf6RcXNWxlJ7NMd5f2adjckyOyTE5xvsrl1lBxilyTI7t0TGbF3KsUMoZYdFWdYwJmp7s/Fj3jpn9ePDZKfNTJVNHZ70581+A6xdj4dRG5Zgck2NyTI4FDjseI+z1ynn/5d0zx2xe4JeATP6IGSWyimN8nfKMjuFSk2sh4o7lytJ9cp+jjskxu5A7RntyTI7JMTkmx+SYUygcs8oIL7MZGVZ2DMbS9hyTY/NH5o8nR3e9OMaBE8rsGC59scoERjfmmByTY28fh9e3j5u8ys30Nzg/VrnOfx7u2KZskmNlcCxy2GQDZ/2NWxwuBRyjVnbMHStH7nAs3eIYjE1f2VV3jh1eT//JsX04RkbCT7x9VI7Jsd917O/hz+FTjrXolWMOZGPvjqESbJnv2HQQV0dwjJEbHSNhx1LOUHxYEOnu8y5QJXgtRCPHCGAuc2yijz9D+JUrD93Oevm11N8fzo6v7drHqDq6ScfkmBzj82DlWIteOQZkhM7YYbeXDCvj3VayZb5jXof5jg1D2DH0udmx4ZT+HTucI8f25Jjz824e3YZjckyO8QQJeNXw88dYorjwvQNTfSM2yTEn/Ts2mEEOBc8xZ2QkjRwbUivHhtT9+bGncMx/qpkVhvTUm8Ov65JhpWPLUjaaxUflmBzbyPVj2bG/H3JsjV45Fjjs9o4Rs0A/3ZBzb4FiA8eGdJdj6dsxeru9fqz7yDE5Jsd27NhnduxTjq3WK8fkGLUmjg3pDsfSaWFaprnX91c+jWNO7F+67MUxJ8PPIEQwZvFROSbH5Jgc251j9cNu7ljgJ5g53c0dMwfH2VuDEirNFzhR70+4jlFLfBlSTn9/h/cpHJNjckyOybFPOUbkWCByrGUBxwiiOPVzyobkkFhz7JSZlR04Rp7bsX576461kczsxlE5JsfkmBwjcqztQyL++YxG6P91xxILRZ2k6xMsLHWMiV4ck2NyTI7JMTkmx+RYHTIb5FitkDyu0jXGWGclObsKOTaVqpIVNULtai6Pkrpi+5DMrM9eUnGsgWRmjMoxOSbH5NgOHatDZhz2So613OsKjjmQpdkCn4BIkj9BEtWKY3RsxTE5ZtZrL/EVk2NyTI61ihyTY4NdzZLDlmND8rhiAV9IqkywkOqOMTGzZDuOUduJZGb99pKAYwGOjFiD0W4dk2NyTI7JsUDM1nKMvXbkWPHWIMLCVccqLzap1h2rvoxzdCPUrsQZJOu+qpRjckyOyTE5JsfkmBzzKYkvXJYvybH+JLOcnnuJo1hYMsuZV1qMyjE5Jsfk2A4c8w97s44RO+VRhThX8QV4CzhGgGOhZGWNOC1VxUhHiskxOSbH5Jgck2NyrKus4BjVxDIt1x3LibyyjDgWeVVJbR+SWU7vvWShYnjkvyO8SLtROSbH5Jgc24FjzmE3jllVMTnGOh1MzIMedcncYoOrXanJsZ05ZqdM34KOMbopx+SYHJNjckyOyTE2U/InyFJqLkrV5lUltScOJ6LNeIK07J22aPd7zdreBySbvi97IrN/MIr/WeP6qByTY3JMju3IMeewm2fJPuXYkBLL/sSSqy+W1mLde7riQo6VQS1O0fs/o36wjMoxOSbH5NiOHRu/Uh42t4kcW8mxIe5Yzq84Ru3Jw3OVEyTNe8+pQmDW9j7g12lrmejsP+gYQzlyTI7JMTkmx2qH3UnkmLJC5BiZO1a542Q+tHhUjskxRY7JMUWOKTwt2GrVezwuvxentLwP6LXcMTMkDTv2s1GOyTFFjsmx6mErcqweOSbHSNgxIsfkmCLH5NiYI8fkmLLoxAtbTXsDaXkfIICtNvcgOCTH5Jgix+RY4LDlWGq+EHBMlMkxOSbH5Jgix3bs2LhnxIYEJQlhIgukXIg4xoSyduwrbDXuDaT1fYiHvTYYkmNyTJFjcmzMuX7YShp/fNR0umMB4FhIjmPORP+RY3JMjskxRY7JMSUQKDknvuCTeC79dCzh2HxCURRFjimKopeY8QUHuPPC+dsp54Fp05tQlP+3ax9XCsRAEEB1UkIkxKnyz2C993pPrWXE/0c8TXXhBvTYFQNO9WecfrpzAD0GAAAA5MG5MW+AA4MF9JgeA5J2p9u3eQMcGCygx/QYkKQ1+zZ1gAODBfSYHgOS9qxn3sIZoMGCHtNjFbIlaG/0fHC2BOMD/H2w9fTYLtBjegxI0nzt/EeAHgPovqwAemwDJKm+/ax/qBX23pPckav15Ere6smbXFWTq/qh5PPtt6mSoUfwSeofyieZuApJVq1fPj3HJHIlVytztUne5E2PyZVckeLbKJDUz0B+5Equ5E3eDkWu5Cqjs8md2s/RSSY+uWSH9U6OtMRyNUCuNs2bvOkxuZKrz6lI1v1yG8fVDb4+ufCsRq5KyJUekzc9tgG5AgDggt0CZbA9DpBeWG4AAAAASUVORK5CYII=">
    <template id="audio-resources">
      <audio id="offline-sound-press" src="data:audio/mpeg;base64,T2dnUwACAAAAAAAAAABVDxppAAAAABYzHfUBHgF2b3JiaXMAAAAAAkSsAAD/////AHcBAP////+4AU9nZ1MAAAAAAAAAAAAAVQ8aaQEAAAC9PVXbEEf//////////////////+IDdm9yYmlzNwAAAEFPOyBhb1R1ViBiNSBbMjAwNjEwMjRdIChiYXNlZCBvbiBYaXBoLk9yZydzIGxpYlZvcmJpcykAAAAAAQV2b3JiaXMlQkNWAQBAAAAkcxgqRqVzFoQQGkJQGeMcQs5r7BlCTBGCHDJMW8slc5AhpKBCiFsogdCQVQAAQAAAh0F4FISKQQghhCU9WJKDJz0IIYSIOXgUhGlBCCGEEEIIIYQQQgghhEU5aJKDJ0EIHYTjMDgMg+U4+ByERTlYEIMnQegghA9CuJqDrDkIIYQkNUhQgwY56ByEwiwoioLEMLgWhAQ1KIyC5DDI1IMLQoiag0k1+BqEZ0F4FoRpQQghhCRBSJCDBkHIGIRGQViSgwY5uBSEy0GoGoQqOQgfhCA0ZBUAkAAAoKIoiqIoChAasgoAyAAAEEBRFMdxHMmRHMmxHAsIDVkFAAABAAgAAKBIiqRIjuRIkiRZkiVZkiVZkuaJqizLsizLsizLMhAasgoASAAAUFEMRXEUBwgNWQUAZAAACKA4iqVYiqVoiueIjgiEhqwCAIAAAAQAABA0Q1M8R5REz1RV17Zt27Zt27Zt27Zt27ZtW5ZlGQgNWQUAQAAAENJpZqkGiDADGQZCQ1YBAAgAAIARijDEgNCQVQAAQAAAgBhKDqIJrTnfnOOgWQ6aSrE5HZxItXmSm4q5Oeecc87J5pwxzjnnnKKcWQyaCa0555zEoFkKmgmtOeecJ7F50JoqrTnnnHHO6WCcEcY555wmrXmQmo21OeecBa1pjppLsTnnnEi5eVKbS7U555xzzjnnnHPOOeec6sXpHJwTzjnnnKi9uZab0MU555xPxunenBDOOeecc84555xzzjnnnCA0ZBUAAAQAQBCGjWHcKQjS52ggRhFiGjLpQffoMAkag5xC6tHoaKSUOggllXFSSicIDVkFAAACAEAIIYUUUkghhRRSSCGFFGKIIYYYcsopp6CCSiqpqKKMMssss8wyyyyzzDrsrLMOOwwxxBBDK63EUlNtNdZYa+4555qDtFZaa621UkoppZRSCkJDVgEAIAAABEIGGWSQUUghhRRiiCmnnHIKKqiA0JBVAAAgAIAAAAAAT/Ic0REd0REd0REd0REd0fEczxElURIlURIt0zI101NFVXVl15Z1Wbd9W9iFXfd93fd93fh1YViWZVmWZVmWZVmWZVmWZVmWIDRkFQAAAgAAIIQQQkghhRRSSCnGGHPMOegklBAIDVkFAAACAAgAAABwFEdxHMmRHEmyJEvSJM3SLE/zNE8TPVEURdM0VdEVXVE3bVE2ZdM1XVM2XVVWbVeWbVu2dduXZdv3fd/3fd/3fd/3fd/3fV0HQkNWAQASAAA6kiMpkiIpkuM4jiRJQGjIKgBABgBAAACK4iiO4ziSJEmSJWmSZ3mWqJma6ZmeKqpAaMgqAAAQAEAAAAAAAACKpniKqXiKqHiO6IiSaJmWqKmaK8qm7Lqu67qu67qu67qu67qu67qu67qu67qu67qu67qu67qu67quC4SGrAIAJAAAdCRHciRHUiRFUiRHcoDQkFUAgAwAgAAAHMMxJEVyLMvSNE/zNE8TPdETPdNTRVd0gdCQVQAAIACAAAAAAAAADMmwFMvRHE0SJdVSLVVTLdVSRdVTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTdM0TRMIDVkJAJABAKAQW0utxdwJahxi0nLMJHROYhCqsQgiR7W3yjGlHMWeGoiUURJ7qihjiknMMbTQKSet1lI6hRSkmFMKFVIOWiA0ZIUAEJoB4HAcQLIsQLI0AAAAAAAAAJA0DdA8D7A8DwAAAAAAAAAkTQMsTwM0zwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQNI0QPM8QPM8AAAAAAAAANA8D/BEEfBEEQAAAAAAAAAszwM80QM8UQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwNE0QPM8QPM8AAAAAAAAALA8D/BEEfA8EQAAAAAAAAA0zwM8UQQ8UQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABDgAAAQYCEUGrIiAIgTADA4DjQNmgbPAziWBc+D50EUAY5lwfPgeRBFAAAAAAAAAAAAADTPg6pCVeGqAM3zYKpQVaguAAAAAAAAAAAAAJbnQVWhqnBdgOV5MFWYKlQVAAAAAAAAAAAAAE8UobpQXbgqwDNFuCpcFaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAABhwAAAIMKEMFBqyIgCIEwBwOIplAQCA4ziWBQAAjuNYFgAAWJYligAAYFmaKAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAGHAAAAgwoQwUGrISAIgCADAoimUBy7IsYFmWBTTNsgCWBtA8gOcBRBEACAAAKHAAAAiwQVNicYBCQ1YCAFEAAAZFsSxNE0WapmmaJoo0TdM0TRR5nqZ5nmlC0zzPNCGKnmeaEEXPM02YpiiqKhBFVRUAAFDgAAAQYIOmxOIAhYasBABCAgAMjmJZnieKoiiKpqmqNE3TPE8URdE0VdVVaZqmeZ4oiqJpqqrq8jxNE0XTFEXTVFXXhaaJommaommqquvC80TRNE1TVVXVdeF5omiapqmqruu6EEVRNE3TVFXXdV0giqZpmqrqurIMRNE0VVVVXVeWgSiapqqqquvKMjBN01RV15VdWQaYpqq6rizLMkBVXdd1ZVm2Aarquq4ry7INcF3XlWVZtm0ArivLsmzbAgAADhwAAAKMoJOMKouw0YQLD0ChISsCgCgAAMAYphRTyjAmIaQQGsYkhBJCJiWVlEqqIKRSUikVhFRSKiWjklJqKVUQUikplQpCKqWVVAAA2IEDANiBhVBoyEoAIA8AgCBGKcYYYwwyphRjzjkHlVKKMeeck4wxxphzzkkpGWPMOeeklIw555xzUkrmnHPOOSmlc84555yUUkrnnHNOSiklhM45J6WU0jnnnBMAAFTgAAAQYKPI5gQjQYWGrAQAUgEADI5jWZqmaZ4nipYkaZrneZ4omqZmSZrmeZ4niqbJ8zxPFEXRNFWV53meKIqiaaoq1xVF0zRNVVVVsiyKpmmaquq6ME3TVFXXdWWYpmmqquu6LmzbVFXVdWUZtq2aqiq7sgxcV3Vl17aB67qu7Nq2AADwBAcAoAIbVkc4KRoLLDRkJQCQAQBAGIOMQgghhRBCCiGElFIICQAAGHAAAAgwoQwUGrISAEgFAACQsdZaa6211kBHKaWUUkqpcIxSSimllFJKKaWUUkoppZRKSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoFAC5VOADoPtiwOsJJ0VhgoSErAYBUAADAGKWYck5CKRVCjDkmIaUWK4QYc05KSjEWzzkHoZTWWiyecw5CKa3FWFTqnJSUWoqtqBQyKSml1mIQwpSUWmultSCEKqnEllprQQhdU2opltiCELa2klKMMQbhg4+xlVhqDD74IFsrMdVaAABmgwMARIINqyOcFI0FFhqyEgAICQAgjFGKMcYYc8455yRjjDHmnHMQQgihZIwx55xzDkIIIZTOOeeccxBCCCGEUkrHnHMOQgghhFBS6pxzEEIIoYQQSiqdcw5CCCGEUkpJpXMQQgihhFBCSSWl1DkIIYQQQikppZRCCCGEEkIoJaWUUgghhBBCKKGklFIKIYRSQgillJRSSimFEEoIpZSSUkkppRJKCSGEUlJJKaUUQggllFJKKimllEoJoYRSSimlpJRSSiGUUEIpBQAAHDgAAAQYQScZVRZhowkXHoBCQ1YCAGQAAJSyUkoorVVAIqUYpNpCR5mDFHOJLHMMWs2lYg4pBq2GyjGlGLQWMgiZUkxKCSV1TCknLcWYSuecpJhzjaVzEAAAAEEAgICQAAADBAUzAMDgAOFzEHQCBEcbAIAgRGaIRMNCcHhQCRARUwFAYoJCLgBUWFykXVxAlwEu6OKuAyEEIQhBLA6ggAQcnHDDE294wg1O0CkqdSAAAAAAAAwA8AAAkFwAERHRzGFkaGxwdHh8gISIjJAIAAAAAAAYAHwAACQlQERENHMYGRobHB0eHyAhIiMkAQCAAAIAAAAAIIAABAQEAAAAAAACAAAABARPZ2dTAARhGAAAAAAAAFUPGmkCAAAAO/2ofAwjXh4fIzYx6uqzbla00kVmK6iQVrrIbAUVUqrKzBmtJH2+gRvgBmJVbdRjKgQGAlI5/X/Ofo9yCQZsoHL6/5z9HuUSDNgAAAAACIDB4P/BQA4NcAAHhzYgQAhyZEChScMgZPzmQwZwkcYjJguOaCaT6Sp/Kand3Luej5yp9HApCHVtClzDUAdARABQMgC00kVNVxCUVrqo6QqCoqpkHqdBZaA+ViWsfXWfDxS00kVNVxDkVrqo6QqCjKoGkDPMI4eZeZZqpq8aZ9AMtNJFzVYQ1Fa6qNkKgqoiGrbSkmkbqXv3aIeKI/3mh4gORh4cy6gShGMZVYJwm9SKkJkzqK64CkyLTGbMGExnzhyrNcyYMQl0nE4rwzDkq0+D/PO1japBzB9E1XqdAUTVep0BnDStQJsDk7gaNQK5UeTMGgwzILIr00nCYH0Gd4wp1aAOEwlvhGwA2nl9c0KAu9LTJUSPIOXVyCVQpPP65oQAd6WnS4geQcqrkUugiC8QZa1eq9eqRUYCAFAWY/oggB0gm5gFWYhtgB6gSIeJS8FxMiAGycBBm2ABURdHBNQRQF0JAJDJ8PhkMplMJtcxH+aYTMhkjut1vXIdkwEAHryuAQAgk/lcyZXZ7Darzd2J3RBRoGf+V69evXJtviwAxOMBNqACAAIoAAAgM2tuRDEpAGAD0Khcc8kAQDgMAKDRbGlmFJENAACaaSYCoJkoAAA6mKlYAAA6TgBwxpkKAIDrBACdBAwA8LyGDACacTIRBoAA/in9zlAB4aA4Vczai/R/roGKBP4+pd8ZKiAcFKeKWXuR/s81UJHAn26QimqtBBQ2MW2QKUBUG+oBegpQ1GslgCIboA3IoId6DZeCg2QgkAyIQR3iYgwursY4RgGEH7/rmjBQwUUVgziioIgrroJRBECGTxaUDEAgvF4nYCagzZa1WbJGkhlJGobRMJpMM0yT0Z/6TFiwa/WXHgAKwAABmgLQiOy5yTVDATQdAACaDYCKrDkyA4A2TgoAAB1mTgpAGycjAAAYZ0yjxAEAmQ6FcQWAR4cHAOhDKACAeGkA0WEaGABQSfYcWSMAHhn9f87rKPpQpe8viN3YXQ08cCAy+v+c11H0oUrfXxC7sbsaeOAAmaAXkPWQ6sBBKRAe/UEYxiuPH7/j9bo+M0cAE31NOzEaVBBMChqRNUdWWTIFGRpCZo7ssuXMUBwgACpJZcmZRQMFQJNxMgoCAGKcjNEAEnoDqEoD1t37wH7KXc7FayXfFzrSQHQ7nxi7yVsKXN6eo7ewMrL+kxn/0wYf0gGXcpEoDSQI4CABFsAJ8AgeGf1/zn9NcuIMGEBk9P85/zXJiTNgAAAAPPz/rwAEHBDgGqgSAgQQAuaOAHj6ELgGOaBqRSpIg+J0EC3U8kFGa5qapr41xuXsTB/BpNn2BcPaFfV5vCYu12wisH/m1IkQmqJLYAKBHAAQBRCgAR75/H/Of01yCQbiZkgoRD7/n/Nfk1yCgbgZEgoAAAAAEADBcPgHQRjEAR4Aj8HFGaAAeIATDng74SYAwgEn8BBHUxA4Tyi3ZtOwTfcbkBQ4DAImJ6AA"></audio>
      <audio id="offline-sound-hit" src="data:audio/mpeg;base64,T2dnUwACAAAAAAAAAABVDxppAAAAABYzHfUBHgF2b3JiaXMAAAAAAkSsAAD/////AHcBAP////+4AU9nZ1MAAAAAAAAAAAAAVQ8aaQEAAAC9PVXbEEf//////////////////+IDdm9yYmlzNwAAAEFPOyBhb1R1ViBiNSBbMjAwNjEwMjRdIChiYXNlZCBvbiBYaXBoLk9yZydzIGxpYlZvcmJpcykAAAAAAQV2b3JiaXMlQkNWAQBAAAAkcxgqRqVzFoQQGkJQGeMcQs5r7BlCTBGCHDJMW8slc5AhpKBCiFsogdCQVQAAQAAAh0F4FISKQQghhCU9WJKDJz0IIYSIOXgUhGlBCCGEEEIIIYQQQgghhEU5aJKDJ0EIHYTjMDgMg+U4+ByERTlYEIMnQegghA9CuJqDrDkIIYQkNUhQgwY56ByEwiwoioLEMLgWhAQ1KIyC5DDI1IMLQoiag0k1+BqEZ0F4FoRpQQghhCRBSJCDBkHIGIRGQViSgwY5uBSEy0GoGoQqOQgfhCA0ZBUAkAAAoKIoiqIoChAasgoAyAAAEEBRFMdxHMmRHMmxHAsIDVkFAAABAAgAAKBIiqRIjuRIkiRZkiVZkiVZkuaJqizLsizLsizLMhAasgoASAAAUFEMRXEUBwgNWQUAZAAACKA4iqVYiqVoiueIjgiEhqwCAIAAAAQAABA0Q1M8R5REz1RV17Zt27Zt27Zt27Zt27ZtW5ZlGQgNWQUAQAAAENJpZqkGiDADGQZCQ1YBAAgAAIARijDEgNCQVQAAQAAAgBhKDqIJrTnfnOOgWQ6aSrE5HZxItXmSm4q5Oeecc87J5pwxzjnnnKKcWQyaCa0555zEoFkKmgmtOeecJ7F50JoqrTnnnHHO6WCcEcY555wmrXmQmo21OeecBa1pjppLsTnnnEi5eVKbS7U555xzzjnnnHPOOeec6sXpHJwTzjnnnKi9uZab0MU555xPxunenBDOOeecc84555xzzjnnnCA0ZBUAAAQAQBCGjWHcKQjS52ggRhFiGjLpQffoMAkag5xC6tHoaKSUOggllXFSSicIDVkFAAACAEAIIYUUUkghhRRSSCGFFGKIIYYYcsopp6CCSiqpqKKMMssss8wyyyyzzDrsrLMOOwwxxBBDK63EUlNtNdZYa+4555qDtFZaa621UkoppZRSCkJDVgEAIAAABEIGGWSQUUghhRRiiCmnnHIKKqiA0JBVAAAgAIAAAAAAT/Ic0REd0REd0REd0REd0fEczxElURIlURIt0zI101NFVXVl15Z1Wbd9W9iFXfd93fd93fh1YViWZVmWZVmWZVmWZVmWZVmWIDRkFQAAAgAAIIQQQkghhRRSSCnGGHPMOegklBAIDVkFAAACAAgAAABwFEdxHMmRHEmyJEvSJM3SLE/zNE8TPVEURdM0VdEVXVE3bVE2ZdM1XVM2XVVWbVeWbVu2dduXZdv3fd/3fd/3fd/3fd/3fV0HQkNWAQASAAA6kiMpkiIpkuM4jiRJQGjIKgBABgBAAACK4iiO4ziSJEmSJWmSZ3mWqJma6ZmeKqpAaMgqAAAQAEAAAAAAAACKpniKqXiKqHiO6IiSaJmWqKmaK8qm7Lqu67qu67qu67qu67qu67qu67qu67qu67qu67qu67qu67quC4SGrAIAJAAAdCRHciRHUiRFUiRHcoDQkFUAgAwAgAAAHMMxJEVyLMvSNE/zNE8TPdETPdNTRVd0gdCQVQAAIACAAAAAAAAADMmwFMvRHE0SJdVSLVVTLdVSRdVTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTdM0TRMIDVkJAJABAKAQW0utxdwJahxi0nLMJHROYhCqsQgiR7W3yjGlHMWeGoiUURJ7qihjiknMMbTQKSet1lI6hRSkmFMKFVIOWiA0ZIUAEJoB4HAcQLIsQLI0AAAAAAAAAJA0DdA8D7A8DwAAAAAAAAAkTQMsTwM0zwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQNI0QPM8QPM8AAAAAAAAANA8D/BEEfBEEQAAAAAAAAAszwM80QM8UQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwNE0QPM8QPM8AAAAAAAAALA8D/BEEfA8EQAAAAAAAAA0zwM8UQQ8UQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABDgAAAQYCEUGrIiAIgTADA4DjQNmgbPAziWBc+D50EUAY5lwfPgeRBFAAAAAAAAAAAAADTPg6pCVeGqAM3zYKpQVaguAAAAAAAAAAAAAJbnQVWhqnBdgOV5MFWYKlQVAAAAAAAAAAAAAE8UobpQXbgqwDNFuCpcFaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAABhwAAAIMKEMFBqyIgCIEwBwOIplAQCA4ziWBQAAjuNYFgAAWJYligAAYFmaKAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAGHAAAAgwoQwUGrISAIgCADAoimUBy7IsYFmWBTTNsgCWBtA8gOcBRBEACAAAKHAAAAiwQVNicYBCQ1YCAFEAAAZFsSxNE0WapmmaJoo0TdM0TRR5nqZ5nmlC0zzPNCGKnmeaEEXPM02YpiiqKhBFVRUAAFDgAAAQYIOmxOIAhYasBABCAgAMjmJZnieKoiiKpqmqNE3TPE8URdE0VdVVaZqmeZ4oiqJpqqrq8jxNE0XTFEXTVFXXhaaJommaommqquvC80TRNE1TVVXVdeF5omiapqmqruu6EEVRNE3TVFXXdV0giqZpmqrqurIMRNE0VVVVXVeWgSiapqqqquvKMjBN01RV15VdWQaYpqq6rizLMkBVXdd1ZVm2Aarquq4ry7INcF3XlWVZtm0ArivLsmzbAgAADhwAAAKMoJOMKouw0YQLD0ChISsCgCgAAMAYphRTyjAmIaQQGsYkhBJCJiWVlEqqIKRSUikVhFRSKiWjklJqKVUQUikplQpCKqWVVAAA2IEDANiBhVBoyEoAIA8AgCBGKcYYYwwyphRjzjkHlVKKMeeck4wxxphzzkkpGWPMOeeklIw555xzUkrmnHPOOSmlc84555yUUkrnnHNOSiklhM45J6WU0jnnnBMAAFTgAAAQYKPI5gQjQYWGrAQAUgEADI5jWZqmaZ4nipYkaZrneZ4omqZmSZrmeZ4niqbJ8zxPFEXRNFWV53meKIqiaaoq1xVF0zRNVVVVsiyKpmmaquq6ME3TVFXXdWWYpmmqquu6LmzbVFXVdWUZtq2aqiq7sgxcV3Vl17aB67qu7Nq2AADwBAcAoAIbVkc4KRoLLDRkJQCQAQBAGIOMQgghhRBCCiGElFIICQAAGHAAAAgwoQwUGrISAEgFAACQsdZaa6211kBHKaWUUkqpcIxSSimllFJKKaWUUkoppZRKSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoFAC5VOADoPtiwOsJJ0VhgoSErAYBUAADAGKWYck5CKRVCjDkmIaUWK4QYc05KSjEWzzkHoZTWWiyecw5CKa3FWFTqnJSUWoqtqBQyKSml1mIQwpSUWmultSCEKqnEllprQQhdU2opltiCELa2klKMMQbhg4+xlVhqDD74IFsrMdVaAABmgwMARIINqyOcFI0FFhqyEgAICQAgjFGKMcYYc8455yRjjDHmnHMQQgihZIwx55xzDkIIIZTOOeeccxBCCCGEUkrHnHMOQgghhFBS6pxzEEIIoYQQSiqdcw5CCCGEUkpJpXMQQgihhFBCSSWl1DkIIYQQQikppZRCCCGEEkIoJaWUUgghhBBCKKGklFIKIYRSQgillJRSSimFEEoIpZSSUkkppRJKCSGEUlJJKaUUQggllFJKKimllEoJoYRSSimlpJRSSiGUUEIpBQAAHDgAAAQYQScZVRZhowkXHoBCQ1YCAGQAAJSyUkoorVVAIqUYpNpCR5mDFHOJLHMMWs2lYg4pBq2GyjGlGLQWMgiZUkxKCSV1TCknLcWYSuecpJhzjaVzEAAAAEEAgICQAAADBAUzAMDgAOFzEHQCBEcbAIAgRGaIRMNCcHhQCRARUwFAYoJCLgBUWFykXVxAlwEu6OKuAyEEIQhBLA6ggAQcnHDDE294wg1O0CkqdSAAAAAAAAwA8AAAkFwAERHRzGFkaGxwdHh8gISIjJAIAAAAAAAYAHwAACQlQERENHMYGRobHB0eHyAhIiMkAQCAAAIAAAAAIIAABAQEAAAAAAACAAAABARPZ2dTAATCMAAAAAAAAFUPGmkCAAAAhlAFnjkoHh4dHx4pKHA1KjEqLzIsNDQqMCveHiYpczUpLS4sLSg3MicsLCsqJTIvJi0sKywkMjbgWVlXWUa00CqtQNVCq7QC1aoNVPXg9Xldx3nn5tixvV6vb7TX+hg7cK21QYgAtNJFphRUtpUuMqWgsqrasj2IhOA1F7LFMdFaWzkAtNBFpisIQgtdZLqCIKjqAAa9WePLkKr1MMG1FlwGtNJFTSkIcitd1JSCIKsCAQWISK0Cyzw147T1tAK00kVNKKjQVrqoCQUVqqr412m+VKtZf9h+TDaaztAAtNJFzVQQhFa6qJkKgqAqUGgtuOa2Se5l6jeXGSqnLM9enqnLs5dn6m7TptWUiVUVN4jhUz9//lzx+Xw+X3x8fCQSiWggDAA83UXF6/vpLipe3zsCULWMBE5PMTBMlsv39/f39/f39524nZ13CDgaRFuLYTbaWgyzq22MzEyKolIpst50Z9PGqqJSq8T2++taLf3+oqg6btyouhEjYlxFjXxex1wCBFxcv+PmzG1uc2bKyJFLLlkizZozZ/ZURpZs2TKiWbNnz5rKyJItS0akWbNnzdrIyJJtxmCczpxOATRRhoPimyjDQfEfIFMprQDU3WFYbXZLZZxMhxrGyRh99Uqel55XEk+9efP7I/FU/8Ojew4JNN/rTq6b73Un1x+AVSsCWD2tNqtpGOM4DOM4GV7n5th453cXNGcfAYQKTFEOguKnKAdB8btRLxNBWUrViLoY1/q1er+Q9xkvZM/IjaoRf30xu3HLnr61fu3UBDRZHZdqsjoutQeAVesAxNMTw2rR66X/Ix6/T5tx80+t/D67ipt/q5XfJzTfa03Wzfdak/UeAEpZawlsbharxTBVO1+c2nm/7/f1XR1dY8XaKWMH3aW9xvEFRFEksXgURRKLn7VamSFRVnYXg0C2Zo2MNE3+57u+e3NFlVev1uufX6nU3Lnf9d1j4wE03+sObprvdQc3ewBYFIArAtjdrRaraRivX7x+8VrbHIofG0n6cFwtNFKYBzxXA2j4uRpAw7dJRkSETBkZV1V1o+N0Op1WhmEyDOn36437RbKvl7zz838wgn295Iv8/Ac8UaRIPFGkSHyAzCItAXY3dzGsNueM6VDDOJkOY3QYX008L6vnfZp/3qf559VQL3Xm1SEFNN2fiMA03Z+IwOwBoKplAKY4TbGIec0111x99dXr9XrjZ/nzdSWXBekAHEsWp4ljyeI0sVs2FEGiLFLj7rjxeqG8Pm+tX/uW90b+DX31bVTF/I+Ut+/sM1IA/MyILvUzI7rUbpNqyIBVjSDGVV/Jo/9H6G/jq+5y3Pzb7P74Znf5ffZtApI5/fN5SAcHjIhB5vTP5yEdHDAiBt4oK/WGeqUMMspeTNsGk/H/PziIgCrG1Rijktfreh2vn4DH78WXa25yZkizZc9oM7JmaYeZM6bJOJkOxmE69Hmp/q/k0fvVRLln3H6fXcXNPt78W638Ptlxsytv/pHyW7Pfp1Xc7L5XfqvZb5MdN7vy5p/u8lut/D6t4mb3vfmnVn6bNt9nV3Hzj1d+q9lv02bc7Mqbf6vZb+N23OzKm73u8lOz3+fY3uwqLv1022+THTepN38yf7XyW1aX8YqjACWfDTiAA+BQALTURU0oCFpLXdSEgqAJpAKxrLtzybNt1Go5VeJAASzRnh75Eu3pke8BYNWiCIBVLdgsXMqlXBJijDGW2Sj5lUqlSJFpPN9fAf08318B/ewBUMUiA3h4YGIaooZrfn5+fn5+fn5+fn6mtQYKcQE8WVg5YfJkYeWEyWqblCIiiqKoVGq1WqxWWa3X6/V6vVoty0zrptXq9/u4ccS4GjWKGxcM6ogaNWpUnoDf73Xd3OQml2xZMhJNM7Nmz54zZ/bsWbNmphVJRpYs2bJly5YtS0YSoWlm1uzZc+bMnj17ZloATNNI4PbTNBK4/W5jlJGglFJWI4hR/levXr06RuJ5+fLly6Ln1atXxxD18uXLKnr+V8cI8/M03+vErpvvdWLXewBYxVoC9bBZDcPU3Bevtc399UWNtZH0p4MJZov7AkxThBmYpggzcNVCJqxIRQwiLpNBxxqUt/NvuCqmb2Poa+RftCr7DO3te16HBjzbulL22daVsnsAqKIFwMXVzbCLYdVe9vGovzx9xP7469mk3L05d1+qjyKuPAY8397G2PPtbYztAWDVQgCH09MwTTG+Us67nX1fG5G+0o3YvspGtK+yfBmqAExTJDHQaYokBnrrZZEZkqoa3BjFDJlmGA17PF+qE/GbJd3xm0V38qoYT/aLuTzh6w/ST/j6g/QHYBVgKYHTxcVqGKY5DOM4DNNRO3OXkM0JmAto6AE01xBa5OYaQou8B4BmRssAUNQ0TfP169fv169fvz6XSIZhGIbJixcvXrzIFP7+/3/9evc/wyMAVFM8EEOvpngghr5by8hIsqiqBjXGXx0T4zCdTCfj8PJl1fy83vv7q1fHvEubn5+fnwc84etOrp/wdSfXewBUsRDA5upqMU1DNl+/GNunkTDUGrWzn0BDIC5UUw7CwKspB2HgVzVFSFZ1R9QxU8MkHXvLGV8jKxtjv6J9G0N/MX1fIysbQzTdOlK26daRsnsAWLUGWFxcTQum8Skv93j2KLpfjSeb3fvFmM3xt3L3/mwCPN/2Rvb5tjeyewBULQGmzdM0DMzS3vEVHVu6MVTZGNn3Fe37WjxU2RjqAUxThJGfpggjv1uLDAlVdeOIGNH/1P9Q5/Jxvf49nmyOj74quveLufGb4zzh685unvB1Zzd7AFQAWAhguLpaTFNk8/1i7Ni+Oq5BxQVcGABEVcgFXo+qkAu8vlurZiaoqiNi3N2Z94sXL168ePEiR4wYMWLEiBEjRowYMWLEiBEjAFRVtGm4qqJNw7ceGRkZrGpQNW58OozDOIzDy5dV8/Pz8/Pz8/Pz8/Pz8/Pz8/NlPN/rDr6f73UH33sAVLGUwHRxsxqGaq72+tcvy5LsLLZ5JdBo0BdUU7Qgr6ZoQb4NqKon4PH6zfFknHYYjOqLT9XaWdkYWvQr2vcV7fuK9n3F9AEs3SZSduk2kbJ7AKhqBeDm7maYaujzKS8/0f/UJ/eL7v2ie7/o3rfHk83xBDzdZlLu6TaTcnsAWLUAYHcz1KqivUt7V/ZQZWPoX7TvK9r3a6iyMVSJ6QNMUaSQnaJIIXvrGSkSVTWIihsZpsmYjKJ/8vTxvC6694sxm+PJ5vhbuXu/ADzf6w5+nu91Bz97AFi1lACHm9UwVHPztbbpkiKHJVsy2SAcDURTFhZc0ZSFBdeqNqiKQXwej8dxXrx48eLFixcvXrx4oY3g8/////////+voo3IF3cCRE/xjoLoKd5RsPUCKVN9jt/v8TruMJ1MJ9PJ6E3z8y9fvnz58uXLly+rSp+Z+V+9ejXv7+8eukl9XpcPJED4YJP6vC4fSIDwgWN7vdDrmfT//4PHDfg98ns9/qDHnBxps2RPkuw5ciYZOXPJmSFrllSSNVumJDNLphgno2E6GQ3jUBmPeOn/KP11zY6bfxvfjCu/TSuv/Datustxs0/Njpt9anbc7Nv4yiu/TSuv/Datustxs0/Njpt9aptx82/jm175bVp55bfZ/e5y3OxT24ybfWqbcfNv08orv00rr/w27dfsuNmnthk3+7SVV36bVl75bVqJnUxPzXazT0294mnq2W+TikmmE5LiQb3pAa94mnpFAGxeSf1/jn9mWTgDBjhUUv+f459ZFs6AAQ4AAAAAAIAH/0EYBHEAB6gDzBkAAUxWjEAQk7nWaBZuuKvBN6iqkoMah7sAhnRZ6lFjmllwEgGCAde2zYBzAB5AAH5J/X+Of81ycQZMHI0uqf/P8a9ZLs6AiaMRAAAAAAIAOPgPw0EUEIddhEaDphAAjAhrrgAUlNDwPZKFEPFz2JKV4FqHl6tIxjaQDfQAiJqgZk1GDQgcBuAAfkn9f45/zXLiDBgwuqT+P8e/ZjlxBgwYAQAAAAAAg/8fDBlCDUeGDICqAJAT585AAALkhkHxIHMR3AF8IwmgWZwQhv0DcpcIMeTjToEGKDQAB0CEACgAfkn9f45/LXLiDCiMxpfU/+f41yInzoDCaAwAAAAEg4P/wyANDgAEhDsAujhQcBgAHEakAKBZjwHgANMYAkIDo+L8wDUrrgHpWnPwBBoJGZqDBmBAUAB1QANeOf1/zn53uYQA9ckctMrp/3P2u8slBKhP5qABAAAAAACAIAyCIAiD8DAMwoADzgECAA0wQFMAiMtgo6AATVGAE0gADAQA"></audio>
      <audio id="offline-sound-reached" src="data:audio/mpeg;base64,T2dnUwACAAAAAAAAAABVDxppAAAAABYzHfUBHgF2b3JiaXMAAAAAAkSsAAD/////AHcBAP////+4AU9nZ1MAAAAAAAAAAAAAVQ8aaQEAAAC9PVXbEEf//////////////////+IDdm9yYmlzNwAAAEFPOyBhb1R1ViBiNSBbMjAwNjEwMjRdIChiYXNlZCBvbiBYaXBoLk9yZydzIGxpYlZvcmJpcykAAAAAAQV2b3JiaXMlQkNWAQBAAAAkcxgqRqVzFoQQGkJQGeMcQs5r7BlCTBGCHDJMW8slc5AhpKBCiFsogdCQVQAAQAAAh0F4FISKQQghhCU9WJKDJz0IIYSIOXgUhGlBCCGEEEIIIYQQQgghhEU5aJKDJ0EIHYTjMDgMg+U4+ByERTlYEIMnQegghA9CuJqDrDkIIYQkNUhQgwY56ByEwiwoioLEMLgWhAQ1KIyC5DDI1IMLQoiag0k1+BqEZ0F4FoRpQQghhCRBSJCDBkHIGIRGQViSgwY5uBSEy0GoGoQqOQgfhCA0ZBUAkAAAoKIoiqIoChAasgoAyAAAEEBRFMdxHMmRHMmxHAsIDVkFAAABAAgAAKBIiqRIjuRIkiRZkiVZkiVZkuaJqizLsizLsizLMhAasgoASAAAUFEMRXEUBwgNWQUAZAAACKA4iqVYiqVoiueIjgiEhqwCAIAAAAQAABA0Q1M8R5REz1RV17Zt27Zt27Zt27Zt27ZtW5ZlGQgNWQUAQAAAENJpZqkGiDADGQZCQ1YBAAgAAIARijDEgNCQVQAAQAAAgBhKDqIJrTnfnOOgWQ6aSrE5HZxItXmSm4q5Oeecc87J5pwxzjnnnKKcWQyaCa0555zEoFkKmgmtOeecJ7F50JoqrTnnnHHO6WCcEcY555wmrXmQmo21OeecBa1pjppLsTnnnEi5eVKbS7U555xzzjnnnHPOOeec6sXpHJwTzjnnnKi9uZab0MU555xPxunenBDOOeecc84555xzzjnnnCA0ZBUAAAQAQBCGjWHcKQjS52ggRhFiGjLpQffoMAkag5xC6tHoaKSUOggllXFSSicIDVkFAAACAEAIIYUUUkghhRRSSCGFFGKIIYYYcsopp6CCSiqpqKKMMssss8wyyyyzzDrsrLMOOwwxxBBDK63EUlNtNdZYa+4555qDtFZaa621UkoppZRSCkJDVgEAIAAABEIGGWSQUUghhRRiiCmnnHIKKqiA0JBVAAAgAIAAAAAAT/Ic0REd0REd0REd0REd0fEczxElURIlURIt0zI101NFVXVl15Z1Wbd9W9iFXfd93fd93fh1YViWZVmWZVmWZVmWZVmWZVmWIDRkFQAAAgAAIIQQQkghhRRSSCnGGHPMOegklBAIDVkFAAACAAgAAABwFEdxHMmRHEmyJEvSJM3SLE/zNE8TPVEURdM0VdEVXVE3bVE2ZdM1XVM2XVVWbVeWbVu2dduXZdv3fd/3fd/3fd/3fd/3fV0HQkNWAQASAAA6kiMpkiIpkuM4jiRJQGjIKgBABgBAAACK4iiO4ziSJEmSJWmSZ3mWqJma6ZmeKqpAaMgqAAAQAEAAAAAAAACKpniKqXiKqHiO6IiSaJmWqKmaK8qm7Lqu67qu67qu67qu67qu67qu67qu67qu67qu67qu67qu67quC4SGrAIAJAAAdCRHciRHUiRFUiRHcoDQkFUAgAwAgAAAHMMxJEVyLMvSNE/zNE8TPdETPdNTRVd0gdCQVQAAIACAAAAAAAAADMmwFMvRHE0SJdVSLVVTLdVSRdVTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTdM0TRMIDVkJAJABAKAQW0utxdwJahxi0nLMJHROYhCqsQgiR7W3yjGlHMWeGoiUURJ7qihjiknMMbTQKSet1lI6hRSkmFMKFVIOWiA0ZIUAEJoB4HAcQLIsQLI0AAAAAAAAAJA0DdA8D7A8DwAAAAAAAAAkTQMsTwM0zwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQNI0QPM8QPM8AAAAAAAAANA8D/BEEfBEEQAAAAAAAAAszwM80QM8UQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwNE0QPM8QPM8AAAAAAAAALA8D/BEEfA8EQAAAAAAAAA0zwM8UQQ8UQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABDgAAAQYCEUGrIiAIgTADA4DjQNmgbPAziWBc+D50EUAY5lwfPgeRBFAAAAAAAAAAAAADTPg6pCVeGqAM3zYKpQVaguAAAAAAAAAAAAAJbnQVWhqnBdgOV5MFWYKlQVAAAAAAAAAAAAAE8UobpQXbgqwDNFuCpcFaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAABhwAAAIMKEMFBqyIgCIEwBwOIplAQCA4ziWBQAAjuNYFgAAWJYligAAYFmaKAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAGHAAAAgwoQwUGrISAIgCADAoimUBy7IsYFmWBTTNsgCWBtA8gOcBRBEACAAAKHAAAAiwQVNicYBCQ1YCAFEAAAZFsSxNE0WapmmaJoo0TdM0TRR5nqZ5nmlC0zzPNCGKnmeaEEXPM02YpiiqKhBFVRUAAFDgAAAQYIOmxOIAhYasBABCAgAMjmJZnieKoiiKpqmqNE3TPE8URdE0VdVVaZqmeZ4oiqJpqqrq8jxNE0XTFEXTVFXXhaaJommaommqquvC80TRNE1TVVXVdeF5omiapqmqruu6EEVRNE3TVFXXdV0giqZpmqrqurIMRNE0VVVVXVeWgSiapqqqquvKMjBN01RV15VdWQaYpqq6rizLMkBVXdd1ZVm2Aarquq4ry7INcF3XlWVZtm0ArivLsmzbAgAADhwAAAKMoJOMKouw0YQLD0ChISsCgCgAAMAYphRTyjAmIaQQGsYkhBJCJiWVlEqqIKRSUikVhFRSKiWjklJqKVUQUikplQpCKqWVVAAA2IEDANiBhVBoyEoAIA8AgCBGKcYYYwwyphRjzjkHlVKKMeeck4wxxphzzkkpGWPMOeeklIw555xzUkrmnHPOOSmlc84555yUUkrnnHNOSiklhM45J6WU0jnnnBMAAFTgAAAQYKPI5gQjQYWGrAQAUgEADI5jWZqmaZ4nipYkaZrneZ4omqZmSZrmeZ4niqbJ8zxPFEXRNFWV53meKIqiaaoq1xVF0zRNVVVVsiyKpmmaquq6ME3TVFXXdWWYpmmqquu6LmzbVFXVdWUZtq2aqiq7sgxcV3Vl17aB67qu7Nq2AADwBAcAoAIbVkc4KRoLLDRkJQCQAQBAGIOMQgghhRBCCiGElFIICQAAGHAAAAgwoQwUGrISAEgFAACQsdZaa6211kBHKaWUUkqpcIxSSimllFJKKaWUUkoppZRKSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoFAC5VOADoPtiwOsJJ0VhgoSErAYBUAADAGKWYck5CKRVCjDkmIaUWK4QYc05KSjEWzzkHoZTWWiyecw5CKa3FWFTqnJSUWoqtqBQyKSml1mIQwpSUWmultSCEKqnEllprQQhdU2opltiCELa2klKMMQbhg4+xlVhqDD74IFsrMdVaAABmgwMARIINqyOcFI0FFhqyEgAICQAgjFGKMcYYc8455yRjjDHmnHMQQgihZIwx55xzDkIIIZTOOeeccxBCCCGEUkrHnHMOQgghhFBS6pxzEEIIoYQQSiqdcw5CCCGEUkpJpXMQQgihhFBCSSWl1DkIIYQQQikppZRCCCGEEkIoJaWUUgghhBBCKKGklFIKIYRSQgillJRSSimFEEoIpZSSUkkppRJKCSGEUlJJKaUUQggllFJKKimllEoJoYRSSimlpJRSSiGUUEIpBQAAHDgAAAQYQScZVRZhowkXHoBCQ1YCAGQAAJSyUkoorVVAIqUYpNpCR5mDFHOJLHMMWs2lYg4pBq2GyjGlGLQWMgiZUkxKCSV1TCknLcWYSuecpJhzjaVzEAAAAEEAgICQAAADBAUzAMDgAOFzEHQCBEcbAIAgRGaIRMNCcHhQCRARUwFAYoJCLgBUWFykXVxAlwEu6OKuAyEEIQhBLA6ggAQcnHDDE294wg1O0CkqdSAAAAAAAAwA8AAAkFwAERHRzGFkaGxwdHh8gISIjJAIAAAAAAAYAHwAACQlQERENHMYGRobHB0eHyAhIiMkAQCAAAIAAAAAIIAABAQEAAAAAAACAAAABARPZ2dTAABARwAAAAAAAFUPGmkCAAAAZa2xyCElHh4dHyQvOP8T5v8NOEo2/wPOytDN39XY2P8N/w2XhoCs0CKt8NEKLdIKH63ShlVlwuuiLze+3BjtjfZGe0lf6As9ggZstNJFphRUtpUuMqWgsqrasj2IhOA1F7LFMdFaWzkAtNBFpisIQgtdZLqCIKjqAAa9WePLkKr1MMG1FlwGtNJFTSkIcitd1JSCIKsCAQWISK0Cyzw147T1tAK00kVNKKjQVrqoCQUVqqr412m+VKtZf9h+TDaaztAAtNRFzVEQlJa6qDkKgiIrc2gtfES4nSQ1mlvfMxfX4+b2t7ICVNGwkKiiYSGxTQtK1YArN+DgTqdjMwyD1q8dL6RfOzXZ0yO+qkZ8+Ub81WP+DwNkWcJhvlmWcJjvSbUK/WVm3LgxClkyiuxpIFtS5Gwi5FBkj2DGWEyHYBiLcRJkWnQSZGbRGYGZAHr6vWVJAWGE5q724ldv/B8Kp5II3dPvLUsKCCM0d7UXv3rj/1A4lUTo+kCUtXqtWimLssjIyMioViORobCJAQLYFnpaAACCAKEWAMCiQGqMABAIUKknAFkUIGsBIBBAHYBtgAFksAFsEySQgQDWQ4J1AOpiVBUHd1FE1d2IGDfGAUzmKiiTyWQyuY6Lx/W4jgkQZQKioqKuqioAiIqKwagqCqKiogYxCgACCiKoAAAIqAuKAgAgjyeICQAAvAEXmQAAmYNhMgDAZD5MJqYzppPpZDqMwzg0TVU9epXf39/9xw5lBaCpqJiG3VOsht0wRd8FgAeoB8APKOABQFT23GY0GgoAolkyckajHgBoZEYujQY+230BUoD/uf31br/7qCHLXLWwIjMIz3ZfgBTgf25/vdvvPmrIMlctrMgMwiwCAAB4FgAAggAAAM8CAEAgkNG0DgCeBQCAIAAAmEUBynoASKANMIAMNoBtAAlkMAGoAzKQgDoAdQYAKOoEANFgAoAyKwAAGIOiAACVBACyAAAAFYMDAAAyxyMAAMBMfgQAAMi8GAAACDfoFQAAYHgxACA16QiK4CoWcTcVAADDdNpc7AAAgJun080DAAAwPTwxDQAAxYanm1UFAAAVD0MsAA4AyCUztwBwBgAyQOTMTZYA0AAiySW3Clar/eRUAb5fPDXA75e8QH//jkogHmq1n5wqwPeLpwb4/ZIX6O/fUQnEgwf9fr/f72dmZmoaRUREhMLTADSVgCAgVLKaCT0tAABk2AFgAyQgEEDTSABtQiSQwQDUARksYBtAAgm2AQSQYBtAAuYPOK5rchyPLxAABFej4O7uAIgYNUYVEBExbozBGHdVgEoCYGZmAceDI0mGmZlrwYDHkQQAiLhxo6oKSHJk/oBrZgYASI4XAwDAXMMnIQAA5DoyDAAACa8AAMDM5JPEZDIZhiFJoN33vj4X6N19v15gxH8fAE1ERMShbm5iBYCOAAMFgAzaZs3ITURECAAhInKTNbNtfQDQNnuWHBERFgBUVa4iDqyqXEUc+AKkZlkmZCoJgIOBBaubqwoZ2SDNgJlj5MgsMrIV44xgKjCFYTS36QRGQafwylRZAhMXr7IEJi7+AqQ+gajAim2S1W/71ACEi4sIxsXVkSNDQRkgzGp6eNgMJDO7kiVXcmStkCVL0Ry0MzMgzRklI2dLliQNEbkUVFvaCApWW9oICq7rpRlKs2MBn8eVJRlk5JARjONMdGSYZArDOA0ZeKHD6+KN9oZ5MBDTCO8bmrptBBLgcnnOcBmk/KMhS2lL6rYRSIDL5TnDZZDyj4YspS3eIOoN9Uq1KIsMpp1gsU0gm412AISQyICYRYmsFQCQwWIgwWRCABASGRDawAKYxcCAyYQFgLhB1Rg17iboGF6v1+fIcR2TyeR4PF7HdVzHdVzHcYXPbzIAQNTFuBoVBQAADJOL15WBhNcFAADAI9cAAAAAAJAEmIsMAOBlvdTLVcg4mTnJzBnTobzDfKPRaDSaI1IAnUyHhr6LALxFo5FmyZlL1kAU5lW+LIBGo9lym1OF5ikAOsyctGkK8fgfAfgPIQDAvBLgmVsGoM01lwRAvCwAHje0zTiA/oUDAOYAHqv9+AQC4gEDMJ/bIrXsH0Ggyh4rHKv9+AQC4gEDMJ/bIrXsH0Ggyh4rDPUsAADAogBCk3oCQBAAAABBAAAg6FkAANCzAAAgBELTAACGQAAoGoFBFoWoAQDaBPoBQ0KdAQAAAK7iqkAVAABQNixAoRoAAKgE4CAiAAAAACAYow6IGjcAAAAAAPL4DfZ6kkZkprlkj6ACu7i7u5sKAAAOd7vhAAAAAEBxt6m6CjSAgKrFasUOAAAoAABic/d0EwPIBjAA0CAggABojlxzLQD+mv34BQXEBQvYH5sijDr0/FvZOwu/Zj9+QQFxwQL2x6YIow49/1b2zsI9CwAAeBYAAIBANGlSDQAABAEAAKBnIQEAeloAABgCCU0AAEMgAGQTYNAG+gCwAeiBIWMAGmYAAICogRg16gAAABB1gwVkNlgAAIDIGnCMOwIAAACAgmPA8CpgBgAAAIDMG/QbII/PLwAAaKN9vl4Pd3G6maoAAAAAapiKaQUAANPTxdXhJkAWXHBzcRcFAAAHAABqNx2YEQAHHIADOAEAvpp9fyMBscACmc9Lku7s1RPB+kdWs+9vJCAWWCDzeUnSnb16Ilj/CNOzAACAZwEAAAhEk6ZVAAAIAgAAQc8CAICeFgAAhiAAABgCAUAjMGgDPQB6CgCikmDIGIDqCAAAkDUQdzUOAAAAKg3WIKsCAABkFkAJAAAAQFzFQXh8QQMAAAAABCMCKEhAAACAkXcOo6bDxCgqOMXV6SoKAAAAoGrabDYrAAAiHq5Ww80EBMiIi01tNgEAAAwAAKiHGGpRQADUKpgGAAAOEABogFFAAN6K/fghBIQ5cH0+roo0efVEquyBaMV+/BACwhy4Ph9XRZq8eiJV9kCQ9SwAAMCiAGhaDwAIAgAAIAgAAAQ9CwAAehYAAIQgAAAYAgGgaAAGWRTKBgBAG4AMADI2ANVFAAAAgKNqFKgGAACKRkpQqAEAgCKBAgAAAIAibkDFuDEAAAAAYODzA1iQoAEAAI3+ZYOMNls0AoEdN1dPiwIAgNNp2JwAAAAAYHgaLoa7QgNwgKeImAoAAA4AALU5XNxFoYFaVNxMAQCAjADAAQaeav34QgLiAQM4H1dNGbXoH8EIlT2SUKr14wsJiAcM4HxcNWXUon8EI1T2SEJMzwIAgJ4FAAAgCAAAhCAAABD0LAAA6GkBAEAIAgCAIRAAqvUAgywK2QgAyKIAoBEYAiGqCQB1BQAAqCNAmQEAAOqGFZANCwAAoBpQJgAAAKDiuIIqGAcAAAAA3Ig64LgoAADQHJ+WmYbJdMzQBsGuVk83mwIAAAIAgFNMV1cBUz1xKAAAgAEAwHR3sVldBRxAQD0d6uo0FAAADAAA6orNpqIAkMFqqMNAAQADKABkICgAfmr9+AUFxB0ANh+vita64VdPLCP9acKn1o9fUEDcAWDz8aporRt+9cQy0p8mjHsWAADwLAAAAEEAAAAEAQCAoGchAAD0LAAADIHQpAIADIEAUCsSDNpACwA2AK2EIaOVgLoCAACUBZCVAACAKBssIMqGFQAAoKoAjIMLAAAAAAgYIyB8BAUAAAAACPMJkN91ZAAA5O6kwzCtdAyIVd0cLi4KAAAAIFbD4uFiAbW5mu42AAAAAFBPwd1DoIEjgNNF7W4WQAEABwACODxdPcXIAAIHAEEBflr9/A0FxAULtD9eJWl006snRuXfq8Rp9fM3FBAXLND+eJWk0U2vnhiVf68STM8CAACeBQAAIAgAAIAgAAAQ9CwAAOhpAQBgCITGOgAwBAJAYwYYZFGoFgEAZFEAKCsBhkDIGgAoqwAAAFVAVCUAAKhU1aCIhgAAIMoacKNGVAEAAABwRBRQXEUUAAAAABUxCGAMRgAAAABNpWMnaZOWmGpxt7kAAAAAIBimq9pAbOLuYgMAAAAAww0300VBgAMRD0+HmAAAZAAAAKvdZsNUAAcoaAAgA04BXkr9+EIC4gQD2J/XRWjmV0/syr0xpdSPLyQgTjCA/XldhGZ+9cSu3BvD9CwAAOBZAAAAggAAAAgCgAQIehYAAPQsAAAIQQAAMAQCQJNMMMiiUDTNBABZFACyHmBIyCoAACAKoCIBACCLBjMhGxYAACCzAhQFAAAAYMBRFMUYAwAAAAAorg5gPZTJOI4yzhiM0hI1TZvhBgAAAIAY4mZxNcBQV1dXAAAAAAA3u4u7h4ICIYOni7u7qwGAAqAAAIhaHKI2ICCGXe2mAQBAgwwAAQIKQK6ZuREA/hm9dyCg9xrQforH3TSBf2dENdKfM5/RewcCeq8B7ad43E0T+HdGVCP9OWN6WgAA5CkANERJCAYAAIBgAADIAD0LAAB6WgAAmCBCUW8sAMAQCEBqWouAQRZFaigBgDaBSBgCIeoBAFkAwAiou6s4LqqIGgAAKMsKKKsCAAColIgbQV3ECAAACIBRQVzVjYhBVQEAAADJ55chBhUXEQEAIgmZOXNmTSNLthmTjNOZM8cMw2RIa9pdPRx2Q01VBZGNquHTq2oALBfQxKcAh/zVDReL4SEqIgBAbqcKYhiGgdXqblocygIAdL6s7qbaDKfdNE0FAQ4AVFVxeLi7W51DAgIAAwSWDoAPoHUAAt6YvDUqoHcE7If29ZNi2H/k+ir/85yQNiZvjQroHQH7oX39pBj2H7m+yv88J6QWi7cXgKFPJtNOABIEEGVEvUljJckAbdhetBOgpwFkZFbqtWqAUBgysL2AQR2gHoDYE3Dld12P18HkOuY1r+M4Hr/HAAAVBRejiCN4HE/QLOAGPJhMgAJi1BhXgwCAyZUCmOuHZuTMkTUia47sGdIs2TPajKwZqUiTNOKl/1fyvHS8fOn/1QGU+5U0SaOSzCxpmiNntsxI0LhZ+/0dmt1CVf8HNAXKl24AoM0D7jsIAMAASbPkmpvssuTMktIgALMAUESaJXuGzCyZQQBwgEZl5JqbnBlvgIyT0TAdSgG+6Px/rn+NclEGFGDR+f9c/xrlogwoAKjPiKKfIvRhGKYgzZLZbDkz2hC4djgeCVkXEKJlXz1uAosCujLkrDz6p0CZorVVOjvIQOAp3aVcLyCErGACSRKImCRMETeKzA6cFNd2X3KG1pyLgOnTDtnHXMSpVY1A6IXSjlNoh70ubc2VzXgfgd6uEQOBEmCt1O4wOHBQB2ANvtj8f65/jXKiAkiwWGz+P9e/RjlRASRYAODhfxqlH5QGhuxAobUGtOqEll3GqBEhYLIJQLMr6oQooHFcGpIsDK4yPg3UfMJtO/hTFVma3lrt+JI/EFBxbvlT2OiH0mhEfBofQDudLtq0lTiGSOKaVl6peD3XTDACuSXYNQAp4JoD7wjgUAC+2Px/rn+NcqIMKDBebP4/179GOVEGFBgDQPD/fxBW4I7k5DEgDtxdcwFpcNNx+JoDICRCTtO253ANTbn7DmF+TXalagLadQ23yhGw1Pj7SzpOajGmpeeYyqUY1/Y6KfuTVOU5cvu0gW2boGlMfFv5TejrOmkOl0iEpuQMpAYBB09nZ1MABINhAAAAAAAAVQ8aaQMAAAB/dp+bB5afkaKgrlp+2Px/rn+NchECSMBh8/+5/jXKRQggAQAI/tMRHf0LRqDj05brTRlASvIy1PwPFcajBhcoY0BtuEqvBZw0c0jJRaZ4n0f7fOKW0Y8QZ/M7xFeaGJktZ2ePGFTOLl4XzRCQMnJET4bVsFhMiiHf5vXtJ9vtMsf/Wzy030v3dqzCbkfN7af9JmpkTSXXICMpLAVO16AZoAF+2Px/rn91uQgGDOCw+f9c/+pyEQwYAACCH51SxFCg6SCEBi5Yzvla/iwJC4ekcPjs4PTWuY3tqJ0BKbo3cSYE4Oxo+TYjMXbYRhO+7lamNITiY2u0SUbFcZRMTaC5sUlWteBp+ZP4wUl9lzksq8hUQ5JOZZBAjfd98+8O6pvScEnEsrp/Z5BczwfWpkx5PwQ37EoIH7fMBgYGgusZAQN+2Px/rn91uQgGFOCw+f9c/+pyEQwoAPD/I8YfOD1cxsESTiLRCq0XjEpMtryCW+ZYCL2OrG5/pdkExMrQmjY9KVY4h4vfDR0No9dovrC2mxka1Pr0+Mu09SplWO6YXqWclpXdoVKuagQllrWfCaGA0R7bvLk41ZsRTBiieZFaqyFRFbasq0GwHT0MKbUIB2QAftj8f65/NbkIAQxwOGz+P9e/mlyEAAY4gEcfPYMyMh8UBxBogIAtTU0qrERaVBLhCkJQ3MmgzZNrxplCg6xVj5AdH8J2IE3bUNgyuD86evYivJmI+NREqmWbKqosI6xblSnNmJJUum+0qsMe4o8fIeCXELdErT52+KQtXSIl3XJNKOKv3BnKtS2cKmmnGpCqP/5YNQ9MCB2P8VUnCJiYDEAAXrj8f65/jXIiGJCAwuX/c/1rlBPBgAQA/ymlCDEi+hsNB2RoT865unFOQZiOpcy11YPQ6BiMettS0AZ0JqI4PV/Neludd25CqZDuiL82RhzdohJXt36nH+HlZiHE5ILqVSQL+T5/0h9qFzBVn0OFT9herDG3XzXz299VNY2RkejrK96EGyybKbXyG3IUUv5QEvq2bAP5CjJa9IiDeD5OOF64/H8uf3W5lAAmULj8fy5/dbmUACYAPEIfUcpgMGh0GgjCGlzQcHwGnb9HCrHg86LPrV1SbrhY+nX/N41X2DMb5NsNtkcRS9rs95w9uDtvP+KP/MupnfH3yHIbPG/1zDBygJimTvFcZywqne6OX18E1zluma5AShnVx4aqfxLo6K/C8P2fxH5cuaqtqE3Lbru4hT4283zc0Hqv2xINtisxZXBVfQuOAK6kCHjBAF6o/H+uf09ycQK6w6IA40Ll/3P9e5KLE9AdFgUYAwAAAgAAgDD4g+AgXAEEyAAEoADiPAAIcHGccHEAxN271+bn5+dt4B2YmGziAIrZMgZ4l2nedkACHggIAA=="></audio>
    </template>
  </div>
</body>
</html>
     XS6~_sۻڐGK:}(&(G9Ndb.	ICۗ$[N9Gi6|kb GL<\ǩTr(BHP 5k$sETH2 w `d0!|='$1$	3LC gGK\@i:8~%\W_@~AST*7CG7pZ@p޻$=Ti"*T/-b X°F}k)?Rp4Z5dHMB@MA6}1':)qk(4O+3wd\eNZ@ѭS9'`[:zhVOg4bG=N`ܴQ*R"r4xno5Hsw{Ρ<uj[d۪j5e!4B}Mz܀F#i]X	-ŏ9PfP#*<*(ifO3[A[5!U5x*W~t;*r̰$Ldi*BI۷mHL%s#7X8Kan1~3LfR|}F5]k.Dg;HW)~ e\c1QM8THPp]D5B(7@Mu@h̉F)(q1BLG	##fz\J:nzS(VYVX{Ii.Zn01W*qIZ=crvx}r{a?^}Ǝ:|4e"BlAz7vqeHyCQ=l7뭎Yv HMunS|gedalFߖ/ˋëg
` ^_=Ot*f KQ&4VB*I<  N2U#Gq1Id9BǕx֣ /G<FR>T$֣uWRʣj*/k^_F;_\/nU3
Ë՚c$NzjӞQ?=iބ}4F[aEN&<ÉfЁ;Uv͗v[0]<[骰.ňRWBm7x:NǀuT̛9QVZQq|MM{_Gž|{yx?^03»j-7ѩdl/0PGsVPRޮ[ELk"oۦ
{~`o(䒶й!Lcӄ=,J=sod-~nTW.f       Tn0+` vvHCd@l+ua(9!Qn!>Z'6_,Q|zfi޾~dL[)mBspN4%&ao4[RL0!V	o7D-1"xv9B.b,"#	knJ	vliTzLDߋ+iJ*͝4Qn!V$Y1ELޤǆ2 HD0= =c[A-Q,JPf.V nF6'0iN!|k B6t#|j͒XikYhO!BcLJNpIk=6"6dY[ϑvdk?puk٠m)wm=!)UP
|_)%pc.G)nI0NtQ8 4WNmK̹[12ߟssDqSBPeII~(J\r)SmMC!mT_\rrb8*8gQ-<nSMﹷAPOO7%PLIciYqسR6>UI'QV/?lTQ8<^Ete       uRn0+֠v'i1Ԧ=vXZeѐٰ,7E6A${|t1{oZPK6SgCBPW@-6^"HR1liޡfno{`Di48<ow5]d"qi2evE@Ɇ\<źyY~^P[5ƒ|q- W4!{ܣF)Zh;rJI|m\-aΡZg6L]e*#1TSHX'\#CmOljuv5>()l.i]L)|1]+H<BG/N+s~C$N7?jՕ  // Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

function renovation_wikipedia() {
  // Get list of elements to expand.
  let elems =
      document.querySelectorAll('div.collapsible-block,h2.collapsible-heading');

  // Apply 'open-block' class to elements. This makes the sections'
  // content visible.
  for (let i = 0; i < elems.length; ++i) {
    // If a block was already expanded, re-adding the 'open-block'
    // class will do nothing; no need to check if it's there already.
    elems.item(i).className += " open-block";
  }

  // Now we force the page to load images inside the expanded
  // sections. Wikipedia article images have a lazy image placeholder
  // as well as a noscript element with an img tag (for if scripts are
  // disabled). We get the list of these elements in order. For every
  // lazy image placeholder, there is always a corresponding noscript
  // element.
  let placeholders = document.querySelectorAll(
      '.image > span.lazy-image-placeholder, ' +
      '.mwe-math-element > span.lazy-image-placeholder');
  let noscripts = document.querySelectorAll(
      '.image > noscript, .mwe-math-element > noscript');

  // Next we delete all the placeholders, then move the img elements
  // out of the noscripts, deleting the noscript element in the
  // process.
  for (let i = 0; i < placeholders.length; ++i) {
    placeholders.item(i).remove();
    let innerText = noscripts.item(i).innerText;
    noscripts.item(i).outerHTML = innerText;
  }
}

var map_renovations = {
  "wikipedia" : renovation_wikipedia,
};

function run_renovations(flist) {
  for (var func_name of flist) {
    map_renovations[func_name]();
  }
}
     Un1WLlS 4=:16{JEBfo	BK7,aVmU[uK,:DsD$k4+!pm	(4Q#`o=ǜujBZ1ha\xKj6|}	py.rIGb=4(DϦ,wT4lz؂V!D/Wz>tCO3e/;<|abJgt΍{P=#.݉&noVQ-+ĞS{Oog?qbM4Errgy[}(xz,:Tr8E~cs W?vm@jp1T)G"N0VN#)S-ղrB%&)(VyCM'@+&r86Ok¾Lƾcw̃imt~r$Ʈqϊ2 SFF:a P1/q40nY;LJ,샤r'2>AL+
tҀh=G/^r"LNYBVOْIҭvۗon~F       uj0}
IMءK{(Qh *-&^z[U5o:
GPkO'OɇVEc@ߣ*U_Z`m^"HRGPA3zxHtZ0HqSK)0.vzy@k,EdCR^M^=u)NQ[. z!֦wx̳T/ѱ7-	Lä(RWi)gtƪ\/G8vy}V\֍<N	xOL?giiC?N9#nM;u:grtkP*" ',J       J@EBҨ.
F\LLyߝXi2{μ"nGm'<cGwn`Kg`5v!G@$A'Oco{W*[gkrj#nWwQ4WdBM:%AIq&'/狇kMb7ʨ\FIi_ -L۶e
=A6EE(V*{RX+ׅ~|KMB_k4&7NCnvRfjob2Hb&_JJM.E8t::ިԶZq1#쑟CT  <!doctype html>
<html>
<head>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<style>
  body {
    margin: 0;
    display: flex;
    flex-direction: column;
  }

  #header, #footer {
    display: flex;
    flex: none;
  }

  #header {
    align-items: flex-start;
    padding-top: 0.4cm;
  }

  #footer {
    align-items: flex-end;
    padding-bottom: 0.4cm;
  }

  #content {
    flex: auto;
  }

  .left {
    flex: none;
    padding-left: 0.7cm;
    padding-right: 0.1cm;
  }

  .center {
    flex: auto;
    padding-left: 0.7cm;
    padding-right: 0.7cm;
    text-align: center;
  }

  .right {
    flex: none;
    /* historically does not account for RTL */
    padding-left: 0.1cm;
    padding-right: 0.7cm;
  }

  .grow {
    flex: auto;
  }

  .text {
    font-size: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
</style>
<script>

function setupHeaderFooterTemplate(options) {
  const body = document.querySelector('body');
  const header = document.querySelector('#header');
  const footer = document.querySelector('#footer');

  body.style.width = `${options.width}px`;
  body.style.height = `${options.height}px`;
  header.style.height = `${options.topMargin}px`;
  footer.style.height = `${options.bottomMargin}px`;

  header.innerHTML = options['headerTemplate'] || `
    <div class='date text left'></div>
    <div class='title text center'></div>`;
  footer.innerHTML = options['footerTemplate'] || `
    <div class='url text left grow'></div>
    <div class='text right'>
      <span class='pageNumber'></span>/<span class='totalPages'></span>
    </div>`;

  options.date = new Date(options.date).toLocaleDateString();
  for (const cssClass of ['date', 'title', 'url', 'pageNumber', 'totalPages']) {
    for (const element of document.querySelectorAll(`.${cssClass}`)) {
      element.textContent = options[cssClass];
      if (options.isRtl)
        element.dir = 'rtl';
    }
  }
}

</script>
</head>
<body>
  <div id="header"></div>
  <div id="content"></div>
  <div id="footer"></div>
</body>
</html>
     WKS0+TAx`	\z:-U+ षh~ڇ>]?\ܐIBNr`~`932lF/Ve0{`+Q(l/b@^h_%``ȜĹIv=xnT_ py^lB*iP, -AG]0N(b/k0gO9
ǽQD?X[Q@2˦aTVȩJfWʺRA\gGaQ2k"^1u3[!tDAxݡ9@F@}0r`aN0K\;K% xT\",p+T9f`ʼg74`<gbN= Οf%AkFkev(y[K̥cFzgZJַ!mj+zW:Q<55M5eQQf<URH3s84w8{QK$ߙSN=ޙrL=эi߅6wi".fl.jU"m΄XC:t0Bqr<0=~xMУQݢNnzE#PVI,\rpEΤ)Jǫl2e
|ƖroKnQ2{k6^ϱ2_~X%pk&+w!Om6Gm0\SѢ8=n{{celВYxoYnBrQ|Qj       uQn!W<ɪZfc;unNC 6֑K@̛7o;?ݫzs_Wz0&B`椈@ɺ#uHJGD7:I޽P$!&p|}bl.K'BPah%8ϧGtPUU	''B/>~[awͧxm6;NJ'b@/u6MssʿD9W )C3-hK.\ހRj/ghKLQq0(XDNْ"rX-yp)+R6n]yi"[H1K2
bOnLM$Aˤrzayğe̽w%yΙ|WORT       YKOHWF#l $"`4tgv+NwW}UU?=4bN>}</0-8{$#:Kq$AZH +	HGE,l91ߍ}!_a
jrJMBƈPrtHwD<HIPb'=?Ԃ1
2"ῦ=	B :Ki$	^ K!9doχ{{\9?vc b|8IXj`HP(5H< Ĝ<b
04"0fSb$ڗɋEf)NSX8@3$L?r;}B)>LZX}zZp%廵aK9CBX7OlT zYǑ[oj:i8ΘkZ]l$xYK(0Z	tJXGG/~c%Ϯ)-\7n5^՞ZG6dv;fO4aa|NhY.xUYggIZ}༗ż a݊PÚkX O]^"rҏ4[x[|?]Bb{&fVLXULdpo.%gvK !y	o-9zUܝ޶"7(SHu!UVi]OJs6Kl揋U%YITgδpbmRoc9R@EfjGnrh@O}1\m-l]kcpv1G\93H@6@B6JB.HN\5jRB4hjr Ujfr:~_s?Zc|ٓͨk3R*͕ʶ.Us~"N9~RBtz=8<%L`q}*hiqLV.ڷ.=>:}' B zRU
l~i$To顪TvorHc60oTh`gie'!/?<qvy֭^NJ̗N&-*':˴󾲒f47zٸwִ'@AL,T} ?RBnŤiޢ[tN~6&vCO\BM0ZDʹ{,=wZMK;aX˟FޑJb:+}j@6ރOh^smЕpv'~ I*徳i72ʲ/mѪ=ytధ<VUQ`.(kp"'.5`4 2mӑ#$.tu%i|>|TbhbHuUU{R2:ns
K2u:s@͋*6:ƶ'Gr4o5R6cv[_wcoB1ȚJei7,JU#DC	ֿY*زUVAMYc(p<Bp^e^1=h"spEU gg!m|CӨoRUskS(b-߰ojw>t`Hftvz/#u|wԉ1(:3ؠh$_w5:7	­1y=278cX˰y`       Y[o8~ϯ P,*+]+vfa4Zl"({xI],v)^;~Ex"nP-_{>?pT{.d~`I	"8:B[T"ɏ"5AuODF߾Hb"-,S{P[%z	/~'PFRtj{TLrQQ\ӣ,Ѳ{ω_i+O*8}4zR8mzazkVHҏmks-V%p+-9{\'(cJ+%:Kw(i~7zBHH%WB `Fe[\'գuwVSDyi4H+t@D4<7O"l)-wB'D',di;$YeٍqƮ(qµY?*ml&nm{Tv7=, B$J@
@@Zeɞh|h@,ܘ❛6egR'OV6>PrHslŬ,rl9}L)=Sdጮl.*Jx_J^X$yu
iOKԎ6bOnWP6+7wHOfEq3c^2v$EYlxʡQgpNM%4ZψVڦliH w:"*,zϚ=6{D~t/BƾmoWָX-؇èrҼ,ˠڂ|h]t8i-@^fvioU{R=~7q(8^<L+^%~Ȯ<n)Ա ZC7bڐ%O묺kia|ltq^=k<kEBu,j@V	w
6尙Zozn0]}aM%]#MPu@`VYF#X脨UK}d[FJ@.K |qogF~udD:@-79aHg5:,҇@Oin:$H]RwkNi-Q"ݏvca61FN ё:;5$}\t	àWXdYdw`sJn-l1	JW(M0H?ʺ׺bwoY={yΦW($:o)F5Y12ϪC .tQ"!4,RQ/a6xeX!J3Ro^Xdn(q>j<LM.6 <}ӄcO׆fQcE7IIWgJoQ#n771rΠ	!no-'KA#mheLDwFYJp[XZURuةf.e7iE
*Sst_gaχj r{jzA[4XM]KՀw's!F?[8ù/awfAW%ц|q0Xr>
ՙRx2݋^ٓ^$8g.lC0*XBky7]Y^pZfH~@c]/@^,=\P0,5	LU65UWɯdwdXQ㞶=%LW뵏4_ƙ8tX&Q+Y+ ozMnB{cw_6v+c{0qpu]AGӊt	\JO_:a&tcMI)l
T跂j\Q[vs@@hGߣw$˻x_9m~=AFP=&4\zѲ,y2udLoEvsZӪG_c2݄8_	)VDeEW:8mDLgnX2ћkM:Lc0$+xad\轙}@'5 NRv6,|-qD&S/QibJf5 [.gQ4yx5(	C       Qo0'M(N1O]ևI^} 6I>DkٿξVu =4عFG)a,hEFX3%B9k}@C/_uDD\LAAҝ Gm	*!q(b'-ـj!zB~`%BvH8$4\mXO7l齓/^h 8,I3HwxE:]OV־:3&̙\~Rpr4@aHP0h`aԊ3ӓsNFW磷?)yv6oum@i!3S8-\z+D4Vq,JֿX#OX	:hZ'~+nFqQ~lq,Fk\  <html>
<head>
  <title>Interstitials</title>
  <meta name="viewport" content="width=device-width">
  <style>
  body {
    font-family: sans-serif;
    line-height: 1.4;
  }

  h3, h4 {
    margin-bottom: 0.5em;
  }

  ul {
    margin-top: 0.5em;
  }
  </style>
</head>
<body>
  <h2>Choose an interstitial</h2>
  <h3>SSL</h3>
  <ul>
    <li>
      <a href="ssl?overridable=1&strict_enforcement=0">example.com (generic, overridable)</a>
    </li>
    <li>
      <a href="ssl?overridable=0&strict_enforcement=0">
        example.com (generic, non-overridable)
      </a>
    </li>
    <li>
      <a href="ssl?overridable=0&strict_enforcement=1">
        example.com (HSTS, non-overridable)
      </a>
    </li>
    <li>
      <a href="clock?clock_manipulation=2">Clock is ahead</a>
    </li>
    <li>
      <a href="clock?clock_manipulation=-2">Clock is behind</a>
    </li>
    <li>
      <a href="ssl?type=hpkp_failure">Pinned certificate error</a>
    </li>
    <li>
      <a href="ssl?type=ct_failure&overridable=1">Certificate Transparency error</a>
    </li>
    <li>
      <a href="mitm-software-ssl?enterprise=0">MITM software</a>
    </li>
    <li>
      <a href="mitm-software-ssl?enterprise=1">MITM software on an enterprise-managed machine</a>
    </li>
  </ul>
  <h3>SafeBrowsing</h3>
  <h4>Loud</h4>
  <ul>
    <li>
      <a href="safebrowsing?type=malware">Malware</a>
    </li>
    <li>
      <a href="safebrowsing?type=phishing">Phishing</a>
    </li>
    <li>
      <a href="safebrowsing?type=unwanted">Malicious Unwanted Software</a>
    </li>
    <li>
      <a href="safebrowsing?type=clientside_malware">Client Side Malware</a>
    </li>
    <li>
      <a href="safebrowsing?type=clientside_phishing">Client Side Phishing</a>
    </li>
    <li>
      <a href="safebrowsing?type=billing">Billing</a>
    </li>
  </ul>
  <h4>Quiet (WebView)</h4>
  <ul>
    <li>
      <a href="quietsafebrowsing?type=malware">Malware</a>
    </li>
    <li>
      <a href="quietsafebrowsing?type=phishing">Phishing</a>
    </li>
    <li>
      <a href="quietsafebrowsing?type=unwanted">Malicious Unwanted Software</a>
    </li>
    <li>
      <a href="quietsafebrowsing?type=billing">Billing</a>
    </li>
    <li>
      <a href="quietsafebrowsing?type=giant">Giant</a>
    </li>
  </ul>
  <h3>Captive Portal</h3>
  <ul>
    <li>
      <a href="captiveportal">Captive Portal, Non-WiFi</a>
    </li>
    <li>
      <a href="captiveportal?is_wifi=1">
        Captive Portal, WiFi
      </a>
    </li>
    <li>
      <a href="captiveportal?is_wifi=1&wifi_name=CoffeeShopWiFi">
        Captive Portal, WiFi with network name "CoffeeShopWiFi"
      </a>
    </li>
  </ul>
  <h3>Supervised Users</h3>
  <ul>
    <li>
      <a href="supervised_user">
        Supervised User
      </a>
    </li>
  </ul>
</body>
</html>
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <meta name="theme-color" content="#fff">
  <meta name="viewport"
      content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>$i18n{tabTitle}</title>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

a {
  color: rgb(88, 88, 88);
}

body {
  --google-blue-600: rgb(26, 115, 232);
  --google-blue-700: rgb(25, 103, 210);
  --google-gray-50: rgb(248, 249, 250);
  --google-gray-300: rgb(218, 220, 224);
  --google-gray-500: rgb(154, 160, 166);
  --google-gray-600: rgb(128, 134, 139);
  --google-gray-700: rgb(95, 99, 104);
  background-color: #fff;
  color: var(--google-gray-700);
  word-wrap: break-word;
}

.nav-wrapper .secondary-button {
  background: #fff;
  border: 1px solid var(--google-gray-500);
  color: var(--google-gray-700);
  float: none;
  margin: 0;
  padding: 8px 16px;
}

.hidden {
  display: none;
}

html {
  -webkit-text-size-adjust: 100%;
  font-size: 125%;
}

.icon {
  background-repeat: no-repeat;
  background-size: 100%;
}
</style>
  <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
   Use of this source code is governed by a BSD-style license that can be
   found in the LICENSE file. */

button {
  border: 0;
  border-radius: 4px;
  box-sizing: border-box;
  color: #fff;
  cursor: pointer;
  float: right;
  font-size: .875em;
  margin: 0;
  padding: 8px 16px;
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

[dir='rtl'] button {
  float: left;
}

.bad-clock button,
.captive-portal button,
.main-frame-blocked button,
.neterror button,
.offline button,
.pdf button,
.ssl button,
.safe-browsing-billing button {
  background: var(--google-blue-600);
}

button:active {
  background: var(--google-blue-700);
  outline: 0;
}

#debugging {
  display: inline;
  overflow: auto;
}

.debugging-content {
  line-height: 1em;
  margin-bottom: 0;
  margin-top: 1em;
}

.debugging-content-fixed-width {
  display: block;
  font-family: monospace;
  font-size: 1.2em;
  margin-top: 0.5em;
}

.debugging-title {
  font-weight: bold;
}

#details {
  margin: 0 0 50px;
}

#details p:not(:first-of-type) {
  margin-top: 20px;
}

.secondary-button:active {
  border-color: white;
  box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .3),
      0 2px 6px 2px rgba(60, 64, 67, .15);
}

.secondary-button:hover {
  background: var(--google-gray-50);
  border-color: var(--google-gray-600);
  text-decoration: none;
}

.error-code {
  color: #646464;
  font-size: .86667em;
  text-transform: uppercase;
  margin-top: 12px;
}

#error-debugging-info {
  font-size: 0.8em;
}

h1 {
  color: var(--google-gray-900);
  font-size: 1.6em;
  font-weight: normal;
  line-height: 1.25em;
  margin-bottom: 16px;
}

h2 {
  font-size: 1.2em;
  font-weight: normal;
}

.icon {
  height: 72px;
  margin: 0 0 40px;
  width: 72px;
}

input[type=checkbox] {
  opacity: 0;
}

input[type=checkbox]:focus ~ .checkbox {
  outline: -webkit-focus-ring-color auto 5px;
}

.interstitial-wrapper {
  box-sizing: border-box;
  font-size: 1em;
  line-height: 1.6em;
  margin: 14vh auto 0;
  max-width: 600px;
  width: 100%;
}

#main-message > p {
  display: inline;
}

#extended-reporting-opt-in {
  font-size: .875em;
  margin-top: 39px;
}

#extended-reporting-opt-in label {
  position: relative;
  display: flex;
  align-items: flex-start;
}

.nav-wrapper {
  margin-top: 51px;
}

.nav-wrapper::after {
  clear: both;
  content: '';
  display: table;
  width: 100%;
}

.small-link {
  color: #696969;
  font-size: .875em;
}

.checkboxes {
  flex: 0 0 24px;
}

.checkbox {
  background: transparent;
  border: 1px solid white;
  border-radius: 2px;
  display: block;
  height: 14px;
  left: 0;
  position: absolute;
  right: 0;
  top: 3px;
  width: 14px;
}

.checkbox::before {
  background: transparent;
  border: 2px solid white;
  border-right-width: 0;
  border-top-width: 0;
  content: '';
  height: 4px;
  left: 2px;
  opacity: 0;
  position: absolute;
  top: 3px;
  transform: rotate(-45deg);
  width: 9px;
}

input[type=checkbox]:checked ~ .checkbox::before {
  opacity: 1;
}

#recurrent-error-message {
  background: #ededed;
  border-radius: 4px;
  padding: 12px 16px;
  margin-top: 12px;
  margin-bottom: 16px;
}

.showing-recurrent-error-message #extended-reporting-opt-in {
  margin-top: 16px;
}

@media (max-width: 700px) {
  .interstitial-wrapper {
    padding: 0 10%;
  }

  #error-debugging-info {
    overflow: auto;
  }
}

@media (max-width: 420px) {
  button,
  [dir='rtl'] button,
  .small-link {
    float: none;
    font-size: .825em;
    font-weight: 500;
    margin: 0;
    width: 100%;
  }

  button {
    padding: 16px 24px;
  }

  #details {
    margin: 20px 0 20px 0;
  }

  #details p:not(:first-of-type) {
    margin-top: 10px;
  }

  .secondary-button:not(.hidden) {
    display: block;
    margin-top: 20px;
    text-align: center;
    width: 100%;
  }

  .interstitial-wrapper {
    padding: 0 5%;
  }

  #extended-reporting-opt-in {
    margin-top: 24px;
  }

  .nav-wrapper {
    margin-top: 30px;
  }
}

/**
 * Mobile specific styling.
 * Navigation buttons are anchored to the bottom of the screen.
 * Details message replaces the top content in its own scrollable area.
 */

@media (max-width: 420px) {
  .nav-wrapper .secondary-button {
    border: 0;
    margin: 16px 0 0;
    margin-inline-end: 0;
    padding-bottom: 16px;
    padding-top: 16px;
  }
}

/* Fixed nav. */
@media (min-width: 240px) and (max-width: 420px) and
       (min-height: 401px),
       (min-width: 421px) and (min-height: 240px) and
       (max-height: 560px) {
  body .nav-wrapper {
    background: #fff;
    bottom: 0;
    box-shadow: 0 -22px 40px #fff;
    left: 0;
    margin: 0 auto;
    max-width: 736px;
    padding-left: 24px;
    padding-right: 24px;
    position: fixed;
    right: 0;
    width: 100%;
    z-index: 2;
  }

  .interstitial-wrapper {
    max-width: 736px;
  }

  #details,
  #main-content {
    padding-bottom: 40px;
  }

  #details {
    padding-top: 5.5vh;
  }

  button.small-link {
    color: var(--google-blue-600);
  }
}

@media (max-width: 420px) and (orientation: portrait),
       (max-height: 560px) {
  body {
    margin: 0 auto;
  }

  button,
  [dir='rtl'] button,
  button.small-link {
    font-family: Roboto-Regular,Helvetica;
    font-size: .933em;
    margin: 6px 0;
    transform: translatez(0);
  }

  .nav-wrapper {
    box-sizing: border-box;
    padding-bottom: 8px;
    width: 100%;
  }

  #details {
    box-sizing: border-box;
    height: auto;
    margin: 0;
    opacity: 1;
    transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  #details.hidden,
  #main-content.hidden {
    display: block;
    height: 0;
    opacity: 0;
    overflow: hidden;
    padding-bottom: 0;
    transition: none;
  }

  h1 {
    font-size: 1.5em;
    margin-bottom: 8px;
  }

  .icon {
    margin-bottom: 5.69vh;
  }

  .interstitial-wrapper {
    box-sizing: border-box;
    margin: 7vh auto 12px;
    padding: 0 24px;
    position: relative;
  }

  .interstitial-wrapper p {
    font-size: .95em;
    line-height: 1.61em;
    margin-top: 8px;
  }

  #main-content {
    margin: 0;
    transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  .small-link {
    border: 0;
  }

  .suggested-left > #control-buttons,
  .suggested-right > #control-buttons {
    float: none;
    margin: 0;
  }
}

@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
  .interstitial-wrapper {
    margin-top: 10vh;
  }
}

@media (min-height: 400px) and (orientation:portrait) {
  .interstitial-wrapper {
    margin-bottom: 145px;
  }
}

@media (min-height: 299px) {
  .nav-wrapper {
    padding-bottom: 16px;
  }
}

@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and
       (orientation: portrait) {
  .interstitial-wrapper {
    margin-top: 7vh;
  }
}

@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
  .interstitial-wrapper {
    margin-top: 10vh;
  }
}

/* Small mobile screens. No fixed nav. */
@media (max-height: 400px) and (orientation: portrait),
       (max-height: 239px) and (orientation: landscape),
       (max-width: 419px) and (max-height: 399px) {
  .interstitial-wrapper {
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
  }

  #details {
    flex: 1 1 auto;
    order: 0;
  }

  #main-content {
    flex: 1 1 auto;
    order: 0;
  }

  .nav-wrapper {
    flex: 0 1 auto;
    margin-top: 8px;
    order: 1;
    padding-left: 0;
    padding-right: 0;
    position: relative;
    width: 100%;
  }

  button {
    padding: 16px 24px;
  }

  button.small-link {
    color: var(--google-blue-600);
  }
}

@media (max-width: 239px) and (orientation: portrait) {
  .nav-wrapper {
    padding-left: 0;
    padding-right: 0;
  }
}
</style>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.bad-clock .icon {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAFo0lEQVR4Xu3cS1OTVxwG8Ha6dsZNt/0S7ozX+wUSGKN7ycIvkJ2OiNcdbvwMfABXLS1VvLXFSMWUgFAh1oJICCEGq8UFp8+fPu87J4S3vrmcvIfOceaZMKOSnN/8z/+c95Yv3B8XFxcXFxcXFzNRZ89+rZLJJNKLDCAZdfp0Hini5zWJ/Izk5e+QAf7bpPzf/yvKLkD0I1lArCOqwazL70D65Xdub5RUagcA0kDJCYCJ8Hen5b22D8y5czvVmTN9gCkRwHzwXvKe8t72wij1JWB6AFMIBDAPVZDPIJ/Fth7zDWAeESD64LPIZ7ICBwAxZBFRlmURiUWLk0ymuCwrG8NtQyqKKfUVYG4RwP7gs8pnbhsOAO4gapvlTluQzFaO+Uoy3nNMAayurlalcOqUKaSUudUKTa9dQN/t3m0EiWOItX6fw6W8nUCDyFJHh5ktAMbUuh0yN4HtBPpWgGIxNYQUTSBhTC3ZccvW3QNoawUR6Afk7p49ZpAwtuYPPHlsFUkFEehHAA0jy61GwthkjM1UTx8BIq2gIeDcQ+7v3atKnZ2trqK+xs/n8JRFVBUEJL+CBGgYQD/t369WWomEMTZ0PgkAaQ8g6ik2RJyH+/apxwD6BSm3tpLS9QPxTGDUFTQkTZrT6wGApIJGkKcHD6p38XjLzkzWfw6ZADb0oHvAEaBHAPpZKohAv7YSCWOup3r6CRBpBX3v9R+pHuSxAB04oDKI4EjGDh1qDRLGXA9Q1iagYQFigxagJwR6BpwxptIsEsYc+roVANajBhpkcxag+3qDBs5TRMd5jowfPtws0rqMPUz1JAkQbQ8i0F1vBWP/GQHOqEwvgWGywPmNWW0GCWMPA9RrA9Cg339YPQR6AhwBGtuEM47kjhxRE0jDSBh7GKABC4CqGzSBZHplNCDA6PGBXhw9qt4nEo0ADYQBytgCJLvnB97yLs2ZQM+Q59WV4+NM8nWqESSMPcwOOm8BEA8v2KC5QcxIgxYgTq0sgSY8HFaP4Ewjvx87Vi9SPgxQ0QYgHqD6q9cIK2jU7z2sHIY4NUAzyF/hkYphptiaDUBjFy6oYa//aLtnArHn1FaOjvMSkdfZsEgY+7YBqpTLKnvxonrI/jPiTS/ijBPHAxKYFxrONDLD5I8f33j9AKQQQHZOsaVr1wSlBmkcSN7hxagGlPtM5Xg4swR6xXwGqWhnk2aWr1/fEmni0iUfiNPLX84nQ+L8wbw+ceK/kPKGlnnzSFNA8nbPOQBNalOKOEw1DiMwfuaQj11dDS7z3ChGmVIA0nRvr8oCaKPvbMJ5ycxqOLObKudP4syfPCmpRcLYDRxqmMlKANLM5cvSf/zqmUI4rQik9ZwAnDnkDbKA/K0jYeyhD1ZtRnoFJKxSWuVwWjHEERjiyCsrR8N5iyu3i4iPhLEbON1hNuUApNdXrgAooHJqgHQchDiSApE+dXXxdIeBE2am8+7GjS2R5oBU1ZCDp5WfBR2HweVtueaWNXDKNXqkeSARRlutiMP404pZJJCHU0RwKanf8El786kEIL0BEisnsOfoOJICIzjLSLmjY5fFl33CZ/XmzSCkwMqZD5hWgkOgnIELh/Yhvb16Vc0RqXa1Ympx1EoikTZw6TnavA9AWujpERgdh0B+5bAp+72npBKJHQZuXrAPqXD7dlDlEIdVw+BGCKmePgO3v9iHBJzaymF0nCUNB9f3C6q7e6eBG6jsyofz57V9DrOpIRc0GMkKUuns7DFwC56dwYGnvpTX9hzGwynF47wFz8BNnLYGx1ScUn64WlXjlOPxxY8Yk6HbgO1H0nsOo+OsVRKJmNEbyW3PGpAAhGg9hwFOyj2KQCR/WjG4TeaWe5hlE5LAlBG8bvUwi3sc6lN390blGMBxD9S5RzINxD3U6x4Ld18s4L6awt64LzdxX4/zDxj9/IEueAvhAAAAAElFTkSuQmCC) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAACvlBMVEUAAAD/gID/gID/VVX/VVX/Tk7/YmL/YGD/VVXzUVH/XV32UlL/W1v2T0//WFj3UlL/UlL3UFD/WFjwTk7/U1P/U1PxTU3/V1fyT0//VFTzTk7/UlLwTU3/VVX0UFD/VFT/VFT1Tk7/VVX/VFT/U1PyT0//VFT/U1PxTEz/UlLuS0v/U1P/UlL/VFT0T0//U1P0Tk7/VFT/U1PuTU3/UlLzTU3/U1P/U1PwTEz/UlL/U1PvTU3/U1P/U1PxTU3/U1PzTk70Tk7/U1PyTk7/U1PzTk7/U1P/U1P6UFD/UlLzTk7/U1P/U1PyTk7/U1PtTEz/UlLyTU3/U1P/UlL/UlLxTk7/UlLvTEz/U1PvTU3/U1P/U1P/UlLxTEzxTU3zTU3/UlK7Ozu8Ozu8PDy9PDy+PDy+PT2/PDy/PT3APDzAPT3BPT3BPj7CPT3CPj7DPT3DPj7EPj7EPz/FPj7FPz/GPj7GPz/HPz/HQEDIPz/IQEDJPz/JQEDKQEDKQUHLQEDLQUHMQEDMQUHNQUHNQkLOQUHOQkLOZWXPQUHPQkLPZWXQQkLRQkLRQ0PSQkLSQ0PSZmbTQ0PTZmbUQ0PURETVQ0PVRETVaGjWRETWRUXXRETXRUXXaGjYRUXZRUXZaGjaRUXaRkbaaWnbRUXbRkbbaWncRkbdRkbdaWneRkbeR0ffRkbfR0ffa2vgR0fga2vhR0fhSEjha2viR0fiSEjia2vjSEjjbGzkSEjkSUnkbGzlSEjlSUnlbGzmSUnmbGznSUnnSkroSkrobW3pSkrqSkrqS0vqi4vrS0vriYnri4vsS0vsiYntS0vtTEzuTEzvTEzwTEzwTU3w6OjxTU3x6OjyTU3y6Ojy6eny8vLz8/P0Tk71Tk72Tk72cnL3T0/3cnL4T0/4cnL5T0/5c3P6T0/7UFD8UFD9UFD/UlJJWZWgAAAAYXRSTlMAAgQGDA0NEBUWFhwcHR0fHyAgNDQ3ODg9PT4+QkJDQ0lLS15fdHR1fHyEhIWGiIiJiYuVlaioqaurrK+vuLm5u7u7wsLExMXGxszM0tTU2dna2t/p7Ozt7fPz+fv+/v7+jD+tjQAACYhJREFUeAHs1cFqwjAcx/G1FR0iIqKIFFEUHKJQKlIRFKGUilSKVCmiHrKpCDuPHcbA99xtjA1+b7HLjmMkaeIu+TzBl18C/xtFURRFURSFQ6bc6g0ns8Uq3u3i1WI2GfZa5cz/tKQafW+NX629fiN11Rij1p3v8af9vFszrpRTGWxAZTOoyK8pdpZgsOwUpeaUxgSMyLgkLac6BZdpVUpO3QM3ry48JzdCIqOc0By9vUVC27YurscMIUBoiprHIhCCWEJGyvsQxhfwk5oxBIqbCXM0m0AoYmuJrqgD4RyDvyftQgI3zduTDSBFcMvXU4ggSVTg2ieCNFGW4/8EkChg/keGC6lcg61Hc8Dg7cc76DkaU5ANnqAnliKb6V4QrqB7liLCcEXyMfiCHp4/QC3O0/boPniDDi8MRb5OGWSBN+hwOL4yFFl0PSYB/0LH0+UTtIhJ9WAhEgSdTufLF2iFNI92ByRa6PzIUPTNih21uFG1cQC/Kewn6GWh0BdeSu1NKRRKS2+EUuiF2CKl7UWR3WabNHFmk84k2WSTndmsGyfZMc42ziYmJhozbo0hxSVsMYRYFhEEFWt7Uau1V3q+hf+Ts2ZXMsmMnHk+wY//ec55zjn/d/Heuc4DmqUg/4pr0XXnO+1Zwp2QP5B1LTrr+D4lHKC3aQ8BFHxn3bXI6U37OuFPKBAUI4U/3b6yHf4TCIqrh3w+vwCQVHQrmv4TcYFwJ3THHxIkSYqZLkUXpv7/EC4QTmrf3J1QSAwDtFh2KZr2f3SOGzQXCNwNCbIkx5LpqjvRuSn/dbcIbw/5fYGQIN6T5EQ6rX7qSnRr8q/fcYLi2vaz876AIIr34olESlEzzb+Iizo+EfQmJwie+WAQLXQvGk+mlEwma7kRvTHxv5dwJ3R7PiAIoixHk8mUmnErmvR7fJoXNHsbp3RQkMLRaHw5BY6maV+4EJ2e8PK5xg2apaCIiJZOJJfVbDarZXNtZ9E1+zfREcINoi0UXJBjMbpiq/BouZzWcRYdsQWd4AfNYY4tLOAQiidVdVWjnpyuf+UoOmELusQP8gfQ0wuynEBCqwDldHh0w1F0yc5z6CY3aM6POSZIsryYSCtoIayXXsgbht51EN08ZAM6SrhBPl9IFDDpFxfT6QxaGvkUUEbR6DuIjtqATvGD/L67oihF5MTSUlrNaDoKHN0oFs2vydQ6ZXs141+yu4IQFumeX1LX1vKaRj2GUQSo9M1/vqZd9SAhP0BhKYEOUjJrWr6gF3Tq2TBNs/SYTKmr454Zwg+ax6AXo/F4Mqkqa3l4DJYPOGalskum1MwY6LAHIAQkShIGq6KghfI6Wy8EVCqVKpXyt2RyHR4D/c8DUCAgRiJR3Dxw9UBLG6yfTXjMUqVarX1HJtaxMdBJD0BBQYhEpEQqqWBs5KjI+CeeKkDTRCfHQGc8ANGAZDmeSuGYph7WP0UmqtUatcb3ZEKd4X9v2CUUBAhjQ1lZwdgoIB54hhzkU6k1GvXmD67fHpc8AAnhSCQmJxQElF1f3yiAM/SUwUFA9Uaz2fzR7TS77AVIACiWximEMVYoDNeL5VODh3KshmUvujwGuuIBKBSOyAAp6iruHRs4DunuMoftzECWtbVl/URs6soY6C0PQO+KmPRoIUx6BASQud8/aCDLagLUav1s9wM6BrrhAejJe1EJPa2q2bymb2zQfEbx1Fk+8LTaNqIbXoJePt8XxZMJVVWyGKvY88P1QjtXWf8AZG21HrTbrV+cQTxL9ur5vuj9ZAoLltHzBlasshcQPA14miyfdrvTeeawZJxN/fuTA6LllJrVADKKFRQ81RryoR29hQKo1elsbz9zbOrLxCPRB+oqNplxv1iulPfyoZrhBoMG+WwD1P3VadtfJF6JPqRzo3Afoio7EJt1ixaLp418HnZR/xZdHAOdJ96JNGx6c7NC46Ee1Kh/OggI+XS3d3ZekAN13nm4cog+Wsce29xkGx7FNrw1BIHzcHunu7PTe/Ri6nA9SbwTPf14vWCW2X5nG77J8kE/dxAPDajX6/V/I6N6bQx0jHgp+sQslsusf5qsfSiIctoUNOT0+oN90THuK6yD6DNcERusfxoW2+5DD2sfgPr9/mDw+OXkK+wM8Vb0eam6Ny8sxnkAUBugIQee3mAw6I9EM/bPIG7R0wOien00MFp0YAw5XfRzr9vrPRr0wdnd3X016RmEh6IH9ccB0ZeUM1qvv7s539YmgiCMx5S+KP4RFUREBKFaFSqiSLWCVVSwBdEKIr5QP6IgtYrYiNe7unpudleWpHlrxdRv4cwOmyYVmSudg6XzCX7MPnN5sjsz+P0BoCXIz+DAsizPikB0T+avNEP0mvwP8dD3Bw5smWgQBzJUFCFHV5jLBiGiN+R/IPD3Ar/PpGcssCz7nCNPodQGXTYw1zEiRG/j95n0PBB00DPyKOAp9QZdx/A2XyBH5H9IPwCEcg4FFs9LlWtaqwfMlZ4g0TvSc8BBQbeiniE/GeSnhNDmotylJ09E+UEBYX0BzUfAQQGhfABIK21OyV0L80QfyP+8h1hGnhbVF+AUOfJobZ6NSV6c80Tkf0jP+H2m+qIEKeAxVyWeFpj4uUXUXQk/YLG+SM5ZEWhK5DHHG/+Jx4JEv4ZytEL+B3FIPwWEWqPzMuaR8PMUT9T9tBR/UGO5F0E+CnisPS/zgMcTdbeIVsn/oH5Az3mQDyWobV8cEX/i5InWV1sD/WR4XsRjMEE3+UfgWojI/2SxvEJ9tYHHHZN7JueJ1iNQ7yv5n3BeOeGUxgLPrRoaCXii3rfof0J+FMonCNq4E7KtFjwR8Qz5nyhnAzTO3ZVvRuGJel9G/A8dmGnjgbnTDSZuyBNhfkb8T6mNBhxnnb8u39DEE33/x/9oAwFE/vn+Bhvn/kjH73y7/9EWcaz3Z+tpiuOiX2zzP8biiXn/sCnfNliRaMT/AJBzwPPypHxjZVUiNex/qL6cvyTfelqdqBzyP6Sfzv1mXc25lYj0wP+0rYPwTw/W1r5cjchE/wM8oOhXZ+pr8K5OpCk9cF7+co0t8JWJgn5MILq2L4EhgT7yBBx/eyyJMYq+Czw/OgvjiQya9G3Iz+JEMqM4/Y71ncXDCQ0rbXb8wkRS41ybd8bTH3hLfyQw/aHJusZKDyU/eLsHRpMpSVO7H96easqOt8/ujmf2wF5fAJDgioQEl0jQmo0deYAnF46mv4gk/VUtKS2zkV/3Mzk9Mzcf1/3Mz81MTwqt+/kLc5W5R5JoGz0AAAAASUVORK5CYII=) 2x);
}
</style>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.captive-portal .icon {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAQAAAD/5HvMAAAEyElEQVR4Xu3afWhVZRwH8LvdmjVSjKyQbKazia1k1sL6YzXoZdy28/J8f5XRC7hwEVk0hZQCXY2SipCgYgappXMQ5Ya9ELZqoEM3VHqxBkapm21jOBWmbLfudk+0Peeu2+mc3zk9514WbN9/zz18ds75Pc/vPM+JTP9NZzrT+b9Fn2nGxHrainb8ggEaRgLn0IOjaMFroloU/Ssg1yxBLZpxBD00QufpODrRiFX6IiUKXY8XcRAJsryC3nRL7EpsQJ/r0V3iSS0/MKU4D6uoQwLY/P1q4i0aYX9xVqyPRH1jbr8UtfSbE8CDqIK60wBjOEb7aDf24CBO/gN12LjJF4dM+dPAoNgMdNkUxLENQltAFViJdbTWfFTcaRbiMXyCpE1CM4vR5uAzdwB/hcxCDI5jXqGFeAadNJoGH0ErVhg3YPs46Ad9JldNS3GCAbDPkFGG/eJGWktn3PA4IUB3oxPzGY4AXSBLCSTLgfZxx2MLV1Q5tFHeWxWQDNalHulWeo4q9GW4VVShng5J0KgZ8+bkYpcEqIJk6H2y0CiW4H58gGMYQhyn8DlqUUltZIk1XF01kKUW5yhm3gVB3Q76MDaRyXBQR1aIIJnyi6jNZUgs8uTQfUiGDJIxZ9OPfxEwhAO0F70To5NR5skxrsUgWaGDZLQCHBHVxnKxWjwuivRS7McK7na1kpUZkEwUzXbFiZfZcVk8pE6xZ3u34AV5TFJUsV2ObBHU0+Q5wu0eJ21krw+eD4lzBvOYf7wLeyI5DEfLx2l1DPqoSXK8SItis/gm41mlago/9P2UApklZE0pkHhdAv6YIiB8NwEQL9HvUwCkzZHz15g5Gw8jmR0QtsizvOoACUjAIdlOZQUkHpCgDqd1gwRslhX3djZAmDsBwpATJPtDUZPqGFuyUWU453IWu7fFHZOvhjiQ+aqiDheQ/bJjXpf2oP+caRA+cgPJpkxckeZfiIHMgmirC8gee4rz0qF6KV3IJEi86R8kg0oazQ6Iv2Uyoiajt4x/qJ1BfcCe6JQZC/BQ82XvDLYHJPUEK3tmYHTmlotpbzCSwsDomDpc+mD6VgHETB3M5Or2c5xUBvGTq7P98DjBEjqrBOLbD2eDZj7o+aJdhnhooJxUbd/r1cJ+yl1mJMMBGWUSP6zlezT5SIirGNKacEB4bwKEXcxrEN7gThUGSCtILaZXMC+KiGN+5kHYITndkSj7Ko3GTIPMEvtJFKt9LDYgiZtVQTLnqUPUOJcV8KWE95df4m85ps0+CQ/ig68xN72lscF4yveCFTa5g9AXnDR5lczC1Jr+4UhuCsAv6YlH3EDURFbgPCG3Y2altmPG9FIJ8LnoOYLbXNDzgi+Myvkqii9sIuocAHZZuN9tAKi6hnaiBwka9f942y2rzFcut4tZOO+3r5J6xcVmYEeKc9xlPuC3FhDHynBA6LQ5GGA2ftnNl82RqDrIDgb1ZU4AnxzUTc7raDeWhwPCUW0BA/C7gYeP9cWqILSUX8YAgmxxIoF3tYL/DkK9Y/znwm8CI4lvRLV+dVAQThOpOPht8p+ogZ4W9/jijFFD5eXhWPgPCXjMh/pSVYD6pxaywPGOKOIBWfkYhXYKozgvy5/rYBva8avzcx19sSrgT2jJnjJMVMiUAAAAAElFTkSuQmCC) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAQAAABNTyozAAAKSUlEQVR4Xu2de2wUxx3Hfxhj5dkSIgOhpICDWilH1AjTGEwdnaCNdbi+2/n+EGlKAvSBopRIKa+KSC5tCU+ZoKaKQ9WSNihqgsXDqRMkHBRBDDi04Q9kGQFG4JAEqF1TIkwSP+BcjBXK7zC3551Ze3zdz/7NnffD3uz8HjND/hAQEBAQEBAQEBAQEBAQEBAQEOAMjeWpOVjF5djFB7gWDWjmNm5DMxq4lg9gF5djlZoTy3OGkmceuzNWoBaiDDu5Dmf4M26/en2GM1yHnShTC2MFj91JNhG+y4lwKVejkTtTv9DI1VzqRMJ3UaoMxlS1Bof5iuunX8FhtQZTaTD1J6EsNU2tRA06uNP7hQ7UkCuxB3kDN/X605t4Q+xB6g8wGWV8njvNXJQUnoH9Op+O/TyD+g5nLEpwXAjwURCK+JCR7ziEIvKf6CRUIC4E+CiIc7DT5LdgJ+eQf8QKuEoI8FdQBi/jL41/05e8jDLIPM50rhYCfBaE+/Cei4DL+Ce2ogy/4We4i2fwG5RhK3/Il5NLwnu4j0yC0dgqBfgvKKmeI/wSopGv0S34/tcRxR/4SDJFZIpwplrCLdzZ54LG9DinalG/Lx5H1+AQP4dNqOSDfIovXb1O8UFUYhM/x6GvRjB+iS/1NP/CGDIDHuU6DQFaY5CaglZxW2d5WdE9RMV3qDn8Op9LKvwcv67mTLmdqOgePI+zQk+rmmLo2eG1Ou8r/beY8+R1AW14PpRFFMlWv0NzqtLxb/w2kk0UysLz3PaVIOdJMkHsfo2pmbHXPFZ1z2A4RPTDb/BG/qLX6r/AK9FRRBzqnk1hFZkAReL/qd8E0SC8iZJwJhGewgXP+v/T9dSEM1GCN2kQaZOBdTo/LfOhhhqOCt3Pxw413FD4iS1CgAWCsNvEN2A36RO9W/wxlggq/uYt0yjH+DW1Ri1Us69eC9Ua/JWPCS1mX+1quAgLrRFEFMvnNnG7cbyDeRh9i2ntPLyTMEi0YSrpgjGo5057BEkw74ab/Ut3hieSjZn8MvbyEW7idm7iI9jLL2NmJPta9ujV/0lVPzHw9Ag9VgiScGl3Zsd5gCh3iPMEasRTIp+vGvWjcKbzAPZ16cF6A2OP+HFZKYgyeLtaQhmUwc/ypylI/5SfDWdiMW+nDO03lxiaLRMk4RA+SF07PuAQaZMhXuyWC8KOXqrfTrpgHXfaLUgWfHo1GBzSLv+gCHHbBUlmjMRHqenBRzNGaoekIuayWJAsAN0Ql7VjL1bgaWcWnsYLeJ/br+u5oF3uCWeKiN1qQRIn3DXHQTN+XXQPCQqH8fJrxag2J0y68FohwHJBEjUblWo4USwfr+Aot3ALjqKsOxUWHcFvq9kGsoWIWyPoEnmgS0SiaFRGR5jKF9bZ8/zwKfIA3u9JNvaSCXipRXo6sYM8oCb0kJK/pCYYKeRwiw1idINJPH6T6sfJBNhmkx6cLb6DPKJeFKJfNFUl7bTpUj8l7wzmPdcF7THUDcTVNunBJtIiko1PuvTgk0i2oRYEm/Twn3KHkCbOI2hFq/MImYGrbJGDj/EUGUHNV/ON9fdYoKYF9diCH4dvI/tAhQWhg704YxEPBCUBJckFBILqA0FJwOTkAgJBZYGgpMUdPh8ISoKallxAIGilbM7HvkCQADVCwKLCYXwsEHTDgiW5Isd5+Nq08V/pJ8h5WK4kSnGxlRMR/6y5u1fPyeVL6SaIBslanxOhVOBSIWjbDQuNOqwWpJ8vLfWQJFML6Dr4eboJUguEoGpKBdnlJzP/WGFaDy70q6AJsjsxpaW2cuBKzOLxa4YFvU/9SO4QOWyksHw4licE1ffwke8aFNSG79oUlMfyyA01V9zA2z02AB82Iucc/s4h6mdkSVrNITewWjxB66kHoqPwcboEElgv7ne1u9FyYXT+Lfv/LqSHIDVf3EF5bysZhcn6btJBEBcKQVW9jMOSLShznkA8DZ6gKWJIqXE3WitG9YcoCfjVwBcUe0jcQS25gQYRnYzVzTzaX70RT1ADuSHDN3Wva0/7WwNbkLo3ITR3Qw69oSxyYcrtfHAgCwplyYmrIUGyZ4JPpJkg/Z+YJDqem9LvJ6Y/SMsI7os0G6T1X/MSFeMr/xeveT4gBOVTyuAXPheIzmEr5xgXlC8EHSA3sEuGGpb147eob/kZamCXTrDqziB+w29FqPQ3WNVNd7i/NPf4rKjJ13THKnejc1wSZq4pW78XLvibMPOQcvWwsuyMrYLcU64aSfvUUd/BxYEhKHcIX5ZJey9lHw+oH3C7HYL0yz7uhUNPqLlWCNIvHLqXnm1rA/Wz9KzRvOAF/NkCQfrNC+7tLxpLgXdaIEi3/cW9gYo8IBb3WyqIF8mEvdcWvH2kQXQEGmwVJFsL1UrvTZw5Woq+zedtFMQ5Urya5r0NeDlpob7HX1ooaLkQdD6U5b2R/ARpgpl8xTZBMpOOMq2lCLF80gS/tEtQLF9qx2TqHXIfcWwmbewShM1Cz3HNeTA6iselk6DicXKuhxL9BXUb00kQ/ij0xJ2x2ksy0RodlS6CoqPQKgRVmFnUuyFdBPEGqTw6yciycHyOMekgCGMSipxV5jYWeIs08G3h+HF+w5mV+jQvsR8lVmBwawoU2SNIXjjJTCmAogTB1WY3NznlfYm//6sYsd5tJ83wbXxKCnKmkx6Jx0BgBXkE//BbkHsdDy9IPdhqfIMldHg4KUCkcn2+OFnDJjrk+IXRpI9aIq3z6cJh5AEnty8E4aQoVMltAU9LmWqJ0U3e9OvjeLcvFDmzqEdQmSCzLpxJAoPbBGKxtyoUWv0XhL9RD2Cx1IM4HiWB2Y0m272N/mp2Hwg63uPbOLGQuZYExrcqxUVMJA/gZ9zudw8RJYCJiaVw7Hf9eelvdovG6HiP+4J86K+ixBZTNEo9aI7dT+7ob5eMkx43GR7kRPhVHMVFvsKX/RU0Y2Ti1BBxl3jA6IbbtUKRJSGI0FObqA/ryAWjW7bjZHS8rYKi43HyJj1bXMIR85v+oxETbRSEiWi8Sc9ut6jfl2MjcNGZbpsgZ3oPTVyHoneTBjoHj7TzIpsE8aKbJxOo1zr1Sf/oGlQWDrND0PWgQujRyIcaO/zotJqiIcjP65DG02Py+Cx0YEX4NtsEYbfO2GP+ALZTKLJJELbov7nMH+H3FsbYIAhxrNOY9/h5CCQ+5w3RUf0rCM26QYXPx4iilTcWj+svQdhvIiT1/SBadGBzLL+vBSHOa00mNPw/yvgEL+ecPhNUJ7OF9jxHS5MfMYF9vMh5mAb5KqiFl4YzyVYwGttSGDq3qQVqQu4Q84KwDaPJDvQP5EcH6vltrDemp1qEzHYTK+jjAwOqYgU00IhOQoX/274jjgrR3zPgdsYvQb1vcupR4oylgQ8mo8xwb8d5lGEypROhLDVNrUSN3nan6ECNWqmmhbIoXQnf5US4lKvR2CsxjVzNpU5ELFhKd5yhsTw1F6u5nKtQw7VoQDO3cRua0cC1qOEqLsdqNTeW5wwla/gvpXzJeo7GTncAAAAASUVORK5CYII=) 2x);
}
</style>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body.safe-browsing {
  --google-red-900: rgb(165, 14, 14);
  --google-red-700: rgb(197, 34, 31);
  --google-red-600: rgb(217, 48, 37);
  --google-red-500: rgb(234, 67, 53);
  --google-red-100: rgb(250, 210, 207);
  --google-red-50: rgb(252, 232, 230);
  background-color: var(--google-red-600);
  color: white;
}

.safe-browsing :-webkit-any(
    a, #details, #details-button, #proceed-button, h1, h2, p, .small-link) {
  color: white;
}

.safe-browsing button {
  background: white;
  border-color: white;
  color: var(--google-red-700);
}

.safe-browsing button:active {
  box-shadow: 0 1px 2px 0 rgba(165, 14, 14, .3),
      0 2px 6px 2px rgba(165, 14, 14, .15);
}

.safe-browsing button:hover {
  background: var(--google-red-50);
}

.safe-browsing .secondary-button {
  background-color: var(--google-red-600);
  border-color: var(--google-red-100);
  color: white;
}

.safe-browsing .secondary-button:active {
  box-shadow: 0 2px 3px rgba(0, 0, 0, .5);
}

.safe-browsing .secondary-button:hover {
  background-color: var(--google-red-500);
  border-color: var(--google-red-50);
}

.safe-browsing .error-code {
  display: none;
}

.safe-browsing .icon {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAA+VBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9/f3////9/f36+vr8/Pz7+/v7+/v7+/v7+/v////r6+vn5+fk5OT5+fn19fX4+Pju7u7v7+/o6Ojx8fH09PTy8vLz8/Pj4+P39/fm5ubp6eni4uL8/Pzw8PDt7e329vbs7Ozg4ODh4eHe3t7l5eX6+vrd3d3q6urf39/c3NzbRDf7+/vb29vW1tbZ2dk+D9arAAAALXRSTlMA/eIxBfACHj3YwhYJDyfOtfr2WHObgEqpjellgY6c6mZLV3L2qKjOZemN+rUv7NpAAAACcUlEQVR4Xu2U53baQBQGAxiMaQZT3Wt6rnql9uKW9v4Pk5XEspG4WFmJ/GMeYM635cy7/8yePXv23N7uxnNwdHSwE1ENoLYLTz4NkM7vQHQFhKv4nlQCCIlUbFEOXHJxPVVYUY3nKSSpKFmIJbqANRdxPIcnTHRyGEPUAga0onuy4CMb1ZM5Bh/HmYiiGwhwE81TvIYA18VIokvY4DKKp1SBDSqlCKIyIJT5PU1AafL3FVC4q1uDLdS4+4rCXd06bKXO21fKdxcNKFzVzUFQ9KoDJRehr0z0tBgBpcrfVyZavAxM7uo2ABHNO8s2NTW4+8pEs4HUMxS+6rYAEZFBYl+Y8FQ3C5hoIImGMNVVvLp4X1FRZ2n0BU035X+u7jmgomWv/zzWR23lB7ich/b1DBeRQVNNty1FHYLDWVh1TwEXic4gs6105UfPdMrd1/HCffrnqTayrYkqP3qmSom7r9q84xyMDLIUx7Mylfn7OvIGmbYyUYmGbmry99UWnYOZ7sFc5OHb1b2HLbS9QV1vED3dPX9fQXFuWiEeF9kzpfMcfaUZkbyn9+bQTfXwvm4W0iA3RNdQUyIV1lekkDOhSx3sdGh17+At0ctA0plDpr/gLqSvSI+kXt8mAj9DVl20r3hGBM0iOwKmBtZXHOPX79fFXCJ/Ure79Gxr40Owuu9hK8LPp1mnR7JmWuv7ZsM+oH3FGZObFoWx3iY/Ul1J2LVn0b7i6B2RZM1WumwL833MoH3FMQ1hPHIGsadnvk94X3EsctPE4xK8p89FvK84ExIRuoUa6Pt98fU1DJUMosj+3/S15OtrGOsB9LnYqm+e5w+es4JAhYQDdgAAAABJRU5ErkJggg==) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAABPlBMVEUAAAD////////////////////////////////6+vr7+/v7+/v7+/v9/f36+vr7+/v7+/v////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9/f3////////////8/Pz////5+fn////////6+vr////////8/Pz7+/v7+/v////k5OTh4eHf39/e3t7g4OD6+vrbRDf5+fnv7+/x8fH09PTY2Njc3Nz39/fq6ur4+Pjz8/Pn5+f7+/vZ2dnW1tbt7e3U1NTV1dXl5eXr6+v19fXy8vLs7Oz29vba2trb29vo6Ojm5ubu7u7d3d38/Pzp6enj4+Pi4uLw8PD///+BQ30nAAAAQHRSTlMAHhYFDzEJAifiwvb98M76PdjqtoGpZll0c46qj1icTJ1KS42A6WWb2WdadYK1cvCb/cJXV+KA9qioPc5l6Y36uRjySgAABXVJREFUeF7s1kuKwlAUBNDS+JtqggkkmODIH4gPRIgD11P730BDI6HV260Z1Wu4ZxUH/4tzzjnnnHPOOeecq2tEJdlsEsRkT+4RkeGRPA4Rj4YkG0RjfCLJ0xixCPwWEIkd73aIwuTMu/MEMTiwc4AeBhd2LgPolfyhhFzLBy3Eplc+uE6hteWTLaRGCz5ZjKBU8UUFodmNL24z6KQ0pJCpaaohksxpmifQKGhjIXurSbbZhr9qRG81yTYbaJJtNuefcsFbTbLNZnwjE7zVINtsybdK4VttreytHdlml/zIUvTWjmyzFT9USd7akW02pUm22TV7WOveKttswV4K1Vtlm12xp5XmrbLNBvYWhG+15YK3qjab0STb7Fcv5tmcOBKE4Q2Xc7KrTJW3yhs/2RsuZwvBjsQShPd0JxCyJVmA5v//getpgYextLSYKdHf+PbUO93No36Ht77eqHCvNnvASaBLp4rooClvpYGurpx92Sx6Kw3Uv873ZbOHvA7Qtd12m7ZZ6a00UN+225a7F5tt8XpA7Y61rJi1ViPeSgPZ7XZnuVh4zdsseisNhAEtzgOvaZt9yGsCdSwLeJKk16DNSm+lgSCghQAax9NGbfaI1wQSD7YIgnE8H0a3iY4a8FYSyMKAxgJoMqBs1txbaSDs6AR5Zv6Asllzb6WBIKAkiefzCQA5A8Jmjb2VBtoMKHXcUSM2e8x3ADoPAAh4Jr7v5G7IVKLjhr21DHS+DshP0xyAel3CZk29lQa6ebAUeLxe74KwWTNvpYGSFVDqOK4LPFF0QdisibfSQBsdjQFNo9EoI2zWxFtpINiJw+Fs5hcBTaeDwaibETar76000GZAnggIeLqSyNxmD/luQOM4LngceDBP8ACQSnTY+L111geRtqxlMfLDAsiFkV8H1GWSyNBmW7xO+eiJyo7O87B4MCaA1Ixazd9bUwgIgFYd7a8Dwo4GIqYQgc02f291kEcd+YJHVmZusye8djkAlKxHHnjEiEUIVOTDFKKTPdxbXdnRjghI7GjgUSqTNmvurTRRkMQAtBp53IkjJuNRiY72cW8NiwdLHdyJgmcdkGTKTGz2Gd+xPOhoGVAUjZgCo8zas33cW3lviFqWhyF2ND7YbaZM2qy5t9JEs8ITPexoJlFksUzTZo+5Tk3FiIWh7KAKpEzarLm30v/2ckczlYXdsGU6NvuY6wFdJjn+y4OXKR3EytP/WMNbNYD6Y9Ag8WCs/F4yo51t9oBrAoGJzJV/+WokJDow9NbaF7QJAKkNpMyb9KPfjL2VBrLtznLpQ0DlYNTKdrHZp1wfqA0iEjhMYsislN9I9LSmtz7RBxLmGCSxW9k9pYye1LPZR9wACNQagIbutgaSfvTI3Fvp+xDwgDd6ZERAVM9mT7kB0HIZJIn4Ekp7W+KRRKfG3kqfYyAg4HHy6ZZwpB+daHgrVfG///3z5u1l38aODsbFrcH1opJ7VPgRabNnfPeaI8+13REdPV4FBA4CRkQyZWekt2rU8M3lVREQns9AG4XmgxLRjc0+v0d4q1ZNVjznNw8WgsTiviaRXmh5K/19jzsaL+biwVwhsbeXdLUfffa+nrfSX9P4rYjnRcdFBWGSQ+KUf3/ybp7vuX6lFp7woaN9eDBxiUEIwCDH/wfCWzUrXwTrgLCj14rGuhTSxx8Q3qpZLnSQ4MlXHS2He8u+xvqJ8FbdCmEFTXxcQdFAJkPP2qfVNvsLNy1vjg9WBKQsQMKPfiW8Vbt6SkdLFkb50VeEt2rX1MGA4MHUlhkRfvTFh4S3alcEHaSczmr20R+Et+rXCDu63DJsux/9+R7hrQZE0NFEHlVh/UV4q0F1B6zSEdlWF/lSsdn/AccLgKctjBheAAAAAElFTkSuQmCC) 2x);
}

@media (min-width: 240px) and (max-width: 420px) and
       (min-height: 401px),
       (min-width: 421px) and (min-height: 240px) and
       (max-height: 560px) {
  body.safe-browsing .nav-wrapper {
    background: var(--google-red-600);
    box-shadow: 0 -22px 40px var(--google-red-600);
  }
}

.safe-browsing-billing .icon {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABAlBMVEUAAADcRTfcRDfdRET/gIDcRjr/ZmbjVTncRDfcRTfcRDfdRDzgSTncRDjeSDvcRTjbRDfbRDjeRzvcRjfbRjjcRTjcRTjcRTfdRTfcRDjdRTjcRTjbRDjbRTjbRTjbRTfcRjjdRDrcRjfbRTjZQzfcRDjZRDfZRzbWQzXXRDXXQzbXQzbWQjXYSDvWQjbbRDfOQDPSQTTUQjXCPDDNPzPJPjLGPTHVQjXMPzPRQTTWQjXLPzPDPDHYQzbAOzDTQTXHPTLIPjK8Oi++Oy/FPTHEPTHPQDTQQDTUQTXBPDDKPjK/OzC9Oi/////PQDPRQDS3OS66OS7TQTTEPDHXQjbMPjMBhLaWAAAAL3RSTlMA4tgPAhYFCcL98B4x9ie1+s49WICbqXNKZY3pjuqcgVdLZnL2qKg9zmXpjfontV8LANsAAAJrSURBVHhe7ZTnduIwFAY3ARIgBAg9vW1v173ROylby/u/yso2Fx3MNaxs9h/zAHM+Sfa8+M/s2LFjx+3tdjwH+/sHWxHVAerb8KSyANnUFkRXwLiK78llgJHJxRalwSMd11OGOeV4nsM9FO0dxhJdw4LrOJ6jYy46PoohqgEHatE9JViiFNWTPIElTpIRRXcQ4C6aJ3EJAS4TkUQXsMJFFE++CCsU8xFEBSAoiHsaQNIQ7yuQCFe3DiHUhftKIlzdKoRSFe0r8sXDAkSoumkIigYaIOkIfeWi56EESFm8r1w0fFIl4epWgBA9qOMpmirCfeWijtoa9WSx6taAELFBRl/vilS3BJRIbRk9/VFTsLrifUXRuNfXLU0y/7m6p0CKxqN+v6lJU/k3eJxu7Os5LWKDHi1tYstKG1zON1X3DGiRMR80Mx3fdCbc1+bQe3o2SJrYXcV0fFMxL9xXiz0987BBtux65qaCeF8lHCR3FabBTQ3xvk4M1yN5B/Mw2+urew8hTP1BM38Qnu5evK8gMw+7IcfH9E3ZlEBfMSO//Kf35+Cm6ua+rhbSYDeEa9CUyW3qK1HIjj5DBz8dWd0bWCd6Ult/uMPEr+BmbV/JHrVG/a9MsEybV5fsK50R3frmBFXtCtVXmt73H4PhQ4t9k9rkJ55tYXwZrO4rCEUfPHfUEcuaZC/umw97TfaVpslu2tCb2lRWnBlKFtf+huwrjaa6Pxv7RfgW7nubJPtKI/X0puQO4k/Pfe/ovtLY7KbxVwve0/sE3VeaLosIbkEDvt8Hoq/hKGwQYvoq5OMnoq/hLAbgc/FVn33PX7pAfE5QHR6fAAAAAElFTkSuQmCC) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAABTVBMVEUAAADcRDf/ZmbcRjrjVTn/gIDdRETdRDzZQzbXQzXWQzbXQjbWQzXZRDbbRDnWQjXWQzXYSDvbRTjcRTjbRTfcRjfcRTjcRTjdRjncRTfdRTndRTfdRDrbRTjcRDnbRDfbRDjbRjfcRjfbRTjcRTjdRTjbRjjcRTjcRDjcRjncRTncRTndRDnbRTjcRDfZQzbcRTfgSTncRDfcRjjZQzjcRTfVRDbcRDjcRDjWQzXeRzvbRDjXRDXXQzbXQzbbRDfeSDvWQjbVQjXIPjLOQDPXQjbCPDDNPzPUQTXRQTS5OS7QQDTUQjW3OS7SQTTPQDTFPDHJPjK2OC26OS7HPjHOPzPLPjLMPjPRQDTGPDHTQTTEPTHLPzPGPTG7Oi/HPTLKPjLTQTXYQza9Oi/MPzPFPTHDPDHBPDC/OzC+Oy+8Oi/AOzDWQjX////bRDd3undHAAAAQnRSTlMA2AUWCQIPHj39wvbO8DH64ifqqYFmtrVMc1lKS5x0nY6PWKqbjYDpZXWCZ1py8Jv9McJXV+KA9qioPc5l6Y36J7VmcHe8AAAFWUlEQVR4XuzWS4rCQBSG0euz56ISgiaEjHwgGhAhDnRF3/6HDY1Ia5WPjP4a3LOKY28555xzzjnnnHPOuSyzpPR7vb6lZAUrS8hgB7uBpaMEKC0Zhz3A/mCpaPjTWCK23GwtCcMjN8ehpWDN3doS8HPi7vRjejX/1CbX8qA1sdGZB+eRaW14sjGp8YQnk7EpVQQqE7peCFyupjMnYm4yGVGZ7q1EyTZbEEche2uUbLMlL5W6t4Zkm22Ikm02561c89aQbLNTPpgq3hqSbbbmo1r41rhW8NaAaLMzvjITvDUg2WzFlyrBWwOCzc6Jkm12QQcL3Vtlmy3opFC9VbbZJR0tNW+Vbbahs0b41rhc8FbVZqdEyTb724t5/bYNA3G4e+80NYI0gGFkvaR779KKZUWuFKe7nlIsT5X//2M5VMZiZB9DQj74xW8ffrwjP90Mb/07Vf5CbXYJg0BtO4toKS9vhYHGY1vDZg28FQY6tBZls8tYBehwNLTyt1nhrTDQaDQcWAux2SJWAxpOBpWMWSvm4q0w0Gg4nFQqFTd/m72HlYBYQJV+w83bZu9jRaDJYEB4osjJ02aFt8JASUBRq+PlarMrWBGI8lQajVanXA5kopUcvBUEGrCAWhSoXs3PZtewKhA/MMbTbcpEa7l4KwwURZSHANnVnGz2CVYGmg6oZ1u1XGy2hNWBCA8BogE1m7Zl+ShNVMrdW2Wg/v+Amr2eRYCcGLBZU2+FgcSBESDfdZxdwGbNvBUGihKgnk1OjPAEwS5gsybeCgNNdTQLyAtqtRCwWQNvhYH4ndjtNnlAnlet1uIQsFl9b4WBpgNyaUCEJ45DwGa1vRUGanU6nMcmB+ZSnlosES3nvm/tUpGm1tFPd5DDAyKFBJGpzRaxSjW5J0o8/MAQ4ZEyKua/b+0Np175blMERDuaECFBZGqzBaxY9iAjIMbDK01U0OVZxcplE6BIjLzFRixgQDwflCJaXcC+1ToKyOYHFvCOljPiNmvurTBRI+oQoGTk2Z1YQyIeiWhlEftWnx8Yf8RcyiMCEkyhic2u4xOWSw9MBBQENTQFI83a+iL2rdgpJ1rms45mByYzhbDNwt6qTtTlQC7r6FT/CLRQ02ZLWKc8OmK+LzooCykhKpl4q7p+7B/d0SjNggRbqGOzm1gPqL3PX3niZakOQsenf1PDWzWAxr+JBtEDQxnnJTISNmvurfBK75t45bORBNGSobcqb9DqBCjdQOl5E370xthbYaDRiIjRDxKQwJk9a+o2u431gYZERBo/kcBIfvJ/TrSt6K1b+kDUHMkra2V3j5zRlprNbmADILbQ65S/z2ggyY82zL0VXsdQnnLdhSOKQzWbLWADIMpDgOrd3q958QiigrG3wusYzmNbXmY4sh+tangrVJ2Dgy97X9v0CmILzzIHcj3ZPTL+h6DN7mhYR5nxHI4mtKNbLCAmaX9QDDKFO6C36hDttcdJQFGLeTWRIupocGOj62cBb9WqesLTFwfm000MQgqz9lDLW+Hve35HM9Fnqw9HetBkNsF6+Yaet8Jf0+xbka0XbYspSMIg+5D8/8psnqdYv3qso1vsS9Hy6SaGQ6AYHP9ngLdqllVpiIB8RygRQjGEdOsc4K26RGzk6YTxjhbDDdzXcfwC8Fbd8glPnR4Y62gBAM/a1WybfYVNyyUBiZFPXYCAH70GvFW7nFRHH7EgyI8uAd6qXZ7NAqoilG6ZKuBH184D3qpdAQlIWp0p9dE7wFv1q8Y6+njLoPl+9P4C4K0GRKSjgTyywvoAeKtBxVWU6YhorovcvA14q0HtouwU0Fw/+jzN8w/cQ/zg6ug2/QAAAABJRU5ErkJggg==) 2x);
}


</style>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

.ssl .icon {
  background-image: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABAlBMVEUAAADcRTfcRDfdRET/gIDcRjr/ZmbjVTncRDfcRTfcRDfdRDzgSTncRDjeSDvcRTjbRDfbRDjeRzvcRjfbRjjcRTjcRTjcRTfdRTfcRDjdRTjcRTjbRDjbRTjbRTjbRTfcRjjdRDrcRjfbRTjZQzfcRDjZRDfZRzbWQzXXRDXXQzbXQzbWQjXYSDvWQjbbRDfOQDPSQTTUQjXCPDDNPzPJPjLGPTHVQjXMPzPRQTTWQjXLPzPDPDHYQzbAOzDTQTXHPTLIPjK8Oi++Oy/FPTHEPTHPQDTQQDTUQTXBPDDKPjK/OzC9Oi/////PQDPRQDS3OS66OS7TQTTEPDHXQjbMPjMBhLaWAAAAL3RSTlMA4tgPAhYFCcL98B4x9ie1+s49WICbqXNKZY3pjuqcgVdLZnL2qKg9zmXpjfontV8LANsAAAJrSURBVHhe7ZTnduIwFAY3ARIgBAg9vW1v173ROylby/u/yso2Fx3MNaxs9h/zAHM+Sfa8+M/s2LFjx+3tdjwH+/sHWxHVAerb8KSyANnUFkRXwLiK78llgJHJxRalwSMd11OGOeV4nsM9FO0dxhJdw4LrOJ6jYy46PoohqgEHatE9JViiFNWTPIElTpIRRXcQ4C6aJ3EJAS4TkUQXsMJFFE++CCsU8xFEBSAoiHsaQNIQ7yuQCFe3DiHUhftKIlzdKoRSFe0r8sXDAkSoumkIigYaIOkIfeWi56EESFm8r1w0fFIl4epWgBA9qOMpmirCfeWijtoa9WSx6taAELFBRl/vilS3BJRIbRk9/VFTsLrifUXRuNfXLU0y/7m6p0CKxqN+v6lJU/k3eJxu7Os5LWKDHi1tYstKG1zON1X3DGiRMR80Mx3fdCbc1+bQe3o2SJrYXcV0fFMxL9xXiz0987BBtux65qaCeF8lHCR3FabBTQ3xvk4M1yN5B/Mw2+urew8hTP1BM38Qnu5evK8gMw+7IcfH9E3ZlEBfMSO//Kf35+Cm6ua+rhbSYDeEa9CUyW3qK1HIjj5DBz8dWd0bWCd6Ult/uMPEr+BmbV/JHrVG/a9MsEybV5fsK50R3frmBFXtCtVXmt73H4PhQ4t9k9rkJ55tYXwZrO4rCEUfPHfUEcuaZC/umw97TfaVpslu2tCb2lRWnBlKFtf+huwrjaa6Pxv7RfgW7nubJPtKI/X0puQO4k/Pfe/ovtLY7KbxVwve0/sE3VeaLosIbkEDvt8Hoq/hKGwQYvoq5OMnoq/hLAbgc/FVn33PX7pAfE5QHR6fAAAAAElFTkSuQmCC) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAABTVBMVEUAAADcRDf/ZmbcRjrjVTn/gIDdRETdRDzZQzbXQzXWQzbXQjbWQzXZRDbbRDnWQjXWQzXYSDvbRTjcRTjbRTfcRjfcRTjcRTjdRjncRTfdRTndRTfdRDrbRTjcRDnbRDfbRDjbRjfcRjfbRTjcRTjdRTjbRjjcRTjcRDjcRjncRTncRTndRDnbRTjcRDfZQzbcRTfgSTncRDfcRjjZQzjcRTfVRDbcRDjcRDjWQzXeRzvbRDjXRDXXQzbXQzbbRDfeSDvWQjbVQjXIPjLOQDPXQjbCPDDNPzPUQTXRQTS5OS7QQDTUQjW3OS7SQTTPQDTFPDHJPjK2OC26OS7HPjHOPzPLPjLMPjPRQDTGPDHTQTTEPTHLPzPGPTG7Oi/HPTLKPjLTQTXYQza9Oi/MPzPFPTHDPDHBPDC/OzC+Oy+8Oi/AOzDWQjX////bRDd3undHAAAAQnRSTlMA2AUWCQIPHj39wvbO8DH64ifqqYFmtrVMc1lKS5x0nY6PWKqbjYDpZXWCZ1py8Jv9McJXV+KA9qioPc5l6Y36J7VmcHe8AAAFWUlEQVR4XuzWS4rCQBSG0euz56ISgiaEjHwgGhAhDnRF3/6HDY1Ia5WPjP4a3LOKY28555xzzjnnnHPOuSyzpPR7vb6lZAUrS8hgB7uBpaMEKC0Zhz3A/mCpaPjTWCK23GwtCcMjN8ehpWDN3doS8HPi7vRjejX/1CbX8qA1sdGZB+eRaW14sjGp8YQnk7EpVQQqE7peCFyupjMnYm4yGVGZ7q1EyTZbEEche2uUbLMlL5W6t4Zkm22Ikm02561c89aQbLNTPpgq3hqSbbbmo1r41rhW8NaAaLMzvjITvDUg2WzFlyrBWwOCzc6Jkm12QQcL3Vtlmy3opFC9VbbZJR0tNW+Vbbahs0b41rhc8FbVZqdEyTb724t5/bYNA3G4e+80NYI0gGFkvaR779KKZUWuFKe7nlIsT5X//2M5VMZiZB9DQj74xW8ffrwjP90Mb/07Vf5CbXYJg0BtO4toKS9vhYHGY1vDZg28FQY6tBZls8tYBehwNLTyt1nhrTDQaDQcWAux2SJWAxpOBpWMWSvm4q0w0Gg4nFQqFTd/m72HlYBYQJV+w83bZu9jRaDJYEB4osjJ02aFt8JASUBRq+PlarMrWBGI8lQajVanXA5kopUcvBUEGrCAWhSoXs3PZtewKhA/MMbTbcpEa7l4KwwURZSHANnVnGz2CVYGmg6oZ1u1XGy2hNWBCA8BogE1m7Zl+ShNVMrdW2Wg/v+Amr2eRYCcGLBZU2+FgcSBESDfdZxdwGbNvBUGihKgnk1OjPAEwS5gsybeCgNNdTQLyAtqtRCwWQNvhYH4ndjtNnlAnlet1uIQsFl9b4WBpgNyaUCEJ45DwGa1vRUGanU6nMcmB+ZSnlosES3nvm/tUpGm1tFPd5DDAyKFBJGpzRaxSjW5J0o8/MAQ4ZEyKua/b+0Np175blMERDuaECFBZGqzBaxY9iAjIMbDK01U0OVZxcplE6BIjLzFRixgQDwflCJaXcC+1ToKyOYHFvCOljPiNmvurTBRI+oQoGTk2Z1YQyIeiWhlEftWnx8Yf8RcyiMCEkyhic2u4xOWSw9MBBQENTQFI83a+iL2rdgpJ1rms45mByYzhbDNwt6qTtTlQC7r6FT/CLRQ02ZLWKc8OmK+LzooCykhKpl4q7p+7B/d0SjNggRbqGOzm1gPqL3PX3niZakOQsenf1PDWzWAxr+JBtEDQxnnJTISNmvurfBK75t45bORBNGSobcqb9DqBCjdQOl5E370xthbYaDRiIjRDxKQwJk9a+o2u431gYZERBo/kcBIfvJ/TrSt6K1b+kDUHMkra2V3j5zRlprNbmADILbQ65S/z2ggyY82zL0VXsdQnnLdhSOKQzWbLWADIMpDgOrd3q958QiigrG3wusYzmNbXmY4sh+tangrVJ2Dgy97X9v0CmILzzIHcj3ZPTL+h6DN7mhYR5nxHI4mtKNbLCAmaX9QDDKFO6C36hDttcdJQFGLeTWRIupocGOj62cBb9WqesLTFwfm000MQgqz9lDLW+Hve35HM9Fnqw9HetBkNsF6+Yaet8Jf0+xbka0XbYspSMIg+5D8/8psnqdYv3qso1vsS9Hy6SaGQ6AYHP9ngLdqllVpiIB8RygRQjGEdOsc4K26RGzk6YTxjhbDDdzXcfwC8Fbd8glPnR4Y62gBAM/a1WybfYVNyyUBiZFPXYCAH70GvFW7nFRHH7EgyI8uAd6qXZ7NAqoilG6ZKuBH184D3qpdAQlIWp0p9dE7wFv1q8Y6+njLoPl+9P4C4K0GRKSjgTyywvoAeKtBxVWU6YhorovcvA14q0HtouwU0Fw/+jzN8w/cQ/zg6ug2/QAAAABJRU5ErkJggg==) 2x);
}

.ssl-opt-in .checkbox {
  border-color: #696969;
}

.ssl-opt-in .checkbox::before {
  border-color: #696969;
}
</style>
  <script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Assertion support.
 */

/**
 * Verify |condition| is truthy and return |condition| if so.
 * @template T
 * @param {T} condition A condition to check for truthiness.  Note that this
 *     may be used to test whether a value is defined or not, and we don't want
 *     to force a cast to Boolean.
 * @param {string=} opt_message A message to show on failure.
 * @return {T} A non-null |condition|.
 */
function assert(condition, opt_message) {
  if (!condition) {
    let message = 'Assertion failed';
    if (opt_message) {
      message = message + ': ' + opt_message;
    }
    const error = new Error(message);
    const global = function() {
      /** @type {boolean} */
      this.traceAssertionsForTesting;
      return this;
    }();
    if (global.traceAssertionsForTesting) {
      console.warn(error.stack);
    }
    throw error;
  }
  return condition;
}

/**
 * Call this from places in the code that should never be reached.
 *
 * For example, handling all the values of enum with a switch() like this:
 *
 *   function getValueFromEnum(enum) {
 *     switch (enum) {
 *       case ENUM_FIRST_OF_TWO:
 *         return first
 *       case ENUM_LAST_OF_TWO:
 *         return last;
 *     }
 *     assertNotReached();
 *     return document;
 *   }
 *
 * This code should only be hit in the case of serious programmer error or
 * unexpected input.
 *
 * @param {string=} opt_message A message to show when this is hit.
 */
function assertNotReached(opt_message) {
  assert(false, opt_message || 'Unreachable code hit');
}

/**
 * @param {*} value The value to check.
 * @param {function(new: T, ...)} type A user-defined constructor.
 * @param {string=} opt_message A message to show when this is hit.
 * @return {T}
 * @template T
 */
function assertInstanceof(value, type, opt_message) {
  // We don't use assert immediately here so that we avoid constructing an error
  // message if we don't have to.
  if (!(value instanceof type)) {
    assertNotReached(
        opt_message ||
        'Value ' + value + ' is not a[n] ' + (type.name || typeof type));
  }
  return value;
}


/**
 * Alias for document.getElementById. Found elements must be HTMLElements.
 * @param {string} id The ID of the element to find.
 * @return {HTMLElement} The found element or null if not found.
 */
function $(id) {
  // Disable getElementById restriction here, since we are instructing other
  // places to re-use the $() that is defined here.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, HTMLElement) : null;
}

// TODO(devlin): This should return SVGElement, but closure compiler is missing
// those externs.
/**
 * Alias for document.getElementById. Found elements must be SVGElements.
 * @param {string} id The ID of the element to find.
 * @return {Element} The found element or null if not found.
 */
function getSVGElement(id) {
  // Disable getElementById restriction here, since it is not suitable for SVG
  // elements.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, Element) : null;
}

/**
 * @return {?Element} The currently focused element (including elements that are
 *     behind a shadow root), or null if nothing is focused.
 */
function getDeepActiveElement() {
  let a = document.activeElement;
  while (a && a.shadowRoot && a.shadowRoot.activeElement) {
    a = a.shadowRoot.activeElement;
  }
  return a;
}

/**
 * Add an accessible message to the page that will be announced to
 * users who have spoken feedback on, but will be invisible to all
 * other users. It's removed right away so it doesn't clutter the DOM.
 * @param {string} msg The text to be pronounced.
 */
function announceAccessibleMessage(msg) {
  const element = document.createElement('div');
  element.setAttribute('aria-live', 'polite');
  element.style.position = 'fixed';
  element.style.left = '-9999px';
  element.style.height = '0px';
  element.innerText = msg;
  document.body.appendChild(element);
  window.setTimeout(function() {
    document.body.removeChild(element);
  }, 0);
}

/**
 * Generates a CSS url string.
 * @param {string} s The URL to generate the CSS url for.
 * @return {string} The CSS url string.
 */
function getUrlForCss(s) {
  // http://www.w3.org/TR/css3-values/#uris
  // Parentheses, commas, whitespace characters, single quotes (') and double
  // quotes (") appearing in a URI must be escaped with a backslash
  let s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
  // WebKit has a bug when it comes to URLs that end with \
  // https://bugs.webkit.org/show_bug.cgi?id=28885
  if (/\\\\$/.test(s2)) {
    // Add a space to work around the WebKit bug.
    s2 += ' ';
  }
  return 'url("' + s2 + '")';
}

/**
 * Parses query parameters from Location.
 * @param {Location} location The URL to generate the CSS url for.
 * @return {Object} Dictionary containing name value pairs for URL
 */
function parseQueryParams(location) {
  const params = {};
  const query = unescape(location.search.substring(1));
  const vars = query.split('&');
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split('=');
    params[pair[0]] = pair[1];
  }
  return params;
}

/**
 * Creates a new URL by appending or replacing the given query key and value.
 * Not supporting URL with username and password.
 * @param {Location} location The original URL.
 * @param {string} key The query parameter name.
 * @param {string} value The query parameter value.
 * @return {string} The constructed new URL.
 */
function setQueryParam(location, key, value) {
  const query = parseQueryParams(location);
  query[encodeURIComponent(key)] = encodeURIComponent(value);

  let newQuery = '';
  for (const q in query) {
    newQuery += (newQuery ? '&' : '?') + q + '=' + query[q];
  }

  return location.origin + location.pathname + newQuery + location.hash;
}

/**
 * @param {Node} el A node to search for ancestors with |className|.
 * @param {string} className A class to search for.
 * @return {Element} A node with class of |className| or null if none is found.
 */
function findAncestorByClass(el, className) {
  return /** @type {Element} */ (findAncestor(el, function(el) {
    return el.classList && el.classList.contains(className);
  }));
}

/**
 * Return the first ancestor for which the {@code predicate} returns true.
 * @param {Node} node The node to check.
 * @param {function(Node):boolean} predicate The function that tests the
 *     nodes.
 * @return {Node} The found ancestor or null if not found.
 */
function findAncestor(node, predicate) {
  let last = false;
  while (node != null && !(last = predicate(node))) {
    node = node.parentNode;
  }
  return last ? node : null;
}

function swapDomNodes(a, b) {
  const afterA = a.nextSibling;
  if (afterA == b) {
    swapDomNodes(b, a);
    return;
  }
  const aParent = a.parentNode;
  b.parentNode.replaceChild(a, b);
  aParent.insertBefore(b, afterA);
}

/**
 * Disables text selection and dragging, with optional whitelist callbacks.
 * @param {function(Event):boolean=} opt_allowSelectStart Unless this function
 *    is defined and returns true, the onselectionstart event will be
 *    surpressed.
 * @param {function(Event):boolean=} opt_allowDragStart Unless this function
 *    is defined and returns true, the ondragstart event will be surpressed.
 */
function disableTextSelectAndDrag(opt_allowSelectStart, opt_allowDragStart) {
  // Disable text selection.
  document.onselectstart = function(e) {
    if (!(opt_allowSelectStart && opt_allowSelectStart.call(this, e))) {
      e.preventDefault();
    }
  };

  // Disable dragging.
  document.ondragstart = function(e) {
    if (!(opt_allowDragStart && opt_allowDragStart.call(this, e))) {
      e.preventDefault();
    }
  };
}

/**
 * Check the directionality of the page.
 * @return {boolean} True if Chrome is running an RTL UI.
 */
function isRTL() {
  return document.documentElement.dir == 'rtl';
}

/**
 * Get an element that's known to exist by its ID. We use this instead of just
 * calling getElementById and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} id The identifier name.
 * @return {!HTMLElement} the Element.
 */
function getRequiredElement(id) {
  return assertInstanceof(
      $(id), HTMLElement, 'Missing required element: ' + id);
}

/**
 * Query an element that's known to exist by a selector. We use this instead of
 * just calling querySelector and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} selectors CSS selectors to query the element.
 * @param {(!Document|!DocumentFragment|!Element)=} opt_context An optional
 *     context object for querySelector.
 * @return {!HTMLElement} the Element.
 */
function queryRequiredElement(selectors, opt_context) {
  const element = (opt_context || document).querySelector(selectors);
  return assertInstanceof(
      element, HTMLElement, 'Missing required element: ' + selectors);
}

// Handle click on a link. If the link points to a chrome: or file: url, then
// call into the browser to do the navigation.
['click', 'auxclick'].forEach(function(eventName) {
  document.addEventListener(eventName, function(e) {
    if (e.button > 1) {
      return;
    }  // Ignore buttons other than left and middle.
    if (e.defaultPrevented) {
      return;
    }

    const eventPath = e.path;
    let anchor = null;
    if (eventPath) {
      for (let i = 0; i < eventPath.length; i++) {
        const element = eventPath[i];
        if (element.tagName === 'A' && element.href) {
          anchor = element;
          break;
        }
      }
    }

    // Fallback if Event.path is not available.
    let el = e.target;
    if (!anchor && el.nodeType == Node.ELEMENT_NODE &&
        el.webkitMatchesSelector('A, A *')) {
      while (el.tagName != 'A') {
        el = el.parentElement;
      }
      anchor = el;
    }

    if (!anchor) {
      return;
    }

    anchor = /** @type {!HTMLAnchorElement} */ (anchor);
    if ((anchor.protocol == 'file:' || anchor.protocol == 'about:') &&
        (e.button == 0 || e.button == 1)) {
      chrome.send('navigateToUrl', [
        anchor.href, anchor.target, e.button, e.altKey, e.ctrlKey, e.metaKey,
        e.shiftKey
      ]);
      e.preventDefault();
    }
  });
});

/**
 * Creates a new URL which is the old URL with a GET param of key=value.
 * @param {string} url The base URL. There is not sanity checking on the URL so
 *     it must be passed in a proper format.
 * @param {string} key The key of the param.
 * @param {string} value The value of the param.
 * @return {string} The new URL.
 */
function appendParam(url, key, value) {
  const param = encodeURIComponent(key) + '=' + encodeURIComponent(value);

  if (url.indexOf('?') == -1) {
    return url + '?' + param;
  }
  return url + '&' + param;
}

/**
 * Creates an element of a specified type with a specified class name.
 * @param {string} type The node type.
 * @param {string} className The class name to use.
 * @return {Element} The created element.
 */
function createElementWithClassName(type, className) {
  const elm = document.createElement(type);
  elm.className = className;
  return elm;
}

/**
 * transitionend does not always fire (e.g. when animation is aborted
 * or when no paint happens during the animation). This function sets up
 * a timer and emulate the event if it is not fired when the timer expires.
 * @param {!HTMLElement} el The element to watch for transitionend.
 * @param {number=} opt_timeOut The maximum wait time in milliseconds for the
 *     transitionend to happen. If not specified, it is fetched from |el|
 *     using the transitionDuration style value.
 */
function ensureTransitionEndEvent(el, opt_timeOut) {
  if (opt_timeOut === undefined) {
    const style = getComputedStyle(el);
    opt_timeOut = parseFloat(style.transitionDuration) * 1000;

    // Give an additional 50ms buffer for the animation to complete.
    opt_timeOut += 50;
  }

  let fired = false;
  el.addEventListener('transitionend', function f(e) {
    el.removeEventListener('transitionend', f);
    fired = true;
  });
  window.setTimeout(function() {
    if (!fired) {
      cr.dispatchSimpleEvent(el, 'transitionend', true);
    }
  }, opt_timeOut);
}

/**
 * Alias for document.scrollTop getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The Y document scroll offset.
 */
function scrollTopForDocument(doc) {
  return doc.documentElement.scrollTop || doc.body.scrollTop;
}

/**
 * Alias for document.scrollTop setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target Y scroll offset.
 */
function setScrollTopForDocument(doc, value) {
  doc.documentElement.scrollTop = doc.body.scrollTop = value;
}

/**
 * Alias for document.scrollLeft getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The X document scroll offset.
 */
function scrollLeftForDocument(doc) {
  return doc.documentElement.scrollLeft || doc.body.scrollLeft;
}

/**
 * Alias for document.scrollLeft setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target X scroll offset.
 */
function setScrollLeftForDocument(doc, value) {
  doc.documentElement.scrollLeft = doc.body.scrollLeft = value;
}

/**
 * Replaces '&', '<', '>', '"', and ''' characters with their HTML encoding.
 * @param {string} original The original string.
 * @return {string} The string with all the characters mentioned above replaced.
 */
function HTMLEscape(original) {
  return original.replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
}

/**
 * Shortens the provided string (if necessary) to a string of length at most
 * |maxLength|.
 * @param {string} original The original string.
 * @param {number} maxLength The maximum length allowed for the string.
 * @return {string} The original string if its length does not exceed
 *     |maxLength|. Otherwise the first |maxLength| - 1 characters with '...'
 *     appended.
 */
function elide(original, maxLength) {
  if (original.length <= maxLength) {
    return original;
  }
  return original.substring(0, maxLength - 1) + '\u2026';
}

/**
 * Quote a string so it can be used in a regular expression.
 * @param {string} str The source string.
 * @return {string} The escaped string.
 */
function quoteString(str) {
  return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
}

/**
 * Calls |callback| and stops listening the first time any event in |eventNames|
 * is triggered on |target|.
 * @param {!EventTarget} target
 * @param {!Array<string>|string} eventNames Array or space-delimited string of
 *     event names to listen to (e.g. 'click mousedown').
 * @param {function(!Event)} callback Called at most once. The
 *     optional return value is passed on by the listener.
 */
function listenOnce(target, eventNames, callback) {
  if (!Array.isArray(eventNames)) {
    eventNames = eventNames.split(/ +/);
  }

  const removeAllAndCallCallback = function(event) {
    eventNames.forEach(function(eventName) {
      target.removeEventListener(eventName, removeAllAndCallCallback, false);
    });
    return callback(event);
  };

  eventNames.forEach(function(eventName) {
    target.addEventListener(eventName, removeAllAndCallCallback, false);
  });
}

//   /* is_ios */

/**
 * @param {!Event} e
 * @return {boolean} Whether a modifier key was down when processing |e|.
 */
function hasKeyModifiers(e) {
  return !!(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey);
}
</script>
  <script>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var CAPTIVEPORTAL_CMD_OPEN_LOGIN_PAGE = 'openLoginPage';
</script>
  <script>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

function setupSSLDebuggingInfo() {
  if (loadTimeData.getString('type') != 'SSL')
    return;

  // The titles are not internationalized because this is debugging information
  // for bug reports, help center posts, etc.
  appendDebuggingField('Subject', loadTimeData.getString('subject'));
  appendDebuggingField('Issuer', loadTimeData.getString('issuer'));
  appendDebuggingField('Expires on', loadTimeData.getString('expirationDate'));
  appendDebuggingField('Current date', loadTimeData.getString('currentDate'));
  appendDebuggingField('PEM encoded chain', loadTimeData.getString('pem'),
                       true);
  var ctInfo = loadTimeData.getString('ct');
  if (ctInfo) {
    appendDebuggingField('Certificate Transparency', ctInfo);
  }

  $('error-code').addEventListener('click', toggleDebuggingInfo);
}
</script>
  <script>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

// Other constants defined in security_interstitial_page.h.
var SB_BOX_CHECKED = 'boxchecked';
var SB_DISPLAY_CHECK_BOX = 'displaycheckbox';

// This sets up the Extended Safe Browsing Reporting opt-in, either for
// reporting malware or invalid certificate chains. Does nothing if the
// interstitial type is not SAFEBROWSING or SSL or CAPTIVE_PORTAL.
function setupExtendedReportingCheckbox() {
  var interstitialType = loadTimeData.getString('type');
  if (interstitialType != 'SAFEBROWSING' && interstitialType != 'SSL' &&
      interstitialType != 'CAPTIVE_PORTAL') {
    return;
  }

  if (!loadTimeData.getBoolean(SB_DISPLAY_CHECK_BOX)) {
    return;
  }

  $('opt-in-label').innerHTML = loadTimeData.getString('optInLink');
  $('opt-in-checkbox').checked = loadTimeData.getBoolean(SB_BOX_CHECKED);
  $('extended-reporting-opt-in').classList.remove('hidden');

  var billing = interstitialType == 'SAFEBROWSING' &&
                    loadTimeData.getBoolean('billing');

  var className = 'ssl-opt-in';
  if (interstitialType == 'SAFEBROWSING' && !billing) {
    className = 'safe-browsing-opt-in';
  }

  $('extended-reporting-opt-in').classList.add(className);

  $('body').classList.add('extended-reporting-has-checkbox');

  if ($('whitepaper-link')) {
    $('whitepaper-link').addEventListener('click', function(event) {
      sendCommand(SecurityInterstitialCommandId.CMD_OPEN_WHITEPAPER);
    });
  }

  $('opt-in-checkbox').addEventListener('click', function() {
    sendCommand($('opt-in-checkbox').checked ?
                SecurityInterstitialCommandId.CMD_DO_REPORT :
                SecurityInterstitialCommandId.CMD_DONT_REPORT);
  });
}
</script>
  <script>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var mobileNav = false;

/**
 * For small screen mobile the navigation buttons are moved
 * below the advanced text.
 */
function onResize() {
  var helpOuterBox = document.querySelector('#details');
  var mainContent = document.querySelector('#main-content');
  var mediaQuery = '(min-width: 240px) and (max-width: 420px) and ' +
      '(min-height: 401px), ' +
      '(max-height: 560px) and (min-height: 240px) and ' +
      '(min-width: 421px)';

  var detailsHidden = helpOuterBox.classList.contains(HIDDEN_CLASS);
  var runnerContainer = document.querySelector('.runner-container');

  // Check for change in nav status.
  if (mobileNav != window.matchMedia(mediaQuery).matches) {
    mobileNav = !mobileNav;

    // Handle showing the top content / details sections according to state.
    if (mobileNav) {
      mainContent.classList.toggle(HIDDEN_CLASS, !detailsHidden);
      helpOuterBox.classList.toggle(HIDDEN_CLASS, detailsHidden);
      if (runnerContainer) {
        runnerContainer.classList.toggle(HIDDEN_CLASS, !detailsHidden);
      }
    } else if (!detailsHidden) {
      // Non mobile nav with visible details.
      mainContent.classList.remove(HIDDEN_CLASS);
      helpOuterBox.classList.remove(HIDDEN_CLASS);
      if (runnerContainer) {
        runnerContainer.classList.remove(HIDDEN_CLASS);
      }
    }
  }
}

function setupMobileNav() {
  window.addEventListener('resize', onResize);
  onResize();
}

document.addEventListener('DOMContentLoaded', setupMobileNav);
</script>
  <script>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is the shared code for security interstitials. It is used for both SSL
// interstitials and Safe Browsing interstitials.

// Should match security_interstitials::SecurityInterstitialCommand
/** @enum| {string} */
var SecurityInterstitialCommandId = {
  CMD_DONT_PROCEED: 0,
  CMD_PROCEED: 1,
  // Ways for user to get more information
  CMD_SHOW_MORE_SECTION: 2,
  CMD_OPEN_HELP_CENTER: 3,
  CMD_OPEN_DIAGNOSTIC: 4,
  // Primary button actions
  CMD_RELOAD: 5,
  CMD_OPEN_DATE_SETTINGS: 6,
  CMD_OPEN_LOGIN: 7,
  // Safe Browsing Extended Reporting
  CMD_DO_REPORT: 8,
  CMD_DONT_REPORT: 9,
  CMD_OPEN_REPORTING_PRIVACY: 10,
  CMD_OPEN_WHITEPAPER: 11,
  // Report a phishing error.
  CMD_REPORT_PHISHING_ERROR: 12
};

var HIDDEN_CLASS = 'hidden';

/**
 * A convenience method for sending commands to the parent page.
 * @param {string} cmd  The command to send.
 */
function sendCommand(cmd) {
  if (window.certificateErrorPageController) {
    switch (cmd) {
      case SecurityInterstitialCommandId.CMD_DONT_PROCEED:
        certificateErrorPageController.dontProceed();
        break;
      case SecurityInterstitialCommandId.CMD_PROCEED:
        certificateErrorPageController.proceed();
        break;
      case SecurityInterstitialCommandId.CMD_SHOW_MORE_SECTION:
        certificateErrorPageController.showMoreSection();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_HELP_CENTER:
        certificateErrorPageController.openHelpCenter();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_DIAGNOSTIC:
        certificateErrorPageController.openDiagnostic();
        break;
      case SecurityInterstitialCommandId.CMD_RELOAD:
        certificateErrorPageController.reload();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_DATE_SETTINGS:
        certificateErrorPageController.openDateSettings();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_LOGIN:
        certificateErrorPageController.openLogin();
        break;
      case SecurityInterstitialCommandId.CMD_DO_REPORT:
        certificateErrorPageController.doReport();
        break;
      case SecurityInterstitialCommandId.CMD_DONT_REPORT:
        certificateErrorPageController.dontReport();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_REPORTING_PRIVACY:
        certificateErrorPageController.openReportingPrivacy();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_WHITEPAPER:
        certificateErrorPageController.openWhitepaper();
        break;
      case SecurityInterstitialCommandId.CMD_REPORT_PHISHING_ERROR:
        certificateErrorPageController.reportPhishingError();
        break;
    }
    return;
  }
// 
  window.domAutomationController.send(cmd);
// 
// 
}

/**
 * Call this to stop clicks on <a href="#"> links from scrolling to the top of
 * the page (and possibly showing a # in the link).
 */
function preventDefaultOnPoundLinkClicks() {
  document.addEventListener('click', function(e) {
    var anchor = findAncestor(/** @type {Node} */ (e.target), function(el) {
      return el.tagName == 'A';
    });
    // Use getAttribute() to prevent URL normalization.
    if (anchor && anchor.getAttribute('href') == '#')
      e.preventDefault();
  });
}
</script>
  <script>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is the shared code for the new (Chrome 37) security interstitials. It is
// used for both SSL interstitials and Safe Browsing interstitials.

var expandedDetails = false;
var keyPressState = 0;

/**
 * This allows errors to be skippped by typing a secret phrase into the page.
 * @param {string} e The key that was just pressed.
 */
function handleKeypress(e) {
  // HTTPS errors are serious and should not be ignored. For testing purposes,
  // other approaches are both safer and have fewer side-effects.
  // See https://goo.gl/ZcZixP for more details.
  var BYPASS_SEQUENCE = window.atob('dGhpc2lzdW5zYWZl');
  if (BYPASS_SEQUENCE.charCodeAt(keyPressState) == e.keyCode) {
    keyPressState++;
    if (keyPressState == BYPASS_SEQUENCE.length) {
      sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
      keyPressState = 0;
    }
  } else {
    keyPressState = 0;
  }
}

/**
 * This appends a piece of debugging information to the end of the warning.
 * When complete, the caller must also make the debugging div
 * (error-debugging-info) visible.
 * @param {string} title  The name of this debugging field.
 * @param {string} value  The value of the debugging field.
 * @param {boolean=} fixedWidth If true, the value field is displayed fixed
 *                              width.
 */
function appendDebuggingField(title, value, fixedWidth) {
  // The values input here are not trusted. Never use innerHTML on these
  // values!
  var spanTitle = document.createElement('span');
  spanTitle.classList.add('debugging-title');
  spanTitle.innerText = title + ': ';

  var spanValue = document.createElement('span');
  spanValue.classList.add('debugging-content');
  if (fixedWidth) {
    spanValue.classList.add('debugging-content-fixed-width');
  }
  spanValue.innerText = value;

  var pElem = document.createElement('p');
  pElem.classList.add('debugging-content');
  pElem.appendChild(spanTitle);
  pElem.appendChild(spanValue);
  $('error-debugging-info').appendChild(pElem);
}

function toggleDebuggingInfo() {
  $('error-debugging-info').classList.toggle(HIDDEN_CLASS);
}

function setupEvents() {
  var overridable = loadTimeData.getBoolean('overridable');
  var interstitialType = loadTimeData.getString('type');
  var ssl = interstitialType == 'SSL';
  var captivePortal = interstitialType == 'CAPTIVE_PORTAL';
  var badClock = ssl && loadTimeData.getBoolean('bad_clock');
  var billing = interstitialType == 'SAFEBROWSING' &&
                    loadTimeData.getBoolean('billing');
  var hidePrimaryButton = loadTimeData.getBoolean('hide_primary_button');
  var showRecurrentErrorParagraph = loadTimeData.getBoolean(
    'show_recurrent_error_paragraph');

  if (ssl) {
    $('body').classList.add(badClock ? 'bad-clock' : 'ssl');
    $('error-code').textContent = loadTimeData.getString('errorCode');
    $('error-code').classList.remove(HIDDEN_CLASS);
  } else if (captivePortal) {
    $('body').classList.add('captive-portal');
  } else if (billing) {
    $('body').classList.add('safe-browsing-billing');
  } else {
    $('body').classList.add('safe-browsing');
    // Override the default theme color.
    document.querySelector('meta[name=theme-color]').setAttribute('content',
      'rgb(206, 52, 38)');
  }

  $('icon').classList.add('icon');

  if (hidePrimaryButton) {
    $('primary-button').classList.add(HIDDEN_CLASS);
  } else {
    $('primary-button').addEventListener('click', function() {
      switch (interstitialType) {
        case 'CAPTIVE_PORTAL':
          sendCommand(SecurityInterstitialCommandId.CMD_OPEN_LOGIN);
          break;

        case 'SSL':
          if (badClock)
            sendCommand(SecurityInterstitialCommandId.CMD_OPEN_DATE_SETTINGS);
          else if (overridable)
            sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED);
          else
            sendCommand(SecurityInterstitialCommandId.CMD_RELOAD);
          break;

        case 'SAFEBROWSING':
          sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED);
          break;

        default:
          throw 'Invalid interstitial type';
      }
    });
  }

  if (overridable) {
    var overrideElement = billing ? 'proceed-button' : 'proceed-link';
    // Captive portal page isn't overridable.
    $(overrideElement).addEventListener('click', function(event) {
      sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
    });

    if (ssl) {
      $(overrideElement).classList.add('small-link');
    } else if (billing) {
      $(overrideElement).classList.remove(HIDDEN_CLASS);
      $(overrideElement).textContent =
          loadTimeData.getString('proceedButtonText');
    }
  } else if (!ssl) {
    $('final-paragraph').classList.add(HIDDEN_CLASS);
  }


  if (!ssl || !showRecurrentErrorParagraph) {
    $('recurrent-error-message').classList.add(HIDDEN_CLASS);
  } else {
    $('body').classList.add('showing-recurrent-error-message');
  }

  if ($('diagnostic-link')) {
    $('diagnostic-link').addEventListener('click', function(event) {
      sendCommand(SecurityInterstitialCommandId.CMD_OPEN_DIAGNOSTIC);
    });
  }

  if ($('learn-more-link')) {
    $('learn-more-link').addEventListener('click', function(event) {
      sendCommand(SecurityInterstitialCommandId.CMD_OPEN_HELP_CENTER);
    });
  }

  if (captivePortal || billing) {
    // Captive portal and billing pages don't have details button.
    $('details-button').classList.add('hidden');
  } else {
    $('details-button').addEventListener('click', function(event) {
      var hiddenDetails = $('details').classList.toggle(HIDDEN_CLASS);

      if (mobileNav) {
        // Details appear over the main content on small screens.
        $('main-content').classList.toggle(HIDDEN_CLASS, !hiddenDetails);
      } else {
        $('main-content').classList.remove(HIDDEN_CLASS);
      }

      $('details-button').innerText = hiddenDetails ?
          loadTimeData.getString('openDetails') :
          loadTimeData.getString('closeDetails');
      if (!expandedDetails) {
        // Record a histogram entry only the first time that details is opened.
        sendCommand(SecurityInterstitialCommandId.CMD_SHOW_MORE_SECTION);
        expandedDetails = true;
      }
    });
  }

  if ($('report-error-link')) {
    $('report-error-link').addEventListener('click', function(event) {
      sendCommand(SecurityInterstitialCommandId.CMD_REPORT_PHISHING_ERROR);
    });
  }

  preventDefaultOnPoundLinkClicks();
  setupExtendedReportingCheckbox();
  setupSSLDebuggingInfo();
  document.addEventListener('keypress', handleKeypress);
}

document.addEventListener('DOMContentLoaded', setupEvents);
</script>
</head>
<body id="body" >
  <div class="interstitial-wrapper">
    <div id="main-content">
      <div class="icon" id="icon"></div>
      <div id="main-message">
        <h1>$i18n{heading}</h1>
        <p>$i18nRaw{primaryParagraph}</p>
        <div id="debugging">
          <div id="error-code" class="error-code"></div>
          <div id="error-debugging-info" class="hidden"></div>
        </div>
      </div>
      <div id="recurrent-error-message">
        $i18nRaw{recurrentErrorParagraph}
      </div>
      <div id="extended-reporting-opt-in" class="hidden">
        <label>
          <div class="checkboxes">
            <input type="checkbox" id="opt-in-checkbox">
            <span class="checkbox"></span>
          </div>
          <span id="opt-in-label"></span>
        </label>
      </div>
    </div>
    <div class="nav-wrapper">
      <button id="primary-button">$i18n{primaryButtonText}</button>
      <button id="proceed-button" class="secondary-button small-link hidden"></button>
      <button id="details-button" class="secondary-button small-link">
        $i18n{openDetails}
      </button>
    </div>
    <div id="details" class="hidden">
      <p>$i18nRaw{explanationParagraph}</p>
      <p id="final-paragraph">$i18nRaw{finalParagraph}</p>
    </div>
  </div>
</body>
</html>
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
  <meta charset="utf-8">
  <meta name="viewport"
      content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>$i18n{tabTitle}</title>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

a {
  color: rgb(88, 88, 88);
}

body {
  --google-blue-600: rgb(26, 115, 232);
  --google-blue-700: rgb(25, 103, 210);
  --google-gray-50: rgb(248, 249, 250);
  --google-gray-300: rgb(218, 220, 224);
  --google-gray-500: rgb(154, 160, 166);
  --google-gray-600: rgb(128, 134, 139);
  --google-gray-700: rgb(95, 99, 104);
  background-color: #fff;
  color: var(--google-gray-700);
  word-wrap: break-word;
}

.nav-wrapper .secondary-button {
  background: #fff;
  border: 1px solid var(--google-gray-500);
  color: var(--google-gray-700);
  float: none;
  margin: 0;
  padding: 8px 16px;
}

.hidden {
  display: none;
}

html {
  -webkit-text-size-adjust: 100%;
  font-size: 125%;
}

.icon {
  background-repeat: no-repeat;
  background-size: 100%;
}
</style>
  <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  background-color: rgb(247, 247, 247);
  margin: 0;
}

#details {
  box-sizing: border-box;
  color: rgba(0, 0, 0, .54);
  font-family: Roboto-Regular, sans-serif;
  font-size: 0.93333em;
  height: auto;
  line-height: 1.48em;
  margin: 0;
  opacity: 1;
  transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
}

#details.hidden {
  display: block;
  height: 0;
  opacity: 0;
  overflow: hidden;
  padding-bottom: 0;
  transition: none;
}

#details-link {
  color: rgba(0, 0, 0, .38);
  text-decoration: underline;
  text-transform: none;
}

h1 {
  color: rgba(0, 0, 0, .38);
  font-family: Roboto-Regular, sans-serif;
  font-size: 0.93333em;
  font-weight: normal;
  line-height: 1.4em;
  margin: 8px 0 8px;
}

.giant .icon {
  bottom: 0;
  left: 0;
  margin: auto;
  position: fixed;
  right: 0;
  top: 0;
}

.giant #details,
.giant #main-message {
  display: none;
}

.icon {
  background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMjAgMTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgPGcgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMi4wMDAwMDAsIC00LjAwMDAwMCkiPgogICAgICA8Zz4KICAgICAgICAgIDxwb2x5Z29uIHBvaW50cz0iMCAwIDI0IDAgMjQgMjQgMCAyNCI+PC9wb2x5Z29uPgogICAgICAgICAgPHBhdGggZD0iTTIwLDQgQzIxLDQgMjIsNSAyMiw2IEwyMiwxOCBDMjIsMTkgMjEsMjAgMjAsMjAgTDQsMjAgQzIuOSwyMCAyLDE5LjEgMiwxOCBMMiw2IEMyLDUgMyw0IDQsNCBMMjAsNCBaIE0xNC4zOTIzMDMzLDE1LjQ1OTgyNzggTDE1LjQ5NDk3NDIsMTQuMzU4MTA2MiBMMTMuMTIwNzYzOSwxMS45ODU5Mzk3IEwxNS41LDkuNjA3NzQ3NDkgTDE0LjM5NzMyOTEsOC41MDYwMjU4MiBMMTIuMDE3MDg3OSwxMC44ODQyMTgxIEw5LjYzMTgyMDc5LDguNSBMOC41MjkxNDk5MSw5LjYwMTcyMTY2IEwxMC45MTU0MjIyLDExLjk4NTkzOTcgTDguNSwxNC4zOTgyNzgzIEw5LjYwMjY3MDg4LDE1LjUgTDEyLjAxNzA4NzksMTMuMDg2NjU3MSBMMTQuMzkyMzAzMywxNS40NTk4Mjc4IFoiIGZpbGwtb3BhY2l0eT0iMC4yIiBmaWxsPSIjMDAwMDAwIj48L3BhdGg+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPg==);
  background-position: center;
  height: 20vh;
  margin: 0 auto;
  max-height: 48px;
  max-width: 48px;
  min-height: 18px;
  min-width: 18px;
  opacity: .54;
  width: 20vh;
}

.interstitial-wrapper {
  align-items: center;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  height: 100vh;
  justify-content: center;
  line-height: 1.6em;
  margin: 0 auto;
  max-width: 480px;
  padding: 16px;
  width: 100%;
}

#main-content {
  align-self: auto;
  flex: 0 1 auto;
  text-align: center;
}

@media (max-height:2em), (max-width:2em) {
  .icon {
    display: none;
  }
}

@media (min-height:25em) and (min-width:37.5em),
       (min-height:37.5em) and (min-width:25em) {
  .interstitial-wrapper {
    padding: 48px;
  }
}

/* Views that don't fit the details text. */
@media (max-height:11.25em) and (max-width:18.75em),
       (max-height:18.75em) and (max-width:11.25em),
       (max-height:5em), (max-width:5em) {
  .icon {
    max-height: 24px;
    max-width: 24px;
  }

  #details,
  #main-message {
    display: none;
  }
}
</style>
  <script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Assertion support.
 */

/**
 * Verify |condition| is truthy and return |condition| if so.
 * @template T
 * @param {T} condition A condition to check for truthiness.  Note that this
 *     may be used to test whether a value is defined or not, and we don't want
 *     to force a cast to Boolean.
 * @param {string=} opt_message A message to show on failure.
 * @return {T} A non-null |condition|.
 */
function assert(condition, opt_message) {
  if (!condition) {
    let message = 'Assertion failed';
    if (opt_message) {
      message = message + ': ' + opt_message;
    }
    const error = new Error(message);
    const global = function() {
      /** @type {boolean} */
      this.traceAssertionsForTesting;
      return this;
    }();
    if (global.traceAssertionsForTesting) {
      console.warn(error.stack);
    }
    throw error;
  }
  return condition;
}

/**
 * Call this from places in the code that should never be reached.
 *
 * For example, handling all the values of enum with a switch() like this:
 *
 *   function getValueFromEnum(enum) {
 *     switch (enum) {
 *       case ENUM_FIRST_OF_TWO:
 *         return first
 *       case ENUM_LAST_OF_TWO:
 *         return last;
 *     }
 *     assertNotReached();
 *     return document;
 *   }
 *
 * This code should only be hit in the case of serious programmer error or
 * unexpected input.
 *
 * @param {string=} opt_message A message to show when this is hit.
 */
function assertNotReached(opt_message) {
  assert(false, opt_message || 'Unreachable code hit');
}

/**
 * @param {*} value The value to check.
 * @param {function(new: T, ...)} type A user-defined constructor.
 * @param {string=} opt_message A message to show when this is hit.
 * @return {T}
 * @template T
 */
function assertInstanceof(value, type, opt_message) {
  // We don't use assert immediately here so that we avoid constructing an error
  // message if we don't have to.
  if (!(value instanceof type)) {
    assertNotReached(
        opt_message ||
        'Value ' + value + ' is not a[n] ' + (type.name || typeof type));
  }
  return value;
}


/**
 * Alias for document.getElementById. Found elements must be HTMLElements.
 * @param {string} id The ID of the element to find.
 * @return {HTMLElement} The found element or null if not found.
 */
function $(id) {
  // Disable getElementById restriction here, since we are instructing other
  // places to re-use the $() that is defined here.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, HTMLElement) : null;
}

// TODO(devlin): This should return SVGElement, but closure compiler is missing
// those externs.
/**
 * Alias for document.getElementById. Found elements must be SVGElements.
 * @param {string} id The ID of the element to find.
 * @return {Element} The found element or null if not found.
 */
function getSVGElement(id) {
  // Disable getElementById restriction here, since it is not suitable for SVG
  // elements.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, Element) : null;
}

/**
 * @return {?Element} The currently focused element (including elements that are
 *     behind a shadow root), or null if nothing is focused.
 */
function getDeepActiveElement() {
  let a = document.activeElement;
  while (a && a.shadowRoot && a.shadowRoot.activeElement) {
    a = a.shadowRoot.activeElement;
  }
  return a;
}

/**
 * Add an accessible message to the page that will be announced to
 * users who have spoken feedback on, but will be invisible to all
 * other users. It's removed right away so it doesn't clutter the DOM.
 * @param {string} msg The text to be pronounced.
 */
function announceAccessibleMessage(msg) {
  const element = document.createElement('div');
  element.setAttribute('aria-live', 'polite');
  element.style.position = 'fixed';
  element.style.left = '-9999px';
  element.style.height = '0px';
  element.innerText = msg;
  document.body.appendChild(element);
  window.setTimeout(function() {
    document.body.removeChild(element);
  }, 0);
}

/**
 * Generates a CSS url string.
 * @param {string} s The URL to generate the CSS url for.
 * @return {string} The CSS url string.
 */
function getUrlForCss(s) {
  // http://www.w3.org/TR/css3-values/#uris
  // Parentheses, commas, whitespace characters, single quotes (') and double
  // quotes (") appearing in a URI must be escaped with a backslash
  let s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
  // WebKit has a bug when it comes to URLs that end with \
  // https://bugs.webkit.org/show_bug.cgi?id=28885
  if (/\\\\$/.test(s2)) {
    // Add a space to work around the WebKit bug.
    s2 += ' ';
  }
  return 'url("' + s2 + '")';
}

/**
 * Parses query parameters from Location.
 * @param {Location} location The URL to generate the CSS url for.
 * @return {Object} Dictionary containing name value pairs for URL
 */
function parseQueryParams(location) {
  const params = {};
  const query = unescape(location.search.substring(1));
  const vars = query.split('&');
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split('=');
    params[pair[0]] = pair[1];
  }
  return params;
}

/**
 * Creates a new URL by appending or replacing the given query key and value.
 * Not supporting URL with username and password.
 * @param {Location} location The original URL.
 * @param {string} key The query parameter name.
 * @param {string} value The query parameter value.
 * @return {string} The constructed new URL.
 */
function setQueryParam(location, key, value) {
  const query = parseQueryParams(location);
  query[encodeURIComponent(key)] = encodeURIComponent(value);

  let newQuery = '';
  for (const q in query) {
    newQuery += (newQuery ? '&' : '?') + q + '=' + query[q];
  }

  return location.origin + location.pathname + newQuery + location.hash;
}

/**
 * @param {Node} el A node to search for ancestors with |className|.
 * @param {string} className A class to search for.
 * @return {Element} A node with class of |className| or null if none is found.
 */
function findAncestorByClass(el, className) {
  return /** @type {Element} */ (findAncestor(el, function(el) {
    return el.classList && el.classList.contains(className);
  }));
}

/**
 * Return the first ancestor for which the {@code predicate} returns true.
 * @param {Node} node The node to check.
 * @param {function(Node):boolean} predicate The function that tests the
 *     nodes.
 * @return {Node} The found ancestor or null if not found.
 */
function findAncestor(node, predicate) {
  let last = false;
  while (node != null && !(last = predicate(node))) {
    node = node.parentNode;
  }
  return last ? node : null;
}

function swapDomNodes(a, b) {
  const afterA = a.nextSibling;
  if (afterA == b) {
    swapDomNodes(b, a);
    return;
  }
  const aParent = a.parentNode;
  b.parentNode.replaceChild(a, b);
  aParent.insertBefore(b, afterA);
}

/**
 * Disables text selection and dragging, with optional whitelist callbacks.
 * @param {function(Event):boolean=} opt_allowSelectStart Unless this function
 *    is defined and returns true, the onselectionstart event will be
 *    surpressed.
 * @param {function(Event):boolean=} opt_allowDragStart Unless this function
 *    is defined and returns true, the ondragstart event will be surpressed.
 */
function disableTextSelectAndDrag(opt_allowSelectStart, opt_allowDragStart) {
  // Disable text selection.
  document.onselectstart = function(e) {
    if (!(opt_allowSelectStart && opt_allowSelectStart.call(this, e))) {
      e.preventDefault();
    }
  };

  // Disable dragging.
  document.ondragstart = function(e) {
    if (!(opt_allowDragStart && opt_allowDragStart.call(this, e))) {
      e.preventDefault();
    }
  };
}

/**
 * Check the directionality of the page.
 * @return {boolean} True if Chrome is running an RTL UI.
 */
function isRTL() {
  return document.documentElement.dir == 'rtl';
}

/**
 * Get an element that's known to exist by its ID. We use this instead of just
 * calling getElementById and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} id The identifier name.
 * @return {!HTMLElement} the Element.
 */
function getRequiredElement(id) {
  return assertInstanceof(
      $(id), HTMLElement, 'Missing required element: ' + id);
}

/**
 * Query an element that's known to exist by a selector. We use this instead of
 * just calling querySelector and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} selectors CSS selectors to query the element.
 * @param {(!Document|!DocumentFragment|!Element)=} opt_context An optional
 *     context object for querySelector.
 * @return {!HTMLElement} the Element.
 */
function queryRequiredElement(selectors, opt_context) {
  const element = (opt_context || document).querySelector(selectors);
  return assertInstanceof(
      element, HTMLElement, 'Missing required element: ' + selectors);
}

// Handle click on a link. If the link points to a chrome: or file: url, then
// call into the browser to do the navigation.
['click', 'auxclick'].forEach(function(eventName) {
  document.addEventListener(eventName, function(e) {
    if (e.button > 1) {
      return;
    }  // Ignore buttons other than left and middle.
    if (e.defaultPrevented) {
      return;
    }

    const eventPath = e.path;
    let anchor = null;
    if (eventPath) {
      for (let i = 0; i < eventPath.length; i++) {
        const element = eventPath[i];
        if (element.tagName === 'A' && element.href) {
          anchor = element;
          break;
        }
      }
    }

    // Fallback if Event.path is not available.
    let el = e.target;
    if (!anchor && el.nodeType == Node.ELEMENT_NODE &&
        el.webkitMatchesSelector('A, A *')) {
      while (el.tagName != 'A') {
        el = el.parentElement;
      }
      anchor = el;
    }

    if (!anchor) {
      return;
    }

    anchor = /** @type {!HTMLAnchorElement} */ (anchor);
    if ((anchor.protocol == 'file:' || anchor.protocol == 'about:') &&
        (e.button == 0 || e.button == 1)) {
      chrome.send('navigateToUrl', [
        anchor.href, anchor.target, e.button, e.altKey, e.ctrlKey, e.metaKey,
        e.shiftKey
      ]);
      e.preventDefault();
    }
  });
});

/**
 * Creates a new URL which is the old URL with a GET param of key=value.
 * @param {string} url The base URL. There is not sanity checking on the URL so
 *     it must be passed in a proper format.
 * @param {string} key The key of the param.
 * @param {string} value The value of the param.
 * @return {string} The new URL.
 */
function appendParam(url, key, value) {
  const param = encodeURIComponent(key) + '=' + encodeURIComponent(value);

  if (url.indexOf('?') == -1) {
    return url + '?' + param;
  }
  return url + '&' + param;
}

/**
 * Creates an element of a specified type with a specified class name.
 * @param {string} type The node type.
 * @param {string} className The class name to use.
 * @return {Element} The created element.
 */
function createElementWithClassName(type, className) {
  const elm = document.createElement(type);
  elm.className = className;
  return elm;
}

/**
 * transitionend does not always fire (e.g. when animation is aborted
 * or when no paint happens during the animation). This function sets up
 * a timer and emulate the event if it is not fired when the timer expires.
 * @param {!HTMLElement} el The element to watch for transitionend.
 * @param {number=} opt_timeOut The maximum wait time in milliseconds for the
 *     transitionend to happen. If not specified, it is fetched from |el|
 *     using the transitionDuration style value.
 */
function ensureTransitionEndEvent(el, opt_timeOut) {
  if (opt_timeOut === undefined) {
    const style = getComputedStyle(el);
    opt_timeOut = parseFloat(style.transitionDuration) * 1000;

    // Give an additional 50ms buffer for the animation to complete.
    opt_timeOut += 50;
  }

  let fired = false;
  el.addEventListener('transitionend', function f(e) {
    el.removeEventListener('transitionend', f);
    fired = true;
  });
  window.setTimeout(function() {
    if (!fired) {
      cr.dispatchSimpleEvent(el, 'transitionend', true);
    }
  }, opt_timeOut);
}

/**
 * Alias for document.scrollTop getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The Y document scroll offset.
 */
function scrollTopForDocument(doc) {
  return doc.documentElement.scrollTop || doc.body.scrollTop;
}

/**
 * Alias for document.scrollTop setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target Y scroll offset.
 */
function setScrollTopForDocument(doc, value) {
  doc.documentElement.scrollTop = doc.body.scrollTop = value;
}

/**
 * Alias for document.scrollLeft getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The X document scroll offset.
 */
function scrollLeftForDocument(doc) {
  return doc.documentElement.scrollLeft || doc.body.scrollLeft;
}

/**
 * Alias for document.scrollLeft setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target X scroll offset.
 */
function setScrollLeftForDocument(doc, value) {
  doc.documentElement.scrollLeft = doc.body.scrollLeft = value;
}

/**
 * Replaces '&', '<', '>', '"', and ''' characters with their HTML encoding.
 * @param {string} original The original string.
 * @return {string} The string with all the characters mentioned above replaced.
 */
function HTMLEscape(original) {
  return original.replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
}

/**
 * Shortens the provided string (if necessary) to a string of length at most
 * |maxLength|.
 * @param {string} original The original string.
 * @param {number} maxLength The maximum length allowed for the string.
 * @return {string} The original string if its length does not exceed
 *     |maxLength|. Otherwise the first |maxLength| - 1 characters with '...'
 *     appended.
 */
function elide(original, maxLength) {
  if (original.length <= maxLength) {
    return original;
  }
  return original.substring(0, maxLength - 1) + '\u2026';
}

/**
 * Quote a string so it can be used in a regular expression.
 * @param {string} str The source string.
 * @return {string} The escaped string.
 */
function quoteString(str) {
  return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
}

/**
 * Calls |callback| and stops listening the first time any event in |eventNames|
 * is triggered on |target|.
 * @param {!EventTarget} target
 * @param {!Array<string>|string} eventNames Array or space-delimited string of
 *     event names to listen to (e.g. 'click mousedown').
 * @param {function(!Event)} callback Called at most once. The
 *     optional return value is passed on by the listener.
 */
function listenOnce(target, eventNames, callback) {
  if (!Array.isArray(eventNames)) {
    eventNames = eventNames.split(/ +/);
  }

  const removeAllAndCallCallback = function(event) {
    eventNames.forEach(function(eventName) {
      target.removeEventListener(eventName, removeAllAndCallCallback, false);
    });
    return callback(event);
  };

  eventNames.forEach(function(eventName) {
    target.addEventListener(eventName, removeAllAndCallCallback, false);
  });
}

//   /* is_ios */

/**
 * @param {!Event} e
 * @return {boolean} Whether a modifier key was down when processing |e|.
 */
function hasKeyModifiers(e) {
  return !!(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey);
}
</script>
  <script>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is the shared code for security interstitials. It is used for both SSL
// interstitials and Safe Browsing interstitials.

// Should match security_interstitials::SecurityInterstitialCommand
/** @enum| {string} */
var SecurityInterstitialCommandId = {
  CMD_DONT_PROCEED: 0,
  CMD_PROCEED: 1,
  // Ways for user to get more information
  CMD_SHOW_MORE_SECTION: 2,
  CMD_OPEN_HELP_CENTER: 3,
  CMD_OPEN_DIAGNOSTIC: 4,
  // Primary button actions
  CMD_RELOAD: 5,
  CMD_OPEN_DATE_SETTINGS: 6,
  CMD_OPEN_LOGIN: 7,
  // Safe Browsing Extended Reporting
  CMD_DO_REPORT: 8,
  CMD_DONT_REPORT: 9,
  CMD_OPEN_REPORTING_PRIVACY: 10,
  CMD_OPEN_WHITEPAPER: 11,
  // Report a phishing error.
  CMD_REPORT_PHISHING_ERROR: 12
};

var HIDDEN_CLASS = 'hidden';

/**
 * A convenience method for sending commands to the parent page.
 * @param {string} cmd  The command to send.
 */
function sendCommand(cmd) {
  if (window.certificateErrorPageController) {
    switch (cmd) {
      case SecurityInterstitialCommandId.CMD_DONT_PROCEED:
        certificateErrorPageController.dontProceed();
        break;
      case SecurityInterstitialCommandId.CMD_PROCEED:
        certificateErrorPageController.proceed();
        break;
      case SecurityInterstitialCommandId.CMD_SHOW_MORE_SECTION:
        certificateErrorPageController.showMoreSection();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_HELP_CENTER:
        certificateErrorPageController.openHelpCenter();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_DIAGNOSTIC:
        certificateErrorPageController.openDiagnostic();
        break;
      case SecurityInterstitialCommandId.CMD_RELOAD:
        certificateErrorPageController.reload();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_DATE_SETTINGS:
        certificateErrorPageController.openDateSettings();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_LOGIN:
        certificateErrorPageController.openLogin();
        break;
      case SecurityInterstitialCommandId.CMD_DO_REPORT:
        certificateErrorPageController.doReport();
        break;
      case SecurityInterstitialCommandId.CMD_DONT_REPORT:
        certificateErrorPageController.dontReport();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_REPORTING_PRIVACY:
        certificateErrorPageController.openReportingPrivacy();
        break;
      case SecurityInterstitialCommandId.CMD_OPEN_WHITEPAPER:
        certificateErrorPageController.openWhitepaper();
        break;
      case SecurityInterstitialCommandId.CMD_REPORT_PHISHING_ERROR:
        certificateErrorPageController.reportPhishingError();
        break;
    }
    return;
  }
// 
  window.domAutomationController.send(cmd);
// 
// 
}

/**
 * Call this to stop clicks on <a href="#"> links from scrolling to the top of
 * the page (and possibly showing a # in the link).
 */
function preventDefaultOnPoundLinkClicks() {
  document.addEventListener('click', function(e) {
    var anchor = findAncestor(/** @type {Node} */ (e.target), function(el) {
      return el.tagName == 'A';
    });
    // Use getAttribute() to prevent URL normalization.
    if (anchor && anchor.getAttribute('href') == '#')
      e.preventDefault();
  });
}
</script>
  <script>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Restores the interstitial content to the initial state if the window size
 * switches to a small view.
 */
function onResize() {
  var mediaQuery = '(max-height:11.25em) and (max-width:18.75em),' +
       '(max-height:18.75em) and (max-width:11.25em),' +
       '(max-height:5em), (max-width:5em)';

  // Check for change in window size.
  if (window.matchMedia(mediaQuery).matches) {
    var hiddenDetails = $('details').classList.add(HIDDEN_CLASS);
    $('main-content').classList.remove(HIDDEN_CLASS);
  }
}

function initPage() {
  var isGiantWebView = loadTimeData.getBoolean('is_giant');
  document.body.className = isGiantWebView ? 'giant' : '';
  preventDefaultOnPoundLinkClicks();

  $('details-link').addEventListener('click', function(event) {
    var hiddenDetails = $('details').classList.toggle(HIDDEN_CLASS);
    $('main-content').classList.toggle(HIDDEN_CLASS, !hiddenDetails);
  });

  $('proceed-link').addEventListener('click', function(event) {
    sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
  });

  window.addEventListener('resize', onResize);
}

document.addEventListener('DOMContentLoaded', initPage);
</script>
</head>
<body id="body">
  <div class="interstitial-wrapper">
    <div id="main-content">
      <div class="icon"></div>
      <div id="main-message">
        <h1>
          <span>$i18n{heading}</span>
          <a href="#" id="details-link">$i18n{openDetails}</a>
        </h1>
      </div>
    </div>
    <div id="details" class="hidden">
      <p>
        $i18nRaw{explanationParagraph}
      </p>
    </div>
  </div>
</body>
</html>
     ŖMO@UK'Tٹ *J.=EkwUIp[B*~3Yw_ϧo.xdt{<9?	 	]QexHHƝT:k;r쬲Stj$"YQ
y@K)8#<FB'A
ɇB\%$$^gh":-5Sy,|LSU^BHeis虂4c^'W5:Á8oYaAz,)
^OYt8턚)A~)2G#X,kvrA"Z?(KkMdw,Xk[7Q?~^ff=z[9K8ک6<*qak햧og׎n<.Aw_{-"TyjϠXPR`~Wռ2TMl?avW9;$6Z'͍d]d\G*SwT;.v-z0+g_9NñodV*WY<$sTjXܫ ÄVtVzl<q@F7ƣ_^AM 	       uQn0+,P0!@Kc%JmJIfvv8\nVp]}{<ų1beewrue(>dd,;;~'I`Nxz}^r,x]`u٩194/×jSU~kBZv?TU5ƚNNߥK^a;g~΅)4=haƩ']|o3eߞ#Q-GE{mp=.jIDogBDsg3.t,kC"֑e%Tp5_Et-4qHQ(?2ukޏ'#H       Qk@)+ai&}b=4|B.[ii !XO:I1Li&/>}ni4U	!<c@Ech\ *!dgN[5*-5:	B1d
k5UNqr\L7b2ll69]N@TErr|C<_803zO~EDi<4ѡLs8JXj0R$gÌ{x}O3Z\AbKJߚgU#_YTfqv!|מٽ gVP&KɸIG/ph;Y+z7-[[pV@&HT*GLhE"xO˶py.9$wJ\FGË	wS;ŕǉk<կq6ƣ~Φi6Z9>.Yk#1ܭ}wD#soE/˥6k7ŋB]"*enN)ș(ˍw@       U1K1!;94"b q%q2MCLl,d&@qI?]ݸ=sdTiq<IXLId`(&kL3`oV$R[AFJ_-e0)yǚ_w	Cp*B3KkrqbO-svq
,3;/J{8w7᫰FUe'x{ÓU%5.ź?7٠       Xr6}Wl٤3ݹT4qq'C@J* )U2. RS${سퟸb؉Н艨NX#V>Q>glSDƻ%-8aڠD3;,Z0:Dq[ժFf:FS3XWLmWZ3+CboYv TeZ)j|HǠQv"cMh#H4m:9LZSwN[}jbX8Q7:Aphb6M68!9J	A&@Xbq)0X we,HcJj6ab PR"qW.a($VyTJLTz48zuz	43Ԗ-jOЄwUJR3jVo"rKX<ig^mhƋtQ+.bQ{o'tj@IeY-	٦)d8+\dyx@x&>	n|eUUc'9Vj,pj=llN9)XJmR!؅_{M+|s&C&h !JAjOO']Bdӿ^ǀn5]^<Ȅf&X}\,pϴiAӜJd}k}RTx4p.r>+(HwFEC	==P|᫤KX;VY{OŒC84AI4N!

BT0%+DWRgv-0NL,zMswf	#BgB]F8'vW&p[r	lGdMGDkLo/@hwEm$tn|^1לMYih	U$#t:K:0ӳu%zK,P)>7yT}-yPQ(Թ\9xqu5\V##C?(l> 
36Y@ݏ/(jf\w<Q	b{3<]477xnU^m6P=μ5mɕ;<྿C+$^wֈ$ʉi=s]w	}̻
s"L0zW4E!.*lfΨȲ{G 3blb,gE(GQpŋH{[ِNmBSFB`f҇Smjչ~f>wo`?sZ9b"f%
>tq hp=dZPtDS4o^!r{[_<An'χ~[þoX}:5Z|;kc5
_l`]83R       X[o8~:r;dvn͠mMf!0
Z-62%n}CR`-&Cfl±$_7ްؔ]%ayy:دV0bY]LLqQ"g_oNە2
le\ I+]Is^/^,E:=r2I?`_gŋ{n̚+EXakQQ(	%^A;E"ɗ:;rB/?̱[4%̅K:SgNOOzi8UiTX<7&ZeNjL}w&yrWLNQAfdNh%(LGbK~$0kLXK ^]d>ܼoH
InIFƸsF.keeT)_ִz5/Z<!2'c@:i<JN&g">CIsc{AcvǋX]`s-(	ĠXfwPBƹzRFaDYd4O(9T6gN 1
*pYR)/,yz&	Rl )$qˣ@I[|B''/U>z;85bh{E1Pg*))쑒*K'E,F;(;E)TL$*~0-Z^x>\ܿZ=~p+ j?sX0Fa)F[^?z=b؁zXi6i1رDyRȴ@(38O)PCt@FϞR{sx{pzct+7@D1vcM-N0eīpMOB~}mZr@0!Z-9y9ie4>wm0UV-:~ jҷsMy;V(cߊPӒun^:b	E"uƼjT%>53Hl2IL;"~F< ~^\?]o陽Ycыc<WDPC[KhlMᦑ7<vqS<yBХ:j*%m__X @"s50	<{ gڸ<p: VMFwoJ^q30!n֔c`R'EMkuf׆0)rG`\VDt$Q%YǱ	.MAMPK["Z ;=%HO򎰗q,x`Bbml׵ޓFsy+f|V͵ZfrMWsrJ ~x=bo_>鎮 3+֨cdŷ#UlJq'!q_.Vߌ7[ޚo875W_{߆?7@Ӗ6Nؑ1rڵ͆a;t]x+fR9Yp[т:_y7	H+]%08:roVI4o}k}&_]_ sAw&2tzb?dB,+DnkiZ
CJa6|v$罨Bbv8ʽRnwJ vP꾦C.97&t!ZxH˟=lCݴ0bHC(pcD4ī;A.(UcNsMPlו%tg_ Xa]=gy[:jru	]b/a\'qHHJNh~nwǸ+r\cɄo]rRW96I6xRG@0X=r܂%*$_՚%vp #mU "`?ܤ-JU˓&,G֐5CGcIuVܼ\ߋ#~B(?:EI  <!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<meta name="viewport"
    content="initial-scale=1, minimum-scale=1, width=device-width">
<title>$i18n{blockPageTitle}</title>
<style>/* Copyright 2014 The Chromium Authors. All rights reserved.
   Use of this source code is governed by a BSD-style license that can be
   found in the LICENSE file. */

body {
  background-color: #f7f7f7;
  color: #646464;
}

a {
  color: #585858;
}

button {
  border: 0;
  border-radius: 2px;
  box-sizing: border-box;
  color: #fff;
  cursor: pointer;
  float: right;
  font-family: Roboto;
  font-size: 14px;
  font-weight: 500;
  margin: 0;
  padding: 10px 24px;
  transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

[dir='rtl'] button {
  float: left;
}

.primary-button {
  background: rgb(66, 133, 244);
}

.primary-button:active {
  background: rgb(50, 102, 213);
  outline: 0;
}

button:hover {
  box-shadow: 0 1px 3px rgba(0, 0, 0, .50);
}

#details {
  color: #696969;
  margin: 45px 0 50px;
}

#details p:not(:first-of-type) {
  margin-top: 20px;
}

#details-header {
  font-weight: bold;
}

#details-button-container {
  box-shadow: inherit;
}

.details-button {
  background: inherit;
  border: 0;
  float: none;
  margin: 0;
  padding: 10px 0;
  text-transform: uppercase;
}

.details-button:hover {
  box-shadow: inherit;
  text-decoration: underline;
}

h1 {
  color: #333;
  font-size: 1.6em;
  font-weight: normal;
  line-height: 1.25em;
  margin-bottom: 16px;
}

h2 {
  font-size: 1.2em;
  font-weight: normal;
}

html {
  -webkit-text-size-adjust: 100%;
  font-size: 125%;
}

.icon {
  background-repeat: no-repeat;
  background-size: 100%;
  height: 72px;
  margin: 0 0 40px;
  width: 72px;
}

.main-frame-blocked {
  box-sizing: border-box;
  font-size: 1em;
  line-height: 1.6em;
  margin: 100px auto 0;
  max-width: 600px;
  width: 100%;
}

#main-message > p:not([hidden]) {
  display: inline;
}

.button-container {
  margin-top: 51px;
}

.button-container::after {
  clear: both;
  content: '';
  display: table;
  width: 100%;
}

.small-link {
  color: rgba(66, 133, 244, 100);
  font-family: Roboto;
  font-size: 15px;
  font-weight: 500;
}

.avatar-img {
  border: 3px solid rgb(251, 251, 251);
  border-radius: 50%;
  content: -webkit-image-set(
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAFwklEQVR4XuVb208cVRgftYm+eYkv3hofjMY3fdPEGB/8E4wmJkoL0pLWWIha8GnbIixFWrvEitxauRQpsLDLZUHALnR3Z8ultaa4zOyKxoTEB6NpKrNnZ84wx/Ptw6SlLOzlnNmZcJJfstmZPXN+33znfNcVeA5CyAOhNbI/KunviTJ2i7LuE+P6zbCs/SVKGgpL2iYAPsN3cA3uicRxvZjQ311MGM8JDhtA+sGIrL1JSTSLcbxGSZGCIOHf6DyeqKS9AXPblri4YjwRies1lPjvmciwEAZ9RnXoT/K4bYgvS+RJSrqRqrICBKxAOK5tiDJuAKEXjXgwSPbRt3GMEr8NBIoCWftXlPWPBwh5yFLyUdl4mRJYoiB2AH0R18KrxkuWkKcPK4VTGwjYCektKOslXFVelPF5IGBngPVhviWCf5BHREkfAwJOAPgSsGZm5COSPm0ScI4QpmDtBau9+eadiZGCtoO5550MGZ/Lj3xcLzMJOByRhP5Bznaer6mz3kQuxIwXs9/3/J0c6yHp0azMI7i3PAkEf8Wk66pGzoyr5NRwCpD+3B3SyBy9xtljPLJrYMPLt59dwcQ9qpIDrUnyYcv2OEivNdB7rqxgXkHUPztGkhDV8SB/OaqR8nYEJLPC4Q5EBq5hXp5iXcZ4nkdI2xfRyIHvgFhugN/0iRoHIWj/UQfpse32fg1r8oGbmJSZKp87ytqSJPAL5uElfn5fGotHJqemHwGRgvBFP+JgFnHinvQa5PBYkx9ewkCACXxLmL0QEtrrdx9+zawfcHpUZSaAxjGVvUmU8VkzdW1mbxmisgcxE0BVD+JgEbAkwIC8PQ9zU9rGgrx5GPLxC1aNpwUoWvCYvCSj6cvLJPLyCd6BkNfNY/JDHey2wKFOxMk9xrUCpI94TF79AzsB1FxGvGIDrwD1OB6TfzPNzgp8O63yihBvCFCU5DH5zC1MDjI4ByBAmuUXHK0LPBMfZyYK14KzkyrPRElSgPI0rweEJB1seN7kP+1FdJFcM0WbXAUAmKVb4ZOu3IVQ2Y1M1ecqACtyf5DpOTmcypo8ZInmYtiSXKF5CFoB7yImrqEUHGz3kQbP8QS95s0Q+PA6BE0zaCVgX/uXMSQ80vBfx+nvirCO66YjtCch6UMQCtfvRfKmKwzdWHuRvBkMQSvaXhXAfMx4SoAB3VeWSFzWyfQtnE5x9Ysa6Qmlkf48sozT7nPEMguAY3cVQrGHOVmK8Z8xab+iknpfilT1IjB/Wfn+cG+dP0XagyqZuMHLLOImUwDQhMjqDUMRxE0XX3GBXThc0YnonCoZiGJ4Bhs3Pa69dk9aHPKChbi7nikVFgoEuAIE2/yjSn4qwE0OyzgOudCthZHqnF3cGIaIz1RtKwGeI0SK86t5aepnwtYBRUPowMySPKijqebFxJGLiAwu5KIN2p3lNfJoppaYhizIw8FmJj3tAFhL55yatfOzY8MztJ/uRL47rJESIGAzwJouRbRdLJP2t1kYzQTovd2puaHczPbaD1BWn4vtWBQ9LOw2oI0kHNcXMqg+ELAxMm8Fyimc9f8NoPEY8mVbJgH7bncBQE1y254AMWG8kGOPoF6ydSKX1/4COOVNbacB7+fZGY6bHS8AcHnzHXAeQMLEsQKQ9UHY94V3isv6lMMEAMFYIBA3HmbWMQ6Nx04RALx5JuS3bgdqBa7aXQANfiXI9T9Ebl/qfFnrhmE34rCm0/6kR7BiNE/ityt7lDt2IV/Vm7z99Qx+S7ByuAjZV+dDfeVtxdOG8g5l80tfqttU+WKgZRI97/KiMKigdequGCeH0bwnaDwr2GWcm0nurx1Rx45e3NB4ET96QVFrh5P+llnjGVv/ebppQv3INYSWYcEFk/5eSbkG0WJTAJWaaSwnwRNQX20YRU0nhlDoeF9qvbI7qVR0KHppqwKJjDTgM3x3rEtRjl9C63Cvewx91TiuvsKbwP/OVp2D40M/7QAAAABJRU5ErkJggg==) 1x,
      url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAALZ0lEQVR4Xu1da2wU1xWeJmmbJlRVf1Rp1afaplWUVP1bVapa9YGSklaRWqXtj5YU8qAxOIGQkAYCxWkAYxtiREkNGGNjgzHG4De4FNt4ZheDCYQYPDOGoEaiIf2TErw7M/cOc7vfWpaIG7DXszM7Z/ce6ZNXu97du/udnXvueSr5JkKI21TT+0bM5L/QDLdYM/iGmO42x0y3X9P5OdVg76o6uxrTmZX6ex3AbdyHx2K6O4z/xXPSzzXcRZrJHx4wxNfx2oqUaOHEqPfluO7+RjP5phRpcdVkYykCRTBg1/AeMZNXxkbdR4+b3pckAyGj95K4M67zh0C4qvNREJNLqAY3xxWCP4i1SYYCwPCw+ER8lP9SM1h9zGQfgIAoIr21GKwOWwbWLJnzicHz3rdiJi+L6ew/IIAUdPaeZvDS+AXvXslkZkbcx+Im/1nMcA+BgHyAarjdms5/gs8mGb6l9c5/pZrumyAgT3Fa0/kjkxRB/uI1g8/BlwMCCgGa4Q7BaCx48gdGnfs13e3xQQD5rSFuePcVHPFnznh3jztomAsCChuMw9AduizuKgjyVZPPVk12aTIBEvwiDMW8JR4arhl8y1QESPDKvHMoDRjOd2MmH5kmARKG+5Z2wXkgL8jXRt3fI9giic3Yq5jQDPe3dH32veIO+Ov9ESChmbyiSYjbaRl6I96nNdPtyg4BEprutuHkRIL8/vPeF4Jw6sgtwT0Vv+jdE21j76L4SqAhWrkdGJHNQUhn4ejsX8ESIAEfCrKTIvfLD5d8qQS4EkRmz8/NZV9uB7AJcm7tS4Mvt1FFnA5yds6PxlFPHhFz4ieIlpNHOotCd+9KAqIFuI1DC+xE07cvYwcIIAUe0o12VE9GEQMNJccM/jdJQMRh8NcCy+SRBNBA1jOLeofFLEJpXBI6vxB7x/uUki1BAme+EDCgu6LjDS72HueiXmMAbqfvU/V8OhXw0qylblPO3tVSaB7koqzDEc/WWWLu35PiD69/NPDY4l2WKO900s/RiGcbqyPet30XbVDN2z824oqqfzqiqMYCuTPCwtRzq446eC2qitDh99I/hyL5tceYWFA9Qbx/LNhhiTqVEY0c8tkzrtWjFujpPcfFymYbpAWCVc226DvHqSnByRnVIqJQkxL5XWf4xOU+UBTttET3GVpKgN4KGe/9lKp029/g4qntafJDwVPVlug4zUnlE2Z0FUB9PhXyD7/JsUeDmFABG+PwWU7pKvCjDFy+7iEilj6OdiAkJ1hcb1HyHXRk0JaFhlaXtjsgIqcoa3fo2AOj3jeVqQSlyhTIP3iSi7k5Jn/CedR6ilMJFK2bshsXlYZML+yxQEAksGyPRSVn4MrQkPi4cjPBcYEA+XDTgoBIYf8JTqQrCf/5LTx/rJ6CAqxusSOnACUtNpHYCNt50w6caIUadfL7zrvij1UgIFqYtzUp+kdIbAP/7TK9TyqTBe1XKWjwbo2BgEhiT4xGvAB+Hqpp3gjVRlYBKjodKrkCG5TJQqW866W9VmQV4KUmi0ofopH/a7lOxJkRRsDHV/4Ale8RNZ3KhKDfPpWFP74NBEQSqbVZlKqJfk2yzGs8pSuSwNoIdSnlG5UJwRQMKguftzW6CjC/KkmpiES7oUs3GyOycB+h31BCxJRKya4iRyDd2oVSdsvS3ZFVAMQnaGVMv+19VcF0LUqLXnPQjqwCrG21SSkAnH8KRqtRWnR1X3QdQTv6GbWaiaepVf0gDSuaJ4AUes5SyxjmZTgBNPsnRtoBy3ZbFMvJmxRMyfRPitwGavoYRQU4qmCcKr1uGNE6Dj5dYwnVoFg15J5VMC+XYslTda8jf/2+wf6twCFAter3+QYr92f/3RbdKmKdva9QbviEEq35W3Mb/Dl0llNuLJVUMD4dd1BFg8ZyESDCeyI7iXpnsevkFQDYdjR0ewA2CAigrwD50vNvR184V4LHUu9RM8njR3wLmDAC6WPfIEdELshoH2oSSJM+2QicdAykjyPDXJQEUDfwykFbHB2mT/7kYyBcwcO4I9+ASp0/N/q/GiAJteVkBsQTcwT5cAWTaR6BdG109ph+cudOC8/Bc/O9texR38EgapHEBpWJzT2OWN/uiL8esAHcxn14DA0nCqm3cJOfcDB9yDkD69ENZJEkgC78J4SY/GFJAFn4TwnDDDpJQGEC4/7SaeEBlIVLECgTR1q4j8IQCeI+APXGxlCVkgCy8F8iHht1H5UEFBbQCliZEMyhlQQUFgYvic8rN4pqcFMSUDC//vMTvOe1HaAa472EESbeeYyJ1484YkO3I9a2jbuBS/bb6Y5jr6Rur2110v7/LT1OOt7fdJynU84GjAKZNBob5Q9SJhu5ebsGmKhMEYy+/otqMR4mO6lfCA6t3GeLjV0O3oN+vMDgP/3INnFUkkM0wxWtQ1xs+YcjXk4R82R1+NnBaE8PpcAasBbNoJMEgo6wN+kSzuqiSjomdWAUDC7ZT2yLXmkY1oQtpbafYXJJhBWA71BuIpGLC/TrbnrvXr7XQi4eCCABrBUdw1Aw0nc+WgqArX6qZtHvRaETOIy0+VUggDbQ0gaf5UAEsoqQ/nfLZtEABg7mymKvG2BTVPvQxnMNVvozakbOrP81ylQSv+DdG3aJF0ayFWeQskUc+KywZ0IvKUM7IGU6ohpudxjk47K4pN4H8cTxXL0lWsJqM6+77cp0BdOnAzXuRlzk4YVd0hXZziKlbU4IncbZDzMaGxfU0EgMaV44+XIvAccVspCjMzxS0/kjARRyBlvNS//EgO8oiNDvnJkNjjbcoSyRD+tXXvKn53qG7yObRvbxDH79wcQHGmMsQ0eOVILGLA2fgD2n+BC/JwK0TpOX/Zk1n0Ahi9+YSaviV+KGd19MZ+5MF7GiyZaEzrwu0ceZnzH4dHxQ73uYJGLq/giQwHc4U6/fq0q2ZOiyuCtm8osZLgLRMX8ESCC3YSazAEyE931Q7t85hMHOj/kO5khgRJ6q+5gU7gO+0sY6T2fp8i+B2cQ+0r38YvJwScN9azoL2RtnWSFAIqMj4Zn0UMggRbvgPKDqLDENx0+WCJCoV6ejAOwaTmxKGKIZ7u+ipQBSAdJTwMIUlBZFQwGkAiCJRwlbmoS4XdPdttwqgFQA1XRbwIWSC+kdFrNU3T2VEwWQCgDyB+GjUXIp8YvePZrJjXAVQCoAyruOmd7nlCgIiktVk10KRwGkAmgmfztmeF9UoiRoNQMlCFYBpAKA/PiI+JoSRcEUcmwHQSmAVAA+4uOXH55NgEyi7CqAVAAYfD72/PBPB1uP2CezQ4DEtj47nrb2KckqIe5Y3WLF5/oiQKaMrz5gD+C7VKjKunZrw/yqMS8zAiQe35rw1rVZ65R8kE1H7IeKa5PJ6REgsbgukdjcg2TOPJKqIfGZVc3W0K1Tw2U2cMl+6/jmXjFLyVep6LCLF9aMsQ8TIFFUk3Be62YLlEKQhgHx2ZIWWx1PGZMpXyUH7D5cIZVCk8ouPvuFRutKoZL/YqN9edNh/mOl0KW8w176zK7EWKEQ/2x98oON3axYkfLhWsSKTusvz+xK5q0iLNmVvFbaYa+YolZPKkJZNyt+fo99BVZxPlj2yxqsd8s7rSJJfIao7GE/TB0dY09uH7tOjfgnqseur9pvqZu62Q8kkz5R0yvuXN9hL1/emBidX5Xwouy9W7E3aZR32S9izZK5AFB22Lu7vIMtXdFknSqqTdq59tUX1Sbslc3WUHmnvaSqLfSAjZSKTuc7r7ZaFfAyLqlPXA0y7oDXxnus3GcNrWmzyjd3O/dLBqIXhbyt/BD7fmlbckXJAatpZZN1ImWEvZOywN9fVJu0/rQ94WIbmVcFA20cuI378Bj+B/+L57zcbA3iNfBaFT3se3jtfCPgf7/fE1HD7nWzAAAAAElFTkSuQmCC) 2x);
  height: 45px;
  margin-bottom: 5px;
  margin-right: 15px;
  margin-top: 5px;
  position: relative;
  user-select: none;
  width: 45px;
}

#feedback {
  margin-top: 50px;
}

.custodian-information {
  align-items: center;
  display: flex;
  font-size: 15px;
  font-weight: 400;
  line-height: normal;
  margin-top: 14px;
}

.custodian-name {
  color: rgba(0, 0, 0, 0.87);
  padding: 1px 0;
}

.custodian-email {
  color: rgb(0, 0, 0, 0.54);
  padding: 1px 0;
}


@media (max-width: 700px) {
  .main-frame-blocked {
    padding: 0 10%;
  }
}

@media (max-height: 600px) {
  #feedback {
    margin-top: 35px;
  }
}

@media (max-width: 420px) {
  button,
  [dir='rtl'] button,
  .small-link {
    float: none;
    font-size: .825em;
    font-weight: 400;
    margin: 0;
    text-transform: uppercase;
    width: 100%;
  }

  #details {
    margin: 20px 0 20px 0;
  }

  #details p:not(:first-of-type) {
    margin-top: 10px;
  }

  .details-button {
    margin-top: 20px;
    text-align: center;
    width: 100%;
  }

  .main-frame-blocked {
    padding: 0 5%;
  }

  .button-container {
    margin-top: 30px;
  }
}

/**
 * Mobile specific styling.
 * Navigation buttons are anchored to the bottom of the screen.
 * Details message replaces the top content in its own scrollable area.
 */

@media (max-width: 420px) and (max-height: 736px) and (orientation: portrait) {
  .details-button {
    border: 0;
    margin: 8px 0 0;
  }

  .secondary-button {
    margin-inline-end: 0;
    margin-top: 16px;
  }
}

/* Fixed nav. */
@media (min-width: 240px) and (max-width: 420px) and
       (min-height: 401px) and (max-height: 736px) and (orientation:portrait),
       (min-width: 421px) and (max-width: 736px) and (min-height: 240px) and
       (max-height: 420px) and (orientation:landscape) {
  body .button-container {
    background: #f7f7f7;
    bottom: 0;
    box-shadow: 0 -22px 40px rgb(247, 247, 247);
    left: 0;
    margin: 0;
    max-width: 736px;
    padding-left: 24px;
    padding-right: 24px;
    position: fixed;
    z-index: 2;
  }

  .main-frame-blocked {
    max-width: 736px;
  }

  #details,
  #information-container {
    padding-bottom: 40px;
  }
}

@media (max-width: 420px) and (max-height: 736px) and (orientation: portrait),
       (max-width: 736px) and (max-height: 420px) and (orientation: landscape) {
  body {
    margin: 0 auto;
  }

  button,
  [dir='rtl'] button,
  button.small-link {
    font-family: Roboto-Regular,Helvetica;
    font-size: .933em;
    font-weight: 600;
    margin: 6px 0;
    text-transform: uppercase;
    transform: translatez(0);
  }

  .button-container {
    box-sizing: border-box;
    padding-bottom: 8px;
    width: 100%;
  }

  #details {
    box-sizing: border-box;
    height: auto;
    margin: 0;
    opacity: 1;
    padding-top: 40px;
    transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  #details[hidden],
  #information-container[hidden] {
    display: block;
    height: 0;
    opacity: 0;
    overflow: hidden;
    transition: none;
  }

  .details-button {
    padding-bottom: 16px;
    padding-top: 16px;
  }

  h1 {
    font-size: 1.5em;
    margin-bottom: 8px;
  }

  .icon {
    margin-bottom: 12px;
  }

  .main-frame-blocked {
    box-sizing: border-box;
    margin: 24px auto 12px;
    padding: 0 24px;
    position: relative;
  }

  .main-frame-blocked p {
    font-size: .95em;
    line-height: 1.61em;
    margin-top: 8px;
  }

  #information-container {
    margin: 0;
    transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  .small-link {
    border: 0;
  }
}

@media (min-height: 400px) and (orientation:portrait) {
  .main-frame-blocked {
    margin-bottom: 145px;
  }
}

@media (min-height: 299px) and (orientation:portrait) {
  .button-container {
    padding-bottom: 16px;
  }
}

@media (min-height: 405px) and (max-height: 736px) and
       (max-width: 420px) and (orientation:portrait) {
  .icon {
    margin-bottom: 24px;
  }

  .main-frame-blocked {
    margin-top: 64px;
  }
}

@media (min-height: 480px) and (max-width: 420px) and
       (max-height: 736px) and (orientation: portrait),
       (min-height: 338px) and (max-height: 420px) and (max-width: 736px) and
       (orientation: landscape) {
  .icon {
    margin-bottom: 24px;
  }

  .button-container {
    padding-bottom: 24px;
  }
}

@media (min-height: 500px) and (max-width: 414px) and (orientation: portrait) {
  .main-frame-blocked {
    margin-top: 96px;
  }
}

/* Phablet sizing */
@media (min-width: 375px) and (min-height: 641px) and (max-height: 736px) and
       (max-width: 414px) and (orientation: portrait) {
  button,
  [dir='rtl'] button,
  .small-link {
    font-size: 1em;
    padding-bottom: 12px;
    padding-top: 12px;
  }

  body:not(.offline) .icon {
    height: 80px;
    width: 80px;
  }

  .details-button {
    margin-top: 28px;
  }

  h1 {
    font-size: 1.7em;
  }

  .icon {
    margin-bottom: 28px;
  }

  .main-frame-blocked {
    padding: 28px;
  }

  .main-frame-blocked p {
    font-size: 1.05em;
  }

  .button-container {
    padding: 28px;
  }
}

@media (min-width: 420px) and (max-width: 736px) and
       (min-height: 240px) and (max-height: 298px) and
       (orientation:landscape) {
  body:not(.offline) .icon {
    height: 50px;
    width: 50px;
  }

  .icon {
    padding-top: 0;
  }

  .main-frame-blocked {
    margin-top: 16px;
  }

  .button-container {
    padding: 0 24px 8px;
  }
}

@media (min-width: 420px) and (max-width: 736px) and
       (min-height: 240px) and (max-height: 420px) and
       (orientation:landscape) {
  .details-button {
    margin: 0;
  }

  .main-frame-blocked {
    margin-bottom: 70px;
  }

  .button-container {
    margin-top: 0;
  }
}

/* Phablet landscape */
@media (min-width: 680px) and (max-height: 414px) {
  .main-frame-blocked {
    margin: 24px auto;
  }

  .button-container {
    margin: 16px auto 0;
  }
}

@media (max-height: 240px) and (orientation: landscape),
       (max-height: 480px) and (orientation: portrait),
       (max-width: 419px) and (max-height: 323px) {
  body:not(.offline) .icon {
    height: 56px;
    width: 56px;
  }

  .icon {
    margin-bottom: 16px;
  }
}

/* Small mobile screens. No fixed nav. */
@media (max-height: 400px) and (orientation: portrait),
       (max-height: 239px) and (orientation: landscape),
       (max-width: 419px) and (max-height: 399px) {
  .main-frame-blocked {
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
  }

  #details {
    flex: 1 1 auto;
    order: 0;
  }

  #information-container {
    flex: 1 1 auto;
    order: 0;
  }

  .button-container {
    flex: 0 1 auto;
    margin-top: 8px;
    order: 1;
    padding-left: 0;
    padding-right: 0;
    position: relative;
    width: 100%;
  }
}

@media (max-width: 239px) and (orientation: portrait) {
  .button-container {
    padding-left: 0;
    padding-right: 0;
  }
}
</style>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/** @typedef {{eventName: string, uid: number}} */
// eslint-disable-next-line no-var
var WebUIListener;

/** Platform, package, object property, and Event support. **/
// eslint-disable-next-line no-var
var cr = cr || function(global) {
  'use strict';

  /**
   * Builds an object structure for the provided namespace path,
   * ensuring that names that already exist are not overwritten. For
   * example:
   * "a.b.c" -> a = {};a.b={};a.b.c={};
   * @param {string} name Name of the object that this file defines.
   * @param {*=} opt_object The object to expose at the end of the path.
   * @param {Object=} opt_objectToExportTo The object to add the path to;
   *     default is {@code global}.
   * @return {!Object} The last object exported (i.e. exportPath('cr.ui')
   *     returns a reference to the ui property of window.cr).
   * @private
   */
  function exportPath(name, opt_object, opt_objectToExportTo) {
    const parts = name.split('.');
    let cur = opt_objectToExportTo || global;

    for (let part; parts.length && (part = parts.shift());) {
      if (!parts.length && opt_object !== undefined) {
        // last part and we have an object; use it
        cur[part] = opt_object;
      } else if (part in cur) {
        cur = cur[part];
      } else {
        cur = cur[part] = {};
      }
    }
    return cur;
  }

  /**
   * Fires a property change event on the target.
   * @param {EventTarget} target The target to dispatch the event on.
   * @param {string} propertyName The name of the property that changed.
   * @param {*} newValue The new value for the property.
   * @param {*} oldValue The old value for the property.
   */
  function dispatchPropertyChange(target, propertyName, newValue, oldValue) {
    const e = new Event(propertyName + 'Change');
    e.propertyName = propertyName;
    e.newValue = newValue;
    e.oldValue = oldValue;
    target.dispatchEvent(e);
  }

  /**
   * Converts a camelCase javascript property name to a hyphenated-lower-case
   * attribute name.
   * @param {string} jsName The javascript camelCase property name.
   * @return {string} The equivalent hyphenated-lower-case attribute name.
   */
  function getAttributeName(jsName) {
    return jsName.replace(/([A-Z])/g, '-$1').toLowerCase();
  }

  /**
   * The kind of property to define in {@code defineProperty}.
   * @enum {string}
   * @const
   */
  const PropertyKind = {
    /**
     * Plain old JS property where the backing data is stored as a "private"
     * field on the object.
     * Use for properties of any type. Type will not be checked.
     */
    JS: 'js',

    /**
     * The property backing data is stored as an attribute on an element.
     * Use only for properties of type {string}.
     */
    ATTR: 'attr',

    /**
     * The property backing data is stored as an attribute on an element. If the
     * element has the attribute then the value is true.
     * Use only for properties of type {boolean}.
     */
    BOOL_ATTR: 'boolAttr'
  };

  /**
   * Helper function for defineProperty that returns the getter to use for the
   * property.
   * @param {string} name The name of the property.
   * @param {PropertyKind} kind The kind of the property.
   * @return {function():*} The getter for the property.
   */
  function getGetter(name, kind) {
    let attributeName;
    switch (kind) {
      case PropertyKind.JS:
        const privateName = name + '_';
        return function() {
          return this[privateName];
        };
      case PropertyKind.ATTR:
        attributeName = getAttributeName(name);
        return function() {
          return this.getAttribute(attributeName);
        };
      case PropertyKind.BOOL_ATTR:
        attributeName = getAttributeName(name);
        return function() {
          return this.hasAttribute(attributeName);
        };
    }

    // TODO(dbeam): replace with assertNotReached() in assert.js when I can coax
    // the browser/unit tests to preprocess this file through grit.
    throw 'not reached';
  }

  /**
   * Helper function for defineProperty that returns the setter of the right
   * kind.
   * @param {string} name The name of the property we are defining the setter
   *     for.
   * @param {PropertyKind} kind The kind of property we are getting the
   *     setter for.
   * @param {function(*, *):void=} opt_setHook A function to run after the
   *     property is set, but before the propertyChange event is fired.
   * @return {function(*):void} The function to use as a setter.
   */
  function getSetter(name, kind, opt_setHook) {
    let attributeName;
    switch (kind) {
      case PropertyKind.JS:
        const privateName = name + '_';
        return function(value) {
          const oldValue = this[name];
          if (value !== oldValue) {
            this[privateName] = value;
            if (opt_setHook) {
              opt_setHook.call(this, value, oldValue);
            }
            dispatchPropertyChange(this, name, value, oldValue);
          }
        };

      case PropertyKind.ATTR:
        attributeName = getAttributeName(name);
        return function(value) {
          const oldValue = this[name];
          if (value !== oldValue) {
            if (value == undefined) {
              this.removeAttribute(attributeName);
            } else {
              this.setAttribute(attributeName, value);
            }
            if (opt_setHook) {
              opt_setHook.call(this, value, oldValue);
            }
            dispatchPropertyChange(this, name, value, oldValue);
          }
        };

      case PropertyKind.BOOL_ATTR:
        attributeName = getAttributeName(name);
        return function(value) {
          const oldValue = this[name];
          if (value !== oldValue) {
            if (value) {
              this.setAttribute(attributeName, name);
            } else {
              this.removeAttribute(attributeName);
            }
            if (opt_setHook) {
              opt_setHook.call(this, value, oldValue);
            }
            dispatchPropertyChange(this, name, value, oldValue);
          }
        };
    }

    // TODO(dbeam): replace with assertNotReached() in assert.js when I can coax
    // the browser/unit tests to preprocess this file through grit.
    throw 'not reached';
  }

  /**
   * Defines a property on an object. When the setter changes the value a
   * property change event with the type {@code name + 'Change'} is fired.
   * @param {!Object} obj The object to define the property for.
   * @param {string} name The name of the property.
   * @param {PropertyKind=} opt_kind What kind of underlying storage to use.
   * @param {function(*, *):void=} opt_setHook A function to run after the
   *     property is set, but before the propertyChange event is fired.
   */
  function defineProperty(obj, name, opt_kind, opt_setHook) {
    if (typeof obj == 'function') {
      obj = obj.prototype;
    }

    const kind = /** @type {PropertyKind} */ (opt_kind || PropertyKind.JS);

    if (!obj.__lookupGetter__(name)) {
      obj.__defineGetter__(name, getGetter(name, kind));
    }

    if (!obj.__lookupSetter__(name)) {
      obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));
    }
  }

  /**
   * Counter for use with createUid
   */
  let uidCounter = 1;

  /**
   * @return {number} A new unique ID.
   */
  function createUid() {
    return uidCounter++;
  }

  /**
   * Returns a unique ID for the item. This mutates the item so it needs to be
   * an object
   * @param {!Object} item The item to get the unique ID for.
   * @return {number} The unique ID for the item.
   */
  function getUid(item) {
    if (item.hasOwnProperty('uid')) {
      return item.uid;
    }
    return item.uid = createUid();
  }

  /**
   * Dispatches a simple event on an event target.
   * @param {!EventTarget} target The event target to dispatch the event on.
   * @param {string} type The type of the event.
   * @param {boolean=} opt_bubbles Whether the event bubbles or not.
   * @param {boolean=} opt_cancelable Whether the default action of the event
   *     can be prevented. Default is true.
   * @return {boolean} If any of the listeners called {@code preventDefault}
   *     during the dispatch this will return false.
   */
  function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) {
    const e = new Event(type, {
      bubbles: opt_bubbles,
      cancelable: opt_cancelable === undefined || opt_cancelable
    });
    return target.dispatchEvent(e);
  }

  /**
   * Calls |fun| and adds all the fields of the returned object to the object
   * named by |name|. For example, cr.define('cr.ui', function() {
   *   function List() {
   *     ...
   *   }
   *   function ListItem() {
   *     ...
   *   }
   *   return {
   *     List: List,
   *     ListItem: ListItem,
   *   };
   * });
   * defines the functions cr.ui.List and cr.ui.ListItem.
   * @param {string} name The name of the object that we are adding fields to.
   * @param {!Function} fun The function that will return an object containing
   *     the names and values of the new fields.
   */
  function define(name, fun) {
    const obj = exportPath(name);
    const exports = fun();
    for (const propertyName in exports) {
      // Maybe we should check the prototype chain here? The current usage
      // pattern is always using an object literal so we only care about own
      // properties.
      const propertyDescriptor =
          Object.getOwnPropertyDescriptor(exports, propertyName);
      if (propertyDescriptor) {
        Object.defineProperty(obj, propertyName, propertyDescriptor);
      }
    }
  }

  /**
   * Adds a {@code getInstance} static method that always return the same
   * instance object.
   * @param {!Function} ctor The constructor for the class to add the static
   *     method to.
   */
  function addSingletonGetter(ctor) {
    ctor.getInstance = function() {
      return ctor.instance_ || (ctor.instance_ = new ctor());
    };
  }

  /**
   * Forwards public APIs to private implementations.
   * @param {Function} ctor Constructor that have private implementations in its
   *     prototype.
   * @param {Array<string>} methods List of public method names that have their
   *     underscored counterparts in constructor's prototype.
   * @param {string=} opt_target Selector for target node.
   */
  function makePublic(ctor, methods, opt_target) {
    methods.forEach(function(method) {
      ctor[method] = function() {
        const target = opt_target ?
            // Disable document.getElementById restriction since cr.js should
            // not depend on util.js.
            // eslint-disable-next-line no-restricted-properties
            document.getElementById(opt_target) :
            ctor.getInstance();
        return target[method + '_'].apply(target, arguments);
      };
    });
  }

  /**
   * The mapping used by the sendWithPromise mechanism to tie the Promise
   * returned to callers with the corresponding WebUI response. The mapping is
   * from ID to the PromiseResolver helper; the ID is generated by
   * sendWithPromise and is unique across all invocations of said method.
   * @type {!Object<!PromiseResolver>}
   */
  const chromeSendResolverMap = {};

  /**
   * The named method the WebUI handler calls directly in response to a
   * chrome.send call that expects a response. The handler requires no knowledge
   * of the specific name of this method, as the name is passed to the handler
   * as the first argument in the arguments list of chrome.send. The handler
   * must pass the ID, also sent via the chrome.send arguments list, as the
   * first argument of the JS invocation; additionally, the handler may
   * supply any number of other arguments that will be included in the response.
   * @param {string} id The unique ID identifying the Promise this response is
   *     tied to.
   * @param {boolean} isSuccess Whether the request was successful.
   * @param {*} response The response as sent from C++.
   */
  function webUIResponse(id, isSuccess, response) {
    const resolver = chromeSendResolverMap[id];
    delete chromeSendResolverMap[id];

    if (isSuccess) {
      resolver.resolve(response);
    } else {
      resolver.reject(response);
    }
  }

  /**
   * A variation of chrome.send, suitable for messages that expect a single
   * response from C++.
   * @param {string} methodName The name of the WebUI handler API.
   * @param {...*} var_args Variable number of arguments to be forwarded to the
   *     C++ call.
   * @return {!Promise}
   */
  function sendWithPromise(methodName, var_args) {
    const args = Array.prototype.slice.call(arguments, 1);
    const promiseResolver = new PromiseResolver();
    const id = methodName + '_' + createUid();
    chromeSendResolverMap[id] = promiseResolver;
    chrome.send(methodName, [id].concat(args));
    return promiseResolver.promise;
  }

  /**
   * A map of maps associating event names with listeners. The 2nd level map
   * associates a listener ID with the callback function, such that individual
   * listeners can be removed from an event without affecting other listeners of
   * the same event.
   * @type {!Object<!Object<!Function>>}
   */
  const webUIListenerMap = {};

  /**
   * The named method the WebUI handler calls directly when an event occurs.
   * The WebUI handler must supply the name of the event as the first argument
   * of the JS invocation; additionally, the handler may supply any number of
   * other arguments that will be forwarded to the listener callbacks.
   * @param {string} event The name of the event that has occurred.
   * @param {...*} var_args Additional arguments passed from C++.
   */
  function webUIListenerCallback(event, var_args) {
    const eventListenersMap = webUIListenerMap[event];
    if (!eventListenersMap) {
      // C++ event sent for an event that has no listeners.
      // TODO(dpapad): Should a warning be displayed here?
      return;
    }

    const args = Array.prototype.slice.call(arguments, 1);
    for (const listenerId in eventListenersMap) {
      eventListenersMap[listenerId].apply(null, args);
    }
  }

  /**
   * Registers a listener for an event fired from WebUI handlers. Any number of
   * listeners may register for a single event.
   * @param {string} eventName The event to listen to.
   * @param {!Function} callback The callback run when the event is fired.
   * @return {!WebUIListener} An object to be used for removing a listener via
   *     cr.removeWebUIListener. Should be treated as read-only.
   */
  function addWebUIListener(eventName, callback) {
    webUIListenerMap[eventName] = webUIListenerMap[eventName] || {};
    const uid = createUid();
    webUIListenerMap[eventName][uid] = callback;
    return {eventName: eventName, uid: uid};
  }

  /**
   * Removes a listener. Does nothing if the specified listener is not found.
   * @param {!WebUIListener} listener The listener to be removed (as returned by
   *     addWebUIListener).
   * @return {boolean} Whether the given listener was found and actually
   *     removed.
   */
  function removeWebUIListener(listener) {
    const listenerExists = webUIListenerMap[listener.eventName] &&
        webUIListenerMap[listener.eventName][listener.uid];
    if (listenerExists) {
      delete webUIListenerMap[listener.eventName][listener.uid];
      return true;
    }
    return false;
  }

  return {
    addSingletonGetter: addSingletonGetter,
    createUid: createUid,
    define: define,
    defineProperty: defineProperty,
    dispatchPropertyChange: dispatchPropertyChange,
    dispatchSimpleEvent: dispatchSimpleEvent,
    exportPath: exportPath,
    getUid: getUid,
    makePublic: makePublic,
    PropertyKind: PropertyKind,

    // C++ <-> JS communication related methods.
    addWebUIListener: addWebUIListener,
    removeWebUIListener: removeWebUIListener,
    sendWithPromise: sendWithPromise,
    webUIListenerCallback: webUIListenerCallback,
    webUIResponse: webUIResponse,

    get doc() {
      return document;
    },

    /** Whether we are using a Mac or not. */
    get isMac() {
      return /Mac/.test(navigator.platform);
    },

    /** Whether this is on the Windows platform or not. */
    get isWindows() {
      return /Win/.test(navigator.platform);
    },

    /** Whether this is on chromeOS or not. */
    get isChromeOS() {
      return /CrOS/.test(navigator.userAgent);
    },

    /** Whether this is on vanilla Linux (not chromeOS). */
    get isLinux() {
      return /Linux/.test(navigator.userAgent);
    },

    /** Whether this is on Android. */
    get isAndroid() {
      return /Android/.test(navigator.userAgent);
    },

    /** Whether this is on iOS. */
    get isIOS() {
      return /iPad|iPhone|iPod/.test(navigator.platform);
    }
  };
}(this);
</script>
<script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// // Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Assertion support.
 */

/**
 * Verify |condition| is truthy and return |condition| if so.
 * @template T
 * @param {T} condition A condition to check for truthiness.  Note that this
 *     may be used to test whether a value is defined or not, and we don't want
 *     to force a cast to Boolean.
 * @param {string=} opt_message A message to show on failure.
 * @return {T} A non-null |condition|.
 */
function assert(condition, opt_message) {
  if (!condition) {
    let message = 'Assertion failed';
    if (opt_message) {
      message = message + ': ' + opt_message;
    }
    const error = new Error(message);
    const global = function() {
      /** @type {boolean} */
      this.traceAssertionsForTesting;
      return this;
    }();
    if (global.traceAssertionsForTesting) {
      console.warn(error.stack);
    }
    throw error;
  }
  return condition;
}

/**
 * Call this from places in the code that should never be reached.
 *
 * For example, handling all the values of enum with a switch() like this:
 *
 *   function getValueFromEnum(enum) {
 *     switch (enum) {
 *       case ENUM_FIRST_OF_TWO:
 *         return first
 *       case ENUM_LAST_OF_TWO:
 *         return last;
 *     }
 *     assertNotReached();
 *     return document;
 *   }
 *
 * This code should only be hit in the case of serious programmer error or
 * unexpected input.
 *
 * @param {string=} opt_message A message to show when this is hit.
 */
function assertNotReached(opt_message) {
  assert(false, opt_message || 'Unreachable code hit');
}

/**
 * @param {*} value The value to check.
 * @param {function(new: T, ...)} type A user-defined constructor.
 * @param {string=} opt_message A message to show when this is hit.
 * @return {T}
 * @template T
 */
function assertInstanceof(value, type, opt_message) {
  // We don't use assert immediately here so that we avoid constructing an error
  // message if we don't have to.
  if (!(value instanceof type)) {
    assertNotReached(
        opt_message ||
        'Value ' + value + ' is not a[n] ' + (type.name || typeof type));
  }
  return value;
}


/**
 * Alias for document.getElementById. Found elements must be HTMLElements.
 * @param {string} id The ID of the element to find.
 * @return {HTMLElement} The found element or null if not found.
 */
function $(id) {
  // Disable getElementById restriction here, since we are instructing other
  // places to re-use the $() that is defined here.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, HTMLElement) : null;
}

// TODO(devlin): This should return SVGElement, but closure compiler is missing
// those externs.
/**
 * Alias for document.getElementById. Found elements must be SVGElements.
 * @param {string} id The ID of the element to find.
 * @return {Element} The found element or null if not found.
 */
function getSVGElement(id) {
  // Disable getElementById restriction here, since it is not suitable for SVG
  // elements.
  // eslint-disable-next-line no-restricted-properties
  const el = document.getElementById(id);
  return el ? assertInstanceof(el, Element) : null;
}

/**
 * @return {?Element} The currently focused element (including elements that are
 *     behind a shadow root), or null if nothing is focused.
 */
function getDeepActiveElement() {
  let a = document.activeElement;
  while (a && a.shadowRoot && a.shadowRoot.activeElement) {
    a = a.shadowRoot.activeElement;
  }
  return a;
}

/**
 * Add an accessible message to the page that will be announced to
 * users who have spoken feedback on, but will be invisible to all
 * other users. It's removed right away so it doesn't clutter the DOM.
 * @param {string} msg The text to be pronounced.
 */
function announceAccessibleMessage(msg) {
  const element = document.createElement('div');
  element.setAttribute('aria-live', 'polite');
  element.style.position = 'fixed';
  element.style.left = '-9999px';
  element.style.height = '0px';
  element.innerText = msg;
  document.body.appendChild(element);
  window.setTimeout(function() {
    document.body.removeChild(element);
  }, 0);
}

/**
 * Generates a CSS url string.
 * @param {string} s The URL to generate the CSS url for.
 * @return {string} The CSS url string.
 */
function getUrlForCss(s) {
  // http://www.w3.org/TR/css3-values/#uris
  // Parentheses, commas, whitespace characters, single quotes (') and double
  // quotes (") appearing in a URI must be escaped with a backslash
  let s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
  // WebKit has a bug when it comes to URLs that end with \
  // https://bugs.webkit.org/show_bug.cgi?id=28885
  if (/\\\\$/.test(s2)) {
    // Add a space to work around the WebKit bug.
    s2 += ' ';
  }
  return 'url("' + s2 + '")';
}

/**
 * Parses query parameters from Location.
 * @param {Location} location The URL to generate the CSS url for.
 * @return {Object} Dictionary containing name value pairs for URL
 */
function parseQueryParams(location) {
  const params = {};
  const query = unescape(location.search.substring(1));
  const vars = query.split('&');
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split('=');
    params[pair[0]] = pair[1];
  }
  return params;
}

/**
 * Creates a new URL by appending or replacing the given query key and value.
 * Not supporting URL with username and password.
 * @param {Location} location The original URL.
 * @param {string} key The query parameter name.
 * @param {string} value The query parameter value.
 * @return {string} The constructed new URL.
 */
function setQueryParam(location, key, value) {
  const query = parseQueryParams(location);
  query[encodeURIComponent(key)] = encodeURIComponent(value);

  let newQuery = '';
  for (const q in query) {
    newQuery += (newQuery ? '&' : '?') + q + '=' + query[q];
  }

  return location.origin + location.pathname + newQuery + location.hash;
}

/**
 * @param {Node} el A node to search for ancestors with |className|.
 * @param {string} className A class to search for.
 * @return {Element} A node with class of |className| or null if none is found.
 */
function findAncestorByClass(el, className) {
  return /** @type {Element} */ (findAncestor(el, function(el) {
    return el.classList && el.classList.contains(className);
  }));
}

/**
 * Return the first ancestor for which the {@code predicate} returns true.
 * @param {Node} node The node to check.
 * @param {function(Node):boolean} predicate The function that tests the
 *     nodes.
 * @return {Node} The found ancestor or null if not found.
 */
function findAncestor(node, predicate) {
  let last = false;
  while (node != null && !(last = predicate(node))) {
    node = node.parentNode;
  }
  return last ? node : null;
}

function swapDomNodes(a, b) {
  const afterA = a.nextSibling;
  if (afterA == b) {
    swapDomNodes(b, a);
    return;
  }
  const aParent = a.parentNode;
  b.parentNode.replaceChild(a, b);
  aParent.insertBefore(b, afterA);
}

/**
 * Disables text selection and dragging, with optional whitelist callbacks.
 * @param {function(Event):boolean=} opt_allowSelectStart Unless this function
 *    is defined and returns true, the onselectionstart event will be
 *    surpressed.
 * @param {function(Event):boolean=} opt_allowDragStart Unless this function
 *    is defined and returns true, the ondragstart event will be surpressed.
 */
function disableTextSelectAndDrag(opt_allowSelectStart, opt_allowDragStart) {
  // Disable text selection.
  document.onselectstart = function(e) {
    if (!(opt_allowSelectStart && opt_allowSelectStart.call(this, e))) {
      e.preventDefault();
    }
  };

  // Disable dragging.
  document.ondragstart = function(e) {
    if (!(opt_allowDragStart && opt_allowDragStart.call(this, e))) {
      e.preventDefault();
    }
  };
}

/**
 * Check the directionality of the page.
 * @return {boolean} True if Chrome is running an RTL UI.
 */
function isRTL() {
  return document.documentElement.dir == 'rtl';
}

/**
 * Get an element that's known to exist by its ID. We use this instead of just
 * calling getElementById and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} id The identifier name.
 * @return {!HTMLElement} the Element.
 */
function getRequiredElement(id) {
  return assertInstanceof(
      $(id), HTMLElement, 'Missing required element: ' + id);
}

/**
 * Query an element that's known to exist by a selector. We use this instead of
 * just calling querySelector and not checking the result because this lets us
 * satisfy the JSCompiler type system.
 * @param {string} selectors CSS selectors to query the element.
 * @param {(!Document|!DocumentFragment|!Element)=} opt_context An optional
 *     context object for querySelector.
 * @return {!HTMLElement} the Element.
 */
function queryRequiredElement(selectors, opt_context) {
  const element = (opt_context || document).querySelector(selectors);
  return assertInstanceof(
      element, HTMLElement, 'Missing required element: ' + selectors);
}

// Handle click on a link. If the link points to a chrome: or file: url, then
// call into the browser to do the navigation.
['click', 'auxclick'].forEach(function(eventName) {
  document.addEventListener(eventName, function(e) {
    if (e.button > 1) {
      return;
    }  // Ignore buttons other than left and middle.
    if (e.defaultPrevented) {
      return;
    }

    const eventPath = e.path;
    let anchor = null;
    if (eventPath) {
      for (let i = 0; i < eventPath.length; i++) {
        const element = eventPath[i];
        if (element.tagName === 'A' && element.href) {
          anchor = element;
          break;
        }
      }
    }

    // Fallback if Event.path is not available.
    let el = e.target;
    if (!anchor && el.nodeType == Node.ELEMENT_NODE &&
        el.webkitMatchesSelector('A, A *')) {
      while (el.tagName != 'A') {
        el = el.parentElement;
      }
      anchor = el;
    }

    if (!anchor) {
      return;
    }

    anchor = /** @type {!HTMLAnchorElement} */ (anchor);
    if ((anchor.protocol == 'file:' || anchor.protocol == 'about:') &&
        (e.button == 0 || e.button == 1)) {
      chrome.send('navigateToUrl', [
        anchor.href, anchor.target, e.button, e.altKey, e.ctrlKey, e.metaKey,
        e.shiftKey
      ]);
      e.preventDefault();
    }
  });
});

/**
 * Creates a new URL which is the old URL with a GET param of key=value.
 * @param {string} url The base URL. There is not sanity checking on the URL so
 *     it must be passed in a proper format.
 * @param {string} key The key of the param.
 * @param {string} value The value of the param.
 * @return {string} The new URL.
 */
function appendParam(url, key, value) {
  const param = encodeURIComponent(key) + '=' + encodeURIComponent(value);

  if (url.indexOf('?') == -1) {
    return url + '?' + param;
  }
  return url + '&' + param;
}

/**
 * Creates an element of a specified type with a specified class name.
 * @param {string} type The node type.
 * @param {string} className The class name to use.
 * @return {Element} The created element.
 */
function createElementWithClassName(type, className) {
  const elm = document.createElement(type);
  elm.className = className;
  return elm;
}

/**
 * transitionend does not always fire (e.g. when animation is aborted
 * or when no paint happens during the animation). This function sets up
 * a timer and emulate the event if it is not fired when the timer expires.
 * @param {!HTMLElement} el The element to watch for transitionend.
 * @param {number=} opt_timeOut The maximum wait time in milliseconds for the
 *     transitionend to happen. If not specified, it is fetched from |el|
 *     using the transitionDuration style value.
 */
function ensureTransitionEndEvent(el, opt_timeOut) {
  if (opt_timeOut === undefined) {
    const style = getComputedStyle(el);
    opt_timeOut = parseFloat(style.transitionDuration) * 1000;

    // Give an additional 50ms buffer for the animation to complete.
    opt_timeOut += 50;
  }

  let fired = false;
  el.addEventListener('transitionend', function f(e) {
    el.removeEventListener('transitionend', f);
    fired = true;
  });
  window.setTimeout(function() {
    if (!fired) {
      cr.dispatchSimpleEvent(el, 'transitionend', true);
    }
  }, opt_timeOut);
}

/**
 * Alias for document.scrollTop getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The Y document scroll offset.
 */
function scrollTopForDocument(doc) {
  return doc.documentElement.scrollTop || doc.body.scrollTop;
}

/**
 * Alias for document.scrollTop setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target Y scroll offset.
 */
function setScrollTopForDocument(doc, value) {
  doc.documentElement.scrollTop = doc.body.scrollTop = value;
}

/**
 * Alias for document.scrollLeft getter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @return {number} The X document scroll offset.
 */
function scrollLeftForDocument(doc) {
  return doc.documentElement.scrollLeft || doc.body.scrollLeft;
}

/**
 * Alias for document.scrollLeft setter.
 * @param {!HTMLDocument} doc The document node where information will be
 *     queried from.
 * @param {number} value The target X scroll offset.
 */
function setScrollLeftForDocument(doc, value) {
  doc.documentElement.scrollLeft = doc.body.scrollLeft = value;
}

/**
 * Replaces '&', '<', '>', '"', and ''' characters with their HTML encoding.
 * @param {string} original The original string.
 * @return {string} The string with all the characters mentioned above replaced.
 */
function HTMLEscape(original) {
  return original.replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
}

/**
 * Shortens the provided string (if necessary) to a string of length at most
 * |maxLength|.
 * @param {string} original The original string.
 * @param {number} maxLength The maximum length allowed for the string.
 * @return {string} The original string if its length does not exceed
 *     |maxLength|. Otherwise the first |maxLength| - 1 characters with '...'
 *     appended.
 */
function elide(original, maxLength) {
  if (original.length <= maxLength) {
    return original;
  }
  return original.substring(0, maxLength - 1) + '\u2026';
}

/**
 * Quote a string so it can be used in a regular expression.
 * @param {string} str The source string.
 * @return {string} The escaped string.
 */
function quoteString(str) {
  return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
}

/**
 * Calls |callback| and stops listening the first time any event in |eventNames|
 * is triggered on |target|.
 * @param {!EventTarget} target
 * @param {!Array<string>|string} eventNames Array or space-delimited string of
 *     event names to listen to (e.g. 'click mousedown').
 * @param {function(!Event)} callback Called at most once. The
 *     optional return value is passed on by the listener.
 */
function listenOnce(target, eventNames, callback) {
  if (!Array.isArray(eventNames)) {
    eventNames = eventNames.split(/ +/);
  }

  const removeAllAndCallCallback = function(event) {
    eventNames.forEach(function(eventName) {
      target.removeEventListener(eventName, removeAllAndCallCallback, false);
    });
    return callback(event);
  };

  eventNames.forEach(function(eventName) {
    target.addEventListener(eventName, removeAllAndCallCallback, false);
  });
}

//   /* is_ios */

/**
 * @param {!Event} e
 * @return {boolean} Whether a modifier key was down when processing |e|.
 */
function hasKeyModifiers(e) {
  return !!(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey);
}
</script>
<script>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var mobileNav = false;

var showDetails = false;

/**
 * For small screen mobile the navigation buttons are moved
 * below the advanced text.
 */
function onResize() {
  var mediaQuery = '(min-width: 240px) and (max-width: 420px) and ' +
      '(max-height: 736px) and (min-height: 401px) and ' +
      '(orientation: portrait), (max-width: 736px) and ' +
      '(max-height: 420px) and (min-height: 240px) and ' +
      '(min-width: 421px) and (orientation: landscape)';

  // Check for change in nav status.
  if (mobileNav != window.matchMedia(mediaQuery).matches) {
    mobileNav = !mobileNav;
    updateDetails();
  }
}

function updateDetails() {
  $('information-container').hidden = mobileNav && showDetails;
  $('details').hidden = !showDetails;
}

function setupMobileNav() {
  window.addEventListener('resize', onResize);
  onResize();
}

document.addEventListener('DOMContentLoaded', setupMobileNav);

function sendCommand(cmd) {
  if (window.supervisedUserErrorPageController) {
    switch (cmd) {
      case 'back':
        supervisedUserErrorPageController.goBack();
        break;
      case 'request':
        supervisedUserErrorPageController.requestPermission();
        break;
      case 'feedback':
        supervisedUserErrorPageController.feedback();
        break;
    }
    return;
  }
  // TODO(bauerb): domAutomationController is not defined when this page is
  // shown in chrome://interstitials. Use a MessageHandler or something to
  // support interactions.
  window.domAutomationController.send(cmd);
}

function makeImageSet(url1x, url2x) {
  return '-webkit-image-set(url(' + url1x + ') 1x, url(' + url2x + ') 2x)';
}

function initialize() {
  var allowAccessRequests = loadTimeData.getBoolean('allowAccessRequests');
  if (allowAccessRequests) {
    $('request-access-button').onclick = function(event) {
      $('request-access-button').hidden = true;
      sendCommand('request');
    };
  } else {
    $('request-access-button').hidden = true;
  }
  var avatarURL1x = loadTimeData.getString('avatarURL1x');
  var avatarURL2x = loadTimeData.getString('avatarURL2x');
  var custodianName = loadTimeData.getString('custodianName');
  if (custodianName && allowAccessRequests) {
    $('custodians-information').hidden = false;
    if (avatarURL1x) {
      $('custodian-avatar-img').style.content =
          makeImageSet(avatarURL1x, avatarURL2x);
    }
    $('custodian-name').textContent = custodianName;
    $('custodian-email').textContent = loadTimeData.getString('custodianEmail');
    var secondAvatarURL1x = loadTimeData.getString('secondAvatarURL1x');
    var secondAvatarURL2x = loadTimeData.getString('secondAvatarURL2x');
    var secondCustodianName = loadTimeData.getString('secondCustodianName');
    if (secondCustodianName) {
      $('second-custodian-information').hidden = false;
      $('second-custodian-avatar-img').hidden = false;
      if (secondAvatarURL1x) {
        $('second-custodian-avatar-img').style.content =
            makeImageSet(secondAvatarURL1x, secondAvatarURL2x);
      }
      $('second-custodian-name').textContent = secondCustodianName;
      $('second-custodian-email').textContent = loadTimeData.getString(
          'secondCustodianEmail');
    }
  }
  $('back-button').onclick = function(event) {
    sendCommand('back');
  };
  if (loadTimeData.getBoolean('showFeedbackLink')) {
    $('show-details-link').onclick = function(event) {
      showDetails = true;
      $('show-details-link').hidden = true;
      $('hide-details-link').hidden = false;
      updateDetails();
    };
    $('hide-details-link').onclick = function(event) {
      showDetails = false;
      $('show-details-link').hidden = false;
      $('hide-details-link').hidden = true;
      updateDetails();
    };
    $('feedback-link').onclick = function(event) {
      sendCommand('feedback');
    };
  } else {
    $('feedback').hidden = true;
    $('details-button-container').hidden = true;
  }
}

/**
 * Updates the interstitial to show that the request failed or was sent.
 * @param {boolean} isSuccessful Whether the request was successful or not.
 */
function setRequestStatus(isSuccessful) {
  console.log('setRequestStatus(' + isSuccessful +')');
  $('block-page-header').hidden = true;
  $('block-page-message').hidden = true;
  $('hide-details-link').hidden = true;
  showDetails = false;
  updateDetails();

  if (isSuccessful) {
    $('request-failed-message').hidden = true;
    $('request-sent-message').hidden = false;
    $('back-button').hidden = false;
    $('request-access-button').hidden = true;
    $('show-details-link').hidden = true;
  } else {
    $('request-failed-message').hidden = false;
    $('request-access-button').hidden = false;
    $('show-details-link').hidden = false;
  }
}

document.addEventListener('DOMContentLoaded', initialize);
</script>
</head>
<body>
<div class="main-frame-blocked">
  <div id="information-container">
    <div class="icon" id="icon"></div>
    <div id="main-message">
      <h1 id="block-page-header">$i18n{blockPageHeader}</h1>
      <p id="block-page-message">$i18n{blockPageMessage}</p>
      <h1 id="request-failed-message" hidden>$i18n{requestFailedMessage}</h1>
      <h1 id="request-sent-message" hidden>$i18n{requestSentMessage}</h1>
    </div>
    <div id="custodians-information" hidden>
      <div id="custodian-information" class="custodian-information">
        <img id="custodian-avatar-img" class="avatar-img">
        <div id="custodian-contact">
          <div id="custodian-name" class="custodian-name"></div>
          <div id="custodian-email" class="custodian-email"></div>
        </div>
      </div>
      <div id="second-custodian-information" class="custodian-information" hidden>
        <img id="second-custodian-avatar-img" class="avatar-img" hidden>
        <div id="second-custodian-contact">
          <div id="second-custodian-name" class="custodian-name"></div>
          <div id="second-custodian-email" class="custodian-email"></div>
        </div>
      </div>
    </div>
  </div>
  <div class="button-container">
    <button id="request-access-button" class="primary-button">
      $i18n{requestAccessButton}
    </button>
    <div id="details-button-container">
      <button id="show-details-link" class="details-button small-link">
        $i18n{showDetailsLink}
      </button>
      <button id="hide-details-link" class="details-button small-link" hidden>
        $i18n{hideDetailsLink}
      </button>
    </div>
    <button id="back-button" class="details-button small-link" hidden>
      $i18n{backButton}
    </button>
  </div>
  <div id="details" hidden>
    <p id="details-header">$i18n{blockReasonHeader}</p>
    <p id="details-message">$i18n{blockReasonMessage}</p>
    <p id="feedback">$i18nRaw{feedbackLink}</p>
  </div>
</div>
</body>
</html>
     <iWȲ=e̎3`2N,sRȒ#0[6/q{$%UUwW%2\MX߮/bXމUwbtro
5>ρ֥D~*I$7 zSzm1nLx?l%]{ۧ*>Sinivi4Hc)ӐSv, ècU];-x>Q|6ߣ)QDG}7t꫺﫸AM-_;jtlg?!:G3w0njMa
%Ұm|ҧސ5y)qMX'b$%puxj΄hȇ$SGa5t(R21p!l5ĴlZ"kk?k7`E1]!<[vw#`C]+GkߒuaVǣ3A6t-U9%zv6vHeE⛮Ê4+xy]ts![ L,/t?!$;?ǆ`Msc7wzIP7@,tĳ ;tX,p:pKmQBд¥|Z0;Gmytg#J"J yUM`Ϲ8|'g:1=O}^
gQW̙o4M`!+8Z?vwr
)#&Ms[4 r!Xa{P,CqHP	4hѴfYYnaM{&3BSVtB}r <bΕ#;gA13! Vzl.4Ӵ"@`iXCq븞AaI܅-m<84=t&펊J$1L !8@0`;j?aKٵbc`ib<p
]H2Qra=Ѣ?t=y`Uϐ9^s9BcPs8)YF&$b|۸vF4ScU<b`&"YbЗmFF:6lG(S t&4(
l1;fJaƘgud4/a7]o3XOod'.gOmLF$R-ϧj7w6`rp_׀JJt!Y?x|2~FD,ws( a<&}*r{û2D.c*[,A^B@̊S>dӦ|.w=7aw(X	;кt'%IYρϯ7g)J#B6B^-pKk82Br6#aSm'`zD42+0ݡr:HF$3_S*rŇe3C!.d=[O	AyXŝ/4\PP JCr4N,\hάø7%5(,}Ȳ)GHXQ
DL;"`Nqr(9O`]x L7=,Ow"B&8AәSG_`)f)15LVjy2%cz1uɥ.LgU[ཏp6e|USq	=׶ghut5dNOğZir|JƴC~QGΖxz};*{uuuk>t?.]ÇSl7?<~\^u?4/>>*7f.0nch^||Tv/{7{~\->zݧOUˍ|q>}7o!Zn]5جjMUwOk_Uvag[7]y<>juo^}nO0l_Fuj@56/IN?}~Qk/n~WfO=ugWlwin@>7U=hg;0;=knoCU=/߫Zΰ6}*3T:]Gݫ oϦ|jggާUs{g{*}Ց3WzxyZGu.ۊ?zo}U~1m_SkSm~lݨ&مmyU<6v75x;pRk=bi0qgXuո{x}W;j
j7%x]W+^n[,X`A#>MOiɃKz47?'M|d@d2\.h,EISe vr1F#ko}_.%ƙ[KPx<ݕu3NnƂp O4N|ô#m>*_Q֧?S+u ˠ+ᄣQRv^m@dձMW6+F@~?jFU1`
_\b4<Op>V{aB!>n.Fޫ;EW cOªؐݸKa
@TqwWAu *VB˶vWŀ-*zpt+sydFVecS5&hV2ǜWhY=(13?'@YzcubIYjd7!?a	. }jxWF<wx!(qV0H'q09,鼏22NMJ_=
!ı8Rx&+ Ǐ3s4lzԛLаayL4YpXLPT6!gȂمaHdA.n?N`ˎmpۧ8u~R /-D`.pAű*$@-p'Q¢p$mK-q2-|0Č()Ѽ[2g^YRH[*4X	R)+lA8"!|l k-f}ۚTeB|bBU:⸽tW!'J̋'jv@9X~nCd}D'zuazhRO2x˨Cl#{gr gnl`+qGؓZW$# 'ŗ	gOr^嬏m|\<8D]~fz͑R/SzC=S:b}ׄ۲wp,,IFI:N:'YZ974 &K/K|,(B̶=6`ಋ阨as&nֱWNQBe:m(pIIj)9~B.M!WT%_Q!Ph&f&}'OφCG(t
%^f;zmxf]K78&
xz{w}U1eN68q"BXL~%)i/%:4ylQw.#u]mgs;rƁ~Ϣ~SYǶti>}-pyX,c\%p<#jA8y| +	 <J!sR}sīLA&BO%5!S*!rqM[S)xZ LhmSIXf<eٟ8ǹQ84g;+r9#u*OHÀ,JeM"c$zu}e ;9kI ̎;DXHrn3lk!q혶3sr|՛Mp	^y~<шȌS?IN74,`]@w0KBqC@iBUJ%<f?QF^4xEK&MJ,pEjDȒ4"|b%˓҄"E&Dxj,ia "_m~j̢,ДH xŭ-ͫ*^a?B"r)?@Y2V0nRqZ&Z"D2; %1/`	6/>V:K䔮MxLϰ|EpTK<uGUr>)2S(b%C\F״DVnQiqϋѝ@Y`ɦy`+I|X\ύK-NH x!6U͡8Lm~~RHl'^"q/_KYfQsǪV_[(z9qF7p)͋,ʂN5&oS{B<Ut>B<inX*nb䏗\@]!	yXIqHS^ȤRd^5EhMYdǖ"lHu
C['C\W1|cdmo9k-l	 T:(樢m+:\"'B@ѷ15Cv>Bس.;
Pj&k`4E	.ڝ7D8 =:.u=Hυ!4qHC{rԕ:=D6`` hǓ\-Q==%`xYl-n)Fu+gT9j*]jLCYd9&֯@3dQ)u.4]Mv+ArQ>$T,\TID)U4ɸ}WMj?\><4Wy%1Zh7V$}kh5H4nWɅkd}.&/V(y!XD	d^^5.O+YQiȹ\0lQ[r:^/(	X0Y:?EO2iT7tYSѪSuBw^qy.z F92%wĎ<#g}D8ªk.:O3ĂNqssjnM\A?+GhWg"It2RK-/_w1wn rYmh\rE4Jy!WØ 
2 	Ǽ4
^<[+ѱGgb=7K/.iv&Gc]]HfgIk#ʱᕄr $?.cIMۖZ:ǨlCH^4g-6;!5%4iKfNX
ګ}
(RB:eZq?ƪ'?mn`Xx%/:P       uɎAFBnia8N!)!prTʡd"4+S-=wGO>Bk{iyKi{p4p_w{
8y s{GP0Y!-%Nb"hL89ay:CG" `gUo!PSG5d1d;Y*,	&%(. ;A0Ŷ@-Y 2ZsK!ES'CB]tڢ2xz=)bUr(<+QQ$QcPW9U(΁gN"4ؑ&n<fy]U5/'HmYH7
Ԓxj *3qD>~ nʺt	]RFVܗa`e+aS{m~Ay0ﺩo<̒Qyۖ2[PWlOrm=+P*A       XKo8WL{ӸvGuEТ-t{(TI^#C$+K3o>&2*LsxsK&+^`\T*=qԠPZc2<F0)נebX&kTo߳l3(Hͤ@ZZB$#|L?ͦWd](OnaxfWH5Aꭈ{X"6\9<
B]+	`r*0VtA`rMڍ~KAVHVF<
p`uU[+G2c6GxjjW抯IvHv(3?-\PMvw)4!`F2s1X5̕4uMY} #?uyy鐗׵G 9M㴼8ݼ9s=zW$p}jh˙b+xq$;RpOh֋4g"/Y>vHi9|RlOu!:g&N )}HR)\@ 4tql[hsK*m)GWHޗ.Y/W<
K5v:"4zBMi
{d$EP_Tw!oIδT{{﵋Ź퓚(<Ri9Ie"Kl1(2MQl.x.s## 	a>Gz+nI{@m|z娵_Έ4dIM	ĝ>ꭏ#|^XuNt,a^R
e6/EƖ-RƟ03U{[㨥9feq_VH%A*t0zsq=9;t;{[o8H\mpJL&32d+}Jw	Sj52ەƫo)hrf뜶u~ۺ?Msfi:"mBm{wS4mAWV^*ĺk*|,	7IMvŽϴ]]lRQ`xuV:	nZIK[Z"fã4Ct?qs½Sȼa:z|7>"(@̯mm31N2d +?M07
L|m3mI)މ)C-#xBےm;Q$omݣ$-
ոY`eNFa]=]}rj!,+sf/rTBFs?S9>.]IyaxBȟ|k![R\;)jp,RZ޻;%56ܤnݷ%+Vq^b(nsV7Sl=垾z6aBEJ)կCvM{Π&;t.z&
^w"⮜ymt53rka9PQAebWBWʐB	%{N8 ρioQK&re<VCsK?5_n	;Z[Cltt ٚ#{:+zlu?NjXMCQZoGo]cԵ襛-PnqGjԵx ]s7c'? v       VMo6W,=%(qIMNA45HA{lѽ&g8y9,Tb]X~aQhUJt2ÓAP9B0kE-1}P
قYL
]\52!ivrQb:pfɔ05{SL!o$Bd-LhQ{Vv5!>>axVe!-c2ʧmLsY4ÜaW^8Bq]\ѵBW5XƜ((nK*GPqw|~p sxL?P\BZDBXE`uyrnpoQ(mYJImҺ1EҚ%nr}ifW?jј$q喕+hKMf:wt;qVR 5Zp/&AF8d,1Sy5)N&)b-LЯ-$j"0#_kBy;n;ֺnUK4Ce86Ԧ崽j'uJVO5?:3T+HMOw&4z3D'D[Dɇ.҂$kvNGXG~C#i2Tp
y\LtH@/INe7|rJpV+74QV5uFApІQƄ>EȎ%+έ߽W9U(YlTn}M3N{V"|vsX놯kY6>K׊Gz?w1t{HxƜz:Ne
Q~6CGWř8JN$Nߔp 4)x'5FB\㟮L"<<g! GbA
/	       VMo6WMN֑wh7@NH8EAF&Ur>d-sfg85R_}̵ډjJEрFzY:NO6`saJs2U{3Xغ@(GIa6g8FQ@HZG^^ݮ`#
LGάJhOs2=Jdޢutp \{/T52R*'r/9ef,Vȕș772)٦FH'ܝ'
%':H**X-M#Z3 }Vν/TVl<Fz2%ed#ϔZ>h0,fXjWhq`*cd}gԁsGI<SA5Jr]ƞ ,_fLkfpA	޷+Q5:d]ּuv*4]_ZZYU1,^9 >x2z }*CXިt)Av	r+jb4~8P/;o!@pqQIcMQSk?OhR$,QfIo
#/dU`.[|Hϯ$]~dy(*??p0,6dsn9qkƟ[7R֮ܽz_QRڡأIiێ=2B2ȸe;jz&5ݧp暥yv0v)!\7Zq"sC1-Pnm>ODvzMA<ޘN,L	}C,;a;;>Wujitcɯ==+GwrQbN"Jca@Ɠ[ܻx!aP	 lJNxnhg(r4^,\Y	 /t{ QUƪ]p9] ZTVQh,&pn>D=u}F2nE3S"w7ttqM$Fu2"v^1p=vX]ͨ3?:I6Ňbi^FkDV(WܦŦ*	|m%&l\V&wxvtgg^PdI.SA=82^Xa&̄)yxhf>0>	>
/       Yn#}Wp`Ԛ[2hdMV/_v@)3fII"}SMϚ*Ω*l}.+Â/`UrfY\l$
j-ó=kԂLM	X0T["f=6DDF"Yq" KIc&Sv3O'l!v.Ȣ<[+Í\\942RA}?cl=~lV"Dμ 3|-ScFYKD3xGff<kWSh%oNe[<	]e䩵~=Lfkvuzy{6x'MfO л{ke4[2T;1٦X=Lp<hȆd8[$ kJ^K\%Z}YGliQ2]+ZaB<tIJ)_c3)$uͤ~uɚӉڑ-&^2`Wj\);iVl8y"͞L?|e<n杂0VkQy#OďK=)E@xH%s~	Qؐbj~YԻ ['nIxRDJݖtZPޥZ:,Fh)e¶R h-"HcUAT7u<q JYJbmkopQY=ܶ}OA/
{E[J1rE߿j0EB ɖ'cb\qE?hNFw5bX Yy2"u!c_,?8O<W;4{~?$rH\; ecԜGźF"-]SvĘ B5h!y.lCA߇wiw-~wOn5Ši6(%רSBelwij9T1WMZ>Iծ9}]OSX|+l7F'=d7nZ +¶),Y95	T	s#R=OicDL,e~]K(ZHK_pc^NwuB%;pA-(D,	*EvXGKY&
5Q\aXaVP`K'&'i=W/YQ5A]sD<hgǄ4q_:TJLx
:9Ʈm(8ัV2CƞDJeDc GO=hFTUEÔc,j7Gүoik#K"c"tZ WLengO|37bQIw5pqb.A|XVF1:D3UBRP}E`RnQul|##-+-pĔ7S&il4oSw*[GUk?)p]^Y	/Vu:#ƚ\[jtVMbRH!.TsN=hVԎ|^ghMS$`{2	I\ssaDCr7%Sm"m^D~׷pݢDsmlnD.tti]ߐskF	0{։@!<f!hF5*`y]7;dw7M.^cE5|Ս}3>WB957J-ϪH|A q˚ LT\E R+\ԝ@?rYucKJ	XEDjZ<:#nyU 3Vц>{ܓD_UdmdzdiYVj9ݷVE7VT6EtM*p@6ͤh!oNpL8T2ǝxҫDPfvtDF`-.c	1>.~6#A?r+Zc˱u(/p$?v~턝doԀ|iPM77
&XJyK]fwU->'
Jw$T=X[fGK_~8g/签ڝ)b,(q3:%}v2ǽvCP{G(:a~,;Ϣ9\+q4U[ҡOX       XKo7WLNZ
-PXqQVP~ı v)-\B!%p}Dr^oz4\)>/d ޼ܖNJ%^qmJ4wPb{Vh49SrZ*g˂{+`
nN_iT<gLITYM3Yug'˛	xHn+Bwq~neDD¬Rd
ZFU^pǽfC3s]319nvD
d5=jnq<Wv*6t=]pۤbVb34I#= 9.k6ם磗/K8eTv	КD̰ӡA%Ut?+ӫ`[0aڋsq-?ANC뱟`2{&:ʁ{0L\ڻ ^em&:ɗ~.giZ&ʇ)5j{FGM榮wב5f;|79z'L*Ȭ7\ѡhUYÚTLM9
t+Jش6Xq5RFoA1tbι6L0`p6?B#sS:{:gkWv#ZD
7"c$XUSȶ
3hB+h4a>C$:SdVź6bapŎ16x51`',e{΂/~[e`>ƢFc`0sm|s!UjI`}GZ IaB-zJ(V9%ȥ95t`e$3%}Q89:|ksKϛ/w	"H&xʉA 2:aiݖzaIS3ɺh2TTnӇ*'@IG%:mS[8d#\ƗCc?Qe7{.6ߛDJ"XNԛ&L(ҘW S˝MCMzIE(^VQ[g>q.S*tt%#GØ]>(P^,78`#cKv;m+1L1MAA^SU8rל%la5u]ǌY:LqxE.rJMO	~AY}Ld~3>i`g>4@\MBUlhrSnw֮ghMNzCo-G{Dǽ(ɜbV|=v{Hnsj:4}{sĤK͊,6QhD$P(s{uz;lVbp7I0Tz֋nZo&u܈/+1ry84s4'W>]]|<纷]	-k]\Vlso,U.k6Ҙhi=g1~0`{Ywv F	ڶ!M#~K8U4W[V8Dϯa6,ٍ+*"LNߐgWԜLa@wgwVY]!!Ք=p6%Mx;a"?|bϜ֏')       r6_xvJ*n:;qę>t;< &rҴ$ss>g8b`sQtmlΤd2h>g,0bn#,4)TgZo(r8{}s1n'IknKbK L+]	ρ:|sVBBrt$PG)ݩ4K];ǗєJ:U<aGI6P#܁u*^؍v3`R]o_;eO#<ijB6V֐
2-_2XK%p/1Μ3bY:!Y4YxЧ#h8Su\`Cbq)"wn\Rk^<
@i4XP,ɱ,hns|i%w4zgNZDaU
'l\aOkIRD$+A	.	i-F98XwDIKKj+LNQߍU+648ۜN7X㐯6[/h]-B#}`t
hvrI!]tϸVϟ-C@2@ylKEHVPۢ!owyu4Z5T;+7|I2\MV\t76(:Axr >BpCi <K)f8>n%g]|+2ø)e%bE`
ӥ/0`\5RRa=S٭Ηa[L3YW. #=ۢ%.[:$>@'#461j	l*/	%{`rdǜZ%<65ZJ	K1"%we78^5JRkL9Sz5Q̻.My_{ÓGI@|2>EJ,tnv4Ex(bx}zH顢1iGow
NCFi>ٚb5 @a`yD[#
ɂ6%:~P-rmXKE[Rl%"lm>h2VLه_[[|<̯'mP@%Y[ġu56J\DJE/PíeF*!X6|7dBA.Kq1i_fsۯ뿡n(í}OJn·upuXߘTOg^YZFV!CgzKuPbיWlP<m:-(ؒz%~4\Pb?/PHҕ3>~#u3eN*~jR	.TPӧUHZncL5t5j[a.n
Hfϩ,)//afo=tmO֝=ϭw8ۯzヴ|I.b4Vihz(=ubxOA[)SOgn?^zch_HY2:2cƬWeesLiCi^xy;7ӢaM0%7- x7`jZc}o޸wh2YtJ3!+3wZviS؄s^w87X:}u3F?uD#M3ZTԇ!^`'EU;	Sw~~XOq;*O*W-GM'_9%tԸhDP߻i|<tjCop1ٸ̉v!u~ƜH65Z8MX"ʡ6zWs kDX[;8~^ňqW__])*FGat,66bnslɁVU?P#}iHvO(ZsN,bRGcg~Kݭ^%5s;Ī%md1|.AvN
J0x<4l*mH7kp8rk	&zFxtS?Ly׻S8l_f-?F;/]旡53:~JuFȬZM݋Sv|qqg?Bx _#.CVmA|V[:q38yzdg=.on߽[/.{RLKjc&`nGmw:U~y4r]ޢ9-?,	
Kg0TbZ^a!d={.fu77Q9_"_	k|?Z~~~cn6WU *hoƫG, Q?(xNhKԾvubüI1:U/mjCW0;>d(@߱<##Lxwa2&vїIo>5լ(       X[o~ϯA%mmI{ۋA(rhL"g~fx-N=ED3ǹggd$֚iD2_32Zrz-a#H+v,OȭbD.^sE,TfJX!XF{BE2+y,kIJY0Դ@gr:\%9ONe)Rͥ#dG\ٳ(0@j_˾z$tt'_}CvWILlcB_r`E1
 C> @gYHiE3<R#(X#`βa:Q  ||_?MM4եR̮b.V|S)V{t!K=="<~rKR+P*b7Pwe.¯ǕUAQp&*GX1@GR@i:'Xc"'LVq3۫׫ѤI^__N'p>a2yerLgW/)g'LnmÛqr*`O.[MC>oYK"Q`}>ro{Hr$?LAQZ0YAGl+%+.vOak鶋ܰs~NPl*+,vw(I{2;*#Q0]5v8999{'|y7[R} KLw4IՠdZJM	,z-n/6W-j͝gw/p(eW#D0)n*%}4+hb|`(|I9??~]Lv w8Yeߝ
y+輶{}tocm?ЃQKG4="|S4W.ҼX_mYZQYȲFLA'AyþZ,m:QE3G矆h0A7tn;oR挊1f).3dP%ppke-Wc@P\/kRy=8EVg$@Se&T`.$I).Xnr]MESw%,hkQ GT;+)8ʘAe>/*sl#Cl;WE{*H	vgIF7V>qɧ2NAH3[;-|	q,D.iv1V,60U!bմ?5'O9GFYj;:mYw VTQx;oɇ?ǿI. TL6AhAW_jW7.G_Q-xS;v 8!	f舃`+ʟ4XzΥ_QJb6[j{h9Mf~Z
=^Н.fM(9Py͆{LŴ,
D4{\cSK2,
[z|$f?qF}[ԁ?I%)\(nj
l>cBʚkt d kk'NhxR4#E3DӶD/ݽl\-:SRsUkDr,<V*ZO8+ڔchxiTԓsqυlCldomFDCrNhqᖆ7zS-3Fȥ\ߢ*;mTYe~[c[dXM!ZN]r"#i	}cʜ_%)a$8RZh5C+N|w[a3Svזp61G`<wEp,T1N*" ^4=LR|e01a9S"I<PCyHTWwYޖCi4Rܰ9l4vB,ΕTᡠ9|+ QLk?ǹVGnj/LPB.t5=eQgBx=]|k50=
{ɔn:W	κ	MEW5]]r2^/>7;s\##u Y]#       T]k0}ϯHv쩡mk4P[,INJ,;qd,s_Nan[2@.Jyl
nPZhЃCnS
B<x[; DnǻsA+h7Ĩ#/Rh$RLDk4
|M`U5^G YM!|pJl6-
wʯ5F lKi*Ã2m]a 
	ͽ5d)˺@3ImWbJXLkF.v[yʽ?.~Ύ#̭U/bO}fD>q'J+N3|Ys#Qf}-NRR!u1j1U8N՞4
M+TR 5	a6_:kK;4f	ӁSkmѶ`;d?aEj*|	\GsW$Y+3|׭P~JM_}*L]EiiLf̭\=0.3?Ԯo]g5_^8Պm~t6o0bGҊ:.E|njHDhkȒ4y4$֒       Pn0+VjDc P	!!0B\vHCEvgfgF[UPcOf
Sxm|gB '.af-BBF:cSfUow a`H#h uH`y.Xz`FϤUZ9br0.˗z,`g,Y	O>*/ &,TFAI	.b`>Z#OSƏYvVڥq'h:)(iy_[żR]鶈5<9>,:)GM|{iaWSEmeQ5,טAQhOio       eAO0>  v@pQkDLSTwvC;E좀zg5elkBu^i`ypuERl\]s 4F!EגAI`(#lviP$rBceTP1'vH9TK~8?vn=0p#3gbg!p:lt$;Ô"ʎeK+9I+1Z637+98:&$*w}C#QC]ZLISy~"EF       }Vn6}WLSe)ud$]lEQ4)|/1$q8<sa&j,CÏa#Lsʢ.ᾶ҆h4WdF:FU@Zb>>]Q(i͹KX˔Z&PHy:{yAZd^~_ͣA!3k3yPٛ$C,1:JGC<ZVieUlݯ.z~i^h,/+r.tۣ͍u(*`$hQ$R_{!81VB'VЩe*,UB)\nRQ9SjC&M&V&~>!͑Q 
I<z{A$nB%kԠx	9b]>5WчQWX	4lʅXxI#6eL ؁⚗)9_ɯcAPrvpC<*5>(Is5amjw]ڌ'qKªmJ0E4@GP-~Y53HјA&73[q1%7mV|vnQӯcx@_ٞ +b*J^' kH@>;BzVd/.D-mڍ7-[EӞ
ck˕re]LKlȊ"ɤҍ4uXȒUkhhUD;7;	t]zYe"	ۏ@7tϼ;?|3&V9~-4	бm8 a!󹷖9i.~UY=Οfˠ#ռR|.q,\Ԟ.nx	JYe2H|&Ћݮ+$[r<"BY׷6ѩ8fݍtpc+ݰ@uJĶK6	  // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This code is used in conjunction with the Google Translate Element script.
// It is executed in an isolated world of a page to translate it from one
// language to another.
// It should be included in the page before the Translate Element script.

var cr = cr || {};

/**
 * An object to provide functions to interact with the Translate library.
 * @type {object}
 */
cr.googleTranslate = (function() {
  /**
   * The Translate Element library's instance.
   * @type {object}
   */
  var lib;

  /**
   * A flag representing if the Translate Element library is initialized.
   * @type {boolean}
   */
  var libReady = false;

  /**
   * Error definitions for |errorCode|. See chrome/common/translate_errors.h
   * to modify the definition.
   * @const
   */
  var ERROR = {
    'NONE': 0,
    'INITIALIZATION_ERROR': 2,
    'UNSUPPORTED_LANGUAGE': 4,
    'TRANSLATION_ERROR': 6,
    'TRANSLATION_TIMEOUT': 7,
    'UNEXPECTED_SCRIPT_ERROR': 8,
    'BAD_ORIGIN': 9,
    'SCRIPT_LOAD_ERROR': 10
  };

  /**
   * Error code map from te.dom.DomTranslator.Error to |errorCode|.
   * See also go/dom_translator.js in google3.
   * @const
   */
  var TRANSLATE_ERROR_TO_ERROR_CODE_MAP = {
    0: ERROR['NONE'],
    1: ERROR['TRANSLATION_ERROR'],
    2: ERROR['UNSUPPORTED_LANGUAGE']
  };

  /**
   * An error code happened in translate.js and the Translate Element library.
   */
  var errorCode = ERROR['NONE'];

  /**
   * A flag representing if the Translate Element has finished a translation.
   * @type {boolean}
   */
  var finished = false;

  /**
   * Counts how many times the checkLibReady function is called. The function
   * is called in every 100 msec and counted up to 6.
   * @type {number}
   */
  var checkReadyCount = 0;

  /**
   * Time in msec when this script is injected.
   * @type {number}
   */
  var injectedTime = performance.now();

  /**
   * Time in msec when the Translate Element library is loaded completely.
   * @type {number}
   */
  var loadedTime = 0.0;

  /**
   * Time in msec when the Translate Element library is initialized and ready
   * for performing translation.
   * @type {number}
   */
  var readyTime = 0.0;

  /**
   * Time in msec when the Translate Element library starts a translation.
   * @type {number}
   */
  var startTime = 0.0;

  /**
   * Time in msec when the Translate Element library ends a translation.
   * @type {number}
   */
  var endTime = 0.0;

  /**
   * Callback invoked when Translate Element's ready state is known.
   * Will only be invoked once to indicate successful or failed initialization.
   * In the failure case, errorCode() and error() will indicate the reason.
   * Only used on iOS.
   * @type {function}
   */
  var readyCallback;

  /**
   * Callback invoked when Translate Element's translation result is known.
   * Will only be invoked once to indicate successful or failed translation.
   * In the failure case, errorCode() and error() will indicate the reason.
   * Only used on iOS.
   * @type {function}
   */
  var resultCallback;

  /**
   * Callback invoked when Translate Element requests load of javascript files.
   * Currently main.js and element_main.js are expected to be loaded.
   * @type {function(string)}
   */
  var loadJavascriptCallback;

  function checkLibReady() {
    if (lib.isAvailable()) {
      readyTime = performance.now();
      libReady = true;
      invokeReadyCallback();
      return;
    }
    if (checkReadyCount++ > 5) {
      errorCode = ERROR['TRANSLATION_TIMEOUT'];
      invokeReadyCallback();
      return;
    }
    setTimeout(checkLibReady, 100);
  }

  function onTranslateProgress(progress, opt_finished, opt_error) {
    finished = opt_finished;
    // opt_error can be 'undefined'.
    if (typeof opt_error == 'boolean' && opt_error) {
      // TODO(toyoshim): Remove boolean case once a server is updated.
      errorCode = ERROR['TRANSLATION_ERROR'];
      // We failed to translate, restore so the page is in a consistent state.
      lib.restore();
      invokeResultCallback();
    } else if (typeof opt_error == 'number' && opt_error != 0) {
      errorCode = TRANSLATE_ERROR_TO_ERROR_CODE_MAP[opt_error];
      lib.restore();
      invokeResultCallback();
    }
    // Translate works differently depending on the prescence of the native
    // IntersectionObserver APIs.
    // If it is available, translate will occur incrementally as the user
    // scrolls elements into view, and this method will be called continuously
    // with |opt_finished| always set as true.
    // On the other hand, if it is unavailable, the entire page will be
    // translated at once in a piece meal manner, and this method may still be
    // called several times, though only the last call will have |opt_finished|
    // set as true.
    if (finished) {
      endTime = performance.now();
      invokeResultCallback();
    }
  }

  function invokeReadyCallback() {
    if (readyCallback) {
      readyCallback();
      readyCallback = null;
    }
  }

  function invokeResultCallback() {
    if (resultCallback) {
      resultCallback();
      resultCallback = null;
    }
  }

  // Public API.
  return {
    /**
     * Setter for readyCallback. No op if already set.
     * @param {function} callback The function to be invoked.
     */
    set readyCallback(callback) {
      if (!readyCallback) {
        readyCallback = callback;
      }
    },

    /**
     * Setter for resultCallback. No op if already set.
     * @param {function} callback The function to be invoked.
     */
    set resultCallback(callback) {
      if (!resultCallback) {
        resultCallback = callback;
      }
    },

    /**
     * Setter for loadJavascriptCallback. No op if already set.
     * @param {function(string)} callback The function to be invoked.
     */
    set loadJavascriptCallback(callback) {
      if (!loadJavascriptCallback) {
        loadJavascriptCallback = callback;
      }
    },

    /**
     * Whether the library is ready.
     * The translate function should only be called when |libReady| is true.
     * @type {boolean}
     */
    get libReady() {
      return libReady;
    },

    /**
     * Whether the current translate has finished successfully.
     * @type {boolean}
     */
    get finished() {
      return finished;
    },

    /**
     * Whether an error occured initializing the library of translating the
     * page.
     * @type {boolean}
     */
    get error() {
      return errorCode != ERROR['NONE'];
    },

    /**
     * Returns a number to represent error type.
     * @type {number}
     */
    get errorCode() {
      return errorCode;
    },

    /**
     * The language the page translated was in. Is valid only after the page
     * has been successfully translated and the original language specified to
     * the translate function was 'auto'. Is empty otherwise.
     * Some versions of Element library don't provide |getDetectedLanguage|
     * function. In that case, this function returns 'und'.
     * @type {boolean}
     */
    get sourceLang() {
      if (!libReady || !finished || errorCode != ERROR['NONE'])
        return '';
      if (!lib.getDetectedLanguage)
        return 'und'; // Defined as translate::kUnknownLanguageCode in C++.
      return lib.getDetectedLanguage();
    },

    /**
     * Time in msec from this script being injected to all server side scripts
     * being loaded.
     * @type {number}
     */
    get loadTime() {
      if (loadedTime == 0)
        return 0;
      return loadedTime - injectedTime;
    },

    /**
     * Time in msec from this script being injected to the Translate Element
     * library being ready.
     * @type {number}
     */
    get readyTime() {
      if (!libReady)
        return 0;
      return readyTime - injectedTime;
    },

    /**
     * Time in msec to perform translation.
     * @type {number}
     */
    get translationTime() {
      if (!finished)
        return 0;
      return endTime - startTime;
    },

    /**
     * Translate the page contents.  Note that the translation is asynchronous.
     * You need to regularly check the state of |finished| and |errorCode| to
     * know if the translation finished or if there was an error.
     * @param {string} originalLang The language the page is in.
     * @param {string} targetLang The language the page should be translated to.
     * @return {boolean} False if the translate library was not ready, in which
     *                   case the translation is not started.  True otherwise.
     */
    translate: function(originalLang, targetLang) {
      finished = false;
      errorCode = ERROR['NONE'];
      if (!libReady)
        return false;
      startTime = performance.now();
      try {
        lib.translatePage(originalLang, targetLang, onTranslateProgress);
      } catch (err) {
        console.error('Translate: ' + err);
        errorCode = ERROR['UNEXPECTED_SCRIPT_ERROR'];
        invokeResultCallback();
        return false;
      }
      return true;
    },

    /**
     * Reverts the page contents to its original value, effectively reverting
     * any performed translation.  Does nothing if the page was not translated.
     */
    revert: function() {
      lib.restore();
    },

    /**
     * Called when an error is caught while executing script fetched in
     * translate_script.cc.
     */
    onTranslateElementError: function(error) {
      errorCode = ERROR['UNEXPECTED_SCRIPT_ERROR'];
      invokeReadyCallback();
    },

    /**
     * Entry point called by the Translate Element once it has been injected in
     * the page.
     */
    onTranslateElementLoad: function() {
      loadedTime = performance.now();
      try {
        lib = google.translate.TranslateService({
          // translateApiKey is predefined by translate_script.cc.
          'key': translateApiKey,
          'serverParams': serverParams,
          'timeInfo': gtTimeInfo,
          'useSecureConnection': true
        });
        translateApiKey = undefined;
        serverParams = undefined;
        gtTimeInfo = undefined;
      } catch (err) {
        errorCode = ERROR['INITIALIZATION_ERROR'];
        translateApiKey = undefined;
        serverParams = undefined;
        gtTimeInfo = undefined;
        invokeReadyCallback();
        return;
      }
      // The TranslateService is not available immediately as it needs to start
      // Flash.  Let's wait until it is ready.
      checkLibReady();
    },

    /**
     * Entry point called by the Translate Element when it want to load an
     * external CSS resource into the page.
     * @param {string} url URL of an external CSS resource to load.
     */
    onLoadCSS: function(url) {
      var element = document.createElement('link');
      element.type = 'text/css';
      element.rel = 'stylesheet';
      element.charset = 'UTF-8';
      element.href = url;
      document.head.appendChild(element);
    },

    /**
     * Entry point called by the Translate Element when it want to load and run
     * an external JavaScript on the page.
     * @param {string} url URL of an external JavaScript to load.
     */
    onLoadJavascript: function(url) {
      // securityOrigin is predefined by translate_script.cc.
      if (!url.startsWith(securityOrigin)) {
        console.error('Translate: ' + url + ' is not allowed to load.');
        errorCode = ERROR['BAD_ORIGIN'];
        return;
      }

      if (loadJavascriptCallback) {
        loadJavascriptCallback(url);
        return;
      }

      var xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.onreadystatechange = function() {
        if (this.readyState != this.DONE)
          return;
        if (this.status != 200) {
          errorCode = ERROR['SCRIPT_LOAD_ERROR'];
          return;
        }
        eval(this.responseText);
      }
      xhr.send();
    }
  };
})();
     uj0DvS( YZ[֬Ss̼ME2vvGWXRCx@	BFQ< ;xC0l	Fɢ_r9)/βFGTkNx;w	Ԡ([w3i҆|==B<^QYm8ԵEzm
g       S]0}^hs'wWv}^dd7MJ2ݵ|H39Ng	E.]`5:˾f$BqJcdIv6%+4>GsmBX݌<zg8PhcI\_]B8'%pZI9Z8he[ep#PN"=(a؀ۛ&H#	0`Rj%hWn`[ر"|Ο&l'ϗ7ׄ큋'F8>X&$^>Fi$eV߼5|2X٨npr%=u N1MI~(m±вLic\TZUTvg^`sYK^9 ${g.       TKo0W0 N{lP`YCaBX-,(GJIӠE|ŏSU0&eCp5a١@YBE1ДEUSDF~A{K@?n/"mZjtF"A2ig:>Gu?pbYiST xVwlk!3-"wU2Q`=,8XX,طjYGkW(3"ThWlͻ^:)ZAD齣%F9E29{t%2gh}I2Fs&#bUyJqy~vӊjR3eG֊L*
|x$Yf=:	 RѴ"0YZ2~~  UgFxD9<G=902׿*pFB-pڜv%y
ơ}m03XSq߲Gh/dz FwEy(AWP)	;OnީBR s^E3&oW:+L&SI:_kq)V' ?Ʋ[+Ί       Rn0+FBl)xOe	qi Ǟ$VO8vvE=Y<3oޛ9]Nb}¶qꡅ7؃=<zDBX=:
|z?%PA
%NVGm{*m0iFB.&3I]=n&ĸ"Y!uQP+\-bɲ74xtV<=f$ž>aiŌEddڙJi[?m#XP	aI%Tz?csӔ%9hqbL]#*0&K3EkY	,\T2̀6I\<8!svp}bSIm'xlŧɊʖ;en]Aca%ZmF-YJL{Mż}YɐyGR>}%_$&       WM WV!Z%tUWD`bc8ݴ/qv΍yϏ w%sl~J]Tll|4bcL4pWCxFbź1eD<&|5s@Fxƌ\8LD@yҌ5J-)gFp$pk
HY޺	d^K&ˍ,Xelsqy҄.f́
:;MR[T(hdk[kTE#}'M"J]r[#0!zJuz+{rg{$uuX~{z|΄~d..]r( ǐ/­pPdBH7}[2W0Ӏf9GAb:
TM	 2l^\j;X΅"c=xTrT%͵3=XI/t'U"P3m,za7^W*Ovwqudԭ{Q]/l˾׷m,b-sKb.[u|S7RUNj@}tJPePW8-}<vJsV &bx^՗:-fd گT^%bW0#lSqc.l甴\t:I&b\0VH8'۵}VPWT(iMi抵/?K
v       V]o6}HyK5EuEU"5rԗ%[jb6,{ΡD|&GS7o` V(2,l	2MhPo2*F:BGˍڢaWRTD(ff!b*Ūqbb0'p!K5AL8wD{6)Rakh˴`V(i*)ʵQ%"Ϻ)/]l3P],JF`J̿L.fj!7;߹W2\$.d5F[h}+cLi/Vi@
8J E:"s;L40CatYڃ6vy|N)vΘ娲0])!"r. [ܺTjRP n1w[qTUʑz!K".h݆JZ8RvsJČ-=HҸN!G~[Oһpo:un[zpe|kصualߤ$|؁?cc:l[|RNTy|DeFyGVhe)3((:{tkl
n OO<Q𵲘q3/*Qq{bNTQ^]ܘP~b,vf
c_&۫~Ի}ڡgw݋C&}`+hsϚ`
u!sF 51K.Gv5PZAJG@T1+yGcȯZ-=oy4颶 ҁ0yح.Ji:|y_gñL+wI.WQ-zK%j߻D:]       XKo8Wj4ʊ6=mZ[LhR i;"}zزItOC"f83w9WJilIwB~@cf|>#gs+mL2^ KDM!Fu$R.jZ#O+D$1$M\2%|8dt;?^|_??¸z{^pkq	JyDP9-NA|$6`N^e0:Ks0u'AK]21Ha2"A0 2&tl=]Ē)-)Qp Ert:]$7ٌ~it3)tHt|?7NoU^r
RפMz ES.VB6-Q3	PƸ8[OL!sW[fWTN:r2ܥeN-_@E\Td}﨏{GDUb?*6QEm"2$1gdэ[gh2"ifT O7nk#2IhiRENNȉy>蛚#~dUr0%f`4=-a3*?E5ُZ='	_5º bEpBA2ԝݻ{͕urqv}Rm3MPtXI7^Z`&t*dtwEǞM
q1%3( ?3p6
x-]s0CPq.t_)ZĆv q!	jLIM^Klo%2Mn)ό.TbGċ")·#m]?@bw;Cr!#5*εo$S\z9G 91n{^VQք+7e+Z~ssPYpWcn\|閩oE15STBd^!KϧussOriŞ
}5"9Gi	^."Xɷj8 (6d}	i;p]mz;3a7Zd\Q#8D~=4:$aI>9\qbf9YK"Y"6ߚz0=LMx|զkXW.xݢn)yӹ7[lR\e///3nKŐ|K)M5Mn8v[]wQΖ+Gn
w#;ܼ_U7FehS|rtjU=rmͩte( j0ce*e*#ZKmZ\e.\~{Q#[HT(;נiXbtAsE:3;el>]9%ڄbɾM*v8b5Q*52/>Lv       ]s6ݿݔX\Z7rx<,5] l'~a#2*2]V̗eJ7+rEBre1RRF{GGFI 2e2$.J񶸧eNr%yw1jQ1ZFP(6yB)MGH3eESߋ8&|9  QVi\yXJi:x2?.1>il: Rņi2>ͮO>|&xK+0z=Id6OȄf-HNTI1$at:Of]EybkL.1]4>6'@94M:=8>$=@fAa?UDUG*(DQ_>zJ	P-zc41G|3*}pʧqMIa_|`yhϳdIsapN1<J}rtA|	Xo5{ܔ4GP ~	h^5TSjS)we`A,eZWepvRADWa!ITB68wt#@Q.1.+e@(?P&ښtJh]`ؼǅkok3VFnDQ"H`%+ap;۠͠(5jp37
#oe4B3Ȼ,~2_CpEY;%k3l @'QZ#Nj(jʪh5Mi飺}		U9$wA)AuKjXC@H3q4Hbp+8/=Wsz~z%*T,zg#:$r{!rtkؾLvREQiܿNVxz+ c-fucC:h'"dyi#d?UQ\ZQsˬM[V܅S|VBVQ	5] 9~	 ƏIM?"sz{P׺VABd3KO$WxiNciժ_/-a؁B:aubm0Wݒյhآ}ӽZXm^\znAa2`a7˫]7b7lPҶr؂TWq;y'1aEVGJS`ɾL-*XZ !1X<Zn.-]ںE
xib\VwoyQ,$!ȡk)q3&'kn$r->:+{hgU	ʛ;G⽣O?u$~;|VY7|:l@X
bkDkm\=^DS8t7nHG(fAmzrmjqOF>ETCz]]u%oAKWͻL#&%2*
sM:	0e`ꁢ~xέδZ&gɤ$>bhG.G(izwR0HMʘ5TP{%&E@mbkxi{AȚjÏUq })ħC>gP|Sf:Ψ>GN_f#]v4vdsݭɨջ]kFwWS3M4zݕ^M՜^OaP,ޖh_UҾJK?S7w U^~ʆ3V't!KZW GCG} "K(fA"V=~mc|}a놢)^n(blStLrv5rTV,_!)%[Q9g4ǫ6ȚޘTm2ӶM>쑷&TK5F+ȇs^nxSٺj8J,rBȵ<_r]*u7:KՖa[cg2jEIU\\\E(x;<
Ջ&B]yW"ʿd7 O
 *[SnO1;I<%<9Ek+EfyHx$YAlк8HaCE''m geػyx`qT&#8qz_9%dԀ_sS$[c ?7KPt<s9/Λn$!+!o?~q<˒.:A)^dQ~&heSmXJ#%q^e/a23ZBnh={vB(Σ[`(Xʿ%>:U#,ׄ KR>B^i{h؇#tP :	ԉ7"{7?%XW8lcUdc]UgXsu|ZDyRj$5}o
6"y7pzB(       Tn0+5BG_rJ
 J\I).AR"^Qv"@jwfgv)l,+I/{,ղY7{Or`ѡݣM`
?+QcsB,iV>=~f9P+!2
j C÷(Lo'7&y5u~N 2JUlOHXl>uydZɤChUIěE_RjT2耐1ÅLa>|=k)JM;+x'HkI/Ia{l!(	W$3ஒY(JQ40vS+)TRgB?4b	oMO?Q)itݯ
0gx]~kvNĂ{AF<{ԩXFM/UK6lX,/`5ײ@iѫ>mN^˦1IFP"p_~N3O~[_=[A.4-  PNG

   IHDR         a   RIDATx^SA
 07;:usKHjtAa%81d/<sZh(;*0>T8|!姜?S: [ü    IENDB`PNG

   IHDR           D   	PLTE  V   tRNS @f   cIDATx^I
 ѽYJpNBW+Jp Tg, 32 s  B}QIVըju}0cicpx3^+o:    IENDB`PNG

   IHDR         J#+   IDATx^10Ec{.T¸Lvqve1kp	#"y$\^#3tT*ath2um!D`(BW'MB<r}@g|31>#bi@sP
HLT*3shsãm׷3{}\#:uBn|USgL4ݾM]5ףm    IENDB`PNG

   IHDR   .   .     IDATxO@p.p'eNZAb71<BUr@͛SHަ&*^QT B;0x0~l03I`C[pC%|ABX+؀OsٶyYVFmnŊe{Nn/t'/:#Cf}5MH?/LΟ^+c!Gy9rNew-n&z)?95eԵrC#Оk\-9p36}2w-~gew8lO?JC/rȪƓ$K3gi[,{OZx©u	AdZ8+z<uKZw$ZQx_   °bTKsbkqʭcQg.tEE*Fe
W/_b@a    IENDB`     Xo6_(R84mQk0-$(#aYLXyO
"T{	[/Kcr~zvN~K&ZHMaMHI<!~"baQX@gtAy5v!HBl6a,#SE8./oI$${:}٫Θ,.½'VJ, S
0
f6@2sm20Cu 	#d	DwAS\:wai$*1$w7U|BC
igЈB.İ ^֩GyaZĔ!S-R%WF8cݒU9~[B]>9#,xI1lx9@/Q̃!rP	wDND= *HQ޺i$t>r"#C
6t.A;{\SAi9$(ފɫ1_U yYH2UϨf̎.̘ԉa=KjNuJՉ]z̪PIrCR]gh*l+}` h6Y-5ukZOeՋ4ZuLK}K)N'z_ehk(ܠrv9=ʷ ]Fϵw~q,K3RStɰ-{wq9
I &Q  {/v3`L_ǱcN`j[bttIQgOz  fXQ x$ Raa&X
,sN?̻R1>"	g=Bb";3Vc=ܠOw1M]Kǅ$ feoMSAm{7鍂i;<ZRO~7a#"wl#ŧA￬
%38՝x*AE4(dKH\L;Ko@EL~_m9Xr!iWj@{NZucPzu``VN9eF"ުjj
./>BuE|?ԓҩ=udh_\~	C<
܃?svg`hYjG:uf0 H^qÒT|L(>	9smc|C&T;vw]Jnyksh+N1{4]k)~.wuC	ȝ
+З6iÊFJ8\&n<&;:E_CRH>`"-qBe56tCzЩf(k8mmP=Ę>r\Uk_,;.;D׃ukV`
#OdNk7Z
S*ݚnr~jJ-ϴiɮK,&|.Se,3,8ʶ	Zu9|6_HZm ;SsO;_!_ ?'5Í       <r8
toPjT:⬷:nOI*r\)DBu>BER[[31Io 4,|.(/~ܭ9_نW*Y!B:I(H+YM`$[rYUDDY<GV,&-DۄG,i嚖$)Y0̪4&<\_]%OXx_0fKQʫ`BU<KGc?π;%T#E`lG
.K}"*x^
X 

ȞڐQE*E`UH(.TUЂ<ENWlBxYm
KL\n&P5RQUTf|3IA^/auBFҬDS$g0Wz27LX0q@dfINx&x-`.U!nATZ쌀8c򗿘5$[_I|IFC!!߅MM*qUaT0Z˄(Pb4l19E p
5)PDLȹRy)>@W\d6yyk埏K1ū#$Y[-4Fi [f"z\,C/-)딗&O7|pCyp`6\Ӝs>*r3_!9w)qbfD	lg|Z:B{mx\$U+0(
1afKK%L@OHk^9#==Cwf,P.rZFk+Od4		4
sOj:_t<;wⳖv?*RA2TO,V/L {o!K83wY0/åB!EŔ+[=u*!%+1𠝬mBʩE|ɁWw*Y1af4)cU9UQ&F萃o_FGZh&rI=uqTcQIϱ_-v_CfJ[j 5h`e6+Xh4O>@ EB.u'	Dn4>A֨	,qO(_fhҥrsTK5IJG;,;x(''rYY1
}	ȱ=XcrW
<v(1%06VvGW1KX!+A*k0i/Ak:mB4:}eoKz-?xD92	C*9I8:&1kTRsQ0dյMpVt\I@0]QȢ/F<CNJ	ƂFb F hpݼ16rbB6Mi=)A:?J#{<Suz47[Scb* *
Xb)}t^ =ۖ cThH5G;ywUWXyneZ.K߉%Tk4u7+|cKQ-UِХ5y	KWpNOqyK`SܲK㤵IqfKbTr
]t f~2A@__'(Ы[u[3rX&n0㌦"	$.\_ˊ;Y0?ݐ.J^c>R8ͼpHU -rP%HX^.)Wu)hOF>u^l+IURЭ뿳vިbM	cHu=+UJ7aV'.c:)ԆB5 a A: 4&
sPaq%hP۽M$2ec=ll10
y$:{Wd	p*.Ӕ%u_u3i9c~f5BYni5zfV({,֕כiK~A)+F^
:Q&f۱gvoʄ7Mq	*T' -,S~!'evP-c1!*-̠U})zNf4l|@Ĩꑲ/,:6E3=	l$08	0p2[2UI Jx8y+j:AO
i54{J^zˆ܂I+eW{&{n&g1b"=1GNq=IȿpKPG88}PiN<TPvUBa/B?.(YۖM!*Gza:G=\S<jP!^i0S;*1tl0C(B/SQDOnF?ig4v|4m?MLD.tH;
{VsJt d>2̮gL;yu-!(rJ"W7p23h gٲ|R;#q>~	&<hz5
q32獍cdB_Th5Ns)|ű]LKE2_bً2on.6.;:(=OIưlaO0D^5rY' |IYzֵC2 C((6=Oj9'LRq"ƜH\GSSA[lU4VohjV($rQv-A7!A$E<As!A6
q3DrCԳk?egZ`55q	D71*$RG^o-J%;T0'`mt}b8kAů]_ZWvֽ~4/3@wi]k?zQNl#9fbiG[ddK,, R$`tIEnՀJ'0ktD1mI5nV/yNF^4i{Jo;ʉ&a	<KK̪HMV{pcLGv|>cWq]fEEA!{!k=+=駲OtRN֑^Ξ-xVsjqxO.!G}Wy{h{V;)pܰHG(-LpmzPBu[Ɋjd{ #g,.һ>-t>+nldN=H'Ԁ2ا{(_d?ԕK[Bhƻb#I5-&-UzΉ0ثDgJؒ<W6Ҁ,`gk.~z.O}qz0.{Hku@Zڮۿ4~)G_eJzU<o'f?#ײWqˏY'5:dCvw.XrKzTzjG*l1nM֏'X%JJ.(TAeBz?Byb2/.zGq[)=n. ߩWd_YS~q,;>l+pJ?8/Y[UI<1%sp
¼\)[IO&w5;xl
J#rg>n˽ع95qJTŒF}zL}"3S|@%sʖ^Ŗ/XIUYkKWedJ$3<^_aS ̋Ik\ulZ`pf}u[읥,M!d')Āsya>c([.xgU)}<aԧa\FYW6^-v}؃c04'= vY䁞z,<Uxp"xY!&Ϡ"v>xHr\4`U0"ʭkN&+]IhLսdէlcL3Gftż̪}[\o⽵uÂqLs ipij␗9hՎuur!t^0Y7:gD0^he ľT\Qp_iz+vs?4s`RTK֝Wُ<1tv#uuЃU^RYT?\ԞQ D[mgp]utlmӌ8Y3z5_~0ǮY[g1si 꾃T|G{lN{Uqs*:df[J6Q_3pՊ>*d2#>κY}mZ8[
P֕l؇o 4X7$E1]c_h:raN\Rs?*T~Qn"	ݸì_h~A|TՃ20N"ʃ4W--dtm0#xp?]gǛ9-Xn#pe9!G 5x|O0HބndqK~RTjJl)x7j(lNuci̻஡+6)J^22ޭ)`Z±V$^r+]fVCn3{em	:1(ZSw.r={MAv0zߠ=^I*I;::͑^ir'tٕ&f_I@i!oA ^W'h|ħʲ=64O¹"Þ9v{RWHzOUwb6rvNǓz9.&ȪQS;:e@<MY퍓'v7w_35NrQ^w8oN4ZlIq0nxT^uq{o9k 5ȡU^/I#*ym\kTG՚CC@.>}ݭV8W+O       RMo0WFמ1ХZa΅"і
Y2D*[00`vHǏGvWu8--|{wmLf _	!PI#h	S@3(x;AhlVX21.i uL|,O^qiW]mD.

Xg5[UL/	Y*<j	Nnfw.J}V敪kW?"*Kqzrdv<1^\`ـ'{/خ]=]J֭Se Jgs`Ge>șDG.r,d#%gw13* C۪~v
ʸ=eLKiH       uS]O@|ϯJHvh>UT!H	T
}}ZM>ɑ};;737ab׭ӫ\WIlCq:a\@<;*hO%r[se*lp8蹭	HW+%ES@Y'.&)Fh֊wGyFٞʩg`rl@z: !Ir,+DZ<4d8mbV\P߅ṁg*=FGyry2/(4y1Zfr<ՄqDR(MW;aj銦쉂Ӡ"jk%%ܿ;o0R=Gs0,o4⦾
$Zv6쵾?{Ouyu=*`l!'*ƫP	Y#<6x$ƲD-tbn@XRj܊8H0F<|ߙUEg_h6N^fGKkFk8,źJ&{y+#qT{$0QA       Z[o6~ϯ8u<q.x1MZ`iwLч Eb"ZJm.lf)s>;IPE7a0>½'ACh?" b>131B Of҉=w?	qO쫀;P,tYL|f+a{Z>82xtLGB9+-.NqcK{1 Qf59sH$e_)(L@Ǜk7@20eLƂ8󧫟~	f<`=x?8Tt8Z)OO8нHgJEr0oi2{p;|8MH(b΅;p?Dk)|4"r8GfRYQt@/nXaCLA$59n@gcd*9Gqǃl( !݊@zwGC8;:E[0SW7?GmxyRtB
VxG像*suD<fi6N	A763e[{)u_]dNI!0ktC8󔦆1a6\D]~E,$7MRצtK_=0 FOl=$/["̻tg5=-h]OXiNXm՚T!	
E>Go>ͣx2	I=O1b-s[nEZm]RB4K^ܘ K W+$_T;TW[99POh!'
$v[(
uStk4/))|zǍe<Lq~O,|H;TzK;LB,q<^^Ƈ.b|ٰ-A	mf$olF饳RMQnYLnu4)[Jھ>XD뢸ۘ.Pde6XŶ-[F
vz>ʲvfTɪbQ97a'	X.s؁!)n*&XNSQƢuPfv(*2#mس:Eghʴsn`)JHrO\T)ɋRh5:FR>3!^J<{-?[U[:V7kbc"bY|I鉦u핶sњAxj$;)fRyYn29bJC:*D 	}Ihי]pZӞBZsE+(0K͘}c"==5'*nT(z{nՋѹ7Z H{8;^,9oRƆAmFgDv&aĔQ4⫒4KJ-#/;I76ᕨf[Dm|Cv
RvKr&vm>cXRR]R&olOR{"wdckSSءjEQo>kQ))`&<ժ6qRFFk9]Irgr|QA>]+(Fꎩ2!;VJ&:Z%-X8LҺzk_$e#W,R
[XXwBYƞ>8 02}|Yvʰ${qW2l[ 
i`N@dya~!v\xkvL٠C}Q,ٹj߰XYs4mf fMPߪ[םZhmn5Q2܄\:	Y30e6]$i}U8u
hz@Uҧ1;1/'5m@Eܵ /ǘ	YVrqy=ńw^lMs.%NOrBZH[t@^V7^M{C$u&6NV:_P.6W7hŦ\'*-nMg"ݐ&;iO%w[Q? .Jև
_C1vPvJ*.mS<[yw&[Szn	oq	J@'ʞMOi~<nu~$26
oOw`1ꧾO~?ݙ(       W]o6}C%movI!k%}*,64鑔Sߥ%+FТ[HlQޜBoFSa<ߞ;ܤ6"s66RBnhECE	TX:31B9=B=0xyZRĨͥAGJt8EWo/ (6D(8~BWLNh (uF.hzOQLX"F5: 
e, [ׄ۾!lڄR*A~)2y%Ǝ{%5s`ʤ(dqGL;f4pz䘡lO~`~DB29>W	_/}s:͌0Ix7t\R[aM:NqÖD06} zC[	c7!'RX|0l95gA=y="H$Q]:OEyn^|Da\8?X'Oj,7@*aTf&zW`CpjHH%DvKvȠS51lbkr-<Y#3BȶSKÿ}xrKR;ƤQOFjNZPCqSCԔ9|l)vTSE27Q>vnhu黒>K-In[Xn䴢Y%_ױj勣ϒWX׆^p]Ls˗AǼ
- ah+t7BkrJaݴJ>7!vUC=*(b$/R!yX+(_FǴRx؋
A_趰3x ׬|OXtu^wiSeږj'1[5b_(CJ1Mwt&I1Qj$͌8,m!liA3:1>	J%f*x#9q(	C惸[եᘌ\+	?6k}/Nw犜uĳ^T^Clxa{9G^Gz|Zo̻(:駖NQgb'       Vn@}+FKbBH4WYZc.]6妄=sfΜgm\$Wp4	sbM*rJuxR
Xth(=?́rn0K`{h=FHskRs?_~\*m7Z)xŌ-lQF`U8@8~ocyX6 E0>_%hzwR4l9/iƄz>M
"OcoIV5qȚ2$I}%έ"$1U5
26]IAJ
J"5uҹ2)NT)ԧk
rcYY6[v$̜tU%\8e~7=?T8ݰ~.p]7Z#/".!ܗA\(62pL;V+`WqT,sea)9\Tyy[̩ϦgӪ$8nDhPj>uzaM]ºdYu:MjSrU4DݧtMA=48d[I>[6G ma9ISI1v	.u}"|iZ}b_ 'y%k_Joy&)6_~8*ڗlVznӬ_	       Z[o8~(;L-ML.fgMw}*hP@RqEn/I.&&ys'w߻FUd4>Ecb'2W1r.CH"A$$!	R1H\<$+HDJB ~0H
l*
8EKҋx0IЯwW7ߠ227pb0_(b//<)@Q~ʭ9^f$8\%DaXH^"«RH:BypT4T<$p */|l(Y;`)fr6Ӛ(c1|^|An7^Ok[phu`Q,V4{d8i*FFCS4Ø#TN(L/}krɟBx'G`V5Y>P_柢PiH3&eC9@i_Zhĩ=אpRp=bI5\q=6fB*3a%b{<p|wi];"ѺE \T&8
	^ngi !V&}~صQx<a\Z`R]@zߋ' I>Ϳ]kKFH_&ϹT4EV g0%QkBRMaT胒i7BUKDq"V8p`$əe-F2cO
*˓?z2 Cʁ# a QM~/F#v$@rHkBhXR0ڲfhL6&#U2jo+	pA&8ШMMۡ-EBihy4u!eOiH@8S 7^R]p-t6d\R}9V0N;uhTiЛRcznSBî|<^ADզ86	I,g},ת&5r::c[=`J8ު`O*+PG4)"]_\gڵfv8^y<njUKWAӴe(󵯁4IA؟8RER(fg785%ar#@X]ײgұ-BHh:y]J\27k[ٔ,۲1kd0cstY|}kqꚲYi4I 7q@˄7;=-醷{ĺھcc\$+@зeannnRk})k(rdhЙ3ETAVW76k*0͖&aP$ve`=ϰ<l{P9uF[sa5u2˲6f
I̽@_t8+g9dHŌCsO<W:|JpWE8rEa@mnasQƄ(łD)>$9Sr 3ދ%iHVlh_z3}7$殯?ځ`:Li,\jڞCW)te.tMU[4e ^-["#Uyȼ̽{n" D9CFsEĳؽ+RvkZmgwb_Ymwjf022g}Hmt+80eP˞CTH%E}Adw[DTzL5ir֖@,%ryA!o5BZ;56Oe	&BhkYln8m\M%\֬rYў2rҵs-jk2\Z77ͯpKAB;l	1g~E$րȒ{G@}ꝇMo}m?7f@^S:˶&/[mD`R{WgW؞M{>
;xWVXGNw	AҒ?7ÿ
s,IP+&!5оhFPfbX_7jtdw$K&͋ 6_a)pN8 -nJKCrCR~Fo7S击DVwdW+{2Pw@~,aEv|݄h%!6;^yhxy^{>[HdPr͜ؼa1+Z2mfBKlqdv<5ճ䉪l
k`-na
NG/X|(-Ve)?]i*A*3Qnk"߽bG$       =rܸحܒc(ٹEGrNm$9w)EHH5ɺ@CپT6]{@nt70;;l^vѰ/~UKvneUG uYk^4aj,J8Kʔ3x[)~`1{uv]79gy5aI\knu9{s<?zwvnG[[wqŖ<b~y;
w=b8g<i[8k1?`^	fv7"i'-ʒ& 0F"t/yN_%W5.3̖ʊ<VUVV)!+nY	!@д`D}o"UfնA#(`Wi?Wq~N)e0MjsC03)OxviYSxy7qgҶIMYO,xѠ(tWJ0wsru:ˁ+6ѿ'a~0$}]&M
솅10w(ݘ5SElEf9.1*A=g,M_,TgM`<QvI>HG0_$s%K" 雇v!\X~TS~;WtiُHw?^.2 dK\\yTru-}tHsA}F-"h>~F ]D/P}0z?+2S(fQZ*X<dtOBToȤY(PĶy*z|W.6,XvS|S tANsDR9kd@`dy$r(NW:4׀GG Xe%o]2 ʔ$}BʾZ*Kge6|"}ic@>'nRQ/d7
Dxiyh"U8_l#@l-em=ɯ-	?"Ի߳3$Jc<hش, %5.ik3 8DT7"(h4/mm 砄jXB=v
,"M ~}=.Y.zH{C=mU!E[w{jСy2n׈s=c7fJ&*4>`$\oI9kD4e㚭 1+`6)UsbSU;PFF3M{iTTV{>L(	k\Z..~r_}].[kh%%0EZ46`^Uz9e9/Z:!-Fk6%Amw`5<EsQ׺I<6(p||nb.ʱ6@}8'h:Lˉ#.ob
WuҸz;	ZuA˲a/vww췆$F^5I?r"sVGRYN	_PsnVJu;:xeT@lh8jHomBDPA[*yg!DqԡM֠ i+KDi'dG%j>|+p"lfM+qLymG{m9h*¶&\yp>-aD	QxvCgޠHzwZ#[>~AuDGD5()
8ÈCifSnBgv*:?I]ڲX!	ʊTuߡ &fjXޱRYj	G8	F
Z54ZTȄkvD>
i(z$IOZ6L 5>V=Y*+s(sH-ة5L:9ۏ2 HTSP	ظobKy3暵~SVպ^*P2wXrA2YލhEuYf+V4i[#)Brvh5?'[R¡SV7cå&:\߯!Mаz^XM@:EC0?t\H#'je))	Ɋ#r8t3sb_Hg@ɢ,`%de
_mNl"Ǆ"~}ϺJTvߢ4r#ɰƈA%  |MC߄6lӷzԦ41ޑg=1amïl1J^ǅߠ]\l@Y6FeTa7qP6<VelFNET0óNkHbh{,v)hZ0On	~"A:Ԯd6:\y _Dao܄)9+	FA*LAh첀P cV/dBS؅!VVNӘ9NIrtТC}:{O{COvW7S&6C7G$8x,r/)ڊ78ia6@E8%68R#|fSlI3W\=ʳFtIsSj.&6%mIG?=.,@EnlΌi|'OaLri&w-7b2@M{EHȃ=uiFP2NXu=%GسғJ%w b/'>JؿPѾ^D͊7鲳7^dN*\KN$
݃)~exCdaGqV0+c$`N14lSd_qak'k!	o|;PG4_߶ݩ$ȳ}`JNYLt}u|=j9<e%&Lx\u0뫄TC/\ߺy)\^2W<K,UA2IFMNyIcBB~+ٵ[3EwtnLN,@lsO|v[$苌:*8퐬fππ.ce<ED$11eUABWtDED1UK'#?9{	s]g4qm}v?x;鷻ͪ}ћ'oίez?|;!K~	*,^*Y~0o0c!3|ShídQZ|.WyքM{X'g(Sɧr]*3f;UD1mr-|+j0;.E<8YT"2ZiG-.kn/3{b~:di3M9(^=pb^)O{k_?CE$-ZGsv[rG˸	-07;$j4|9F2bsJgk*q	Yki#<ND*@k|+W*'4F<4.P	.my7.ǄQaOjN{AS.R~%\y2IE`XՀՊ.Mh!gyR'2VuM{+G0`ڃa_Oes;/t4*GR42>9B(m*3}k"38a32}A{)Տgw<vD5/o-᳉P jψ9imִMvx]yiwICL@ٖ<e
=.[G s;4R#@oJ'=/醚rto"5/]ܳQa㎟71(OҶk3-/B3!. Ov_w:m ۸^pӹ'-,Ƞf1l@W_nNjCp;wM|]P[%U'PEQLam!9RE v2eoC逿~יXzuwgd}r`m!5m`gm!C6AC,z`Y7uOZqpUgt@`	A#VM
|TYU:EhѼw'WP O޾?ywhW.&t0vd|\?p0ۊn.TDj]\ewX_%*ك.,E[bgabjgwի'`肆F{xtv~J̠oi/hW0	YVm-޺ť|TU[qH*[<K[H 0w[z_|*e*}׫ -)V{Ul6iQHYZk#c!yғVݻPLE8_!;9
#1aռ9h`w`]Xv`ެ[:|;_S[B@	xjpNWW@^.s]7AN5JrQB"uU1'wRN9RzObVUu6وm	O\'(]ډY..ʑ 3R&s^)d"']F{%u863HRԫ/;1"x4jBoqpFv:|qbOa۟*Ŷ-'u+.H^+J7XE\T#ʷ0 Ԟ~'t\5%T\rTpKx%EU1FcHFaG8J%)nq(Rg%OiHWԪ2`܀:;7{
~BW
3}rx&d]r28V17N	8BHTDf2DTgQsFͭuN?s9'펒=SH=m.EG薶:l8#a֞觏%Sbpԥ{.V#fU
{3f=o[W;X8cvUtMjhT[$0JhԎWDYw cjZƛg:M@ҝ5JqnP&Q%7s{mRN'E͹#$
>tʡ*pR}_T.1ovƪQ̔Ȝީ)<=k#!+UIŔmۈJ1._<GD#I^yQRa8"KPX#O7A:z@HbNrthH@qvvrWɚds0\z%vgi,8f612ʊ$_c}e6r}>{t+4'b)$T+?Rh[ 0}0xa<71o_ʁ!N!!Ш^;Kؽtkؐ$[bɈ(5Yx-s:m%u؄B?$3OǞ?:TF2[Є`"ٚt;2ĆQL=%LLXuesgfmeҶDu2*6wZiDھiKclTȶ'ʺ`F;xW&[>FJpg
]e^qǔ	j:^'De~^gR-~1n)Z{NFD0Dvpc/C&o`t6~Ƞv5{OOtj(=B	YP1RT􌁔ܤJIj:$wǛFv[nD<U޽(u\e}YubfAĜƼ,
ϨU`RzWxCN=44C(\IL}(/C7ۧI=8/iLm,4bdIh3mF-/%3{ N43~Z"x:a빛zۉb[pY:Oi! :`AMeurYeȗ1b"rF 﫥YM/P?1>*sAU2u^#˯))sp;`NdYIEX_Ѳ?E>zn}YX$<s5Oݟ)2Ѹ\ܮ<3dcX9TCKvsŸ󎁥yɳlGORSTޜ[g"gSUW;aR:i;=岖"
-T	J\1{Z8ddP{bټBFΛ˭5u61ϽxîVi}v)R6r<Ji>NL&>gwv-REL,^MGɽokD;Ddfܼ|WBЍFr-5
'Juc`:Hin1iu|̗fwT#FIj)!0dhw0LԉHOAjڽ|vw#$=+\%Пˬݹ٭vD4ޱv<qQhOaklMX!1mտnntxw7M7U<=g?Pǆ:t$t% H1w\u8<Ucc=F5[orݸ\;͋Mi7)[ʶi~EE؄^V.4F=7y$},U="
}x= Jۧ)Tgrc|-vNǞ[8KO&BP4[bDyyS/8]֣,a˜iap0JOk^d_Č25`?:%glxj26e25|<-! 2CeGۓkVB'5B1jȼH t9s-rkZ2[%V/q׭>ЍAސa{*T?aI3~r~#XTDbJyHB\?P+hu"_Q0gѓ6x/TK(D{@rf+L;PL"_Z-54b[ǎg^sN:&:fy m|(Ad}Y<@E2o40P8hxw!$@Չ~7tOM>gpL}S|sCevHVϵMtCFQMC?تo2y֯ہE0`Pq>}goIIӾMyϫyl
"֏(Ki'Zƫ,'OV۹	JfNUc{VNoiX":RKc#PZFۺ\%"IEyǢwW{Z/l7yPKo{/u7_6{wɬA*.Ybl$g_: *hoP"M}uOzIX]_u{N0IT	]˔R#q;?[8Alm
ϊ/{ZCrr*Z3JgS.?S Dq5r  <!doctype html>
<html>
<!--
Copyright 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<head>
  <meta charset="utf-8">
  <title>Network errors</title>
  <meta name="viewport" content="width=device-width">
  <link rel="stylesheet" href="chrome://resources/css/roboto.css">
  <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
  <style>/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  margin: 10px 10px 30px;
}

ul {
  line-height: 1.7em;
  padding-left: 15px;
}

a {
  word-break: break-word;
}</style>
  <script src="chrome://resources/js/cr.js"></script>
  <script src="chrome://resources/js/load_time_data.js"></script>
  <script src="chrome://resources/js/util.js"></script>
  <script src="strings.js"></script>
  <script src="network_errors_listing.js"></script>
</head>
<body>
  <h1>Network errors</h1>
  <div id="pages" class="list"></div>

  <script src="chrome://resources/js/i18n_template.js"></script>
</body>
</html>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('errorCodes', function() {
  'use strict';

  /**
   * Generate the page content.
   * @param {Array.<Object>} errorCodes Error codes array consisting of a
   *    numerical error ID and error code string.
   */
  function listErrorCodes(errorCodes) {
    var errorPageUrl = 'chrome://network-error/';
    var errorCodesList = document.createElement('ul');
    for (var i = 0; i < errorCodes.length; i++) {
      var listEl = document.createElement('li');
      var errorCodeLinkEl = document.createElement('a');
      errorCodeLinkEl.href = errorPageUrl + errorCodes[i].errorId;
      errorCodeLinkEl.textContent =
          errorCodes[i].errorCode + ' (' + errorCodes[i].errorId + ')';
      listEl.appendChild(errorCodeLinkEl);
      errorCodesList.appendChild(listEl);
    }
    $('pages').appendChild(errorCodesList);
  }

  function initialize() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'network-error-data.json');
    xhr.addEventListener('load', function(e) {
      if (xhr.status === 200) {
        try {
          var data = JSON.parse(xhr.responseText);
          listErrorCodes(data['errorCodes']);
        } catch (e) {
          $('pages').innerText = 'Could not parse the error codes data. ' +
              'Try reloading the page.';
        }
      }
    });
    xhr.send();
  }

  return {initialize: initialize};
});

document.addEventListener('DOMContentLoaded', errorCodes.initialize);/* Copyright 2015 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  margin: 10px 10px 30px;
}

ul {
  line-height: 1.7em;
  padding-left: 15px;
}

a {
  word-break: break-word;
}     Wmo6_qu7u ]1,ݧa(l1H]$KvVtݾ^{xTϢުAuna6=99\Wl!+hPa6 A܀QNR!vPK y ?\ OQ͙IHyZJf%_}q-gJCB@;~r&?[r% \7gn]5>!lIZiδA{1*:-U).>a#!W!dB(r$5f_gbfLɤN1r1!$(]ŪP7:2rmv|kIſb2.'@f8N}d'ELkHz8xv;]1LDe$UB:9|y6RVF初iUHu9 ExQz~D5'8VBmb`U>)`\i5sx5QR4!l~EiN%vRс|6sd:;`<XtHp9tQm2c˒ȍ}%xV3iJs+|ؠ	{)q:=n	IEttD~su[JwZ*NhKWAn/ˌmGdY$y˨fˋY> uN!=BK%1Zz݂{&:ڡsPGAp6`g:>mQ߲esD%<ҶB_S6(}s1nF%LE/
1E\i1voH^jEC\{H&Wݘ喒5(/4\6I8p#]iUxvyy礞!6d'x/kZ\Ӛ|.tVi.;熨qb+*ԃ^-9,+y+FRHcˣ)Xa)zQ4QU'тZk?փo^Φl`0'
toHpC?kFO,ͺ㸉L)4郊><(~1	>H':cIBD%ƭ!եSpF/LVlrO#TzKݳ
X*-
'VФ@pTFu[N>5ECal>h       ]mS_۹ssMB)%wX2fvv(ċcmի-vHdȲo)S-4BGA x'0ȃЯ7D!7oC A{0%sCpIi;?]@Z #[^Ϛ,BQh w.s4;CE!!پF=eu{"b|fζ8|8?樋߱?G-9-TG{[IѽZ|,-R#NA@!HO1sm'#~8bjv1<%p&S';7.P#DyaTҹAkKq\jP5uᱎO]-
_prdtr &l'lr;c\GN"|1|-(% 1m$ CڡL"0iT!(KtAB8 NJI<9Oxb!Y oe.1s.>/P4<B~͟،.$yl-Θ]_i|`HwfƐ%A"Kwsnk?Qa{ !$Y4W1B F9G;~ }ٛB#`rXԔm"k+Gi9xP(\ze#CܪdCQÐ1>1OlhAL(Nydgu/	;;zoiTWk	O _Cr_?K0+0z\T?vF6cUQ.Js)Zht*81&aP_* OMET%6{0ȟ~_*`!u	LuuqzA"LqGтPwjf	3X3(brf>21MP$ↄu
./GkKg:e'BDezSHG$31D#:ɱDV́-`(0Yc/Il>=k}l3r^>3\ q>ܙr-A	sͲ5AQ@uٰmZDchhB.#r'nxO G("\@%ϷXd1>-&wJ[i@k$voZFK$Se1;GN*a)D2Ȓbm Ů7z嫑5O`NrhDuDWG7wtR-&3O\ըol*o*KSf%HS+eKQ_1	5@&jTVseY2x>]:Hsи	ݤv~I%yc\e9]KcIfYW4"w絞uK2o֚M2ϑ㇘\ms5x9W,rm/wTnڼbdגpvᗞʿ2>X8`d~JR!_38Hs7^1^cV}6kcg?X'i(k-
o«;sLŲۿY}Wl
wSt[&wUq
J鞢dsĔnp{)_Iy)}~s+V6ᕕVzu*r7|ĴֲSqx-bxcjۢg?;ׯIyIh8n:rSv{)*tA5g::$L$&iJH}-gr$1W8Gw`xtKd̾9ʥW X:$-~gǣ@XP{x6>{1QTz//WmMudunC2qWB1־u`㢛Ō9]˓@fEV;y*BR&/BAfr	/Zrv}I5|#.ZZ hf"hSst4KV2|eN*=% (1ӻ+UTtZJ;zp,UܪvYqQF0=u!AaV7˿a#mZi~h;Ki^iA,8FYbY9J+Q?ݶ]U~ĠTo1-UJDT*;(A)ߖPgxyVMo}-1+[ad(`UoD*(W
Yy	V7]6;Vը/ Р*Ux+JGFlј+%Ke/n]Y4źQΩʭ}5r3aP>9`IYWDA/u@{f}\1~T
ήnJ֗اo]HŰ 2VPgܠi69D}|
hө)Xegɍ{y8p4_@LNj+NmoT!xx?xR5)[UyfoIemVlîYJse>k+(p²)wyhhnWV}ש{.FiJqY^W&;]כPk9JD$02K6s2#V ]$mޡR6FQ3AHw灓d]Ps$x
S},Q,fٙ<h9G@*}4og:i-quz߮s#:tSmGFw5x˼`%	/	JeNA-2dvY~	A{['5Tїu1Y\wf{g}uΓ/59XA֯g.WQlu{v>pJlһz>Ѣw.΂+5_l\%YbbƑG /jr       uTn0}+F*"iH-TJ}8Xuq(t߱s`3'ËF䅅8Z>0M	ύ-Cx|Rk4;F[֍20=A"H2[0SՍ #Bbd' *Ohz|M&-)L`E>j~LKm0y:{X~"\ԕd=.fVhҦT>u&V>y<d&TSa+Gʨ
u1Wl'r.PݐqNVW	!-џInee0DMIٹ `y
 Ao1BIK`ifhYx'Eqړ`Suq8m.qZ]6kB2'Dh4@iCZuRtdؾZ.ZiA^l^2lw~`%Di;`;Wf'rΧB[nB@W-#C+Ռv=x!;2.(m\]tpbxZ'
7lvT1WxnU=[,q߿5d)A8{{6I       XoF_1 t|O6UFs}xEm(.ow)W']~,i:
`ʽ덅>?ln6	spD4;̒|0jv#U!U=u, NL 6RQYJUEsOׯ`%sL&xUpDqejdr{\ƂXRdA7"aD8lկj*Ec%Enވ"QHg-T>K(<W
-p`d7bI?^F[KrntE^ZRֺiin
sL-ɈeƷrla,X+P\BjK'P8KdrMg7(2,Ib'ׂFA	џnẄy
p4F=5ɱX?{Bp|f}2o/0 F5z
%Eԭ>d4\Ic$d޸@xq65.qzd$WYfr-%x&I'U!FkxV<&31̿Rw1C(SOhjGCsYobX=(Wj|I,fk|lbFaUG`6#
s֊^V֒	)4_u:<=Dڑ=G?RB|dI`|StZKPmM>蛖	e5bXST2{+LwNа/
i'4wpg#<A%`"0UbND;tLk,nHW{#1D*d'VȜJϕ.p$7tl֖?ܸoiqKG%"u^SER̘iL+m=40OJ\1KMnyyGK؏Qg3rc^컍L7Tzi,a݌?t-wVNPRlX";S/#*}ueFphIZP4CQ2oB?lTO&̿®6">|T-:fL*{#J@R%nF⿀FÐ+x "ri:_K㴉K7bgĮp\GѬ]jNgy}#՜Y,ʙzvG:\xy{3m_j&P
nׂm,'OC0]¸-;UR3~Vzud wA|Gՠ\A(nKD/Җ#&xƩi3Qt7ԗ^PH1rK=8o!2I$lb]46M_qíD2VS0oubdJ/}RImh%-Zd"5݌nC"Q#yG4{4%9߱ù &)UYdq mL匫-gn9g\IM^"\G~qiP?+%fAaǵٙH,+eKg_)Dvu84zU3XM[W&YN9GIi#\ LILA:◅vMzۚ,pk{KC5o0L#ăoPIhi] min
Wʉ#mƭ	S?rׄXՋ$d}6#%CoqxAȆEjCÒ;Re嚚5H%fʳ<ԐFiXb$~XL pZi3JpwX掛WdYԿTaT?o'2       YYo8~ϯv+;Nz*nEEhAKĄ&-wHʲd˱h\<	?`W"^P}$LEOcä8D(HJDI28 O!gDij΃W;0p:3%'4v5USәT7TLt3q@9:):>*9jYnuא"W%)55s}oe>W,[+xSL*݁7#ҨךH</ɘbPTNthz:;LFDZIcY}
/޾zcit:Mb2!joReREѣO5~<{SJ y1s8Oc)QED8I/ƾrI08]쌥0ZE'gLaNJ;V)PR3bؔW4e(b)K5P'E
;>AJ%L#7IoX&o̳ŮM0H#RP4EILL5F^R1^JxJI1V3a{*$_˗/-	bG27MǑtlP| ]vxH'a&kC5L-dGy,m^
9zY)J1meɉ\<܇ݕII	ں
m,$6]*׻'|OD!SgaFDbVR5,tPթÚ@Xp^/&h/$SALw(zh#o	kUxYo=1w18p<hTwtY&6m= %tj,б. kGF;a!hp-\AEkuUs뽈$zX:XsyJPi`{	.z'XK~pSZhkkE9/>Xv -'fӟ,_.,{U{ms8`p]wLl(.X+O7\aL[tPmoet:ӣl#rPg~g--wUOyT7-9V32=?>A, ISɈu#/+R(I$ݵ/K	JBog[{HM<Xs5嘶$߿j߸F^9BǼH|Tǌ`5iWˑ7ܨUa[.lKjQtD{M+J΍k2[^pX?Ͳ+.~[4a^?17-u+Fް8d?`=FAYNE4]Zl"Ks(mLGVdmp\X	j=:K=z|g肵bۦ-Zaۧlzhǿ )Tv%s繚7#y[/'#"g"/_)j<!	s4	NUpwEj5T@e}D"g@D9)4ɔW>@oi\)̾΁;9!m}-i"J^a;+!pG-hr&޹|pXʴ*76Äkȅa,'9o[QZF}P" g;x2       Yo6_q0L
=9Cd[6v{phKLj$[H%Qذmxw),x6UͳoR
T]VT)2<C$APIMO᭤7L䥈)<?
FXO,TJĄjI^2^<_\^]_&itt(0g{.nf)Y2c (QT"Upzv%g*#yI"!
⯇ݩ	cIʒ0WmoBg ]j!!>YwD"GN3E૞:>,ON|gJC#+F*ʛzaD'	({B*G"xLO?ƅ3je(1l]S/_ӜƊ00DK/ٻ Ni|+4?G9e[I:"Xf(%rq{yGj Z$fE%ÆFffŰ	~ڗ[	ޖzmCiidD(ΉWdGg]׮ɪ8ZgxƁ㮒Kꐏ8ݪDI-Csݴ)" I?pvJ@/E(TSu/;"^*/*D@ݎD
?*ıLĭ, :Bmk4fH+,ldA.$ B&9@gصkx{i֧^E$7{D}qKϢRê3|s3'+q >Em#!<<n]rJ&fL8fA|M[6zH˭ vybƬ#:Rv+c[߷t''.9-JdkXʆU'~fM-ׄdqoVjA(@hs,^6sỳi	 4wG{m̻.4Z9/1ɖ:ar5E@U5'w<퐖Ik LZjvG5׃ZtuU?nt7.ߪ6{{ɑ `My,BlzDBx8<OrOuVp3XIO^:Wxv։k-^En TpslMUPUU$ݽm?bEXSky2qZI#cѾuqeRjT9գ
ZpJʱ\_ff!]z*4EeM%Ӷp]ttעӃ>y<si_AM:$xO0֣ {ٺ7^:Pɗ!PߖxR]{jqK]{W)ht6jjKĠweXǡd:}}Ti
RK/=*4pŀ9yEپFhTOt_M\GF
W9(+\	
XA+RGRr|R)F{i|Se6͔&^m4|hÇ5Y{M&$2َ=е9'	 [e6lX]m0mC;C*Y1>C93&0L|?C5*I.>s/}AN<<SZMYV&0'=M 'hzSizXG͛DXXLរ¶<%c/
ognizG"xR.^ӂ5!iTӽ؆[TEځBdR;}?_;$6=w:Wbի>]ECPջ?t]s_{ٙ]ʘS/1w#QgeT89z[cl}#+q/AW߷\_ԁռq;+i^ۯNo=-Zؼ`<(=/[ʏz-W(sz{&·KӨ4*ۉi"_!       mR0#ҢK,%{=Tz{X8vwB>D˛fq
[rU!KY#lkOnxicM>8xf¯@%Zz I!=z
|y%Z. {Z@[۾x{Rq2\y CiB*$|U|,7&y\;rF;]==@YJF6[T&HMOT3RV9,HI6&sڨɟQtf/]3t(hD{'!z3GK'ے /g:8,R:8#fŤ0$w7UL03Nsdqu9$8!^{]k73^K^J:?G yWL:(⊝ɘ=ZKc.u_QH       V]o6}-;KȎ.+E{(JbC*I^vb'Bsx'iEej7P+\7oR4};Yhn4^^x5Xe|
Qr1܌q*qf|&3\[l|nmu(a.Kp[:[wM(x5ztkßJ	a%[5-pohJ@pF6F2OC4N|:&5c)dSY_*&0VZ,!*~1ZL"E[RИHQ2)\&_,6)&#+8l2.
Cu)<=Bi,2^+xS여{S&,VܵzqRxp.E.4rTeWD%VcdkGH>fy(͕RiyH`C3{ܗMÎ/(vmbq&0UARP398{NMƃ~opfVns^)Mc#FxFUuݠA[y8vGʰ>>"dC~GAI|\AMYJp=HlݙǱG]A{8h`WdׇR͒Kuz:ӗqӪsM4Gڪ*8eU7kDsP^/EALq<.V]
(Ro)׌2RI;^vS=
7:IsfBsZim;z?˖rT 0Sٶo~Tzty[N?Su :+n"NtzǴ~&(=+'\K~9>LQꞢ%ogiݡ:cBE5G%	       }kWIw~Ev=-<sw{v\N*ڒJ[U3#YYpnsQUVdddd22rmM2UwS/7n2wS|6V(5TUYy5Tq꛼RU1+iuq,U*QNW~Q>&Y}jLe$Ugp遺G`e6)ՇӃg.ն qj\ig[ïyvm&hUU9<\oIr޻i{d뼘|I%N8{eԅUd(c:Pyꂆ$e:P"h'ur
`>>FyU\g5F߳+if^7 9PTx
B*-*N`J`XؠlBO=RU]ΆH=\)(
E-`)bAI.FP)!'u	e=WLM yG#Gŵl5+G0!OtJeQ4pyPMPY9=W@n
3M_>|=a5|oӤLW Y>~APprd>.֐*&f)pe?66('M1O':ӌƘ 3A7@/8Jp8"4EٖXNa8N2ϪÔ&,g| VI_Y=2 q%esq@lMdtfDuYU-A JzcWEAj`J}+}cAZXJ}f4e5'=p!M
Q2d]^آ׋r鬺nuqTQvJ]#˦2Fd/gJByjL.o<=ԃkDq%3/A#u7-h^ή@^Q/K7)xʖ.2SM~U'ŬVw7[8	+5lblỳW^?`65i܈8[XƬKPM=!OmԸkeVeH2x>PuBp0)H1(afyxCkM v`DAs$BLr!	*j
OY6ϙ59C3TrnXwJo1;PEQ.WF!VFFknǻ{g`wbhu"dhd	ڱ^G"E S	YƉմ ڗΣlbzpzm8WIya	ΔIC]K	p}m xA!
ĳH)o7`ݛX>V71.-2vg&­fC)NFYbiiؕs	!Ё0 sJu)O]$QYܩ S;~`Pi1n,u'N5M&Ww	iٗ]b'{Iw.>#i6ng*sPXM.$%*h+*hjB:"`8HaG'aSUtdϐSkqM< c4ZQdcPؕY2_RӐ}fn!3!qQ x̋cT }Q|5|RhĚnb& M0}Z? 4=N2wX7nrm\YAv]uSE{D|	e#{ԎIG nhh4;oP}A!(4HVkyZ7'M^t!\eZ- m	d!!	#ᡵx\&euQ?d̮h.4Y-*ǃՋ_rHk5u㻸VmhL:k(qa1EPמ^sP	xs}%=`X3.v
|J0٪B}β)4*g))JT2ғ4"2 6x;<H&A^ü$Z\ 
Indį#o ``u>LF<mQًM):e
~+;0G0i^MGɽ>'EM<&Q##Ҥhvr/-Ws9 L T&!Ni5R*&߯/?"Zb7AP].|FܵjifhU{?t.?/UK_[\v8n~)?_TfJ6=EKUҴBj#o*-ˏmtqM2)<r[{L,DXPT	.a:8FL`gUV־ĤICO.VT,GB(mŰKƜXNi?|P 015𰲓?8"d;
ٞv{MKHaa<H> 6BvF5=W%"R{iwX$̵<E<HaL?Pj-DJHAXwlCNOġVڶ5Zʬ7 >]<Xiz,$ydZiUheC醿qz*x.1)REM	8ne/Kﴨo1	_(S]{cT`X'#0ܛp<`ķϟ۷c8A)=sQQinRt5Ѝ2P"XoochV4e` CN0ɿlZoXd&#
X3ĵhT[ޡzn,&n cz}i(J {Y?&#tVb:@;uLTp8NzCY!c!~zMnyQ4nsӤ.MWkkZ{>jg[F'D.Syu&0yU߁ǈ@:Ut;g=ѥ@yC)~b*'D44;y<r|{wF{w`Ś[h6Im|ddH~Ll:;/a2I&' 00Po1VMzh8?'ަ{`*-)	)/1洌Ii~P@{\zc:)\8vdW|C?d1OspocWVZIY9+!@~d'Ġ]贑"Edi̡&-e1ǘzTӲ F׶e>>Fg
bVe(Q3ܕt>%.FmՇӃ'g'ڧ*59_cXf 3`UҊ!=ͪaOdMF$>2}2'oFl Ad}~_IӓG'Y*f'p6<uū㽿eY?56?$xb+	c`PL`^cۗM6@&Ƌ?Y<L.i[Qr6oѨXI	aihpvJ'(R/m<<kZyb˵Sx`[:q01IUw>Y|\D:vkdOm+*Kʡ1!mD*Lf<瑭8=T1=Hsvm9C^Y<R`9MobݫеF.D0N/R,m`֌%ː[A̮IUNrt#c\:7K1R2576:9N]Ȏp_n͏LG4, (Mk#0rb7#	[:7k(n'vk}1(Yct,<|Qys1(l-*&!MԚjI-"3TCá|>Uef`Ԇמ=kU\6$L
	X;

w0Pyp"07%k|e9jF"ґ qB`rԑp+áVN6(W)zF4^;'Y+<̮fۏm`ʀ~j3?̪z/<<0J{>]1<@ <)xkȓL+< Sń<{qjRF珞)JBtz;vRHtrR?q	Ԡc"R712D2D`9 dǃýݣWGQCS4Uvtt
䱬O N{=y;(mv%F(:NڎyC:>9wg^B1,/1ˋяئG(:1~2TVh3 ԸL2:isf|/dBpU5fmjlbo0[8:x':F7'{G'_{{{ >ۙxn_뛓䷯_XȎ{o4Cl==ͮ.hi<K%(b>U@.6z?@4-~Oe|a/RNyX`7w4Co`{Ai9ΒjVrv.&$/g`_fY	dT죯:
LIØ<)6)}:!>t: K3}K@ĺJpy3+Ǵ="%#^K+fQiA|ɇQO͛b.&
|";XTwc?dK9(#'010˕xNj[+",RFEAg^g'㽃A_eTFN$*h䉤\W]8QD?V,u+ɽ;ߜ' %Q qI5S	_irĄ-*܆@VѾ3OyqX	:Yx5-X'Ut2yXy4!@UO;@dcyLљf[:ɰ-FfxmӠu#+6; |W[&53	w#N-lA3g'RUL/b}EL=hg]RpE	FacW}gmko|3܄dC\UV߫!nU4yМJ]6⬴@MΑdLlb-NsY/"jGB8fS1i`~_vQ&sx,1,'_هIt'=n^ObZ_McZյ۽^̢5bz52OKS.<9z<cʨpYZ=3_co_a\;wֶ(9:qH})?'dkۑI%ǆbnviҹ1ehq=,OJ͢J7Pڌx#Y]Ƙ#jKooW	Zw>FJ(Of?A^yr2PZN\oЌzIhH'	M"x:j$jW?\#wJF`+$ָOkN{wU`,9IJL={OW3R_;'`ot׺Wyoeiv[tm}J-B)zt/5~X&GbA|&Ãf%vhBYSbP<Ю$[qCY3X|trVgt]ijɆ7Uw}#Er၎ 'Մ,5G.8D:8WQ`vu>3*kZt vQwCR5tũd
/Hw_Gega$V矻܌g
X1ᨖv	j49[˕jwh&CP  X	b>W}vOA8#ꮫ0}wA6AQ"{>&4 B[vGo	@!;5m;f"Dm2~NS@:7#M#g;92eP8AK؀p&V#$zkmL/&OD/@@dW!Gh=~K	dӨC$ʁ8+=K}vm8ǀ#hC-»SڐOaAi 5dU\,&K
dn<hxMͿ:EoFNq<iV^ax6sV&2&3ޟpǇNwY>rgޔſ-Vm^%onKVYFtY[K`f3`wVT_eJܠR)f.AucMQ^V<iઞ$_$7G_f  cHgE`}{I6G/^Ssti!^9u_$Փ\1  1O:'ߘMu[t,VMZBs
Fg q+$?ZW,{iy@Xuʊ!*>iwiFLs#j6z;)
;|؝	vp?N,A%9p!w:tY"\<rim롧*44T$/<:#&iJH-qt{` PioްmguASI#BQvmu|iTOP,I3;AH^܏I$czaĈ[t ]
gQ+F_gu6BUGbo)uA@ܠnƻϩ?FvS2ˑZnTЮ
t[8!jVŎ1d8+^7#N
"PdJ@8_֗³rCЩ	:g}w-#Zfթ<B%83_ZzWYaTŔqfea
?%T7^t|=֜}F=qmf R@IƹC퇳
HHH{_Bء>˹AMm~T̲ K$jQP4g\jՋ. 9#z@=6䳭8li{SNaJ|>MɰC^ ܯo.p<}	m]1_dePf>݉Rd&##m R<w4s/9'W>^DzSDoFh'Sy*XN:XsyI:N{g>WY=o6hz] Kc06JtkDfLE=`?H,`EbӷnuewKFC>yXF~=I	a^b^BPxGsS.״005hLG]iާa$M[$iTO4xZg|kxf? @+<T~*^0+L0g:tV}cslDMΞYUɘwȕHEQ'5ơrJ/t,߫x>A!쒭Ys *3()a]'<ғfY8,`~dAAmNw-j+TۗX1=r-vb|EͿΝWXĉ"-&TcApFuC.Ꚅ:, d-'ete!=k#Dz?
UW/^6#S"^ۘTń.D*8c'A_oP>T͇iƛ n)u&H'|;XlVk͋]zsˬДƖy"|.08&#6ü_,HI{/1ԋw-Cb,\so%?>O@P~z֨tj"OQ1+cɱ-|7aII+YL9gY||ZM(-hgonLZګ,[/VO"n[Lxn.[?шXn6k`/b}0Un}y|kfn,V5m~2;Hd1tBb3[LnF!⽿k= 5o"l1d덊^l(66i3 F$
~qM`p.u1o]BT`d/wuQڶozn1Prej(kICk#)Q"DI,Dqz:%(1zm*3u'Ucz%RkC?#jO:t80%5%0_8%nD|!h7oC4yX2L4z2:Ds64>M-2PjLX6]fڪVJMuu,\u̚j"Kg4δ(HL4)G~ h|	A,u19e4ǒ0f*UmaK9gSKBqܛ8lDlyh"a:z˕v|O5y[kҝoNvz4 *)ա)D͂\BBX'{/ޟ}{vxblR(O=*~nޗ4ݜlT'awzpv'V_잜~%uv`.vKo:BXFjĴIZ
\~(Ȝ\e{x#;Z':۽M*NI
%a~"t]p>_u	^QV&Lg%xP]r߈IFn.imw]f>2=Ľa\SHpTYHƘMJ?j\yiLϊYyJOq۞=#LKtoh)(XW9>{<yqD]7}jK}HW^ka2a#0zcL6Si5FW feFg䢕={ l+-hk=SV3>vkNޅ%L`Q C</XLSTmwC)XvfcE-]6`mc[i]ˇ;;Ԝ͆wWb6"or9v@5+>HۢUQI6
jmh~\뉈ӛ*M| .!9fj*(C}'I7钛";BGSDKsj+d·8lr	mᵠiL	M2^]g-/_)20izm\O < =S}]VԤ*yrw\tEiwoJ\pf ~˿܂}=*knr|Q5i/P4y
mդ4%wQ	e#J}%oZ3ŵ1[Խ-ӹXjˇ]粓K5s6^e⛀&	.[M83x9zpP,ݿK7LdD9'])'Yp.:	<(;E}`'d٣$b窳98fL[#sXdBZpuwl̔zx+C+GS՘w(S<p3ϳ~X>u>E>=+j3؀(lW7^3tw["n
_EOs}[	<d׸7͢!۹_p\f)s 0CT9ԝn>mN"!%Hn
oA<9 {lZz I&׋gVO4Tr'7i8.ZBG>9տ1<
;N#aC"O[xUݹ)U]-6=#Pq/q/s0ImVYTQLjTiaG>٥§(pB.j;eփgOTX\kjoTF mNom~v!C,*g2c$\W~KoQ[J2ſS1cjQV8*f*Zq-e(6:w sHVֲRO%Q>"oei^65}sͮӱTj#b"G#{f-h=NZlKtim[Y/[(\:W8Gδh !SZdEg3r^o\):iݡ|[~K_?Ǿ-'e!?c-\L~3m*T@_unH6چDA *r&:Eٗ)!_W0'c$<||Y';WRZ)JKöw
tzx==E
xGu7Օ#oחq[zQ{c+/OїoWVcxޕtUwcV$KN)l)4+[+KƞVغTcMK,I!Yzsq%g}\)8$4/:i]|| `^wI웣
MIID_:]faZG
}:"?j_'Dsv4&AM5m]E*vŵ| >nQ.]ݐe>87
8y\h6\+>,ަڻ1G1hѤY嫅3}=o%&oxD>Ҕ	+Qgy2<(SN:^'[xLЋD4U6R|XT%Ԕ!;[jx!e,Jɨs'ϊjnmS7_Y;^!G!u}(MM4U?	-3Ld6Ayڷj6'jLv^N5.sKd-<~a4de<a^G0!*߷|̈[O&8J(QOx)+'k?;ǃ@M裍pLoj
"i۞(֡."Gla-wA5VdY- $gpR<([o'u ccd+1%ef**[]RPRxk|G5X<ƖL!hRW/,YѰ,	Zr_[ S[W(Ag^^>20dQߘH$_q5Lhog)yW6y<(S%ǐV6NrExeg)'b辥[I9gARDHݗB~?bOL,NPv|slosp}]twE".}'1ցlK,?ܷ8 Nw-ypchU匬Nqo%{FjI%mpZ|-C7_5R~wnיWK_Pѻom:"58wizbj纒/}69 pLޣ	O5LmD)<AF<iYrneerϗSU&qz*H=bfk"M$<Ըfn_Jz	{ì1K/`cF#Y%$L}?b-5'DÏ;Nph0>@@8V3,JpBu}e|VyBB30MhhHxqfam,斬$]l=Lfp&'/jw|G">DfU {-XAb{(eDJpKS=㲲ċvlPHhxa)F:ω^>vܾuCy4m[@,J~Ǐ"2\6-jb[mʄ;g;^;//v^7r-F##"qrX(W.啈bPy(2pR(E07Ќ~q|yuE0p߃R/ab	cgC"u[(]	q>ooAo vQdQ@tծ',!4j-fvik.\tXVG_x߱
) s;n-b>?XLDj
;k_>8lHVl)|ݢ!34H3OQ]5L'U0M\jCV{H3JOft%u2N|ݪe%R^Z~煈l9, #ś 
ޱl>_ߌ8H6[1T^iBŨxS	k1
nt(4FQ65
>2@_I,'ݒo3ʐY/Izs{7,L;m4E_y]#UQ8#:C@A)ƋH		w5Yw\DVsXXƘIoNIL]}2jDDks"j526<FŵEh'is/`anľn{^u8l_cU&*	TJᡮ]TWGGq:/Kcjv2/b
jn"<B㣛:Em}k2<ύ%&/){w,K:(P.aZգ֙GFPő"9[Klm6oM|&[ojZKT*EM7lp!ב8t90mC*Eg3]=I6ɮ:=祥g\VWD+&]>F+*con|o͛o7>v#u19ϙ#S.v8*cOfr2%x?fU?XlKN	K.A0|tCO qmnKk*Tb]t %i]K9$8:Kӣu׺^ꇪ}y(Qr[8A6MZ;`bdZ^،[lm^[Oxoi)~mZb	FLXhSB'@2JvMk[2)/_Cה.x01ۮ$\wSZ/WrR2wHWv:zn3sb!iIQ; =m<קx:'rZANO(՜wiNn;l/'i{7x|^s|p,5~^b7TUY'uM\Ϙ^f:Zgofa=>Ö9}tJ&Eџ鷶);h\GK}M=/w']-BNz;l$
hHBgC|ޡqzZ*R[avn6~$o!==3KYyJMc|-psK-)-_\7M{ÍlSxFwʻcξQ4QPYJ6;qԏmHk4;4,)G>>Zq,xFGV1	a,7mJI6My,}8\*Z ;fCE-f`cb#?؃\EW]x^3*h,PQɉCxO{fQG>#Ncm%sK92yy9bɑ~q7	'K\v}75Z&ӝT`'vo{@yr=)0HzaMn /Vj"Eܩ X_ɴ, 1ȯÚ2jlohWUw֠3*f`][PW~K  )aYLo`{hF	n"+ut?א-Ţ(|3OavxQLechFD*?g'g{-. }xT2GDsGY:RO	_q?& fXX"+& `(@ZXMd/I[5MuuM~"pw"Ad	}h>0xfؒ2^ej4+"C7ctaToyp]o)o3fUcd`݃=?ni715Qw=p6d$&3M_%@h\([pşp*.H/4awxťd٤)%S ʼMo6UCl/ʞs]FۘƲH-jf6ײR?
nvy@\%%JOI!ODǀ]3F11_WR.oJ_pBJu98U47]\왊q5Aۑ\b	zr^5l	eY1`faqa$t9Mb)2UNN R
PQQ
4}hZK
zjH:T\='TskNPO	u!|tzl><-Fyk2dR6L@ԩxVg{gg|@(|-Z6XɘnGȌ*|aӐv=B%UJS5?D8M[p| B2P
50?̧,/^wgis/o_qyQ
'jwkS)˯?iC;ܪZm 4-c/}ϊ!|OyYEF\M_,)c>Gׇyu\$hpBeb2׷zF="{QU+?*JH ͊%Rt)>gX ,UVǩE@ZNuсbS0˨GYRJF0Dc-Xso!2W^%([htqϽD""i2*&Muwɜ'x,	l<}jV
փ6M]O͵a	L; cw7e+HgmFۯieƷf,BW/=R9=Xm<N)P	tRP)>JGJ4r)H9P[U@A /f)m}Wf-5y7{/N$5)yjZ>zx!y<jIs~q~uCS>LlwW~[duVqȢL݀w|2~w2~Z'\w1]wpdcHM`X.,8\T;"O\%![(x7a*!Zf-%9v&l5SJ#+$t Kv;>
Oy8\  6f߷$o '. Cz-wVnݭr]>1HQ;h،=H)mXp	J@q/ќ+ԓ,Cצ"1Q
(Sd֤Bvp>i$
*+#AMFݒar1
=f9@Gk}
#Wt0-K<U]SC\UG$]W3 +_w[TfTpʀhD;nLmQsb w~,ȝG6JQ()g~dO߭O>gHҔܚWÔ*{j:f:&vy+ڦ>x[?8qm?e>N-,yBү0S'nAQIB+)٤Ű/VGd5Y4ץ|̂\:-d1]Fg4G7kjtz5t	@N$?M$BbEy}'<>"ԧNEIt¸5#"B4 A$=גIIOT%E'-<,2'Z;_4l$qdū.lt^jVL㬪p?-Yى@EVn$vD7Ux.DY"UBfJ\'5_t]KnXPP!\wV}@r/v~z	hLI%[8mt?sDQ6λ5E\yx5rY.pY(!Tb$lw\hw֋N,A_Y'HZP)b)Ӟ̌ZD1&L0_<QeW:׬:BIRMi)c55-ru^gcKhWmSW/NkS)rRio/_atsx~[aq_ة >r޸EC:87eJM=YKIl-[*TA\F,1eX6*Pn`K\Wm3<UF-R݉kLNҳ5]a$ZѤ&b-QfY|Mu>Y~޺}w9n``:nB;쟺NN.♞}{t`|4}]`h/wk_ᬎUY6ÒP._j~ĉܮM_?It?`4P&(O$ºrV>;=! W?gt)F|ƒRĨKŋ/fԗqaږ0o_X3ޡ\EDk3S+ۯ}Cxu57>BK[)ΌhvQMX7jyEz&\ՈQ]hLdoۛ},@=Va7A4̻%ݜP
tO6`N%Bb0xA6hLg_U|6`aR`CG=ǜ566ma̎4TefP2#<[\՜|+:gP[9얜8>$N?jI;0a)gtҶZ|ڿ#;&6kZa@?ɪZ:.̇4\(      ٖH ^_5* H@RאַVX؈Nc?s<;rdܱ .
eeu+#Af-rB0e˟>G	1M*),&7_1EU䔔9M-m-*&A'XbZ78WSۈ)tU>"ӌ>#s'kmr	I9])ۈa_@M(8@?y_5eA'?=Sc^dT@cJTXn1FC5Ӳ(>&Z1R:L-C~s_lI3Z
1/臄3/Ŋ9臗'ϟ4@^slv"k
f~@G^e,Z2%Q>&U?R,3~TO<!8ԉ[0Qr3aPxSLg22`!:RYN5}&1㿕i}%rębgpdQI,ԒD-+%%aC£I-UTk:#LcYN,Ж^4S+vRĆMh [ra'.)NaoL2q7AQTNC<rp-i]OΨl0:*jk#(@?yYJt>TAxUykrꢤ{ vK.
:!v\-^p4<vx4  	zrfR0Ǯʔ΁qh3x2~gW
~~~zS_6C$v@B	?g$0=[o?#W+~>1h\E<|̪rJVYKrNYbjTsù$qSH `E;߂v/>DW(chJEU{Gt\%Kq%D%e:/a8s5s {
ϝ"4MM
jM)緿ϨoȲ*GeMMZ1Cɜa+ \TPg½zOV/.ׯie{P;_ A8c\Bv.  $ZRWg<[)-r;o1PMkAfNr,FDՀd6w`K)uHdڇsWG^((
3^	ơ+IkCй3qF{cmӟ.T,9}|v<e8!0V}S'*#Y`tQ+Z4MU
OIsrTz{	=fxzTwg?4si!iK2N/%Ȕӄ~}apa^ZQ/O.NtA !!Fd3v'!(K/߇qr}BZ3;ZW7SKI͖+f5_VʡǞQ'WEhV7!zc{f~1u.mϑS[^N33L6{Pϣx%\uth	u[+by0:OĩƔ- L?"-}y>ye
+g裢0Z'˱=&l'_Fȿ|J Md">@1+:z9LeS@
䐻3mW'OWuzGa_R: slftEC*&Oy
쁢ׅS5 {8H+ʄ 6aV<s$Z $~/*@]խ܄78HƈKBoÿ[ɭDhxx˿|FXu>r9lN
-H]g2;+=ֳ{#RPܝNkA>(Y,\+-nsq<t7ߞO2l~}R"_jWmJms-+CRC=G'/sN}a:g2/њMPNqE$ޮWa=2ֽE	t9X>&Jp$s''-
@K=D'cw(}2puwXF^q?>I׀3Zq?3) @qAA'ߧh@5HϘ=!ewϦZIde"8+Nyrde ]0_׻ LwVݓi|8{68bs6?\v	&,T?5 eQr(qwBbΓ,KUܝZ:|˱+@.O0 ϮN*NRsvpsfK-Yr&6o-U4h~{Ũ*މ#w}ﮉWE8XzhfO-+;1r&oބ"XwDC(Fx}	U<L\Rkg70ę\,tB1oNS7~>КSs>>H_7;
lHaq=QS@4cE_x:g6RPzp;k\3S JlMNӼit<m$N
wr	)ٜ\إ5櫦BA=-vt{p;{Zp/raE?lo:h= =r&Rᱠ$(8sمs1`1!X~'p_g dfȅzop"b7?NB4 >"=a|DAح]mtxsè:Ãq#|CI9
FDF?>YzP}t)K|I|X0\iZ,	l;Ihha->;Po53	mh7QBM*s@)x5|is1F۞u  lOAMMh1C΢ojPSЏ/$TE:4w]!~b:uyYCnn5:Y_.xӐNu|7۟'':OTCM	IXC<s.,ORõN""*g|ѥd2sQ%\bi@*	0x5>@0|UuMQ`v3͛9ĉĐN;6x㝪ܽ~Qw{=tMwJy$(z\!idwr(z=p)Xu ?O1J;egB#r&٨n8Nf/JERd 󴸭RbkJ\V#am\ >:x6	ߍ0h4`
ߢ3,IؚPBGkG|+`GW'd$iX(D&O	3OPOc$`DJd3O	⾏*d
{G;|	>%دO8$
b_P;}`_t!qOdp	 l6_(
>:kp,juQ!]A1<x+D/>_{qàG@`N5X2v p`_x|w߯ )jDwv~'R0t9rIr1g<]2Q,oA~aNaЕ}/zgL#Cx7O03	F	>AK֩Ӏpȏ8yS |1
!Kj
ôj*zt+d2*l>'.Tק榳i<.)ǪoN;Ps৳9$νrPtBAx$D~lW* K=^eu$,:_`CkO=!! \D~H 7@فCG*z3o<ECٳ	Gs-8=Oo"wbd;y>]z_f9ىndn{h)3iQ2RK7SQ!@!GB;mw2秵`~h:|~ )VW)/=a:]䂪GH/|e  )ЧCϔ'|/yz˻R >n<+d'4#no\iGݖDT4I#3O{hy[N3#n\ww,<`{>O`AǗ#Z-הˮ,<dAqƩ<I|}>N|
el  }I]
bBYBO{p)_iF'XQ1bR]`@Ҧ'5%{-ʮ/3P$"&IVF֗En4{:(j`q(H[O(уqP8>wVӗ`	Q^f<1+h:c2ڍı@9j?(r#9%JLdjg+N#'x
ٜ7rsH9v߿b/?lιa!}@'1X/
oo<N\"`w[%񋪬3`L4vQ[x
ފ3k~2? CðLko `3etFJV~K;ck9`gscwKqZ=xb+BW*#1y.S{qs|PrZ	wc`
P,CY
y:vUZEN_?Xk{銪 *T;`DuUg};qY)?W8zZAVw>c`|DђW8Ct{fT1tI"2my̇1 
i4x[4qT`/s2sN(/r ӫ$?}cS_LL]dwR.0!'OV	X0,u
v]˧B,0Ҵ+|= +H4i߉)bIr Y?tD]SHfrq:'jN_J=v/#&U2bs/lE5O[uϥ8/=}&׿U!к*Rp_/{D.}@O K*[HO &Yz쭫'lݏv`uw}qHhENt"8&VW+|ҢN^:'zCM@I`	O,)k g=gU_!0䬠<	z/:!˗:@>Y$>ӽ!R!qKpеD !VXbsӗ_t.8s/72YXSir:&o	=3}BxbKYq'*krI5 {
"i0+sS^ŤC ;򏎳K(q LRbxw}ċfEzh˄xØ#R\?25N}K9}9g5!{?WifL 2a+Z^ =aZ%g.N{I!OOmu1J@<϶?BO'(G\UwوQ^!ogR܈Fvz1+TSԢ0֮t(*.Jǯ=_v{qh?M
? `kϵFBRkR4'F_MbII_*pw>z7oSrʽ2nS~^qr!7UﹼtZ77h ['Fڼ*LDOr1r"@,ۻWwܽ.O QW똦}<
8!CZCywz>jл^	ΰ/5XB@_Ro+fC_USMUȔ079]hx2]ʐDw~{R;wRG#/O':osUbY3UtmGeιp d;fF^4zc%:TQ1o3[βTw|Uoz}1Wå;SZNyFvoVS(n=M4]3_(~ ]
rSy^w*J
rwH"bOWgq(79#x"57*8?~=g~;ZkRn(2q]Dx'r[W? =tv᥹>#Mצ?Nž?.W5$xL_@k,}׬/#2X#_"Ug~y	$~@{]~gw&oD<$\2u}op~s.v|o)='Wm. k/Cw}}W\hWLߋ%P'HTVg+Nr0%ib:o	9z/KqUxnG@,(^=L)q^:oUlMz[>σWc̳{ :~^s"/2f@!`xO<зsqnߗNqn]V-}*Х:þ@atkă[n _;D(BsQ7)P?;Ih:1C>NOK{C"xӍH$L>L$ MӹOEǏ륳3 ?"Жۤ
߳we'^<]2ib:3c6/^xYxoŎqj~[ss˹ar1vA/y>3<y5J'&hVܼ#h[]Њ^ݳoup'ɏl55n{?Ѿ锇]tNW=y/8лƤ%	5p͹E}XwZQ0wPq?Ӛ&S[ HgUKRʬHK9O|Ger8)ST[HGst3Kç.P✲|tLZ|t!-pΰt%YnuI@wTx-nyw,{kUFy3F{Is}F"?')[y>;8.a76ECo)P_g4zSx1Cw	4TrQ/g+~r:c*az˷uwH_w	ɔȼDCO\ZL(|G4e	|'`6+5ByJ;(swYmXP~_üV#*}$T4%YMֱA
{d
<{.WY:,f^:H*D0LnG[BX_Ŵ-[ti6oft-:$[lҖjzk&6ܦ]_XaEɲժϪz[4$XfrquVsC@EѨHAWF+{`q<*][;Eqq?`AU=UKb>mQVd%)j+5v79-Y]pacr[b/r<S6S\.R-s]*JHTj~9DJ~O!R`c}w옟̴GJvXYbu|}8kU[X7y꡽V	qQozjs&ܞMR.պj$R#<(6C':BWf/֛ż3ZZ>SKv.3s"CLh,B+slng-P6~A\>+bio!KZXn^9IJM&ȩwyFzun
M&d9A;2x;)7F$cL|X.U,*sG%W4LieY3iTw*6;cf٤r|]b.m{ϥJzzRT÷u+;RzReRA4yf~V.䴢z+$̲<-0JsLf:ֆƳ,'AcQlpiu](["&.O۬L:fڥKhV
י	GضPղCl]5߶D|38$'tg6p`4;#BBqSYڶkjMXOjv)X'Jqϩs"ɕN`⩑2ym:fkQ+ݛTO@PnwҦdOi׭"?Ȱ5zR@)3$ͭ3lVc[(g]hxCtW@^MkXbH
]9Y)vmFFj6IemӆX7׋a]%?UeƳ/9qN6*/Ǖb^of=`J^b6A¸WDg.$cJd3Wr4A[M&Y0S59̯6.hV _~4$b}su\jR\ί#dg3^Ye,Ho~H򛁀u!_rTiYm2Lq?'"*L㸕
N}Z-ҕxǚAԵ|cV)fwXvPZZ弉[*7f\ΡD*rYs@^>%j<N!}pY0hHH~ EXc}CN6h\UP"XꡙB! S;Z,*.QTW\j<4,y[7pP_-\kS
iΞmn}TZрeu0]mj.TNu\m1bnfn݌[tKLi˒-ŷ:=_n/lXO{`o|b^b3WmZjy	s2Ʈtq\
I_Zcįl2L^lmlڷ-r&xѢ>]YMa,M%0&'Ɩ¦m"Ӓn-GvNqvNmnгXOKk1r4vm߀7@ޘgʹN@:6JlRwCLV+zq33A%trZx!N&>SJ=*cṷ2EBH[(9)͙]FTS+bH%)C4S	2G0'ך=nXZrhz:u%FkEΗ'pk3LM6;]Bh 6!f-vm_BU^'!PD<J IUqiԚvU[dg v%-FQBXQ0-ZPæ;SbptŦ4[gjwRXG!b:+g	8
6eKɞY7VQT@ZYJIEܕH:*f񶊪q.Zdō[yY;d;ʰ}j}"ʀUJsHmif:(Vdw(˷U9YCdaG QRZ&bɁ3d,/K2ZN9iL(TIDQ\)!.fCڢd8*Jqa$6jMb[%U#3˗2<f*M9H̢0ht?gW@-5uVF1DK$XdL,m3VC<T2` ]uak㪊Vg&-ThbD7ISzPoY?+Ƕ53 QrO3ye~8n.oM~)ֶkc	mL#
uS[37,xQUt+TCr3gVZ3}iϧS|S_m&'(CU,f(Āh\rUAq@-+0cZPJWb_ 0v6*K8jq]*C(JC`BW̕ʣ3v*5嚭vg\ЎjlX{N>n뢾\U+<TA*@2P&:#:M_!=haf;mU:Q%RczOYcirre^LI%sl8IDiЕ5[U%KdWұ#只(OV6XU<S<
7j _HNȺʑ;[|]Ǩxэ~4#vfn˘hVsJ̬;&L۝ZccOhe6T6lw\Hi#JE𰰷CKfF@2F	^a7(̫!fI4.9lT;}Wkqq;eumW,+sVx<kS@*ݜxn<)Wm{JcT,BeT[3W=30X zRg|G$4G	Aզ"lYޔBRXޔWY\q KLpDY/lOz*cY+%X0Jik.LG|RTϰs!9kYDu25j>G%c)=72>xZA[k2rR ze7DFOӽzHUzeVRިX4P{IJAKCe onٌP*SZzX-%GfA4@b[8'ؽJ%{}ېHs;|wҚ IsyMũ8,%֚FeP#ˢ6kYKzSĎϚq-]1>"IW+dh8gq,zjjm}g5\b,模1^@>st^ScBY`lh0^K1BzSn"*bJb8,K4PJt3rYܭijl%ךTfݰ, [jZ@=3*nfc,uV[QȺP1T:?i5Vsa2B-/50\MvqVR55	XB\yK"Gf&[n+ DJ{N iB'CZf=G;
h"d@'iB{YKm\4¤nV ,.%1jSSeIbT_fс8;CTև&`+=5@ Z^9H~ =r"R?0ra6켞_gRn5X_9&6:[ۓ2 ~~C$&ygUŃ^ V_4+ h=ڟu^LB"(;0njÙͳz$w|KN;(%F~T #KH)PyEĬE]XM`kh_lvR~Qx{*Э1\m;:~ <],$鬾43eMgV\jjRQQԅ`bYiح$k5<O'!9H
ʙdՁʺe_q/Q2əD><#@,iR1k~aIMBX|RIc:O&Q뿾r`vG43&.^q>PMU	s2`n^?&ޕJ;(
Bd`9ᝆ\N1#Dqz}_=3Sǔp_Cq#Q`\5sG11e^R(Oܧqݧ?UR gI.x^?Q,hwiGHJ|wm4-X;1M*Vvjqʴ9)".E~)P9q> w(<q
pR|ao]/f< rRg(P&f8>PNސ>gDHa硚͚4u.v0stK7m7D:9tӹO9yv&̐iԴ꽥%th9t4 -?aKb~2IA\4;;I<A.G4owrcǧ/,gw0mWo"?*麺sVV")_ڹg&ܢ!C׫gG/M}S]9y~l`^_}X"|ı>?)uƋw:58.DV5SkqvY1ý8>koF;.+}{ "ʏ׃tW|gb9#L)=:y$NH:; iYyFw
xD~_!\2Ȁt~qzo0/MǽxU/Q gGV,:cZKG|sRO.5PPLn Glkm&><t |MpL}ދq=q	Ps{B';Iqxyz<%Os/\ུc7I9J-fnWƝyqυ{' U+$E,o=	x\Saq/z >ٰ=O57<t~=?=v+"xљ+/:.]=YO$;Yο&U$P|T#2)!~@hxb.`+,wIڇ	ആHjXwhtG`SM|fsŐMT$hKQr..uz%Md 4smH4
ܟj{⃶xq0rR6p&q 6GygQ[--@Ƌ@c,%Kg硳y4?+:WK '<x%x0|DZ56t#Q]X*\Yg"dћ-B_xE#e	O=M`tQ3}ʫOD>=*}س6{C睡/-a_Pr!rߙsu5Nl>)3fĖ Z07R<-GJ̋)pj`=;lZj;b `HPw8|)C@<ǈPT=|r<w\A0f/`Ei}T3YJ#KR `_DYSux -}MTNp.]/r#NR+5%we<ځA*`<eKG		}}^?DLuliwgyOa]HE"I$[6(A+M Nz{}[R`0
]~zOh;l> ֯_sp|ݝBYPɻ)jvgNnϣ/ S
L#`w7=5w+1xC%s뫹B#wkbځQ);`*;M s|bKk+rq!qAs a%f@nRGp磔uN 9_NLj[tf@k8=%cH"vq^
7A7u!B.AޯxR3·(f޹c5X)z>0|gjx
qb=k&ɻ=f}
Av<C3RIs@/w@_J_rw>\Ν{53vVG/|SA!yt])X/.ةrG#hQSd'ː?vNiʸ	A\qcpHO8$$âbp#/ϼ+"Rw:%t5+J4k墨rZM߻C3<Vlؗm+lAǫ	h	5,/;Lbx  ;/KD,x |}
la G@rxj/< СPxsL87 /Dw 8qEi|A9!
+)H2]V8NzeDa
Ow> _V8w;A+RܢǗ x !))u#gلw&Lv vޛͪSᅔKKN4&>wcdKCG8;PQ/CCv;,\

,Dèޮw!b3*:L; Pp\DB[y87]0(KQ0BJWALK# ө#C<|;XuT`%Fcν V!uFxNKMN

`dj~pa I|D`pޅ}[:X!@`LYT8&VȾ! #0&ɱ~&Ã¼aプ"  ,gҢ(? #B]Oxk9nKN0MKo{DAA-,(knY!@QTN߰>:pسGG[\dcNO4nꙅ?/ -9>s䆛۞dF^֔*`ķPؿ$9nmĳWb)-<V86|=-y7軐o6CJ9[1x}ΗRC2w!p"J7Pt=aJdtB 0p)a<K|%F /}DlE;qR ֛e#vƖvIj"E0Ս=9DGk`0.Z˴t+NM%a^[8xq{m]xGf4>v̆q[)2`q`[QIXH]#mׯZ0?|5x-wN ȯO=}FsGba'M{ƌM*;,oN0|4~C/g8#bZwX?;L:ѐRQr$7Mh^wǨ3JȈ1>Lq}⡹~pQ,rB'=
SMyZ@RDӻy>8ެPn ]Wuu# m/{>wl!E1ĉq}I'úTDe):P{ڀN1a?
[2b@?>-%vk}ꗋKu$Ϟd8_WIG|^TRs-%X3r13{Z`1E /Lg	GI`) 0'9%|zōWm bmC!N^xT
]:>?T3M?g:Dv*\mۉ4%VN4[s낊
ȯ$\r31~]'t̀s~/	VH`@)rsK1E7R\OwBN7o'}bmO߾)ka.2BɅo=%DxXi"Ti+gƟP)őgc=% 5G<aФ51 >#t@}/<DȠ:ӗpr.oQ6lEK@,W[s[4L	H5/Z~ۇ/':wZ"mx/a;ftH/"JVH&,V+xMHꑫҞ2P	=}gF<jג[;Q- .Â&bnu릖FZE(#,aӒŝZ8(MPPs~qjY6ݴ^?97 ދiÝnAG@&h#16u6ibI3&ώW"DB]u#<7
'`b|F"FB Z@w4̓^'[>pHZyeMmޞTw/k*3Z˹{Inh?JH\47ϋB}:ks	|6X:1kxTmydƠ\sݴgnƲiܖ
c3_?oyuӚH)Q`J)ohj&K`B1o8gf-҇	>6lT˕%HlŁ*Guq0PaW3  9YvL1XdfSVuA"Qvn65s)_ZbΜM<m/f[}씉I#D!EtsF!vN%y46璲,nsLR^O:YAzD^gJrw%2}J^fO&2U'qf>+[SGi4KbmrK(yP.A(ZnRO#/J{.G$ \g{E5VOTRivƧ8j(p$2.RN+Xʦ֣r8^.>
"g5ǉ9FldC)";\%TJzBng[I{[SVFk;'mk6(ZܲKQjd-Ɂb,(b]ce.&ӞX54JQp|0Yw9l5!Zc
oH7i9rA16fJ"FUܐ!d\$ij^énx]0ŧ=Mꤙ22/r4N+a71dV^Unf"E^	4S랪d57IeVϴfiq<(z͍hNvvf	K[T8"n}ݛ)۵79Lcj/,y<wOK}DDUQm&8[6ȼ2ӲtHk˃e%a(P`6d0݃Ԥ4<]i^w}nAT7rɶCUk郅[nkY:]f*EV2s$2c2 K<CG6K}ddu)Y6WE<3J$N)Zd7Yak-+ouM&Yt̃ۢıy=8"&e: C2IC!:-4	R?a0Ǒl[&S6*YhNhZEz!dx굕P(ƚʍ'5 2n[YvM"i2yA,+HF͏rc0WK]'u̒Zuy>uڴm#B`6d 6\oK
=C#yC$*V
}t0)eڴuq;Sv]JEsYT{?rPe=(t-&0p-^CGrZ{.)8gFwZk^syӞdj+Y۬xt5K-E͜Wn7#n$Z5i2zy7ʗʻ8(m
+Ӛw;RX!"#irHX:ehFrGA]rvJ}Wbgͭ&Q ?XZ-6
=^Jv"0m
[@4doaOyQkך%[];'.i*SJ)PD$Elⲳac<Rj|rls\YHlgjQGdr"hUm/sGiakb]#Bpp0ȭ	B<>6%iPE0b)QDHݦ`I{T=Jbծ?TC>֊D~2K/{i4zS\yޓ!gE]*dY촎& Qded.ke	i*UufZ7v`I.9Z;B3zFy2xJsG	KRk[!t]ixdB2$w4NOiv#1A-,Z^vV;ۥ٭ -w:յ`xDHj0+jiI7Fz@	ޮ6cHқyuk\,}KѨ۳ʼ3[iݶbW6ٕrih!P
`#@|nlvp5-6F^h54✅Jr4U \툥\&Sbʶy>[Ud1
),g6:|ɮ/,Ln3dgz36EechIFj62amr盖^s2<$et PH;-ڇ*ZZQ擃"vd$q`
ee.15uZnW8t\"GzѮ!bI.XZ>ͶTnz#ASAݴn,iZwnFo=2f&j^@s1l$:+1KtVߖ:vYOvPkkҖITkXP̆îjvt#RsEP2(nw#2)3L綁$gz{ʞ5N^D7rrn	U]6>2"Z^qQLvᮮ`띬%KM_iH}$tUGD_3=f֘zhܠպ(n.ݠ*	)-רW,T-lI*0rCJ#ڬrq"G:+ E}lڂH@)"~kww"%am^SsV͍{xfưL0ov~+;¸[[E-;,j	6Ӌ-׼IP٣Xh>W{B_RGT67n v'y)WZWH?<Nl~(ֶJȬA1^%Q4V1FP¡S,+{!<W\&7YWZT3TRBfcB:GDDfI#VʺeUF5TMlqnv Ty=דٌmɁX;uQg`mQkY>ըYp܁)zdU(钤T%)!\kҳmkifGu]VIdz>Z׏m^3;;	Ze];ZE[2j,))k8t&mV?<+=bPj]Z'-klr܋B$ZbXYuwͶ¬tSVƂu6z򦑞UD$38.^Pq+#=l4k]c`d&:eZk}`z&-#a\gfqCaubʺ#[5CQi]W&]j~LfYjwCmCqj=#[϶9xqܴ˴I#s­PӉWsl&fZ;kxgIs6CI.v])MϓlYU䨮\UJVd{Fa@R0}2+Asbà^д[s+Nުͨt;_tQnVav+|=vSObgW/t!?bd<(J}!(}C2|ޤXk] T
zvJ3K} @Z{ZkD/5n:k1f"f8F՗"}'"ސ$9]"[8($&خ|vzaqfř6/w%=Wz/AфWחt"m}VuՇY!ّXg*]h&]eHuOo|U+O6E#$xs5nd;{/]Dqͻ{ct%MN9aQ=%a'~5V
Ÿ	ئҥ͖ͫ*z:_>#xY~O쁧2iMpG2OEnQ	$1)arS=$Y#&̜{,I*I'}x>ؗl l<Mi'^"uGR'mj3䉟otkJյA^xα`5;ԯ7uRUd۲zLC! X3܈U(~˭U&{JL;A$b=Z-dE}aAؗXd!.hYr*;d]"
0ODG}6rAxvkG5,ew/z-r;a)^>N7a^RPQ2qmyjrUf޶a3tǽYBaΐ}C,Q(n{demƨ@G0q HN^2\h@K
;c^;C"qCI,>SSΩ}%NHzqz[9J	֖gílImO)ɨ.XaXjY8V4*$mfl0߫0-PS聾8Z^Ps4ՏjDh.]xyv|dś[>N?.$hfQ^LޡqtK׆+Q5yM]r,·1AxgGjja6/?pg&Uo~iVaP~1Oб892\@tO+<9R
5$dտӰʾw"RXuء~um&ǱCڼQ9z5􊑴R_}p\@QN-[^$+nJa=ZXC(\=jhہS0#=bbhD	h~I]#DWˢN(/*%+"1 "Xh@PźX$2b$(Ej0<h<ț0X37ux!x:KS.
v)z1 8@]^_TP@i	zY|j{/zt_ޝ#_´+l!KC$y^oE\5Q4-J5_X!:[4q^	cbw;mӗfJGZ$+Igezf<i @/3ݕ2Ex]Y+Ћ9.bDw!T_~RgK˓Sv[Iq{מ 9|I ?wadQvSj)Gv3C[[]۟RdʍI'9UBEkZMY^
@AE!U"kv>;1j<:4؜A~}B[9I뚈y5	[7~0v.+kT^X uOh9t*;-PŲdK=23:2䓽pjY	~#'
 ~ho\ Ycu~Wry5SΉ6ΰ*{烛y٤wpF TSmʾ8jLsf8̋N7aС#O!zU_0/\{s󾱗q;w$)3~q<7
@lWsQhܕZ HBdY #{P6[qh3 a9Z4횿tmן}^ߐ\ܥׁ}#AwiTi}o^03obRks
sP >	PqQ:S;#KbPȎN4\0m׺ex|>]#LӾa|r*,4i1w6*ݦ"W@e:ϠhxS?|LZJXР4u@`$I/3-#)1I}kE 'tLu-~34	֧Bbiq5çL'VHr5^8'7Zf$[rC2D_(@N
e^{S(׻Uxft+*14@Z#mrxG-$H0<"g2י»;*r^ßͯ5oӾn92s={Ԙi$E,
vGNDR[e<mHMjVd{RNE~pYƻc}#ۉP))4cG9, Tc`;2|/|@1tx$<,\8-+FWA2V֮EH +nl\&TFݽ(H_6i-z&7uZ/zQV
>rݻۏ0!<T><8efed<E톺a*Tl&s>d# L|]fF[w4'fm[Bx-s;̌BZWj(GG\t}1rNW\d(ƴi+Og(r(CAՕ8gޖquؒ?#J3[8,s\:Eb!$~[{@&>%'i>C Q<Gz"ېmj昕]48a81+Q,Y&KdEsM̗YZYp OA
=8,>㾠AU'Ǯ}CMkGhDGG'\S_O#d?@I׏젠k(N'W:/ᴀ2ҥg Mƕ~]poLB2ͷe#+ڹ7};(^yɀ !­z"-K7Al{KP ;S/˞lƧr#j(Rx=֣7ȢaĸJ7@ofN_\C應aq
sr`{`n Qؔ$uR$2Cimul$V,l'-'}Ͷݭig;mѼ}̸>vAObi#)+^Ȕ;< WZA2 p*(f@ 0oP^&,|8횼Z$J(Ƭ;9LUd' .bvq2+}Wlq_T	0֙oV&}}	fTrE0@
hjhmm~;Bߙ;M4n=un2\9kQ-KRpSpGMN=BmC#ZjQ?s^8,soI.kO~)<CcV5&ɣAQ}m
n:Z	fRrR" }4hPms[X2T  :QKHXt~DCG;USwQ2f)VK*68KMvh8C<|}ITfy|5+pjn%R_x|_EKVJL"4cTP]nك0כjo6Ig}zQKkhcu8B HAE?6ZpKU) (r~yڷgx;qqRtߢMqZI,;Y!Uq@Z1ޚ:duU'=rm2ϙEvܷ`Ym~p{̊ϥ)Ȍc֊ FP?O\Cw?]K}!(,K/D&J@[t7l	rCLZ%O4W3dD$`B&&Fm,.Z4e|uY:+Ͱwˋ0ZHKBb@,I!<?mCq&__ML;7WmluF	U,8Laں8>&
$H병$X$}Yܱ^:wZμSX"À؛\ۃI0RLG+^v)
- )Dڅ~fGdl+݊lqw} +97t 6\&`c5IK.*Nר1`4ē)eRG+3ikqԙoNL4OuVƈ_d֘ѝU
`ح\36͎Xn[f>2%B3Ya{/;
ĩEU
%"gD'l81rfœ㺔A9Y0sY3"ZP~9guYibFHqǉo@_m<kD<345\`]Om.$$)%ÚۼdT2wץ(|u;F,$Wk,A@$1o8}cSl}̊5S:J׿[kcM@B'j\YS
8¼mJ:^]E&upde@U8k(2Ж
VW:EVM?l<PQt<*c|R݁=ײaqOpt>x+CGV$W\beB5u{5Wo$	.~vqMr!HڬM/$K:64M'&UoC{b|RȠ^KIy??' 9[@Σ[wS	fzsHc8ňbfȀU-KVPY+ZG_
ĨN;??m@I
B.\l7En'<.epfMScqwqY3$*s=pML4F>hEG'@Vİg챬p`,yP.CV/̯NQ
)W[~c&:3O+R
quxsۜmܠsk,Ej;1얌Š%E2ecl֏Zwۤ49.R>4ipWBTz`Q䝗vAęmFnw	Q`&^鰣-r cå|jjPxk?zB 	VbO&LեP#KZ/D*jXga4ѕCsP=tf/\LYAGs[Ax,VBʃE*?K^KI^4~:NY]jg~la1lWڷ[u|EQZ]5.esu1E:K^=l|tN>՗K~gIY5҇}ZYw1St&vi	)'a.thM~tGi%A|aqFbU=oi=e!.86pYDX»~zߪL%k2N֢T}ΝR9^bz#"P1R49F'L3}X~?Rѷ:NF).q{]ejsMܢeqP*T˱CrTד&j6KM%qڻiL>Mgì8P^9M)_'jqvMteetBK:<f!P\d/nk9v1n>V + ܦO83vg"+PaF=9Zań2%Wu!+^ ߡ.dXOVisE0#u̶RU|"֨D/p_F#`&~Pnl[bxw󂯣Ӻ:=2HC ?n5ӗ)=50\(	gvwk}J@*X۶K[O7xP]ZX3%w]'h %dܗLa'FTIZ݇{͂Ntֵar#/z춽]{5]'Uݪ\x2]s\%fy$nP&E/;{Co@g+Lw&&=>W_dՠ>s hh3f8% nh_%1:Sb-XCi![n^cvr`w,;~t룽`W hſ<$JFmO"oV [xI|HVD_bq7*H}J ~Q#éahv3ZCNDtr	7W^Ƴ<O
!j=ײ"iQQf˭b-fa}lIr >D0FBhP_H!KU+̏yuwIdX/ˮE@ B2|"BI*,_uj%!&X6+ӯ<4T+Jn{hZ(s)/*"N"BRwG)!lVЬlG
qQ  $x=*p	Tyhwϵ}=ȏб_tG0X^)Vӫ(#8aNLd`qʸZ%Iuy]Vqu;}D̏-6~d:m q/ωn+L~mqw/kZk)zIĮ$/)H'?gxruwoM}]E@bx9-typ7f'uq!dAu^ger.F/Auy+尅w`K\_`Td=	$_͗(z;]0|~4%or@nE}p傀]c9~Ɛ\,ә--|j߇)g<EQ
d}geAo5A'Ƭ~3[_ɅCk>~iIto=Wqb)g[fx8$[?	}	H#/trP0H`@ȎJ``MinY2k%Up/s]xe}Hv+/FZ6bBvx1wצ"eYJcئtR!Hrc:\7k
Z|(
Y+彮X0jMdWaĆ2m*Ve#ۖm`E\תiSH:d/ɲ0 _cv#eKw}+,ߵ <HsٓAs-~`÷6wb^DUC:+i`gl|Z雸G硯 lKd<Z}g抢Cvc%(gHیji(`DCc~R3zm_Fˏpø9tɿ;D^hL\!@여E?R^[/,/7Iq󢷫< ŋ`_1l?ysś WC H	J<vE>	2<Gu<\o̩C֝Xn烉el{xgCyk*ATM;.ԉ}~Q|wu0Q{(y@#Ǘ/J:Zp'} HHiLV=n9jL<!2lE($`P9>n	AX1r|=Mj/h\'so80;d;:ZbǺw|7s;+t{3r2-rGBJQ?w%,`YD,V+i0Gx|rxR[9"iIf~-eܴ$knջd_o]+?7kgҵ
WQ'a$wgl-A;}tǕֹfM	jP4ըJA:ɰwRCj`!A="Ȅ!tmD!9*#.P0?a{|7	qVLubl;#BY3ܶ+$ƄQE|P<XA'`hT"e?γȷXủؑNqJleΕH[;Ǣ8CFƻjvȵiҒ:}f&rA m% `[}lXu ?{.$7)Q_a	]LnsٷN,@$iIy5CjΐϑPsM#W!	3UNXu0wtGEo,#~VteQa*l;lfZ#25to;Kg\j}I2Ps] r˺Q	-]%1t]^N$	ktY^2?0mo
cnm{`%6ي+N+F׳s	0!%ݳ+p0Cq޹P8zJ/iKM.Ԍ{i}f`Da~IvQ|Vs)"9s2#O#Y[`CW{h%f8Fk0 SUfܾo⒬4AnʣMyj΁c-	u[<۩o=TIۘl3߼=*6/DIUs*ZCc|܏ZFرMQ5ƕ<j֮e,EmA^\K%10 :As9DnzPef =hHw O5[_[X"UKgq|ЎϠ^FCuп<K2J=,̔oio	|N_Z]m7XmvEk%-gznN);W>@b!>뚦3Oeq}e^l\qRzXc U8wyM&dXKazm(O@N\yF1F~S%YTrGJ%H& zhL|Usь?kߏE!Jl2I} Vc!v剬!ԏw>Xb`J7	9R7Ahr,~{U<N>l@6WG}9> c
4(
u>+PҰ5Ս>8UO{/i)1-)뮞Xbv<g;S7!
8N>E*8.aKqzu7/m=k[P2 _,A {7FF%g~lʡWmgH͌D7 h]з=tA[$e|k&f{oRlNI"oi1q{J94S&C6ޏ~I˾%zʮJ56a5d{9/!,۾8#.mm2eNstrЫ)ҭJ2x鑤3rh_	39aF)-e_lmoX@ OmPg WIQjK-֝q̍F-yyFVt.}XPlKhJ5֫9-/=Ԛ@ )2bɉ`\O}5ɒ_|X3~LUeBq	՚-q-cҭDWj?2b<Y{ނFN@:g~yM	lW[76qO1ѾQm %%Jsa|+-/V/7N8*TiER9e;hÔrـP˒3}ZgrV
^ݑvs6,i.[B,Î}P/?{TcׄăLPּj[({kվǳB*cB	^n2}F8ԀwYhlnS`OC,jhF#{GNXzkQdG<ڳ>~f5Zq9#ȞuRkzBVA]-529Ӑ%܎XRm:QcRvn)fЍJ)x@ S$ȃM/wc;ii?'׿䦟o'71V[䦔ߚ{zs&]=maU<\T [(;;D-}\xtip-Q蚽Hh֚}HdmgosFzFb	)Lod %WF{=eA2'oM"omPOz~lG^" 6ux}s+<."\'O]Z=B_"{;f%];.NE9Qm˙/D0Ժ$VR1n]Eb,#5 Kں7j~+,*o~إʲ׿?Of-[t|b9VYɽ>u2,Obu5TbCn\N_dVhWŷ9U'*@{;ގZ7FE=.|<p';:v	v+13VkC|CnÃ`ywj6/(|hlFDk4cy0ύE%/	﭂] QaÍ3b_v!q[W8{#'#?GaxPQAzS=.'&uzs9o>	I[~#$#X'mPY[P1GqbHajίU娍'Ѭ;e,^Mgk"(9s>6dE4c2MEx@6)w}2?"yhݯ}ɢR,b%P2Xِ^Nrzm 6^[nJ}C1Mop%AgӿT\L^@SZOB:OmZ.BW,5DHS;l>m|_	.QxY _gi0-tS[L,ueEVS:9x񢓛h'1t9ZCy糰d"@z&#^Ե98{Y"2Uk|s,qRl) VfլwBx]64VI	\Ki»5Om&&	
\|a<Mh;p#| Q_/N5o89
<n7Ftmyd<<Hӎ[$E<<g:FP1N9<WKXڤ#y޸fE}<JWxO-]&XgFUcHMrUvW_OHjXΥx-ӡ q$wѫ#"jADM{rtSXpY3kRgHIhc0Ƕ-OG)AJHpQo뮐)nZЀR1be L۪;R.EUPr$zTkzfm:v3َS	حј9G$sj
j
j)6SUg~J)ˈS4@NUj!u?t<oeơ-D~R\?ɦ1USk  T=ʿp`qs_˲,gY[oe*3IYIOD_J;<L	EIV%y8ڲOFڪ(zg)_DʿINLڽudl/>N)_Th=]-Q$*}WhCKymZ-V02T L氿XsP2S;dT-8*6/ƆHe	X&ٺyE}eF-Uȫ0א`ݖ6O2*;c7/gU[sFDVItsJ't%dΥ"SqgsyB{#x8o&S+)ݙekտHحvKyojL	T/+L6w#."|">WAA1֝yi哺.+&FL1dTv#g,g
s13Xrr25ynǲl?Ix+UYV`b>?"^-r_%#B$kƉMn}ci@4`S-J#|mn˖U+}ݭ!@tUBH p㺂(@ ĉ?7o?/'8AT}}7Nwm+W\\	m0`Uq';![&6L9ݴ1B.X7l[&&n[>]J$Qk#`%![5E2eVVN5k#b8jZBwpl1AU-|S_28ev)pc4pV׵	?
v#TMf[]/zLfbRèO)Si3^DTj˾5)j
Pce*S3c *r:RU"2~.hVœ@;V,DR`C/݀x6w(eeLkM	4Bm6Ԫ8ްBSMM[MV,29 S|N,7ZOWE*p.235,aGcZnuճθ5AʈgSBWţ!3 H$x61Y2MէJrl.%͍^/k.$1{.\,Uʒj*&Skr#)^skbXVNa6F=n[0pȶ]`zAq
S;G.-jNFtdeo'tG@uh&f]"L@M2pY㵁t'b1xP*ڳpacy%k9l]c=b OVGl蔕HAM7NM+G')7ƪ&#Pڢ,4Vk2i!֜KZH}ULߞTV^+YRj4)4e`ybxǤb04/cj/xV$gJq] [;By.HX6˻HTE%譻|9t%6f<Nj3{MʅZقZfG5GpR]$,ǚhEv>Y/!tE-t:]-;FE{Nio22czZVKFXWr㝄4㭻X,RͧfKJ3œU:g[n?[*4Y(n8DѲ;v7`Z*u_`H;X\J)!ܟ%pu3Rs*1jQh
0=zIO7x}cI51gK657No޼[]C8ުt>%Y6RP/ؐ3j^kʚkk"P\ٰ[\jS	ZjD9usZlYDc5`0Cu+%}ؒkmt$6c8%LtԶ.!ťLb)0L[^Y=nV' .GR"+DN#mؙԡ`~2S,x$jWdA3y-˚1Y'nHԮxSjm KIٽF \]9VVJOh	~*E>~D%.ps}s}#_\K!,eP2!Դω%م?1Ӛ!=0I rIN
mgeRhuRB,t*hV&UUiT	"*ºZB.] 1jf8l|S-Gcr4BTXqequ'%Nyoic<h"0D,pʄYu[5CՄ*pR!md'(e":FuUn[44/t#wA;vtm]2 ޖwLvH
FSʋđk5l>J&ZuԀ7٤DtkFWk& 5Q:Sr`tR	F+%czj4	2w2>״|g,B!Nǌ(onuV3k{#B3tv"/:"hʠ&4G(J0ehy]4"enN`5#15gXzjuxjeRt5nb {4qjn$)Ѩ
&]8*7H+X1tKYwF;I߲+M𡻭M?R/5b܊cŘt5qhr"ͨ=&BS[Vխ	Nz8r`h	v9+{K5=Z	Cو߶cy
o2{ DܤlV=xt_v0^hQ}][k*Zʥ^ZQG\5h:lsE.\lZ3]YLחhuĂGcv=^OMۭ&үag>IRdxBJ{84A052?.[\pL0&)oBDeuCSrqi|owol򱭿A*SȳY~ R4inq)Đxlov2VjVi},fnIgBg&Y&s^)8\`Amc Ѷr_:N6lWdLI=jH"8'XmDҤ6ytsijk
ԻЫդmGb(IX+;E.EĬP@㮓r6e
ǡ&g*AX9=#Pk^wнX۶w815-.>>\]+^jH!^,'呍ʎkqrjby~-ƘٔۮiN0*:Ŷfz4ao<Jn%\)O% ~{mo;UŨrn
7dPs뮐|5	sX\ۖ_T1Ak&Z[mNf>LE[͆⁲8hbf@+N	
e$hP3U:ڡp%C<b=MG-$ih	F.J-FSlH&`pM,gj2Y2nA<W-k#jAyYm6-"=m8)O:s[iM67Ah2kZmi%Y8eѣJդ2V~R/qW;,ٔAx/UmjLg<JN7)5Ѻ&VHd4ʄ\mm#Olqo\jPͦלӴ(&˝fQåŬnN~n9[pz5C892zsSBSjwkApǈ
>tVTiꀎQg]Հ+;mqn}(:j3p4
ٝ2k	:ҙ+>m6EN[7=vC؍frySRaqjQiAY}:rcRbAvvb{lqd,h l`]HBG	kh;%h4Za!\acwS16pxUIߩC$6,6-q;G]ϜF	6qSfcšPI4yUШ#uD:4Ԙ1$F:b
q#IՆ*p]dFtBngL-9H @FٔaCC	/5t0v\npLx'j`(XZ=.*VfL!SWp=DʁjFJZi}(1 \ln3KWj=]}X5㕢H:+I'$;@^rvu%e&BwDlaVə qr,Q!7Es;Mjz%F	[4_TZ)6G4po*;ShkTH`#݁0vC"\H#|N2B6u*XrEC29Jٱ(j /MjPId$sXdKx**.QcZF3d[iy)u@Hõ+
ӵiD|xX :rUVBdLw]=M`tRebװI<	ebz䮱ܸ0tk],+b:Z%ʼlYV,LBRWu$[hmW}5icxlXB#ed3p}`ƢܛyNn#/\&dMi%piD.dNrgoFԑP,=lDlrSp([deY6fe2YK)%]bDiz֡(*M9!9ڑ~\-9hsIYnZ]yP!Í^/L i¢j%860ܐAGÑwv *hք0|:@TᚙTЃG5m߬uq}v ⌗0!D\M[N#pͺkL9CVV4w%4M@uǞR.Xh-/vEXza-RΘDFB?G#eg@Xawd]_&U)@칤=Ś;scTBW	hObG4%x &-[R&r&7WIlĜY'VXF	M~OD#|W$9Ѷ*qKIrkԛL_
)I{0cOM2bTTZ-j-c@U06xЈH༵#%xb&̰;H$v),֦} ,N/阤]2vue^]BINGٖﬆ,1	p:e_<y/PI޲!WSr)TSg	'@M0]`r@b{*F\ӮfCfSe$St8[DcHfdA6G0L0"7ۼh֢ym348eCyԟ3jڄߦH70|7Ր18-G\}8I^ss4t1cߐA$P+lLqRӌ	qMV3A7ttWzuFa"F"f8R!0zwz,q5wlK*nT^uqnҼG+3wB״xݘ"V
/ǼY#wgyST,E[w_P~s}~7x~VBlw֮\,0ly	NV%YRֱ_,z>dЇS{_]M}-p~[gbG%;ݜ*=Kl#+zv,])q{/%yM;/~c}U4)T̏_1qѸ_^3>{o#Wr0KZyn+QШ}.;R6P|1q-}h|FO
"O͕q4/of0DJ-׺JTJf
eroݕɿaxKrQO*WK*5H)GpHיxgA6ivbsfp,0L^<-#Ӕ	ڨTRk=9pVrZ3]sݤQigg#6e?F>F_$Ue'2=ʘ\ꎟdrwX	ߏ`dWׂM.rJ?tdNVl|%h-Kl~^]HsDF@>glV	r?aTۺ s1&N_#QCC@}9JHs p +$XO߿A/f|4 ycw%i]jRɟCn|miVSY
_5J%U`>0\`JGc%PNUWbC'{irxugj)Pfˍqse;}h
~g?mlkqSX6xO=9o%WρY91QWݴTU
U|/ 3{`&fFAݹzSXa?a_)a@ZI17eF~o9>Z=?~&ԉGts
މcd?*S{NφK0)ywKex@/HX1O3so~ Cq|Q-]UF|r~aV4_ߚ/{⤇Z;|5aUd0&GjGytI79)GP/B~XS,3Z`Ϗyt:^V3]T&Z^췓Ic{k˃
̄J/"gy@iqR
B-\~K?'`j()dJheQ)ݺORΏGg"g~H'{WiwHH>.RN"gDb+ #◼ԯ_,=TPG"i-bg\GJte3wlA&	.;AWD<Q֕UֻS|xĥ{cZb<9/}v8v $_EyNw27δ7%hz$?\=h-F,ѳVV״\+pl?V<]Ŵ/Nn	9G4Ӆk}coqcpq@ˬ,(&(Qfp1˕Ct0<J/e0
=h,xoR\_.-Ѽ꾞V-VזSSlWHId]?q(05
|=?3h Uuocp#P\;1 'А\EjX/-﷏`;?wI d8ϧW..b˛3o{L޾w\K0VE+'"Dֺ%OZH2ئžJ.Qq+_S3-8!]:A#g~/8~&ޖ3aTm+~@,)z,QC|W b)8nᥔ B)-xan{J]a8xO1o͟޾CVS}
Q'njN ij&do΋#C4B~ao7(ߔEm!vBg]isU+"~7"K+=/3!taF` mҾۿ<kWF=Vԡ㦟~TA椀aXi'0w{4*w ץ8k܁7]^«ʸ܅*7CzPӵP"{=sHN`J~}~mJv^:z{)ҥ@$|鼾`g=-I$\=[J_Kp9W^\+}g^1tzi]6:Pc8 tVս{G7ѓtu6s蹢HFDUeiMUn_^lmboNIo=r *M)3j#S ͸opFf0J{Kez>`M)^l/2'|gC5r&T@Vb6s!D7mxxςflq6:J mN<߿iwŏ}}/n|CjC5^5HqԼ&'jҠPcYֻ̝}rtcaVJ>.&}sO߄};R_oY\14^	{]Oy)!9-p}	X,{Hj79M*9>Z
3GFٷקu!2əyCL8dN:xTXQ@DW	~w|I 3ٯ#jz>Qgg\mpK19x855cS3Y$̍|b}0kC_KE%ڕtB,*IvT<[^F.R[{1Ƕá
'xF{ߎӷTȒQ} @!9o[9UΨ`іs(/V-a{B](P&5sعxsYDmc~cu.bٞ*\7c)޻{y8xoR~@x@\Ǥz;%y۹wy9̧o><*b~*7P.Ta6_Ώ¥j!}q	I~_-h#KKɧlFLi~}Bܿ#o@WwUkXCkhrq[uWH3=,sE~p.YnqR?Efiجwkʝ]~_9U<HZAdEzk zJmby~NnwօnƞT,Zfu?A_7P++A]+AeQt
~6Y1?Heвݴ|l6F_XWg'(^p쟊ΦRy?6s`q/=},$Y"ǩChaǝzrwIVWCJ;c2`ҿaQ.Sʾ]nCFF3rbdHv;kE=CU*ߟuU`sw7Szl>s];Rk%~0B 5{Z]*@NoJ|r6:Y<WjA-- ^U%p8b-<X✻^&|Ggs
l1f=[-ZSqsz7@ܮL^ZM).e|oW.~evag,7SZ>-:WLG,ۥQniY琝"~XR-lhkwOSݷ~6=
~sk⿿&>˧״efBj[^}Fs&:Q,R*<OtOx9ZNv\tgM6u檛s,Lc-p@媝-%/r9u׀V}R.ʒBcP>C%v$ _ry/)ˀm/ӌ'R<3؊]'AKg2Ie<>Κ^"
{}^(+JY4:(I@\זRdG7YOVFYYʒ7|eh-T`k?Њ} ,1^\8bt՗$4C,T_iLҳ/fX>?E(hyΈz7k6~ojA/ݫ8'yy7H<KSfOn$l0b˨20r(w'r!T[TFt?}NI@dGZhkk;-O5n%2ҝrƈPYyGj^qm1bƮs_Kc ,JaqS/igE_3-ۏ	Ĉ9`j쏪e52El@((s T59wTT][>煓kw}xyc֮W}fwzmwY8?0{y	nY ˥u=8''8q_rx={*5B5z<F|5}<~$ w'E0r% tAy􎌻ιIu/n9vG_\@l)Y_*yogHt7a3_BT /2#;ۦt_YGOZWyysJf@|Y|u<˺#o,	| v(      ̽k{8(ݿB͊RV>G
;qۉs9VKK͎LjD9G/ ܝݹ8"BP(>mE~ulp_[YzQ7uz٬"ŗlSVyZ^U*o5)YK}^_EM[jy?Z|:]&iѺȠ򶘶Bg7ONߝ.Y{}߽~ǾOGz,[WY-%@^l岕Mek/rvyO[s\e4/;_bZ~}(g7٢ZmbQ.:IZ@[E9T-.Jg,ޫbً=d0pSz&TEm1YeOn9i9/}o(|/ˬ\t]۱98)oeVU:~Q?ՉaQmYTk{R!8I(/

/Y^7g2+3noOJժJ+ө |ee^\U}/UqzVXD^QV<],dVNRhWebrݫX;Ϻj>˗p}jQ\X7ˊu)L ?8ʤUT1GI9|6Z[kZ,ϐ^DX22iE*YYwY.Yo&jQeE
wfmV̶V߀A]oՁBZ&̅Dc!7s:p5vsr[-nJ:l[	4`K`F΂ӄFdj_X_o<>9;Sͳ2HK~.8Tߤu\h9=_~zOW٧i֨8;k՟^u;G_袼;dWeYv n@,
B$۵Ӥ"O	<*yy;cV-oPz}*V8Xd0\kx݃) 4sٚMEڻڡM"]TgnEʾhW<a~NJͥ-; 'H'
@0PmR_ŭ5j9Ă7ٝYsԊmz*Z.{HĦym>bbef"08VYaI}4V7ʖM?
Δ:-LӼ bSw`X8Igtc,h
d&"]}&;EDx{)^1 dͰi[J)5IVx`Qꇀ&ՎכWhH
:FF.I| `{ zZYuncyPz7Pݨ<M-X3i]E8.jūPKk^̲>FBe~u+RUKPh:&|ҪzʯJ}9a,@Ugn9x<0~Ίa\fD<5Ft͏7kM-%)*YoRC< =/9&߽Ւoj+;.W&Vs=;	8TN*nW4-f1
n|YDzW-:PǄ U̦urk)Ay}
4` -^2elL0|CBcx맯emltdRR3Ԁ$ef< Uʭc$,"Pb$Z4:khpNnTIku?"] o]9%_pwavPY\ T3{ҘrZGu#d>bjMI6F0NWHk;rXg(o Aߤwe"Lsn"[2})~ʮi\TWp.Ef!*`.j)=]1Q;-n,+[ثȫltni^jhťzR騫9 25nL-HS:S, <t<Φ>V.[JgA6n8MVyHc܄\!5+<伐Nbyp@C[8 I]E@2
HPCw]\ڀDv8+<|UzE8l¿H@jo(	f\lW=__+p^8Eƶgvjx)V7miC4m1q\PrSpJ(Q 5ihETF!VEOdxj&1[\C׿n:fޅN*Bq9Wٕ_4Xۈ~<Nqq[&wvѣVKE0΀K_\醒DLiu`xBeZߩV!J:sP9(˟")؛hS01A'ILYʬpf:ʀRPWv(ǦaԼ*T(PMYEaRpgՕ<Sβ/ٌ1hVvxH_Jȃ_	W_sPckD#"S__E?3UI7XǉB%5>O	4KDZQ*LU|u4]aQ|qu7lgW闍aXJ<Dm{GPjMӉ7I9+v{i6ʞJOw~z˻MV:y1y2jԏ,_3.`3Z!ө <IoXw"_mnSZܒJ7 ,pa;Tz,+2wdFJն(˗*8ʦML-ϊC;J0}E~u 4(i-;J
 yS_mgzӁ7x6ߔlv<b÷E xۄ]$Ǭƽ^9}./x9QEnT	-[o>i*W~/>ؠH~˿Vw;M޺	j˟R00kSY}+*5#^#/1TYȴ9nl`L#q=%#U<$״%WBD@Q7W^@56
(n$t:dDAb'Qx$3hm**+MrmP:& 7p6)'QB7׋_՞eh cPbEEP@*	0">WƗ<rPu5{/j+$Pt+>{hJ,>oɑ:<$PuxûQ)&G55/ε<mRN6]y%\;no;fz`^8{7RK-V.+~0W?C^s}%r_wZjƕQ#PJKNN{3%[ͧ[_[,eSpKwz9S"RVvU4!3VN)iXlj#fwUZW3-+{WY綨eBDҬP
FCVsk@m/'[եΩsLDԩJCFp'&30M^UJWbu_]NhL@.{?V]޸('qS#.GXTBh.b}Kbpmkq>iɦmP2HSNgҊEBؑjo"&]T,8)Mx"vԭPqS2}M]^್?Ytʧ/6yyJwvJt/M[p.Q*<<(OBf0Ņ^W**;y[;;hq<qFv"TW218C-{'p Y ^HnVҙi_+
g\GDxV-BL{#TnTpݟb{cPwiʯŤQY&&7mՔlbw	h%<mG@ɥ~QtXFġ̸֓Acp;#J$y/o.y˲_Sرjdl^܏PNOF|vhŀf,mC¹x_a[U@<2$
Ɋ,Y[HN:o}zFęz[Bo6$>I:TO2WyӭTbb.F`ǑD+|ݣ2/nӀigRRyQՁ4ɾm}ctޛsv^Lk<qcKx74x;ᡮcڢ7}3vb+Jl>es9*QVj<_()-yy?==O;;>zEihdx;$4z	&לè1CqY:ɴM]Otos/u{#-o87C(z'Ϣ|	d:"=٤˛J@?yj6\35u!6	M&qgC52!q+	rJ'viq	im}xXG%: Ccu'3:/m/qa/aȖg:/͘=m+x"&LuAy{b n8zFi.6rBv	ɋ+R[H$+AIZt9QP@{SGcbfaLgFOf%5&?WZu,Mۂp2 ػo]Mx#kI>쨽c|\$.T;2	!R@B⠻욻1$`*8j9kllغ*\d|Bv2\R|7OJfeogFeJ:wÞ+~f$*#&~_֤M\ZiՂ. %řj]5}lg.}a3i"9Pb-'Ma9˶^DQB)LWĄE6*с@^
\q^aw*E
c= a\6Qa"Yٳ$OFjוy(Tqҝ?)n錝T|PUP2`h!椪::s9kȄszrv6ǿXY|sOQtݶ"8DQ@KmχF^GF"S|d %>IL8Y,Ij4N7]AIU%LG5\ȒqLtmh _.{`ѵ_QL^~GcuZVX{CB_ϠSh0/>gF~N7+]&0,%{}ώ׹.ֻVbDչ%'c/?Q? )Yr
jn"<kk':pm;Mo}ڒk%1+'lMn~f8=6X{T4jĹHj._-I#v:,_Ө{mYKv}|v^!囬#bGbqqđboTB#bV]ǧu?	?}=4}>Rv	&O?>֟OMxʮľKf՗%ھo{wtTFaY<X_@a_C-`4\+J9!A9͍\ΕaEa2F^)WieT|aDVжW`ѻa>=gL17$BLhVNߵaxWC>2oj^Ǫu{9j,!>V0t 
"k-Qb	<ELUAs%_Wx[u=b#1{O7
RHh@wS?i|"St5&v}дfɌٺ9!)K8cz3dg5Cq'w6Um2 )-u8b >'6"?Ⱦ6Me2kǞCǰ!ݘemP<P$#֩i'%vs?3C55@FKKͪdnx#OA9:mpcaV$]ǫ7W<ԱJL#7EAȆtMspXhN,W&SϜxf* ZW;ekCCQT gK'1nķt˄.f.9/<FzQtal~Qv?K2=q2YE&3wbZSǈjS^o;rmOAGl|N]$w푹>f&*/	)(+v.&4Vh}X^o>?&Gˇ3re|yT=<oaR(N%,6 22]b
/~4ڽWzXC?)g7nTMz	zV:ֺ	;e?w6~}.=[h4u@jb|  W^os[ECgp:4UJWB#[B>j`v]+2b~͔P⶧U6})MqLP$#g,fݜdHy5odQzS_<=I~`	b~=<ӚÇA=	!ff5Q&/ӖuTRb7HX&ҖٴȪ%&f0zqKs]?Wwv7~+b[;_ө"~f]xb2N&)7mn/57:Vg3OERHੑݓ Эu sdH6U՛xcKP$=9,&9 ~N@Q":04g<!I"ވ*:mK|J2Sǣ. s=שS^4}ȮnK6CҀyV.|7-h,V.<6ѭzrs
L{xEjYQR$OsuHS\
Gr^fHX$bajSwb{E/ QLۀ7Lm?jhsA"ρ 鎋Yg,rrӴ.Z g$C<NlWM1rZZo~!M 3`Yނ&qT,[o+PlQTU9n	^8&EM(F\̜qT2-o^E %&oU>fWw_Q2<ʘ#ȷû&l֖Q;"xnSgKM2Ŀݖ&).*hZ1vVGAùВԆY줋R7Wf-*Mّg_;T忔#Sx	S,"x2ÿ77);DD{!3w~Bqt-yHomcN `įf)Ĩ[~&}H:?GQj*S\u$c%;ڷ1D)+Gĉv_\mAޞ;{Z&`c@[`
*TTԚ-8<?hJ=$jE(.:49d?t8RU~IrR&M7f8дE_N@L_e~h3--x؄}bddt'ک|0:0D
nmIM1^h)35h:X஬gHk&0{aWFM5jhu8KKa+9 }HӣE-?5?Eulm?e岦:kvEzʓU
'];1))HB+>l*ѻWC1(W(?/fJC5DpO} 8qOa50XUWppmD_~lޔWb:>n>T55nMcKq_Zgڭkk}[_g~NXe b',P(RfJvh:"n
!XpuάD{~e-bz%gJM:[5[ɏ=_1M="ԷHyso`Vnqv7Q̽d߄*5/sQӚ
Ӧ%JGBAi$YZMUK6-S.,v	`o\"gqj,HλږmPXWO1{0iዧ$.p0ɷ*eqqo&, ƘATh!%ޞ4Y*.4-6Kt;4]M8<xWiZLZ3hħDC!	S' xGA+%g4m,BolنSm.	L})˻Xay9/܊51Kz"J{ak`]",p&u*VuhG:{DZ#~޶54Q7 ߏܲAhw7)FA	=m|Bae7,"sAu'KV+quY.
U(!΃{|Wl6(=**V_;k2,֛͵|Yހ*pB1(jeGS8A{0郳lZ^TU",P<`rѦv_HtC
#8ᑣAf"`X!֠ǋֈZcjSd冈"Ua QKQW_NYosbeeKcssr)гE:|`=5R2m1U-u]V W x.̓O޿;W<OI*fC#5>qٱNix3M7rq t0=yOKR1@4usd.%ʉHCyF- ^t&VmŴՠ\|ST:gtuΖZNAzshJ6qǻ:Bm
=Ae+E<4Bx';og˄Y˵2ȊJM$6X=K0E?#!`/I@6c3KUY4@2jԴc QŊƋ,VF[	O/Hm~Ou}L'&5u':0_Y2)ĤoU }.>K/cc-fCWm ROB_=Yb@$E8{dVS':Oy-LnCGWcjIE+??=T䇨7ʪ	~ƒM_f<h`ʟ6E1|)|CsTY93oVT;v_ړU	4Y̰uZٴE0@l-b4uщoщ"@@C0[P?Ω3+))ΛIlDRJ<riG{~ Sq5Hv>3$+ꗧ=b;u}Q!tW6oE':_iUCdl*K7/n]6%4Hm{z
loal,Ϗt<Ѿ/2@2/hZc(p{_ ȋ/,ʃ܄>a4%<Fp:b!'Ydko8rƐjHwP"9cI!e[Ή1⃏GnWG 0la;B^#oR_~	>ו,"@r%i{/~mgI+ch>7$jmH	86#KgxU.\8@San(VҤja_9n'-j85ЦX*ZM|N8~p6G>)9f;!ye.&EH47NV.uyβ&0]L}w@ZA'ufe87!k&-añ(	)܆>"Ltmc!}!$ІP3gw\WiEy@YVz lo{hwG~@FmnIuvv`CJC
w:M
;(h4"Q:5Hj"Ǽ8>|I^̝F@|IC9NE:ȟOIR_̷-p,3a-ۜ7 [uAwxH"FLʵ2bK1k}Esfv>MaO6u@˜?qMq	wB
p5ƂBcC@86Avlv;ذ]^fS:T.,b^˔Xk< >P,PUv$Yh{ϟ"Q6\ZcY|u[tqǼCv7q/h$DH+z8QHߘ d.s{px[7	%& k\Dͪx??1#aARD&iC~Kޝhm0&R_z7,"Q'Ќ9@phYB;'o	7'<DD6m^8@1[ZJs;cUxnXf|j:p`b+)ƉRl!z=<~d~|8+Jo-m{@;6UW͍{e+!\R7Bf<2K_{mZѺ1\.M -E\ 
Tf(N>ZEyWKФڏy-t&]1N|u{}]gqK	ol
ZLѦG]eowE%cc^KPliVhEw MȦF6wu7NiNewsʄa"h)񞸪-n߮1gon%/`gyӷk	!>>(6$H[>|+v9bɺف@謕e;[bqFG6(堃/q{mXwo>sھ}?{-y$5w	A#'y˼jomw%%&{>^nWrQњrوC&Q:	Dc9m'/;Ɠ$Ic}9af٭lT_yE8!'-%*8HcG'%v;q!y!r#;|Ff6mrO	!qnPEp4i%1 Ɠ(BIߵd}Px~ܤM=gMSAAŦuG~:w>9')wu|6YBا tg;XI˝/腍|#fjºLɰc4M|]n
S'/s\<wZ0զ@OYq3"N?Vr> ;O:<V,[IixsבZZ4Ew` <ɨ}k͖崲ߩ9Uqꍊ6IHdtTztq|­m30#_OkѤ>axcSV8vUoGxYe&Ne:7T!s_g9F~4DC]pنf\8KS +ʣ5њ1
)$yC<fWc|[5Q<~旳ov>r9vUKQ	9H_~[-D+W
"Ape>yALHJ ژmlaWYܳ΍c#v.jh8DFu_.;՜eg&?8p1?&czgۭպIuBVLT+ zKcuys~K(NAOE)Yˢ&/{Xs`K2[X,i-{(^kfS`$({"ѯb0v|7=%,o7V~%Ì^'x¿m@mhLxlmNp=rw6^biyxUCrҾZϺZ̓I:лCDNb2{v[e{[D[pD.ldsDuLL\,@;!&ɆPqvL@"*$Z5aeIÓ¥+Gr؞i-Uc8t\rg"%t$D{u/`8c])6.".{5:JÊ{;xKBBQV`[	ʅz$bNtb X$X${wʮӌdwj	0Uesыwfm=QٲmJj>U[n:8ۑ⻍aDX,jٯa.$eGԵ?5:~a3I.nM[+@)ˋ*B;ҸM'ۂR
dlF$JQ(pR0Ƅܰx2/kC"Ԕqh+N߫زጼ/=u#tqeT襧aR!G403_#]zVD#a{6L;>kߔxY߂5ꎎ\F`5BC#N%'5tkCbpHIe08%]#U6$j%r!JS7N!ωYW@)L"' 1q;oסYc&iLf%ӑa>Lߛ|m^ֿצՆq;y|1(]^A	32):^Ymse^
f_HlJb(+:M/FVFۜF $S7\mXT#V苻x]eMd@<&ʹ "x4\%dgYpRL畉()VID7['G!PPk"AQ2+:StkQɝ2*؉7+T* xBTpC .$'4.F@pԤ:uQ_qHQgz+,{u6FVMp.qy8GT6m^h`b¦{p<X:"mSJ'8?t=,HhU+=C6}uVOfӭ,,9UE`h<8/o<w> ^)2EWZsM;|,v6!u6R#}WEfRs?zj| PGů~]m7계Flvxs߆0u{]6GƵ/=k!1wzk^u/YqgfSBºV2ܕ-w7}zl?U60`ްy~6m`wAáW#Np:I-|5c-'uMΈ6K/y;OiӖm& ч9mSmvdP9x8"n9UfL㽄U-9,)`Q4>/L"^-cGm}'|,T/7rN~Qcԅ `ǽ>3|`|FF.A	"u;Zӌ;7cdnFZZ΂6O?S6Vb;g3F) ̿Zu0ҧ3Xv*2⚫_;A?^+o=9;۩zrYEܾ/Ч-3i1^;Њ\Vj yl;uV*/w/jxY
gN[[# v6\U٫k?3XXϰd=r3ydlIwv'=fvm}9;rxn[-YYϘy$WYqyK͓eMC|vd2~7Oy]<<}&G`Rq-`]р@z*8Anqպ/.~nm]m-"e5ܧllA4˴vǼ_4mLF~[9x{!SX2.Z@5{USԈNl߱-opz:ڐQey:
WJb\<a)mpϙGϓy×zǬfZ4<HU"-7@vQڷa]/^7M8I+` ){],KĀy2N7Qlt.#lq16Ng5'xB&63or'7s:iRҢ4!}$y`}:&fm,tCwcmlcWSswe;h7+Gofb!b|w= vz2SSu	N039h5^㯩u=O+&ߛx4=elO]O0qnWEqNv?MtwCusFLy99t
BC5>BMO}
6>NjR;(aUyTr:3})O ']%OW'O?>)-?`9޺>9#pظķN~KGk3@k$	=fG4C{:(๗OE.=V50ZBgiN%ԅkxsԑAV{
winJ(4bj̟585}kƵxmvh+ki'W~nvP3C!>ciu!p5\z$;{OV4p
8:o4w֎/M:=]#ZyC޹s$[vWO|cEPv{5xsG!ɠA_G|h69# 0nw;	R n<@?6@/tCCo}ѷ`7;6+<ܕ@&1DPk[kf"-f{GʧaR#ī@RJÃ?3(~,~5D!_tfzdRM^ߢ/nk/w?~<KU@':9xp ^sX1Gpݠ:gp[5τ6|zPƓ>ʡqd/Z)Lq\{Xoɢ\Zx{`k]*Q$.Z/MN m`(λ=	?{LC>=`\0xeY{xYUԫa͈]Wa#tNeL-*&֭$gZ8kϯA
-SO؝H|W?;Kz+(<=~75::4E:uMjMjYCw3c>4gei:}75BWtaMtt̳+s}eݵ|g|Ȇ#>|C팩vUzg|""l'{[0 Nj*id mKZ^Tܶ!,
;J^'ൿ2#p0>476߷n[3> <v6\zG	RQr/77X$Hc%UrJ5ϟK^.T(s6sfIJ|*ٕB:P	؊eصQcj"H7!+[MPbi]|k@	3**TbBr.mA'Srz;.IŠ
LHGsP<f;"hjP.4'5I)zZlAдߩh~~$@g;ԥ/ĈvdEAfrpCm%ũ]ew$GVZ??}?*KO ӏGT0;ټw|)3Z^O2T;S;ѕ,{n
W:G;XF?uO*]Mj߼>3SSwZ;;PBw/ip[@7U8}7ɿBϟ>yW+j_R'oޟb/Z1?brgAR9wj0N;8E$˟{)q_߳vpyzhuvչIY/&}?AGSUZ7շHg}H^:du:|IJ1WbU?}B
Z0=)gevD!{+QTQ5~>
?SG{bCu|Ad)#>>	}'FU}gkVͤ>nqPڧp"H3V;
I}ƅr֟$=؜ 6$|rYc.p R|^G=TfǫoFM\hnwUv|R\pqfxJ
 ^gA[̥ncDi1<_"sHOg̸ؤn4@.$T41?ܹw )-&&CH9AF4HFY[ڷ8OUBzEQ>|ʸqF3Y7U	Q+ݳ.x/gJNJϑb#ڕf`Bq&` WDլ.Le9_^*)MB1j Æ
>8H
<!&΅4Q0zXv)
{xȄ5kf,p ki[
l0'cK(Q6vrY7^0ȳ5Ѷ/Ēp	Lm'@+t"Bn=/=ʗ@دkdD~݃kc8B	k8{F a˖dzҹ9"~411ܵmdHϦxSj^ݐ9UxCl] 㷜BH9&UcmMyЈ>}躇&0C(,J<| H$
NYHql8d\pXIFAI7u"پb+mcg@ΧS<&_m˛Exk
i_fprdvQYFzYci=|f6uԄȸs&W%mlH3\-[ẘ.`ƫ!&u#AAu9d'RAZvWIZeU-5$`%9yqN,ٗ1;m<VRutRc6N_{Vec=m!f,ܬ!J!bc="QtHSehxGnAn%'yՇiɧttm=XMnrKf
*Z}kr܃wة):@
#}.SȖ,iQ:Pd_ĉz?3ƾɟi}p

H)bn!K$D+w"KDHк?k_(i.VP-ЅvsYǶ*^}W	.ޯ	I?Дܓq4N|i&t귏n.'^,U/z*쳮8O8g{Fo_HRY Lj޳/m,-lchߌ;NkikS*nG:OeÕ?D%[[b{?zd`X0[bk7߈{G?pe	vIg͹phx7Ka@b 2Io~A5gܯSaA&#' .7֋}$(??2J_>	#BC .,\YCYWfaCt |Fjz&2*Q縢v/K/'a+c99cUy<׆:c}}̪r%e1S.I}ѤF专$hlleF:ɪg	W4'9qGQP,KhNE̸ۢpm-6 )+w	.q~sr0E{Mf4LCiBe|9LJ`3+쩈X%<W?:3JNSb]qw{3qFǾ-J\T7+ߗj˄PwZ`Wjā9>؋>4$:@{jF2J WCvL<}CTf:S&1JC!j<0p>XDd(3E38>
}Gj1,򛠟|v^C$ٓDgjdBݟH	rJ:4z6/^W YLTp,GHnpy9hI$m\ãh`C0WZ0>Oi$"Ykv@!͉FdčtWnk|#[kT܀ɋ
%S^z[ -hM	ag#	|C!^B/:00D\؅\ݦ"(|154Vͫק5Uo3E1\c}"<s솑:UY0=;#P8=:A[තMsQTKJښ#z*S:M2OhsV^)v "4[f?"8C鲯ݾpX5<{l.oPmՁϔl -pJx3aPalGJ7+~"!3>>;>qwe\ _gW-Zy;>NjL訃?tMxN]1а?~޽|srYR<>>9zs?0~iÿRXTN~9S#/ёH>RTB-<#hO>G#Q?V8?T3G_d!Η^B74#Q].AmjV/x$^q
KW*~~3E7h:x7;W%Fr@﷤녺~X[pET/lFo1Ҥ]}4ڬFc/ ׬FbSun#7F`l!뵠\q&{ha1=~_%Jzq|=LGuY!EOa_SXY10IlR*oUm^JI5i	\YRҕmc((YU95%Y*ђzMeڏsw_9?aA.`ߗez;eoҫʇ<Ky:sЩ(|&}A%djԗKd(O.iYA"̞PإȼYSUUQ.2DZft[y^p4:6 mhGｽZD˭UbD@]ǅJZ.pi@]<,.@Gj^@Lh75ų@/ɗ~nWvΙwiup}'ףZ&q~&!Pځl!ԑX^g|rkW:W7J
dL&
x"Bodn8rG)ϨDø)%?v~LT\*t=ӵSq=e]j7]a-=IRMVH}m7kp1bQM,&r6{Mi6c'$AvX[ N$JoeTmE{L0K\Sgq=L\B8}ԩ@ۧe/ŷ8G	30P*?f^.[Z`@|[Andx 5g݁.R8Ȇ).QKm/\9莖^࣏~fWEwPG4@_ٓ{5`# G.(7p#h[|nxa^jCnɽU\>#ym9JOLkh{S.yqrZzlEWp΅N9 q4W2*,OtU%:PJG^UO%#cg9k.aU:EUkbiE
<' .2ǈi x E:ϩ^;ϛ]&ctxJid>08MyQ"r_UCzV0RbSQrV~m.%Љ~hgjYB%pf"c6@!!0H"S6Aq/@k(N[/LN3d $N3<Kނ^T!pNؽ_I[,FRGN
,"8e?NBe8	_KBYW""Te)<!s@]Cֻ*l^ԃ1	-MqA⫩ZЧUBs|T.֙Àp5MJ`IDep?zٺ(am6Hq .K')gKݙw#At2g"4T ?ֈON>=\Mm=-0S{4U@2!T<&L0qH t2ȽMS)3^v{/wBE)M~	t0&i}ٞY5z_@wN`\ (chy;^/|U~Tm4VgŠ.>E(3ǮjuD![qei߃ZSntH}*{&aaOo3{b-'sbVB%Hfutz'nvԬJM2k"'iTpfw/ڄ(XxCg[xq\G1`"i@5:&Ěēޠ20BGCԮw٢zn.5:~oX5]@vNt^63h.]Ej94 V|3~gR9m{Xs9\ñ,MQ]KcD||5<7ll%5=r@nB'	?;FN#-}pǰM HFa?b0JFRDY:B$XW,[iRDD]5(du&eNǒXNߋIX~;_1w#oTl6=-۫kOũ&]ȓ]`-uxov$J.g{+*>NbP"9vj5`!鵭GhgJ:j-*ڢydPm쮄FmZ\ڼժuWf&&ǫ̩
6n}dv2d3܁ K{j}^+JR2,%zQ-dߋ0߫İkm1y
 )spaB޷vuV{6:T]5c7"rwt
.`xw5u[Y٩ۦȻVAL=t9f+΋k<齂Z}{GEqU
>cǅǁf)/HWtNc(΅ .}P
wUa+<U1F١a#Eꓤ񘺗krM%7t* jEnre8TVƜj;ӻz?D{7v;]e=ӂ#<j@SOQ6~{!Q]j/lb8qsW:ɚakwIoͶ+LEy>eqj'w35 z(w6-<*4Sb qehD5i	?7P˃fzD",qASIz:&WAtu5N>,FZg<\\W*	@0)=Zg*<{^` p	)v$j!6Ӧ`MxaDnTY}ӲdM|dF#QGP=W?<rÔ<j#;0K(NtHRĀxD".gKnjcOߜ{p;x;.^} 'mECQ'ɤKy~0103L'Ԇ8!9q-;'_˼6$y닠:ڴI=Ak;x6k#lJ1*c-@mS)O3{ ^\N|07 ARmT\wt
o=9GƑjya9'7f Nf}ЧT2VӢ5@
.Ț80S"5\IshSl^+`q}8Cb,$6sNj/Sn`4meo$zH#~DiO584zĴ'bd_[+}n_HwW۟:.0ưF6n0:Kdݾu,LmOGSpH2ss/-?a8352*D1$xA )#V'Ǯa@ڧ>OJ1I]|VHSUZ?qШP7Љ8:ǿ9ڻSEv)(A}e1+ө'[,p`$-CAfJ%Q
4AMӒ^Ms\	:4T],*^Cfn	O[>MإoTAxh0e-5Q:L4)vaJvY~#PvLWFLQI<3p5 a]mZ`n~L]-[ غyD e'Z8(UNz)6&$ldgElٴUIrLfIiGJ3a~yCHrwr!s6{
)
7<j"x#	սK|Nn@uZk⊃dGq_@Fa^	~,L?`ȍ';򁂦XTF`K б|&`4ߢUâ:41]yN-St)iEqoB
*(	C	?/_5:݃o""qID+Βa)I5%Stbzq+d9Nx3<Wh:@"17㡮rV[hKT]5~	puIT#HWـ9f4S
Y&C.)Ju=$]EՄ(U[ KT.=h$Xm-DLԕv;ΐ[ilv֦Y= şLp0\Tz>gxy/t|׻,w26FzT>5?ڡi2gwxց0|⬨nƁMR@LCwNGC0p/ [ˢS}no܁4x3QQ!`bP~"buP}ˢ/7a4AD5@QWm{FIFn݌kW	m£WA`STjen?=\<CLhBQݥ:WNO?<"`28w3MOgGJ(U?Q_b1"k{HC?#vH*arGN%(F4쒞Ub0J
]*dVncnL>j­>ЕR <zL{$` 1$)	y-(1bA&}/~C1wo|/P
%N21UKG?e2  7&bN
XϯTbsJYx}?ds[V.{9gl'~j^˂H+<^T^p맪v;ɿ\@h }auN/ݟy[zbI+~Xpr>^TiWeSn)֎Yk
-sT=ׯȷ&q!od,BPd?b5m,)e^K#mpr:ctJjzC;њ^巂7:Oj̡CmWt,!߻xb;sD#~bH#pN^VKlNO8~xw_+6h޶pSL(T,Ex5x`Zk?)Z{`v{S~SQ8c#w6"/\yd,czpr2yfŰt>C.Y(+ZA zEo|{g)	er)wΥ]woә<`9eT<ߎc6T=e^E+tk̾ɭHdEQ/8{BN4}L&\62qFVYpi,B@ٌ
92!NܢtO~/X!mgƠo#$	M'Y}$0μ5m 6O<yNF|%3zS](]}"wlqo2̗DPDbMZ9Nq8R:WhZ%iJpIgÎ$6mI?4o"YRx3
x=వ0-w.?lb1DyGlCS`s\^r%\kS&W##5 LLܴ@^*գ={2̒z+.\]wBF# (4d}S3m| ƫe>ս9w[P;RiV߃Z#D7.gHxT07
[uR b9[6zYd4:\.w*VSZV"6|lZ-#b[&)VV^!?OauR$*fl1Qm-E9uf^gb04Axe:ï@XOkq<N-B_ZG5AUW@ԆHb@ؑ چt'48:mFh?C+n5VRn!0&i!O4":ۆ|5h0tQ7ꔺAsГ1C0RQ%TG&N{|aT&b(b4`Do*6bVv>EсN?>뺐7[vU68pul\5aSq{eQƄϗ8:p;/.疌5qu-6jE,-t̀-(2B:si|3㤑zd!5K-8APd%؜9hU&ӥ$9lͲb%f-R%,v`5pLfбZLEU2so`7$eflH{$JB9AS\rp!ST~<j6|d`vCR9Ztvܻa05΍Lx/E	:E!WoyNRyY+leĵ'$6E{S5:x?UFw?utc޵oF1Ѻ_9&BX<f}C7(fèPq
$.,d>O⨭&D]5 
L4x*jP]W-lؔmS"ZVyUFy!&Bo읾C@Dqׅ'":	xQ	͎Ar1$:R;yo*S>@x'Pe ?wQ?*Y|;H5d(f
V'[ͅt+u~jqtT׍X]eIy&SG]Zʴg:8*+vT 3F
USnKk{{ifpYJ-U]j5!	f^,!xlR#Rne>cȕԊivs4pw暖k}y+,oh5vܝh'OAP9?	rq~4쭼,Ez1zs=d>م =9L[=EJ
5]&@o"uf{hi|B:ѺJ-E3A=mrn^37v[Æ\29/$)A̗2jn/6{wDzM"=yhgUGVGj/ۅcAXn7;S)X^P%zS4ep`߹pu_LzR/+e%K{o'Š.O8^g(9)-UVGr~ӗ33VeG)1Wٗ9׊M,Hzc>Te'v0u,N4t!JZ1\Jv.U_1r!h؝=v*mEv~E &D VRֳ,64@zcED6^ĸ))Ei¤gX(fɘX"Ԧ>%YA.K: O2|i%X`'DRNl@0E-N`FBפ.Dލ^oB˰Cفfсi
+3{ժϕp2oA=[a*`|`\iZ@
;;
Y?3L;eѫ}Σ޴VJقHMb
^G}kQ-{n=>"TL`%3炎{L"q@G4Px7/Ybg½Tq#hO	1	BcǱ
pfy9f6шbقjb%wk#ϧ,;&t7d./.?:7HM{w~%ݎsAb4:#wer gX?DAG$8d6$ZEfxEIZo&_eӰIb?:^v<	4Rh=<BW퉮1pdzڨ?š	ڥPI)]Z{K&v&;0F V<z
9vLf\'584;ÐqkVC[OXPRTZYؼZGznq/mgڴ)OظVU;t7vyj W C&JXnb#2wf2VN/ϴ${0.VG)KtwSiҐJhcOc̪c::uRuA$~ 	P?$洿!yk;@O 
!d*a+Nӓg	`iNy dvtI-xCf̉ÓID=|PEI{8}{B
gF.END0|}i[Bq#Vi-'ۙy
ݷ<ʔ=2x,1ƼђH1d]ռGܓm'6	>aᱜlyA 01ڨJQEAzU׮yϠK7@_Xo*u]^]ASxà*|oQmtGCg>]5@%>2;,#8lVwu@쵛\K	l}a1mD(7΀YIEh:?$HDmL{쵵ZۘTכm&Vȶnw?г#9di]1m-*)c׉z1.%@IվrfP6>:8`SFJO4c*|!\ VRSBWBBN
ޥwyދ*:F~ϼtIIF8<@B"ϴUJNH\O'WMLMR3uԻBρ2N
ed~RIYNeO5e;aURwqABLB.i#0W{`7]u^9t.FR &4C5ee	 4E:;tXYPƋx159_l!K}'[OYl@3U&;:VlLƓKt˼
O
%I#ݥmfG:F`N顨Z(l3hf޼c؜Ԃ#"ʖ\Tpgh/4^ͨ?W/z?6imZ;SC)Dggi*X+z!W{PͅtJٙz'-[ @P4'{/$r2%\:	j܏yN71M`'`Y"5%2Nn[xՋ8v˭ˏ\gbuEmm}.E5~*O*tXu\Gb?zneiU5( THpzX̤/,mUtΪkg[mٙP%"(t#$4v]n[9İՋQJGLf:	o>^QgzOnsH8G\|*U>!#W=͌e{Lb8*]qߓ$5J2<un囃=ݨcpMjm@ ;bSm
a˹~h?M.M8)[3J$=V"f?2m2zֳ)$k2GޫPjJC&&٬͕ ];f>$$m1*@4H+J"Xޙ+9<98yw^7-<^"s#SK޽%UTXCMv^Pmc468@˾ՇםwKnPxPk ǡj=LYajBmK)BvHѻ3(K3+HhsOۭCqQfa;[.Lɿ[?Cuv/aѢuCXϰIAw͹X3#(wj>V̟7
$]͜ĺLRcmmUFWڬ`:Sޗ5F2YRGeׄ  XyN{R:"meL}D,TMA߄mC="pT]x@if{h³qؑ9wP9T`g[<xMBxgfA\װ?8Ɏ5v^,ol&@7pv2w-s'KQ}64˒'i{+`wƇ'G??9~IX7gÆ!~W0ݍ?|sIN&n'ݣe0 G)(_}jvl/'ZG?܇t|
	ڻ.tskúM`jo\gvsu$SD7U1(I&\IIЙg@@rPů5; g#`8}U\~yvͺyqsxTͺN;;1AwNpE_ya	.烓{oPގ -c_@3C̽_|b;WΆ<3L"3i!:s1L?L6%D=^?lJՙbcHG8WM]]=d*֔*vv{F]j-|35`ߌK),l0bHe0X[㸌*rmYRn1_r#womM}ncw Fx4QKRٌc ZГ#PyODauGo3ZC??M1*0b儖/9WkX[\QE_lNTOi~6s%+siKE̻kP?ˎCeҴbXjִxfar>jZЯ{\2ꗐj<*?SX!q^2DAM!ZOHќX=YzDi&΋II`Ĕ2kk32?S8]qTQ7E $f?ŅrtQrdh]SɡM{17-*C"ٸT;Y6fRp.^??lAc٥S+Y9 xśWv^J6WF	Ȧ	n3L_LL'QI׈*mc{0_|A&<퟿~p>+(-x!1%ޑPnks^hxkq{'YH꣊޹^HI.h"z9l+QO0f%ޝS
(N uYCvzZ4pWjaX馈qWJPR{lA[w&ew_%:q]LoeaN,{ȋlyO#|$ oEDڸJ҆&3VhIz=V*[k^k[vsy%Pr-yiYf&z#yah.	~P#L1wS  Xj!P>q=Wd~&m%:oP꜎7:n

v1b{#Q@%:;H7嗺Ry
ϛ`]ʭ#8})7&銝r?HkG<DQP*C=T+Kӌ݉`#Pǔ{ymú_Hhf井APXWt]](ߖ$hRfl~RskZslZ	8+DNN\Mрx
"RTV9^QK4.^eu|mZN.n[P<1-o	^2~O<G-]ȃ!Wˮj6R'G	+g?Y8"R>j*Tp+=8.Vnki4K{$-TCؿ%h~[&S%`'j	:&ݾ(&&8]{+T$q:5#!c}oD~[Vz)-((I@m R
Z~V 8HU?n9dd	ʋcQA"꘠\	Vʛ6fAj-$v|MvwGIjчOS٥7xN=~ݶ	/vSzwLqN^^>е.<_0e6:f7BGgz҄/v7<Dh%FϬ;|OoO޾a݄psG4?P㻣NÇyL.C'mW4tC kYyk<,0=9ڷdo$D&e~;_i`a3sj A; ғnr
uNa Ǻd6w3"3l]ܕxI;gp[L8gM,1_΃A{\BNGfo
'w^-M ۅxjjV E=ѢX@םF ]e 7o1(oP[:K3rq3rp5Qh
<3T[lD]v[cᣯ.0xݒvO7)H2{*:s}q7ww^MFNɗF-#N÷=|?J iF1|8f+}yat/lʓ$,E-)-OL=be/C=Z{FӴ+.N.Oo0TײʪajЦ N6`	?	(OֲS+ h8/2ETS^*}`
:̃]$*`@RWpO&e<:=8@)3IDK6#F:y@=vGQYLqjuWFal k ̯%hxxz'";H_wyͭ	N7Uy^zZۏC[,@ۡ$K)ģ\ѝWR}˽穌a}"mrm9Cj".}js96V#ED{B倉U11i߹v2QtP6A{QN=ez{-t[?78LC%:XxXBiQ&ŜHI[vE9n+66!e*Joqˤ'#G.i"TӪrPhq[Ĩ$W+j}@Q/K%It>̉7%XβJ-&͛ .?wwh?{zRoQ)=(\sc~r	qZ^E):y-i9
Ygh<pf~HP,j2&J$7ژݢ68(`<@q6)oGMz,
|D@4MPeۗ;沩,)<MZ\_MOEjh[ R$C5O(6'8ךm^is8du`xPS_ǴV0Tn{"jJy3<깛MV	e>c`#)b9:^N\djwffk֬6ۃ/m&" }AE`] 拋Q\͆=ň^O`F(ǂRe+Rab{U~Cq'd5:me<Z.h$E<PEEoJ0Ǎ̔wgv*{,gfBt9&iB6r^͵r2g

VYo0~wF&G+=uHً7No7{/xu3m'ωĀp.6ZT J5³5L؏E<E줥syDChUb-&	H]vu1*c_Nc-L'\nޟr	m%8Mڔ3R'eFF#zkvQMj8mPGGo LCNwjI 	2# ~hapق;B4uus| l'PA(H-cΥ4`:u݇AQL>lp%d0O:P<	 Dyŕ4K`K(蚙bˤJږ,Lk'(<@9X%wq"VKꅛ4Asx_n.-NsKT5M靈!DP|Jxy_S՚*Lզ^wWe{F'lf!n>i {_hd'2vs\k  y3QT:s2c֕V\=&X.A|sm
{Ԣ̶.Qv<ͧ\LtΤ_sU4R)a}^4:ƻmxOrmiZAJ~{9:*hN'}hאcS
''Rv3вTUK8)t@zL_Y&ӄY9Q9sfM8@kg!̫P??DXOqMCRel	kkAB;>ݱ#{h-DqKmOF7v ||ԇ.̒*i~U\z7nBvꂳzM..pzsvƽ-SU>/")/N·sPI7Й(Á;4&;o߾C1~m\a'{oup@,PxC]^ {|~Bh@?]@]sPZ?d 9t
\EA1!UT?ryio4 Ytѩb:!R'F.%t-b;ԂWP6A%ʔ^Hꁏݰ:|n /߹NO&<i &iz7y& 0؅sbj|&Ҟ鰋"Z
LFQ92$7MoZW'+l]OP,f5':.fb5)`J}Hǭ}ȫFrlD'<Xx!?г<Xͤe[DV첗ɆHbN}սd@b	)$mLl%OZ-h{j!!nWWbTMZ)Kv3s)V|}֯mB{~
 WJp% =i6̖*n	9Z[y<OuXdj B VWH4n^RJ ۷;_`qTZ]'@O	B#]JhPVN;vs)늨AS=i']XPê D|E4ANj
5\ɰX/AB=ފMq9b ^Dtתּ!0I}6ī?C|8H׉7T<xeCqǘZE^ыjZ'p[Cm|Zo:;nmIos5kM2q3ogӎ2S3oX$26;vhZU1F1$'Q9x3'7=":hy=C4M#WhG:ox	:Evˬ4`jAwlkC,8սX!޴GA,;|lgzF₥&.ow=*L">УwrgN*/mYfއ#gsK<jRY7/TxyhiBy⎳^HG `I5i+ ^gW|	PI9,JB!hL@ԬM#7k$O̱o'US8f9B9Q62.:k~jbOo~2|Wu3n˳w00d/`2x
A=u:Sfo:lfZ%&t$uZe02VEdnx.n07{%$hUhdq(bd<jҾ)4*"6h`1:Oko`iZ,Y$-1s,R؅1;_V _G]:!SRϨ[4U#LPEyfx[/	
k$H 'HlIWbpxZ!/9gF_-ݚ><|v"ֵ:E·%MN`ɼiNCdU`m;= wr(ǆ˪y3{t!ndvc/*D *b>\Y+62iHmkox[f9E#mj;tqurw7锃lrb(toU:Է5sfWOnxvN2nGSS[;jf|93?U(4gp`#iuׯl:&ٴn6|)vދp㝒/^%"n#>D%ag<r(1~񢆓0A'SE26z݅B#@[w$g1RaGH
?^Wb1^$)|;Qu^q85x/.?Hu3|`Gto~yD^k_d?];cZ|=afSp5W}- [p}"gGV]9vwAp'?8GOrq\
($r {KE^g{ef';޿{B2M
"F}b@臨O,!
잙Y=-$^=|YCoՎȮUèvi'By`0	χJ'k]LPLྐ1\[j|UqD\MFY[H:"[@gEϙ8ù-?zp"G@f+'fhe<zmxϭi
d%Ԡ5ç'G~ǁ5<"e"D'k7)!ƫ[jR)R%RMצ6QR+gކJYu<AcIo#.;7rR-`}sdSVWm#Hz35|zI	ww``	QI<XMIѬ1pz4No"(5'3HS7!SXeT9<U3	;=?u[}v,cp;f`B<kRJ6-xye"/`7GoճzŰu)Vb*1qi4bJZmi}i\
RZ.%eU䡩{nQՠ9 պ`('%`3U;Vf'R.֚΅'N.ghX})-d'|y5hmayt=\ZNk֥|M8 j|SUO=kD@א!ßMܞ芋MJ.6qg_e4&T՞n#H>1TWkV"ޞx"	/2_&s50#;č`z7QŬoAȄWpk @t=/]^g#ϭ~,khgVTUԯeSlmZFgE#jly=H{2VB2{@cH$F]rQ;wf9
6v`,s1{0Qrwߴ<eI m{1?`0ލ;/zVntR@Zbh7yY;eѻ{QvbЃ0̹JߗW)IXR30;FWSmNzwd(ƏىGQ9~By)]]8*bd=qׅ&;%=]>lDx:O"@uibʦ#$ҏ
p!e$eE8yU*lgFqhQMQ+t;v҃.`tF;adxű䈜O
S-eVE>xdV>J&JG\+a}=΁:W5guT$vszkhOF?e.h)G`:[9\.8\E
B_d'٨9񤸩\zw YcKd9]Uݵ._d%P̑rZ.k~> f;t9m{L$֣v [n{ 䮁zX	~=Cb7kvH}pm焌Zi5{d&#nSW}Fskt7(5/ei/߂>$4>3{mvjP!>^'Z~[ZTo7~*/-3\uEb,j̉ vs;NvW?|n=MBܲ7)հFhal\N6]_(o?)}+X1{8;pARS<ҠO5X,pc!5~=-5Ƭ|н'xd>[s-E(V"bt{b70vl ].Pi%ND>b!Fx}l<tʁ;s;6*jH!i*t6s趋]<m׋ʁ06휭'AD#~vinQbw)i>Wkׄs$nהM3"`ϊ<8f,Cm.2TbΉ_fX%<#G
Xhڋ}&PFuAI4:fFkst!M֣<yxK<ۂu*^VZYVb`/HXX5>zHov:n0ūyvF
pw_#<Tupy-+$=fOv3`'$0G#Ev^q]xF`ˤKDGLhڷ$|luS=LD+	8kv,Z+ ?W<"iBߵ/٦BQvZdHA6yʦֳgi y5	Lʼ0iRRTsաA=w6!x|Ye0.~BNW38.zLՐְ(2?;7q,!|.j<i<++~|-	aQYz:?
mlnMauGseaaџv6ntY+1U6^xX{|AJj*1uʆv.!R{n\V/wAG6_ܯ,Q)[`oJ|y>(.XMLyiP'nK5jgbLp{t|cZ-\<m]R+
韧IZ1$tgc-g>"LTEJ cfs^6H{aSs_c߽tȔȆF:PV0}e+܁9Ko,j@9._ܐ8z/ڹ!V3qCt"nգGL'%ιg@	s0{%nÁnG#nqcFVX>[s}9Gñ6`;=ʯ0l:J k	S9{YE.Ȝ^h.m틉cHw`	Inr8:Rc
5$;wwQ=]yp!gJ|N*#X A1ݸYDR߄ʛ)zq{g[xS^}NN^MvLf\J6P7)6U2K7D%-JQTitEܦtF 0.O"=6Ǉ$  aU)e,S'[OlL0		8sj')F"-	(MYtF%sr\i=~Lo#	{*덑&hMI9})K帖KJ*ZB%<(Ж8;?I]wmGÁvD 2LoXzDڣh6]僢a]b*zS;$6校ĉbb8>c(׮$dsgkqwY<o$/D' nѴSYJ	_\#-'Ha
V-J\9Ѹnz|8K%}ѷ΀vN5SCZ]諀-q׳<:oΎүsOg"P0D'^ߛԂ*[	*&eݬukHmfȸ79uڽbtl	p="2/W,Jp=b4@|ԩ]Y5wTmEY=jӴ(rm^q(	,sst^#!}τ7=d#ڗ|_B1ʂTqXgâ9yP"aP2J5wp Tp+ nc*`[8.5Iыf-J:U1bDya%@=DvC+x A~l?x3W*¼@L;g_0(
K]-J1</lMWC$xܶ/M]^\R3i)"^)QػN"t%^!^gww1_2kYpgjvf<WHg[%ލ:3CWם/ڬTDϠjϐwJITJTv9GIAծ0Edb)uJs)}7Wfs/J%tY][Ushwz;#sf/:}AԷL7;Hnu޲>EJ7SAT-9nmĕf]SG= KӅfǢl;8L5sy^^\˕g;*:S/
M|VLtAS2pW+}īn*M%~6ԊH`U}AAx՟5t]q^L3J-kY88#zlz+.[t!u1H	/%!V񀗬9Ϊ-]Nxxt8a8ȥp۲&DIHQ.+kdvek_-Eo PjŋUYw4fG>|%'huEƌA-QM]R9<ۗfc305q~NW*_;_a9~N޳#`kg~-V s@3gZzT7-vHN3[Jsm9Pڳ[ާdY^+#
r`|$OT+ym{%YOeo$isZdȻ!YP쪫iֽYV~T7ki]b7z-|>.I^H^
ZBm/GvX=]#;si.'s+jwʿqaA@e38  ;,ZCѨ̄(۾Řk
w'/;UU^Г	ֈ)*ˬ|fh0''Nys&tqMNd'x["fl\)=Nlf{tw1<e3!㵤<`*3?PH/AL̰ӲϜ{B5|IKROsmpQ5&-n}׮d3mv^$hX r}ͫUv9H(7BJnbl`-H<lU7]3z"t^_ӹ&rTĄ/!AX: [J
"/Ъ~FyɄ(6`eVaiO482!p莱|8=COnK
:ցeeFrnŀRzwƣuόՈ1C22%dgjsjQ39pIЀ]e*5.kKfZ5	O%2AE!ʸ@|SȻdggK+S"DNC'V Pj>R`h%<>WꩵMe~ĬƜd5Ƹ m`hWd8M3u:[n::ʝܪW;yN5E]s"\{<Dv|	#dϴ{xػY؟Ӂkݹěl6DSe'j`p;7hԫ5WY^iy`ⴚj^?ҢNOrԧuل$e.WWjO:Bw"})⓶ƃ[]~u1v~v]s}C-&X;x}C#q'Vr<Z;!Βkbdam8zņ#¡܇B*a\B,OYݤ|}牗.Դ}NB k88"XDwӯDG_m
ױyLw51@2g/Ɨnec9+t--aFބb#~Ngҹ\p12b{!6,tH'^
} 5ݢ~ot)Q1U Eu6-'L9=pӄQ6H\U?k[#R2:(Fh##SJ5	0BJ7BhduZH;'P@aiyW  J$=nWwGbpWM<7c0nۃC8K'sקP2R.B5pzL H1% qu !țBõO9BꬁI늪̐lYejj£qYVܲ r":h'a/[q
:5Sf᫣H7cubGi5CR6魔&#$i#="#I{V:²۸Ut}H׏\!xo^|EF9>|79MZrj4qFУhPa嶲u7*3k&h93X[5HOu
YyvH)RP?Au&J̽f3b<^5>4h^eW.AH%Fǆ!f3!Ԯ"8;a-95,hbO(xܠ-jHJYkcߊGsUmO
ޅP>bs!%n.ԩH-uuW>,_>p[ Au=xj'X[cOc}? dd$%1!V蕐4mq7y*&RI3zbKqe]ev2GYcgW8p2m.@,ґJHY~1F-;2w1R}trp=|-yX*\8uQO1<)Yt:MU[_\&+ZB:*AG1l`Kta"}3ybc<\H1!Cp'FyL못9DL7BLp"8s;ӞҘo&0Y~PTsĠNR!i
C.{m @%{N.EBIԏ&mqX/ǽ8eTO1Ld{hZ .hnz
6(M3bRVlS,Zz|nJb;~ohr]7C.5;֢<(+rYN[?H:҇[~Do6xvU\=-~$@úK7i dri <S3ߙVf3ٻÙIn' W(x
s}}}uZLQj h S=M2jͫXu=L$TWyFϛnoHs;cHdGӊ+ f&4?ݼn_(_BUsX^հNZV~
ګ{dFqߢ3IgtU63r_#ě)%DHAqg2ܬ&cz$wOyT}+C}9՚4x=§gN'mu;%mPCʑw/Ub'Ǧ*YB,afr!Hޣz~{AdNNh" $WZH``GFݙ+21a?1bV+j_˷ ׹vi\sLs+1C&Dnw{WpW"J
*b@?&7sA2zG+|)akksssx?ObFM(l-[T6
qQvn6m?IJ-v%uاg.]_n;EE[lZuQTk)Kt`Њ/idy@Jp?7Z^$yEoP0	6f8-}.:^_z˭,Ԙᭋegl$ɒNJtV7\+gCNg@3nǊEvYZ"bޕP1yĔ,+}YF+Ī%|e}2$(£%bR ).Z6KXR0- qildh-!c!.>N}\}dn
糡ￓ+^R,UaO$ݍ^5`w>#Hg}/iv#"&RtifXP?OR'E̒UzXjGNMF}o*	=YvkNok\7Ӂ(П_BXx8|q|V<Ot+<p#Vk̷95©t9ݔS.3ua|ЧFySŴ?(~$H9boM(Z?[g9.C62ȻPҊLG&ja;@ +tM%Om˃[֚
si_\J%1;1JsDd?Zq#%Mn_'XǙ~*e-I7K42q*Xkvr܍KTqz&m~zl)d/51!T,
_i!Emb(F.;-<ɀiz#'D+Nvyɿ}g5o8
1}au[󊡻Ģ>	zh׏6V`[/@ݩj@U	Pue^/]?=ͩd;Jsשo jnd5Q:skh7sa?96Nwϖ[̖!>"7o\|ITH$+lYn
U	[LZ$=N%L_K#&XH7L^PTEJodj<Rwҫ	<IHL0w:-y48T\dZ|Ա{ٻ4FRTUՇnߵ3Uq)"J9q#0KxX[ؐi($II`.9վ@)4@&t8=+Gtc(Eؑ5M|T@j-äX{RCGឧbt,| Sfv_f2y1IYU[ȷ4:oui7dN;V/蘚BxJkj_@#FAaLèbW9Eb+E۟oT_.mU 6Ok6ŨGl=͍廽j_P_(Q[Af[Vn(	0L-E,E7z6)=)N8i,f-'mXʼalQ~!'u^aq(V2q絽F,]}#Qm4Q>ɐwge3t/+r;~>C߽jW%?gy@nffmnc2kRR{+hrIb("[:Ԓm3pұpxk<Rdu+3@A,Cߩ{bu09dwu	0E\a((}gWYɱ:+J)\TEQf㋋a	An["/r=Q%Iu=ИX0CS/C,X& Bbļ:ʠ=Iu>ic#@l:^y0YV6%z~eՄ%a]k0((mA.Jt4D
X8u&{0f2S.k9 GH9&V8x~6UӐYLωGCp;Aǽ
;4c	qO}CSd \n ~E
ۋuuuuX1e/л3	wwz?_}jv~Ѱc|VUӖ?iܳyvyZjJɷ_݌ZJv>}鋔$a(6ތ@<=a`Q,tsc܈Vsu	y]W]~}h{}ITBlD7Qԭ`jѝdiٸ[4
Q 8_\5#3dRm	s=>oo.ns{-5Αg7pD<|V"f^&iocKwK#Ce[FbgA",--ZtZ.s1Ֆ(:֭OU`C4?SqJ^yŮ|^p#k&^Wx:;5Dd]h8%,E8Ta#{-L x<?5mMfcKZ&I\CqBH/d)=([xy}dy\$TrF^;H=ܵ>jUm@[* Nh̔C<e,z̷9>5MFs2@h7goGo2i&۶0dUK׽öo`cv;-IIEKm[ɵ,i'Iٴ<k%>IdGÛ
j`ATZf&щp|'i
Dǃl-嚌M@Xg!h!EgX-faC !3<A,~_oISiTf3іҀ8_&Ԕe/]ْU7HVAM	au,W! :O>[ {*\t/2qԗiv+mdad?]klZOnr|*ɓdЫA9XiRi|,o._|3RpZ/'ThݤD!ϨӡFF8*.r'[yə{xݓqU-cr^~il<8h	Mdb|}5V.q:ZbV%gشoek='1@stOχy@[Sc`6&PBn	?nZcRTƝBsX ^=qUV?dhvWe{p˩94LCr+ /'H"ܭ>:&L`,ln᫗yJ92˧ϓv03AIza[$b9-*xnli/$6u;~t62ܑuwٯh+Kn:VsC%Tb`Twk._娕dh&(`wxVYaz:*HpR.;`0{
/t5df2qf,^,R+Sbm=j 8ښ@BAa-t۷p@Yo)U,06گff>}f8ߐ_c!dWś|cw޺.#rt%K&esujY1t/9mQWWiDb>N=]p[rݷh]kdGȁ}?iK8F\=w߶,̷0wV k-So6EJCÀ}83H|mӗd"'׳xƺd4ȟmmIn1'ߴϟwnC<hOOQz@h%8at!L9Bu/!!Y.T{;t?OwM[X	?-*; ׿H2*?25zYs'TF1Co@Seqqn9IDaVNxR]C=N"6h.7=]a'aǐNg϶}'XounK7f1
(8zX1,..geϟ3oӵ#a\yvJS[zm6<W,Cg_L޻y?7)]ܚ2>0dX8GZj'~5#A,2{`NZ:G_n7.h
G Ol}Gu@ntkߤ2;5?"- PȂs1(~ޏ{7~n]fjaF:z?w?C~|4{?tL.|ߧwhpRF~$}{[BaIa5	LB*ˉTXSzKV>BG\+b2klfٶ[=%:غ/)4CK.rNONuye%>Bw#Ϟ#Hq pQ0ؤڤ-vK2u֮	>mY1f,Rˈw75P{$q;&d|?+Ppe<]dx=ԛYo6~pu,^@%-Qyq	:^<̔[@$;j|]QOFcК7Mprh0%/B9Nީ*/6m<+ˇ&*{*Kh4+SR Ey6EdQ	W5EL _y^)dܸћx,;d=Hsֹ;L2pYx̶䡒(T*To҉'كWDP}pqz as-*M%&D;37 @$#xIx+r#R(`qT盆19h3HW^VfNi-4n~:lUNrHfg-37EYΊithߢDUqtpsu:v$JW1N>&8_ 0\)>Dg`hs2dv"験2<h0 z m|6
Z cS_Q0Ge7JlԔ3gKq,PmmLྲྀ?%qEd]P#sMJgKe7DPyEjZ_ݐҢaWLE&|q6eECe\j˛zbnGcbMp'3ݠ}ǀ &晢5S>˒-Ȱ}FFd\?ZŠ8&wQt"n8:2HM+x@{l2-QX+ѓk[y}Em"@B
+B#&tq.eA2J(BkUzS1cs*ތf#FB]iA<YZuɋ[3cT ?S4+%2PJ.cDaH@2r?zJkӒyD
=U{q)(=Sb!iaCNe?~)˴u5*^? _"7U(ڧz&M1[0N2w[LvIiXQJJP4GGpl	mLx
Tc_pBcOQe!tlPemv\oeUpM~RLª/߿RCuPA˙c9!6ӵ5L$]O8)t6ZB?{37M-"\U
[q=Oj il2ۏbMͭ7R5~%1׷XZ9k
-ÒK/.OhښIsKK-2\tKJ^0:qHY_Ig<t(@]r$),iaг+a%z$ވI Դ/j$"sA}tlOei8X4)ayN 1Fv$nB{wk:D__^se@Qs(Eonӏ.^N[a_LE:,uw`SᘯNyT;/}XX[	.{ԅ.UsF\(C\f|
SnA$a3υ`9ͣTp"+9,a#lRdZg$n2eJE,0.*V˖[w?"6|Vng8YdMp  !B%gȒ:FtdҔ-24[lc5Y͜d=T/C1';٢#.e<B&/s.Y/`?c\	$Jk|v9Tq۟<\-sځWN@\}0wJ6rVWzO|J.6$'߾)˃m4	'b4vN_>tt(mEzW,ZZџ(`	cp ZOۮh2x	^"5{#{E]Zm깳-IN7ڱl05֒{aiha]R7qkk^iFZ"ŚQȤ]xB/	 ұ9[E+dJ 9#v
5ȓs/D`JPU&'kxz;䶭'+>B2!Q'T3d]ZNPKټbD?XfzA$mI6ѵ5ZԚ{><U]'1]z4v<[Cbv`;lz#3	xX%#[u%$Fw4YerzHYrw]HZA
xzeS-yX+p
ꋁ?aYr0ꄉK%2jVZ:jq~-[WQ"	
![Vȱm&Ib[M[|.# e{^͝j	W8^ʉy]&⢅xE:''D'\gIJd.oi)zQ]xXb&YOaOI\8}j~╕[+ؾWͬW48eM_;NO֡hlH>3Kػ-F
mE|[rLD2ktӃ;uzrC˪g$5~-H&!MrqNtl5^:[CTv$2/zR+Wwv ?.:*f}bC:[n+~`t՛{yI;1{/BM9RrK>o#k:8$	M7o&pJ]at?So
1V+fWW:3mOHJct><o}"]|(?Uj7zOYN`<jBf4ΧE!~74i3Upepv0 2DM_$	-Hϩ?(]+-zh)HOޠ0'Bbs}3"s)AY#=T٧\sxWJ]Om)gǁ㏼I.e)Tľk	wGz?TDF\]{$)S@Z:7欉dI*6<I{u($ S"uVrLNd༥J}{uUcefr<j+Rj%2leZ۶&>򷡫	y5E_ $P^ڹ8.;$	c\FFoF얨 H [=[/.XN8pz^^E[8y^As0H{,0;:m0L$wyC{E8e:M^y/KH}kagfMJ3:7z:M5jNE<dHMG::Iδ$
v2[>9wj:W?=y?Dߦ+`dN/]<w48{I(JC5U*߲@H^>un&+^'s9 u|j4f`m5. Iu]0@}@Zʓd:3@~ ιi1.<<f&#/"Q2C;_C\`ŧ%y5"cFnTףdA>}utբ]%s3E6fjy~`NN*=K̞KNYX,4ܝ4\
Yh[~t]_ڷ	v-r[T޳C.88-Հ2y2wn{U{wZ{Bpʳج9p:WY @,8,󳿎;>w`!JJ:%
,$ݽϼ`3z~bПYj,{^=aVa@ O2$.:eSjsbDwwK_&zR:"xkk&$~}A>26p9isH%xcSmy<BC&Sq_[khTiO	ZWD:?"zv;w'O#֯	!i~:gƾz#pW{_6W&
ѭwj/phSgoFٝ;,:S5boKf0P(yT2:|#oqU;VHLJdC>XTk&T֞WoKI#ߓsk^AhwD,j1,-`E/m0R_EsPyޝ<v2ɅoWJ Qk}
@<'	3/ _{'UϹOqF[ldVPzbc6}j9Y-1pRH2rxnziԇRuad6.%B5lsѤA>Xג=˹D*JzYYMs0rT(5V$\¿73>܌`m	}xuA*`W1H1ˬܱԤٸ{UWI=y\65i	MDIK~?b,FBq<rݎ׮=pg7b"*vZxnQ|Lrfx3(6֫TE .[W!gEe9g{u^*9Z|juu2rnyu0} VNiV:Xtz9'KOOT
Cٹ~dxx9-p@Nc\
C/ T`d7v(_M,Kơ҈ EtJ,ryt,ڮ`
(jL!xpfu @ˊ"#pUǢHKyFSج/{!Hj-QTwCiTATGD@Z
M%%:j;C]]Oh&}F<7Yܶ6ҲI@nZ0T{8sOݫ !}1\vxb-oNYa\5YyZ<nR ~\qA@>q`A_b_7իWL!=C[KR4]Nmǳ vethfs, N0~BOi<f|Zl̳֘6!zshX7em7#5{MtZB"k3u/՜A	p23lX2b35#gtt8|_wp9"EП7nXE,s+tI:݋X܃B'G߉x`o'OvN^~|}ӛ(ɋ
<67<,byW?v~itXo^*LD/ga2lQB*pxI(@o(BTPjCGb_JD$vvY%T	kk|Av ݡjŬseb?0{ջb!.3 fub	[v-D--P;@+?b͊A`	e~Tsiχ#.]X~Q%xmN*-	%e[/YZUNjEUqנ~ФU'fGh'ycfnJaЙ(B "~~Unyqy@WCp;c
TxAg:jn|9;[Ϩݠ}x	Tͥv' M4f=5!gX)C8̕X`cv‸Zm<VZRU55jWwXC;+n9,n,SV4149v(( {{ɶO,H'o%1!{~hk %^E4d@!jhƎ:\u5A5Kq`5sq}ޱuUqCFXFY8N钂+1(AHQRo+4'~D[|'gw#na=uyif2|mH/_Jj	|?6 AHs/hw0obO:N~'|࿱]4r|lTB?c:ummynmltr@2	7e9ؽ1n&~׋^$d\NhKRT*J%|PVND/w?}I~J,IDlʡ1X(a*@'f\bIPKOq*̋1UvªY-rA3.E1C`\ۋ9`qe,md,gbC(!9dK.¥C
"\JUd}lz_.WFSS贸vl:oRfV1z@E(1K{ȘYkVj$8{/>F;5eoFHSsFT|5zq@n<l{WI	[cw&H-x;ZR[0&d$۶Z_eV[Zey\v$n Ft[zαGWC?i3~O_ECg-pJ[ϟ?D0)K8>Q2+[SEr>2Y 0CJtwZ)=q!Fn+
ˈ24HTXJSwKAi;NIX|7aW7-D+ýl\p(yȖ(£#/$ĒO\pEY,M[OwQ 'q)R̻Q^p*TKL1%4ej`9VNa0\>qڻy淽݋w;E~/eQQ`֠'of7
zQ`2>EA"ģ|Xil\u'mj0mvYJ!U!_Y sj7$Wm:昑D	\U{UٟMS&
6#fuwOBc0F`=z9ʕkdvWvOZ`5OHqQ.#/me5-d`1N+c'MfLhgxbdp~Ð[ ?;;lX@T]Z+Qܲh3P֝iM	>CUx/>ϓs>=ЄsC7ϋ+z^obi{\%V:M@S~VsͨES<t*ts$6SMm\krLRDwY=0֬zQdZY#|f4L>1[r@jJ(=qf?#|mגrA7	\N/K=dlg+bp.Nkjd_iT2T?H McØ
[:V0.oki]Wv5wN!|Ys6qqŸ4L}6}Z|@mEO<"*1&xex,{[bd:(j&CX.A*C3c|<x&YhQJQ/DdnyPs3sN;?=z1s.UDNW%v^yp>D_Rl$؄- uxNj᧦k8"O&^z53Fs]b}
z]qd}H>Lo!"9:qL1 C|dqwY7f` v{"eLTX~ԻW&s!]\:p9Fh5&u7<lD7nԾ~UȯW`H07 3XWSÛM| `cDܙJP-wc*DeH[ `틀a0^:@S.8c}ҟE2(J]! w#fY1spsY$$9yz֯uc7".. -cDۏͩ)1r-QTpR|{#O\YIDƄdNN W+1ӫ#04YDS{#4R7"${Ukal^@Lw's`!-0B#.
w)U@@Eoɸ1-U5]梺BX+8.PCΘ~[s\ r;Wq%N>e_b|ϝp%֦v*n9p$\0J`p-GQRIc8°?M/Sa-j-I20?:XWSz\V#is[]g@H3&DYVTH:~RPX#V$K.NF)G(f88:㤰WWD\kjڭ/KcEPc]y]d[*mwԶm3w$4['|M900^5	o̶0$U'%:UmmW<m,[l%Hy]t	BM((5(O/&1[͖K/YsznhE&dx,*ZJx9o~+p2f#A9l.Ew.fG4 /-O3%	}(JTǃʢ5!2M	٬Мߟ9!jy{Ҹ/n؟\MO;v[vBC&G	}xd\ĿV([뇃@h4à-Jgʷ7󾹅Xh#|W#H|&\efX`'ćkm>0mE%<,}l]2)g}?!W/%Ē9W f
(,T}F{'H3wo3x.&G,%4_x-ֳ+= .F *reHFD;Yޖ0q{E)Zŏ|=~n{nB4i^3~¿_IW̎SnC =	wG~Ǫ
k{<~_G},%~S|#S@=ͽ:6wwk_ze/NV;iMc~>@+H7jw;Fճ{ыhΒpZtϔhe&5oJk5
ygg:gA<dbqN NDO-↯~ukV'V&iC\L bp:YPgб4ɢ=>b ]ALGnm؎"mN4NNY`
p$HkFTSapɫjWHP 	S⇷=X8gO	*=]2+,Ja-VWkK]ǳx:A8q#bn̙	xE:
.egզ>yGB?:s	97"	D4HH骚oF}Oү~US/Gc(%}$46$DdCЏTfo[SK\XՉV12ңM<5+J,\K@zlz6(g:I~WG}hntVUwIu't	aMsFQkIƯ6~!qFx%zeclӟG/_6kD-;"gqz b&OEXS1},rɢ&,LU4A*L-SN^O-sK/Ye<x"8?ye'PrGs(5ram9~zҰ[gN!ق)$.e{2RM!<אm|Ry+n%Ӌ2OREAmbm[OJ)E7SbSU_%/?wN6	~ĺbUmMBtqߚUoosms̀uȹ~iz$	邯MįZ̋ŋMŋe',яYҒ%a%zMMd	\ĠɱMűغX4VQtUg+ &Y0hdy=f\0ku%Aׯ`M]55]s˫P>KRո2UVK4
92M̺Pw	oe`$vPS}\)	mD+	VK䛴Knc
M\^`=Bz"e%X=Y7$b
}V	©UE{,p!߫Zm'[yĲxȦʘk6fؘ1; c߁?P@/'K ZR=ubHu>!a=vEPd@E0!2+(2"*E*	$Đq/@c(8姳Ɵ6DyOd;bƥk1{(c P:t@\A2n0~DlhsEEcG/Rnc*~ˉ5TMi:YAlZqݷ/Zrfn/mHvB
VQG)ȊaddG<poї>%;@Wm7F1gP)77 5.b7mL_Q3m?CKsI,y̀:F0<L6r\/$@-VW4nk@4ll´+02ůFq\;ycvvSne_쾪YF/k{^mWXc}(@e;d8rJShd@K!!ȹ,#PNR^Նi?s"lڗ5djǜfuU@P6˫߱\^[L	|5QoRi&?mFiDm-P3lOJ$&HjO$PjOJ%&Xjq)MvK*)X;r~b-}Ś?N'30<ôVz/Tv6VEܜx$%>ukSƔ!B8aMêMCږ(I^Y{q>?ivc2]k$z|^&\6
Ua'񪎠r*F7@@bX%Z7Ha8^Q>oIkkU!1P=6ޚz+'-hs@=Tr$ڞXpUC]2Hz,MzM@fzqx,d555ITIHAjfb<R1"1!y,T	RՎjLXJ"NheM˨Ꙇ["NaHr[@hߑe5EbLXyv]4kbPF2I";k$lCa_mu-+aSM=cv''D=+JT0]Ǡ/IяA_ǤY)*UPz;ߏA#~v[6^SR<cxg*@(1;[?bq-0k5Wk$!iksBU=A5$Pk\:Wn
XߺW}^p}[\2	+lKgV-W햫v]'x*j]K{Ugkz׋~ُ/ؿ&{mvw^*ybZQ"kzn % D6 c!6D[@{3~%/8Q،\1abY:އ`nk
Ɨ͗AxxevZdBooꔮsH6[=[>[?ɹ.V
__:7!9v|?oOǃ`Gȱ\=ԫ껵A@y!ԅOޯ*6ڠ0/^-wgnn$pX,U5u 6Y`%?K Ǹ`PRu \#8.|b1`v	 G q S9 h>XuXx]r3,	` l%S?ÌK[6EƐ01ㆅBpܰBpSKHCP3HNi##s?&MOKJ)%s;9Ns'_r'g#ɇ_!ն{YcwF*]%vmя\DDDvBK`n~$( H(~k9&FmfdhF.x{4#)J5j\JUldR##qs^1̏D`~$	LG}%LFƌ\gFn07la~Iʺʺʺʺ2n)9|QceDdǴe=>H$bymMa	:9&e8Ag	:	:s}칹ݘQ>gJa,.Ƶ>^J?2~Ҏkڗü?藔=_מdߞ`/	(uI8YBZvH37ROb2ÌUg
}=0~LQ
H
`&qt;e.b:_	騾#sFѹjkl\: uCz~j=j=:q'ôĿ9/a?sI<"\$8sq.9j<3X٪|:xe1
x^؝8t;C3z bgCPl6UjG%_{"!~\h`3'GD~D>)RV7=hW6^=`ʸ(z吊!wdr=2ŎrcGz~۠,ŰEaԎ<7 uْ0G
 AWeAS*DJChu;!#L3esPzgCќb`UW=|=tj9'a@y!#y+]Hi4/'{QMh@nD:aZ]!RJpK̪ܼujQOaroh<p8R:O5hFQV3nbPf,/'TbB˙*6@`<W]l10/]nT`Ԛ랔$He:XK5$GͤQT2je@#RT'Qf*Iigoܜ

azyKi[Js9[Va:s}a~ciܚ+7|Ty 0⠡4W;kuk?$Rn|A?l]C`%-.=U$`x$/1Z(_~އY70M찎g>\gψ_!v>"ܫbW!&K,V#!V9)w ݑv$D"7͊kh,4#=~X'miF%iD	[hmmmm?:dK5H	݀?pbvj )❋?hZDo-]j|HoJt8Yɬ	ܢ쿪bI[`=@~? )[G!i»vnlg2GPӰvU5dƄ̘2c  iC_Przǻ*H6eY^譊?\XBp.Tw5Rub3-Z%O8
?f_]BbtoBe	ٹ/K4kiy$OՆpwe q]Ƈ*4D&ļ`p&IJ-؜KkS^yW͍K&t/Oݮ'ᾌ	(&eMEeIYbR6A^ F;E1&hqd<ybr{SPgɢM0uS7b2<y]Z#h\yծ.9^Ο?΃7@[1vcWU^v\-".h8+"o%݆!āaC	=5r	㘙e"x\+ypc`l3K9!SZ}\E CJ]A Xՠz
71v<"xj$-{mJ)"ud0bO!ݷɋc~g">8%<L~S~z@%j>BۘY]lYcPTŔ
˖0E2w>N{AO:7p٫a\hj:'22H7FAD`D^	D@*t]ĉ^$X_BW&Sԓs&?ʓJ!l"aʊ-Xf%"+Y	fqo!}ĥpڂ.{"Lg^>"~D4~Dwcwer4[tDZhy8Wi=jVT016lch1v5:~]$V/,M
7nŅb/h=Ć
o*)2\UQ];)fa`ٙv
RYf)f)IJ)m1?Z:7fz.ĄLCvcv$@WmI*6#V}Nw\-z[{CfMjӺDt*Ģڞ$+E"hh-Ģ퐥6aEfMscH屙dVZKKr~iAN	a&*_̵ޜn2b)_8b* $BN1:(`"^ؒ\vjƪWoC׼sX=w/@y8U,lery-&u`*>QƬ syr/W[qc
\Aa.a{ͫ:}}k"L}ԏCK>cGLA%S1#Pҥ9QCvL&zrdLnUd;6kna<G@61NskBxjazy
3	hXBlTOC=su:㭈-*OP>S:PC?!lz[hZ]Q9EYD5l',/Sqsڜ9G9"!EP!:\|ʸ60\1tq	t!^8WOD`8`[il?I}Tk5MF!)id)o~J̐翕3lٹekK7-ȶtH1/Gk(Sϟ+0Nk0.'Bm~nsۀw<-hN-ʿؾ`ShQmx[vNOO_V`Cˈ^Gv?V=Qn _ݸbjWב{F%%WeaulagCjjVgekeO䪟^0rT£CV:=m_M肽l|e?D?VIɟI[,jΎ9;VX=y	PqyZ_.IV=մ=FVа*uZTC3]߿]8cs8ʰi~xĞLcfl9=AO#A.Br?wH\I_(Ֆ6㍬vQŊ$ZxW)JSyzJ]2|W6uopC'-_Na q:Hמ"w'{C#u}ror_Y-dZK&ф%l}+R勔o}JlJgebD)r)/DR^߰p/3ʖ߷xeÏX<Í7տ~JR3onδ}jۍEJhd}	v&)P!WYMVmG٫߾V5)nq9v:fn:GٓTA2_iO]KXћd/۝sAveGؕD׋yܻy=<qVV8cp;mdywd͞'wz9`kisF	',Bjee8n\Q0Ϭum|`l}iTUs	n*7~{(rf3iR?11G{ov/<|w|qwwrqt`$8k݇_WNirh|[oA4s
@qJ;jlNbJЎۇPH)zh2D;Q'qR50e56Mȼ*!(DN#CU@f,Ik'A%WF{hIAY_{ZNЀkk[2u5h7:Z[&H]_mwZMZk}%Pjgs}-j
y[LmTzmV׼̫пm.jKfn+_A'z20o͑ss<x}'MCc)I8j Tl&_n/MaWNF|<x֋1Գ9Rժ>`%#)%]=~׽7NU@6KN@Uq)rVzVPz"BKB>Npx]g;ՁIHbw=ГœOQ?g[Apguͯ)'q4X뱍&&4WZ	
%\}NޚŔF24Um@!&"0wV ݒ _Z2erRPhS(IՁ/e2ؔnip%˲Is%	O!'z4bER&s|k@v#.&u~Z^$_35-j!bL:D(@4d!=H/"`Iv`=vI+p3pEQ%Jd:jXΨ&oc'8
{V}C'>JU+e- TkY3n4+3o2Y$W*+."f)|chYթn|i"q\Yl(M7 LQz:
'`E(kRYo^xͻ948Pvql?,+6acϒe,jIo S1y4e (+RiCv{ )p $E`P+2oȒ$),t_<g	PjYHYؙ]9Y+>dgY탱]j/Q8`ErK__)=EYgݻn/@Q\qZxcDHY2F'`:ϧ]*/:F4`cw֏gU~}-hQq٪vݙ,>Ve$ʵ `p $ΌcܜJ>"@U/q&m@j|@Xsթ?X&:d<ŁGIr8yGԗAyh=*j<Ő-h#.3OV@DkH2@Q|
^u)i*B©(%=b94$89&K(w;@Ak0vodPBFBdƓ}y=lKT+ϡு9 |ge.*Zpg0<y`꾿m6s-Z<9jxduׯ4^<(%\xPtJiig K,0aʉC	ݕ\z}:4Z0,?@zt$¬`)_:aN8b$0lÌ*M27K9NF~%Rw#mx-uOȟ[pMM)eTQWXxz4c3SMz
We>B(ef3^bş}n''z%/)h,~54Eq5X٨ekBxDTfH	5Zhvc3h{Lki0%}90{ȒU) *!`(=TX(%rtnRSdSFT+0^42#BG|9ԦϽIF=lqc4sz_ߊҡjyͤrPi;Mi^F^х?Tfdt-=`E;sextO+;
uLq4bCĭ_𪆻*?ϱwy"I|	;~8]ŋgp,oq,dgIh2:	1ﲩE4ǘE5mKeyoNHεe+s玚<5р#hӋ2Z~
eEsp]%h]8P]>0	BvFw3&I;'o.ퟜqqaAOQ|ժz]+Dp ?	,+_R~RU4Omr4eF9	Ǣh,B2gWs	>CJ1wעZ5}eJa!3;*M-J !7:Th{'PS
G
#
'"ITi6}k-׷H=kp NE=F%Rh>)`䣐Qpg<*+ΪZ5cfYa$;d:rBiPgi[~}P=,"zv|7 Χi<GYkX 4`/4~2+y55&̪-9K>NQJfP2'(}d0='8Lˤ@lk	F
 4QһmP:lɑVz;}Dk<ld23e@6dш<f'ј͘7$}6{`VYjkmD3Z{=.ͭ@axA"y8LỏMXp'w_Mb}hVg#gHCFGp"%SRPKKٍVY%1hV޽PhA`vwE@~EdoH \	jgJ\-o._kg'Wd܌a@Kwwop&p0>Z̚Al6̯ 
PFԠ,6_	F5.PUE(̄fbꆴv&
f\,g5[c[Pu@U&R㩌zZ"=d6R=FrfwKkZ
]"k_d`z
tYUTPjx3K؇u!(mwr:>pwrIYM$Ax`i#kPq\u콰IۊBƼ/Mȱ(f˰LJFhd#Wmj|޴ۥIh^Z"^u*N~zx w>NRXq~B4ǰl7P<B,*ܵX\x UG<-nY'K-?O=F.B!fAͳA<*s%O4~'[d>X`9Jڟ̒pJ7.:c&>,^9%;aazwgrݣBʘ_^."_j*0G-c7zl̍yϾ┎r/΢YEQ*r5T,~Q-8)ͪyp,VKiJjUדD8ky)6Ȯc_v@|hUgj9(^/0yF]U'ǲ[VQAV/'Z$4(??bfaׅvOlTfJPF,"O5!\ْZ\0ڰ4)m1kyFu!i:Օzhc
֦L캫 lT%ɦk[?<x`b􏋓ӠZAD2Ñ	"#ܳY.jN4
k	Kt;:WUÝ_8Y&ؽBrZNF7Ֆ5"Ԋ(i)IP5>y@ׯ-Tu^/y!JO6gEV:jKK6+d'@<*W Š5Ox&Pl:gՊ_nd׊ڷ+~d2.v[ua8cl3؀>Ճ.|8 	tG>H{`f]&t0gdƏeڿ9v*udN5S eSU$ex~{è\].2=Wh<cOG}D|qXO6C;g'jd^XxtoX@9YBQj6f$P~>>^? J!=CM#z	~9(d Ovr 5ґc<H[E:oO{G*s#ז73{fk{eCW?7^m6yS:+y*5fPJ%Di0zXm5_kv=1ey6n|َQuwv	rcJku<s8,8#FOduB4G>ѿciAq-ДÂis(։|nFdjoH$v0̳S(3 |#EfX+нk). VTf7ܶZ´&	a>h=AH/rd|đ`4ֻnAkJ놠?y_ %d MtC7Td
|2Tdv)φJ1*	O>Uu7	>4O>mO$8,t]6FmV7fuciV7b nS[|Omϧ۬"QضZ8{1䂁~Òwx6`%iH_`8ŜV0V?qVe]I?US(+"/"=ByHPFTFV^1o+gqx:-iY)xg΋|u</a|@9+NCdʭb#VF`6S+
pY(X1?Vt c{C ~PjHq 	o_^h/F2W4]L`"/ζۼejU!\tؕCbh"OiBD[''ٖ)9o*fV|fRyL?5_) &w2Jhun;.z9pmظc|yt0]oXu8pVT(hH}Ψka1ʶ0OkAւaWz¦Njv^l:PbUG֪KW?"NQK}wH0hnq:a#앢8Uj}s]'篴K cnhYXA.哯 o(;䲽o)0^㺍)1~'GTǬY5>y=hM6hN۝U9]١;Tl+:ɯn7<:d=wqTZJv7-xj4޵ՖJ^G.cqg4
>lu1P<L:bX/n2U4q%gyx4At:@EΆiGEhvlESG G+1|$_&*6#*0b0@^/
A4q11\͙. _S dhdE"-4H\$B0n]-yQ<\%h<N@8.R"R)^Ɠ۫jU <(ak暿!A' U8qE l>-b]%GQ8%AaLap{j	m]PO i(.& 0|ћ#tx}no0ˢ"7W}Zc^Ґqrwu3`ޮ<q~}Bcڋw:>(R҂_uq7h=y&cShIt
P(8(Jq=uG]{K?( F3&Yq!mM^5c|[5}-SP4wy܍}r3VK(|t,8߸[IU5w+r0SF6f|dSG[ݰFY4[",8݇kJOf귚/Pmo$ZT Z,'.Mݓ֊^SūN,pTemc:rX0:fh؏^̀a@݉
>9^s1:fbBxrOUMU (k)bX:Щk8R.{'9Ze7n#נ}ۅ-׺[xyP-4ykG<hKLPUYvx0vfҺy+ه{}-~6'>2E$ہm+,u be@b1}ۙйQ@7XLO8L"ssBP~)BK-VNNp}ܽ~o9^vEo~;U}f1~o(t:˗fn÷Wl,9B
# `BDsi˳Yn.^:G2cFJ3?W*[&3N.yר^MtZxcƯ:)lS0,j_6U"Pe272R	=đьDc݆ q]*#>Px*/Ye.~PTyHu4ps귏}ZsT _7Mn#ӻ.vE'KbśԜQ=Ώdˡ5Bqn}hl4<t, KUkJ=N̓0˒~nc mG?p5BDrh`:ɽ<h-UOƜAt޾}nA{h$.4"Xˢ0
_NPoXt~B0!]^QYJ&fD>(-9zm&勴-ʅ qy=zRVޠ*ߛ.֥{v&H>W17+^r#`nM!0ty截u:~*ct<G~Y>WS)wVBK:hP֧C\p3tRKb)?ScׄҸ:Nɛ %u=^@$JI8|hH 

1Opmj_${<s'$Fgb=gгo$fq\|?L#\PҍQZ?SS6u-evՄᕬK"qϫ%2~Ee(l9Dr2.(L8pX	B=P9tv{G	4'W9ȼԉry%cP!4lȳHjm_
M/';<D	KCJ<tC2z&"+zY8{8Odѣ},_M'tAL<Z< 6\:,3HqaPU&[]cKaO5oU͸1=%ቈOGi4Zh;˫~ D3u-Q5":2MFY\53&#SWZǉͱ.l?s$)3=Қ5"f5@o(hg<H3(e]/Q@R,բ%vzhta86g-0׺(zw+]krN:嗴h<78xptpo*W8ET7 Kx~wxӝӓ:GWaiK*8gfS;ϬoHs3/g'Cc12lgBRo	<7ُdfNy~Mu)Px#ٸi\B0:J ~#)bwS1݌e@V{W6÷*ۯp9*9HL|M@QG3H	89?~U]/)7W,&nqAǑX,-Pqk.c[Y@8e;:ftk)qŚG<ZoE?x h6k`
#}+3:}fBޅ#eЫ,,1.t0.|ኑݧɻh` ڎIKqo\jr܅D{k43)Fu
yDnj-}3I!R>Y<V2|7$lti	lYSe`ZHZ1G*7m+XyYHGsn!mì]$/r _X- s蚮YM\8~Bs)E;CX|DZy
аMGsG읜\i!08uƙ-n.y%??y*{]uH_*V*"f"
O/wԆE3I>Uy:R][^իʗފvO8+EI)-]\-FrJg]_$?H;{BY#z9ctg*`P=Gjc|M.sEU<;н?xuw<4l6h⁓ӷ% V͓e\HcyX"}1,^ɝmd!?Zt	7'LЮģ2Zu&o~4TCl˽_B4#e߀ӝE.zse"þS^m{ed9|Мh(h	.PN2-hf'SZVmU-e):J!w~PywFC4")2EejJtIv.Bʉ{ovN}8;QOYU&Ѭd8͏Aw5sXKIBLq҄B# %YW'3SE4/qLَ%o&	Bu%Xz[@u5g^an z+	D4(kSoǖ_rRezFe\M,)Ē;ğ)}UD[y8K*mgi:Nqĵ{+zicrGY[/99RT2C- 
dbsUnqqoe\<jhzy-,q)ǷWVf\yR<bɟbY/W5>E8jq_],&9._Jfh{  {Աq^< 'NAnDBA{Loff	o_7 EEd`-|MR&BPm80a$z@֪ЮLᢒ'흜~<޻Ӡrr;gq,i4t{[ܝi̋+	?ճ^9{G{+]JENݨ6F1/+z^m)2B<>qdVcBD@iE(z \+ _#.%SYnn<;r<#Í3{;ħ槌ɢ
@]bݎ=i[`ۺzdam.?
iϟ/c$)󟗛d @N<Եv˄2IF̙CZ?*Ȉ2i78Dj8(0袷Ⱥ@YTLnCR/*X&Iij09Y,!أ9mM9YhxFu qBd<&Ni1q&)NMB9kxtyƿ7biAf{Bk 7>˃y$5Ϯ27+4LLxzD`)b*_"ebt|1d5+PYԘohZdd^ԪV{2Hid˪u]TZw"_%Esej5/տ8΅r<(\Ӣx^Zb0`S/reEr("XP9,.Ӵu`CڶȊ.8sm-j"mnG<7I#]Yj(
W Kx8꾤s<qSaK'ҴH74I'f!rsLj|$"wF{rHǫMr`̴{LY:ť;J}vX*l&?p23N8ub)ygC޶Q-[nٛ~-E7ƍڥ~]φ-mv1Jw*X)n~oKibNWn /|8<>z`t?.ć(n9xgaxg+{[Vǋw.^|vX``_Bpw|r(,- 4bߎvvtB"yh" t.|]zH]۳dJw-_̓i.c~o;ە70o׶tޟpG ɼ=7;bF`XB tx~]v72I;oW/V#87O88]Hخѫq: ~x'8L`<2*N^=tfȌ(V?D'#Utq!S(Q87~Ōx D"ݛdl-[*`gf¬-\F'hh4XOwTi8A y܇>KddBEtj 'rR* 't!{X|TpFPtזa:rҬ7w"T,O8i+#a(b fP2|p8yNIٽFݸb$ܪOԫ6:,[Qd/\IΒgRE"=֩Eg {OJqM>Vn3	q؂㒼Q˄_S+.akÌnZ;4yreL6gb~7>zM*6fhoJYM-j~.ȏ/"53

fsI3Qq2+f|K~ǵ//x=9#\XCDwֳJc2tfV~p-?EB#A=xu!r,
0^3kgMӿhn9GBHf>+cu{DBa4[;#7.-ԏvQv<)C8}KMoΠdzrZ;WV§	}<
'z<ۂqQ{;s`w:AshcI')k (Fy&4aʝ[<nae?f5Q)de{qGq"sV~]y(Ʒ;U\T3u+:Ub4|(#rB,qmG}!3
Y6R)2"ah㭬Sמoύ2\8]4b#\^EMP;ן
RR(a2&|md!&4%T%X/I[auA;t	)1oo[Qm$6x{XsǱ]>9޵.hjR&~tVd/JEc]Z.~5^>2WE*{(N$8SE=Z1
E`OvH8[`PbegZ͗fKmPPo(xd.1Nlp!+KT2AW$A~,AQj. x8R/\P֯_ iA&q?$Zxp$(K*فB.+!Lv)kY)Ǔ04
͒[*NDB2ϐ'$.c(9PR;|fxN!'XYP4QܐrE9,~v
h`)yN+V%T|UIQ[PCQN{z1}$+*JXm!_;8	䫣v@G=%s.wf	i:J8D\)lA}lpٛFEӓ$Cٽ7,]ۄY4ZUU@iLaʌ.js|lV.B~1-l S^@^'r6bQ<*e4%S&uRLB-;T<.Eٔ\ y.a}iTtyP nRż;z.X;'u4[V®.'(qS-O?$tw#Pl G!b5M#EDYFaCIٸ| PHaE<0Wx*,0hE.6&@٥kb&;㝓SX??=c
tˇYrޛ{+0{v~2vo{
,wLK䮧\\%7Z,~B	f}j廙?"//P19Ö(zetE,^Z"-G-QUOϜdQZSd5&gx|K7++ObN.eU!|e1ro-g,75XIq3rY[)݄Su (-5a
A!5$bvA은%%l .YvC+o4
[0JädZ/jvE˗]Nh-қru<%$3GRTď8"Y4Aڥ%TK/٩,:78P.֮s ud2[F=<yڢ=iv{FO;qDjX+nLWVF^|:N Ϭx_)+JY|a=Nbcq[]ˮ;0[!Hw'r"X)k} 	G} SDVx<m/ٚJ/? %?'>3jUASg#*kBqEWh1ꩃee,jųZ1f઎WbT\\ciDVfB4
<\Ldl3Vn>TX@ټY~X4ߩ mNo^}V?L*8$X`$xI[p ?WvU>!R!Q& :L̀O^Z?`[qnA3].rg {AD7zmz	_GR.,Wsl.4HV΃pa.:xvD21I2na6%LU#᜘ ӨD7h%<IhH"휅Cs0T
6\(5C<qbr@	m U*
V3trhPe߳h]0AnߜMnwQඬ-=r;WAU+ ^13hb:m?7ܾ~r5Vgc}uZ7kͭdGnnmnmvZk/V!7拍k[kkk/:-]W/V֠F֚jgEkc5F P Jk77:kV$D^X:ot6ڛNx7^4V{6Vk}mmu+jl:ګkulnlBmk[m;MhIk &l4_ `^6W[[F;""7VHzЦ5XpG?<6ţ5Dr(ȏ?gWSXghbhMиrQtV:_kYCϗ?Q\ghqwAok`PJyޅz ,fjxpqS*X΃JXWP4gԱ&Iz*
'~6ӡ]G40[Ϡ;5<ބ~Pb&C9$8CiPpfn}P̂?_~+E#-Ta0@ķ% ^/w|kLf?au$iԠ\_?ň' 0h7F~ZV]xYE;eF:r۽MMߞxM\7UJ
)OD*4@Ltېc~8NSgd%؟TQ+Hٮ̾$,DOS	9pLڦqH5GQO@	]J]̓*1x@$Tf@	Q.8nw)5q!+ 9[zPCOmf%a/B*YHeBpͧ	, 2L:.l5ƿjRf>nϛ$t{
ݽW&!gĳU8M9w+33P=/^v~;=<اh3| J4<M ?gU++f0AaFqU5n8S+Rykҍ⺆>z^pk_A|]	eHnD)lh{Ym赢IVåȖcͰI=BPԣ/cP(
B";J]M>q.0FƲoU%0ȶU9ֽGgy'PK	Ḿꌎ1}VQ֓v	kF&ojRW7Me{ld36B)wA#s ֿSax5lܦ,-A #y9c&+-g|(axWAYUMP[ijpb;.FTnĺ,fYcTuQVDu J-D{Gꂼ3rW%Rσ8:ihyݿtK".SwݍX՚Jk}b7/\>	tb	z&a6ȄҲ!+4V,_'lzMY/Rl$I*V]vCdzHJAR[ßv*lڳȜWqӀ
o𱁴3X-	[ƹ31#	[|'[dNݙY0in:.4aOB߸ЭwͷH*z>ި+q[AY~G9%R]IJ
8]Xнf?*@-!n 3MX0bb#ibfқPsefI
lFS>=uۅrZ7wКe4>I1*͑=N$nL5w|!Pߐ#Dp,,^z %vA#呼mGVIN:UF_-_IOuUtښ`sF`AJ7^^2Ϯ-Y:uNN~{Hk;V[吭z8Փ둧wg?.@M20tWp!+B/;ʮ+ǡ!?̫`jk0)":+r0I	ftXkT^Y( SO[!Ά<:ecV$h~OfY%T2J(M*EBf\ VpE,`'vh08^]Ʉ`Kkle(4qgP(& zfϗ>m !KƯX5X32VeMֶ@hJNt^1<=Xj$D͉3H ,sæ@F71=,8zztOP||fPbޗ=NmXҼ Gb2̯JsԾ6'hg;>AXѨlV+[۝x<!q3&<UT&_Q-di1i~~F^ȠY_mmc5ޘ^;$MjJP~rt.	*̔c#Th$5䩤9pgDW%_ޛN6$ͺMfF>t~V3voeXY$o$cی9Մ76{׭esGvMvۘ1|.Տx7]lvlhHߏtB@!9eC7Rp{:Zrآ^J|etY]TNoJrxK)@=i"Xh!Կg	9 u8VQ5.^FHIg"eNuSySV7C5Iq!Bd*0	"'`!%jˢ{e>\TBɊ^ ޶-z	/ dz%%9g">(I 0߱Vͷui$p  $wEs,t&zsL*UhI#,Fy}0ZU/w	\fl4ވ򏝿h	_"0ro#2IW0?Q>
JQjиŐyʰ84UhYӚN	}NH25)+%MR <_	Ûu):IV&M%ʴoV[a\ƫLh2ТC7_aK8jc<@`+e{CA6w~!mp Ob(o;hMhPq->Iٺb{qos&{uO>A ̝^wspwN[.ɢ?nEG;uŝ}+fgQNo{xQ}<iEg?X'ķȊ㴘|dGxý|ng}MR;OzD%s6_&|.vL'7ɘ8ŲE[B=*N~x(fZygUQRһM֋~Ϯ';I[%[g|}{`/&-bE|B?Nb^wT<F4܈6	Xwa1P,qô73
#4XDQ<1~KW<	B;BAl$ܽ{;n`ka7wwA,1o = 6u lb!71N 27'E:1ϥTt.؍3K.w;$ZEL/>	&<#%co;⧝}8<@<繰d"~Ϧf&H̒@[FdXTc& 'Idڍ/흃V%:?`t:;0eVPtmVbut Tl="yn}ufQCqz gk/_zhӛtz
VueS|bj^,EDYED4WGzoAnW,+<P["=)pjN9EhOl`} tq^G6kl(Z
DNjjci<pg
[ÝW1][=rjNKٰt'9$P
4oph^! J
ZTdIz2[B㬏%ez=NWlY:šM']۫RBdz	emM{0P3GOS4k=r@D
z|B7}坻l#A1f%|:㣿	{Ɯa:ѝ[*e]Y5wA)F%b2դ($/|b;$T,fMx1|RϕLbHJXqxp d$~(b5&׶kjus]G+:(5_MW53vumv:UxK a*jQ<qmslޢԵ4/LSgpW<A3rB =;	2var+Q,G]#cntzѶlk3zUOܤ20[#$TÃ
hK ꧊Q -E
hP0
ջ\2|mMLI\~a-0#X(
=c3#%1n;G;Ã}VǕ}4~gos/aΧ#p8?wv6>-9dϑM+ p
m?TBė\p*nwi; NLae6최17E 7[b=kxxdy
 T77N^hF
p$mKO$"_ #=E}յKjߝ"Z.yu;}jE<-ȏيUH⮩с ua{ݎFqwښ/k,HrHAܟzkE.(/Y/E6JkvͮeցTqq0,vKU/n^ĻSSZ,28ҪaK:!K3c_ǆ"cL
&V!kcuGMck)(PZ\*xK9nw|Tؕ
}*lb7ڒR̮yTZ	Q~FvMɊlcƊ>cD1JpN[A#FB}+-51-+iKU 2>QvVySIM	p(I Tx0MjVCQcm̀5, Pui*]͋y?4M{֋FhuzT,g	HfdT0uE4#,5"X%;	<wB-aM7<+{MA3V+Õ$IsQ̾|oϡt7P=5lđlbeEb>T]m|SMu_%DN*Ԭ#eK)jB2SHͣchX63j(e&Ze2Lw*"Ǫ
-gp4ꁡ
q8(t۹-=?cCK2xGTƐ/Bel6w7as'<vJtYi'%ԗ>I܎.'no<X_+OCaF-jbUɗi*>Z:(1ρ %u6̟R}KLH-G{۷o-sIHg`w` ?}ғo- ߈Sip3Vp;dƽ$b
G`(,1M	=48Aw/Cнn_i2P㋎4xf3A36 pa18w='n6ȹ^CVp1*AyκeSZv Ñ4UN,xup0HDk'6m` V 8zu +|H)ژNpdSfi~[E%&Ή%ockS֣hwAORaϠBVʰEjd݅f
/-nt!2a>xxizNe㠿b̗+*K0@RzF5!<ķX\sqT/uNbDo'J=OH(4	OY.AxܭgjWT)K:k+U4gy0T/SV3]2>$)R<`.BV	r'*Etg(w!c-ո5]vꓔ;2Y۳`-d*[Y׼("K%[0^ՑڬbFȵΧ9g|\p4tR87שfj"dW]y%K>QHr)
,f-Z"|W剘cTD[LKh/`sF+vYf~v絠(yxx0fyʹX]pb:TS
]*揯V%[5U,${R)žHR_f8hU$|ϛAKHhP̫IJ5m*ӭ&sKT^TVoT-acŭNwNZ<!ge[I9ې-13:ZWjY)ggjvL۲W/*VJ\_TJmZ.z+~rL
&U7UE_@p\bsbڋmf1+<TCuT~*#&&e:N
HsHm>dtwvڴ+?
עH8!+<ΠV70FC/S(P(<1J<~l?&.z]aoH5ʐgRkʬ鼑В2C>mi+q/Q6
KOs?wYtNctو2uߋj^u:oړgڝL?k0ov,n/zI[ŧR7M/4?ҦM~-JݻD\ί#"aY[W/tύt'ytZ|_WоO_SH}1,)	|ۓ4s	J17RͅI6`rRh6gxBanWOt:Dj!k:76)Uʶ+g+^Yqܦ򹫌!Tp-+	V$"-d$MpIdN^'IoRYu(DNБu1Q^h;]}c֎Jbt[-\ ͏;Χ6J@<DE@&U
N,wSxx Cf_!npR vǪI$B0Pi%?NEU'0JSr2`
h䇝<mNv~.00*ᰁ%&5w񸔑ЧakZm:B:4>_YN`F/9~tzQW"߶lX%+1R9ܿsm0te_D|ԤuDG}m.T͞zk^w.x]U/tv@+|ugQ]k[RZ\rEP1+|[
s'
<*cU~Zv}\w΃UJ`(6$v[z^␋/l\Xuc<4̮ܳLјE EH 6#4FꋹQSAkK9#)R#Td!ٟ^M>F$EPHn<6+UuoiF2lU/0
:]$Q*87
ng\yKw![rgG}׋FbH+2 )1_.u_=Ggu~6:VtF)IO[EV]tjM 4#:">WxؿLItrCAL`"6O?:v]m\xcnXB0άpS{}?e%8P9d	lAk,(д]Pv Tg;U.g5\eZjj6g)ӏ- >z_uϻ:.0e7зo}o)[U'<qU (\]n!Kp)5rl2VROKy_U}	n3ޠٽׇ^)c^c%.Aw~ubr?<#f%ٝ^^2$2^q2=A29ǿ.K2!3.BMR	53^FE#,W偤 DdP0߄;Őۆʋ IH^e]UqF`boldLRTJK 96vz&+Ěz$B;POi]VO9B]Gf [Dvxr#cV0v/sAM$8d7IlK-'ɼ.֗OKV]vi*OWV=Z$KPN;XJL$ζDn{$樧k׽Wޡ'}Cy[mJV-X)#yOB.VnBV)ʣxasæqŊY_f}L^
oݣ*uiB?Ө*}x=,&!6IZ83niKUPC#%kR~92U{'g<Sġ.	5T^Bp+}qȴ)Z9/Sc9I!KioߊF$Gn:T֗𰂅zWĘ_kWtKhzYS|U!胫tus4b<vd'w<ho` 1e+ceխNNѷ@Ěhz|nȺhP;xTo!:U?5dS\RXsb3e<hVkHiR=\hY7_߰~iUfl<
NNs,!Ӭ;ĩ6dB\RoC>ZaPR{!C"1bZ!r¹2a$4ccvY WHBz	dAfiQJ8GKGz:lW,[,Ie׹u(X541AJQS8VacVÞ<8L*TW!%	pN	|"_-cتETX%@*ҽxzOEU1#:	Ddػ½btjm_8O4qoB!+5,<x|UדIwT6ȩx\lgVpi(.LwkCGiɢ,EBf~e<1A)Eb\p]H[>Aã(ݝV$)Q\"~7ww[Q4iOZ8<<촢ɤ?LO*H8TO*2vG/ܒh*'TԁQE!Z߸<ni_q!t8@F>D	](0q>QR*T|4gn~NbyOF}jQ"mAXVo'm&;iGkyAǖ&^*W^&jZUT(]JHy
]on>̌W=m W	B춅c
SlNfX#.4wʰ5MݐM1b}Ϻro8Fh!Ȧ~ZSvAd{oٍdԲ8ʭA;5ydO?ڞ_Od|ZQSzp6tZh49;:[hvSb-ڰI 9#ͷ9uq?WKr <[0.el|?`<RL*,ItV#6'd7fwb֑L)e1jU>l_"6k,Qj4+h$BFZ=l`(U5'p=ըȺIh6t
a
NxheRW>MoDuwz\/:	mE?=EzrC]&__/%$:*3x̸v+Cfݯ!N5q=9Ddܬ|/D1䊆
*˴upt+JihYQĦ!kbPBn,0wU]9ŖPЗBCe1Sjl{vGzJ9lr'63}tX|=v셸r>[}SȁnG]&y>GWL͛(+\C z6RP7o6=7	ygdww|p6? rDPVh>>:DraD	#鴺|
sӽ	YpW K?}a̲QOjbId}'
Rr>f)~ȎeT)vmWAS,+Q
v=*qN+Z
N*}`odgMrwɧ,Oea"!_^W3<J/3aR[1R,F[ȔOUvN0;>{6ȥPG>l۫~3|n`߿wy\ |cw-.a^nPALVk~5A#go_̫gaRTʒӂL1u1ڝ q<SѹۜgoA0OTƻ%WFOcǾ0$<ˬoĕ@EI±X)azEȫ\o9ªkm)De'?h~i6E"]ŌnVs=yPZrgEsBmkG!K=^b~ҀP[ǝ/;;?1%tE9AxMTd[^g{'1ݝ#yڊ+;_:kE><8d{ y\(6	,> K[&K̓\,bI1?ƅ]JÑ.`؝zՈ~(kJ<y]j1`4wsAګ-.tfYSR~X~HY7/Ow8_^EQ^d0PkMYE%-^&,Fn
i:B1BkXCEHDSTvԣ!Mgg]֨/dA<Q/S|b^}Rm㟆s|xL**F%oz@](lsT@|j
H[jkU03بJDY̩@hOOv笯+}ټקM@*76|2~:!6O1|4kyG5j[r&6hEW"t}ݒ0{Þ>ϦPn^37>nE6/Ļ72/+BMEްEyNg'lVRcp p8s|juvw;;nIUXmz^%K[B<ígwFsXc]+hYj:a9{Z:X9^Ikc!:H9-jȧwl}]A4!ҧ3UL=!}TOVdEvW8S8Χim&Ԓo=]g )'sEƻ@nVt,ia.R\jNG^*yk/|Lp?
OҒC=,T|N7?hbefN$"ʎGdtx@t6ۯ)*xe\F..~`kp4[Nu|	F4=>40L2,BÒ­v&#H0
Xghڇ5?ۭJZfz)]n	zWw#foJ:`?`lr=jݚ;BW(J<@g}F|-EU4F[9&#!)y/4I.2 (;Gz9Ra-\34zDU!<5r*\|kϴДk?&y\2․rkUln'Ld=قOv[Qw>{QlL,̍택nCk{,}Mp+m,N3:H`:w3%x(+I+V9D%e|q=-x8{
Tqκ5OG<Ц:;@XYQS3I4+6źbT(^96S"y3&QyLip2Џҷ]>y+q	Ha~Pr`j	  RPG"xIJWt#M|~zb4l9hU(9V271\vLQVZdF1>[q|PuQ
DSM&AG}{tV\ Aꬓ&}Do.ȝY?1DgYW޷kciUZ~%ӏ\
ywYDmNW8ٕ>jg]$
;*m{89ȑFF2 j:DHzEQ|W`zMFT"CٲITe!4((6= x2+<uT-eN%[X^'U]kf40%عIOq(&{Vz)(ժe|o%/wߨwKFCy]T5&j̞uۯaOMi\#e/+`+7Bzdd=|Ez/7J&}6 svR:EkTG& >h:U)\nUnmķH*
V{ׄXH3S<uɧ^o7~[>POy>JnٔscE{5IjKǂBQ/mN|7?Ժ~3bcF=7s7(m-$-]&|\Cd0[qJY&j㗬ϗ@D;uG+ZMv6zDY^&g#m~dӷ@㮪U]tF.0ycY>UvrAj3&|̸S&
{K¦٤"8j<v;6v{T[mF))	;,VFs$ZNPSDc{>_sp1ˮ1MOyaҼh)Qw@8Ɵ$@[ʽ顦OmKj̪u%8%2]8mׁxcDT}HWf}xjK_gj<}뷥(Zzy,[.Vh߶6ʥjFOy[V]8ا:
0Po偯Af^#5Yn;PIiiVT;%r*ԲY9vP%c=ڭ'۱4o@AUm-Ik:8*j!⥋EWFᑶL^h 5`D
;H`m@s?&ng4Zj͓"{ܻ.&O7i]D=g݊:v>);tO?Ë"_K)zcdΖ
Y,{I?1'꺧^$2>*MmE<K%zpbO60WcW|-Fm0)xbӉ.FzPPPVDؓ?x+(w4V/-uHu:{vC.u╣,f%\=hG&qOk5g^T,"{?0*`K[ͩJTv#ݪ6.g/ݴr6ܴ+p,`Steݕ,yyi,\vYIw7*0;P>b^g`THKZPfe[ɓr4̶X~)bɉS{N1<xQ~kIycyvKt5&+̽a4hr8Tpz$H:SqB,;,:\>gd-ٺz'=x&&MMG&:
'^sơsߤSabLx=^TfjYP𮉔JדuAYYNByiP}@1iKs[\H&C.bpڧI/ s*ycJ*iY췙Ky$ph9ԅpkXaj \FWR=ބYHqPȿy;i8;DQ>rzE+x|oAqzwKn~cgksH~n끥TxuӒm^qS'@rUrQl{ZW$f{fPS&dpGrЂ0hK&?2iH/Ml6u}]d} wZ.K `WvhYJiݟ5Ԍ4!DΪ|:"g'S`<]|Hm녬l^-/'.J7o _̿ߝmXJ}.W"mS^U4HX#م7޹ӷŀKn[+fIQ<j<=pe6Y㓗Bz6fy<흞^iodUeK8}xXә+񅫱Э
8J4vFǌy=wJlG`f,P|XlQ}ڗWOvᾰ_Cp	dHaQ:j>
+]iE@D^̲i9JL}꣜1[^t!8s=۲B*M~HgQ7`һ8أ,8)֫)O 5oC{sݿA!ǟw\]kk䱮qC[whso͋Y~g}k 2_DuTÌ	97G<q(+[PK@sKӏVm.1Zw#*´E%É<=4)ΗI(N!O ?F*%m&I3A<uف_@Sڄ.ý$<座.z0Z<PFthdǚ:]!9\DR72}oG*=TGҝFMosK1AS0n( [>W
KЊڱQ^ݷZI,HZ3],CbFF8ku?c*u +T6 x$ͤQ5UIk&ͣ_P00zop
na36dd_:cz$*(Ѯ߬Ɓj[kE`b*kl+(mdGh:<٩R	:i۽rwFZraOb[Nl
ы#JZO!蒱 c9x@w{[y{&3AVba]PGQ5KF 5$|9١;BBxD*_"'W/sb~^̦L Іߣr}QDuQRR?TNQảf&x%X滨HՎA@F_CU+֣0woR)U!4ѨCU%x:SZZي"sBXTR[bx|h5)z䶅NW4=.%6ZJl)5㾌ǖj6ٿٸ.',k'ZSbx<snkbI;!Za-
+2+aq)0_Vk<wSpʧFyoeO)ŨX*Dňϒn:6q=Ѷ&k1CrA2}!I`ߥe=5_(Q!_UԄѥk0LS&0lG)xf t"#QCS"bʪ_v[:ބcYmAxTH4vX;IkӑV'Ra{#'S] -aFvͧ[te&dM$e=J_[d6%v۲uͫQXR7պXlt9m3IU&_
 Be	6a	BЙNItvtʎ֫eNx`=݀*T0MIAMy]`].`:ķ<l7}d`1	SV3&a} @ 0 Ηc"Uə0J&$$<%a91j^5 s.Mp6{b1h7nye+
r3A؂Xq\0:}WQn,BIs|Iﾘa% Ds QB\a~$޺<EW?nJ}\L|=RxL׿]|Wuπv6|J}rO?[\DݺB35eA׼s@ ϑy$ZB(v%)ߟYCҟB/k8<#fs/sP[jt;g&wqfIK+!KWI֣F8.DIn<>6bVV|pZXdKJ2Id)[Vx$40òi(Vu @sY҆ENp_;7Af/h1^SC|l8fn1ez |WpcS0]a1O~>۾+lͦq1M%4hi_ȇwgoS/N qӺy-3$.EK6Bͻ'{Y-ueE~Ks֛0VWr]2=M*~ǜ;zOBM2}0>,<E3$@o{tW2?ṭ/XҪoU4\9M	B.cX/?A=mW#W]fμ-r\]~7웚rj;DXmJ`|ҬҮ"ýS/.t+fN:'jwt[gTvg9a'Anbg(-1+Hbu;;SPF,M|cw,*~N ;# fvg<˿dmb?Mn6'`QKW2x1FIEj$KK,~u&p_Rh7\LG6.^dN:wiAo/z/7qwRw%$g,+8vv	8QG½b,
_DD?PYq2:oj7Ǹa%*g!0lwޮ,Be*8,ќ)!GiQUB9A?Ltm҃t:{ì.EBF9?+f-!<^fu1w;́b`	 ҞtCxoBdtL8?©,* GAR1w TQocSP3pT$c6Wpa)Uz)~!-t%U=ϥ><If[N񻗸EW튋*Ԁt<݉jTȈMJL&E2+pLt_y}IaEk[W<:t%5V H	9e9=)@Ql?EK\tW}f6Ө/yAR9t:mP:gbxevx+ALa~)ȋC`">
j\'urEݏRa461:BZ8ڐAaޭi*R²
H2TDgW<VUwN<&%'55Pj7Q@0ސb]۫cQ7yGTk>kz/?#80'*y{N%VSnmLx!_MjޑsԪ&9Jq2<,#d4N~;UdβUw}ޝ5IxG#5ْ;;S).Zt..	`e.+acmt:;,U&vu*9AJS{t~NMDA&,um-m[.M'\:3'g%m?4A6w]7P0Jt3Ff"d)5V dЕBE͈Y?[g5H	<@[1\z'{~{]GY&h4-ң: |ĝ̻Pn/SGJD\8_*	 M;)]ok3>1y$ׁiGFY9uqwJҩAs,#FƍG08^G?I`:8&|Ťd	Gt 3Ez[J1YJ,a*}r ע6\רKիܦ5:)jϼl;Fj|]
Wo{~^obJS`1~Χq_4gKt>NёvTl,3a+v: px+[wWo	ΧR 5hnRtvs$C /BȢbAptB&L7L/6<Az<tS}	<tsnpQC iKRj/aD<<@EN3/=/AƖ* '6PiZ{)D\':acH==c:6:= -8'lvu(>!Wy;x~mQg:]Jl+4~>n6䳌{%ص3*U~|,d߂քaYSY ,XQuViK҂׀ Nܩ]*tTq,[;UxD*0ϐɟ)nVFts/tk(D9z1kM'}0k,VI9Gm6	[V|>QkAaD
JekCE=w'(zD
_уtESzq* ޣm#[:HPm׎*)3H>ɺsDa
{HMk\ z##t.w*U5<uB}hS)'I菌cs@Seޛ7XsξZiOjaC(]vEtiMe#4@ҔGM][7d*p.p
8mL&?'
3VhU	N/pg{i/N
|'XZ[EXݽݟӁ@M|4{BzkuT2Z1UCz,I6#`~Q[~w,f{'AsP78|k5F(X9 C.paygFgP\.a*:+cczF,cA ~]+,~Rѭ/|_ u  m.έF%qAPzbAo(ZKtR{nTֺXJ6yVz
(=>%f,˚X
OdF0ZؖOUa
-O p֟gBMQ`EN\h!nӓtkDy^0R{UWG#i&ѽ4=̈́o4βG6I ["E
a#e3ڋqnixEP4*;![#TOП/1!l(1(`6\]$qB8aCm	b]N0Rw'|Ld!SR^NJFR-u.vY[zJɷd(ly	691vbN><LHsm? '`T#Q:&fCG"T y5>!FD+eN5(-\GYbFB #\ƣFx* Ǵd>Q*ydK]T).ö)nJAI^Wm.]ж7.MZS8Ä|xʌ/Tmރg%A3%ːŒe-&Y+q'pjCHH;'mL_t>'+0uH;YfI~W@_)OuuXPUMb(B
'/yif7ESw4V,⃘ܦՄpϷ5/gӡdvl"{X,9ģʅo9THoGEܫN4~g9+\9ŒJ$XMVUbyu˫{]]xt_9#XڢZ )fH+:zqZ+''ثRzvn>aR!i[	8%_#
$dce[ԧ<lN/e#`K,>*]R'y\x3}")V9ps$ӤD	w`UivK1-v]9m֙>ʟxȊV4٘gWLWXpkA
f3!(23.贒Q&Cg缘pd7X!良AG%  !WbC69˷ FCZY)ׄ<bKܗovs%:+^X	2	h֌5E(E}YiqD	@zR3!m3J(7~ut;qF YBa|vZbXU}Q:m7&ڃ'/-PȌZݱDqި2Y^|$}y6Q1LG;wX()d'JT-Ү^&
V+kk[(VAZ)+a2OpTHh0K$<is.!e.Up<LƮ+R1u-q\ rm5ʋ	f;6D'@Vf\lTعYL+om2<RZ쐊]8NdaE")rex74p
-$2jwM_HJz<	k)k`]PHwQ'NeYȑBAܦĽ%8Zg6$ϡMPrx==z.TݝJiւSUaia⓭-j~*znڼI\sa#k.oVp_:)3ԄdU@妐֤D(<-f't:§ uQK>V應ڤV8puEpdzPtAK.mCT/h|lv6>@QgUycԂ
^Yq֊glqţ֛a?8|6đa*e2*D^R9@Oˣ+jz-6C@5$٩~7ZA56Ydr O؃ػ~P}^mSIv	3E6 "6h1*U<v/PM?B{ǵ|֔9QԤ3}mnLfdbW.pcm[~Ps: ~	סJ#j+veVɣ2Yr<QiQ&囯z>3iڼRƚUĮebJ3ַY(f#o|ͪ"9ԺG9e;u&*ly+3,Ut@VaFEKښpQJr{\܀+B,]X0wg9FWRd^AbE4]F;Ww%TV/w-g@|h[దW;.$Y֔iDh<x],sIՄ!NXQp[	I3K,|	$h?Iz>hHć*?MM!5(ڻdN3ĄyL+\a-.0hH_rʥEhkh 6%$T9~XNZ}}>~9]7i7`ⷲ!%r3(C"
]0<z!%cj-@6U?$7#yߨ=0:TJ%e`ٲjUj!z*Z*u~0Pκ5Wa74vU6P|r[[ՒEM?FIF\ڸ[aǛ4iDOv cN3U8.QϊplS$lTh$ڃ9lmU:4`ZT;W/h+*dyhq+i.*vۙ&Mg(C0*>3[}>+`Q-ܙ#m*C[iB(tJ}TU?۾܎S@\b2#J	Y:tF^hķ\O&}6eˍ{nԯȕf.OLbw|`Ooj"B"de~^^6;&^&2?b;L!҃(scфɹtQ`6 Peɝ xqʛH#B9Iy0oS8MGpYB&Յh!dBg5*_ѲbAp4C!=u/}3BѼ+#IBsj	r@XeplXEJ8#"K-YV[6URtW<K	~|ZD;ЁaƝmsiH3cĠLKVx-vvN4uykNm33'񴹒|TyݿCJ(5)fI:YG~ MU拞pl{EF3-^ꔕ,8h8;>ޏ)ڹW@}sNt-8e}Dq~
CQ~(HAmCt+)C	7aNkHyOiӢ!$ʭ.u_ϯ޸.SZ7TkXTiؐ:A<Ƴ'TC
u(%Kكy?꟧/ GNf'wbIkwK::$7d|cΥ;Vj%d{=%P^,H~v"њW.DO\y\AxPuvWi=uF',,GX4aR׉P@pKpb=P(hUMގj}hI6D[:1h#w$UwB,/?Vw}N4HoTjWO	wEsW	L?rqD'aNVa>mT ,-"{ih#jL/5:3\aUB隗1 SNw,mM43X!@/:!6F!n,.1ex1{tI~|BY۝˥IF6L")Pp>mDd0ajo.h#2g,0PD'[	.s3Fq6l
ZPtӌBrw%cczP+	9,d1UKBWZ}褊n|L%gMhEIKKyJSk0qȵ>Ck(s32<>UPg=\ݔ0XiUۊYLb靨l.h20|RL;:]ۙ0C~M/s%Ek| FHJ#2PUM`tN5vNh&fibs˚.Ӄn]tNMuHmY\_/՗ZG8.F)yWvڟ"lF}s2WPV/Km8RgZJ:mJp0dbQ˅ZZfLjU)M!h36eueNa|EZLG}B%rnSl-ĩ:AKe#\SbZ(@.2 Y%2`><&bW	MuzcN W>:D}7G"C^R}f,	Mb&Q,eb!mS\؋+:=v9Δ|d|X]nu\?6ĲeJN"P&T4&o(0C||ӱUP L6G:Gaw9@VZxa&RsNO!+ * zO-TD\dɴ yC\lhyc#amQYra#8ȈʗPAf]u] gdE-rziƆCrgB(- IZ:B<5',vCƇȰ·\տ!RPg9L7J6DLSjJ=p2m:`+բ;^Ppz"t\`xU%ebAW}& #@	&a14J4T=OG;۽<>x?]qB	iz9@7Q6|E?6ϽͿNv`75%pGR7l\__ϒd ܇ ݟGӴiҿgPj"v)P)D|a ErO
COd+qJ;gQWpZ\G O%:?> 
X}!DE5^R,,桯X>U#ޑUA06Dqo݇7xu!&k[v8G4J0"4ڪY{"U2Na0HJKV&/	`aL!耗j=-l嚯3.&hoZ6OTU7@(LHq
YƷԐRuEFPM$f$ѹdCk0i%8e }q+p`I+SX,&bS뮋Kic6-To(\gCe#*"G,!Z~mXt}\z	OY	Z_#-k[ޅT,Q%!
lh>߃Wkݯ0D#)9$,W"RD8h~\FsfCc8uhL-U@ hD~Ch#ɪ+P%m9rm\溄q)*؂^3^dHgrru42*Д^lTtvhNڧ<F央cT!/]%1CXxVݹ2-y*!&;#fcw3M"L=}zk4fRӱ[хX$<{|@k@E}|ۀ@
y LTax6/T:#R#aMa JS:#0pE$ w1xH$$jƖۙ>TאPJWN4ZaE/m#[h6ͪE!:Vk3lΘ.b5cOh4K/pOl|<?oL6Ku@<׺9&:ڼƹqjėNnO>}wF&eHN-E2,^EY6ƢO0$ܥ\[iqG=tʄ~GJ
>xA4yt	9j
JEƂ#pH;X3.Њ"pսҵ8	Q>/,%S%Ab|ֱJТXˑF\RB 6+\5d"V2-&Bm)֤9 <Jo@CʩO;kc.?ڸz_;ɒY'B65F.-W_l\Wwu,fq.A<IaH+Lt !h.aE+e{ny9˙6ʺa4c`C{A e/6_:%^m>by٪j jk5CqqAZv.-DE;Vt	bRK!l{-"z-Zg(JՍ`U1?:b	cZk=k!_)<oFQXJQ]mwÃ]m.Y&fSu]t@خ*H9F"d_Uե[WBN8#}}
3w%it~<{a)8fa|<^%ǡ-C05Z 'rD׽sv>*-DGl(cAEYOKjZ,H}`vR
mksxԓ{r\vtbhS$/%TRMQXjڛK\E\V ,$V\h)!ڏutz1 Qz@Ůhp/lS2tCh ȿ]iéXrM~kk-M8Y
ɽvz(
ɋсV>A,/Ld:e >AT^Ǩ+<Wј]`e-Hc!ci=KJ> җI 1x._
h%]X)C38<#ă&8qׯmkk%% \4=s̐tC}o[볙[7ZMIUNP.zئ), =Ыһd`*tnr+zkh(4҂|fW6<8*
X@ݏnXCB;!v%0{ױK?w-vE&`Mf#yg'Q*pmgQ~0+/*qdwx9&o+9=#t\
әHө1dTxcaC0G\1VH6܇W)T-kG 9z,DuS/'soP?']	iUD|fhZBDӊFnoHsm73eD	` d|~$9h>MC=|ٱkϚGslhwC>Y-7F6b,Ҷ[蕵rxpޡ$ۦ=u;''`ꩠUBlc
OmJܤQE升Di
ȷQ
|JV`fc8o;%HFNjMK]$Q(b3
j&AXM
 5),PiwCkĭ(XYuq񎭻ʜݻOTzLE*fK|u8ާ"VBzN"YJuAIJUtL\XF{Cnk&1[>]aiMQDg	77!l\`D#h6%vO0lW縐	@c*)?0vOblrlGǔŉx=" x[苚
YtΆCw`ЇpؼC/vD6*SIawjLRF7WH,Qa2WEDh %Xt!UjԘZE?6a%/dm.l(o r2Bz֞鉞<.,VkQc v/.RFӣ'Gf
骈B7VFS^J<V5M^v)ȭSRUQ҂n@`$>f!S3:pvzɠ
h ~ГVc>c+`~	6[u:ϨO*HA4qTlbt|Ufk.cm%9Č_M͑bZ	 2IlJ^chEQMvn;'TPo|T]zv-T.3'fJyJ`eeWhf6m(Q~,	#pq\D]eUt[@qezV^;bn'-.?+ÅfrLΖ㛣$\xWKE!a۔3LW2.NAO{Fn$q+<{L6{a3o8i英nWERInlyg7[RT*JR	;m=%c1hK(ț(zJ:ޕq ?!0%`9U44KR%Tr@^&oa_,.UD\RF98-~0dv#^TɊ4WT6%d%ʡZT@IhZ~6X~|K4#:忨E*$+K0z!wI_}:@zai/CZ͘7^#[/΋2laFHCQΎ,uG N5Nolm1xŤ&*AXjƹ]Fdni2m2оHb{;(j7o`hFNF`i9
u{Am2t6u2DL}}rh7|#1hPNTMr^?l؉Wf[cTTUG䛎pU+!eBv"<R j!ȷv	'k7 m+<<=DszPybyN*I,Әe)yX\UF4o8jezO"oG|cAi)͏lCڗ3a&eڭ`MdGJ	&ꨋI"[VtVi )o`pH]qu*rj~h<E?pV,J&5l;NB|[ǳ^F|O"贮<-S/>&nZ
12 $*(adܩP^YMAF-أi@śW>C~M$%ty٬?X)4Fj1bkiZl7Iotq	`t=wJpؠl¢-2 I-{߷f:F巻yMclA6%X./?ѹZOj[Ar~6Zz>P#׊
|#[Xjvpo,P1fQ` rٕxȼrvj;kLE!JFx};!ڮ% v`.n$°Hl%U fMiCǞs{8VNzj멽NiT#|%'՜@Zzsi 쨐iQozב[Ur[L1Y:#p]^S$Y<~~V<^0+ͥ<ٷ;g[ńT֊e,Z.MX \ b˸;/wSg2_cMJxtՌ2B@[Pa:TF+zT_M<UGJR=mGO#m˫OH/Vs?e^_a)0ILi,Nꪳ?NI[Aޭ"8\o.#4aFv\wr>ȡKǙ	pW2_90e'$d%d1'j~	^TSɥnyCnTCt	a^k'޶FUH[X(V]nLa`&*m6XG7.5^$5.ƾ	`Vm!]|=I2W׭{N4WQK8|m:W!N(8x{GA@WPC!jىe"FjAN(,զǋW	&02CЃtiˤ!8T{oFd|Q_*,EOs;(+n\_Xl.8t	CԾK(eፃ^ H#PZԱBх9(I#pSGH1dvٚB$}qp?(t4/d$"jsZ+G7}J E)Qǰ]7u38t`9ShDwK;H%4n'	=]ðnBnۓp}Ql~#+ߣ"GiL ˩>(*^uvD{LrvݟfͰwzx=zB9\"c:?Zc9##!0~cm<1?0J-z)2UGZKIPSAaol׳An|j:j6:f`Pk,SyAXY+qb$QJ{^מmc}%'|_+*X௕0N>(#.(>;BBRD knHt"b8H^]C5EW Cp4`6Mc^Z0c֫CxwjaQp(YjEVjAh<Y>=֖zYG^Hȅd('WgT(L=F"­&C64=pO3e8s>~aUåoUBdERDDՆΔTFT>أZ([!Lp[%rN1]1LS.VYyon^`Ƈp8&{QƂzM--BWfE[ﷺQc{|+Jh.\)o &ra+)zs:|݉XkuVҨ_ZРv4E> ?8i+qPYv 30JFp	݂+5:V`Ro
j>"*M^S=*NUEA0!z*^.ZvA+]jw:Oa%( ^lmt<7"&
qoI+qZzG Z!IB&V(t_h Џxu9$DXƀ_k?6tԾ}޽=]JFlSNTTY<
Z<n@NOC2ruPm~h?iNm%A 1RA1An x\RRʘ҂n[+_wv,qphfdX	HY˦_glu=i=@cc=qDW5N%g-5R5QPQ_T6˙pX_2v{h|jjJ#NŗqOj(Y+*	n抵引zm6N\^6 *(Bެ%<n5P	*1GyT)j*NYTj/ ;@Ud$u!6tk	J,.,+@^ܵjWBe/㛊͒S5?)R/	<G/]_ӆq!kL9Cnᣩuo^CP@hڢ{2yӓHतuU-(Lv?+:f=?_հ?.1fOO,bښ)HkِjW.L0sbzC%"BlfGю5ĮPg@
wF^ l0HGqtDƍIVV7aK 4gQyƧdʁT+y`T+KgwVv^ZGrq4W=.zm&9ꦸ&X0)mb^72ru01|,7!1*t$0U[*^24d.
_S:1d(qj(,P\]\&i,TFg?F*kىy[1%8ݖךFwgd G}ъ?bE~WPAoۦKM{tZBz7)58IL~R;gpYMtV淗ud,񲢣SUr5_1HF9QFa4
B)OW6)}8~\g_q®LlZt)&ePTAߛ^g
)N}6H{*dcd7`;
?^"tSguET@]RvýxY"SGGBFC]t^&VFet퀚'd0܊+ VȠ' dP8#.[_2_^%W]DrS5o£{h6LVÅfq<x6@1r\ q~!0tlA=Di0@	l7Ԁwin%1Otu1np<A:̩lcLJ;,tB➤v1q9G6KEs6)~R8\Q)j֖(58aQ8}yxفgc'_M/9>N|?p4B6/2?0
H^9iX$(פ#@0lLvʎQ^BI.UŸ3X, )6h[W08U bKܵz9_(; [%x㖉3L@DUDRzN5[pp؆D^t9ekڋ)1EOo
V9C<uԒ_j[g=I[Hh%#3uct{v~&_F:c|J1'5{T(I$7ez:;OS{}Z0<Vrd}TǌU-3Bx_|ty-!7_W~=ϸix/#p@Dc>үQ6DG [hZrowRh5`*5Js/ ks͟Tߔ߯m>|{ڽ:[' 2$ɦ5KywTmpPT!YAV/]r
5BZVQ+4ۣQ^Rzj
˪u4̓vU6ǣoVfH#;T $u.iA	ٖfT]J'A%ـ
טYAdTm>J!C]![XG:XLr,l-hirmP#ޙ	k˚3Dłô3:-3$pR_[m:)&E,enaC)ыTɃOEM *E4~$0 3Jj5l%°gK.4[$Ы#%QY^0gye2!=A0Qf\nuv9ehA^>_ZZsϨ,.ЛZ.e4VÖ+]l,(rd`D>2jr}]]*NDRO6)(Gfw{;#7< DUuء"cմ4Hntx檺|L	UmcTy2M0oL?&39KpQӊeoti3DafW,pR#oW'=21G@B=}sǍj5~fft5b/Jh"ǚb+WUXV{mX)L%	bW(-@W!s1j[w/c%)~8?a2Ҙf >-z>WƺA̚-pTޛ:U'ҍQ ?	1/Gr_C!0t@6dTh'@VaT'ƍ6$FNgu#3HKs])q[s@-2vV[`w18/|1B(I)mɒqM͜<m7/3Uޘ̍/-yۢ@c>GZ	;jd	t˟[q%aa,k0Srazh (?pfm4h)+r%V{Yn[|Mm̚ϤXvmV>e,g2@ZŇ[P\K=Hzq"qAB68FصqеLgvm:_욼taP+NM/)͊A=*O3m!mT(9W
sL@s%(XT5Db೨Xa\h@V?. ҬRTX, 1k1XCI^_DH6 oc=CMa'C.6$g."mL,؆%O)/LwpЀvpqn$}f+{v~[BP^M: mmk`.-A,QlƊ 8 "CrV21]IGl9"{U&=Nl.s{;gulmW7~ p5r-%SU=iz+Uk9aXq(љ$]ƣPsC@-t[CAڙ7 rApD/k:! k´q-(8C+`g9Mܤg(hڔ.ꭶԠٱ*,A
0L{lY PXytkIwaYPHe GB9*HeB|cssaME`Cw6܌ pN׎环z^Jҋwyv[JeXj}G+OF4"'/ꉢXުlK=W}ՍsRBD$)6i1հ{@q9)Nm0O":&ⷫQAӀUuPlmzĥpm[g
`x#Ey"Y(ݠ Z,qJWӭpZO{|6JIQT2JVw\HQ
	gm}j:vw7Pب'azBlpլ">D[G?u'
i<_*>CҊ?ml+~J/
Bvd67WN}9<6@D*Tm~{__@2DGՍ;;Q6T::<=.Ω:}'pĴntt9:ǽÃnǡT9ϯ Z6;lIEh^RcNAvOٷ` ]ۘ!d: dngqhy2ϒt.C`}9(xZƏx|p_Ǔ䟏_mE2pMhf!'kv#P=d}.͞A9ݭm;݃͘[̰=nW	U{GN [W𶸢Ag8Ǡ>)lO
:e_ieT9ÃZdf)9<:9>.6J^fqGQxk2A,yYw:v&lka{ixlGqrQdOmp~njͯԶvsz[Xwun1nSi-J#WoJ.9lT>P]P_~t]l%=K )Gfw+);PU[;`xzWSi 4Ȁ2va}|<Nh2iGVe}qyTjU#0fnŦ59DjQ|T3I`Ƈ/GLJ))\ŵږԑ^n&BlM<0	r-jQ7DbP.ԯ^-]/
81:ңִPY2zIx	h!ΥfG־/Ègj?`QDx'L!'5L7ATm7|]`R6ATwgJ5Iu枥ВoqQ0^e9*GM?uig9GYRgU2q}%Á+M-7r8-AKGQ,W<+o Yx[a)xt/i*oyR㒗"^Vz֘Ԣ^CdNGBUk8>!So:3R-=9i9QHZ}в7rKbECTUX[uHUnވrUa.f10w9|B^x˭ުÎNgrPyc6w)\"g!;"Z b8,Yƺ_`U/,jg]7M7fHԖڧOeg.ub%tˀMwo｝qgu؅|T:1{vO>k^tm0V߫;[p}88wE=ފɱ*ӕ>8j.TL?$<pUc
'u47M ;\]=n= 0٨vg\.0w-aoPigӘ[R%aުŵ^h;Ց	!8_WU	_EkMyW詩8*ZW_X짿
X(y$fљ.1^==7="{&_QtX ޴!{+|d#L[+IPEg7A_luז6Gp[&<E!	1G%*tŲC/^. -sAhTa>^Q)&3/#{{۪7w؂6_+]̆0A3-Qwh65 .x@w^Fj֓:<N؍DUxw%Zlld0l`qκu[{HVbe-[	^h8}ą^Q0I@-GtSQm1Z>:)˒SދO֗G[+XȽ:I<sL4\=N{q	<h+:Bq݊أG~{ST2WEBw98Tmd8?`<%kj
V$aZN**fw1Ul TsH+Z :snGjOO-FqLf	rY{ϰK@9$ۺCgU~+<P!\>l>89P34}M#'@MP00Y58D,eO'P62W5$>?[0uyQ8Yj] KJjՔ\=O+)2K?jdGQdMG6|A6Q?)hQ
FepHY 2w@>fyᒡ"&K_leN7Ĳ+,
WïruVc̀-R6c:/Siv^V7.lygEG)V8 gR5yiqwfs1np5 1WoNMPI\V4~!If`d++v|3:xװpX).i,i%>AZ1fN+jHV^^rf+"Ⱦr#\`KPf_tpɥt\5t2\-CNz%l	\Q*@sY-ibVLU4*&*D60Iʲ\Mn6V;	م>&BSBDc+Xh7
IN󺌌gj2_N6MVQvAPteQ[x{9BF_E0>k5sbGD_E}>'3&ŸhV&J7.=4.m}N>YLnݔt[>SMtیݬpF(to5eB>4$PʦBwWy>`	r,l8MSP̖+W1nx7`X^8^nF5^m6qqgb:r3IUQ<qa<`lF&e->d|v<X3	圻w%jko+~"3 o0-~ s\Q3N^tw^#1lt<{ٓH꫓+GD d_F{PЇ"ى?K%t4BhUS$ebٸE`\1oӈ xsn7v8Z>H$΃ʅ#F{LrEzZԒۗ)8_qfVj/ox0ߌyi⢨i[*SƼGfPƦX# g2X^cic.Wmb2̠2\$C@Yv5B3ԙW˿-'VrH4P{*xzskX\1FHR	Gۚ˗eO8.d
i	RsV~N*sGTeh6NB<O=bK/,mKce>Uj{x"XsCpUaL.rsŤTȈ(yqS'?T}sƏ揦M&q'"m4.!,ԃq5)C79#>)x' Qj)Y:X5s~0O5~
EObE!k5Vi`h.dI[xS/9,ҏX!h)2xįĐϻ,תsP@saomFj/sÐ.4rLr+(MXoނ(֔D_S`"~@ظB\πx&)mP~In/rn{{>{iYn:W	Gَ+	N>X26>k:MэvS qkצM]o.ƪPmgvWζ TM%*K:]"wMR+R-~ bbl8tFJfjGPCs^6¶XIhVW%6fJX"1A}>BضCWGpb)R}L/n3uy?g7]o`Gu"-$YB<@0/#ZVd[ #h`ߥ%ĦcVa/dPLD)V,_^Gezm	;,.ex kbEx:Mx4PrQ˧O]\% =hdbn<wy*cKzrL.U䛔9uX
*Rش&EOZ
	ȪC>Kb1`
yk}?:4xAvu=C<𖀴)<BMsF ҁ_TULnb[L^=
h6"*гWӱw.[{3c$RbFӗ]sfr{l5G9۵g<&7J͍k7EVit;;]{}gjɬq*"|	:+p(g
UP%ьBڄ]NSTWq1dhjPH9둕枃"}+Ĵ,7e=_R]8D99!g\]֌b%vvje؋o6AyHM}RM3ȦnkKR,~o̟1D熅MGeIM6K'=In֌P\w^v%ou9Q?Hu;E{}% ]o:r,<4gW}8rNK9̂?ܻ_1 }-Ⓠ<;O%'c4ґkcoaPϳ(k>(<LNOZ2ШӟNQ3W'*ygCXkY1p0IHE;{FYBg_F_<W-Xt[<++`!KyinwX2%=Vd_@QٳY]Z.AGVqFYxceToM DHHk>Zx9~GPD[e#+_+K9Ii Sy{k%R`;),򇣴|ۃM[hՐ7
֜%ïMY/R?h4iwvmS-q.6tS\S/ \5:S)^6ox /?N!|ӍAxDi]v/g%'̣"{RbɦK_VTi8<:Aesz'@<WaX`+7oл+qߖ@<P	.`lֿ4ޏjU'yZJ]q[F7!̌{vlnǒ]N!;[~|1Voh606<p[W=r9þQ=hу(%C '#&''	`,Zk%olZeq\$43{_|[^L	{p%mB4zI~=KTxx5:<-@dG^_Csx"!ZJ
-^nހ(M}*^b{7RDYMl6FUg^kLm9[Y1ڏ3Xw+ٷ瘎s(Όﰰح	֒IV"El"4~65!qx'D>Hs+@=SA#0ąoc>eZSr|j0^S%DQRBc.h('vLz!ԩbH/-,$Rf5<9L0aug<yg)/ N 0M6V8Q]Ͼb|>wP%f8x<1L|e2lZka*C!ce-z\u,Hͪ0pY[[,T^E4t5?RU~׃B]Bi/t4hQp 7P~vz?wp6Z{|uڟwbKuџd!/֯B?	'Re'	]H=֔n)k-z3z;K<U5s+t4	~Ifľ]o|ɼvq<W$$A-.\xZy.KףŤH}5y6f{XSfҡ1SsNd5$cIzunsלyI7dU8S]w5]?xܸwTGXIGk=<A &NJn۸t;,*yk[7,yUH^\qp)խٷOSBjsudK vl	^7ۤO#r%-hF(3G&jgR8pc
S|?`hcbvẍ;d4acxTEMiI|5Gn_.˶ς烼?eٶg9uGaj98c.Ă)v]%S?f9G**(1ƍ([^kh嗡jnw{Oc,Xx<8̞bH;-?tJ?V> c}n+UT<*3,l2p{EϿɥYU[<L򥿪[I~;8_fÁ8k2Ky]״r0N`.|*z_\3=|1LMD&rRڙ~xyqT
vl?ቫ^z`N뮚_jZP:e,Oٙhf	S&xhGJ_[JeC)w
&	T."I7^H>W5+.z.YP7t*#p. sA̸Pa_=<
=@=[iom
%Uz:n5t!0"3S	럺ЏҠ8(FりriŎ>εWV#5߾qbcrTmWΧhЕ#3Vo#;43ҋJU_o?<Ѳ {G'֯׍߬L{/NbwH_H{_@l+6O-Uw;W|Z1~iCѓEK1ZA&p4߇SUO0:EcL!4VculxI<z3+ơ oPqcb'SGbSoGfh.SnHFƶ_x
aL|%8CX;V-&֙#+gHC}3XzS]7qƅݠUOg7T'db&M Y~}L/#L(?OSyqb?dhLV5<+B- PͰWBbÜSw~- fݩ`+TћmC섛;ɜvDwQl}MYsT@ËE6)T2,3>OrJ]EY]2x6MZ*J띠F魤k%v|"Hրj-|nE]8>"k8hVЊk)&rbQOlJ{4p*(,uT@a!U=Ei\'J
]ڦ>b2FbVe9Wiϧz"JoX.YWnB!R2N=ޢ&l֨oMǵǏf͊o,6`}N~m|s~{ҠKfokPSgaM!@]`e]&9M9AC/Mħ0M'n-E7t>ps}42фj&GMm-9}Qأ##M4\ `=h_!Y5em1QWrJl vN2-5qKsAKGt 
,d\>P0C	֖eY%J
|ܬe6bYF7)68Q@օ"1ݯ"XL33s=͐ό9pV6~&̌ό]%A[`i<  "6aޭus.Ǳ\ފg&fg-KQZ|R(C.O@7`y(XGƋͣLmx;~5efi?xqP&%UAs|v=yݾAKMU\
j=!u3+k@Vӛ7nBr3rbt8Tz.!nMⱛP8vgdZbpqt0WY$4wʤ%55*
g.CѳTm 5#< +j3lJpX_rί.77gEv4vҿl;c%o/z[;j(#+d駔ע$}.VLs1%R06ETzM^MjC E-_pn=Bwl_.M.ЍZ6(U2SoIz;;2Ȩ+|42I><
Df=Y']oϛ7J7-##kר!7P_|iﾛ_턩ַboU"J[\fY#opIeTފ5OVܼYـIdX԰;<ي xz#ꏇig@V(^p_}
?9nǎ,&ய8o3(_Z309tզ1Kk+Ԯ3L$CZ' '^M%j$7c}NEtr]rI5#O!PxSoxOip=%[={6֏u,5Q|I
~g0Q%E0Iw	?«D՜mf0ýlЋtKxEϏǓ:2$ye11z@HE)V^mB& á}}xAH!F{=mxT$!3JI\)BMRFirxTSJmR%3łz].-u&,x o!/?ZJ+0(;D,QH3V{r[3&tS@q,`@\B%jR NNNJ QFxYhd,M&%ߧE;8KYd4e$GuZ`ԉJ!W}߲ +]5B[煰 ue(
fpߢCxC:=C&Nl`N)?7nt8wCDɷy)9,Sip؝?z!FpxACW$c1V-:	FbѨdҪd93w`'	v41"Z'i<wӑ/)V7w HVWwaqk\)Fk:. p!n+
 NG+ykƘl*CNe{44#y	f͈1V4)S?r^.dObsE,FP`qI-.`>е*:A5fh|<Cxy6;),
/V͞lou\IϚ^pYsBRD)NVoiix	?HJ}p/ĸ@TY$3ڸSVu2<#O^w%ՋHOd_3zJLG`xa a:~=Ln
d m]XHzlħh[jĹWDg۶bmfB;@|烦@?jנY^X`d{x!gt.Epօn!snItMEpqZiΠU=zǸDL?Jr^)_u=e<`vx3y=Cx_I;ed/S?k}r܎~ho|f"|fGã߱mdwpmL/ѯNJ|<>g0nxjHn|Ӳz_<WuL_훲*FxmjQva#Wmgԟbd*n"餼F .,m[[IP/l|S2RLg^zR`BV/V[5n?QR"s/~mnmIfOI-N\̔~1PqIZjb5덿pTwf:C4{mA0Xd\,?vhoHCBhfRQ%D\!}?ia$s!{|%_踀> ֥f \ $'cbB*tꕘiNnLϓt{<_*4/]#]~:X
hay|":Y.~5Jy$;vʚq5\U!IvZ<ѯ^7\b>K^v.j|P{ٷˏV tq"eaVכW:+ܛ]R4	BȄr+a:'v,T` =C+vwO>Ҥbh, ns
XP~PKE9UР΋$E_.%^yGܽfe`""XxCX<2sSѹ8/($:KQ( ZAaƏD՚uLal)0dS:ԛ"Q"/.m'9$4a,+
伀-ì[l8P|MտM[Ux3/VǬ
tīn<݊ H/.~?=ԡn:ss2S83H<
Gh>C:L0deQ?>J)稳M!Md/E߬U=X7T{{ސ.U=];{C.9A6%?@Ћ\(qvW:g_vAa+cAj4>!FcW, ˥z1V`Q" >H(P
֧t8o8L kaI4_ٛH8UKbqlj|,}G:x /_ib;͖ߵћ~!Ye?[3I8ofv 0n**='ߍd+<t@5_o+:6áNWblu%:}#VX ةKu1^EQ ` kDS4#[1ZLcJIZ4+堟$Љ3+?\HhDbga/ʹqWz[F[fpú"QM}2@i8q4Zچ8O"s	+H+f]IՁTyu'ItmbgY\{У)+\bÐ%+]z 76?c{0tm~ӵMc-DJPUhצvysx+EAh5Dx\! c/ua_ҹKZ;T8iߔqk(+t(Z[ӳ-#e*\`W[d7Ti#/jd2jj/{ׂthpcŋb2K/6G2t7Ҩ<g@_MƠFJY(.}mhU$߾T}XrOh{ŅUzJZEbQʕaYǔ)AwȺ5yArB#O~68G	pE#0Hݳ(ǣiIPps/N	A1xj.Q=ẙQĲj7"Dp|#`&DeL]JQ`=*QM<4YFBED<2E!Gl$QDUjzTj4 
JfTii|Kl{ungjnmWY2aCD$o](c/i:\cmQapKLn`VCUD(fPht0bK8O&x5Y
RN/zxI/^h}֋~&j<j%(.*Ecy&P{d>|7	y xӗ;Z>EO?T[*C,,
?:)J1>쉜q2Z02+A>15aKBbbah#uhA3:G8D%K:+IԤJQqkgy	:YgD3j{DögįbT?8|??W
?"O{G)	J,H2^"זBkC5m<#R]hۭ^n(_VK׷PX$Jj(br5=//Q^v_ASI%xpBA?fK6\o}k6lRUaT7gK. &E8.ܨ7Vh:3Y.mjkrygcL!Kq0@..<C+:l;ݑ[iUVd
[Ywڲ`!^ZYcsSMU]?%J 58()k&Iʩ[@w'SM:bWx/4H6Ա	2|I1>3(Sѿ\=
ǖUZ34}'dTB6Ϩa{Nj1z@IO)@vu:~&L,T̠2u+c'W5~yXơ%%y	ل8چC"q@l 3*t,
Ǯb4$.fvw !]7%w֚+MAvkVxf
.\x;_oH]N8r4ĕ~`H~8N:|68}3QpJe\5j-3!REtN#c,n!\]wϟ+'t&kމֆMU9Ò° ZyiBYu\@؉A.F'Y.EX2>feNu4ZKaƤ(wgv?W47&JcɿA< kh{[(;+{ ;p]}p8뺰7֣wkzλ'{{[G;>֧d=Nu%QsQ8$\n$"ϧZ;O9(ld+/O6pQxP!6CV{BñuyxsRNբEtZjq|M?E{n]êc[Z$qF?7'+ʕ>QP}3Z)`ͭ5P\oI,;LtbڇNl{2I~9BJB{+S3F~NCU*Yn*Ü|xb/pC9*L]:W0R*|Ѩ!-P;$i;L
n^@OVh|'%}9i*nJv4eXa?kAXkEdvI)1Pyrn&V F~SMp1gJ)|w\m|v&$owiʵӢ9Cs+EP_3kGuMEbMd z6+r mVq@HNP<z}mIYɋb8f2t[G\X)@nr)~ki`澘~	*Hǌ؊P>yS~}8tCRPDy%q>\)G^p2b(VUfuYzfn^uxV[a,ҍј<v-V̶Y"<$ߎ49k]6[/PxA6~dNJIZlAÃl2W'k
&'M|'}˽+)	{h?J4폧ariN0&<Ν>npq	DￎǟA:yi3CXRO2 7rQ
|p^\l<nnNwn?+A1^hFȫ3םX!~ʳRPzBS|B:^4_=KС蕬QGdPWp}hh, `;w5β	f`σx5n1#DzUq\V
i$֬?V#IhJO-TiWVK⽆3}M-0MBr-hw˒j((== =AB_:ZBJ#Yh`tMR)X0?#Jh<|
0|[qM#>[s`o列 X]ǓEV4b6 /4;ҙh$.thsdVJ\aڶGsOJC{mYۂ Y\Lt(aVAbXgts6xlns)
Lx%QohwGSUp_pz1Br/wN#3`#;nnO吂(9s1?q'[Cd0/eRIeĞH|mq&R^1\Ӫ>k;Q8
/QTz1 IߕL
]!<GvѕN1ϞɃU\tw~'@T^hn`nQJi@TZKKni1c\'%eHsX@3%Z-=FF,PRL3:%h+uӤě	5t%YbǮ?^?oWVvM^*QC-.kodGnּJQ'ut{zGQ,w_Xzag!wC9%/SUe4_٘~4DV=Ң= S$hO)_hH<o߹7^͚?kbPw#b ԊpGj5+([Q`S@ͅ홸2g#[3N?ewQ{k׎'n0G̕))PJwC׭o_U='g?]6Fo^Gg{{I6 AF>'wE^3kE/9Ph? UΪ u A4~l2Nٟ)IڃZNڌxkwpC`яǳK5&ᆩ1ҸJ&obN|~󊃙A]iŸ>rPT[U'ڛ "Un{ڧ1RC54RMdm8DݚLM܉RnjȔ¹`;;xSG5X[H٢hc4u=7uvow7bCW|.~7Cǃ:Pwd.B4=~㙧//`_{ q>P6KWȟ	!71ݕQP7|Ҥ]KǺ]M]<_NLPhAp_XzQ~`W0hQ!I>PY3Ki@vK$eOX9hJ$0BUOEU<c'wN`w
h:QV󻦕MjmߑH5_pki_.`OK418BO0v>,RTKSFE(z%w0Fnމg^Wt/Dge18tA$*@(
pq&6||!i)nveLYjZes0}%h͝ (R,2+6ꨰ)<j=29Rߧ%d{;t,9Ұ0>di;+0&:2bݼ;:}`nrߎT
rGHI
HU;Qak:9Zn{OZ{.::Qt:݉߬iSstR{tKP)0ϸ%/)GNsfAH/Pϧ~Hu;]_;k&z<\)~dhN^Č%+n/&sM"qumSae|dh#O7/۝61oۆᄳF=Φ	x|꭮3 Xig%OED?#H-n=ZRylK@!PnY
?D~P99Rw9t~V~l+Xactctnb[3
;&Do)yyfeO&x|YS>=}>rxuު?T <Y^}gR6h"y<+4-&txk`Mh}K!\ą9xcmЪ?xLwzs&Ԭofo5uܦ S`lpW%{Ӑ#xjʡf7xd/t	=dAI=N܄|~<C_|`rp=UIs"V{vyA\:jO웟jՇMWb^/:ϯZ\pۮY NIIpIħ"tK}sGpHD#{͟kt2Q?J0#nOg0:okkVaLRl6_2bo۷X.YEuXk[}8>P|`rM>6<{d6^E1B`apӢ6Hcs>QhvZ̒P캧YٶY6W^<yyW{:Ogue\hٷJ),n=McF-{o\3oDm%e}*QgH5uXB>:-.O$=tdS4{$%iWJLY^rN14f?|V/K+~O:_)+ ſ}G=W]T6Xd8	&~z1=xiqEGIC6ܭp1pއn`5g4w{|l>D`Πx?V7`wE&!2嗮2.4J }IFr]ܗ񭓽N}CwoUXw횚5hkJ= 3OԲIa4XAj`QW1f:㔸;O HVhKvȍ#⤙ٴ9dq:i2O,!xo992_Y3yNӃs2ѣ菓X	wFǗL&D4BXHPc3;}3jMG"W2"*Wu y5$$G'~zm®yYKof0=0faoj@a/ Rl7:K@>@4/ail^]&9E&-xFHUVl{YeS]on`O6A!tPxno5X7s{sz+!$	u (jw/UME}WJ}f07PcE,XSax/2 V-!AUᶦDZ2zCC{K_*/gpS4u@6Ef%]%J@5^ h-{NCT_/SU	.4u&x{8ӃI:bijċWi8l%LA6(/5-W*l8JeL[7ENbq"3:ןЇ&usjK=wc)]fFJp%cpGp3	>e%tH+\SlQ9vy/L0_tP.`Sil}g
󹲾Y g3ҿb|EހZut|(t=;!Kzixbi8MB]ȌHMgB2]c@v;.BI<RN̖ngG<~&폝^w`wwru?
WU9v;]}m2tbok?<9&~Iaɇ
hk^ldpC2v~&"ɇiR;bt:$ҧ?sٳfAwÛassh=sM3hdA!s[ET΁2$.dÈ1$!D=uSd(UQkmltpxZe_U
;Ysr)5Bjiw3z㭐
\f ZŮ*aR3:cP;jq< ߈ۛ
4^n$ml'jqG-Njk.hQR׽v'||ݪpWșw+==JsI?MWT$trʤS$CD-_ex/(AE* Ġ3cJ?u` _NrHLc"UTӛG_Z_3-9&WS9(_V n&|ޢߗZUhͣ:1=$fƫRXLe:;'JOe!#<;҂곀TPPtO0|&K9ҝ^2	AKǂ(z:T(ӉdXjK@Q'jHS\QoBdN	}@QOQT<Oxk]=c,؇Txu1;ay8~F-ZoTjS#K/+حbi3XZmz]~ce	4Kr/U+۝_ePLX)M릗?$49"9Kj'&{ogb^6R铲3M_& i.[щTWkS')CcXN)Bqa%?(=6Oz @q_c|饃SYm45WTT@	FSozr] 5$_XduSgg)̦B.;Gh{*0Ql@AڍƨWP%ۣ*04:dR{:H-/|7τ9g}"OVP
CarIp8܈˱NʹE{g pqN3E-uLrvTn!;cL'z(W/*f(8K!u}y4ly6@(s)'*R+n6E!l0{hA*Dyꩯgv2>Yhz$;uQ.DZao/D-ǽb"|c0UE3L2CzLC4l@n7&dVӑ(C^G[h<M7;Us8Ti3M)slSH3F1jvYU $ r,Tgjp}aK)	=EԹ5kp_szFbN6caZ"ZPkpؚ ]WU9=GC!x{}Kt( 1xDt#Bx(:֦󑡞)yV
SSjV/!۔O u #L;sOM1~-">Q'BQT4Qe$UhRBtTY@F$1'L`<mVEWYxr3;LOj2&9x\"}Qy5W*ΘVEK	V3A})3*}$lA-2p+lmխ>9Y=#N曮*#nUY>W_(uEO0U3[il5iIsVuUS0sMH~
';eI<O%$PlV഍UmkhS]߭~XP6˦ U-Z)}?÷x!{'?)QC?ĵ 5xз>wA3yuwu8ʣN=:.Yc:ފYS|_	D:<<:{goR'dWWk[G;itz>NRx&1B=gbǪH 6Z掷rgK2qUJd~δ ÅHŲA^
biPVw(
9'$G-d{%K}֎,iEz&YEĖkdؤ-> fSLr=;1(
BP(Bj">Tb5p2bP`j@$L(t2aHs$h)Ƴq
S>-EP>&ST.}ɝq?ֹe2kfeo!E*
LuKxDm+m̒l2ZܯYD[$KwdnKϊt=%4EY10@X]6)OR΃!TjWb%Uq'jkOmYKxUGtI8bKwZ6f4C0HW=4+b΃CY( [u޼K[Rz 78K֒|t6'kGԒqqL("wQ]̿-߉9vle(EZ1}+XIfg5<NYD.sxʖWlQXiUՂ?UZ4<.3<0̵ڸω (|S
xz=ƹil67ۣpCr?/]_@Sy$G x%3e(r8 ƆaSXU3'fލIʀlT!Tf<KAL/Lֺ2jV6sQ2pk[L!"^JTvXxԒm֫Eڭ4dUa*N<
Oy#%X3Mvg6T{30Yh*Opt=SwˇK&-|dxn._/[j%Z"pӋZNNMZo_?5#
r[G%)E.n'3Xh4h޼;[Ag{^ȳX?neNsakL=gֵd%D\[P89 
52%7f0nVy&̫Wjj(Oĥ݃Lŵ__Zz%607!w)K^uا1?$ ; 錎v۲OΧ$ }GTq>%"a/Gċ5=s36|{NSN +14ZK	iӦה{G	i
#w<9]ML!tv&`P=$?jڧ}5{iƚ%nh}&Z[7W72N=4R~RL-1Q6
Z]vN'Df\mԀSC \~2S+h;cmpY9\ʁN&K/ {L^&O5iYJ6aK[0J<RqK61._Fϭ2LKe7TXa{&w)U<f澲(Y5wk$#F@iQ$]+
l{|;'UYw/ \եGhᤎK')0ЦnԷuoq_)Y*8Gery/EaL}|bAVZs`p0C_&0$zEǣQA}yUK31Z$2NKq!Q4~viY%ENVTϲ4X~XӀXP_P%dqi{t\U(~&GӃ%I.[\>vo(CAFW/k[_Σl,!cI}|V={U6/*8&EGIЅN9ëLYl(PKa|˿ꇼ#uj(AF)|rE^(J2mL?Jg
fIq[Iy,m95 iOqΒVǨ30|(A~&Pd18H/Qr0BPT֢B&Ofv'˔懝@	U23|c04}sK.É- ŋZnO/!&ZG~S(<_SHYVЦNw6M*BtU~G28,C)/VC$t	@휑{I\SB[-Jt808?m=o=4J#&ju+X/^Iyh7t.C<QHMd	nd%N͈nDb~MX+OG"\*h=8Y:ǀ-;wSlxwm")5xScӁm5Wj*|8(io%Y
Y
S*M>#Uh`E2ܹ^@I@{O E/ ;N00Cw
qqeǚ0tt09H3!oIn5v&ɬ3qLQ0Ծc\Qa
1F>L拲\ԢTX2/F	Mαh9LJB(]9^ڞ+ˑZODxTY	㹿h7fP2q\C?On`[c*܆ gI=%}* )sTU.ꪑ@_@u$$MhPvdĿ`sDTf,9U7!Tq8YA^@.z*DlY
],ד0Ņ!@uBdg4S Wp+X<F_Q%89 L_Zyhc24`,(fۡ?/FG%awD]Qa2z?5@Vb[58)؃0\C,P5^dg0'%J촶GL-EbOllO~U7bIQM }-ƤHYJ)i%X)Z@ d<Bns	܇Հtd@	?ʲa%s	>ad|>9cKlaƺ!7s%ؓd֘yuxê.O	`g	au7(mm?oOp%,s\/oI2_WBĭӳڟ)\@\68QΣ/G1J͝Od6^zG6"PЁvB8R_C~)ȩFxT.ABщNqӢ56>X8&W4ή jW-3ŴUjhԢA.3P1J\;۝)7^,'dȋgX)!da//67O02D*sb_$PD?6IX]>T]%-r;VVht\z䫜gUSY8-7" %G^݃UxvS:GqPXe"-/zWFIĬR\ѿ
$k9rhe/+\Ȯѩ_3\|&Kש$%씩#4y?no.2ƧL(݀4{DlxOC6$yA1*	Gf齗t$IX7H#Mw!3 gh9~<15tѵ0
@vq2nctm#M*FkyH߶"Rٽ.t.CO,%/Ts%e ?E|g\mFMCl?<86O9bF7:nݜ,Dr.YY0mx%6yH.xDVm A`0+TRاR/-CZTgUAl?FK'vZ6 k{h`aL-wɡb9wLp@{NE3_#3LMC%HòsgIkYe]8:!8$4DW߭)lϻ'pta26}1ڸ^<r#[Fc#.
Jb-o0&+rlHe2ePż	8o;*٦LhPтW6M>!S&52P ^MfZ
 P.!WYFvGZh}3rVkv
&hyNqPfp[!6޲,)\*M4yEϮ$d4.)A,?5
a~aeO1~naRLiZf1&KWT֗IR?{Ϙ`ۦS>+'`H2'&o/zzi#SIh۱f@?ڦ<OGcNRC),`yCGTpHx*oj^еӯѴ^SNEb6V|Imų	$.a1MW	,+S*J;HBBUiHS=eDps48Oh5n|-	~-R&خG]9iw>|Qv^J@ctVc,XzL(bT憎;kVD&ي7lOPoe/K|?zՂs"QvE߽Sk-}I#ↁXw<fדyga_R⟓2)&8s)bn0,f<ζzw[)\A	>q wCH1i)UxȦ{3;O4bSKuj/Txd,Wl\vtvd3шU7wYeLW|'<{TߺZJ(z/yfV*LCjZEisj<>YOjA#k< ꢢ`8LK@|ur?%r!>9|Uv~2|&PPcxu]b2.oSz78tc	>!CP
(nH1\Kw\`ۜb,{=78wl MicsHiCbV&QFμmXf%xAY-И3jmW5#Q&{O#ZTL&#%Ŧ$8g+ٔ3I3	6d]%YmA|<o,`M8
xR*ҏX?Mf7Gzt)cr>#أ"Y4J'#1쀂 ME(vEH`VyE{=ܿv
ۤw(M`MUnw r0uw` 94Ƨ{,g\c4?=YM+;ۗfxrثzz(c bN!7hx3MeA% 7I#?fogڂlƗ}y_nE;]sùdf|O#J\̲(IQ$+L]8M-_@yxфj$ zP3n<`J
r1kSl+D%½dfD?/??R̹7n#:46QgT+#J`͗&Nqzٴ#gc)1m<Mg[/_$Ԑw!٭|Xf%ZNncof*4Ot>U2 5ͫ9ޥg
{b2itՉs*%_󘧍`(~_[+q"c&hH<V[3ةVZ!C`_}J$:L%O|}scZ-.h8OfbOxܓpbjb=;T\uD-OC[c~'ʰ:X}f7t \ge(NUvnE%-h9ߢ^Vjs{eT`fi(papț-nǊo%|kNC#	R'ۻ4w*Q1G/HeZ}(%#O|ٔmhWڨ.'KP!սu˴OشrM,"P<Oh]Wʓ\4D(s晙7hǎyyP/Rƽ/P!EG7ܨ	o9%ctY^_1'2p%L/Z3SapxnxvX<l `nn~)jÝ *GǎYs1NRca@a˿1p*db9xd\36a;["9ؿȈ}`8H8trݚa?y:wh$LX?W"qN6kSjΓKŻ^0?GYW>9sy@Uh<gO&<Stԫ{:vuǯjV^oܘ5cȁ<x<r*C/=1;m]]S߭55[%j}.Atk~JDt*@O5Wje!pjܰ2VUM6MpQd<}KڃNJ(y#^]UTw܊(Wp>c3=Z3VCU\E>iAuNq^ռTH
hZSzJot+<ly5*mxNns҃I?Jrו/^omnnFٰ7*<Mq,^|d/]1do3SuBq"zmm "xZ6{Pp5t?iӟexvyvyȤb|&E5H׏MfDvPQb|rQ^8h_k3y- 	$W`״5%$	'&(PçP]aT-24ӓ_{\:cѡ*kRF8[.&}Ìь乹u*ġq7=rV"VK]pKD,ˉUN-'9[ɛƏ?JnBKEˢ1+7c2.HLy77Vx_<*YclM sIV+^ќ
ƨ
U0! :A(J>I!Y)JZp"OslmjL?>ʩُ?	b6b)-%]ԴӱZu7fɄ \\N..X4$I#ENeѧukI=D- F;OsU$ITP$E \%X+fy8K%X8.G>D_l,Z)N15NuCx ۂ߻4duK/4{t+Rw4AGîc>{m>ضY@O%YIϹB"l3eX;,ꈅ~o=NvMh%6i	q4NH.˫xP}ӮN;ɸb?K<y9_h3.c#POA%Z:I\ФûSAi=6]oLZ#hDQ̮0jdvw0LП]d`slLޚ Sif{5XcUXYD77ɬ)4xfm?DBA=^t^LlMώI +Q-bаWNu3ЌW-fگSN%7rXI|&i6'iGH0X`
&P#+4_@{Z*`ki8陾T"ܷ)T+ӴDQ蚬9ٺ5{/'$(Ex4hny94[jS{Բ	 N3D``	E:l?XB<pG.ɫ7yY,^P1gp)Cd!K=88Ճ^ KS=j4f,L:ʍX?55jOG%
n3*]ir8Ok$:Gw5\Ȫ r֍yT!08H_H6-GaxN9{84^i~TJr|kA.8]6y4x9<cT =Wj؝QN.A`jj*N0!qTYVh<٤VKuU<[o$%;>a ~u{(~keOX^Tv,nnJJfd2MO-QeknjQ2M_`l|OHIs4Ա ]FMJmUwkÖC)hOf70ª~K,C_ny_I44ӊ]-ւt	1̇d^")R7~~~&퇶^ݷ&Ő]5oYN-ίտ	)-ŧHW*¦o+ruyuv^7X&WVEo(?ufw0O|6cV?6X%$I蛢#VH
En៯ukKot[K|KK߳\a:Isu͸s	ǉ_o߷$C,YntTF؟oO3w[eo[}Wj]L#q\fBnFwڸ^(IJœb2xqz}kKD
8A x?D|U,f(>6E~ttJC|0Yf|.wN[eZy?߉[3GS2QZuq7I
- t-֭RK 2G늄f:R2B`ZFd_^FN[o-V|UZVy]wx'5U῭GQ)GCC6 [O6(_qQ~TU?Җ ʷo
QPPB	%<uct{cdsf4	bѼkB 6|2On$ąvƲ}tCTUg>eu#:% ?R&Ԙ=qF})Ij|KZbjjKZ%BI Vj-hZ~擮I&*1b=kZA7eoUa^N^Y;YVGuC/괦-[(w5lf)zyd6fsL[[ud[,-*cTkƫWj7e/1ٷ|(@Jjh?v{㽓n7Ҭ<ϪUlwv~Õ=Φ91̆'pAH,^'Yy.?>B8zb@Ua7ͦ\wL.!.nPYP Ol:}ˬs^,"s óT&>&BceIYҜ%dUuu2Qē$gu
FC@%z{_M-'n7yEJ^s
 a2<i'=MfWߒ/`BN^[|0HF_W]LC(ԗzH֕@K>DN\1UMu^<Q<))ff!Yˠ imUn>eA$d:g HLFIs4c1ZU+گyj PӺ 2mY`xf1[{K}Rmc%a?CAَ?	m:L8a]&ġɔː?)&3rb2!)LVn(S9pyNlnJGrr Nӳ v-Bi̮S8#
_AKWmS;Ƨy&.q땗vNCUIDSR@P_x(ȫv~Zk}bOrQN ӠlKG}jz)lp|=?;:T	Gȼ,1^j#7[{kl)^۸LM 9
%'6`[[|0讒-wI͓Ңl~^O2"0BfN]tSmpw'.	u6waR*;释ꃺTl,¦p~qT[Mz
E=ߖZ
X}|rwiMV>dɜQ]d`5Do)v-ZƜp")
lQPLJ&
t&*R[%NNW7휣K3.|qpeymgt3K47[,0kLY6#5=3!dƍ7k&[.B/n8}J6ǒWM.N
-dpտP~`"~ŹLFM:\lB||ةra0pp`1]g%h_$$-n!vGű_LUC@lWi
1~B>lī#]{{5@M1_E=`48lD
 \ʇ(Ɇ'_Q2Vix#i @>h~JwƐc<Yd#1;`c6[>.(88^f`T'"bP@qz"]B;P'`Xʵd"0}a2NM:Z.*WI77D;#	k6"|j\nFgW2Ճ)|9_?WsI8DU#@	;ׇUW>B7a{pm=!YZHZi ܐA/$i3zm^7}h<Y{X[Ql0:ES'_),NwtҪѿχG{{:;mՂkwv~::<j}盧pp9аZW}wG{{mkѯ?藽Qoo\KY^kW"\qCG-jW-ANF󳦯u&qbSgS/;C8ra`<򀪰"PEvw~;ǓǣnƮ1OVFY7I}ÔmewPoH唂fl0`%3uNSه0~şPC3!׎2lm)$BJ\	o]?m,?5zUM _2<jqMQݬYs7L	43vJؠkz씶
<v "r*h39ݶ1qo^:J\i@ ^
Ϥ?KV}Õp9jS:@˱oZ@1{45[N!e\TTi
lf&-<KF_dO	AO}AGm%.;%B3I.ԳrW(/&,	s^|D7FB߼^M"c5'e]fh$߮@vQt$9bcӼM)Њ@
>4UrR4r%_M=j:$}$MsD3\Z{:<3R5L| 
{M-m%Zo{}8&E7^b݊׍*IKmIm@,ނK}(WrUtjNW0ũ^a
bZ`mjr	Zǡ:>r}=y<!(	@w27ɒzQ11D͚{u29KPJ,ٙ
>A-nyOS%Uj{b-"t0ġ/v5݆|NXn>,90
=DX&dAM~[Y:S!J{(f lWş't3Q5ӁZ	}.ѻٵ:4B6]V0G(
[W^B݆|>1֩F`1_ț_<0bقD۩5ٷl(_0]rtj(^3
sWIg^9k]x[1V#м?Aqv5sh@vQckc_`*5NMZ׶
hd8a}r5b8½ IGP	թ+?k^19ǵ+v5>m69|W"@kk4iv=&o}/:r FVN^Ol,Oz:gϔ`M`3uCtk&\J'X&ǅޥu ~70sk\ǂ7kQ=am	LyS?;s"?`<j5$Qunr/CiVX;dM/q:glRׁ:
vu3?1k!q9^Ǘc|y"q0U n5md;:MvF<Sb "e9Zr2>J۬SUΖ7^OgPfy_2U@+m1p4C3aZ|ZTVl;ӾNua.CZϱG:݊|ѯ]:vhvzݽI;G{t>EʐNw2g-ZTUF#ȫ	n|葎q왮1gG?6?:{dlͫdo(jţMD 9E͚%R$ܹCm"l{%{t#lhpn BB߸|GeJ]eNE- Ke}I2b	{Ԧ
CS6 M*e.
>  /M V`]jPh_f'ۭAtaң|,|0`Y~=wΉ	A Olw>s0n@Zhrq2D#OuI]eӖLH @nZ᫉,936TC9hVWtgg`İkm/r$b[.}nPsbz:}@ZqZ3Wr^$J7ȼI!&m~Kn\{Ye}=xNW#VD:Lf7@ɽ"]hUW8Q٠WMM$/)CU`yуWS܀I23/g1i{2f@5'pq8MM4 2mb>GEarrF(F!&	ɀIar~Fh_߿ja]MX94~%6M\ğ1Voxĥ|5aY} aɹspW~sN'/i0O8gOB0*'Kiܳ	Ww`a;oǎFʝD($j6R}V1ǋn	g(`E2Mѷy"ulH#-~Nbה4<e1h;iW_6Kf9VX(6J<A_T6;Z6(*:1X썙N>5UIΉVhkV
Y͛=zOace;πD#`RCXںIzȶI)Č s^Vx9YLM)?L_
51V;Ï.j7o<a}%ɂ ~>7No/UMWh/j{|עχ탽Vd1s~'xD3(Iwt|'tPu?spу[pNU<weg_G|.P{
׾:FHeI5ݩTTacm<*",~~s	A_9yi{_NnD>sA/b)5%C*YnZ=io @aVR ~=Fa#'P?:!f{8z^\Sd,cF@+C|]ɯN[
4 o}Eؔ~]ZY
4=oYhnYo5QbR2b..\ BUnA^.k5Gi*5*\Ϫv>otHWbW^.R.Kk]EMOhaLEXK?qlMbMsE AM/9/]3nN ԬZ=sv0ƌzenM6o_qr
.")ބ'k٩BajƆ-,6(D90 IUDj9GtaQ`՟d\.kg}NAep}hn'!-U%D\A^~^}b6ԌsfS3{cZĳƈ!/NHsJ
APk$L&buݯQ>|"HH.mA@X()RCH߻Pzk=rhd=1^	d^Z®>WĘΒq:Oqp2%ag^OMDE"%
'!
.7~^5f!VKʙ[&x="
TsOei2"|jHsekT	s[LsUвnKTN_-,RJ={g>b׃L7dR]ȫS*OUMdi:*/IZd?y#8@37$M*%Q\(b
@2pFS9[Ө]zƙ^\9uA+ZP{/u =r'o%ұ|.NÓl'sbT=\UA	W5&k ⋧p~9A冗i me[U̗H e3܍	k)T5RF4uGWF1Mt"О.B5|3b-ѷA2(gdj'fEqbZsc\ːb2r}}me5=m-GFzP)}&ԩ7үIZ2HJ`赈TnNzPP8gd0)9
(E5J/LtQ%W4\;Ezrͼ}'	v""@{o&%<\DSjE&[g2$7)$)]zh!-E)}y5
2F-<6"&nb<9e#^M *=0:\KW>BHc[.uyWD]w#fCPדfb*X=W͟*tՍVYINuw:kA,#"
aYT&1d=&~n.F[Gl'
v&69hQ%S+ݐ2{0~6>p84䲮tGon]?QYcgU|2jܖDJFޜtH}%]RQNrh8'ݚ(e@04篥/y{I\^,:W3֮_6Iƴn?4 ɓ1\ۂd!&+H;!v=І/ţUiH5ORHBZ*;*9#P
VR{sPXΤPv`)$@S[2i8e<߿Hi-Uwf?ß7j9%@*\*#
䎟+
`9F/ݹs](jfv+-kp:qYGӡvjr)]CDjm[`ġ=뺬+U%E-?9V)Fa,hVL`c)˗	[O>: ?pg2q*GۯxνIg}X15˹;mahW_J0d;yzS Bh)>5}z\ޘ]=Ж!(:p/VRuB}l8ҜҩJQ`
Al98PUXCorz֌M
׮2Du϶=ԋ@N]?WTH/DlaSJ' Sԧ<Q*V\sW9b~$Kxw'
tO@r7(82Mw))~C%[o@BmOMMv:x8mP>&/V]Y}M!>\۟HX^,#Sg
A9^ŵ6U_UGuOj=|A'Gs9fW|Β)YFXuۡ(yG1S?,w{N0/'hS[N\%tdtvlV|ru6Z]'co#cinӴ+"S5t o3/&77S"ܬh-x@
wu?J ̋#tg2lyɂe)C	-gs_	+RRQRAh-:6j5i?tho*g	=87Zχ= 舵W8[NUT\KnzKj V",_JT3;w=|O_}73k޳@˩/o^-\ͤe3bmEd	S]uR{AqaAˑU	&8ZLU(5@Z]3!jK.^?~oV%Ye)HxC=MdWm>5=M5C \+3g+.qyG}	_&uwc%㡄B <]o8	Ǒ	 _ՃhuV.Ao8P߿Kݯu1K̾U `9(<<ӑI6XBc5J=&/nDdӃk`פm'x{̄8;-9Z"#:Eoq%µOϐfJҬt Pj\g£n:Nm>mj:>&KꢫԀѢ@J֕Ptr)L9W	ՊL
މ%pWF-ݎ{'嚃ױ)Nw-)d
F.=v<Wylnr?^!I(>[?衁${ay0:^ ==GPGZ\!RY>Ey"讃NsDpG!/F#S3e43$tx8W[v-lc%ԈlpC>!30+#3~V&Sm0Bz]E.e!RkIrfH&C	]_GrwұDyt<j,NpYG.oTe6M@I^m58v#7:A[mSH&ɜ1vBsDA)իLgta]M
Wpk	GX;YEY/JRF5p"ٖ^3R,?ҳ콽}~vfU歴*0~
Tپ 4=4'OI3J7s>.X_cv.s]ܗ/X%Bzjmz瘾YȚM0mo,97ÿQٹ6ʩF[Nż$wz8=Hĥ)qOϒa
=`|l,Oin̄j:k<IF.PKRXdRX~PxNHt2ȯl)5_$a'{!Om|a80qO%#:D;nҵۅ!	ȵ1oa]W&z3UB+.|s9P`cm	׽|PBg&39?]wK.pVhr,D]vGBA\`w_ZN/3j[}#q^ʷ3<p1Є-vUDl3,v[쪾nl}>k9E̠ԅ[`)&TI-WB:M|?«4s"H?ѫrd-oG%~KJJY5ͦJXw~d;v}e&J:Wr~h8>7cGv+ǫ|}^qϋ(qp5]PBO<p.+M]'8H\48ˉ,+4r.7rĜ.
4[9H`/%V0So:K.L!f=yiH8K/ s?TqW4Ü\69u9-*	_YHqho:nsxJ&vyYtg2}eyT%ڻB0aTDZo2KұhKuڞ mح{/rEwoM;3P>;s@n7;Iǒ!昞n8@'Rl2a	OgM %Kg3ʹ&mJx<{àիt3ndhSyǪ}vau.1+b)xf{JP?#!lEchZڌ q\^ou?zzYYdIeV_ն.KpRe SpOv1ԖE{ϟlSgu24YPsx`~W>$d#t+=62=o,#	P"^wnP;+>ۉbR|^.o*)˒ΘT5ހR+A]	uǷB6P'5Jp50rkwɁ nZޒl1{"*J=Ŷ:?8vFｧ{mSCɸ˥s	vdXqX|?! xbj O#	'j67@4,ٵ	?Ot1ƭMӴxݖp9I&iRE@/U_[Ӽ٨5?иwcVio|hkͽR=&zIDA0ܷv4ߙ Y}s*kQ桖8,N^pM6mSٶ:rvAVX/ަb6	>uxlѦN'ӺNB=/Cdl+j|Ӎ?nۂWm1n?o3c9MnqUR϶]SBkjkytȶmFO!`l[c)b|tRچ;Wxor0	/e_y	n|omAbA[A怖K1;cn8LZ'}>O\?ЋgswOo\iQ8Mdֳ/l[ƆuU!7Eȟ7[[=Ur)!{Ts)'+sNmCVtF畊0*07<HHW#;kq+^xs<::VOŹR;<oJ0ȸ}M8?.]5Tnh}ɵ
6V8p-a$&a(w9'Kiٝz;ۻJEqH ;"W45oM]`I+J~}S)s5>*+j+pIdx-HLO/g/bJP+jxq/=nQ0[뫕r5<uGzpM=^Bgg	ha؇C?#sFPhᖻolRB_EAyhOlUF驯qv3sF.j^#?w~1*f fӯ(cr'R  VTVk,1$Ȳ.aD.`I] (/98COaN 0K7֛(y15cnű?Vs>.SDF&XQ!9gj]"!ʾCJD>RCde?s]z©]I4Bqs=<?TA.RmWCxynJ-f4M󴸥sXi-rه 6H3`hF*zsv֠)^:X+?"Z:UFZsoCjzgp X[7dT95n0	*lOįdEG=(iyd pmxn9?~<[/+dLmrQC)VsWCZvI2a c8zr<d}xh>{"qݑٷz᳎;|&6fڦ*Q+w _8eP	7|o&Qި;'tA^+ŦKe`(2q}ۙܶN& 6YRG2egslޥTf6+Qh?;|n\Zфt?,K;݃2Ж(d@L6 RJ 7L؅NP1+B\YnrJM+MTA5nӵZ^4XmmokGQPk|
\:Q˼~E%">v|ty79%~%/)RI{TP9-Y~_J^2I}3ўΟ+5Բ:T<[7+ ]γaFΞ*4%ڬ>+RrM%bu+"kಃ!U|+d\RdwRC"($р-)ۦ3z?M8W"R RHLmTIKF2f`xϢ<λ4zxk:[<2rz#I2ɒǁdP;:svf) iq ༿'[uRv,Z @]:xȆ/LH
I:Bɭ^TC@"5)b(7^Ő9G.NXmM	O^bw-K¢7ld)f`v g6x2]P*ژ31DK/ZA2 zd3rHxx}OGcsY;矖 t?{%~'#4	c}+'Ife0ѹKm]Kl[۲#~8ID 6߂x}LFq	L(:BuHi	#6nTiG>-m7U(Gxo`OClgvp[?3qi(;fCHDT7-Th̫ubk}v>c|@uԿpzx%r"kz	z$wV1 dۜ*JbhȎnv4,gk(d{E+fwhDtE>lj((TEJ,(/9NFC?o_+SJ#MaV8POY2ԭ_TtMuk*<ZρBe1Ype ڶ)=6CF?AMQbZ{t" Dp(Gh>{:w!Hl=;aT0{_~CJSvF/k	],gH
)M꫅Izftçv.r-^қ)gDI#	$k[zFxR/҉CvK:q'k0<[FE	'}@gq;H492a
_X3ws7Y~4
 ZZnsz>">TX) NFm[SOcєqWˀIt1ګ&n0JQ &*sI)pj?բHѡ_Ռ^xX
,VG_hW^110a58J\N'$?	k$%rγHɏY`A:@&H7l=ł+8H7Qh7 [н\u8j7/*힨Sm	Mزw)0JC<&-t6@2u#9{/ =iD\;U!g%-zf:D@Pm<LƎ'Ys$Ucs"< ϔqsۅ8槽N~)^F(D^ok	
@g򢽝HԨ-񹬯#$RY\!Ǳ2^˼vmxpW_2euVGxۛ+s6J
vVzx&ՐR#.!3'Yr͙n{C5&q\C'Fj׊'3ܶ'9^\q~%iDQ[+EwX%H ?)61:φC(.z:]a7:p9Ur"kch>M'7}"zoYRl^1N{䂥wt
Bf˷9g!q*A)\1\|y?݀jB-?SM|e(ҧ/Yc_ԜyvC{4BsOF`N2}LlvLo/wo>ˍަ~d'O{㽓N8:mծ&a-wr}תspj}t0Ed&(KAM.RxXG']>q3xA_v[txZs5Ĥ$}h
װO59_-OWܻI34ݯ24xI3g2L.ENmi&˝UJ@)yJPp4eBHA(`5Q#ZYOLfT͚l8( Wn"!+m?<ʽ*hC#&O
H=m7vʧF-i]?VykG[WDd-V!?E}x yPpftc:{G<?7lAz#W5/|YcΕ:o2K!a	
8>5+&ԍ!1ɧn\<Mݡlff>L1fFJ^,QǗSV_;L^w
QE(cgS|<L̫_Gڮw=?$a@`jkg9q_F6% Tߒi*.9?O0<[2"NǗ[Xk^)YϽO{';CDƵLSk޿TK./I#8Bg	$Kw:_ ~5|-a;W;D4?:?<Lَ4̿xGqOebvh؇
79uRcm G-uR~yތl`%.8ґ!nT'gyRV"?l_h0knp
)Lc|qTcڪuM(Q!ᅦK#r:EE]'ske&9
o-\c@`5Pp@Jm$X2sFw;>f% Nҭ].Pyk_!isT-7z)nI+{I"l:ziurRhHt>ހZRDrtKH
sPwGF7;M)%hڕh!6&Y&Wf|i 0Mfpq6B!hb,-j=Raˑ4'n!wJ*>7~کUc3O@w"%o>-Ft:JdƄ3\$YX!-&r#XB>϶9Zp4 3(d$M->k[x>H_d1h3e`Ӑ2?.BaT],T֞ [|eGx{;·'{:=Uq`dﰵAtN>u{_NZ[fh:*RTBDFHx6}L!Lٔ˩3"v4iҒTKvLRZ1d).\ϒ|T;!@6v8Fzb*9&(^X6&r 3V8-2H?G
bRnRIf/tɡ"5I&4~жsEdŎ\zj>k푚)*&&/PAlpANãop4E03'ԣ2k#uO;a>Ux8	P"aWtql]x7ίYr4CE1_ EJ;Ӧ6PwLVrĆ^yi6;HI{=%QYW7+6'jm}ZK+ HL\1J>Tams@]X1-eZ\G!'We\8(lLocʣp-gy[]0!-"E~qGs7>9OZrǝxaՕx):uP@~;pv	󽊶\AiwEȘ// ?޾'g5>0`˶?V4Cܱoo\V0RxhiR`W:e>N\Uiy8Yw[=^y
 ߞy½seìmX54l\)	Z"B
5҇t%/neP7URKS&eݍHسN݀_WݕʰaએQn]"m!x.nTe|GSjt.3Hc5,Ru]0VRWz6t|M'GG<kp!w-!;,¼|S
d|*#&}xZW	RQ3zLuys/p6Qm~29?Ueu*DZyeYVgqDmIe/JU? &J1@[!jYdneN_q(#ʔU,J5+	y*&n_|1!J741tExg	bM4ީaVqS <.ʿ)7LHEp8Gl$L/RrxT#ocgqsZIZgK(|& KݡŎu,DGwPLYNGXܫWJ64r m87m\/M]mWLo\ xK:a}pjg\M/[Øu-V;K]Ųj#+!r'sՙ(:;IzVI=kw-ȗӢZ<d#h|?ΑGyMy^Ay86$~ }>, ߝQ
}BDuYzII۵B?q_sl9T7"XbR]:ic	Ck,а yGL˺V?["AZ$uFwH>cqF!FiCu.`&4;w%y>hبu>p+FâKt3x7Z8.m	3@^~?斓Vs{rDJPpv9.j8!̬n25EAh5J@|=ksVB7e
ab	٪ƿ!)Ed?I)ΰO$5P̣7,wRL8n#+mXXUةZ *zO"60*OoP\o-F㱦3LFZa2{>KMߌ&6:E8t4OuhVj"RvK f`4~Eg;EgU]lES䁙
/^Z/3PUNI(& "dܢw!YT*Q8ǅؕGUm;~cż=_ d>!\*rmg*j.AtId*5ӈ;aS9A(JsuP1kw/Xp}E8^*GYrf8I!zX2-dg7f,,\*-6|(7ab&~W > T9Ye'cu~+ﻛ/Y+rgo'Αt@hsڂnr;ѓ6UQ5m
ce$)i07pX4*&}ygbS[yIwXt.eK}7bc-iI2jY. "·$EK(F}]P3:|<lc6C6S'Jb<Tnj<CfpA	>
^mpLTR&R4)7Muxzj
lnO^SC[KX0T~Iؤ*]h)lqK;x%k
*M @: ^O{XċJI6 \ZsFc;/]fnfg._w4h,'ݪL'Rj	ύ4JY-\󯹅ЛzzyBtW{K8aʟ,@9*jBdoROLEc|%8sn؇M[ˤ]7Q^}+VM64be. 2Q*Y@k_V0B:ji-dYl.o]ݒyygDEd dSs`,FTTb AAaʧ<26M:)'ubc)VO{/:x?궶67ohdCzaɭOkoK3&)Y-1ôI.A^<`4܈K2(|,8sY|;^ܐ6#LQ|hQmXL$bȇe}+Z=5?&ϤRgƏHA6<.oߑ}v*Z0,Խx`GEDUh`esp
2u|bƦh
G+.z)&lqc SzPzz`arMʫg{6rq|
eHjgwOT(xƯz<,ȒF%9Ⱦ J%;{v"	   %I~8;ʹF	"i QJXf<ʢlޤB^
$X4[	#?L	5f@--ߛc1j|b	`O;ߛ応::iU^W9l}:u~r0.'ߗ--ǼU"m7sY	%/Ղ-꼺[ݮַlsI Ԕ\YVK]Rٌƃ$TX#[l۬8JKA(~U;|9V~>l`7AUUySf]Hʋ='2҆RoLdL~oMFi:Pt_| t\~~bX>?nT0c0I?oZw!@M5|\]Ee'XwQ7G``?Wī˻6u;*>tMzU(ߟĔP!.L8UND}Tz̛NeEKy{0[
vB!^3a_D/-2owNO`V|yN9dڅlfՔM2BUK 6˘}0YM1Ë梓bq);x
zM%MljMS$z4E+h"	,8S
uSKYΟ&IV9ALU?vG׃eoO>&7T*s[P:7O@uNQ)w`"\maRFjwЇ<%8F?򫝰LþB,=)vp G1ѥsy+A2-t\zGqkޅj&k/=mj[5Ius̒f:%Um<jcL{<M
w٭aT֬T!͐~>P.>QcR op.j7[Z).35!Y-Da37H;3Sߚ<\LpR%O)U-L:Nd`.0 P<F57GZGކTb7^A>+j刕:[ÿaO
8o	~9,zsݣtȱt襃dZ*V8'bfC3vQ|^bFHy\ɵQߗCݰ~]w&ܢ绍IݎԎoKS V[-V'~*0V#Gx¾*ہ(_0^uEBzE5nXPJ0:#˟̀hX޴jT-D5;QˌRp#:j8vn¨_v[vaj*IDM5CNS?S }un(a7 t$N"ON!1)4p,R> 8Uwwk`M.1-tN/pOeęf 'Y挎؞.ހ8L6jU)W\OO|]8Z=nEHY	:S.T4cb5AAz1o+g߂gNO]X7en~oO<sH7^3~dK9V]><zo>~[V_TwtBV*Q*I?z?9}'DC{'ɨOpx+-}ei@Q|qy{VJDφ"[48w/K9S$Ro"DB2uO~`KmAu
՛Syۅ7#۾;fu}}>oKMs<ragC&Kё154GHOc;p2Kኹ
qiHDf&_PI7p[IVVִ"	Bۜ!ȗ쎍QGl` (GB̤jb''|K"S&loA
 Mƥ-VUOٺKt|{fSRVHTb-8tK&&l&ڄZ:֡ЉZMmE.&hxzvlg	B[ZرB78ݴ$[#aCD^mE;@B[6{j݃Nk8γg^zPQYCr;maqW6	ixZj~/"L	vn VV7 !ު7p-[|bFc=R 29V
.z	xĖSɪPU1"oUL</XvE>LUzk4yODgSL@%ƣ& (ȵ߆1h>+
1YL$,Jh-k{SJމ~{|>k_[~:/A)Y\x~9dә|KGJ/.O@iM{Q#:DЋ(_'ic<Hg9?KFn-y]fU.\@dt'mȉZ Kv; 5qR)bė8@o|^z4qҖЩr]Fj/\RI`Z˅½5n3'=U7|uQC]]-kR8C0BE6p&׎^9x#/ _U|(Ir`PJb lS'?\9eZEVԕjD&< ߐ?dW|P!3ҿMIU,[0QJvjV5f0 \Baky2'f*N4@$Țd	B ]U6=><bnxyI*lIڭ JCV#B4PيA7{JUI^,s~Bn1 ]߬%M)O;_ 6+A/;U֜5jnuS{ܫή`qBo:Ct[)8p$էi;O=Y>r/Y14
g6xcz&/;}Y=5"
yQBL*jD1CUƥWd\)[9jtkecx8OɚFIM[16$%4E#A=|etD,$q%Sau'e"~u31}aqk( ґ| $=3#Uz]YW'QNƺ/!YϠJk
-A
q	c*XBW,|M+UkRHv0Q4b>ݲBncmZZݭ%+~+,93N/ǋ|LL r:pA`sʕ+։M' #HFt;եN"C+:t|{9uׁ妷d?"E́xY4RD|=w
L$m,YF6@i2Ѩ[q<hd	,2jAv躉8?6bt8W,c6b.ME3w6ŬG\3RNX^ۦPp |]Lgio"|9\idLYLZJVp{2&$Wxñ85UYɄ0lFoa:4F9<`ωwmOO$TrJyzyhYOC%(1e׏PbuT__k]OJMɭU>h0"h2CD,#:WY"R[[UO`YբNiK4C huH<D1ɢp<!d!*$:fid2[/ko[<$7[RlHSHe TsKL]稐JG}UZdΊrEmݔhjȭx@Ӕl_'JuMmU@x:yLx H#4,
BXjۣr,Bhk-	hڎp0\%s{h;jH!g
{֖-㖹=dwSj!8,zp`T
ȿjbc$?V\;(B{mؐ:d۷˔b;2\f8b11%1/9`c}rq$?{bi9Bhd7޾.g(xDT8Tp(-HdѮ)0zj{ )8}mQ_m׽$
fЋVt_
_iiJjLCqLCjZa532V3j̞_wau`ɨ~À#{lL,4l /5,ݬꭁ%	ͿH.uŖMBzd	iDҢFY6HV"rMxtCW3xP}~Y.Z(/ C7V&^԰vB2b09?SkP~#ҌM 
HOzŊޘ9Arc
{W{S\Ff4ԯhA!`DSeǓmũH%(֓u#@Z9
-	OWg#+H.;{iQo^˪5KG\zxo]f~6!p&aUWǹH
I| cɍdp&1x#u7-Ke@`|})L.IREHtCNFÚ*#&=׉)]/:}/H%d=C!K~<[ Y,hVN86N_0a	7<̝F/"58ȇkaz҃$#07>![{RU஼^gɂ=yDu@5cU ɩl-rL)B 5Sv;dWOF@5yl>ifx裂RSj܄f0U-PxLeh@'#l!M lVcjˡ:9l*CC]N-c]:}"_:C6ˀ8M[{3{	q!A	R3g;/Ԩ Y*SvL^ĲPZCyRRk5Su>45xP}_s} 7jYS ^B+VV 2.y6	B%
!jܽEGCo~JkkwekpoP_x71?}|	ZI"4F!<0؂G%Z2]QOM-&	W;uKx+&OEcNĿ_&DbH*эoNu
\Lũ=KgD'Ʒa	 `"BK5>`AI?]6;Â^oE?/'IzL*4K r̯|(dC^ϖ-s]R0|``0vhZ1{å낋CF	tUZ5i} }l9{?!MHބս ˖;ZJl&
'W\_Tv>}*@{6<KAB5YFˈ:>ؿU]4 ٌlb74<w<AIFؽ<l7Y~!!fb[x8kkW6i-t/p:j(RNDAT/n<VHEB9KFt\G6Ȃdbz?1$VI$|n^(dO!۟yG'HH][>MB'ӀdH +Ň[3UbFFBUAΧ(Ibf:~A^&dLy5*gcNpOC)7RjI}A D3NTqV#;ʾg:^^pI$ -M#ICтxNV@߮I0cgoߔ|
㬣8K'&%Jÿ>Sj<1FM
Ny1 >_:oZznDů{wvd}	jO]Ի,պre1ə?M$UW(9w	~w7Yf.xs94_GEquvrT2sEj5~eO__k12r0QGen*)|SJc]4}NL>eSQ@RqY$k-e|(cC%>~ԛƻ4[L)(#+eUD?D/vvFhQm2=~*Y܀d
byxw?Y7I&uR'Gɲ=tEonps|0c2'&ԟ;WrF兒J*&ܗ[Obz0ۃLڶTT0QM
2+Nd!X,gLå@ZVW]0mExյ!*#qtRW{	}dy *9x +*fV;'@%zJš.^i?a_2\>y'vzۡiwʬǎj"Tt04v^DKZ%\0$e?p!v|Gvɥ!lpTPY>cP!/!=>}SI_F[T*2JU	&ĴxecJ&6v."r+`;1 ģd$0A&}AsG8JѴnɇ0PeG؆bbR!F ṩ1ro!<z)$CYxec4jFClH-%N *E*1E\ѕL08Qi&𤻺U8 >	ekq:?^LUc6DNEB?(e&mRާ6C~&|S#n1_3MP\=>>qT؏_Mb?w~m/ TqQ
wM)04IŰB&n!zփ4[.S0'C5\P], A)dop^HW,nUބzPϏXrbuXu(V*2y߅L'A`>Qa@m?p+Bۧ*M:#ɥs%$J'fp_&{tg#qBϦ%jD'{}	@>FW+=,0]s 7u3C|ԁ%WhFT8퐼!|x}cYr-fN|Ɨ?݉_bCHA<KT?{q._`w݄17y:+i^$#'$2#<Y:Lʻni됲Ȅ
LUO2\ho{rz9ȃ3"g"(.J1.('A]iYl::{2k/XʊaBUʸq$ԕZNUN{86čRe-Sq4<Z҆} [>2ZݼM&],e0:JECr#=~q	dAAĴL\dxQ-0UmӇwŌРzo'iȬUa.jCҺ ZǬy{E
:۝~nV9-oB:J]#a(vo]5!UPkvN:^a8Uu=q
6'\!cҚ'՞8њRDK?F[Pq7?-T#4C9yz~Лȟȃ nM7XYLɒIp̟6`tiE4@lRCGtcxzlndSp$CH:0Rfᷭ4}3q*hbaKpt*0YY|IzN?uk=1kBFR̔FA8q{sZk9ٛcM̃9mXR<k:X.,jj21,2Yb^OЊt[أ!+A5\Bu%9\g&
iQdvm@$'*
K@0N^zn`jx:?X3zvLpay<Y\^r m{X]^*Ax*N8|i1e'd8aQ1,^fpMAkFT@QAԭyO"H:w'DFSj11r;z)&(k	3zXlZҝ,kհ!{bt2Qu>c	l1V`A.d=Mw|n<RiK";dAmdw= Nm& ͜	s:Sf[_+96L]8/!)Edp$c5,FgFɈd1!4LFܡMC@;Bc녭
ȇ>{]5oR[G(-!*	32zS_RϘn.LQax^OQhj]: # KHr*'L{,OO>A,ED~iZxȏVꑃ9ծ)~K
tK2S1DAZ(zA̞6V\\?fR<nFKj
 d:n>G_JfU%$!ʼ,UMp)ՠQY\n1BzRFʧ]0Ox <<S$r)shxvLfuPk&
£aj<Q;WT?C,]tr {ȫbZT;Wt@8Wo51)_q'F4^X-s8m+`AXDE
*ͣ4
텅`},Ug %jvk`+:tV%-o3	ݴ>=ňɌ
ݖNz1N'1zKab.f4׉T"3UrfJE,4TEcOf^6}A]9B|a`pPF89ô!.]vdp<t0bm^?uNZ]<r>$$^MXz?r 9HΒ]p

EgpLR)" ;hu䬢a4>NF/Yh.#8O2ax#2/1`W[>pmJf~;t}/:sZ2E%ETK Qo.!G[eDʂ\_\V;Ls)L+\$/I&s	"IǗd<XѯPK'n7O^}}0]㲜ȡВBbarL|7W+aw,w\Ǉ૬	JD|o\*-l l[६S4"K S6z6Q?k,xaڈ){K!ɚkAǦgB|)]X"74 UfV&w_rjSͭ~@B$x^%nRBuHcJ[yoۥkX:3Teƿ;NGhJ;S/!|DtVMc0kcC1яKkts*(*?#WK]GyZӅ|5	[_I­/}8ϞogV2a IV&[&l$ACCza2+V[	,f<s֡gtEMisQ݋OD%KyP,\=*M+1#q'`݂X嬕^{‽⭣6ŗ"oDwߌxzng)oLef#Yٮ'46?6&RF#wG1d%[k}J*T^Js6RT'dxB< 9#tU2]z,v8W1RpufL;7ojvm]WBiF l1*%O_yeY	sl*qVPBcjeJsOQ["'fo&ik ynph뚣pT^;_Wf/Ϟ}L÷XdB;DW֒ v6<ōWV_}4eK}ߑ]6uOQ-Yh6(ϴ쨜2F뛟n$OYG[5m!P	CJb?rҋBhȦ,O(eڛ7blKNh֞%s!cND72h֦LTEΔ܏	V<*X!(Tbߥ3d@P@ڕpЕZuo{Ȭ+f ӮqOznNqoMJwl"FU[[y:ṎE:Ƕ_@Fb0֣6od^-x/_H45~PlapC4~qC 1`>3?{mSg|(MVd0?GV]0Qm`ǠaS=-$|x_: 7B%ꭄm>tvN-e?:>;H5aPCY]k<}vgaOA#?;_>7X2&11PKF!U)1EӷЬCb׾WzxG_>PE~bE8C( D+	ۮ1Sr?g	pk`%lnpޭt|eu q?A>jzTFAokAݤ1|qwev+jdEVzY(**~CCqz9gJIq*"$fHݡɩb,`w:*Üi5XPyYve"Țil>ўz9crw,ٖm5l{Q-LybD8"Oqk;UFQWw&raRMAևR[Tc~jTUF#j&72otQMK,6:	t\LJ[S"h²w
ĨFH(BMЯ_vR)QĤK
Tz{d&5+BɠoHRYc.#RZiɺy3y/t?vԍ62@0a2Az&,i%j:fR)ؑ-2! Ɍ<_C.
௓8;EM7Fk,𮣑	><ykOGHd0>ٚ7d	XցCn@ \>wɦ\kUW?6s5~e,${H5)Z3ț0
ϲkQ!.1ܑ:5cjF
x\V\>ǥ?g'7)xrM
D|	~۟[Roh7&<!^pE!6g,JI%vR-#6j>ݣ"9p=(D\z@cV(ݤU%;&ȳf!T/FgbBUە݀$eqӼfX=>@)oQkPP=&x0>f륆ͳQ6$6Jٝ0MK7k.+
]Fvmb
ZPj|z':mB<vMO.!m]:A]iXGz3Uol8큯\EmZR/؅Y!$71Qo~*6)=Zxk/U%|#+/SFfSMX~6rjzF?R\{`ꫢSp(/=HzW;\BM
\1> 73Q/ӡח?<E3;juB#.h h6xZuq[H>dȨn CVXJ.!xiN>#*6Լ+Ʋ-/W>?Q9@(|\'z^3e4QZsz[ik&u	2(>JQy8=ZC\zXZ-xUςh8)˜V&gKCeLηǗʭ&&0XC|ED}
*Ēv>(gB@'	r˵-/&C1zĳgD؎FGF,S&d֊(a7oog|V9-w1ؤ6:VNggV[K~AmjXu{)6AF4gjByrIsG/y4r.hzAx$bE_cnЅ3bWȓpΝ-lkZYnGXP2_*jhpeHPReswK"p<7 s0h&qz[qJv_	Ef/z9+	q0}6"rHh	C(b/S~fJFKM2_~nnL
'Nt|Cۧkj?J?~qiޱk+y%"Xҍ?fUgUƯ
sYKk]QE5RP{GJZ.?ZΆ_E8!g&9H/GSx!!ꀖqF+SUDI\A8Kϭ=XȒp~#߼4%ڟݜǫ,_QAA{t럜݃ ͣY+J;8sJ5/ڽՕ $A)JŚܚT^0"=Ssn=?jrkl'[A}(L/9ÉdU3_k2xP$q`?漬1aYAL(
D?NӅJE^ Sدiˤ7O950xw6t^Z؍[XBpW={lI'#G\ ;9ZrYCYUsFqu U
{z'_NauZ~/ǽa	cqGl	dTȈo^0p:2	Q9Tn&PaI0uӝb=2$~9\Rܥta-rUu\"}I7BfUJqOGBL.uA`b®76>C6#йGagQU%tWcsCU5|(t%Tr{uu܊ʰ6[$.<Saolm6IRpc&¾QI7	U24D[tH)
3o'*T#+vr{hGF:: LR J6܆D[aˠ þanP_)?_j#wX~ީ!dsl@oҼ.^J#W||(h`/D!-+
SJLP۱GXO^8D
Pp?_uSt򥴦nM|Tv,b^M667.%g&~Me՛x f1ٝA8+zR0pbd.J)iN5QN6 v Dx3C+̏$?aǱWeDZ,V9lZh1^sPkJIq]/؜cE+i0, MuǛ޴/Z'PG0fЈ7 O')CjYAM
=23S=c͓tl0dL+`AM`22HUN~7!W#w뺤v(0<̒[Ӛ?nvڙAK
ʇAMQO%5XH5]+MrF#kFLqDwyqM
44.بL0$KGKq<vj[ę3{1ai+00=_xcA'^(*iZiDA"ɒ."stnXEpbG;p2qZ׿<`Rb'A8k? bfs <Jo?\ k+V=XC}y6
WB_&CZ*37Ί71Q==rF҉SE23sw+H
UsLI&UꫫV$O;+#!;`P|waUR#[S@eQGyTF"BhPisQD.HqCUΪtczM69kj8hhy##38^vT;ȝnofi0Y<vo5*0}]̓-%QG(..E<Y>ǱQ
"Sx]\+(|2վ$a^s;Es!W%,oI`b-/@%}Q:l]Ƽ˗ax~?8߻:>YdhAƬ'Ԕ˩us`(iCDgEA/zе؆t>#lXeX 97·1neQ޿0XtV@h9bR2[Iot#	UT'l1Aޯw@z.fPsӜvKMXŒy藑v{显on8#-5DL;fvt9&j㟢t&ROU4Qŀ͇ML^ccCu]4Z795NXn;T6ky24~su<#+ۧ4P,%skML9v/Ui_.U#QfNd(Ӱ`mQIR#pG8	C-H
<Tf){$n?skWjb)Wx]&XŧKMhf҆	%؀\6otL;4zgKY+A":V:.^Wȴ&W'9c<@ȣH|vڧ}jrw[ӧ
<&z}-:~tk86@^#$WzrQv\lIwFjzw{뽌q-"gG^QP y۔&'?vέu"'x'Cj-\6t 3)oZ2Jl.cv*T \G2vr[ɳg033SxB26ox%1AMUC4QP$_	)p򼷢9ʤ,e2<]Cxg+T+Ld.ҁ8sPY-_Y/QNXn=FoЫxY5bsZ"'@"rr/:7c\9v`;q AW$ěue_7P#v{|lM=ltY)ͱ5̞HT?Xq|s{gS^_κY~M$
g!LsC]A%䴲J(6@\)gW}!Yu! 82lްM<JBva:HHQL<Qq=OahcΊ'e@kdS9ƄoJ6#], ZN֜Q$N$IaYd̏ CO_7h${	}x
5YC2,:jF5
^o*'}!, Ieos
&v	ykF7k̿L7$v@M68M2LrFxF73;`GI:ddMėQ,?<A*lggΣ3Irz.>DynQsrL)M''vz?^zt~MNRbCt)6^o0ҺD,x:N_/} T^?׺h$fl 3+s"3/|QV0<Uzy( Mr zȗ4JvĿq뫅yoSq8]+x4XNdʈzf"#khC7BR3wZƣ77dԒ$\Mܪt1P}2OJsĸ1ʁgODlײ;Җ~βeh?Q@D>E]i1&9a̩~wqǁ[h7[0t
K.hN]:l|kچES@zl^ہͬ5Uku.fFt46n{P|֤UHc쒮Wwv㳳'MͪU?Vx21GjRM؜B"F+:;Uyh8.(ۥ	n 6;r(u!¦EFY%З8Yq ƽ{)FX߲丵yyל0w]Iv1ODAx Xdb% !.W#@yhOA:y165}GYZnw9x5<7qzzZt UrX	0U# }vXiFO4b5ʪj	"wYlH}p|kuLYPk/vvvˤ$~L'W=c(V#Ù$j&oCLzg0T8Tbb4gϞ5r]g`^
J9QWf>:~0>
^4jj,
kY'$("HsMiW6)>T"ԟ73^&|#WA{fx y61p0pQRPsOpT0 KnU#Y&rmdUVT{_gZ*ć]2I Э)8wݪ4223/h&b]2]A9@ :TlwNi vy{|ktC4a\..kQvUw6_ _ZԿ5"Pވ阌Ʒ*B0syRјes@;eD֬	{,nGRL4:)TIBt(QR/$&DgH:ua{-SzJ
n-0FE/%{|r_+Xt.Yu!T#8pK(_D{#U׭ߞb@cW)@8-gDr/%itz@^?lj_CNoˠJZ@jjPݓ֯=Jts;f4x<
YPs?~'"`Q qɚy9jQ:gjF(雀w	M姼e\fpH9:{͜Z$B3vN
(ϗVwt1nk/v~w(Ӊx`,ʳڋATUĕ{ oJf(O0z&}JlLiU՛O/cXى3qRZ׷M<{ )>4!t-[In~PcUmN"@SJwj[V$+>\X|[RϾT&QѽZeΒGr!xA ctc0蘋	Gj
dH^$:eyy~~tRQPyp1/H/?<o@MUܪ֣֫ju!%>Ix9k(0k3SJjNB๬Ik`փsUY1U|6;99սTuR~DVu_ ="5`?rکڪ T#g<=#$]]WpkEUN28D[Uٮ@fb}*#,w_+r9lcT~gsԿO3i9.k4!ǐ>A(40jqʦXtZTfB:h:B:<zۛt!hQ3׾Y'yi\&`h[u+D?B=UD)]#=5%Ֆ6;S5![4Y4EP2
k)y_^BrEܶ^ox=!+4"c{{]a"u1C;iRx:,|Od-nsoĪ+\'Ѕ`\p^P ֪JVlQ
0Ƭ3Uo_#2\|02vc߁b4_CufLsRݹռv+vuLO15OnM Tq2.o^ vr^_Uڊ3De3:	lV95 p/ۂ6yOC&,d&Lpq,v/MJ(\鋋HB%ƛZl
cڐe!͇6|&AT(K2I!9DJm* Du[Al0)PUЀ(ɟMDNb)ҨJ	bZhE6(&Vaxo;^+QrVa?JA_l.+4\kp/ːPQqgbYmQ3^-')2L㫛=sMykB.xܦ_`J#LlHA4
w>Olڹ$H%"-pukc+1̎Х?tu\^ɛ9!!Sr!YSY7aDő=
 Rrh^V-'EwHUQȡ3cRľ/ZRp}qkn_LSztyc~P&Cէ"YwJl¾RP6 h &(
*+9`uﭝ
	$4BaMQ)(E-F\#
sD9M"b2+ky?0zꛎ*T-!5>&=i#}·lP{@J7쾊g5-Ry@+}B\Vh*	SO~ 22Mh9*h񗗯J	ڒ
Da<	R{SAVF B+ZjwRͦtm,w5wi[Ypxu2oFy,6AP*_eC=qWS~uQ*Ͽ`
5;Ku?L7?>[N}iiNVfp&%Ȣ]E(_Q㽁?9;L	gYsr>j~%ü0q^|1ļp}:R>B)ߐ20ki}}@|Ə+neг+$ts\Lbp,r9ʟ_3L͵,;}=_Ρ4Owًs(Ϣ|Nqg:lym܌JwuWޑ1(Y8G:lU!!!MDa>v|U?Qbr,>Y@"w&45fxF	G9YrHHk>+9:~uWpbUWW%MܬLΧO09rA#XJ]N'm^C|	n{[(4Vb(NUoy'u'fH0q$pbTGln~1u`,!-d&kGbj ]+mP
՘v]9ԹNh߈J[h4YfJ/fѝ*5{>ஒH~Bsz> H_LE%#kw}8v@Pnw4,ߥ{Mǫjuwﷻg=^"tjTXi	?yGze}[E`JL[{Gj	#fෞs!Q8
BȪ]Vebm9B	)Tyb΋0~5@ь2%7?TaϚWyyZ[oax֝*S>'t׵:͇|yU(7"4*GqG8<txcG> KW%G *5̣d!"zDOqz|5	y[dmEhkYJE7FKb[a; j!<Hq<ԯ=~n-{GQuAg7fSYfdP3KH~񽀪J`(Qu$ mP}4v$&
jD(Q%>/U^tzb1ԬbJXbZcԪ}AW0~YumVw
LS[,ޢqDWTϙJ̍	ů݇K|yaY\/TJt$**u6xhkZx(u+moLʫШTuK-:ҨIr;}	:?P :T*R<HEr<9؀-jlh"=}S`~,uȧ/̊n<2\Yv\-*pf3tɐ8$1;ǙUxww|})	`]9]J3ëC~Eըz^&6A
R$Wjl@fW:TYTT$W"&aW,O:iMFq.ǅb>.pJ	
)UD%;D+iMRq1{(§[8=5$UV%fx]LpT㴷Y(;<(j/$Y>1&`{b?1U27c?˯k JL3d!yl}Lk:ƤS",WIX楛#2X6H纔CQR@2֙-fʉ^6LnR:P;
Ҍ	 ~t$uC4a 7|>;0Rr@
9wDujAY}e /_ !GCcpS**w*n̫Ӥ`g~	UyYdGz4QoQ"9jf6"|
9m;I0钍	h0PA_rV<9n. fQ//s]Җ痊\=bJ9B2L0V֬N!p,Mճ0:ƙzk^0Ԛsv.dZ77ԝɾVTh'07 	W^f&ǦlkYgߚݨ7dI3+bGu׉uDgKyF
KR_s[aL;Y7U,37s1;Y;)DKc(%XY[`poYO~`=6_SVj^ z:EįBW97D(oQ҂4|,/jؔ2/VY0kbYOӼ_|b<5'&1SYMqr@݂T6`wg/O~,6<1̳No^a]62o)jpsE]_u:?H	 #?2&@*؟i''v#6!
~4q 51LBr5usJ`P[S~QrI	E2_r6e#  Ԥ,HX%&nn!
&B^o_ݠ|̂*p	x:[`Ok}!_7 yiTc9,x28?uNA!Ӄfr>ry98[H9霅ȸKHPZ'zCf,rv72	j_z+p-}~ gH 7olykOu1Z9od<ZѢ|G2VC`Ɗ,&'bI66Af(MN6-Qy8=T.RmP׭68#UeV唨#y+ tcʚXWz{J>ڼkzKZ#} @4+wC0P8+KͱAnq dI{UQ=hÔ1e:D',T.%<Dk+[x*Rݲ9I\`^#Jh46ZrzZ兩!z08.yLQ]F>0;+	T
lOy$,߿BgO@@!*
CWn'4SWQ
6SY,[7[L 9/&08!1V1'SbP񿩳ow"M ->,B[\ط[RGkŷy\I&/uu-mss҈U,rSdd#eKJ Dx@:+_=8^%Nt8?8/qt|xΰmM[/BX&3q2mf'
_yNM[h5T"ef\u0_!7u&E6AP[	MYq0<#O-|{XIu$
\t;;ы,-YS0neA"z
DUPJbM`䔗o;wâSUF=+HӂFNrOAy)Fs/T\fY>O՜%u/LeD	ϷX[ũÒ
Euo6쁭]SߪDS).-쨂z^VކL?0Sq2$4V8ԡ6MM,IO2꙲0e^\JՐ
(7PӜf6PAMYo(g16'T$5[d؅@\VU@Z8	_M$#i ٤ Μ%yl7?$G+hB>u!W3;8y|Ϟ:.lH+zC̯Z0F6QC*^U{$3+dFUt\==|χ2(3P
(3$.cc}tzTxV`WMgGc++FVTpW).>T~$eyaL/ƃͧ.|-CZhz+/m,Vd!juPՐA*Ol(R֤j}4	Gjɭ(蹧i@1s/I(u/sf{q-C-C`aga!%X)뾃.e={ذzk?z?N:qH"HT1,u~7Is S߀n@>V
cF,
H"T7NhA
u?Hkh'Lq0AU)<s"m;Uc" nn+iV&⺂io{m=9=ow<ݕ>NH*yM^d8oO|a	T^.Ů
Ϟhwwb0dr3@r?*
컁G^	at-Oe`>ƂYwb+'Ԡ:[Jf?IU6ڀa9m{6JWGi M)F?w ,DQ yx#}xa3O 9m~;u~} <U#߆=p'Siڎ8 z"舁5y>o';m20Iܲ*T~xAoRx*P֏;|6*jmȽ (?%b%\[-{*#+ i`7P}Ff[\NOᄫ>[1?g*FYFubJo;ҝ}z@C6qGkO19]!=ssgE.vjza^aTZЪƸKn刧6@zl*)B%}w!dAHhWݪ>|1H{nđ/:{8|rANLjse)?	Yqz"KV%L+!lqƉoъ{Ӄ'cQ1>\֤P5o29
PmQRJ1r+ΪEn3(DƂoʇI2ױsg#ܵ=7!9pkRU)NeP 3k2%ۯǼ!䋎.ޟXMPBD }aԼ]`͓rhh[:UB"ک
u=EHڴ*Q}htCiǇpu9Nh9Jacʋ_\/'1%xh[[__>kQU-F3Kǵ&A
7EPdŹ=OX9.=h;ARQxPX Z0
+s<80oQnq-`o
&~Yu(^$4[O[z=A}{QWـV:JRmzݑ	ًW B|;YT۷h^9r V;NWAG[ڇ؁1ٵfsF1$<Y2|PS^'ɃvCJDly$LA#9~4 )=H҃@q:F=tjb5LtzES~ܵ!>Nn`cG_DG}c5boZ:D7KzhaRY8`roc.yutsF'o~
E<ynf.N;;,ʥ|M@5-lXhHOTr0xEX&ƋlFRxAtH&#a6B7_n8MhfB$l9p88Ep<
	*5"ڸtv-$*ްcHQᧆ\F|l;N5N <9 ,!
𪙮/}C(TʝYr0m	Yt<AXNLc~	V05BMp&c^+-gT;MWt8ңL=$\#Z4+U<UŘK3UgZR?FwZt:-=]Z](ޔ"pq[l 0뗅 wq_yKVwšZcTkCaSJUj9b~c:@u/PEl"P`J/_TnнcdXd3SSC< xt}߉vѸ=9vZ;Unneg#=oӾnuI [?)U-1|OzVz!	6.C҇RiUem33u%l/f#3i/J&/*o
_:mdT1'!9&e7njIl 7]ؼW-l֯ꛬ0}vK`xUS߆ml6`{`6E,fw. g/,L6%K/VMfRC~i|7Au9g^_G[Hƹj<:8L%*m*vEOPbd?I6.Li`sl.E:b%Xօ*I)S3ֈxckJ:!}s@7;яpŀWUiK)*']n.lAKLN9B4IUg1CV_fȁ<@fnv"3FMs`2y` Q2hMo7qZa4ZSOv| (mfF-&Y
g&*lKiv4]&/llȫ7M?Ey()?"KJQzdWD~ůġkj-Xkf~t O#҅&<{nꓷ+Q_T0vECX, @$ɨ<mUM3b0 HYz#Z$/+;WFAD>d3fG*pr:2@/^iT
U$ `^JXO0vX0X&[ŰFgCONe+ z;VU`v#PթFֆ\`%lp'~a2r|k%DtZ~Zj憤ߟ7LoB4K*ߊ XYChvupB$;\9ttHgrZo/Dx)#X⠁agtj*r-Bôq~c7] Lx[h9ldD#/CLN\?H#ciQ?NCg+c,c2,cԺލMBtJ?A	!gK6k#7خ7OxdE{OnLteǙgD5
wV}jY:0T12NyJ)4Kti`C`R`r[1	ĳEJbдf67`C|֛qگ-x:Jd5l{tG7|S度Zl	S7A x"j?+̬	' vSAD}ZBț~Wzpm78VW8߰JfeiCS7aV.27@,!VaD,flIwz|8@1}sH\DSֱG$A:NJ.LXծg;ƹly.6YoQEOZ;>9h\PJNb-ZT#ʡt{6_7k
N͖>v}X$lu2<aіV֔F,EYv]0l'RRztrzú
ԫ*X_[ƺ~Ԙ5\ݰXWB4t(qS!E'BGAt_޾[W?B=FR=R+[εY߬v,%U#Q!G#}ٽ/A$AYY.I}	r4BG:S:Xi>̀}%cx4:1&3GDھܵCʃ6[ɡ)6
SmkOg`U~ƬtAɦx]nRd5g,Jמj I;}tasɿ+rlW,/~3r0G:TN|Fؽ}>黗!}WpFob'4qsKQrz˻4N(ϣY\yu>Zԏ#7'ouuڳn#5#OYiirr?{(0tv4WTe/?E ARhߑXx.Pf"13?ːa6]*kޮB9t D	:E?rv
&.dNlQ^BUSL:%/UbV#pD 9L~')T"DDyqi8}LacAY돭YQzpTٟ}_H'AWO)|JѓHEXKH?PߛT#;`Vh `U$rnZF-nF˦IƻVPWQuCN!dfGi،8TUJ+n&2 %lϬM&V$(4{{y%mh('1NbPqY3)4y=CʕqջQPT>9?"U{XʖO^Nd(]8cw$6ëKR8>0j_32N紈0oS-XޚTMd]dU` ǞɈ]%dNi2UuV"[%`rIӼfR^rZ#I1V{!
ҝP#M53>lwVh>? =uޝ&7ozT6]]-􆬍G)~O旒1Ϧ_UIz	=-5H;VDpY9 ,_B|2!TƯ?NA-7Jk(nI~U֫d~~p7Kx$8=DJ3 :!X'GA&55z8\3QjI0M(QOAvv8>v@cX/4LNG1it^듫t8ydCeAT.|\P8wr\T`?m4sp./iәNeYDҭѶPHFHiXet`Z$gj'5şɺᥒL&û'dZ
t.v6d˼Z'5t<I@y}2qh(a$sJ-*aը"y
])(m<NİB/!	Dn@^5{3Ud؟͙qc1Vױ|ACkTQM vU	٣(uP%Gu+,ݥ磈y2QZK	_X<+|)*L5TzjyC@A>tsY
a
1\%q%Kȥ dƝ̒i^84|Q,Rrx\
i=_һq2Dg[P	Ő tf90N7<{i33"O`9voF&^v<t1|6fOGǽӏڿ^616_Ȁ5Oe_Q:cw
1-݂^mD
lWWͮJ|:#]iA=Z{B;VYJ_(K
4qe&ù$G}p\î+^KrG:qɭ#>Xȼoz .Vb*%d||
_O<IU?sh!q^G.11D%52L.	IVH	sȽ(wjBk4wUd]O͉\;2*S'.PD:IJd)cyG.2Բ@c\(t-n~F׺."xmMzeµo{ۿЍvDγd-=Px@Lob"TIpAG9^l
5DYyrLZloA_nDftxo},kK/V,ґj`]\m91ȷKU4>g׽Qr>LqUϼ(?_+H}!*YM&sp|MW}rɵK0[녶-VVmcM?j~>i /@[AN53S|4
AP
;PF
0u:fvGn=';%Z6VǒpɀliI$
{JT*è3"'&`ziBZH47<qQO/StJy?aWQE}tʪS]'۽m2zp}87ӿU_O?˂7GknGxY㽓G:Z[ q^t`O 
R=J']P4i2ɱwuwN?z{?Zln͓
R9=+1ђzv{o'w{E6	lywtx[Sxefi@zίRFwxxѱξV<j
	Y~]3᫵?yjjIpFK= wk7yэ-ltmk-}~	lq0_(CIkq@C&ˣJ6#z/V.JP:xK}>-ҹYO4||3!61D0ߑVr֛1QN<\؋j[|qHpTy`)ȎEUw|wU&IK5b1MB0xOva TB	HP[1tGb!n>e^XttR;6;UhD/ȋ."ȍNx:qz<]G.j8ZGez`xaIKזۀh>;<UzRI7ϴaYĹF6>5iss,aTL}w"4]qM5 tzGBH臍*2]=H/7|$EǨ?A)|bMNIdi%[iDzFoh,$H, FXg7&ƢD!NV0Bk2">
/Q_i4mH(u@%>.@!'2b=F_9adt;ha_pdAuW<D&2c[LGQ2fW튃?lmF!я[/WZ|w쭿TPE.3ѓ?q.]农@֦nopuXٲ~W@RGqjACR'˕+5ھp4|8ʢ,OQ
1p7\NnJ/%	&z-io=.2@\l">xa'hh#tlt:d/`iivLs-OǅXBt2&Ȃyawl=c<3/p~&|cq6ۨ 3uOC^mJtbbK/ʒoΪ>$mvW/U );Q]3 jf3PVKh@ώ햔}|ºm7 P{qW/|X\+:pt} EsD[h#v..&`u[0Ysܣa,7NNK!ͭea^H!Yfi3*Dw"O+k`??8ƳI/f]AhC
ՔCȖAw``ܧI*Ӎӿz/zEsg< ݵ&_vUY>#farzɥA$ŃYZ:oD>:ӄx0ϯ[~A	gx OF_=Fԏ+T:O2g<kϠrFtq#ڸi: #!,070sC( m_yxpc+C]hR!
 +|@1f.(5O$5]؍.	6f?AKvtc]21]QEjLX:09|1-#'P$>brs		H(#9Ư2̙*KȂVXMY\9ƩQimk"Qb?fcg(pd/ਜ"9>Nt2nmrN>P[hg
wRz{1}uk%Szms{`P<"W!nqFEUj/Zn9!=O
+U%FC1Tow^"z1+ČD[чB=^j6"rf,%E(}}ƞQ7Z?`omOh7o//.,JqƾjqAp{>yf8Nf;!KWXRO?wQH^/4a6aʷ),5.]ʖ~V[8.3X͟ec/N>SC(߈ؤTQ?j9ۏ.mAr\ 9qmAJa7!;30ۓʢYC$ԛ64~hG}]XߊXxtˡ[ɡTp%
]NҙRD92d*6dr#ܶB31&)Q[F?߅;jz᫢p
e(Bgx"]ʜS~>K'zf?0N&i?BwAu<S?U2C>wQnT).=l]v_eT K'üWaJ3]˪?3X/"X0I"]q7( Z:8LG7_|fuJQ2e8=+Ɔonm6܉rPeX#vFcQlզzQ5z;)v3W^?erpzi	'fZғ}βFو#
~6Z7=SB~,-lv`B]D]hp	Kٛ$kun/۶l+A$U2"Ma]_kiJe%*z8I9NtT$~/R
%jE"O?q8r:AhkB`=M/pFG50dnowc)><:AQiN.jtcIf\lonJUҠ%o`~tZj(w=`׻Dt"ֶa?*)Q1ןmIeOKl5(
699-V&괭Y}>\|]zyDzRQqVfZJje2BY[CLQxgi9=RzGKhhJ!De8fT?$7
1Z@cʃlp2O#Ɇ80BJsY׃j$jB}60?9Ov?QDJ[Q\Qn}"v|MZ1<D^o@BerUIL%cExjxJt> s -b
 j%Isx|,5B:`ҿfs=M8<
I()B-@hvͮ0&12 =7*ӾI @ɍБ7D.*Q`FɽGHx"Y JJ/͋#U-KA;ٲvbi\/4]~yEadc`'$K/R1nt]$f>̫/)EՓOGҩXA"O)yRn,!K{flIv)yd5|]O-%",}`>C{6Kt,IU퍺<:m;lvO*_xYPTtI$Op\|)lor4o+WvgnџFF: v;8:/\!X}]TǦ)Pq`U8=ؠ&NQW1iPA',zd؋kE7%PZ71B9!9OaUu= "<~/e_m6ɉK9؈|UcHsbYznZuf_t"MBsYr9_PB]i
4z(,]ߛiMfĢ<QXsWm F#qKЋ/-f9S/5^!GxJJ?@o9cbv;t%x8֧Qp*J}hSS|jn<)4,0EAOp4K=D#%s&":_	yza`.jLd*b/pzz&>)hiJVqc5X1ű׊O/ۈu=|#"VEPQF-4NxL%xd,ŒF`!Ltq98?$jS*=9ڳ
+6bq76'2r_޹TxFjl_`udL򫱜۹Uq)hTWTi{lqKީj=UK×`dMꈪn/N|720O®pߩF44ԿO%硞|2w;[ د6cl䦎 V
V\aK!-,챨4 v\uo{';{{?=,sӷo,fhwt=?䦂|{`w;	Z4
	un3}ݽK*EDPB	尀,>P}"SB	^X?ѝN7
(Ԝ6}ٺULw/[w8
>c:knܮ5#!ZQ`*;6ܲzxp~';C*[[tpRTYx~ޭ'w-,i%wT"@)Gǀ=_3!$WZjv)j4/.U=LmPdp^c	2~L?+j-.j>4GWvaޯolx䋑T~{F%>@D/:b6	2|LFBU#1.I`pU9{щ@,!T~;*h_u
O8LkCaTx,VtW2ɔ]m̈Q}͆1@aN#7T7$?[$hoGh4nW1lmO
[U\RO+NGf}yzj`^Ρ|0bIG^l'Q>(B&FJARPC}JFQ&9I6Sb童{8'2J6:Ew^j`%<Bˠ`@\(8:RL
uHk3(7ufi#rDÛL|i	'{@=gMvYV%̲aR--@RQ4nuhC+'<?¶tҪ-4]p|cvv?m*nz6コ l>p`~d~:ot!I4;L,eבy
yb,Bzy[Il<b 1n(Bk'<-rQgP]Z}]5c,{'re;,'ϯAˍG.-P"䶩|{I*Hs3&t
fJU1nR6j9:2P
*acn?SٛlW?klPK*iַuyKlt\b!@fΥ͇T,u^<nf[~ܑnqBalu^0Y]7	 $U%Ű/>W֭i|>u{Ș@->*D	"##e6a$Vޖ[,l~Ga5FA[~`~ȗ3SdXn&wq:PēBM߬ES K/֎*^n+/=	;zlA'KtJf/Ē,NxZcF-}h~Vϕm^ޓj[+P7;^czb=RVǲQE#Xϐ;)oY ։_$$(0GV*$ME{5 u!xLMAF# y5 +5޺2l9z˅ӑ}ƥ"fp^axR
eHn]Pv2<86'׌%fDOvywHjjvX3ҵa@L5%iEIj _9P"~v]5cuXn]`nKpABC ۊ@և;u>#fw+n83É_&3ыL XLS5s1T~*#w:T7b6fnȜ,߻#ԣ(rs_eX;]~,(
kz+6%T[Ք 4 R)`=,Y4	~;[LT$sa MixZ$3DJXvt!.
9bcgA0; ؂ORl@k%&e2Zv鄳x؆p@t |a>&VBY<y_BGY`U-U瑆Ų\lv;`;N遌5rEߎ֮gn5\SGH뺖OFT~Dk&o53i^W8D?Z8UnuQ ,QpXɖl];0F2oǙ3ku\PV^	Pe=l|:BkM25z%̥˦+/_l`Zlfyx H HjZ]n拗^߽(5_u󢣯rA!`_aY9P#(f{Eeb^zGb/#%9p%=<F(ws`4Co_3{}Z`u8@|mi"[|~Fazա,4$sTȑڠa-{M&b솓|s=u5@4DCf:Ě`|JK6xDt/ċˤQyW&*n4eaǉ 19c G{ԆA5mO;q|sǮmM֣\qXLB==aC1cHJ>qo;G&u$}vOǷwllڝzx,Wp^7dG^Toc,C/Ţs1̡"a55@v-Zs9&+P/[UOcrs]0_*Jg/Vטkm,.l<묧_o7**3տBZ§T;\N3piO]ZC,{c{#lU@&97xtB5Px0`IՕK@
!2bwQp§a݉wF]A, .gßqAl}YL]^V=Rε~\Ճx#>p暋?aFt	ڼ*=$6Zwg3
ʮLw4
,HYM:T\FE-bwVaMr
K>Qj
:f})P#C4WK>r()RB4ѹ $Yd_w0{:6!U1:5>I5 :SlJAv&h?c!IOvkx`fA?KWjR^7
w*ʦ
~#I %@25Hs001d"˧ao~=i,mDGga8R\9AVJ7N{N"Zڙ5LyH2˧Pطp?̆+ ?ߛʊ"FzR- ,D Ed5\<$o;+uLC%p>?x6ɕZL/ֹMbTSYS`ULۡ$˩bdGw5yC:)10Vr"؁ŎZҿf[G8V߹"(PUUD H3M9sƱp5@
pvGZa:ٰM;,yτ
]$pnULtaTiqu˜`ۀ}~2]ޝo 鬳9p! NGe
*nB(O&ם&1ekR*l:§:Ca4OB}b7%U­-P*e.?;jlٸxr2M/Rѹ!Wabz*x.5Jj|/c1 S_la=)@qEiSu)lYi+`Mykҙ$n=y B}yfyH
/܊ɭ|z"Y6q;)$aInmI>(~+Ǉ\Y,喯{ސ	wnckGzrds]\HEDVBBYk.q汝ڐm# a
.=ö-KKn^TUI%|ʫ-Blb3gW0ppi"{Ha']e'K:X[mtm\|YKOL964xkr"!3v_N{(M½ts-m1۬&o&`Es)yjTI8~Y
^ 1ߏ'-(\ARwu7q#Rxt_^^7}lódY3?qUzMD"!YjH]	 (Q1O%\)&VQSpm.jNEy)ڦ&	&)=FVvSUZ>¹[6eWy%vSږrxi7Mn6VCfI
K?)
{}q*C+`6:&׶g"26鿥A![}ؖ]#l,:V-==^O9i}f[~ZۦSg*ɝ
ʙFČ7FgP'ɥ6&ST=ն~1q?
zM䖣[]*P&B[p|Q-7Oȫ$!;4'@lCZ\2?_s}R[HF	W[=ա8܍b%@KmKwC:Ɇ38~h4?7.<*(ĥjC$(bEgA`<x#F:gJ^LŦE=7bS*>)fMBі|LԌ[q|]oN/vAbҦ/BܛvLZPH|,2`:K-~a2Iŋ1{4+|ؗ	H@fN2Yod"hj|9+sC60:H׀9色Hx5LbG#0?&3ixb2;ǔavbLWEs­42?IX5rN{`' $gY>4tm'ͯeEHS_a:Y8Kld"ZՅ}H:KM+۔-'a6WS;!0fMQrcaMMYmi{ӆN+-)Tx%:y	i6n=KKV˶Bˀx^0d?ߏwׂۃu7%Z{T SK2|l_hZV@	4YUM[󬕴 k	Ms=LǓt:|kq5M/pE}4F\V]%W:գX4IQ;?Gq:W+dpWi,_کG
p^qyhza(6=NWrU59PIKo+ӧu|1d!;dsp?fۣo!ީVF
ʡIsMMW#Rq]ɸzq6@QA|q굗N;FUDk{)m`c0OOg9P͎q+A=EdC	½2]IAՓ9Zc\Ms՝B)	2k<j%F(i2ʋR;bJX3ứ,;v qHtV],Tu3O];z<۰=Gûx5@ׁǑR8i Gא1v,JN<R"KV<s_	V1\rc@d4]}*?"-':Pj4XmލY^ZQ8}5CCR{^35LD&8wqSt0Ğ38{;A0 0eivJ֌ױ5kV/+*B h-xQr:g"DNK{@ôY@[NeZ\p8s&}HY⠾2P@vhqduđVBZ8T!|zkc_]I^͐U7,MBl	E}FB[)rƵd9xkD3]i:6_3F=xcyIᫍeAviq"b#讀ҟnA-7w-Z9Lc!)!.B>YhIB/LhƗ=8m
ԷA/zDke(i Rb7(LƦNcL)[_Wc0zPʫOD.ӷf+[ Z^x9#@bQimmN*'Kքj=l.Qs<fɔӱ_+_/)[Yպ52t d8։g˺ -M_I63wF:|`Y_VTyh-0oZ3AAE}{hM/Qt}ױIMg=)Wo-TO¶Tx>00\X:ʗ?GNa/b|twp2i9ҝǕ~pnhLs_k83"
q{[byz||̶*
}^YÅ&i޾P\ã=ufwp҆f:zH{pp*` Rmvǿl}oW#LD7I7PlC碨Qu1ٹJ;{S
oT{]R㯪^*{MqrH
L)+1Rw׬Wڰ[v炯i_q]-#[B}[[lt37v{-7**32r^Ӧ`"$Z_5Mui,yOU! 2VT(KEZz[6ڻq{>YdNwY!I!Π"	s{r^\ubWa&ϓ6)ΕtBwhd=:ד72K[׺K|<<7#nW/#;x.kWcA^7$U~\*bgz>M_T_]{◺&ՈvujBUWQoY,Z5(Yoip-)GTg$#7P#Q+F\E}+m!Ayl)K036%5CLS)~h
K1lkϟȵ8.3R{*1Ր˞	!ِMBZ6-PY	g8GO)bA0fd\I JsxHF:Mx(#%&ҶN$AҳQ85SMl _`}rB5L!]P aڦ"hS <Ok҂ؽUZ}.~RDT;GL(p?i|:;ELjkK-+.lgMȭ\hY@|˧{<5յDl.6J{ߗ͔6eq';JGdudo[SeHUզRn(Nqv+޷JVE)ɣ@֮Bִ;N݀N$@/f/>x5M8PKP|BJ^E^=MOE+%3m\!U+-qLoy1Ov[yq9ZI|0N	WRd
x
قKC{	(괼4aľ!_ŗ1re,6u4־(Kf'%%M`:TdKǚthY/Qʣ q%AC }fAO'0u3_ʏUZE
y6HqC(BlsvDY54o9eo0FTO~'ƊѹvQׂzv4	zuPEGV! :^'¬ш',>*,؟d2C7O;ĺbͱ
3lFٴެeg 

b!4EZ`Ht<AgյU3,Yd2Ax&&MC.Xuaj!cE%fDZsExR6yw`lQd! Ba 0罆q'R
OhКR@g!qpq+"HU+]ޥm+UjHk4Y"0S
=[*|fe)!Eǭ+߿]g#J&z?ȍcNQ!=chN#ǁlx"֣  B<ɳ>^;J)ډ!&! #-q&uL"+L tKmXzlIZش+҈tVEm^ݠ=>I&Cy"Skageڒ6
`g-m*=7ٍ}S(bVjc`!]qOk4%K&;	!n9oNmR-TC$cqN2dSnKo͌dNu4ǭY/}'9+W5EK~}3,khsYrf!8Wz@`Q;{%#g^oð6dζŭ>u5󷳓|(F@bsN^*tV%XS>>,PnIA?#EUKHExM{N&̃&BP8mDjzY:B3 pU FB(%
"-݊M}!BҫCn=C䙬=Jbmɵ&.fcgs&/ąm~7_%QX0CfXO޶3LMg\NwwbFwEQoѡWa_<XOhkkѐmgv2M@u03'AiI䱃D=^VU9U"OijiuYG6*nd'W
Vњ3 vd'Y!'JI-xYѭnAW-קU7LN#lPKƚ%xZ_[p)dBql-V-T<1M1$+衳)T0+W部Np-qvMv-[|`yz"|BcRI⎂%<QQJӫǵ,UX8	IMChśKvVL+_Clww[İqBmgwiVe)#+)ix>19ת,ilR -Ivԩ7[&1mc21_}/PVYE٧R=q":7+BTA"#gݜFA]9"ٓ{|X\BC˷/g)>.z׊wQȕd~;X72_{[Z]ac&[AA4*}0V:ı@)_~mಐGJ$4R(LCC F0FAs;SKx]¢ď{eGk"agUOkm6!Nqts5IPMߚa$eaI ds{NqAYkb1}{ gzssywY0Zʢ>[UnʖX]<)ԃ-XOc<8?HG6#:-:[`=NW xtz=3
:VN9%K͙=WIޢ^וBUGϊW޺;GC"y|Y䒢SXմճ疊&_sKNi-Ydv;hBK	hxP#OtTQz۵l=yYT،Y^݊Y% h31(;%?@)X1[S_AQ.<w!ŮR:cl/a_|W,Q^TΒ*=	݅~XPPօ%ǴWGy.T:ߙfI_sIVZ:;mNy:#ŵc>UR9WSϑ)Qˮ#Y>*]Ջ~Qdcw :|CY)`5:ue¥kS}&ߝDZP!,ydnd`bOL?A=b hky]Sj`'^.~0@2XPBL0']NA񕂮ł`W2yb./8
,fBsby$,'H"uĠD
ZU0@"=&xzjhlT( 홯$&/Fl)㥾K-XqzGAv%SgSLzîD	}>y:4#114o[os<zYg)z aHëB9j1"w	:Zn#I& ں{jTZHQ̥kH`*4GP!Z }{sOw]1/uy.'m𖪵Y?Am%\-TՌ`FH=B=p(<{[%baud%pҶ_cm|?Ta
rͭicH&([sDf4M̼?myS|}ٲce}hᇁ2ǗJ/frYP3k*cHǂY_ѷ+mDe4`BͥI-վlha&
}YNgɸlW>Dܰ8ZCl$V&G*B-{y}`8\@,ʭ
o]_܄KryUdg>+/l@EޢBB;WXU49Û/2ݤ-wYU	sq9UfQ£M+5&u+!#(!mO)|=ة%9bpbyd{:ݍC z-PH6!*%6YSi\{JLdxZ~B'8aK}LVN%ԁ] CUh/]5/-GMٚsgHWUvomGB?*$htÀ(k
IuI'S|/Vg#~5KzTj9j$ D<P-U`Tv/*^M"\9_E)ٮ^Kl|"*svLa~6:}Z/zqOٟunjWO밃gMЂ˦-˺\6񐢁j^E鲶(PjȟC)dCԳlwp\wX|4"3ڵwvzGwﺇxV}t}rğߪ<BT?~czU{a]e|_鳴9.`XzߣP&o:;/Znz
3*HY.RY!Fa٦)`+WJh^Yy'жM\OF#0zƳv҇h~.
JyZj%?!	k8Gk23^38q9vV:-c/ݑD2|*;6vw:>Jы.TP|+mLrGSykO`fg6ąm;)xiם]x+WV/h9J]UR8%pԇs)md-KhFW`'o-+?xlCE
¥FTH-*1;:? ᛇ޷k7
~H&g{=@g[dyF$T=a|o2js	;{.m*)KnwJ$X!57~L %)|i	Z-PEo&&Y@Qp a;E&݇0<uz.%$}xpS+ƺE.8ASwӏ1V,IT$OɤgL%Oz+otLBje</+4HO9agX_qEC[}(:I~/ga\<.~~P&Ӊ<!{kppjp8y⎽_9.\D'C[]E+2<X[	Qt89hN?M6/	L%B=1Y{@^<}"
	a N7	S=	4oGcQ\Z.R4<exm7	W|)'(g-4uN')PPOq6	DUt1Mejd|nfNOBmxP6z[vLyBg\k[<[8mMõo7ؘ#UC׍	!9|ɦkP+짙Dt{4O-fEN\?Nl'Bm]^ǋNꤛTL1FF--
r.[%ic2u͎ݦؠ?bJ	sc%?HG^Jy>g֟gսDl9:ަD:YKfuE稚FbN`fRpDcq{{YdcϒQ?;F2Uo6!̧x$ߛVHu^˩##t i6YJ!^f_&h$2Y:"x(j70jCop>VČ5a"*-].i?H6 $.#rK&4ȥ8q_?oӖrD<@NHb	}k&Ah@: d1a Ѵsu٭db]
A`MBdN[}![e=C[%(kH 狮jQ.Qޜ Dxo)jY={:֯VPzi./El"9	яAAQK>vF#p	'i#iZ`ζPk:"k,Vc9fzfz1ou/@A.dʺfH].tC)-o;a?LNhd6K (#[I$5C!%CHk
$9ܚɢ~4}+
dbȏ-~{=ɎnC;P>DZn.Lpw`J91p
p02cO~ݴ,Ui㝍($lg;ZD9D?Ę6)op;up(-)M:]!6 okj-H_ml¿ az)Ʉ)fW5lIlwg\neUzm󚲯Vt\4Ko+v":ҜcAk>s3M;ʮf*ѩ@E꫊{)mRng ΋1Iû	+
DXXpS
7jx$E|Ɂ<m>1yYVKJ*0@&TF-kKYYM4 KbfN3*~,UL}kT`Ԃ,uݛB
6*<ׄ|;rb7#b6HE*;+k&%etBWfOf=1M.Kd%)z-2Ʀׯ4l]پUY%:fKH[9Ti$~Uvtަ7f(^uT~i{RO1Eɗt\"=W/K&DlF̪Fg\>$P8U(+s	6dBK)\Pځ2бVCD^Z*vFѮr@P-|U,,IDwlJPpEևaGK'fϱ=xpϱ-9OjpWGqE|kZ&YWizVӱ~GyNŪتWfNhxNM2aZ#8e	iv{$Qmy #	#`P̳.Lb_aRq5#7'gdJYxru~7?Pti2HI;]zDtmtRXgw6!aexu|(v_\)>q4;;ھ3TRqPL>\R.Iɦl5gX!&
dK"cZgpQ?vvdqhPs1rGtO-j*̀J(m[L=9OySeq˳*,RJOǿea'(v\c`lISTiEm6{9r*NY@Y YaՆ9=|5~n+VJ3/sӈ
	eA~@<[o$
Q=)&/Asp)Z:Ϛ^.Φ/Du 7s|M>}BGBDد]V]MGzaCJT}('<Ue&Zx?<NMXP&% 0o_`P.<$?Ls=)M{cSY$U$~%klA/?p=NXz-ҙ 8Xr[NmbS[EDɨ4*GÐ~P|a`3Wu6fFL;bMEKsT4u*@9D/~8>N0B`xr6v3F $<rKcq`Ŵߨ#z]>Vmsr۬SXYQUZuPCzQiu//]MT+%la+6CmfKS3"ZVWy~8FzK|vpwNf|rk)pdB%fOm /KjH-E%=Q1x_N-ɿh/DTRPr`FcɎoD>>7#	^	xVmd>L>Y<^,x-
X.3v Z%O=Y0&xV죃=dSY^ 
K2Ǟӊ'B`MQHz,t2BWCe(7|JP"wz`Fu٢hy;NO,YIV0I)6y{pF_y]:1gkEgدN9{!ylT@_)R/x,@SN}VQ@tT<V[gf]ux]B?-"U	dkt
o-󌆋$:(3t.W6ģDw5,뀪~V$_a=Xܠ-[G/=ӍjLWpS2H;|[xј?6u 1Ho	x4閕7r |I]zmE3r6xB*5=xN)2ѻ\ X+u0g܍O޼Vک?LW槎Q>wmUwE{hBw,}}Z_cCMYy)35Ym*~x8G?gsY^7'q򚯶\ӑjG"ԉכd>SU'?X gvC*D5O rRx`X3NՐB|\gC!ǣh:G)~ݮ4_Rd*ѪG|{6Xy{X涎`HD[6JNBrm$ <D@w>^\E*PݣR]pIiHQtL/wz=ь_!y<..̔-(˹1فT&Uwrf͋,bgIaQa,zV~|>(4<M$K]ƿlOxz4LCo#Eڽq+dg^kc.YŜ0ht#kZ\FwnCΩTlc:Gc>[mpdkZȐ%u<|;Y8Smt-xS.TSBܰי9=He;g?â(B_jv.$UŚU wkඳ<L6a`GGmzЮn\K>'c#{NpC;IENz,4-yж`1[->l	pTfC?Pg)f;0RPEKN-pz6j'Qf&.hR)hSu7[ѻ[ѻ'7G=<w!P&9u;c\*[srA3@>5Q~@Xwhmn&Yj}gcϙ!'|p$1 
~2/%D)sQ%zXra)4/POjvɼy99i1Wġ<̛q%C܅Lj+,EpYA(|ϱg5@\gu)Eܱ!ѡ^.묪!Vx+U8K!}"W+YUt8q>x@+')A
sqP8w!rxْ&cβ>gG |j9n!]8l;hn}41p`Qev%ޙif/{4"'SJ%V4;Q5=MǛ@;{Gj)
5f`[U'{!_<{]\GЬ8.լs2M1d,Yڀz4)%#ǋujSQD>0c*@UM~ϷM}ϻk+$T81J,օnAvP]ӕW~f?7XXݰA:/Л{2Fm[e F.uIb`F1s#dE(XlABmW\
|r!mI1Ʀm!de$Gm~U]# *6ŏ9Kgf@uQvS^8"pakt0̦o"U`2ڟ)dckްdAxs_d(fi׶1+cZ٦$HEh쀱NFOӀX}+ lڵ*v{iU]5D\EF1Ŗޖ£I,Sb*'Af}#du-/ĨRŃo}|DFzi=5@:]>oy6%GOe*]˙L?C8VZ}Yjsл[rvj"'!J"c}vF5<jmevna-<05 gj}dk%kq	ϪZA5k`Y˪;#.ضjlc^]!zaig{pto7666;>U_oUAiJIm<OxJ}4<q.E'){#]/_/ih6Qa(g	ƣ@xpqONұfk^NYBx}-\&ضROJXhrȂC3#
{)r"Jqi`phA̢	)ʕKgo5}Y!jnZOC/.hRVy[/-(f|ֻirL=ϮalN	˽=擌`5dZ6ab謝Ubߘ}8ί'Vrr$s~-I_Ɍ\_tRA'#VJ!m VgbYWnt?iqt&g{
Nu/mA(@'ʡBeCI`I/*d=FmWu･k%B̨?9;+`mUGWwGRW0VmîQiOƘCJw
û
S=O[S'Tv*/V]F2(],9 |LM$eeMcyfbO-Ȋ;>Obo{wO{ﺿ~?>A읣%U	/PlxP(ݓ(A*>P
;Y25 4 Qsk*Eb=YizPRӳ!l%<w)v'AS o=
cz\KFqT\c)4\*s?a:
YCYI;bqY 9xWꅦ&ԗzt> i:Ȅޕ>KR+'Uhf}jpǻfu~V6+[o]9+Sʰ291	41nM9y<3MERW: ӱ' }I3GYVA;C8<JcjRy.Zr7z
7ڦS8m$lF*7I|
p~SV)`QBFhn'yB5u瘶f^@kKoPHac{o@{,͈"O7#3e2-j֨0ߢ8U^{ç|{mm/׵xNiW: xם(od";(ر+$GG[䴻KqsmOfIs9ԣ|<*Z}W`~=倣G8s;޴B[Rb+/8bϺ{dl,جoN`v/Bzt80nm6kDul\m:߲EP`:
Tz"08xف?!_GL"8(޸ts6;IE-ݸ-Gncѕ{ǹK_j.uҗz|=OTdx
;R{lV+ly^J**rsxd7pDTf,ڸ~I};w{'B?J"Puc2*<3އFX7=ȽXGIY_%,
ћ1O}[&P:	#e9znA~$fUfR2:@91p8Hb-
)Y%N2!ϯggVf^8(4N&Qmg xau>Gm6#	=d$(,I`y+5f=?wH%yNiS`1'0å O 9V)R![HYF-vţzJq&<pxm6$Zu)+`~be @㭮R\қ3`uk'l?pAbdW[,t:͎Qy_]ZUVfNaiҭK\dWw1bLe's&0|Et>8^H}Xbf <xΛ_Y\FQ$t@l@jq<ef/
>F+zz{AXhY>āW',s~nYz-*gMO3KEUr_7oѪv#5[C-
䃋-W}2OSss$~@C]QeSK19ǓbM.e1Q6"wi{x/ ..6@'j1d10m+tҝLtAᬹ
.7!@ճc]'[e@{r ;:[!u)\*L'݈wӂƚWP{u'kҾTos|xg`>Yr	znQ5mL/j/.#~lк㽓.ܗ~xw;z7g' DL5ã=8{3}mF'o~^F d]&P2Gx=CAD٣'k<|nVk@g
Pi~.|9y$g]: B!+6yqG.:F'zR.C2r*Ye@h*L,,.֝}?0[R˨b;].uL8w'Rډ1yTP0mfV4?/梴vuDvS'/*]Q9˙NLSOqp\ŏZu6m.t>UĦIn7gvhgcj]ԫ3iwNHMigjV_֛wmkIϯ <;X²a2v!dݐd1ò/aH^I0۟sea3Wv-U߫n$[;PZu1h-jy8BWiRͳ1^#Ux#_ǳ-]aeFQWKGy5NJ@k7b<sqQ\D@,e~E2ipq^MqlZHQd6
\wyK ~_P=\7zƵ,<ެq?M&Oج	z՜.5H\Y4yI_UdRU_Rg$QfODE"T0jdPwM:l!oﴕeϔocZ6mM-tx'?+U]a<mB_Ps_SqlPcѸ⵱)[aG?~ssph7t:]Wk\;aWΰ4SC
n{}n9+c7K^)72Y	F6ڢxV4‶>ks+qne[FO8KzMfʾkjeGdV9
G=t/}@6e$D]ɋ&.EoAwY
4w`0;O#5jELQś0Y)BВu<J80I^Nu:ҘiE\ا!SlHIY7aFr+ob
y۳Gi6ykid[g;c$}Y-(%ޗfnGhpۃ,­WP<.%"Jm:kWʜa*}#<th?D7QTVȰΘ{xfM>s{֙4:PͶndݺvn\0*OHg?*gezD?n:m:$
HM;[1Y>d
}WqɈ 1}46yN=~D@BPm-l&SJ;Qb܆sK0P!s^1V4lN`(`iX;!YtEw~M`4|a2y=+K@CLGma«	
tSet7q浗Ӈowubu@"`^*΀^Xʺ砓K ݨon9Ԯ]9)c_֛O|"0g*LsS̋s}yku**\uՄkfٶCtӅ8_yӁxNuxU]3ƚ?9Y	tC/M8Et_#AQ2}(z86(;hc [%-5ָɅ!byDXs]E2devl$[P=gi=Ռ5MmǹnpPJVdƲjTV9G22oG_`9<=o:,SUztm}>0ρ=vBf84g)Tit,G߮1p}hP8fq?E-{4҆Se_ߢ?X"Itv-t^tM",->_# -*SұחW[YAl<'$j)qEk{XB́S(X.j<QBvqNiad7b(z8.T|׿hKUNTvy2ʡ+i'&G"'/_rwV\ӄ(dYFh)^_!# 1slL1{R/f32g5yؕٕNfn~w7,w$
N4),"E\wcPO5[db6ɤA8TZR	aZS.-Sx<R_dnDcZv$-7
HFwhV1+xOYQlҷX/Z\\:hGIπӢ9ƺEVJpU~:P7,J=@}	e(sd'?iz*9!S&襨(Sp :B26"~0삩;ڌќI,҅Xً4zt^")^`g<تLV6/Zy\!O~Hm1g0N i!3#[Kd5j1I-yjJ@n\Q~뉧_V!bVWܖz^q"חT~FEsVSE}!IP^S`~,8@H dF:a՗]Ņo)^+ß>_x9scؙJZș .3@s23U@Ԗ@u2ZFt?c)8Oɑ8P^8:Bxiy<OMe~dZmJ	d#MB&f fAG)Cndo<K7AQ7C)J2?|egoӗo˒~ZYK=l:!9lނZP<c 0AW%'qT;cgEPV(M38fwwc,`rG+\A5_}D.2&Qv3@c.msTȄF9SlIl$gG!fYiKcfvRaP5 CUXpޅimvYh!'Q	ƦP 7E{;vJ<VV#aJǮvő[sORJinOdbi ӽE-dQP0ٯflxN'ZED#^e^
ݡFM6V~gL,|Iܑ'BerVnn2.RU(%[RsO)ٝ6^QV7	N AV_a(ݛAV}7ԃIT-ۭTO=Кӹ@y4O?~,ʆJm֒xUY5RbSr͂`pls4 []Ab~u3D-i=ɗE/o3TƂ;3}!~{!)8:kςhnsűs\9}ʸ"ͪ)I׍"1Zj4-MЇ}h:.rOKqmޘkFC4qэ ym,F=AF`$46nӸ2Q^W>уi3/\Ao?c 6}} w;[?fA~ev֚MO/u؇GUN\*fVmWAӡ}j9Yd_\ "sb-eܮo"	ɧ*w(`֞/15+SoJ@f&GzѪzv9'|oҮ9ӍM"K3t*8/:t}8<GlUzMcO3_zۯ_HK8$7k}rmQe}K'}ZbRn*͡WN\؆)]R^'Z=/3%xwn\Vw0e*ߎMXc)"{LocT=ܳAIQNLS]%ބ%	w#*MtعE(`n /|0`_zjecaէ,y֚^XVVSYCjE.S@F/0A+3 فahBcD<EOX͏ϣQLwZ[{f*KofknLAY\v>*̏ΜUL>;/FxeLʙ؜Do}-wm_lwpPmap0D9`8d6XNvRloN}l"sL|c?_>?`>ވ_iYN4ΒY$N&qɔ"5"q6*ָK]liO||:/WX_^o}i{kocq}xX
i5"#=ví~ikR߽foc8ZpO;!H;{ӀkXԞzF0b{šěSk/xүg+.tD'&H~ib'bHiwϬ\U"A|3172JGJ=M&Mdi#KR,5[߸ t @06);nM2<(c>gÏ}&XX
*nr)&}oU8ef3-\JЋi˷߹#LPA<s@[APxeAE+ R$ϓYM2tB-pR"L* &A3qZ+ܭk,x_c[xnԑfQ@@xqlvMNW^7Fנ.Oz:V!Ϳ_3ȏ^!4/ǿf5<	C<t.r2qN8oJ_M촿kW ;띻Z/`3ШEi}rV:2O;n~|i/[߿}Gm=GcUaŁǣbyUZ!IkYO|	l`̱4rpǽ-LZ^\gUIPʩy.8gʧШcw
q_"еù":w1Lvڍ+M8HΓwf@_J(N)a٤$@#w4jbB(K~6VFHFuBHmiC%s5TsڕľW	5Q%~@NC"=+6\"OICbbۼ5RX+97Ս|QXelԕ5re^_=I<RB$tW}LRA\)/`~9ʡV8m}b;X^^ָ3j3x$\TukF@5.:<5̉fy݊p0*>Me4+FN%Du=$w0ʁGb1٭OA,~Bx0q+	j>-@U%dZaԛoiEk~S|sP%gA2X޵K=:S?GWD$u@O$X-KBP+Lô_ZUj':BSQh(1*/dlR/%e!h5ovЇlHH7h5؆VycI]2>3O$7L]t̷ꤵZm9;ՈJp׾;)J:2s[fɬ6X\	Yvd P1f3b30PgG$hI=62{&B {%q짡:(%O8p%_StUIyGKH
B#0ޣWqϊ1Cy}yn&e |~ymSr
`~Rlڸ{nsQ[M%)Їy&v^^a?F؏x8	~맏QpUŝ4ߣpՠO': !U5iwE;+6u=%JНnW]˚9fH͚1qډ^K;}J
YPn#ݒţY^R3%9;+:bq9:}ieE|mJ{vip Cc};:ۤJ|	<U4ȡPzdԙIUqJD>>6CZ%>(tmuu㰄rՇArC9WAVkKuqNc'_fed(<tъfqW?0E9ITG6U<$͊1+XT]I%	4%:p^c8ly3:o
uk
uUh]^г䵓77d[Jٕ'.aW]K3Fu+4U#+`U|7>xA
9~xc#IՁ5RyVs3,*".;R┙ǘ+BJHPEM+@Gd6*,|a)%j%.ZFj~jFm1dxiQB-\#s P%-wguVƑ&+͠[(Y4ՠ]/&oLj/Uv-t^<{1x_L]]=VO14*;5lJQeuXBGA\4RE~aDկTR#iA,~i5"e2=WC[*s(}$*]<kX괘mUhs@Ad}CJl5_BFMn5U
AC_AZU]w;&Kd:EF}Y-W̖Q?TUc:}vqY%fzW_{ƺ}rXc^1b2'Iv`F.~j3k]rR<4D8Ul`m'8^cZN;83+mΤyk%DVc^|$vOsO_!.D*4g3
u/Ex.e*QU/USr]ET>Ma$%p-*X\rIC5n4FK|tJRB0P5-k񫋿&INUgA1?VhFJtkw#}z)'"; & ݩR{q&:+[(YW{Y*/:X5h|̿)44sq~1@#R4^ZRtn{OWsKm39Jt<NxPMA1Jԓs`ʨW{1QǫdITuT}:.abmgSUݭ5`E1b/.< UDs؈lHG6N0~fd2I(84WߗYN/N-J"OZ$H.M@ $M^i8tRݞ4flJ׭S	^K-\5K˳e:(!UQ:.FȐiR\Bmt8?kG8?cO>Uw}o<U2zX_ܩj^.d7
b#ՌK¹x"ʗj.θ2=֭ƀ(>[ُ/~Xnhl 9fj}o;SƐl_fMʗڶfawl#V:Oyw)6r,Z¢W&ش86L^L܆B_QkHQ$Z
O#Tܝ-]nOgcU!H=ʗsnKTm]fVssf>fi}"t0d=gqug^b)g_
{p5S.M<z<ZYOjWp63|t^j"<	ojxTOFm	C kc{O׭et 2%+%ʱц˘3ymY}zJ+Aٍ"<-z{kwڮo1I	CWkom&4eJ[4,	\D$7ah	]Q֒Ggջ\&#V¨6eVn&oɢDpk6{5v I|˕:ۨHfwl]o@`pu[g5agjw'N0[$NiOg < _<]Ѻ)	d41^3rJ(T3
v8].|e07'M8ZCiN"7=P;-k;ǎe$Sq&m8 SLe[G,/iis8o'!|/uԯ%Zyq]yªmkaPO40)89E$A(cHҤLq3g*=iщv1[|~:gh'WCޮގǅ}J_ڦ](lXK.2L{~"W3%W$/yeVӜg"GD6oqdkGf	^x'yd@`L3udbE[:[m:݉&[o?w߿}=tv8_Ǣ!o ~vn,cqǳۚ"4ynӧF
;|W_(#;ݩ+(.Tykoo?}+b(hm&vx$EDF)f),^5&b\]V\-#{J&2ƣoQ,]]2RHn{@q^8c#5c׶h\v&w$uL*B`F/E<g=v}c.6h[D
7©x^Lij?W 36ޕ,2n1X5
6izE4KlHȣ9yٓ{u/n~qkd.$r8<S696etcpڶz.8̪d}^ / CCp0=`-ʽxeRֽo?[*tԆ§pUs}?{p.Hz-4ĺrZ~VW+St"p>R$*')RL3 PչV1]7:++54}Ytu
[R,]y$8QEzgkwxmD@?k|XI:$<;YJe
wV!95Pl^zǉNr<VLtB}2QI Crkd	o¹h~W'7K>_sS~5{/R=Z̸8m_WJp#ZD'O*EjJ&~d&SQ˘i&q;W	3"w41QeE¨hbUnf&:vpFglP3h4trů|
Kι%@|<`,<]aT?wyu=3\rFfYփt$E/L~~;+=v٦;ץFiڳ29{FqͲܜj"8SMy~&;g;=|m|:v#WN~2	$OԷ%i2md6aW 2Msȟ/͑	ÃU#khđ}ňlAt=,)
ڽ;Ħ]lWQ뾌]kE"dZaGew0翾zq{B!\&F
u0gc8.6ےq\*5$Hݯ*j7ͫmrBQl4+6]klKUL|G7 
Ԣmu٨GքzC'MW>/eo^!(,=QR6LNVHymGØ&}"k~sRSiquj^$1@rPJO Αڇ(ёkH-y1$Ds(gP"
VBg괩*q.:T~HBj-G6ax!uE9DG.@bekx\*uf{wC2뻣Y,=JxhP=۸x
5Z9ne.qNd8V8?R<;3ٿwY)n7_:uǔ?ppy,@tڳ`_Yn5@<r;^ᱥT,'K)>yQvYLwcF5*`%10<\|ˌ*Hy>Pì`
;qAS_d	緿gMO *CBc$ @!LA=e-'vl9'9m;oua GX= dnpbBؠz7_ק۷$<,V9;n} ,͵RdkAc	U<9f`$*_8ߎ
["$ +DdøיE_@h&t׬d72vRe?zY;J,fomNs T7إm|'|σi;Uk;s-؝_NOl?B Eua &6o4U10*p)sԊIqZ_]j'o໺Bxx`Jg"	O=y\C'oTŇw~^~UH~8:M3'QqYW[q<K-p:o*8q$0^.#k5jAmyjeߤEW4$IuF/X lizUd8wV9E_Ft^'8$+jB-c:]I<x,6܀?D3Q_o/iue"{g.fa:|k&{^7txl7=u+x``|C;JNhߴQpo8ukk5%4aoFB=;e-,ITQ?;)a~wz7q# o}nt [=ǹzǮb+Ԕ9 )ӌ`ZϾY"pvZ`^8&jurwg?fj	^	HE6.rA!RYll4l6q!g*&n<\HT.η5r5^Y>%,*aǰ($80\Q"ՑjD~`w"-3_v3̙)*xwwрyW>:Xe}cc2b-ȸV~uG>~TzA۟~"1Q4p6|
3(Fx]ӶEpՐÉaM_#ׂ%{wJLn,RkpO6{AY5_&u$@4c/ C<άx]!de~e}X;gB{fTyX7jUВ"3Ͽ	
s)*lBzs01tiUj/ml9GHP[Ul3hs̀UȨ1VVq0p	1X<ѦèL_}ywǄFd1DQlSY_)akh`cmAشk,]akVu bk>M1ο֮\t'5o,<zMzC$Gy= x1]Agx&+q9(BZ@k_J'g;Gr.MQ̎Zo_:$Y:vzѥ$U^ij[WP*u@ʞg7qzYбz1>P-	
.)b6*#44j!џGR+NljD!qCkxtEy73cqs}"9Pݎ^@K=/
p#bI+(U{K0eհy b?Lpn)T2"XrMr2+]!ћ49}"^}S3FO)H{Z>Fr0R/0 ceܷݹ-
	Ѹ|NoqWc+gRM&8wϫ^+]N^:n
Ss=WeYG ƵoP$Rt7K1;Y(]_v,IFdfmܤFd٬s*v}R&*hf`q0׎1PSJYZםItTGCxՎ.2x18sF9й"N ۾ax9j!hca1UNEEeUk2fk{/A͜GلOGhra}Ԣx}{q툞fl-d	>ȋ.ۊ[%ҥ,^鶰h-O((v\!gG,Ę+ĵHb*Nb\Fj⥓ˁW*clcv?kwE~zstW3-eF	ORX}:EuEyTֺÕQVI08y<1؋.!&0(bk)E[j~dŚ |Vtg(8R/:[%`Q,מXvŚrkaf1h~/	BSŃ>~DŌ0*v{aLj<̢쭶8
iکZVoT@
a]ʹ4b	cnn2F\\/L/Φ65<KDi˹K,CW/u&l.eRb>;;+]F;.\(BɲabUI`!喹Kx<%O7uEҶMA	2*4W}#Bz=VD!@_=!?<$ת)LV}6v+[|U;J#}$X9ŌH7	ksqM*cJ{Z}O`o4K){n@91[cli/Qc;*#>Z{b׀Y>*V*A
+ ER|dQWE,Q]"&ֹQgMB5ZY5u,lgN.t'3oM2Ro.Zhy7X;6?b\PUp4mje◺IZ˂j\yqh/琴F#
Uh$;		9y5)!m,N>{]ol7`PD]%?j:WSzC<e9/d9vϞxKŪQ~S4r0B?GP%҂XfڟЌ0#t1`
<VsB"N`pfJib"ϴmj.YV`\.󴨿@Cjmڍ$`Ca`]tiVISW__3Y?fYa(NdF*ve¸MNsZ[Ҫ-!WҖ0,w)pf9=ז_EacGTi*3g{W\eF_.D;[ |׈Ml1c&@5EӆLgyjj}>ͣ".S[ 0(?eiM[|ks	
ݲ01~ֳ$2,sP4oU Ѭ(3y]hNޛrMOwV(!1ZM5xS1dݘKsEVҡ[G]r~]coyk<.5Ĳrϙܟb:ݻ7
:ASN􈶘W̏_4r~ꝻyG'R6?l 'iT`X/ zՀ/fߴXFnF$Zq>Fh`ܲ1i6xG<|+TnԐy͈8;[b 2|#D^+g"̬_q`ٵnEmrm:=H_}l6)}𝺈O^%, Irc80g+8Sh Y_'Y+T>Nad4{IMsX{{[2JER]mM#׽J)5y*_[^<Fs1MK	Տ_wQYգ+>[uνG9]QP
`KDP9Qx3>JXE^g0*LxTBֻ3
ևXMl2X6tsB|I`fCNnP}x[1;AQM-D KBe#\wW;kUΏCK
4\OvW 48퓦9_Tα2$e8)h&^xa:<oE`^MUbMJL5n,o=X7
j zˉ:Y/V@٧Q_k.E/_XVB9rr?뺲^+ھ5\xFoٝZ,Z|5i~!m_WVą {DϦOTRī7Scf2cٽ"(YWP9KU7Tn}blFU9,:#c|a6p9~ʣq+[;qo*{IA^F˳BGY,!*,΢P1*̅@kCV	$:",%H#T/&.k`eq'jFҷn%QgvTC5!:/F"=8z6_CUuA&(6hX1S*e(
.3518zϼpj*Y)3&ԍ/A)Z6at:+ksRڰkPR*2mh6)1?Tv&-gWV>,I7iy6yWZ$$K<Gːs0jaH=!'#؞=u̡;J3jk"V0:Ww{j_9_3P-M`:'^=3qE	 ILVJG1◻&K,\,1pMp8grtJLē{m?,߷.ps->ȼWrPak#Qvu?&<6}Z7U=H`)t+4;AC)>_IGVkhAϞFH &c&U[jrX3$Xj54/TVk`8g[Fױqsc9r,(T6ew{:,XI%
E}8M8hI4%4ad]*bbé
'Q/"Cm#YN}JGFo|lE9a`0)',a|*n(]QQ?5̩6fL\9	
n`ܭb{( d!}}Ǻ,p'l6c*dܥJy^oFvt&=quKTy&'a$)>F!V+||oPGRvj}a#TKa,E˥ύx+(XW~0P >fW$=#d^_^%Z
A􆇘'VV3T`R4#*]A`$vĆh+K
#}UFJ)/4HA! H}KOГ41wȳX* N2yB
#ai/gT\SXUju}I8yXDb#;߈fpAf̨l!tbwjӘWC PoV7H\l^%}a~0;i_Y)P(e98({X5+	2"J z<xDU8u tq||_\"2$ͮ97@m~0[Y]ki$`$6q95c;0KM|&@ELA"C̈́\L	7بiUd
\#Xq?c,z"8*g|@|gAy0#u,o
[o:`#eq9;R}UWSCA :q:b3\[8|eM_{L(H/oqk׹#OQ&Vɋs)͚v\X~uxXi#` W9picE5˼c Q/l܅!G[k/k'ҲF^^|s97rIp'9X>с}uU]Rzk 28Z]Z]
5jv&"+b5+kYT,k[\}a0[@Y,Uj3SJlޗs7f3ONPPonbsr7kB7S{yH)i:kHo0ɝ5AɔNfA91F@M3ߜWu\|fLZ'
I	'`65\bRÝkWH>-eoE 0l["/{QQWA^ezW8%0:E)4QI%i-
b'VVP2ul"yr#r1C;A&"_3&9QfAľC[ycK5WTY2 p< Xr ( <	c0ٲF|mA6Q_bi"U4aGi.>֎ ƔdTKLZM&/}U3y_gЎ6	3
0hp7	0:l!CǺe
:^\s ?ג<I,\Fd`Q cPtgK\FIe~&^yK]ޱRYhŢ! ) w bjD3ҡ*~*faQ>h$P%@on^%c ?gld9E&$'r{G'<\j6"j˴#5Oz\f)5fo}Roa$-Oe4-tI}&K/){	` Aj O~x٬c,q#mMAG96eRtsC{prYc~gW]t6.)?Fy6zs#9Q6Z@s})& -e6uI|\dM~06s|Pz#XNoRcD6@?Nw(|Rͬ<IV.M/o_Iko~4ӁxP\#+@R0 &rhu0oOyG${H=uɲqJHL '&fH7[4y^Z)U/	CE=wG٨鵺P w`4
CʿQHRğT	8+ea]Kuu}ަ_RXU?kyvBumW5' _+0;a&&kE6ЩEg3mQ_eP^K֟IZ!U	5?q?ܸ(P	WZ1CcK/1QFDBg#c7@WnYո' )bw7}sttE\VB~:c܆*Lb #H+A&X?F>D'xӅ4Iz"G:֙?Y=u7ok7"o#"0h~&g뫳Vݧ/a~|ijŏ/^(~ËNr5o;Ϻϟx~jwu֟yKUhX:ց!'^Z6=YO@#c_kyǧ6Uv^ybt^|bfowW&BRI<<zG[=$Uz:ukt= ]A~gem5F1:5h.sv_ {Z,7mxX yo'j
GM0@%{'(mkA{^{	j!I8;X? ףOrO]@B.ⷓFhg`|BkN>}Ip0]^=@!bLM+yO8rw,$]3	fБd{eӗ:+MD]Ǐ;#p9aճƾ8? 'z`ދ% ^>o(GFerx(G+
:fK	#VfFI=]oᚉRf,LZbX^:Tsi\GfQӳ _aA3DU. r?Y)FZˮd;VKă~c&!8'0?<E\gOxnm]﮿aGCy:eY?Aքet|)evH9||YB	+"/XNV:>Z߾,uъuʫXE65bn=`"vF.@mfJզTϗ7|<oܵ\͔1,򎌕@(]>fmpp-y0yh4c4&:(	R{f	HXCrᗳ2fiAwܔ!m77h`iȕvvΔ",/un6tX|#.c׷0iANw}ƠyvxDC`qbC~,{B*H2 jo(Iy2ޯc$	H77O~NW=k_[c;)2I^C6{g=|&F쉘}%'⍧++3%`!jЩR!emQH#tŐTI5CVr2z8|" ǈ JXYr{ќ60ߐy^	,]]%cw,z/+ê^?򉤍[ 2	W
*81e6гlMx El4FH)xFxZ0`,Gm7fȯ&At09TV}Fy2wyǊldk!f++	 
czh"Q:lDMj$
bˎpEt奣KG,ţld&?b5a/"I/!9+S&!ꢖazj"{SJ["SӂylKx,(fhG0D/Q&w@J5 O7):[7),̜(59F稍s U@lO.mWֹZ=}~ޯxe|6p	Jy鷕OL^MX,ly)Fq2a$;Y@LmRjvYO^S`d^rUҵXsԾƷAquvM}MIx<٬1! *\o Dq!_@!"@3ҥe+̂>eOB^8IGܭ?7An{GeݮD5z:Ёlji*AeXョK}|=0ap?08)2Y&aЈ+ veJ!>d80;c2ip<ɀמs5tw> *'#X޿2! 2JznH俿.7批tss{g)(ouYŷR g0L +RH|4Qj$-ĺ,g9L@cG4{H0s=Q%GWl׏1
g++]㲼:MYJgn7irk4Aa2epF(l@T~5Sho/4c&p%()ayW6KګfvۗGṸoW<8M
љ4\MfuJGu٬0^j.σ4mo͐Y3m^`E{˿7UGaoR-ôw@Xj?J"2Fw/nr 56C\y(䬮pne+;-'%V=b+!@=y&1)"#!<Q3.n|#'77TqZ@CVUغ0?JnHc?sS"WJ q{2~
yRTZ!;>&L04fgڞ C߸qP#7({o7hƜ6ҩN_e)Vy_0'.2f3B??HSw|r,#tx V6g}1	b0m#MX{f(%P;v5՘E'c[NLq	ts]cW``uwIҷ 8P;>5E0DMy9F߅z&!#^J<zN?^<MW/B@&WA' 6{!Z`=B*ERU?Ҹ~|C^|{I_$,krr>c^lH& ȴv=
/y{ >m[teZ}c̤͠]_tʀb6@52.3ffh0-;SL()	?dFFJ/; 秄#bK>U^aeU.sQMtYQtw]i" xK&}cۿ]GT;|HvQ՞[6Ceˢn^O/W&V%;97`x~'Br]FPǨbl,|_Pd@:A8O2P[) ]"ňR923sEp%v_n(1Ds!.ȤV:Pt.ܭ[b{qYT|+GRƟ㘫	n) TQz#|~~_~wOKg\yԲqD`;\֊A*`˕ssPR׮\gvQ}X/k.1GwOd~Pfnn?jt0`R|:wPZv$)QF)y;0r6ݻHge=ui4u|s6;P !$p ~%3Б!).$0-^&~eAS C>'s2979`>D0^??z.aX~)azm-4xno%D~.	``3_,o#t5[nKC# C2|fv[4:~s4_-7SbݜYYX{WV~H+τ2ڎ  o%ACUnE"Ab<5Y|߾_è̪+5
pN:sjrZ:V2zu=}oa7⯦K7^D?]kg bN#_?NU;Ԫwiӻkqjڽ<NMkӇkJc}gh'!ˍ[֗57aIYyƟ5oX.s.[M2Z5{tqN
CCۃ'A ;D	#\vfaJɩx'La%ʖ~'u2OEwAuR?-?\C:yKeqw^VAŚQHDcevұz"^S,`MIHV@4cq> <D`1X73qާF= (V0t4/Pm&EpVGɪOVU7#:Q><":s~y\OFJ)΂ȿAaU|h	PՇ^Fj/7*}[}]>?)KfN|U|}$6=U<BJV<ӺV(u㡚uV*OġT詘4X}fGu4Nl4|`sSm
ũlqJSB+@X)CE_=26lshetKhn6su:_^Fj2mT^4Q05C/mG[:coWMsLg0HsDGjgUa:j0ۊ&:,fruը㿫Y3^9ϡEpWIh&M_?wPpW1wiU|#TL<S-OXAe3\5F5Ʒ*n|2ϙ:eꑸGm%1`z5[͂SmIx3
Low⯝Ot"Ov9u9}>kz3}t"W7n
pSTLRO["֫0D2Fzh ڵ@O܍5luIB'ɘYۉe=%k'I 3-!a,Y܈pH,-փЧYpט<;͑Nk_(xȨNnH~ JWK(wC%Jg 9w~5LSDo(|20i@L0Gt'>Nvm_L3I(iE6>upbc'8~:~^vad	#9_#B "֜jnj%,`mLo/Nc@[6tGȦz;!]Q혵ic=a;VWm<s.Ź?ĹP0g/]ģjLi]s|ՠV"Y~MYK? |$531yiE409c9KhWEXxf F),`e ^,=UuqKx+wNKg&}჻FT8=̔W{f[SS9G<ŕJHPX,□2%A0YcReFwee}c49JЅP8N&%m+F/|b048!93v_a
	L;zopzE+_t$R.i4%\KѼN邚PGNbp»9{g؈@$J$9A̝E/
_+'!A1=XGnZx=V5ei]qvC`yyJJmV_ uO_x,bXlPq(=Ű@ċTp#ì\ ,r9K5uP<|s
j"6-rFd;{0>OxAKSу9fXRCN=_<%/58DM$`ZI|N|!]#B6(gA`:c-	x
@	
7ZQ8ƛhu Km+FGJN <Ww_$}+iahkngh'<"=r}Pw´YC߶670mu{]Wo}/ؾ@@v?y()M\K2hA8h#n}:dyXEGhAZ;wf)nez&A@jh&e"/i| #&AmZy3֡6d<uS=Xl^$F͞a2[3f''PE"5i}pCVVUHZZxV(OI	֤6ħZiThlo <MU2вV5Ӓ9FR_W5o

:=(=SRC$ '4N׎b&[xk2˲:0ՄV_G>z$c
8p{Y4nH̓9d.P7ӯNjd[30l;k|^gǯIL{F96sҜ?a_N&Oa
d݊)Yi6'#{@Sr4?Ջ
TT}<c)Q?^;cU^'FGsƕ3,.OVyd'771'"܈)s)N5*L+-^uu>[`b:ݠM+,ژ %ģ BJNQXe''">-3%YM@xi%< $>c[N?wVqxQC1>]ggU*IpɍXeN`Yu׮(;47Q~NpCрT|emVA	r^@d9ȠulWcM!	B׍*` #?}_!"uko}}b
wz[ s]}8>7YE8>q6ʹ7 ^o+7`M2pgX|}	CHi7`ꏬC{QaXG)љyVu{CHԾ$C1م8i`$h(ÂS.OSHq>h/=Pl6̄$@wự emߍ.+?0썚Wt7N(%JR#BFs%oPJSnrq'z˾O{ց UT@-}*E):V?A:tIn.:ۊ=9[idXIICj~1C1z#X|U 6C×kvĴM\o^`f%,]%V$ DT"bb16!I`F|(K/77:~8gKQWy? `{g&hM3giQVȔ+'̌+6@6PnAq(Fs&-4hğ6G`uA&Xt`]rVc swpwWV.VV,!% a}Guƹ5R9ɥ/¬ݴ봲r[nc#J!sRJ$Jg!#tAo{xT*Mu׿#x2UIi_k7mvAc/`mn0@<	W`YCmQDjUhStWgэ-qbϓN6\YaV#챜Dد++O%o=̧[*M
d!4 	KՍ(T3&KWzrŀ.MYf"3!-̄&K}vw*0LCshA<֞"OΙ- :h2PРcF ݎ;^%=xxh4Ў(B"xZ_J@w?X(YP8t'oAM6UCy2P]նT#%ֆxmA3 ŔbpBsf#M>{8jUWKV	wWBa}4`o1ϲO;>(Qwl5hG(Đ3`y̻7˗w4XKrM'\3c3ۼCM͋D-kcY%YriPKdQ}Ve<P3ޭ<+\zit-b61jE̽ywF>-lD48N&e;Lh]I`XWOu7 AYw2F]]]U]*M)#_ܗNS)A-j]Y-''{_hnּT!d+ee5_7G!ʄveA'aO-H7Y'u-Fo7So˭ĥ%}~P*+# QARAne-\yYJdu6UbjSxulWa~8M]*ḚvީQ1'-Zq`'Cdо/w|?bǇaVm[;C^9yeVCb*)c80R3D@=To^LNfz#QF5N&c(7@%{h~Q`@CaTNu*U}-'˚M:adb&#{Ss/+j갠1U}/9O-7Ŀ@x+DוeRbW+e9		Cy*ĮD]	p8uu+.OO!1xz֜۷VکuM/EƗMSlpqAqtJ4޻/`c/`^+z{~YߏNqL5+{w!"䤻K'^{n핕qcT'~i_PoK)$,g	x)}BПۇd@s5~zՇ\z.dm!::i]qnƯj~Lk˄Om.	+R:4C<|[-zSTL*z>^󆟚\j,6M"86ڍfYZև:!J#;;W~ZM$Ob0.3i[!q;F%'΍]n೰{-éPb3DA逝`{&!=_pb'lߧo#,҇čh9t;j'!ҫC).Īܷ"y4_>Cioؠ/}yL&B[KU[\4Lv4]tF⦓@ Lnǵ~G:vFs*%LPф9VE?P5L= fNZS};GRRmgz2H~p+4Ɵ[vɗ(A8XenݨVnX4L8xCyP\` M'8Ex-Ǔ3ou>I4,zȓzqvwxXl	~t2I4$LS,$C2էlOГf"[5сMa;lMZz%kiK)C֔i;v agIN:i;a۲Wp>7JbGI{C
;!CjHI_IcgVCaM9SHFZ.9ShF|'L
'tnD;Mݶ#]Nx-;_\i)hKxEߗJ)mOS9k~8*(ujttSCv'1hQ7a5m(xD*3I]w.\GffvTmpQoM<5 W?gRGKjzMV>֕Ն]_#nЁ'w1U?W6#ǉaŃ^Qvx3._IRXyZY{	3vJO3Vk-dXІpS!jp_үjdi&Iݫ6ʾRd]:fN7s/s+ff۳(-!,JBPvլVlZpkr'<U 0,rh^n`V!;M݁h=abRmLXRUre4tH jv\=x|DfBb
9l Q~)GsP?plDk)b$=]W=dfm^ݸ|K..vX^bzIZέFέ\Ӧ;tt[{s	WVf:L%%܊4pVT]Npsy"4:],i62
ըD``[1|]rd4@c!KүD2uq9YiWJ8;dU-Lef(#Ta/3Έ 5dFbc2Aaym-wK[94V^l,$ev{ߚK?PL+	J3꧁,gҷُɐ d8NQnY"-{ICD?0HNBhbYn^tѯ~lx9aBN"\p&B
k^9DxL.4+z![jd !D>?Bexmfg&cY;&vXIn-:RӋLi O7_yRǄ 4ea|_5KWZ~-@pCjR0T{.|^P	[&cRK|cA
^rn^;	rݷ^F|Mܕ#_®YzZ2_#udO{<&DQD5V dxVLLn1}<* m$f<Z҄U7'K+*k(RFXoB%f*aWS%+K=;CC"
V4kZZN]bxvlҾI`P^oE#mt2n=LbU
޻DP6@$N`x^nQ
w([I,|/!M"\?-L,'	oY}RPf=x(=ue>B=e}wΒW;3])1Ƣ=0X֜[}mMS[̘ה]YKnTs^}v?"S{e@HJ-$l*UxWWDFnA%LR.H7=C\GDr%#qT"+J]_V?aIhBޤ *i1ΰM}^z$[ioh1lfU5zR ûCDb bhҽuۤ>hXaXZLQsW	WCA'*4@нLdIpW#]V)7P:qK^,obY9bJY}po0B`wy'`BV;EddH}7;8csə@˫p͘ F&N|zW"碓Ȝ9uܵ)wv\\:ιs.rR7:Ntr{DY*u= u")vnR_/7HurF%>%:B!h%aɳ& ĴvM3;WߞuRPMl8q;/<i5w6v
ᲊ9XVsRUgfU3wJ}g2i+19=rb]3H+}(rG-omw}wwn+Ӛ떞_~z;}}w[q*f@Yy@`dݷ@F[A^kk~ӉNi"cxIr`:ab<w8dMϠɠ_TH[sST&!mpAnty?Ԑ񥎌Jg$϶ LiLg9..v!pĸlκ30gƅk̭kDrz2`W%#mpvO	ot 3\ˮKȮg\z$D*t'1};G|PnFRQCUFW:t[NVYf~dU{љgf2(_Wx҅-e+Rډr:	|Yÿnrd]TUٜ-ZmY>/\e od	sdrdl^)Vu$LihBTO/\+m4}ӦpT0q0	=O<].M7]QYxֿƚ@.`&<sk:/N&Bh}GS- `e7QGQ\WX;ƪqNe1qMj]  3՞Ө~4һf/( C4⧆^}qKG+;dD!.ok=*O/7>E4§1u[B|qgR;;@kkD8h}JC odgq;_	Le"pL_ה'?X.Sqޡί~qEcа1f,ьki`pir5M3چ,dv8-@iyvT:~Ykj"اe͜DS|	&ZT3ҁ-(݇_1Sg|gf>t\-(ATna9.!K3eI	(L;Ⱥs^ۯ[Ѳ3!70ôXqCjny_~'-t;.@X['KHbELd寜i8E䌨^S]<5`4JUz-XE.7K.8'&t:Y9݇}Iǲ
ZS(2|H{M[%z0{57nGҚi1I嫐%j4\Z1faN"mK^fKCwCnbF@_O;eXJiKU\fwXX	稲f]	2Qt:@<q'L,L[KqrB0&ͰVYr_nSB'Q?!Gl0f18,ҽx&Ɔ  
V҉SvTۙi8Uz=!8Wp$'ng)Aj=5)K4M&*|ThR"X4d$@d3Ynȿi|F"BdkNxDPt"cЩ~I6a;3!0QdZuwU[90)RT+AUU6ivqK=Ɓ6"@~(rRa jm.ڃ>ST\6B(Z~vChV!$nwoߴ74iz=MSlЃC0}Q`]6!|D^:gGZڱ݅sevzCZEZp ki4>Ȣg(߫ݡx2VT>QJZ' t쒥3Idn!I:_t˒k#fǖLZD_Oc#d=Nx28=;zf=w+hDiB[Ѐ8;HSmiHӆ_6eGB+t<k#]ښG#C??ߕכdmML;U^
'.uZcԝB\hh,w*x4#AP:x`1@1xFd"Cs7ҖHtY
a])TYG˗B<;"L$v>7nXF9P}:BkL=ЮQGS1	;6Ơ	dpt+%CsBÕVIa=P-obIOq	T)'BӆYNL!	Vјwp!Z!|ѱ)uWΙ6Mq;X>kDOH;KFKF	β6%(;#&:Zbf睡Yj/O˝m%wȞ=um`ojNB,_l Xbų3XZFA,V$̅GK&؜ժ@4l6tXkD"]ŭR("̅ςL'2
4q0u@hr:JL<o/dlY} %	n)12|A戻>S*JZ@d}MQ.ʛZ& hW55<O9 ![W{4*r4?$'@V>	QN5\eyi,wFvj=e'z@HxMCL#'f|_`))8PoVq	9%Ԟ[<m* |<CTlODfmz% J?f)[i@Xw_f\vכ
]&T6w/$c.D=u*Aݼx׮Ъ*ps@_)-=^{<haxb;[ɿW٪Zծ"y^K-Z3E^unB/dOy}V9[?M}[WxjCf\JƢ]Uă`T P&poDVº@ BvIN(qPV&"	9䂄YQ"+De^Upiz߅Joz=*0DPa1B!:1{8PygnF8ҥXj$ֆ7	3<yԭ̨R nq6OU?Hx(h51DYlTAfE=9&YgeX)'Rk,$JNG!L7*pp9ߪi˰!jwuziTjbl'4g;ԡq(7c_mǢFt:!Bfexex:;d|HLG aiX`&7RUQF~r(g`)ت?>i"ͰIbfpEFV?6nk|QpK-JVo+ӄHPfu@f HQO-ikX2tE:!؂T3SyלwX-G1h~Q(jAn#=xae "MW{v\vᇄmS fʐ\~GՓ؝0T/CaxEzHhF(=G1L{TMTo,㼭NO#ڽPZZT+-4+Ñ3ZS%}F1=v3) xr}vAUíMuw3(筡7bPYV3#fĆ{eCO]XK [JK4QHE9P 2I[JM(xmCE[g %Z
jpC#hk7񲆲Uۅƒ`yH'ߖ񰮜X 51JՍL'%Gqۍ!`Ld>!N]28BcćmʌT!wDQe򩑴R1_gF=ʔϚ`\'	TNd#dQ=EjBGVS\5z+: *׆Gܴk@4֞uvZh3AĢ(uh隭:8^xg 7fo /eUNQVxOlIPq_󮶔 fڒlNOV5ˇY?zV!dknǼdA~/CI5vaY'1fj}B~
B|
9[1뺡(h000*3Em7¬Fu[r[2罳L5LԜ+q@YĺaPXC$B%L!C]"7ӓj;OǪc%99QK.4/3R T\acȌcη0wMosۼQ,|8ED/38ȩͨ(׮WI0/j!?4Ba߭ ׂl"»qλfEwHk**酩i>w_zW5Fa*xӦA{8?QuS}o=xT!OmKЋ65a[Zo52#/^X7MbA_]	@Y+&PwHi@OPM@Y/)<tu'n8ԌU/TX\KoCFknv0sh\klJǶmVi2Ǩbpccł#gT
-v,Uݵ-@\f{y^ߘN˦OUZ3}0Ki!"mnBe
hXKg1LCY
ڱHf^9i=Vz
!k[.4p3>.DCuuʡq@#l*ݸdf3ҕ5)u%YxDe^a$F%uvT'tGa$U.D90nK5\<ȭ9kPS)bPjs暻U]fڪDĨv#I cy9k.]	E`<tx9Le'i-<IG)q1[{hAi2Bhf{aWY\-5=[fDe,N1еXx?AOpKp⏖T|Cw	%4/]č|Z_`uWHGn]NKB2[xD`) iwvԓJ䜲 ' |.yA"ȣ^hL[D!rCo5aJglwWv ~/:/ɗg.I"	0dZJ&6P鍨388I'.D;>oYo+V7o|q;񷩫yPxbawo-1w3>!:0h̯n?߈o
3Kϥ:%hIUI^(\awF&Pc5Ը̂	y<*z&|9}Q# u?eu=~ҷNk u|!ېҰ\zɅwI7P?kD}kQoѷzEjmoh'?ۥ/*Y.擴C3$vRx0f%Zh~UZ}ӝX=w6˱qi4CPqA:Z:	C罡8Z9/)7`:PwVd!P5a7BůN}[:Sux8+ʽ(CzaݿKM!0&&|T;z/ۘK~PS:M
R?a4':VA/R6,D,hP7n߀j'x3Sbj;BL) c(tAOEIK/Y:~fřb]Wq2.βk< LjυG8KFNu"JzvfzCS)O~~	N8J.sGlDgOk/Ipܭr5x[+{ǽ>KXYK$ٶ1*grmFQ[U5Ogyj#)f!dYg_SDJ˰4Xi ISK[aV@)%b ~\̞-pK{˥ /33*i)Ě럡`j)禳,L#7_]7|*@F☼Ung/)MO_}<d}4`(sԋ/n)7p w2cDqltdLӎ/]*WAR+]9baя7GzpcOƔ5᯴PTlna&9@(PAOJ%,K1n?ѯ_/#¨Ee͆cRL<45<k:Z9lB,y!cu\/Է[ɭFW5
pՖl)j*.$v
=x~ꖞ	6ӬCviWWGjم^
G]Ћ'9Pꚉ~nYvm@ANi&mGQM*zP{-JT%6&Yhh^i^s1;GHXѦ)Gg1Dξ{!@n0QH.b&tqZ9]KUmG<*l嬇	<ўLTɔj-$orL(oyvK7-cM@KMr1F0F@'M26 _M
H/)=
"dsmX(Ej
p"SP	Ք
/#2#HZoL^uzt	r`YNU芅pl*F"UąY^0Vvs Ĝl6܆\MVom25!nEC7<n.DpI]:?WmrmbN׿^X6y5Y O^:eêr0(ܞY;d ;%|&Y[Pm#rLˠӗR>ǻTS?gk!ZW]~\ڢ"ڂ\z	K˥Fr/JGd8E=?{(aƳJ@[z)$_Sް27, źqoV).!ghq1AS6G@ۘRݘSݾC$?z0[@m'ǬܼzZp5DzU\-Ʒ)y.&[xJ+q6*oO}5jO2R[)"X=@DBɮ<rlq+e:exW]GZ|F˒|]W&XʥTaC*%c+Xs?k$N%{_ZK7p]7o
3&YV~vdK\dMcXϹk9#"F^92`/ܦ3-ykr]_og/Hi_6XԅWd۳Ys귃/g׏eCQ(B/g׏bQ0~k#bmwwu2N阶 _,iA*qM=*>{}H; \}7D*H똭I
Zco`OS.[K&y7zg:͙YW<??؃')^R+3B vviN~G@'Т1Q+vy"鲛 ޚ]"zbe#
3Ёs5U_*P$$tVxm	nqbH[?k69&<*}8}ۏ(ss!5AO*O' 6>8xi$]p[<mYt&a*F_	ޞ0CDtiGn_Aղ-Asr	P)ǔMε|o6t<U_o>L8ξTP~EKI9$N7l/CE'y=tsՒeؘ Vf!u)Ŋh:,civJC
Hԣ370 7bxOď=e]Xpi^L O+{I/h㠊7%vlB1
Yٛ34Tכ?eU»k#	J/ޟY`:/a]m:CQow{P>wq6{8}^>'<w&oR,2?BF-c]UA7m}<UCMN΢vv%7ȿChzE܈AtZY#Uvvr/,<1jM4)0¦4;4j;TeWK͈;+0)Jw^]s|@v]@ewjwv&IK(PLLS
ya@N!۪X^#?pe*[λo9~<{>ja8JtbZ-`I@UvkZT8B~:ekHEf>o[~x+yXk@mvߍ"XjBv&n$i1Frp{Ff%OƏxS_{{(Zˍ!K9%Rҩ=Z-^vhMIzN{+BRk<?tnؐ,is*pog<Δ2"I˿8;;CGVWNiTS3O)B퍶ݪ)QF|9{]}Y8;tD#_߃"Hx,
QYTnҏHлgL	+(ƹfj=2eޤ̛Oa(ZeUn>rE%$?ʴl	ŕ@Vf'FD,Mdm6;<Umܶ(yUU,omsW)*ǥ~FeLjJVƦn:=./ٳ,"$dl	F1E%CŦٚm#Ifh*m"Tzi4&O$Avr,MÍyB_LZ0ߖQy?Հ&V2q@i|Z{=*^JxҨ,\A@M+?99]Z+g8qCknX^I8_(xVӘp3z6wEW4n\w&2xy/l4e|[WqeN:[GvGqI4 p^+/LmgZebyX?II M2M,Kk.W:qM"BRs%>۸Ɠ[VBdk9sSИ teXڱFiUi>t#J|jCm2e1To}QFTBJ/u	lnA:_vxvUʹn/s+9tr&0ՒUN_I#ЈVĻLGJJ4:cՅקÐ{-9IB=nьj#,85}8GˡLmKX͔q׋UXjXaņ><ų' f[Re'*#mjP@^664<+"J*dљ"J9e'5u6K	+_lMl(=߫wQ&wQp/Nÿ!VImYӸ8"E<gF$=h<ܦIŇz\xpls=ZvIQi3@c`FpVE챼-F'{	L+5^:{Unwaµ E˚?[LcN63uuCdӺĽ9,'KƔ
M3zT@,APO9h*QߜHz~doJ}ERK6^ GGNs̳ڸ+rzYm18a4bYq{TA7W6΍2M!
a{8|C@~F"|[u ,cd$^.F8"x ۂ		͒W77zө
@jF]#wv)AA&@"L:9>_[g-j ݤ%MFn%OJH)o&©U?MHl+$+ +[:~nE[uZ@*ݸQwiL-	Tg"&WJ<C~kܥ._;PSFL.cJxIF&*DJZ}_qyp W7Dog>|je]znoÇՇ݇ɇCç罹=<GU"4d"o0 YqyKs'ǘ *K<\SfAi,%w.2TaS-S`GTTo=^Sf3M$)"TW&Zm>)lhʙ1nGXVM-Tw?KnsZ/NRID?a'E&f-A!B1'"B)N	vIJ6Y:H}YH5M^p=ȅk[2Pൿm^ϝ"VNwssӽɼ7=ֲoղ)_)lτO_!Q/~Ytkkuϔn~Z%,u<[@x2SʃWʦ}Ցk`?q,cZ'3@bcI-јv\8NcQڕ*]n~`H>DWr/.%A^7xqM2vдjq:*L3.'xOa`e1tp*Z^ϙ(͈FN~|fok7.$+APvOL>fre/$AR.S"ZMZׇq%d>`@moFoBt
rEyEy-
T[o}JhS1RP|V!Hi<JI<j)hN9_73ٰO_=rejF[|z
=F+᠁|7(LWQ(}[) #|Tn+ծ움=0Q5RuKpvCFE`@EEb*3HٮVyVL4x0@k"9*ګ,Uk{艰%J@N-rJ+M5.{BTStԬV9ӪD  RMTʦ&sNk̍Mg-3Vnl2FoĴo4J=En:WE,|s±3}&}d_<h~WSK\_"EYsӖ0C&/Rp$ɣcXqv˩Ѥm C,ੑdlI#G9%\^^^Ta4mؤnHLg6oE-3ªP6+/hLn&irb6<bBA_$`ogD1$QxL4OGBBpgRiY	Lx_pbqLKR#j|c!]4'E;EӟA~PP2:]D9/;sY$ .5I%&S{{˹^V%Gbp5A;fUc$ZP;Hƃ:_H؄Epvs<·ז:;F7(VZ P`-h=ŵf#V.;F=t|Q	򭽙I֞.HB?5Hᙒ3w^+fxAjÈY]
,fDlf.晶<
"oB~Ʋ.BK5iUBon)ҏ7Ȁ; SA[
Z,)Ԫd
sFH_~L,U_'R4y:UҨj߿Web?u}m%궥Ыa	>ΛʃkVL1@I$1KoRdW FT]Rc\U?߆w&	6~$S?,x:"QBI((HT&g!hq8*Ӏ1g͏Trѩpk~jq0❝SBMns[a̲_i*yݢ!o%t5SPúoOan]sQ9Մr9כ9n;\AD  cQJ`")T]8(/v@<Dhܪ+4[$OObiM[Ds2OIt/u-/aK("6NߋqJ}5ʐ.[]Ia9nڛǩUƭo6ܔn;`jzw	^{f|sZbn
%»!SD7+e`!Jps'kcSLL\|oIz'pa܍gFEZpkU7g1|,&鴬9\NД+}/`C'ƣo`J"ߝ[1~wͳ}n:ܷY4`Im
welFcno&i|Ղ{NQYII8a?PS2&˙{s3~g^oh?~Ͻs~G}}:({Yw_TiC1 x~xlA7άk}T2I9]a;})+OqspgN_6\e-ǝ:9xN%պМ~'l^{Ɓ6]}|-Bsk`vx4|^W2i{L;gyuwWd{i>%AF+^AQ]Y
fNyh!˞q{!r/C:WK컰sֽ5{gݏ\}]}\
U=xYuSr%4ĺV@J{5H>p!M΅26=Uk/z/J;c"ovvnTEhWtYT)|)v>||-;%N!p(13DW<gDtr/d(W n+>gٝ)NZ˦38GTǙ@q&-]8i^flL9v5_0Weٯ/\LwHkn*!C7BB%5GTfJwǷ2Eu~܊a'^(!DHCGx9D
p~g[TUjpIh^g9=LTԕh/,B][aoYPYYpy픧;npjrQnx~Xrh(]9e^PH~ٻ2ۄ1%;;MFliNoP ~wvD!Cɴ@ubK'ޣb.*2CQRBR˔T*0@+Xp_bϝ7IPh2Wb=+}`%mgѦk-2rsڡN\|^pGhN$0.&+DR9/EP{q SyJjr}އ3]
Vn&u2n?l#T{:W6#@p`Έ.*{ $О8oJ׊%g?q-5LSUr!1Gp|tھoS¾o3ӭC0E>:{ZAKBsWcp-yULxH{/x0] t@Hogc:.'^}"ju		Ԛ3wNT,#l! `?
o{N/aL\)ÂT&+m|=3|;=7q!#Q*Gy;>2)=~/7 jl^[T0QrDp5~i"?35*g*>T*N_ֶ=f/eo=g"z}D~ukZJ>6V}\ęRGTj[?n"gA1x޲TfK)4yBNATϼji<ƃaDuC53^l~*良DU~e^gS{36(׌X8v/jxrCz.37ߏ+v{?2MәfFeEUfd:?he6Kbm~ܟk6(2|?^]s45]-,$~=@ ?Wwi.dw$1A629羘0#*BwI<wi:nDbC=5sa깩ڢAj>jYuRB1tXFCχnK.YT\+++'6һ׏'O}}0V7V럐eynxwhAHџnhsդflDO\Ҽj?n*o^XrWxΞʵPoQf:+2V]m[fI|x]̥MHR_.K#I.[m-pFbd=ZԠ15q9㿋y^._˥)oECW0[NXTdu|kyu%]ڄpWNGQ{xs{tg{牨bo@/pX0-{{?DSoyGS>Qq0^seBܜ3TU,7qL*#I$ ;?gm-щ17A"?89T'US."9U&1v: Jaxx,soL_/k9>.!U;\z,A`O/@Զ|x|,"FH,EH=Ӓ`׎V~70ӬDL6OaʣA5`<i{"M>.V+Q8hRҏk``O+n``_{<54{5L`& hQ{ &~i&jx{7$F_=HaFs'1 `|kwp@Ym@
լx$Z`)DÃ#߽.r/(XOa8S{t׷w	=?q<YݥqSxD]KiP`wP)4t/H`^Qy sK8^[Hv ie6ـ& X$&⯼h3wic$G銤z.5iG{jGP"-P&-1e
0)'[).aJrPOΈAB%ҋax6<%,PyS@Pd	4$΃G`v
:Uap Ȗ<Y-ڸ,,uid
(q7 %#Y&spHӨ, Ze zl88ڧ
4['q1}KHȻppt@pK4t ܛ*GcO4.!!%j/޹w UsK~-UPE2O!m'Tւi="TK+oVbDj|6-Hr#B>j_Rf*,MgD	Cr4]<tzӡkO@>7.֑.v#9ڸMUM]*g`ߧC$@<XAюD\?Tv2 %2El]Z=Z<mGHncZ
xb@b[% LHC:>`1$lCDDJ_yYNo[#}[4t7˘ňʣ^GHŻ<Z޽9IZ zҟL8 g|'{]$Mf\fm^?heqw9N| 0v U2沄3'N[2*9qd?6t/hkD@9y9ySPl|V)k%@l9Q]AOBUz}h?Z}qL`vecVCt29URCZwM
8
gFa`e#ϜܚXᚎȾ	ZΓ㑜Qm?n6p%@v-Oܴ;\ӁJΚ]nuniNGeAu1o`r{Op'.-+_56u҈çϠі54wv,ki:1aϖOx	)+% ¼~,GEeAOMT>Rs斾-aC]K,߄{Ayŧ^vB%|);-2L(4IS%;;PfP6O;cf,yc(flSfDz  !YLg*"3a̼c	;~QF7Џ.oV smڵpcj΃Z!t舳(n޻G-FwIܷӎpV% _y7gda|WEQx%U2kJ=84٥Gy݁2,m+:E
VCX(F_y㯼nx7Ao[ь3;a/'kwPi=k'qZs'"4{gBEk|ѿ[ѿ}܇0o-={Oҿ-[j3m NV!e..BRglVp -iIZFT_[;ĵR={UBCۅ,ɛYAo\Ϟ3Ǝ1O<;qC	'}ӿSxvmu2B;eBii<{wW/$f3Q >^~YKq08D-%gm]xL9SҘi%4;Z\xհGqrBp~MidHu^"/8@
&ןϽ#$/"+b$\$%ZE(ςGlQA&Yq;tȠlV;[Kwof۫Pe ><	sBS%[
,2`Уn$U35mTY	{xg} :.ԭġHÌ2F1O=Kۀ=#jA_bt T1Z|Er7'>sYFq5ak+ўwċ@ԽaUe+tbTNse,H>73tVΌ@KN9ڢU|D=ʚR;:i@VJgf/!-nid8KBz<oRea'PihPi6M~Gy!>vSqLEg8fhiu8tJ(p1LݠX_TV_DTg,G&V[eR	AAXVdZON!^i=i}oۡC&Zgx&6DL:}eیUr&DMƧ)Wiu[vsSHd$	"LZ_u9{1qkחO|/zz{&ra~S#s>oO5;U}~6r}6Yt' YOT&*UҢ(C(<L㩗}J%#<
g<O}Cڭ7~J6ţֶhW4)ԛDKQu~wu ;X`::ҿc=Mﾯďr&\eK2K(gU#WQ<J }>Ӓ`$jMSMg]L-hS~ U(e|dɚm|/t%2Bhp]0`\%l6:CG8'~Q=<aDWņGlgi6
,lA^ӖGv^Q Z;q`Ժ~_[}ab1r=X,o4.xTr8 ςCm&	pC-i[|3^-F/z[^̻y9jD>&>h~s[u^Af-I4FȉU*G;/gt]4f^z<u'K7ntNSz3>N8w	&Mc_{v@?+,~Wp';caNBQ^F{k
|fMh?8l*~S{ƞ'#7O$mkS4fJ*0Zޯ5݃51J:ɚC2cEʙv t:ƞ 'Y&dA3x4a-qŉK꥘,`:U^+7WnV57Sx[ڧ4NwaL}Umˋ«ƨ-ca5Ɖe$b4N$[ 2uNʖ~*F:\[T:k{Zvz<y,thzPO>":nd>3@Uuy2׭+s-#܎'z|<2jK}e5IHC/A^E-\NKXbP5 /AYNfSf3]B@5?=%qִJc<;LR]+ZKyBswA-ݙ;Q	E@JCVŸ=[.>V[L\#S
;7=slx.6Y>/@i؂e#hŗls	Q7
v@Cu=Q8,;qEC׈]`O+ZqaM;P8dsO6dҧ*ΝɄR\SM>ؒ8:)^N}w׾{뻧{ỗ{gMGG_-ޥo|#bh;v`%B}ARiY/|@)ݮWa9.FLD(̋Md7^iH78+߾mj_6uƩeǒrK2*6mO[~_l%*n_w`O:g݁K;I/UݘQXT4-f:^$"oY{["F]##sa@+Ӫ]MXA,[*(qn +d?MfoIflYAB(ԘtQP8|X^dxݷ̶Ơe뿤v7'(1)$#:|v|Y40SZ?h߷DQa]{p=VwdΡ.%OZA$#hĬu	@8 BY5;t{`ɉwv:`$98e4S&	MK6EZ%Ec-qMvpsr0܊^h/&TTxL4DbG%BtW9)﷢ݬFx+	#IJ9פz5\GG+?z׈I"Bx܎xfoTv9rlo^Ԫ*m3.]a>sٞq<KxIhsS:	Jd#)MUzvL@eRsyC~DkiG|MmWksWDmrժ̓Q!j4*D3</|oo
נ$w[)Jw]!_̇{CH-&xLz{mQ%vݯ=5Q)kAѥwM>;oay[N,*"b( ܠ!H+_V8uͥi,芨 {}͉݋&N!7_`?d/?r-j=ǓKwr;p.@sgM	S@PSw}}n[a2Eەw8?К'R+Gv9]G!Pz3AI7y7no)OxDC 8sTidSϫNQ3jr(oqtXg؜0iSPT2=EԪ2B\qs5S[ZQXZS*}YBREj)49L<38v߂bk
-s`bDAgtw)CHgH_{6%0GJC	<P$
Jd8%9}3$#I`{_޶$t,@)Rd4ϱoc95}	hS E"#o-gBQJgiYꬨSUQfak08wOwa@V[+YKݝm{<HyZ!>o9XOqsTbxsc$8eń`ӗ#T[QZa VXtByf{ӣF6g\
8|E/OO%t^a^$ʋP""[YpZ#l%V؂lkmMxf/X=Rh
"&V;݋(1;Ңp}n{@=p3wUt{na*@ߍDѝl_[@]
 :q2<uޅ?>ht uⱼEXeo؋\R
z%>E3|2\o
[SϜ.beÐQlc+hTXׅ:1xc|D*Tt.$|>`iz>51tQy9RNEUC@1}L5S4B7J
JzɁcW+$^Ы^uA;c!8±w'q}Ps 5.*- Y $3@F<faF`IGβCcTo?_u۲SODaHGa&lq__7,^FtY0xogFiC,%{βH&_zk!B*E_kg F/";j܊O߽AI*jCzML*`Dos #Y<=)ߺHו#V9;N;1E[@GE>fy3RWU#>uѣ|[o{]xAu⇑}2IesVvrCMTUyi1z۰w'T>1}yzuqɕ#w`tDlP#Z#ÁUI| <6W+ovMC-o[Ճ#dY˳J"/30')nyѧlאix'nDđF:Hexqlk1OwÕy"sTiQ
f8&N}<,]/ƌ&d?s;HAjUQsZQMb.qpO-(PgMI(w/{3T)43cə~*GA'MwnI@(tk :d?W)Y~ˋ?c?ER0(ur]sRH@ፗ>$U"!wVZr-}Bq}jrNѿJ"+E%(ozWgQZlRP'n텁Hl#vE4kv%e@
+uG!):DK5\rZ,!w8JIdȨh+x#E"B/SQ(!mfܽ(S^^*DhTǎ6iPy:p1U8^NH5r3ү._	 	0p$F2d,_aS%m.:Gޯ##	C}2"Av&pQ$$lq3Rh{ Qp}:4u31q}ZF)eC0xΣ<<A_?x-m_̩&fuk^j|xOK:`}i>: 8(C|V;q%??J͝wǏM]_6Rs O'	b:G^hcihH KTcGˁUgi2Fi3l|uz^*t\ct0è׬ϨbIIQwZxfhG.!@P)Z};^<[\OW300x9Hh)Pt%n?'^qX~LaubB/z(!ֶF;W:meAkIdS!>da	r\g9%1*,z9~,qw^?83:>D<}*_KQ Yp#:/|~ÆLn C;ڡZXh-PoeVW՟쮾[Us{ĹO]U_%arB!рW!bC.4ho<HWNQ>jKuڨG(P3q6˪!]K()|Fɸh'UI E$gz*,~w"dGo;E5`&h\A(Q8fVbeEFF;EqbtFb|>oަx\ڕpge7nK+qvg;pC~ȁ-]+vEV{"Dpѓ(7&@ˡ=9u><Kg0*>j*ϣG{> -&.~n.hNJ|吵%O	ks&7hƺIQuJUe"\n?	i A!uV 3[ǓB(GO(۟<n}i8HcqP;-%Ća.$`[4K`60`dȱl [~f}> xAHDh1p8K^;t[;kNfvS ABEh0P,1g! zUhx\IRv$ʚ*iȣNxIhL?~z _ؙL?﹭ɀ'3$j1J|v|6DnQQNF&(?Sp?	{zs1L Z.Bb<~۹Ǭ6A#b8kU3!g.,-tٛB;w,`&`^88sK^KΝ0
|^
'hO-ީzOQ'	 ԁS;ChT5{=ɼޑlGKܺ#N~Cַ9߼؃bY3ֹ [4f:Cd.bc> {GVgr˳z#S?g|a Oב0XYdZ@gBEQ>6z)EWa]g>Jb}2.Ǟ#Y4+CQc?k@hݴ{E;6WdN(%~<E8TN@0.
vP8ۭsq?;9޺i!;Rt|fqFy{(7;y@.@96/߮ӳt?w'aPgE?7	M*buETeEai:?وtUNɔE~ѵ_Qxxֈ\@hTwyʇ,59'j2O,rhN1>=+@Pk#7PW8)x6fl_vY.Q<'F{(Q?4Q jN}6r Lct{
0I$P_fP#f4_7QN|/ˉJ&׳{/eh.μ3ilESvZ䡳jlxk8SX_ޫf,oIɸ O6\}"3k#+-}#Z9ٷW/F)2_ qCxN]o߽)a/j?m	Z܌KoVQ+lG	E^')<eCWˁoF$2k=&Ǿ0(kq>Ι)#! 'abȋw6`dwgH1s	uZ8'pqx<Cη=ۊmM6'\ya@*/q@,z'PԇYxbnS]^ ?A:?5u.N֞{ mhbͱ01<-ҟO0#x9p\#~pQhM(rC)8"˛LiG0#=ን9TXZRHt%r	VwL|:ZW@2	2f&I g}~rL3#e@	8=H(qJ>b#pҢY+*wSB)2lQx	IY]'-;Ee	>.q	,D[Q+٢x`+bs
YpnQ/PΗm?{~>%\FYt2_*jwؑK|t>y 3u_qvgw_""БaL4AK[ 
r{jdԁM{l>:ʲ˛sMKyz9xK	ZAs Vv	{xZsbkz%g(V xwsmxlϽŖ?8;!v%\%{r+c6,0 ӭÂN >0v]O0sh E~Ѿ @{x]+=Z/,KsiFE8M8ӭK^Pi@1S#?ir0M}쫻52w0$RIPXl=u(+pX6N͙-|Ƶ2ث9͊ړ:0*]b֍ۛb{4E3ʈlgrmJ~E̏E)eú4̃ꍫukʆ.BH\oD`tIcEq>F.^6J5uÐи=Ww  #x)x	LD跄Ax\H2ݡf%P2c\*JpOtׅJ\_k%
D%q	hw˄Xqr[fϗ:_nQRT䤫礀{
edٙ(@7߬a)F|u5x¨P5Z-Y]tR,sJe(<O &?v6D֒.HAtQp<֧ZH@|<qpj%k}ˀJ	65414Qu8.ih-oBMM5a?ĕ"Wg:x\̓R]*4Nz>}@!eRAC 	ΐiFYdG̫;`q4gɷNBTYQ&"G _`<)v-;]؛~K2hc)^6ǜo:S'Ҧ;po	f@ph )U#JYE"*pv6C*[HoMd_~4FtdwgG̀OUҡL\xYtV)dC6#X|	"pR^BJ=ns@=LډlGD*<[
kCVnP~Ee-tCC:OCxkzݠ(}_׵VZ6VER\daQ^,zAzK_lƀgV7G$rt[<QM;{\`/8zȓ;?*3ʵr)o +[լSǑ!oRs+Q<SW;4NB=s;$t#v[q"q[Л藂Ŏd'j0DjEX+qb,ה~˹_<rg}m66"kQGP*apv4M}\/2㈅t.|V$jq0$W rck(7Т fLr|
w	m@TWrs]F_JYv^-׷6"kbkhAy)e9ƥT8$LmH2"q~9ޤe6R=&4r$2XYyp-t9.^ȪX(+L`|5O<	hĥTVTإWEEBD?͚}&4[]: rG'h :Ӡar/@;=!$\%*E,|)_oʤJy>>x8uWzсz:ChfAp jD+ެ HTm3óʁDb^t5ocNbt=ӳEiRyM2 GSȓnZ<ja.%)ڥ%D;䳓ߔጠpơ\zGNƻf6Lԟex#PC@+8
!KDd7=!=xR<D#:GWocխUՋU(liP7g8Y_FV
%陕#m?6]vAfc]~8S[rP-'M<t5~ӤGH,GFaXK26aOZ
sS'ӠwƉw~燽~o{J	\d@&QI:<fɼAOQSȠGsxyCDA32QLJe.?bF|R?u2B[b'pKig b~XF#Ҹ髆ȓǄ"fǣÇ 0Y[fJC059@
O
}8쿊%E3A 7m3@eV:aH{ƭ,:oe+)YlUjyE<P&TV*9_ĭ+a=x[<=ɛVgQpyK~A+
d?e,(FfuYNz"Kb~#;"G(B&":pG6BrQ($juQFM5;vd%3 SA,9HKsԃf-4>B9i3VI!<zG4~[=#CX#odh+< =78#Vc0=)[<J\?xzFPwn	i4xE@9pB"ߛ83y2ڳҧ34"Rԡşxs80.&
|g,IK*ml*², 	qMɪu4?*nalk^Di-#Q&^icÞ>I2</]ͷKWz4ޏ	*%u\yR6rąP/4E`B!nfԒWNq$k3`89 {O~k&%("!閃ԋ6IGf.Ru7ic#2RsB$|MqmoI(ﶉy5^_:(--B(GPPHp2KvVdӞYyLqAG^6:|Y݇-2K>>&pA+mďCľjͨ,imT4"ȉ73C\'2rBlpƐK*vQƚ+ GQ]P! N
h*#7J'@6%@ira^Gi^_wR%BE<F]PU`gl%)0sd3{016ߗ}.֩G!OEo^Z &maҶ[Qgwh>\!\JBS.TzoEFC5
dpЙvɜuSBŁW~M=ɗr2Y 	[S+ț
*Wi2xZ;ԫP@)ݑJpV7y lE2aQw!#L/ʍ'ek GbI[."0oHT鈜F;D[xϹ=\ͷ6pmkCvLqsX΂<:,ѝ!pQԟ=]G׳'j$hR	`(ZK?%pIPv͠ɂAN C<l7vO[ 8iii"YCz4*>-OfpP\_@duɾYAMy[9vpXrmGp ErLI`g/|sma[Jքў >@iC5֌jjTk`-P"$t"_z3vIo𷪨7\C㜤@լĞRm,Yd=B{^	7'HnoC/٠XP/a_ /[.%!	Tn?HլފXmV<##K\VbrZ纫b.eG8ކG1N%k SbM\5)ŁpKmb9]PCi<қrG,~MՄJY9/yuИ;%U_QncW%뮵jtC lܼ[ijst+7ed$)Zb y*aE7a X;)d|/%S˞	5=k
FaA9!D|NWw$8w6:pԠ3hJcn*F@yrYkzxz\=_+0l^INc:{feW^a=`>>tlԳ$]: Xt:`	Eӻ 7 y&>ǏyxSSٓx=¾{dw={҃g^ooodoa>0={<=v3m,}xGulo~Of{VvnЏ{OCˏ{]hBw}]Ɵ<vAgޓuw ޳'޳=z ݇γg]l: =CTڇA?E<م	?
	ݧww#{&cs0a.BNTHlc|{a!ݝ}'eۅ:. x9Ϡvaq.гN.̢Sh'bS'OO{ Qm[脋^Wa >Ȧl\c1`#pF{JKř0'G>U2ksZ;3Gň"]miQp0:n7z2*OTT"trMxY}A|/p}hEty9,x1D,JtrsZ 8 xޚqIF+̝Rgw{\c;F@(02MR>1C8aNive׊
`RݝSҾ俫}s_ur-DSl5|(ojU4ւOQ:4}mŞ	<Xݶe_"@NT3$6=%Y8q#iddB0%(C=yo]\@Qrx/LwI$`urg2ηpIn-U8CR'Fنu)%'\}Qjh4]ؤ'oݫ{х
6*y Y"|~WHmf^\&z-}3{c4xH0`.@xV9eR_[P'.(vԙw[3<PpkßrBgeaaC0N!D#1dЩK(2$2čnt{Q:jyI2\}ڏןyn82tGЛ3<nXXDLWWkI f(pűʒEjG,2`<2KAWA]\6o"]G%nrq~:fvvc|oDΒm}rɔq)\^YQ',[Igg?E?ɾ(gΰ/aG>3EӒ3F|g샻+;wY2SzMJ4bR9=Ksn_eΗu\Cw˖l1pv$	=urXq KH_zI#MB	פIV'x{O+ mn~.^D%,4N9;[/3kÃ^W9D5W[a;tEn4r=wR</lHqro2Ef6C|*nmc5ínn;C5s@y3Efz/;Rd`n>RNx>ϗ@NĘݻ(0FE``(2xo+ Sh#A[wWFy}	sˏ8O2$\ FZ|6@_lwΏ	Z:x@>!6"j*Ү	NA 6kkH
?RUqCa$( +Y
xN̹4eS$,g-PqO0~eDЫ	ZuAJ[rFՃ3\;=RUrpMӡGQݰ.q+shZ*=EdƂb
2UUZ旡e[oxbMaОp"h!ӱGgq
QrV8
Y-44)5=ӆB0<`P	LkqF =ollsgtEV'_cR~dVE/'߿Yԟ.WdU+[Lr= lR`Z~vq91g(ƟEq?)}`;//(v|&
a[ӣGW0<{sx)/ĔbnZWv	Mޅq=P<rVa̩ ?<Lslquq/a#y_XYVNۈG[4dSyQPͿ{tĮOj@ムC&BqSE녱-^ZG"sjYk#17M.W0EhSqZ/4j~|M?i E+.ݬc3J8C8PT_z)ZOު:ؾHguZ<'wu@y<} vCKκFV,im}g0EY?ْҏE!x`x4fAIjlWg5I_l-ybBaBF.p~Ȃ7pt81F|S^r4"-dJȣVV]f:-09 I_Ig$>yXhl!AlL};"8a[n5dR154مD=˟E5;qbF
t}D5APQw*TRGr_&U*wӸfuO~(57lP,!ޡ0%tc4Lv Er CQ%Jժ{?GwQ&LހbZl\&`B@G/Nr%̱Lt^;gwd ,@4]FI:Yqyrя7w"ƴ#)Yx]@Dv]7gfy%n'\m;2ϣx/lmĒn#X-L[_ Hekضv=\1v8XC+#mC4c`Xkw˺<Z^jmxoȡ5EW5crf=Gge̓ӟA<S?^u?#_s;u|,)rTTÄnI8 g>ܻ(4U}}g$8j![v66/D_ٚgdI:c_J~VWwIu+&-BԭjHH"HZ.ɗ:+Z|MV?#9OwNDDMIq:.qƂ_.d<2
4@1(eJ NS=XFD\T&$6a&	4h_ߢ5þGɌpGzv8]s7x$yRYexiӤp0T 8)+8Vm1 p͈ژ:sT.jAnŨ#hfz妐UP}]lk !JʭW1FUқJjm㢮qx9t]6ΥJugJHYo_O;;%Z_M"Ǵ/x鸇q*#| bgNJ8??=3VkVҽydLW]UЌ)͝u neD	fqk;ԋ$+3ݍ<VtD)Nv`YUZ^(ڻۓ='vSew˗m^^_;6N|[<Dz/`ռ$!$n	ЅCH(#0yOO˪`.yoGऴ&5_ЭA~B1PxyN\G@p@ɮsDg`H}.RFgZo_2lqcNȹxk >Y?<g_z]6и
??n͑tó#O+8$a/I[m΂&Z'ԅo<=#Q
isj=zؿ~D![#sX`_>S= qa_Kà&+vrp/854 .b^ ¡e侒_IXFNy!'XESRߐrd✘8GFv^C{י+7FAazx}igvp0X,hǤv6S5,_6B~_eX徨]%Pژi1GZ؏[t"|OkoBc<ھS{^7]w47CfXKAAFͺz_i)-eo w/ĴpǌKgvϙ@c!"Պ)p?~9"q%ys}lp&,.
7#$r@N(→UxOCM~R|`}wZ^MG5w~qݑO׸ʬ\Nap*lw}UQ~Alu5 dd5kp1:x0GtqF@GGBRYO!g@DGXU9
]tto:qrJJp7y9s
?xUt1$Nt='|H:}H({!H)Q
BUÅ9ݏ841bCBCw	Cri&i
"fD3~'xocK
Kx	PPAw<,	G'R#0;Nal-hvqhyC;Ped,	Ŷ >>4aBJab؆FX3*oY[|'Towi_fNqR.q}e+(xJ?0Tb*C #ǒPS:E>~Ow_{}wT%+o>rGZ1;nt} Ǥs}LPgVDAK.w^~U30pcsԈwv8rz#ކ /0W)ғ*zƞ*GԗA5 5Z~ #WȆ7]"Wl?|lXʁqh`Xȶ6M<,Stw  ?RWŨwý-7&s;z@4t|GMYj&q>mZL2PY;9}=Bq5cyx0^v\FSz(S?SY솏=D=}sߝ>?݁Oc>g;ɓ}A&ȧ~۳zn_yɚmγ_eM\7Yw}(R\ǩ_%~2`?R>/fy K͢LD7@IX7̹~T4xݸ+@5eӦu߸uS/C>aN;_-n
#C^Yu&J>oZU+_gPo2XxAt|7 Uj|Ll>ݷxt_~[iPw8P{Jaz$uh^kZބ3\,C %$/Pc8#KZZlX4"Um,=lU]6~QPF_tN`ȏo'8#̉HHPFAq%ogiگI!]xqfP	}otO/O.+p~xp:$<!hKlKuN7M|Y4kpQYDQ"&n3*ȸɫ/q2"3*RԬ><$qyNvqߜ}yyٹ$6ې+4<.:v2<.ocR8vfa F,vŏ!t/}*yL#j0Ѹe<LKt  ̘=E9Е*>{q+q4Ƃ0~?Tp~K	9ޜ-XH,B*nYoUmbMw -SH쵹YQf<HFUK"8XuzrZ9aߎT3m:iX^`ޑ>d.WVOŁjV8V=tc6ex:KY@W~NI0BN	|mH]{W?2r!o_6G8z J8R6	
djEmE6L#Q[z$jWTY&WK$WԂZ,Y^T$-ӈPe!KR-=TVoػH<}Y^BެrZDao䑀ߣi8l&S{ޣCf;9/Rt>75#|(~}ҙ< 2"ωj3e1)W<LQ\\U(;xlK)Mq T9x C o S	=&) ed̧C<VFYoUaͣB+캬`n$38 ,4MK۸&Pl}?%sTiM|̛-kny="/*pE
Q-	@*2gD0
,q+cPDB:ɹ^d[$/v!Y5UU_UT*4Wk[́d_g'l#JUwhZ1_yue͝2sFƌMTMG9uVt $ؕ?򩩱<:uQ(Rw5~tȎa6Z$۔4r8_9HjQlb|b4EG_iUkXyH3&.[aJ49.ٞ oWutݬYj4[ruFf6N:jtNj)
*OO; czO8$ߐ W#yO!lvO+U<{wPO}}3#$o4$f-ŦW$	?=a@:!).It0x{?-|GWIkvZՔwQ}յqeqs0{^jXI@TX09P?	#D*CWNFd8t W3׷}hT&f
rZҸ;u3SOͻub*K`2 @̀2N@kiSD:+QoMAar)n,&]z|F]MώB%٪ MHqӥSɯ13ai\st[*sZ3joTep* PIBNkS}%טOi=6 M҈&daWRTWDFU+יNfh͊+f_~5,,mknv8xd#~k [P	-<Ki4L{p??ĞRKXrpUo_42|P_DY̎6˻TEev궰y%{ZDϵmSo꣪M]D6s6<6-TK=L\G|+|FKy`E.7wk6<MKtd5| !nŤRR	AɭKIz1ۚ*V,VEjdºz]bUTau	છ7DIak*Vh6> C	ZoP>MKRz# |SI[ډ'?M➦d.:o}ޖd}&X'-YײS,Ygb+J|3JFrEc45
eYl)F`@d佡nZtx77M@PG/i0'4]KTUrɖbHf{@vqJi*.VJw4Sl<KV(͌B&VM.L&So*M2X|{wBzQГ4vN<Ob@]%D!ۂxP69G[6D@)4g9m+sl.UΊr"䟁Ta9V@⑑t`mE)bmx=sj:DS2&`&5=5]{jA4}Rܖ@Eǁ<1wU.)\qEQT8D۷B,O$쌯*[OvWU9ե|<1X\&	0UJjTi&m}b"%MPJvEf+zdOkQi6Wֻ
la@+ǬdP!ד=:W_ޜ|6PYr֛o|vvς8𘟒K"4M.X?M0}A^]ȏ6yUQ1v٪t^Rк1]b*ap@#Ta>!Rf(.9e5Ln)}W$?Fxa@UkiCt	
1}2WJ]1NÙV\֤ž'_Buo?8t7rFXY]Tɥmq*㴕L
X]m%&3+Z27h@^C^6@VF7MoQPAM#_ˍ|4uFHFmç/MlCx,L<8/ 4Z._15L>0;1:t{Q93@}/29s[]Sьd,4+yii:U_W<΃>5Ck5Z*x^9)XnkӆR6!8V~TjZUIg! R<1?t">%E)}M=׵|Jˮ+qQLrZ='=׸6c{1_HW蘇tL <4b/CO=J#ku+CO?hI9S(Az7C-̵>+!ti{%S,2NQF!
gcnh#[d/smRZqɻ՞\LCihhDUll~oZlYF%g^SG-]*h@5ZKàeեzZYG64TѯEC[Սz-I7mj_(t4MY-(&VVL`[7d僉:xu&'6zg:ψO!QZtN*xuǯT%1T/-0G2tI.:	Z*2k?jy_{^Y56S[WX20I:҆kL!}}R+lÏeˈ@#	z̙F^wX*(Z\=r%Fq|2%6|,`K?u(;DvJzՒSEdsJ˃0j+XP
ncnKpa+CrDR<CM2iI%"r	$~dlIw}Yc'=SS8qLּ;tiFeCtq+dfv1~Gdw,XA RIE'}0kǀw`lwg*HXlV݈e֕B(tef2/ub+vf!#lIiY^a)kMHW6:b7K!/8]|øeVp0s8.ECۯXy*l/Ђ7j 0U+S^3q.2_sKpAl蝚ј egɨ`/_kR)Y elXlZb!~~#Rg/8ْ2]@+Zϫ3f|18};lWcƢ@=KdYڅox:>	0ZAWn2+	62E>,+Ckȇ/k/pz,JǷJUL:߳BCha3$@z0 fUmdr%UZ*m!5高5,mLdGh@5ړA}7]U5fɤ`b>*0Qd$4*MyΣ<Xn(Y\&B_xwgĸԽ`.㶚>е>]XUy as\p,U==xucv삈,х{Ux<UdAҸ+SF=ZI+Ɇ5bLWIGX֝NNh۴<{gшTRͦWtkP^ŧs)_-6!!OXE~zW\-	Jqw+@QhcE+K蒋ɼ].{z.5WMGnɗuEt^'k3!S/Y66,Y4S3Z	3KUk\nf%j5hhe)93]fwI}l"uJWwZ,|0җFrPR sz
Eo{?z5݁VQx52@00zp!e](ZĜ5nܯtO5W|fA`",A[[zvރ޳ggLuK<\g<lWBY\Y[ uk_ˋyßg<UWS4RD*ZM#mƛQҾd0:J+/iyz+5YRl%
VXVsZllw3IWߏ>~pWs4T|d(XmWLR]rY:.\MZL"ꑩRS.xFٰ(װ7ZaN2nUYO"{:[օoKENhb
ϯhptf{;V`H*}n{wk*6cmiSY1In$RЙ1ilP%l| 1H!^ca= hdZM1鄊*NJP*]] RYweVbұ#qyi,B 
 G_}6|:1jdpj k=TOK}?{@(G[e& `\^}~fW8mL:_d%[49% 'W7u/2_yQkK"sƿ1c2D!IHDĖjV)݋X9'_]z[@ʭI k8uu*T=ԓd*LBM 1qqb޲ZY+E>Pj)CUO(-Jku5Eb)*X9?I1̞o;$%1$M<-ZR[-尒xhXHh\+8VXtM&bRi0+Mo`*ډJ8遾#ve!Q/Џ7\.#7\Р-XqমIPB;sZ|0o=ȼ籷ͱ_4wG'Ri0zE_8I'm?̻1t_|j
zr7X}߾O&*cC@oyG7kljA-xjsu%Ek3bSN;v}A22
=q72Eڗ7A8h^ImH?(kwjQ>KkFvȍGsZ5EA~Zlv/a]!5#6kZv.Q}D
e";ʅ+0֯9
5;[Ft1s^׭з.8PM_1jҦ1rC
o,g8ㆱ)SplYۃ1}-_ 拀g`W6e6ZRPp^-I`}1?k] DV՝Ud4R{eHFfjzgjq9|h +tKM7v1הTi3ڤ63gXݩQΨ&3,uM2E[^yS:X(qU3t&R3z{f<kxt'D9̂U#m˫øf ϥe{WEmhdr	SpwCFi*m c/`Fg;kG`yJ-	5CԳif:Xf$ԳU̝P)sGѫh)IΝsl^
;FPGP^9
9Ǚa[L릓OTd/!{Y'_icNK/BAu|<ɐC]vx4+x"SJ6C5#043aȯ|{Ctdt{Rd/N&aS>(O
s/Uft{#(>OR,Y5+n+i6u:=^Xv83 5=B3e}EeuݣdR{;DXУ^VO-muSv\3B04{wxlCM[A"	+D5i	@sofьV1TiSa%jE ՓbrZs5jiJZEk_'?wo?6<J7__?SVĐnБA	-2ujl
n_D3~AߺUV+2,0sS-*qFMe!DJKhM[PL%Rzx鏻.	N/!F޽|4]8vNKWDb~4X?c1REP y`ugWtg1tCQcLX(0|5*P7[fe-O?(;g~5J_Y4 OϹ:hq13j
?QizԫVs59]uԑZ;ZhkkO ^3Rȫg3uN
2>!ˎ9tLdq[؛|QP`cQXDJg©*>#^tQ+z"ʀ֙ܔ<K7_]68'WLJ
+surHUި8wI2&W
7z!<iY\JY>5ea
Ñ9y{sIҳnKkc\+z(g2P;,knz{:KktI8̖_yn?^u-T{U$
Xmh;6"S@ZG6@	&0Rz&B7ɠ:PC]lYOLÿrd߇ljF>su;%<Щ<=IYz5=t+!E[Y'^ElW#ne'|PA)ɢL#[MYu5yU`;4LhZOx-
+UY (DIJ]mMDLTkxPc	;t"XLG[wF[ge[n)=SsZ:3_vM!]|T#va\iɸZLlW>'{ƨvJ7^woO_nflƱI}+wmv0>{	hJЯA@k7Y>mu["6#%i;MQ7N8Q;ߡ; ap1Woh,\ˮkj<[ۆY}YRg4dW+\'enD:\d?ۧ{ugָ/PW@;]]h^Z×Z_^֑Pp|G<j.ł[	gO5P2."82J<6}BI{ō23$<Q_>AѸw{̯9@OMѮ
&Z&VEmJYbcX|ip[82;iiqmnjgƶ5BӦo;١
mQgsf٦2i+qf:JT{]['~Y/u
?˲(u?nRaIn[3vWvݎw6Tc.c?V>6G&m`fˆc٠8E_++4}=)|׺숃;.[4dENx1
o
ceGz};U`k/ڻbHʊ%F*:[P*`+LgtWnQ~k.LUPX^:c3qgpiMs̜'1BH{06ʈIFP,+ȻGӋW~PWSRTT0;oه$_O-$u"oJL wP{/ƟK>Uf tor:*nՈ"' W?;6#]84qtN^~Ha9
=Դdxh\uuOamgin^]JrUyٻGs:#6D;A.(<W%d8l8¼ŨA޾ǣ/o_}zo^gQUKH	8rU/6snxhJ`7]y(zZJNOx9 [z4\,cj}5_%8@"bf΋LG~PlynZ?%^w_N^~|7߿B#X%	?&qn݁ Vꍜ$ܣ2O3f w@@V>0VE
}J"A%PB<@hGy.?'<miA!M͙33K[*޹hXoJ\
R)B!*xGʮZo^ۭ]DlEje6sH/{\YA0Ҵ	kM\!sTs$*(cQOuۨW1{lCgBIQ]Ugʣn	Ax6kU[$s-)-f5VN|be|wi 3򻝧{rg%C!LEA-,w5
(60AJ
Ϻ+ ǫއ5$b3 CWvbTn:q&DV&@'p\ӰsR<g٠4(JJ:W!{ނ,TQ!(}|/me5ݐuЕ1H)㫳ɏYݵ74$]Edr5v#[٫̪dؔcl,)y}5Sx('Km76A:I>EvrDF+=m.QFXYK!񝪅Z=.[T+d<*.ʃM;zi?gL>J	hTrRdv<~0>Y>-wy%v#0(P5=,kx@.E)Es|'u*@a#2 #-[?PP)f@/c`V:@l&8Oгɇ0:77ɩN4?Ե`ŷڕ6|ǩkY+[v4'ӳirڱ#5Y$Srx i+,Q?">O3]b Ί{6!z/D%NE~J`LxPwDy<K'r$FSX WϤc
.N^~~>zo_x_^דW3J>40$ȉD@=@xHOY:&q0As?x|	kxWitzL(KqXY8q??DAs&:]¡|Q[puiHx:Y-S B$2$[y>˯F8QJ+_EvfNH5P8
.8*5vbmS5<845a_*50f$庲'۰ ;A1HU\t$AD@`M(ze!F_R1.m_v0Cu5oakk!?_4NudϩSMc+:Tjfh p,5㪥cIx+{D;aSkm#	DxDb$FVY`@ʉP3.=ĉP94bQOv4k$K1nznZj# ?WײX(&	mܸM4^0"UL(ğأ &~NgLg+p7}*:gg{x^U&I$uXgDK!<|Up Lb(99o@vwΩ4'9EԚ1Vro)4})YGnaMGE+s42f7}.ԭ#@@H \U=s3<]XEFFFƂ\~yY*i"eH *.͒%踸/7ǝ HPb`\D7P7 qGh]?Oʡ_,\FL8*.t,蚀&o̘шEMi4
)3_e?҇
4~W[ǉ6kRH2XĢATJ=+1VI8T&e&~OtV޴ptng!2޻=ȣ?BnmUPG\zz;\q4SOD%[an	0=ԮS7~ [.pe}12v5;[ˮ/|,0ؕe&$1?!J6k~|00#pm.=.ekU>!S7)^L={umϣL+	h`*?|[	yy:E?DQQPsb2(U_ (+h)^T)ר@>X` nЌ/vmPpC@yT]d]em]k^5hoJc
"7xEh"lzvbnƛ62XMq?~%Oݒ:7MӋ*ҦxT᩹eTR?*b)#u~-l]}&@H;UT+yS` $JW4[m$
?"D!&aV>- ao;}?MWzЃ\76iGtIc(b%τ[-,؈i/W얘~1q/:zՕyhoH?Lxɮzͥ__ٮ7xkC-,}ꚞO ٗvQV?)@n>PQUZ+?Qa_}4Pq=igYvXGE*$"CFZD/v,㌍kKu+;6,ۛ%B{NAhg2wUd`!jWk4ڽwJ:(OSN~"5kfj:nd':eRAniZ2utūU2*.bᘅhWZƾN0uө8bŇ")e:s|3MyѤW5ҬU- 0iзzeÑ(1fL纽ЪRdykc'C;w{kc¥k-U#H\Fh[lNkWZԱM?6ށASA미D?N|1'.*+ qمRO{#
ƪY7||ƙt'A|Pu}8wtU`Ĥi/ڣ/VBHr jFĵf*1\	Vg&ˎ':ɖ>RZQ*\]j¢fh(i3N&tph^L+fүD%zj7kYn9uIݍzdr =Ik{XsdkLbAn2"LqH$4Eat=ߡ	+qhn4t32`U-N5iSzCzz9[72_ϛ|!N[w#>o2'u' 9i3ݍmˠٟ2>x0L¿ q:Qˌ+fUk=+1Q5֥͘efDzs `>D> 5̼#R!<c[S.,)BzOcmR`>P9B ђzZ[EaŧMkMh!OtE,cz17:.0rǡwAy
Z~rtZϐ09!-%pce`yqu%`wez|rJO+JA(8[鏪".(!Pك4u3]_A kSf7ْ+nItPe'#&l+ߏ q[f6^w7s-S`s,GǐE !)*dU13ld-9|bV8a	B0E/7 A tNz;&"/HpZn!;GP;ȍwf1'M?3FCo+#r,uL9lưX}wM!E)jL$z[1uEy(Їz569^lHb`iwNjoL@/N]CNӸ;Y :i	c&Ίs`8|Dz4C"tD{<7ᥟW'$lxM$ψ?8n]02wzǃhBh~ϿpǉH3~GI8}YWEcN!u,+<ƍVx߳˅DWf*\cۤ>'I-m앉ByTZ(KLJ4=HYDr^P!(,dRf |mA7/fCfxxdmqOwl
g
aakIM2viA0^J4/ąwH=@gH`T񝶦eMqn'9O	[)n`\8N9])q^-is˦ol>@kʤ8iZSzdUH63BVjDWRnZ	vJt
BzAi*KYGS;;	ebD%%
#[hMHg"I[|]y1	FBc ,#0ṟ#6跅ߡF2N"vFpS`pHU\Ɩg>d xԥe!BZJeZ0ai~ڸ`2>XCľGL`3D	8fPfi>i2kvh#c=!0Ze惘5Fܟ
Rd}}vH'qUSƎWN.0d(U)f/2԰T-X0RZ|EƇooKz-ǭ i^(U	6(k`dpg)N['ʓׇsD+e9l?9{CM 	]3 
dȜv%YDh.)O!d}
32ΐ{5~?@Ǔils؆@6E{dZރKy2A6b۾Tߴ-ZIы.9b59,@CbUxIHY%2)1R.o6DweR\/K~`o;RC1|#c7	bN\pxq>D
6\$iB!0:4ۀEAZ1ń԰|ܑѧxh%{2s 5a| ̬g)O̸JANWB0gJa^]^4x8x}v[	JR]Z
[9G]۞b-;UqT3uu}g(,kY%_wdq8,%1 3? 6)
caE|sL{\yM.]m*gmE6" r+%LTwm#}Oyv	
70q3n	Rܞo1@ĉ (̦]P­]7US[S_%5Rϧb
Z ),	16puŚ$iYO"y7谜v<Ckr)f]H&ZibvSA_k%qrZ3ΔۉV;.@K6Pè>m?qG+fV0i,來|nŴw=b6ga{%_bE.4VZYa4e"eNҊۣXS{ĹAآ|fO` z~0"RfK!<&'kV$CrsReW]	W<>6M?S.)npB?R%	6?{b8`\QdUJ:H8N/ku=3~y^צ@o5WMi}t}e]'
7P" CUmt`EYG^o_ƾL˜DNOW6}ntcVўڎ_w2	r;3r<
d@^+E_m/q<]0Ϧwp*M a1Go	qM#Td=i(rt^mwU}+ᘚXCu`"sLw!Ψ59Aj]_>݈㵞\*Գ31ŴݷEd/cs0~G'E7>t6
99"3fJLC[h`	L qDKG72vpȴIpȍ,)ܑMFMxlHa%ݢJ9	(KXz]uph_mAY
X %)X-RƬg
ALXY_w(O= #ہZKү
ZOc	C\ȼ/"<!G C_\&iT~9WpҸor=cGkM8e*X|EakaX̣(<U2>iX ^.6Tª25կXӺ|ۭz0:^q<5=z-YJ7Q@2
[D%@R}fب''&~\\kєri,(Bz5*a-ytъ3[w`CM0ؕhZӃ0dy1G	v)B^S1j :eN}[LΚ$jHf̿\1=fЕ+Az~q859Gd̃bȒ̵^|
89am{tбEǅ/.WcV0yGWөBEg)9l~WnSgqbxP̰*y@ÝY	,r}4ybs01 =a<ͨ.r߉mwtS'i26ThH}E`)]8L@/^=>bky8/n|>DQvR@UcTVƜuqj >|]Vv]e;99LÍͿ^@NG)6ɟNv)hӡIW|G(~n?0	А1)=\VW:=^Ŷ۔,׷-$ܜZr%êjU= PG}z~ݤ|'g5EZ>]덦G];r]O`h3{5Ĉ)ņ	{X:f.CS4mV>@]3_;0GLs	;{0YN0~ycnAEH_.sz,[d$bf?MM5v(H#oFŨ:%\*xUB՛튌LS0aOFAQeQ^[ӜSq7qh6Ul,L=J?mgtD}sCɊ'|%ParM*mjsmnaSxEX8^l-rRdMrټ_K~:j>"?p++}\1DX|n
B&9{R>$Χ4׬)&czwք8©jx'4N-H,?lw"@L|]>ClݐuU#i6b:;>B/K¿~CÃ-)Q*Q
[~)[`^}RWHZ_Ho@#.ڈvwinSc^@j=NXSMAshƜH%$~/QlF?L*k7Qdގqo.#W.n!	(Ǝ[j~цM׏'s kE^r>}=>0oWi`
lE>WwC?@zZ76vD0!f|f_jqWl6;Jɧϟ^cW !m2L-dipP:l]8ﳫzeF RΝNPŋӶ TJ!U3]O,FB$j?|)	T:SBdB =4#7컽ie.d[v͏"# e-pwUFN>PL-S;2/Z|!ݤ!;j'n{7"ia|JA"{h-8.5Ś-NK
-b
70^Z+	D34du	N`j赳aħkhd4C*Qxl,Kz-Ru_چքrJP*4C˨a'yESmBe.vZL,aOp;a>1f#YjDl~d;vsKiEK5Vaqw➾:E~{N9͢&2S๯غwO}t)2]8{~ߘ^k~60mCPH:@'\yDs0R7aB5.p3K;k%VzMݭptH6:Xk72`vLv$ &l@'u]'CK6Rs((͢M)3N33!0^ڭc@><L1l|a8y0sЖ`5Կىs=Z\mN2l.s^aKri0'f6cCd雅C[۱$$U\B#mK/ 7(PE
SD-nүXU;2Ҭ3%ha{NB]q_ ^g_.OUAM%dR`iutuWq8~\9њ}~vm)أNrgA(ˬX52=o:[Fz)̚%ɟ'42 ;ۿ|fH_wMNAKK/xkKx+ZΤ"ѰcAo (; Ҙl]ANBooa:̮[@	h?xI烓Ő,M5%Es0$8h:d!f98^}p=ZB###^< evEoP!f+s4vHJdJ,SyvBIga<VMIjfl#Hf=Dh("Z}.*p}Dx{˂kXPFT<[	6.Eՙ!IpUǧ"MBͥo/e`%$uBqɗTV(iC3/,ν0_OIJg#S~~bh?".[j_ۚ	1r	Nq)/6<!8m=۟:8Y%l*HcA0'~J/a3:YE;i(-,DoFmw87e:A7"ՃCaZ	tp~G4nѕL # ǑDp"?Gow0Mx7\n;N1`j9!7^>iߵ{?Ѐe2؋,hBC]sA: anȬ,6#|@	83
0?iBNӌZ%9}Najzү?s>ciNu{´9050}o/]G9J4}g%4eum`&gZ^p	=p<ԞB4j 0v> 镌ޝ s+(/ }	wSI_u[bd!aqVPԭ1c=L`NyCa-!OaJ-C	te
,]rfN) Qݶuo>z 'R" =]xޝ_&("64"0:i'py0YhȅIo.ITnh1:
da4$m5='F!hj4ĪUinm0.)n[M-[DaLW(ӽM{![y1g08`M̀iAi)$	E$WNf g(p#R<C	IIɧi
LLFo}FYf7x[g5Ls#*a^ڮ6+o̐ո~E`TDPjutJU|Ga5+2s=+IՏM"&TAavSr@S6q֝&I1j90S.T_[xjT'T?L$ؼ`q]+*3q=W4'6^Vx'ޝG9(aLQp~4Y(;|H'=P mZ`J]:^}gړA-k|e&viLٻ]0~~E>gyv;yk hT1nɢ,gtc^70"7.R(@0z_nq{F@F~TUzǵ{ VDaazO`7>X^L-S	2}i8n{mQ@đP`RM8nw?Lti-vLDnΛk?Hvӥ-Qjs\ 1z>$h}}e~
>b3-[3Xx!ԏ,­?I!q	8am{(39@	SaVg}_5tL91?(1v4}']>I6s$ yH/גS>KK2)<!nj`®?	=<U	*ݵw*)d4>϶*Z#
 J:67|zǒI|d|^))Xf>D&qk6[}hDخ۸[0,>֪mMQ "}c8ҳ%.Sgp}P8ypE/n;V:Xݖ^_31Q]6cI/We<Vǔ"Ѿю`jgU|bͰN9M;@9!(>~Н|F dq" |~mLUrwCF+N %Ù%5ur3+r7(&ec}44业qob Z	N/Ɯ )2'2ut0}{4t"(A?顯rtobDC1Q``F@Ss {@wC;,w_hbyQs?7
?`"m%lHz6GM|D)4S!S<);@4ҟ1O$@I4{54fBGM{9u5Wʵ,@52|ǽ/~'7<~З_5|~-g7~Z51LۍPlj[`;>j .7wqR' Bȕ-fA%2[sZ{P{u72"TGv
nmfWMl/NYb}$<hMl鼂cQK G5ePmpǟθ'wp0
Okʥ=>(C2z3;A|qa(HEyG61mj ahSdb!o9nTH)NS톓ަc#$Ceԡ3= ;/tmA=hU2 ͬ8ـ#=]`J^ډ[[oY;kwM8M&9-S0*l1M<-DZ F0YS+
 #
sTɴSP..BTkՌvY:af70q6Ҵ0<aH]!qIv5׷˪hJf/J+jZ̧	B{t͵h#'+	ZԾL".3ֲ'!< HG&=IcN\֊1;j%gaz0-U46=ӚjZnf2B퍄l0l}[yI@$IL;0aNTr_wONZSgqw(I.Y\#
/r͝ESxjzWz;WT?iyLr6	3)	f违&	z!`z4rR38/G3$sIګ4	WķoDc-W򞅔\S+SβsVa{Jc{#ȏJ+ }bŊq?ӼZQ&W;Py{X /8_MX*I7?ow6S[[k"2XaĶLbj )euIthq(f*˵M/Ypq!&F1b5qU3WEw=L3Ӛ>a^Za8	v{B/TJI"ѽ޻PP3h>Slxh 1QHoA4uoPFb!AS ]X#)+a`&)K// g
88^Cw $FH>#hm܁]Rѐ%6U9`1o6} .oTc>D$
! }0_В!Oy;uQaKؑEs'POqȢQj]w$~R.qPKpLH[L37\C"-2nn6$0*쾿?,V"3(Lm[͟~U̟<y<}|}uwە(9龩~\W4KP3(`#
	?(`<N5".0.C~HL[f;Yk;C2w6/XijdPI6VN=Uх-p<.&FNP/4LN/ 9;Hdw*in\4RxjL {u-Mq)_7C
/Ym$%?Q +NSZۅ(vV'*O\?"Z`:Ӭ܁jR>BZOT7ᅲ6jAUaDAWCA7mo*@{jߐ![WxH4zd)tK7DC*DxoFx1D`zq'[BB}|Wfi^ٶ^߾6
o8eetzI|6,.fj77A+%7p6'n` w̭=ԇ':,Auڛߌv(JjxM?/0AKrbF鷺o<`7"^`g-mAj}nhR(9Hcĩ_h/Q]OipvE,vFY,!5KÂ
W^l%/m^ݢ̔&ASmُ?V5g?cy"	$ȣ:N~4ʊzyD[>z'whVIbJ˩s]2B
4pޔ)xF#B</2Ӓ@'u6vԈL8yZEjٖ*m4x6*p(̅dyE'0	(djmB]-&."@(~؅l^@h\XJ/g϶iБjx< s$wS
c5r:^gM&
>W8wB?s	TYˮ2hL)Rd\)Zmtg@ 0Nۀu)zHcPՈC$,RTw4VOX0h||^vnqxg,{0Anhzf DaIDYlG%l: lh,P?l3Ml3=1+LPԶ&Wf.5ynx:p
|ꊻǑɦm6$('O!&%WѬw	,Ww0c d*NŻy{~ɝZ+X r2ↂbw_(ԇ nsiw} _r0w_$0[FWMf?*M5N5I.$ݩP`Nkoϝ]FҎaIfz6U`viZ8?>Li*kyu^bz'c ϰYOnh嬸yekD7~DL5x+m:9p
?xWo%r'29LFN˧k0"4$7?Pppd	%'0avDbxlgCM♠r=+8	Vgrʄ"1"k@Fs~]+W~[:Զ?:&FR˄.cWc	F$%	#Tf͠0[uM7Ն$pYcRv:1HSF]m\ḃJgK+68LND̆?jG^v8g쭚3gc{C!!DP/nAZ[ֶwlIQ8&"\#NG.#V怇8+
\W҉lE3v<N%Jf3Fį__QW^rnj6mCoilb`2i/Jp0_)s#puc>Ҳĵ/OIPǤ_*W`M=-,|xyQx|xHHz;UjNXS+G:~b ]0n=ԡ:mlpS%N.MTF϶iDLT]hGi *q9=E[-IG^隥_%=`O%־BĮDƪ},|ZoJM%CGԇ2!'-p2igigW?Uq):뭱Y\:a4
7F{IVt	xvR_]?vҦݏa|7^{ zbqs'hevQ[!0Z=dHw ^YNm)ĄmS?BG?`o
Odd,I9-FZ8֙] c}sS]a=1xdؽIף%"1:"+ʇiEnKZ	)bAkM<ەrZSAVy@@tV~lip{D[!V@|a4{66~X	*P;P{BUB<<pD2zSq# 5u*'
Fy9ڃz5heүLj7Z:B=8	tGVNINS"`q+h$nr(p4.Hz	qSIZ|&qa`&f_Z߼uf}ͽM7
|!u&V}UW_A+hmbGHD+ OT١g>
4.h|yBr	WmH8!v=߮D8_wDߍ+:!2/nY]y@BoO3+?~N~ד<o,f <&l,u%MھM&^I24	Sm&:*	ߴ݈VٽDgWJqX:Q1~EdΕ&ʠTlCec%}~xKw%A>6e9b)6I,saKٚ?E,XY,Ղb)xQ,ժCKY2&X|^RetT T5KOm;["s,Jg&YߒȢj`Jh ~T*U5yU*cg,-h)x12:P/Da?:2\	e98e-w.JГpm	(ㄔ?P_$׈GXF+[87B0<>5I${_Zc,̻u5#
cCsPNL(INofeZE;V5aq	`ȑVEA5BOlH.~ʽF<@an|1x2uvC,`?ef9MӤCNP\[gN61 S>Z`1/z,A/18	j@C;懣aР5l&0lJg+xyu/e1-6bOegjiw-ގG\d/a(K\61cc&!'$9o{6ϑAk4ف9r4m_@&}92?BPiT-CmkBi6gg&ѷh̙)"1>IKH[32U։gfwbTq|3c|#j~>HIa$-CVuh/r%D|In5ƶ:tѸL*QQ&	x$7`iRt0ryIFP܌ˇ<Ls\Lt1z["KO"5%"`0u!&`u*1PV'/&2wzp&nwT1P{>uڰ3sE3I[x4уzey	
ㆱ Ȧ&.]]zsӳ]-N>tCI.mv;O&8$ʒ?@LXtPP樆_T{NLA(Ҝc兘yqf:(W.K;d~gG+ظ۴0'p+Z,-'xWE;E>&4oI#JĦu?Sh+P(q^ڭH)HG_4D"$5][.'	*-(QZF(sB*|<2SVp@܄yWZ{Xv(2c37?
5vCJ/rh1.7/Z	;\ @wݻܮHcUsr]T8k,x	շ%G,b	P/r89b*L*Q1N)#dBxm9Q3zF:[yh _WV^.MZVY|:4;rXGS%&wB]dt{E,٭5:U&j1G2v(xk>kk^]bvy}3mnv}}#0#"FiR-5`02ԲMJ)3NIu{h^E%Ze**ڶY[E:wSꐰH}ԍ.X4
 @ff
/ =od*X7"7"[vtN#hx[y#jhLX͋`o䌅'L(!x-m
fwOFL}(z"`ͦA;d
{=$;?ِ5ܭ켅F(ia&RK)Q@BXwp;DyF[y=dsv.
"?ݲ5߶s (iq__0[z'p>DB.kdk/+0;{#<_0M;iTn(l,[M;e'U	qdt?9~(yiG8ukГqf(ppdExX:n\c'EW'Ȏҕa+Z='mw&H6-N%HߵoV7,SFWbqYXq3޳f/#p.B7YkLNU[y3?`*1 &(~R4`ORä;
Cp4֙e`Sn'Yn{+_LΖ\;-	S,UIN)ՂnE{ibB$I4O۲Ԝ,7ul؝<{Oh7ԆHx"kR=w(zAjBb~Vf(Jv3v]J~"<:c!.YF<oQ8hӾA7'&D*AwՉ\fn#6sUggBS*GdxzM1.RGW
GHÛOX23|a7gh"S^웭Ja.r@$ShX-{ɟԨwz{~ȮsNʱ?*Ixnoj1rje%rru|,9ڻ)*J$ץrgCJgrJކ$w@m0/<R.糷^;T3YλMd-vlvg=ogsݻOG\6v<V4$lVKNOIo2viĿcb5:pڐpnU8Oqo{	7vrQhmwv}auyS{Aq4[;ܣZ׳VW[FѲNT3F|N=SϹmA2\6N	WS{TYkt ,r!?G]_])ljPګ``֞]gV9:8W}m3I/qMFU0קonG*é=Pgꟴ[^\UV~8J:v"6OtrET/cjβ~e0WҰQ8*< "\'F>1-g?љNYq%=@VCb19-}Qwg5lg^{\LZ_kTj(w.sǡ^ >F򓍯}7]m6WQwzy_}H5)\,SXwbU,%rmPOPh6ڞGb\tΔY6McaW,ŜWId	yk_/kE*bSCͰq,\^&j|Pn܀/y^R!9I*C12_ES~<.|{TT5pgưwڷ}u4U6nD:؜VmR1ln~/UUĩ]I`1O}Pe~VZj\6R&۳JT;^3|#sTWێ를y5LsNP?2iT'OݦIN*kpꍊٙ{{pK.熿)Cau'ķ~oZW*UTdVi^ްwʻ㲖	ifR߻Wc/UcQOtW<H7Oe07땿3NscH΅xHlc,U
V1-g\RMtiRAsX蕹be>ugl9ȃ[TAv>,
|Eg7BmY*+aiwu9GwU?<HCol2^3%Qsҩ,,'lcWIVZϲ`72dju	dZ&ӬnP#g|[KtS͍S/:8hbZ"'znEJmlŔOU`=ӳT]RDI?>yy]4U!,NBh$4g%O	!
܋/oLR>Qw=Rq嫬Y9ZnfqVeVho궨Í8?ԗήTUӨ\j&b!%,JǱ8I1[:ah7KJ?2vXSȥ&Q$Eh+tٮ,'[*'E\<ufM{r]ߝmW:^JTj$GB~&YmXX-:+Y_lN4,vԸR[ɱ	tjnQö(aۍ3`F]Hnn}.3{L-&72]%}w=ƊR*"VNub}WWˇs=~Sx6)|~RbRFJfûbX[3r"6݆P M"Px/U%s7C_rO6Sp+eLr>艹oo⺗nAE<Ų\Bg)P׃̺"nXj5G|4<5Ħ9TtΞγ͸eJn?kzRVX͊Q*-{Ocmֽ(Ϋ1M;]x[:l0ufX)%9[u/T:1,%y&f[{DRC?DUsBPʥPسMNjBgR:<d2$anub%iGz*ܪI	5='	k{e[޺6\7-qֳR(y㴜։^<f1.zT\ԬM4xR9Q4#Qbj8rZVRe˰r]'T':*
z}+Rb7;ȁ:,Bԯ@<WFz:}DRvwò8LlREuMd#['6P*mz/R^[H/zt}O9WMp͖f欼|9P=:UݩMlLCrԞ.-3MkJ0Us>GptwJ\hܪdwR왦EJt>P#:<&֩^"̊C	l48̍{,	^m'28[Bf7zu,u@ONZg;wdN{3'[4VsNpLdx.]]eRb8[ޡGln1uwd4CO8x\LtΆb7Lb(O]9aJ~)^#X*6"= ! ^Pz4Fyz+ϋRs%S`(~NܓosòZIknw=-$F^uǚ9ICo=)/Yx
r	z|LG\be:hwڤ\D8NFDN>dw
W85Y"bܣf\v[)&N8aK1EsK9u!Qܷrt?XT9;n6(Խ!tusݭ@O9]ENyGX:^aߩa>yEU\6b=_DvI QKw*78 zNC˧ۥVvU%=ծY#v3o?{:Hr#=AiQ~)qkbKzvR2K'UF(Lr3y]FwO]1e}jh(ZWnRyiҬ C:xzRUH0XusΗ`pE+0g;Ytfx)ȱ4wo8:`*-UbOfxRiQ6MQ[>OS58EyPjYf<@Wd4Y$%SiiFM/$JR..՟ȃ?hiU
z[ȩH{L;
P9]Z=i8ҫHr"3[mvUar7
`2as4|	?\Q	`峷yzt{Srhs&Wɕܪ,j<?.PNKF6V(Bn0G70X$(ebü,}y3:+W|NDRE-avi 7-o4Uڵ{P-%݉ث (WGd .3BupXs@}uP䷙I7iwmlF̾OvX gC)WSvrnoR`_pIYѲ	N8yl`{DM*(ΨJcPn\l5!3|Qh)(\LF3]v	8AM=[nZB-?k&媥BiQlOUsysk%9*u"P[^bWG ˥Ie߉5ն0ˣJ*GFrYEށ۶o
ʑWB^wTq}7u2V&|yT;y_2!q&]azJZ&sEhכi=r^K'r~Խ57CJzcb?qZ)4uf1%=_$Xpb2)OpȄh%+mTNNw8ՃYb0יmmJb8f*7;Ԥ"bJ7a~-ϝmtWk.NfrVf|նm
h4|caMR۲o8cps&ҽ*)@l%VsUF\ ,BZ)m]BZ_F"<?BݥIOԗE4kDڷ]TIp*NgHn >5[C.'%ןL`*w.~ 򻻧yx=vfOޑOӥa0.@}NFj^%5M7V=7`
[fHSyͭr{wc~{x>[mc8^N
Di7̬"*xRMstJ)7[VfCWVr,,1 _ŞLYץq(k(nqi4t8c,C}TjyL/5x_gf1:RamaL2',?vLusD֎Tf))sLQ#s:Q;FSK,7
q6.քŁW}7MnWoܫ+'a
3bb~싙PhRGae 7XoPUAr|h"*sc+V^
+o#xNrSIe,tƥO)	bVrlY`;GٺohBbPOK|kRSE zWf*SX&"nwBn=rĸ=i9Stn*
f#.0IgQi8y|M>*'pؕ7|d9m;Mī4>4>P0LN)54I3<j~iH3wԕ$)QBpfl[xNDzSEkТ9M;z3Zuz0(d |S̷e(26J4)5pʜԂZ]>|ISD;VGiM/$ve^G2J]pֳg5H䦋S-z.6I?Y3|X]#R8V};uwXjzjiJđ*?ߎS,vBvifș@rv~~trp<Z%p<?nVqEH8ϧP:
Ee~`&ׁѠ^9L}M` [O>dj[={Finqo861p5W[O~jNh 58ۺ'#=?TE^JNv`6GhN\lqG]/=.Zw*:r7pGVy5!+Fl\SWNM~OrtvGЪH.</`m'FM!y^Ŵ*܍;	Muݜb]k1DUGTw^MO?V[YV舢 U] 3x޻WD^Rs^{#\`a.&&g7֝7GZ&~'h]@ /A6sۑdGI6kHRM9^zT`hvo:8-306jB)~K-tib;UԬxnyX'0`D-~jb}t*M#$
yah|m^P`zk 6P㥍uWPTd6<Kh/벂SXqFY}&y'cMjBnn}6oEO͘,­X= 	aLAh(?%7
w=˜徾i-l+5g5e}%BP: O6!( R$*3;grrt.2/{[sd:B:N1F/J78@Ԉr1+bf%XjzdԳLŀM+S8[:%na}ft1Ss)Jpr#*_[zD_܂rCv'pTc5[E\q~a1b9әR-7cfY^mB`WB.qjvB6x{Sj~3n|%	{7p|WO	wD?k#9M,fX}Uy_͋ܯ&B=יTi2G'lHk"Џ+'xëZ06[1u#bBBh<]{Pn Xv9T0^ȶtB&*{ɌO">/)iK]R߽[3 B֗%{%!8E4"Imq1&d^."p+[-U  ,t;vh.k4bRXf뻢ʶBF Wz3 &F)g%%)_i:^R[v1<xq(L7B{Ƃٞ|HAI4dGF k6l:$_W{냢FW6=Y%^somo:oFZ_dL53`ָ#!{l҉l9pH&D{vrxƆ9\qM#aUG?"y)2HhVGSy:FTVX?d @wG{D& %Gj,>m3MoWQU4UWbX~]B8̀bX144gc4'rKS`n>@ kayiV;M Ǵ h
F!U~wW1*WUҭ+DE"kMPϏ-*RJs#t醚11j3B(^cWb&607$|lRDALb@7 fx /@yYGZg_[!X"KknB/2iS71UBIte2VuvIV&e1'نn̐Dpi-U^f<T~ef}z34_VM:>~nUV3Y?r'vrG2~yO}:I}J3M	͵[BT	7#:l	b4ERuq$;^	INR7c>ZmDzIl	ɲI$',J{vgh9E;e:6} ԫ2W03Q\A9Gǈ)a ]sj[I%Rn>L{	 qv_8x;,IB+9%K6$r-\eSQI,*2&="ʓX
il7wwp(%_dІH`'BdB#tt¢;|)ucPpoD؎+.0oJ{$w?'4/%F9mU|]{^]9E3GC^Lhף}9qOTIЦf(cN)`	XvݏW1 {sCjm7-P+4ؗ7:NKb>jǡ`#h]~U93`_e;(Iط)52X
ľY#,&ZG(gAˇM%6mHw&VT>𝠦6Bxt)+O˙:>k-{h,4HII#ߧ9WVɱIeXWaH~(ҧDk:ݧEv*ni >0BlhFt)P~v/ן-Z<dXO^n}E7 OHK`úňP!po|HJMQx K8@1Q$ؘ"p۔a2ɑk0;M"YT_ #F)H	~-0i=h@R.$z36P4ÜR\dk+{hHƁQ
%oyc`QbSd/Pkx@H<ZJUo2q|qN\l`&+ͷ_r᎞qYeϛOogCXYrs2*IEvcxV.;o>ku@a>E
)m]%";Ǧ@(&>ez8H-{^t=B=P)CRȾ>5qLx#-A! TgzFͼXwKs$Ď,-CЎE^tiLGvgV3-Vp$R`޿ŹeSIZM2%~7AX'TY/K7px btF[6IYnyS? 1<-x0|<L-9FU{"Z$+ZuB& VY6@0Htidq)0'xȨDKH!;Ӓ0}3q]"kw٩U`22jH9h[nT?k#B6 ר&QGȲGc.rSc8^	:"|0(5t7Ikd&ntƮvr->Lg,QOEa91vU^X} 'Q<h{Ep%hN'th51W%vp$<bqv{m)uz 1˳l&5$nAi71ʋ(Ph<Ә1<ƳA0zTcYa=;p	_{Zb	2q}PBZ޲ޗn~@]/
ViddHw1c /DOP	@]P"!$U)>!Y4dz?تiٿw9	ruSYߒVLZG@VmqXW\!EʍhF/b C,fLD5#5z7^_>(9:Np'Ruefb!!Tl`~Ehf	j`JQQ:kl#Q)Qto9 \75Zzgvlf:{牔2?C>RLE$JQjڟ6nͅA0csk)G ';v~N{t,Ʃ`,P &!1?ՕK<d ˺%Z4it$:BI9M}4:kfDoށb1)}͗q@3¦PzRRÞp1K-ʛJ&M2!`;p>\7JX;x~ؘ]n	9	qTFVd
طF쬨5Hޙ
šOS<PG2_ lM\("uiܧgc]O1/Mtvg<-Y=|Tì@u Ty'HD-)U4ԪS(~yǁ^<o~J:PJs>#Mm[^3D~E(RoZ-قYpsW4L"i$+Gpz-i_H
BMX⟥U׿j)5Ϩ] 91D<~B.Zt2V<*Z'ZydbmD5۹&cFHD+ǼnC`m$)6$xFB!@6,7GY^CGP5(Znd:g[=zir=]юY%$c?)74:x9.]L
5"O':p^͇*Ix2yX8)[y	[{M. z	-Qx|#G+WK&͓Q;/:{h?"KYq#~ʻEbN唑':lv!elP$i-#	
)&a_Tak}p'2%Ir]kkT^e|&8? O7y?%ICn#Z<떦@
` P^v'Ʋ?⥀u
TPVjڝҕU;lP7Fp(_:ťV_#'[EKpIMKw9:΅}-Vo~x<	YF|N"5Rt#x%H؅Vd}љt.
ց]R#xD>\6g0%鷥{5rb}`嬬~xKð%VϚofgf%)THZՏ!v55t4NVкl|y]Y#{oteFLKj@$̗OkUrZs̓/($S: -Sΰ+7uCb F
5%>v~O!I.=7]iBE&4#Xi1I<lI=׽zHp(O>S6Ky/]N =Q`80r(5;{j ^OFؐXdE~.Z-몛U6PصS4ߐx:ֽ19YI!wq+qo[%urCʡ_vEs*.z@lfIOI?` }/*nW$W$*U؛A|(Ja㴉sPL,^"|u7B{+2`+K"w#?:k
#eu,xe!&C;uPP"Au(!p^7xJNxk/*k7eCaA($N ~}T׎vZ1oLT%50,sxԿagE72StWe^ivi6<B '<9BDK
gC~:o&ͩf1ymJ1f2u5CHnغ"/\~C4xvC	_~UPzkhx=~

nFL'XlevC6Jpq jMnfgbmO,%t\q(r0;?j6jTY,>[:w29}^&vb Pc3[h2.5t~Oߖ|FT`gX:`ZԎDͬ`=66aiMOaaP=
l[;5Ph1]j-QmXҀSsw6bd䳏r)^wAv &.'׺xudn_S>.6BDq̨B I|@,KEn0>>	=jmjޓ_T>JИ ;I>h,xf6ĕ(s(:`9gZz]c$w]Y,g,0Fgm }7_f&zHw!L'( #Xe'qIwOԌӄic[Ľɋ2_nXg]y#\tV6\ZXbLIC#!uыމze} PZ!Qgc ˲@Ynd'T A
@|e_>qAҊj>,sZU樍=HS48tԽFO2ue|[TRDF7u8(l2SWS~!2	B1K{B
.#'"2iLq|ެ\R@'KȮo佤EОh2U+
E,%8!螀=h3q@V$N_ Slr~mY .Kfd()8;Hp8=?-|2d&,L6s8c՛:&Uu	w'@QD#*5@Q)u`\;M2]	4m_+&qMEirET']bBl _DG߽r't̷\PB
 PF#k=jdo;-FnK)l	Ԋ_,z;@6feNT"h4ÿ8+QC%J+FRôj#qW<ӵ5]"ryfQ,ZZ&yvgaƫU4RW,S>샡}|^nKI*R#93J4S?0	5p Ѝic](t|!"k8"E`@#	lIXLta<LE`ĝoiP%Tl|$λ[3;hG]rr~ש&41#"_
ꗱMvH-Ε`q8k.QDJ5WX	]b4ng'~p78 ,4߭ԊA οj6I}0˾K
]16&Dki}1)҅'z"8YY`+0nnQ5*57$	' (v,d.ճoR%c̤bAnlD)Sdy },bśC\ݘtZ~%-;yI~4҉e\a)S9-a6mI^%љ3(/=:k9FU\ؠ$Y	H'(2sk_չs%Jwcu.r)i#2yx:Zt>NY7^;jZ>TݟCr7*.Em%e5:fOr:Nuk5n^af%hIR3;U3F{m@b18
}ub-_p*{kF5hgaVw:S<X$\5*cX,\cj%KTS=	.[N>}#ٜ+Lus{1zGTH0:3֚`t̗}-KF8$/&#ĳ٥N$*3whW	Ƽ`eז@,%IDMq+Yg5FhnmBu4O{\~~X3EzC2e)r(m_p_D/]F>vx}{03sƫ0yc禮;ɉ<;j,:;~J|ci](ܧm%v!3&N +!y-4gօ
=m:[m9"Xu1B
x
Wo2ՍA_kg8E`:73 ={xُz$|뙊Y	ؔnSa[Qs(^3)!eQB+wQC.%Or5{(g2rYw.|VQ:ky;rLV1/:nIWRB7!j;N}0?w9.H[Zم.xnu?wE;pH_E%ƿ8~CVzaN7["=#!1ؾnG@ %A}`ysE\<U* 1׫A' Դ4޴L?.	<S~}_]8ջW:i`#LZK^6h(,KAy7SmY/{.Mw:e g'Cx9/qŀ?K_qR:dqa`aYƩb-C"%zs̀10''FcTcl!wCU8]y0l#S7xn5?K5OQp1_8SFV,PȐWO,#H@8üa3$TrbۋJٕ^ŧҨϟ9:
eĈь2Ʌv	L׵jsWCE`]Pr;8Z]ɀx|V&(/8aO.1IU:+Ҽ ېrum(
??='h_
1W74eϊ_2x"u
b0aWZ٤ʪbF|i )X؎zKDHdqvB!9L{ɷ"l%7IuIo)j5La2<j5P7c(gy"`$3>klGd"T:k;f߿Jі^aCgUHƪp],z8?.=A"o"\CU
[iIK܏S;>PK0\!MIW,~\ ;)َ>B^1i{&"J0(@e,[/NnkG
¬{YNZł'IAŕnVrhm?Usw3mpY*` bˍKoaDu?W:(PݑMV4m?: BdbMJN?"jە%a YV1/SO	FҜ:GDH	p˸X^G7sB4	 %j"25Ntc|~3l{s4WY]>\趿:aɮ8|fқZmab64o߈k>[v]^oKkҋ0:*5VRc:d#Z|V.<Vzp,/YCȔu"
p#6gzr|ί݋X"BdAC27+RZ56)G#sHfm1i$n }Uk\f[{RB35㪂2aQxK(7ZFbikj<qjKkyLį'䭲臆0bπ87KJ[0dU91rʾ{y,zB'|ZW4IQf4uYA4/LTa	^s>LӴ2BF?HdQQS^4eQZжNr{6P	`*zW'Ǆ~>@I^`&$eqK ^倹
/7d`ɻ9FwPL霄 4l"z!xs' ";}Wu,ɟ/Ɋ7ފ)B[{%]f	E~Yruۄmcj42
R
TR͙sͯb
Bq(a}O6CF$"{iQ10#U,s漽~$^9\E /f;BV"R+>duD #OWe=͔iӝ鈡P?1y/W_0n@|MC|C" axFfxrJW'[h$RI'zl77DGi2~0'.w	iuw0;+%ijcwU"{ *wCL˓	tzcMv+TƆ$сCmNI3*(0 $!rk~⟆Xe2+Yw7Zi'EKt&}6R	̾)v!u^f_/Y<D+N1[^V\&1[{ *:,$O4G&	Rh1|^($$Yo.;QB-ߐIة&@_x+$'H#Px#i%Ʃ_CL1P:=D/I=YeH02ha 0~n+Tgi[0LtN^e}I,jZ'D@v_쓜>as2͕1nɹ	t_X&;;x,騪%]nh;^s
4uRg뺩3h)' Og&E3'~exw7Hv=*V,$E]on*lK>\Q<>7I{ylP
qpRbab7Kg[;  '$׹GRKILbpSHYFh?'~%Yk_p]i#(p/XEۯD$ -יPV}ྜྷMJYcD݂obdloZZװ^EzeL@tu!m	\áTsuφ1:nB']]ܛL9K m)`û;ȝTNfafClw23㪽,G﹝P}zHGT$\[جfW|)m`4%kY Z h`!V5g*=슰G^?HRqr;pCi<.L)|G\rH"'z1_{cf*KiMTub3LfJOuǼ޾w{WBgfJw_MVHRC.JOwYiG@*wQęlBfHSaw]5i?9u,c*El͖5\$6FRV}!@0.զ=l90 k
`pN>
1MKiCη8=L4.[zf&xoH`
x%<إ
Vʿ8<01`)U{to
NwhNvإϣ`R6TY}92a:[4~>'/&bHk{^Ʈ%)HZExmO~-(t14Zf$+w  Q b/NgeG;%B웱/F)T~*9QTt+%3$9NB?2"؆> 0|RhbM)b@U~K͊Ֆ	pCXU	qЭ G]:R߯[w`	( fkɣ)]%b+n"	+w$h4;Dv*R_;1))kFy'p}(oOىaNYQ?Ia.]Pv  vQڝ
&nO%קjr_2kT=7pVO `Zɛjqp
/1CĦ.XR%&@@%yVa* ӗ-7%xpM;?dwIaIj+B0;%%ݭD$h@8hȐAtA0QFC^F匥qL)ߑ5H%M(ok ^'11QDa/Ȓ;PC692o>bu9\,Q	SΦ/]DlݏAw荘R(&Sl(,eq/q`sܤ8FIj'zTh@8Sft<eN2yh0(h\cZ'C0|VC2& v|^
?[
 Aqˏ(CԐ-~rOvVGO
5X~`wW0,Bx3r#>	967raoI,U~ƨaHGU{h]=V\*!<YM딈RP=80YecjK323a1[aJ[U%?-)4o0h3 mc{I~ӿ?ݚq|0lՌLĖFJX<nw*rWeW._{Au<=c$})[7~Hduv|ACgkՄDÿ]y'&H\?"qݼUiJan-^6sr<"0~Ƨ<W`Ͼ#aGTy_?!w ߓ#|ow+K
l[~Zh(4E<֚Nߙ1֋xq
̽sLWTUhuVN=(u%a6a9 }QC2˫ d zcpR1L5UK0ml	魞tZԪGN14]$Y[]=f˚fAdւ?am ŝoy.K"Xn֒utT	=.NE8_	SDD7'UIs6Rn:ԃ3KeX_4kAtI-z{:/˴}ig9sKT=yM	ԟ/Mݥr&jV+l8f$>@PD?ܹ\ڷx22A;n` >:a"?^BVʗ8\BQCL\D{,6jMhGQ,=E		G0rUܜϼ^DTNbF
f{?t4i"]=[qP,`1Ӭ(y*XL?uqE14X܍6ܥ$8h]0W=Hy<~E0^O50Y<$@.	=UHIIowIZo͋#7q)|Ny2O#&Y&yaW@r!8r'YC3i#OKkʵwX/(d~̦yH s4ڊTgt{oQX_0X\0+b֍-d!P<Oɟ!-raP'Ug7|)UJտ!y0GG]_VO2թ[AY3E7SA'NGLkUvmk[	kҽ/4%V.m#E{sw	ʭ_Ud!li~ҿ-}	VĕΕ+j*iwthPAG#Y+հ1ݦZ1lm"|ɇWv35~y%y^Utu7`Ir}WMqN?I|)2BoɃL$=鮯/O=:fK+-WJtgŪzSw{{mi^{#!\C?S^1m|Wb1Wb'M_1Dq0Hu_K8TںyK]+YmR8*0c!(s2'F^ '= H:\z4LFeK3r^47y*p:pЄq:mH!3<qj&JSߠ"wvxC&W,7o;KY3&~C-śyn}VR}|^)P	9t]k5֭m˧-Ukbw?bxխo\_8b1K4YzNe>{%?_Lp2~UG{$uhDt3-Yc<k  anjԿ`eEH߬D˲|jcoh_yB4¿]B @6-5m0/e$4vz5h h3ಹ']ۮ%4 twdqɨķ1^?.q]U'M_s-zҴS9QiBSkӌ~RyC¾Ȱ5Z3_o5ՉS3󐬨F?zM}(oSZW;xwlʨE&0&g[=RCAh&ڈ{]lLHg	-۴L=aF7@l3 !Ł>&"=r2+4ǅfO"?, b9\(lPïhGփ( 5|ά[DPQrX VS;U<]^,g$P#N$TsaXfwNG5ƶ<@]m
H:|E=Xq}} $6 y*11ׅqjyjZ@UPi,F>ʘpTA4{
蠰*s*R!Q%}KGޅ슁':T 6^>?FGh>Kڅ8HL_0̋Rrmf+t)BFKD#iLǫ0׌e9_LH\~]1|C*%%;״GLj}{\كB,쳎GفCQϮw԰uw[ȆFh&npVMwN69 `f6OLhNA"4gJ(iލzP5vrϢգktWÊc*ޏEl{63T$T%8e]r1XAȬjiq7<dڧt3NaİhFN	REQcݽO4.imn].#2Ϊ80 mnU<紙Lͬv׀<ӀRy:|hMH[}{N9RREͧ]O9?k2Sj*:
GO ю47߶D$6	:WR(t~Z*LY/&1v{֡3yLjEct 1d%s'~ţ+.;ޫIt.Ŗ3=PL?"\'>YQ@J*eaYRP`*~u¨ %Oդ(RMVa7%| esĝ:B\!wL?[x#mggzeafE)8?[\mjON;Ny90BX!rY\&u\
֥;x@ W&Iifqߟq vTֿ<pE+%iWe)əM1}Kd]0s"VE;0>YG:/+J濬Ʊ0vhsK]N|yTtx//uLύ]ZH=-:yo\и5~)v&;t+_W/fL ZGk X PsOe{+%=זnwTQ̍.Z~_m"0fSŮdH2t9ء0́@܂_* Sa lN^ldF[ӯPTr?7]K|.D]l<$W,.KqTqu
/CbkiBMo#rgmM!8xhq\qVI~f LS-	uw?Nh"FXj0u4}ˣ07؅٩_5erޚN%!)ﲢ(",m]#0ɚTA+<3$Q8R6wZ jHjߏ 9RҥbaL.{SAF.vlfKNw[xѮ<'=z~<I PMa=h\<rgtW_Жl=osC2>7Pw4(]3O`XU1'z"?.ó&m!*լ+NFVF'sq;{{m=H5Uaˁ+Sܾ/$K\
;!~Da.ßJ3m˭Oz'/=6KV6"׉^].a!!O?nmvgl~&XL`FqB]ff:ۭJS
:@RH㐨Ѐ=ð]y_NspR$2jrG`4ZTQHsB_-ށ(q!r)Gv$Q$͋T8ڹu1m܄|IE#y+:?0Zo$+՝B|r8bN"~)Si}dOUFjN+gR5)ݓv3ۭԧ{|<=p?MqN/I8p4mPQ/}x(WPZr$jc,*erYϙ[k'#N2恚[{Hol<$Ugj*LTzm"uA7YVAF袋<fcXl:JJ	{ygF=nڗ[wVlft1hf$%ݨ~Ags

楙)ii	BS~̬Q~UjIjs*5F|z2'[e'5<;$G2NLYQ[&߻rW#>Qc3~jLS^ȬXeZkhOob #GVtim0
L/a<*ÓZ4m/K6ޫZoQɆy\_19߰	zV$_KXݎyꟂu!|ta`o}g<utcC)2六jNVBJ@0rI̪`_j/o2w	þ߀ilkGz:M]bsg8y:Yvx
8r$+7kr+5=X2VX82*:3  ΏtB)ZrsD8nm'/pK:$ce8)RK]YͶ\\UZG;'gO)}'ݘ)#@:n?nF2Ib~~{~=\f~l+L9vV9}̖Xf ߥm3-nMݠ>٤J2M&bhZLUMn0[	[k"]8@L?!UgCF[-~ÈS_" (~Y]kn2Da+s:WB[rr%~)t5|Ph^[CNٛvR,`i8{DG;1ׇ˫KGxvJ匝jHsk?T)m[b(~&bO//KXr|-ndt3-)*!X<NtB_%k2Ny(ݕ:sBbV"!%:%ZнR7. >'C+~Yuܻc%Qd[r9XX~QD&Q0?LSߛQr!hy)C(k#^Buuv|{?dZ\5}1=a$|+`|ݒ8[:j| LF7P/LM$x՛>GZFHt#&r	:bAN)Uxyz^˺0v7L{bzH*حk&uQUSY5JW&eXkVv{%dwg˖:F?Tt꧳(NJfK}I/`3P^4Fl_lrL{kn+F_s0Uf%_K&Eȯ비#ZWNtTB߂qa֓ICD`^BԾu}_J0l|a{Nh]Zބ$w"J(Bib+-tꢛ| I.Q2qmZ}[Z]	|O"5dT13$[#R$<7:惦OD1z?\ C#G+>	*GIV/:W4{__b6ʇ(^+ͺi`aا^>&e~$;~KR!w@
'>iHkZR%m`*Xv;2\3yD4sJB`P?띙h`Y˨Rr
+?ʡ%|>@f0|	d}E/n|!TeOՓ)khx<Le@ꝴuD
%$*}9r3bj̒ Tz88m*ƆNtc/)<޿=zKiyByl)`7'/cX)lpAmKY'ÍayW^XLɳn3WCkAAd0F<9M%#a)-[8=PR6}B`|Z0i3$ōpL (tgEp4lspB^9_ebֿpHP GW3f,bV"u
-e9-7pШq4DM,YpK%u,sM݌2gL!f8~OUtNuLZl.%}td,Woj]<)H@B!qwNl	/y.0X: hƍ]-`f9Ĩ#=7;_eƇ֦psvlO:A"3i1O+khq~2,=26,^abLp㋮:J_fm/a,xj#Ȼ|h3ܚ4[la@@ҥS+<lvIO:z9")RC2K?䐞X	XH|u	eBC)jCYCl3D,QZ.9Air~Da^(Jĸ`6H뀶G՟[[[s?9Eѻ}'-y}z:ETL	Z|}Cb4nԭKךq&OrDSLkzՏ9v,dS&2!. vJrDשwi 0CH!_tmn~ڗLA9fһxY/p.iss_JK7G"dM)y%ԨbN#2-_xbJMߞu (q
u_/$t=og^ˉdk4?Ge+T0k`b`Xn4-T	Q(ܸ}8ӻYMPԺK򥚺5rG ؽrrǣR&$d cQ/K}}:x1h?$}1!L){SG݄:Xq}di">7-_4#7"㐠9C\~nF:tP-؟Ŵ؍NsVnk1Cce  ϺKLQTs&YOj~)%+j{T"`Z};}Qa37=h@sgfD./D=7Vawx_@ J]!J׻N!E6-Ϳ/dkn٘\>pom5@et#o<!:&@`s$[Zd5Ve[UX8|ޒI\$x81zHLҭTs	rNED9)."fˈ-)y4%e[ )P"'_\9>]D#}Zczx<I_?a O90~&&nW5Br#wűAhT)2٘|$~NT#Lwxsf7<ZӠT֙`vj	Q5	0)iu
)#PRʅ찓eچ߈ƧgՕ;#{r׌/w5'tfW{3s{|D) y,5GoY_VjL&1b :̭ݧcD.J?/τ|q0#$:/v롴ܫhI0jjE^C.d
vRw]?36sܒ_m|3E	_S	2SLK@fO*LG9mtc;N5$.`B?pڠ^'(0da`(_GOdA	e$yip;_0۹Mat
krd#NhN= ՛O9}M%oP:
qЀPA2nr;X[;EЩ T1^>XE]Wh_$H}ȧsm5 c	Q<qKC*wPZwy~Y7-X!1vteZH!zecX%quI-{)˭\o}F{d=9;6ޮ?OLs>#?~k[7|厓O<(MVVFݕw`_K zoHTi'Dl2햄O!	PZK}\'e^y!Vۘ{uE,~`sSLb{_&"8/pzӍ/M$>x,b0*ezz! Hnz5 e9tD~A)yA{ܢqHl.:H@\F&hA/g
1
}Z $!o,F=>-|<.TO|<:켾7EL:](?\&D밡%e],搛OnR "8"ԅdg()#
1̣O?w{4t ouKdz7;aiu߾QNlRAܗw<y&!nRJ)l'^8ѣ9m8ZtK_0
Joꦈ!KQ{f۶b?qW$iԚE(<&
odfk4'@Ōk!˓^M1inP	gkw!ڰ,2ߘ .,c=#RJ>uk⣯U#E#j<WKbS{OLj5L4#
w8Ϭu5v1kaLjdae~UމYr̨ҳ@k\'?ǙV(ƅjݜB`Ty(HetD-$Yl#)/C.[#PA3@\3jFsWT|#zA|]ysAm^+6$P/4tKM&0OKf& 5"Y)G\|+eicCq_DP#l=`K3chbUTWW>1fp̍$ /,'3,l>5n%d¦@t[{1!i_
kJ|Fډq(u~[,VC{`Zq"(O7]}lW"$0~72Dl.!IVRRhmf8|p.dM'0<H6; <?k@yC
\ďm*o~)0Fϵ:O7oeUj	iTE!93$*
>cLRglӥ<4Vnh-#X]%eD#_HQEC1.1g_MF4:n&Ԣc>yXJ9l3&HP*GR=U1BDW&YYie+uyj%Fh?|	}ߥ˯5Sriti4դH^Q$Mvl-,glCnJ:F@~zN%|"y"9w=eJf{Q<@
q̹evgq=mMwȮCּ9WOʹ~s %L&
-(b:yVÊ S;oտU<tJeGׯW	v*ʂXiDGg!g=J cˎe{e5^L7!+#[3bv_Fo
 Of;O_-(NӌJ	cߦd)L
&5>D[w#Cdghl%Űq{r(RAsM{|O`YPoj_2L0{H_Q=QYU\:BP/P|͔/S9)Qa74qSg,@##dbx=YOu?sxa~_`hvM(i$B#9F-0|a'e
<_tF_\[i^2 UvV%+r{:| :f/$`pbwdcsRVv,2DWVoq'YO@">eT\N4d~`W$*f_caLjG$ci}?$,hv^\I$ETpC}X4khgB40,ϑsb ,DhpZ>F`9"B /7)Fc	[_4'#=$y	oh!xTW'VOxq59=ߪނ^%~Wk=t	Oێ$I}}[뢠_y/V
M#&J>l(3~?9:nE<"48
`s-tscbO1IH&Rj1޹6\S>%?Ŏ:`C;#a.,*\zU<#dq	/
YdkN9a);_!c>BR@$/\A[
(lP@k	yl[[`!%`;\SG LdI4(`㎁d4o6UP,m{nϏGTp¼Ud.
Dě(=iq䇡mj
 }F~q(JK
ytjf=WA4fiL}@wdXC;g 1:偿e|=Inm`svkh
UKKӒ0'ZOe0qbL* ~.<?Ф;ˈ^./aNhǙI
N◠7YJ%4]j6`02!N;/(U6dЉmG5hMP?˰fgו-̐"cQN*vfbu@F2 G|'55M,`d"mgV<0u%QY9:|ܧ\?F ܨ	HF|I4̆ʊMCN,lԯ#hTU%<ZػeXlmٽ@f&7@ KnV!*.
	NsC$&4fؘ؀`5`0/%_Ԍh8]G4ƚLz#{k5DJm&9)kbC I إ>o8䂱cT	A	Yvl]`ܬNW|C]r7v?XGR`Pu~E8^{8j9#z<JRS0e(`Fڋd7k%!/{{9.SƩ.G7GadEz+T Q:`Ջѝ(tqSx\a˜">L7V｢3egpGE)+[Y#j1sZ'zғ(~OX`'65J_ kik&Ry`USbyǆyk\ M䫋sY(

d5"5ZyF}.,=5tZDQK5Ѭ5ܸ|M<#tֹƈ!H*V2hr\N[aS0څ<4>l<yCo'M`8Y)p޺$bBM als7` ZC-3(X`&KrVޮ'e	2VOW+.IB
]|6#hޝ,MPhaS1[C[l*A/]<(+!><  x-1xV kF1?T*gu#'!J׃}1YI~UxfeR@ /	$9ȼm}fE$-M5٘r/&Q'@d28>hߠ YSđ)ØP48?AWKaa]5zq㇐tn&?ܽy(|0jfgnG^0M6;gRT*3Bv[a`XNx),ވ5um\@FVvikY'VR&'ZakcUA't6;IqRR/+u@f:qͬ\mٟ&^e(E}#Re	KGe]&I}+9QRZ*+c,,ߓWzۋrF]EŸ^?#,׳fwf/Ӧ5bW~am7&I3nKiKh%ҥH)նhֲzimk:O<cdw%Ӝwzq}RҤ-^
|f	\oW}jd γA5KBNPs:yF30LX[iK:9M-yAE'X)!vԬ_ϒU,ysyi֢!5._FTT9j9YiZLckfz,ݙn,d6X
J咣3I&Vnm,OkjKY透ilYW)R<ZarnĥW2'}|/S+#iB<4dp>W|g2=yM\|՜LJC`O2mnnٞd?X^d3F \N]'02eIKqyMILy{
I_C_nLӛ^+9{ixvKr*i5|+	W%ivFtҩ}ou)O	fkGTGSAִ=02Vt*+¥S_	9l7Ydx[gDjvvbpE}(\BwDS87/KEf<L+iUzR:g뿾8w3& Oi&cCԨ$4ܹ?kԺk^
r~Z*g4:m Edl檑/{ԡT08HKn((<6K8kIhWjGfj1jCImf\+ۉu6`Yt#٭ʎ
nQKiMu5s!ϔB;lRt4LJ_tלmxړtS06|/vM%#s}3oisRwf"U]un3mܥrhd hc\*V*#'IXr>9&y"Ǘ6ИmLS}4xZIq;HiJd$!&}SHcy^aC:);5v!wԺFv:Q33QmbCvTb>T
@U畵eNib'`^%jPYrY>4-	HuI{ky6UU޺ftjg|'Yqe'Mty:Ŭ:W-3ętUKyluS|aL9Sk!DCn lˉr'j'E+H<'Uk|j
z:[G}dV^]"_hXNRku;YӖiYWjh{Lk>4fdiH:>Q\BT31ifJ4-B(72vwBr;Oֶ"j,M5r-ih$hRVvQۊKƻ01*=c84#;GB;i#oɍmX\,@lQ!աjs))kZA]>VjՑU?և&եemKG*y^KIqrNxPJ&`(QL4ꅖjfa@bIll:Xw7Fz5ݮBtSLUr4n.sRGu3HI̧XQKթ6Rbi21؎4P9.ŐoYrIˊetv,?ұ
Ѷh=٭PQk盝?3:S ի	"MgDO2'rn^t H&#}דsOdnz6-TbNi]J؆'>7636jN6},-J'MLIIv.
L\Leڟ	:ipdcC6ez>F4M"=r,ke8XZ,Rq0z3
z!T-r汖2%ɔvMu.*CFZEځ,Bk>HOT+SQ67rGjQ(rXդϧurenSunH1PyƝ|a4M${nz2ZrMrAqUKŭ5S	eb4&d6CtyC˻.Km}Nr̚-d_iq*B}ͦ`4GloJ53TzlSug(šӲJHH<:\A%/USbDy]_EseRmr$ݽe.gT,`untکzӄ@.R6{X,'K~<E4O|aSS]Uj6?0zPV3< 4rǬqkUe%0;%,m0@5̦Z`=VU9G.5ġZ_Z3DfNQ#t$uj1,e^@UV	X?r|{5MUrKk^eVЧ[ {2(au0~:n:O.?ʉa؞M0zV'SY
NB0[bkM9+GjI|e	#̙=ݩhysE_ZjLvi	^3r>KoASkVM%>u'.9lKr^DF\gvUZ':%Rll޲ii>W&?qvyxaJMՖwӕE6FiQwV"YN"-K&qY,jқ(&i+q@I>rv/gllBꁦYm
[/jKjN.M6DЭ-NI^
a{$^9[uF4r9q$FUR|%u%<f.1ؑZXxLbXݼpdeͱFo,Q6}?e[,+k!dD;c.*_~hBx^^t,32i)Gzj4oR
}!u:l@{eCSGP'Y)-6\=+qJj'O/{,WFy/דz&q4.[	v8WHSHzn9k(*3A\zZL@By\XKu6W۲ڴ_ZTՀ#Ql:Cz!glߞuuTPJ|;ͧުOӱ3%ҋ#I6
&)Q#0WX+kB*=D-+M,WX+S]וUpaX/e'6Z!Yljr^RX>'T'NR<a։Y-z n^ TbHjKXy]#
SF@$$Y\/Uh1P!8҅QĬGЦB"VX%w@=+Actm}:MGS~8_Nq-PZm0%$ǞOkj.*|%=ۮ5VT-SsU/;'SnYfjRɃ^&8%'r:E>IMvrVUeig0T-y<'&nbJqYݎ;겲Oږ9h3)Ob^]䴬4Q7ˇ,k'ZTbҭjgykޙvBBrUm^+-i:;*Gd492Rlg7HzDhdgΗd&oVf>'v͕߮6:r>l=SHy鲳rS/_%ϯrXEVrYl5AT*t_*ԸV9<kj(2o|5y.I^®EK$Q xfF7SfаFŌZ1TkBPH9c{϶!Խ~.PlP 
KhLvmJQպ=ݵ5sNݦRcBjY[rMr}4LL3(yʖ3͉ܘ:rod^!8(ΉE_.B/.V2ƬiɵI97AH1i%_1D.E$
7KdzZV6UD!:M9$Χ!&rNr6%6բ	-/irVR,RE.$'ٯ\(ױ)DXXL$ZZAN2r@i-ųI$W=2Ʋ,9M>WJtOf'ؖͽ֝w8 5@-7er޴<ɓ<HQ=ù;tRV驰R[,]Yʹ506ZOT=>S"_lV\ִ3+
TLuV7[3ba%Nn륹Yhk+HK*<SdZJ&rvV&h<:d۶ڞD/7Y5jVD
W`/XzF;Z%y%zs{"/`i`nYTiEjP_VĖI&DI;t%ߣajSm'rMl\FZ`ڻn+mSZS=+=Oћqjf]fnr%R<0wLyrT&xycږ3VlL,9k2JT84X/NN66yj)`D;3|ݢD}qc]гa/UݮYq
ѤSkUtI4/9fp1Tu=[ueR}}]j㺱dVj4sA4zn[h֕fMZncV-5*r&iBS=nӬ0f)3"9իeJM.Ҭ[gޘ%wץj;ceduRcԣr,օP\,j|/$NxjĵJeuZ=ff<z.tYqjw^*$vP5K kDF$qdr,tr؏sb9ͬ	?ΠnOHu?Rc:v=RJJBk\PULFzmIv	yʥ3 @	-x~]zG[^H銪H'm`T"ժ͏nahx&Ud_Hqr2E<FʂmK̊LzUI!ϻsST-YntVUae;䦫fڅMj^[5`M?^fqH҅iWT^I68$QYn&1A `,РؾI|WlV.S*eR}el.'7\IcJf|Sէbx1V0LnvfsY5M[x
SO
-0bLjT-%sLnQDNQW{va͇1`h+,I&4N}Yke{{mZn'S:[ΖlƣW$(a!mK+PܭӉbL2%0LgyCzi_m!kfi$P&'K3MV!
]ǘ
>(Tu.lBHrgE"GT,YbZ[8"X;:F%5)PY(Љjs$TQ2v}ьc[bܜ)U9ZXkfƥz^32!XzRk[i]_QJF:feՁN[XZ5Gv\IsdNAax9ᜓ,wjZĩQLdc?IY,ѡS!lONf.ksZ]1)jGXZAc2ue唾4׻z<+Nu{)_8UoxRKu:ԅt(SVm2O&'iM)
s-F4MJ畔/҅ܦxUά>5"/G:?Ew?c%6YOgcZD4ԅjDfmHDi#XT-SΐJ#mTl;GuK1L2=Ɩkwhʱ|A&ޏDItSqcΌ
yf\z2Fe<TM͎,k.LlT	0ϏՙO9$l=sZA',:6ܦZeײPc*B: C/v1i?쵲S~Zt YA9J2[4.) %ba'd8z]Yr<Qx){.w;`f&`bMT4hqz1RBi܎_]8c=`J|հvF?-Qe}jI'ƃB<XS)#&չYh!RUE뱙\,Y!do]MˍM C]ݙyBK8]v"AL&saOFծP[UҏyVBM-Ju#3+|VUs=ST/ṬՈӘ6
Jg9ӑbiV\2HIjfU2ygtlYnsO;t&xfQ39iK1lpLHz]U+K_]%߮%$\lKB_)&dU>;1/vcL\YЭltk5TOg|W6?Hu 5\M93Ul,יsF9&6Ig:ISӻ+wK=44ĳљĄZ=IaɜrP
h;ĂqU9xj
 oS[~Z/(9WRۥ|Y2ēDYQRHM>tcku̹өtULJrw%'_q.?HLv8cM]a-'րy\h]Xu^M&^YlyEh霜S3ܥ:u֧=@8*1C5-ZL6Y#AIeN2NlXj+ͫ0klulDjɣBШҫpIڭlS z}$SPfDO'0I8HXᘥJ4}LO+7d)R]>LsKm'ԩuñYj#NJ>;5.jleŠ{T*̪OIi.F]3[YK)XW"T!3}û%9qwR?FQL+)jJ2uif\~3daPjE݉e}G*[*CB̙F2&cl^i3f9̙ȠΆyt&"UW8(+tc
R]k0Ai(<ldCe|wHEj}i`$
cZ90>4,4)}z jx"]>gŶHRQ_w䱾jyK%r)Eo+Cc \/rZ(i,
fTsG-j{ɩS_;\*;+%\%
U$r!Ŀ~z}04ዦ"?㻨<WC+dկKC!\FWAQ<C|eȜ.*;lN2b]d.W7KU"@K6.OFԞoodR+Q.[ovPAAbC[k`Z'*{QފΏgUЀ#<>P'oETeK7U:7[nNkAWxAĲˇ}FQ@wV*!B ,G.t8^O"无x#
F]4NCԞ @a:9`xrۻ*Yt#^Q*G9#fy^fA>MUxԣ͵#ᬻSH&dqwv񅌡CbJ+j`"޵@6͇dPN*Ugg^?:O:h

(<Mc«$ƍ//] #6WTUQ<ȓK  E'>ł<`su_@1=0'{<T]r>hΧ$k}S,,	*vS:mպ枫$R6F/ g(n1$+'0 ՕX<OI:;@_FPTogXYW(UEik\G\dnHLc9SPbȋ7z!36@?\' cv!!A#cX"tK#~U?ZB(DR8fU$*
}+D]a
!Т<eEgq6^"fVq~f%IRU,'Q0ʊ_
0(0iرe6'(^gtٽP2U1@J#A56OR8"p9[N:I$z&SOp_tEHekI"MWѿP ЬGOa@{\WREKO-	G8a6S+z
=ZaC컳(H+gxk"ZcalG[S5#fѕWĿpU'yi	!YЂS**.l	ϑa) ,CSԬ1@7I}Qm~	r2$7E]#
`_gr+qq `_PdU|tXԗYUwzO	sފ/2 ߊo0ԑDW(?*Ih2Q
<wG*+k+E;͊|*VpO>4l>>oќD:ĤD-&_Xc=oqZp);a[Peb8DRWU>=4\er9W3~?%HĿ29.+uNk!ȳjC[xcW<Hk%H0_N]φO+*Gtwɝe߬+oJR߿F$?_^H};,S0?: 39jtGf35|F?zwon7G;.QqpT_>(GÁ\NL$^`
d폳//֪MyJIC!Qpxã<Fk~ߦKRҡQO;:~|@=(4sqr)AJ9u8Dr<;H4!-<؟p	<0nǉH5?C.[^z?? Kp\n>N.7-H.&\޷G.'r嬕7ȹwj _vC``"LF+7Z_g*)ƕ&'HXZq>V\&H.`*jK&[nY{87hk 8tql7P\s\F.r~n^SFM 5QѭYFx&nPb	ɯڿ^MoO94hC??WmVO:Uu2P$u:uכ(]Fs3Vуui KOye~IuD?WO;u"hoC,
,2t
[:u֠/$к54o8GpDu˕bknT>7`dć}\Rr~UGL|V=R_4!ڌ>ZuTx(ȁ
`_>[lEVohЌ .Аg(e%FX>0[/waXtݎI)k-l934Cq')>Z @}r||PЩ w4(VuG4/PFTW"섳tVCfFVYV*PpJv((= ;eCPE^ܴ.bGh^UEџZC9x]YAz=S"x'(F!*핈dG**5^%r5@(S5Tlm^YnpQN(B%&m[U.5cUH
9G
|}(Xę7h`Ww
GھTáv
6؇3j	_xp`췻r+G*	
w
ڍƳ?J/j߀ UOo@
 Ύp?A!ȫ.yU*%hy5o^;I/5	U੅jfKϪv|#-=uZuJzZ}9Q{xxo	
Qҥ0[@`\Ϣ r:Tݍ'mڹrO.q*N!;n $eAQ)7g`!ɡHīGx`5[('1s""oKDu8*@{"AX. :N(g?~)Q	 ;KtdS'b2ڦm
?E}An}nseǷOT)kYCպtuV(hf8<yb{5m0=0ТꠄoϾ;LWB=4TwTkٕqˁcsu;qr@P|.s^Y"d04d,(>g9'\mO=ڇ
T|Aww\4$GQx8ʤ(*/vGgngwqfA$;)h2Ow85P.kxxYs/íe*簂Ã(D㗰-_OP<{~=3l^t(0ۊtU:/~P/de*bBYVi$|Pv]++
B`~/"5j{mQo;3~S:_SB1nV߬+?ր&{&QoOܖQD	vsjc`5HCʝlA4/+*Z.m6k8z?`|a10׆0VqCN}}cNk{B;:b_L!Yk$(W8Wl9܅⳷W#Ё-R 7@ٵ"htfΚs< NzJ$iw`9<lm8*'?9z?*1vRAPl\-C(hzؓbNj@̞.@wl#=OC=W3Q't:8G΁Bҍʩr/1Bp-BѺ|o=ؤf~F~h<!Q4XH7@0R݅9P1=a;?#^>LE6~Vz1/o:Z.pDl(r<~`ffzE!wمgB
펱߃IlhcxP3OpbA/ҟVdOG)
kQs[(2#g_Csp~xr,;'[qGĸ.H_EG{jZZ(='R]lC3`BrLQ&s=6+a7	 5g_+r|0 "[ZxaS^v
\hA=?d#Q"aYq;H
SFx.m5Ԟ)w]EWP|Qz>l?v	PAyx,}=A燜/X{/H2-jz38ml~N;a"^bn3d#}ؖ6F6룱jϜGxHQ$ɩ{~	%\Gƕ8+4¯߮ T
vgc(F/`o#ͬbp"zCD`A.{9 yׇ2w~ ܅cqOPq:X?ҀU4d^oyE䡮J4堄^G

8mBl@m*gaa,p.Rja?Y#1?x?GuN;r5r ΢1!Ə3:N1bYLx{Դ#$ݮl{N4w@>;c0taA9VEPr>ռŐZm{1ʨ[0JYKoNxBn<P^F.x@ 9iS3sWĳ 1P-ڶ3/DN{t`eUe%6Ս"+ѽݯɑmVt!h2%;} hWL!EU[` 
إTՖOD@k(6ia=umǐp|.uBܼ/Lx5]B͟TǓ98S(]z*a/UJ-hϰEvaAl+ĞOlk=@r/kBY8LH	:.ü5~d;s)??yy̧j鏰ƏOB@jE!ܘ{D(mSAx8
&ly>AW'᛽>l.AQOP2tGo.cnRLrswmoFJ^h|BBmBDPE3p,Ok+rEb9m'mQd{YR40 vyg@kpdKkɾtS1<[s"mw߬̋ykZB2X&|7z?ыMo/D F: `@/~Y $N)6}1JT&:0_h 8!pbg]ql FG8RxGoMqQy+Hٞ93?.gW|u3pY	
Y0\Fe^=fFp6o­ηUt%jju>b`*En^8Gr|]^݈;g;-Nܣڰoh$A<Ɩz(	~aAx^go!n&)x)`Is;in֎,^<e~?\
`UX,f#3 e@!{э0ʍ
0:#+؝ BQ8/ȿ1=w]=|{0W 8]D-VX	W'd ~FPz#땅Jz~6%bz2ow@x~+ޤ>7`+054sK\=G$45pr]DKpAMQ5S"ԳW/8	~DE(^ٟ.\/Dxy9~?CF\gS]c/ocEpT/e?R|!*h:gH㋇y֐3^.F%FFiQQ,ej񳆠՚^BoZ2`Y\tLu}~TFr5fWqH\ڽzo`P] !AW4*h73*?"qS+~kzѿkz۴A/|;4ڰ:\n5t5BlOEӦœ_%T^ޒ~
˖w㞓(C`ǫeS}G7	׷]OFøg|(#;1~π%1+(UH9^{Dq^\Uipf8(hf툂~vAi?Fcހu=_Y5 y?]>"D_&x}gj:Gu'-`0~0Dqd8wb</]O_nsܪjG%V_oxg]C$0x5"PPd OGSu#
Up.WH}D/.#lE<%?OxzE|gv?QǺTFZA%.E_u17sY|m	Oo^>soʚЛÿ96\7tV?6qagpTm
2Q ʼo^xJ_wq;O6ȹ'{+РPv;h0D?+T[}!p1E"iC,-Мl8}U#}wDyz~8XnHn۸lo;oK77KlX,CEB}&_qNw*;D@y~yg遽ۃo{[G++JFXK s`"f{vz
aκ-@MjI~/|#'$~b^GAj޴LgWc{11v6&=h?܅AǼR2pǝCװ]!CxVR%"h p p[u4lUU"ţ*b`>qCC;F<$gYHAᎰUr0M04fUREkno(X%otᣑ󝊗r]טW۽0%PL_zVoF×\v!^ww#=:7ЍE3nvHzLf۰#&WsmzU^_|%ɣ#~:uoнݼA۵/kv`	رKsϝp9ǎ{;]ħ$eG+zHn#sp`ix+F%^C֣QXKWgŻ.|s/$>x]܎IqΫ$kѫ̈B8m@huu`n ߞ3ROq+VXw@jUsWUv]Fo+{q7^=?eD!@c1l͆<;Əc(avH D<0Lޥ1: W/W?R<O
d:'`+߰>?+1#{mKvE>Z[]O_9h9P]z?ka%>ZK-`My95}qɞ(T%(YivtL?@d5<Q[J׭}v#*}t=Ӂ{|BZn{GÓxw+{tbt%gp>9?:
VQқhj)XKnJT-gEx5y{Tt7_5۹O4-6gz,&FWpĜTϟ~cݐ/o}62JYۊ	Rp9uq]	' 86
#pc^cGחOрq>F
` =5n ]=?-`G!ChvOt+D1e-{o`S]Li?=6Y0?/z80(.B~`h_UV&t=s0_$qrywGT{^>܇#~~_>k׍u_7VKԝ9)U4>?9a%~7{Y{D7}ns|O{7^	UỦDap5謀\]{yQ+Eǹ	7U,0wxy06RW'VX{ _AMatnr	u
Sq򑌢} ?'B屉9Xrq|_uFJ6h.tP{BW?8٥+w>~\60СTg9@X[	1@&HjF@!Mz'&7&=KoR4l5%Q_m@תּ_#(F<~ҳ nc]Sᮝ&`=: JB_yE
n+~KS#`׮8o1W#xgĭ):)B?߻g8F-8E{//$I~LN6 TD^Cp%'<eWt\i.PQ5KAh1c`@:Es?]h4wM܀ HkM8ELC}߉J|ivXiUw9J_~ϹԃL\P; .b">sVs( ,6aEd8*_CBVǫ&/1W}^vB"+=A`4z';H	p/\&{({9$ր$^4 *p 4%|N;1x?1vghǷb%$f4ިَZdS( "eYlPT!qX{DM}Y2&2Gþ/+@4	v<$8[7s7
T&]!`lZ>gN/AZ㔀 ІM?r3)
ѹOB@gn|5AjhvC&?#yUGj$UEx@:|".߯|R
=`ï;<XU$F3n;p)8	$E	])&p5w
tTOlMMg7%,/Dp$t'3'hg#Q?Pl>	sbWxJ懶2+]O[#sζB\ɑ^gS_l|ؑ_<n1Jx⠍>at&%	ۛYfwW;l[F[㸕Y|@۶ ]:/&C"zurTg7,PxN6`<_OqﲲeS6?lOvG(Xgrޯ]1m[__^ؙDO-{%ߝ/ .+fý^$l1tP^?u8䞽xù[}'ߠ={471κq6ONwrI8LswcJiPFK(뽽 ϚïAI(C7WF^Pd[jz/|Cx	Tttf̂˟6Hų*Za%q*zMiOLO7" V$Pڍn先SLzIJGoLKWRuZ>ϫÒ/aEq#_qCN%"{;+o.v-Y{IƵxr*x3T%-Ț9I أ! "_!ZP>Td@?6=D-5{)&.zve40oE7÷I( [+`Y~GvsF/jbܽHڃxb n xePA!:أFGᮣ"C;Io&㠞K
`Epd5xkNB 0/Jtwxm
NČ&0jw.n_|# ;NمMD|SV5NAX7tt %Lx;	o˱a÷	K:CXt$OL0`zotm>-ؠ_(بov*|]84㺻	&(ieFʿщ<ᛵ>˰ڍx-Vϫh6O"
?Y¹C˟fנz`<qj>| /+6?zn%\O}X1rqFfĮK4Nn>6WSޞT?#ox?^j
\	Wķ󟡊0_zxCLr7|%/Vˢ
{&ҴT1gV$GB)pgP;^TY</tsV\b_b`7ԗP*N'L0=[%z
>@4Ϊ#Y)C]<r#9@'?1G|'-q_ i8tfRWJ`,rU<V2-$\|g;@('s	W(<Hsyt*^<qUw@s
Av*\
vG W9T!A
=[uO	?77|	͠g`Jx3lP^xa~D\tY:ITVp<
~8*UO^MIj``l׵XqϮSb,\@AxX7	^3r2[45`#и_]ڲ()0}?nЏcdb򺤕
AX۫1q*ޤq* V0?TOPx.aF0H 8\8Z!cs ZOW	Ml@4l.b iYB	=K0{HK
v-\VU)b1$]Nj,8D!~X'`?4ڌ/**#yxm;+s	xH}Nx}86|HēpuMrY$)foQ=^vC5Qwˎk#S5սMh!5$1nokz/{oD$_6iyv7O0Y	3p_cwvB&W"vٻ!nT*RU&
z<{w?Ykɽ?xxs7A"l͌Vp>`]P,;+.Dk({q1DWhEX؏Se# \]IQtKV)i 'b"'L<XWg*<vઁ0j7lu[ay-0-Und(	{{m6z!DVZʵس߬n=hEJoruk<7&7Pa.VT#45´v!ZBi#'7wVxVWtx&ŷgA왘x$4LHSG_hAT
V~vJ{zN[zJ&'yǷk}^[͢m6+~{
"Q3/ŌͱN1/tӳvfnY?Mp[ڶ/ĭ8l梠5;b@[Q5?VI4u;u0y7D9&Yϵt~*uegkƸAJ͵̌FIyKT,Ҹ-b2q%~$i](?MN|j¹7p,ڨPhVk6eR5dI"\ZKW>ݟ7g3vNZZ]iwW ƕ Ӧb\*=O#;_
d?,_Ī_Sʁ}da6ݻwWTkQӁ KxjZӵU^>yap%\OF/jIdO^]%&3v^jVX=؛|#	b(ÁUK2ZՌW.zeQn>Wg%NPcե[q{db6N-,zք~kT]x	yd`xd4=)ڪo?|[G~<J%fh =EE7Kb~Wm,9E<ȨJƺ_KfzA7FפEG֨>e`dY`ָ0^H*
ղ"g3O77FU0Dk9d wΆp#S*#MkT۸vL|mRAN)8}kVف*)^3ycįbٹd'91,'Mt֫_cN%	Mv1GMgQ\'WJK/nMq\zXOve$ۗ$u e?[>kaQOEW W,pX1ymØ&gTtvaQE	<Ҿy%bFp`3vHtnWnVwa;.s`9&9^TEx_{}K!4\7V&Yҗ:i`N| oͶ !x0
}в.W,ㆲ5FsYbL߽`ٖ|8
_D⧳\-" r %AF>/ү1W/aگ0<!xF3x{<#uIKެ
)%D:Rh罠pmb8_=2ݽ+6!)io׍ل9z`ma-
ųz༻piDt:;K|6Jc6u6DnaG)-~o}t5#D+KUzr؎z{"6-y^#S*L&{d^=IJpe:RQy%)}Q#r%1EWr;i'vsdJdBnf:.5Qڧ-ڄ6t3aShk1Ϝ~3{=]M5P~Ɇk_N1]UkǪ5YnPqƄsir`Q;SKrLpH}DU-u765XnFRpDtjSz:ڞp{[(8 D%'ڒFRׯ7 (cd:7ugǘ,T÷mJ˂|&P|S4H)V]o)u6%7|WT]WZFG0d{4a``!O}2BY`˖ouqVLejV#oޭa>pUy.ȝ"е<ѹ˔*#PX[cCnj_=j祪C%9wF?M
O'4|!!A#F.Xx$_]cu@OzE_QTm뛾_9!ɦЛH,.Hת-"'=ozґe٨gk'%\cՈ6U,{f̒u'Hq<6|o.Tiϵm}nkv̦mN9m3L
XlXYg]ã޵8>ptPi(af?[M1ɌޜͦxPrs4y5[7lpT9QAU
PYwu^k@͠^V	礓]7>A4l6)x+JQ%VT	mpi"iꭼ0x3?+GDx4}Qp~)_o$becB5#y	SN`6MGdʔTtLڷy'O,Ac%`܉ 羲{``lw;ջO{vlt2ܦsٳi -&"%bz&Iūtԯ4hg%
t^oog/VQV'FqY̳S"ъF:U}E>~ȆkͿ=i5>D̓Oad
ǘy ;C_2Vq0/,xM)tR͎uEv"]Rf|1M2Rsx9>RYׯ6M8D=WmG6o^w[iujWYx.נs.Uxv!½ǫ9:
wVGߗMcuVXW>9A$/0z
$!@s.AOx	mw-(oXUkjօz4<iwz*&obw*(
'Z@Z?ŕ	R$`BM	:*h-r(״H8}/j>11
?C#/+Ŭt/5ҽ z|΃j6e+G.SCpfk\&-3EsvY4cF*Nv[ߌ P,猇``&¿ fZ5'bЉ6TYuъ2͇+ڠ4w_mJN3B9>e+Rs53u`?µ~6LxZYG%|l=Bރj6ZdՅ=܏I;3f
<u
H-Dq>g3E)tO^hWrxҮX1m+^#qp&D\coZ҉

#)Ƀɲ@H.L#+r6YBWX"w)
]-#m_k6Xc
Ez:!\-Awd<иK+q=(Z~g68]bC1銁g4 \~BW;!PFZ1%f3ٞWjTB:p uju-icyOkҧ->C5P㸡pѷ,VCW::֊ [k4됪d_ߋV,I=Η@I3HݾYsU{(YI0^|t`-mZm8Dz'oN=r1q	u3"әb2G|knɥN^Vkzlȇeb".X4<c^X|EуFX?{EdKOjq5c_|kjp&.e[f3f<ZK1E>RT1dvUnky}\WӔ@#zcJhPqI[
vòG9N:el<'txM!=Jg\2]*%ˊM묫]+qp;r^=wѭަ}w]򼏺9f,b/:A.oA8CSi#oh?AîRW/ljzb/KZ~#f~HN`¡T0{=={0۲MMO6j0_4/2^	|z4;X
Dg"bX}ԸaJ/ֿ(N%d8Z:MN4g|!7@^4ӁL^LA2:4&J bY5Q=y<.hGIWWDHtR87gdAA**t?g.]]lbtA~'.@䢈kC @S3!H<GjR˺͑-k0:&eLo[wUDˮ,S/a*~_״UQD '[O>@uF=&",caS4Cw\?MUS~(dB#?%&jp;Qbi"-v!ݻgfc" ?_jG\h-0e'Xy[JEỠp@F9|gNs7$>m*(~EO)\7~\6a2?ApfgOs&ss>@3GrMtΨj~)Iچë~^)	`7mNRXS9
@zN~FKGt<̈́T,sx6WcPh?
le{xN*z*>ƾ^aU	Br#MHcw}=m$'{(H2_ZS%Sՠ cJ-gXfe^`D3_NUbp3[i/2k5̈1K/+!X-K(^DoӋ@]Ε.`eAo5&~ u +lJ˝S%/Fϖx-_.ETa "G}q! #O)%	mM7LʝM3j?rǪ[/ς@:鍛JTYTSL<;Dg\~hpUM_pjϻs$$%Jb(}ZMC+q4 ܻ'>J,@k}-K8$a'R9今jm
mrU,3+F*lVNgja`gVgnmNi)2p i֌ kͪf~Ds*,*u_ZwBJ9sdLׂ+4ZxS5W]](tyV)]O~%$ӭ`T5pw-]\ԖNZI#QB'.v:`u;ɫa
]FŠna`tйY bwG0N3ݫ%KQr闦;fst_^|s*)V7rDjB->~Ǔ8L
׿hZO,PدdIrFdl
쳾!%D߸.%usp34;X<ow8r\Dp	=ӫׯ޽w;|H<ԘܓSg*2_ R(`{$i|Ww pr衳$WZ!˴Y7n,6"5<[+)uH-y+2S+XZaez4W#ėY'nO4"nBOO@n9do1޽6VtTN,i'{Y:wEy[M@נ>.	SrPEVwyVZ|$"ޝ^NmYFU0
eg̞3f.Zou3́Zr v`ON{cA"m@qUmt2YPk&E?<bDFŝ0RԨYLNbSEh9ڗ|~bmf`5	lؐݲGQ4MZvdts{aJIIaMKTB4O8՗5H=Zzt&O=䫸Cĉw/|z<\k6	T]4ϗgٴ܉:c/o@\ʷTCz DvA{bOآQ7.ԭMVrՎ׵Җ$#>']{<5c`Yԟev_$}ՍܳgjydE9"յHjF
`Z)RZ0Q蹎=k2V\E6u
i9IuV8&:NW):es-KFE>%5߱xW4孝}7\E{ꘝ|/SmW-wl(V'8WOfǔ8&?ThԟlvzYdkzdBF/$	uo:jݕ26W~{+DrCCH^ ed~r	hY]aӥ))B:H[jK#ViAsz"d^1S@}f-Usg4}vתk< ]++J,67wNhʭkp'ǜ{917 ?Cjf^<J7wO~ɛގQ8*!WC¯R+щKFP(ld?~fWbI{lOF:{&26BDvæGwwy+:S8u^]%%_O|>zAy[-0V䏛t-z*1P>NB^Ie8oEd/K !,Uצ_׆DcEl+fS啳.a-j@.ٱ5K)ԪY㾢,}.G»!犜TN6ү*lA!EJ':<]fiXCB'[GEZu!8=0I$nQAmQK㫾3G`Gԡt-~l~Fɤy 8)83A:a0MB\z5W8\-9\Def(|=gm1I
5y1"8e+\.DqvSJ$BNRݕj淯nf?9zUb25F3k^P5U}W	v'u@lC]ՊY&3,w5L9V9U=)?.7%%t!e9d2k_C^wy55oZ^ׯ^]QmC3?p]W'ZdC[=S>&R :Nb(QBl;wEO7ef0o?%o+fy}ZkZ,	j׊#vVr~fC@xz`B-= 9LmFggpzMv퓾z7'v\Y<BE5r /Dpl9#',as#Qkɋ"uSuLϘyKS8<]BUm:;=T{/hqliA!Dȃ	r9Cƻ zpF\k])MNb C"8v}}</gai/wk6S6l	G73Qg%hԎR6B҇q>~lly\rYHhcZI6  :nsysc#`E[hloTZ"Ɖx	AbHf5[rJGҋ}+OW;nghElGlwoox`]`=)?ә[}ǁD<ٵrzD^*0"-\q+<vq<y9WQ$X89+{CrQDA[G#DkD|Ӊ@?n;M2[	o8#1痶nIcPP7uF3p_mY#j5Zϲx=R#Y=H!xIynܻg|0*ʵQ<7(w{k.G
6\#,rώ+-*"Jyە6'LmMعg"<
5A41Ûޓmvz{hk	aX&\Ef\#^Q-:f_kk!-8[*-)wYeBZZ,_IkC uQVfx-dƟ_6Y덾v茂F'sW-};9@J5hUw+朖 b#`7QGB6b_e#'ۛhG#N0`w5Ee^:Xɴ2sC~_6yG+cdY[匮}-ݢZTzxqX2U6[ZdUjgsðriXӍėzYxIc$u#mkáT vULAbQDK\<Hg+ַ>U&~%-h@b#Xv	o4B)p$,Aۚ$d%[a_fh]Q0k|}=,/8PFF^cg:R5aԚM.r;SkGqBlݻ%fˊVnm?g,><9W	/kf͙C<tӞp K-]lp6+rwԦanPʸ ڹEZשM%WI00ʰbT]LAB8"8)ϴxM{ZՀwK_n͕6L9vi;<fi{ \@T@Fp<TUN' n:@Jt:W%ZDoYR1t75"Pq;Ito2	>)]o-{66<VW<W} {9#/	Hq/9yLAn־ r#Fͦ4FD3uƯ'<'HbAd#e2k[N\AS~䗺FvI4IVqꍼչhAO\HD"ҫiTb5MU5(!8֯F(} rUPccFX%o!bl7MAibS#0w	`Zx/qʜU'r>?yO~S'IOЅgdӀMT*fgI{6C
tfMƆwR$o[(=wyި4ޯmx+^?%/Awu7Nm1ws,3T!lSTV27 u6^켥s[lD{k;qN?>m%ee[-k{>YtD ?װ+lX(5OsJf9]
{E7Aj.xbUo7WJ:.qh_z[WpXrvQx{^uNv_|*^6|uzTMOwÖn-V{c"#+{3_ek
ErsƏJVELn-+9z]1@Tw-=ib]U=e7e+x{,Vssvo%Ju볕ܥC|[I|{~I]Q<}ܲxGgB7M-9IY8rhx9=yP	&FT^:G䝓0]8u(SmdhD=P\nj6?QZDWD&y84;i$^EN7(;ut#r+">З!#׍b_4\ ͟M}'dó\՚^йtj`qCQW^|ޚ[oQ~%wS.[d))SoH|}?-U]H8T`k\aCħDj\j}V;ΥdJi4sQK<Ư;Gd^r-wT5zM `7p=bE3t.Խ?;=.Ŕ`-ӗFPjgcaJ\iG\mS /	"UC5wCrz*GU؊kb:&'rx&*%M`I ȑW-YsQ]0p+%+:<?3ȡOQr@P1] &?fd~dlpޗv`Pc|l"		>##ZX9ڏK}bkΑP!ch/8mE$&DL¹N?nn71dA[h{&<[Ԯk2/q Lq#ZnI3䍎4MH#uYE`_+2wlXSaWwJ6to^ٚ#TW(jU2UĪNko&PE
Cxdb?,BD]3ݺt;GmpxDc^]@4Y/G-;Ψg:.j#
-jʯ~=|IW3|0N{eHJQ[^Tq! \%nZiGo/?XarY$N[M"K\$K/{A)+ǕX"qw*5jpmݫOGYJ卞h' ͇{+.P4A?u7 %`OC%ǿT,G8y;~ZR@|/oec>QrмTtXRew,T5cP9nKrkރ&g.)g %I*N'ggS607 @d"?F^2/.e]%6/taMWo1rKy윁5&lb	z H\!1&~?\떈xO0AhEϯ(ogdHn7,ci|:նGjCCWֻGOL_1
Ke\WDDAucPlI^3[4d7͔HLI\iy]frݻ'uNgSQU
dɮ!6#<	~Rq`r}b~=ʎZ`0.4b9n7J80$jF-%j))6[Χ' HPڊ)hv^eN/Hk]qd(7[l:Y"+4Ztq՞Bo{vs!e=f]hp.)P%vKɆp!/b 3p⅖읒1(&I -ZWc;c	W	~kN:C+pe@v:֑uhkji9s*VXҽvTVaHcl޻n]a_i`7Ol|5q`z֛/{m߲81OZ]Q6(W O !b'2.y \5xTT3q15PUh{b̀4Uo3kܞC4"T˲}d/QܒA~EcDTX};8e8X7d膵iq[:||7 nA6hI|BqT@|}PZ$|2>(& Jtb50߲KˬBss/f<I,Ogj֎D&}:p=:A0ȟެVK$-	pyz=1E[%B{mh%YK/%S[/?饩 30ъ@-~W`h#/j	Pѯ/Gw%9,ir*J!ѡHHpIoB|g<tP<۽F3>0_|t`YoogO/T6k(5?wjsj8\; y99-˴m/<|{PLD"2߼GにW鉚X1x94`2]U.~ͯG{(=STm_y^bWbOjୡk]er_N/SnR_޺x`жv_l:nJCr_w|y1;6 1P^-6k#~'ӶLú0S&8˶0o0~|@S\9)->VZ۪I-rK":Q<9R>I(^=1سIS8"V.^IeWg+y(XJ,jŜo6xn?ׯHYI߅q3-e0*A]%J:KqV+5JN-*' &sk'ҞӀk#P0iBpT23$
`hPX֘-9 oTKz>MYNdS9U"Eshr!X-=NTz'u`:@%6bѝŠ͖ؖtt2[I)iLY
o(,.AV-QEyë.\o^lΫVÍro` R~I^R\d|{Z#4+|ZA)Xɼkq(e]E+"E؉ڶ	dXX(5uZZMl(5zPi-"h8BcGM*zL[Gȶ:GaJ*OuK!$+9|+b4o(IxBj-	zJ䆠Uc,]?̶Na5yG<K1,hY.d~)jہtBZTG$˯|Aev4#4&yW10؈
$v5t!ܱ2'x>3u  0-"HrǕ<ENվ.8ORTO*M	GxdGl0NMh1G*r䕊zD*+^B1]Jg(b;y:={Wy]Çl7<QF)hٸ0sqXhɢ&-ZDլWxhzz؂NXml$կy$Im
쩜#M)RfjgqT6fQz*`b#SW
\htEXz_dC@:
r1+C{:Dq18C`MqPu>unX:4j+gZXvYB?D19xAUrms57lelY(*ިR(Z,aqʅ-UnHKMfuzJ/޷T/H1hFf3m2>[	P^m}-}22̲S)1#c
sUty>\PWAj<Պ#1?i-lE?m}&4IV=J¨9/(Ln9Uk} rXq܍vcEhmXW^l~ʥGN8>/?vT˗d~|6{v|W{V׉қMFgJh/RG2B/ƣK3=c3y+t۵^o#sC&Q{tܻG`cQMSWy`*eRy(C5c0'(@sڌW9AN$#}d<UKTs08K/KXgŲ@r]AiEh+Py'}OFg3X&wjfÆH}}tTda|myU& @,h'MBM<ϊ!jS2Do}FwZ''v"ݱ4N[A~2smaeW91-.5WJicWONUW$BR0Z?\;]#;]	~G&Nɩ
PODh?M dzۛ:Q0bD4qw\0ԖYb! R$T  BI{Tv<LP~A2xOsnښ5Zq>~ӟQ"Mmq!u-.q]M'ts@tAm	%'(m>oQ<!u>}o04;B%#M;CFO-I  ߓxW?WRmQG`] Xզ ]R.ΉƂ8^lRaGej\dROiq|t2kƞy47l6k4<a$sDRKe{Sֹ3;şe"W@ASB}4;f7ڒ%WI#.sSlUcWփj2pµx#v_hzY>̚lsA@0gt[j[=r .YVᙠzhd)R`׸¡PlV^}oFT:zt@C?R#_YH}H(<d?	ofBzV}6f/ʋ.ɲ-\tU5túnJ=5'N='œn{i,QE<KFmo`{^W'$0,7]n'ֆ{JJ$aLT5S]66\:"t<GiU:*k:*#-ؽHl O+fqs?,7lwKh>Q*M7&-7uVR"7֟UdPLy3QW<r%i|vz"ślD?8FW>2$j̑g}B:#|*(nOP?f?ZDJ%Hb+"R-j^6,muWDx4ugUiH\M6x8jh鉲+I)o}j_6a0@Go|Mʮpթ;ߍaBB}˲Wvd gSO4U͇+=?44EMdUL\oNc?%` [	!qmo`ޝ%5ZF0DHi>6V}quۣة5^
'ՊVRɏ͍pB Q|_͇D˼6;!`$FLWY~ MlR+SNpI:|E!6֚r/W+I rC!	+b-."L-At)NU#ײխ) cځ_270-o;%?]>hJd]XidZѷtXP_t}4٭ioy'KF&^e:</`pu>XoWSU'il MA#%9|'\Q=k8&XqBYk{[t޼[gMneGXp&n.aK6W[:p"7;?8%(Aw_lTzEͥM_Z1	ͣjbDf`G%2.-DU-
nwֹ:K,&]V̕$^Ų4YԳT&ybuՊ2(
Zt{6p)z}EgP"z9Q=/iH0)iVQȋ-|?hV#mГĳ.\c*:ah{3DPkpcJ#	}{U&_AF@g5S4f nv6bUQl"/7~c5ʉ/\U`<ԇA1:KY>66H'iVI`2*#fdD1؄xxr.(VS<
h2X
'ͤ*pvZH_j#fRwbpq2I
1qWy"8<AE^j8cԂGO&mx18	5!խpDasS?! Ñ6d;I58/ mjz)ukQ癱[	wS\ӭSU,n8Ng*I5j4j-6n-N[lqЭ֠֟[E^L.o$՟pPag_\lm$[W_P.F> m@8 /cյl@?ZyɩH&X5d885#QkeӾ]iOHH1.sSGJ[jĩfbyîo	!vWV]rc)W+X+7
'Mp0 ?`8:I	z'WԆ]~kQWTGqktϫRKbU16{nG/^~SJO.ߞ~fm_?{~*gt}]71*L
S|B5Ia38 w{ܨD]/n$iF8CƟV< 8;>yxu߇Xl?юK$2{,CRn,dcJyJ27%wAkVZ)AC,JQ]տv$*!AAt6sk|
5[vsvzcbM<}6wL^z}t˵]<hj_u[]tNtd멱DZ5zEW4Ct7;sqgu=v'Wd6
d>:(<OA\n*]rؑTǓ7|BG*ױ*t;+Ѭ1<aFtp9)he fEd^h3wV 0muf}rBNVQ~~5d"8]yV(zoa'ܻGl%NT
Y*ݕ|OL]ARdE nrز?DvC7iS.n*CqQXm#	%T~=0WOrmvq`	<Y1?HmFFj.?R0M*yT=E"Af}T)O󣕧9>$QR@DZ$=h̴>( G,#cR	:fzFs+{Lt)qdi/%<ȉ,D7@ym]Q]?UOa*Դ=;&"uDVDs2*zs&㈒]dq4/|kFՌ
~\(Tt7Mcr°5((
&+P4l5}
&cxt09>eFbu8nſ]h.޸^i7n:}gY:O=	?t0ly',#}3+]7nߴ򍥕ϼ׮hi0iS:/ӏjF  }EQjg$,%a,܊<cTTg%JEfFtD	*C-vg3}νTLhH_06j0Oru:&NڛV*CGSL?&bi*vjnWw"ⲉɿCzבIT3yYh`MQV=uL ?@yGڪAB:|>B\^./od,t@EBI7f]Bu7^C:0.>MS=r؉/QNe0xj@a3Ӑ7f
*[@i,TJ`Em )d]ꟓ[-U))Ӎ;R)y6FR~-Ѻ[nwH<.[@99E_N3K΍O'`?v.¤KzQ#/9`{xO#FU
-bwz 5v0*55>Ksy|O)׊Xڅ!Vl|s%;#,IՆD8SV[vY{%2C$=H\("cn^%`#AbELI+SKb1ǟ/Gm:"klR6B5w	8HPnz.(4I\1ћI>fqEf+mYTHtX}oc%j
ՉCRVaˡ⪕JK)3ſ:5azg~T*fs"ϲ9n>Qe Upq?C\g)EfuYnB8AqPP35Q&>Xi|5.MlGqv܈ͤ?H-'^| Ҝ{ܵ {p(i=ⱡUjLΣHl]bV}[oHqyǋv"=VΈc`Yɸ~0Y,9u	lWa::AK\QC]áeCp|C+rqr\IdIL8^C1ĒeXIM=Y;	8)^A`=PWC'#{e("7}Ȃ4tq^K:IT{eh\ukPɾ)+P*+Ey,M#~^uEzR( z(tlH	M穥>^
d#ifyӋF74L/؍\Af|ܔ\ҟ0T	5\/b{[Vb˿#v_#%Xl)b@OvږIp)d@j>1̀"OI,0x7nkʗDSH=v@#75PKK(uM&Itz<ڦgymuQ=mUwqGs=҉"w6CbǳMꝯ_U
z STO pZMόhq6RO"ݬ"a*Z8±E2,[XHLɩ-7̛JڢڮWF585&zXbyXi"TU)l)BiPˬ?m\u>Tät&3|"!GXwem:_g]8^B&Բ< #BvBx7RyE֨Z ^AMXV+TVVؿ膧cEθ8}uQ8'vjp> :?NY X 2oR骡.ͳF4xg:t,5vDAٴתuƠDvN3޴23_8ᨧHCEX+dU8;l(.3ɥ &ӫHWg^{A;i	)ҫUX@튁,5$zxkNJ1<s҂^B4)5ƢԚp Tf(Z̋0v 
&t[k|Ԍx"%TavڭeB9MXeptOaFKW*S9V9] yMRe%3X!.orڏƼT/6N8w@Ҳ mԾ[zWӰrɳ2Ȭ̥Πx//~3ʬRxz{B@հ^Pͽ{f{	:יG3#VH$P9x5mnab6%*oeodlne70zJhއ>t{)C;g%wsȷ-`UnXf9g"2E鬨hs	#攰s	*AzrF3J߷EaCpIe-7VlyFÔ9zPcOj/w|'f~cgѷJS5Ie*g,Ŷ1,DPQz#\ot66KYP}J}-}@lۑ\쟝+mGZ7W]t/KsS;(ǧstJp髳Cu~yjKi^rrjufuH+qսt@.V)&"A.KqEg&R}I\mQ'`}u ܼ%9IlnK)j	D54!+j*VV[_Zu#t+ ZK2<Eg<H=@&Hkm0Rm5)m׮ww߽R"Xx72,͆~<g<t	N 3| }RƩ5Fޝ Ý4H>/R˺ 0la!IDYHY#?6ooσT?|Q{U[~sIPEWpdt6Sks+jKRGnD/%~>r^Q+u.AB3"	v|gd#pf%E~[0yN;@[A7R̩]9	:Tp8M+q
f'0.Qe|<}Q>W3@ZdmkpG]PH>5L<ƁǬ*2P,T6G{faowf\1T=LH=}}rduiH?Ԣ2w
t`c{s/UfWnmzfk69ZkiLlÖrqv8LuhH4o5XTr'Wp@.~e9xXe<?]\ĝBݗ3#j{-uָU}jmo~CFRRڥbr"QV%v[	fLI7xd=\7`&O>JUs:Tc>	A[j]4hV6~B6;Vz\o#:D~uams dؽr	GQd0<e
`<yMN,o&.DbF8oGSD1bN8D<
SZw14 bRW҄^5'y8;#R<Zb8EׯȎDU#eR;hogֹ;Y	 "__#N!tO-8#=y%I0sͦO	P8651*|sUk[jmj"^vfK
p|c<Ө kD`}ILBub?{ڸjaoi(tsU:_f(̷ROb+t}p+NO٬iN4fN>KBj[kgpsguc]{:tIfшNQ*/6>93Ts_~7UØ{m;-8K6/I'Y, --fuKMc>\f
\CZ3h.&>ހ'Ƞ
@pAN!kc,nw[g4.'&Mc5L$0gOH{d1]<a1M%")M7+tW.tqL
tiOޒp{:H݋=J
9%۫v|tuN~KRlmԞjѥbEj!يM8)kw\|2I1XE$ekDQb826qK[L/Uny[Ts9`zm^ʅs,ƽlH0	mOCm/y0cGcޚXJ>ZzV؇StMdxMJj$mIi"l=hhL^lڟy¬ v'o$֔rvk	"KRMp(o'B$=Yoґ+pӯ֝N]*=5bm/>4OO1HQwKGxLZ%&Րd2`B+H4LS\*cD{;,7-fsfslTs 4XJEjv	nw)>U'-0+ѢO]S)e|>A^S%P4шZVPP[P*2Wa׫Hzgo1.I.2"3-(})31؞=,^[򹲄j07z'M[XCoQt4:̓u߀`mJcH[e,l$l%1^-
5ʁBD-%`!Q}y'wdzv0␏վ,+xϱzhAء툷J/,j@k +9j{BUl'\YpCJ_^64/2UOF療Cc.W]F~<+jz@tޞ9ƻC-ZCpD!m9W9_'xrV.C	AZ>bYڬg^ֳ9*u&_kT0_MP6ë"(ζrCc 1bn=$+ -<j6CEO4'SA4Ex]TbQZN4VcZ>D˦5ZBN"ec-/8ѐ`\uvl6)D	UOS93̈́xQ_s]qXa`MsT0u̑\k>դ'&_a䍧?`cm5c,}68kW5Ԋ%j5x/G6HGH:aec/lj$BG)v}2B#cGX񼡆 VGU%p'K;O8u^
(&_OhT,=F+y"wݤtEpvm˸7-n*<ȯːU~]#t
w)o7[Ti۷_j!by>.j;[|Yc)}jW_Dp*PJuTH:°{T^)ciƩLV98M>.5	RejydJ<y6~M.۝v~p]|fLݠ|3>J[A{D*vͭa/Ļq#n@mʤ'; 2"^r;=txxd2w	[@EE׳x
\zb̰$ɐ1FMA'Q%sQ$^J0nܫ Öv"E&CStK27-s.1j Dw^&! - {u+rn,u-ʱ2z!nP?bgn@th_l:TfC皽PTe<$tRWB@h9l/WT#UMiB6kfK>?d4 Ek$oT-]z۵;9bR%km8Ɋ5`\ؓ-JMDj|^7dfG"#O9CӜLy׬ovvƆ▰:/̭Ѕx@X<˖yYڐL8e땄M!.>-D8^y6	aΧmFIw NcrT8H5Cʒ>Z]9mըT*94	՜߮1:\ ؃<\mwL@se,lhp-ѤH+R'lCSHƦJ7(R)i\*L<*\4Txh#ӱN#L۵R}]xq1H{=Sc~%}xLO"rL\<6~y+ЏfYln:]_H^HbzK8fdtw$&M>ΆYQ^U2ĥVk+6lV;$I>\C{gh79vLֻ'*{Uǣ_Nl4mΛV~db{pg#^.`\I>DQ{:)pF8[ĉV
u{j66d5tk($Tbo5@HP5L;\%:sVO˷FlH}<'T%;Ys[(گmU7͛Zgno'_t9ցeg[/Ck:fdfMq>D|A0،A	Z2KKPH,҅avey#QR4»XiW&b#W]RFjO'{dN9'0Miل@[\mKn;Acx!t=D5PdSs	dߴDd-~zt <dP;#+o,+$x=X6/a*%&j5(`yR"E2~ptnIхDM&4"suїRU<	+%BSijU)+RVuܤw/H'圾&\`2iU26˓v!v؆H#rq&{XXx^gAVdn6#p6`*gNWδE;,CP+IXN&_8S^Ziyz>?\mHnd I8 nOF0~?ɢB2'<P<{(rUPΨ{fOsY,yn
69 ,Բ_q]tR pMM<AɌpz:3!91&N`I mf)bW9遪]fy(\]>&)8x~N;ZݻPQql8\5COy^9<0Bgy<kl,u'`x=f "qp³>5b.O.G0IHGGf_S-eg'>B@ZB?p0582	xN%U&࿔u)m\q?;^os#'|7:M6=>F[qk"֑{۟}ָ(|[&PԤY[Q<@Fstѱ8Rv^4G12CTݦN5ׅ;T|6zRԪ>_Wk6vgY]|uGB{o;b;B@KWc6F}V6Q5iSp`Z(^ةM+!]dL?uE\,]eRVCggr0r7I]aj9S_-JS'W^"hli_LXA{-Y_Fkx F(1Hs=pܴL of ch@k;2Y?PW	q^ nx|TBmL/X(<i6Teɜ^aАA}K>knB
W.h=0~KCw~uΊl|+GJC(ze况})ۤ߭.fb(EYҷulRHO<!iIDdC<ט2b^cf6U` +ۼҹzv
,Zz䃔Hc`׺ӘӠkAcl+`!yƯE&T@>*Q0ɃV
}K?'R3TIo+4m*(Xuv>k UK"0R]%w=K hM@s]ک9R|^N:S~
׋_3/[x84ƿS.|Z7yVA1.In#-BKJau}aQ+֕<-(Af*nWFVxG5SuDs2b[rB\SXohm{Äp̽M_mkH1"2hr[-o*ǰ A-%ηTvrpҟLF'e|0yW`_M5ZÂ逷+pJe++j\?LMP?D!WW8{S{CKf[{VH4mq39F
GiC}S,p|TB{Q(p?w謽e}p$k	;.@F0	һLMx`ݔ"NZd*k	{jW!|{h%?Umݞc|WFAp iL]kM5NY-C2eMt!l~(r#?V)A>wP -i>!4C_r*]\q2bv/T	`Tt];[temm__rË.Vp>jZQBcrwq)ŵJt{Q7"uo0LYb^Z.TB09)-"Ԅ9;Iy*ٸhOu+;x{8s[d1u6fZu*|qY~pƩ_7vP'tZuUe_Su>wמsN#ԂhyraR4G'Oٴ66k3V
jd3!+2j|F2W@G ',t\лs} 7$rY;cB}`- \L	Mavx}ֈ%l?>aVa^Za#ݳ`zŤG"豼tLq6kUe%t]'3ˈ270CtU=@!t:%rۓgք1/	]w7ѯ'䅞.gXWWMlWy.pEixW_&_|kg 9rc5L5s
5˯xyTvy=hIdQYmhʲjt9`mZ(J-ݚf$C,s!DDOB65W@	(YChLZ!@_!wGeO=]ЍpUqBD:ec#8.p "pT9Pyc_wFϗjڴC-He)S2	SOsV5bpxGGhbx nBƈ/1oD:13|9lkafe*bU+ַTdRD͂˰V9Jk^V]y,}nzׯqwV˄.66ڿ^lz#y6h=ī1`Շ6:`sfEWLVW}x@EM_"[W؎x~@y{ϧ5P*
CETep&)Bm6l5辢kgkygk24F;KE4-tTLp	G&.ؚ ( k\rˉd(ѹ]P09ݩ3K v0L)3wF2f&_n<|(M"㤁z]hf&YOԏp#'NsT<޼lv	^-w3bKv9{U$]SM ԅ*_7't/_?v&_\OGh5tb&3.HOIpMaʢ1jRU-KP_8Us*mR}>gfvJJ#XI1JJ "vf	nUV7r5eyH`V:>f::M2ÛB_ɔMJ~<2@D1h,fcX{6]G7E ~ow `L@sJb"AAY6>St)_5,uW"ׁv5N${̋%0M{|x-/pWT<l\&ċ^ζ6u'pEvp;vX,_Bj޼$I?EVJX9l10a=T@BŨJ4#Ϫ{fym#232"22222D<@^
AS	펬LʦewQoid{@R<|bV{e2l	뙞խV|e݄`JC_Y>啫.t>މ)*kQn.w:Eؚ]89I^L.rAx4rHJD""T(eVS㬍/׋[Q5hOi3tYvRwB
Z1MX}fxA<QfStMȷ#iek6C~r`oa}to]Px:J`&,LOf)5NXig|Sg1ٸޖpK`
&B[þSY*ɧsGZw|@ɥLsRx @[Qqq)vh4D<jWdڲ:l<AVW'Q3D<C ٍ=\GSr.[QB?P&Q:nv?mKPbwo2n{eqO
 hP7ǭ#=VÚ,F܎(o\POƒ)kAzuk/s0
Kǁ]^XX/'['[ _\-*|i@/Gw-N!ˡ?5O油,p(5PA%o`^MQffJh"j Dy=#z=Bu9E"[Nsk81e.5TOVMpNsxxt::K;0¢uiS}]{IxO̔`#vއL H7e~J3l㋋Ie'2;̄#r9/ηA0~(3rVP\eIF"1JOZnK=l.` fepHEYi >uJS$ua}k˾?AFjqgU8F\I͊.R- ss}-W )%
",=
)]KGn5G,JJ /f=;3/}5qWW~|Ft|;4gr!{/rK鈞* \Ahԣ;hG0|m\o!r.xѩ0 &Ǳwa{b>s"eQTqG"Z #0OR_HAsHҬ>B$EIqY,yOt'!̷6;#2nSIX哐mꅹЂ!ct5uW)ԸfO6)$+}MZTQiMN$nǆb @x$ƠWfe0xdƜQe;eB-sJѰpY^2ҬQ?QFp`NO $h5Oy՜dbaQ?QG¾:zRG,C8L#	sЄENS`"᎑ {taNmL/`=c%(Yfus2,]^zj|,~SD#`>YDW8%ia-?YeM7ەgđ՟\iHQmLu 5L,&h9D=29{0zϿfGX lS+>(GރJ	@=M,]dbe"\Q_FGV+<}UW[a6ە33>nl]޳nKL-tzhSJ`xxzʱ3om9Rq4JF~{HS&T[ьܔ4K5oH8ADڐ)94&nP3xyqw.D޵/HemSHzg`
9EUF}HQdYҝ1)Ac\ܯUP_rfȱ$!暓m 8YD,w?[3i)Eй-C㈋wv_Q*)<Q{#+Z-VOГX[ ν W947e=wkfl:L,TnJ'pE}un; gw__G%]BѶ<+rkE)~pPX,J냊N?tO6ou?zO!9Pon"lg,8}էT{Pg|i*W"WZNpQ7R=xUzF/.Ḓ/Eq`O\0iN\/!Q!MI^ATا|k<EEKS~Qg[D1މ.<7g~!X\pg)CHT5vHLk,vv}kU}A\6U9rWʒ>2.)^M"9^&3+Ͱ:a宺Y_kB\JJ h=܈H(+d/zU_zXg_i揸,iHyfaR2OcP&#su<RQa.U8y.GY^py;F_&v;1[Lxxw=:9^n:lG?ވon$9MY޶	.C
٭rMۉnd׈w=!Մ3v}34'cv5NV#Rοb6kIp:!]:uk2tMd3D麟1 b1{R+tyɁ*_fN淢_0TtX<3
 şio{@Fmn ll4
hC?YSVG}P?٬s:P<Tqު5|}||IՐjxN R	YdkN8g@tic/$tQZm|<AvA92A6G-")eWbmb7A<:]7hJxk!P[ݍ#M2=G)E2	|md$)`ʝcJGdc~})w=[B5f
"K\A<~esoR-821Svv/^	=wYspɠ(^Sǯz$qC=H0|W7Rr|@lb[؊Q77Wis͸)$')ŧ2<øBNϟN?F{owLKQVv,٨t^()a7Kh/*vg&2=s]<Gnmsƻ/w <lol}Ugw>	f;/xhДqF咺DTΎ~1.Ctc@!`M(uBYΡx͝]dSkT7drjH;C6HZU^тϵxbJr[2nW;>
H`FZdU;"a=`CcEY#-Cqwa8,5 _jvDC+\֢h(ExH'QUXPG"X )<)a˂gnJ LAF
9|s||ww]U?.lgF~/28H="IEkN
Wa7GѻY7ť`9HAP򉠿ƣs`M0qt|ޗQ2ߦeS6`+Z[C 9*(a_81LW.o0a-қ D1Bz|-	4okt	퉢(>fDWg@32(,Ctػ#I&;yҡ&ho$ Jl0QۙJckrzՓl7no᧷X_п:*f+dotMXЧ{;C=69l~iw۔}<UM7v)W<?D*3I_;(s4E}bص]=REuQ{X,+#U쨲XɓG5sGd̈́d|Wnr5ۍ\a:PtYtg♞̚弟hR5JFJ"X_^y/5mSǞf`,YKUjRcֽ+)(1)E x,VeE)yfPa`mA/`N.!U6n(B1i')>Ezik`'H'IU]
F?f aQ]@۫?ɈojX7#1Y:/%|F)<lZEZA"@!0+^">fiy)E$HoUԶbLPaCe FSGG&HkIRH_J>z*bEbC%`edLJv,T3;<GhnIŧ4|Ev9EF!7E(2LیXYb0(7 ,6$@J),7$9I TT/.~bP5s[=D5)sY??9es`OvĉD$Ϊ`HY|e6!3w\7[<U";;gޏ[쳫>~qP~m^|y4ކ~n zR V"+F2d֕"anaƀ^^jjbހ"gub7&83>IEֻQi܂LVP4M	An@ 7Xb|0|-a4PU{GN|3
1IffipM\yf:)b**wjiR9S-3޾D]vSm^(3e_8`G{ƿ@a+@@"JJjؚ1H2&W]ƛށ1ThO3I/ݓM 6!& -˗?T<z¶tS?ud\^IѸIdz~ø(qǲU&\wK[-"sXHH`+eKx+V	D(<dZߍR'Ԧ}P-o`U)U<0@hLwdB)2RjI,3<\G*3L$G2[}p#0aŠ/ϰ/之Tv1XtH/E|g-Mp;ɯ3OC
 ;A9dRC=y*-0	8lrdFy'˔2v[V6 i>W$2݀fܐ\^`)d\/}eX
[U+	DY*zI($16*\|
`Drh==+1 _l|Z<Hz`chv>[k#ʗ.ooX%|^z:fTȤXD\㵓)+ZZ1sG0UvTx ]hE\ Jʻ`!9:49i >kRRr$d9_oR|ǲ'7{y$|4	!K}Y/gIDǳCһ
cYH)=xc% }J&!tC.ϟa#/2VŠN'=|4ΐ.uVӍT,:D<|ԍ)TX3_aR>gOCz28K?IOÝÝߺx&wУm=a O4j =^E>'?w:+!_-ts]@pt3Gs8}ռPSq|Ә"'Q7褓%T wN_*KHuQtkὠg&")-P#`	kאa>LZTT+Y|e||t1IP'f>	,H+*lxqp CP)6nw"b^&!qn}1omZ}y/EW\̟&/yfs;@hB5.c0Tp.<ltp~vV&KF/wWޅ^l:^/^)M_~[gf$ϘޯgLhv~ss%ATE%|9Ҡ\uRR73S俼_-4DVϔ9gVd+y˰R	Cghh>80A]ѣͫ&Ȱ`%(jo~uhk9A3=zM[#PY[n/?2<<s9??#O7/ry\Ԛ3;k}#R9IVDNH\b/Zc{A.n@NFdTλMtҳEo]\dF]d(|_)jH\߸U*.ڨ;B_u00
2Tj,NuRh=|Kt-cN0 "*)%uJP=O:bqb%<f\tM%	FdЎi28PsDbm:Hp?0N<*{.gUgdɡBA9E<J^sŻ~{Nw^9RQSidjSD	56ҙ8i@*8pķ@a	]oI-9=?ŌaE?w
sa	3HɎڲaIvUGŁWa=%',Em\8`)n[e)5-x[G#DY#,2Q'G9%wK4;A9QiGUPp"z"%<ӛuFʓSg	tK+Z7LR\MpGS/F$bX*h!	b*TH)O%K'[sަN!*%q|=	:&_).@gkZ6xꡊ0ڮy+§(3k2'ZG-	!;ngA&܈*T]գvyu\wu_B5_nsH'5^Ѱ7C3@]cjU^BI@~@/84m;Լ!`kĠ:XeuNlǣ02(+;`7)colq)dk7Y}?ߩY7yp*|y9-gW^t2障9+2.BX;%FI*BB'I~PX
/Aݤz{%t<$B%UE硡$+3
) ڧp6;hƋGD%Oi
]	S(Esvo%oBva׏=#B1?Ca+xx	z+"v2|b4@U$R^ԑ3vi 2OH@ Y(!YIЋ/Sħ T4
|;o0BTƇ32`}^7,Rᅠ,aB	Z$aPI]?Vf_[Ƌ2ѕUshCvE8C\e3C 0wy.L٪&zC->lc3t*@gWP: N'$|ƫ=K-}T4sG#KGlmI&W A GR~
 @b)I_P	n9> 

E6$GHo#rq~PWPڬ o"&Cq#q9T@uTG9]^K,9UQtkb4,좳m|+ԲfMm"VK{x#9ppocĠ(08^n̨|͗'٘}8U/O!4hLɓ=TT<	+`V4qo͕+ptG&&CcL3~j)Kj(]Ǳf2ʫ~	2֝-RuɳBQ}mu LA/dglfr*JW~kd@>ll6p.-#SQhuqeWgjj) dSf"J(MMPUMTÄr7/y^+zt|l
 &}4`aYeo]^K!z<B78GJ_EΫM^}R$0@r竩V5C_87D_=xCm)
ͮԂ
3ǑdIt~f͚$|cmUe;@F|2BCƈ[qk'DG	2nB%Q'jɠ =|6778yt"qD׆ɯp;`͘^0Cqp)j,2)	0/|t->TBspyP_[GH`;r4?yG8[
IKlX cWhq95IདྷPڣ0]kBո{U5N_]*w}TC,r=j$`	lz$7R~<K1}n&S8GdeS_?FIH]Ί\8yErzaL18\B{}bb4:ga?UQrDFI!M3М|e[)*RCt.$)z@7CB1Ѿ"	ɘHM,&7{&`%ƺ|F11Zjv4(ԂOp;c:04(m,+d s(qj3_I)#+ZAZ䅣8pC4%n!2b8T}(mR"F	VI,25bWE!Mq=5Tes7*Qpt1XIX|}H3+NOF_C]WMN;4Q%RFId`#u+ۣ(N<5rS:+gVQ[+cv\]lgJG9g\JNXe9*l] ڑ"6"/O#my!3s;n&.xilߪMX>2g!'UI{}mkM~vfJ`=C󭂧V3rVZkyb/#<lAsLq{WaAur4UlEw;v.[Xw@RetơB,ӛEd &V© Z[=|U7<U"jXGT]x.vBFJ	]tP-0Jc;;{JC8'mt[ԌoU\X7Od.:Eօ:i
Ot>Ic?hp+&s{ M!ѠRP#.;ǤjBl6 &̦u4lNgl:mFCz7Frr1Ro)'*>O
nt;e(u3L`ٚc`]bƹ9,.+E5ܥrɴó,Sd@zm%T<h d*HT"@[%ұE|8jb2&^ٞsAį )$THa.Wj?661 XH7~FڐT:PE#vO491m9f@)J*,'tc ZfWפg!J:\br:]+r4wFyp*֡I) Is+Щ2o$TrGtد x־`/̐~qiAre/)؏92o*^ֲo,Y欏9Aʢ[N-gY"jՈek4rl"L̝;)z GOv"jetZ6$_lI֋=hu*{M.<*sG ;E3<@mbQvE͒!HqirHMsmj{pL[;mpn
M<Ө?B'~dŏxIn_~7>SsY!Mw>>|p+ԁ]&Hj #];ǄMː<mD)G>R+ӺՑnקݗ$e:rDBPW2)6ف4KzRUz?b᯿}PB'OW|ăq:X!~=6J0 HTQf~d촩⹂"9E󴣪+W]Y"br65/L i 0`GnNT*	8_C-cɲiA-i.z.u*;\l}"H}8U_%wNX|1@9t~|):"Ayg r
ؼ U,G{^<5 >c[Vzbg/Ya
Ѐ'?؝zlmY=i色/oYC{[2bPfhH˔r,nܖbӖvߖ*8I\IcPVzěSLW"+W3uf%ŀW!e!MHܖ:bNYkb4VBYK)ՑE5P
xvͷ@Z靋6x^Ke4~;pŉ'v0mt憥ڐYI-膁Ή/jHqʾ':"Ԥj])XL="`erHyϭ01joj/u;(r5fgeOvg2>MЗ 2߆m4%$W%#cEo¤.Óo~$
/S6&šHP'U":%"CqٱLaaQ/<9:S~bb]כ1\rx_!R4rFT-A@pi>F3P?
*({~.T-rso/herYeq;ޤsV PVAf!}|O7x0r(oe>T}+4fZVU$BAD%A0IHu]-[fSI)VΨDWE);PX3nה	H斶/mkrEG$:Χgڟ!AdGV[؆3K8`-ħv;Jbɰ>{x⋿Eƣf&5k7Józɱo;ъjU:ThRd
Tg>c\{6ցFȀ[R1\VWRԞ949̒{*ZG2ti({9QO HG.}OZ+-"AZB&.cL_F
=l UBAFV#JSg8(9^!rBՇ־ȿޮjO58S6C0<ZLG^ߣӏɭH@&#hc%<LF:K<tV0Jqs"gL'4"~Vs(9" u)4ZBEãwHǝ;hoUvN>b.$ÿ85V	)F97g@v`Ê y*o)N)fY顰+#QjHvB=QŬ"zOh̳ jA@foAhPh<zo$,XnMJVѢAa#bl\`V\YrB-vA-E6rʹ	׀ha,Z9\(G+5#QXVU![v9S9228wkNGLO*X\68|:G+|^7J]oP
I1M44NP\TEۢyxT [ -mŁƴ#
&[t!&|\B'ujV.,)ň0fG<
Iz=zE,\	Y _|UTAO_V*VW+Øfh1yO)b=w΄BxKpwG;í;GǇu?ony	6 	9B:wQ8jk¥-	<Je8ͷFma}~ln6k5\0K[eY=ah튚XS"7rN:wm?PPQ;*&-9ҙɵl*	^R"2mD2*+o\nḓiLG{nia{iɡ.hUQ:3ޫeމG sHd--I{#Tji:dPA{	;(JA%+y?ޘAw$^W0?;p6r!d)Ҍ^X.˘B?xfj80(li*g{P|Xf{\&3S`xGAFyl|j.ezaԳ5jbrAdX_[H	ÄDa0.AC(/Bz3Có[a/96 (}ittOOh+fͥFm{Z@vssOZ
)5f&okؗ9L]o>kj.dB(8NK9UJ:(M8Y뛚u<T򫛱i⹆lFP;)E\8Ln6:6`Ĉ3-xsʞOfƁl،-h<pɥHeN/>n7"Oi dJ1Ū?=`..p)+ [i1o))nkdQ9e@]va8SEklz<f0qDy?IzSq=T:
pqnNżD~TP}clCyK(腡n'LA$%$g5["UNAoը1fDC5*8Dyr$wCW.^闽D2\=z'>A+tQ^WN_ϝt=81bک]Ls]<(pV3&laTf6w-Y){_r#v;i&F/Fv璛80Y4k)=7-mZd\ngR*WpT˶%{ Gf6B
ڍn">'])SLrEl]4o9IixnZK9w\ d
jlNB;<DYqAEm$2ߏ8!$3wp7ktVEG~72tQ?^E12{͸9,9m$WFrfH6O(bHP¸ݞB0%.A5CBOpgAH{B#l3Xal6jҢMOϭOxY|#?[Aq˩@7A/L y6wi8S`~'LᢾN>VMMX&lff\&UfN#<211-"7v}&m1N݇'*Iv*dSeq6
oϺoj2S_wE|7lIA>s
~,$c8@+r(DHoUe	ssg={pKJHw@or>ftRƮIvSz2LX -<LzJJ{G9XR%$V-{XfzsÓNf-{gmYè%ej@iC&s.
=ӡ=SZ\"<G.-p;jx}*'?J*.Ĕ-cz&o :
^4D w8.##e
1~NT~՗aĔكta)@Ͷ_PsiLM4zMAZҔ}H<e&[S2+\zh{Șڲ3S&q#kW	cRvPfo'٨dۉ$K#V1݀bӏY@P\{^VǑ_.+F4DMZ<񪧯 `u0zU0=4AEv/a4h=;)J˯z|K!#ϭ~U[?^.Ɍ	W'%m9e~6_YDɆ~v6%EJ+Q3a0q&RPy!s*2m7~gQѢ'+X{荽`Dw]уg_㳒fP<Ӆs#њ [t
 `mII܁k!w[&Ԙex^M/>2Sr?0)Q(RIQ193.)BvF6ڠп\q`$SVz1mGm#[
${3EMB:8sTNr|aBH_aEح=9mw;rwsK8.$S
WWFT+槴 q]06k,a{I.yP+A]%ȸc&'>>eUToFŴo[b,Z	ʷ1nԃ^?XPCm=''^ȣ9O!=8)_Ed	u{,#"l;v
7V|I',e2*O>wf^SybyQl:\+HCU1AԷolj &o)b]{u5ӓbvԵOIה7Bm[ѪƯur!3@ةU?ïxQas59R# 0cRC[G@<]]Ge1 -mF7+	|3PzH$h"mSs&kj2ldUҤj{АmH+'f&M.Y;ISz*iGRS<ӇNsbܮ`5UN|;嫌2r
W{C7^}:CǬRr+Y|Ƌ!gVaWӨD-d21db.)i2%SXN0PING'FHIk`W"VuYg/,/%x)h;TCzpcIVn8S9Ȳ2mnFߧ`4l!.e0`R'7VejQ)WY	X	<DFS,v]
JPTSn̗tLʌ](x	\S^5WHfknN"JSy:{SB!B23ҹ*-Y6><|sXw024
ꝱQ'4l#d	C?B5s]|}֎LV% iBH?yG37,:x9ŸwDAYǃolnu?џ.,4h]U::^?m}'׎ͭMџ-nwgȟ_?Evt1Җc|66 mN)%+nXIB="]@@f#=.˚$&'SmXU~eJ-uK֕Dq@oC*jϺKU0
"scF60,<8C{[}` l.IQ+CaeRE

e8lJgsZb0keqT=hSdX+R^!Xa3{*"z HbSoX
]P?{Xۉh͉0{ `v)k
 WC/mPXO@u+PұًǶoy=R0f_UT@:Kl>ZiC-ʒa'"4q$:Brm|<م:zrc#){ʂ>tx$rxPNE=$6nwd\@9:iP?40Op~30^`v`SgX#ꊢR;[ğn^`sڴBMY}X~F,GÒ앂(!dc-ZޝΕjZ(ږf8S|65DR	i
2q̄_8b9P.홟Y|Ru+MQJV0`qh<`Wf>#uvuA1KJkKsDZk,ڌ
@-RaZ&*(h{'Q#ox)4uL}WR_	-U;9Bbɒ9H͈s(|qr-N1d4kmɤ^zdoxg~wƑEz06;Ï0{Ck 3jsݫH\Ȑ)d<fR`|dLscu`$a)uC<'] UrA	<:Yn@n'369o1qڛ[L	JǢ(q_L|YGje}dk**R7})U VCl-³I_D8'x]iZmGDCeʡk&[ sRWF)ǆ8amsgzPPJ<k&9()c;8WE xccAa"*ASJDB43f)$?l|	:#F8U4֬V .AoQ З.J#ɯ잆r|p<N/je=Ejz׵?a>RQ*[FU$$8ګ#-;f9uqz"%yaN^kܽ~2AB5vCMVD27M㟕3rՇJQswE%.y0X?%0CBT:?=U,CJD "+6
N3yK>/(8R"⹹2 ⪴LCWmRu5.
ӫ:Wzqv[ݽ6kq>3~xz
W*l:Oga% 1=0S{ELFKRJ+|XOft^mq$Ϳ"1dqYBge4:ft9<@&L~'zW5vsi~yA0 E(vK5a/cׯD--}NXwssa@kW;_fk+ͥRKrAG#!I.ׯe2zՔz7QB>|7!2sN4:L7(C/0a*Mv('FJ jU>tZ>
S~ny;==_'$-h\h>ej_;0~)c0(KT,l6u5M".>OOQΌƧWV$ @cA=177=p@ANe&<@H/	Lg
R~&>@]c;U
ےDBDB Vkזv)O^5;[?Z~ՀB!rAq+}ROW͐TV9ңhcJ>Y@	~"94rcRDR^,WJ.>5maYgx>ƫlGh \xXwxMEθm"@;B+qcF*Wۮ|'U1}]m<>f@,zA[hږt$GĶ		LN9IeߒR  l
 &I&H}ZYHꈃ4nPU
%\R	@xm2V~KC0 91r-hiFds6ĥJTzYמ9^Y	DN"+Ax:n4Ej|?¸z j%J7n^Uk	ȚJ~rU(,9P2t/өG:3ZX4Y]Sՠ9.@Ѳ{AٸUِ]e0j/TB.yܝ̬+n]&$Ͱ4KU5흽m=9PŌgVdVdƖ"36x"3vq"P^>U,[6;ssE~pΟyno ΅՛Irٻ%t/Nt E%nnm&l5B].o{5<شqz|P
ɶ9|ՆJEPW:DqEJ\%u,-؟Eu'l
d(氡qN;f~ƙȚOD=Ak6cPOOrPawF'Vv<$urԬ%[oEv=n7/Qa_Zc-َ-6sd)V8w&;̡O`t9FOH򦭲uzIOǦX^fe.VgxX^	^(~HOg~ EH:Z]jGvO8R\9]4Vmd{(k0^E@JU:: <	oYp\
}nZ	WNpg*K'Y6 5µiX}Ӱ3:>Pr8OO@9

UX&Hh4|8mk`Fv*@.v"HY"Sٷ>@,P ,-.`_#c.881l^{?>YE_thcjz3BA?ttLN0xçje(Y0Yƨxjt+3QƧ3[kKm?k6?o[kv|3lgcq'=d%[o`ﾴlڎ0 GJ<74jQhIRJU+Q<AbPfkyVZ}~PEu38mCl:;<MUX&T+2f1X]]]*4?xz|(0mTyni>__[hpl=[q"0J!J@ 	EE$cޚ<]$~]/ 
̝.g8}7v>SfNm8`3U:
7Ѓ3gջ4|ŧ3ouA
'&K-Xf{~4?u&D?ZYYBs{"0{IQhWF5I!.G0׍f5ӑB1򓞷+1dWoG6Ux=!< c"~o[8(^ RBzq_ߠbp-h.oXYFv7D7$\-Υ()R~Lzl!;P)j+_Q`@jx
c{lfx#VS#Lms	Jz4H}ʔw|ny-U.8lj`;jRp~ִʡ	]uiK-A7?nQ[ﶎGEvuk{dMloʪN?uvnA
E,@qv֯K^]!0PiJott!aEC
N	(`kheRlR9Ϳ]^nm//ȳMvX=iF}L;]1ՠTNtbj/}:"rO3OYkͿ_Li۾
{XUJ
*v2BjDK]0Jm8WAccta Z4$&u;P:&`BTW念`\u'-KN5'y
Q5ھ))Jʶ-	 <6N?_=_rhRL)$kAq/m NRkjR5(7մFCP#O4$VՀbiU/l2%ie2e=JH/rK4h.揜~ַ{LG#ZYQ=W:SȻ	k<ꡆDYR1NGUPDu>B8spVWůVE}{`t {ssB/}/h?UYm-PժJ.Xfe0W7$V.`n`5@gʁp]?I0<?hqAo́ՆZNVl4%ma+:S3tcYjT+	RbImGG
6
@e}YBU 2RwC	dՒ`ˁ U)XU'O.-"f$yh>y11(9Ϲ$ޒe`V?VVжwSgN!wXq	ZBhNɕ35A$p-Tj5Rr:rb"+QJ\Cc,%NGr5D<$UúiGShD	OD	>jL~EPm*i"`ŷV
2fKLdJuXM,>T.k)"AZo2Fio*BR4q^6R0##L峯ABVj%3QԜ;5[4ViDeݥ 0>B
N[ 1F1^>:$iw@??kݴ=ND^8zb\)i2§YR$^(rfE>L95}B$xaxJHY!g~&SL͚b"kg73Jj5Gq,رtn|IY,^"]91}e&QQMf.[&әS@њE43v^Y@Z=@tVXvC˄wB֦AF"A<6Qon筽rlo=\ݡnxTHRd0>Dzp|9^߬x"aH6@%;db2|;N7bh;S.R˫dS,dЏ8[;rZ-8~GQWQD[򿜦|Lg.lä]ț;Q5$mS#-&'akre/ X#nU!3Hǉ`ٶ2V*c=S=?$Ff=-S}/"F:=[i{F*V(j&S@U"7?sNݼ*0̄3K$83r9IMin{9m'~jXLt'Vi_T^nq_rRN$0Yd&
Rzݙ46=MX3e0*ia4j
(#AViS]^T61>PSVȆ_V->kS!Z5%I5YBiX5N\R9Jov4_쓧fqa-voWz4
Φc<{mNq5nUTJ^.Gt5쒗˒'+XZh{H %5"0Zi>>V?>>>W(4շ	JV?zՉYcIR୞8?^YRAx-Jb'cseE%S"IPb`IQ'ml%!bJŪF;wjj([F/,Xg8̓Qu	kdօngsq3|>ysǲ1)W@ ;9cVx?[%}^G=\O_raϋ=Abv įı_~mQ&3oOYߊ_[K/|C7ߊIZ4a
o-.p |K,[h$ފ8WP1/9/DȚ!s+.WvSi?6v"WtimQz3|swќ9:t2rj@͙"%ќFlC4,#@dȑqFbՌ_8Vo*< 276	iVʒ B۵O%-sӚeJ2Z4(h-8a2E}\|_'q@^v޺יlu	[Rzq9i%X-R!.'V
vcKѢR[ p	ݧT_\}ecRN\TyAk+/{go}BX[ꊰ?`sRTb1oǲ_kL:F]k\]_kiPl`;
-iĄC<:X$U\Z0Yo	6Bc6ɡ!߭818͹K9WtRcZBTzsŎY[m5U$(ði9i^3U9䬮O{k++rW&m%%/P}bs2WxCUY|.v|-L$mJJmNC0}Id̝H6@fbU+eV/Z_aT*ͣCK1YYWvkwIcٮcXxJI9d'3!H/x~` M:gXWk,RuŚCYN+NmCF0*An'חgPpU<ʩUv,,U[EDx
ϥVJʄыk_rݐMN,1;qv1qovƕVBoV@2iY{weB_q,Rgv$%+Nk4V'!MS"v`){Қ% 1ZTA'6	6:Zd56r{m>drrƣ/'ĴK܀B#h!Ig:zód0zmͪXi[l
NU_쯪 5.\.AB9
%YGN4݉a{2-ǒ0*Hn7ۗ/O#ʉcQ:1&FJ`9XRifi8H]x3$A&L>ꣲxuw(ڐG@K`sGpV@L-g>^SYBh "LؒjtDݓSuwF0W\)
E
|3(1
Q{Xy,Pl1(<XoXTڳlhV?[v>`f1isKۧA7&\Wiig*VxF㆗dJJ{|
#xnaen/
mn$l&vsL}_yfu4tRm]F!'Pjw%}C'l˩-DWEOKq#ĭ,Ž"~Qǈw+~To-ztgL^su1Go5d7닭ş0PME !ޑ㯫sbዮx=C8iH1_"(IƯ4!z@w2	ȴN[3qG7WVzWE.xQ$K+gvS1?gѫ?(ue\ӑ8w
>{ө@_ؖ6zxuԻP- [-}'O:oiO7%Dk!k7tkAQ<169E(u7zw	+a+<.G]Roh^#p#
S!M@'*6ʼ)Gǥw=?6f>%~3;~k=*oj]/U\{<[=gv >b峆S H5 =8١Uؿu<4{'^mu3NŴ/ ?߹r$c07g[.C<T{lPoƀVWxg(zeeȹMiuZ֢b{VD$Fڨ
+BC_SX{jY|ٓ*fTcyni15?i'-,YLGu[C=hWfnw+e鏡|sNzc
#)\m$ʵVC=C[O6
uɁ҉(ѵZ^t0s7FO`.Hlߨl[W1K*4U7Qܞto")M^A4iiY!wjC5ӡP#CajUAXh34
]P!:\@jLO8Dj
F,;`cG-qW@-$f.@)x%$>7z[զldFV!K
xu:"Z	e' ",Ƌrbdb:ǅf#iIotB#trL #89our,ArܯD4A`|˅ع|6[T^biz*4=oGQyW~P 2: ^&HR3z1)!fM#ۇm6Y1Z#VU	;U1r)Je>jgBLj6z;Dkw"*$wO]q21RDgrvl[/v]g4 y
	7:A"oA}[_/׀q-oW m5{؁'Pn?] ?ͦ;5q7o~sAw$>Mtk[#j\Z "CƵ~B߸>7nqO-mk"1Lcb kO"܄xrČ[ASnɖ?B0O~
8[Ky*.SqTܦs*Sq/=Rqڌ=Oѽ'mex+ແ\Mtjy0!M\<#̶[cx-3lf1\؇tKPVmN*H?UN|a;kdK1@db~\2v:m)(
V}@*8KE<:BJJOұT%`j5pU7o-Mǒ4JW uأ|,%%3|=^a	D(LEp 8iEpka
95dTOWUnvx78\o{Sݵ?j[O_Mj&A~~_XА@Rf	XF\!0RP"B_Eyd4nj43;sFe]9Eu_OkTeLoPVm5-=6:PP$oImϞs:3"O+onNÄ2OT2GsGsD0󎋴&_4 #CDZMK_;"þHq$}Zp[2ۇ9yrP	rlø_C?h
3sPt]K75sEDX)3,/EL~o5Lr/Wb!C/8^ 02	ЫQvV7ΣS88RaC )Y?j LZt3$y$%xdBYZv_PK@AtU2KucٴR>9 :[<<lyRJnJܫ~eJ˯KIs?6~ʧ4o)O}mU[c;`iڛz|!ЧFëFHo[ν#-Gc-lJL)dSK52(\[/D{Sa'j#	>4j?MxVB$ǃi:W('|vpMwJqS.}lf)*'@AHT}"
g1R44*RmN5yJz)}5fʓ5rz){	ަ\2UpЇ~>N\Rg쳘BO.?_eMk"g9xV[eh ,gFW^zͶYԖtGx
-)?ξnTkܿ_;y14~zMpd"5eŭ V%ظw׿'
@b.%zV'{t3~$Ǯŧw|\xMxu@PFQ
45csb,LWÛ)Eg+(F*6<KP!|Da|XF)úSK\uS#)?}$9Gj'6ѫ*xk?ݚֹ&-&}`oWZD>ּ9at]>TzP@m	z|T Y3F3 >?lg|NIjL{X	g+^FeQǪ4UdU[[z.¶>[%!OO(lCFRK17}KmmVA"f+_)]cnhMȖ^^ûzX}|gW7H<|f0z9?Sc<ϑgEj*>Cvs`jc7N37~:8`dF߄(-%~0,FݕX+qhAT!y"^Ó_M\H7="RBVEb_Lx?Cx<?r؂bJ3Fj |x*j{l#O+@ڡpJM+RhЋ1zZĜ>M\s[S#68}fTh[^BVwVLKW[X+Rf>7HH	|LP$?|>[̎z.p/Vo>	\G[)x=/\d$ Wu.ZhPÓ2i7LWb8Mݐ2xZ'mYf7Iq3+:^Zj>k[:ޜ%ɪ5F8YfGGnz$|`W;0BkUP /V劎\m9URs
$g%۹1#-/Aێ7I|с}܀tIs u^tmᒒ:Iz0LEӎ` h=b48<mڽԏ=ӛ,r~.ÁduQehqmIxfG
MNLU,>9jq;|*I  HøN&Rd%啘|;_O,:k&yzyUrEj2:+{\e2zd5(]fM( ӫAfPC;X.*ni_2xT)V4f5`UG
C(z
j*pT/cH:y*k`MT+zl9>)ӟ
ҟӟiZ6?n͉Ks0Oеt,3g?7Ďx<<:޵~J9_P'2i%;_z|N%svx!vzBMO 8gMCz.ɫa}.<3^t̥rw \
ӽ{o{{t(	<?<Ma	y uk/
q ?^my2iƞp&h^Ϗ>݂%$7:x-S]C ">ꄍcAUޗM_.މ	>~eǎ]m߇v}_={}οfJG@ς~2>^ׇsR"| zY_qq^0y "|HjM7"j'-]8;<z7F*(Nͯkp<9BH')	DnG2Qv8O~'~ }'#uaP_'TVr:[4)?_EnP1Qx+r9+xVns-SeZhR*ϖQ<j:c3B-tGprVI׶,^DC+Ra&@Rܐ7S/&=E֭ zT6[ƭ' R%Ho\tUwkZԅ;ey45qWggC*"|oGf),/lUAf3WcXx{Qυ%.r@lŝ*BTh|޳PuPt6>a`2hFjI8
 ta,zT3?d&C }&@sP0]Xz)ȀV^K ư>)"wRv]0<I0Iy\3 kxJ= 9|	pcu:Ǉ".qQ1%b"tH])g(h#b G2oBm%ѳ#7|3iEx	,ڠWm J{Ɖ07nP Vp3h԰EAfYɄ`['%K%$TGsF7ݸ,e>z P=yh3RqF١+J/1=QBs$@~p*,׆_0Wp3#0L◴9C՗ɚur.0@+u$D)JWN\݆I``NF(ҴԛF(R4u^=%g5@(7Uc;>33;/؏.⩫;'_b\&y;6_2PrԽ ̭$vyFavD,`G/WV+Ѓ%KP]=(2r}]n>pe'?A[϶ayjYw;@v]5 A*$uNCv`)8)r`#=NUo/~bX0vh2!N;[ot$*ƾf2$W>m3=ESmoR齂ǆ|CfR/:!㒌xd8g@mVbtw*`	ZXexU>cmd=ЍLhQoP9^O\2T=Ã)))$a-e^@omq#x*}ꎒ	X~'J.'GtyBo)K)9VБ/ q-\LIӖ}+Sԭa
=ƫJ#d$t增6:qo-
*#SX_H=qfz\%vf?nJzkԗ
-Vd _'A-"xax]rā]
DBCmb`

aσIT38-YǙq0gf=X;V }-3៤u2c5)5Cwt}z]C3JkHm]nfgAx+}jH֓sD}F氈a"w%&Yeʮ`LzI Y#@"yHߎ@2"R\P1;>.E0Y+'*~8jt=٤@~ZӪI['¹+Mbb"ơcU$Pg\
.#MTvSe}?%Sb  3IਕR\+J,$Sk*mFjk
ұHهʚlX;=vĞt)7
 Iq1:>?5M~ߧ@ȿg/17BLQ^a`@ԿP?gg+_}E*_걿ڲ,Ys?<ó?<À?ҽH!{'1`3^}H8φVVKZx^daȋD^hի0/yO8ș9L,VwFBfO1$5dTTjo|].).9cއ.aHEZxQ!xqC--H)y'5kR%,YXJ.
PU+\uzE@Z`%P4Y1%^Zfy FRG?6tlL=$"$Ma1gF+wO&\}`Ů*6DQ~(],C6n\ֈakh_+x[^v2Y.8Xաxya??pOHԩN-E_wGyܭ1q?!r	s:.!)\TIL3t]-sL9ɲ<YVMFں#gݞݵosgk-1q_O^:y'GgQDyA7!7xyt~rqw'ggo^cx2uU(H}##I/dvvByTڐa7	Oե7]KM9Z-4qGE87P#GWeǹww-v|NeYZ&8*΍M	<> _<cic&lEMjq	n;E1	N/-_ξ/t9A8ߚSŏG/qri<-ۼN]c-yE,YRV /X iDU23M{ݶhA*Q$1$j黙/cLB;2GgWC"XI]FϠg`Sd({A+a=A?CŮഓx<1E$^L8[Pńo	vxJb~-`n:-/]YKzT<RBYrd?Fy;FW^Tfɜ0#PVkg?j@wXJ`!>ǋAë],p/h:\E|XFciEgWܶ&
=BQ=I}},v>?LCd$|DI.WwDP_C¬b)i#g#2w,%%9fӮ-R[@qk;Hgx=JZ_ׄ%`I&K7dHpU^8̀W%zg518{;L[`Z19w׸߿ ELDX0C)\v
6`r;L7Lb$-b1+U;Ĩ@bVz&EXU#aP8m.d1\on'#U1~(L~ZYO4tC	k]+]ab]my2٠gv5*4dqos8F~\\`M]1]q{$	;rA훠kskx>[@GlHog{6X_`R4hxJ:\P;]k.q=ٜwg&urx.;g7^2ޑ]VxQe0!08Lf?]4>t6/.4Zo>|.W<+"hˋ@qE)=vmT 1
U}gNJDa1Zٹ|~sDgjҐ®j*>50hCej/WD(N厪dm<ɧZjQBz]LC3*Zjne^^hor=s܄+Z:0	&~@s,
Y**1<OGO#AxA\a<"+&hg<.}dILK1]T6xB?D`-LR;sZ; N!w1f[e/Rv؋?,:VWhg/nQPJ( %^ggKi)6ro`Ŏf;J4odmKN$~W`T{[Z^fGyo|>7^:
m  k	 BUB0OrqP~vQ^"yGEx	T.=6w7SP!`zZ1MAmzNA#r~XmD6
/=SDt*Fd_i*eTsn3_R#mUkm!7	ft9%/DŤ	SEDss/oOv&wR	b{{_bYmIw>gtU\؊~O|=l);$]gc`!ߨ_|vVv<Y}6=yw80U#U}r;RyK,w
EP"eQ_68kºc3'	\ͬj~oLaXD5(A}Ahf	͏Iph₢[أ%nXF9VY堏DRS}s NlqB؇W\0ڑ!7"u[O_CC^I>ԥ;ч{=H@/|΁ɱvL]ρYN4UȰm&.X`B2A%i ~(OG*93]bhZkEfvţ;'-5YBL<X?ٓSaѿ7.EQA,;k/THL^E4l WrP%KU/aӹyBġɚpl"L(7T,o{VQYh\&jw OF2$	-@xҘLBUxNB3?BItZ1,G'WGhf*ģx&Z0=6OvV%9ې	-Si$(s?)v,m,bJ#5?
o!i@B*نj(ōw}tӸq
7XdG}rqׯN^VyUY=Mpxl)'n::NA#\DC8Qg.W{JD#jv',ZPJthgQهGe5?y0_[uRGǏτshCz.9Ν&'MtcLD|4c5#y@.}T/n$ރ꧐TOS1l'du&XW&ÊTh-M@)o]s.x!^S]'Fsi0e9>elI5{;9&ϧ3	%d?e^	;5cA3Klm>"csV"i%wb!#Iq\F֌m#t[2"i~xymSD[YE`Kwb(IRB_@ya m[ w-UFjB!y* S2jۅv6P`en?t֩ʳgĢʦYE8Ecot"Ѻjд8W[L![A(1( dC=Aw{y޼=?}uѳ'-O߮2;Zݐ;-{pϋt:`X_:qU|D%P.	~_shHB.	f.cy<G]jRfA_Xyt>`WsMUHwޝ<xy۷}k_W&e1`wfѷTIV%m^'ųs?.@Ojsej31ߨ=nwi!8t
鵻H	g=HM%hdV(1.o6S3к5?gp_0D;Z9%Ϫ瓨cT2f{5+,u{C5{\@J2 ƺXXS6ng ϮdV-(_~I/2>-?K:o_~~xqzŻsius9[7wtgoں7AD]XT-nlШrT"7ŌO]l菴oUdM-;)p潅(6lFKܲBpnyE@x4*^7-+ox)yf`j<O"ۼo|Sʳ4"jeM-Y-x_:'; 
@^[k/o&ofE`U9hP+B5fvEئu;| &d{Cz
]thA". f|EL-i\+
Z-17Ë2ym3~X *TJJZ,Wx!lqLP#Vb(,P8IG[>26N
yAހv\q%F da̛4d;gx>E얈:"Y	{%2eO3v$
ݱ0
cL9F/oz/Uu"HD"+}ٚ]/OV4J/@IA\	/FA
C	a6qa6IɄ"!٦@+%Zwt'so'!VhnQ gI5#$v'~?XŸZ' 6N(|=B!lb!Tǫis̈́_PiE@,Y"BFͧ)T/x<x;p؋82:/"͎OiXEMoډ	$%!P!̶̆LelլᦰkJ1oZ6N*5iF:J
h)6 Xh9Dy{:x8	S$w
[BkP*[kvN_͹3+=foؒpfd 	T/Dj8Mm$`osmY(N+\Vao>;*Co r>)LQ<=_g	Ln8yHoolGfCT~(nLxUk*	.$K:DAQ<,ʾPYAFq$䩺;XS, tm&@xٟj6k~Iںr,,lU`@yIcϔ{it1Ss̈/pgA
Fbi%(#Jѷ4B 9CR}r:䇤 ݅'Pi%WpL"De)؍o;Wf)9_10Zzn 7q'{(z gϸ8؁D ٖHX|}'8|$gU2a%S\Vk3WtC`Br%~(ev{PIt7R0RㄚJ^ګDU6ǍU,yDWDNQ4ژ6;"ȢYl#-4"_f(e`},5V#qfA<&ȹdn[oSdFCU@
ҙRJ(yжY Xf#X;"[_5#OGYPٌ55^?Ͼ[no(7儲
F[kpm\@Ѱ1O/1rpcĠBNcwkJ_*kW)8b|-wC}K	3Kk'.mgepKS4]EQlX/"ʀ5agt[q<x䥏707m`MuE^l g6]>4>rH'QmkL+PVϏ* GGa`]~ׄ*昊OmQA
"z~h#h(\*ㅖВ@ys&cl
"+ЙN_{قW:d枴KMWcB(ʘ@@aVWgQ)`O52Nߝ_{@/O0 4%xTQT.KJX;3}~hDSL!!_oo茁屻(?#M<O#f:~"tءY#ƅ<hT? PKHِZ]֓jkЁa/?xAf.WŰ(=T?4yo.p1
rwܺLтTYy=:U%x6t!|{j*>eȶŃB=k xWBהXR^m݆>~RH4ݩr~H5ܷ/OA(eR
ᒱplshH$̘>-*ڧJf.]ݒyAZTW.U^!"	C_ҳ$.Dv	/xzKkQ{V('S&u&oHYA8&A }z3rxYfxd]A{C
eܺR3rsL},%xm}^{dJ?[[ E*5-8ANǓx:D~CV'Yԁ,Q`E4h_J+
fU0N[ -bv]Q9CALgt;3)O"qIt՝]_	*t
ٳ\ $inhAP_٭Ej	M3(`Ri.ۋy}Åo Tk*#`_,Fd5кu7ВY Ώ/uxaĄe?m_T4-G*o2
`2F-zLY3}h hiy/bԑʫlUc$ɻ^??'1_W)#hgѻN<~{OG/,afk1ᆨ@gJ}:{h}?U]8GoS'nz=|ݿ0T;xaIlh;ӀGKrlu)$dǔctk6[>@k0}}>lay>՟e|=?I748d{GωWʀw8Y47O	77[;JHZ;uzY'nUj*5OꃀEѦ53[\o:|49H7No90P]3po_PVOks:|7	HoXּa~~)ΞtHpMKnpu+̌vA)%vkXпxhǛuM~ޮD7Aalz=$7SrΘ#rQR34p`?ų{7#]{fW
=snNA &C{{9ve&L4r?ϐ#<	_CPzOc!J/Ymwhe2#2~.~k|_5}D>ac1Hvq鋿Em ,L`##Q tWUf>#sˏ2wbZ{-=fVTuCu5rA+t͐q̬eN'3@1`c`3y=9CDڹWOWOAp_z?ޝk ]'z6c\~+Z`c+Sy"):b#Tbv@=.|
dEixJ^=8+l8^uo 	}txXcqP+E,^_;3	 1]e~(B#W+_@$dI!JGQװTh߂wc˹FPـCĆxؘ5ٜo#: 	zX=*d<]Vz%./o.Reow8ꨀ?F+2AW?RǇuuWx0fTQM4pdXw'u8oJ%/d[&0Yk񳡀>'BBqzv."\;^2Y<x܀UN/gEιltKk6kjѬrYnzz|`UURTϯ\g^Q+U5
Ejj*kzYi_0TTKPu~P+u^o joVmj++7Z^ߨT*JUjV4k͒WAR
6\A_+e
-WW_z^^s0b@QEVC}}FS+X\˕`V+*@mV%^!٫:k6zԬX::Z.:`р1TWBYi-^	ek0+~Rf0R<YZV~FQypT h0jɫ֫ Z8`X]*`P @J VU(V`eZi <`JVt"8ōA&	
! ʕzYYmU[Zt 
G\fjU8iū`JXp %:_B:VC"m8 R  .J0:IU٦/(['҅Jȇ5X5 ~7< 
>̅#o2ZnVaX~Qj+ Xi°+0o ЊX&za*2> Du# a%$
"9UaDu$RPj`fZ6k%lT5kR/[@fPH5D܃ZDZa@6z״畁`5Xެa"mJUX'N`1ZHڀagU&V&%#ʰ>&yX0@\ЛW ͖JaԀ=AK0s؋*HxTX& B} Z-H}*#hTgu$\QP%XP0!L0!>0S2XgMt$&4Vxq*JBY$XR\K<|& 	U&	<-J65ԡuH,tVp׫ĝ M\H@C5_N`$ҁb  
   n Ձ]& 	Hǥ
t[)D ,{8l0Pa.a[8:ܬ7:0HuMXHlR~.>J:d @Bs`h4@*uFf
 	/`N%`t07`T}+|`v#49k%Lwp`ʀ; a#߅v(Lw
L
^F$} <0Ʉ5K\g	}@:P $bs
*+"	!]5 ȩ4(80p4N0cd` }X `H>hD#J2pX>[	y
zGi4
]}bp@N4 $<N4V8jf*&Ԇk

UZP9 9
)0L3h@"5Y	
${R.,cX6 hDQPăHpj(V!G5R!VA +GZjDH -o TD ALQ`^hwu)$j!GDFci"b%D4
sj+ȽK&
r	Tj.PD~*B	4TŠKW	ګZ5^4iӌ2QyH#EhCtn;R,<%M%4,6~[n$2PØ ݸײv1nB'?Gl#a~}$q͕~|7u%]ĶvAifmmhpf4ZF+kwy4J	lC7e:Kz!x lw\ ϱpy7h|-|m^
FXr8k	r&]CJr?kәEa	pE?0Aڡ
 pc7x dnGڶgfz/{x8~%gx(k""@5>>}9NxxW<q(nc=}N݃MkOlȿkb>FCVZ^b$]+,2O&V-*_t*sj"-T[,Lrɷ-Ϧ~B$RFVuI'{{fBDLvcnoYf?|r՞IV*œrh0<O4J~gHU%<5x>Fva{
}*v'w^iea\ X(z?("o}aTu0a<.(]A-/* qD-xn>V0 nN㈸h חaz'?C>ӹPJe4;Wn*]bu[/^rvЊ(Gwl`>EK)U!R9etE=|{۟ƃ¤$?_ʖ<hdy,%:aܴXjy,YUfZ5qL:xkFOW*J5)dbf@1aZ7/hϤ@GC큃CR
q#	r/##<L
5!qQ-1G}dvњ@xRkqEJj~)oT 6p5zA%,|'KNcҪ5FP5=z(j@dʒhB.Sr=-4hAS"a~MI5a`RDs
{Q6WtGxJfmw7,M;㖇Y^KYO[e'd"/.7 9w'$L^wiF7_t iS٭Q~]nRy,9}*g$6abl'ߢ>Cu\S@d틩xA`).IIA$eH[ZrJAW|AɪJʽCM?modGmfotv#q6sm`&
0.9t-6Γ!N.k-ٍ&R2M@j7v;GE$Ua$tm Njg$+qBC/\ڕ,
K6Y2 oamN[y2'>3D^<Wq8}B*vr7BҋB)\GN0X.2_9kb&wRJ~6b6E6Qr8h@f{e_xxx4TAwO)H;}tJ \oog愊=1|]o0Smw'0j<H۬0JBBGq}gFPsQ@L ⑍Ҳ $ab
!D_VWq5C?~@^5*$O1n:AQ;@'#\-VŇL]}hr,y.w+1ˤ]
wfv}nڐ|>&Cԝd
u"W;CY%%lLbq!&m[`k"w9c<vvd
.ȆacWɒ˭٧LTM6 t[0ָ?d+#a;k]ϙ.۶`xԤґ`#&/V)Nqt`cSlZBC NġRDNKKd,P}OHn#6d_ba cƦShBw k4B@>ٗsnNF
Tvg6(YSKw\R91gP&!Eڈ^ \gňo(/!+yd$n 5*0[^>:,n\!90],'AMyxvdzU+-JsDqtC
% qWU:6o1/ȹvY_ۛJLne@guTuΫx?"b?Bf07th?gB Mt(@ms0bn2Z't @㣗/N_\pr]c:BF\<>y}.h@Pj1 z'[tQDf+
+p1l}Bk̒`fG[]	%ع&ԣBwN%B^.7WDa0f@gP`e*]%ͥ?\gc Ґs}]t4)pYĒ0FJ-3`?7_4se2`$}ʰpIU/%e"Đ"2ա5ZY2&Ǟn\eqc·VV7S))I5N}}`;nYD)Y8?9!X/[]m6%U/
VЪ	<έm<	8IA0{-Rhqjv{z= =ƗB÷w|gA*fҭ):9
/	2QAEr.Ύ`O Zi0--B:&xd3S
4eP&-<|7x^&5Na+m@7X؟E`>=9g|1 =E-")/#oԢ{~ϳKD%ҹ2򮄶	rQQ'%a;OLO}mX0ȟ9e^j*N#>BPfC'zzQr9IV]e\ڄ<rFGo /i0s<ubN	&xVFxɥ8n!ۜQ>8RWЙCOnS[GR VI$K4x .m}35x4lm9UG$-q0?iU2ӔG`!NˣqJ˫%ΆYJk2y.K,ZUJA*3foi=}[\asm+(A{~t~t[QDNVaOG	{qݯ;2Sey4cW7nr]#Yq;0ꖄo?_5تh[ɷiu{h;OhYM~LdsH+7{Py<s@|8i?1/{r+ec.IWA;m$s&i5o6qcL`y \Zq3$Z2
a?zE;  q[;3^GnRWN#>]0Y("gQ*Zߋ*+Kf*,Q{$>C~@DOu7[9~4J:xgdgT~wv܁R*:GfVPFJ{t*e0RtviC;i.[<l|6eHD2m_ [Ha!Js~~~<R>6hl8@>RX<$#
$l?#4pk՚K׆pҞhܝaWNF?J
}N?[^{^ Q=X,n=.$eժ߬9;57pp#+]8+Z+%]|&APV˵3(a
x8|A=~WUI|+݃#w|/:"&֘L2Ga@ox%U_իxFĮ:H^ˬYhh,^h.x=h 
Xvlxk#;ȏXw]jcҍuDY&XHFY+ۇ\En#0E"pn K`TNkWu[~G0Z`G21j9QIDn+y%ґ1e/RvX0l98?Phݖ,ОI0bw "p;"pˋʆf]1V\gÄmW+BmIv@CИ#&j'%UaFX801r!?`mQm76~${(:VT#imGȚ>,AjHCXڍSiĎn}m;oapTꐗIJrE@Xw-{7mV8) j5Ov;^k8!2RvQ灎Kk"=ZWQ(5FM( jBV1J]d FB.ɉ/Tށԋ07[\"m77[}7,󍶱kp&[A_﯇CFF-{k3g uJ:zGXEdˤ
Fm+i,nCNu6dU\r-өZ5OFzYo|iGآGbÇF=r zu_c#'ՄtqkZѰ2sjH3z#7tyWf5NanWvlV+hbpl蓷[rxbR#BХn
-͸ueF
KJv51w)c:z310g9jt:\:mcr+\N}})߁Phg~e(3ﻣYͺ^𲯴+;y/bp>!@+F$?oryǫ4~m97N-{1T,SV̭W1FG8ݺmG~o+nɢWq+nYrK%Ѧ;򢠴MW	cgjʾ#S'#8Z8*
Z0"
54:ؑn tY j;N.?!.FQrܜzd6|3:\i+u6/;,c8_z%<:U,!9zZG&󬢕TQ~8	]xdL׾27*['KF4D7C M¯h$-V

|%5DaSX)3i͖q񕸜n1,T*+KavM߄9o ކPk6"r̹u?Ry:OE4m쇈cZK؊}lwy<$K^KWU\OUEKb!0jK#Q0}򱕾i4B+	^fvY3lF~dIr&i(t!T|w&0sΆ#Fc2dNq&YZH8sGdNixqzxҕwmⰉg鬓wgGF
A^zx=a ?GU-WS&ySpͷT̟Rq$URp򬲚Q̆P.
@H&;S΅sr{VM5,anesg6Jdc;138i:Ʋtt>r,x0XYl`W*bMp3njdFcLZ*)XUnu
gC5fnZ~o]e0c^U;GΌ-l+;?ƣx{ǫ'F8<:0`7YKĖ9ġd$!0zCkT7чfSlaV ?>ٷQ6+z͹>A̻<::%\k<@1nUm
i7&&Vyen4mPPS.Y2WK/v	a4(  N<pI`rw`$s\Q2^e6.a3!RO|$* sǫlǉghodc9dQZ,K'/gLZF)jn[:og#%jjL^!Mg 5JGA~=MK`@}lg"crn`̋0SdRIҤm	29il@瑡"?"QFE1]*}pqco;t	Pt=wTV>FcE	s@FCpܬ"suTY5PYҫ\iyC;YU`[jzkx 3
B&" Fr_)mً`	fm@&~kB	A
eLHL[mQ g/zf,i!rڗӁa`ڸEoBӧiq@fe,hA1
qf,zoCҖ
2@5	Ev#]`37&\mQ(V)GΤv[-K+ZE+$*;~̻3\RI"Ɨap8aȰX~AqyMlz>˹pz"ºc<A82fh1	HL-Ʋ,V>{Xu,eAaABAz9VAaUXnrU`Eힼ=˳8</C|{"9>O$cxkp>%QxMK:;<v'E`+i2rчhںa<BFk\my5|Uh>WK% +n2XS&ac
Gp =LɃ$%b!r@[<C_j?5ؕ]?b~
Jbe{x% Hc}T<$ICTK/NfϢWVy1w^^4D>T{dVQڄϮ?1yĭ֔7OXF"oPx"FҍᇀBQ{(f_l5)>5 JŌ5A'bCH 8+|luN2%O,h׮<#jxø9).'qRc4F庭K?N0{uXCq$!\lzniLϊGNPurŹyf^ >C CZEcpBja/z)#)X4{߁4aȸ6ot$ R"U@h(\k_-\K+N3Mpa9laPLBTLf9Vs,}XrkfBz-ujŽ1<NDfKU`*=
9f} K|h(-Ix9Lu9mPS! ))^0^>=\x6,'E%ztZzj1 T6je9SfnL9;wr
ȹ<S8a&|2niBk"oLNj7ADd\W!5!AhJdF]]H,-@i%%II=6􌬮*Ecjz4t =iD ꈢ'#H'
A'_rt?ӊ~r&ïQM<KV2D{\}S=wkp
BwaŝyRj[#/
+E ]vx1+(G3pA^Kݵ
NK_ʵĤ4Pw;yﶔ5oJkPq'yQI"ץTAdtG<c^qC}DN<H؍^5PlL<lY坜~/Wd2'`6C 6񌐗Gysb \{e( ;4{IxV<1HjxZJbr%Qg0ک#?*<@rxw~اR4	o{,?p=2%6-P!l?4_HoF(2l=zV4 e5`~z<.G.E%2^KhR.eKh(?~;q!+п26eL5*mP	4PGz`Dt1?OZ.bE$~p(ʝ=4r/AR F*aECf=4<И K*58.0c$23D=4ұd=4Q@K+2cGV(ut(kXOy:)t!;OI%zcaq08rkTư=Q1ԣ|t_j\0v}ćDptKkTFSN}{~x{P)g>?}K[fvQg/ت OZ5;0ݻoZ(ݛwfRb{-Aߏ߼zkj[hڢf&B=yqNxq䝨/^x/w/OĠ	E* >z?OyN޿_J?o5bǒ3(&"TPC	Ki;f7r;fnsNmjl<aP~UK`0	w'=j
	Ӷ0"&'jjQq[nY	au'<tNe,PcQ/Y˧^E
 (LkszkO(7
d$J烁]0*꟪8i@V`VA'ϋhz\IdX?`c%BT-WʣK̈́@dA$݉w"4QUPpa=T^x!uJ
0@(6ct;X")G|A?dO]/"QխT4y k,tQ<Pqق7Dr UPwpt/<p&x>>Q^!TC%Cl*|~i"(9>8 4}(~GQ>AS(!ͱȈο!tMz(0mu9<w	[byQ@^0qy(!w?v{W=0CW(hθedxa
$H	'P Pq#w'Ħ>|Dhj&;_d|A(	cdr-c `HĲ"}o~`-NyB-#ZVk@ \Ⱥbtwb<8b	w22ihz]'%Xbs2͂Gr'YKONIFfuq0A(rpK!97MXD^*F:mm%]&9mo+Ҝgmk҅8E5F.iʤDu "O>cvql>C HT=m2&G:ed[!<~go-=dɆ3~3GO81YVA1p .+)ژAb%+ pL&nFBk!M?kБ!B`'j~,5QZ(`0КgcͅH\}wf{F,~ϯ yqXvls	iXK <ďnC'v&@O]tns̳~9k2[*JR$J媔xEbKLp!=A鞯^.ShS'L4Fh'阉cF#kgIWʤ!%P/je\Sh'iұ:'^d@잦V*ol}?ŔU),6
-NО[-,vSvv5@P}ҥ6Fq;G4L"S?M:U֡Ԥ6 JZS@mԦ%A<EwCwD[10qt2;;-&{ex\mK߽q+E#SJY\>|Y.Eod%rPdùdRb<	y{pAWedNioe5uhm JkvmJ$ݯNWGyB%uQq4pmB9lYXIJG~'w,O=$7Zh~ݤ#+$/fddNW/6/wIU-2R`MO=V'^cnTbwk9Pv~A$2eeJFRmQV`3d5zdJ*#~cگ= 9 :"RTuNJITЈV7J:$t	a?'CWmjΐ-[ʕ`=/4@Ǳx+=&DܱS_#=ʒsl\ݏB'.:n Sk90cfRmEp<TOt/Z#TI%קK 9aֿI)jVfTUk{Sn<'dxϯݜck`ݛK<Io;\%cڃBTkD\s(3v6qDnOK0qFXwABMD%Z]]Vuw<>-FwwwwWY7lr;?Uo҉`"橪?=j
'	vueE%S"dHl^6euʒ4AbB_iHeXc٪yrMa{<H:.MY,VA`2Dȝǳ|ȹ#pHqEğE/mvFiA%S^cy V/&uNΕR1N!-lm+疪BߧŅ&4OE޹VeJ X0SIt=YWwkQ앵7qо֖ݴRY.A:W.*C`$=]rsKSj&D	?ע`PJڐ%kqco)lȴTչ0玻YZZ*.V-[?U蛊V=ʂ,`}7T̕·3/.m?IX_b0_-]M^R.J>AJGXN-bz9k49^TuKV<F/8#2DfZ{y)0_#(+FT]Pp/ݧMK ?Jl.J yJi9p;uk! A	#uN$֜^Շ̆Wrqkfo}raʖv_яkFnfzX[%ߗJ[)EN^<g1!eϙbA] /G[	"oZelaڰ̂O\oۀY	ﱣKD˖К1+Nǵo\HYM$5KXCI`r"/q$raĎ&!+`g><ض]d2G]о0[	I^yj\oLja$;v^m_ɮf[:ѶQ;$xMDӌ(9hytv.M2c}kΎ޲r&}̺CHM;N 7;{>n %o]̈́仵0_mycL;		`^|n( mRMy{PZG(Tǐ~GؿS,Eтvވ^\0bE7+"
у\g!;<ce%x_!&aPaFAʼTD_b%ea   V'6rZ;ځduD)nP\^E~{RĂXVʢ.A$g03iɀjm
[LNJmT][ i"aHV#O%|Qpiu0ʊD%v5a0;jȔ^4SӞOKARLґ=xxo8ƆHƽ?CV<}h@Sh ٫O:5Y"+b$.@H|cŕ7XBum.}	h2"Au,K^Xr.}	MqU[|VqT8}qE[}=
)/<q@+'^ue2%y)F5uXTWl4*oO{bseVmI`|:4a*ӡ?0\/N乓̃+\R^$ԕwW@ltI<fBܑAۨ|owy0Ӿ竅Jf$XU f,х}j*C.,x[`%4ylιquAWq*I3gJ17nVt.p&O51^Iݔ m=N5?@yCQkѥ[J\@ ظˠU8@JK$A׈
K=~M T<t^j,x7⬛Q4ʷTEц6*a<߮o#Uo5jon9`	΋^	땕y1#E'?g]΅,Wz~}|Zo P`JyFE]q^cynik4~*	>j}[Z4:nHvK9LǬZgTDpie#Wg㴂鏁ed\Vs4Tc@T+r$9	WJۆBH:Oq,0)x8dՖsP{3HQi~j'AikQ1 VqIq&  @~4^/-Xrժ:;T=53k0tw?ЈO@L=׷<̟Pq8\vО;Pw5*a)$P/\]]aẰLB;]]9|<S]{X#$2F|ґb
#ԆCW8ЗR\yBLx~ۉϽƱWUlbqm'Q`ޠҨ.,NZe@!<R9odr%Z,c]sV r;a-n7L|-aݻ1a-]x
'!.z0tR#Tt+% Ұ S%IQG
3gwey.
]ǚ76WU!$$ne*R(]P0rgp 
CBtm!Bal﫲+N&@Y܊83hIlPB-R!&P\:7u6;dap;9EudlYo|WpA51/&kfֽ	n#jy1[xB?4Ẑ-M)t*aU *{İtd+*}Li	.bn}HVVo=BJxxQ	`VN.w\(
j_ R zDRk;Zi P{7*i<6/:W>u&3v(UU-'|n~K3g7)m)*#,.+!B*\U"fz5[c\Gk'?۹tfsbBb)De΀W`hb%b@EF?%c1aN|3>sH^kd!%ܒtK..-ӆ	uTUoDZ#cd/نHnulj6dKBo\|à99>b[R҅Ъ.:e)v.g0_~WY~D x%0Ί"|5̙ߑ3Lðv7ܝQ,%½B1+MwC~_lA7&{~˕:Ps9R<030uʟ 8lkz>RVĸc0LEj`(I꛹pua'?3Qw񩎔.?SRmwh?켝F~lH{`T*>՘j$Qfcu2BpWƿ% /GbC}M>UPTGkisW겮"q_MMo[%k
/6z*$2c}7%ţgZ< @7%]$L\O1;-DNR<m?j=~_OFf/tunk/<5i[3;(³Miڇ櫸X-fY[ĞBwfev5I%r ]-/I,YxtͩTrsI͛%2Moq9wERՐwWr22k7-+i*%`Ģv$5Z܄M{\ho"ᴥu煲nqx0U@S=:XMZ$w,BazJ#0&O-ĞeW~PW)x>wrv3T%hsX%&E5>δampp{\Tk]syOSjTVCeV]Ad~+4pserܗTJ]	30K^Ӌ[:ԯPyLD^Q'?6
TR|(ROYh҄\)hvgVC5-w81ǫh#OX^}^y[-+\PcTZ$m<Ǹء{X<&t/CY]HϢ̈́	^~fUS	ڇ	kz]sn	|msԑk!<)+;?6XPvwC^X~ 
[(1b%iodx%[:Dl$EAtY7?*OXME/g)綬IqH[Ov`6oHXV,⩎nYlY6 V"oT"tx7I6s<"6ּo #o~0C֬/BZQ3Y"!Kparڳ(<7'AƾH=ĩ3[c)~|]hAe?m?5$7̶aOyiדLO|j\gvdڱɣ/R@XKm7>{gjo,=GbCDWIװvfñMr='z7/}nzr<ݍ^q+V&8t?|nO=gY#~MPްd[~c+گZROVC_Vl<	|*ʍȵ%`ӵjmM
C`!Hl,xCgqUDf߄qpqpM:j9w629^S`Ao!:αo /F7.o%+aJ%ƃ^x>*A*B*n,`QoBo]wxW}PZ;xa`Y|]߃e>=PwXA1,VOjE|ź#ğAu^T'{WP]keE+ҽ*+൲Zojx6O76YnՖ:kMV[Ƌd7xlxWb75Iշ<*0]g:nB-8OI{R_i81^vO2;Q%SPJE/=P4vqGxW #1ȗt^=%Z,7B ꍀ.E0/bXy2KP͢,^\JS|e???֟7S5x}@36p$@C( f,B;	 PxX.,e,RՖ`XmaknEav3lҙ?g,џg?K9}ۋZΕAST@ST@ST@QT
h
h
hyJj ~a|Vb߳IG\X>I	Y,Mu7[-JOŭfXm[<mk6ޕJt~(;>Ty&7z
,NK`
*԰*n6Z}O5l1A6 VV C)ʪ_g3>~vwW}|;hT$VFfffXށ$=>plqDmz617~18((GWq?o*0$A/nKa"D;l좷{v"hmv=wN`0[m~ӭ͚|~u{ҎNՄdo 	
Dt?v@/qqr	+e뢷_l?*:=1V?I~Iß!
 k C<ۯc(,($L٤"Ѳ$!ڛw+2 o{BƦ|81D~6K|;;P9	R[?	'f3K*vl^Z5]Z9}5pދ	gB띵 p5Lͬg2j_ggl:[ADL=U<2J,@J<H.{GEt1jfKBF46KIBuߣ1:ΪGϺxwgНvu>k@yu@zO<@kQ`LyaPQ2,e!|-G~傝:whEڻW+tKݪsCCњ7lLnq2Xڃ=h@겅,g;ݹP Z0BG2_MJfUU;9PNwd82`.Nj-~ՀPo8=eħԞuffN`Ɖ|<VO7:4E?"M#zC+ #LXtWya @[`\3B.dbp+p<[h8}gvu09X7^p(F`[IC!1YA6ln66HqTFlnayjn+LX5Jzx)gn̰Z\<}K~wmgY=Pm<^o>g۲rjn=RB39otqAl$C?[GW|3D:0V[hCyH_&>@xK/&2hڡz?2x׍lѕשҥת<]km5ABx؃reee7@9`H7k	,~w>hM"0o޶X_~ Ģ-q}T=CXaN6}M N؁ɨ*3m$6H7XH
EW^Qanlz!#ri=-9=9URn8^Nu[v8us/	@5c!گf4jÁ]?Q#xJЅ"*)T'ZQ ^[?{Tu8I9>^hU&brvqv>dJL|"X+h廩آ^0l.~mrU]C'(l :פ."N&c^) 
	gTO1$Ηub5$c5T|P?HZo4Jciý\%Ne/U|kIH$pX蕚5hj_֊/XX&(5tyʢ)gjg-JCύ.;`Si &\fGUQ*5d%-CMNrWY[)M3<Twf&_5{ʂfVT7빚-AoiZ{0,w8H[R*
-ǫ1L_f8(Au~Ra=h:2TDx,uسVy%8Z"6SEa'|jb,je5pv/d^֬#ߞl>îP2}]#k1҃s(iƻ}Q]y2xz𓝊jKi^|~'_y0sV5/5fJYoO6\3钬mǠbV1|a@E1Ty֖N9Z!a\L߂0uʂ iciI\+^Ă}+3E!&Bb)N;{}@?,T/^kq*xѡ\GwRNJ^^2_kJ6]{!QVbx#8`CfWz-<S~F {,8G~/z]zT((6b{#;LpjeM>mozNF9QDʯ %90_|JNVIEǁ:ELJx՝7Yzi2ۇ4JY#+3njVjV9@9$Ec^bcq1tz`SM	ZMۻƈJ8olk2N;:83zzP!0D	^zbiu#3+*,lox*v<D )PR<Gx'.UG<l/Bo_Л꿪&-&"[l<l>#*?:!Myxn<Xم~Sz3y=wfuC:Yv~i $}$; sbΡʾȜ!hYФ15Z`RzͦkvU^Z5Pf/r{qclvzb=:DxOST[6:b"Ei2^6">p>晑j鮀Lh6;;ii`%eyN7=$:	o7M{itmɸ'ăLa;W<

qZI.ݨnC_"df8H&3_(&m'{;D]xw2ar!Wx%%)ް{ُq2Go8[{@"dIѸ xZ ώб/^L6_3񀝋=oӿ4?ƃ2rqB8S-ʝ1i؏TƓeة~܁.~9Z}
	E
(Vqt}Nr1,ߐDbX࢜Un7lC8n[-h(
 )΀*},иqr2nw"lp0ihk$Hiw&Ǘ!%\0LH佔b){prܽ@e<O[Xt)6mvb.Ҹod	jxkFZ7*1>js6//F{Ǔv: &,;vx,F.d}MWx!#YXAܚA(Ր1QR$or$~Hς8 ӆɔZ'Ë(e/d
8_`P^)1E=.wܓT>Iʉ|`<Y9tCΈ6E>Do19ptB	籉N"zD{8CT[ף6t,Dd/_R"Y6PFBXϓXUy~4*V#	|Vϐ尞V'b#Q{tȢ]sz{dLTsSM\RN`fKoJ[F
*
+HjAen.i#0AeI^(ݫHzHfdVI; HQsfJ3
Ea1AM䖶Эeg{< CȻE;ʵ1E^r!x Y3L(6~A#W=%H 
w+e{)j+?@NIj&XD҇*kuVτ}ޝzej~*6S&yMcG6*[͞;7y^dy'SIk[ju++>q^L
jz[&QmSʨ$bhnS+9n`+c=x+%Ryx̴8'GG5hYdKLm)?XJGn1AQCj"	5mP 3;(K%Mb\ƘB/<,4[ssgȩ<p+.o1:+ֳ?NН3.3=ʀᤁU?4csP8Kҩ=l-iU̩1j0a+ic>VÖLolfi 9M A=c,"ύ=Xd,	,|T<rn]2rm<-?s$z93O/T]e}&!mڪrV2Z<cv3R?&?oS6zj5?d˛f9+1BV^i,f};2˞{ZCǖ[Jގ<y\ܾut%Glߎea׋]H[%]o 3yypyġ &+T69SlZ *tNNVJwZDxjWQDUg@A=F.5{8Lr,?v1F+9֯o4'x[iDt.eϟrNVL
!A%Aoy*"뀛TzUѫDf@T/fJb%FN8:hO&ckt:IS  ?|O @x3F}FvU f8Dl!%A$J(R2e83c&:BYeJ
:zh>Eҧ`U.X]L_5O4ZD{ރtGcny.xC23G3ȥ;؟`wȳqWѨ[jjnxWUMChpy}v+F\	qrC;4ZP'͹eǗX5<'J-TJ/}Ԥ)M(;lfy;YQD0E,*GO(YFb1]:nFhdw-<ŏdHt1ЄEDEq?&6Ѩ0~.e'H"_Ʌ:PЪƪA}H{fеv{,lg]HWAr&zڤ;/8&S9~a4"6_H`dL6VI'm]r yza^7 6$jvm#'K櫘DVPߣr [PݡzہM.8YJkOpgzNE۩f?R"+)6_ijwx5L͎SCN.40	"{2,(C7"Α1fdA_r٭@{<,fFܜ%15n1~&hno/lE<9n_n/ch`rX:8Onq%{peAop;?O$|q{{먵}+>)%ed5<ϟg?D}[nZbQPmmk$'@֏?V;eϓ#U-s{}xY~ {U3?ϽͭnSǵ؎$Fy	2xLx#OաϬ#5I`(R>+=r.1]/0]G
JVS.YNZj]w&2m9HݭD2LoQ^zF!NNun}Fa=$R51Z2"5ye)i,&(m^ksd/st;7-cڴ5Zi:r*)ʬjK@͎FVZdv"J"~mJ	cJP17ŬŶeUO<S9͔c\?xa#D:Ґww4^J%l,K16voFm0͝N>wwc ̨I!C=s~9'Mo`893WCYJ}'p7oɣcHGƂScXڃ gֿ%*6֓RĊGH#YH	OJMosA ̈́Qo8fnO˳N?x)gȺbrV]Јx4kөf}j6p_x``ݑ7㝙LLTTl( zrص.`ӘL|!'f>d[>A"^Fvj8wل{&OW$wp$TU*M+4@=X $)͊om[	n!wx`&?chSt3NNV<l:IAwft뎼-<b* &
 nVOe
<4ݬpƘuEy\d&B0E
7r~OEQhKrci˴_WRv3żn0啠RggCWĥj=88Ɯ˿үhl#ݶ>{V`TvPx?o%e"e͸p&rK2-RnVrv"otY?v˥4O8d?]4i4Q20NA3$KA2a
"@\ՆJ(dZLõEs,$-m;k	1>pٟ9uԑF"4ϕ@bRt4>Έ2؞jώ|EdN
fWV]OT8R43?AedL#Xv)޴*vFߩsglOtj$N?UiZOBOA>Ih>:@h16[`J}KDSjT_c>`WQ%3r-n(A3?p7z~x̔AH@̱evmbU|r`03t$5H|w|j g,(z#EHRP^9:Ep%N6a{bHs2+	3ɧRsWۼ(js59@5I=N:{A,{pLo܎s.4Dnp{/9/ {t'qL0⢁S(#D(xh|~aTOgIFTC4}aDc`su!Є+$cl@L/F7@fII@
/J#:z
F&#K=>z6~Àcd jӄͣTiF95jCۃX) \<pDD;Dx$s2B~Q?xϗJKWJC۱DKj20Fo"6]|YirjUBEzfbFN' HlIr0bg.Chi_:R+yvgp>rE~/,ߟ*Ȧ~-ڌׅL(# MD"X'[/_zj鴗A>&PCrqS1)l)!8޹Y~>ONWb__}~{ʥfRn>Z{% ֿ
4^$c5wwMu@1n=6
s3js3)E19	jkxܣ%:8|@BRcΝ.R`3!%ܴ6Q틼;/R9?wfH_FX"ŠN~$O o't_7SRH!4u@qCbyΚp<<GI"g܂ _ 2<oAj:IN}
rhg~`$RI hW<QɁ\(6gyq%;D҅Q767zadHʂb} EPI? _Fd*<hE:м%4,iٴ|[u˾S,i06-w"bwa1-t ݰ}nR+m>0Yzh"wg`;(T?TSQ
dB-	
 
,RS,H}7u9ZI}_D舛vjW`ފ|%V`ҾR&'Lgft-Q'ão;hV*@mUF}wۊ,jK`t~W@JS[ף2m-dx9Z/B
42af=x{ _W~vH~t,}Uf۝/07d*xt;,ﳟ|Hs`qT ^b3_W%_o|,}Մ_Bչe`ZqBV kz<G'7#'qF9pssbm?W/_fL/Wn=*TSs
sxh3b-͵'E^g$9#H:2z[^7dy,C.Bܠ3<:ce֑:ܽOn[y ҡx4NR5탏iV&p&Πw(؇&Ҹ3 fXQ4Lٓגoeg_;QmBU&M]}zQ63%n% rk/uq7JhF sIIoaGO~RZ9xxA?<;Qaxo7ryP'r(x隧`S8EM~ZLsu%h}4֗gjHwERK Bd('#RCІ|PdSOI$>=Z3Ls?J0'Խʍ}d.¤=T֧fÒk xo߮ML*|JYYo|$ͭ*{{[2F	;[ݝ<PK;BʠLY@rr;+GvXEFި9UN;5$6|<(Z2t\DhmѢϭL,|dm[	^GtyJq	fվ4wn6v,cw N2WӷêGng9'5:TFJ<ә!aubKüT{
4qtjgѵEƣCN@}rN|h\P	EN#PV7?o .bXmw6/D"yh%NrK88GX6`O׸)`B`AS<2]ʌ5Uڜ6lFxD-Y]̷'!Jgz8`ƦDz:60mso]D;oa܊ÓAq 3 TDi=\C䚊gW#xIn(mK7\5iW<~||ϫ]/io_HAYO^vBߎ1AvTh;DJjK;4*NΛLp="v-pLu~zN{D2eCRX7h
ޞ;cRV0}V!S8ځ[C:=(	둨vr>^HBQخ%?0!f>㾣ZZNɇNQ2T"~{hLJ?v<2kS+gڣZJ`2P}y0Iq%Zə:pqC50`cf
Ũ,,kLD}wx_Bz`+Bd|WN#'0)J vȞwK)UAwi~]vI#Z,ܪu{w~˳W$'42E"rx'6s4sguLd"إqP2cQ2J#KsWAv!aԁ2ͿuZ*PD *ũe*g{2D'PHZx#WT5ٍae]+mŕ%$q5ƍ{1x+৆Ћ
B\@L2jWp6qGzRwwydJEArPhf}dkp>5Y쉪idF:7"RD-#Wp*㉠uT1'=q	
=XhDāRgh\9i:
r

xT!tB0f>>_:ZEV>WԽ ñrZYV<W=N!hԩRw.XwpzPƌnk2	lyUn@2a4ƲNta2%Q<#X{TE%{@(g߿OoT	`x[fd9i̜BXA"\TxW#tK*iˀ]xG8/oar2:iL[3MDM'g
I6A2ҫv!w"؝HPW >oDvz!5y1kOU=zZkoKm>ΐ'R#@ $7_1oa:ؿm_e-1^eL;qݛ(qwŏ) &@@0mlO;]gԾS̙Q3 MN;ڶ4h02SaxM&)oLǞ1V^-Jq3eeSyJ.>"Px/WqjֻMȧd)壠	`IW,Eaa}Z6l8C>/;(SV0e9gz'*ΊӺc/.,;{W (3ȉ8N:.FK(rGj2MYbJ"U^
q.M	ZlH0sSi4{]4/FF#/YXXc[0&	.3y4H '׸=RM?"$/|D`_xtKnG(QJ1*7y9/|&]Pw*9(qSQMk@FVi'A/KSTcj#LJ,Em?GyӚVM0d0Yo;LknBvY<h(T9dV'fK>ɏ#;'$g{1՟ϱ]L	TDwݰW$l\-k%Z껹iǚǏf]tO ]-S6ۜtX{	4)r"؊hpdk'RϻQ={yCӯU!R$Ŀxkf{z]gf{bj4j7bkim頰2m_~!?mF>Z"䋛	,e-˳sbC-ס(Iw㢟|5xJs[:	-[#1%,3yL_	wm&-+dbA>н<aӏzn)
=ᵂdN1$99d>[AV&,=Y_RZn \<دww2N+41Tʄ$QX@mxп(Ru@ǽrӸf
 rwŇב#mȾx&/>HJVPGAۼAG5h?sJqb}ʿY,>/`c~܏qoAGeE1{Yk]~ʡs˦G<шu4Jj=j@+eF'{`[;Ğ/p=LID{WX+XNWޢ!]lj$@G;L÷:$$݇w[@I"Qԋ04"xVRNSTM8GqmOfyQnm- Ze/~@>~|Ts|!<wl7ԋ|MUDSXpv`(Yx%2?"j8)Nhb1ҜZ<ƜTσ6oH+aFŉR'}iEC/H1S@v)>XiK|o!k)j;|GyU!G4}-+r=J
̙3g8hs$quϰyǗ1f
*Tc7O>W/8svC/jF
D r`{Tѐ59#TG	CEs3G=Rj}hϽCzt$rb ~V@^7n	Jz$~`|38E:[O(?#=t!JWӣ]"'ڲhYLQ=\K}+8U	}%)!6.?]5s$Y援4?,|s񜡧AT~*zLW`5a\P^	"\@)5EF@j1 ođ]oIUQb/j
,|KU=vf%#BBerؘj2\e+0߃mn+HeW^){ů6kG`>ml!jÌG&;6hj2(70-~Hh!?0`VְDzCK_v45S	z¢IwCNMOH:DKw)D~tlk!1LYR9I?8Vz.']EL@>81;ƍSxl1;.[IAL#KuTvmr*=o'JɾkCpj#H(Uv=7PDzk[Hz6)@JVvI9T(j][7nt@
cr(qtjX9#(K]ڃ.E C݋sy@$|Y&[?vo˨E]z<hH`&tp@4NSYS'Mz9Z<i)v[*zmz^FnS|to'Q2==t1̇4-9>C؁|@-|y~c[rFVPlE௻Rӹoʻa2O8!ԬL5f#T6U.Btx'їV1x` MʿR?_W0.VukORL&+3|A)*
ZoL`Y@i ldT1%"N 8NWw*([cާO
/NWKcdRjGUB]DLfH0Etj+c,(e.̩krsģ0Q|䦕U]?׫xHۍÝݭzA97οn"':e:~pBc©	<e]Kɸ݉-vkAe+Z~h;jc<S/R%!-8Ǡ?կaj˫	Fw+@A2nr0F_J':1M2!e݇4F#@b9ϞVN
^!.7rh0PtLҀJH serxkUÄr{:x<k+]Wꈪiz	S8t}B3f92RB˫F^p˛XIq\&L/$٧OHP.觰eD&5(}$kzڮT2_RKb`:15&fr$ ;H*8ឝƥtz+F~{y8졄:TJ e#ŤCd&5UD/E}u5>hV} 1%:˴"s

N7#d S;-8m]m"RF!Wb_{ ;l91Nmyq)`q^/˚$"a,+e?9_V`oG`vw@}tkG3RZe唅v%,~vmRPq\	td~w  1..[/O]X~uɑL)$6Ȕw(%4"jpr"Wt,]JhbT!ZIY<I|Àԧ5sWM?ROF21oBծεd 3'K]@K&ȥ=%Y qMT6,X`#>wܝl᙮:ZV-9
~̈́V^38FҕhmFJ)+d&0RM3$`~*$v|=NDՄBll; 'Q.Dµ)}GkS77M/Gf `׻Ň6
$P`-/	10%>WJTGun`˴{Z4ߊ]0I[,2Z+xc)EN.Qzr3cfj$3֏?m(ֻ0?7tyͧjҿڥқf1XxbjPO	n>3*>}WpFuuA =*֐;L7FGWǗ;MB`hV$j @K&sv@8Yb˴H~p|sOi!e2޸i>m{9>Yf6y_OC*$X<oJGu|DvM;_1N6m/v&8d6x=UUj~Jhp<h!8[")<IJ:C(f-SuplŃkɜV>Ѵؖ3L?CDnXeoܢk6ign) # j)3nbV;S?7eBP
=' ݣg F"7bC8s-.O1 g)aӸjtԨnnLSQ,6U&"P)OٺtO)EXd8`$~
Msi8ur>Y})zɘ[l}݁\2uWu{t}/i*U*ih2SbkH [YSr.T(?XyͩUp&QԪqt;$xjk1(-[ ˒ngv);yJu%ipbJKNDz)|]A^Uu)f1i9=<
Wp8
6ܝ07廵nCG6Ť=ܞܒrkSeBmP)(7@ͅUWFu:U;cTV)8~D^n5&܁ Ƙ6px/͟HXF8P94-vn#wFk;+_ͬW|,+=MNQg<]W~Oie^<aUxۃ|,_ԯk?`*SX
/{,.=.iD;IՕvܹf
A jXkcp8c2e'C`D254n=tO>m1Z43?mcz0RDMDA*=L"X!5& H+	$~xrӏYHtq|.r ({/+`Ou{p`R./dORvwth(C,l{E1S]SYvXM@' ֖~=5Wx8K0?>]W)7%PP2pP᷃(z
Lqa?<@h:)#huK۽J1<ӪxSxQTVWVű4~SLҚ۹խ|I=b?3gP{;O\:p7-ϸ;9j+}Oփ)OLLcADtL-f~'Ma"/[8JM[jjLOɸ3 ?jAfu/@q?ۍ004	2>E1`J7rk^-eB?oxw!i]eFhn?ژ֧vp;ҟ/r"Obat]ȧDz<PBg=Piݏ@`
_+yVz*FȘ4|F6;5ͱkcP:iθ6^<jg|3z{^g> TJ yQz:6t"dr۪0І#m<k
o؃VIiker!uB5߶PfgShRk|OgQkICLrN/z<\(X^q^{:88*>f	TÈP#@^A2oyC/T3lq\cuogYY+Hk]X3OPo)@BP0/Xq{31})9󦑣"-vY}L=xSoIK[ދptYKfnq)η$=ڼ]ܑTt@i7:kwn1pXŪ-~BMB2nӑT7JD_E+dx_+'e_;(Jw4;In2J}iqSNP8 o;_okK'I;ߵz`^p:aG[ZmnΓl}wl|Sxxtqc((^v`Qtqs,s|uWaJy=cMI;0oPAGfM)5v޽?y* onWe}jm~;lkw[-im/NuW	C 2B|]mIk'G{+(pPWOWYŧ-',¨8NfFm|c]bxϮیǓ+/r9,bIWgKPQǠN宰.u)]TWV9|:Jpdh88kz f~d^<p8HgNOfHJR,܋$<c<	̯Vu`\1XVCyJ?=9ZjѓdG0^EcOeA3$cTۭ'9:[GWx+cm|&DIrjJO;";
RcC`4pv vMm(8Rx¥u5!;+$g4T%"o|&W03gwctKI'OOEҷëd>NgtRǃqL<1؈ۛ}@/K<}:
У`:׻LsM8Rc2ͅf
R|U9[PʄuE9&dڤ0;|]]Έvf{Ԟn܏5#Ѻ+-#L1͇^BԿ@fN+MyZ/1@u"WJ
)Zޏ61
g3e2˜RVtև&?c\W"]ڊ!sd6ᰜJَ#Xc'V{5P]xS;ѱiMּ<%XRK246;%Rs]$5	]N:`m)&U2Fm ~I{t[K(/pYΛs:vFes'U{m+ se,}[>ko< |[pҺ:ǘFN$lpY/Uݿx{3P|$,?nin\J'ocY܀qyj;19^[RLHnUtM9Jss>n6c<-'St,v#F rP[ЍT`9bֶciܸ}i/܃{䊄ۍuKQ{$0шOτCXb}V51YT$w뙰9ڸVtu,vNr)5*yҹAM	~rSe%{{4
7ϴgʙN3;v ^+<O,$vTB,EOX<^Z1R:ltD+]Ki#dmUafp`]R>}` `.`LM-|8tK}D!RSq܋{ݺe_M	vΆ~1I:Tsˁ2똹DJ@vNn.W7K)ua_Yh.5,	e[X!jH#gs^P;vϖs3[L 1h/JG0g5aʚ"'2b@)n|,+~zE+2](UV6_WVh^:
HE~=B4֬SG kg7'1G|v¯2ƾ	i.lԥ3/_|"`07uBy"(=7dt,8&Cx S`wQb OׂcLUWjji
x8a\Sf
P
(dcxAda2*(	ܖ2pw
	;v'2Ern<79^˟bԊUŪ}ThO--]1%;wR0"'4U\AWm%gȠ]˖$y J` fXh-r*{SƑM<.Vh-	qn|}W\&(|t+b2iWŭ#f,kg>Ski;SC	,ԕDJƆBZe=*kg<phe&pfx\N1@I
ťb'@ۛ`y8Q(qsZ݁8-'qf@~OѤ4WL/ Iu3
 ?kR#AES(ֻ&PLupd=Pua9(Y)rmyqnώ>1sY)<JK
g<J΢p j1͜2;qdpnC_r0/ͦBpH6y;<!kx*Vv$7ƚ&pLQzp$CR5k&V+*ӫRkYIGeM<7Vin@a(diKXmr[᜹
@ߊ ONEљ1sѤ`|;c
)(E8?&}/1`"ċoP\i!H}0 ^qqCJ+ɩc[NŖa,i&4aAw$4<!7'#W0| ?%C?`iZ`'9[,d8|`p.s%V7yɫ&8hzӒ`)BB,(*RWcAL1n}rLxN5I<~Ad٤2OF>@`bЦ	ڣ὘[~߃x FBQ-$L#?#V̙FOm=S|Dyz#39.Py.[XQY :й

`xCNA4(m\iôjTq:=MVgiRb\t	HR<C.K #R6CXdl*pU(PʃGڂnb25;+hz%aXиT嚰L$B%Zb8.v0Q\ȼ!"<ΩG77p␺Lذ`3guةl|qXDa,v
FC"UaB6;9˨!RFsHo.C)5~/0wÉCȡeP^,F*JHoS@J'S2H'
ehѱN1±8Qt]d86YvFS?Ѧ<:j{!_RlcH0摛#vglL:2)`kW XvNN,3CX=frBErs>ASt~@6Say14"an^0.-2-o#ܺJyΞ.h()B	׆Υ2 <4԰%ib' }\yTL0oiZfFܶ<&~ݞw	q:Q̊ݨ{anfC5©%7Cv<F)=6?&KVOLx\X
c`dLt֩|f,u/jɫ@ReWG6B_X&EN
J&o'7}[QˤXukO%Y m21\JJB(./?bcϸrdaڷNӏIB!s63yA6hALÈ|H%Y*PL&MjC
9oš>`j[g8d`KE}z:ҙ,iH:D9Ft&fe?	@hĭǛNKx]CX>X}h垫ϣFhb 7eG!jT@oțҗe뙙/PVk\Rz~
b
z<hlX13B#I[)L{*m+FeȫB}L.)e&aXAUx;p5ujpiȊ+u>_+*oK33kO;0Ec0xbW<|99kYޭ*|GO[27y^qwr3u X%U#ex@gɢppo}iT.dT=nit:}^1fs٧gc=RygJ%s<m"bk1j&c$&8EYJ)i<c7SU`VăVå'3kQvAz7ɯvHOUus3cF!h0-izOi9T#%;Н̑"`@*Vn3rLUӸE(?:ci:nWzoٕ1
Eyѭ>zs%ʒՈE(~2cH)ut%03 K/u;Mm.rzQmoX:11QBBBxW FhMEcnu4@;< WZ1t>	tf9pZzGBPvk<Kvׄ2	mR#윢Tȧ s3YB*+6h!B5aԯшk4oJMԇRr(~śB>S&_ϑ=:DMf L U崝"Ҏ<)|yJ4QFhb'
}Rs}g؏C?{9
kXmr6}t:dӵ--3XpU lZ@pT~[v:5'jDpv[A6
Fc
H4uM0i#NrD]kNd8uM0~(M.we_A}W@΀5sEhzjm5RmdFTlDe```^-6r中5x{mכDO-r"E:ڱTNf
UQT;O\P$ǒ'gr<Xx3_Ke5JС<+=UzЩ٩f5V:~ !C`ir-h;lL;6o_rcOhcu`u|ڈoO\4rIsn#ME]rFo8}<U-  *W$NWu9 tAT91dmK\ɵC^Cvf)MI
	1Τ$]V_4˜9OҩU!J-_kĝΐb?VoV$;$7uh';w4xثՇf]LEv̜]->6WLDCMC!{k!놵RNϔ"\.S,O俻ߎw\z9R>Lt1rm9D{\zdҲacKQm!y>4ρ$maAM҃a$>VXE>t%}o|TuJTl3SFMyw
ym?y{$'υz}bCY+1"Gl e95`ІLZJSRX]R53/eW˻,hdaXX-yStjVcإZqs.|mhP#4%L BJ̌L˪VѠS3wH\@"C839Eܸ48EjH-:V#}j)ձq_6kȐaRwhBUxdPKʥK-<nnP,|T`T2rcIj!=P{aeMdnTDE[b33Ny[eTc/=f	)׫C vI2\X"ZЍ=f:e`-V%5Ce-_S,dcrylNVnN)R@ìEv<u)mYq睝qݻR6$AI1>pB03<жA v2yoڴĞcO8Y>@n`?e7^Zk(<9ypS|\Lp3ݶk*DB;(KA?dw]Ikh G3:(wt-9-[p׭>8}Ty,>'DrK7E撏%
ۃ|q&٤}< ]Y`3ӾEuc;MSIynO6q#dЍ.Ăk4)/b3DR P7=S
U盃Æ>7'Yc"$.AfR-Ƀ<U/]*"!$*"0XTj<יlXzf2ڎ_칉zĝ̆X#es'W\y#ǨĐ|_\_
(ݼ$n$7д:Eg)-8]c>3ŹY~iz1J sgQpǳ֍:/x41A*-)\ߋ,'Wӆ }3]Ǭ?Ԑ[Ͷj禚5bsN E'hUKÁ&'6[vy*z"'vkfv!!h=cn:;1F73!p[Av'/7!HqY8XFm"97:@6Dt6?^uIᣲ'7ى 	9KIw58O/^kgݱg3_Ν``\% ܊~}:e&$<fMG
g/_{8/"hܑg18p⼖j^Sejݯ z'Y};ER4ͭ¤J̦4{YZ\uwjgy ٖt(h\dIO}y>9Ib@IMA}3s}u:OBL{\Bɜlg17sɪP+rGg		g%6Q&}Vr"7B5/_^bjlAiTb+%є\zȤN׆AsG&v#.Qf8֢/]חp |{,C%HыdV"*Ά7yRhEW$it\Vp7UMt':xl;xj*@b
B0iZoX_YH)Owg*b1r>"-CFQm(!KF6n K&VW댫O'W}ⱺObsdIB<KfRO<)=)E}>3"o'DeE1Q̛kFQ5bg[<w΋`I&x?ʱ$9-cnG]Clv~9&U|Z;Լ,ᬥ}iٞnSM=97ɠ;gHܪI)l=vNU3˜eMC*&)I]YD	ǎ;j_EB`\vV}NچW/pzF~:am]@d-&kX+HxBAzibB\' h6/YqDaRAP a9L-
sQZr(Y5O7RU]	םB}%XaF,_oRwS+yGխ"s^ܔ9j9jFf`AQCCH,^<NS83
sGj)l~UZe%@rC$5F[3Blɤ2CN*4$~B@Ym>Qksٝ:>@tB
%4}\ǌx Ъ<%(orh͜#T6<gݹbFZgo576* WW|8V2n]SK嵶i{f^b*LqOL8a,-;S˰9a5>+`nvTV';:gLX3"V4(4&]6}\-MmRڿg< e3EH\2|da+In/yUd3s	S-Bvm(T;o9J<|^e)H)Brp1*d	AH|M	ĻxJU6*2[b
,yD;﷦SAJ=8lX/tq(aց\E
j0JSR-vΥ\d&(0#H;iՋN?N}VL]d$;g	#VSg}"u&>2`}l%5_ӜmLOYe4DӊઠA띳Jaeqz2"B[a> 9/z|Vy|Hl/|"p |y=&#XDFD
bsX2Γw_if
M]i)89MN)Nl=ۆ^b)3,uЙ*_&y+򲳤8c-3MÚ]\)[h0}O-P}A{!6НѾjjg2B,u8)ZYYytE+d/fGx2.	LA!Npr'i!n`k_MǲA
DcO%X۝L#0~wyaAv-qZ\C-ezI
Q0TI2%|6VC68Rb-
pySJר81(ĹiEYG+St:)tM61nyI9!LOM!ۛ}߳VoA떡EړvB {,CҪteHӬwIRwsğ	`#کy~CҊ:dXN#L>SV
`.M Gp:ꚡ撡)BF#Mċ"<mInoS_[,	WxT;H%G-O-Cu6bxcR]ZQLzI+A'_@SxLtQr$۷|P@9x>çlRC#/8F8>WJf1g)0JiD,ґr=0_t.'fDeYjI@y)1wY\F`4~>[&JҐLC6כ3h>!Wo\bJm{eEo!=UbBXİ[IWL
 E{{5񌳒WQKdJz-ǫ,DGcr[zd|{*'rNuO:;GO9s2. .]KD&Yt؟^Oȴ~'kD?'cV>Fy3S_
iFӸ+$BWy)bR5SC$53Fmo8SƅK}:SӋ?!x6߃Փa0 5{Rz.h`xj6Q	WV5{ŮoJsؿ<g."UotTFZ{`"-'Yd oDiKvVN~R)dga;.	.7tJ + *6b{G2P_kݟd2έJICZr*WIBedT }egO#A5fX"KLdDBO`xұ(HsT6hTQ0D!RAڝZlgJb`̉Zs3'i@i
1-K[oRMM%3)^>6]8Yy.z1_/Wϥ\R-fH͢B@j	?vxh#tg5R7<uV߻m\2^ɮ $M-d59R6BjǞPWRQE_=E;4GC{\Q4-G0 ,{\`9i($a8Pl&*ΛyΩ)hSVYuq-p!O̗]_L(ɷD⥤j)h]ћ_%*|_fI-"ɮ +YRw"1@
 ~iԺ7J
mH%rE iϏ{/M$?SFL8z;T.:|'W'P <G Ptxzr;3G=䁇DN;=ի(m;LI=5}rgXj뙍}ZY`
ƒ:SɳHE}ٛw,ALI}@ErBӓ%bYHPglL&ѭyn0sy&qz:	Aw	dh`NZ=؂U+`enԔE5i5a9#c+6ҁM.AP
	M	vfour'L!@M1q{x_R~H<Qy vV{-˸ u9Y#iJE؄PLW;֭MRQSh:B2DYN}n}OQ1>7ֱh_,D*u4ʧ_M\)!X<bV'$(LdV*v}K|/u8M4j7+>¡iJ50sIj[FsC
[`M_C^K9$ݹOofZj'op<Am`.|p.,cƫN࿖?N>l=H[	ۼTJ"?=SY]XX(͌=,3kX80C>zYa% 7
!
i3>]/3_d^ӥӻkX0ͅ64_Ve0Az<.jGaD1実͝2˛]]	!*p+2+%pݸL*3uh2}.pe`҂Z$w
1ӉXs!N |7R#dqHۈR.peBBoV/y:i40⯾?ǗhQ?X
}lY|cisi)n;YaL1RsdYGow::=KN/{@3BKF߇-A}Ťع.xwK=gT,~
E	Y]=f.*j<
&5»ܝGNh9fMm/s=`DB9^jEq_ƃh*`ݜ㋤\H00-h+a3xH@9Oy3T#ްf:AE1vx=]4Ufn!҅4dwbGݢ~rJ.u'HTtcS4Ύk=n7o^`h4
r#P -h8|lKD]qC246ғ%-p̕ǉFc!s~XxC1w9I	M4v&U-IWTh9$&0EZ7O59=`>?jtVVbjn@`5V>U-vl>uS:^bSLSg)[&b)XU/itO	#iT	s6ϝIgCY7,ѧ!9T}HsC*!@)Ǒ- XCE R!% {x~S*x">X~2gfd?SIV#+`X?PN 	
n?.uss%S52x0E4敀>
Qq([5;Tel@nW U̺XO<YR%C?cʾv?<"RF/!8j-*WЌf ew2QRЁ6z4={9*'a"ӕ -U.Sɚ..tE.R%?\$&(ů۴n`9gEP gOS=TgxZS)]ٓZj=S 3|N a3hM1ⷝZ:4eI+S(Q2gs0lf~EͶ*`%)m=+88Cn67~|{|`[zR̬$*_TkKذ3)9Xh.R]/ODgay*͓vƗ/D/-G1g*g~ig{%roko^dW<Lx˕PΫH}TG.}9"yӶ<Up "Xda\".]%ޢA-XQCܟ߾ko[Atf|yl"?c;?v%onmtimydթޥcYQ(=nn?:ma1;'23ʖgՐ[e	5АKmKYd\O1:4Z8|1- Z
#7s!+W\G1ƑXYⰯ9(Fҳ 6?2j=;@qRb0&=DWO@%-9u⏘A!OyzrXP?qwÚ&BU9q!Q"}4+~͞)sx@߬үpDV#SO1fYJ4tGPSB	j
IݯKQn kwrȬB"].'@1AZ{ͣ1\8Q9&SHbf|Ʃ-IɿV0itO2@ r9GFW"jIdMhOu3D6U$B:%`iHGBzeWA"Tb[8yd(Ԭu .bŶh7Fh5Mܩb|jsVb/ެL]< vO<o?P'?W$	N]JFELiɿ\]ҨF]Y`0~Nf&v\>W942#z@Af"]m-c
f_Uߐ.1g/x&Zv;ǶDōws$K2"m\r\mAᥴ{sU=兝aԋQ6mG+crxI"&T]5_,+#(j*Yل˪&}Khx .n/d٫T"F#(噙z4ȘL2Sei@(cшL#e4lOPf>=㙗{%kF[Yh 6k"-
i7W/$RS,M>OGp0Z޾ԫ#`i<-XuP6oe^Q:{*N0Xc&~4Ly+J]K״e@Y [pj lz6B(9 ،~i<X1?#\d<2sׁ+)8/_/5Z誝I4L^Y`э@eT2ԍBaB`Dq'w*S6W. 	hSS0lQxقYb 3vF ~44uPux: A<5Ek3-R_l22hgJX{])ʲw[rXOGZw.v|1?1[v\W{@PTB/wѢݕ~-lX˖*6od&$2cy?VWՐ
S$JcwHL9Xxkj(ah踸E"ҧinӋIEiϓ­s3Q3Cq1odV0ˢ$[MSG/A#XIr!H ;In{sQ|R-k` jit1'lM.*wxV:_u_e}X2Sa*`4@0%)xVoWز*ϴ՝O?woH9gR׆w/hUO#?T)ϓa&g!1prKZ)	'-Axo'㟻;u	y#.  n
i[4ulۋ/FPZ-?/4Y>{rqd$>VЦ^ao2Jzkab"mO7iL㵈:	B7MhP8ݹ=\ZGLuȴ+#%)=Oz糺P=l w*vZɴ_Kch$VtS1߸J)}qUeN& oULxQA2dst 1NVoX/`d#B&ocquGxv`P8Ykm[yRs7QTH|%`A>w1A((U,N]&|cW\54 YEMJ ʞ^ŵUPNL.v){	S޴sr	ObJ	yT*}3KVf{C4]e%3uVO_0RHD|@ `2wVi&_}	VMF`MqDч*0U_)(xaƷg:5kҩ.c);o˼XЊQ,L(y6-B'O		';p
H*n*nn^mS4d%3'6.aǎM
n7x(]ey	?"y ۚmX\+1Md;$wcalUfc,1Zz4q1T&-@з<ȿ>AttdFpdθL{bƝ,S#lVZwVD_?}D͜C{=v\Eu Q(i=u
Wq0l/P;x;/w>QY1L#UҨo[A,V%I$nor#|rjcu] p@{``	wb4"N>=76d!JMjDԋǓQO-tv;?^~~j]=><t7ՁL	)yw:ށ6%[[;G(x\ѽJ|3tF?n"1ٍ"0XJDchxqy._ыsh:Yi$!:5$U^Nk(8l
bl"25#ACJ%8JPA^PQ׫	&ם\j@%e ~1IȡfP@jI<[VfA|btFPP
9!{E~6kdͦ+x/ܓޚ>"-E%cTۋnIm;h{#Y2aB:r}>L^wN5\([hT	)ʯ*ߧFٺ&ONp d:$͗/_/y|brq+US׺BTGX=WEiL	$!EcW]1,kj(3$D#zo*SĮ"e]cUgݟpFjloӉ.+ܬ
X<OV[lqx3LhD
F_ٞ|z
6qKצhf7FS$!0%?Ln/#q(lJPp r|kU٭[L?5{d5f!D0/%z>@eE݅38!qF$]S
/YYl%٫]%e=wR)!V^%φ wXi%`-Μ~|X?hIh-ߡs16vg=9|Y"Iq{1h-G:8Q"K1яV(x媊@l
ԜnނM"k+?ƓTGN!JopH8<ЗRߚA6.ݑ0DUC=vxׄ_i?
A$vO]H5yN9Y.>h'`B"]C΂օ\}3Ϫy\㡺pDvZ 70{J h1qZ,D,J^%U9R~[IL}$ZTܘN'% BS##/@WR5,Eyac"2{W㖥<Gd\.>gaaAr2T)ܓj5E1{.x&RSt>=bBOq76(2q VPBɄ4JL/C5:J-
!Bτ8Y2`>\M ;<؞H-ۯUo
NorN##PƏ2`4R|_+cPq5ҽʆ fW<fdJZ+2'hnYM{{<hT;}!͖fg=gӎ@jI-kѮcG쁡S:j!aE
X.%R+\dhl:mYc"+75mnּBVh:V)YGtw0d5dbjFl1w=`zNW	OU㏿}oLj=[ɩ_x"Zr^sD@pI{fMpl](<<䠓9sI:Cu2d;cJr ގF9nMfCNҰRlZzWOv43uC>zS.Oީuq|]O/^01q~] 5qpNH2p!ͷes!P:o.[索gxSD\/`mW2iqinRJ~$0`?g#n6oFc^]'{_yE9eVA%R%գ˩%ŭz~	pH	L9٬	ƯZ˽x(jzEif*gqWT6K=usH|WG Ā3n˕W+Gv֮'Ҟڥͭ,7exxZ }@!^,\yU򩀷
|*t6" Nϔ"ńew^;UIPK\FX g׶1`A網Vq^mgrҋ{v;j{t.8gЮ0,q;ZJv.CSY˪|>K7MT& V4)w*-ǃ&05J!J~r1rQJaD;'jb=Le~ ?Bo%Qg:u@|4Zvמ&ʟOK50~@<BQ}GؚX-=~5w}^X)_:*UlqKQ_`]*^i1ga:(AUM}Q\d9Rn1[wi/ v9Kh*\_Pύ8"j<0ڈB:t!Skoy$J6D̕#Nۋ5L]W%RN\5kH4(G(+xˍ#w\)qb̔YeSkXrH!AvK`D)Mqڢ~#OVfTYHAl6AVlk#9ӭ3Ne=FkTܬ QSN=s#t~p	w/"kU_#vxbnO ˉ5sYS9zŠz?l؀O[Չ⌮$uy;*0t9J[>ä	4%V$4=XRfS/*@MU"&=jfIY<BhF[#,e_-65,)5/;)ب̂JNyV˳±*5R2;8ط\bG-S"]Ǹ;{bgn=!' =e2M.;4a)]`t=8ا듲L<eQ:Mnl:z2ϴI1bu͇t%GA;4ȳF	~C8)
Njү/Q
C6V@4FҸQT`<tŖ$WFW7$icS4(&!&2~cgG%`~fkzFr	 @1JTYn.JwG+43*0$]&R<.B;=@ %3-Xt!e
/˹eȮ3TdZ/QrWw%U6/yY}-<^TH(t7P9D'BKS{y{JjC{Fŝ(S\kW)Bj2W}e<abE!knꆆ'
잹c?) MrN|YI4,,Ef>?CL*cn3p	:dU:7u0XhoJKJ(_}Ӌ?ZuP~ kp$>>4	27?5m7ENq&׷QM<Rss/e\	V _{CW!?vWxHAOrq~[K<3[-Xa	G^MB\Re5u`u&x-	.%QNoɌh$6Yf-]X/.62_}%&]0	|VC[dxm}Aq?>EIj'$ 
/D߾5TЧYB!_\Gp
JCb	^Aim=x]ku.铝K٤c>z힜[BWAUK2^V}eeKh'sWvӓw|6YY-=2W6O5wPeKJ&'~?OIOҭ'SB`M;*&@$;^xl
Ѣh۩,7l6Nb QV nqx95::V
jkXT:]/Xiߪt#hQHcԯ9T#JFnk iˎ)O%ۣhgB{㱗^\`Y}ں*H?7̾~3zA4"PgTv]t 	-Lgwt1^*/zr<4/H,w_U4guoݝϷ2}CchxC&s`\/HUNDϧ.o~.]˸$nJ9A]Qx}<߮m6i&ҏ !QǙngKurOhv>LbUƐyd-}Eջ0w T"P^\GYrsPhkNE}{~{bF<TaЉ=?'|C8O ŏJ	v#+ ,@pLbK98/$W"$,6&}eZN"q[PPB(WD]+ߗ%HNqOAˡsq.\Z$nlW0PV9Pѱ~e,n cm`wMa4(gk`;^ɣYRr!Lܛ$͐4'<% He/P˻ ʑOG.81ƯzȰQ:@NM"%*=R© n-AskR,<MJk@lԓhûY0K}>ԦpUlu-@5pTUSCВ3L	%1Bu/!b/CĿ}"ŋIiz¾-vRVID0DVx7䚬 zbB(,{8QYu>OӠPn6잌%.WU IACyd7BIF0.Qڅq`PR,JYmI4;wcۊlQѻ-5	OL;t+``9}4#W ^\uU8o"h(KkQ,Nt/Xyƺ^	jɰff5A{+W*WIqPmJ'n2Jn}???|Zi?+_a%-fL{H:k2aC/{GĈ,Zc`^I3c`1:teh#xD''6!׾rY\zYrPOZ^ ׯ[A~}D	!y}!B__kCc\cQ THUV.7'@%18ޱD٪Q~*Vg|~(SSʇg&l'./ٕ՗L6liZU߃be'{zX,?u&#eYM]5 <˨ѥޣl"r@ kfuE2:F.RLoZjڝtrۡ ]fjE
1[w>>i26ybނ5D_H	cЗ{ǹbtENQ_W@<^Q8ouNEyJU%;KSp;Db`|B[yJZ	DmW{"Zl"q>JzCxHHjQpxN.(Y'U!ulҊf/Z*j^#'}H[L|̽iT_rWZN^7/(n%G;j_Π鼮 σ;hx	aeo"H5Xy>籼Mx)Susۍ8 9-jv-;ඐ`ގEmY끝A#UtqLCWHOЋ]/<EGdb=MgQ
HԤDEHDQw)(<~\4T/ޠPŠ{9ueN<ԏg?E	pQ*>hWo ^mk84[y+ bުs
dPQEOE/X@z\E@ߠoǱ>F	ZU1A庲9,%X-E{[;r#f <g2P2yHhؐ=8zc8i
Leq"rhM	`_?f;&,#||9e
H4	7m)	MǛ8=eOҖ^6u`I75+E2HZF*M7zltjs"hw#:aW'Q\o9?FIaE7'׀L2NZ4=%BHFT0ԖԲ@X+aMCcQL>eEK}[LůOx
 *Z
+
6v,XaLԡZQ*bvb`Um-ᝮ|Qj>ǟA[xf&Ut<ПrӃ8/`4^	Jp ps[I>䭨Y9<DNZ\$LcAR"q 1hA^K^g=4`z
}XVe=v/	.gDֆUne9]ŤX,=X^yqzЋlʜkص~2Ʒ2S'udq$YTMf77e?&Qdc0<*!IEvqRdK*.2$oS0+(/~	.)`ܛFbc'*;l7hhț~&γv]]X]D\p*@g8q~cM."5uٵV1߄Ť@fτE^/1WZS+zbb/йl# n},\ުDLQje PEMqSIET{Jd.IS^(Ӛ-	E|A'Pvq@ ݕޛ4CGه^%
y';/d2N<1rԆcDNiClF_,8IT[{_EtD^fhrDf^= K׆43b
.jzJV2]v+nj[ս\CF6}"٢vhf۠R~ѝ+ћ/K|>ރ#QVU#>슟ݷs%$_u1ۑkM*;
bKTK.ec1.>&td5獘gψsތ}!V
|-w_<Ѓ>
Ǚdti!ɏЁd'%g:
0hނ8*$ 4fmsdPP7*TMknFEytq)y1L]EկR%뱨?^*o	- Q}J}nm@/Vh/7\T>;|i!10nn'B*h0ݺR9zyէ۝A'Uv+xgk6oQ/ø]wc#GB7j4ݨ?!yz/ʊ_FBm?	Vu[YVgJIRՕyo87Du*o&[c7{uf-l1K5nq[tV흣L"6>hMIz}@tc9no:$^nX9nccJT?:8n/]i>Pd8-`}gA9N6蟶"k?$ڛIZh[탷d4I7ѴiGOIrS)I0.(x.l%0k6k*E7y?9-5C-5*6<87t[clƞi|2z5,jl~\dc/v`^O;O8K~DN<]W%W6$jD,uτ6۝bv:{hESIZ`0h0ٝDo=e(	xؙh{|ڝ@۴j!c=9"[?o#dK؎ӋI2&5y0'ݣc1kM@8Ov:,l\	8	:7jd_P>;eɅ~3k=UB<J5B;WpP=Vȏmy0?&8О;F^h
!`T^QrUcbJ6sCrS2>yikt3Muv
8jj*/{	5|*4n#%cT#FV3Uħd'QNfCN?tD7Ʌs$J a(q|YKŉܛ`B)YB{	B7Bv/gĉ+ qMs?JI셺w^V{?Jؒz
!]C`4"$D:f3Q2[Z"Vf.;4%)LR3RD?m{!~&@[\w#}3t:IŶc$S7Q4h)1U,(gDYIHel$9;?wۅ n6>Siѹxg}ݕKu_$ZO,tTCzwbs ɡۀ`
U3gi2*A:NNj~m[ik4@m?.ܟnMaqxQ*/5S=ot[&(ݷl;NGJ֩OŢj>dz[sWmOӓh4M6lwR&Axa<ӵ,I^:/l +8լ罓ZeS}8wԛ;]GӴ|S	 v<8 7~thK899TdtS2mmsǓ
v!X͑q3!?-1o+WZ*LNv6Cy Hqy!0asV	UkFyM n4$6Z=Ɓ?cc(xhtmi7[h6=۞\EBU	
V K6fTܭ60ΥEXU.ry58FcG;5Wx%ݰwIό|o>kmeo^WD1yx$V8Ǭ OBF$#*BNd0hTtgV@Boũ&2jon$͍1f4$_~8#5BtEKX|p)m'=x6׮Gj{Vp, 0l>e'^q轘hR{q\uRL'T'e 2yT<ͽ`QB招hrMNh|L^ bHλmևdPեt}}tľVVŽX`|fGz(H5q.-<dLScx	`Ƽo~Ӈ^쏍ƛ7GkSKfLPlUђO» k33G]P1`	Xf'g\*+WkFa4i|1tj^4*C?|C
χly`.TKmVTp0cαoi~Nse&*^Ceh%VqF<]%׮Fl&V^]!7Ⱥ5^XOxqj>#Q%7$C2Ĵ
\瀇6t<u(9lOGV|m|VARi=uBV8xZ0Ɵǂ@^-4#v4ll5]68yHLHV3߿+/}Ix^wMWzO;byMvxKOt+O_9pwXĺE-9T69k)RZ߉Yzߛ(G+2HjrC߳+P[fNz8#{A4yC)A2$ܡ8CGC SpZ:McWu6o/yj04cC-8JH-[e&]$<=:46i8O'A ;HQ~.Lb<E9F/HhHt4H$mǅ3p5oѠ!,Ȕ*ZR'cP'RzYd~R4)M;xmA	g
{&a//7j%sVP )A9yp=	߸~p2hŸa0H=55;gävƐ<ǚʗA$H'ˇʧt-|nJ6It87豊gyɏ^6էf3{T {eWyqLt|l_a~JD;ǛKtUԣc 4de/o]c?4np?'cc0t;eAsg1-s@klQ䳦tY0?%%] )m=!-ٶO7s'l{FP(fx(6{:16O<G=IA'װ_cxS{B^I7ǤlJccuOKU9ýD2pt?ޤѰ{~ƽW9}1{.^Td8x\XOd_LeMA.!Rw*Fn{c?`<tF$7u^Ī΃bMtKV$cx(jq?.S+v1QĠZjgN&HW\v)J~C$oˏ߬cp3 S.4SŅM9x=/^31V*!%K?	LtN&._;g+6rx@lor%P$.جBHsQS6
Bo.W}_!R,DوoELhh{aBs.vbʻv+Vo0l?!Fn`ɱfJv~PBklC~r1$?`r:ۼ AckS˷C%Gٳ(S-٣R+O]5 z$"`j5P~Q1u+sr
GOd1S:8O
_<Й%XAvr/bkCTZR]2aͅKz4(<6(:`bq6Q4di~LëjYTg' lt Ti@vUoiNa(X{ZkJ `ĿzYzl,𐾊H|伩k*gP"rtrEsVi S[I,}.S)ETK^/7ʫe,f`+_i-YozlFO$CD߯`	k4GYd-ӗ6LXE}^,d!*eE\RVCf3qC+#	SH@ڎ A	7j$i=3ŷ}7;+%9vYAzYZyZdVJ甃̅`L=-z^@ϫG@H_$;I>S*Y|;or2<jue (xazǕ%;X+ĕBP^Ha4{6W&ke	+sQE:6o{ԋC4ro#RvdFX3>3-#Nt=#Sr2QPҥӃbƄl%9U7ӗgvG(*u:yQ5,Y^9R:	GZ=LןWi-3BP֮z 4^ﾪx> s_Ry떷F{?_/:,;W
uD￢q.SLSx$Xp&ؖ71^2H;;Mk;^G
l6=.<S%ElMԘ|ܻ(ų+"=Em!gj:;GVP=kj~22mkkG=ӄtr^M1e89A^Q@sHf%崵ؕ{],!!|| 'Mbvl+=V8-ar.-B<sU*w>ƅccpL	)
*g.虮F`vYxU$Ή1xw=IFCBMɇ+oFjS2 |XMd)JQS9y[xwD%pdr5/7R.5pK8y--vu"3"oz>S/3۶|CZҐV㞌QiܧLzN][K?#;}.SVqXϢ*{pu<y@HbhFN}oMqMv,X㭙]Hy|<kyDU4CV*B/L*4߇rBHx\bM⵮:+fHZt*&<ᒞZ+bǞz0&\.gCؑ B(Es-#*Oy9-ntʘ(gq@1=G1 EdcErTUBHeMz0_˵Wd=.-;RE[R)VG!HHgC
4Fڔ8s6L,W-~yœ2/B\w`Q!kLW/ /0C M{9_GQ?	'VbC=4-PPm-"6s\IxqW& JRI}ro6t%9Bc']Q9N_ZV,ZֹCc+=U|̢ࢡg}fEh ?'oD <oA!J5t8fEJ[Oe
4v7 , t=4mTM=4ܴ&#$͟Iir8Ĺxx#sA@Y	Ȍ@->9;7P!Hx`} 	H"vALv9Q%ϟ+^K>Cso#{O__x/Q`vi˜-+.e^ME%BŖ*݆Q1z!( :]LVӤbi\ 2\ܱ7zXʙbfe=!%D>Lӊ[k_a.y..9"p	|_1xp9<hou;N^热n{P,toFCW}Jt9GuhwGvks@v~[GI-UPNmˁe]?B SFԓs~*(;!%~4ޝn;kXڭ1\1)}+Yb_Ec'+wFo˶+=amk,[A>`>*Չ+>+|
Y@?gñWտF>|hb5$z!H[BSS8x	#m3"Ր-S%ŗ^DAwnl:ՠ.ù3LyM}EgAUj$^,F}Y(/g1Xe?eֻ}?*O?{F#
ϯP즤HN#ҏc+};җq{]Z%8> dI%w.A$AѦbˡqrg^z3T߯*]o3`e<}7^PHL>L00lN.NFQtx`Jbt93I/fWIPnw= pn%1K#$5	҄>P h&   ĥBHHJ1WH@=fl}3(?4P9/%ŲPZT'XWR,-늫~pDa1"_b˔jxBRPA@p1H%Tj 
&'B \H]%G fS#|%	&:3<2>.%o`uQt4T÷sF/r.gM7ՆElyN$-C{WQ&[\͛t2Yc.ͧ 9I2FE/\Γna4PP99iEf&&(M3'~nvj1I%*`W_y@p!E~37ȃx1|ߥl0Og7ܩs]cv>ۋq)*=4C,9qњsrl^<F!+;dA#j /:J8liktx9mYArgbȀ{*	Ez#ESs
!RD`E">"?J+ҖVbW=F3gV.le0)ۘ0ҭʝġ4=k*G2q~qQzI%D>wct4܏3b_s&4VztĿE%HGNՑB{f\=kT4%{	8y8j*}ATLh\8KU:J`ɓ
(β/:d/%%{ߟCp 㺳y_$8%p??j={@"D>TbyкGXT畭_%ʓA<ـBu3IRW;}e3Nqqh^4yf9>XS.|Tr.R|qy_cEbj{u9m*ܢmPPrԉ}ާ`&+U lV45I?"6t[j*MK:*{φl	m쫲̕%} ,uo;hTE֟ߪ׳}.LK`q_CțE:%.vf=:Xc3,l;VEwLfk?AܧighHT)sނ?/86u`LkPz@n10,zCFOoOry+N57a5^%okK<#,DθJM(p= N̽|ןnF!a-oO	yfΈSCK 5j-ft{;NnLC$b,_Iђr*39^"=P<]L\ꉢx~!0,$!0]ŋ_.UAv$ł3S@%m}JP<QN%łT+JLzz%MS/_NPpZK8(3[4s~]VFnt+us~6a\ˮa3llER橲	57njhZY`bOVs[: Q[	h6;8Iq=a>O/zKOop"^c!%"{ՂV*rAEw%[AicnMN>oAFP}h6W}Av>.m&\+H 0H\۞٠t|ՍJܞ*½YC9([=,r9SOb1lʝwAт'VhP]\¼u7z3ڷ;.~>ph`$3g;ʝ>Z6kFWJ|)d"(X[6I;z.0kqwZpZOOB%uV!^M67X#0'c+jµhw?OlŞ0{~#"*wri` ˗[AQinVlؗD{nx~|h?vŴ1Zw<F{;ݟUzʝ4Gj o}8RC*eԖx/'d0L%jNo`I
%@U@Փu@{=*1VeeR9DlZ6:wP r&L,d@bSph^vGB 
oSmwg+@wpUJtUvn4c2vuԃ561z
zX)L]-xYZftQJ"`&815TޣgSqE}Jwϥ9;l}zӽLǗX~vѯƙuiR
,BOz˗mr]Sɇyz}jK&bol wHZpwhH4UX3;"'وUW~ڳxJp]oWU'^z*l_ 䵷_nk?_߻ݗ@=-mtS[C4K`9ς8Ub\40\'Xʹz8XwRQ&L4=	Sޒ	]p*Xw.p $߆T)-VP	`l/{mrLVnA<zV#fk?Df Cܒ{Y&%gE:J|^Jԋ-OMt^i*O6w(M4e4Qk||]ދJm|uNe~:.Gh\.Dyyآo׌T8XE`Nb9<ݩ7G7MҦ2;EX/O@>lzc.$W6Xkvxv=<P'bo"՗fn4Oqu3oBc+<TF\sD5x)qK^lhVw<<1ꗾ[L']aqZO6sűZL;.3_KjC{g};$ǃcڻa~kt4a0]E@alMݏ >aFvbwX-lAԯ6w:k 2KWř}@ҏ_Yj\P05dx]M/ws$o!9@I%it&w8^l['GM\Fj!=^6X_ݣCbVQ:yVC(|<X!#S02ў#ǂ42i3F^cl\oZB$K|$&Qo`_?f%x<!lL
 b;0Y2H/Aм>McxE=i{?[$S`t7Zxf92jȁF4?˲T^/r'@8rsŀE5LA,,8zfo#60ܡ;4qe3lf͆T'ߔH13m}Ȁ髥<^g8G\u~6ГۋQ|uPJk:b#HTR)dN
L9z%908U<O/<>;,"s*d2i,ĿFQ);j8xwA&,ͣ8|Y}EH\3Kygl^;XYaamqG٦/HEVcd>DW3ðїE+Ua'c4:>걂e`R(Rr}C}10g>f	W
W`Oo+*
 
1hP>Q!pؘ%ƹ-d.KэǇ#G^)j%favvgˋ&moVROY7NU-<Ig(eY6C
n!pʃ@8
&E.Csb=ڌRp..-`ΠF=,~5g]߈%{j4uH (F-mCNMD+)P?Y=qJP.DbS0-xftr:e6lVIXT~x#Nc2?x2y6sGB P'eYC]>Dt8-W-"<P!X+!D9
j#"JGoOx{--c{f>ʂ{,7}QLދ|*>f2;L?;<:l7BힴY^3 E*`
v
RNݏN1|B,f2he(ʆ{n7H2ϧ,UzcNIi*7\D[J-CϪ`(wUS?M]V_pr?1(6A |7"@I~,AP~՞C^t CE-fV"AN!Rؔؤ1̚Ml\]dDh{4Z5k|u><H*Umiݻ2Ӎ(y6b h(bLf#wC<'	Nb9dl)ԞTon^Cj-KnF `zb5V*J"R#4wlhԋ߷rGe53u^bǢ2Y"="Ȣ$O4Y޲"D\ٽ Й\(4-`j?apTb҇B-T-rUqR-ZKXl2Ƿs=A>te7\&bhTo*}*E}u8Y1QHpDS
AG?p5Ȥ36W5<$zt.p lf
~-zoz	*v ?'qt9r1H>B.5n59egyD+ z΁^g|8$&=FU:7%_!wgl`0n*({sh*[,HFQ婯D*&Qˎ94wb>;CuΡ#GAӧw=z@kpϾ;ARЬ"LJvK/h*T|M£lگ6Wx$O'}ѫPk:FndKl׊f,~R}HtCo9٧Okzʵm~ގmߺĊ"ZHs0>,ow~tM/m0IWZLٮ6Z*Z#!8MO"]%Θ{.eX6Rl<SZ`IMHrDʝ_b}۪	3f)/\jVkKX"3K6KA:S9ZR_#-=ySO2LfRX!uVX_/^ZH'#H|cIXAc,RՋE/	/r:ЮTP}{F~JWIo/U5ZJO2<=Q$aS	EÅF#!]ܖzzdj2',V5ncL773^~ka hy[sjә$蛗pfGZ|Qx~8dYC?tBT4eAfzazRpH$k^[u԰dՇQ7ExcQ"EMC?-~hOvF*}!fQ1Lh6O)%e-;,n!ff@0V3saբ36 66X|39޶>v[Ŷ׵ZMhª-6R@>GlRm&ǋҤ:)żb{ő&	N-uKҨ.HպrG=B+UM+1k
J~wJxd:?osE̾^L_Egѝ0pRv;:1Pxzm3Myf35%:%	ТܰU<;i%Y"thec2<TwRx6Rʊ0Aa2Pd0}'Oe5?CgN /=3
pk0E/igϺy!|Am~'&v_{Z
az+#$y:ZJ:骉~N拏FN6(lǽb6bIgvﬄQ`9g:N_<jt"Ɖ҄s+_׿|Q]z]xt4^3P9z*JqiNs¦@RmC&/=nxΖP̛V1>.F%UډM@*_BXY,<<a2DKG'ʦZ4T$5VAj3]6j"]ΎN>> nR470qQBPǮ''ןt\'C#Z%!cx0dL	:tm|R}7Fl@v >n_Xt&ܫx9xe	NuM} {xDf\]uzBxV B"q|˘`^iL5;3]Xf⇝<5K`Sm	aE9ŗV̟+(w	M,0'LTUgvQ6[QCXQQ&ܵGXoя-B+&~DKo|ۈ_JR1@ʛ
cNTLk)'Z\Afu8x-Q$3g}<ذ}fulE,JDCP6N9AtQNzT'Bĉ@2~h1?&;youn-U0If잻UxRܡELCCkHPꔇ]nZ.zX~EykI)l[VZv'gE	绘IsCI^0i>d 69w*+S
(Y)ZUk\N룋&k"=T0VB@ؤDbc9?R-,:D!2i:u9eIl4qJtC`tQA\3T4h!EzO_+X{)QɫT2g0sHTW{8ָrCP4huA*LLCk)?!q`%9sf+ֶgAoSk%5Fp}4T+BZ$մE gr)1p)aDBu*Cxl+7&+'pCҬ_IRmHs5Ŭ5YdY"0`g£%A@8
j>/Τݏє0TŹ!
;c? g0=m$uzb!AKUy WA'Ȅ#Gff"rTqHJ\f:{M/-uy1B rY1M46 	Aa≔?}SV
zhLD>6cC&"Z*|.LM {$3y$Q!.IHeZ=01T00
3xYh8K@Dxe#j#wDxR`9`~FG{I{'Ba x6WI}2w硆$⿤C6>LirV4G)h2e=>'2~C|O|,q<gSJVmߝpT]dlu(U"x1S eufc |{g3C ב6
,9[1;CpJF^vss9d(yjKؼ2D	@X©ld-*x6?tX3؀(m:ב1noj03K}h[_zSc<U?M
Rue &H/'SЕ`>;5Í$A׼xfWc&3R'Đ;1IDג4vͪFyRl2p+Ԧ̝/NN-8w\%.M8EŲQp$9JõiD"gd^G8 tˤ7Eg҆/V+rLŐg|чN+r V^kԊۖr)F=)'`?٭5!+I^]v8ZdZ.C}~cN?'tHgz2!zV 
H@ݪKêw+b[zW`
9tϴ4<1(0Q2Vyj4IjgI Cr!2ZA81ztΔϝ%|KXo84HUN#q!JxPL3i_7n+2s:9g椫gNbt6s1_ΓvgbJ()D;fGƹ@]aIo8T?	{b?qX;f'/(I;cD[A%#mA!$s)d,7S-ަZ-x9fYBF Yw%U([Ŕ!@Pu:\KdU'
$Z80bu0Ad΂롺$_3wHʄ(vf	З%gCfo_] {_24_@vy&'fA??.V<Cn vzg:f-}rdܱ9 ^&Q]qLMclwc&TD扠oV4ѽXx99IX.MFC$޴7ةsT^`nR=ǆOmD@hhd֣+㮳}3c$ohx|OS,#j]>wx;-L{~oQhFՍu3'O&G?̛Wu&&hCDTZQ$,ඖ4ϔTLuS4ano>ZkO㒆BOz2rO_^b5M|VJ!$@0a`	0ZCDD1%T,2-e<yjx;}.=掀LԒ-D'AOCƆc 6eIs6LMuӋYfm*Pnkbg;a",.=YI?IBxXXw ';=PxѲ(M8`RzяOʹ\>ؒɋP׍?'vfR@Jll-leC_v?<R9ufBmD1=ϧᙎ6P''pY{e})qh,N'um'>d2?kw|>Y	ӟ34-B1aVYޟLf襝i@ӊOᖌKǬe&xH(hnEUǗlXSu.LUgO5",~r ۶v*6tfW5/_ɵx']>oPp]	B)Og0Ja^2"	zn;Ƕu?C/ ɫ;o=ZOyQE~K<ۘ4y=:`Nd
ˏYDxѨ/jwRA-'TF NQyI1
5"_%;pPޤB5MsV;Xm8!.y|;w5>⩲Q6hzg	z<5F:(ۓEYS߀ˡ<d5Vn<XrmyߖΓrvř&~-*xOx趙Hjt;b?ۇ {$^ti&u͙#-;Y"L2ͦYY+jwfM޲fi.7(}B-V%2`Dnܨ
[/tKnBLv6q`3\DϛAk[cHˇkҋ?*AMH1u f쎵N%BS̖LEکM	J<ivCaVpߕvYmhFDP+WR]FN\oy&`2
n&
:_1'R
WflZ{+M;Vwi	}ϽΡ#oɈbJu0~D.κ(RcWK34D{v1ιƔ;+zsD*V9Ok)lJU$R|Ba8%Y|E]NFp	-)NNwӹ8jfp -@i9K%]TzF9_N [\"Tu*G%*o0fGQ8	f~[/tRԽ棤ujyYةYR;/ruצǊT[+j"+h0?(m}WOiM'nD\и,|{LPj0ձ5
,3.嬳Ae
`Pk^k|-TPӚO+:!U9pgnTsu_*pN\4G]oa?C`Zb`g=`Zၝ.hLewhhC/:dzJ7 (LH;ljN\osk
\=|U2K!]XoA^L͡;c-@}L]2qvz-@SxyzۘNq|cIA\LrL_Y!9F{w~M	a&8,6`-v8M'd!fj~/ˢhx
̪dU
RI{=:piRCq;/TLV*\*\B.gr9M膸]|zZ
HkU6敄V`	Xc)}!ڬaJ𦾬\=E|0Ev,+Qcz:"
|zg:1jNI Za|kG}Viï#yWէ=oypt`īf},N U  Z\kV	GguVjxpOvÌko|0WG9Rʀȏj{'0A1aFCy|9:h]o;F_Lh믢?{Q@ӛfSƺd*bBHvVbszJ,_R4sY 7%&|zO?_g`xɇ0I'),eH|}$Ѹ9H-.2[VMlj?w3<?L[6AFK7O<ZRt	5
0otUA`wG2g\_֯zKG.ŗ		*8Yo!3KM@DڵlTRvGBg<m~sԓw͓v]x&_uIɍ#T\qDspB𐶧3d;*96 	XCG5JGCF	kg<A_3&ِb (浝4].`fk	Z@2B^-ɍ=ÿ]$Ņ22)hyKfZOzST\+e.)x32_|y_A_}>^>+2Vk Wd4#<oO'	%yJ)@f1W#/j:wdġ:Ar|aڻjS _ WI2:r:&; I#KE6%\sg!٢K2K81f|Y`m^M޼0x|1{0"IB<H8/4nܰpjHC:^ȋwG+ %kS\dOAe)G Q;}@CK)F9I"<qw&8h%$-Ե@DhCnmlEL0J$(emPbOM%zץ[~uGZ#_SCk`$[H-pdpPl{bY/,XBrx-%3kz^uBhȀ,M.ʷ
.8Z@('Aw*1I7J抓wQe[lߩ~-_Z++G0+' Lr;G"$v!0Q;FvNӈh"'Ƥ0O[vlNĠoz,>	>_ws̿CH1Ԁd-lElTۉz(1"KFçӅzepg2y?µe#Rgŷ),l,X4Nfmu<;fIyД0< /%ۅ))뉈эSã?q?$#*W>EdQ\;Byojq_ͿF	غM
`a)k :K|렝I<LtvadCS*οC\/v
y?eЈQl+]đ!f/@㬫$☉YO?j9޽aRl9EėZ2U)cϓ.6?r 1U7HҘsjT2w"IS8=0ņC(
3jS
EQHmM/p˫*JjE#xIr2VȈ&ԌN"ފVj+֪f3piZK3AgfxHa0-4HX	銱7ӑq;31QV=T.ʊ[yu3`vtU;U7cw
<Q{)xsw<
뼴h"TJ?{Da*9};Ŵg[JCZd
r.	cX("D9\	,7?d=I@$*o#FwB;(vloy˸>=ӣ\lT_%oTi>SALpxEPbj*|R9ޅ^r2TϡAB\S~>CʲhI@]Cv~ՅᥔqSA\D*ۜV)Ru({KwTj#Uoҫ԰22hv\&LtqWQ+W
B,!H+H/8*L4sc$ֺ-gTxni8PP#63åra+
"eM)b֔p$5xa@E\J `/"HaDReEv I=.|U\2KFγ/|eo&j;F)ī	F~SBel0hmo_}Jn2!uQMI3mziyVy2䜺B$)+]m ?gWjE;kSUi).g*7)*%%-`-i|>I\NDwWI5#GkLA,}^@1=toGQ2dAKf~!>oGS>g.I6jGpJm&# V8<?v]SpO{Avc;,",5mؾ7d{wVǋT/P?N!A]W '5^6kǪEQaI߂7ժoX?Z]/&(P=ׁڃsX6Wye=L7s8Gq<aBo%V"?~/B^FȭI/iQiArc^AUMIJ'AZD//Re3mBm鹚=4 +,a l1RJM58`A _띴GQd%$W'~1&<Hչ	q;#!YHAVIQ>F%6#/B6XOۨ-
<A{*e:R-rB&eeZ;p  =pAjtl,7˪~fyA(21˞XZ2ޘuٮj	nJ!v!Ϧl5Q\u>n|:`g؁=?mdQ"Dh:Yz&#`<d:Ir1b6r:;J!wb+yO[
\|;\:@b d*a,W`\2{9"H~TtbMS(:Sf2l7E&䝠?ts'FYN~-O4Y2_b'À XQrOUxC_\`l?YydsY&ůz#Fî~F2j1V]AOrtU<=hY}B6(r$_nS8'Է+ uӘݔla𿵆5M}ڮf*/z@QE$fP$)<:+/`ճKDlZDϒGZU߇3nFV+*u_S9%Og&@X&[\x_;hθd@%'dvլ/kX-;_LAl)94wq^a4i*c-YivQ&M	(P;Vl1}{[Uu=eq"7'*l!pAxhUei=D'U¯梂|79^G.3L=f<Q$95PR9LA9*i"\d_Q	TNrϤ7!v^ {5eMGpj4MEgl޹8La2rQ2{]㠅*OHz_UΛEfd5˭o2:US&Z#70T<'~{+APY]pO	 	(Ѯڽ~=ؙ}>=+=;{V碵4kcauV*yU~AZUH4nw͕ў*|,r_%Jb˯+}mCׯǇDPE]\ˁ.GNotv;XGJRh#l䠡@܁1p)lB=.^C|o٭m:bP"}C:U_Ѐ#҇@[l:ݟ*9BZӧHP|'>8OX)c;*r[H8<Aܮ׫X>w7&|YȎޚ͒A:H/Rt鍦{p62:˦4ʝ
cMHU|ٙģ,͊#˔UsULZI W)_lcj*pa|Ϲr&#euzng˜rН_|6V"GsFgFWxAM◰QW/ dj*Iu'#6S@u}1LNy[ږRBIr)Ͽ|Gq6i3vS˞#EGDu>nR5[ʝq+
JS|^>GxéKB?i$FPy:Xb,(m pNg&BZ?RH^@_@KgY+ǿ@<S_.7qeLPU_yׯIII#$]I[A͉_O<$gANx:G{⦂BsЩ6LՋ"KOy쵞N5+s"?QmP7zq6CEBֳ^hv,0-s'^_*94YwQ$6oFDp6Lt.ߐx߄34y^J*]7ڬ.fy?Geβ?KȻ%\al<HTw`BO.BS	L Z1;<%􅥍^pCܝãEtnK[@|	Pp~S ^t%ONZ lWy2??妬G,B՞rt#.2;K?;	)9GW4qD+]Γ[s2M ^.cq°IG3[>'_`fx.`5s׾`*Vd5(bvmP͆p	MtIK֟Ae:.dN1	~KF: !gj"]kԃөSbBD$L\sRI-60CW/_t$͗MfĺЊ9NZ+LKr@$|6J6ʎlFy P||:o|BK$C0r(cRqXZq 0LO|'KmVX
APza,[e4s7gnPo]YNzZ0oM)$v6{EWF šitSɂ0fnʖ> Ojoz^7)+w$hlwM2,!3F9qVa!ϥ;^|OT*먆- i6emEsիW-<sFZeig_ڃLWid:gfCs&RՍdlg}EHs͎2` wKF@(jZp򍽓%r$#uRxWT+k^󴝝|6qy{;Q]^pL̾!C褀DҸ(Pձoڤ <ܔdruRi)n2-2pP6|ieq@^qncdFnjDE
4U準ZcF+E;?9Kïrl]o_Ig->#NJ9i,UZlRISf:+V :2G5$Cb$fb}A<e bU>@&IFyfh9Lը =BlyNC'J3Ahd:%=!PPьΞhEzQcUMD94Hоc+E\y-Vs^BjZEW:އNw	v0Og;&=ǙHy:\o*3p1pSUѢ}%lW]"A((Ne.FcQN^IM[YO Bl'Cg{xe9/[!UiQ>ʭa%	3hO!La\zpp} :ܓZo{RĀލc#sm!]C&ݰP	yg|cT!j ;YrTɅ0&J[hy|b xq7Tlr4XJI/#hky.6ˆ]üp&MMif!]ʤxa\Dmܪ.Bhs_j *y,OMM;ʊ=qajǓ"O :X.Y@uog>L b,EK_3L]DivBm,N/Y|eą6SaoXK1h'G',-̽y|IX-WJ%tZ!g
cr9pWyOx8>1ylr娒~6woؽF[rm<E s{&Sb1.
3ada&TɿӵãGkGĚ{̴"8ܹZ R[m[Չ3~37x<_yy0-:<&Òַxg2	"o2c3].,m_)W`acaBpGWk>"S!6@^_֐lFyLŉv̄KSyd2ϟM0C1	~+߫<}f@A&JbXOv(Ɍoyoc8A)#ɃMYi;5NVJxp^N,ǠOd1=k6ytǧ.i,d'bH|, ;4#|wߔ&J>6:d!-%*Y3dxK@!;-k|^7ZIF3xe ef-KVȘJ] BgZ`<Y9*[A馴>AT!^ 
%<~<щ%p(cr$C3e2e"XeZ-c/- L%Aa]rDi&\C{mw5uS̄|n%'w C#+~aBIl@~TVcK쮥;._R<BPב,ũthkvп(.KPtu^gʛsBߕ\>cr	\CiMchPI4Eb?0 .̊+7mfB_r+z|'&^0Qs mDǻS(G4ZP%4+:Z!72A!97);eBr[/fM+"K]4k^#{5<\Y(A6`úw`UU35Q_kX
Nå4?#$M,^2r.&
kΖ3\&CHP*cۻ^\Tc"}4ૐs)~J؈v|ǽ0@τ+K|)VAf=g=[;SlV;>[h<`GQbjrU)p#r߫mSU~t|ei' C9PnQK$IXGB{	NAkQqLѥ*ܯ<(q8Ea,BpT 뫈	sFnE2mG}N?`6~ez4ע.0TNg5x.vAEFs-Q>UEȋw3pNoq>J'|! [Yt~b<`<|]͓WM)z42^!N+F4qpJQpqxq!
JWW2tlH=ZUz8YFƚЊkyhY!
ǹ5t,"i*uޢZ`3yGO=Zo~+4GzLfPC+,|6ju<pfz*+}qojx|[:z.*$5Z?!r
ajw|4wMDCMF}ș* D< 8'|d\Qt#/Oڇ{N_wJbsn58Bpa1E'4
Ь߃wG!([qfΪJKJgV//
0<{Nٚx_yp׳,fQS^aMyX(j6n忶_+ai1-uT*3@!,eLb[ONItϣ|x)tm Úw[z}ھ|U tX'tH0NL$9E..iT焬!&Wp0f`:MOtfHc?Zޡ_f>0Rt<E	~KSD竪AϤɶc&$cG1Kx"jWE$,By!'̱r;@U+<1F/Wɤ4~%ð4c  h&AٖjْB.,aKc'DWh޹.Li;!j-HYhukÇֻޑ
^5iT''J)UM:$o~[$Jc"Q}.,d[Tb|q^|};7
»Q9
Pmm^FDslnT$uJ:lT_TwI)1wjtLÉFbANINadf7,,D#YzoaT;
d.aHLQ30j1;3V>_Z{22h&Cc	z')*}	Bacl29eYTL&<ȁ"jFNȗ/]TcnQݐ$ L9RC&^TYŔirUÖJ-K+OÊQ%
ՑArBf	]JjW|b=֟4q8Y<&ԫM|I73s<ރԷj*y3 1'e\VŸRy`gKYH6bAEGt*vHѝo{/yj*i2,NFYbˀR+'Dkym9b[`KODy/uL[ƾPxB+t\VuX_$+[Q^LSU^$7h͉w0ހ׺+ӧ@+b&|.tq.j締9VX&8^jWNJ`KAF3cj|F.?ؔ'Id8htp{W]9^Sva7bvA=yXl 2sMe{]x~jVIQtLuj:\)'?yK]d薋Vř|ɬHqܦ@vq.}\lWpPȲt72)PHH/"YQ]ޠMUDG.GΑ|-?s+*TRZs;n܏*n{#u)	,tD!;"3~-ЩHi<smS鲐jS_xmr.K0{fM{Sƥ>'dp[_$ոlya	2uR](Jyi)V3r{I*/Oq|;f*)Nsn6?AsLv~uSYWIqs^J::Ývxp8O*CUZ5hԝ.RrrL[㮸;:c|nM8S{2k_AWtN\"Wuԋ+:ŗ[6OO]>Vz3=/UQLw<J>n	]0c勈?ܹČH.6L	6%_΢,@B٥nmȚ`EQF<Ov\9\:UMHA5F2LcMq!^0
=z>W+[2lNg2Ak=VB2bɊ P?>ӢۨTцDE<{)1;N3HyjfC3GXϪr$ه3ZĆQՇꧤKcK%B,riG	?C?bi`bVCjt܍.1KN"5tU)u$ /?%al]`d2~ULL$}8OXykY
߀nIEY0OmFʫ{* /*"lWe='CdWvK.Zf58M^%r-YH$#x ,:'F03s2W=d
u
W=	u.\3	i][2.M?G6"dmϨghˀbH*ϦE\1
Ibe	_2s3U@u@.i'XM*{,#oC֬3$2wY<8mE8Y{yHXn2Fr!ԬJMBȜp왋7OB*Dlk_KMIrO3Z#&!gh[}ֳsvqrG:ٶdi 2YF(XEb[ۦ%WU_)+:͔ߞ3Vw>9xHR9	:ԃM·x."L:7+&ق HC0W4"|)椑<#^$/gLqKV<XΡ	gǇn9"CKk5mrGKw AMjI/^zfR>œIދuYU9V2+d_!2V6̩vi+-3J:l]3<RD>Zϧf|9TJrf
WPkAUE1I}v~'ӲUg3<uaδI
d̐xyxS 
Χ33@rwk,f~ί5~Jt	]0>:;Iw޳ѫz]~|Ӆ`;\9'ݏ'k} P;p}8iw?Ew;'CPJcaoƓK&7a:gpg.b[Fώmȳ4XNsV6Ɯm3ǰ-cmaa1lĶ75$:f#(72yFP̅g<!rm-s)[T@PDE-J$5(iۅvzWO@$vM(0QyY ~&gyK37La<D(1eazS0H$3AEIj`lAJ
8<0dI̊tơ R<,1eȗ_wylg}9rOC+N'0Dos z%b[!y.OvolʟBmcyc:6c`}	.NQovӷ;T`mQ1ez$fu?Mx7,RQla뛞-<a$۸=[\os2jQ^g)?nlBtcE{t%Uk.W?.6ϙ_!9FYH5\rԋTK%Z*S틵jT~t2\MmɚV6$mj_=4VR7 RCQ)߯%S]ѩZ9Ęl;o?Z?tt%"2>/-*&vkdbǀO+8Us'8cRë%1Wء;ׯ2:?-]p\
3@uѬiENu>m!bzS\`^!$kiS~}wo{֠n߲jpvlNfpg};F	ٴ٠b: &$:#r"š%_hWgb+'xTdm	h"̪vr6NڹL/{^MD[h tCIM='[̧}x`rc_hU<^O^P:+6oYlr7 #+ܤ//@PF|.
^R5[cfw!O1cxR+F#hy.o&%!WN
.<,B5u٣lJJ`oxo<9=>Kޥ6D)9*Tt܈yFEg^΋ܜV+aLӃDx+U;UG!~0:sFzK}DxFi^aY*Y W[vCJPakkl`l! _p _r.I1gQéUT%s)
8=&Vd\VZ#8:D%vE,ƸU8UŎI8`'۾\BW>_	0 Xh|MGKh (?@4HCOxYܮp1يٚYn,?wV  'z^WPz]V,\tP	x̊p/AEdtٶRhEAp%\1WJXmS|$:[v?hrI	Y]7gƝNعx#y	?kX4ξI7<	_V"f/f{)=KR
 _nenWZ _zm/+ C\&bkFW|O`vXxPi%g"fk	,'DZGw}6I눏'?#
9O1z~dx=p\ꙸǁjڈs?=[8SɳbjLgJ =hc2,=)\BOO=$Z$؈GUNoԁ"6}APfim*M0 &M<t-|	r]$K{KG&]5|H)en\Rn4T+49M06Br"\-?LV+'ot~S/b9%uNV҅yi]mu<4!u>g8_jOcF\` Mc>,n"7UKiX9mX	@BʢU	\U<+A\}l6CbZiw[349*qjot:}AIU>B?5l+9AqHX6ofzR3R4e3M݄+sgfF\yk2WS[yHi&Kg+~I/6ȺK;9JyQ˹t2-p"~'!XP$vY"]axRtŴ#8G[x׎~@@	oj:C~=hJ#I7jxz>śqzʟ]zE*څbϥh\W)?}-vpٶtE6q[ɔmrkCS[3kZ9<]`ga+b:޷LJ8\7CYݜq2]w4&^eesE҉Dk3%͸m/ĪRLHUÆ1-eˍU6	=m,:f4}u:9+Nz;TF"MYo}T֣WbWg"m^t3Z$	& T^OPuu'λ^ѫԧpz`nd)>w`-oA.>D*0:z
ZQas&MgPv1UHnXb{W0a(LG,X RbES⚤tEkbN/Y44G<L(,?|F!C+Vb zz^g{iX;<:l[%7q?>tzEv<]
~BP탣VL!6a0YFt/ef bh m ;`L:"j+ ~-cGK^յXcL3n}y8L=0M۳uMg_Q[QF:+ Ǭk7 k)kt8L|pUo 4`q^UU-##YyC.*rf]v.G%{dooy'3 4`4P"`Yk#OyNG~9Zp.Kgb6Jcuc;$Ά._AY=-Ϗ.N昛l||6g0~2z7¿B%," mZhi+r>lv"O;ͼ@dJ4!Aᆘ5y :&uoJsK2J(\dȖDqAÊhq%5bZ!NL⡚Pm>{j}R<q,TS!YmϞzuxYba\"HD'`:&\6RFľ[-#S
QcQN's8! %&EIetT:t1$kjKXh2&kN2GL|`biByD#=5g}\ٌ$uj%8]ljhjy<|=1|Qc5s،Fa^oJOt҈P"J8DQ4?7îifled˱咥3Ҕ^enNijbthI#K<hӎUVlA`+`ID&c{izQJEcQ͆aȑ)<{Iۡ@22lr??@o6	,쯪Jҥm}v/-J%$TgmlΦ5v5>1&TŵGlHHʽU2~)>O*v6~#Nn:M'$l1FTc=ȉy(T h?[P9ق_-]SFjh[yJݻBlO?tw
B봾]y$6Wow@O'쟥pD6MUaRyRc|-Pa\\)V)@BeDMp 8)nadCآ rRx!^!	*5P.*Nq!voK5$ŕԸ  CW!YL2Pr91C/ѐ&H`^!h@}P`g*"pI[ÇK=|wmy5)t|6s,[Կ)27Bt'^pnnprU?#ppWb(Nu[SLz%%`}ٮAѱU1)ۨ^txrH]f8@ֲA(,5(кSEdD2K*	GJSDr9 cA]yKKя6&SftfR-)0 ,_p:n=ݞ@8XDvHm!aR[,CU|U^)@1HlߕUUz2	4I;nXg&
ތPkh`aeCQ~/2?Qt.CT~80^i]тǸc->63ֱF0$hR(adblI	uQ.e
N=|
ҭҔo1b64U3GUZMB},=Rsjxh@63lŹ_^Pv?{uU樤 nS> n~Kuਟ9(R(Â$uCBp[|$\1BAXh~nsz/x-WU6not֢|U,%`:7(nEk<~;3I-1\_qB끰ŋ
^+B]j3ߦSQ9Ly5llRm-jt6JB{]&a_ƭt>%A P煩}!D뵨(.{r!v!d=CiXL!0!D/觖9L!P^dg8J%6D0\ڹG DrH^@,DDTH*{'	 n,b%ca/7,pԬk*/IL[p.H%xÀy.R-%O0ldg!jՠ~[YEk|L)S:K`%@ da ,ZC(1mcr[	T~i\6Ӷ;f\<~<TQRcŰS԰r`x˗=a-Ռoɇy΄Z&oZ4I#^92(%腡܎
SZmsYL>ece?;15/A3
}b5SA}cFsA%6Q>G򻗏i*צE>E>pTE'XE3(HTEgƇºiB.E(5dO"/\վdإX`#]JP"Xh)ۃW'Ū::{)&]xssO*"sSqb4#Sjő:}H2Lf4a:օO$5L4{@7K?'-S
y:l^LPUmv\SrIԥ_׭5*^PvBP)%6i#[Ov:rKKO)C궣<*]X=zF̄(`Ѐ]Zoܶ".*HC}/%z`>)_qɬ	Lɍ*x`UWaS{Bo%cPL"ZEs8EE'NR@N:<s6>"%yyy0#dOMiLGHۓtTAlS5n-$(LtGV2o$ocRi${>п\ߓI/e'RZ=g!;A5kWn>HmZV<Cొ_; @`,;%΂폅:EtF/|&Al#IݟFؽc
:U!WO~h^$$;ho?o~~BP?<{}&]1y'"tm-,nucj
cf' Z:#!ό2|ʲ)nebR/sj@Pq*	'~d^5qc6:v>A`41p҄['(>$j:7Wˢ˯
jX ="+zԂˍ3rϚ**etp[`+Hn.$|-pS`oA reLҫ!Sr1#'RQbd^ρzGm~[U!1q7?.XRrzߊ]/|4uEq)]ۼFw9sʍChMO(6hPfsO`;ϟ:8ԅ*|ePE?CF6u	ϕM+q?@5Rg4b*[T,O[O`ej#Q;oύ%ҖP{⇊ 73GR4Zc*J9>+8~+?r\SxR%oU1C$/t	rT$?1HwLuڈ&bbߩ[ܭ7peE_=׋^Kc*'n|&&b(Lɐs%7RwAw';7'~ `A4ZrXp`\[Iҏs(tJ1+IǕ.-lZF}V:u,4}*-8v6uM~Fub ԍĞNA[;ܽM.Gd?)g(Jb7fhj
hǷ @odđsL/XwoЍ1 pŃŊax6ދ\xA1	iz!1jIPT7U8
pMJA@֞MV<Jo1R>
Q0ԎxEF7	+%G%g;nȂ%']JmQX^f?w t]@t^Nv&"?t;"ʐWBCȠ6zecl~sI`O9jK/W4@Fqe֓Υ#V--edw.yuCT]IA	fT*ݹBjV+-o^v@3gHܹ4ndMhEGo;b~e2^#X-rRZquQ]y6'{'Zg]|TYo*y0"bhh72y9e&oHX/ٵNB'eE.	8<4a~Jy:U%TLtq* c'14#览$1	_oNfb_sio?fv;08JYUZUXժHȬ*_x3p8XTF7o?doZX  s7N[qJn`(\g"0ž'G>$%aVnu\?givpq^'
|6OmxȋH@ղ9Z,2%T7Ij|"P>|4SBv	wޑ%lkTLFxwBn~IIwYV뺔vr%(.n1|o)Y*ϾV&PdePp&^[c4q?:8}K I@[IzF^
1d,Ͼ73D)Ui䚰2hW+jN2O-I50fҕqSm%ϹWmop_'敞BC:,PvUYE<kt^嬮xa:#2RCĆ|lagy*uΒ2)
ZM(hs|TTNp'?x-嵐Z< 4}$ GFXsTnu*4JhVƊ8ⴋL7SWPE.!wOšk3P:Q+?m0
#w;&y[erx4Ry'oN&[Y Z YFfň}W{n	i;z[l 0?a?`<nmR\wtֻ0xʵq3	vĔ:MrT"̲DP[jj	4jz`~^ҳ1,[À,U5!Qz.қsj!6$}I Opw\ʑHK"`m*DQn}(ܷW/=p(hrUy¿Ho IhKO_aGզ%ϫki5KxHZTQKADzQJ(Y[N.*]ٓ<\8}ӑc57QRT2^ՇE
ၔXݬֵ84
]
|*;eݩ@VC!0~%Nz֋6G>	UP%ݚ9Nt`6,J4	SK3:l\K9Sӡcߜrͽp;\<k+s]vyn++xZи+u:ȗ"T+( Je/o64nzz|Ţ ͟O-wwAܳN/3<|e<ڢ2X-6YAp/4l-v y(g(lB-Π9	*AH0a/9lBI#}rI`87uxϤd\Lv{Wߡ0rGrK{a{`u_Ʒ#1:^cK=miB`XXy)vc$6#,
u?3m6@Y`.hai^	[
>mݚ`ΒN$	-\fβypA/H*jgj9:aաOnfb+D!1#.HŪUǮpju:{q(]=JЅuXi1aQw%O:DFtkKǣPB6
nK΃KwkvsKDőz);~c`}  ߵ S5++#KOoJLUPԭ 6gA*F#
y{&Nxw!l
p<;gN%|㻬Ӹ÷6L#ua-jg`NSN;xKm}V)!|tA-YeCi}<pj#f1׼G:XQ#K;^	6QO+=n݈{8،e}^Cq6%Z^y|L#NRʥ=. ~{+-wv	2x {8g?ÝݽwSo?| :L{aRS.EŞ>Os&Zo6v(:`vEERw߉xpիdClm{~ljt;C˝ppva'	"{R"_7<ۊn1+aݒʫQ5{{at*VDbĞS'-OQwq8g< ZI r!GU*p<^\ɕȦTTɜ0]vF8Ym؍CDݮTȺ,Wr:S	t~ȺA.'sT} C,oE}C~V
;)	!Ղ2+´ʢe7ٍɝ)b-랩Rx})~".WHVSc	{S>Mc< -Equ`PѪs0.kpգ	H͋ ;%"#{Q{Qe|m၉,Wpm*Su/}ퟃB݀\KyEVn@vSeb _=ן^`>~`ѯ]4{K1oLYˮz[:FUpŬ>^knp-JA:Đ oP2\u	#qpeE^b/ElVZUSq`J`d dx2yЫr"-YU5 H78. \;[ڳTm/=MYY+(K`DGd+hr	H+!6cHF"2|x)Bu)Nl6I=U<<DN[]yyCYLv;h\N'v}[+bg4kqm1/>f Dzq]]VSai"G4JR1hI@UUNd]Unc-sCe<f6*jF#K|Ѭ
:p|j֖#kU	dxdu$SSSqjǼ_g<6qjA擉	棛XX+;<Ղy]WO;S"6E1o'O|9#P*@ƓUks`7B6_bhЖk){ٝ)VP/I>jm/'0:,pi-(#N'j:edBp<9K+ۤ @?7Y`٨9T	R]SsK$;` m)`I-R7*~xRw'bQ9A]QaTIao-#/Sd7bUqH82I"C^\U쑃(N$+\c;Pkjh7'xB/dȀ+m}!HGAr6ĉ,1Pb_2uPx}?>;q3>ܞJn`;3~$6ȟm+8E@uIņ*Kboc!ӵ;n-9X³{8znd-$AbZH
hAQitP['@@ (s|1\g'h`Qo%rɟX@NXRcoTO֫"yX<v隭6I~Zoa$pAHPw=l65bb&AheGʳߒBF"zbx]t1cuxT\px.b5	_@Ƭ,=UCJSf2X&(L&Z 8d'*qu5[y2ew2SC1%x[YɸSEX󻘪땎|	_\TaH*C%{SOi"z0Sp\|,p@|.VrC<?"-,kPr-[:]L*<c|g*DLiAB$V\^ECD#9%+,^Yl_Hn]X: Wz?,E6G atab$(HxD9_#CDSad`~P.u%l\#lDyQ	ѧDr)h 5DNtn0ufsRsa\ii@uJbO׃Ri(*Uk={V]^CVzV!ktvoawVݛV82v𽧟PrTd:LDLH'.vQ.+]-mpc+mLUIeST\\O9O4JTL^15\10(3^>Lކ;'POcb L*_0"qFlpu?vsLklw)\@YPo'e1\I(>ӭ7&SR//8C-,:{aT <)ɒJ!.IJ&~ZP;@ZI.Ju.h3cVArrQeIagt̴31Q{mwӢNY r;	>(*
ۢcKΪ@rhK
 Tu]Jwz<fk`1gJۇ7yc3.ol/V5;UJ}^ʆc1^h3 6n8C)/p%&<s7XK_:*^Q&
㍯?]Z?/_*E
b疾ӋˈUiUwTJqPPź&&Vy>Iqo,	.@h,t*c^s2~y2;M/',\۸u=|gm
%
5D^0E=#.vwl+ϚcH^/#H>gHϣ8Q3+AUj*WP@
	갛
Cg
w?뷢ju}k[J='БK&ѹ+n8TFujb 0zr"Iok/ΪwHJ;_kz밚6Lx{?ޟvhiVmvu?HzZ_Eb9&ehD'$c_i~F'Y>}/J;hH ?`j!7k0eRj?*MT\wb׺U57fZ5X<ͭ)kq:!׽2pXkAUc]%Ίk[|o-mr4.R	y	DUmqWvmI?-(Ǟ?llR(zdذڃzR$&Xխ86B9B$P1w@Ca]@mY%K}޵T`۰U=H6C6f>Vuw8Mm`.ID=CT MY)=?og+?q %9UsovH2jLg,4.3ϱyiដ'Q0x~lQР.Z3Xt1zUZ{Z_m3eDb<-zg!yB
 2Xj
UH҄ZM!X0~9Y݅b/+ޯL"诗AYoßJI1GV.]NLl,MQW-#Ō<1Ŀnø;yt6`vۜgin(/|>'ߏ
`.א>\0j&m;:V#W'FeS4C땭WW[07-6TAGFLu6 BjGfyQ6(2PrUPZ|H<lgIdm+=\zK-@Zކ3p+(EO`JqiV{4giF3~eځ/`/=SEtMsvg TP.#wHeieZx۠V*\;b39/uޭН\c2 d -\!7"fGS@S0kσ`gs&/7ߔ:a
i2M%r1|pjV}aesz@0K# Eɒ@U:҉c&ĥI3>4HG-D-8/.ش*%E9}^dmGdjo?g,i/ڜQpwӏ#"'	]uCno;Lduh?IOB?o{8i{N_)#n*~m7q[şMVyOc6~Пmh^UJGcM	z2)N-}dS4~$RtBǢ+o|]?g'Ň7)n b1?~Wo~|u=U>i"	AtRR-?UՎl7R¤2'j{K1:J~BuurgUQˊ_җq+6Ϡp:Nl/˽Q!t[:Pt7$RJڴ#5HU/]bE/BڊZ̷XgJFR?+&z$uQ#bK8Pf*Gr} yװ2j,.ZSQkKqf\~x'#*Al['
`VKy8-Tt@r+*uDZ2Ws:NEay(Du>cj
vqN`|uժ"xzPsDfF;cw~m{r~˭(dBZpyhDbM><zS&؞Y2 <GiNu	iq}\&7-i^!zL'flLBӝ,MT*b@-vF(ט;s-６cV{+8#J8-	Bi]Y:1b!Cmr>
=dkh&*2}QusU~
\8@n$hmSl=im４OTmC ĺc_8@k/ԹqF r
9Sr+L(.yigM*kV]Bk}ո٤ibFlS@85[&VmJTuS!/"qZ;\;zWP]sy9#[6iQ?p3<y}?|r?{{o+Q]pKW!, $ɮ
M<,Q-Hx4mD_'M֯A*8¸3`!1E$/a(mI!0Oi6ߗBYa/1kmS-H$NACBZn[ջ]bF9ś[m[ѱ:;l$I(Ʋ.U?[>\_ݓ%;:pTM⦦}I<
j,F/=`Z͊l[94eƬ|QzD1@qT
rklk U 6"tYcaM<ueB%JQnb#>."*Z9EpI2C,_*iY44&Ga>T%$c6"3ȽXИA9Ca6Եa5iBרo&bϿj\ZB_mC%{־<&A}!TsdfGd_;#5 lOb;#Lu^dk|TAZ73	凹rӵr0\]D"jr"-9zj{#T.dZ6
khır9䈐s
3|b+Qգ!j%G훼YIq΂u%s/zm fH:O۳˗Ұd۳Y:eOr/xA\}@ӷelYbXnppQm9$\TTVblƧLl;%.ˇ	_M^kBr]Xh8ԼVSw(z=ysw-`;0L//0q.fcTgvO\z&I]-|VfQN9vK6ӸfBZeL?IKt}QvB@'t},K$IS(S.SgZ 	~+Jm6*HE9טBTlFTF ntZ@aiet?F& Db80க@r%7:(So`jbCF*V2`шPKb)>IE!&680br&Jpyn-ƦTJ64hXwd6,<	nfj ]m]bpt.\)֫b.P2.4$J85p[I1 ޕzoAi0QCD01K_#yl?U_1'{;$RJBoZQAP<Ŗ'DIthe:+e'_3p4xeS`2wnk'ޖ/O;*d.Fo%|L>Gȹt7||L碆tOHbǚX$Uwx-4ACxA{H2]Lߚ<Mb+/W&~cUPhj?RPŗ zHAt~ MF}T]] u
v`.k%q;Xc_qǬw67G9Dz,Hŋ Y%8y^D'4>aSA0 a@ˏz&/H\3ŗH$x_fDdآ}1@ivI&Af,E;/P^n}+|~ݏ^ifѭT1T.օ6V5N3ex )Dn#)#V){W,ZiG)Y"t*CܭSP~Ut(FF$!    uBe+2E[DzAmqo>XZE Įσ*""֌zjyB՝Y6Gi6Sדe1gc%c=aqj+!c	уڬE$s ^sõKݶ-8yZ z 9AS7+hq]]kx}ƴ1/&u8I>˩IT*w[򢩮 eBB-G,td]\z4!a􋛞p˫:Q76ί ?vo*x_E9=k~p=N4|Pa+Ż5b&ѼDzqy.fNdQ @3߭CRfA[Z6QNW6X̟p!+hɜN«{d	|>A r߶=$+'k2վF<KXg߫L*o?u3H&AC$
4ף_&3YWqʇ&@m.DO.IEUϚ]Щ. FtL6"ڦFx4+8]Vz::MU_&\+84ɢ9&%P~`	Y|\aQ9<q^\cKCO̘uHLb~-HYuOR+/Fj^w/Z𚗮lHmG8XĎĥV7}GH+J3:6\aWuw'vᕃߘ=ۆX_Lgf%_%ԛf).Ku!-2%(B`ecˤq`>{Xf14>FfmՄX[5MBwlMUKI4i֕/Κ1v1AsIc`WGbLimϦgt+j*yG7-5D+r]&P|bK>:%-J*.gJ{V[
{5fjMt*gaK='B/_~f vͱ@q,8Q9&S&o)z9i7Oe{+i\v8f|oWE6Vס)kMNd+;b=K Q";r:
Yo3W^z1]FFYI4	aIW~%8nN5|Szʻ]R|$|[bP>yTZ
5nk6>jwj+tڻbTNvkyij6c1w|{*y*MBh1$k-%y۹BFdO(i)ś.qQ
D#$y2b
OQzP+{:eGr 9..Ol)slGut!͜.Ĩh
E?T@	)ǻ2pۚ~9^S= 2+T8!KQ6,ȗ%ٛS6	s3~;BOe;@A|bnds= -Ѥ"EI4Gy{"|]'.vvoTbس\T*NnH@>	2,[Eg#X]?Ƞd~/뜛QPs)fX: 
=ڐWKs5dP9mXaF3-U'GwOY}1h[2ҟLn0ÿ1m%yj* -U'XPi]gngE5H|~V5kє H2GT=V9ҹ~ۅ ].Hζ@Y1kmn^JvVi?Ud]{L>ˬ	.N\EY|370k43-jp2vɃŦk>zYǞgT>T&p:$"GM<<o.Y8tF%
A.kۮTW#VbHWRC\jǙt7/J0{q"6N&Guhzp^|~-PcHBg*YIry@jt :]z#dV<d CFK8ta(ʳMO|#B1% \KhT(oVKT'oSU[^B(=p
U\E@U}4sEvOOs	/lZ/X#Nq̾5ҢaGXMyv
)pM
pbh,>7lKiXﴴw/gv͋(ڊ%<L0rXߒJ^Ԡ:PiZ9?m\ҕRn@~Qۦ.D;OBB#H5@]{ޔ[$eBEJo&FRMh}6AQ=bu/8ǍchCR[V_K˗VTX^	L+pǉ9Iaoa
*ڃЎrm3q0+!  {[6vbذO!Z1\Vwfz
<FћO]]q7]nuH"U|+`	4@'F"Rk"{w%^^9F,rh"ds%@![;jtT';HbI #&=
xIL+PO kL}2e|#ƾxia=r@aohγb}fj۝/w+Ҋ~+V+{Z vz|)d@\l17{?ka1o#oPvmzk0X.@-EcâsWGk<.Zv] }9̑$o]їzWco)(0c$QP &RHnOrw2S6i4 nt"Ā<J;mQx˷Yܫ޼h	Xf黹jX6BE`>U3XNyY@ (:H8+dBʶuЖl!@5鶁vuȘӢDxu $jzo))_V0*ӽITܰDAd;pec/ȯ2D	\:<-G&8y_5'\$N0Cz&rEIPB	ϲo/ H8E~']zď**/B톺#ŢC5.4Nnm$4Aie(n՗lT aA3Q2VQ@Wp迖Qe-x~ަEEK>4F-o7w9RmE*Gc7ʮ
@VuLCSO\ٌ7bup`$m!MF:,ZFt ~dG&c߭Úϳ'ZYƨa~{7DPIlӂ/ڀ%daE*J\㰌k2-O8jEbյ8a"@Nj-Sr8 !m˄r
v?=Ƒ%wǤ-A'7%7$&f2w$9]^Vf*Cez+bMZoS6O2]E{tڶWǔ$^W@^@EE%rl=vͱ.w䫾b(c{~˕1SUe]42\9mP+¤»P8Xrk&xļa@?ڤd˄c7u-j]]󤘌]'W e8Tm6ri6wmx>NȸoJ{gO%,R1ZR
O$rZˁOQi,%q
o_BNAIU/PJo3ծ_\yuls}i#sDS-~sֶaeV<-#D!)^K-@[4=hDkщ <Ztk)#tF||
n]#ҠTSi`c_^z/`i\އ=m&E@C!>3*҉	bp @saGX'u	Ҷ+H3Ē\X	vCFxO3[g}4Xe~q# Ff$[D0W ^v @8{XM-Dudj~2SCeK:	4,8G	D,`IfV$B~$\@U!BY䳶 WRa6|(PuV@ƩKC uXg|2r(kO`W @̞\Lly}kZiHq"]pioAۈ.P(oТ	-Il,
WyzHXv~Yn2tKu˾X tm&wY:?,ϋObW$1}N'dbTlrc"++:yC
:X5jH*yIvk2^gbs2?'Ï)1ۓo>kަW/.x
p{Y;=@]Gfh"zE+-bM-Fߋs[db*
Q
InGhV~ӨrA.ҿEOWU@!SU_C%$>P1BO<BǴ#y 9%ij䖟ә$W|֩&~<\ũ<t(1h@L`<TʙgB,&~ʎOn=S	KK¨HPtZ>Ug1AM?7"tZ-.T~ڤX
GMKb=:Bk#3n[kٖ
ٲGKJڈ5|SKv8:`HJ]6k5y7&2 Tl kdy(-@;94͓uS2[+.0*q@=ȱ@
nr@Ɔr^柲a[c`XidKH3IR9i!v0VJWpC5lz'1J$DtwhRΣgOHAm&@V CdȬ(aR"$^I4$јUVeyym yՉP}ĩP$R}%"AF`1z6 =|7<ftCMXѯk#$c>PȚ52$ikn{XŁAԸ;-:9#IsZChFrP H>yPNs(ߢ ,U+0+v͔t8G8<pjUxlu#LHkZIh\`O´yv+r,f<keDj D{28ó7D˝IJL 9gUaܖU]fsjsu҇bKǎMQKi-0ΐEJ8`cW|%@T%e]![2YL_ہ:k Aqu)ԦHCqXaUUs~L.+"Cӡ.X.y0rA`/%Ú)^؍]le RALiTKg\VD+'R&?y] KDCg487?M9_Υy(-uRޏ;v7w~ywHDh8:"};&JC{qpemurWdVDvxӿ|ِ'Ot/>ӳmT+cG@xd*0>X{iFu+J2/gDb~1pMmp.+~y#Su).fIP"Q?[UXoe 2
Tp1sQBffSv "9cBXB>zWyX`<&訲hHsIpVW\<F /jK(Wz61)d0L<ǩ&[s+߂v@&:2<։R߁B11JevGuX"?d*lxE'WY\Ahl;6Ɏ4I^N&Wx4kf@
wib?voC DC'2Xj},\?Iy)U-V.GI xrz,'c5vܤt)b8.jN;UxM	&bř42\mI~6Ml:hh
0x2jmt9~5T3벖*T,q*_鑨\t扽$V('	AkQތ:5ݍuDoN#E:?=/-{ߏbF@ų6Z|HM9jR
(Ar/_	[!-J}cTE	|	h񿁶(󂾓gQ^I&2X:v?^^d7E Rk/LFE$wcU	+ݤ 숏j4<]sݽEJ'qhzW.ZNfj}`ˡ8$7q؇M)ybs8oG^7FĴp6ٰ^yWus/ALvu?r1EQ2w=-Br;1쾇mfmʔ4貵 u0Ã%	@A_W01e `w?RVrիޛw}ƟXz[c#og?YF'kaEJa~,ZJ떲0ڃD;me~zDc~
!rS9~X(U/;LOX&͹dhWn`UDU-^t2 |syٸEU=YDɑXJa;Eq
	#}WS"dlec(酝Z%KBDCE0Q0p-A&;U0?e_p@B@IM@^]q~Vv\!j:ıTtmtC_WztS~(REpT3j<-+3g	edgH9fH7֟|4h4˦5Bʡ)y (TaqA6̴([5骭]rgI:߀-WQXȐS-h_Mz∡cVg!%\~%Dr;eA7YI~kd-5 r%w:WToZG֏=3#j]a(
7 bWY>i=1:-&Na|r(?VuDxVV&nUl(w
;Y ./.v_zPC M${#ܣLT&S"n^l]BgcvEEEO/]N:<"d&vnje`Xe|$^d~ލCc#3J'#zX.bWod'Q.בi.s !wsg UnY H)qX,ntx8mU(^J1d@YzO{֏<wdp.mLQB-eXfA(*
dsxLЅX	&Dfx$lYhgRyM Qg``kO
'ZIJGm$RS)*fF4!=LR4_;RU=ḰQT|cd#Ki}ݙ%;!b!N"ö[O`by6=biv藐*JQ_4?pݨQۄnAqtl씄ÝRE|b^U!L]Rմo$H#LMQ%asfh@~>FJݍ7(&[ėԼX>%ORZԏ~g&qAguvb}o?{v~<ig_d/lN(~`*6rEhj'CtC٨+h	oRnLK51iF&Ĝs(vUkVQ?c=lwi(csz6AbEaAWnNypXx&g)%˧bWGb
wzϋ;Wx}їNtmvQ/[ UP-xZy-tɮ$3za)Tg8	GGH6WrSߠ%K@i,1U&.4+Ғ1Rk0;}jct]ŝ\1NltG][V[pc?2u)Bb٘إ_ާu=}r9d+t+4/<AdGJxBx9yWL!+xƭ4S'Sr.y[0\E$;aPFpjYL`%VZ?8sKj%O 6	z1a8]ճNēĩ)V勍)p&;U, PsM@W]Gr믭9y	K{A
+Ȫ>fhCf(h#W_֞^CU~Y'EQfMqEλ5s,Z`mϖA2.%Tbcoҗ
_'	iY22$(PQ,8(:<c.VDiC$<VYV)$xHr?3)fBtTDQ*5:Ô=(zr>"5|b4R:̯9,|2`N+|ek%>'v8/Tc]tƾb_>BP4N3.#XzVM#1-Ox_m؝e+}ǂ%@KQ*n>zWh*xj=чwy;$z98M$hY+
awn چ)=@hslvfAwC>qx_ZnEX0`FRcb#{9ph6aV[9BVbNo/Y*֞zb	tSkºs,K3?ت64D]?X~m2xHLһF)YR&R~F:aX}ː*pJiI.k^dgf)UUyqaUǙ\]f+sHת*FVlaaVՁ@=@XwGl'd
~cT	d莋ѠN^X-tIהѭZ҄4WL}q۴п;PlX~eD}s뽐|×o8ݻnyy"OT,-XnbCct{e6[+CB9IQ~U<{DG<"E1A4x˛o: xdhyLiP{w<(ZPk2N,G|< /b޴htC"g$F@{F!xbHUhSK]78e!&Oэ[َD)!![5Ldyr	~SG0f9 'K=t9A!'YSҼEwp-qѱl/v:-bon)NwhW|FVNhzeSImhVCC{f:%^+<꼻KVYP2Aj«yT5"Zda{ 5,{'ԬLtsWE2aHDI=et,&4DpzhiZ.s,Icp<c&!eYR#N%~(SZ e)'k2Y7IzJ/n$boPs&z\m̵5$/ʎj/FfC9|!)fE?K8c:>9_Qε*`N+*Aim;lZk +#:Dn#2Y¹M@jJ0	1Ac]> H^=2HJBBuePԾzeicBLry, ]f	ƺjv-#б&Juɘƨ$Kf!J	~@7F=w1d8VTacF	$i(
ziiVLֲb49n2ԴdNv:S|Hۚyf_XvN@Uڠ;t,:vr/S|jB:u`Ƽ%׬cr?Ď6	6U\&ͥ+tukn8Icdsn	3ҖG5ZA3;I/:Z?C~&qGfW:KՕP[LmE]!`F0B:Ȗ@1σ#+ACVTϋςgW;db|JըE㩦r\.|}zr,w;$2?ENHDݰ~3)Pܺކ%"}#w|E58\.&6\#h5#>r^6Lȕ&B7N1(b_K^ˌT,0g=6._@J9E{/O5
+"7rt*FaOpZ9,f'?@hbf&I1G~6^GήZ]Lcn-v42:5n 6.ƝBp'3ebԞnpN='5:kj%# jLu*4t߾)+=aW%R-]ҽFE) ӽ.
]U\5*\F6?`;%Fa)P{'߷ڦzFZx69C mQ-4J|OLSOgSrv쩧$4AG|ǏGb]=%<~Q*DGUCtD=*D[&	W[bS|pϝz P2誓/OJt]ǹ@VMxU~@+_I~N	^QׂU}'k>jzꥵh.B|şh шhx2IΒ.ν[RfFb/<^q/~#ALx(j^\?9;Kx҅tX7#LLmD4|9~YR$'I '|q~Y&3CPb6a0	2Dq Nĺ1VK'pӓcWV8r%
Bd{SHoEEq{4.:wG^U@3ОknSaHvM*QITdFI Aau:(:#*.8?t~Dj	wl
S⳺0|ӊw*PRx+B*4M[/ZByآm8R鵗*,Y:8
#->4_D&pQL6qw2IrE$Ȝ>dj.V1M*"HR~<CI'`=φB~~@fֳ[ºDrS'fzYl"m~d>T!ʺD4ۿ=:qkm_V[kkķ7ËG>q[(s\Gl{cdb]߇pp`ՇaX=`.؂spcEGIS<O;.'cx(ǓK(;KDr+k:V	a`g_.og538Um	W/+^+̝s݀z
@,xX~PqR$Xy5*[:f/5ouK:wvjG.;2	ܚXW,#;ysz%~%@XmV`>y`@0L_m0%&=:Vn0qS e$U`g[b(yQau%+d!"Б?4ێoQ|zZ$Xta_f+AH8y(Wu/ݧ9j|Z>ԧlLNtK!R^90ZOB>ݺR_J@b΍͡HE``p__eM\ǥN#MAY-it`y!,OOƀMP\19HbWaǞ2GxAߑ.zXL;uAUQtEBB0UtU'ZOsue+7oWjlc]n8xtHa;{ZDJeScj1@V.<|h0:r$,g}պrqu~v>G K]A'i{)M^~v:d҈8PR'9 Il܀}Hk4mZIN硜KT`PANxVPvVUJ3[,!QYK]r%_jr`;z˺CHh7S+\-߯&_7a7I^1d:˗#:,M*[;!jY6gLŬX<(Uu)J2@k/׻×{]4{lR5E;G9}z
ee_ hPHN ǩ֬o.d`BM*'{L3u)hWo}]`.ja[%/_rіPDQ*0[h0I11)|X$^ʆ6GL<y">
`̗o8!^&7, 4n3efތ0}hCKEs7^>
K^5針`I$6-jGe7mG^hA&sQi	ڟ叮ǎvEN%} wrk&K6썻jqb1[Ǖ3$&Fg&^kȐ	<2_UG
7fb^1pPXA &9 nk]k{]CsjQi$]v[ҊC:+2Ɲ0Bԙmp*MwvpǲTܾ;`7>.;E[Z
Y&;ۙ`;ج7fVmP=qlTw$1sAj_"*bs+<ݜ<cʬ<]9]:;S1oH ]Ҋ}TYΘh*ufH6Z
r=
ldXQT㲆[Ҧ3(.] j'I7_!Fѽee%DT:g$4ڑˮ
ƒS&xNlVrp9z||2gY:&b;`Z(bSL/G]} ^u/y֗IZq4Aed!-Wd 
zk)=,v84uBd/!}5D/`Lg
\.7ɑ,IرG!l'XYB,doZ^qoRH.fѤ}AɅVX>-i?zWHbjH,4Pz-@Qe/L(QmaZ18e\M8ݤF =ϒ+N]0zWN![H>xhv,U0aJQ:6lܖrzASW֮GE샥	T"@I9$93R!`s쓞5EM{cyE.{8g~H[zm?>#fXpE`ݓpYIH8l8vҴ+HO#*Eb^`T)*Dsra/z'߃=g*&Bp+<`ȉ5:V_]+2H?W=
5m`OZ1Ce@kEZJ_^нD|l#x@"TΕ+SEG .Wo][_bI` /OPݽ҅A葘\(|O/mry'){ʁ Q84>ί e[%f#]̳^4\oŉ6)h/3k.֑I|JE@~h㌜M+AǮ(,ǝ̓[kH61-U	=P:GW/E}7$۝!M+I]8)ڇI?j{6os*H)Z-qCfBؑ3T {v[ 5VoO'>ksIYj.J&阀cXG1OMxؿ!Ag9fB*0HSifx!fZCF,vb˲pP..޾XNv\w:t|jǭhM\A&]@k)EV^l#!dlu9>g1=&Y-yV Vr_'[WY6O[U:ZL[@_{Ʊ$d0(`y3O<l1bV ,߮~TF#lg/6~UWWUWW-	.YNn3P?&46p SQ1JuJӥuak4x}%fUAVk[3,xՈ췦NNϭcBV/	YCAɬ7'dq#m	[iwR8t0>mX$CV5P(:Y8jNs}ǣI¹''lBuЪCK-Ma|Yzuz[ӁǇz騅2b6̞U"<q=Vw^hjX27Й_=l.k@"~O;>ү(X8]ZѤkVj:G$ZuxH<(Je|pr$ y Bt&FlaPb2U0#^PEY<ps=xyj $.&|gqL%:ռY&+jB'2N_:u nBFˠk#gZes?[	7Ta춽(p6UhJZ#z{%4"A/|0y	߽!z'5.EC]y&åĞܗ+sber}t@d>SITD5g=6si?^re<Iԃ3OƴVO;RG-r]*՝4yZjKa!?/ZTĨ:8VnyuT/}8.yj$Upma$~9͡B|!FZ(Pg`'y%AuzҠ|-;]kr%>ByKv^y!]Lwr$"%`1rź^) 6֊Z$}ڴMjA9DM/bbi6^!
`ȧג:nw^l^}`gu1HQqePafN(IsBA}0N5G$W_ߘjw_-J\D!@WpK]#_ꖚem8'(SIH#0C؟'B6g_bZ|KaB'%lONie~F1%[U{,rI[Pu☦RWxkpCyqMmCul Ä'IlXl)ݚD/<i00UGMiS3r"Y~M2HCn2A
=[w)z`[>
$4Rt	|Ӿ&rF}ݛ.=Jo"YLvxуbÐq#ͩ/M NgSg7b*fg?bR<4CZB+CX@&%_QMiY4QH3F#f3|ޑ2S]8b+;x4= 2h_E
aM	?@S7*֠D̍kYǽSȿ@++}H7EEz0x͈܏P(v
4=ZH% \ZH!A!fx+N!e+)KUw(m1FhNd_z;^w 3Qsgp ĨF$Ohn
TFCfcBAB:r)ǰ-|{|hTKn5u!YapZW]rTxG)tQ`j94LCl?& XiU/ɳHSɳ!m0~# 2(+ToGBS&'G`Kv>\}'x@]Iǎ<qWpRGɨN[F&WUDY|Y7@]|&%)E?pQpB$S VԲ yZ)Nd%N剥R]Cp'_@8>L1,no˕Wuܝu+(Ӊꓽ+W!Cow3)E`/e%T
SIe%yk.˨N{-_L, }_|QBUP0$%[;ihdRhTC̊ڢxjܻETE"2iYQ-cL 8 [my6a~%L.Qy	/Í *!^^Spd
j~	VIĉ,̖)LVp{AG@٭~mҽ^.zH+yӽh-38e`M(<u:<jF,:?+Ns~DS-n(#7BR+"S3#Lxf<}kîҥػ)|߅=_泏y[36B/geq$Y'E+5<q-Dsp0$)}b
Т֠x98n|(iinª>>,izZc5>a|
 ˃t G1A3`,r,Jb+woo>JT 	$\-t :Ddnݢ~K^j)ג
=!.!xF9}_Am_*]F%/tb`f恂U܂K*tX*"cދov^{7;L6MPT>JnM>;Oң6i_!|t󸍊\=^x#
H>NQX Cb"="N̶/X& :̞ƈΙۄ) 4b3A NĤ4[
,:=#NK	wIWZ
cfZ>^D aA6hJP`mRA	фۼruh nl$RUw!O6 ҘM--CQkC|מiq՞uI()ৼToCuQ<YoZu5=	.)ɻAooz4v^Bƒmc((tKr&(I,PF18DißOKa~R4{7,M,קi|_¯bWɲ+@ Zehwnd^Йа{%bɷ(T#"lskUޫ+BA^JnCnc-#Vc؏aŪ8<%)M7#bĊVx^?P(eFkNws`&:7 )
L KH p{,_bcw3
vԴQE>M4,˝ދ.N㓢ڵWWI8L@c7x9`py|ķ8B`HՅ[ӓjSRqy`Πzng^4!.7zWb0g9K0g{ 
EXjx02L`6"uІK:-;d4n<REV@t5	6"CfD3tS
<RIR
n,V(t^t9r8#Fe;.H <10x<gEssIjv:aRMDܑ[f8f'lY}iA2XuZ;kCu$DuƏɬjJEE2ۙj[5DQJ+Jeyvi oTj,q$[Y~jiI)q &Ao	r0%),tFkP䤼'(gN
zrc& zwX#=(<O3u W"#J5jʡ	X!]$q:޼쨗Ո5߬^cA:4lV[k~
H	ۆ57\u}.ov㲘^d<hywh~x<,DQM)rFO4at9[K>oW͗N0czB	j4)8 sUwn|0`ҍo K)G
o1)vyYt=GYho䢰R*pR٣U̙B7xdfĶsx"13`W-];`v`Zlq	VqUP#!\NBJ8ZQK}	߰BUMm[s=%̳teΧ/0rp)(L̋a	H<؏mmQu 3ݷ#Eʳ;b~BPDwȣbMV=05ݯNbۯ['p#!GB"30|!ʢsWx17TO %ػ?B~uй&ݻ?31Tf uL~8(7(ۧ&MKmi!̜N#nXrKZ@-"yŗ.(cnF=Jy*ZrZL
Tr'-Xˮm,lD4^xXO?;`{MU(k/l,".1Pm!ۇKn'3<F9iFZc'ʜZ~"gmT}$Nv8g*Pc1A_:-LXzJdfSWj}ȇRP*2"Ns-]whQ-!N!ᷜso;e",lҭj@ujIIEKfxfFI&7W NP3p:8(Ulcno[,Liɉ>] ux_dV:Z	9z ӶxZ*ZlЊd 19&Bsz<Ӧ3йm$S͉$u*K
֙ʈv(uh877n_5y<OAHC쳬2$Ieu:A=P;9(ɨQ5x.9ü!a'0^ѤT4h#Vt^<MDrƵNPKtCT&J˜-`Y:b!$C0t'5oþ6HT&J:XKCcqΈsw>!{Fv.R	F:&-o<J#[ϭc(TѸM%hYu{k/4I	!ǬHnX͊φO$L"@U^fcQ/v="Vs݆9M$Q`.;f Ta..:"M?0hp[߶T||Y'k_Λ}Z}1.bFc*]AXFI
^jz
OTέE<	IlM	Rv96V'	F˻l\fPdYF"=z%a4	RY9ZUfIu<^,'8 c>FQI?ƚ<IEw5_2BZ;Ufl{ԐZ.9Bjc+7:(/!`NQVyp=Bq-8y~^%bq/@hΘ_)lkvdr#ulD}EtU	Kj1˸}_zP(F\Е:fŷ$3 a0/U0O=#-a(|LQR?«7;ֽ=YT,]
Cyg:KlE +?iP0/#|a8sg>&ܗ"J>u 4x@bݣ7@W׽F \3^y	a,948 b7P'ӅG)fX:Dp6?|0ŹBʫCyz{wg/_t-b)e 1|!6 PttFǔڠoi03Mۇq Ɯq'^(8;/TZL4QFҿ3Ǉ
gE<և$uUr>ՏvɹƐL4O8܉`t?C0k_[Iuub
/v 	F7DO
\/C+'m[fYUXd
љv@]DMAÙ.eܝQ_z"^Yr<0q{pOK.,^Eҋ8K!4}s>s+&U|:њT _hTU7g66;~4b]kzs	ģ^C	+9~ݎrKߐX¡f+Z!xOwe㛻d@7^0W֎9WD;8A SЖEr_dђU̜V"~ ( BM!#mW_!ߡ5/#~v{rޤ0ɕzU7m\20eUVb-0Je6GuY~k"Doд6~[vQ(ņdUW;.9c_
f!*Fu9ݝH>@ElW$n#11de"ya^
E}Dǋ]FN?17c
.P߄/`;AE
΃@}ohKL%9[mՙO_c*tz{[A;N79x"jA>*$;{6p(O
q;Fڷ>ZIFӜӨu(F"hif:gt4%o'W|\L u/7".l'Fcn䴩8gq1]m։ƌEphCU6l|gk#_)ӉH@"D+pXP+01G,˭n'2u#]XN0x13Ip|O1Sдbzw~Tⓚb+!#WiR+1k|M=ͧ+0M8j
g^2 Pn°\Q>lm.Z9	R.>\_NG蓭^K,0/l`BrVe:=bc#VVmpl;gNnNjWTLU[aSrxxmrnI_䕧.U@H%gӳjo3̟Uq&Z  фJT`ҷ.
v#ؗ*g_3DFͽWow_~:x{j-L#t5Q} h+B3U^,xqr~<5gh3 8a	mП"<T/af9}Yǘ0skˢbhKV߼Y˳]lfٰp
oy>t9 <%fxoJ.C.U G0d7Լŏj-Ng	"7`HUleQyWCP2mjo#1a'4ԳvPĒ7i/;b%B,}÷ &scڇt^$BNy=n}Iza'ۓܓP_ͶZb*R)Y~,ɓdo5{3G>1i	ٞc}5l.q>=YT!6hrm/R}-Q)EFt"x^S\@;۬9-9vr݆rjځŐ,"ӘM|q3#)>7[Ծ(ARrUfDlknFv3ЋG$lBjzXP:Jd t<>k:ذs^^4I.-\^NbeXv:=jFW=Gs4P_'N&mQ
$vPu\<3,N<)#JR0"imwf<!@2AC^ShYSf=7	\k48r=Is;wڷ\pK۸ڦ-4{%^Ag1O"Jc Z"XA7ua>ULĪHݷqcͣ@MzN/uFSό,fzp쟫g 
T*/B_Q۵9jͿYUޜ$YmkVϗ};Zh)R%gqkxAVHJڡ|,uN$-`/)[96y6;˟nIXi[W﹪Q5&9 أ4(18h2˕&ά"IVs5CUwҜLR	%M$,^z1}i#7vW2Klv/2:/<	f0\djB\)칃i;,4k%t0PO<pBPu*Gjssak%:W=Wr6\mr-b$ςI[U|<j*FSgsu
|(Fc'jE<(\S$0ݒnH)z~tn8Fg{uPE]ȯwDJ5M.09K*ý9^*ٌV(+ېWL|.26(ZFs,bqj-zĽ.*ktPX2FUC?ȪÀ>\'_1V00:X~[dWPiY4<!:Njv{}y~jMwQ7	qh~|84+-b8.Y&yổw}ݻƻo-{ݻx#$Yh&SQ(^hfO߈1JqJF *
<M<	S_NOMp:ĩү `ĕʴ2(2t17E2|q ,dgVZYOsv3=6WH\p2M{ӌ![@>ATQTKLߦŲqR'Z;UWԞu:=Ө3gn3cJwp"׶XAbp%HHd|8dI<DL~ѽh$0)12A>icC3;AKKᛍ̮yT<=L8oY*q3;R`|z(Y6HBܫyW`(ynt*s͗UғPdjj8LrC5(&|Ŭ$u[)Iv^y	rNI]bCu6G+`~̩hbpv.p< .1gɿa`P-Y|\z^Pl0ڧ>r ->S:bZrmD	7YdM02G=+M+41+3>K6G!'oG'7LY~xb*&p>݉DLzzcBParQI?M,'ؖOЏ{έJ<^n<$
P
'Tas̆p­g$~I
``'fMo/z\E	5Jy)S
!E+U9Q4ʞRU_`'&@ayZO|A|H#p1BQymǩp&o1;R&rB"6b#P>Yn*]'ٱlhǀ{}GQ;dOy0".W9My?Ne-fa<du&7yV'%xS=mNk.őPjTõ#%}tgտ51^aokn&i<?FTUi3M덵8z]~φ{o8.e)f nƴY-dd/`0-tuz*B}T(dFub$qr^~ =yHWeiVMǠˆtP(Ҳ:>FBy<ʪ@|	43uG>@\o۪sJG|,"R+r9YCO)smL&QRkkUޫ+vCqsԂ+}m,t,IB <IHq|Q ;;TL΂սbxmΜ5+,{\p⯑l^Sq` ~ՓP,gh5WDuJ>Lh}'Oح~.mLIt:EmsTt[IX[kU&uiȀG|F/<wR8CcAn-/!ꛜO}g-w	94[3m]_7[Fr[*2^45f.E~_;QуOPoԇ<_H슑wMvoco{l%jx~%XDS\3tb֦&l>m)F)$ې#ivM1{6RUv-`!g
/<L/ӟtτ
zD)k7".
S"2Mu)ؘs"&^Tf BSl"LjӺױ[Қ!Zxs4	p	ie/\ٶ++]1(FikkNrd6mj(x<<LCF&dOރdT8
&RYhM_ FEX
~6X|C9Gw#RĬ8HaVr`>DBo "%]7`'bе}~[hǫ#Qmmꙡ	[p0rk}w`gkbFi'1Jp]7)8T}}&ϿlE$;p`m\Gv]qh5pZ-0GɊeQZ9A6ESnji[k[Uݥ0j4qCl d$% WxA)3_PTF(aͼ "*vF<j.Y;ox?VM־̔MIONۚJ!2h2}7ۢLko_t~#A 52cB-Bl:xwƁHgWA#|V@>:ɊfetyJc%nEBVoRP`f`ceȆpa7gU^#Ҽmt6A~5Vm8WIˮz'V+ʹrDS$%8jIID94켡H|#3ڬl"Wf8[3D*Ă赹ˋ-%˄n9(#OOB@^79EE,?E-]߮=YMIG@H,nwTQ+7O؎LMՔ-Q%;5o+d(npk"ªۂ B. ]PwdL(ɘߜJpY]ym '3YʚP=i˦sݐjcyZ[;q!ﱠ¼VLAfU؂|U&[|I'rɥ.8k,t< v{Qj;ͩo]B>t:UKæ4C.WԺE~Z-PZt=亢WoCOE FѲC)q: <4h ><?QݕUy8ONj׶o/qyk*	0,Wɼ'pH
v	4O`|2Sg6CsPwiHż>n͠s
>?]uO[ekqAdI*mk:wD}K[=\AL,]C/݁s1 Mwsb3V̊6ZzѢ~V_aL'$ᤣ (,t0.;sMzr3skN|7ZUCtA{ Ԩ= 
	'HO,csB1ZԸD	>X/'ߑe2$FSFgsCʓK0.-,bDڳzO*=dwM\ObP/xӒK|<9Gj}Y+)ǋ+
ñȮ;n;P/d Ԭꍃͦ$s`_ڿsK?ưo-y$e3-ϨQp-{']j1z&{faXeء~j`!Ko&7Lc/\hC(,Lyu[{,hD#vfjMD3;8k֨@Tm8OӔ:P0C[U]L}t!u9FWr%֥#]/R 
ȃԳzrѪКխUW3ͩ-1H9Oi_e[`KP{Xv:;݃.W~z)}!3%6((N`{'?.90A`;HٸG6ߞ?$6_u6G?$:Jmxʷm_ǏV?_WW7V_?mw:	7~>~cN|㏝-xO=vϟV;WBυGkdgC55~x*!yZzػ'תvr١64Znho`	I
[訙mu1*IH:@S5;rdod$?z_N`AH;;1'l MD+H"@b/޼,٫,Ƹ\*A-cwZXi0L$xBH/	g;` ߳Hc,fT2X@T]bܳ\&QO"kO`}Dzn?|hڿu{AZ,C	P/"p`4a](1t;hrs~zJ{;~oowcnkc/tj)Nr0vŇ"'Jk/0^(Vag,*2+l39ީ9X5O[h>0ye :s`x՜&f5EN+,s!E7&(I>B81MK8ϵ~{}zV~ om$i7X`dMi#롼8 F
`}4V6଒y-lI5=50 96Au	c`yK^FK1ƽB(F>yޗwBz|n0n1+UNz)CPl+)}J)!d<^R\!Į0t7A4d6㛼,Ubi7TW.!M!tVHc)^e]en1/f53@,)yϟ4jL<{ȝ&8vmvd7kgrF<JM1\,ruS)G)?i#~hW'k$v,_wU6i]!ܨSOU]RuV22@܎sn;[9SѓtNf}WZ{om݀Goy1̗7|\kϼG*<.dr4"C>ۂ䨅S6 @|K1eSŰEgpdzSwd7?"o.pR{<EZQm^HP3HFYpUr`n?Go˅/vaj-B[?aSy?}Tun/;̻Io㰝#sY۩UNBzS<r=FQ]w<Š\{x	^J/!;
akV!}Mqwe<U ߼!>T/%ǝjTmSN8S8Y7uyCRo:c6ͦ#㲨.sp҄[reLn3jWMӯřd}fYE6Z>;z廓 irᇖl$qvlcACQOr"+'/"${JHVP.}ɍQ]8!fki.@y|S6~FV>?8>?8?9WϱzGsΏlX^/(b2z*اhVH> +5Y@̫>,4bUK|߻Y\|3G_=L"5]Jv{}E~1)Z^R	:"}BH6t(ݘ¸GWOe҄W^rSO:at?p1CHf\__aYp$ڪt2	t+NNe>~q4oO 7'4`x<ICT`]V!ci%2-")*3yc	 3cE7JR3Y#6)T>"iqtVd.$}Z}D7.
^IFVm4#w$[cv]Ƈ?D)}[YIa& sxxSnlSc	VHTz3EC..	YKfiۭERymڡ@ siMI7V5Q=gCW1IYLԜ]xkIv`<h}5\؛5Hkņ. ҂Le9B_Bzir#TqHFzvnH1 h!g#\#0RnnvpvL#	(8^wDhuPI$(KOES|mZ@`h)X@[n"RQfxɏ0~!i.S֋IL%^\d5x-l	w.XqO-Iyg&ٛ_1i+cbCnlLͣfv=)p[|}5ۛ?Kx|Fݽ׭NyҼ64j[xk:7cw_ݢ0&vK? 13|y'2( i҇`bJ>Ip"H||@F5zr>G+wO,F&Й#z?ZTjEe
oU:%E\&ņF:_Y
_LQ1L<jy( {PGJSwQ3rSNE˜~-3k84E?p t,v>Pz
./d
K<q++Pڶ[9#u_ uZ(?I~@	0d㚾6#-)Kk22jO.kҸ@,JLDbkNٺPC3t[Bȇn43t#"6o6鬧 ۃjmSgYح.+Rd0Fd:<7p|FX.y')kvpʕf'f1lL%w%-l΁9ag\rU25"N-t`+_8YubdW	.L/,. /~z_!%3!M-KLEpz"d&U3_zԬi=dn%-;^A̨.%=`n'WAgm#m>H\!<8qPΜ	6Z>$ڨ}ΈF6]UY{~}/&LRY",TĨ7:"Tb^Nc_TKOYH^JZ6ҦrT)M!eFlXcDHb kKjlĶ3(v-MCg9Hg=Ό[LJL+U}z@;J"MA*{RZ䁌Xɻ}<.,!z(gK'ce}w
SiC_ 3E_9~c_2S9MH Yce(9p҂UU²\.`փBBn\dOֳg2AjB&GܟW9dspԼʑbb8t½/׫BrK 0UKync<u*ԝM_(P&HK`JH焤eL,Pbd.UHd
pU2`hGmuU1\xJ"6˸UscO&'LZ;'z<XMFY!Z{ɚ
Ҥִ=,g,ޢmHL-d6;(ZZ2i\')I@TecQ;rΈ4saѼ?星1=P<_W Z]
m4w)²@%(x|9ZFGiRL}'lJ#|CQkHa))8EC'=kާM% <!DOCTYPE html>

<html dir="$i18n{textdirection}" lang="$i18n{language}">

<head>
<meta charset="utf-8">
<meta name="google" value="notranslate">

<script>
function addRow(name, url, isdir,
    size, size_string, date_modified, date_modified_string) {
  if (name == "." || name == "..")
    return;

  var root = document.location.pathname;
  if (root.substr(-1) !== "/")
    root += "/";

  var tbody = document.getElementById("tbody");
  var row = document.createElement("tr");
  var file_cell = document.createElement("td");
  var link = document.createElement("a");

  link.className = isdir ? "icon dir" : "icon file";

  if (isdir) {
    name = name + "/";
    url = url + "/";
    size = 0;
    size_string = "";
  } else {
    link.draggable = "true";
    link.addEventListener("dragstart", onDragStart, false);
  }
  link.innerText = name;
  link.href = root + url;

  file_cell.dataset.value = name;
  file_cell.appendChild(link);

  row.appendChild(file_cell);
  row.appendChild(createCell(size, size_string));
  row.appendChild(createCell(date_modified, date_modified_string));

  tbody.appendChild(row);
}

function onDragStart(e) {
  var el = e.srcElement;
  var name = el.innerText.replace(":", "");
  var download_url_data = "application/octet-stream:" + name + ":" + el.href;
  e.dataTransfer.setData("DownloadURL", download_url_data);
  e.dataTransfer.effectAllowed = "copy";
}

function createCell(value, text) {
  var cell = document.createElement("td");
  cell.setAttribute("class", "detailsColumn");
  cell.dataset.value = value;
  cell.innerText = text;
  return cell;
}

function start(location) {
  var header = document.getElementById("header");
  header.innerText = header.innerText.replace("LOCATION", location);

  document.getElementById("title").innerText = header.innerText;
}

function onHasParentDirectory() {
  var box = document.getElementById("parentDirLinkBox");
  box.style.display = "block";

  var root = document.location.pathname;
  if (!root.endsWith("/"))
    root += "/";

  var link = document.getElementById("parentDirLink");
  link.href = root + "..";
}

function onListingParsingError() {
  var box = document.getElementById("listingParsingErrorBox");
  box.innerHTML = box.innerHTML.replace("LOCATION", encodeURI(document.location)
      + "?raw");
  box.style.display = "block";
}

function sortTable(column) {
  var theader = document.getElementById("theader");
  var oldOrder = theader.cells[column].dataset.order || '1';
  oldOrder = parseInt(oldOrder, 10)
  var newOrder = 0 - oldOrder;
  theader.cells[column].dataset.order = newOrder;

  var tbody = document.getElementById("tbody");
  var rows = tbody.rows;
  var list = [], i;
  for (i = 0; i < rows.length; i++) {
    list.push(rows[i]);
  }

  list.sort(function(row1, row2) {
    var a = row1.cells[column].dataset.value;
    var b = row2.cells[column].dataset.value;
    if (column) {
      a = parseInt(a, 10);
      b = parseInt(b, 10);
      return a > b ? newOrder : a < b ? oldOrder : 0;
    }

    // Column 0 is text.
    if (a > b)
      return newOrder;
    if (a < b)
      return oldOrder;
    return 0;
  });

  // Appending an existing child again just moves it.
  for (i = 0; i < list.length; i++) {
    tbody.appendChild(list[i]);
  }
}
</script>

<style>

  h1 {
    border-bottom: 1px solid #c0c0c0;
    margin-bottom: 10px;
    padding-bottom: 10px;
    white-space: nowrap;
  }

  table {
    border-collapse: collapse;
  }

  th {
    cursor: pointer;
  }

  td.detailsColumn {
    -webkit-padding-start: 2em;
    text-align: end;
    white-space: nowrap;
  }

  a.icon {
    -webkit-padding-start: 1.5em;
    text-decoration: none;
  }

  a.icon:hover {
    text-decoration: underline;
  }

  a.file {
    background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat;
  }

  a.dir {
    background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat;
  }

  a.up {
    background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;
  }

  html[dir=rtl] a {
    background-position-x: right;
  }

  #parentDirLinkBox {
    margin-bottom: 10px;
    padding-bottom: 10px;
  }

  #listingParsingErrorBox {
    border: 1px solid black;
    background: #fae691;
    padding: 10px;
    display: none;
  }
</style>

<title id="title"></title>

</head>

<body>

<div id="listingParsingErrorBox">$i18nRaw{listingParsingErrorBoxText}</div>

<h1 id="header">$i18n{header}</h1>

<div id="parentDirLinkBox" style="display:none">
  <a id="parentDirLink" class="icon up">
    <span id="parentDirText">$i18n{parentDirText}</span>
  </a>
</div>

<table>
  <thead>
    <tr class="header" id="theader">
      <th onclick="javascript:sortTable(0);">$i18n{headerName}</th>
      <th class="detailsColumn" onclick="javascript:sortTable(1);">
        $i18n{headerSize}
      </th>
      <th class="detailsColumn" onclick="javascript:sortTable(2);">
        $i18n{headerDateModified}
      </th>
    </tr>
  </thead>
  <tbody id="tbody">
  </tbody>
</table>

</body>

</html>
     k۸	&6.8E[(٥DEq{gHJHJ~ln-937IV%Iin'eRTۏW_|9ƿ%'/("}h%PX9)LrqV<8E|iJF^X9XEWM7qI4i>!öMũZE6\DE[Տ?~|\Ḙ`INKXuX{t
rarH2!iPkr dpG0~4"H2[E=<IiKuh בov9D>,o7l2)4q Dx~m I*
I@l`%J<^XG>˘p-M۝Z<j*ڱ,ź)X*2Xp1H$.HQ4"DU
5Vԩ]sRz$|{x^-tbf.=fNb=eI^C'ZvQ8l^ W>{?LGOy.hW	O\)/o&)u!᪸aiR\$4Ż3Ww=`^#T1Yׂt{=(qn2iW+$zwlggM椬B_9b@;4Fz[V5jXkpM@	<8+vbc_WBKFڇ;Ý5eZ*g
lɝ7|j X½.,q@=_̢3kp_h,yn,gԞc,_JFOV Vєe r6c?'2A\:W k!
.vSw40Kef"F&ǥE
E4X hC澅x'&
$ET&|/RU]QW:'j0a奨$Ņ(}T5ꅌnHánL0kwjMIlxGu8's|t ./Ukp	w'I!H WFL&,K
HjA.!uaSY[h{eC /*'ƿ<wi2m@ڊ+l*  P6^QoQ mJi;#?BE#LM"Hd9ą'ޑSA8sek6	PN>E컓NT*.E'~izHsNmtVǪR-Bfj;j,]K32|(ңz]#M!M.m8}^+
*[QWGa`A_Y,
b1b	X%|(;:mv9I$勲Bۘ>D+ZVjlX:R竍HzaFbLWL(2$;oM٫Ô]`*gCtG0+
Oku:Sk1lPU<M٧!"V5Pu_g&4VThQ-8doN"a#5Xbe	`PI9كeEdԶ@ ևZZ@?;@jV&TSn{h].5ǰCŏ#[{?5cϽYupfuZl
TP4w)5B>21R4v9xzpR]q餛ЭZϢ]/,}'	QfvfS1V!OtGTս緢q>4uLM\wQ	m=Q. X7% w3firY[>ΰ]N/,	s(AЈcW,9bRذ@ Q8 	`n*YϮ{	(Ӳ_NC}ûCC/K2FY@:uPjZhGJfx9A8yfK(6}1|6`?f:hkuQ]fMZc:>&zdW(]1h@R%E,[Wn7&,RZ$!BB=tQ$M`^v."iuj}G;(CNӮ+,+j ls7*Ìk2Rhb;Ӎb x(׷ae{N\NPv]2C鴐?R],#cQԟ6jC7e#;|ODvQ[Cje(~:ZSٻ~[3ëpw0k'8K!Uֳxzxqk;?vV}nKާ<r{d񞯡w% U\Z"c)?=9Ϟٖ	BYi(ӞIKFFB\GkSsCstF}-=㱱4 v? B^z҇45]h<7dYpAlpԇ=HV8mƹ^fTяf	JiĦɜ	 '̽MMgG:w,B~^ux \E>Jq~ QCPQ:ɶvv&IX'"X:Dl3% %.TO^
St8jir`kUJ@Ew.i>M>BYû/dytsڣ81`V1Fs=u`r{}l/%p>V:3+REZup >DAZW#Үr *=]Bt<^yg&TL0"@quSD?!R9CL;  9ȵqF		;:#`-Q;R[P{̰}Ѻ>	^z[C )"mG,&^OiFwӝz6d:y (jyǏ7hlHvSb'7|@nPDbIY!O	h?AC˘ӺBd"rI{Dno;D rAv+M%JɫurRDIǊ.0f&k<./QpC czh0d*jЪ$IoED/^r1%t.[Ry$ы({J	]~H9!7$gpU(Gr-ys 	7!~'퀂P(koqV:/lX4 HdV(w0vׂv@:4.x~\@B$>^E'`*O7>ƨWScT뤲(Nţ&y'VlSvm`/2-*x~ѵv:(&B\n8O
*͢`eW6;{%ܲ%v9V""Seium#v)PzT5"9BQ8KxYǱ8H1t RS)JT÷cmF%a{EB_&0cԷ}E[L$_!:r>_ -Sh[ƪ_b'-UF[/~xD4Ók$]sQVro'훞fY/Xy[xM6lJ{Z_4>uSTۄ|X.ꢭ}' _o}dB!4dk?~Sy	;$27,<
3&H       U]ob7}ϯD\>6TBЪ;,|[$a=6%m-g̜934)2)&fu7dYglnz?RؑVڍd\D@rgjҭEL𸤁~F)l/8S-<#ezY !%cZ:RraQܡRhey+[$=	5 Cp5g[82yq;5[5.\\vLQA`F]\&\g@xitX>bpDpKCLH{GJ ߏh^mzצDek@g	J:oU-@ӻٔ8N-?J@F]VhCfܽKzPA?L&{SJt<wgtLx0M<	}WstfTHvReO/YB'$h	w3PFbpNl!\B݇Ѽ?(6FVBbA-JF?`"FMc`d=e6V3i]6[5MC9ݢ`ʕEBؕQ̗KPr?P$?m';gǋWT,G ɚcyW%}a9%xоRF$TQ |2B!ϓhm4BuIZo/".
+e[?	+19|imJ4c&^~o'6ֳ 8Kx`_hUjF&,\n@,]|Ɔ0/*`/~W($4ZP8
d>@%8:&9A
)]+.X[^nL*aXp;q*%^,+j}tUj,7	9Oq       Vms8ίMC&@^:p٦|hb[Y[&@ ]8쳯qǋ`^ER<Ȋ 7[ v,AВG@a4al@%C"zgr"V0"+X29._
%	(PP1)i,8iʗ,A)R(JK;J5'((%#	rUdQ?9,JRS0ڽ]Nh4N	˨P1>453Y 5REFsII;|p<L<#i	Nvc] !;;p ף>\݃=qXN^߾!
~{=
0? v4tQۋ\'ԊqnG[7B7@5['_ѽzF2wlAC;P(q0C?}7mcEF^HBr}ڠwӋfð!͡鹸"[vpo l5F9<}kߠG?*R\CWzH;"09aC{-t0I*2_[9߽h[Mb"a
s3to(_ݹp+w=F@n53tbUkye֩ǭpqS%|hLx3[nhH2YX,Y"t?.Ƅ
,Hr$ջR~cY$5S+!9<Xj:\%p,>'d,]Y8>smVgHV9Ԏ$IG*p$)!	)ir[ja89!C"xa@/	1IiQM(u,/K.ZqYQkI'L*+Uqoܺ|YNNQ+<1craMgm֟NfŌ#xShO?=fހX4E-9|5J"AxW,OfHT>zNk7wr-\WVN34k=o];s6{e̝T~XքnqH%^3)#IYVJJis&uiV+PÖz{_TҘcHS8V1[}v*؂njNiVdkKouͩGdYޅ:HԀ/Sy~#U @6l *rX8O&>#Uo:ph|imlK~okߍ3	=fsA}-kfn*שasRZ}_̳lo©<TiXeN?mW媠oI<s_Ȣ</>5,}S*[Ү&/	O_       UMo6Wfa'P=mP$WEDD$Ҡ8FZI|h؊f{oFZo|
ۗ`j̺uyA]`e+α*3YY2k%(l)ael`sҘJT)c JJ(d[kUn#~IĩkSzѕ<t}OzdVJBӵE9	[,=z?GJ9jF08haǲm"ȗG"xR2eH.p#Un k8H	\F9g\{PpƶzKI"H]]IT$5#n!0@8ޏ֬܎,h:EgiaڶW@Ō琧&<Ky"bAo3>0Ke9Iw"Ef99Xc<4~59a,H
$O@H҂@b~,ҁoc%bY81yq[NxPIP  +xlH_0Αv͒Y/Nz4˅1C8fΫxd=_h"Y}a(*n=l~_`!
)j;8p+⎖q^bQ0imYvC_B޸E<((Q8"B,BVG4!͇aivK䇟 nfgdw- ;rt/,Ӱ%=년Mc>eI(!%3)vА:tO 9qrޯ/cqqrr6xC5=Z<S;k<F p%Е5:hJo;oo2q"?Yڔ~'cN@	祿[)Cod>|#'Oqޥ(t6v9'>=b_wyH^:ZM;GN.V
+t)GB.ܥrjUOW8m-^JJ᪖<GQU%NUn_d/>r\4=!|^ԝaJD|eAGVk[+㿿;.	       ]J1).tEaAߣF'&%:nב2'99QDw2:jPD@&)Q"D
,u00}"Q`iL6"<:[ fdZQ1-Qk3U?$RPM-iOL<JuAm$w7ۻXw(Qlmq	2BN}pyZE.KCfA߫wk       Un6+KpEEEDd%Fу,1	4(*YwV6.=ԇg޼f48 g95,{4\:=xkKLL[oC0Bm[zBdklp	|vC kͽijB5ߙt{MX܋8J))"p3RϷ{pj}@QFƄ]o3]~u4zצ㴲m6;/LJնʅ _\iTٺfiצ]a?xA{SwaxI NlN	.E8жŧF\ptǰE8p}x'nh0y({Pz
T1/,nESmCR7R,%,,RS|R̪`>07XKj	j
"O*b
yQH&VȲgB1e3rKESy!	R$U$+.җ
dLxz.[,%.4ʅGlq*զB$YoMDٔԚ'GQLn#W[ƳvT;Z*EYEF"3dUG2)+Y,(hFyV)-yɥ֥(s:Lf"'41%썮1C{Iy%(M/|N	ϱyBQq"lSӐ[l8OcwÁ8JKZ\M&W(=kǍ0n
|OEk5 $JaX2c/םncqغvu_	-b`\:{ι'\yOp]Zv1ֻ=n\m,w	x[7Oh\"ȼn?!{Gk4t^+;˒4       KO1S(j/z*j%Zc	>mA4hg|gjXMpVZWp]il=S)ublF0RPosp\{9d0t}ԮRIJ g23kB
!1s0]yw
?qptDqe+Am]!.~M~LNCU@;' u%YBl)\"BCQвIE1b9vc!E4J9Z1΅^p0uu)U)p,dg+M֩A.\!͡NVr tډ2\EeuL<Aftm Bu]@R
J:ܤ=*mpY@c<*D8(NXP.۞H*nڰ9./=Տ~pO懩JuI>YWՍr$17GkOyr3k 3:: RFN b,%Z	 *@$= VA+j&EH7kQʶF̱Ey4Eo1Ɋ|E8(ν.craC3LڣLǳC?b>We nUIw9֌iqV<GKFJ㷿I#Ѣ+|i	jNѬꌺvcPԤW`MsqqKhM{2ѻߒhmxqtË	A4ϯth>%Bo>K>ߏ-T/㮋t&Kd       Wmo6_qH?VmݰYcIr`Zc"iR^0;M2mT{U#>VfSÇ#xz+sSH:;(-TN'FX֕Z52Ρk*dam^045&Wk	$leU9l+sr|7_q+}ѹ"%KJI֣yЂY2K([[@.VD]DGZerbe@07gbVUu"hp/0=t7o܎|BM֔RעbPRA)jY)QاȻ }s.i$Z5͓@նLphV
0 ujF1GXFxXz)JJem}O 3E]	
hqY
h>aq~80xFqB0~NW\,I /@)g x̗ 1 Rs48_kB4s3W䔧!F1˹b/7I09 삅)$3>?tpːþ0fsNx̂zz
0Hr> dNՠMKBI
1;'d9NR.SgQ4qaOX||y-Lw7yL!SEʣ##L}ԞXG!+xlr<$9/lX0%OGLOwƱ"NICn.]r?Ŀ|\Y}[?Էwp$3DESNF9BlaD}VT#pS_$n!~;ɬ=Z`J؈~
P[NŞ/	"N;AwvqeJ{n},9",Vˇ+-z4њ[mu{EhGۦ~?^svjppԩ&M7M7}]b0նk%ܺ481Cnxpߣ}V*8_]r<]/Eu'?_ЬDjJF)e0e]RpJǿTi);6Ɵ$K3Ki_UbU|}Dv{SF^ϥBg
ڕ5e6vƗZm4yImV\xL!j7-GT)n˫rLU?EGoThխ\6Q~ [zynP} 	Пjc /|W*ǻ(҉l#xO	KGRu;NQZhe\q SST{Y%Xܴ\iuk@
-PHQ!4vDNlB"'4N^^	+ƞjߢ7q[#OiX(<ڇ=,7ᰦP~tkV(U8hcߙ dK       UMs8Wte)Rsښ9[Jv[L>jk035%׭}_{:Ϸܹ֐1EmK!7O1~+X?0XQ5tlGڄ'Wڸ~Gl->|(;؍+Qڛ~g4ݓmՀu϶{uC$3|9s׏=͙ZC k@ġ#ӹf1.Swn+3D3m ƅ/.tRٸ3P6AA"=jb2q4w0{,;¹#+=n pdO
`G!m`wᙻZ9sKuBj W*HhFPPJ-4JS%xJN"Wa>D?XIRBk*CezD22|D,/$KY`gBOR>P?Le)g8,W*R4R**ׂX_"uFr)18 /;Q~/qL(p)Li*8]PH%eb鈁Jk" *R	V?JCh͡AR%s%Be!hI]u'cR`\E DEaR`
T*dݠpL#Nyƚ#rfh#TcDEl{qq)af21O\d9K-nP<yH[\4p}ΣP]3;OZ'/N\]M nO~xm>H8b<h0hQ,S2&_aczU|s7Evl];0x`\{?&hSVO繀Hb^10D1@1@gzK3ۛ{hV7ӢKR|A̩7BX]`N=>8yUp2/yB׫6x       WmoF_1Pq8$'iRGSͫ,HʎQ\IP\ri(R8-z*yf晗_Kʶ
mif+YMFV4^_ l-N7u@JQT#",ɉ7jEB5֨UkHT%UQ[KJUZ]^-iukeV`TKS";Up$[aO,^UuU(VjvN3ާ\lp*V0^*$TC%ѬS`4/IFzGg¹< :owO87HeHK?/2J)ϳ?		ϋ$n_,f!b	iϧe"	Ӕ™,> Eagi4l<h]EĲ؃!<פ$G,E٭zes6w{>-$OeLq3`GWmapQzf_/v(A<ϒIJg! oAOh3EDx	zL`Kᜦ(_9?.$Ix΃tyfQ"4L L,Nu4`$CT@u2'Eo@<=uls3'.ۀf>\><q05H^=Ic4/fE8B&J/JY /]|RK/EO# HC9#ߕɦhz2Htmohn{4ڝF;cB1IEE+SSVTU7'z[PwW3	C~-:^6<@tR0Ùn3tƒ'Osd֘,<0=nv:Cq<Am*m3|ݚZ7;մ<\Rlc\I^Z`1#ۜEm,mU8jwJkm~Cmj1<EFI݊Ɲ݉Ub&7.U?!a
Dp9l9/S(Ǆ%v^5{0yM<H[
ed?*b|\O7FB5^{rjL(w!C`F(4FXl1ȷtn%Ļۺ-oj?,+~ G]|d3^G>n|Le=>}ݕΟ[u;FQz?0v>\^&>`JQǥr9:qfhS6']p(Au˲9봺БCgN^#v Bka|@"@,P9	fՉGnjK+=Eu 1zbM>u<w"{U^m-
V~_ǊTcLhUC/bfX9tWxoDb2eb|pykm&TkMgʈ!saUQ/(fnFy4=		7!ѢK?RԦb%. kPzni&|>87F_~Mࣇ+g~:Mܯn䡠Ox0ri钎$!'̟A\jΪOx,       V]s6}>&Cfۇnc
8nʠؚDҾ53I~{{b8F
͎smsr`n1y>(ixÇo[U6(.7pSdsh%6V
٪[FTLAq`/eMRAdp)5W1J>܀18)
2Y5&+6W	S&slhXMVfc$Jjq=D3i^c¢YDɕ>``y,p˔ˬ-yi&Ls%X<o7$~ @ަk7&Q(	x2Z$v>vt|`&5I@]F>xLAJIbՌs0.ini b#!%SVi`b="7NdVq&L?3xKd6ܑ d6iLl'0%ם-cxx~6;Dģpd`[n|r0mB~Y]scCo$ia<gw#ab[%"t]a=}J%|RH"u1zf3RԆbïe5t$ȞtÒHfj}:'GChiBqhbڽpe{GYvwvGODBdf&+yS3ೝdRm'W?01;9
h4(dU̐;؁;:[h֜$'Lk3E}<*Pknٵi1Ď0ؘa&Q)
Qב][lS}k6͟%+Ķ+;]sءX(D:!O55FPP^(fV퍢g;QxkccKV6܈ؔRVx'6fA?5WU]==}[ݲUZ(ҳ+YUTz'wBƕgYA߈N˲WmlLdްHiu34i4{Pj#JvCӰ{n_&~dٻ{Ǝb,n
/
       UMs0+N!cHhSf:iUdG_w% bHƻ]2CY"?Ȓ%3ru
hi)dPJG6ѻVU2=5]egD#lL7*qI*g+&=2RI_wvFC;k<MY;÷;.0$t Gh9B5=/H`b'*x}S!~3mB8Ñ0.׷_Hv_#dYb&-k*f<)_Gϖߡ
]HjaYv*TE"Ծ¹0W^pE}#hvkcH<y\%pC+q^@ZwuG_MXh|7`)<iu%DВvphb̈́Z)YR2-_$LFlt2C~ay5,I't4 x`sH<mez:ڡbAR%Kx2]2uF,H/@a
t,8ԼҴbiXD`aYOC97Gq]u*yͰQ[<ڒNi&a-/s့)V~#Jr-EO;8ugQ$>gm4<%2On'w7#Ft       UKo6Wnd/%& K.I%Q脀$$-;C+wsn1p|uyO>oo3_oA]< Sl!M0t3<Ot6DoѺڱ}0`Gn&<ڱG9?6>#;m	#Etݫpۈ;	n,
Bohm ni:ܹj^ii@otnM;l6YnSFpQ%&}v{h	s`ؾ]އuCmރOF63Mh}lC>jߒ0A'TPfpPE;ԉ8pLx
RyQKu穰S0y!
T}㵬DopC^7R,uYpUVZykSxSZcZr VR HViU˦"ĀRиSYx[Xq/+RMB:EJk&țIX7r]+*/Xb4%+KL-d/9Jen!$uFE5}!$
-3Pkd6	`+	RH"jJh.(wBQ\މP*(!fQ09\Q2DٚK٬/1%tdp)t/9K7Ʀ`Ȋy3PE)9t/O:=C&٧bAmY=gzA+ i?քS	t4...0vk0.xXU	+h{kv[/~vαaH9lB՚Ëg|]|4̢3m		[A7w$AqˉA,6:k <^{3avo:7Ms8ga)       T6]{2^"l2!=X%&S{gT*p V~uK&rz	}~?~'Xxt )<@N12m{<G{h΃agΣ{!gCH(oȠ	N6t.F)kqM/8ǣv|:J()!yF	vНb	y
~Nn#mV0w"XƗW"=#\+ŅFߝ;i ]mpqx3>5pF\e]&,Ѻ޿R\+~GK"<ؾ]KT:-\1l#N!1@8ɏ38Y0
\꯳5J7KA˹0k%Dm1!,4(1T`1RU[࿯Zb\g Q-2@!RFf?3AaUĿl&Ja\ͥ" k)Xj-5WLx1EX%+oT\[0ȔJNB(D$Yf<F_8bjV9BVl;ؤV|E]ϴ6RvՃȹɸZD`	\j-2\zmt2.ײ"Rm	H`丯#;4cXLBX*t@Fh~T'I;5vͿ,uX xAq|}rtdr_tm/6|Ɨi<3z 2x%ݹ|XXiBɇN\ٵ~/&&       0DY1Qq~ I%mAEg7sf($ȥ=7&b9_p3xio2
|}ED@ޑcD8ZܤESFTÃ~ONݴΧ\l)SLG'h6X,U        ={:S>h'$)iz.!$ͫ@ǀ&@{dH4FX_
M=$WT6ș4^V`VAZVBNCs4=tmd@'3;ϧ4 co잉tbXCO&h!! x3mllVc+K"Io y}!'4#Vqlzݳt  :Ӥ͞cc/n# 'B2Dd^o:AOfhiG!^Yl$l]sl!G'S3iX˃18cQ~ZhE G,06B0}A>pvi([	&V-Zhx>ږˬ,PsliC |Ӻk4N\4H4;mR괚ǷVh6@kvA7FM[yysU4mUyu@;y XZ6نԎ\F~_k͋fR<mv)PZӬ^Zus[rl/jIMҸk\uHvqCv71R(IըwPj.tҾiԛиoփi.kgɭ@ոDVAqvjh5nS5ݶ:(i:jmIռ4ZۛN*Oί?:4N__׭ĊzjɇPT[5BV`@ؑ$WYN}h>4ۍ<tS MFCR /xLبN;4OI䮉shvU[뼸Q(xyiQ8v>|±lt|cklCۭ!:1}p2B`3x~f+(LfG Ybdǫ"}N*BF[=UUh9	M^x'znDJ:)J
|sQ-*D!yt#OTŉc8۝ι2vU^;uéNjunP9d =w?v@}d6ӫ Eeodr-{LSK.=o3&,X
LE KͶ5,rsxz#&|7P\荣5`uo00]y{S_fg;eiL"ljP͵z:yNjq>Sn0ۃEE,Dxri2lôCD# ]12h=tvhNo(sS'dmwdˤ8'lзflYoNxX#ǞvHBwoU3*?Wy>9P	g% )a́fёQ2<,ΊCq0f	D

Dj)w
.˷jِqWX:HedدpzvV*p7P eh1&ڲ]ƥ¼VBRiKY
R0d;U}{f`ukVzw6j};jkqvXPjJ͚ӷo[w[RvxV<7Ek'<yY}}r`|~[/sO~4/jMx2oG去l;'~do[*f(;N]
04^۩pք:loSq{}rӛةԿ~~|[t]w?M/_n;Nfk꧕M|~Ԝ}v[ܿk?^wg4+r73V{d:߯jv/3yW:5=87fsjj-Wl٬h,Lnfƍ=j^u/`G<pq'g|r:hva{^5v6_O^i<~ۺ4o*K9,dE
r,\B;t5sW=m\+yQdIr陼M7d셞DLCXEN9ƞ<tLƁ0|oOaY7]f.Br4<-`OJ0OW/1ctqISudǛ,]ہ9pED8	qބGF@E/LW (Ҵҹ8%q TWab&pG2J(s\%BUF)x˃PXH&0|{bLˈf4z"}+썞_Z~'|@0ǂzJjHDhqa#PrT^-EVv
(ͬ)9Q {4	ĴǪl5uvq7pGň	v5R'^EAf'?I^Ӄ)-8u`>5.wYi٨cTk'ׇqwtT$,e@ѸtT'Vo=ߞ䯌, DqƺZz\AoX UBQg:Nʶ܀&]KS'-YbzEW|/^bZIU)vnT`$Bs(C6Yք%-Db99pLtG̟p%`-F1+=^'	OWfsY|&WFFWff 1tu.b
Z6ya1i9)@ףlP 	PvҒ#)`AMrJ£0	+10G>L,`	b'svC4M'i.Y(ǳG\bA}G(uQmz~NSWZH5YCd!V`xtV	ay|D8	D4HąEsKi"#Ղq<ԉ?u,o4e(dHN(	ȵgo0hb=T)FcyXG+A2NM+4/xޘm9als{hImmX͙kTsL	O*|lY"q?",+~[Ăs/@WVi="d//FLS8) f,ǔwpq΄韌=;_J\ElKYN`]J*WsaD]l,xObx]ɸ'^[o@&] HՊ|	$JVqQGQ>㐍aQ̓Rq}AP0K}|* Kqgl8
S]q',A56訹n3<y"-p5u%)|R+H!/i{!&8\c	$D6L~'G/#Q/tRi*,Sʟ3/P~.c`H.,1o%=-9&Mo*ڱr?KlJK$
0Oi!txJLd=Zod/,wH]fnAIrQ`irMnL$s	!6.i˱UJe[^Y]Rhp/)OebIꕥ}yڱ[Z/B>=~wUc{v=d$!e<9vjcwMW,ƯOНmWT=GWX_AɟRdhU; 79(nh
GTN]3h|ӘVM(:=t·K;dC	-CsiK5{^V['oY8s7DJT*`[4Â<KJb цA\q=ߵJJŪ,׶$t'H,1c<r֩rL<(LZ),Pz{rb\d30D)(d,iF `dgbT͠RO˝#9DZYf8
%uֳ,UMd/MnM6VqUJV-"i]Awx#hyAh*!,$aW<t_YA9b2|[8G-7ʶ-{+p~Dgbc$^C2ɹI+x*ۋtܵ7܎shvl
 FrAy\9\aHn᛽<fl*|/߯څt(pH`PG>XDf;Y`څ	ԜYv#N:1?ѷ)cEߦ[9XS{ns'@pIy7\&@K%|<M7E
=%^&]+YKL-6ӓ]e`E%	(& 0ixÙ5QuI_G}۽2l[᤺=͊;mT:n5ڙQ*Q.o`C!R`:; F Xӆlcd)R&s2q f.HiS*ա;`f4֦A&q7miTrMp[q2euo&+S7{Mc# 23b:]x*SwO=N9:<`Y2*e
meE:.~83O<@htg\X~`-I2SG%@NתqO`Ky;~,}:LTr+WP;QG5;;/Gh_b7r#2}EGq78i߃'}w5KR({Е>m__QYoEoBG=!+A}jdd2/ %5]jt~ϰ$e#8ɏR$+ʑɣX'	9@ڦ̦452jSV`]!J'a2NS7Zf|~ۜш=bkQXӢJ%g||+ 0\Rg cٜצ:e11XCFA gd߀Aj0کÈerÑڿ9"].}Ά;HlL|p}MwEyʸTjLFGM'?WS&!9cTiE]2q*	iCh&rJR̈Ӏ*^A$JSWI ib
*Į1I"mO0]
^|+XwtDYukЁ'_Eu0?ԨkXC_Q=nRZGUv u)ϱ.Imk(؂%]jm`޾S|>*RG<i,ce`	ߞı{gZc#ѯڧx&`|qt#itkY҂NO	/;5	S1Q( X	P<'(FFdrKxD'eaBoch2{xScBESO;f}s͟ha9JqD;۶%.gMUN,VJOz&B(6g9/gǲ6#LJ7*[he̥1	KO7Zh4D&!$߁Էrǋ"dL#5M=d	ȣ0LrH= L?nvT|+TǷ;%E7uʣ`6Vaf*ijb?`B'4xh(RE^rY>p[Ws';bY6	9=x~Xoҡ&Yw^JV@fu{2BZNڭ~aa3tX MnډiJK3m`*g|_]7|p2_ ѳj~|wf'U$//	*l-՟|f$IScBTxTj:e)WM;͙A5d)	&:iKU5"Z7	`XehOls.<aT޹C%Z"6RDMȧATYq_=?ؒf6a4MAA I ^lk4ΔISXpӊؘdS|:r{/
uzUAi($?\kEn^R-|FCvtwj!{-w=O .iٽKQQb4
yԖٖZyAa~{cT1}yDTIOdY4&a8J@VN]D:R8HT4FF=)r[	C/.1:-gA3w 76Ŕ`lguBiqUY|u=:d9\!ͼ>,ץ'F=eWI?(f2XHs;D9 |MJhDʞ'.0)ĥO|HŃF9V('1h+\Q>LX9߯c凋fM]1&nBOon z&dԥ24ɛI;J%jME.Q!9B&wG*ѨG;"	"|ƑKN9꘨}N>}Ź	Cvpc7H^?b?ٽX}!ŧ_H22KOcҥ4}I:.E@gEDlhZ8:UQ,d{v ԏX!ǿ e5jE|EJ:^xtS?fQޚMQulm;%{{>:CtT6laTR1kq<>dr#o(\2@ ewRť|sTiBj8 	&<L  (S$6i0Bǰ<Vǳ{6H]2&ЕXr(]Cq	Dl1r,MqVnˋozrRڠZV"%z¹'pm1,4zն_γH"ej1s[Ox?/'i͟0+,-?Gi*VmPql`+WǙ<[I@9pG8T>JXYSY5UǯoOq:Ϫ5	LΘ&2b:	OqFFI=!+>ٔ=EVw}P`aJ1LCs
p'478LP2J yA1ws̊ VB+B}[$F=8ڨ'oqo{Gߐ2f@cqƷǦ@;'"KBCʺz)'jeæP}TϱLc>H(NG~u,ǩO<%h'e!x}ZI(YZAuw _6p'&Lwt)*GH&$?'ZTT	5S:{eg6"UŌJ(6Ncon@R|P:1p<.`Ѡn
y[ŪU2-#KJekL71fV=|j(PBbDN 2 ѣIc>x9Kg	h@K(
̄j27?r؏]\5K.!ԡM<1&Ntoq3F6ӝT$!*s<=5ym&efޘlK9Y~8/%QT$%eMf=eH)&ZY4ǮpopcOi75=9|&}\;A/HQmqGhK.ԯs<TT27]r"QΟ?>O9ѳv07$n	q z&ƥ=s5 eO<|uaNnH@-*oٙLs[g0~Mq/;ܣWk `[<Bg8hɅgu*?A6gk;-0k=dCUknI(̊	Y蜛A=k
-q_2#v70i($OH0UJ'\t;f]F/&rul~遆RǨEZ0n+;15V(dR.32w25^O¤ǉ^X?db-9J(]ne<@?C\bTM/bV2wў_E<V,s4LWG9i{seqA)l?`@+;5uح爟h.$H:brKuN*Hgd@H_$#GDIg!^"!:(@ȸwϩQ2gC`Yl72x'+ tI)**L[EGXpSXOsE-P
˿#BXd|",e`UAGW*IimoU6)ÕumJJJɲ(cEM$=ve;;W{]"t E;-	hUWW8џu;nWkFOU5[]ertaY5TVӜx>*SN$Q'hb*XU(Ӫ4 CICuT%l]E(O)	ߪWIt?aS *~@hNOVէP$pVh8ZkDXYnU:GgPq08&߭eTSFTWĂK>	8ZF"H"4|-~6!zQ[Ӱߍh%*mV8p4 7Wo|CO~bđsI4<uۧyaZ!MoΝ䋜4GFT;V &Etb -Ls(JEj^lCHs       So0~_qBJci2x͉5ǶliA9'֎I~$;cNMY>=ML+SV
E:S
B#=xӹ
2Y(O[dBT\Cie:-@jGrsVRa̓M&B@'@OiXiB0m3!JR>ūcROv3:ZjqRzY%	w	Vm!&C2;ĤDa6pHh2:omDsAi[KHxVyP_uj#m!}#AXTHYv}_NV TX}:獣`C]Bwu,Sj%5R̎DSz)Bذ 4ŵa-!aAy$q%kr8RwX3iSoN-1 CE҄`,>Rly&q"y=;7\$S2`/疇"Cws3ɖH<y;3F,v˩[9\C s0U       Z[s6~ׯݝ-*C";GֶeOtz34	IR$,k2{p!	EJvՋ$\? r8D(%dϯ~+0hM6kt(It()NC!(Z ")JMaE>Fw=$>z!]R0
C`+"#f&	ad:	o>	{r;7!sIst034У$
QAo7׿ŉ}!0] KKI ڶ،k(a&d\8+6T bT&qh=7]hIU YS']3b3IbYOr3Ji?A@5Sӥ 	[G@yfH\De|:kIJه,<E|ctt۹L|^N9ꃪ१١E z'(W |"(px$/"'h,$4#X̪NƮѰg:B
r@>,	BSĤ}w27HH#`/X<YIWіU :ǵ փ{%c?˫  NHH3[`h//yD]AԳҤV4m4
,hHiK"x7I8BPg4]1_Z,;Twf' tP~$pp):EfVy+	=d}3RopM?|D"[{IY/ٲPj_gts''^&+v<8@2+HHQ٘@- <(``G|=jU+Ajq^F&t!@DI{Nux2]Mx50_Ny}(}
a/>M'Zإ퍉ak*sDˋT;{fywz^p<7lzak\M15	8`l%ԪPغeW
}=lfBlp5.-mt&$
+s㲴6xSkcKlSQhNTJGӥ13iڗ4eVWZL9.u m%.|bJ؋S@z\]Gs3l`MW]N]h'_,U߅꽁[Fq`	6F4X-L&T9Ԗ,Ύd+os:#/1N5ئoTƺE9+r2BD`7&g	zB6tI!
=7.-(y9E}Fe]};E.{XtLa̘k|yD}s-(ݝ:'Ӡ+"Yц UhBְgRcN=SdYbI,MҮ_'U/<Bt-`{hD7vuqd9g0i"_*ڵn9]Jkq?+SVÙg/EAue& e>5|'RRܳ&m
%V{CE~9,7FG@Bw[5lyh/(s0rpEu9wإiL81\i5)#Ct+?VtehF#S2cgx4D[7C`o4&3{3őUtpvRfH;%ߑhݟ~1\2[r'>UD*]e0~()ec%lȈF~[GqhKb¸{Q/(oXgH9I[[*	0ìMiK.Xgړ{]b$=*\QNfuO	d(yRl.8풠{w%XP+- ~~iCjF m \#]" (fZzOzNj|VB/;wWțB 1Js	y^a,$X㰉o&0d!lc_E@+C%nT2m)IG6Qcz2_;/r3z[Kud73GĶc+4~59AP̜8:P%TR$շn3FdBV5C.Ý5fҴX,\*rERboMLs>zː*ߞ+62]m<HVE;5	&9Qkc{m`ˏhrꆍ_x	<0r֑U 2t3URHigv̟X'J;+bvQe,Nv&Ϭ{9}/>r/       R]k0}ϯSle;iHmVƠK7ث#]
~Wvۤ
c}st{q.li@50* ֓e@n̾=d<aS[S|mFkA,:GBL	V9X DiehǯFJ`C4_DI>iJ1cn܊$I۶qVI9OU+jQa{kN+ƁtN%WL	0R(<m]	g0R+vUE9K֓Pҳ⬔.[1-$&2;7Qbzy,lU^fQHCI,Ih`aB*
h_tНao!B$6^!S>}L^{	+O&+UHmsIL㗂tUC㿊'        WMo6WHKl7i6]^.GJ$")TloCeYz-C{3nQ6;"cd޵Jsp4(zy8[SSiвULpYW!q
eTHTV)P0N,QRki)^JeTѮT9UA&T	m}	l׳ϳU&!LP<rk0Q&͠ȪL7 2{
R3zٝlMwV"1"jfI Imc8
s0]HUu%7"`-w-<3G]"DDbM4fӺ0*LgJL<0Z8^Gso)}=8thOŝZjY,H'F^!w-g4T1ѺXgJ,'6ߨ֤Qa'/,'H9m*^.`Cf"vWƣA݅Kݦ	Y&L>D)Goz&EԷay%zzC:U=HffdcдlEƙ?Lu/j=容<wmt@F6Mw>v薞Jyqu|7D9}؀:7/7Y8z6.M5Q%t`:z=Zo9a*uƕ4ʓs,ΏBo[17~J»s%:v&k߼\oǅ|Mߪ[AUN@,{rOm?lo\g=w7t'ɉ[=?#ݐ:Lt'jZGޗc)hS8R
nSa0       koF{~8TRЏ@%:A|"("WHʖ̾ev޳3;lryEA?;z^ ]h,;)KEI8!c9Xh"QNY٦$%,`|e%~yrb	i0GO<3k`!.
COQ MrBt+V'fCҹ)HCS+qg'	K"
Q1#6Xn^]'~bNA(Ep=Rr
`bIM;H/Xq^:o1t\p'ލ5?_M'=[F8`x.&co_{jHY[?^MmׅW#Y!55z\`<`w<D&c}J\{{:įֹ3r[ԅIʳʚzzdMzz5q972m踃強&r`=p/Ѩj)4F%%Cgj<4@ס~#+{X[X#[5"!;4cp_S=錮p]=M&Cr7qsg`}M\k6Pgq`|~:uس+ϙ{p9Apn͓1g2%\ڸ>%rY7K?0ߍwx`tBn9.!8BuK&|D#J|W k!%2Ȱ\ާd8zŔOk?W9eKx(&	x=lD磹`3xsBB?{8̸cŪ0:{t]|ЂmyiIj幔PW7	JF)܄Qw~L`Yi[+ CWs=
%͜V!v8B"F5Q5K2nCxtdPs>VZt&(Ҭf5c)
?3d~~$صGal,<*%v$vaH!bfx\HL8;;N$>_* 	X@-FC⧗-!}Fw%U-T	n0*R2$&<϶BRI\;m)VNT.Oנ6I)7Cտ
Ԗw>1i-,<JF	
r&02iwDG
s+-O3¢шE$.}};2mez[azUq]^V8^4o~UXWdǕZj$iukEo<jіŏT&^\=DIw[{E"r/|{ak8!`drmeARGpGC	40~T-7Tq.ӳ[ΙZ+)*[eu2J{]Jд#Q฿G%-i%Tt:U\c?ϹEW]qH8`I\<YR˨RVSI*;?[Yp 9'39u-K(S3>=?wzT٨x6fibqn-P-*7Fxnc/L)bYW>Id'24<QKGFIҰX:{oRGsGHE?ZWJQ~RX*ut_V&?$J6&GO`/ΐ&(J6[_&b!<2.b>:
2A:o\!
ӤS@⎭F2_ F)+GNbkw(e&ݭ#zȩ-}ց_Uzi'XGpipW\BYǠ⣿%zsEXu>jҍVuBImufA*ݴi[9UwPT}w彧T*'ףe=;}_Gq)4hO
J}TK,B"S\$Fy2U|z9)UST+f~uެiD\-Xj˫=W;_z`f ahoUQ>F^[DԤM(AO~E^EޙU0A!5G9jT̋|*җbdS9t߂]юdi7H˪Uѝ5N$^cF?ыa.7+4f~ҘF`r!Sib$,}m$*	J4^?z 2YMwpvr|_:8ݱSoLg4cyjҡ
H00FZhݎ;FsDQtX5m0ίKm ]NH:b<I'x˺.>2[[mF~eoSA#My@O	atwx>u䑣eޥxGҝ;}#`Uw?y^EzpW4kډ瞊t>.x'J)%k)hmfl~>.~^37qJi4\o0gģ7Z7J"xLv) zEHľX\iD@fz6+JU
6
R#/OVL%56/	=R垜
)Zw|3'͟nKO?50_L|{es*r$ndh:.R뽉bU@,9e.`7E?TN_@j7R*G\sU(kZEryT#rf"UԖ7	YMd3f[}[?/W3v3BsSuֱd^
{C>QY
vH?!<kl?Bxd|+uX9}x2R%sC6♿4]^q/f]XZq:p}<Z˽u%!qbs+G&k/BFu#zcx݃/;dj#ˊtI9 ~NelBA>_Vٸ岪)8D?Mwؕ'ƞ6K1b&&wڟ,Yo:PY7 ԃg۬ӝ6[n\Py`p<j$fyNMp55t+:x_9	wm94QaDDˁrC 3{&.	´(/Xz)       T8}K&a92'aPYI-d1SS[P&=-V^Z×|Խ{?o0wn}3ux3j1nҴvnO꾅`0oL\ھs8$fZMM	GiŻWbuAsoCҦPhф	ƿQbi('ȕP{	_mLvmoNشj{4<?`GDPg{Br8 9Mpu0a|ʸ 
T9k&9`x*"3Td ,JRLO(Mh \)(%*ؒZpZ^e'(Prt N@rK.ȅDR3j7~VLjV9TeB9KjV)]#I6#ZB3!yIGu/O@x*(9ar4*WE$-}cp.i%8*-t92#	Mq,R /UR<&aiDNKY(;Xkt&wg沈q<.zq]5F^(t/ՄrS]O}#
>Ŝ)lI@kM(*k!򱌔Ûĩ˞QPrl}}ֵn?~0i/pobz[7?ޝqx;pI\WXwV\pz~o፟FFczlwvH_V       Y[S~WN,Ix&$v2>ȶhp,æ#ˎ8ڄ[sUf+rr>8;'B,F4;IΈd/,6鱘gJ0W\13FxJ2ˈ鑐TnBu#\RY/xDFPȆ5Wd#A_$xD"9npЈRHČLRHH'G<#	Cui8F	k&5\JA@8*Y@%%R2Z",U47IT1iI$PסܔqtPb7mUVh̀12te-#:1^H0t4XWtY$۰
qt8eFܹ>g79owL:d4{xۻ&c=4y0|$sjT's|<?L\<{#t4m 2Hd޻f=z'ݐ{}NIq)yH&{AƮ?38i@;{2itfSCk$'ڎ]i πJSϐaL}o߂G4{=k?pyla;r+2hav`k@|=];ϛ?ll6kgSԹg=!iC[G^p(/ Vl/:֙\0CB|>.p5s`;׺@6m;u{Co7|׸otgǰvrxK}n+bSZKX)!RilE"rH^W\#^$)+bCrvsu򟓓Ts	 N,݉٫YIR. Ɋ1Kү<V!o+S"̜VĒFdCL$y)zĦz>z&$t[+_{|wҏ[udDaE8	yCWM<Mxʬ0s12ClAD%omTr3ǚYiF1~&dfEcEc/#~
-\UѰv֗C_PT
 '<nR3膥ΨͿdP-~OarC5XQ:٠ɮ;ME1Ҡ->L-!@5dUSlhB.͡p:	C!}(U^?9_B`GyZ(W:mWc
 eW|7<z^(јP =PvoPV.N{	!>b&UT+OY$Um%otXM/DBk`Uܕn]:~ǽ
qz7µ/|RTي҄Z\Ь^ݚ%qcE׻%}?ªaQSddh_М\z,eYBU+ju.A҅MiTPT]%%UKi
V /iu~іj7LQ{F-A4	[`R8hJ![jVbf*JMFGIof)h&¿p.A`VBdUbMᬙ})JP{iŤTy'S!?96w ? һ%kοUV*6[IHR0ZFͳry\c*ʡс<WwVПD*=-7dǏUjiSmÎyhq{6T422ռ8H,^WoFQUgbUk7F|0X;o_ɣ6+̕H"ߡ̕{͚ sHϬ<*~^Z_GyBe57((4]\zr~!{#?.%F2`h!8bmG,y-h       }{_Is#0amfy _!%PcVL7"*!wMȈμ$IY٨l<xA0gEvqY%^6\]K~	IA5$L
R⚌[qUOt:N~6M|^rM69ϋdeg>U>γQ0IZdF8u6_˴Llz8F%6HQl$?1IeDU)`ӳ8?4CqV& 0c-q4I+R@_"@xI\D^ $N8ͯȴJŠ=ȡHҊY:)A!iЈ;$mAt	檌AV)%t} "Ot_	
rW$a1 9 ʏ2?nPxd%匌P]WDMl% ;INޞ~:MG?$o~dO{?;M$[;x͇ӣh'ZuS$G=o;{?"Syzԧ]-;sO˷{ۣc:>upd7AvNvw{x7E8Gw.`fn"Ym`" G@'ww.uS=?&;[[? z m8=@܁%'ޜ~8M~8:ڡl?=qo{d#?:pK:ݢ`Ԁ|8٣,;<=>tc8nACOAG||ߏk[Ȏ^fR{?nb#qdwh J;F)}:dk=ğy8Cٷs`q*9#-N#!_v`n&̧v=
;'%}BS(쏧m_j^?mI~9:UI~NI2F_HLIN\eI2G鄬'2]pӏ7Ivȩ0RXe?=#͒s|N:Y2/*`Bu-ҊH5+_o)1e
*y4?kCFܧ'破	)R;]KH*NG1uoz2*M_).)k2,?9awx=NVPeuq>eMIbYOH:e *&i7MG"P>Ϧ,;n  VەVF),:No@r\w Y7L1+ !A'y'R132i0p`JEv^:U}mC_^c`3vZxE/æ/3p>Ub>t域ӚyUQME;iAN~z	6(e$A38^_mBb{l|Bz`lw5vng`VW_l	%i-BmҀp#o,UK40F,fSƺEdABp h=MW0Ш`=KG )	c+t65_Xikth[}][+ߑ$"r2|	-nw&&ݿϟO>:$lW=(O{&a@Hd}oWx14x(ڳ0ZHꚋϞ?^]>YEp8q.V"nDgȇO~RbC'y$yKO S&[J~5y~k6a4&_iƙZ#[vE5̈́z=1*}8@0dо4nB66kIǶ?QKV4&nמBCp8\$H[vya
)IMPU|][ؼĿ8P7eazUMhw{=&ejgo
٘6Z#L['ԭ1`JrpaB`żt21oLLj @tyS	Ҡx#6e{GK866!b BjP]bh	b#2 _Ɉ֖6/mh"'	]v76}cZcp}׭DS@`&q	٥TM`E~E:4rMGdw.[܄@D=/BNz\J,QU*ݍe֞<3y}5ɻ5>F]wR454>*H	Ir]:0̀=@ i@	`0i-(3UE)p̰tkV,J"P>SL:阜gS20eLXC'k5Vxn鑟&oP6KO4U!f}QHZb^58ϊi
y\ta,uCWe=jJM&eCF旆
|DFHT9v+6Rp0!Я/l O@}`]yڇ66Z>J:+b9`]]cQ5e5**P+I|#p2K%H[Zإ?͙O~A9-I>3	BNlv*gUq]G>]O4NcܕRB$cϣjU9Pvdj~ōq<_[}_?hVH?fQ^Ǘ1``xeټh!|RT7']&Ʒ㠚`>^p#?rp wēy;ʄG<[ gOcYAzX
kË#9QM	LOL&f̂7qQs9v5k*V:*lcxdB*	ܡӄ~	x?|LfS3>]Y"xųχɋ|@@|Fإ|J=:h6տG"VZol`ٵo[k׾Иs}36~mq]r(єVk2}QϣG%`vtҨWVV,\(JGi}ǚG}!{CzzuƎd dcsO Ja^ۃ&c@\J>EbM5RZwLub:X]V{R:$l1b2u6-Ks}
0h1cg:p1vQAG^ov1nj;ߍ[1OwHzɰW3;tu:⍌RTޫH4RKRvp@^g@?{ 55_N[~sf eNLM|l͒eL"Z{m7ӕQ-aR-t#NpahUtM@?K<><`=L^Zhۖ֠]*DT\5jNM3k]a׼m˭X4Fju.k]-	͎4I~j`$5,
4?u9	݇m!ML̃m"4?-۟Ѻq4hb?
p{ׁGz,l&3ݠ>
#U#PJ	e MWs,Pb2ZgfSutÕJ\gUNVZ28-JR4H얛oțtxxâgCI(Bi(kanC<FCAbX.;0ZG-=roc2׎/Bҷi1^Rjo7څFH~$.NM5Vٶ5.wV͆j[+ۺbb[Uk1<XRH,UH;ֵC1(|oJԠ`䑌_TADC/bSN8˹7ͪdRg}ݽ]B}|
Z%^kiI<&#	EtA
UŜ&$ݿf?	L{=f̀'*0Q{Zeu46]x$]n%&M
>a~{!MZLL"_ dٵbC%0zXqYg6hɆW1R"(,J:T32=ӤH1YetqatD9
~,#3u	
m&vN]tGVy26+^|o崕h-tlyVKs(1ۻ״i0V
|2E)OF W7L!M:7+UVLPd&J[	#:-0n.y]%P\'['xnWɊl˘;CC.Pwi.:dA:M,FWo0eiBtqYy<NRM6dQ
ӊ5pg˝*NRoq|A&gCU{G+jFdzVEl2y*DZ'u6bh~Y!b!Ewr͇xP&Z> ]k|"!Bߨ|GPLc/f-DA6G9g
CSL	xSt[r-?${Q} d	auaim ~91oj)WPÅ'~>E$WԚ[&ǮdTKu+FL,E1R?RFRi>,ĤYPe7
;.q~biEIݦ.O}	ȳbOT4ߊrH-H,EiA7h
춼fW{x!Ңu)
L%o X}^J%;'NwJQЯ8`Ñ	o6]Ϡ'@1J%M>~$-?KĝE:ujbׁوa@zŅe݌Խ5,{l6sSm?9!EyL5SKYܫ96+wPtC]"!Ͷ[R鴤ɒ-&usjW=9\`6  %Vl_G2`ܱh,JATh'AHRI>\9V+Zu&I8`Ӳ$EJYXzj*[at4I1$n)=ͣ"ޞu*(Use$yh3"UfohsfAwu0웥2}4g\ׄSv>DQmr
;LQVFHZXz7/kqW mȎdװҙ]UR6Vx=Edrz<0Ӗo"q3cuG'ƩKƐ}38,I"Eb1^Wv&EXy67<Xʋr~i<_UZp5@08q4|%HC6݀ݕ 146HC<PO!ƄS!7BdcNI]Vj"j1IHOnJhta^ȭ![{[AP_QkYTi tWmd	5V'I3 +=dLʺ\[dͷVzwBXMYVdrx[? @U,2On`HI:U  dzCԸ3uXf
6%ʃ]yng]w|o|sOř.qCHz$ÀDUá/]X1q]sgTqK_u3VCqPg=O&$1/H$9.}[4iAާ4Yosnk?]On4hS_1`btw-M|!"XA`r2z$?3$Ȩ@aơ2Q&}؎!_tq@3ohqW?(rHyzEk6g>*l/f+
>A>&8$?l|/#̥m*ޓRxGD;hɾj-bԷނZ)G(}o3"Og3`6(+5+Z%;{ȕ9̷yPS8Ȃ8\M6Ї0dpJ9Tk)1O{DM|>|L"[I<=ҫ?{<օh\\/Ѻ }o}v6(
{D	(@:Qˇˡ攕8Tdf"Z`xúp1ONؓE'O={ɓ2(,AKFYtjq=LWZjYYvཏXc$Vō Zb̄ǿHiy#:Ohhޥ6DDy⋹M4ah{Bv<U֥(@>s``Bٝ{قHߨcxḿ1Z$Ү,dϛ.(%+'5r>A^ȈQ7'O]ޘNǁ!E7\NaF`jxE<)(#L lgevIGy4u.( PN]yE,]CZxbnCI8W<ȏbĂ}q#*##;eIU"^VV.Deu7xţ3ipmKM3}妴MdWQPaGy/K~	0ժ%u(,wmU";la<agd]'i2Iele;,Ǳ&ug1}8.[<
5ZpPks5ܐ9uC+kvd8o,3onke\|.C5\tۮ،7z/>^p#nwh0c=,qef;O-,X~y}ɸl}$:z5ީYbɃK-CV|F2xt{Y\_4L'XqkW8mw,6"nHmӿ+8r%Rd;;~,_ĊE&5)1;7dB͑#/I/p^e]Q#@3HjV;U-IqP'T1=HƂ2&1r/yA=x oㄕuLF	yMCӍa֠+ul<&e,Uyok}!`a%xpI\Hkirnwg=Io!^g$tdA>3ylRBRP*ń:*yNu]u	WK'o*e0dl^^*NFfQHý5oNt24WK00M;7IjSi7UYQ6=c[
C譟!f6ǚIGҖ;Ly«}7Rre%/ժᅥ	5;f&1Z-nǴ+mZHW_C)ڪ";tF,}F7gEvM-= Z<McI1]$s&}t)CPZІ[K0!*Pq2JH`Mu}I-tӲVambpƃ䐖,$tDql5u3W_C{4Hm0RCKeMTIg$O8ȷ/"5Ejs9mp/5.$.c.ĥ;	>7qp'Ct&?Aj7ۍ,?[5Eh[_+`!J'WG8 azYA=vHn'6fLA=!j/wL-S-*dHѮR<?ʌQcD%edVcLc,!4JAf1+	9't(ނHa7Il젉δVNT˸{KdofS|+p?Z_<PzϚ4U7ڶ:zimWdF*HjV
$yPD+=22SӬQ<zYK5jl૞fsC7<Jc4t֩mjTlSv&tޕN:l=yV&q͑3y.E@wt"DTTSg<?*NcV]R V6[-L&vڰ+rӠʩ	)CݪѾ<0kGl'"N1ة30=K@SmwIކѾ@<jBo@uۢ~q Ac4w]@B(~4%Xs2nY7iMP`FI(mu	\Sm59"kT?,ri*$ wK5sBSy0MRN9>3}pc7S|XٵP-/o{(S7 e!eS%.QE1S4l TF:#<]T17.ȯ("jۧ_~VpdĘw4G՚rk-c9\ߛ]{u%$S8d	/**OAc0f+KA8|̩>Q~xs"ia)&h'Ih,E{_(Co>,:KKt^ؐ|fkֲU?9C}K-Vl6^vMkBzߛ"F˙qSKjoRc3fnӯz ߢCH17rDT tE>#:+v"cGLAƠ[/>vL+KV6Ok/"r&:ZJ3aԿ"7eQ
cb,VMLc;ϼ@>thJ~/y߇ٿ/BR#ԔOe&exsFPh\_څgV+WFmWO:G}|l}?=#5@&d]'fȝ_{u{e/v0AB
~)I_48M]zO7y1&ś,$tГl"	Zqյ
$9H\Ifvۗy^&4 fHK?^Zh7%z#d'}mx#`-po:B')E|dDa8w֊':aDn<vqZ]QYU쳄jԢ
'r\b>Wxvҏ<06||VAb|Jf3L˽i:D!و:y'k6ĵZZv9_`[%ʟZ"1k/ 5JgN~U?лPKΰ6oFW^!4m7'Q*Kgǖ3 jP7ׇ_N9	8͂Ċx.'F
=G[+0Tr܊2ҸRb Sҧ{QvPKucKo]gȝެ?UЩz۬/o9KE%=?Lo2=1MsT_е)EsBsIh?]氍w нau17y]byу;s+?~b:Y &C590s-Zfx.fvoY`K7$oSV"W6yrkZ;vV@+;gòMWt˗6w;KC[+V(|ϩeNɭ-sFǳP_k y+o|8}`C]"eE~7ԤI]y17du5=
~XKu5l0"O47d雱1U;kmpKlz?Cb%`/}"w	Zs љprPs Is?6`v󰝬sţAw=m&j,%ckT&.vȯK|{1Vmn&x8q dwF'qVB~0?ݪ_	bd6;OH>ݞ']u2X>gEN~Yr-غAu>ٌfqe4xEL;?A_2/ʤM2 qsz#Czig<BZvt1wZܟ	Hv0|=8sY1(V}rÿr
 IpyMYqw^fe,Fݶe!2ɑ>ï4	A;<YNC#_ܴhz6|&o:'qg}[Ϟw72:nzC9Lmz7j*P	z==˖K7ee|3KSNW*]`p@Ce6r	lDۨu.pj9b<bLbu5,-۾Ľb2r%1Xq W%\y?a8hPJ[k=qT׹Ek^vrxHfUT:Eh	n[%0RFB%+-G$fxBAaSNUVTCa.PJuADEzfG|#bE=2'!0\WB	fBO!vVV7Ձ! XDE7V߈˓w-;Eqz_%Cɝ0$XT_ҴÞzrv0D"A}lfݪmm$	@
MƤ8V	_29ˁ<{\֚|^3ˌ_5s6F+عU"}꺿+DRa=Z=,ќ/ս 1[`]?tZǗovKOgeX3vV?W:A61ɴC~3vΚo=kAq,Y[?n={|5>\/XMeM2~r9_eq`{n8,"5RJc)f2LuyLK[."v]ˇXޝdgXdٵ0wDd+׮N8/Dr^čF',׮AFnshwޑDL%Z{!bwR"$vLf%^A_Á/,"y_*m Z5{h7Dg_Yq+٪C)V8t0t2lqo{Dkjpsl#x qkC݉Hxr+w&wt<1o&
M0 Xu.v#N1>d`:OhmN# tI_y%'bN7vјO#6cP<U	$ާdD,ߓщvTu:j߲D]6<q7>fLûȤ҃}vV
6]THz]^B(k=r~zD/=F2ȅsٶ_}ٚ~zF׭`´<\;oC7|0|No%*YT;zPDb@%Ҙ'qcgtY4lnS<LsH̢q>Sޜ[7UўtK1:wM-vUn k3*x؜W-S|Zhu@X6
&GUFEɿS )0^GgYCssKc+|}KxX\;xzo~Bp"dF7L%Y]Ѿr0>}2{s_O.1$@d]^/vdgg'b6/Z-9; EA6e]ey}mǳw^@o	J:&/OP#jg6W/Wzm̟jc^'7>yz<۩rrny%>\Ew1NmBj9]pVDn6ҊЯT/7W\?;JGi6֧i(T%lƺbW[YەsB~k0+?PRPƀNA&F:F%NlLD;bGf|:TkMM&Av4qF1hy5vfls0[.,eB5c/&*5]A`OtJPaT&`JyZc	o	n1"Klg!d
-O޵Z-ZnD^ӣ v(17pB)JZb =W?ܳ}0߂oc*Wx]~AQ@4RQckJ
^BeA7EKFYp
wq#_-ʭ\vx}`BXU6\zj52ѭMM		<Rĵ̩o,eѻ66<Q|QփEsX;KOWC-;Wn~'a2o-saQ󛓋:Kڏ#o~IǤGOfg.,׺PeQzn$UUݾLdXyh̬W2ypjZW<adC ,)护S]0YKV8aD3h^6yg=BE?wYޖoZ;80ؠ].[D렖8gUp|:l\NcT6c	3hOuh&x`_zq_c ^xC%j,>|jY7ˋ(ePzL^qAr(qGNAsCt&-hG}Әupkv?=Зwx穼Ok.3A0$jCo-p<~Ha?y2pφ?l	 d^1'%,[jִ>5m26!pñS+j&Ϛ*v(RD;
uknD.	WMFZ?h-6(2XYڃ*SӬ#QA.5$yڼ`ҷA#XRtKYw;`[UZܱu Inp;BZ1vxE
"Ό?&X	{Z-W$@$' :;+qH%qm4<ӢsO9ϡj3\/-ө}ZYG&Գ:\%\7b3ˬ(%G6ࣇPfB91td[t"ٜ>d,ϛOQB\O5`YR/h̥|l_\~Q Odw-l/dҚǊk.H\0{,Cn/{/7N\h(<4:[:AO4l+b{jmuCC9ZġzfJ|aT43Y6cO̄$ "vc&bSNOjok/zY<~た vgb|TadGmPi׿ϻkdͅf;Mpߦ}k+jxƹhl)i>#_CbO;<гjcf^\*<ϙ:Gj)!P	,)[`pːo}h&K4hoE~+۠ b|^_m`-6iA#hti"M;aBYUO^<7l?zwj!5*L󃏾ZaN^n"i.q4 ~pΤ13(?X}fyD#|!OsX=zG:Ϡΰ'l<X	)$^F.͠M椣%等	C?[x$`7.YpSi^Ы؀jv5^CN HX[c&%=`FM7/rCNh/ 1x] d}> ՍvL6Z=e\V~>_@vƓAqh嚕*'x,lab- /_R_PIH)xc=7[z-Uքa?Rl9CZX27`k*<X;L
!	f2}TXbj'&CJ²Dg->vff1u(+M:Ɨl<lgQR%[6w늴8[vc!˚˝߸ԃf{cb幂bQEE5|k8|{%Hn(dg`9}:!`ٓ$ 6KJh3l(s-1:O<ag*9#	MjS	T(撐	~f7d6@:
>bNdq\?(Jn%o.kVss_;{<=qh_)|mgB?>Ǿᣳ^ŏa˹>ds
)tӵ)gPW[*_ӧr׸h|G: X21X_B҄{B̺#!vi,ϐxÜ%)?Qc|4e{-m:ӶԢo3fbhZp^pi5Cy8pm#~V+n@;5CaSVsH>AAܮ☵'I6N)z~R$ BGޜUcC4'|8JHA|˕H);܏PzOmc>ޞ{
Ÿ r	.pc1d(O'U)X[%r9ha*6]skw>-!"`Nk]'［A";kvt	=Vk~≭cr&7 %03RT)^Gp=VPRg^C$\^5@!,r擎7^ۏE4V\ׄV}=Ѧ:s_w7k˙zϻmf2;/%*[{4fjagцng8*MuH7zaK+BYcrXhg.i(jMXo؎: CUGeK.#z #~ {1$h($&y9u>7j6w	i`y,^Esʷ}ML_(/7=sD;iJ3ҁEjC#ߍh$:VQEsL$s0<#rIwP뎛!F;&w>l̷A&.&9GkN븩mIavF'6RW-|>J}eKc
lǦ]/pύ$NեǏ) x|N~inYO,/p	N$ UIzgd$tZftG?D}os/Rwkyy2[ǲ2P9>TAh!yOD'm.2|6-gR{Lp(yx`T]aEj{M:.H1es-H KlU,{]5Fע9֎H\zZgT6 <@Eyxpy8UӸ){:Cx䒲/GcXWqO^kFW18T+_ã}H<"xyw8oG@	k6j^CATwi-ޫKi]G`u;M1h[~>"`.g޹8kN*+Ц-;Gfm3պ+W3*4_uDӗRm<e/7 WiBecˢcHJ[1 BqJb0='O(=Ӿuuwp&-LwL$	G%~!Gwrk?dsWs 5'`8_Pؽyʪgwu_0(Xp/\Byߌ[^Å[zl y[V&)&H|ŻL:42Zh&Ƚ;ޔ`fܮ44gS'Vl&p^vВ] *v$=()C>%+cۚFgFUl߆x>aE,6N<^t1/E E;"o^6'V[]=yD!1F%K73r$|	!W:i>mAfj`5]M3C/f2u2O'\#)AhD@?Řkf6=~d1:7xwA7|:f/f8h!Ҵ.W}&#L~ t'U>T=gFMz׿v)Bo2'}ƺsU_p4O;Rn$/ Nu~ZFgSXQEbҀAGK2dDφM%,#,#K3֞AS>ǎqa-ۂ֛ܤ_>HO9Io@E_oR<n֘QʁXQ _ k	lž\]}=Ym9Zۡ?Gh10*Μ=1Kw0hņ{#q̌>_	5;q%%	TT:Ql&/,ǻMٝP!mdX{"U_2Rq'6Ρi"ݎW?­B'g݄ťqgOeYצ/w<H]=(	IC)6FzQ`(<ݟwBǼ˝D'	_&{+z$03]\'m$"lOu}iqڱUoa>cVg\+%<4$}_pu٭,eJl䥮`>1rutCq@M}Zl}H܀RkSkT1iY9#<#ㄦhg<ѧs"ۀ'>~TBeHOZ	wo7մdҁʀ3jŃf)D|5ȇxpȜБ|-R٘"(;#	>+i^%H$e96^\/{
\q%14yhSMn$_#9lsOhyrM&UU'z@ g|+#ދwy-X;_ɗ=噚<$^_>ako]Zݸb&K
dU6īlrÃ/yҨ_Sp/A?q0ad8|'e~fW4EvMs`Y:48Ռ9s;6U<2?|JsM*R]LERBԻlšQetX7]SOZۇS]9ڠ+<zg\Pid9hKZ3:>56`k(*<as"B>8LfsznM&	.Fd.kk o@{s\<:z~poZ CelHVUx(t 2C[ėvgbX($`j&+N/\Ojg_9jŠІ\	vW?\#<~)bsMZxP#]Muo^T	FQQҫiۡ*0Z4almk_Ƕ;	#2')Ow`4PMю iiz1쇱Do60ҍ7n-ڂ@^mؼdYLX"LwUa6#ߙ0FfLQ!ř!a|{Fئ G,z%ymE~s-;ɺw:C!6B_Cڸh(luw iWp߯#P(֓U:yEb1^$0!w02ӊwxlfð"|rk6{YԘ43]4k,IOd\<z@@e9SGOnw=Z'y;$sOPF]uލ?c{njy݃(:]N?;,OS6ߚWމHY1߁VhSã	 '`,`(a%iɨP/R4rʛĬaag3YwHH3:yu _@n0`:@k{k@)*J\T0&ul@iF~ug'>#hi\_fȘ8Y9YyǢ%o~#NE,U,8Qmx`4ǖn#ƊGzK[4G7S",[S4񋄰6trPkyES\Rs!7;S      Vmo6_q@1.dqݥs$ɓ0D%ѐ`%v݀Fr&=Oo+Zz=֫\/yvJֲz Hf6Zn%2m-APmJ;T^WE2kЕP
{
p@T6*12MTY/8yUTE5кB	gՠw9:Cmm#0WBK@S-?6*zr#}X[qN4ͅ*dED0#Dl\Et-diNSC|0R"[HxqxܺQxgl;psP0A"	>vc\srBӄw>#F>G(Ď ,v_xp @&k[:#WBx,;>OlR<	(saF	|آQi3{˯l9`\`7,H r}ReSISߢHXGK!u@<g'}bX91mN8Ih3ڽ ux1,a8#	-fX0-b`ĵ	i[x(Z=
o湸zfi[3FwK|Xb85=/!O|&B.}~lH@<f=ȷ[>Qey*pg7oq+ļ6>j>NG<o'xJ.Op:v2}HQ2<ץx4Whկe.Ss8UeWX\_U"SxodF>_-{-2YMlb2VK:~G}BmvOz-28~2s*kiZ7DhG;绘5ff<7DT2͐O1޽ZB{+~Qef=nl#o;*־,3$ilmDeQT|Ld)&kɫ?f?8n;҃6Fs,_K_̳QN!y!2Z9QG"!Rhf2xM?B3zH@kœ-L(8V?cҫm29*aQ7!O­}d K
\ũmW4tx>HΒ,")4gV\TsQQ97t!{U縭c"hRoGN       Sn0SDvT&Q%f3$mVP>|;;ж8+o@gBXgw{m!q}T5lBaQ!ʚP9bӟDphX횽XՇֻj3rl}eYKvNfgW}+-d؂wp5F=0Ш鉠q,7ДE>Վ	w+xOO*#8ThZ%v-99`!$:m<#|B\c6VCdB>`gH8
gr4ݕRk}.3C"M|/\x3.ϔ\       Z[w~C(2rJ,"OۓPf"^$+^7IMNsK`>` PI"΢8trq-ӂ.tcѺݛ؇ x83h8b!x
p;.͓|fC|gQNOo;Uc[7~dAHA#*pܥ쐳5Wns`:%~c?E;.NxU+E,Xf2-((6Ȋ<P	??1`K+Lx:b CI# N'~YXedΌxVvCBd09um̜\YwtC6g<kC!3,i553k25ُ?M(8h=ӿ&Sf܎ilClh?b#ư̚@3S~ȰI+#+gehQngۉIhajqU2>y䕢Յt?qYF=fꚁ_uXLzCh5΀mؿu(ͦ0g2Սh>hhyFt630P@a03 cKNg1w4ChZfI͓13#.ꃬcw:<ZIk}ԅ	,D(+ӒAk:N0.06W&J#2>%W0mH}u}O Җ;I("BC{>]̸RK j&<¯;)@/'1ua{^cDU.
G
b@4/</aFF2x^AX :g Oӝ;t#Dg[$.ۆU-@΁DG(BwO|L}$OjU"MX''UN ޭQ"m;U_>NVsNȝ{\!޽ׯYg 6$s'bqHbq;EX'}#p017ŐGϹT;\4I'+uf{wPgJP{<7eB*QNriWnlu@ttu.Y[m'0oah9'[HB)〕U墂KwPdm45^mpQsc{$h{	T0iR Dl-pZXX/ !6B"0(Rٺ:\@.A_BvY
RH޸ $ExyC}q
;c6S/1&!on/>= ;KG,w Eb=h]gG/,e-O$̗'Gn;htDHrG!7Q{$}{и
~[WCV)^QV9xf{q8MB#;UM|Z讠 K%N'	=<4sma؞ Mm2Q%9>/RiRk$Zh$%%PLK^%,iu6Q''MqJ2V7j[THTJjk)sm-*oD_[e_v^1}뀋 .B?Mv'\fǄ$7&V'+`)5uBbܐD0ǶppCnDL	'Wb9ѾbGw(P=q<135/mk/T1T\fv_i)bIkxN4n){":kCZ]37unlq2ԫFYVy.<yUIy8<C[ԘzXEue%\["A:<nf_`%[)|vec%rx(XdIN$][Kl5di(An^ô"JBTɛ܏)4h&_lhމ>6/wYu$JEC餛ŚډA\Bޒdo+sd.Im/6W\<DxAZ@gUTbq^y8z6BL1ays;M!>kYlUbJ\zz;R%ѰRp~]S$Z~7h*cBk4N)	ZL?|^K;hIQ5JJ͙1=%+#psqJvA4PT<i8R8{:? &\
=N޹(ofA$*K(rnkw;cqBiȟMqFt/U^>{W$DŠV^Vr*/ܫm8Hml>~i:;QR\/	#෈SaVqPCVֈʍ:sx,'.eؔX!Aֆεl?D
:9n0Op'5]cnu MEo켽P67'وjP-
"T0DpXo[޹#rb!Tu?NWJ<OHn.:!_ډGג>ߎn;WxoO0lu{ϼf>n=\[+wɑFGPgN	/gQ<TVbc/fW  ڭy>AA->"_#Ij.zyJ>g+t/kop'N |)=ƼG{I[lN*<PhX)0ucmMgcm9@O#[x`Vp$J`sHV¨\fʂW4$ïdč3P~*<ȟ>Ez焇;h E%>]t=렳OaǩSiҗ |-ccϵtf0[Kq`>oOԊp=5zE,Bf[} x_׿`	kBjm,-# -gWtW-I!=ڑaTj9O\[rjS1P
kXxǮ)pp򵧷>wǯLc- wVTJgha9Ny0o<vuWB1       UQo8~WT]
KBpRH$ۚĀ!F)Uo![O`<o\g٨ep7Lޔx/KpyEDFV
DU*ͬT%3݂6[,t*0씵я
8e@BѢPhN!wjS<X\	U#NN^*fJ#ײN[NX4/ICG"X̑,HRNVVM~h	+ejkh7@6)]'p<O{>fc-CCxBGYG,NROqͧO&4?Z>OXB CPQYZh@g0-=J`ƒ`?ytxQ;O2,B?"ǩC#icglCX=2H~+%GCsP',H(@_A:gP,=Fؔ$؟wc/"a3VQl1&%<`-q<["#
a)w(cIg<`?3-qGN3'NK~.x0e85Hѽ #L~fgb!bOX0SvM)%$xc)kg;s]~S2n/O/u3t꧲]<M_J޺J?7FR!ʞk]arPDYbVe.0Uĳ¬Vn;t:;:^~_mM!q֥*`_}?u(^Up)x.&K 4Y˾A݋jNK-Pu)9(l=xCGUZ|jN*6\>:gáYŹ̇k<jKu>y 6s~VSu`*~`u3GCT|6yFhľ	Rm.6z(UhSjG2ЧVyV u       Xsfy%v~}H6$T@d2}N4ly߻{ҁp⾶}۽ݽ=)ۜA^dQP(7O5.Au߾4]$c9d,g=uT#MͷE&'!~@nyi5xnBYa043`!l>
qP0ĉ!JIRN(f9j9S(4+JO$iLC(-7	7b?Z|G*"hgEr. ,4خYRաHq=_,x~`,Qwmڗލᘀc`L#0&C<s̳~pQGQhЌ-?OuvOGB!cL<t5B͆JD[y|L:Ʀ3ƏFY-'uiy3`j853gjLZ`dXcs#OdKwо$С,::7&c8A#kcBHhCcl\yw298+Y,opeCr7nF}6sM7=pkqYtԳIG=n'f<۹%\?nMwȭkE<B$qW'jd]I6XC\7-3n>eb(EOK0,"_
c(V6})ޜ,tp_lɓ,wX"!S0O<|5Q	mL]al_2t	`vc_LkOtDK=顔CEe#.,@6H{Ң Rn!,D\Z5k*GU)HexR,K3#y)	GP%aA.c1H5QpsPTާCn$LT.9+nXi \3*Ϝ-OިqMeB.xXMloBH1%wĭTy4r~ű< .3P?]]àK|?|^m?vr={ßهRpx@-픧Vl
6%y4q?g1M3+OzVIל1lNxjPU/-Bx\3	+{e2Iѕ^MaVc]ğcOPy3Q{ʔkzǱJ=M1§bOP*bidt	-R4ZC&};C^GUUf$Vꊐ;qVǦ/t$CKS,klpcl>H'c7XnCFdQm
*/N_~,맏z=<"wmCan4Y>e>ʟz(#VG*D8rMnU	{m|['H`HG6#T"!nϑFHZ-i4G+;dr`}QP4/v1ƿ-t(*yaP
orl/(Q?6u#0;ubX2|}16I e)CrYwDQkɫ:Յ>o;QOҗۊ%TJӜ{g2y:~|X-}wb*K}gC~lm
bQ\R++oՁ?[sĽiVӿz_(T1+<$qo5ms~x77/M7.a
b?)@6H֚ȇg-7g[*鿥pe"eEFlxpUli3SL $`bn@1}EoAmv9s(Rx:{h}Uz{*b86@Z@a1jhcT_5$tJO{#~˝>uv*9vhd<P\>JYOqkn<R?=}:H.Znc;F;}1ړ+BǗ٣PJtH_M%EjiוX0Qڮ:J-VnC|[:"%؂ԾRU_xB)gٿE-       MK09 Zp@\l+	TJ2q>I6pl_g]b;enGtPC<èS^ &lsUH+6PWw,3]>$Fsz)xBdّjV <:SQo.        <s۸;JJdw^4n8;dn:	I)%Azo$@ܴ3e`w_X. ʂB<ޓ'8Ͷ9_wC֌tyQuyD$goX @0])2	ӈuް<aYl	%//O
y@k*HH`HiIDx㌜<%K`od9rQg!Sq$9OIR1kg{{O=#_$h?`޲LBӄi+
bc	0!r˓(r$9/KX>mhOoNclˋ0RhADH(%hВDyf{-Q/Y RbJR\`9=HF%|}fG#SgM-AcĚJtC/W|Ro|I]*<e4L&e(i6W+W`uj.iq;LIlV{P.8MD1` W0Pwq>ICq?H"H>ÜQ㑚u!h?42DkGcE2b12X
 [nY; (],(jn"ZSz,X {,2\A
'.q_-8B w=o)lrvJzf(u|{0IO?Q}_En0۫XCZy)yEi=Iۿ2İi!fޥt{gJdV"F{ 3T4J2zU«
KEKViHEbjY$cup<f΃@Eq "z@=Dt%SpxM)l83ʖ7"2KVXPH9KDg&?һ֛~tgckOFJi(;@s)u-إQM1C}yͤ=wC#%ٟ{A|t[|znBGb= 5u;!Pr\]\5Sr&#ǝ&Gdf9#DB(WX(sJ04tatL 0
`ɟÏ?j(4~Bo"XSLM S##5;u@>k~AkW;'KuZP1(D""#ʪ@0PBþ_wH* aE0@b/+:^a$!c/ם(/S!MW^.&^+=HXx;PS\fD 1	46-AOq12ֆ`9-U!*cﲻ!WI3
!Ŏ[@ay(A*:03&h.l>W;͡BC:<wxX^Wo$L)<FG&f<(SMiw2]a,hsUQ
at6țe,~йgO<4F/UyvK隰c	4]&Żf?a8-pڝ<{(&MN1*Y@@UX\![L`0tg	.I=zUŧ_f=
 L_r9 +^UAd^v(L:<YػA][|9dѢ4c6yp̙w{+L؏UEcgO欒}	\¿M5gvYߥȠ)yP ͿSEr%	WjԬ8kYK#^Pȵt>u:"9-)E)ᑲ(LcToT`A̒X&˔1 /'#[*xL=_gEWvgGPkǨzO֐kCם
z"HUgy8,O1S)%{b$w!a@>EWo`90PXC[UrIu/ ʺ;^}GC\Ú)ٶJ	riVzD뭭{]SU+]хtzìe 
̷_o9![FIj@G(wo)v xca7q*Xi:P7:(>KTY8, [u޷p{|iu5{be0iܾoW/k{W$i8,c=?d"]	DKgwK!!n
H)ki/34!҂CT7&=p?cV9jI|q]+x:<"ʯ|a\NV)y[fCu^./QK^L<˰.5yd4maB
54A"Aj0n)86ÚI<-sQ*0&'g=7Txm#bޱhGe!>Vc/O-IƬT{2T:h(_nVx+/Em3e,6f˾hp4^5f8s [Svikmdfwx'ǭd%
FQv7;mvbBBUTPتwHaTRZnEB|hCa	(qOpHKDV)1?n??Tuvxss`x>9} wPHRQgdxKL(kvB/q7ASvB(]p-9VT'|*~4J,9 a=`cPLJoU/x<R:S2P0FcAhn]z́@62"y'7$'iz
wSN\4)𾻛Oq	SbĐ ~
1d~7x<4e&ɚ~dǽyiO's~Z{L_r;un7EuQa+vw<T_y6qH^ "lXͪ^xuOC[.*Nח5Ļ[+f$1"DVDU>NuY}aK{rȥ{Jgv=9fCj9K(N yj3q2II*kaZju!wpY>9{oJv**xRYT^A=~fe\k2׳jgJjٮ[y*޳Rv1Tӛ6L4s*̓~o~Xj䡱\#5zfq=6!OYVw]qFIr汁%yc?7[
J4D8v@&+0vܫilz뭃~@\">+rWU5g	>%\?X	_0	Zn9&u9Ҁ"-_l59|z'|L%|r3rȡR`lRi7ۅR홪zX_|I7H2_CT%hu}>;],x)&Ka}7ug2KFs[n;<]4=vQ:~^?ͺzQv*ۜf_|qfjRÖ=/;OT&uױI3@Na'ҼMQ[T˥dNo)UnND>;{8|TsۮLUg[wl!u=HV6Kî}4I[IZu
5ޢJMl7U[G}0491, :󘋭tˊ=q5Tߍ*RX1G&\-fcܥS&GAɞ9q.Ǝ<c.nogc4gzg]VFêghzkM51QOڿ[603G3.fOrz͞lgp6j:d0#שu@yEL}g0`)5uVU!r($h2c}#k<GyU@J=2ڵkn(4UAH2c0m !\ um6W<q:OꎩJXMu&S
Zz_pdH|_x>9}r̾C]zߟ͜~XFRG\Sn״"w#NtUi?ҜuWj߁6jlʋle۽<tH  fLaC   "    +
B   3`3)gEw  *   Lavf54.20.4      encoder=Lavf54.20.4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   Y L              3h.Z?(  ϯ/\ž1<c1܃ư߫"ޤ_TwrPu0"x4<'aKiUh.x	
>t9*Qs5D	i,14dlkH흃<̽Mqt\#q$}tEC JR7REV|]n$kTi<VGy)zXDm|v}pnk iKS20kr8cBs$ԥ05LbVff,ײݾe jKEjr,ɭF}ՊQ,𭔭,&	[͐[ Vpr+I#g<1	(S^z@$E?sЎ_{<=WAHi \޿SJ"3 X7xFxX?/m[ݴrq ,v$z7
PZz6]):Ư&أE,N7fQ:bۤV`?baGDa#@iSά Aӛ]T,(Ym*Re3LZ|1 nȉmCDiNFۜq#-]M)XIHa&rX [PbQϕ2,rWdC-UkD~VT-K5$",8p6\W)axfVsDqǰH?pI=gΉ30*j\MRtn*_sheB賺*C=v9y[m1
r3C,]\)EW^gf*w4[Y#6U.rkM)C
-3e/Ego2W2Q)0KufqRzgJ"N\xnyj&iJm][tzF*%f&M%Y3(`!!0P""z;<#l?&t|[fK@L|!r|<@3x0y-c2$#{DFD'8.yeSޔĕbϽ5%K#ܹ̄Q|q[>2IQfO<t#L3Ȳjn"NMI,TClWJ(>)_[ɣlCj?ī|y@2kP>".'Yoۡ	]iOJv>h::q8e1T$48Ы Ȱwɞ|\2I٤N!yyD1~MqN̖C$2yюf=:a[H;dI1&28ʁ"!%/<$˞YT71%XMmn|ŒHwB>j#ܕYBJ7*ycfia^ETu~hFI%mw:Eå4y4mq:-G7GA9>6fTbY
#?_״_q-;t51P=)_R	C"ҭR@GC.'B*)4hU]dX\DP>.C$l'd 3<Aw8ɮ0b]iْD\7:1Ð L>K|)b  b;y4ȈHhixKQL1՛^U rFt&+y!
5GnJˡ%G<1^N40/"ɪOnoK%q$*!Zn%OҊѶ!%_;@qRD5d(d^Ӈ}eyҕ 2!|-*u-4	t?bq(b;HQLmAƅX؆EEL0ɒLf%<A"B|.C<>D|TF<M5<1`^|.# i'xF@ x =`
v$:l8GZDLKI'Ieʉ7Iז5%K#ܹ̄^*_	J77B:{҆I]Q'Ibe긝βQAM(MhAe?偝-}S%(GY>yV}cjwڠ:"0zRD7Z0\N LUw0D
:<TJDoemL	#*%Yic+L3ÈiQ9x|&ZGե#@syeWDPORqcU!l%@[i5'ҾǍUwk)3?ɠ*W<@nBD`܄+u	O}+\EkgVW	nOPq(췎肪=rRhRjӅb3s4FDg{)I:Fq#J-l'Pj$EkjPcṰ;m䆰8љEZ"YQkZT3/YUimES          sŲ1a^	(()4/ErQZ@M$Df\@x>)wc>8'-#T)ݍ./h)ZB|,|S?3$[KSxhSfB7
@Z=6̆ĭTHLNo
<gZQVsʝϻRs`1Kou5]Qʞw5HKZGKx=J[s[]{fY:Yqg5Re}?KQz1Nt@y&>`YtISR8AuL|K)A.B0iI?LZ)d&@HOl+h(YZ>as TP"cD](\hBE"QCi
RHǫ##N(@L2$H/'yʷb\6̐zZ}:̺kRv{jPsBVR]\rȬ.Y67|^lڑSX(p[ܷrDӕ]#Rm[R_?]bYEsH]x9E)7vi:kO&ZRk~y	u t!8QOhDP0@!f-z1I'F'`oENq,jr2,o*2#܁R8#Rϥ:4;PFǟ}Y"d %-0݊N5ӪT"Mp8L$M{H>0*rE.QjLa/r>Ô<ߕI
$r;m,VFy+ؠ1\3q	ep~ī8U'9˪~>%/ }]F8WTShX㈽)ÚLPSI]qSyn%
 ecw!!A'(ֲ'ʖ?UQ䚸Z|ܽ\{`nKT1ѡszN I(@	-ۀNwDA_RRkIҨRT%W/f$^@tqϠ(rR=0FCjջBܼ<357g"~;Wyֺz<ݺd5h5NT+Kǎp,dR}u,g>q4Gfd7ޔ(0'O4(קwX=۫$5Ssn_
|}<І]Gƹ%\3!%x35WX\I!5r.bՠ/4X `LyȯxeԒpRN<
TxQbQN\2n((-MD%#rLQt"_ͲxrM.|SstYO诟^ﲩWHl(.u+J:)ݫسvgV}Z[w2ak<Cפ/6@EY%ۥ:bL@k4w3,!"!,m-ԉ*Xl%YT,wMZ)vkFP5/^}JE4(ц֩YvED1"ȣqHszlDL!%\)7f[1'"͉AYLh#*Frz$jIMK8$޳"hJs#Q&hHadFtbH/P.ի K1Ѳ[#wtf EVVEqw/%P?DߍkChJbﶙ|JBr&.viwc+iWx,9 /6cdd4	1uwFE1<[U0e S+1fpU{qNUEQ6bM2) #k CJL $|'j L2Ȧ`SѕW|U-_Wgiwۦj@!}P5QB>ƳRs7Н	A}JVXh'؄`F\8(:J eGE65>ݮ˲m
,GDX^d^_qBCvUEdzStj;ihIN.=Qgnt\HI	+Rl=u~#vg:1C[OLEO}bvZX%gYMH$Ԁ4=4UBOf$eZm)P_
-	g˺ (f[X^`֛~`Mzmsvg4 `cbf'L"zupT[b(ZQ@_Q9I[#dyWi6 UdڜT:W[;ݹwml-C2Q%z/U8uߒ"^=kZCJ\OksbYxdKKj|t̔}nێzGI)NZ*MתƳ.yDѥޛ
	&ﻗԇ,!0=Ny%ٗJ6T:Rv:X_/]'1L zujqRY[Yso¦ܬGWzHd@'yG`^AȞp+@GݬzB9[f~	W[!!dƷkgҹ)('ppI26Zeʤ(F p
#at)Di[%yUz^Iy{l#T6WIdgSLcv6X?-_~uj^;NrHQŚy,]RJB/׋Ulҧy^kWQU9/TzC~5!W ȼUǥ# @rU0L%	QeУ'ߪE \
4+x-c 	P x2rYEj9IN6GX`kg^)] 9ApX7=_ar^1|A(7fJ.Oɧﶆ,]iC~P_r#n̛QMJ7*EnѩlNZ7+	gKpݸ0LDˇ"gܛ6n!f<j;xr:U/c>^F0
gP,q9LN1g(KY.ǝ%];ʼBFˤi:֊ &Xq2C$2<$$$$$4( ; MĚ̍.j*5l[>lqLpEiSt8'Ag5;E{9*Muأ"!⻒mՍ/D}ϒBDsjcUU+*	fbCh|Z|j&eIݱ?UskxAuR/>zj^Zc~ށto'/.G1uuvNR{
qj#y;ߝ).|D}L99֢G-5^-HvyuvCb٬F*,-/ՀM˭},O'ȭ酫5
Эo+%jfK~kޠ)DR,rSB}*>ّunYⒼX@V%BOu;M̦/jS,Z<ۭF֣ M2`э)	-+ߴfMioW"0UT{Z8?GD"rP(閧dn=cWAݶU7}Zs%j-~M].=c?[KtX2JRRLSʉ4c:l'GNO_j=!*F|O;i|\ Fߐ$
w.|r-* rB^1{ؔb$]LR@HGItoL7J^G񳬱WW?낂;{Jޣh_32yD/g{Tn17C10,\H`fn\n\>s-nWű%E7JۂW]QM7\Quاa2}^UtaHMLRݡT]=K5yk)WDyf"nL\&ǝ;EO*`G:f\n8k1&XX8wlBB-0
"kC-hD >b[/0n!"}fAYm2PQ5BxrLYlC'Q)90S2Ɠ8L<0r%h.?	{mC]:ߢow-/MrojrR7E7ȹMz+uRR4LpQ2!r;J<[R\TKuq[+eշ:V?~_\"M^ZZT<$&CؖQ}y/sc#Ն͆4+#ʬ^/:h	|+(L
XwOic7'> [pQQxňPHD@V;-p	LL_[r
h*g,mJn[BAD@	1ga5}\%<C,i;C#0%h.?=esߢogr&*%+iDH~\U!5,FrYY9{R:
-AJSEA5b][sc
q.1R%ijR*$7%GrYFqy͌V5 G*kHQ"oʤH&&Q]3[dV!BZ#{ .1Z	jFdI_tB,BMX2BhY(<9&,6FGCؒ\%<C,i;C20r%h.?>]:ߢogr&*%+qN[DH~\U!#)*9[,Ĝ%)×TKuo3b}UXRo'ۤKLTZD{ԵJ_$9h-#OyXl3@)+#ʬޑ!95JKU!TcەiI2߆uv|Yh"0-  (MoD@V;-p	LBHܑ		SDQS=cl97-f  j䘴*Cؒ\%<C,i;CL<0r%h.?C]:ߢogr&r`b}ٗn ɵS6V)*9[,Ĝ|%Ip]Q,a&$A9cVXBY~jKPV߫׻ԵJxI2MÖ{1ߔ3;f!IYPsW	H[ڮ)T9aNx@qDc۽Dd pPaH!J(ǒɌ
.3g,/b~ƃoljڻوi{۷*E#rIĮ%cjڊxr*'Tk*JۘSvlB(Rqҹ*'*j]=/k#VP|j]rl9J7\K<7Pjᑺ깔:vy>,pHr0I20Me@Y'
#y7$&M_{> UYl@J!K	HZ{*gREVuɓWKBl0fIP1P2,bN <GazYg$iUCb2Aഫy=$9 MMk,RbϓP UOIܷԠ6< ^IɅT䫧4Ln@&wōٳ*;+RnXI_j?ͮpHԙ:6Q~3Hr2SYeUx?+z'PU5hw*#
%_BޟQ~Px?K(+ ApZvjCGmï횥(00pLύzQ!Q1\e$ѵF !ɞKDU>x&ʒlDչֿL;3=Vi	\A XQ\U\ͤE	];ጽ4sʓK?. dG D1ăZRYJuH_M]OJP0"=AtƖ2-XtF=-$7i	_	sNrp9OǞԚ"}g7јqg =E̠!$,PhC>]}YG<}eRrvgѓDAۓ/i[kV,/S렿{kdqBX&ˢ|t"ΉGW7''&&ʞ2B=.&R+BYNzjNGtl,l@1|B$(`pURcy[{do)Ͷ?@V~6 LvsVG裖X_"L0bI	̓/aET9ƛ<I̚\kڷ<vSkZji_r,$!p'2rO*RqL%Wn|]q;~%$݈R	:c}+iV
vC{gӍjBkscWz~M^mWԷ[0ҠoLq]Np?wi|}L;$бvLSۥupGu!L= ug,BbX#A_Y5%Bm[GrJ*m{Q{h[~ÇraLܠD.ܹL촂am`ܲNI=KUڶ$\%.*ߵ嵡tm&#(1σ+Cy̩u߇8KC60Ptg9N(B^( T]	7x]>V]>٨_5f)yhre	WI4-ޤ6fvvuRQ` 4z_Sy`IIKMmw\.p 
!#ybYsF6G+nG(򴥎w6-'~Hr%ԢZ>)tc-|AMꚱJuS(ݩ{G\>I\	8s^^߹A|Qnd(D%-+Xn?8	lzIRv/:K]T#!Bl*=/gPQf3/UhKZ$IPw]݋w2oԇzb:,zdJowX	o1jܬ<0)ZAd:9"Nke9Y8i8&)D;u#ޘqJ + UM%!sď5ް4aWVU`@XVG{@L	ST<e7M-]9-^zGJYue?&.]Yٵdm,9SeIR$>Fe,)5)돯:Ғz	{<Wb	?I,T>|NU؉-/6!2*=n<7.6dWR1dwɼuBTN֍ܓ~ߩ/l O
5Nv2YA}y9F+E:ݓw9#l9PZ4LeS; A@I;qd<:5zpàa_	f#B,|˞W3Ĥ!&-;TVZ2J*2ֵeSkYR:Ŗ2okR>÷nKԳ-^-+J麭jÊmkNıK*ǨbUT)RK%~I"k}J5kVql[Ӟ,[]0]}.}J6	:m_lAE] /Ϣ-*q,&u:rQbh᳾"vg[ns<
rOh/: v wFOF/^=(1k䐨g0X'53\2_LI>%%DGFNsU?@:ƕ	*̫jyTTep彭K.ϰے,j׹-JҺp
⸭~m;ӱ,zʫpkꞢ*}U#g{z9^.$MrwoPcפ왭+v9s՛v`_oo_R}']X-Vն@9D9)8e:B^;Gcwq'EѼ׽x/slr|c$Nŀ(IE\gF6?/A} }?`A4"|˞W@N'<LZ2w˟aucJFIVve]ekSʦֲvB޷-jYv}nܗ%f[VɆi]7UmXWli֝=ieUc_TQU{;E=JTJRJ"wK|1]V%gdl[Ӟrſ],}.}Jm6jX6>	CX`3̢$LyMweH-b6mi,uᓿX6cɐFp%yM݉-ḸG$0/eNҙU:ْ*BFF<]mQïn0unՕ@7Rs1f.!kOm׈1=1"zDm{J~'Wo+E9?[yn_oO۔DXޜ(
⛨*:WdxkPZc\*ةXHLpC?f_{eP\`嚐zՏf\ )5ULYHk5M!Јq	vְ(r&<,GWL!#g.&	&kQ0_B*4ĎW勃2TӬ75hK<C} oBߪBBI.)qW,TD$4`kg^Jib7l:p3	:qz!RdImUE05#ntQ
&o .m{NG<&LX[3tꮌ<?\"Of93:(nN=s=*mڕ/n۞rB'8@yٯ0^si[V+Sݭ41y,T)Cq愨q!E>
Kace6EA۴Qv]}FY-4'}f"'8(J0c9p{P"+N}cM¿.o]T(~4ΖьF4dڎs{28[]܈.n34ȱ% ӊ/گ{ɮ\_<d(C"sRiJwbjΣeTQ'B@2K:yc,xvC.9"֧"Ru\RM%X*#Ma$q4;lxBOu׊gԻh2Wx.ȞڙZ\56'tzK;-1>
n~3켙JP^:IUAl`P92eOC/(	XnT+XALe܊[MU2T[ubq9	@艓VzZďmI*
'H~\Hxڌ*ztf/ɫ<qukQ]Kˎbu&Xx9e8⾏DS;o"&$}糉μ\ao?!yRsd*A$zX[#ql;Z_#nnYz>؆a;dGhʪ@ܢ:h¼Ŵ^iPSE>z;%ޯђQN=M$0(]-1H;,jrAmURRsTDQHJFT
Xv+2Vd=
S9gLr]JQl+@+%榤DjfgoR>-mi/ȃ/ʿrM
ɗkFt%*5OcQs^	"'=''÷Gwl[\Y3Ȗ߫;~/t":sK6?Ӓ>뜾|\9i:+	{卾!8Z+eLC\n"W6CE\&R2*o1-$Y|_~K6Wk
`)$ϝi3Kh#XɆqag{MK2eg!㜺	yp~ $UvC!VҀi<ZFdĩy_YM՜ֵopQBXuM詸<mkz*DnF&!x2Nҳkuײ,9+E`$|얖e-9}gLۖTW-!zdO.{%S6A)Y5Eil2nH+_H]oPZ)u`hN~7ܙRC0L=Ʈg?oTm$fSmB^PIUxd2ͷ#SzNy!jKJ"Ruf/Ud
k(,[T``A9D9	Ksҕ0JL8rIOMvihjNHf_~1M}.3_Hc/QFeg>X/#)OכEվS{ߒ>}W=k[/(Rjszp2jԍCpl+ܫ,34ᔀ\BF_"+ƒ4<l6gP܇Zݤy6x3u&TRi"HXLǸ*&garٲ׊2N3HiKoKСҗONuyeU) FhMoQkԜ&RAڹ: Cz)d;6cb`߼Lg9y/$l𗨣2.$)y̧_\+ݵDשpCU~ș5HZHFz-(_VjjTXbF"XduI>&JH0M񳫯ٟ#@~{yRljv_ԛRILE"iӏqU&Kt	P`oo|~~Z~?RF1\^UYf @,&RAڹ: 0#d;6cb`%}q7}>X`bʊjSQupL~HF_wd{n༢&K!dLd{f}u#m{2dK/+vx55}MH
5&{LI3	|+JD_:. ^kE&!֭iM^%ԛRIvPT,o
9wh,N,Yӌ$J        *(x!E%q}e\tIdI>`hjvjiӷϡ% llG`'k'9E a`iIvo*!Q7ZD2:lhFa@J~Jf_CC˘(lc@[SED,cE,?;OCv6!'m"ב/am oF5,&۪ye[OmCeO+^RVgAoOagRk)WzQɹȤWTB{PꇹoUJːG˩~*(Qqu>Y*k<ҩuJj>(`P	\$֐Y֠i^
+hfqr6RlψEfr~{B$$sPvo˞h"thd=YQHVv[{oPWf9R[&1_(>wuS_Fshx&ftIv˺?Bʄ\]+.w+F%ZFxMe+\q[!}c]|k)$$;BS54v~vs~LRud?/oE-$f᫅n髆jfljp>er\g#RkЋ`l+21tKd;z-H:V
mBn/IPn0\β䉀;L[Tnq%"'G
(p05扴n$!µ>LYl(eHϭ&eF.釖GvCk*#`iiN-6edavq17Rʍ4]V~^֣
DdA\3?5_Ŷ%L*?f:CYfWPXSI5E"
LGG2gL{ *,y	k*H 6ij<p3FQ5`$(;l$h&jTqD:oxܧe¹?Q{U};\=;F8|AJD%u5T䛉b>koxex~k(Qf~Y߁Dϕ1Bl֡O0ʬYWg8yQsm|&;K+zЅ!7ΔV2.](PN$%j[y}/ɬɬO/5397AC]+xU@.z&D6%E
io;{!H^s5%r\KKTS	mPMbt8m9TANB_8xryηY6~{ejJeߙr嗰L"{$I몙8m&&vOoeٓI+\tLòI.Rw)iϸ	aݖ"OGDXkjqڛmYx1  QDDDEKDHr"ʗJ0,K6\ˈ\E|a$>2{̜VbOLY729#V	K9I"e&ٱvlEKkOL{ov$dvm-VYp\Q+ߴ>^V<%kĺNX%|+b.Ū#:-H'g6)L3x,w5,aGؓ㹟{QcZQc;1mAB2*a[PS(T'DDUk}$VM%'h,o1?Zz%[kW.㼊* Iv㟢8gIzԞJ9DD$	G>!"E5}8DYDiGE
sA$i{O}*V*GJwGinCy~Sl'P]gѬ4GMb"D:(E,
E	}|e2#β\~RU
.R٤G6+IY]Dj#^{wrvĈ} H,?E/*5دr,{8G\} >+n'˅R ~Ш :,UK;3Vie"o}C8DjpQ04-QkxI2bIݪTU[tl99M;cJvٳM*_M{AXh(RD9eډluPŁU(J"e)CLGeQ{]d[I]mCW?F5bL;SV$_$<A<RH"gG\	+/3W./AyzҀ~֠T	sHy7J=j;DD Dh"Ø"&b"i9TZ &LدR{j+V#%K擸=NXҼ)ݶkϴf?tJ2^z}lM/3H,Q?-Ö)j&ԋ}ʥIb</I({\~RU
.Rh-G6+IeL5]6kw'lHIxnP&...FcvAIkdEګ`]~(dr-ciF]LHF*TSoV+S(#KT[ǰHXAaJǌ`k29Ҕz~'F#>rBiKAd[Ƌx|3Џ(Wg:wqwU$!:	gՍ\žh	4ۦ̑aئ<2)ۿ#8D0
oxaԛ/ڋogZ.&|I1NEhڨ;+S3,+*iNJoacmkysȏ](_WSz׆)e=EP"nq~~ɲ(P>F*~'.Ok2#^yu.N'Q.J1EPHBq6RkyǾ'R1^8-qhbU M(^kV!/LݠZbqZwd8fL$N<q^LCؿݕ|ҞK]mhyyK9.I4E~d_,j%Ӣo*=UjiJ"8P4ک6oLW=IP# H:HB%"R;yU_#2M!Xz
S}Q"YmAGNnRtTVDTViK8i<$iHzVJ2Y4y#6[ʸ"Y8-Ǯ±qqLdMA"u^f(J['=Ez9q60PIU坕[h}[UmW\ތ!)g=f0b!sw1yܕaUlibX%bX4Q򒳓6Tל ͚CUpP!(0(lZ
̋\c+j+& g&f}i>D@ "PǻΌK$Jv^˂V1jݶ$hG/Ӓ1ǝM^2@tŮ9UJu
NԛZi14'OeJ5V#|B]ĺ-xzB<cWw}UEaVgZJuyWk q~أGnƏ":$%bX%bXfI&deE.onyI3tXHEHIK$T%;XvY\Y)c9iQ(6TNKPzk:̆:?&AC OD~st>N \	jrZǿ暈UIĳXVUsد:ۍrvֶ,c&0tY[WIcn#Ք,bY+n|QIگB?7C0v5B>1PሚE-}
WB4ygxMn~V\ sp+[^(`o.^(ڨ*<<7hc,(TA"y/"&D{1~:	lKBA>}l)'x̚Ϝ~#f4Ѹ:i2_[??Ýs.гLe(d
,KUAiҦϕxsvRp}H̱~ʰ s_ZD][ޖe{[Q(6ipHxdu\wUAN+Jk;$@*h3^4#BRJ+(	ZP-5qj W}̫ e_Q.r>Ѩp%62Wj$v]%s/rc9WDłxR-Uu*֬tڥ6s)<VD!:V8HyR%d1IUO"ilgBX-p\!Udކ6-Bmpľ62SIl)bi[[3UK]5&ˏc،dUBdH֕1Hr,,DwЖE?Rߵ1i [f]fU2?9qasL&E)KCDdEv 'Dc0*E{(uU4ZMUX靵K:.xSnx5xB.tq(Gud1IUO"il,gBX-p[BVH6-Bmpľ#n%2SIl)bZ%3UKV]HUd!zQ2a$LjkJeYeY<$4,ds|f*ʄ+u-aUټfeY (:3sHyԙT%{Nh蔖	nrfN#UtLX*-XxR	^ZoMjtڥ6ssldKo:V8HyR&aĪS\+4i})ŉXap\!Udc`ٲ&pľ6S(u8)bi[ps0o]{?쭨ri2fB3UTਙ0&4EYeH J O	9f4[M3azaw15~2^J%b	<F +Inʆ]|le1Qf*$RI Ξ.AB$tofhRǹǎF~9`E$~#*8*w4wBJ=}D;6aKg▔Q̭"/DHu	񓿛&+3G\]pKjaٟhzJ@v9TA6JW=vݮ*Lꕓ8
N5]%UG=U&-0GzjrGLzGl]_=:cJ)	 FIN,/ѥ0D{̍XHujnn/$}HRˇ{MOң̉C88:X*Qm1]	yBޜUa]w
fE>5x^q/<ry@r,L27BG_t[8c/yzg_%mUݿi"芻J1
rRSkTLVDKIY\lODbSkbE#?8+Ȑ':fep>)`gh2`v	ѭDG3p&b"g?1EkSt/4`5̭DZJ\T9+6*b<;eI0͖yc?f7~	vgK-q-E54p,?(J.?_if =;w;`r7G6_߅6EB.@Z8"[$H"Iqo?VϚtdbϻ}b{Rj|t5-GˉI<,;#!I+0ܘv$b4dI@9 /1.W%k6%k@qp[y/FjzђNX*tFN8)y_t35>GL4ǯܻI.F}ߺ>륓-hN$%qL*	Ato ȗ3źd^O+AYi%sVYKYVh*?a_q#y),?oV|ɓ2Wo&0n`,wʝAԹqz?s9
k=RFj~XH~Ks	YPh\'ICF+([W9~CUP/X4H
]bՉ_[e
\&'uK'ՖI5%1&@#4M%Se>m,(r I 諭hOi门{2<z썶D,Ļ]$(Wk?O!+82M_u*_M<a3hhF[3.OJ
Hշ,9/rrCty+ȉޭ~3t~졫jԎUԯyO:Ϳ<-ƺ.j/
W9bVkhb8%''uV%kxVj%xj~ltitxSNZ,kŞIOzU&= P̾CE
8(C]7UEN_O'LeѕHBάópi.+C1F4gʜ0N.JlB~A׍<X,<n[4(9T%>}bH&'r˝#,+'{`Rͥzl?J7[Rn*
:®*z.,MA׳]Xc (AU(=%BS<27wLTFf,:K2|,F*)Z%ZNJ&e͏LF]^$F*%d,9doHqqh=
$Hfj6>jiU"uG}.Y_2uּ>xM3!rU3:_۝}E'2-amџIoxB~ȼOmJbsDloe.p}e	!WB`Oq+1BAny%ב[
"w7Z[ˍ}Cr7ioN,18\SfL/JF8W;ݫSMTe8S\=4BtV!'6:MFexMdizуc#g\Z&"FQG,`#`8;(	!tpT_7ꢦP?JȎȭHXAA8LFH>^pN@2Ƥ^=~鎣=D6zZWi_WUSXRrj
KdV[°̰-˦+bQW&AT%Oh
e{:^6$Y_dVd
e^)`ɷtisDNI(V_a?)j*_m(45$kިlydf{br3[-v=X$p)]dj #X(VL9WD2p|DE39i@/4̚1I!VmY-Jpe3p'+r~t	A*5My,xҥ&Gj"57yS=%bb?!ؿ,z?](f\)!ӓŏc⇑*
mJ;k>~gEXyIMkI+cX{i^ڐl8Z$pk5hwj5wҕws	JQjD'1ZPo?+e me0jcOG~aDR"UU)\=$'0$2^g
Oag^b'73!@ǿ	C>9'egO-lOa{&H~S˗5'\YFTUh6Gni2t{9Ev	@IRvE#]ͬL\sƧ>pTM+>@_W}K
Ҍn\&q.b	]Y__DcwY|mUcU\JN%I;v*Txݩk>ZxY.<[E_)YC%-M.ݤ`XSQ8?|Dm_+4Nw`WjZɋ=$yB]ZgCͅ[^$i2{ hh3kx>Ðy'd[''REo5q<Bj*HЪtJV#4kˢ;GϠ$;"'On	HacS8*Y{_Yx7ji]^M~N
/ͥe{r~ˊX1BIʄr#TW,?>6⤝
*Un]Hy"{lg%4Vn2VPKzi%)(uL N.O(QWd Tazڋ/9a!=
Cmcq\9=aIm]/\mME;
gh-QhMҫkp<?y<;}31u-=4 YPJ|(>Vq&y<1YΔ[WQSͻMɛ̃6x%8zo5!Nd(3<Zqt?EB=gHBt3jĽ(&תT[0mcV^kW[ޜ_9-B:5Uu`+Ax\VvWBڋu*Ѱrѹ4r;Ptcj^- h#V"WIi(<OJx!yd)mF$Ƶ|bza!#]A>o~*	Us 22s
Xo	ECd/jYyy]A{ks00h6ySS8r۝1jEyy=U.<E!|@o5IRS3mUU"mv[f=uC˝6shڱkT_w	],OOcloU\yTQb]b7җ2.b/z?|:tB 1XB+ )6,5"EC%h4&J-m W	JA,7x/bqԨ̤*"ɢԑePڴ#+i)aI
kwAAcR/di-+F(EN<J5
;YaA?S
	RZ|ܰĎEX.Yc xK5%753	XW,8sUl׏}#[M:	k"Q[hu:j$OcXL/,	uSLK$YAfY,kn&O5Ho?#f =I{H6aQ7o!$DX'̨ [Es\m
51u#U9$+FIQjrm&8cን,_^T-5ޏ>(Kܱc*&Eb¼ܤۯdmZf=%<>bwbRhNτ˼]\UָWJ
uЦV+
cXdkϝA7G[I	ƿ%nJސN+}\usit-D^MO<=/zߟ=AlMܼaQ"nCf
B`ِ񘰉֫+: = Ŝ544h QB5gNey(:/ŭM,aT@RXCoPd??i]"~hc4;|Y"o$wsݎd'&+`^cݖ5*N@YZ:~#82U4([mпĬ^=W]t}A^\;ǝ{.}EH~
Vni:ITz=͊+Gci15_}<bP5C`X!'/Z={.We:RDp:HB#jQ=D;Mχ
EBfsU$MT.@ yCt))I^[UzYDQ."*%Y	Dpn4i2Gh~e͊ʩ߅C!ӕ6~w^+I5!~ *v"FXռm-8R\cf)tk{Onw畕|R!v<ϥ-j**[v\9>]
@dKݪD?ܵWmfVUǴ;",gmK3$$w^P*fܳ]}}R8mDE{`qTC{bi'j*swCǁL؄aPX4
Ȧv`qQ/j]EYomF#ݝ%:RGZwI^uڨWLfU7J\f7ۈg\фEfb夠5Fm׷[MUj	-= dwy6,䀔T8aPXJrGhw{mKӲ~zH>UXYUYsUcc]"}\mL/ȗxH;yzzu٘o`}2l}$ɰC㽑OoͶӝUj-K2ȇq$  ~rFpFYeYdbA$fS1 I 5̹VCy,b0AAAfh/2Ab1LU+hUd3bE@(5×npB\M^hWoMբ־j[WMAwxIL>h<f;OlI]]IKs'󛰛g3d(t`PKChB+WVytʪclk9D]e<qC%&*`=s؊] 8l"%WJ,u:*5jSV[lS73jCOS&EWgo 	 YF4aPiRƌȶkKv`628Q6IH{uO4ڌTegNd Pȃ0gqi0`I9XŸn~{i{fa'B=bVz
rEGtQf$= m"Yy{J:ڼZ}	7^3|#p#l;(
~gb\*LPPNNx!@>B
,AJkeKIjb4#+&.cm</u*z6bOR nBؤ};e1~XJ8tR_Y-8;h{G+[~b)QM|e2/GC#\1,<\!8accIA]]vշT"~nz{-\ޙIU-meEeNKKJ_=rܭ|Ħ2>-hQ|TȤR)ExXX8Hf}Z(0+D씘Ap8<8ûd1T*ٙ39bm%{+YqFۑ3t0-(L s8H;Rz(/.7	1=,vES⟱:o}+uʩ$ܦ{d?Jo0FH'dZ"B;ݵ"ޒw,Y:wFE[zqT5V-1}jUKJl{!	J8տ	F#SuXb7࿛?'
߾	<t94[TV jȌ8jQ[gcHbV,2xʡa@=	r!co^}%[Hz|18p[ݺO~`-!9Fq[(}3,SNaEQd
nևI&k*v[{IέrWlmG5j_h3D+^\_#Ssu5N}%ݺgK寧WCu.tHD >CuH"gbLVOx1?ht(8U-:OXPޝDS0~<iW#]lٝra4*#~xFtBMK Ewn,A(l7AmGrAe\}<<,_GIGkfWr͢Ocvy;{v.^/uKr'eaYb,e}QSD8(6O#
⸮*h{ıd4L,P&_;6WSE5(yX+UA_XdPh< K,f(>RٱJ
4Sw$3Qфsvt٧;М#U+UW9,>9l(.dTr;2K:Z;h;%!V3$m	6cO"I(t_;@Wq!9	l<wXgχYuL	+Z)䜜P$dkY)֦X+,+TB:By` 
@di`T=et-*ڢfG
<"a(NS;AoD2c.q!~;wAϘNdWd55h 8:^agi5Aô/yQZ>
=
4%pL\c,3r,2F,c&KY%6\V3+(miIVe92VQYpE1`}{׌J>kKt>c]kBaJմUXUX]\e:4Α(4kѠF/^)d!e/,؅piMy#&i2Y5$)a"/LFNl
SR{5Hn>⑽>֜+DڕOy1$_4SGc:2[觐 Kf8i9]Q`GjF[4⇺-'m؍v}lcV)@w9umSe?	Fb̹Wbbp>\hmF,.	(4ۈΒ"Xoegyʜhu	?XqR78.yRx%2{F]%ҴuQwQ,5MucƗ^3J"j'NÛ&TC!XN㝯y\!V-g3X'jH6o)6)qERŢ`gyS0?AK!Q<Km0y0S*IU(e!5uy]͘tm"
u[Ҩb%2Pw2ˇsJh©
HEّΒ"ٲ˟5FR˵%z79WF#% 3#%]hb<ak4ٝEusJԬ28_laJ:uIxĎ"wCOZ
,;RA|Nq^\(jF-_׵s8@<1
^!
1jXռ;ۆ9PXJ	F-1 eh砞`)yy]͘tm"([Ҩb%2ߑmùX޴ivTUQ\-9+WHE"HR)/{u*zX20`"NLA 3s5MATm$SFP\Y
@m5i"/D,"rrjO ]ή,c2eNj{ZĵU\ٺ+t%cR+tzm1&$\.藴W)䖺olweOPL=υtenFv>@NU	&'B;]&j[D(=uCabX%bX%!!!׼"T\܏>! %׮d	X4r4D"C.R#xgBDwEb䤝^o^DxU,'PّD3IЍEqD%ˬsuwb]TIKvK|{{kwfe:%gEiGQms4՟[R*bWSb9%&v_.`w:TR)Elr-I  S3PS3
_dMƏ&,$+,dm}t~Z"i7HOzS2XRw/&&;eq	 iZҁ|v&D#wɊC5ԑք0ԇ*xn.H2]Yv-Mf4x1'3XOޑzKZ{엷[7OD,Q4Htˎ#i|6f4z0F1>H@ #H4#BYHR)G&|rE_V6LD&d|V
b,`TB/*[pa(25v>$Q:Y|ҮoN<<oA-S9p8qZl5RhC}K߱'յzؾa;Iru"#yx"ٛz@FWzEp/3ըcd~IfB*o>woIdMi0-GJ!Рƃh2id0<_urw	U3p;z*p[>EŞCaM$j'sOzl Mڟ}>nw8*2.Q+$&IL(9r2c7Js]7n"idʗm,4qZ فvwiEO晦3KJ"󲖋ǎ4qYtYzKXR!9Urs-J̉Dj54覙` Z$cE&u= Q>¼̕{I#8x!!^	#^J,]T8}Ν0BaAH~:+;׋DjvG5oĒyE!(9|5Ϥ)g]4jԏ:.*o-KVN"yzEϵ^p1mQ4C	Q'W47_[fxU0ՎA*~#D|󤾳<ȃѫJ5(֫bEGcќ;]vM(/肨%\/\{S#(	m*9N]5~kezC'2|I:X5^qjRGMmj^?jmCs?I~KFdRjz؆ښI-vll]~/i?@]Aݨ*%5m/֗M_^_+Z=\O/6-rN"2ntLC PYbH   矾&jr"
2Fzx \^C:D'u'qgL;m5X  K.e#goofy;>V+W*RJhkN3`Q}65}'tS~SmVpUKFV2|Zڮ깛_wE/NٕSz
6{M~ۚ"+[ֳ|{MsEW;v;եOceܡ˶Z"f=S]1@KRDnW?oWs_=n˖m:`i3)\B&$ǱU5|sꒅ%^AF, 
 rsGf?T-s)W0ʑѺ:G,F|kV: hR{)'ml3}HИ]]<R)]Ԛus쇬$v͈,^w+p~߾TmR+R_$ֶf}޻eK⓶eG.z^w-jȻ嵰H\+mݩkΒ,2P-Zws*\Qo %V"Pz+%ٯ`[3H!~aت4%|sꒅ%^CbȈYDuHD8!z-O)!"'@]Y.3ZBN;mcf޷'jDR0ynR4^2XH?)V=
u}JDK0UKFV2|[zU/NٕS| a[]{M~ۚ""mk7 h{MsEW;,^$Y{>eܡ˶Z"vnc0U@KRDn]s%~K_=n˹kvӦ:)\B&$ǱcZ ӰAϪJ{eFg"!dDi3ǃȌ#1Z
Hm7<u2ZS-b3}^؀*Åc0 \=-Gq`jtPdPW%i[Y]M~\(p1M䲩k-h|zDGbZkBå.o~ Qt}5~%ҩx7=jK*?J>wyԟ\*Q$
ǪZ4r2ΘND-a<2:V1ʎ)ˇJ.u*K+Y~oWцc1gN!4Ј=d6cv}v扻7
B;Gkw]ANI1]X~w!b\ i]vr?T@g;Jjn{|9<p0ׄh9/@f̌Jזc	(uQU@06]Tc]]bɷp̺Kɋ6gjj*
*);ζ1^^[C }e&{^26HYnKR.nS+b0RmǬU^)6MRAݥ\ӯN]HQL68b;<+pz!' ?ֿ٦ŲvҊN􂩭)CȘ,d-2@ر鶡2p]H^GmN_7tDe[newMmPC3|o.{?<T[,oˊ&R^']RKu,֏Qʓ)u\%u#<5X|cWsΥ>!6	gͻB}/7\$N뷏Z"qT6rULtvS֥yʂ9Z~rnƗƱvAUȫ;.GGBKTF/hq9DF(~+$eu ;ەC#ƚҴOrb07$Xɨz$`Õ=g4
MW$GhЫE]P}CO1E]Vk:Unb*]XLLWw_e0'3\	v\V!doR`v5sz KV*R1X6UCn"k3AA"	5xcͼ)7[i'x>rҎ'`6!%x~O+Oxuㄘz!bry^7USpI\ڐN:Pܐ Y"ݠ|ΘrXonnB!beAx~$@A*y6L4n3S].VT ngR4b˕Nw)Y#Ԭbf'CAc8
PƄ(!s,83/-xh4-	,U:fI^O}Uv[;z
W7)ޗ֙]$C"ho{+&ϐo(,PLlz]~e1YQe첽d^!(>Ǐ2
)fnʘ]o[qHw:.ש.,f@TW㋈B-}GW:(D-ܸƤ5Cm$m8z, c3X}N5o)Uq˘]O?xl̡r}{;ZP_L+vˣڻWVuS%{xָ\IeT-$M?瞆ٳ{[z/\<"J#	oZU]:B{*/IRw!K".].z\,ۄDEQ}mC/cB#%c3\H2 Vh8\=ezjZꄏ^FR1Hӳk:L%PQM=:`j!@垿ɈyKIDF*lR&8Pu,p-D8>:V1v5J=d)}Jx>_5tu[v^,ICUd/RmڛqDª+*Τo
^ASuSrQؿ[,Ft5I|~7Wke^KX<_ޤn[yLGi>W#ҏKkY6ic(GW*c_!ib;ud]<]켪8;HOR2JL)Ul.~v$o%Q krY5֌BD`xt'^)xCP+f:YpNVbBUvIF2]EO[;)Viv[RDU#43e`hKRd~ٲeI_6GigTvcbݷ%=rVnv^kv9Y-G[uS-\q7'ʫTڂ䫥!XU߭iX|*gv]O-l&ҨR8f3@quPGO#N7dċ^?&)^i`r˔޽]Ҳ dј:HND0jɗ+#<@+.	c4LHAʣ"dR>0HKtce+,췿$	
hfCYxS/bflB]2'͐7/,$
NQ?{Hwk=o+0i+6{j[Vg؛ijkQ>U]ߦK%]/zōgڬ~^GJJǻP8t@g;@`2b~Sh|UKg6t)3z<nYJ!/?ϭܹ";vMHX/t~)E\5xwy	P׻%5֌BD`xt'^C!K-YX/GڪTJ%"Uv$c%TѺuL;)Viv[ߒ\y3!epԲgflB]2'͐8q
򤯊
NQ?{Hwk=o0nےi+6{j[͏ZVg؛ijkQ5ߦK%]/zōgڱۯQe<oE=v g2{GC]JHXrRQ>?w(Ktgwzcɕx~_I#O5ёnK IrZ包yIN:W,4Oɨl<Ǜ`vd\5jeo@-Xz'IDN{!*!vsWʂinVChmt/nv}VƵ}II?eX^]Yly*iYSF՟I=W{Eva#	GTus~oyז(#&m͞MZsyIv6DQ0eU#ҿÓcRAۓ,D:<K{=k}JM>/[9z,1#IWh#gIF,%)vO~R``!^ _xQĄ,:ƪb+{CX`)IZ	"RI	l(BnFPqƨ18M~"tR*Ak_/#ggaIOF[PsfxX?Su_:$
n̖ Slˍ%yI;5KڑFL9'Zv)r2}:^͙SXՒm|[!	*!M0EwΞ
-iNcu1Q7Fwb#i\SGyf$'.vvїƹb+ ppJ@o`*}Rd<=WH~aΔ)O:N~Qd@:9Taǥ!hl.*||t\|\&tAIcx̡}w9K!h!V=į/Zn_V˅b+}Iߔm	Zvwɛe+3Q^,߅~KӦNkgNFXm[SvدyԶ35F!Oo̦}"YSڋY⶘y{vU:Kr~xT5;^AaqygM 9V,]b2vYY[5)*V%4!CXy:٭w=B$S.6s-!U=~NWfO]|NWv	'y]G
ɄǞ茮
Mm	QL҄83o'w_q~ƶKjg
(,źёi1
V.a/vK㶘+NU?LI jpbqNZ95ceϔt|4pkj'RtUh``ˮC2*	lDzO ș*eñb(kqE;]HaX*Lh3mܩs2?$gW{	S(w?̦fMeKŰ[6}7TlYEJO3 14yUi<SHLƨBSY:OC,
]+Ho|uHil_ǹp^%y[QYv"_#9TGʦcylǽn p\x;M?3Yܮ^5쑏[,
/6F9vg>׿&j0 / /5mkb=EQQQ]11Ri'vХxO^]y)[SbJfh2|!܌?ee1:L:y+//7_:uEWputs^tE"fh2dWc eäw
'Qa"ZԜW'CUuWRZL')xw~K#WjoL
k,=Ez M t$Yxio`^\YUK*$LtLtLQDTEDTEDTEeX]⯨V|7YF my/r%3o>ÐFu
1 W{*s^_"ntkދ\g1yS艘b/Zf0<vYPa&tYegYG@ulkkpzbh3!Uj;3^Ji33[E.h^Z{4XͪquSU'^'^E0[r;UPReD鎘(KR#qQ&)+sȔ;d3C~jz'"<Zl]t$oZo}\g1yS艖E[3_W\r.0:,ɳ:ل58=\14̇!
poL.5xw~K#9n.m26*mA`j&ߚ54R)'rثͮ[IB@EJWÖYeYb0MT𬰡'4?\%N؞;F-%2aK{%u.`#r(	+fv	5W~7-g@0f#ƂS6B{)*'xX*+GpvD6B՚ӕ.܊kM7	+vHGX c貄׈*Ts9C:ƥ#׬9Cfnɞd2b2wЕ,x6X*Hs sG$2C4b!,bQ|zO=P&cQStRa	/2	$>5둗D`פpRe1c'7ܔ-"š_dVaM<2a?=|`]x2k6yv	A&Yh4l1W"jӟӚ,./tʃAPQ[R}KS4Ci
N\b\FdJpr4'QIj$N@v`r==}9'V.YFd@:di5:N*Д=g!c!90D?c4<)v/,;3Ȥa"5#DME/l<\EnB'	RDy*0.&Oiq{q)yKMCj:3UĚN])!EJ=1- "ܗ?᫸	5&7t^4M
qB@*b4#Hr,,Xf'fVg3n"KǽW^=bf# @q<z_S$Z}Mr;Մ{sQIk:cAϺÌIN;Њ$6yOD65yH#Q]쬋J޴uiG]椂
XuEq!m+VrLMuc{@qnQ~z9d->®"
e'ENбh4,,4#Hx:H 
M^q?ӄzZ3a| L)`^B.4a0i7Y˄(
RP]|Ik$Oq
~}9m\UeleeN}a^$03Bo904WgY!0|P~u}Bྴ.jnȧm1UR2MY1*fd\ X:Ң|nRجnLNCHB!Jx0 pP:JT!e62>G<
pőjIYoLPNGg?Y˴#)w is1643[s-%#.+(cOuWo? Z/[19iaJv?81zU.ֻWZ-/$UZ=PcX'{vNJY3+cFQj5	\Wq]eؠxQ~υ'q< cHpJ!Ja:ȏ~=,tBi4G[bY8^p%8>T1"|\<9!1,S +[6:F1S\?NkIO,\:0_ |>*2d.˄u[~Oy1]\g-1ށZDj%b {YhxK3~&+myf A0
ˌ`I|4*/~z`ױLP.Eٝ:$#eJoPc.lU,zii'fXӪt̸IAQq
G%c&WlɼLcd("#~B郝ni{v4+;[Q<"R>4ywU՘m.r:5̚iheL[VEpog74B]IoKm˹=V&{F؎EQºfPZX^wkƽrs?HBuY5|Fd~GIuǖydê(pudb#̩Q5
le͙JxS*ҝ43.P{\GL%c&Wlɼfi<>_`fp6<76Qv:Ǆ]Gڦ-,@5؍GVPk5-9̩j4݀u~&恁tC\+ڒA~M]Tזw'Oh[(<u11<nWz~Nk&}t,\y`=wL:ppudb#̩Q5
lfJLJvXӪt̸IAQq7Bh L%c&WvlM7d(""w/ᾘ9ل=5=jliWQv:Ǆ]Gڦ	,@5؍\ uPk5-9̩ol:w
6u(e»aޒA~M]TזQr{Oh[(mʣu11<mADTMXUZe^u_ɏF}yFSxN9g3[&(qI$J`Ij\޴P|=&b٬V^m`V_lN:?`A<-_C	Q*3j}a)rbT~yJi@6R H;
xVay 
*բl${yC+\L#Wr%*XzdFW/PjV@~ɄsT.xa$:$Lи>Fl  2i$I$DCkW:"lqxj@C>Ջqg	fP"<yV8gRL9C&_,WHZ9E`kN3K`}ƯSނF%4.~3pJCB[zpIBAiO#9֟ҘUrn5jmY*G03Ĺ4̦(68.#.KZ7	rJ윜JE"8ijQR!YT@pI6W^R/kK UԖ+ke؈vxړ1w@zm_.#5<V:6vϝn4f|MxVBo[gCĘq;N1_1!_C+\;JMxg/͙	~Ҭ̻ml"$ICRf)	|gŶ%$#7rwR*/,dƗfxRQ"HR)!*MnWDbE'!La,@Ch$ }?CK@SP3窳^	{S'7+J'ZJ=UC1<\ŭ/HiKuRo'lgM.O՘I1BzabMv*{_9"yLU{!E9W˼LJ.5`'lzWvFTbSOS֕CAZ1)"9$@$E"HR)1\WYy$ >HL,9X.M,9y=
8PMXލ(FG:_Ew
?RN	S~:jWEW] ,\mhV*c(nB;-҄&F{P[ȧEJZ3곿	m9(		B9,gVWI8H3
l[aY޳>֨iCqT#U]_B@Q%I\HIκ YwH h u  +l`i\'Kٷp<sS°ة%&/Sd@8t0Pd~At왦QheЇ@FY."kryݩ"Mv-Z@oYY|Ll?I|q$LTYƵ;30#SvcckZWޘ	ɪ(I7wJw+ߚ-˻	?sҽް/8QώY>X؉|q+1`DVI7.{6-0i6$&[ЯXIj(֕b	I4{ꥺ)M#ޙfӌ,qQ9#@@"SK=POm!#dVLg>wdUaA;^@-a򒵍mW1j7̉NO%zNm&YX~k% :9WzJ%oXTB,]CN{gx}9QJolFnߝJRHެg޻;۟#o/eYykWqݺhɴ1IP^VǛS{jwD[Ho_a !7<QJ"(g \S[HŨPbUp#CXL؆f"'w+0:Dӕ]p׌HMmF$Q[BMOs>;* ligyIZƶ)!>c&fc!8!O|37A,?5k_%ne-Fŀ\6G63`ʨ	7S#7yShwvV_)f$oVNR3{o\Y÷X}zY],֊n-m&9L|Re*tBrձ}R+m9tObFdU҈*"o|m"զ).y1ainwy9!I^ۮNsW31	GEhM~:"
	
(Fkw$+nWE,'f.-ndLPzrKpByFۈ%[ Mp|zJ%oX̢@1ce"XN{gx}ÙU&d`f2ߝJ K,܄^Fc޻;۟#vZ[_d*1ۦlINzIPa\ly>*_GjwDjJvF">}Rbum'6sqYo<a;R$c`kpz)[@,cGd[[@VOs>;* l␌9hX]Y3H\I
{n Vnx5_=(7ic2 ō`q,ba9	0AeTRزC;~u+l/r7r߳zn|kc1e^U=o'x&RBrձY(R+m/H.J4.ESMoEmǫLRfE5:,2slC3KJS)ݷMPHAn lv(h_&M<8ld+'[!%&kÓ=jqPq7$y/>l|k+}%ޯBuT}bO1o[&jӡ^@|Y}-Eҽx-Y[zYY~g*mXadYeCXuWѼJ=r [{}vY>m(:nݧTR:fhϬ)-7\ęPҖTPhL1].c_c+!͙.[tk|x)
%BXV*LDPSYq\3V!!&S@ȽQC^s:C~ga!7?S{[<~>)U62I/e׷U so%é٭n_;p{@l׉HJ>vu$&>Ȏ÷ml]bb|"4Sh	@iɮFf^u$>>%
U&	Ujl$nPjֹb#"GI%uiV$d50_9^ܗOT!R#BfMV*ȟůe4\U:gT]2=ҊZ|O(\Kp6Y/yTs_"\ oDRb	Wq\t_SsЋIqK~	$dg1lɳ|(8'*8#˚d%9,%ZژjRڥnήQtؿ:m2$/ΙYվ{{j7V%5*x]B2|$
E-TN*|ѪO~}GTvǔioC*פWmd(1>wW(:3"Yȳ(.M68+uBIR4lB\uD|@!U)9)Lڅ7śYtxL3y:n;L\[EΔ>89í}z,E.g
9S\ShʴTl5t΢wNدi_bR?֒v|-rI:{}LL(8ti[}0Kpd&Z;;J.ru򂔙MM}CgxhG4fX9""I_o4oy3}
lfG	>ʲ?Z)jf@Ơͩw)荻j*dr8l<"Oѱ/Ɗu.KVkz./7UŀnRW1]*,	,XFʄg\%{|ceH)"C"ڳ9e>ߩE$==U	%#(ў`:XUzB`?ZJ{R^U.-ٟDɺ
zljNqoT\^Z諏c}d;^}?-UzY;ZbFX˳KV+BְǦx,x&\{zo~m޷|.䧗=9`$8I-d_YTlo}s(NhSO:cH3jGz,"ЂȫUi:'X!q9j:=ononS a A*v'KTM"TA5k]R/@ Rr>e?/h ` Ezqbc&}aٲv9hz~գfx?DU*G\3mPUkJ:ƻ̍(KiBܵ"t]ک|`,=36/{|:N*|JuY7Vzp[Yw9}0M<m:PʨCQ\sm6pmz) R&1_g( 1<6sŇ6]Ƒ%ӾQCw+-4L*rŪ{yRau`3B_w{PZ̤GgI48+dIăEnM,T*wu=b8=ԛc7ݢeE?$?yۯoo?zTrj;ͫ9~IAf[>+Qz.L	yUGItIw!]W/ۇn=uW?$(u^7!2A=3y5KŻ%ZXL9(F֪RSx=<Ĝld,(,5w|ÍuX> -f"P&p#\`7Q`tYb)E%}&uRθ^?%@EpxH|.ixNctMa*?0C=~_?v?9.huĕAo\P NLrOȏ子ZK[;! kDZDwnēlQ)֚ttRU~j>Ӎ6YxlG$mZ/GŴ80O%/BUaƸyGVn	d'<BG痬~{,R#LR-`rTnh}f#PG	L)%EǴ9a&PzP8@Ȥ5)6(5lY<ni>]˺vų(▵
B#\+jR*>uGOV5M[Ca<Rg{=Uok¹SXs.r->^,Mr:z'cTTt" mYy<m¼T& ⭝"όfM-1,:װ"4U)Xr+Id[}5eGjj Iؘ0M(#tPђcAڸx[jOZ3wI^2F梣->Ǎ>}!w^԰kwNgH<أ5:<RֶaTZGܵmUܣZRRgΨ,j<6gCs{}Ǫծ*pX+.ze׮E3E$EZO\ޤojriF8eqEVc)^d!('0qɶuwa:KY6fTf48~4%U1li(
kiFf)Ǿ?OCl-IɭS(BCߎ%<AR95
Ԝ2w&/ięrY,Vг#Q\\CDd.	lB}QTwaxZ-^[(w=؟[/bտ{Z(dFg	ġo\]Imw8L=R\1c.&hN+
B?`9fpṵ!AETBQH\7:#YЧ~ԟ8Q%z+>ʥ0/"),Ն~GFh+LJUl]CLC;dU[\~i	./d<UbO]v}GAۮPV$,~VR^A֮<*3yzhݴQ\sj?v<2	sRF9s;d}w0$ueJ$,TZ<:iTvִ쾨(RwrWm2L_Xoѱz/1_<Z'\2U'Iԯ{+唱g؋ 1Ƣ[U,{{7ȇk1nUf)	",LIѳI1A؁ظ1/GeRqy[|܇iU{x(@\n"S\ %	#\:G楡Q"<9jcgՕ*fHZ'3w6IiagIQk2>mtjɼ$~]9}␬.AQ&,Jҿ{aU\طu_7꒨osֲۗ`%nwsd
E#bjBqE7Q=,}SlY
lNl5M.#S~'|ڷB,D53y"cG""@    y%{GHB
(Tm]W}ԓpP Eۭo|ޝ*{}/U$+ޓRgi̮܍h)1bE#a+X\c'ly.V	zF	WM(U\D55!8J\s)jkjgf0	JFRBs8n',vZ[؟ʳek@idiHx
_6̒JHfY/윴z5	\_HL2,ݕrr7=IU9  ^;ˎzPIjgf"8Y^ ΤEJP[kM*B+Ɂs盽ɄyMՌ@(Ӛ8׫orȩ7߼+C0{HIx&_涂F=S\TyN6ʷ2ve]!ҫlg)S"ir* K?'-j=biDhOdW [s>FW	ҪsE@Ewm]"Ijgf"8Y^ y&9*ƐKq@n%1JIoF#:#_)q_쯆X\Oc7F!4!N5a)@Wo37Leb}HafM]mUڈ{j猹Ŕ+6jioXe޺!Y]+lg)T4f[RhϘrj=biMF[Vqi|nv1A4NS*, 0-EǮ KVk;17rgdjJD"pƺ
LdүR[ѥE%\;_)q^MpWЃ
uU
qW}+2>0{HIx&]kh*mD=S\iG4Gʷ2vebeJt~jT=M1WQtqICrj=bׅcrKbQ%aj6i{`*0TX dEwm]H!Gکv1p'G?x!W(vM&4B-P[kM*hJe%ҧG&Ϡcn1.J&oq5y}+iDBkv%(
jwѕ!BKks[AVSj!2OX̸_,NٗtBg4Z޺g)ScUРFQj+3@d!<*sSP,"±vu/p}A8UE*Z%i{(.j>HRVs
;ϳOyKvU<,S41DIYf&be	IKȸQr(T
Y/"^\SCؤZV0Dſjow=p"zZۑiUdU)?=VTмӚ%/	K	[#hAR-Um	 7'=FT%sHyky5
2]0/WHu3(D}<G&8hoɦǆD=Yߪ#+{vN0ɤlkF	WyǣfD6*fn)3,N%_Pil=im6s5EG.]݇$I6~xuH z;_g԰U%QfYT4?eonz tF*)2݅qwVIr?Hf|eYeYij긮D;fPfd	Zbeq>CMLAY"㢺(fj5p!Z?V	eCʷ֋v$9'FֳJ9ְz?9[z;BkZǵ	T0Tas=Y)rKvxSЖ_	Qm+}03f_+ VhHf	XPm8Qu]0&An:DYo9.[râ|5[*I0QvDFj9Z1K%/X豮'Bs9,KrVc֏9?}^+!SjhcNʁM-D]˻7Mg~Uݺ]Pbcu3fvjԠJaj^\+,rkYҪ2]X-4Vɩs5  (N*TYSUumlJ6*R;djkDVV?yd[=-aVA5܀d!&Ud,D;el3S.1JŘoo'
j4TI
hKkG4}&*q=}V4Ƶ/P^39Y?DKz7G=PW5.Ի~vohА߯~b~}Ix(dlg\MCH"_5< `LDDDD!B
 ~j| -|U$tP|z?=^bqT)-DMn~0נI4AGhN|%jg@@m~TUmOgl1#"X+G@u|o-W؁_8xp8ȆqpQ=!G7bWMN^_;A?-9}68{T}96QֲZ/xz*5$)##q5[PAȁ3J),!j֗+kR'~	5[p$ QnLkL%ty2!Y$݁SsrcmoPq.^:}->d~~	1<Hsp^r<~D(t#UХTfLjJvh4[whUfBd~lwf:~Jץn;+(Vl)05dEV@5Y5Y5Y5avj4 CυC>QLfi	T5@ٵ"^~1w^PH"gvŠM()7$iz1uR:?
M?>:(Kԋ(-l	n
$tGXOieQm@ޤjq}G.z:(i5:&V~!\.U|!ԧ['Y4ʪ´Qп_#BҀtϦg#09K=ӑi+ڈA\Y
aHtQDHmPjbA px (0ҒV^tvm0TEUBJ-.cf!2HSFʭSG+Gхr[)ӏU,ζP-m*f\{PkNLWv+RjEm2k6I'ɣuLTMOڳ{S5ޝ-'2r>O;+]!|fE1?q#s9F }9nZH;sT5$蕳P($6(}_ \R8KU]5$ԁ]yYjD߅AL-}Qfqm*В	0zkx\=#QOThM5MhvidNu_zVDҖ)Tƀ2ڃZpc+#ZukR(n<LjI'ɣuLT57=YmI	'2#?xfEQr;- BH' P HԱa%'d3CdtI#n*iƢSV5)B-l3j08->0ū N?0wٍRs<f)2tS@;YafSE|KnLNk^hq|)|YgKTeAXL#(g,_jҎ%%EinHj2_-6%U7*0Y,F|$$5雮X,f7SwɰɣJ
Mی3jx_74VPj
n^n GHu	kn֊⡼T%Hwfz. TvJ]歎j7COHfe!Y0wo4k?voxKNEwA!#׍A!0F]ٟjBrF_sDs1h=U
i_m>7bq"E*CpςDJ럭L2	SȤR)EZTGVIDx4Z'Bg.A~ >ƞ0g)q]Mv<"5.^21n5hFY I5pkw#ۛ-N40Ik0IMSdPK):4~=i[2UAAVgoFHٲ{UU#U3V2VUvzD}/V3d\GwYpH . ,ݾ'{r˟G
22JO[LInDt>)àwy}tߓtIK}(l)ګ-z^m 6e/\~OORv2U72?e\ͪڮØX8Hśy7||]ǡ?rpok
 ˴{v&ݿ*Z"PnSP.UZ~]j6j2(Ү*hUբKQ}kqu#(Uh+\J9#l%_[;uv!sR_Ud" 6d/cS$ևiLБU\Gq.Մو;EV.ˀzSFpYBރʣw9E?_{V:~~TGla5]%NjYѶ6	*[-<DGo62kF#eLonD^Hb&FkeXq[ s>QG:VW:=M|sV+ʚsu9gy{Mw@=]c ,Z"T/[˙2"{utbWw
S>瞪DK>9M]kBQsN$%'NŰ'e~;YvI#Kz^w5e
 d6MSa<G-EjXT"UM.Z'\#FA N*[Z{lI}y*ng0'm?E*rxY˴٩	w5%flyLф@C%^]dKfu%߉6{IԮir_i}zgޔ{-gsj}/1="푵V̩/)eX(*VҮ';otT+6YuV?d#&EQ[>궄+l1X`4E.19?"%%gr*74]ƍ O
G\jAhS}TBĶS:(k"'ЪM0o(ydڟ9FB	Oֺj>&mOm{.U[Vj^_;mzݮ:H4r\(Z$UʣW?;N&}9څg:|T(*/G_jQ^<K2ULľV7$_©-].I7idy%hP~&?.<n9,?^DELKPKF-q	V77.In4	Fx0`
'|H9-~ʈXgScSЪM0o(ydڟ9jD7y%?h[Z껭؛<SnuUm[){w#v5y]:uuFdPI6FZ]uILxsѩЬuerQT^-Bx.|o)V#1S1/ܑ~
j#tb(kK#i,[RP^T9P~&?.<nڭӑRD7N_?$%,+0+	9X,%@r<_!!dP9MwyuQ2ؙ8 cSЪM0o(yp䚑	Oֺjcbl/:&۟m{.U[oƬ?u?oӬ#K2\(Z$UʣWSC$N&}/MXV:|T(*-U=IٮYޚl)V#13-谪zYՌP#.oy9umޔ}}:*ݵr*Hf䄱L)ti?oopF'WyY#%TSE✍0D&pN+"*L/m濁j78
l:j>&mO͹o;.U[Vj^_ݮ:H4%2I]ʣW?;Ng9څg7/J$)-E]ԟM赔om*f&b_E"*<V2B(6<մSzS΅e+}jmnE%H=}4(}2r2Ŝx)g|01 BRQ#0&׍zEುZitoO.dBsG'(vYɁwF}BgܤM̬~8["NS0.'`{?,j7jtd=.q͘*5w)zv^Kk6BfP4)[uNʍSl-!aVpsEmCMdRO׼O*MchPw(U$rQ$Xe*;1uܮQZlCK`D*I7uNRTZ4@ybƒEFQ}r8hiZ4{LW1~DD)2jzf3vYO
&<ycOV]@(Ȝ%(bO}m")ܢ;z&ȠES]dU[Oq_$Mޛ*um}Zͺ*g.{M"G_7ͻ=ד=̋=a;	4KuU%R
_˝Mdc/=*߿[wo7	t9πAQS"yQI4[>K%DOYЦ/ߢ'葀wLY%J-;s P` F;nR^5M[.f*h:\us7.ltfwB$gODτ2'wR\v{*=i6Nw*"UҖ2)JȳZQsDjuPH{vށ(#KBv2Or"c}W~(?4}%o6TUn,& Xavܫ8^i8q$[LʷE|5.d@B6"ULgE^ޱ)墠T0|n[բQ^MQ[a(ԇ+r׊TnMENReec"~Q=9KB.;_#v;9ۘ;9BnpՎXq[:)dWj~g3\qo(كVS<7KjE:!ݵu""iԫ_VK>J+Iu;XЗ-Xjh
9%yAby+*".p{ȟ[2T_,"
7FnieDou?GjM!(2c",xs-K#^U* `X)R'?4ߋSY qptZ23'ϧQZm~EGhr~']?ˏ5;7N$-#\aPf~y^y̕kBAhw0R&$CU ]0μk*3k*nalvTNU+7K1I,G}~Vh{˙e`Nhf8E6Ю%CV=b}U4]	q6H5J.<d&!'`:S̙`Fd71CvǦP*KX$bU12z5mg>\]30U2h68?(FV&~
`kKG|
볅n(tI4dY[DKN/i]}&-inf1$eŖ5˟:Ê[qHi&4-20o>	F=8Z/%\?m=Xݹߢ/-k,TQGJ/=guPP%iu/W{sx&bUk ^%YNAX4F1WBQIAFDFU	)Ի?o7,iDZ%v2?eb"]]k{n,eћWBա}UbP^J6ն̾ߪ'9Կb$_.)q}K%͖AبRFۢTgh1RiҎSV[]ϕ,#qW%9tEYHMFC;_;)S!PÛɑb٫zA];5n6Xx(4l8e9~ˑguCɼsnĭ6_3hP9M3o)4ڔ}1JlG~P#
١/<[clnꐜC{uӭVgzɻV>ά<R7C+o7oʰjHo^{<)]	yݣ~gDBUd!Vrcs{jYHsiopCJD Wx5nhj~qj{*!	6Rq5B6L[5t{&tיnXc^MclsWXѳd.G"՚f+v:!CoQJM:>6=LR>-=	CPLhb}7t8[|'"^s`kDIjL,~.#yLC+&˾v&ߴ^׹sʽ50`ۺݣ~gM=>AҶvqy+3:Բ h\q.~^;ݘ+r-hF9S))8zrU&-=}G`kprG~t|c( qbvR8klVe7TݣĖ'̅"Jޣxt|mJ{>~|\#b>l
I\nbgww$nHNE޽V;m;O;
g+Qko)<W
MC|Vԑibrz%<ka.Lw_FH{$}WdlwYLgRGOkvAEB+}crXa45{v` GlTC-y^m?Gzǩ
(KZN:ꓪN*jy.Tg1wȀ@ "(wlXU5g%/YfdPL>FK,׭hi2mDݎfHM2w[R<?t4pSk#5W.@%2/W<wGR:,)+ʾ6)J^m7
ܥsׯy3I˸~Y$ڞ(z2ˣrr{>oҟА~gоK	w</K)gJ)>USww    9o2R%=2}<,a:%{ӶAC-Ƒ	%Q^"4w7,GRmM=U83CRTIcUPC>1D̷sHp~ⓛEn$f/
v}C-hkCQ_`߄ܩz:}Ymͺ~d;9f1e4y_Y5c5MM{j|{ruF?#P%)$#AJgR[ý5:Lf	&@}޶g6%bXz7!  #݂b2a̦c_H@3wecj2u@c3C=ŬaԓMZe6X'drhqgB5?j>SR(etsThPiUFT٫3(v߿NVu#FjE)4c8Jȅh/}۪;aCu FԬd
-hJaj*+)E1D8g(o!2pK @U-78B`IQ#B'`<ı(sᣜ8	vtE:Tw1e
¼LZ|(?Mػc07>9ku~a3iʹ4aVjD/%6B?ׁJF	5Аr;T},O<Vw&:blL"\lTГ	WdT
	ʅсQ'!ܻO㿚UQf-움S'J$%7BsxP9HN~Y~e7?Lt1h\|{~գe͕=e8s"OyH鮭ZVNgG qoHQEEuW2W>nvpB3ե5ܮA-"X^xׂdIh]RuğebJ:<X
r쟥w>ĹƢ<14d<E/%첥ydD_PC1u
<Ċ
Oa_kN1IJp>v3B3t2-l0E,ŐETR˙{GMuoԶx̲	4bY	 qoHQEWYW2W>ngg;3ե5ܮA*ۿ5X^xׂ)(ZTq'u	`9TO~n~ABIN7~XE/'TD4C7"1 Υ^y+RRI,=u+iݟ))RΞ|@1=Z&1<>'̴yZ04qAQK.dR)5ս-!2$qCegG
gEEuy	>%rnvpC9JZSUܮA-#Ux)A\Kd'HjRNO@@d-y^-.A7+&:Pm1([o:SAސ b^yk<?uk4cSI,|@1=rc:CwVodlY=e82)MT鮭Zdh8!NgG
gHQEEuy	>2W>nvpC9Jե5ܮA-#UxRd'HFRNO@@d*~n~b\4;EzDe\e\e^t pWJBv&;nP2T8I\VZ q,*c2ȡ
;_ɭZ].WբRh[6v$0Y7*8xa
n,ofsQGX6n{%kc78Y RK1
[ަ1M{%{NIi"ef#D7dX태b;G)""aL+J7I(u:<p'eYeM$bAG҄5MJL!@XExMqFL槵>ug!4"V+hlު=.*ҥsQ(XݤRr-u$bX]E9:Uvv|_E!O؄/E%v)ͥ;5{)a,	6G|I6V?t+ 57Q*r{1SQl{)heDR$%$CsIaTH[BjMȗ4Q9J|bfF2B.ʲ6ԕjʀAUԣBC8T<[5HGgB	LڳF1SZٌ2I3Y(iFm	v:6_2xO<Cvs~ڝ9:S$_r]Ғ9T"uuJrVo[>4FfoI˔B@cq-tsm>>:J	*Z]e~z
Dj[p!֌!m>IuEg>YFHP t:BVHh?2ECO
b=9>I &\=Կ?7(x~_<\4L0-󻴒[R.?vlF:
y_z=BRR+fBF5M`c-faeCUs߁&Vrޗ4K=x/JW>HNP$/Tga^vjjeNY DXߓS&.2o6Au̷AHk֏u"4ck/_GUxy:f >粸ֽgB!"<q& {8P8}6zort-}WT==UO"_W)Z"afIci:uMeQBL)p:0`g8ֵ')rVѐ)Z@cC	@xB&!hFfJer}lc}J1֥X5(FHM$4X%sHi!<F4v`B>b )NlXrE%:~r_7Pmhu[y<r'F*}
4=)@ͳ"j$Ss;v8Q8r!RnS|Za*yg"		c!y CٕJVMud6{Kb!'ܽ*lWfxVtMYtϓ	n%IFT%nk`C&]"7~@&A<k*c`^R(d_F#*}@G[c$ax7:IWtr>"wcYdYaOҞ'_eA:vVb	UF {YF-椻X.A)__~T 2NҬ))ZbuMK~W~V]Ր;	*h(
`I>4UR02ië
M@oʵOz40!WL-[T-]5!( </CIK^T"n4kKSOc+j5G%9މd!u ]oMZcyKElzgYCbw׻-Qj~PceGpɨṯ]+5xZ5(wxB(!;>N}Ŭe)8~+O]d*6hw!&:0S#IEU!2iëĂNUPO|{SPLjžF%n@'Sgb)kʙ$MU-TڦiMm(kwuA%$]@m(/6Xy(RVm.V3!;kifqS(qWq2dqfK!K-W;d5C	Ot0ѹzZf\)8~7SyO)5tB4;tbTEa|IhUR02iëĂNUPO|{sP2@JS-G.	E N?s!$*Z'ЫAm"V3K&P䴓\s	-^&C.ToTVxշ<Z γPw㡦ՙOs~]sTʏUn+j/е^kG'jar;Q7q-q~MhUFJedU]ep]^c:Ж@jm{k!1rȗMl5ⴽ^+1_N:^eg	U.M"BNXdn~^mKuuԛ^dVg]0c
Cn3X/u0ߢ ;̵aQ>jsɽ%b#EW4Y%Nfzl
㪄1hjɬk۫*YK-5$t/E&kjx~$JhًnpꀗYL   7mu[fXX77
썯rє#ؚq|E5Cĝ͚:5/ 9E&£M5epm o
kyz"hCX$'z;<O,&@;&Jku}_dޯK-S*Qlp>lݛ;K0pUG&\] 
zWmi7cЇId.m1C$AHDD*z] IubB0O*t$xƕ	ڞ.(e)C*YMr"APXXZ!㍦p4hdjTdjԩ9\JoeV8OSf`hJvx#  JB,gCGY8Do\$a5nuNaNx,&!&oVF{U+Um"Z9]e^2Fc^λ"ԩ'2aҖ&(l/hC,gƗGXWS"j% \"@hk|Ԉ*6n#9mbaBZ	$y;Xy*5׫-Wyy!%Dq7q&X/Y/6l!/,dTbtK_+%Ȋm
*O{qS=;x,EdiLK7t!1;|vANW2+kfT2Eǡ5^s:>xJY_:oa۱Qio6s)mĺ"l
PV^3HO~g^oRؘx$0!TL-
w涫<<#,ϒϙ$Ai$[вf2HZ; +=/1)t5JBJ,@tz\_T#s3(qPճo++GV瑩*j|wf )0Yۙ}r_ۛtӳN{Ӛ(P0 ex(Lt5 n85IP/9߇*]XDҒU!S_4x%ھ(]l@J%!VS:\f}Tסޠ4ghZkܡykMZ()  +c5b
j&2K.w6ߴ$4r&ԪMh@Kh@5Syjn]Ӓ=SM.D'U'};!5Ἐ"!\W[lg;3}*%,,OX~37${=hu9pR@ver熹M^<E_t{'VPhx?yr&h""Jv;TdW_,%uGCGXsޖqUHp7r#$q̠(lQ4E3^%eM3P"Fl^s+{B	
N2#:[j(D?'SCV]n!8 9J;CP2َ|)@*$oVs\NP.EdO <MY̴"DzFYagQoZFFrg'R7$&N]ՔPo_dc$vSlЋ]5kasuc[;p4j\JBl$pXҔ%aP<d`Z6}EГ7y&)H0G؜Z:|LcKXPw
OIJXT(*$$2T	ctޗhtSb'P>HsAЃn=D~)tʸ17hpb-WB\(ΔIN	7^r/Ejmv"}9zɸкդSϙ*UF>`5~[\6E\b	ҵ~k[sO\JBl$pXU%D y(mP.frMFR.aC.8iR:1@i-5Mq/Wr	GuĜԘթKV+1/1!6N2|R%惥muM1WUJ!DzpiN"\Z4ijgJ_Q9KRc5ԯMdX//R_7V#OVQCJ}XMkߧi6:th4RنhC:VooK<\-W5344cJR$:*9(&JQ]BL߮IR(dbqhꆂ5V<aC*B`,1'5&%nD$5jDDRUH!ictޗhݞICb'P>H46pL|M~U*@&srIk.f|
ҟҧ Ssg9KRgεKky2<m0u)Iۉ܋T}<k^ӊy͝cZk2kp?'V1,sO\JBfLK)H`|䠡Ejt]	3~&)Hs
t}ţ|LbKL/WrnD@NĜԘԪ	 ,cez_$#vz>&m@dR0jD\t ۡ2czܹdJ[rA5SWnPӕ܁pX4@(w/ҀP^6y+:lGT\@CpSHXfr)9*cR$xEgѷ2FT6{v)&i@X9aCRsoZR9EX	#RKQ%n	T!#o|_Ԋ?PG:[-HxF5ШīPo._l*5rogd"@ש6pԥh`MMS9Z?#D"R	mI5Mi]ٖ;|X	3GFGƥ?.Ոru9%"'& B$M	ؒ35n#V/[BIDu, S$Tr6EҼ'kz;V]SP ]Oȃ lF9%fMw;MRFIgl]nlv%ڱһj&hf7~<YRcIG)djBW>R(D*;Uvr_]$LbBf`NO~qp[x7JM5IOˤ&qKҰI
PzN=
4hxF#T\<;g/@PF>X	iQB<[OMn̕KIԐa'Aw̨Opߦ_|zD|&Dlb0IgBh-6T҃84R[*1|"H-Lb,u^< Ne."Hs.bNˠO m$(-S*@@1	O"i5jK#=Ty	,}\2)uSPtS	hIc̅Kh+  ??????????????????????` O OrYklKı,Kĭ=6fAՒtk4Zvh-@>-s$i(&+DI}Bq<BBgrewM3[[Ԧ]]l'^,>	g7u93>ty<u_۽"\/Xf<W߻3M_*ӄv;3&
5j&uNHYNJ3SjV1	cB{"fV"Hm*"#[ɣM
2Ra@P		EBHrΟZnX}6;*sڡ1]4H-`U"Ϋ[8a$Ս^%"	[>XT6H;ɥV.{hO'B:,޸)Q0
/eltOU:nV5L+9HXCBAdϔ0U^ڈX6e%uVu>jihvU{FR԰_«7LC݈LaNʊHFz
D)B%"Iיc w5epE{d<C^ԄT rȴDjo{.Co>t䅏aci6XL۲ҡ	&q'u!ꅇRܫijU7Ǖky}L, R:"	mY1b<smrj{j_ӬqpSsK9ĒK֪ENtBK?vb%(b|nsz~)m|]jnX$k~`4ët{;l]6l,C0O`r,)ھkr&9YTv(+PByM7<W*ݦ`XMɇ*g81CMӹ!qvŗ7
sNDaFҲ{Y=.c:Yoxoo
0r2?e%T{l^C׿kMMV\Q|/?Eb0x8x<FPO!E3kt$b*7nݻvR炁sƉ4E EᕮP-B/J:yjuN'Bn.̔!gEh9:fv~NP/KPDﺕT5jwGݨ?CbvVoQO
m*̦^tWdZ{ʊ'mGmkSMacAsU}W]kCf\,RqIWS7SZkZ/4{g׵-UŝE&T2uMyc
D4x
_S%Tb7?P?"(ַVRޔn:f&bo
 F)PP2I|12%t@5uVvVvIE+:Ǐx"ߜ_%|*ΒNq;%[*Ώd{]:telZ}v(>{;>>qyaֶc]{UME'eR_w>$vK7?5ԵtuE)xD`E*(T7fI
.^zB{[5ʻ&B
dm|7dT:E19loJ P3X7C [ɇ܂
	|12%t@5uC!ZX IO	&/,`rXc:I8RdVd[W:=iQN|m+iؠdϛWs>*m-1=.Z:\YQ۩.<ߜQ⹋GcVؑPDB.5E*~rp
_kS=ߝq&U2S*UI+`7HMO-E\o* r-`hA~PC [|`*UYH	<#jw~Q_/U+0(!Z=  _;1I8RLoJs)Qtr[-o݋isŭm%eOGʛjLOzغKĖ?jokjnNcmڗo(\#lH\!Pޗm-TҾz,pS=ߝq&U2H2UI+`7HEQiRj1dxh  AÙyuXN
	QN'@f/tb
ɺ'jw~Q_/U+0(M)_af<{ŌAopPtp*lK}jt{%6lݺObZ,) g͍凋Z$wV6iYuTω-.~߬FzVnNcmڗSh'QdBX<bL'ܵRJΔt8貮^zB{:Z9gy:Pi(֧bǼxB%q%SqM6a D 6 d}-lu/"O!vŒO^́KT-%Zd1k=:.׊0mDmau
d(GpIŵ}ul++YFUy$qc5#90V)~@ָ35:i
[qe@yZpTqe%s[vz	E?xr"46EL;ɢ6z*miIl"4ȕrť2Cr Xɡ*ol4eDPATK)z׿\{&m"9OhB,ӋVJaeXsby9Ǖ+3Dyߜuʗ|tʷtߚͮQʳ<2
[jNԶĖuqOekrLf<hZukV77@'}6TU6f՛I:FRr&tE/X~ٯ\ޢB[GbBڕXF_P%}T{0@fv#)R]bH'<I߫4+<&՞AD"b3$ơ lDVkva|}?`61\r/^T韕;oӊBR,y69+{s{i۴<
e["Vz.{ԇG783:O		+|^b;cldR`쀭#U3cy½8!05C#DBUJX1l"R²7+>2b|j"Q9#
aMd(Dћc¤ano'lʹB4Y 3t`H(w./-ҀLR5[Xj'EvXA'؃ݏ9k;wv&Vֲ~[mdćtt̽,ln*-3!m!h=puJܩcl1jXUk9˛`o&vS#&@`4-W//;E$)N[	|hZEŕ~I5M()KEAs=%
;q;/S>|ܰ߼>KWAiȈ|5OD}7CIZn[Unb+(Oy)[Xe3Z/%4Ɯ#M2Iom{íFI+%/}=7)}q]Cat+5W^y\fKd$_Sގd)7	,I#$ju\鐦J:lnQ(J#ZU4xр\ER9w;Rw%[h'a𴑂aN>#(.RX*|oZl>[#x^OTVԞ/6I̴{)y\ݪ۬y֩YNא7>J?fTML_>xND9'$k]tƞtU~)PE;)҄-,=y02rM9+N]f۰I`~?ӺRUO168S!A1HffhDyQI.tQj[-
+OJ0j(r3q&9>m<x Eb=XOIjY֬O!xcdVTWȁ&x-N_ޭ|n+L7hʝW{5_}rvԕϚF,.}"/_PYpRKB1+3YÔO^nt0
,G{yM2aqdVEu%Va"\Mk;kkϑVzઔ
rg5	]]$H~3ʺ$.@}z(|oM&>QBkcx:LI)a(UuE5WAP4MccnGɚQAy!eISʻxOd//)sC'3DI~dL;W+P'uT:~;";~˿?Z9*&y\e_ULI#P@bW3Hmn~Sq!
8Ձ+S)@jAk;[^k[[4itUVJ꒤~gp,=y+oݿ^r7Xs/Ye(ǧ@kgN'/;HyE{4Pi*Qq.NocվsU~YGS:=$ab5n_SUq6Up%Q[P=<eT-"[e^u]kzUigBoXJi-"Ry9*pr2r|%8|#EowksK|re}d`+1FYF  7,
ճ6/dISDAA`qȁզ%bx<Vpy ɘ,F^ :a0:(jP^mG뭹Ii@%4=2 iQm=lJ;(t:8$@0w̗"{ڶ-uKa*jё*^nڎm}o^/ܴwoVQ4&qJҙ.p%~N0¿VYb5:4<BR?z9sX_Z^X;'ܪU'4ˉ,mM")@->Z/zRww1Wy!1Y8J6#u]HZs>i#X2Oث䮼[I#dYW&1ޢ!w7Yc]o2g-΃]tϮ^=cmmO68z;ڻe]Y[y?юC#J}Z~s!H۞/u,ǖSn+of.:ЕoI0358pl+(v`Ǣ#}'iB<F5EED&X2ϭY]cPNǙЍQ Vuĵt9gfSrT\}EB6T$:t^D#14nšR:,kmyհ`I*ovt1'!@^4YjwJSgp9F{OCfhVB7@:PIe`>؛eY<PL%nFpb(K+طO9j2#Lo犥*!(9EDD+gdU_oNmH(ȩjOe]Oc,,R.qU8	;3j	fz=[MoY{fwUTc 3dmΪeywqQe8,OR.{ZnK=վI7ұͣa?t(o?g`fDr[J{+	(=v!KgH-1Cܓ;tF_ B fCzApE/z=mw{NcԽMG3tB`Q{Aڡ>\s9ubTUI'TRuI'P'rr[=}&Hg8^v=gpcb:deyО888qPbQ|vW.̵p}nMvI#xe0}(A]:KyMlC5QfSJm5$)ZzkUQrM42nWT^8kH,C=#2yWr^Z؈_A:|maW
pՒXyJn[rB)~)aEF\W Iiaw TZcuCL$UuíEevE"G#fJ4=/
h-
zhmD}Mf͸T@Sށa?`(i>mT0
t{_ ]!?j _<!]ěÿ̖XYB>2JKIٷ\Dps9+cӝiHLۥn7MQ۽l#~-Qb;]Р/,L|gƁfTI
(̈/E+⸮Z%!(h  X HLwQcE4	B<"Ood蟢HU'mw(4TTS
wOo>T::V}Tnjq.^;-FemekDdT=הuT]m~WQV[zKJu5u4N"cu5SzvVQ}Jh=KQOdSu%C1_J0@(IvBFdOg._8
BJz$ֳAUP*1Zh%<g ,R-D6Z?=ա,tmeťʤeߗTH{'5iG())EOnbHd}!JݖmZUjQlwhoSv-R`}؃k~5vv]-?TY~yCd=nQIͅML_5uZUŃry7 	!5hn*PP|5kK/#.TV{F-v@BPRavɵH5w(5ۃaBhA> @gkXzEj 1i/K]Z]F]uJзFn-(>{3(|6̏)XͺJT-W`u?eX]aoƾ֫Ewyڏ>6e쇭9<)<W՘̄^XرGZ[uMJ .6AДD
E[uUQUʂ7jn3H֗_<7L+TeU'X[7xr2t37y
)xhl#D1i|h# ܽB,r6ьIz]`6bR7v^xfrҏZQOPS]3(]i<B,۪JT-_V
-pާS>"8! gߍ}]tS_qi*_}v1)_[r?Tyjĥ1		ưb6WUp	!5jjbj!#Z_|޹
ϑ%Tb1l{@AHIPOX]d:`5Pm5jKu G%h ;_R+Бl0sZ%bbΑ(ݗB!\֔SAOL*{shO2>bnҭWՂc~7/"YGD5}dl[;Zk-%]^[j<Wf!+!u~_¦.?bimּd="HEA-Me;R3?Fn3H֗'ALKooK}$VM|@bR`dyY41`0&("F
ҰM;T:6{?(<Iߦ!DDh̴esS(y_n@SAkň".D$ߙnQ;h5pT:W[r+5tLH:f;obg+oQ`[NL.z<Ȝ.PaD+AX8k{{uB"Co{%#jSIe%FW,ui KxFEdt%eU&fV9%Y
)ް?@CM CB<@K={.#a	P8O'ȵ͢>60eq	Fi):^
RzQ#bO:GׇWSbӼGB;sOW{C?1E4HoiCøڦ@*VЅn	W٩NOy{;X	F%>WXi)QwXP"݆(-.Ҭ*.2(N%ytuCWvĭSN@_oA ;EAH"}L[i*$xJS;=A#4zͽ1p	KkEQ^UE^KCү![kaYa'Oqb.N,&YbABh.,,XOG}245]*=n;1Vwx٠Fy^IJUٖY4㕽egrҳv6fPT2
ivaVqBh.&A=s\/|;DNU1 $2rl
h7UqHQ!0FEKA2x}CǗ53E}C+5ե=uROwO]iq[AgMAw)c-:2o7q^UC㳓Qyi\</}eWqvWS±_ǽ֯1Nkf}0H(.pTɬɰ4ˍts FilFtDmuSJR&`aR<.H0z9{
Q\HG7RHLep!ڎqHq;Sΰyڻ@ױKV;꿸_;%s
Î	|ƖMQ+q1adҿݥ=kjRniޟ|P}|EYueOij-->vmXe"3'FpOǂQ0X.[%[sHmSM6SabX,d<<EܜV@!OLSXf%Ylʄذ0ås"e5}byug"#M~.T>,<)@XOVƟ㫛ڹ$ڊHwȤ6o,GCg_])1<.~mg_k­z-QH{]C=P(0ii-DmLJų}Ihi#ANBHѥTR)#OF[h0k)@ QFfgKTK*ViƓzycO1jh{Қ?}1@&Ud,@ߐomϊ~xڨkEӎV=xC4Bh65͢|S'yd]f$ZMAoa*cu-e-,9'{AjVUs#!w³]ϘݹH0*
R R'v{zBW)9k*ZkTN                 %o-7~Оq   {dgw&&M*&.oe#VPp*f+o?dA>NWM!ddbO?i?GX{Hi^@4(|qI.s&Z+J^-65xׁ}4,@z$J(xtOX%{;NHiG/z
<jy?kJrxKց^A=։fT2[Y+)]MlsS#CEڃ3ڱma$u,cB51	TFl7xwSŐ'o<4V1/Bc py]pSWz:\Gc4qJ1BBόd̷95
P\AFlg(^^+GR?BG\b
n~r@'^ց"Bk'KA-e't+eiߔD̀׷AmHS9/ rċcn&a|k7^M `Jot,64k0#Ba<!yäCj20tKR81蘧pLe@eU\ %(x_v..>1*UDUMgMG:I8譗1D6$쭅#lC1@Շ
J]a4y5,Hoi7Ukz3Zϕ1޿Z$KQj+Gѝs[W3逶L8*EϫapМ\c$1YkIcWMHD,kC݃nQMİsUll`J#<0E6,EдÐq7v3prN H[	y]!N!%G"P.cW`R(Dt(M.AƄt[?~IbX:d&LHu??jRaM1B%܊injW,$Bd.ŉʖ9B7[((j0~쥱y#(&[%ऍXʧ/9T9ogQRDD HڣTO75Sq|' B_6ÁuGZGJFKUA2!sb&Hj<EvzZqX1e"I@TиA/1Q_"@V1[bURaoC;%܊F漟9)/⃳Ի'*Zpj:W3^o)e-4CO7r/$hvsB8yڧyKSYhPlYiL~c⃊0w$"|ͰpQ+f򒑮mxPm"d	͢Hj<EvzZqX1e"ID1p=^bA:E8?&[Nn~w oT_[a#&"Q'|
pb4{?Q豸d.Xk.ӏ]ZvNrĵWBFk0~쥱y"XiHy&[%ऍh^/9Ty	T5QT6<Ih,nb-8H!l_3l8'T}yټkכDny7hQ($t1p=^bAi_9lE%d3;Ż6*URoE]
zܖ5&"[~pb4óΜKRŉʖ9B8ejNrĵ{ٯ$$fS'z'K޾:dUऍXq"T9VR{d?"&*07kxαAAO䵸kg@Bv#0Dp"kZYIxGJT#j;jkc>	jD1hZȩSjqЦ;(jOFM
 ȒH& H56
nSnw	GEҙ/XNK6ApKt\*j[:'n7MJǃx?օ!M Iд{\\:]H~'#}
4-lnkhZM>\RՉzR\]cSZ+O!xz(q7<3a-Tpvn߰o q83	Oha1r{Zj^,܌=^5?3$c++5RuvH@BXJqyǹEq"j㊅RzOpS샤1]C:1H$bxnT@+xjO_W&.Ob^5Ԅah*	[izz7N<U1>\ůGD)]4B&K>YWni9e恢lsRSDCJGJIPMPOTQ%(t\^-oC䧓up7/	K̈́'08YsCyQ3,ؓae㦨I)vxŤ'	I6oJ,x16YPm0jKCy/X_+Giveo65ɾE
o箢WxErIfͶ=˄3GqݧPͣ_c`ۨeS;k)֪^YE8dQaIt*"fxxmV<mƴ3*jnAY}DKz7*ImAc%<YrSS\  jL;7 y'ՅT`tѝw#)#0k2|[xüT/;~)"@հ[z=I㰇}.9g[P ؉8WrQ/WR b'uBL=	IWB(mF9CYȯy[46=5ԗ) 1y"
!PsZlL8E'	p
e611Aa+T0̧¶6&R
ȧ&]AREB_hDe!LĔB;f( 	;yP(63@UgC~'kbmVF-
`%qPOpŉIU[',HE"܁MleX bҹTͅܦ2 ݙDyZƤcoM@1̘/1g{-li?O#Wff$',OKw^[Ｏu?6fwakXI,C3+hbF2lذlBW(?C)7|Hթ'7JEH>ŀNa;_〟?X)YAwV2[h@xf>[)uEDGQw@c`cl292Q*rleOȑzpMQ1vKrE[Z{q`PSmF;3c(C*;)o'
ygܳH-{BGcPZlUMatjaO7M@GҤ`{Lp|<6w8Utl#{Eymw2]T	4b+bZcNp*38d3<9bguK-WSt?#Csx*E8P웙$GTѣD֗nR<HWɋei6a2%kf2qTWpdس1<!w IgyeSY(F}#'e\bB]E=7b<myފm9;0[\L $.Tƈ>A,yϽxZMk{+|DzHixwQk_RRVX,QVL;}(ӫ>YSN    ]kEg5^Á鎗nf) ~>]VQH`xD=$:EbwOm#|mD2cХt#\E-H,>X^b[Iغ닎#V5uGO亨6b*;Ҿ7R4+"g'섷^© ;1]oT*wMMsIMU4saF]sa~a=&F[U8YYIܢU
|EmLtELtLtp07ڡLj^e.4vM) @f)CM=
ܮT"HT\1Rl|f.]U5nY/I#FL~:xYF!Iغ닋m.>5uGO亨6b)|o&iM9-=VD_B[]/aTMVqBŐxؿ7p;&
ݎi/𩪦[61U;b|!LkqgN)}VVmRQH)1E:G3xZ)/'Tyhn(AsHh6
xD=$zncx3=rP!RepǡJqWhչf$3܆'&;b.ޫA㴻Xm?XoUyK)M+Kqk*	;ކB{D(cKh*j~*}pօkqgN)}5ef&Cks.*eG¬.o2/:ID^nWϹ3a@֚mQxlp0Ck-BX,z|8r]k!Z$S 06kjziP?laۯZz䚭hr]Gd\;P~.yejs tMO|nÝ
}(bGkS!TerJ'J~;ńlBLnԪ"@^Q蕑1U-#7G,W.#n1o* eCu6$ʋ9y7pQ ^d[ib9E;tHBq,.TUQ4EeF޸9C='tR&l&4#zF <:յ_$ Gֈ}AېZ5LrvGݣt}(w1~T-bMEk?y_>2џE0]Z@</G
sHoĩq3f5"V[KHBlv9ʌ4h|amuYFe(4Hq̛J|AtO{jE(=#ʑ,,Wd6
IBt(]7h.O`!822=iъaQXvb(SE;N,H
{e><F=|Yͻw6Bv:nUe
{tA<n˟c@M~40kB0!cΔA-ҕ
O!p ׂV-T!?!خA>glnU~5Fᩡ#ޖzN6@*\+*j4rrrrI<>JOćI
\\˦TѼB\KȜ,8ey-J%>zO䴾a48XrXQn&5{DKJ8k=x0eAYbW=yYױ0iׇOc 'o3g߁B-q2m.t[D%ҕ+V&b"GghܖeRSGIdO>x^hDɃe$ҙ,Kı,KFD$_J=BOuS]YsS922ᗙ1,oCG.PvAj
QXƼ0:DC}g"ӍAp8":zMZw;ъPy{Xm)o v/MAq@l	#JrBmՎ=OЗ2]#R3v@),90BrKkʊYY3U69|͡{.c\P!%Yb!%M +)D;`g7ۻ&%]s*	;I@$@Hn&f)WkVaT
	8(SǄg=a iMZ$Ս}VN̓Qao	-Ù3UOD8m.ĮCePο^9Qd|:֊[oE8|d'\ОWcJ&AHIcb1׉fW9d}uz."ثꯕ!s%$پ(.PWnW~˞By0֩zie˖6MLXV:iiLc^MRkOm{SEMQ1,Lyd!E-$ B13jr%%-pه[Uxl*Z'g&y>tξ? GQ^%ɿ.S!
٫55gqc!:+5$;!a9a]Ю[$6~#kĤf@[#ٜ	#DNiԾ[rlϭɀMij-s-VMh	0q@% (ƲA4rcnH_n(|#kڜr!Ml,?RԐ:q "oG:q`kîW0t|ʾ͘U$",$q'ʩ)?3/G*{o)KTȤ(kfMf=Y{4錄
-MIŅ)X594UwBalڴASa -lfp \`'4IREdMl_ËϦr3 !KjÝi1ʌUݑOyldD @zjHІ87z8m2K[îW0t|ʾ<U$",$qTz\)?3/]Dr{o)J$v&"GBjOuF	ZZ!MbAXڴA]:>M3hN+yVORMnREdMkx0ތ!?2*PL4!2bѵaΎi4F*n'fm!i&XC~ t!!B$M^N?b~ۀ%-puyIfUxl*oqiUS ޗ*JmOz GQ^,kj<e#y3@ЭQB|vVjHv,)HB:sXPnl-Cj=vH4S2 ZhN+iTAt H:IPF
D);,lZ J/q^ĠM	i峦f"OP+0r&V,6r-\ŦhR;AgpBO@ekxgph=6yopInAEw^Y܇K X-s|º3k|&)ֿfl1iAꔤJb@.A3Ȼ =.1xG]:LY;<nY	DMERJrrrrrrs   MwY]xvx!I**!̥kԷ{u/\HcÌ7ip<(k*"rOEƟ>L?ɧ&Dm
%#S:PVSGٵrZc@#YS<]VU[_(*mcnޫ<ߔN31MJ!aJ"-V0{~rDJ],f|_JG-r薛=.z;c(*&*­2o:Iյַot t{9[TWfǻݰ~{7LلiEkU!_M*Uu o<A-IX0H?HyYtUAa\JBy`e!0B8m i`\-HU*
5H2^.1uӗ# oL3(B߆3-z_Z9;L?^փ	r˒¥.
DC~GMC#"Dhr#ʓJY3ؒkSI݁J¼BXR1싰0cYS3f
+y: 0΄H`"=桰cQMʚƿq^eu!Wk2aE|zqD=T/h/P)T;TSzW1iq{e>[ePa_WAB ~7WQ__վ[탓$QҐB[Jg[+ܱ㴊tȳYe[S+q>&"iKŏ1'ūmj"ƩiB\'(8!@	 pކUg}"w.AM#c/@XYaIaH!M-0Ee#J!6gDև.-oQ\2e~=؞ng6-TB9JB%%̄^vTG׏.$Z FL!$HINh!Q {NP}{	\N!W+d7pմ4V}>KqW0 ߭Fjˢ ۬&Bl7s4)CHŖH2I?-r"ŔgHⱦwt$K͔˪o^VںáFs/E{p`+];5źDfI%|Ymj ȿw-j=$)IİY};/d0#xMU|hXTCͧ4T5RE8U_9AK\=deisFv0n/hų7oqkm_MCͺ<x].8n
T 84IŦH?K?nU\0kLge#i	3e2(Y{1;նQK^mjH^xvX?JWzlKϗ@(Ai3On-R/"RZxd9zծ{$#p)8/f_/@tmL*{r&_G=r_(z6k
	zrpZ	7=sYmaV`ƣ;7}ln=mqO_ܕ|\fn35Fjˢ ۬&B	tR VTIbEIfiL:Du3"_tfe7/pF'z
3icIѸ~ݾ]]bnJ	r/n49_Ok2"!R%.NէA9ZIR>=a/gzedFDgvR/#_fP/=T5REU?c3,k
v0cQ
_c͏6<pU SБ#8-zJ@"QɊ.7`vbqkS%Mέpbř7I9,s˷Xg)=!)2,N/m  vWa&bSښ["xHf)$/Xm0$mҦ%>OX;]|\RNϪdH/4#	<HȿR"&
/Q.%M%5R":svDsE^7|IL=_Ob]Xg6Λ5]ꗒTDC*:@¬%iALUрU vʅԃd5PR浳VI{yΕ}ĕ|3'!rDߘ82"0s3h&oZ!Wfp!16ּKp>r{>p1<l9SQ)	[оqH<2/19G8_D$׹-Y6[ƹcohDgNr>(D8FZE%AhH8AcDa	PD*fH3)fp (T Q@:HT%~)&$iVrBι/QI)vAUC6PQ[Ub*g)(ypFN܅Ջ^	gp!QGN_x)$W*wqNyڬ-]<+˱WgIȝK3Mb2E>-)n˛OϿ^ͫ-޶2/YtGk12 MJ}$${miMYBӓ{/Znܝ`\Ob'3#RT[T(Dn`BӸjGwjaqR{!Hj O<
.Vm8J]BB=*a_X`.fK^0b{>w+}M:2}t!s[-FܻMѿ	yDHfF_:dZ3%+cUWP\U+'6}r{ܣ@˽4]scQnHXoENo^Q51TA<0'`%C+Qp-WEʔ^.
EF	iϥ:QAPYwsޕ[L߅].çƩLI4kBr*ىU#HAJ52z[Ю
@w98y<rr(w]. dŊS1_f=N>Zy͚&H8/ZB(RK1-ƹi>8`?FS9^@L@N<~Ɉ4tי:g
Ii#6oߢd;pC#L/2Y91mi*f5QlMp%WkkU^tiA	\oMizLCz@tĬtJ$rf+G1ظ#CmL ̓.oJVY'Oȭ<ߊ}|ڈ|d
My~uﵵ'ua?$Zw+,͗^[=o_:DpMW,o^ׯEhԮQM_owA-$E}]eQXz|
1NR!2=Swy5%!ID"U/h×ɉJwS[y{\brt*R `}$&GzʥMMZaEBTJ-.htRA+%mL&B*gy~LJ?3HWS~3Y~-d=J#XT+%5Rd^/KeҕZ݊NȒU'X;5Z(WS[#_']:Z՗FX55"br6}O57'#-ti-HY1g}S]I:ͫ)Yh->zx!aܺBZkr+r1,R(s߯o7v!#T U&ع }F1T7RLk3Y"-%|thMI/̬)DՆ$
gL-8{/gﯪ.[TF{>F3
TSU
_˺RU}$NvkeRT[
B-#G+TKS/̍fW<ktkHj+47[-8mO]^RܜG6ѤTşP3MubNslTjE^jݯidf_baM_8e@j6\NI#[Zf*zʩMɔS9(BẀGKK&=$/̬E0[ˉ+aS$+rmmP}'ϥϬ*~QMVު)'JVlWuD7:rTQl*
@Pd/箝N25\\Q!{lKrfb=E`h[)/y nN}S]I:ͱRM1WUKr
{֭J{tȩ-g~.r:QTcUG1 %	I90ʡԧZ!FW:-n4_Y+la2UegI|Ͽ!\[OelE_6>}(}aSjUtx-JUjbS$wcʥj`TVrG̏!~V=tuebx׺ԊG}'nQJٗ=,zV6ѤR%!^@t+bWVC[+F.r.b? N*5W䞈M@33IQHQ**'Wq]'B1}"k~J4hr}KrGg5 HbR!wCo.-?3qoWv필4_yg+	Fw bD	ku	v@$#Ӯd}%~]ezkY)LЯGO!gW^[ȗF%U1+i0V9QQ_\ͤOjl+4_K3\pB}h
-ĳgӡ
k; q9ѿZf4 `9%hCWtƂ3D|]YM:r">-2:ajo6|O
$[H0wI(nUIYc~PѵʹPt#ZSW:֘9b?tckUlwRW\$wj֚jqqEUrIĊC*S@.}y+2d_>eS^.p٩6G%|Af׶:ahD4}Dm&$tF2F\^Oqz pz\:Y2nVZE" |nDY"[L@s&"ueYQh=Ziݵ2@H|oܼJU׵nߺ3udnIÉW4"Xn0?Dy*uN%ʵH[Pszt]~Q}KŴ(i9}[ȠY	CΩD|}QzlYG41-k֫aeRV5QI3qcYvS,ciBiF("'֢/]?si aj7#AKsl[(Tu~̌ॺV܍. 	x9^:1)ˠǳy8FVL62#VkEDmT1^Ԛs֌I\%lKrŷya#Ck$P[T̡EfSH#GfZ/ȤoMe~΄`&Q]T~RmCGՎ6Ꮢaֹfkȉz+Fs|ș>ɟ1Sk(ؙ(i[e,Qʚ~I&WfXȾL_L
Cnb*!f:$eFU<7
2]V^V(pCW(BA]`1[wD?U=
s Sjh#-Ptg0^jt^B\X̮!.*]r@<)p!!1)ۥt`/Z68BQR8f;bo5kU<ӦHtGΗ
Z,6_/
oEJ18!r}.ğ"J׋Q8NTyGt5ӄ:)J)KWrfO-6SPho;ՙ%LMCfBG;Dy=ʄ)IUY	TH          Kr2)t#H4$ S~fδѶ'G-=^̰A߀V5qLq1yAn$rd$t J5Jvz'RUmvVΧR#ga})GV߄m0ykn#ѭ	z;B+8圽##[hnƅִeI2,}%+Ęhۼ<H  AjB!@""""'  &#P]΂EdlYcӴ+ +D7ؕDH艢,%5}lD$)IEؠq6KF|*q{U_b?pM4mx-McF׃^RPxj9VTL{[1wX!UUBb'G*dK=iV3eV%j	vz⒅xkڧ蟩98;Pc^ʷ5/"@BdY@ŢyY55Y5Y5avQ 877ທFRjA42/!qYog4ڃrn瘋	!Ll܈t9uzGzsRn'wmH_~2AmO}˅E^={I"!٣Zہ}5U<|I@P%V4%{LFL6Fׅc=^~$WJtK>뒝Y>*Ϊb3KP	B!۠NF&cMQi=n7^E`N!az G,)uH9MZ ܁OX]b{_0iEU#Fر&(Տ	GVt:M	H;SKwgzs9(Oc+ y<utuXk'})i^1m1Φ5a|] NnIրִM05ܑ&ip_:@j):p6*#cCy-j^*bC+N$'E$څ[QzV}T8䊕dQ+]"(6|Q_`+88V(tRRΦ(DX[HQr[B6]"֡-AGF|Ŀ`:yߝ&CiπERAéՇHP9)e`1Vx'?Nh_iְ趘SCt.,t?=$@kZ&HiӍ6Qj7oF*nň-PrZJI8S޶J)X"F6^uT->eU'71
 n7ӓ#H4I`6	y_5We,JIFv1OU"KӡL:M"P#`w(߱%Zo8K98fIE]/a0\Wbmo;0PGfuoJ!+]6}043H6W~\kWDvLRɍ_VD񪋄n?W&G1۝|MM]UXUZee|3>'oc$v8p6"EXк'l-\3簪/V+>8vsw("v6"6:+Zh+ #_
I}>E;!G7tCE@ϛh>O@p/|3h=fj
;AtgaCVT?<qB2)&J:/[erI]q-(E"HSB鴪^߻q^.'J7x
/H	FlK#Smp[0x)H&nsL	_&p'z%λΒ==k֗,ĝ	[d{
=w?3eB}aQo5X_.) oqjU½3K* 껚RvZd>-dQz/ڤ=\rFtGU"HR)GNgyu Lx}GeԦP2&fq!Z/dT$}-r>*Nb"عas,	b(Q!*?M#i*`K{ӥA3IΔȏƴQZLBȤéG*B#+hĺQ텴=e	Lj诫C5yw:қ;e_Z"f]x]Z	'JQ\ CzS;B(>%⸮+⸩Qjıe 4mRsxRQ2<3DHA4'nRޚCp	<yP,ߙ}9w.3j8$2AcK~뢵d_)fkf
" o	0zx63O0i'=+2!!KʬUfAF6{r_^N\zRv3raڦMlO|rၵ"+!MtTD'D̈́`eYeTYLSaCy\E]0ǑS~؃Rd{83@<{{,[?$x	¶d!t.R)+x>=Ww=zy5}"ACS
LF,GbeutWT=G;҂	SF243TG\oEuD44vFg.D}Wc?"Ì;lgqV}mJ%,[7 FM6j	&Ta&ڑ~Fؖ,IƊk8Er/^DDװ8NiRQvUGcdo%6ъogbdkWP%|lc/9`B)VVYmItWq/u< xj,S_1hUVN(TrseIKE[b[X-0$cluLYjK^Uyp,9ijWwc04"3EpUmV!sOi C9v=&-Fؖ,kUgȮ@KȀvd*6{3J}]ʏ+,&d=<1ܲPh@'qR{%[_nVFoٚqI>l,҉<0ܴN1xrH>Zd,|U0#|D?fJʚ-^8?4nƆcbWt7]=[Fw˄`-WfVҼ[YXX1=ZH+VO]Zlz5bXMF[Vqi_$	*Uv{*<԰>z3trAQiJUvY}Uvfv,M҆++,O#7-29Gg.IVbhdSk!fQdoagRRpدkmc{58ҀcluLYjĺ{Uyp,[NӚ_jWwc04#?yiWh®a$K'jbP crj6REeZd`	9|ˤFJ`|ږQT2gD)>v&FxWWʜ:`B)VVYmiDGN^rk˳n$@bȰȧB.0.-x9x9-^8:ֶCJ1e!ף;Vs
Qk~)cY8`iDg-0!EX1=ripd&P	@Ahj5R)E#Q
3Q0ShԡSFeA@#A"&f[,gmSC#)0O==n"[w*3Z"a(o)9+O1Jej_9tBއ9Gn	cn:*<o	CjG6n'8AtsgBJ?)+
G'fsb-dZ'.%ha"AdY:	]MMHNj5RX%!o>HˢP鵂(31#BEHD)=2躯%<έvyP.ghmla0r-5InLIg!=g˟{F.ҡR_V$͈_oʄ:>
}!j~=7ٞ
͇ca67*1HW&'~1Lnf2{+ݗV/'*CWϖޫ,,ґm]WP"^
fc##o@OWԄO|}/ ϖ %~Λ+&!S	e:ؐOb4!Ud(J؋lat*5%-rx]/Ѿo,&:? Z	١ī?T告1nw;|jy֠G|:@"P|Qvΐ
;b* 9 ; ; ;#Wvor1!+i"v	p|^X7
'%{|/+Ǭ,9;q}iDzBˌjiU/$ny,EY]2W>[DԺ݁?qٝ~}oTUAX6mkR.^WIf#E vX<R{,V_ւ.(\f:Jo9ߤJ31OXʾKSoJ|j쁕`˳\tjQC2Uʜ'8sfm[p9AհB!o$mN=竩QFP*#ŨA4sߵb_(lLceKU]`qH@z(uKCHV{壣R]%)lr3>w,56R^5CKimrFN(u6gmS5^IJ*Z[*υ=k%5kwd:*sam0PSm\t̍]%:&D_W;&e_$V>n^׺ݛW{"&Qn0UR%/O!>z¾g,fE Hk?w${PM	qHSƃZ"6p>DCUZyZ!\*Kn,&^fVETv"?VBQ8 {PvGUG4(X
g=Ye	dlDyZNOSs纞r%Ovg@1}
ZUq$鐘~CE:g;;xѿ'7Ij87'^oKv+ϖ1umJ6Ok
~ܧd+s-k_KNًdVv0GX۱)M"~qwET02BYR}c;)}%g
j7([VP]W#LBuJW'T;8m-ZTo[\\z[maRe+Rj((іN4m=(.[$mOVIybcK˻u:+zʨ	_KVeҘII]vd3sU-z4/GJh"iЭ?ih+R:ϥQ@n^io^lF7X,tc*c9,)h{lom̺Je&
iL=KCqYhL lWU]n~r[^HV%PR!`9O9R]DR1lr_@bQ_z^ɺB;>Z!@FBP3eOB
-K%K[FuSղC^q-mq5Ί޲*Wյ|tc'5z]1L}e^Dj2{qJ;4zMj]V}Jh"M+roޓ3>23ϭb~ٗI[>M҂ ǢxbP[\̇XMiMʸֽ@$GRʇ"&=w_N\%ch( :\	a
m~[}2Yօ6c_ QE%}0_J`ļw_93'[ݕ%I-dԭ-zH,i7~#rIcR&R<8~ű^r4wa8!aݒG{ƹtVΦP[㜴$af9^@0}
`״hЮ`̏	q9{|Ҝ3r|2)d^g/kGL>H'qĜg*yJ_Ji8"k6w#VݶﾡSpH3>2qУ`1C5,l[yp7WUM'0jڥ6#Kc:A~@۔k6oZj<7a[Z[{9{;֎^ )J0Hq<Ԥiɂm_
`inq/?4$J_<ڮdL&eKUǿcr-^lR
%:3T2K\W[9L&Dx`4dGo{Ο#IV+wåvK̡$	m :%H!6iy,OœMobh7Z^Zd3Q`%]qtHoׂ]-DN-7ş_sfKlЙuǙ.,TەWFsչPEW~*;	FZ2F
Rݮj.1UVfi|$o[ޑNgr]{oe	DV287Ş3mɘkql S#>EY%TϙnpU6dqHWBL҄5dB[dq*; ^s`{Jc!X|)LϏf:Z#m;.Y=<|
C6!3uuZJkivT1v<~b9\J8GTeMe?iG_Y+#"Ts{l[n]4(@u
}e	۟I>SgH||6JC2w=15y9Aup\x`Dx.s3~qJ^ݞ(!js(b#Ml,_,Љ%ނ!G	p	f	X}"	p3唙U*b%ZV՚#3zeCaZXZE~ef]-JZ0N0^!?qE5:{&#bP&z<Hj,keQ'Doڏ/::Kqeς:
K&LL=l|n<cpBSc"uU~OU3X䭁Ӿs)U";rUDx y:f P`	7^mA765|
F}.NuQV!Z[6oTI;44jݐnIu#PIX} !>L3+akr8+/@9RV)vp{SʮE뭒>""i6\/q9sc;j[%*Y]~0CpA]"ږi\Ck+{JuUU^7ޭQO:V7S^<	ڮdU+Kb\ip5\ꡡx[py#qSS?B}/9|Ѷ5bZ5nOy&}iMKX}[(RP'vibv;N@.T;ƥ\KFOpk!q{eh
K 7?2{晴O(d4R|_UT_`J1}z;fzi*o*s$x"gɘTQPop \
+)iN-:gaD%!f?AK>\m9bC%kNAzm:b`p.~#\=/&F#=q10KK'i_Y0noiaO&Ez.lV[<icw.񫹵&rU<~D,g(V_
FջZ,)˲{&=T5	|c"(qTvߨʹ16Ă^Oe5D]KW"Q=V#+NNmL&gs4nu[oXuh< e$->Y>&&d:w>(  &<"JZZp`M:*m/܆	,ql9e땉Z>0lpL02H^É-,Gb%~ Z`VqL,UB<OH||޽˛Yl/-ܹƮԗ/dMNvymkkEL]#0!"ʅ>+R/ZҏWOGmʹ16EWUZE_ƯC|!N{0h\6%jqZpsnfq3;!5F~ׯGo$]5^J0s B>&&d:w>(  &<"WT8nUK[4хi=4B.)3S.6㥚/}	6	Nŵ:eeh k:q2&F#=zc$~ɋ_Y0V
 t&Ez.me7rX7q&佑6O:-J|)Vh؆<ʆ\=
}V^=*QhbmN(l+٢Ýv3n&K0ݴfgs4n֝Z^%#	U(<9@<6~B*2hp7'
 	ȠrR4ђӳk'KbB\r<&cy%t_El&^mιXu<XۉP#r1ZY?L]d^Xs{MHVX"{6^[K둞n3u6dܗ&I'YeȔ+np#j=;y:OԋִeT|vl}Id`H%y_.Oe5D]KaΧQ=V#T3*L1pe膩n6bh指-760ˀ$biqcmp@m_3KG3gK:j>?I6iv0$Yt{t3~ޞ甽xFΐRfASsӬ]>U+UպC7NzP2tIr=JXGh>jiJ{Kskjm'Z.{}bo&4sV>HTQ3!>n{6)AZb
mѴѿnޝvO&QD%9Ʌ(2Q2vk^++7]Ţŧf nTq+3y	
*q tcZ߰i@HN~j3jVډn#
2<bt=lTR}*[2}&>w3Ws"㝨ص3Nzܙ;Oiv%=3[*=~hq.rtu:/ݥEIr&j+KYMܲk}xjdkW֏hSREY;
XS*bf§4ZaIZnq1Te<df&ڙ؃>7[`n4߼O*&P%8d2Vd9p×3)!h6:TDm=gQrھSdMtϭQP3Kcz=?KK,UEYmY5l>Yv
*[Ke:߭:zfR
1EXy.tw݇#V'[uK?1<N7ҙN"4Ri4SwybZ#4:<U-R w}Y
]F  =cPbYeYYeYb0K"pQI(sE@T:}8+1Lw(Ʋ$Rg(D8]pDp*ufR1	ZdT'0D8!M1q<23hU4X\xۥO[r^LVx4!WVSk⹽-g%bHj4jzZ7SABEF7{P?6=+<A P,,a:%jqO3tV"G*!]`C,ꀦE sӄ.f"^ty0'm<ǫ ';oP&*ܝ}@>Cn	N;GĺĶ1I?$ZփϣJQD/it7Bꆛ;TSS®',?d\d!m""zGO%M*rV<B/>mD\	}LxT LaI!@?"l0`|'M1}Bul	`3DRdH=xЙц\&jִ&%cO&0<mcǳ򓛲zcj; Zw	\,Ռ5d?P	]9@2a;@A	Ӽ~,:F(>Fvi=>R1r1wKntJT9Ȏ&%EgJZ t۰Dyrk	?x0l9WR)E"HYhnN`Kf[LJrߓx
3/[IC/961\BHԻC]I{H ôĬ6tp.:]ưUt]_KL(}f8atDFyfm3(ZdZЧ=UʇVJWRD(ԵcK(c3QbJ*5*Bb">"\RuʛE@Vy H,ɰKΒ"XTX_l7F'lT$rgXC	ı]8|1*NWvʁ+EV>R6"n*y=ތFg?ui1F>k\(LXRUԆR5&k;7#Nҋt3=Kfen)t4'ևI-#8B񕈪[ :ܕIփAEE<Qi-aWb+2nm)*wgID*VIKLV>	6l߭[iŗ|/3iOamrZeI9-^ ڊx3i!S^u9)Ũs4S7d`Pӏ Ӣ+{Ο)MZ3KŌތFg?ui	F>k\(LXMW걔$tP瞌Whc#Nҋt33԰Qfen)t4'ևI8鴢8B񕈪[bܕIփAES͝Qi-aWb+2nm'wID*VRM>7uD25JW1txO4 OcI	RUcbHpGWwNh|(1j,WvF8	X:.-	\f)xј(r]*68Lw7IZUe3I*ꁧ=`^	ߗ)%vM^-3԰Qfen)t4'h~Ԓ8鴢8B񕘊ŲܕIփDZdS͝Qi-aWb+2kf'wID*мRY5Y6iwyDKmZuBMpp}fY؉qA@4Gxomr+HY1Rԣtw[
Wطnav~<;zw-+3	vsȼE@50`oxOc"V5lsO(r^jL'HZ_yF.%:fvu٬\|[QpPG/쾩mʦh G[\QS!BQiO@ moFucjL*< L_%ހB"ψ6.NO}-)MbB<DJZsJDi KLpp=T6$zr;x3_#nt90C@##E-Pm\ʊiZJT%,íE|foeGQ؈UQ \jEwS1J"0C'/[Q*TRe4j5bX4D62U]|0C@+G!d2ALL+ahA+D]XLϑpKmQbC
w89½Js]0{ׁU&k?
?)H|N#$ߞbIt9 ^7R,8Ozً)pF_,YRp$]ܒSh)3koϿmTkVWns~QjeR+*%1s߅JHѧȩ	  4(gJ*TPTR)E#G.IDV@GӡO^rxP-Ur_,ՁG~aWQŬo5b2O{束IЫm	T^%>dh}xlK-`Ȇ=f33oҮF6ͫĎ_`Vk)N`j0NF*0&ѥhT\HEwAe^_<ĴbT!A3C$3O%`g Jx'㘪%}s90n9ޛeu44fqkrMSl[DBk4O$7\xr|K)G+vײ29mkU.huiZ$	NޖڪC=Dށ}4CrB9Iۭ,WRIL;$Z#$~U˂Y!gfȥa-Tݚ  հs0]XJ#A@WH'v[RO-2%|-u/uxQe4<Ҙq-G:ʕ7vy($u|$	C>YY;'-Yd%z=rA)O޲QzFarBώMjtG[%B+*!6ZƸ2Mbp1J%C	TR^C4e_K}/++m|F`A4tc]u^Բ3 -)t1R/WOu-uI.@8_t|Hظx-dz.yNgrǶj=ԉvOn>qWAMfpW%[=8
^l_YVіdĪfu'bBcJT{xiP_MToJS@n`ׅIh7WWv$^5M(& Bi}/%_Q5p  Wd,7 M`2#]j"Jd4m"ΔDSձ~Lڝ\#+Q7=Or/bU Y7|ӲYܥ?Y=ԉvOn>tS[8+Ef9*^ͅ/_dBhO2bU3Ed嫩;!1_%*=b4/jzgeG)]} 70Uhxn`ȴXśЏ'!史~*ZH W)	%_K}DU($3 d[㝀C	̊(52qngJ"IǩjPؗsTiJ zqeE>i,]=ԉvh&L=%ߘ%[Ӂ9_\tHD5aEV@~[;!1_%*=bJjzgeG)]}Ҟshxn`ȴXYg]Ke*h)@93D_K}/)֫sQw11#86W>dKKx8[H$>Zѽ7NZp6$"dCFƫAo=;_>G?%wG~^w[R%r "ۏD2$٨rU=8善іdJhRv,BcJGFFS)˯=
1υTz>κWvגOTR5YeYeXZ%fD3B{oox	fޙ9VJQ'>Y毧g"1:02AnD&cv6iEN"[a-$I[ycG"k(g{#Ճ_JJVMjyt 
y)O6F
(T93z7[eQuK9${OVib?]	sQ*.*̰    *?hSBp"aت37>W4mfqU*sjLlZ]LgzPWcm?TpbEhRVT\>X.Td$f&kXlܾ/(Jki4Ҫhlo]/GmR>	c^dKi?E̬,`1#de(=Q&FVT07}?NPHjl7/-ywr*5	U5UN5}ƼY,<q&A-o#Ǔ@uj 'gu\Mi4Hdo%wgj'
iNW&оZTeTv֏#dHWӄ2Ag3`iO+xe^U	 q Lp`}K19nx[Øv3"J?QėD	L_^7dϹOψ@KPBۿn5',lr/͖?:Fp<8o3Q|؄s4܋VRpB铠G#6%x٥DvJ,yXmLd͎w8/Pweuۿ7w]#1;(3UbDrV?sPe7ѝFݚpnD<ܢdbIKD%.7wOQ!sl9Ͳ0.
RDd
!*'%eϪIL'+EZ_o}1`@Wb(-=`E"nSY8憏Q(ɋ݀evlx;rΞ/Rb#^SS&wgx[mT:54޶[k_DW-o-;>pɾ+Bkziq5D-
bV$ffbT*jTէ
OsNo":Q/zlC%>j	LpsqUvd2!{gg&tBt0*63w]weoX$㰻 rv5F0Ġhw8Kdc<yNJ]*rnٱUÓȇY!ӌM7\u~oIdv蟔n޴jj}GRs@:UAHmc.֢M_4}bP?ύ񹨋2)?I}X;=@vrQv8XM2E2hٞR*}z*[bc{:{LI8˹%JeI;V/Qm{J'`0|Vw`"T bfJ>4ceZ՚ooePSD(9t@E2Ƭ\PlZdt/ȹE	Kn?5sGkK1K_(Nz#;A_\ÆU]N\$7^Q_UnllYR4Udܷ__tC_]/Β搟Y	)+kzkmtV"6=\Rz4Fr~ho8wnڳCMgbN	
}uVCMlJeihd6ҫ#4^hλuL3[_m3CQVU@!c(hv<r,
֬{-rL'$9D /LD5fX*bכ2:z!~EȦ/J[qJ>)gVibKIQD~ 6Gy;pupʫIzˑTK"Zb*Flk2_%!?ׅ9eoMm1Od鮬]޲ַǡ[JP"dˆaۣE9w-u۩6sؓ$*W]cjg)դ[:ҎmN4VJy]2Z8wfꙟ5f`r>,(pgxU:XBՔt.٘4q `0tpX+ZS^_ʂ}-t] 2]2rXՙ`@ص:<"Ha)mj3cgVibKIQD~ 1o4wupʫIzˑT%*Fl	ێ2_%!?ׅ9elt3Od鮬]޲ַǡ뛿M"dˆaۣEލǂ-u۩6sj;O$*W]cjg)դ5(mN4VJy]Ѿ-=,ro0Ӫ[ue=zxn$`\0Lܮ9 1BzL`Rm Tvx d!2Mq1b`6݈,sI,w.ӊ^p(Y(TN-
[wOK_g|rB|띬t9kd+˵hY)QZNTr_(w'I$gZ(gGCFOڐk<5ͼ3FKNx[|/.5,<Eh}OH<,CrEfCETrʗ$>)K蕜'sQџؓh۸E=SFTio$<Va`qEtBXIsv#W]B=rR)	88/]f!Y<㇛\s6i~JQ{k|zH'.DM:rAFZG
^3؝zOwر8
U).ږUIi/XK}7}cբ|tϮXsX.٩6ŎH6oNoa?"'<oS$t2S6y{oZij2Lk=uy&JY?LXԱm?&k\#geW`@yd|&x) hh*p	 툖9L)XŵuEҷ{0=O~is
l{upK-,r@7R6(s%{U%adfeY7E!,8twGWZsޝݲfGˊFZW?6̻U6O]Be|T~}~ō}M,zk]=Po;ߗv5j_uǕi,T󟘈ԌNn#b=c)E+?9ػ	-]"z:&G<#/#G,5g(n$2*?Ugg3fQт#@NRzE]<'#g7EXoJn.Y	$1#A/m5m?K:֕^tV4ؖ#?uţtZ uǭe⷟;n)y,W/S4FnF#3/kp7R]cV#׼9T:Uzہs5t8@5y&Q&.JIN$X&}%"8CN_g'2B1:t>jºi	IDE^LR;4#%lFz1$#v]CͦPl&g!Pʅ	5Nw$Y]нP`e:T'sS»S8ykp rd.HqƆҤʇ!4Fd* Q/s%:{EZviT))GAJR$>-x)_yۺuvvmH]Tw5j)O#RRU//nub)+EnO.,&wSΉkgsd~,[㔬4W.IL膖/ H(U|@y/}E)eQKT
_K(2бYh4NnKRo<ͿeGJbE@u}tM%~IzCas-7A		K;,WTL |`&vdR{cSsnُB'21bxh<Dȿ*;Rg-r#;?6<QeI#;24hv֮)ZvVv˼2tHoIPm2ӎ:XpdznT^#e]}Ѷ4"<hbM{]E׭k;e>'͞P!*!TV쳲[5/HP)(xy8h@n,LmػM14J"Uʖ4: 	o!`k?c+O)\>Go7$dt$`'ЋFDy'OMy6>κqu6I'U}ʏگjit]#ggQQT-Ŵ9v6BVm[Wm_B0ɟ,UZ޺ZjJґmq*e.*JkU2 yJ=IXK; <^p!Ig{JGU2ayL%'5Ջ,JC#(DPJBY(xh!Dp{pY^.SLdI	^K)GjqSb C(U]̵}w2>-by	  +#Y8F^5xXZ"wZ?}ZkϹ_uӋ~\r[JI?dJT|f{V3NU&k;:gRo.-CrQ@\jڼo/!tLd7lʪן{vfZR->5T˄]@|I^jR)G_Aث6޾	gz@NBþ`ӻHJbiKR}M]XĮD?#(D2$MF ̨#!d\8c1X4"B6lfYW*[T> %P7컛kGˆ19ߊ8WHD:21+#T)/e,rׅ$^}ͪn;:tڒQ"tq]테Ӯ軮GT,2UJ*ˋhrmG_pHJںk+zȿą_34ݳ*ֹ:x|9t[p.}"ƿp/ʒL\(ο'փeV:m|x%}Cwb\I1/I7ub+『>2đ6M 2#NiA#dWʹRڦU1 -2XAeܬ]
1ZxdLS#HUhEWZ"wZ?}ZkϹUg]8|tRJ?RcmWc4.U&k;:Vu(CrQ@\j붭޶/!tLd7qf&k.׀WÙ+WJEp.}-k
p/+/LHR|}h6[c}|RXw9wlQE%~RS|g]x1ߌRJDfTD=HdQV!ځ5@=' mumIaCW"H&SY91B[AYzjuKԻbv ΠoԥS~hw5W`r|w6FaҰ镈*EFZJ}Omc[/N\[+]1}m+:ޢ-_eVSX>{nii
.x~ӗY]k᡺ ށY.eWl>SXVew	,w=_LcuS/R`T3}8J0yEA;ƒQ+L
}& YZH          1-htPz`n#{\9t!,$hBh?GEg,hrvm"	3J%GK잎
l.Jg2N<Ks+TeF	TKIsr=؅鱝&^Eu|D#UҤyا|(WOkgc눧<cT˸ˠ]8T"+,8ew	)-Q}IM%0[^*pBinݻ)!D8`so.5 3e-Dq/1"`Aqc<AyR cKYWQ/aWcc.bH&ÅYWO{ ~OA.njza{Hֲ!s/Ӂ(_cw[dzOnٕTǴCoAWVOF-&~A9VMYW.!XIla]AD)+%.45PnY	R=h-,ko3*8XOm=ޣvY'Ы-eK,QDTEdUZU\dl;# gN;}EHAdn=8<-96A_3TC4?!Ƈ.Ri	8c۠5}m.*ce|oo>Pn
-iPWH3vq6p1G^ʉ{6G<ɉN'w1?,?z ';31-K΋v5TE?T~=G{;%VMj)mU/!sot*\ov N9ri!<IkXjx5{&eY2,uOj@4yR3bM%Dw|z	C,඄">qE$}Y~ZoVI
~GΛ/o[wzD8Ě̯S~8tHw70Sl?]Xq-ȟ0X޷-C^J3Bc*mspD*U?JiX̨=?Kmj=^W,KӦЛJJvǳYaeVi=V63aV `-1UK#LwQΌ^jF	>H) z"mƕ5h&J4ʆiGS;먿"RM6,*nQ5/y1@WjcMey^J+r`c౭@CYǍGp,˜忪SȳC>	=Q-KzĄ9NҔu:ska$Q&!a @<I$B!B  Bs<ۡ$ePji61af)\2KXMM%\Єҝ5ZZ#sobΐ8_%ŔLӦjRmnzaհEjͷέĊҿkwނӀךJ~~Y2Aϕ|5MUMp'fpܫ1j(D:xqFx=`5&j*(\%sUqVav^"5	 |*u x
y},099+"ά[jlQ`*8'Ta?'3!-Pђt4OQKUH1b DT)zwq7ˍ`u/dDLCWLY-]Ӿ!{Jbd3ܒIB9k5
t6$!3e-xSK[bRںH"0%yUJVK(cƂ[D `V3^kp]Ň6]Zs\uN j DQ"8||@e')kU>-eU5tO\C/ѶjHY(8 2$!;Ak鸷*-YAR&ȚWŪ&oz5`&I _,'ו_L-S?-c=YXۍy)5]9!}%c]*ѨSLvE=5T<tOdqvPCYY^W(%/|js:1rbIj[Q!LRLR˜lz.rALC N0_nb(9MX©o(mTHtO\C/ѶjHZ0eA4LA-t!|zsʼ=>,VPT	%_+IcX-ɁH9sDW=`$KTO9/|)u\|OQ`,msI|`c-65YWiYU@9J	XOdkL:U?>_R7_7U Y&5nz^Wʏ*<3N$tҴ$
S>eP9@qѼ-bj}hBeW4^w/úP=T9B#|r,l]~3S派^`ҠO+Rzzβo#ifvMl$]%bO}n35YTDY"=1)M,AUKRYOy[7V}w:Aڛt!m6#h]kS;nZC5ma҄F#5~߷߷~C}$@F;3UopY.}`-@{\@*2ll<=&+e`	)vpO>r`++tM6m4]_}Y#v,э$rzr.(e#Kqq@M"7Kv{Ue E/2S)QgWޢf,{km΋4|.[E_Yj%3`qSV7(T/˔s"WW%h@w[m;Oz^bX4d`:Ƃ3@UbRmⵢ^Q![n53 H*ŢR/sG6awn+|DWp1]g C{nv5:go6$`O7!N+u'D)ÍES F(P^J-#SE)LH7nG9iՍCa+sEkjUZnȵDæP@(n]?e*q\g}Ʒ-rܷ-!4$.I
5TY ierf0U
'ZE!ʡ$(Bm'@>7+TAћ1xl8LC}k ,tnr߿R;lB83fY|Y}ACsĻ_VӬ~'<Gj:MXwcF8Ɣ<kAQ5}CtٛJzSJfBYO{3'ƣ1&=XOruȑ"6-rܷ-rK.tG$-1AV|>|}{ca'X-7ܙ
G8s[$ڋb"-18HuԵ+ͪEܨ:ZTa5~F5vAzPl6Ô-hs
Mc%i;s(S86VӫVweYf uAݞЋy_Eqef@#z%H.qe~b}рab
j+QRJ9	PZJ_oo]nn%@^  r{|lk0ӣɀ/P& !-0Eʄn\_%~(%Hyyd1	|qJ"^7.^$Ql`$mnD7: m/%	Jz˼c(wjoR0E _P֫/l#Lv0wQ=O,zNcS
:@[+X
P5T^q}P;mrXQPX&gNӴ]v۷" $wҟQ'Ab}@ha Wb:"}U,+ЊYE&ӎjifڪ4©RA	#֐Qԧz=T'Qh:uY摳/|׆1Xb:9r#ZeLtR$Ѹy@mm'xTҚX2Y?9J<	yXUp0שJb73U_̓~7OwHrD4J~'iػv۷nݹ"<V=?_dpr>PFj0	5qz#'R¹Q#fiPc43mUfKUT}"0RVQԧz=T']l:uY摳/|}xjv1Xb:9F6eLtu/$Ѹy@ZЏm'xTқ%*Y?9J<	j%B!x#%!RjU7~~wM$NqSOpv۷nݻ<4D,d#?p+tlDdD\^xT 7Bl"m8fmӊNSHLk:u)ޏU8hE[,25N`VylԽi^݁gE}ʹW&,}V+\.:8\7?Z o4eR[|'58xpCEA*Jo;Tgrw#G;˒'8H |o=}&NwD߭,2KgK:A}[Tp^W "9Y畹*XHJd1NJ)^@z(9Sf&%6^nkA.SѻTu)r-(z	H$#bt!c*ܻ#л|M=h#$*JR\-jڴ}DW7ueݢ^FSL]we"-X庬y,3wM6uq2j#.	vm'˥r7g#wISPgiv'd{F
6AaOĉ7p]wranofk88KG
D	W<{@`x \0ʝͫqfQcM*F3/>JA	%r4yRUU9h@x)ѳ]o?Y#kav6یfZI,vOrZVpBy4ttΥy_7$V\=ovl֋:6PIP4~xEW߉<զ;K-7lt2RUYC[ڽH9dѤ&,oznWEb,Ařlj>Vr?dkQY:$kܝkֺZ\'\"{

?C&ËMf/ -̠"O0I
i _:i,L;1+e/N}?PHtc"Mҳac:^Q7n_y;[JOuaPEu-N5Ԝ)A 30,zge_=	gRXW[ix
(||̽|X,EI,XˮZ˭&q*6*Fk;rm٘Q5ӥ@';$oAuqiX8SVWnv2GRK)%'4椮6~5#'0q>اQ;WOY5Y6S Uɫ)F	.Ȃ֒F]q_mnΟ2B2W4hXՁRKaƾD(̸)<eQ]7xCwm|VI}ճ(#?o9<Tɱ7 #!>I)Bro=$htlRfw
RZ76~ú?O~[wg.Q5qг5ws`U7WQ$iJL]VhU|C,h`@IUUynbq5JJ#CG#y 4^+4Báp,""r Dʰg*+{" P$Ψ#!O`1Id+*IH!sN(#3!"TD\U2
0o1w9"K;zX^X+_A)VJ)_ ީ^z2CKɝx`7YAԟї7LBop41-agj̜sr}h1n͞^PnĜ,[=yF;'21GCdV^{޼CCڝkyP7b)C4w=n>|,caO"LsR8.T@0fmr#މI2xG$Y(@wpaVׁM;ǩ;߂\:xOy,^	6W8>3'E"6W
)eLnЌdSx,SLO2XC< mkϚAVK!սvj6zm0iSFôlvZ )IoEII侫)n:C[~HkFt͒MLʚԩ6@dIkSKBqaN6Jew^nywko.ol9eLZ״'XulXY  !%AgtGa`-6^]\ؔF֊.EnΧN@q|+vog>nFRR9P/]'7hn4(;oFmHm_V$\Pqe/A\C!PZ
憋S zvl/[DM4D+vIU7=**jJJ(hQb_N׭+eg߶%?Trɂ£,-jSr2V."ɪ0ڨK݁]V}cU*)M9);LR*+zM;X
(g:ornT[JF\@0tXatEgqqa`[ڐs>F:l+/S,`o%,5Cr_(SFZc>Ki*5i'ݙUV(IA[
CB'
[\iHm
^бwޒ|UWypEWso'<BdN%91ykĵA8,ssF)Nܴ- SI[2o:lbǺk%TVAU~<cV֞ӱ+~wp֢1yC-Lgپ	hkQqo>M%%v^ 1%0͏Cgٯ}{BAJKTa+ %&;/`_P<jX O}:DM	$wg%~eJPIP oCTXdNdӱ]þ4bi$#xJ -EWso'<BdN%1ĵA8,ssF)NB
SI[2o:l&,{TVAU~8̐|o7V֞ӱ+7EEco[[7/_(.׃]07#.|~5MJKJ<"">f/?tl`Rl..2d$D2Jdw[Ҏ~!Q](VoXE@T'ʩF,V=zkYCHmێocNs[@R1=AӋ{=&%`~^\[{&~MSuM511Ɖ%8gNg63/4_lO-<ٴā"ERN:eTJL`܈t	{^l%LT
ӳ\ʆⷼi?:~h>~3
DOE;cw)R!^.;߉r:bdCF'4LGrH03(̽pC{43T3br1aN-V.=]y)N2Hr/%	P;_(0H!D,dwcNx.2!Z(>&z5Ĥa69ME԰Kr.ބO$`武7"|l,<õ(}gaӱ:IdF.eJR.ⅅ-%I~MZEumU;7vݴV." ~SzĦ(CV|FvbZS丆Xl~$"'=
3$$=%fy%~
&ؒhخp46r,rfg/|, 42if	m5ZU/Ob
IvL= Ps6 y23?L(ګZO\oۗ=UTDX_Åݟ)%Ԕ)yY?,D|m$مaWj~V.rR]R*e1cn~I6L뒟<HSN~x<-"×"o%Ҍ:Ͱ$v!7vo2Z	@DBrjߒ@80SrrjHjYUS4ئ/9n
doHY4fn4\5TۍL[Լ<䂅tz"'I]I9{"mO,&Lx=
bTV1蚲'2!,͵(Td.¨;mfW[jۤׯ.pI͈pm_f6)<@KEG/+:sS<'|crfAX,z-aD͸fJѻmA'ܛ.Z;ieSbF?9+)C~-G#&|Ҥ-EVFMץmyk<[{GuA)Pz0KnNeҵ.m,̯܉Y6Y0cy4JDDQMYLAX*i䨻	gNZRm"P~mc'l*tܣiۨ0ꥦ?mP2N-,铅8i	jlq+ן{2NQ$~v7muןWߢ$1|tg.ikc%rgΨ\}6g}oo9<3&62]"17nokm%WFkCF[
rY*IkPeRg:0,	gx*64iJFs?֢Iu̘+awfZ`yǽxtç.r2<7 r0df{ҎjE^TLtO6YTҜQ/\YA-H.X!EZЎ&zfkp,=,@dNbjx0iHYvOKwzZxm5#,TW+$%uGNKwܔ4;4,^)>	H<ԅ'z)Z粼5f1.J_ҿ)K(ʛ%!Q&PMfx&b|M}2߈yڋؑM	&DmE^PiuՀf4[MCS|N"JIL]w71d~h(F`_ l+'Mgp
׌9Kp2LLhBPeML`?5}v0K.Gqs]e+JF-O]H?P6{|d=Gt[7 *Y@*&HV7D7EySRv%$7\\/9h
5$!;Ug.Ȥ}RdJ-.r%uݬk%keCnIn5+b	=-|ʤ}QX+?V<Nѐt:(Somz]E%'_ewwbg!c̓| 
Ta6͞-*±?#N@nR«iu&4!(2&W0;:pK.Gqs]e+JF-O]
P6{|KCrt[7@*&HV7D7EySX'h9_B_I].֤Y(4J9n1"%ĉFtd{,G΄>Y(IlrM-&%~aMU H3̪GI\8B@P 3=oC'9YV^@ō;%A@B4Ǜ @>	JIYlނ+^3;DS#$U~0ΤƄ%T=`?5}vdv?˷=/"-O]H>aa(yki'{|d=G!;߰|M__[7 *Y߾$dkc|$MEySRv%:BmjO78(4J9n1"%Č$}RYUQ,	v+ַvQZs䛵[\Dn4j7U@tJZ@CRwQR\ 2YOJ   .!hT@nݻvC49gS1 m-y3
,-1Tl\] 7,N^GhƣӆRoX-Pv䓌z3	&U'C:ER? GZ.35t]XkʝC9k
sk:%\qWBq0X__q{!Y:S@dz;8J<p9c	ۍ?d$[2&\]Op}L.5x1?fkF#3UPNʹfiZ*9w_K&SN[UY^Zi  ͙#}dYH(POX@`v`TlfQu0bu9s^<X)X#!މ[]fʹS\727zqB.j3 M3qǉuÿڨEh:?+.m<HDwl?2Q|zY
GzCn'!Nڂ?r KL'GBSqH{*CYG-?_t܈7Ȍ"Aa%jVԄ!ollȍ#^5"j_45d	ynVLtwE.e81S-nGOAz==kX 971)kޒp[4.9|FiVj-UASI}Ú[%LD!嗂\)+SJ|]h-PS]+e_53c?}{ZHl$ŢI.RSapܠR-YDWKKBWlt97nG3s;CCBF15`2B-Pr(h-a+o#;JEw=*Otg+tqA%;8xs3}ohܯOIxIM(]C]jE+x7qm&9*V]Ϫ}YH>Yqag}Nю9?k{9eSsu eojM]4X+6e+\x[a L+1	nl"lR?!!!!!!E?Nfҙ6"+l/9]}XCpB9LP1[pOʂ9"Cl#-c&MhZXZ  &딞fo*GťrCjTe]f޸)m1c3<9qrt"b۷p8/UYvu96jz^clBjr!'ڍz)R? Yg&3o?!Q^QH!eNw&rtV/>!	{:?$&cBcDRU9xxȹ	*{KH+eh;5mQɉ=he&?Eq0Pr\ glVEKj 4 A+GTF29͘(FZ~wSV5^zcotE|:m_Z9"V'M$7(_TD4bOPU8Hcs4p%Gk~FQ..aߜek+=J*?^zʀjvB%'.s7#VTKQ4{{v{g5{mWfcͧx %<ދۼu%(e)  >e`ȳb3PvjB[6$D\*نoK4ivWqN,zX/]'gҴ<O;hPm~t4RXJس
EY#yw_1fK"n̑άJurJ~.ɷdΪl-PsB	o=M\~B'SH4a롯^x%yCz/o̦s\J}5w&
1`@Y11CR=aC;c;:vX'*4G]Xݲv5pz\,#?P^+.89!i4gۣPS Ͽxm\}*~EJ*ę;\5PkX*E_UJ<KE,UH>ʷg?ečOLi.Jm32I=۶Ajջf3ـtʕ3-w+
vb*!?I}HINXf}w1+8]=;DBIbыU\pV(0:2uI|l]`;9ْaG,|,|Bޠ$AT3jC6D"ڨLRh^8,nؕ}6k/R>,9}\.O?Zwh~TM,6OKg+-[_8p6lւ\sYk yvTvu]&0?mE#{[j]Ǵ*y<sIiʸLz[lCu䘞dMLeaO5YVqDL{Km[5N7 xF=jlIJ*6غ4vs3$
X +&=讐ޠ$AT3&3dI"ڨLRh^8,n؜@*y*8l:_/~]'e{r]SOƛKYlϫ<Z]"[qKl2y2MÊ 9aU+
.R붢nU õ.XmG9M\&xJ-]!]䘞dMLeby5YVqETriT0/le,qT`v"
`g	mA XsieG$pn/k8JpMHfȒE˵PEȤмpYb#} cX|Wjrtmweivy;Oh[?m.g'֕HP[-l2ّ,a48`5aT]⺐R1)k"nR;R=VlG94AUgԢeFvU~IF@T"eaG|P/=AQ~
dZgXИ)[dUe1SW_ql	jMm(x4BzMi*$4c
 K̔H)n8Kcb@ugS]Є7&3$@6u&wX{\іawdA;MZϫgȒD]#fUkt_ r6e1M8^๝u	:O}V7$\rPɗ˺\)fne$et NY%EًDj1we\+PFEȗ*.FZV{F.v@BPNXZho3;ThAG,i23s1@Pz*HXEG։5oѻ6<Z	&w/gČv64|4hOXd*8*yJ=8gl=49{-	$y	Hi)vـQאk'ވP#(^g!튛+QAn`¢|;E@G50+}5.tv(ɦOkzT _Ѥq*Zb[NEBΩé*
IT%PBU	T%PTJedY)H|E eIdc^<rAaUQ1 ,	)TڂB2IאMSf "~&BFBQui04AmX8봨 N!"RtE*vE,"N|XI5E~U j97muLc:+yn:{jd3Q؛,:v?vɼi,B>kgd,;YH(uH 4CNe!ξph,"<gUS%m4zAIutd?.-3rY[

^
bjg&и6{F*lc;r:c̵.T[4Ɉ]ȃn>.l&&dW%Ϩ"$A2Nnc@׏l"ARxhTEtg^9Jr?̉`2zA(3e~DxDU,ocXzߟ*Y=
9ye ?0/
̳Qew%
c=_DacV)wɉK7S_V1H)׸ /r)[(SbI3)]	4;%8b*<KG/b>!2=z__u_ϰa;r#*Z4ӷS޲M-LQV&jrFVFOb?TE]F	/F9rKOU>^Fw m<몛Tzi4:Lz1g$,u.KBuJ;~fNZOB|hǰm8%8@f&4:8	Bx$}gQ6 Dn㈏]c EGlž5a0R8&iXN(0$b	'~*CP,Bs}̀42G$\k՜tͻ._Wӥ\gT&u8gG}|%dc`yG%f2cCz0\qp;g~/徫OcUzwFD_]C2[0h7ut#ZkkZMGTQ=	Є)B<1VRV0v!*U11	[+MzQ4-q}?X*VtB/&+_	ɶ-V9<`9?Ҿm`0`LG@$MfHeL`E&3XT+Al+.CRS3ʹVOxU+	Go F{i2݂a-k҉8!fFÓt)YW=sf؆LYȅ\_g@}	؎:ݨ2Zh5[p3gza UtQYOSSeCNzGnvᵡb
G$;?yu݀f4[MS};ZȵM]g"	V|\nXuD`)
 D#Gf @0\JiSYtٷU*k<I8I?t!$y&kn,2v%)(ĩbGL/L;Os/_^-u[Ѧpw$hZa4Mi9AJJߕsodw8(4J9\.d{J$'eV~GurW˭jdY$
!7vt_\hnZ@CRwQR:F*%JvfwQ 7~_ΝxJ_&E%$YJg3M`%}KG%>:; MFwr%wDOz%7iYMMJetjo
7d7w4#vg[ sgam}HY+7bV*&+Rҟpm?T]U)Z|ĶƿʼLY'8lFUyeHCq]T$H}9WIFTXXtDvB'
v%niBE|b(
%BHH{c&h(FـA#KUb u9 IIġ+VjLim+q́3(\7S&;uA3j*}vtt0۰>;Ia?lpB@F<5\˕H$YxZEJjY@
0=TNnBM$yS},	>Eٸ9vOH-rt=+n 7sK|1/'|Eiq
9{L)a՝GdqιCxvW>GVu"v>zARࡿ./:4֧bh,cFA<w$޲N	MC$ ɶ.,ұU꿺I~UĲMGR&RxnqF,lxcg	%vIQk˝BS~B=_:,ؑ_AJ߱)7dQyI5mO))lȑd}E_%Y1T+NӬ}ONWgZ觥)aGM,vݹLw:6D4V%z\l%{WP$+-Y2~')_
+e]"NhA#KVȶr3PFer{wBPݓFAv)YJ9;2_U҃/ 濨	*x4_4'l]BБ!8).V#?eU¦ζU,:޿9ٶT;zůy
I׭~T7I(>kTed]yz\ycלT
ݵ}T-[q`YwˊtK\|gy	XES (05rDw%2c܏F,q;ܹ_rư%ힰD1L#eLoD".}LZ{V~K@?H"~~V΢CAN&7같o0 mұ(ͅL錚ZlvĻ8k
u$Wv7"B-d"[/?P	 p13(WTHУ]*oHȡyYS8ٖiQiYV+<.1X3qD'6bo].E\-f[::J&F[5gdϡ|w&.^*}sG?9iú+(w{{F4L3~G2Ehz|6Y	zc>HYaZD%Dqi%+`&2!,lkjAX!|uzAزdT/7hIڕKNxot KR[m EMтF& ?GV:w4!yj nh80ľL9r#ngo	\kY%'|,YC`5\Vڲ&GJnֳ32*,EUȺ*U83\e~6
DK/̪T۲_'?$R$R~ȗeOO޼zWWBzI(ͬO#]8e_\6a@MffX|nJYɄA,S.檫ҷo,$IV>	 KoNЦdaK#ӃPPOôd{1m֋99,~"մJ:R0~Jg|pSyG>=J,pwYw9IvXf*U'(/̖h;7Sr:qJ̤$Eܩ虔?'fRv>sM*JBm*eaeٞ+u6z1gXu%ﭻv@dFkkWbHn]yJƻ<Pw\7fY݁q-D5H;%H=!nywPskcb>6bk2W`D}˂2OnF"~Jz"dXS|@1rG(L2WiߚҿDjŪ*a|/%Uv[uanۖei6Uq\V][vգkwoYumSSeqPӖ7T5,tܔO]}!Igj]EZ}4r=Z!Mev)j\˖XuL-LZ=k~B dy):eA8q52A6AѶ϶g[m#F%q\AKs#h@>
QsY|n'EckM*\ƾS)hcvy?D8B3d^jkJSY*{CAhXrWn]edWnYbZv}dV]qZvumVye]{`U%MLUCNX4SH詨'rRu=v=%z&m.kFHʈkS~)|=r.Z7b5jF,2j^, A:RuʂRGb٫d%&gGj4>bcZRNs?1Uᑴ {qpՅ(t,>{D#aZ%k8ȟ0 )cv˙N.Ȟ2rǣ#>'o5D_5ZWȑUUSصF}C!BÐ䪾r,;"Zݷ,ӳ&ʲ+ӴnF׼.޲*jb*rnkEMFY>)+ߑy'z6{yV$idʈk7MZ,2wb5֯Ti2i+aDW*/ϲ-+Tc@ᢃI5Q>f` Zu~(9`kpGxe$IՓA&̵ˮZT2.TpkEZI"
G;&eV$0d8g>1Tl(mǰh	:oN{.IU^~%^Jooan Fo^I2ۥw5LsF0AQbꭵ[<V_JmjJXYS6ˠl=MT5NsR~3ݝD'K|DBpl#uc;ǫn!KW*딬٭Xbf@Nbh*FolnK7@	d|+:h#
S߼R_'M 
GeUo-տoRx!&sq
vp^/ gѯa2ps3"$Ka^(3wQ<l
j6*_«rV=PDpF$`aG?C%ߒɮԎد.1Vhۋ!}{(uD3{KoRyڙ#tȽT	y3b8ukq͇7jV6Y5j^^B\k|מW
bw"UnC7ID9`x8H(X,P'@ #hقVcrWC߁%G=CUCkb3jaq8rwԪE.40Yb`g
5ɞOLpFPjMPR`Iw6ר7jI1-gJ
֞Үa)%HM"Uuo&/!2R&KSh$J̿ioW)T{\ᇂs޻wEw7c'9!Qm6 Pґ&o7~4;jI8OU~nbn1鞈(qyh,"Y/Z&)j*¦'K<ȆwUFGe"EMc	gNe-{C06
@zL3Ja5(|]fFsگRo$<2X {I˝ʵGc+axp4%5 aAK'M80DV|sd*klozJnbԮ{t,f\w5cG直I(CԜg76%-^fENiYZE5%.Z9T-s"g@2?Eoa􁗴@^o"}Y%.WC}=OwýjǬ#w]gW+6w`Hd?ӕ5pQ'-gJ,ԅW15Sї!tRhB,Yȏ_Q"52SbZ={PI˨뛻[(~W3zXWP!r1{
\@Z6H!WRIIK_hc o_M*gv|*OVy9^6p׃7+Z}vTUD[uo~pUU׿߹U֖SZB~h2`Ķ,t,'oe7<3Yj@c#Iips~#ün]?ck! C{mSseKT/	
Ԋ؎1""n-{^R62TE#ƕ>іf*pI⧚O&*It~kAq+n.IYZSr^$#ZV]X.IƞfpNZ0V3Eu_HGYѐV.튺LK)(iZZ+F*IHZӱ Y05~Bj8ߘGs+{SR"Bi-$`VS
%	9Ki΄P&pU~/nNrmmW|GjGn  \ f`.&&PU;1plFQR2A3A7BI Lth o(Cc(YDFdcnwre~HW@Pfu/=҇'[tJ
j]}QᩚjYvkᲖxyxdYR]mXFhrZU`е!Tx+3Ĭhj6q|C{:3 #Z!!77M
)Roy%D  z$TleRJ+JvJt'K:Q̦It30d !W$M@Z؞NŠ/`a0MP!6cb,ɲCnL3A68ydxm, V=i+B5[Z^kw\kJf%.~۹ѩ^WK-h'{tnP+ٷ]Y1܎-W.#=9{nR}:e^z
SHi]=U%>Y(a1lQI	R-&C	RJ/YOUKQGA3-	3u0a J[ʜdiỊ3YHpcjwW[<1%o%7Ab_*%7$01&ʪJi0ph-;Glt' ۿ%Y/@˔{m^%zY(Qq\4QFl֕&:KZw:58CZ>N	vܠWv+7;Ū]Gzsn庭OL]RK}=[%/Z[/UjR_$#n1=) ZZL%PbV'TB4-T3L"BZQ| Y)*¦n?äfQ$8V䱵OHxiH\@"O!#BlL0*̛*FCnL3N?	Ch+rW^JAj[EI_k΍N^9kD;:B](݊qjtgi!ޜ[mnr-" WMJ.uyDkJJ)uwT]d=1ۥO`2HJi2 (e3VRm 'YI[Іp4! Zu@r%G>߆Ew,xN{,wbƸaB6!0¬dpDrX2D"R$zF;z>C1B1GՅOc^d2vk?l۬w3:|=~/=^\9+unR(ZlH[%Ty::eVȇ2	R-,\p1jiG_V1 Ⱦ_pi30;O.<,d\|E]VG c
>v2HռM!75Ju^5BK-LyF]M>4am]EwmΚeh:4of&L%CXt~?`TޣF%5]i2g!!	-AG}HHc7rIǹpܺmޏAU?==4v~mzDS,U
i垑cXTNObɵǹU<)mI`餓ceք
%ΣSug?~<|qŐfs0ӰBbWXH{?'^{!ŃieΚ"c!T̔W22} uӍ'V#خ@=Ga:A8hRR`JbMg,ԱEF
FnV4+$ݭg܈8ַ-6NK'ҕXXr䝪)
L]SMKkKRyI&?o{xYa,ˮtxe_GⳄUS:ӌBz)+1n(f  s+Q 3DCEQ_q&X % |Ifa3m7e| 
3-~Ɇ0Q	b#%vG*S]$4+u*1@	E*٬9a:Jrq&fR]l'7Y.DH%MLop]PR$=rKxR&iBNቾ)[-P~ȰnAetUyrsߐm">Jy*}h<Fpm֕s*IЕf;bov-Oԥb}qUP#<=zP2TLD.5#OV;gPRӒ́fD<Lܼ좑σbY~5܅/Ru~T]u'Ė!2nʆyyBf4ʢў
B1)M[E\N^aϓ`ИIo983).9ϥ!r"G/wojlPrc{.)m%ƚ?7GOl/znvUŭ}Wu5`q\V.s~CzWEWmj=^4Aѿ:ҡTT5*aݤw5-CU/_Uϟ6xM{=16Iܫ҇iJf~d#\LwJͥNM}o.RXpM
c`  ?
"ݗR0~ч0eyxLdlzTG_J4+hE<&bRuDBp"{UsX2t&?R[NN$K>ȉڛ˪
[y$I/j@$-=#ޅ雦7E1keT,rzYun~;`ͤZV%a{YV֭sN*TT5.`GezUeڨ:?Rn|oq,+]HckAekjs !r22Y0mجaH3@;]|T::?FP'18ln εXNc0ݤ]riLL3u[o{ HapG_ciG<&{FJ±;zTXGZ)6ԈNAx獝e˵:ۜK7	lglNKޯ5fPv?At.B.MJtoBlDPKw+s1P4VL<rUW4M%Y?cy|`7"8MW<Knܝ$
JH;"آv@lƍ:h%uy f`Ȏzq'kpXKER_|ceN/k:.4;>+q
ҰX97!=o˸&hg7k)I!Kk"<pR73UHkhɖ*SAGDAsnu6Yׯzeʛ	2lWlr
.QtgVFSZ_rU퓅Wiڼ/mk*>K_A%?3rL^rQvύzQ!PB'B=,Wc~%_QԪj˥=7 * (W{{31̗8t!sC
_HnWEok̅+<F]׈"3P%kd~LKY"CU +MTө+{/d|
bh$i;4Dˊtˊ-2nh}8HB	^Ӄz=aӋ4,8p'D	li:t喈֓#Viu12ЋC0t{Dr'߇gM<]|L                   Vߏ6~_1DhhE+uvt;UUŚ0FVq~AHv{/E<x曙g8[;N?,AMl%&i
ȂAf(OWi^"rh.aqLﾵ"2FE\"BJgj	R{n)FA ;m=P?i4u2}ͧɇ	V
\.晓>(bJpb!,>Z8A>!vaTHW +I)NtP-GW99q,qhRs]p܍bwb*~p6iwܱ3.WoVO}K'Xe*}ԏvErJ'Eg
4MA@V<<+l6g2y
w]e8 %((Zʄ\7F"\"{j_9AOHk/bzNRV3cPVԒB
Rm%kJJDƉWW"v;TQgtHer¡wOEHwg~Fpxt	AHLbiȈ"Kg"v9D,(ؐ,<֔kR8fI1PH4
hQxyj&RK5IMvzdixЭ#JHgÂ=vh䠓 S
_PY=FXD9AZp1^s,wc*tF(+| }H=ˉ ΆDe΋Mm1VO̓CfXf$^xRVXoX*)d5j=rf{7KZW-:VQ)e7|ZPTw9HF6Mg71_^R(
BHs h!lxI+'rBpVh]׾g[E`Om焯A.:o/EP:	[
&T-. 3       VmF~b~0H`%U4I*2ocJwvrk/<p˔^<ELU
F%>c,7'@РREQ#2_â.f㾦*CDaQ(aS2!=j6Dd蟝m+\Bai9W7O:}w0C*x,;ll=>#6dme0=1sˌ*b졅q.zf%jjʕ%"fGƶNY#3l-	ۭi[a}=/*dM\1\lqpp/RAv5gthvh4YiDȐÅwXۤ->اA
6X0ƦXfH#w4ң$nVms[9웥Xt2Cu05/vNa1nu]hv50n?&sN8++SZj؞6;*쁍oOV 	щ<v|J˦Mp XݦƼVBy'yf#OÓR.̊cЃM*Q#0hï3JPRV0M`|&=nm\ w2RPއU/%*A0|Ss"Zs^in4k%Jc6ʈ0P2c=wX	▶JIȥ$JSS=@o
.![-VR_s%YtYel0?-oFN]*uZ֣͂TyX*?7Mr@p|I^w{u[J&cY{)V>6uȇ0BzG[e0n}~Ca[|RUɜ(754+#^5`p2"#=:uzݺ5ߠ\Rʵ"~1775Ucԑwj[vwAHd|4J       W[o6~8EXdÀ%K7vM=CJKGH*[dX׵/sw\+煅<B0lI`,x!;̒h܀QNR!ϹC-1
<]	Sff!ef,媒pI^]O\M!^/J-|J52WVi61L/,jF֐l'#yO[ѵfҰr%cՒNaB%f/qq³Me0rriFt(Lբ͉{;ʤXZ>#%j.YŅR** #FB9LZRt J߂"dȱݤuUj~Ef`Yc[S"@򹢄LgC'P[<GIft--OFv#FOjÌY6L3MR؅x|XR,-	.KdVg2,{PZ͉%JTx"rO-cBsQyAf
D룹Oi8>Y%s}{o{A*7.3DTvtWPrdbӛ4#|1y!Е/!zdP	7WVϕxo</c%^׆M;sNEmEߛ4Q@Z+ݧֽV$G`8Ͽd%Yޒr9舼OW!8 ~UwLT߃SɹT9֨se醓0 S|ْ~!==\ypvvsNv
@PJ2hF^ծdY`2-^&C\7j{ i{?
4 СѴ0먂y)X8_H$ዪ߸Ą?<]G[L4'JiSۊoS_5S1A:2hP@(.%)]n>~n䜶`A6=żM̦EG-|)4<v"\rˉϏaIo|p3֭x&~،\oW~%ACꎶ'llת:?6}K3|t_(Vc}`a[7~#8qqwe9!T3	<O!\r7i?M~Z-fJ$4J'uN7_ UqVkXXy%B;JFbXhDO49vh|ZwQmd['ȷf%qORg^tGGֱ䋈ltT5@}	P]>Z<yX]!.o^D|JSArw֛;	,5&ͭ:H`ҧ$MvgF0#fLT(/$|]L mrsОoA
u\1d.j^ʹfJČC1nj]퐁$,ˇw'pgcmMo 6       XKs6WGC/rLM[O4SgG@$d" e+{O%{e߾ ],hJwd=BW5kyAheX?0*%㶖Y+rZv>Yyz9 ~\.8k;yq*6 /N''=gK%%kD7@ŌsK&>vY&X!=cu/7##u?r!/YӐB2Pm
I4p'M8y(	<Ho߸ !B2><'¤ՃQ䦭kn<F2cs EY,k(3h{*a*(פձgCfpɖm!DH&@3Aa!3:ht.+uX7\*Fio=0JV:HYIWَ"fyB"˳-R#iOr	zitG^SEKv-9mnԌs-D׸;mE	x:6z7qeT`@Ws\ S%.|lNuKv?,	ʠ68Uу/Bk'T@$4Yqg[2AU@!tE̹J+L-9=l`؊y'sME˒4/DQ3	O݌=
2 Te)%f]Ԡ)pBzi)+~qM[o+~
Vym["Xa[	!+KKnjf)Ҥ/Ur
JOM$2@` 	W|%!V6hM=?vėnn\oˏïۧHH%kWkЩr,:՚W,CA,I(;`u wx8zb|o|9^THntwI'Qxz8B'&/C3;|lI'y=1]5PTDtr	.zp:~7Ƴ9tcܹqLiei&1YB#(Yb~ד+.o;]P~UpT	#Yo3RVdgPUxEbW
H	Euzvk]~맔&@Ð#񛌚0ȸViOrBy,')U,H\0HnTsndhAh9qgs)nJ}̮C#$ {CҎDO/Í{yG.pC=q(ܬHp2 5̜4o:vj'P&N8<|tMG{B-n
y`9:u	C(
CԍTD7UsnI]7Q21Jև0nk]t
>iTTA{@-)fZnߴ.4S<Kt韎'಼ϐxT{(0ʤ(,zzUl1b kwd=fàdz8gW(Ao+Q_ƏhwN:슰laE{4a~Q7F        Sn@E 5Mfo4n
fX]pA[x~f[d Ѫ4@-aQkhF,r%3y+J4IX9LAz:|aZH3lIA>JaG;~1t3pt3rsFv{|,6A# esf=^ԉ&62tB".~r#WʲL&)
TDݰ
ڀxO+T*o-O@Ǎ@Ss	H97cqn"<<{ޤaCKW]bNn//j[4򷅧rVjt
~ 3c
ϡ       nK=_hkLU-UrL۞xzv.IߪVpXiuB_&ⶖM2Y;]ˎاMV3Av[v֦:ٌ猵8ڟoݢh'߲NoKU,VYDY&K۾yY^*ɎX<iOn5ˢkp6+\e)N\ܞ\j^h2W	ֈ-UKt
n@ 3e+ ٷ"g*W:Tj2lf\@,Fl:jPZ֩mw(yD48vg.f -[F00>Zɞzᱜ%H$8Ά8#$~_e޻TBhE8X5֓E@KIJkhA&EJ^ [PET`}k$CUqU↝]0dJvDDWCh)aWbu!_+V6eJf`DܲK4Wp'zzp!ϜtWs2`C s/0(1"&y5cf`4=S)~_QFt}SY1F{'ِXӛ7`#R!A 9{yc4R;1qx͚5#{Z%	ϒZ(t 8V.(fb-E5q&	,Xzcizv*(3+M7Vpv*j]=f؏YrER
C#!AM3*(-|F8b>IN>%H\PN[Xļ$jeXiFhF 0@wGTI-9lpRNU- SAv)G]oC%=EXj3<աRTczF-ly_
]x*Ң@PX%Tm∰poًt'9O3~6B:o>9.dFu2gLKm٢*Y]nKW=%;hJH>Tϼ=Q}tp?/LZ"}>S9
uS-3ir<܉&LцMAF{{#V	lA/Ǹ1z
_Oop-P?-\_؁m'` tk E>H4^*̈eU,U;K1B01b:U>熱F=(Ε@[ ͗/stơX.ˋ.
^
D@nP3thճv	<)s,mOތC+2lzc5Ԯ@gt7ЁCc6fERuUVV<:p?>ًmÏDr;R<1R}P%4d(syƲ)}:vzo\%:ou] Ԓد0]5B_}Q>{V%h2Ih9ɍ.__ b#cm>K<
~
n!c7E-̓1[bwhk͞^:U	;ddqM	cD~p_g\ 4a`֢jx5!9;J֠>S!]VTyao>"'  b8O;AQ掼-)Dl9/RQ(Q 	#4τ7i^/xQyq',Żփ;(	pn ke&(~#nQa}6U_8g㌁ע
{-\'}OW1{C6qР148OKi$]f5O+}UJ.ƘL`m}{JAuAk-kH^aC۬+'NpSyZ]+,g ^,
R^{x
dmE@PHdtaj='Fi=,`ʤ/U6	|/0W9i7m 4!+v.NjY<.<oA>˥Jt<RȍI H7Rٓ9cZ=$fd;3B}@Yˮ؊9F"FDTYP6n;mXv JtF%$ZLT".>qʦvoqZfI/qy×Nw,k}^Bm2];(Itf.ݽK>YX{%Y̀ N˨iy̺0.9.KS-Ho	Q`{R|:v+Ow)3`B$|T2Í~I$mz%nO%!"_(Lgcb)+ڇŏlGBƀj!C{|Ʉ|Ң06`C ppg䏴Fxy|C_'duz|?ݍ[0yX#ŖFoPBI	Ěa.Mm@y]އ'p>phȟ[nrڅmp\:|gS(cCvڪ5uIR8Z-k{&8/ϾxX>^)r~Ywp ҪdC$K֫O"Q╻PVӄ@k*4b2A$zk{O CX"M\~Nv/xE_a[{É1J<ͯǏ&M趎* ͼ.d?z%N.lb\2Xi \Guާvs+5"'DW8Oz] s "hi%e%sIU'.{ow,ot4۝IrjD>Si[ٿi.LTcfT6$a|qőũuwI:irM"^Qn*7rY@'\A^R)|7O\ZQRw|e/Fz3lQ[vz otviqMԿOJ;u>DTxv3QաJd&edd?/=(2       [ms6_L;LzqӜ\28mӉ)PSJu@P}WX,g_W_ͤؑYŗd\JYq\Z)i	A.rNkZJB$-sA!S^
YSɫDnWtDXP"ޏk`"<c|"8 MB^y QZnwJx$Vʺ*e]Z'Mk5&FojZ nV+;A0CDÎ}y*(%*o#_*~%ǑwEJs*̲BPw2H-3V꼠K4SREዳul@(]g;%'+"lzKY`F,F䂒F,8apVYI&TziN6ZĄ	2UƝW+];тPk$?T"E<	͈7+v+ 2?h*f^CPΊـB(@sFƓvt}{⼪"c+r#hL_=O8
FtIq&VkR?	(b<'\#Qn~}[xIr8luwfwDؐ@ac2vWhLlF&w;(`2A^#bhd;=Mġ&9/]JOAQhE~^h<bˊ|Z+U"Y7K:Aȼ5V[Ғ9==%짏ן^q!yjg/8,u7'c6yz%jH؞FܨӜ	x,,};h#I|H0I-i2Pp80#0#W%_vA2Tl="`=lmDW/kzF<<zG8	(XGGɖ~F$sR m%%ߤ>E]9MұDҦ1g
L@fgTIZ']aZìtAmV:'mU8"sPu6itDuX]L=ˊbi_}i1c9ЪSY0IL2^>Gk!BN%a #$PЪ&k#]ڏvF Tby5ǮF ΩQJL=hJ%heY]NQ].DVH3!247f؝H2c@/^j"0MеNʜtf5TqT A!	LLKYXq,B%'78kQIZL
S= 7Ys~`RXl*eYGH/9n	9E8 -9ws)z}Dº;?<rA֛.tPSq>j?C.!м18o-!^3FL>͊lIw_}ݰO!Snڸ-vr0f#(E	,"b0ejK#j0(pH;3\f'aϮ}3<-Pζe(jw2Y7g*ߨj5Rנ'Uf#DnH;7
{kՂhpRMq)-ޔlО ܵI T8IT;FKa/*fDQ6c:\$r:DN],\FyW;B#V6<uhsKÑҮ񰊘dKmcn4@ғHU	~f=[Tw-:3'oK/_~vD']T"BlԩF~عaW |ky=:G2M
Ds6,)y6]$]N!\UxlUfeҼ!k@@;E'֦1
jm`L=f)rUˬxsLީ;mĭ #3@eu.L%;%pL&/t(a0GL1{nw0mB:R.a׌yH_Ţ-]$p)XeхB-e M{u˺=-u}Vvp,w>
w6YU&Եbku=uS'hxAOl,R7mmzr	/Y[;@czigISF/Ռ	$\[C+*%"N~&wEuꤎW6uBt02cK	Ñ㿭+_3d<!5l
&0c5J*`e^BI ] '0x^Nj<5"k#J?31r""wH x}y|cx`պZ;ڰ\.Fjgr|Cp,U8S5f[/C-)
}."~h'C|5}!ѾL;H
fҶiB:J*?Ba^JY	Q{Ơ]LV3ueϧgOӛq2K=5q'*8Ww@ǭCZT
݅a9h ;xZE#p^~Uꀢ*c*zM|-n3<VVA:c]Q'w-U~=G9on{w=tTCb nPhX%3ϟtEk|KN1;Wk֛jLv*J%Gv
Rn/_͞"7ЄV0|4@p3j#hw:-r1j6c7[4	xm	_,G¡uKC+ngTs ȯocfˏNyro|~`|r <(vs@@]&᎓>DCHvS5[=v ^cYi]&4Af;&u<3gI߷[-7sf+5^n3ӽ|!ݜpMiOfhBbZ݈;9^eS05=Uղ[A:^Œ-ђ?$[|Xbk:J.VAzr.=wB|%n-R \+Ҏ헁'|pmJr|/0Y"2jMVAߘ͌{ ;	m0gy{~酒㛵3lk0G/.U&^RrAGK}64.^F"s+\1^t>[opİ?^tW'??Yȕ).O"'B?:2       YYo8~ϯv8quEl4
Y#neIiCRw49gs|鮮 ]'BH<V[AN2kȇ{ZQANI|yFjf[S>-N7f&'V%9_HNmx#`t%<
ڈ˪`<t-|BDUafn/*X&9oN].ԗ=޲wm`}Ed	lj7&XU`n\WO0fT2H=BFu("$4I>b"KT") M2K=
W$FE uR44*3rPߗinS/!jSxvW%,URR󪖑\`=TlyDBp5_e mxC$l)\j4TGs8ԽqW%Sܫ2d v+R¤dE	e"1_U	^8S%`P},emuSNI^g<\*E+^*F8eu2_Rm /~]RTzoi1T9Dl	C <x'=%lwfHIl6Üģ\G38xuȼx)mn<Ѳuc`3$n+;mGуbuhۃf9mȚáTS-LԲb0bqlT0YFA74[{(F(MA:Ts:Z$qt{0>~dIT0ըQ`w̺8N7<]&]_܃&Z9^a qsKeShSWG u\HPypCE^e*Wϔf!:pYx:x	mp1yYQ>eGVBJh	O[-|am@tR.Xly[C%&)iEg%m;T7	yȅ1Hc&iwIhڭ<-p8M~.%)\)?BA=ҍzTz,!J@nk{Î(@oWU	s3@5!`ׄt8(P4BP=ɏ@=x8<,	AP:~19.Y]݀(CN@7L&OW;֭ԏn;Ugj}L̙*FF'M٫臲rJ(ɓ{JA
*=$$O#Pײ[urMotq6	mTB@ 9Iye{GC CF}<
N76ZgNhCv{p[Fm|\m|+ߛWP)y.
<pfؙ)сAwb~l`AsHjz&ZASѠʑp[ 
+>a.-q/;	LҢeZU2kgrZMAz>,?G1<_؎}~>T͚_]3*V{}~BE$ia
UA
}4V#3	 ]c(%j6Uk0!Oh$2d׽*4jQH3AӦuM,a:N|+[i8u*75Nx|skP4,K̶ivW-6ZwX.D</Dbs&!xie^l=}Rl)4g+v' aCT	%0AQ	J$-a&Q!`8ap2E;xh_l׉q%K>yЯw'꾎_?"%p       Tk0~_q{(UiA>*,9IWO%Erc/&9}w?X]tjQ|lEٜ[lQ^9{m@%S)]8^aScF˕h]d`&U1Z1Fm
AIzj90$[xjqϬ^0Wٖ.`>_ɰɳA\m澢Ҵv-ߘ5\D5:{r}dB2D3g[là$pu%pL%k;\rƔ3jpE=qH|jtPOe(4B'b<D^z%WɬowrlǢ5쬿N$L!iiQumq8OݮqtdP588C@T1uf(XS2q~{xM$AN',b$C27Ac"~1CP	cRo? :wh4'rLaLAyE7jv%OS8u')kv)6/Ɯ       ko7U%|+73'C>ڥ!,]GR5H=Czvڞ2Ѫkk"Ubqz\L~/N8PUWUF:=MA}lGmCY"XGlN+	Mo6%yV]0\S@ޢlx@~?Xc֑|~e]F(˖06
8}!VYEKYgSFY~)`iBO-w˯8g-~^gy$8B34'<A5dk<
aN?q6 &IY}x.4#)@u֭I|TUY@؆fU Ӷ[p3hs:kU{s]faDn,E&(b74s ꊬKvjIX,[ja@Cyƫ1WES#ݫոu=*yKpPdsB	?42VPyLXfXp72HS'֖݃@rcw{p"Tc?=7\k!V8-_'_۾*P2.RcԂ?w_v$K;;OFsz۬k/o[ZY1J~I}jzwB"k!=:5Za^fL,&	0bdl&r)5[f}נ( Q5DOj)1;GJH!_8?短i)amWo	0-k7#ڮ6YAr[	X&!Ghָ'uJ	skXFgƖ;2(ȥ;`vT{((\j[&&Zpk$0&1N$4Qwˑ1q%82QLkTGT@(XydE:0_]:/,'P3F0^Hl@W~	[ą.9#0L< 	LPe-,qx4v!HDG4bl!d$N`EBRV>BkPF:\=W
eb$p{>Ζr2y[H`=%/";muٲm!P91[HV9#Zz㍧#v _bi(+N:S^CK	!8#]ʸjnqřmISIxfoQӈN(cWjוNhsvq@$L	R~7]Ў\ie<(9<Gq<Yz8*>Q^=FeFUkCR9xN!2H/ZD+ӵ)z]5wWQ*XH^B=II{*(qUMHv
ekUj\.6EЉT\398"!`XiD2t  12xKϼKLrZU*t@nCJ`*k#qM2Bb`%_!1!TEr%!U@ϙ3uaB;>z;*4&?eǦX-T/yf[jf΋&/~_=Dr bWGUKڞQR`RdC[>+YAۮAAߢ^ceƬեE_w3Uǥ8vya*q7>FbRK 9Z]֧^ۙWdGQ_=P=	B=Bqm"<đΟОx1=nͱb{O16׵܀-o\~ܼ|r:u{6wpJ3>՛ޥԎ"e߈@TM6=TTλBlf,{e۰;Q%Jk6T`P
E9}7r{8|앦SĀ2/<3
%yvx/TT5⑑ɰ4"%N4a8<~( PZ~#3;u  eI	%=gTWptlq`뮆CM>-$_22-)ZSmxxj@ "\@"ȸ{~<\:=yy8(ot!ϗ;+Yvz!$6H#lx;}p$,#tIEΠZ4'\@|͂b"[MǟA7.N=yMݣjL)jwgC9\b-HoU:	er5kAޗ!Crn=5vhBAFlO ,=ϡ)tatW/c{R0C8=`{ITC@n$=$bSd{|83OO5(uE;+*5v{yΧl=m|)^"v4-BY:>}Ʒlx4'
~Fmo&  <html>
<head>
<title>CEF remote debugging</title>
<style>
</style>

<script>
function onLoad() {
  var tabs_list_request = new XMLHttpRequest();
  tabs_list_request.open("GET", "/json/list?t=" + new Date().getTime(), true);
  tabs_list_request.onreadystatechange = onReady;
  tabs_list_request.send();
}

function onReady() {
  if(this.readyState == 4 && this.status == 200) {
    if(this.response != null)
      var responseJSON = JSON.parse(this.response);
      for (var i = 0; i < responseJSON.length; ++i)
        appendItem(responseJSON[i]);
  }
}

function appendItem(item_object) {
  var frontend_ref;
  if (item_object.devtoolsFrontendUrl) {
    frontend_ref = document.createElement("a");
    frontend_ref.href = item_object.devtoolsFrontendUrl;
    frontend_ref.title = item_object.title;
  } else {
    frontend_ref = document.createElement("div");
    frontend_ref.title = "The tab already has active debugging session";
  }

  var text = document.createElement("div");
  if (item_object.title)
    text.innerText = item_object.title;
  else
    text.innerText = "(untitled tab)";
  text.style.cssText = "background-image:url(" + item_object.faviconUrl + ")";
  frontend_ref.appendChild(text);

  var item = document.createElement("p");
  item.appendChild(frontend_ref);

  document.getElementById("items").appendChild(item);
}
</script>
</head>
<body onload='onLoad()'>
  <div id='caption'>Inspectable WebContents</div>
  <div id='items'></div>
</body>
</html>
// Copyright (c) 2008-2014 Marshall A. Greenblatt. Portions Copyright (c)
// 2006-2009 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!DOCTYPE HTML>

<!--
about:version template page
-->

<html id="t" i18n-values="dir:textdirection;">
  <head>
    <title>About Version</title>

    <style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  background-color: white;
  color: black;
  font-family: Helvetica,Arial,sans-serif;
  margin: 0;
}

#outer {
  margin-left: auto;
  margin-right: auto;
  margin-top: 10px;
  width: 820px;
}

#inner {
  padding-top: 10px;
  width: 550px;
}

.label {
  -webkit-padding-end: 5px;
  font-size: 0.9em;
  font-weight: bold;
  text-align: end;
  white-space: nowrap;
}

.label:after {
  content: ':';
}

#logo {
  float: right;
  margin-left: 40px;
  text-align: right;
  width: 200px;
}

#company {
  font-size: 0.7em;
  text-align: right;
}

#copyright {
  font-size: 0.7em;
  text-align: right;
}

.value {
  font-family: monospace;
  max-width: 430px;
  padding-left: 5px;
}
</style>

  </head>

  <body>
    <div id="outer">
      <div id="logo">
        <div id="company">Chromium Embedded Framework (CEF)</div>
        <div id="copyright">Copyright &copy; $$YEAR$$ The Chromium Embedded Framework Authors.<br/>All rights reserved.<br/><a href="chrome://license">license</a> | <a href="chrome://credits">credits</a></div>
      </div>
      <table id="inner" cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="label" valign="top">CEF</td>
          <td class="value">$$CEF$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">Chromium</td>
          <td class="value">$$CHROMIUM$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">OS</td>
          <td class="value">$$OS$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">WebKit</td>
          <td class="value">$$WEBKIT$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">JavaScript</td>
          <td class="value">$$JAVASCRIPT$$</td>
        </tr>
          <tr><td class="label" valign="top">Flash</td>
          <td class="value" id="flash">$$FLASH$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">User Agent</td>
          <td class="value">$$USERAGENT$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">Command Line</td>
          <td class="value">$$COMMANDLINE$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">Module Path</td>
          <td class="value">$$MODULEPATH$$</td>
        </tr>
        <tr>
          <td class="label" valign="top">Cache Path</td>
          <td class="value">$$CACHEPATH$$</td>
        </tr>
      </table>
    </div>
  </body>

</html>

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file defines extension APIs implemented in CEF.
// See extensions/common/features/* to understand this file, in particular
// feature.h, simple_feature.h, and feature_provider.h.

// If APIs are defined in chrome then entries must also be added in
// libcef/browser/extensions/chrome_api_registration.cc.

{
  // From chrome/common/extensions/api/_api_features.json.
  // Required by the PDF extension which is hosted in a guest view.
  "contentSettings": {
    "dependencies": ["permission:contentSettings"],
    "contexts": ["blessed_extension"]
  },
  "mimeHandlerViewGuestInternal": {
    "internal": true,
    "contexts": "all",
    "channel": "stable",
    "matches": ["<all_urls>"]
  },
  "resourcesPrivate": [{
    "dependencies": ["permission:resourcesPrivate"],
    "contexts": ["blessed_extension"]
  }, {
    "channel": "stable",
    "contexts": ["webui"],
    "matches": [
      "chrome://print/*"
    ]
  }],
  "tabs": {
    "channel": "stable",
    "extension_types": ["extension", "legacy_packaged_app"],
    "contexts": ["blessed_extension", "extension_service_worker"]
  }
}
