Web Inspector: Network - HAR Import
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Mar 2019 18:27:08 +0000 (18:27 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Mar 2019 18:27:08 +0000 (18:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195642
<rdar://problem/34820974>

Reviewed by Devin Rousso.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js
* UserInterface/Test.html:
* UserInterface/Test.html:
New strings and resources.

* UserInterface/Controllers/HARBuilder.js:
(WI.HARBuilder.dateFromHARDate):
(WI.HARBuilder.protocolFromHARProtocol):
(WI.HARBuilder.responseSourceFromHARFetchType):
Reverse parsers from HAR to WI.Resource types.

* UserInterface/Models/LocalResource.js: Added.
(WI.LocalResource):
(WI.LocalResource.headersArrayToHeadersObject):
(WI.LocalResource.fromHAREntry):
(WI.LocalResource.prototype.hasContent):
(WI.LocalResource.prototype.setContent):
(WI.LocalResource.prototype.requestContentFromBackend):
A Resource subclass with data fully supplied in the frontend.

* UserInterface/Controllers/NetworkManager.js:
(WI.NetworkManager):
(WI.NetworkManager.synthesizeImportError):
(WI.NetworkManager.prototype.localResourceForURL):
(WI.NetworkManager.prototype.processHAR):
Process a HAR and extract local resources.

* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView):
(WI.NetworkTableContentView.prototype.reset):
(WI.NetworkTableContentView.prototype._handleResourceAdded):
(WI.NetworkTableContentView.prototype._importHAR):
Add an import button. When an import succeeds reset the
table and only show imported resources (ignoring page
loaded resources).

LayoutTests:

* http/tests/inspector/network/har/har-import-expected.txt: Added.
* http/tests/inspector/network/har/har-import.html: Added.
HAR import tests.

* http/tests/inspector/network/har/resources/bad-version.har: Added.
* http/tests/inspector/network/har/resources/basic.har: Added.
* http/tests/inspector/network/har/resources/empty.har: Added.
* http/tests/inspector/network/har/resources/webkit.org.har: Added.
Sample HARs to test against.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242948 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/network/har/har-import-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/har/har-import.html [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/har/resources/bad-version.har [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/har/resources/basic.har [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/har/resources/empty.har [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/har/resources/webkit.org.har [new file with mode: 0644]
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Controllers/HARBuilder.js
Source/WebInspectorUI/UserInterface/Controllers/NetworkManager.js
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Models/LocalResource.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Test.html
Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js

index 05b39d9..b128307 100644 (file)
@@ -1,3 +1,21 @@
+2019-03-14  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Network - HAR Import
+        https://bugs.webkit.org/show_bug.cgi?id=195642
+        <rdar://problem/34820974>
+
+        Reviewed by Devin Rousso.
+
+        * http/tests/inspector/network/har/har-import-expected.txt: Added.
+        * http/tests/inspector/network/har/har-import.html: Added.
+        HAR import tests.
+
+        * http/tests/inspector/network/har/resources/bad-version.har: Added.
+        * http/tests/inspector/network/har/resources/basic.har: Added.
+        * http/tests/inspector/network/har/resources/empty.har: Added.
+        * http/tests/inspector/network/har/resources/webkit.org.har: Added.
+        Sample HARs to test against.
+
 2019-03-14  Zalan Bujtas  <zalan@apple.com>
 
         Cleanup inline boxes when list marker gets blockified
diff --git a/LayoutTests/http/tests/inspector/network/har/har-import-expected.txt b/LayoutTests/http/tests/inspector/network/har/har-import-expected.txt
new file mode 100644 (file)
index 0000000..516f304
--- /dev/null
@@ -0,0 +1,93 @@
+Tests for HAR import.
+
+
+== Running test suite: HAR.Import
+-- Running test case: HAR.Import.Empty
+PASS: Should be able to import a HAR with no resources.
+PASS: Should produce zero LocalResources.
+
+-- Running test case: HAR.Import.Full
+PASS: Should be able to import a HAR with many resources.
+Resources: 11
+https://webkit.org/
+https://webkit.org/wp-content/themes/webkit/style.css?20181220
+https://www.apple.com/wss/fonts?families=SF+Pro,v1
+https://webkit.org/wp/wp-includes/css/dist/block-library/style.min.css?ver=5.0.3
+https://webkit.org/wp-content/themes/webkit/scripts/global.js?ver=1.0
+https://webkit.org/wp/wp-includes/js/wp-embed.min.js?ver=5.0.3
+https://webkit.org/wp-content/themes/webkit/images/compass.svg
+https://webkit.org/wp-content/themes/webkit/images/webkit.svg
+https://webkit.org/wp-content/themes/webkit/images/menu-down.svg
+https://webkit.org/wp-content/themes/webkit/images/template.svg
+https://webkit.org/wp-content/themes/webkit/images/chevron.svg
+
+-- Running test case: HAR.Import.Basic
+PASS: Should be able to import a HAR with fake resources.
+PASS: Should produce two LocalResources.
+
+PASS: Bare Resource URL should be 'https://example.com/fake.js'.
+PASS: Bare Resource MIME Type should be 'text/javascript'.
+PASS: Bare Resource type should be 'resource-type-script'.
+PASS: Bare Resource requestMethod should be 'GET'.
+PASS: Bare Resource requestSentWalltime should be '1508723752.694'.
+PASS: Bare Resource does not have a statusCode
+PASS: Bare Resource does not have statusText.
+
+PASS: Full Resource URL should be 'https://example.com/fake.js'.
+PASS: Full Resource MIME Type should be 'text/javascript'.
+PASS: Full Resource type should be 'resource-type-script'.
+PASS: Full Resource requestMethod should be 'GET'.
+PASS: Full Resource requestSentWalltime should be '1508723752.694'.
+PASS: Full Resource statusCode should be '200'.
+PASS: Full Resource statusText should be 'OK'.
+PASS: Full Resource responseSource should be 'Symbol(network)'.
+PASS: Full Resource protocol should be 'http/1.1'.
+PASS: Full Resource priority should be 'Symbol(unknown)'.
+PASS: Full Resource remoteAddress should be '12.34.56.78'.
+PASS: Full Resource connectionIdentifier should be '1'.
+PASS: Full Resource requestHeadersTransferSize should be '100'.
+PASS: Full Resource requestBodyTransferSize should be '0'.
+PASS: Full Resource responseHeadersTransferSize should be '200'.
+PASS: Full Resource responseBodyTransferSize should be '800'.
+PASS: Full Resource timing startTime should be '0.001'.
+PASS: Full Resource timing redirectStart should be NaN.
+PASS: Full Resource timing redirectEnd should be NaN.
+PASS: Full Resource timing fetchStart should be '0.001'.
+PASS: Full Resource timing domainLookupStart should be '0.1'.
+PASS: Full Resource timing domainLookupEnd should be '0.2'.
+PASS: Full Resource timing connectStart should be '0.2'.
+PASS: Full Resource timing connectEnd should be '0.3'.
+PASS: Full Resource timing secureConnectionStart should be '0.25'.
+PASS: Full Resource timing requestStart should be '0.4'.
+PASS: Full Resource timing responseStart should be '0.5'.
+PASS: Full Resource timing responseEnd should be '0.6'.
+
+Request Headers:
+{
+  "Test-Request-Header": "Test Request Header Value"
+}
+
+Response Headers:
+{
+  "Test-Response-Header": "Test Response Header Value"
+}
+
+Content:
+Test Content
+
+-- Running test case: HAR.Import.BadVersion
+ERROR: HAR Import Error: unsupported HAR version
+PASS: Should fail to import a HAR with an unsupported version.
+
+-- Running test case: HAR.Import.Invalid
+ERROR: HAR Import Error: invalid JSON
+PASS: Should fail to import invalid JSON: null.
+ERROR: HAR Import Error: invalid JSON
+PASS: Should fail to import invalid JSON: 123.
+ERROR: HAR Import Error: invalid HAR
+PASS: Should fail to import invalid JSON: [].
+ERROR: HAR Import Error: invalid HAR
+PASS: Should fail to import invalid JSON: {}.
+ERROR: HAR Import Error: invalid HAR
+PASS: Should fail to import invalid JSON: {"pages":[],"entries":[]}.
+
diff --git a/LayoutTests/http/tests/inspector/network/har/har-import.html b/LayoutTests/http/tests/inspector/network/har/har-import.html
new file mode 100644 (file)
index 0000000..fd8deda
--- /dev/null
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../resources/inspector-test.js"></script>
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("HAR.Import");
+
+    suite.addTestCase({
+        name: "HAR.Import.Empty",
+        description: "Should be able to import a HAR with no resources.",
+        async test() {
+            const harURL = "http://127.0.0.1:8000/inspector/network/har/resources/empty.har";
+            let {content: har} = await NetworkAgent.loadResource(WI.networkManager.mainFrame.id, harURL);
+            let localResources = WI.networkManager.processHAR({json: JSON.parse(har)});
+            InspectorTest.expectThat(localResources, "Should be able to import a HAR with no resources.");
+            InspectorTest.expectEqual(localResources.length, 0, "Should produce zero LocalResources.");
+        }
+    });
+
+    suite.addTestCase({
+        name: "HAR.Import.Full",
+        description: "Should be able to import a complex HAR with many resources.",
+        async test() {
+            const harURL = "http://127.0.0.1:8000/inspector/network/har/resources/webkit.org.har";
+            let {content: har} = await NetworkAgent.loadResource(WI.networkManager.mainFrame.id, harURL);
+            let localResources = WI.networkManager.processHAR({json: JSON.parse(har)});
+            InspectorTest.expectThat(localResources, "Should be able to import a HAR with many resources.");
+            InspectorTest.log(`Resources: ${localResources.length}`);
+            for (let resource of localResources) {
+                InspectorTest.assert(resource instanceof WI.LocalResource);
+                InspectorTest.log(resource.url);
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "HAR.Import.Basic",
+        description: "Should be able to import a HAR with fake resources.",
+        async test() {
+            const harURL = "http://127.0.0.1:8000/inspector/network/har/resources/basic.har";
+            let {content: har} = await NetworkAgent.loadResource(WI.networkManager.mainFrame.id, harURL);
+            let localResources = WI.networkManager.processHAR({json: JSON.parse(har)});
+            InspectorTest.expectThat(localResources, "Should be able to import a HAR with fake resources.");
+            InspectorTest.expectEqual(localResources.length, 2, "Should produce two LocalResources.");
+
+            const url = "https://example.com/fake.js";
+            const mimeType = "text/javascript";
+            const type = WI.Resource.Type.Script;
+            const requestMethod = "GET";
+            const requestHeaders = {"Test-Request-Header": "Test Request Header Value"};
+            const responseHeaders = {"Test-Response-Header": "Test Response Header Value"};
+            const statusCode = 200;
+            const statusText = "OK";
+            const requestSentWalltime = 1508723752694 / 1000; // Sun Oct 22 2017 18:55:52 GMT-0700, when this test was written.
+            const size = 1234;
+            const timingData = {
+                startTime: 1 / 1000,
+                domainLookupStart: 100 / 1000,
+                domainLookupEnd: 200 / 1000,
+                connectStart: 200 / 1000, // HAR does not include ends, so this became the end of dns.
+                connectEnd: 300 / 1000,
+                secureConnectionStart: 250 / 1000,
+                requestStart: 400 / 1000,
+                responseStart: 500 / 1000,
+                responseEnd: 600 / 1000,
+            };
+            const responseSource = WI.Resource.ResponseSource.Network;
+            const metrics = {
+                protocol: "http/1.1",
+                priority: WI.Resource.NetworkPriority.Unknown, // Priority is not included in HAR.
+                remoteAddress: "12.34.56.78", // HAR Does not include port.
+                connectionIdentifier: 1,
+                requestHeaderBytesSent: 100,
+                requestBodyBytesSent: 0,
+                responseHeaderBytesReceived: 200,
+                responseBodyBytesReceived: 800,
+                responseBodyDecodedSize: 1234,
+                requestHeaders,
+            };
+
+            let bareResource = localResources[0];
+            InspectorTest.log("");
+            InspectorTest.expectEqual(bareResource.url, url, `Bare Resource URL should be '${url}'.`);
+            InspectorTest.expectEqual(bareResource.mimeType, mimeType, `Bare Resource MIME Type should be '${mimeType}'.`);
+            InspectorTest.expectEqual(bareResource.type, type, `Bare Resource type should be '${type}'.`);
+            InspectorTest.expectEqual(bareResource.requestMethod, requestMethod, `Bare Resource requestMethod should be '${requestMethod}'.`);
+            InspectorTest.expectEqual(bareResource.requestSentWalltime, requestSentWalltime, `Bare Resource requestSentWalltime should be '${requestSentWalltime}'.`);
+            InspectorTest.expectThat(isNaN(bareResource.statusCode), `Bare Resource does not have a statusCode`);
+            InspectorTest.expectNull(bareResource.statusText, `Bare Resource does not have statusText.`);
+
+            let fullResource = localResources[1];
+            InspectorTest.log("");
+            InspectorTest.expectEqual(fullResource.url, url, `Full Resource URL should be '${url}'.`);
+            InspectorTest.expectEqual(fullResource.mimeType, mimeType, `Full Resource MIME Type should be '${mimeType}'.`);
+            InspectorTest.expectEqual(fullResource.type, type, `Full Resource type should be '${type}'.`);
+            InspectorTest.expectEqual(fullResource.requestMethod, requestMethod, `Full Resource requestMethod should be '${requestMethod}'.`);
+            InspectorTest.expectEqual(fullResource.requestSentWalltime, requestSentWalltime, `Full Resource requestSentWalltime should be '${requestSentWalltime}'.`);
+            InspectorTest.expectEqual(fullResource.statusCode, statusCode, `Full Resource statusCode should be '${statusCode}'.`);
+            InspectorTest.expectEqual(fullResource.statusText, statusText, `Full Resource statusText should be '${statusText}'.`);                
+
+            InspectorTest.expectEqual(fullResource.responseSource, responseSource, `Full Resource responseSource should be '${String(responseSource)}'.`);
+            InspectorTest.expectEqual(fullResource.protocol, metrics.protocol, `Full Resource protocol should be '${metrics.protocol}'.`);
+            InspectorTest.expectEqual(fullResource.priority, metrics.priority, `Full Resource priority should be '${String(metrics.priority)}'.`);
+            InspectorTest.expectEqual(fullResource.remoteAddress, metrics.remoteAddress, `Full Resource remoteAddress should be '${metrics.remoteAddress}'.`);
+            InspectorTest.expectEqual(fullResource.connectionIdentifier, metrics.connectionIdentifier, `Full Resource connectionIdentifier should be '${metrics.connectionIdentifier}'.`);
+            InspectorTest.expectEqual(fullResource.requestHeadersTransferSize, metrics.requestHeaderBytesSent, `Full Resource requestHeadersTransferSize should be '${metrics.requestHeaderBytesSent}'.`);
+            InspectorTest.expectEqual(fullResource.requestBodyTransferSize, metrics.requestBodyBytesSent, `Full Resource requestBodyTransferSize should be '${metrics.requestBodyBytesSent}'.`);
+            InspectorTest.expectEqual(fullResource.responseHeadersTransferSize, metrics.responseHeaderBytesReceived, `Full Resource responseHeadersTransferSize should be '${metrics.responseHeaderBytesReceived}'.`);
+            InspectorTest.expectEqual(fullResource.responseBodyTransferSize, metrics.responseBodyBytesReceived, `Full Resource responseBodyTransferSize should be '${metrics.responseBodyBytesReceived}'.`);
+
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.startTime, timingData.startTime, 0.001, `Full Resource timing startTime should be '${timingData.startTime}'.`);
+            InspectorTest.expectThat(isNaN(fullResource.timingData.redirectStart), `Full Resource timing redirectStart should be NaN.`);
+            InspectorTest.expectThat(isNaN(fullResource.timingData.redirectEnd), `Full Resource timing redirectEnd should be NaN.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.fetchStart, timingData.startTime, 0.001, `Full Resource timing fetchStart should be '${timingData.startTime}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.domainLookupStart, timingData.domainLookupStart, 0.001, `Full Resource timing domainLookupStart should be '${timingData.domainLookupStart}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.domainLookupEnd, timingData.domainLookupEnd, 0.001, `Full Resource timing domainLookupEnd should be '${timingData.domainLookupEnd}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.connectStart, timingData.connectStart, 0.001, `Full Resource timing connectStart should be '${timingData.connectStart}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.connectEnd, timingData.connectEnd, 0.001, `Full Resource timing connectEnd should be '${timingData.connectEnd}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.secureConnectionStart, timingData.secureConnectionStart, 0.001, `Full Resource timing secureConnectionStart should be '${timingData.secureConnectionStart}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.requestStart, timingData.requestStart, 0.001, `Full Resource timing requestStart should be '${timingData.requestStart}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.responseStart, timingData.responseStart, 0.001, `Full Resource timing responseStart should be '${timingData.responseStart}'.`);
+            InspectorTest.expectEqualWithAccuracy(fullResource.timingData.responseEnd, timingData.responseEnd, 0.001, `Full Resource timing responseEnd should be '${timingData.responseEnd}'.`);
+
+            InspectorTest.log("");
+            InspectorTest.log("Request Headers:");
+            InspectorTest.json(fullResource.requestHeaders);
+
+            InspectorTest.log("");
+            InspectorTest.log("Response Headers:");
+            InspectorTest.json(fullResource.responseHeaders);
+
+            InspectorTest.log("");
+            InspectorTest.log("Content:");
+            let {content} = await fullResource.requestContent();
+            InspectorTest.log(content);
+        }
+    });
+
+    suite.addTestCase({
+        name: "HAR.Import.BadVersion",
+        description: "Attempt an import of an unsupported HAR version.",
+        async test() {
+            const harURL = "http://127.0.0.1:8000/inspector/network/har/resources/bad-version.har";
+            let {content: har} = await NetworkAgent.loadResource(WI.networkManager.mainFrame.id, harURL);
+            let localResources = WI.networkManager.processHAR({json: JSON.parse(har)});
+            InspectorTest.expectNull(localResources, "Should fail to import a HAR with an unsupported version.");
+        }
+    });
+
+    suite.addTestCase({
+        name: "HAR.Import.Invalid",
+        description: "Attempt an import of invalid JSON.",
+        async test() {
+            function t(har) {
+                let localResources = WI.networkManager.processHAR({json: har});
+                InspectorTest.expectNull(localResources, `Should fail to import invalid JSON: ${JSON.stringify(har)}.`);
+            }
+
+            t(null);
+            t(123);
+            t([]);
+            t({});
+            t({pages: [], entries: []});
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests for HAR import.</p>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/inspector/network/har/resources/bad-version.har b/LayoutTests/http/tests/inspector/network/har/resources/bad-version.har
new file mode 100644 (file)
index 0000000..0af742d
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "log": {
+    "version": "1.0",
+    "creator": {},
+    "pages": [],
+    "entries": []
+  }
+}
\ No newline at end of file
diff --git a/LayoutTests/http/tests/inspector/network/har/resources/basic.har b/LayoutTests/http/tests/inspector/network/har/resources/basic.har
new file mode 100644 (file)
index 0000000..cd05876
--- /dev/null
@@ -0,0 +1,119 @@
+{
+  "log": {
+    "version": "1.2",
+    "creator": {
+      "name": "WebKit Web Inspector",
+      "version": "<filtered>"
+    },
+    "pages": [
+      {
+        "startedDateTime": "2017-10-23T01:55:52.694Z",
+        "id": "page_0",
+        "title": "http://127.0.0.1:8000/inspector/network/har/har-basic.html",
+        "pageTimings": {}
+      }
+    ],
+    "entries": [
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2017-10-23T01:55:52.694Z",
+        "time": 0,
+        "request": {
+          "method": "GET",
+          "url": "https://example.com/fake.js",
+          "httpVersion": "",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Test-Request-Header",
+              "value": "Test Request Header Value"
+            }
+          ],
+          "queryString": [],
+          "headersSize": -1,
+          "bodySize": -1
+        },
+        "response": {
+          "status": 0,
+          "statusText": "",
+          "httpVersion": "",
+          "cookies": [],
+          "headers": [],
+          "content": {
+            "size": 0,
+            "compression": 0,
+            "mimeType": "text/javascript"
+          },
+          "redirectURL": "",
+          "headersSize": -1,
+          "bodySize": -1
+        },
+        "cache": {},
+        "timings": {
+          "blocked": -1,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0,
+          "wait": 0,
+          "receive": 0
+        }
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2017-10-23T01:55:52.694Z",
+        "time": 700,
+        "request": {
+          "method": "GET",
+          "url": "https://example.com/fake.js",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Test-Request-Header",
+              "value": "Test Request Header Value"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 100,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Test-Response-Header",
+              "value": "Test Response Header Value"
+            }
+          ],
+          "content": {
+            "size": 1234,
+            "compression": 434,
+            "mimeType": "text/javascript",
+            "text": "Test Content"
+          },
+          "redirectURL": "",
+          "headersSize": 200,
+          "bodySize": 800,
+          "_transferSize": 1000
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 100.00000000000009,
+          "dns": 99.99999999999987,
+          "connect": 99.99999999999987,
+          "ssl": 49.99999999999982,
+          "send": 100.00000000000009,
+          "wait": 100.00000000000009,
+          "receive": 99.99999999999987
+        },
+        "serverIPAddress": "12.34.56.78",
+        "connection": "1",
+        "_fetchType": "Network Load"
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/LayoutTests/http/tests/inspector/network/har/resources/empty.har b/LayoutTests/http/tests/inspector/network/har/resources/empty.har
new file mode 100644 (file)
index 0000000..1ca03d3
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "log": {
+    "version": "1.2",
+    "creator": {
+      "name": "WebKit Web Inspector",
+      "version": "<filtered>"
+    },
+    "pages": [
+      {
+        "startedDateTime": "2017-10-23T01:55:52.694Z",
+        "id": "page_0",
+        "title": "http://127.0.0.1:8000/inspector/network/har/har-basic.html",
+        "pageTimings": {}
+      }
+    ],
+    "entries": []
+  }
+}
\ No newline at end of file
diff --git a/LayoutTests/http/tests/inspector/network/har/resources/webkit.org.har b/LayoutTests/http/tests/inspector/network/har/resources/webkit.org.har
new file mode 100644 (file)
index 0000000..49c901d
--- /dev/null
@@ -0,0 +1,1618 @@
+{
+  "log": {
+    "version": "1.2",
+    "creator": {
+      "name": "WebKit Web Inspector",
+      "version": "605.1.15"
+    },
+    "pages": [
+      {
+        "startedDateTime": "2019-03-12T20:10:24.230Z",
+        "id": "page_0",
+        "title": "https://webkit.org/",
+        "pageTimings": {
+          "onContentLoad": 106877.79807019979,
+          "onLoad": 106957.76758808643
+        }
+      }
+    ],
+    "entries": [
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.230Z",
+        "time": 87.56101131439209,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 414,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "text/html; charset=UTF-8"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=100"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Tue, 12 Mar 2019 20:10:14 GMT"
+            },
+            {
+              "name": "Content-Encoding",
+              "value": "gzip"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "max-age=3, must-revalidate"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "13664"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "Vary",
+              "value": "Accept-Encoding,Cookie"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "X-Powered-By",
+              "value": "PHP/5.4.16"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "WP-Super-Cache",
+              "value": "Served supercache file from PHP"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 47447,
+            "compression": 33783,
+            "mimeType": "text/html",
+            "text": "<!DOCTYPE html>\n<html>\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n    <meta name=\"robots\" content=\"noodp\">\n\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover\">\n\n    <title>WebKit</title>\n\n    <meta name=\"application-name\" content=\"WebKit\">\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"https://webkit.org/wp-content/themes/webkit/style.css?20181220\" media=\"all\">\n    <link rel=\"stylesheet\" href=\"https://www.apple.com/wss/fonts?families=SF+Pro,v1\" type=\"text/css\">\n    <meta name=\"supported-color-schemes\" content=\"light dark\">\n\n    <link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS 2.0\" href=\"https://webkit.org/feed/\">\n    <link rel=\"alternate\" type=\"text/xml\" title=\"RSS .92\" href=\"https://webkit.org/feed/rss/\">\n    <link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom 0.3\" href=\"https://webkit.org/feed/atom/\">\n    <link rel=\"pingback\" href=\"https://webkit.org/wp/xmlrpc.php\">\n\n    <link rel=\"shortcut icon\" sizes=\"32x32\" type=\"image/x-icon\" href=\"/favicon.ico\">\n\n    <link rel='stylesheet' id='wp-block-library-css'  href='https://webkit.org/wp/wp-includes/css/dist/block-library/style.min.css?ver=5.0.3' type='text/css' media='all' />\n<link rel='https://api.w.org/' href='https://webkit.org/wp-json/' />\n<link rel=\"EditURI\" type=\"application/rsd+xml\" title=\"RSD\" href=\"https://webkit.org/wp/xmlrpc.php?rsd\" />\n<link rel=\"wlwmanifest\" type=\"application/wlwmanifest+xml\" href=\"https://webkit.org/wp/wp-includes/wlwmanifest.xml\" /> \n<meta name=\"generator\" content=\"WordPress 5.0.3\" />\n<link rel=\"canonical\" href=\"https://webkit.org/\" />\n<link rel='shortlink' href='https://webkit.org/' />\n<link rel=\"alternate\" type=\"application/json+oembed\" href=\"https://webkit.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwebkit.org%2F\" />\n<link rel=\"alternate\" type=\"text/xml+oembed\" href=\"https://webkit.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwebkit.org%2F&#038;format=xml\" />\n\n    <!-- Schema.org markup -->\n    <meta itemprop=\"name\" content=\"WebKit\">\n    <meta itemprop=\"description\" content=\"Open Source Web Browser Engine\">\n    <meta itemprop=\"image\" content=\"https://webkit.org/wp-content/themes/webkit/images/ogimage.png\">\n\n    <!-- Twitter Card data -->\n    <meta name=\"twitter:card\" content=\"summary_large_image\">\n    <meta name=\"twitter:site\" content=\"@webkit\">\n    <meta name=\"twitter:title\" content=\"WebKit\">\n    <meta name=\"twitter:description\" content=\"Open Source Web Browser Engine\">\n    <meta name=\"twitter:image:src\" content=\"https://webkit.org/wp-content/themes/webkit/images/ogimage.png\">\n\n    <!-- Open Graph data -->\n    <meta property=\"og:title\" content=\"WebKit\">\n    <meta property=\"og:type\" content=\"website\">\n    <meta property=\"og:url\" content=\"https://webkit.org/\">\n    <meta property=\"og:image\" content=\"https://webkit.org/wp-content/themes/webkit/images/ogimage.png\">\n    <meta property=\"og:description\" content=\"Open Source Web Browser Engine\">\n    <meta property=\"og:site_name\" content=\"WebKit\">\n    <meta property=\"fb:admins\" content=\"1085088865\">\n    <meta property=\"fb:admins\" content=\"854565306\">\n</head>\n<body class=\"home page-template-default page page-id-4118\">\n    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright © 2018 Apple Inc. All rights reserved. -->\n<svg xmlns=\"http://www.w3.org/2000/svg\">\n\t<style> svg { display: block; width: 0; height: 0; } </style>\n    <filter id=\"invertLightness\" x=\"0\" y=\"0\" style=\"color-interpolation-filters: sRGB\">\n        <feColorMatrix type=\"matrix\" in=\"SourceGraphic\" result=\"red\" values=\"1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1\" />\n        <feColorMatrix type=\"matrix\" in=\"SourceGraphic\" result=\"green\" values=\"0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1\" />\n        <feColorMatrix type=\"matrix\" in=\"SourceGraphic\" result=\"blue\" values=\"0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1\" />\n        <feBlend in=\"red\" in2=\"green\" mode=\"lighten\" result=\"maxyellow\" />\n        <feBlend in=\"maxyellow\" in2=\"blue\" mode=\"lighten\" result=\"max\" />\n        <feBlend in=\"red\" in2=\"green\" mode=\"darken\" result=\"minyellow\" />\n        <feBlend in=\"minyellow\" in2=\"blue\" mode=\"darken\" result=\"min\" />\n        <feComponentTransfer result=\"adjustment\" in=\"min\">\n            <feFuncR type=\"linear\" intercept=\"1\" slope=\"-1\" />\n            <feFuncG type=\"linear\" intercept=\"1\" slope=\"-1\" />\n            <feFuncB type=\"linear\" intercept=\"1\" slope=\"-1\" />\n        </feComponentTransfer>\n        <feComposite operator=\"arithmetic\" in=\"SourceGraphic\" in2=\"adjustment\" k1=\"0\" k2=\"1\" k3=\"1\" k4=\"-1\" result=\"channelAdjustment\" />\n        <feComposite operator=\"arithmetic\" in=\"channelAdjustment\" in2=\"max\" k1=\"0\" k2=\"1\" k3=\"-1\" k4=\"1\" result=\"finalColors\" />\n        <feComposite operator=\"in\" in=\"finalColors\" in2=\"SourceAlpha\" />\n    </filter>\n</svg>    <header aria-label=\"WebKit.org Header\" id=\"header\">\n        <div class=\"page-width\">\n        <a href=\"/\"><div id=\"logo\" class=\"site-logo\">WebKit</div></a>\n        <nav id=\"site-nav\" aria-label=\"Site Menu\">\n<div class=\"menu-main-menu-container\"><input type=\"checkbox\" id=\"menu-main-menu-toggle\" class=\"menu-toggle\" /><label for=\"menu-main-menu-toggle\" class=\"label-toggle main-menu\" data-open=\"Main Menu\" data-close=\"Close Menu\"></label><ul id=\"menu-main-menu\" class=\"menu\" role=\"menubar\"><li id=\"menu-item-4270\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4270\"><a href=\"https://webkit.org/blog/\">Blog</a></li>\n<li id=\"menu-item-6091\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-6091\"><a href=\"https://webkit.org/downloads/\">Downloads</a></li>\n<li id=\"menu-item-4272\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4272\"><a href=\"https://webkit.org/status/\">Feature Status</a></li>\n<li id=\"menu-item-4273\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4273\"><a href=\"https://webkit.org/reporting-bugs/\">Reporting Bugs</a></li>\n<li id=\"menu-item-4274\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-4274\"><input type=\"checkbox\" id=\"toggle-4274\" class=\"menu-toggle\" /><a href=\"#nav-sub-menu\" aria-haspopup=\"true\" aria-owns=\"sub-menu-for-4274\" aria-controls=\"sub-menu-for-4274\" aria-expanded=\"true\"><label for=\"toggle-4274\" class=\"label-toggle\">Contribute</label></a>\n<ul class=\"sub-menu sub-menu-layer\" role=\"menu\" id=\"sub-menu-for-4274\">\n\t<li id=\"menu-item-4277\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4277\"><input type=\"checkbox\" id=\"toggle-4274\" class=\"menu-toggle\" /><a href=\"https://webkit.org/getting-started/\">Getting Started</a></li>\n\t<li id=\"menu-item-4284\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4284\"><input type=\"checkbox\" id=\"toggle-4274\" class=\"menu-toggle\" /><a href=\"https://webkit.org/contributing-code/\">Contributing Code</a></li>\n\t<li id=\"menu-item-4281\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4281\"><input type=\"checkbox\" id=\"toggle-4274\" class=\"menu-toggle\" /><a href=\"https://webkit.org/testing-contributions/\">Testing Contributions</a></li>\n\t<li id=\"menu-item-4282\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4282\"><input type=\"checkbox\" id=\"toggle-4274\" class=\"menu-toggle\" /><a href=\"https://webkit.org/policy-and-guidelines/\">Policy and Guidelines</a></li>\n\t<li id=\"menu-item-4278\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4278\"><input type=\"checkbox\" id=\"toggle-4274\" class=\"menu-toggle\" /><a href=\"http://trac.webkit.org\">Trac Timeline</a></li>\n</ul>\n</li>\n</ul></div></nav>\n        </div>\n    </header>\n\n    <style>\n    header {\n        position: absolute;\n    }\n\n    .page-layer {\n        overflow: hidden;\n    }\n\n    .hero {\n        position: relative;\n        overflow: hidden;\n        max-width: 100vw;\n        box-sizing: border-box;\n        padding: 0 0 6rem;\n        color: white;\n        background-color: hsl(203.6, 100%, 12%);\n        z-index: 1;\n        top: -30rem;\n        padding-top: 45rem;\n        margin-bottom: -30rem;\n    }\n\n    .hero h1 {\n        font-size: 4.8rem;\n        font-weight: 500;\n        letter-spacing: 0.006rem;\n        text-align: center;\n        line-height: 1.04167;\n    }\n\n    .hero p {\n        font-size: 2.2rem;\n        line-height: 1.45455;\n        letter-spacing: 0.016em;\n        font-weight: 300;\n        text-align: center;\n        margin-top: 1.65rem;\n    }\n\n    .hero a {\n        color: hsl(200, 100%, 50%);\n    }\n\n    #fade {\n        position: absolute;\n        width: 100%;\n        height: 1261px;\n        background-image: radial-gradient(ellipse closest-corner at center center, hsl(198, 100%, 20%) 0%, hsla(204, 100%, 20%, 0) 100%);\n        z-index: 4;\n        transform: translateY(-450px);\n    }\n\n    #template {\n        opacity: 0.1;\n        position: absolute;\n        top: 0px;\n        width: 100%;\n        height: 195.5rem;\n        background-repeat: no-repeat;\n        background-position: 50% 49.5%;\n        background-size: 101.5%;\n        z-index: 3;\n        transform: translateY(-400px);\n    }\n\n    #compass {\n        position: absolute;\n        top: 0px;\n        width: 100%;\n        height: 1950px;\n        background-repeat: no-repeat;\n        background-position: 50% 50%;\n        background-size: 98%;\n        opacity: 0.3;\n        animation-name: bgspin;\n        animation-duration: 360s;\n        animation-timing-function: ease-out;\n        z-index: 2;\n        will-change: transform;\n        transform: translateY(-400px);\n    }\n\n    @keyframes bgspin {\n        from {\n            transform: translateY(-400px) rotate(0);\n            -webkit-transform: translateY(-400px) rotate(0deg);\n        }\n        to {\n            transform: translateY(-400px) rotate(360);\n            -webkit-transform: translateY(-400px) rotate(360deg);\n        }\n    }\n\n    .hero .content {\n        position: relative;\n        max-width: 800px;\n        padding: 0 3rem;\n        margin: 0 auto;\n        z-index: 10;\n    }\n\n    main {\n        position: relative;\n        z-index: 10;\n    }\n\n    @media only screen and (max-width: 920px) {\n        .hero {\n            padding-top: 40rem;\n            padding-bottom: 3rem;\n        }\n    }\n\n    @media only screen and (max-width: 690px) {\n        .hero h1 {\n            font-size: 4rem;\n            line-height: 1.1;\n        }\n\n        .hero p {\n            font-size: 2rem;\n            line-height: 1.4;\n            letter-spacing: -0.016rem;\n        }\n\n        #compass {\n            background-size: 150%;\n        }\n    }\n\n    @media only screen and (max-width: 320px) {\n        .hero h1 {\n            font-size: 2.5rem;\n            letter-spacing: -0.016rem;\n        }\n    }\n\n    @media (prefers-reduced-motion) {\n        #compass {\n            animation: none;\n        }\n    }\n    </style>\n\n        <div class=\"hero\">\n        <div id=\"template\"></div>\n        <div id=\"compass\"></div>\n        <div id=\"fade\"></div>\n        <div class=\"content\">\n            <h1><a name=\"afast-opensourcewebbrowser-engine\"></a>A&nbsp;fast, open&nbsp;source<br />web&nbsp;browser engine.</h1>\n<p>WebKit is the <a href=\"/project\">web browser engine</a> used by Safari, Mail, App Store, and many other apps on macOS, iOS, and Linux. <a href=\"/getting-started\">Get started</a> <a href=\"/contributing-code\">contributing code</a>, or <a href=\"/reporting-bugs\">reporting&nbsp;bugs</a>.</p>\n<p>Web developers can <a href=\"/blog\">follow development</a>, <a href=\"/status\">check feature status</a>, <a href=\"/downloads\">download Safari&nbsp;Technology&nbsp;Preview</a> to try out the latest web technologies, and <a href=\"/reporting-bugs\">report&nbsp;bugs</a>.</p>\n        </div>\n    </div>\n    \n<div class=\"page-layer\">\n<main id=\"content\">\n    <div class=\"page-width\"><div id=\"posts\" class=\"tiles\">\n    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright © 2015 Apple Inc. All rights reserved. -->\n<svg id=\"icons\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\">\n    <style>\n        svg,symbol { color: currentColor; }\n    </style>\n\n    <defs>\n\n        <symbol id=\"default\">\n            <path d=\"M 24 45.7600002 L 24 45.7600002 C 36.0177159 45.7600002 45.7599999 36.0177161 45.7599999 24.0000001 C 45.7599999 11.9822838 36.0177159 2.24000001 24 2.24000001 C 11.9822838 2.24000001 2.23999999 11.9822838 2.23999999 24.0000001 C 2.23999999 36.0177161 11.9822838 45.7600002 24 45.7600002 L 24 45.7600002 L 24 45.7600002 L 24 45.7600002 Z M 24 48 L 24 48 C 10.745166 48 8.52651283e-14 37.254834 8.52651283e-14 24.0000001 C 8.52651283e-14 10.745166 10.745166 0 24 0 C 37.254834 0 48 10.745166 48 24.0000001 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z\" fill=\"currentColor\"/>\n            <path d=\"M 19.2141787 30.7527044 C 20.0566026 31.3582067 21.0164459 31.8087988 22.052466 32.0629879 L 24.0150243 38.3621108 L 25.9644157 32.0671275 C 28.9532689 31.3397602 31.304042 28.97474 32.0270276 25.9677724 L 38.2840894 24.0065666 L 32.38318 22.1457238 L 30.1049072 24.2136546 C 29.9995478 27.5073249 27.2907334 30.1510903 24.0134391 30.1359337 C 23.1661809 30.1431339 22.3840431 29.959524 21.6645278 29.6641888 L 19.2141787 30.7527044 L 19.2141787 30.7527044 L 19.2141787 30.7527044 Z M 28.8019182 17.2563866 C 27.4120183 16.2548466 25.9438825 15.9331447 25.9438825 15.9331447 L 23.9849759 9.63788916 L 22.0355845 15.9328727 C 19.0467312 16.6602398 16.695958 19.0252601 15.9729726 22.0322277 L 9.71591065 23.9934336 C 9.71591065 23.9934336 13.7573684 25.2679011 15.7780972 25.9051349 L 17.8923556 23.9486543 C 17.9116726 20.5783691 20.6200789 17.8803136 23.9912031 17.8674375 C 24.8266313 17.8130168 26.1806153 18.2277657 26.3381938 18.3358993 C 26.3381937 18.3358993 28.8019182 17.2563866 28.8019182 17.2563866 L 28.8019182 17.2563866 L 28.8019182 17.2563866 Z\" fill=\"currentColor\"/>\n            <path d=\"M 22.4528571 21.5612813 L 10.1267612 32.8610634 L 25.4820204 26.3285511 L 37.8732388 15.1389366 L 22.4528571 21.5612813 L 22.4528571 21.5612813 L 22.4528571 21.5612813 Z\" fill=\"currentColor\"/>\n        </symbol>\n\n        <symbol id=\"performance\">\n            <path d=\"M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 -1.77635684e-14 37.254834 -1.77635684e-14 24 C -1.77635684e-14 10.745166 10.745166 2.84217094e-14 24 2.84217094e-14 C 37.254834 2.84217094e-14 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z\" fill=\"currentColor\"/>\n            <path d=\"M 25.4586474 22.9633529 L 36.6273818 12.9367924 L 19.3784717 20.0882179 L 22.54035 25.0378408 L 11.3720064 35.0646845 L 28.6179627 27.9103051 L 25.4586474 22.9633529 L 25.4586474 22.9633529 Z\" fill=\"currentColor\"/>\n        </symbol>\n\n        <symbol id=\"web-inspector\">\n            <path d=\"M 28.5 25.5 L 48 25.5 L 48 23 L 28.5 23 L 28.5 25.5\" fill=\"currentColor\"/>\n            <path d=\"M 23 28.5 L 23 48 L 25.5 48 L 25.5 28.5 L 23 28.5\" fill=\"currentColor\"/>\n            <path d=\"M 0 25.5 L 19.5 25.5 L 19.5 23 L 5.99520433e-15 23 L 0 25.5\" fill=\"currentColor\"/>\n            <path d=\"M 23 0 L 23 19.5 L 25.5 19.5 L 25.5 0 L 23 0\" fill=\"currentColor\"/>\n            <circle stroke=\"currentColor\" fill=\"none\" stroke-width=\"2.5\" cx=\"24\" cy=\"24\" r=\"18\"/>\n        </symbol>\n\n        <symbol id=\"javascript\">\n            <path d=\"M 11.4057939 18.0146224 C 12.1528885 17.323319 13.14598 16.88131 14.2562501 16.88131 C 16.6587038 16.88131 18.5125003 18.9853621 18.5125003 21.1375602 C 18.5125003 21.1375602 20.178953 19.4758651 21.0121793 18.6450175 C 23.6138782 16.0507463 28.817276 10.8622038 28.817276 10.8622038 C 28.817276 10.8622038 39.1931445 22.2383022 39.5748423 22.7381568 C 40.0895548 23.4122017 41.2154452 24.6437363 41.2154452 26.8207002 C 41.2154452 27.9043457 40.7691081 28.9601004 40.0240604 29.7480538 C 39.2725506 30.5428415 23.5041804 46.2228621 24.256517 45.5146369 C 25.0871144 44.7325638 25.6062505 43.6260296 25.6062505 42.4188109 C 25.6062505 40.105895 24.4995839 38.9998346 23.9516194 38.3444074 C 23.9377433 38.32781 23.4369464 37.7753288 22.6469581 36.9043367 L 17.0937502 42.4188109 C 17.0937502 44.7694729 18.9993383 46.675061 21.3500004 46.675061 C 22.4737422 46.675061 23.4957691 46.2309411 24.256517 45.5146369 L 24.256517 45.5146368 C 24.2567055 45.5144594 24.256895 45.5142809 24.2570855 45.5141014 C 25.0873513 44.7320588 25.6062505 43.6257541 25.6062505 42.4188109 C 25.6062505 40.105895 24.4995839 38.9998346 23.9516194 38.3444074 C 23.4036549 37.6889802 12.6902909 25.9456715 11.9591809 25.1002579 C 11.2280709 24.2548443 10 23.3242225 10 21.1375602 C 10 19.9614421 10.5362909 18.819193 11.4057939 18.0146224 C 10.5362926 18.8191912 26.254167 3.0662162 27.2247918 2.26492532 C 27.9645636 1.65421303 28.8917931 1.2750595 29.8625007 1.2750595 C 32.1068344 1.2750595 34.1634331 3.37253043 34.1634331 5.53130965 L 18.5125003 21.1375602 C 18.5125003 18.9853621 16.6587038 16.88131 14.2562501 16.88131 C 13.1459801 16.88131 12.1528886 17.323319 11.405794 18.0146222 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n        </symbol>\n\n        <symbol id=\"css\">\n            <path d=\"M 34.3509426 18.7507162 C 32.564454 17.6916021 31.096954 15.1643395 31.0728076 13.0728197 L 30.9858202 5.538126 C 30.9618449 3.46142442 32.3778969 2.62894951 34.1771329 3.69562079 L 40.6588754 7.538301 C 42.445364 8.597415 43.912864 11.1246777 43.9370104 13.2161974 L 44.0239979 20.7508912 C 44.0479731 22.8275927 42.6319212 23.6600677 40.8326851 22.5933964 L 34.3509426 18.7507162 L 34.3509426 18.7507162 L 34.3509426 18.7507162 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 22.3883659 25.2906441 C 20.6046264 24.23316 19.1392369 21.6969806 19.1152755 19.6214854 L 18.9412495 4.54767084 C 18.9173111 2.47416506 20.3422003 1.64950223 22.1276511 2.70800103 L 35.0949445 10.3956191 C 36.8786839 11.4531034 38.3440734 13.9892828 38.3680349 16.064778 L 38.5420608 31.1385925 C 38.5659993 33.2120983 37.14111 34.0367611 35.3556591 32.9782623 L 22.3883659 25.2906441 L 22.3883659 25.2906441 L 22.3883659 25.2906441 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 8.57225363 34.8880373 C 6.19393433 33.4780584 4.24008165 30.0964858 4.2081331 27.3291589 L 3.97609854 7.2307395 C 3.94418061 4.46606514 5.84403281 3.36651469 8.224634 4.77784643 L 25.5143585 15.0280039 C 27.8926778 16.4379829 29.8465304 19.8195554 29.8784789 22.5868824 L 30.1105135 42.6853018 C 30.1424314 45.4499761 28.2425793 46.5495265 25.861978 45.1381948 L 8.57225363 34.8880373 L 8.57225363 34.8880373 L 8.57225363 34.8880373 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n        </symbol>\n\n        <symbol id=\"standards\">\n            <path d=\"M 8.20156221 41.7446204 L 4.60455725 1.39999998 L 44.1294427 1.39999998 L 40.5286241 41.7383005 L 24.34281 46.2255399 L 8.20156221 41.7446204 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 42.0710239 24.0177617 C 39.1538386 16.9070258 32.1617573 11.8990479 24 11.8990479 C 16.3635634 11.8990479 9.75107907 16.2831086 6.54212676 22.6716502\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 30.9761247 44.4830419 C 32.2260967 41.0462637 32.9749756 36.6675422 32.9749756 31.8990479 C 32.9749756 20.8533529 28.9567421 11.8990479 24 11.8990479 C 19.0432579 11.8990479 15.0250244 20.8533529 15.0250244 31.8990479 C 15.0250244 36.5317055 15.7318455 40.7964804 16.9182797 44.1870585 L 16.9182797 44.1870585\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 6.58618164 23.392334 C 6.58618164 25.4881886 14.5338788 27.1872144 24.3378601 27.1872144 C 34.1418414 27.1872144 42.0895386 25.4881886 42.0895386 23.392334\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 7.57792629 35.5492537 C 10.9596878 37.443268 17.049483 38.7070228 24 38.7070228 C 31.5250917 38.7070228 38.041274 37.2256916 41.204187 35.0669761\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 24.25 12.9990234 L 24.25 45\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n        </symbol>\n\n        <symbol id=\"contributing\">\n            <path d=\"M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 -1.77635684e-14 37.254834 -1.77635684e-14 24 C -1.77635684e-14 10.745166 10.745166 2.84217094e-14 24 2.84217094e-14 C 37.254834 2.84217094e-14 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z\" fill=\"currentColor\"/>\n            <path d=\"M 29.4897098 23.3065925 L 26.2706917 20.9393745 L 26.6482584 24.3031351 L 28.4802897 29.4247528 L 29.4897098 33.8205977 L 30.4989581 29.4247528 L 32.3309894 24.3031351 L 32.7087278 20.9393745 L 29.4897098 23.3065925 Z M 18.8503641 23.3065925 L 15.631346 20.9393745 L 16.0090845 24.3031351 L 17.8411157 29.4247528 L 18.8503641 33.8205977 L 19.8597841 29.4247528 L 21.6916437 24.3031351 L 22.0693821 20.9393745 L 18.8503641 23.3065925 Z M 37.2876041 24.3031351 L 39.1196354 29.4247528 L 40.3400738 34.740219 L 38.3454433 35 L 36.6368638 29.562799 C 36.6368638 29.562799 34.8092967 25.6310573 34.8092967 25.4866582 C 34.8092967 25.6310573 32.9819013 29.562799 32.9819013 29.562799 L 31.2733218 35 L 29.4897098 34.7676909 L 27.7060977 35 L 25.9975182 29.562799 C 25.9975182 29.562799 24.1701228 25.6310573 24.1701228 25.4866582 C 24.1701228 25.6310573 22.3425557 29.562799 22.3425557 29.562799 L 20.6339762 35 L 18.8503641 34.7676909 L 17.066752 35 L 15.3581725 29.562799 C 15.3581725 29.562799 13.5307771 25.6310573 13.5307771 25.4866582 C 13.5307771 25.6310573 11.7033817 29.562799 11.7033817 29.562799 L 9.9946305 35 L 8 34.740219 L 9.22043846 29.4247528 L 11.0524697 24.3031351 L 11.4302081 20.9393745 L 8.21101841 23.3065925 L 8.21101841 21.228001 L 11.6719607 18.326455 L 12.3810787 18.2218901 L 12.3810787 17.9233051 C 11.4619725 17.51054 10.825655 16.6183906 10.825655 15.5839024 C 10.825655 14.156738 12.0368217 13 13.5307771 13 C 15.0247325 13 16.2358992 14.156738 16.2358992 15.5839024 C 16.2358992 16.6183906 15.5995817 17.51054 14.6804755 17.9233051 L 14.6804755 18.2218901 L 15.3895935 18.326455 L 18.8503641 21.228001 L 22.3113064 18.326455 L 23.0204244 18.2218901 L 23.0204244 17.9233051 C 22.1013182 17.51054 21.4650007 16.6183906 21.4650007 15.5839024 C 21.4650007 14.156738 22.6761674 13 24.1701228 13 C 25.6640782 13 26.8750732 14.156738 26.8750732 15.5839024 C 26.8750732 16.6183906 26.2387556 17.51054 25.3198211 17.9233051 L 25.3198211 18.2218901 L 26.0289391 18.326455 L 29.4897098 21.228001 L 32.9504804 18.326455 L 33.6595984 18.2218901 L 33.6595984 17.9233051 C 32.7406639 17.51054 32.1043463 16.6183906 32.1043463 15.5839024 C 32.1043463 14.156738 33.3153413 13 34.8092967 13 C 36.3034238 13 37.5142471 14.156738 37.5144188 15.5839024 C 37.5144188 16.6183906 36.8781013 17.51054 35.9591668 17.9233051 L 35.9591668 18.2218901 L 36.6682848 18.326455 L 40.1290554 21.228001 L 40.1290554 23.3065925 L 36.9100374 20.9393745 L 37.2876041 24.3031351 Z\" fill=\"currentColor\"/>\n        </symbol>\n\n        <symbol id=\"storage\">\n                <path d=\"M 39.9236499 31.5126111 C 41.869091 32.6498521 43 34.0625041 43 35.6923077 C 43 40.1632127 34.4896382 43 24 43 C 13.5103618 43 5 40.1632127 5 35.6923077 C 5 34.0625041 6.130909 32.6498521 8.07635005 31.5126111 C 9.14708175 31.9858647 10.3798534 32.4104194 11.7445378 32.7755154 C 9.22593316 33.7562269 7.92307692 34.9214488 7.92307692 35.6923077 C 7.92307692 36.4947878 9.3350136 37.7246485 12.0606138 38.728817 C 15.168606 39.8738668 19.433505 40.5384615 24 40.5384615 C 28.566495 40.5384615 32.831394 39.8738668 35.9393862 38.728817 C 38.6649864 37.7246485 40.0769231 36.4947878 40.0769231 35.6923077 C 40.0769231 34.9214488 38.7740668 33.7562269 36.2554622 32.7755154 C 37.6201466 32.4104194 38.8529182 31.9858647 39.9236499 31.5126111 Z M 39.9236499 19.8203034 C 41.869091 20.9575444 43 22.3701964 43 24 C 43 28.470905 34.4896382 31.3076923 24 31.3076923 C 13.5103618 31.3076923 5 28.470905 5 24 C 5 22.3701964 6.130909 20.9575444 8.07635005 19.8203034 C 9.06881359 20.2589632 10.2004933 20.6557834 11.4473978 21.0021956 C 9.12353139 22.0250817 7.92307692 23.2072017 7.92307692 24 C 7.92307692 24.8598001 9.3350136 26.177508 12.0606138 27.2534028 C 15.168606 28.4802419 19.433505 29.1923077 24 29.1923077 C 28.566495 29.1923077 32.831394 28.4802419 35.9393862 27.2534028 C 38.6649864 26.177508 40.0769231 24.8598001 40.0769231 24 C 40.0769231 23.2072017 38.8764686 22.0250817 36.5526022 21.0021956 C 37.7995067 20.6557834 38.9311864 20.2589632 39.9236499 19.8203034 Z M 43 12.3076923 C 43 7.83678727 34.4896382 5 24 5 C 13.5103618 5 5 7.83678727 5 12.3076923 C 5 16.7785973 13.5103618 19.6153846 24 19.6153846 C 34.4896382 19.6153846 43 16.7785973 43 12.3076923 Z M 12.0606138 15.3442016 C 9.3350136 14.3400331 7.92307692 13.1101724 7.92307692 12.3076923 C 7.92307692 11.5052122 9.3350136 10.2753515 12.0606138 9.27118298 C 15.168606 8.12613322 19.433505 7.46153846 24 7.46153846 C 28.566495 7.46153846 32.831394 8.12613322 35.9393862 9.27118298 C 38.6649864 10.2753515 40.0769231 11.5052122 40.0769231 12.3076923 C 40.0769231 13.1101724 38.6649864 14.3400331 35.9393862 15.3442016 C 32.831394 16.4892514 28.566495 17.1538462 24 17.1538462 C 19.433505 17.1538462 15.168606 16.4892514 12.0606138 15.3442016 Z\" fill=\"currentColor\"/>\n        </symbol>\n\n        <symbol id=\"layout\">\n            <path d=\"M 44.5086986 24.2230775 L 24.1090229 24.2230775 L 24.1090229 4.50363839 L 24.1090229 4.50363839\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <rect id=\"Rectangle-1-Copy\" x=\"3.70934714\" y=\"4.50363839\" width=\"40.7993514\" height=\"39.4388783\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n        </symbol>\n\n        <symbol id=\"accessibility\">\n            <path d=\"M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 -1.77635684e-14 37.254834 -1.77635684e-14 24 C -1.77635684e-14 10.745166 10.745166 2.84217094e-14 24 2.84217094e-14 C 37.254834 2.84217094e-14 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z\" fill=\"currentColor\"/>\n            <path d=\"M 21.2941031 10.9732032C 21.2941031 9.47814808 22.5062404 8.2657032 24.0017464 8.2657032L 24.0017464 8.2657032 24.0056947 8.2657032 24.009643 8.2657032C 25.5054527 8.2657032 26.7180456 9.47814808 26.7180456 10.9732032L 26.7180456 10.9732032C 26.7180456 12.4699287 25.5054527 13.6817661 24.009643 13.6817661L 24.009643 13.6817661C 24.0087319 13.6817661 24.0072133 13.6817661 24.0056947 13.680855L 24.0056947 13.680855C 24.0044798 13.6817661 24.003265 13.6817661 24.0017464 13.6817661L 24.0017464 13.6817661C 22.5062404 13.6817661 21.2941031 12.4699287 21.2941031 10.9732032L 21.2941031 10.9732032zM 36.0001139 14.8094735C 36.5893262 14.8094735 37.0670742 15.2869192 37.0670742 15.8764371L 37.0670742 15.8764371C 37.0670742 16.3657279 36.7352626 16.7740776 36.2854567 16.8992097L 36.2854567 16.8992097C 36.2778637 16.9011839 29.0669982 17.7329174 29.0669982 17.7329174L 29.0669982 17.7329174C 29.0200738 17.7459773 28.9600896 17.7640486 28.8905382 17.7881942L 28.8905382 17.7881942C 28.6130921 17.8856879 28.1933543 18.082042 27.9395981 18.4301036L 27.9395981 18.4301036C 27.8733877 18.5288121 27.8196297 18.6340507 27.7781722 18.7465784L 27.7781722 18.7465784C 27.7692125 18.7754317 27.7581268 18.8026145 27.7509895 18.8326827L 27.7509895 18.8326827 27.7502302 18.8322271C 27.7013316 18.9912238 27.6732377 19.16161 27.6618483 19.3430819L 27.6618483 19.3430819 27.6618483 23.5734271 27.6633669 23.574642C 27.6633669 23.574642 27.6949535 25.3620263 28.019324 27.0936782L 28.019324 27.0936782C 28.0701968 27.3685436 30.0944752 37.1009042 30.0944752 37.1009042L 30.0944752 37.1009042 30.1055609 37.1526882 30.1063202 37.1554217 30.1058646 37.1554217C 30.1192282 37.2267956 30.1283397 37.3002955 30.1283397 37.3759214L 30.1283397 37.3759214C 30.1283397 38.0488101 29.582559 38.5945925 28.9098243 38.5945925L 28.9098243 38.5945925C 28.3578174 38.5945925 27.8973814 38.2255744 27.7470411 37.7227681L 27.7470411 37.7227681 27.7426372 37.7244386 24.9494974 28.2516056 24.9490419 28.2552502C 24.8633935 27.9793218 24.6456279 27.7639853 24.3690929 27.682285L 24.3690929 27.682285C 24.3476808 27.6756032 24.3209537 27.6684658 24.2873929 27.6613284L 24.2873929 27.6613284C 24.2763072 27.6590505 24.2656771 27.6578356 24.2550469 27.6558615L 24.2550469 27.6558615C 24.171069 27.641283 24.0600602 27.6341456 23.9274874 27.6519131L 23.9274874 27.6519131C 23.8465466 27.6598098 23.7695542 27.6783366 23.696662 27.7071899L 23.696662 27.7071899C 23.6860318 27.7106827 23.6757054 27.7128087 23.664316 27.7170608L 23.664316 27.7170608 23.6682643 27.7194905C 23.4406279 27.8200214 23.2634087 28.0140976 23.188846 28.2552502L 23.188846 28.2552502 23.1885422 28.2516056 20.3950988 37.7244386 20.3908467 37.7227681C 20.2405064 38.2255744 19.7800704 38.5945925 19.2283672 38.5945925L 19.2283672 38.5945925C 18.5553288 38.5945925 18.0100037 38.0488101 18.0100037 37.3759214L 18.0100037 37.3759214C 18.0100037 37.3002955 18.0186597 37.2267956 18.0320232 37.1554217L 18.0320232 37.1554217 18.0317195 37.1554217 18.0324788 37.1526882 18.0435645 37.1009042C 18.0435645 37.1009042 20.0672355 27.3685436 20.1190194 27.0936782L 20.1190194 27.0936782C 20.4429343 25.3620263 20.4745209 23.574642 20.4745209 23.574642L 20.4745209 23.574642 20.4760395 23.5734271 20.4760395 19.3430819C 20.4646501 19.16161 20.4367081 18.9912238 20.387354 18.8322271L 20.387354 18.8322271 20.3865947 18.8326827C 20.3799129 18.8026145 20.3688272 18.7754317 20.3597156 18.7465784L 20.3597156 18.7465784C 20.3182582 18.6340507 20.264652 18.5288121 20.1982897 18.4301036L 20.1982897 18.4301036C 19.9445336 18.082042 19.5252513 17.8856879 19.2470459 17.7881942L 19.2470459 17.7881942C 19.1771908 17.7640486 19.1175103 17.7459773 19.0713452 17.7329174L 19.0713452 17.7329174C 19.0713452 17.7329174 11.8600241 16.9011839 11.852583 16.8992097L 11.852583 16.8992097C 11.4032327 16.7740776 11.0712693 16.3657279 11.0712693 15.8764371L 11.0712693 15.8764371C 11.0712693 15.2869192 11.5487135 14.8094735 12.1377739 14.8094735L 12.1377739 14.8094735C 12.1875836 14.8094735 12.2348117 14.8173702 12.2826473 14.824052L 12.2826473 14.824052 12.2841659 14.8176739 35.853722 14.8176739 35.8553924 14.824052C 35.9030761 14.8173702 35.9504561 14.8094735 36.0001139 14.8094735L 36.0001139 14.8094735z\" fill=\"currentColor\"/>\n        </symbol>\n\n        <symbol id=\"safari-technology-preview\">\n            <path fill=\"currentColor\" d=\"M 24 45.7600002 L 24 45.7600002 C 36.0177159 45.7600002 45.7599999 36.0177161 45.7599999 24.0000001 C 45.7599999 11.9822838 36.0177159 2.24000001 24 2.24000001 C 11.9822838 2.24000001 2.23999999 11.9822838 2.23999999 24.0000001 C 2.23999999 36.0177161 11.9822838 45.7600002 24 45.7600002 L 24 45.7600002 L 24 45.7600002 L 24 45.7600002 Z M 24 48 L 24 48 C 10.745166 48 8.52651283e-14 37.254834 8.52651283e-14 24.0000001 C 8.52651283e-14 10.745166 10.745166 0 24 0 C 37.254834 0 48 10.745166 48 24.0000001 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z\"/>\n            <polygon fill=\"currentColor\" points=\"22.453 21.561 10.127 32.861 25.482 26.329 37.873 15.139 22.453 21.561\"/>\n        </symbol>\n\n        <symbol id=\"privacy\">\n             <path fill=\"currentColor\" d=\"M 15.1685425 22.4941973 L 15.1685425 12.388782 C 15.1685425 9.69393273 11.9195136 10.0438255 11.9195136 12.388782 C 11.9195136 14.7337385 11.4121047 32.9981208 12.5127398 36.791912 C 15.7058774 47.7983735 27.8522124 45.6566123 30.9533121 42.2509347 C 34.0544119 38.8452571 35.8653963 32.8762332 37.0588085 29.8327181 C 38.2522207 26.7892031 41.6333465 22.9334922 41.6333465 22.5465483 C 41.6333465 22.1596044 39.7727879 21.0338966 37.3194354 22.4340812 C 34.8660829 23.8342658 33.9888369 27.6603443 32.7864178 27.6603443 C 32.0030918 27.6603443 31.5285623 26.0635537 31.3628292 22.8699725 C 31.3874544 14.5599594 31.399767 9.3992148 31.399767 7.3877388 C 31.399767 4.37052481 27.5358136 4.795092 27.5358136 7.3877388 L 27.5358136 22.2770282 C 27.5358136 23.2870868 26.0021868 23.2870868 26.0021868 22.2770282 C 26.0021868 21.2669696 26.0103761 8.09132176 26.0103761 5.18199504 C 26.0103761 2.27266832 22.1464227 2.27266832 22.1464227 5.18199504 C 22.1464227 8.09132176 22.1382334 20.9905839 22.1382334 22.1596044 C 22.1382334 23.3286249 20.5935527 23.3286249 20.5935527 22.1596044 L 20.5935527 6.60705859 C 20.5935527 4.22138407 16.8868104 3.78049185 16.8868104 6.65940958 L 16.8868104 22.5465483 C 16.8868104 24.3345929 15.1685425 24.3345929 15.1685425 22.4941973 Z M 14.3868104 6.65940958 C 14.3868104 3.91189632 16.3888941 2.0323497 18.8710271 2.16243845 C 19.4064988 2.19050256 19.9212719 2.31118201 20.3960158 2.51120572 C 21.1877723 1.27053788 22.5338737 0.5 24.0783994 0.5 C 25.8329397 0.5 27.3314259 1.49432954 28.0521144 3.04262047 C 28.4563953 2.89966794 28.8859215 2.81223849 29.3306484 2.78780542 C 31.8648524 2.64857757 33.899767 4.5808987 33.899767 7.3877388 C 33.899767 9.34637369 33.8881312 14.2782337 33.864856 22.187356 C 34.5202025 21.3829967 35.2264688 20.7500823 36.0802432 20.2628137 C 39.436804 18.3471473 44.1333465 19.2889515 44.1333465 22.5465483 C 44.1333465 23.128154 44.0064029 23.4570378 43.7758938 23.8828557 C 43.696642 24.0292571 43.6066485 24.1738915 43.4964616 24.3384554 C 43.3490867 24.5585595 43.1729356 24.8042179 42.8700195 25.2170834 C 42.806542 25.3036015 42.553006 25.6483262 42.4922733 25.7310538 C 42.3365877 25.9431221 42.2077478 26.1195718 42.0809068 26.2947759 C 41.7586267 26.7399377 41.4753868 27.1414123 41.2083271 27.5344165 C 40.7821735 28.161543 40.415498 28.7410189 40.1080823 29.2802128 C 39.7959116 29.8277471 39.552971 30.3202329 39.3862735 30.7453553 C 39.1818924 31.266581 38.2603789 33.7727457 38.3029435 33.6585515 C 37.7697308 35.0890777 37.3098255 36.243653 36.8074885 37.3755123 C 35.6023636 40.090884 34.3213906 42.2652752 32.8018031 43.9341106 C 30.548363 46.4088748 25.8352037 47.8817882 21.4979867 47.4114012 C 16.0964787 46.825588 11.8453759 43.4641638 10.1117407 37.4884774 C 9.55240337 35.5604914 9.3355005 31.2870616 9.30591571 24.8221077 C 9.29392339 22.2015107 9.31516557 19.4953509 9.3614022 16.3674639 C 9.35539556 16.7738105 9.4195136 12.7514823 9.4195136 12.388782 C 9.4195136 9.97655668 11.1818898 8.12242436 13.4096084 8.00247119 C 13.7471824 7.98429426 14.0741531 8.00621829 14.3868104 8.06463687 L 14.3868104 6.65940958 Z\"/>\n        </symbol>\n\n        <symbol id=\"security\">\n            <path fill=\"currentColor\" d=\"M 15.8033934 20.1726723 L 12.729666 20.1726723 C 11.5979508 20.1726723 10.6805143 21.0901087 10.6805143 22.2218239 L 10.6805143 40.6641887 C 10.6805143 41.7959039 11.5979508 42.7133403 12.729666 42.7133403 L 35.270334 42.7133403 C 36.4020492 42.7133403 37.3194857 41.7959039 37.3194857 40.6641887 L 37.3194857 22.2218239 C 37.3194857 21.0901087 36.4020492 20.1726723 35.270334 20.1726723 L 32.1966066 20.1726723 L 32.1966066 13.4832662 C 32.1966066 8.95640542 28.5268608 5.28665966 24 5.28665966 C 19.4731392 5.28665966 15.8033934 8.95640542 15.8033934 13.4832662 L 15.8033934 20.1726723 Z M 13.3033934 17.6726723 L 13.3033934 13.4832662 C 13.3033934 7.57569355 18.0924273 2.78665966 24 2.78665966 C 29.9075727 2.78665966 34.6966066 7.57569355 34.6966066 13.4832662 L 34.6966066 17.6726723 L 35.270334 17.6726723 C 37.7827611 17.6726723 39.8194857 19.7093968 39.8194857 22.2218239 L 39.8194857 40.6641887 C 39.8194857 43.1766158 37.7827611 45.2133403 35.270334 45.2133403 L 12.729666 45.2133403 C 10.2172389 45.2133403 8.18051432 43.1766158 8.18051432 40.6641887 L 8.18051432 22.2218239 C 8.18051432 19.7093968 10.2172389 17.6726723 12.729666 17.6726723 L 13.3033934 17.6726723 Z\"/>\n            <path fill=\"currentColor\" d=\"M 21.21522 29.8126384C 21.21522 28.1150656 22.5913746 26.7389109 24.2889475 26.7389109 25.9865203 26.7389109 27.3626749 28.1150656 27.3626749 29.8126384 27.3626749 30.9503515 26.7445504 31.9436939 25.8258112 32.4751558L 25.8258112 35.9600933C 25.8258112 36.8088797 25.1377339 37.496957 24.2889475 37.496957 23.440161 37.496957 22.7520837 36.8088797 22.7520837 35.9600933L 22.7520837 32.4751558C 21.8333445 31.9436939 21.21522 30.9503515 21.21522 29.8126384zM 26.6228791 12.8501838C 26.6228791 11.8299912 25.5165562 10.8603871 24 10.8603871 22.4834438 10.8603871 21.3771209 11.8299912 21.3771209 12.8501838L 21.3771209 17.6726723 26.6228791 17.6726723 26.6228791 12.8501838zM 29.1228791 20.1726723L 18.8771209 20.1726723 18.8771209 12.8501838C 18.8771209 10.3705376 21.170712 8.36038712 24 8.36038712 26.829288 8.36038712 29.1228791 10.3705376 29.1228791 12.8501838L 29.1228791 20.1726723z\"/>\n        </symbol>\n\n        <symbol id=\"console\">\n            <rect x=\"5.03735352\" y=\"5.03735352\" width=\"37.925293\" height=\"37.925293\" rx=\"4\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 13.164202 13.164202 L 24 24 L 13.164202 34.835798\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 24 14 L 35 14\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 29.5 24 L 34.9999999 24\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 24 34 L 35 34\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n        </symbol>\n\n        <symbol id=\"debugger\">\n            <path d=\"M 24.1320008 44.328125 C 32.1512251 44.328125 38.6520901 35.226914 38.6520901 24 C 38.6520901 12.773086 32.1512251 3.671875 24.1320008 3.671875 C 16.1127765 3.671875 9.61191153 12.773086 9.61191153 24 C 9.61191153 35.226914 16.1127765 44.328125 24.1320008 44.328125 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 13.7861328 10.5 L 34.4768075 10.5 L 13.7861328 10.5 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 24.25 11 L 24.25 44.328125\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 34.1640625 37.0680804 L 39.9720982 42.8761161\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 38.5200893 22.25 L 44.328125 22.25\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 9.47991071 22.25 L 3.671875 22.25\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 13.8359375 10.9319196 L 8.02790179 5.12388393\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 34.1640625 10.9319196 L 39.9720982 5.12388393\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 13.972 37.068 L 8.164 42.876\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n        </symbol>\n\n        <symbol id=\"shortcuts\">\n            <path d=\"M 5 35.8242187 C 5 39.7527757 8.1847243 42.9375 12.1132812 42.9375 C 16.0418382 42.9375 19.2265625 39.7527757 19.2265625 35.8242187 L 19.2265625 11.9442883 C 19.2265625 8.1847243 16.0418382 5 12.1132812 5 C 8.1847243 5 5 8.1847243 5 12.1132812 C 5 16.0418382 8.1847243 19.2265625 12.1132812 19.2265625 L 35.8928161 19.2265625 C 39.7527757 19.2265625 42.9375 16.0418382 42.9375 12.1132812 C 42.9375 8.1847243 39.7527757 5 35.8242188 5 C 31.8956618 5 28.7109375 8.1847243 28.7109375 12.1132812 L 28.7109375 35.8190088 C 28.7109375 39.7527757 31.8956618 42.9375 35.8242187 42.9375 C 39.7527757 42.9375 42.9375 39.7527757 42.9375 35.8242188 C 42.9375 31.8956618 39.7527757 28.7109375 35.8242187 28.7109375 L 12.1184912 28.7109375 C 8.1847243 28.7109375 5 31.8956618 5 35.8242187 Z\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\" />\n        </symbol>\n\n        <symbol id=\"timeline\">\n            <path d=\"M 24.625 7.57617187 L 24.625 24.5833333 L 15 24.5833333\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"/>\n            <path d=\"M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 0 37.254834 0 24 C 0 10.745166 10.745166 0 24 0 C 37.254834 0 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z\" fill=\"currentColor\"/>\n        </symbol>\n\n    </defs>\n</svg>            <div class=\"tile featured-tile two-thirds-tile post-8672 post type-post status-publish format-standard hentry category-standards\">\n                <a class=\"tile-link\" href=\"https://webkit.org/blog/8672/on-the-road-to-webrtc-1-0-including-vp8/\">On the Road to WebRTC 1.0, Including VP8</a>\n                <div class=\"background-image\">\n                    <svg viewbox=\"0 0 100 100\">\n                        <use xlink:href=\"#standards\" />\n                    </svg>\n                    <div class=\"featured-image\"></div>\n                    <div class=\"background-vignette\"></div>                </div>\n                <div class=\"tile-content\">\n                    <h1>On the Road to WebRTC 1.0, Including VP8</h1>\n                    <div class=\"summary\">Safari 11 was the first Safari version to support WebRTC.</div>\n                    <p><a href=\"https://webkit.org/blog/8672/on-the-road-to-webrtc-1-0-including-vp8/\" class=\"readmore\">Read more</a></p>\n                </div>\n            </div>\n                    <div class=\"tile third-tile post-8613 post type-post status-publish format-standard hentry category-privacy category-storage\">\n                <a class=\"tile-link\" href=\"https://webkit.org/blog/8613/intelligent-tracking-prevention-2-1/\">Intelligent Tracking Prevention 2.1</a>\n                <div class=\"background-image\">\n                    <svg viewbox=\"0 0 100 100\">\n                        <use xlink:href=\"#privacy\" />\n                    </svg>\n                    <div class=\"featured-image\"></div>\n                                    </div>\n                <div class=\"tile-content\">\n                    <h1>Intelligent Tracking Prevention 2.1</h1>\n                    <div class=\"summary\">Note: Read about past updates to this technology in other blog posts about Intelligent Tracking Prevention, and the Storage Access API.</div>\n                    <p><a href=\"https://webkit.org/blog/8613/intelligent-tracking-prevention-2-1/\" class=\"readmore\">Read more</a></p>\n                </div>\n            </div>\n                    <div class=\"tile third-tile post-8607 post type-post status-publish format-standard hentry category-news\">\n                <a class=\"tile-link\" href=\"https://webkit.org/blog/8607/release-notes-for-safari-technology-preview-76/\">Release Notes for Safari Technology Preview 76</a>\n                <div class=\"background-image\">\n                    <svg viewbox=\"0 0 100 100\">\n                        <use xlink:href=\"#default\" />\n                    </svg>\n                    <div class=\"featured-image\"></div>\n                                    </div>\n                <div class=\"tile-content\">\n                    <h1>Release Notes for Safari Technology Preview 76</h1>\n                    <div class=\"summary\">Safari Technology Preview Release 76 is now available for download for macOS Mojave and macOS High Sierra.</div>\n                    <p><a href=\"https://webkit.org/blog/8607/release-notes-for-safari-technology-preview-76/\" class=\"readmore\">Read more</a></p>\n                </div>\n            </div>\n                    <div class=\"tile third-tile post-8582 post type-post status-publish format-standard hentry category-standards\">\n                <a class=\"tile-link\" href=\"https://webkit.org/blog/8582/intersectionobserver-in-webkit/\">IntersectionObserver in WebKit</a>\n                <div class=\"background-image\">\n                    <svg viewbox=\"0 0 100 100\">\n                        <use xlink:href=\"#standards\" />\n                    </svg>\n                    <div class=\"featured-image\"></div>\n                                    </div>\n                <div class=\"tile-content\">\n                    <h1>IntersectionObserver in WebKit</h1>\n                    <div class=\"summary\">Web authors often need to know when a particular element on a page becomes visible.</div>\n                    <p><a href=\"https://webkit.org/blog/8582/intersectionobserver-in-webkit/\" class=\"readmore\">Read more</a></p>\n                </div>\n            </div>\n                    <div class=\"tile third-tile post-8569 post type-post status-publish format-standard hentry category-news\">\n                <a class=\"tile-link\" href=\"https://webkit.org/blog/8569/removing-legacy-spdy-protocol-support/\">Removing Legacy SPDY Protocol Support</a>\n                <div class=\"background-image\">\n                    <svg viewbox=\"0 0 100 100\">\n                        <use xlink:href=\"#default\" />\n                    </svg>\n                    <div class=\"featured-image\"></div>\n                                    </div>\n                <div class=\"tile-content\">\n                    <h1>Removing Legacy SPDY Protocol Support</h1>\n                    <div class=\"summary\">This is a guest post from Apple&#8217;s CFNetwork team about changes to the URLSession networking framework used by Safari and WebKit on Apple platforms.</div>\n                    <p><a href=\"https://webkit.org/blog/8569/removing-legacy-spdy-protocol-support/\" class=\"readmore\">Read more</a></p>\n                </div>\n            </div>\n        </div>\n\n<div class=\"pagination\">\n<a href=\"https://webkit.org/blog/\" class=\"page-numbers next-button\">More Blog Posts</a>\n</div>\n\n    </div><!--.page-width-->\n</main><!-- #content -->\n\n<footer>\n    <div class=\"page-width\">\n        <nav id=\"footer-nav\" aria-label=\"Footer menu\"><div class=\"menu-footer-menu-container\"><ul id=\"menu-footer-menu\" class=\"menu\"><li id=\"menu-item-7617\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-7617\"><a href=\"https://twitter.com/webkit\">@webkit</a></li>\n<li id=\"menu-item-5365\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-5365\"><a href=\"https://webkit.org/sitemap/\">Site Map</a></li>\n<li id=\"menu-item-4185\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4185\"><a href=\"http://www.apple.com/legal/privacy/\">Privacy Policy</a></li>\n<li id=\"menu-item-4287\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4287\"><a href=\"https://webkit.org/licensing-webkit/\">Licensing WebKit</a></li>\n<li id=\"menu-item-4187\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4187\"><a href=\"https://webkit.org/terms-of-use/\">WebKit and the WebKit logo are trademarks of Apple Inc.</a></li>\n</ul></div></nav>\n    </div>\n</footer>\n\n</div> <!-- .page-layer -->\n<script type='text/javascript' src='https://webkit.org/wp-content/themes/webkit/scripts/global.js?ver=1.0'></script>\n<script type='text/javascript' src='https://webkit.org/wp/wp-includes/js/wp-embed.min.js?ver=5.0.3'></script>\n</body>\n</html>\n<!-- Dynamic page generated in 0.244 seconds. -->\n<!-- Cached page generated by WP-Super-Cache on 2019-03-12 13:10:14 -->\n\n<!-- Compression = gzip -->"
+          },
+          "redirectURL": "",
+          "headersSize": 575,
+          "bodySize": 13664,
+          "_transferSize": 14239
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 1.6499757766723633,
+          "dns": -1,
+          "connect": 47.99997806549072,
+          "ssl": 24.99997615814209,
+          "send": 0.102996826171875,
+          "wait": 35.606980323791504,
+          "receive": 2.201080322265625
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "19",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.325Z",
+        "time": 47.72806167602539,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/style.css?20181220",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "text/css,*/*;q=0.1"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [
+            {
+              "name": "20181220"
+            }
+          ],
+          "headersSize": 442,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "text/css"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=99"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Fri, 08 Feb 2019 00:54:01 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "60432"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"ec10-58157650fc8cb\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 60432,
+            "compression": 0,
+            "mimeType": "text/css",
+            "text": "/*\nTheme Name: WebKit\nTheme URI: http://webkit.org/\nAuthor: The WebKit Team\nAuthor URI: http://webkit.org/\nDescription: Modern, adaptive theme for the WebKit project.\nVersion: 1.0\n*/\n\n:root {\n    --background-color: hsl(203.6, 100%, 12%);\n    --link-color: hsl(200, 100%, 40%);\n    --text-color: hsl(0, 0%, 20%);\n    --text-color-light: hsl(0, 0%, 87%);\n    --text-color-medium: hsl(0, 0%, 33.3%);\n    --text-color-heading: hsl(0, 0%, 26.7%);\n    --text-color-coolgray: hsl(240, 2.3%, 56.7%);\n    --inverse-text-color: hsl(0, 0%, 100%);\n    --inverse-link-color: hsl(206.7, 100%, 70%);\n\n    --content-background-color: hsl(0, 0%, 96.9%);\n    --horizontal-rule-color: hsl(0, 0%, 86.7%);\n\n    --code-background-color: hsl(0, 0%, 94.9%);\n    --code-border-color: hsl(0, 0%, 90.6%);\n    --code-text-color: hsl(0, 0%, 26.7%);\n\n    --note-background-color: hsl(50, 100%, 94%);\n    --note-border-color: hsl(40, 100%, 90%);\n    --note-text-color: hsl(30, 90%, 35%);\n\n    --foreword-background-color: hsl(0, 0%, 94.1%);\n    --foreword-border-color: hsl(0, 0%, 90.2%);\n    --foreword-text-color: hsl(240, 2.3%, 56.7%);\n\n    --input-border-color: hsl(0, 0%, 83.9%);\n    --input-background-color: hsl(0, 0%, 100%);\n    --button-background-color: hsl(0, 0%, 100%);\n\n    --submit-button-background-color: hsl(199.8, 76.4%, 48.2%);\n    --submit-button-background-gradient: linear-gradient(hsl(199.9, 78.2%, 56.9%), hsl(200, 100%, 40%));\n    --submit-button-text-color: hsl(0, 0%, 100%);\n\n    --pagination-border-color: hsla(0, 0%, 0%, 0.07);\n    --pagination-button-shadow: inset hsla(0, 0%, 0%, 0.07) 0 0 0 1px;\n    --pagination-button-text-color: hsl(0, 0%, 100%);\n\n    --screen-reader-text-focus-color: hsl(198.7, 64.9%, 36.9%);\n    --screen-reader-text-border-color: hsla(0, 0%, 0%, 0.6);\n    --screen-reader-text-background-color: hsl(0, 0%, 94.5%);\n    --screen-reader-text-shadow: 0 0 2px 2px hsla(0, 0%, 0%, 0.6);\n\n    --next-router-background-color: hsl(0, 0%, 98%);\n    --previous-router-background-color: hsl(0, 0%, 95.7%);\n    --router-background-hover-color: hsl(0, 0%, 100%);\n    --router-text-color: hsl(0, 0%, 26.7%);\n    --router-text-color-light: hsl(0, 0%, 40%);\n\n    --tile-background-color: hsl(0, 0%, 100%);\n    --tile-border-color: hsla(0, 0%, 0%, 0.1);\n    --tile-subtle-border-shadow: inset hsla(0, 0%, 0%, 0.1) 0 0 0 1px;\n    --tile-subtle-image-border-shadoww: inset hsla(0, 0%, 0%, 0.1) 0 1px 0 1px;\n\n    --tile-default-background-color: hsl(215.3, 7.9%, 42.2%);\n    --tile-background-color-blue: hsl(200, 100%, 40%);\n    --tile-background-color-green: hsl(79.5, 45.3%, 52%);\n    --tile-background-color-violet: hsl(280, 18%, 57.5%);\n    --tile-background-color-rose: hsl(357.1, 39%, 58.8%);\n    --tile-background-color-orange: hsl(37.1, 100%, 37.5%);\n    --tile-background-color-goldenrod: hsl(45.3, 56.5%, 53.1%);\n    --tile-background-color-purplesafari: hsl(276.7, 36.3%, 51.4%);\n    --tile-background-color-amber: hsl(48, 100%, 50%);\n    --tile-background-vignette: linear-gradient(-180deg, hsla(0, 0%, 100%, 0), hsla(0, 0%, 100%, 0.95) 80%, hsla(0, 0%, 100%, 1));\n    --tile-background-vignette-dark: linear-gradient(-180deg, hsla(0, 0%, 0%, 0) 33%, hsla(0, 0%, 0%, 0.85));\n\n    --tag-window-background-color-gray: hsl(0, 0%, 94.9%);\n    --tag-window-vignette: linear-gradient(-180deg, hsla(0, 0%, 94.9%, 0) 25%, hsla(0, 0%, 94.9%, 1) 65%);\n\n    --submenu-background-color: hsla(0, 0%, 100%, 0.95);\n    --submenu-shadow: 0px 3px 20px 0px hsla(0, 0%, 0%, 0.1);\n    --submenu-border-color: hsl(0, 0%, 90.6%);\n    --header-menu-shadow: 0px 5px 5px hsla(0, 0%, 0%, 0.1);\n    --header-menu-background-color: hsla(0, 0%, 100%, 0.8);\n\n    --tile-background-color-amber: hsl(48, 100%, 50%);\n    --tile-background-color-twitter: hsl(197.9, 70.6%, 53.3%);\n    --gray-tile-text-color: hsl(232.8, 100%, 37.5%);\n\n    --article-border-color: hsl(0, 0%, 90.6%);\n    --article-scrollable-border-color: hsl(0, 0%, 80%);\n    --figure-caption-rule-color: hsl(0, 0%, 80%);\n    --toc-border-color: hsl(0, 0%, 83.9%);\n    --table-top-rule-color: hsl(0, 0%, 73.3%);\n    --table-rule-color: hsl(0, 0%, 87.8%);\n    --figure-mattewhite-background-color: hsl(0, 0%, 100%);\n\n    --syntax-color-keyword: hsl(292.5, 100%, 26.7%);\n    --syntax-color-keyword-operator: hsl(357.5, 100%, 33.1%);\n    --syntax-color-builtin: hsl(309.6, 85.8%, 35.9%);\n    --syntax-color-keyword-type: hsl(17.6, 80.4%, 44.1%);\n    --syntax-color-preprocessor: hsl(60, 20%, 50%);\n    --syntax-color-comment: hsl(180, 6.9%, 60.4%);\n    --syntax-color-comment-doc: hsl(186.3, 8.3%, 55.1%);\n    --syntax-color-identifier: hsl(209.6, 71.4%, 38.4%);\n    --syntax-color-string: hsl(70.8, 93%, 22.4%);\n    --syntax-color-escaped: hsl(0, 0%, 66.7%);\n    --syntax-color-number: hsl(194.5, 14.1%, 40.2%);\n    --syntax-color-attribute: hsl(44.8, 53.2%, 33.5%);\n    --syntax-color-attribute-value: hsl(1.4, 79.8%, 42.7%);\n    --syntax-color-operator: hsl(0, 0%, 53.3%);\n    --syntax-color-whitespace-background-color: hsl(0, 0%, 20%);\n    --syntax-color-doctype: hsl(0, 0%, 75.3%);\n    --syntax-color-error-border: hsl(0, 100%, 50%);\n    --syntax-color-property: hsl(295.7, 76.8%, 32.2%);\n    --syntax-color-xml-comment: hsl(120, 100%, 22.7%);\n    --syntax-color-xml-meta: hsl(180, 50%, 40%);\n    --syntax-color-css-property: hsl(309.6, 85.8%, 35.9%);\n    --syntax-color-css-selector: hsl(0, 0%, 0%);\n    --syntax-color-css-number: hsl(248.1, 100%, 40.6%);\n\n    --code-selection-background-color: hsl(212.3, 97.8%, 81.8%);\n}\n\n@media(prefers-color-scheme:dark) {\n    :root {\n        --background-color: hsl(203.6, 100%, 12%);\n        --link-color: hsl(206.7, 100%, 70%);\n        --text-color: hsl(240, 1.3%, 84.5%);\n        --text-color-light: hsl(0, 0%, 33.3%);\n        --text-color-medium: hsl(0, 0%, 51%);\n        --text-color-heading: hsl(120, 100%, 99.8%);\n        --text-color-coolgray: hsl(240, 2.3%, 56.7%);\n        --inverse-text-color: hsl(0, 0%, 100%);\n        --inverse-link-color: hsl(206.7, 100%, 70%);\n\n        --content-background-color: hsl(120, 2%, 9%);\n        --horizontal-rule-color: hsl(0, 0%, 33.3%);\n\n        --code-background-color: hsl(120, 1%, 19.4%);\n        --code-border-color: hsl(0, 0%, 26.7%);\n        --code-text-color: hsl(180, 6.9%, 84.5%);\n\n        --note-background-color: hsl(31.9, 20.5%, 33.1%);\n        --note-border-color: hsl(31.9, 20.5%, 42%);\n        --note-text-color: hsl(48.7, 55.2%, 75.5%);\n\n        --foreword-background-color: hsl(120, 1%, 19.4%);\n        --foreword-border-color: hsl(0, 0%, 26.7%);\n        --foreword-text-color: hsl(120, 1.3%, 55%);\n\n        --input-border-color: hsl(0, 0%, 26.7%);\n        --input-background-color: hsl(0, 0%, 0%);\n        --button-background-color: hsl(120, 2%, 14%);\n\n        --submit-button-background-color: hsl(199.8, 76.4%, 48.2%);\n        --submit-button-background-gradient: linear-gradient(hsl(199.9, 78.2%, 56.9%), hsl(200, 100%, 40%));\n        --submit-button-text-color: hsl(0, 0%, 100%);\n\n        --pagination-border-color: hsla(0, 0%, 100%, 0.1);\n        --pagination-button-shadow: inset hsla(0, 0%, 50%, 0.1) 0 0 0 1px;\n        --pagination-button-text-color: hsl(0, 0%, 100%);\n\n        --screen-reader-text-focus-color: hsl(198.7, 64.9%, 36.9%);\n        --screen-reader-text-border-color: hsla(0, 0%, 0%, 0.6);\n        --screen-reader-text-background-color: hsl(0, 0%, 94.5%);\n        --screen-reader-text-shadow: 0 0 2px 2px hsla(0, 0%, 0%, 0.6);\n\n        --next-router-background-color: hsl(120, 6.7%, 4.9%);\n        --previous-router-background-color: hsl(120, 4%, 8%);\n        --router-background-hover-color: hsl(0, 0%, 0%);\n        --router-text-color: hsl(120, 100%, 99.8%);\n        --router-text-color-light: hsl(30, 1%, 62%);\n\n        --tile-background-color: hsl(120, 2%, 12%);\n        --tile-border-color: hsl(0, 0%, 29%);\n        --tile-subtle-border-shadow: inset hsla(0, 0%, 50%, 0.1) 0 0 0 1px;\n        --tile-subtle-image-border-shadoww: inset hsla(0, 0%, 100%, 0.1) 0 1px 0 1px;\n\n        --tile-default-background-color: hsl(215.3, 7.9%, 42.2%);\n        --tile-background-color-blue: hsl(200, 100%, 40%);\n        --tile-background-color-green: hsl(79.5, 45.3%, 52%);\n        --tile-background-color-violet: hsl(280, 18%, 57.5%);\n        --tile-background-color-rose: hsl(357.1, 39%, 58.8%);\n        --tile-background-color-orange: hsl(37.1, 100%, 37.5%);\n        --tile-background-color-goldenrod: hsl(45.3, 56.5%, 53.1%);\n        --tile-background-color-purplesafari: hsl(276.7, 36.3%, 51.4%);\n        --tile-background-color-amber: hsl(48, 100%, 50%);\n        --tile-background-vignette: linear-gradient(-180deg, hsla(120, 2%, 12%, 0%), hsla(120, 2%, 12%, 0.95) 80%, hsla(120, 2%, 12%, 1));\n        --tile-background-vignette-dark: linear-gradient(-180deg, hsla(0, 0%, 0%, 0) 33%, hsla(0, 0%, 0%, 0.85));\n\n        --tag-window-background-color-gray: hsl(0, 0%, 94.9%);\n        --tag-window-vignette: linear-gradient(-180deg, hsla(0, 0%, 94.9%, 0) 25%, hsla(0, 0%, 94.9%, 1) 65%);\n\n        --submenu-background-color: hsla(0, 0%, 0%, 0.95);\n        --submenu-shadow: 0px 3px 20px 0px hsla(0, 0%, 20%, 0.1);\n        --submenu-border-color: hsl(0, 0%, 15%);\n        --header-menu-shadow: 0px 5px 5px hsla(0, 0%, 0%, 0.1);\n        --header-menu-background-color: hsla(0, 0%, 0%, 0.8);\n\n        --tile-background-color-amber: hsl(48, 100%, 50%);\n        --tile-background-color-twitter: hsl(197.9, 70.6%, 53.3%);\n        --gray-tile-text-color: hsl(232.8, 100%, 37.5%);\n\n        --article-border-color: hsl(120, 4.1%, 19.2%);\n        --article-scrollable-border-color: hsl(120, 4.1%, 19.2%);\n        --figure-caption-rule-color: hsl(0, 0%, 80%);\n        --toc-border-color: hsl(0, 0%, 83.9%);\n        --table-top-rule-color: hsl(0, 0%, 73.3%);\n        --table-rule-color: hsl(0, 0%, 87.8%);\n        --figure-mattewhite-background-color: hsl(0, 0%, 0%);\n\n        --syntax-color-keyword: hsl(299.2, 58.7%, 51.6%);\n        --syntax-color-keyword-operator: hsl(6.8, 69.4%, 57.6%);\n        --syntax-color-builtin: hsl(279.2, 84.3%, 57.6%);\n        --syntax-color-keyword-type: hsl(28.1, 72.2%, 46.5%);\n        --syntax-color-preprocessor: hsl(43.9, 51.4%, 58.8%);\n        --syntax-color-comment: hsl(0, 0%, 51%);\n        --syntax-color-comment-doc: hsl(186.3, 8.3%, 55.1%);\n        --syntax-color-identifier: hsl(210.2, 70.7%, 46.9%);\n        --syntax-color-string: hsl(119.2, 34.3%, 57.6%);\n        --syntax-color-escaped: hsl(0, 0%, 44%);\n        --syntax-color-number: hsl(200, 100%, 40%);\n        --syntax-color-attribute: hsl(43.9, 51.4%, 58.8%);\n        --syntax-color-attribute-value: hsl(28.1, 72.2%, 46.5%);\n        --syntax-color-operator: hsl(180, 6.9%, 60.4%);\n        --syntax-color-whitespace-background-color: hsl(0, 0%, 20%);\n        --syntax-color-doctype: hsl(0, 0%, 42%);\n        --syntax-color-error-border: hsl(0, 100%, 20%);\n        --syntax-color-property: hsl(299.2, 58.7%, 51.6%);\n        --syntax-color-xml-comment: hsl(119.2, 34.3%, 57.6%);\n        --syntax-color-xml-meta: hsl(180, 50%, 40%);\n        --syntax-color-css-property: hsl(309.6, 85.8%, 35.9%);\n        --syntax-color-css-selector: hsl(240, 1.3%, 84.5%);\n        --syntax-color-css-number: hsl(200, 100%, 40%);\n\n        --code-selection-background-color: hsl(214.2, 42.9%, 32.9%);\n    }\n}\n\n/** Resets **/\nhtml, body, div, span, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, samp,\nsmall, strike, strong, sub, sup, tt, var,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details,\nfigure, figcaption, footer, header, hgroup,\nmenu, nav, output, section, summary,\ntime, mark, audio, video {\n    margin: 0;\n    padding: 0;\n    border: 0;\n    font: inherit;\n    vertical-align: baseline;\n}\n/* HTML5 display-role reset for older browsers */\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, menu, nav, section {\n    display: block;\n}\nhtml {\n    font-family: \"SF Hello\", \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif;\n    font-size: 62.5%;\n    font-synthesis: none;\n}\nbody {\n    font-size: 1.7rem;\n    font-weight: 400;\n    line-height: 1.52947;\n    letter-spacing: -0.021rem;\n    background-color: hsl(203.6, 100%, 12%);\n    background-color: var(--background-color);\n    color: hsl(0, 0%, 20%);\n    color: var(--text-color);\n}\nol, ul {\n    list-style: none;\n}\ndl {\n    margin: 2rem 0;\n}\ndt {\n    font-weight: bold;\n}\ndd {\n    margin: 0 3rem;\n}\nblockquote, q {\n    quotes: none;\n}\nblockquote:before, blockquote:after,\nq:before, q:after {\n    content: '';\n    content: none;\n}\ntable {\n    border-collapse: collapse;\n    border-spacing: 0;\n}\np:empty {\n    display: none;\n}\na {\n    text-decoration: none;\n    transition: color 500ms cubic-bezier(0.190, 1.000, 0.220, 1.000); /* ease-out-exponential */\n}\na:hover {\n    text-decoration: underline;\n}\na,\na > code,\na[name]:hover {\n    color: hsl(200, 100%, 40%);\n    color: var(--link-color);\n}\n\nh1 a:hover {\n    text-decoration: none;\n}\nhr {\n    border: none;\n    border-bottom: 1px solid hsl(0, 0%, 86.7%);\n    border-bottom-color: var(--horizontal-rule-color);\n}\nstrong {\n    font-weight: 600;\n}\nem {\n    font-style: italic;\n    font-weight: 300;\n}\nsup {\n    vertical-align: super;\n    font-size: smaller;\n    line-height: 1;\n}\ncode {\n    font-family: \"SF Mono\", \"Menlo\", monospace;\n    font-size: 80%;\n    padding: 0 0.5rem;\n    border-radius: 2px;\n    border: 1px solid hsl(0, 0%, 90.6%);\n    border-color: var(--code-border-color);\n    background-color: hsl(0, 0%, 94.9%);\n    background-color: var(--code-background-color);\n    color: hsl(0, 0%, 26.7%);\n    color: var(--code-text-color);\n}\n\nmain {\n    background-color: hsl(0, 0%, 96.9%);\n    background-color: var(--content-background-color);\n}\n\n/** Accessibility Helpers **/\na[name] {\n    display: inline-block;\n    position: relative;\n    top: -3rem;\n    color: hsl(0, 0%, 86.7%);\n    color: var(--text-color-light);\n    width: 0;\n    text-decoration: none;\n}\n\np > a[name]::before {\n    content: \"#\";\n    margin-left: -1.7rem;\n    position: relative;\n    top: 3rem;\n    color: hsl(240, 2.3%, 56.7%);\n    color: var(--text-color-coolgray);\n    transition: color 500ms cubic-bezier(0.190, 1.000, 0.220, 1.000), opacity 500ms ease-in; /* ease-out-exponential */\n    opacity: 0.3;\n}\n\na[name]:hover {\n    text-decoration: none;\n}\n\na[name]:hover::before {\n    color: hsl(200, 100%, 40%);\n    color: var(--link-color);\n}\n\np:hover > a[name]::before {\n    opacity: 1;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n    text-rendering: optimizeLegibility;\n}\n\nh1 a[name],\nh2 a[name],\nh3 a[name],\nh4 a[name],\nh5 a[name],\nh6 a[name] {\n    display: block;\n    visibility: hidden;\n}\n\ninput[type=text] {\n    display: inline-block;\n    box-sizing: border-box;\n    vertical-align: top;\n    height: 4.2rem;\n    padding-top: 3px;\n    margin-bottom: 3rem;\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n    text-align: left;\n    border-radius: 4px;\n    border: 1px solid hsl(0, 0%, 83.9%);\n    border-color: var(--input-border-color);\n    background-color: hsl(0, 0%, 100%);\n    background-color: var(--input-background-color);\n    background-clip: padding-box;\n    color: hsl(0, 0%, 20%);\n    color: var(--text-color);\n    font-family: \"SF Hello\", \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif;\n    font-weight: 400;\n    font-size: 2rem;\n    line-height: 1.33333;\n    letter-spacing: normal;\n}\n\ninput[type=submit] {\n    background-color: hsl(199.8, 76.4%, 48.2%);\n    background-color: var(--submit-button-background-color);\n    background-image: linear-gradient(hsl(199.9, 78.2%, 56.9%), hsl(200, 100%, 40%));\n    background-image: var(--submit-button-background-gradient);\n    border-radius: 4px;\n    color: white;\n    cursor: pointer;\n    font-size: 1.5rem;\n    font-weight: 500;\n    text-align: center;\n    border: 0;\n}\n\n.admin-bar a[name] {\n    top: calc(-32px - 3rem);\n}\n\n.admin-bar p > a[name]::before {\n    top: calc(32px + 3rem);\n}\n\n.screen-reader-text {\n    clip: rect(1px, 1px, 1px, 1px);\n    position: absolute !important;\n    height: 1px;\n    width: 1px;\n    overflow: hidden;\n}\n\n.screen-reader-text:focus {\n    background-color: hsl(0, 0%, 94.5%);\n    background-color: var(--screen-reader-text-background-color);\n    box-shadow: 0 0 2px 2px hsla(0, 0%, 0%, 0.6);\n    box-shadow: var(--screen-reader-text-shadow);\n    color: hsl(198.7, 64.9%, 36.9%);\n    color: var(--screen-reader-text-focus-color);\n    border-radius: 3px;\n    clip: auto !important;\n    display: block;\n    font-size: 14px;\n    font-size: 0.875rem;\n    font-weight: bold;\n    height: auto;\n    left: 5px;\n    line-height: normal;\n    padding: 15px 23px 14px;\n    text-decoration: none;\n    top: 5px;\n    width: auto;\n    z-index: 100000; /* Above WP toolbar. */\n}\n\n/** Page Layout **/\n.page-width {\n    max-width: 1140px;\n    margin: 0 auto;\n}\n\n/** Header **/\nheader {\n    overflow: visible;\n    width: 100vw;\n    max-width: 100%;\n    padding-top: 1.5rem;\n    margin: 0;\n    position: relative;\n    z-index: 500;\n}\n\n.home header {\n    background-color: transparent;\n    transition: background 500ms ease-out, border 250ms ease-out;\n}\n\n@supports ( -webkit-backdrop-filter: blur(10px) ) {\n\n    .home header {\n        background-color: transparent;\n        backdrop-filter: blur(0px);\n        -webkit-backdrop-filter: blur(0px);\n    }\n\n    .sub-menu-layer {\n        backdrop-filter: blur(10px);\n        -webkit-backdrop-filter: blur(10px);\n    }\n}\n\n.nextrouter .link,\na.readmore {\n    background: url('images/chevron.svg') right no-repeat;\n    background-position-y: 0.6rem;\n    background-size: 0.5rem;\n    padding-right: 1rem;\n}\n\na.download {\n    background: url('images/download.svg') right no-repeat;\n    padding-right: 4rem;\n}\n\n/** Pagination **/\n.pagination {\n    text-align: center;\n    margin: 3rem auto 0;\n}\n\n.pagination::after {\n    content: ' ';\n    display: table;\n    padding-bottom: 3rem;\n}\n\n.pagination .page-numbers,\n.pagination .menu-item a {\n    display: inline-block;\n    padding: 0.3rem 1rem 0.5rem;\n    background-color: hsl(0, 0%, 100%);\n    background-color: var(--button-background-color);\n    border-radius: 4px;\n    box-shadow: inset hsla(0, 0%, 0%, 0.07) 0 0 0 1px;\n    box-shadow: var(--pagination-button-shadow);\n    min-height: 2rem;\n    font-size: 1.7rem;\n    line-height: 1.29412;\n    font-weight: 400;\n    letter-spacing: -0.021em;\n}\n\n.pagination .menu-item a {\n    box-shadow: none;\n    border: 1px solid hsla(0, 0%, 0%, 0.07);\n    border-color: var(--pagination-border-color);\n}\n\n.pagination .page-numbers:not(.current, .dots):hover {\n    text-decoration: none;\n    background-color: hsl(200, 100%, 40%);\n    background-color: var(--link-color);\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n}\n\n.pagination .dots,\n.pagination .page-numbers.current {\n    background-color: transparent;\n    box-shadow: none;\n}\n\n.pagination .prev-post,\n.pagination .next-post {\n    min-width: 25%;\n}\n\n.pagination .prev-post {\n    text-align: right;\n}\n\n.pagination .next-post {\n    text-align: left;\n}\n\n.pagination .prev-post span,\n.pagination .next-post span {\n    display: block;\n    font-size: 1.4rem;\n    font-weight: normal;\n}\n\n.connected.pagination .menu-item {\n    display: table-cell;\n}\n\n.connected.pagination .menu-item:hover a {\n    background-color: hsl(0, 0%, 98%);\n    background-color: var(--next-router-background-color);\n    box-shadow: hsla(206.7, 100%, 70%, 0.3) 0 0 5px 0px;\n    text-decoration: none;\n    border-radius: 4px;\n}\n\n.connected.pagination .menu-item:first-child a {\n    border-top-right-radius: 0px;\n    border-bottom-right-radius: 0px;\n    border-right-width: 0px;\n}\n.connected.pagination .menu-item:last-child a {\n    border-top-left-radius: 0px;\n    border-bottom-left-radius: 0px;\n}\n\n.connected.pagination .menu-item.current-menu-item a,\n.connected.pagination .menu-item.current-menu-item:hover a\n.connected.pagination .menu-item.current-menu-item a:hover {\n    background-color: transparent;\n    color: var(--text-color);\n    box-shadow: none;\n    text-decoration: none;\n}\n\n.menu-feature-pages-container {\n    display: inline-block;\n}\n\n/* Front page next button */\n.pagination .next-button {\n    display: inline-block;\n    min-width: calc(33.33% - 3rem);\n    padding: 0.5rem 1rem 0.7rem;\n}\n\n.nextrouter {\n    position: relative;\n    background-color: hsl(0, 0%, 98%);\n    background-color: var(--next-router-background-color);\n    padding: 0;\n    width: 100vw;\n    left: 50%;\n    transform: translateX(-50%);\n}\n\n.nextrouter.previous {\n    text-align: right;\n    background-color: hsl(0, 0%, 95.7%);\n    background-color: var(--previous-router-background-color);\n}\n\n.nextrouter:hover,\n.nextrouter.previous:hover {\n    background-color: hsl(0, 0%, 100%);\n    background-color: var(--router-background-hover-color);\n    transition: background-color 300ms ease-out;\n}\n\n.nextrouter .bodycopy {\n    max-width: 1140px;\n    margin: 0 auto;\n}\n\n.nextrouter a {\n    display: block;\n    cursor: pointer;\n    color: hsl(0, 0%, 26.7%);\n    color: var(--router-text-color);\n    width: 66%;\n    margin: 0 auto;\n}\n\n.nextrouter a:hover {\n    text-decoration: none;\n}\n\n.nextrouter-copy {\n    padding: 10rem 0 9.5rem 0;\n    font-size: 3.2rem;\n    font-weight: 500;\n    line-height: 1.09375;\n    letter-spacing: 0.011rem;\n}\n\n.nextrouter .label {\n    font-size: 2.2rem;\n    line-height: 1;\n    font-weight: 300;\n    letter-spacing: 0.016rem;\n    color: hsl(0, 0%, 40%);\n    color: var(--router-text-color-light);\n    display: block;\n    margin-bottom: 1.8rem;\n}\n\n.nextrouter .title {\n    display: block;\n}\n\n.nextrouter .link {\n    clear: left;\n    display: inline-block;\n    font-size: 1.7rem;\n    font-weight: 400;\n    line-height: 1.52947;\n    letter-spacing: -0.021rem;\n    color: hsl(200, 100%, 40%);\n    color: var(--link-color);\n    background-position-y: 1rem;\n}\n\n.nextrouter a:hover .link {\n    text-decoration: underline;\n}\n\n/** Footer **/\nfooter {\n    content: \"\";\n    display: table;\n    clear: both;\n    width: 100%;\n    padding-bottom: 1.65rem;\n    box-sizing: border-box;\n}\n\nfooter .menu {\n    font-size: 1.3rem;\n}\n\n/** Tiles **/\n.tiles {\n    font-size: 0;\n    display: -webkit-flex;\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: space-between;\n    box-sizing: border-box;\n    width: 100%;\n}\n\n.tile {\n    background-color: hsl(120, 2%, 9%);\n    background-color: var(--tile-background-color);\n    box-shadow: inset hsla(0, 0%, 0%, 0.1) 0 0 0 1px;\n    box-shadow: var(--tile-subtle-border-shadow);\n    display: block;\n    margin: 0 0 15px;\n    position: relative;\n    vertical-align: top;\n    box-sizing: border-box;\n    overflow: hidden;\n}\n\n.tile.spacer {\n    background: none;\n    box-shadow: none;\n}\n\n.tile-link,\n.tile-link:hover {\n    text-decoration: none;\n    display: block;\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    font-size: 0;\n    z-index: 1;\n}\n\n.third-tile {\n    width: calc(33.33% - 10px);\n}\n\n.two-thirds-tile {\n    width: calc(66.66% - 5px);\n}\n\n.featured-tile {\n    padding: 0;\n}\n\n#icons {\n    display: none;\n}\n\n.tile .background-image {\n    position: relative;\n    margin-top: -1px;\n    height: 0;\n    padding-bottom: 80%;\n    overflow: hidden;\n    width: 100%;\n    background-color: hsl(215.3, 7.9%, 42.2%);\n    background-color: var(--tile-default-background-color);\n}\n\n.tile .background-image svg {\n    position: relative;\n    top: -12%;\n    width: 209%;\n    height: auto;\n    color: hsl(120, 2%, 9%);\n    color: var(--tile-background-color);\n}\n\n.tile .background-image.has-featured-image {\n    transition: filter 1s ease-in;\n    -webkit-filter: saturate(0);\n            filter: saturate(0);\n}\n\n.tile:not(.has-post-thumbnail) .featured-image {\n    display: none;\n}\n\n.tile.category-web-inspector svg {\n    background-color: hsl(200, 100%, 40%);\n    background-color: var(--tile-background-color-blue);\n}\n\n.tile.category-performance svg {\n    background-color: hsl(79.5, 45.3%, 52%);\n    background-color: var(--tile-background-color-green);\n}\n\n.tile.category-javascript svg {\n    background-color: hsl(280, 18%, 57.5%);\n    background-color: var(--tile-background-color-violet);\n}\n\n.tile.category-css svg {\n    background-color: hsl(357.1, 39%, 58.8%);\n    background-color: var(--tile-background-color-rose);\n}\n\n.tile.category-standards svg {\n    top: -20%;\n    background-color: hsl(37.1, 100%, 37.5%);\n    background-color: var(--tile-background-color-orange);\n}\n\n.tile.category-contributing svg {\n    background-color: hsl(45.3, 56.5%, 53.1%);\n    background-color: var(--tile-background-color-goldenrod);\n}\n\n.tile.category-storage svg {\n    background-color: hsl(280, 18%, 57.5%);\n    background-color: var(--tile-background-color-violet);\n}\n\n.tile.category-layout svg {\n    background-color: hsl(357.1, 39%, 58.8%);\n    background-color: var(--tile-background-color-rose);\n}\n\n.tile.category-safari-technology-preview svg {\n    background-color: hsl(276.7, 36.3%, 51.4%);\n    background-color: var(--tile-background-color-purplesafari);\n}\n\n.tile.category-accessibility svg {\n    top: -8%;\n    background-color: hsl(200, 100%, 40%);\n    background-color: var(--tile-background-color-blue);\n}\n\n.tile.category-security svg {\n    background-color: hsl(45.3, 56.5%, 53.1%);\n    background-color: var(--tile-background-color-goldenrod);\n}\n\n.tile.category-privacy svg {\n    background-color: hsl(45.3, 56.5%, 53.1%);\n    background-color: var(--tile-background-color-goldenrod);\n}\n\n.tile .background-image.loaded {\n    background: none;\n    border-bottom: 1px solid hsla(0, 0%, 0%, 0.1);\n    border-color: var(--tile-border-color);\n    -webkit-filter: saturate(1);\n            filter: saturate(1);\n}\n\n.tile .featured-image::before {\n    padding-bottom: 80%;\n    content: '';\n    display: block;\n}\n\n.tile .featured-image {\n    position: relative;\n    max-height: 450px;\n    background-size: cover;\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n\n    opacity: 0;\n    transition: opacity 0.4s ease-in;\n}\n\n.tile:not(.has-post-thumbnail) .background-image,\n.tile .background-vignette {\n    box-shadow: inset hsla(0, 0%, 0%, 0.1) 0 1px 0 1px;\n    box-shadow: var(--tile-subtle-image-border-shadow);\n}\n\n.has-post-thumbnail .background-image {\n    filter: saturate(0);\n    -webkit-filter: saturate(0);\n    opacity: 0.1;\n}\n\n.has-post-thumbnail .background-image.loaded,\n.tile .background-image.loaded .featured-image {\n    opacity: 1;\n}\n\n.featured-tile .background-image {\n    padding-bottom: 60%;\n    margin-bottom: 0;\n}\n\n.tile .tile-content {\n    font-size: 1.6rem;\n    line-height: 3rem;\n    max-width: 100%;\n    box-sizing: border-box;\n    padding: 2rem;\n}\n\n.featured-tile .tile-content {\n    padding: 0 24px;\n    box-sizing: border-box;\n    position: absolute;\n    transform: none;\n    bottom: 15px;\n    top: auto;\n}\n\n.background-vignette {\n    width: 100%;\n    padding-bottom: 60%;\n    position: absolute;\n    top:0;\n    background-image: linear-gradient(-180deg, hsla(0, 0%, 100%, 0), hsla(0, 0%, 100%, 0.95) 80%, hsla(0, 0%, 100%, 1));\n    background-image: var(--tile-background-vignette);\n}\n\n.tag-window .background-image {\n    background-color: hsl(0, 0%, 94.9%);\n    background-color: var(--tag-window-background-color-gray);\n}\n\n.tag-window .background-vignette {\n    background-image: linear-gradient(-180deg, hsla(0, 0%, 94.9%, 0) 25%, hsla(0, 0%, 94.9%, 1) 65%);\n    background-image: var(--tag-window-vignette);\n}\n\n.featured-tile.tag-dark.tile {\n    background: black;\n}\n\n.featured-tile.tag-dark .background-vignette {\n    background-image: linear-gradient(-180deg, hsla(0, 0%, 0%, 0) 33%, hsla(0, 0%, 0%, 0.85));\n    background-image: var(--tile-background-vignette-dark);\n}\n\n.featured-tile.tag-dark .tile-content {\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n}\n\n.featured-tile.tag-dark .tile-content a {\n    color: hsl(206.7, 100%, 70%);\n    color: var(--inverse-link-color);\n}\n\n.tag-transparent:not(.featured-tile) .featured-image {\n    box-shadow: none;\n    background-size: contain;\n}\n\n.tag-transparent:not(.featured-tile) .background-image.loaded {\n    border-bottom: none;\n}\n\n.tile-content p {\n    margin: 0;\n}\n\n.tile h1 {\n    font-size: 2.4rem;\n    line-height: 1.20849;\n    font-weight: 500;\n    letter-spacing: 0.015rem;\n    text-align: left;\n    white-space: no-wrap;\n}\n\n.tile h2 {\n    font-size: 2.4rem;\n    line-height: 1.20849;\n    font-weight: 200;\n    text-align: inherit;\n}\n\n.tile .summary,\n.tile p {\n    margin-top: 1.65rem;\n}\n\n.icon-tile {\n    text-align: center;\n    font-size: 2rem;\n}\n\n.icon-tile h2 + p {\n    font-weight: 200;\n    margin-bottom: 1rem;\n}\n\n.icon-tile .icon {\n    position: relative;\n    background: url('images/compass.svg') no-repeat;\n    background-position: 50% 50%;\n    margin: 0 auto 3rem;\n    padding: 40%;\n}\n\n.icon-tile.download .icon {\n    background-image: url('images/download.svg');\n}\n\n.icon-tile.developer .icon {\n    background-image: url('images/developer.svg');\n}\n\n.icon-tile,\n.icon-tile a {\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n}\n\n.gray-tile {\n    background: linear-gradient(rgb(40, 40, 40), rgb(74, 74, 74));\n    background-image: var(--tile-background-color-gray);\n}\n.gray-tile {\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n}\n.gray-tile a {\n    color: hsl(232.8, 100%, 37.5%);\n    color: var(--gray-tile-text-color);\n}\n\n\n.amber-tile {\n    background-color: hsl(48, 100%, 50%);\n    background-color: var(--tile-background-color-amber);\n}\n.blue-tile {\n    background-color: hsl(200, 100%, 40%);\n    background-color: var(--tile-background-color-blue);\n}\n\n.twitter-tile {\n    background-color: hsl(197.9, 70.6%, 53.3%);\n    background-color: var(--tile-background-color-twitter);\n}\n\n.twitter-tile, .twitter-tile a {\n    color: white;\n}\n\n.tile-content a {\n    position: relative;\n    z-index: 200;\n}\n\n.twitter-tile .tile-content {\n    position: relative;\n    box-sizing: border-box;\n    font-size: 2rem;\n    text-align: center;\n}\n\n.twitter-tile.text-only {\n    display: -webkit-flex;\n    display: flex;\n    justify-content: center;\n    text-align: left;\n}\n\n.twitter-tile .media {\n    text-align: center;\n}\n\n.twitter-tile.text-only .tile-content {\n    font-size: 2.5rem;\n    font-weight: 400;\n    line-height: 3rem;\n    align-self: center;\n    padding-bottom: 6rem;\n}\n\n.twitter-tile img {\n    display: inline-block;\n    width: auto;\n    height: auto;\n    max-width: 100%;\n    max-height: 256px;\n}\n\n.twitter-controls {\n    padding: 0 1.5rem;\n    box-sizing: border-box;\n    width: 100%;\n    font-size: 1.5rem;\n    line-height: 3rem;\n    text-align: center;\n    font-weight: 600;\n    position: absolute;\n    left: 0;\n    bottom: 15px;\n    z-index: 200;\n    display: -webkit-flex;\n    display: flex;\n    -webkit-flex-wrap: wrap;\n    flex-wrap: wrap;\n    -webkit-justify-content: space-between;\n    justify-content: space-between;\n}\n\n.twitter-controls li {\n    display: inline-block;\n    margin: 0 1.3rem;\n}\n\n.twitter-controls a {\n    opacity: 0.66;\n    transition: opacity 300ms ease-out;\n}\n.twitter-controls a:hover {\n    opacity: 1;\n    text-decoration: none;\n}\n\n/** Twitter Icons **/\n\n.twitter-icon {\n    background: url('images/twitter.svg') no-repeat;\n    background-size: cover;\n}\n\n.icon.twitter-icon {\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n    position: relative;\n    margin: 3rem auto 3rem;\n    width: 1px;\n    padding: 33%;\n    opacity: 0.33;\n}\n\n.twitter-tile h2 {\n    text-align: center;\n}\n\n.twitter-controls .twitter-icon {\n    text-indent: -9999em;\n    display: inline-block;\n    width: 2.5rem;\n    height: 2.5rem;\n}\n\n.twitter-icon.reply-icon {\n    background-position-y: 33%;\n}\n\n.twitter-icon.retweet-icon {\n    background-position-y: 66%;\n}\n\n.twitter-icon.favorite-icon {\n    background-position-y: 99%;\n}\n\n/** Code Syntax Highlighting **/\npre {\n    width: calc(100% + 6rem);\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    background-color: hsl(0, 0%, 94.9%);\n    background-color: var(--code-background-color);\n    border: 1px solid hsl(0, 0%, 90.6%);\n    border-color: var(--code-border-color);\n    border-radius: 2px;\n    box-sizing: border-box;\n    padding: 3rem;\n    margin-left: -3rem;\n}\n\ncode {\n    color: hsl(0, 0%, 26.7%);\n    color: var(--code-text-color);\n    font-size: 1.6rem;\n    line-height: 2.5rem;\n}\n\npre code {\n    border: none;\n    padding: 0;\n}\n\ncode .keyword,\ncode.html .tag {\n    color: hsl(292.5, 100%, 26.7%);\n    color: var(--syntax-color-keyword);\n}\ncode .keyword.builtin,\ncode .keyword.literal {\n    color: hsl(309.6, 85.8%, 35.9%);\n    color: var(--syntax-color-builtin);\n}\ncode .keyword.type {\n    color: hsl(17.6, 80.4%, 44.1%);\n    color: var(--syntax-color-keyword-type);\n}\ncode .preprocessor {\n    color: hsl(60, 20%, 50%);\n    color: var(--syntax-color-preprocessor);\n}\ncode .comment {\n    color: hsl(180, 6.9%, 60.4%);\n    color: var(--syntax-color-comment);\n    float: none;\n    display: inline;\n}\ncode .comment .doc {\n    color: hsl(186.3, 8.3%, 55.1%);\n    color: var(--syntax-color-comment-doc);\n    font-weight: bold;\n}\ncode .identifier {\n    color: hsl(209.6, 71.4%, 38.4%);\n    color: var(--syntax-color-identifier);\n}\ncode .string,\ncode .char {\n    color: hsl(70.8, 93%, 22.4%);\n    color: var(--syntax-color-string);\n}\ncode .escaped {\n    color: hsl(0, 0%, 66.7%);\n    color: var(--syntax-color-escaped);\n}\ncode .number,\ncode .tag {\n    color: hsl(194.5, 14.1%, 40.2%);\n    color: var(--syntax-color-number);\n}\ncode .regex,\ncode .attribute {\n    color: hsl(44.8, 53.2%, 33.5%);\n    color: var(--syntax-color-attribute);\n}\ncode .attribute.value {\n    color: hsl(1.4, 79.8%, 42.7%);\n    color: var(--syntax-color-attribute-value);\n}\ncode .operator {\n    color: hsl(0, 0%, 53.3%);\n    color: var(--syntax-color-operator);\n}\ncode .keyword.operator {\n    color: hsl(357.5, 100%, 33.1%);\n    color: var(--syntax-color-keyword-operator);\n}\ncode .whitespace {\n    background-color: hsl(0, 0%, 20%);\n    background-color: var(--syntax-color-whitespace-background-color);\n}\ncode .error {\n    border-bottom: 1px solid hsl(0, 100%, 50%);\n    border-color: var(--syntax-color-error-border);\n}\ncode .doctype {\n    color: hsl(0, 0%, 75.3%);\n    color: var(--syntax-color-doctype);\n}\ncode .property {\n    color: hsl(295.7, 76.8%, 32.2%);\n    color: var(--syntax-color-property);\n}\n\ncode.xml .comment,\ncode.html .comment {\n    color: hsl(120, 100%, 22.7%);\n    color: var(--syntax-color-xml-comment);\n}\n\ncode.xml .preprocessor .keyword {\n    color: hsl(60, 20%, 50%);\n    color: var(--syntax-color-preprocessor);\n}\ncode.xml .meta,\ncode.xml .meta .keyword {\n    color: hsl(180, 50%, 40%);\n    color: var(--syntax-color-xml-meta);\n}\n\ncode.cpp .preprocessor .identifier {\n    color: hsl(60, 20%, 50%);\n    color: var(--syntax-color-preprocessor);\n}\n\npre::-moz-selection,\npre span::-moz-selection {\n    background-color: hsl(212.3, 97.8%, 81.8%);\n    background-color: var(--code-selection-background-color);\n}\n\npre::selection, pre span::selection {\n    background-color: hsl(212.3, 97.8%, 81.8%);\n    background-color: var(--code-selection-background-color);\n}\n\ncode.syntax { white-space: normal; }\ncode.syntax .newlines { white-space: pre; display: block; }\n\ncode.css .attribute,\ncode.css .identifier,\ncode.css .preprocessor {\n    color: hsl(309.6, 85.8%, 35.9%);\n    color: var(--syntax-color-css-property);\n}\n\ncode.css .keyword {\n    color: hsl(0, 0%, 0%);\n    color: var(--syntax-color-css-selector);\n}\ncode.css .number {\n    color: hsl(248.1, 100%, 40.6%);\n    color: var(--syntax-color-css-number);\n}\n\n/** Post Typography **/\n\nmain {\n    width: 100vw;\n    max-width: 100%;\n    overflow-x: hidden;\n    box-sizing: border-box;\n    padding: 3rem 0 0;\n}\n\narticle {\n    padding-bottom: 3rem;\n}\n\narticle::after {\n    clear: both;\n    content: ' ';\n    display: table;\n}\n\narticle h1,\narticle h1 a {\n    margin: 0 auto 3rem;\n    font-size: 5.6rem;\n    font-weight: 500;\n    letter-spacing: 0.004rem;\n    line-height: 1.10746;\n    text-align: center;\n    text-decoration: none;\n    color: hsl(0, 0%, 26.7%);\n    color: var(--text-color-heading);\n}\n\narticle h2 {\n    font-size: 3.2rem;\n    line-height: 1.09375;\n    font-weight: 500;\n    letter-spacing: -0.011rem;\n    margin: 4rem 0 1rem;\n}\n\narticle h3 {\n    font-size: 2.4rem;\n    line-height: 1.09375;\n    font-weight: 500;\n    letter-spacing: -0.011rem;\n}\n\narticle h4 {\n    font-size: 2.2rem;\n    line-height: 1.09375;\n    font-weight: 500;\n}\n\narticle h5 {\n    font-size: 2rem;\n    line-height: 1.09375;\n    font-weight: 500;\n}\n\narticle h6 {\n    font-size: 1.7rem;\n    line-height: 1.09375;\n    font-weight: 500;\n}\n\narticle h3,\narticle h4,\narticle h5,\narticle h6 {\n    margin-bottom: 0.5rem;\n}\n\narticle h2 + h3,\narticle h3 + h4,\narticle h4 + h5,\narticle h5 + h6 {\n    margin-top: 0;\n}\n\narticle p,\narticle div > img,\narticle pre,\narticle hr {\n    margin-bottom: 3rem;\n}\n\narticle .byline p {\n    font-size: 1.5rem;\n    line-height: 3rem;\n    margin-bottom: 0;\n    color: hsl(240, 2.3%, 56.7%);\n    color: var(--text-color-coolgray);\n}\n\narticle .byline .date {\n    font-weight: 900;\n}\n\narticle .byline .author {\n    white-space: nowrap;\n\n}\n\narticle table {\n    font-size: 1.6rem;\n    border-collapse: collapse;\n    border-spacing: 0;\n    margin: 3rem 0;\n    width: 100%;\n}\n\narticle thead, article tfoot {\n    border-top: 1px solid hsl(0, 0%, 73.3%);\n    border-top-color: var(--table-top-rule-color);\n    border-bottom: 1px solid hsl(0, 0%, 87.8%);\n    border-bottom-color: var(--table-rule-color);\n}\n\narticle tr {\n    border-top: 1px solid hsl(0, 0%, 87.8%);\n    border-color: var(--table-rule-color);;\n}\n\narticle tr:first-child {\n    border-top: 0 none;\n}\n\narticle th {\n    font-weight: bold;\n    vertical-align: bottom;\n    text-align: left;\n\n}\narticle td, th {\n    padding: 1.754386%;\n}\narticle th:first-child {\n    padding-left: 0;\n}\n\narticle ol,\narticle ul {\n    padding-left: 3rem;\n    margin: 3rem 0;\n}\n\narticle ol {\n    list-style-type: decimal;\n}\n\narticle ul {\n    list-style-type: square;\n}\n\narticle ul ul,\narticle ul ol,\narticle ol ul,\narticle ol ol {\n    margin-top: 0;\n    margin-bottom: 0;\n}\n\narticle blockquote {\n    width: 100vw;\n    height: auto;\n    padding: 0 3rem;\n    left: 50%;\n    position: relative;\n    margin-left: -50vw;\n    box-sizing: border-box;\n    font-weight: 200;\n    font-size: 3rem;\n    line-height: 4.2rem;\n    text-align: center;\n    color: hsl(240, 2.3%, 56.7%);\n    color: var(--text-color-coolgray);\n}\narticle blockquote > * {\n    max-width: 1140px;\n    margin-left: auto;\n    margin-right: auto;\n}\n\narticle blockquote:first-child {\n    width: 100%;\n    text-align: left;\n    margin: 0 auto;\n    left: 0;\n    padding: 0;\n}\n\n.post .bodycopy > p:last-child:after {\n    content: \" \\220E\"; /* Tombstone */\n    color: hsl(0, 0%, 33.3%);\n    color: var(--text-color-medium);\n}\n\narticle div.note {\n    margin-left: -3rem;\n    margin-right: -3rem;\n    padding: 3rem;\n    background-color: hsl(50, 100%, 94%);\n    background-color: var(--note-background-color);\n    border: 1px solid hsl(40, 100%, 90%);\n    border-color: var(--note-border-color);\n    color: hsl(30, 90%, 35%);\n    color: var(--note-text-color);\n    border-radius: 3px;\n    margin-bottom: 3rem;\n    box-sizing: normal;\n}\n\narticle .foreword {\n    padding: 1.6rem 2.2rem 1.6rem;\n    line-height: 2.6rem;\n    background-color: hsl(0, 0%, 94.1%);\n    background-color: var(--foreword-background-color);\n    border: 1px solid hsl(0, 0%, 90.2%);\n    border-color: var(--foreword-border-color);\n    color: hsl(240, 2.3%, 56.7%);\n    color: var(--foreword-text-color);\n    border-radius: 3px;\n    margin-bottom: 3rem;\n    box-sizing: normal;\n    font-size: 1.6rem;\n    font-style: italic;\n}\n\narticle .two-columns {\n    columns: 2;\n    column-gap: 6rem;\n    margin: 3rem 0;\n}\n\narticle .two-columns h2,\narticle .two-columns h3,\narticle .two-columns h4,\narticle .two-columns h5,\narticle .two-columns h6 {\n    break-after: avoid-column; /* https://bugs.webkit.org/show_bug.cgi?id=148814 */\n}\n\narticle .two-columns p {\n    break-inside: avoid-column;\n}\n\n/** Post Layout **/\n\narticle .byline {\n    float: left;\n    width: 191px;\n    text-align: right;\n    padding-right: 4rem;\n    box-sizing: border-box;\n}\n\narticle .bodycopy {\n    width: 66%;\n    margin: 0 auto;\n    position: relative;\n}\n\narticle .aligncenter .wp-caption-text {\n    right: -50%;\n}\n\narticle .alignleft {\n    float: left;\n    margin: 1.5rem 1.5rem 1.5rem 0;\n}\n\narticle .aligncenter {\n    clear: both;\n    display: block;\n    margin: 0 auto 3rem;\n}\n\narticle div.aligncenter {\n    position: relative;\n    float: right;\n    right: 50%;\n}\n\narticle div.aligncenter img {\n    position: relative;\n    right: -50%;\n}\n\narticle .alignright {\n    float: right;\n    margin: 1.5rem 0 1.5rem 1.5rem;\n}\n\narticle .alignnone {\n    display: block;\n    float: none;\n}\n\narticle .alignnone.size-full {\n    width: 100vw;\n    height: auto;\n    left: 50%;\n    position: relative;\n    -webkit-transform: translate(-50vw, 0);\n    transform: translate(-50vw, 0);\n}\n\narticle .abovetitle {\n    margin-top: -0.4em;\n}\n\narticle .pull-left {\n    float: left;\n    margin: 1.5rem 1.5rem 1.5rem -25%;\n}\n\narticle .pull-right {\n    float: right;\n    margin: 1.5rem -25% 1.5rem 1.5rem;\n}\n\narticle .cliptop {\n    border-top: 1px solid hsl(0, 0%, 86.7%);\n    border-color: var(--horizontal-rule-color);\n}\n\narticle .clipbottom {\n    border-bottom: 1px solid hsl(0, 0%, 86.7%);\n    border-color: var(--horizontal-rule-color);\n}\n\narticle .clipright {\n    border-right: 1px solid hsl(0, 0%, 86.7%);\n    border-color: var(--horizontal-rule-color);\n}\n\narticle .clipleft {\n    border-left: 1px solid hsl(0, 0%, 86.7%);\n    border-color: var(--horizontal-rule-color);\n}\n\narticle .mattewhite {\n    background-color: hsl(0, 0%, 100%);\n    background-color: var(--figure-mattewhite-background-color);\n    border-top: 1px solid hsl(0, 0%, 90.6%);\n    border-bottom: 1px solid hsl(0, 0%, 90.6%);\n    border-color: var(--article-border-color);\n    padding-top: 3rem;\n    padding-bottom: 3rem;\n}\n\narticle .mattewhite:not(.widescreen) {\n    border: 1px solid hsl(0, 0%, 90.6%);\n    border-color: var(--article-border-color);\n    padding: 3rem;\n    margin-left: -3rem;\n    margin-right: -3rem;\n}\n\narticle .mattewhite.tightwad {\n    padding: 0;\n}\n\n/** Article Figures **/\n\narticle figure {\n    margin-bottom: 3rem;\n    text-align: center;\n}\narticle figure > img {\n    display: inline-block;\n    max-width: 100%;\n    max-height: 540px;\n    height: auto;\n    width: auto;\n}\n\nfigure.widescreen {\n    position: relative;\n    width: 100vw;\n    left: 50%;\n    transform: translate(-50%);\n}\n\nfigure.widescreen img,\nfigure.widescreen figcaption {\n    display: block;\n    margin: 0 auto;\n}\n\nfigure.widescreen figcaption {\n    margin-top: 3rem;\n}\n\nfigure.widescreen video {\n    max-height: 420px;\n    max-width: 66%;\n}\n\nfigure.table {\n    -webkit-overflow-scrolling: touch;\n    width: calc(100% + 6rem);\n    overflow: auto;\n    border: 1px solid hsl(0, 0%, 90.6%);\n    border-color: var(--code-border-color);\n    background-color: hsl(0, 0%, 94.9%);\n    background-color: var(--code-background-color);\n    border-radius: 3px;\n    box-sizing: border-box;\n    padding: 3rem;\n    margin-left: -3rem;\n}\n\narticle video.alignleft,\narticle video.alignright {\n    max-width: 50%;\n}\n\narticle .alignleft:first-child,\narticle .alignright:first-child {\n    margin-top: 0.5rem;\n    margin-bottom: 0.5rem;\n}\n\narticle figcaption {\n    text-align: left;\n    margin-top: 1.5rem;\n    line-height: 1.5;\n    max-width: 970px;\n    padding-left: 1.5rem;\n    box-sizing: border-box;\n    font-size: 1.3rem;\n    font-weight: 400;\n    color: hsl(0, 0%, 33.3%);\n    color: var(--text-color-medium);\n    position: relative;\n}\n\narticle figcaption::before {\n    left: 1.5rem;\n    width: 15%;\n    height: 100%;\n    bottom: 2.5rem;\n    border-top: 1px solid hsl(0, 0%, 80%);\n    border-color: var(--figure-caption-rule-color);\n    content: '';\n    opacity: 1;\n    display: inline-block;\n    box-sizing: border-box;\n    position: absolute;\n}\n\nfigure.aligncenter figcaption {\n    text-align: center;\n    padding-left: 0;\n}\n\nfigure.aligncenter figcaption::before {\n    margin: 0 auto;\n    width: 20%;\n    left: 50%;\n    transform: translate(-50%);\n}\n\narticle .clipbottom + p + figcaption {\n    margin-top: 1rem;\n}\n\narticle .clipbottom + p + figcaption::before {\n    width: 0;\n}\n\n/** Page Layout **/\narticle.page h1 {\n    text-align: left;\n    width: 66%;\n}\n\n.page .bodycopy h1 {\n    width: 100%;\n}\n\n/** Load Effects **/\n\n@keyframes fade-in {\n    from {\n        opacity: 0;\n    }\n\n    to {\n        opacity: 1;\n    }\n}\n\n@-webkit-keyframes fade-in {\n    from {\n        opacity: 0;\n    }\n\n    to {\n        opacity: 1;\n    }\n}\n\n@keyframes fade-in-move-down {\n    from {\n        opacity: 0;\n        -webkit-transform: translateY(-3rem);\n        transform: translateY(-3rem)\n    }\n\n    to {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0)\n    }\n}\n\n@-webkit-keyframes fade-in-move-down {\n    from {\n        opacity: 0;\n        -webkit-transform: translateY(-3rem);\n        transform: translateY(-3rem)\n    }\n\n    to {\n        opacity: 1;\n        -webkit-transform: translateY(0);\n        transform: translateY(0)\n    }\n}\n\narticle,\n.feature-status-page {\n    -webkit-animation: fade-in-move-down 0.7s;\n    animation: fade-in-move-down 0.7s;\n}\n\n.tile {\n    -webkit-animation: fade-in 0.4s;\n    animation: fade-in 0.4s;\n}\n\n/** Page Table of Contents **/\n\n.table-of-contents {\n    float: right;\n    box-sizing: border-box;\n    padding: 2.5rem 0 0 0;\n    margin: 0 0 2.5rem 3rem;\n\n    max-width: 33%;\n    z-index: 5;\n    font-size: 1.4rem;\n    line-height: 1.20849;\n    border-top: 1px solid hsl(0, 0%, 83.9%);\n    border-color: var(--toc-border-color);\n}\n\narticle .table-of-contents label {\n    font-size: 1.7rem;\n    font-weight: 500;\n    margin-bottom: 1.65rem;\n}\n\n.table-of-contents ul {\n    margin: 0;\n    list-style: none;\n    margin-top: 1.65rem;\n}\n\n.table-of-contents .list > ul {\n    padding-left: 0;\n}\n\n.table-of-contents ul li {\n    margin-bottom: 1.65rem;\n}\n\n.table-of-contents ul li:last-child {\n    margin-bottom: 0;\n}\n\n.table-of-contents ul li > ul {\n    margin-top: 1.65rem;\n}\n\n.with-toc pre:nth-child(-n+6),\n#post-4132 pre:nth-child(-n+10) {\n    width: 55%;\n    z-index: -1;\n}\n\n/** Logo **/\n.site-logo {\n    float: left;\n    font-size: 3rem;\n    line-height: 1.04167;\n    letter-spacing: 0.015rem;\n    font-weight: 500;\n    text-rendering: optimizeLegibility;\n    display: inline-block;\n    background: url('images/webkit.svg') no-repeat;\n    padding: 1rem 0 1rem 5.5rem;\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n}\n\n.hero .logo {\n    background-image: url('images/webkit.svg');\n}\n\n/** Status Page **/\n\n.feature-header:after,\n.property-header:after {\n    display: inline-block;\n    content: \"\";\n    background: url('images/menu-down.svg') no-repeat 50%;\n    background-size: 2rem;\n}\n\n/** Navigation **/\n\n.label-toggle {\n    cursor: pointer;\n}\n\nheader nav {\n    text-align: right;\n}\n\n/* Hide menu toggle checkboxes */\ninput.menu-toggle {\n    visibility: hidden;\n    position: absolute;\n    top: 0;\n    left: 0;\n}\n\nfooter {\n\n}\n\nfooter nav {\n    padding: 1.65rem 0 0;\n}\n\nheader nav li {\n    display: inline-block;\n    padding: 1.5rem 0 1.5rem 3rem;\n}\n\nfooter nav li {\n    display: inline-block;\n    position: relative;\n    padding: 0 0 1.5rem 3rem;\n}\n\nfooter nav li:first-child {\n    padding-left: 0;\n}\n\nheader nav a,\n.sub-menu a,\nfooter nav a {\n    position: relative;\n    display: inline-block;\n    text-decoration: none;\n    font-size: 1.4rem;\n    line-height: 1.5455;\n    letter-spacing: -0.015rem;\n    letter-spacing: 0;\n    cursor: pointer;\n    font-weight: 500;\n    color: hsl(0, 0%, 20%);\n    color: var(--text-color);\n}\n\nheader nav a,\nfooter nav a {\n    color: hsl(0, 0%, 100%);\n    color: var(--inverse-text-color);\n}\n\nheader nav a:hover,\nfooter nav a:hover {\n    color: hsl(200, 100%, 40%);\n    color: var(--link-color);\n    text-decoration: none;\n}\n\nheader .menu-item-has-children .label-toggle::after {\n    background: url('images/menu-down.svg') no-repeat;\n    background-size: 1.2rem;\n    display: inline-block;\n    padding-right: 1.2rem;\n    padding-top: 0.8rem;\n    margin-left: 0.5rem;\n    margin-top: -0.1rem;\n    content: '';\n\n    -webkit-filter: invert(100%);\n    filter: invert(100%);\n    perspective: 600;\n\n    transition: transform 0.3s ease-out;\n}\n\nheader .menu-item { /* add bottom dimension to main menu items */\n    padding-bottom: 2.5rem;\n}\n\n.sub-menu-layer {\n    text-align: center;\n    padding: 3rem;\n    box-sizing: border-box;\n\n    width: 21rem;\n    margin-left: -11rem;\n    margin-top: -99rem;\n\n    position: absolute;\n    top: 7rem;\n    transform: translateY(-1rem);\n\n    background-color: hsla(0, 0%, 100%, 0.95);\n    background-color: var(--submenu-background-color);\n    box-shadow: 0px 3px 20px 0px hsla(0, 0%, 0%, 0.1);\n    box-shadow: var(--submenu-shadow);\n    border: 1px solid hsl(0, 0%, 90.6%);\n    border-color: var(--submenu-border-color);\n    border-radius: 5px;\n\n    transition: opacity 0.6s;\n    opacity: 0;\n}\n\n.sub-menu-layer:after, .sub-menu-layer:before {\n    bottom: 100%;\n    left: 71%;\n    border: solid transparent;\n    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n\n}\n\n.sub-menu-layer:after {\n    border-bottom-color: hsla(0, 0%, 100%, 0.95);\n    border-bottom-color: var(--submenu-background-color);\n    border-width: 10px;\n    margin-left: -10px;\n}\n\n.sub-menu-layer:before {\n    border-bottom-color: hsla(0, 0%, 100%, 0.95);\n    border-bottom-color: var(--submenu-background-color);\n    border-width: 11px;\n    margin-left: -11px;\n}\n\n.sub-menu-layer .menu-item {\n    padding: 1.5rem 0 0 0;\n    width: 100%;\n}\n\n.sub-menu-layer .menu-item:first-child {\n    padding: 0;\n}\n\n.menu > .menu-item > a:focus ~ .sub-menu,\n.menu > .menu-item.open-menu > .sub-menu,\n.menu > .menu-item:hover > .sub-menu,\n.menu > .menu-item > .menu-toggle:checked + .sub-menu {\n    display: block;\n    box-sizing: border-box;\n    z-index: 1;\n    opacity: 1;\n    transform: translateY(0);\n    margin-top: 0;\n}\n\n/** Accessibility **/\n\n@media (prefers-reduced-motion) {\n    article,\n    .feature-status-page {\n        -webkit-animation: fade-in 0.7s;\n        animation: fade-in 0.7s;\n    }\n}\n\n/** Screen Breakpoints **/\n\n@media only screen and (max-width: 1180px) {\n    .page-width {\n        max-width: 1140px;\n        padding-left: 2rem;\n        padding-right: 2rem;\n    }\n\n    article .byline {\n        width: 60%;\n        margin: 0 auto;\n        float: none;\n        text-align: center;\n        margin-bottom: 3rem;\n        padding-right: 0;\n    }\n\n    article .byline p {\n        display: inline;\n    }\n}\n\n@media only screen and (max-width: 1000px) {\n    article.page h1 {\n        width: 90%;\n        margin-bottom: 3rem;\n    }\n\n    article .byline {\n        width: 60%;\n        margin: 0 auto;\n        float: none;\n        text-align: center;\n        margin-bottom: 3rem;\n    }\n\n    article .byline p {\n        display: inline;\n    }\n\n    article .bodycopy {\n        width: 90%;\n    }\n}\n\n@media only screen and (max-width: 920px) {\n    .main-menu.label-toggle {\n        display: inline-block;\n        margin: 1.5rem 0 2.5rem;\n        height: 3rem;\n        width: 3rem;\n        background: url('images/menu-down.svg') no-repeat 50%;\n        cursor: pointer;\n\n        transition: transform 0.3s ease-out;\n\n        -webkit-filter: invert(100%);\n        filter: invert(100%);\n        perspective: 600;\n        transform: translateZ(10rem);\n    }\n\n    .menu-toggle:checked + .main-menu.label-toggle,\n    header .menu-item > .menu-toggle:checked + a > .label-toggle::after {\n        -webkit-transform: rotateX(-180deg);\n        -moz-transform: rotateX(-180deg);\n        transform: rotateX(-180deg);\n        perspective: 600;\n    }\n\n    header .menu {\n        display: none;\n        position: absolute;\n        left: 0;\n        margin-top: 1px;\n        padding-top: 3rem;\n        text-align: left;\n        width: 100vw;\n        overflow: hidden;\n        box-shadow: 0px 5px 5px hsla(0, 0%, 0%, 0.1);\n        box-shadow: var(--header-menu-shadow);\n\n        backdrop-filter: blur(20px);\n        -webkit-backdrop-filter: blur(10px);\n        background-color: hsla(0, 0%, 100%, 0.8);\n        background-color: var(--header-menu-background-color);\n    }\n\n    header nav a {\n        color: hsl(0, 0, 100%);\n        color: var(--text-color);\n    }\n\n    header .menu-toggle:checked ~ ul {\n        display: block;\n        opacity: 1;\n    }\n\n    header .menu-item-has-children .label-toggle::after {\n        -webkit-filter: invert(0%);\n        filter: invert(0%);\n    }\n\n    header .menu-main-menu-container >  ul > li {\n        width: 100vw;\n        position: relative;\n        padding: 0 3rem 3rem;\n        box-sizing: border-box;\n        transition: opacity 0.6s;\n    }\n\n    header .menu > .menu-item > .sub-menu {\n        box-shadow: none;\n        border-bottom: 1px solid hsl(0, 0%, 90.6%);\n        border-color: var(--submenu-border-color);\n    }\n\n    header .menu > .menu-item-has-children {\n        margin-left: 0;\n    }\n\n    header .sub-menu-layer {\n        text-align: left;\n        width: 100vw;\n        left: 50%;\n        margin-left: -50vw;\n        border-radius: 0;\n        border-left: none;\n        border-right: none;\n        opacity: 0;\n        transform: translateY(0);\n        transition: opacity 0.6s;\n    }\n\n    header .sub-menu-layer:after, .sub-menu-layer:before {\n        bottom: 100%;\n        left: 71%;\n        border: solid transparent;\n        content: \" \";\n        height: 0;\n        width: 0;\n        position: absolute;\n        pointer-events: none;\n    }\n\n    header .sub-menu-layer:after {\n        border: none;\n        margin-left: -10px;\n    }\n\n    header .sub-menu-layer:before {\n        border: none;\n        margin-left: -11px;\n    }\n\n    header .menu > .menu-item > .menu-toggle:checked ~ .sub-menu {\n        position: relative;\n        top: 1.5rem;\n        margin-top: 0;\n    }\n\n    footer nav li {\n        padding: 0 3rem 3rem 0;\n    }\n\n}\n\n@media only screen and (max-width: 690px) {\n    article h1 {\n        font-size: 3.4rem;\n    }\n\n    .featured-tile {\n        padding: 0;\n    }\n\n    .tile.spacer {\n        height: 0;\n        min-height: 0;\n        margin-bottom: 0;\n    }\n\n    .page-width {\n        max-width: 100vw;\n        padding-left: 1rem;\n        padding-right: 1rem;\n        overflow: hidden;\n        box-sizing: border-box;\n    }\n\n    .tile {\n        min-height: 375px;\n    }\n\n    .third-tile,\n    .two-thirds-tile {\n        width: calc(100% - 1px);\n    }\n\n    .icon-tile .icon {\n        margin-top: -40%;\n    }\n\n    .with-toc pre:nth-child(-n+8),\n    article pre {\n        position: relative;\n        width: 100vw;\n        left: 50%;\n        transform: translate(-50%);\n        margin-left: 0;\n        border-radius: 0;\n        border-left: none;\n        border-right: none;\n    }\n\n    .table-of-contents { /* hug the edge */\n        right: 0;\n    }\n\n    .pagination .prev-post,\n    .pagination .next-post {\n        min-width: auto;\n        width: 90%;\n        text-align: right;\n    }\n\n    .pagination .prev-post {\n        margin-bottom: 1rem;\n        text-align: left;\n    }\n\n    .nextrouter-copy {\n        font-size: 2.2rem;\n    }\n\n    article .scrollable {\n        overflow: auto;\n        -webkit-overflow-scrolling: touch;\n        position: relative;\n        width: 100vw;\n        left: 50%;\n        transform: translate(-50%);\n        margin: 3rem 0;\n        border: 1px solid hsl(0, 0%, 80%);\n        border-color: var(--article-scrollable-border-color);\n        border-left: none;\n        border-right: none;\n    }\n\n    article video.alignleft,\n    article video.alignright {\n        min-width: 30rem;\n    }\n\n    .scrollable .scrollable-padding {\n        display: inline-block;\n        padding: 0 3rem;\n    }\n}\n\n@media only screen and (max-width: 600px) {\n    header {\n        padding-top: 1rem;\n    }\n\n    .site-logo {\n        font-size: 4rem;\n        padding-left: 6.4rem;\n    }\n\n    header nav .main-menu.label-toggle {\n        margin-top: 2rem;\n        margin-bottom: 2rem;\n    }\n\n    #wpadminbar {\n        position: absolute;\n    }\n\n    .table-of-contents {\n        /* Collapse */\n        height: 7rem;\n        overflow: hidden;\n        border-bottom-width: 1px;\n        border-bottom-style: solid;\n\n        /* one-column */\n        width: 100vw;\n        max-width: 100%;\n        position: relative;\n        float: none;\n        padding-bottom: 2.5rem;\n        margin: 0 0 3rem 0;\n    }\n\n    .menu-toggle:checked ~ .table-of-contents {\n        height: auto;\n    }\n\n    .table-of-contents label {\n        display: block;\n    }\n\n    .table-of-contents label:after {\n        display: inline-block;\n        content: \"\";\n        background: url('images/menu-down.svg') no-repeat 50%;\n        background-size: 1rem;\n        width: 2rem;\n        height: 2rem;\n        position: absolute;\n        transition: transform 0.3s ease-out;\n        perspective: 600;\n    }\n\n    .menu-toggle:checked ~ .table-of-contents label:after {\n        -webkit-transform: rotateX(-180deg);\n        -moz-transform: rotateX(-180deg);\n        transform: rotateX(-180deg);\n    }\n\n    .table-of-contents h6 {\n        margin-bottom: 3rem;\n    }\n\n    .with-toc pre:nth-child(-n+6),\n    #post-4132 pre:nth-child(-n+8) {\n        width: 100vw;\n    }\n\n    article video.alignleft,\n    article video.alignright {\n        max-width: 100%;\n        min-width: none;\n        width: 100%;\n    }\n\n    article .alignleft:first-child,\n    article .alignright:first-child {\n        margin-bottom: 3rem;\n    }\n\n}\n\n@media only screen and (max-width: 415px) {\n\n    .nextrouter-copy {\n        font-size: 1.7rem;\n        letter-spacing: -0.016rem;\n    }\n}\n\n@media only screen and (max-height: 415px) and (max-width: 920px) {\n\n    .home .site-logo {\n        opacity: 1;\n        margin-top: 0;\n    }\n\n    header,\n    .home header {\n        padding-top: 1rem;\n    }\n\n    @supports(padding:max(0px)) {\n        header,\n        header .menu,\n        .home header,\n        .home .hero .content,\n        .feature-filters,\n        #content,\n        #nightly,\n        footer {\n            box-sizing: border-box;\n            padding-left: env(safe-area-inset-left);\n            padding-right: env(safe-area-inset-right);\n        }\n\n        header .menu .menu-item > .sub-menu {\n            border: none;\n            background: none;\n        }\n\n        .sub-menu-layer {\n            padding: 0 3rem;\n        }\n\n        .sub-menu-layer .menu-item:first-child,\n        .sub-menu-layer .menu-item {\n            padding: 0 0 1.5rem 1.5rem;\n        }\n\n    }\n\n    .tile {\n        overflow: hidden;\n    }\n\n    .tile .background-image {\n        padding-bottom: 33%;\n    }\n\n    .tile .background-image svg {\n        top: -65%;\n    }\n\n\n    .table-of-contents {\n        height: 9rem;\n        overflow: hidden;\n        margin-right: -10%;\n    }\n\n    .menu-toggle:checked ~ .table-of-contents {\n        height: auto;\n    }\n\n    .table-of-contents label {\n        display: block;\n    }\n\n    .table-of-contents label:after {\n        display: inline-block;\n        content: \"\";\n        background: url('images/menu-down.svg') no-repeat 50%;\n        background-size: 1rem;\n        width: 2rem;\n        height: 2rem;\n        position: absolute;\n        transition: transform 0.3s ease-out;\n        perspective: 600;\n    }\n\n    .menu-toggle:checked ~ .table-of-contents label:after {\n        -webkit-transform: rotateX(-180deg);\n        -moz-transform: rotateX(-180deg);\n        transform: rotateX(-180deg);\n    }\n\n    .table-of-contents h6 {\n        margin-bottom: 3rem;\n    }\n\n    .with-toc pre:nth-child(-n+6),\n    #post-4132 pre:nth-child(-n+8) {\n        width: 100vw;\n    }\n}\n\n@media(prefers-color-scheme:dark) {\n    article .invert-brightness,\n    figure img {\n        filter: url(#invertLightness);\n    }\n\n    .preserve-color, video {\n        filter: brightness(0.7);\n        transition: filter 0.3s ease-out;\n    }\n\n    .preserve-color:hover,\n    figure:hover .preserve-color,\n    figure:hover video,\n    video:hover {\n        filter: brightness(1);\n    }\n\n    .nextrouter .link,\n    a.readmore {\n        background-image: url('images/chevron-dark.svg');\n    }\n}\n\n#template {\n    background-image: url('images/template.svg');\n}\n\n#compass {\n    background-image: url('images/compass.svg');\n}\n\n.search-input {\n    background-image: url('images/search.svg');\n}\n\n.filters-toggle-button {\n    background-image: url('images/filter.svg');\n}"
+          },
+          "redirectURL": "",
+          "headersSize": 448,
+          "bodySize": 60432,
+          "_transferSize": 60880
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 0.5440711975097656,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0.5440711975097656,
+          "wait": 23.939013481140137,
+          "receive": 23.24497699737549
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "19",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.325Z",
+        "time": 6.961941719055176,
+        "request": {
+          "method": "GET",
+          "url": "https://www.apple.com/wss/fonts?families=SF+Pro,v1",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "ccl",
+              "value": "filtered1"
+            },
+            {
+              "name": "dslang",
+              "value": "US-EN"
+            },
+            {
+              "name": "dssf",
+              "value": "1"
+            },
+            {
+              "name": "dssid2",
+              "value": "filtered2"
+            },
+            {
+              "name": "geo",
+              "value": "US"
+            },
+            {
+              "name": "s_fid",
+              "value": "filtered3"
+            },
+            {
+              "name": "s_vi",
+              "value": "filtered4"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "ccl=filtered1; geo=US; dssf=1; dssid2=filtered2; s_fid=filtered3; s_vi=filtered4; dslang=US-EN"
+            },
+            {
+              "name": "Accept",
+              "value": "text/css,*/*;q=0.1"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "www.apple.com"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [
+            {
+              "name": "families",
+              "value": "SF Pro,v1"
+            }
+          ],
+          "headersSize": 608,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "X-Content-Type-Options",
+              "value": "nosniff"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Content-Type",
+              "value": "text/css"
+            },
+            {
+              "name": "Expires",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Vary",
+              "value": "Accept-Encoding"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Encoding",
+              "value": "gzip"
+            },
+            {
+              "name": "Content-Length",
+              "value": "825"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "max-age=0, no-cache"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            },
+            {
+              "name": "Server",
+              "value": "Apache"
+            }
+          ],
+          "content": {
+            "size": 13445,
+            "compression": 12620,
+            "mimeType": "text/css",
+            "text": "filtered5\n"
+          },
+          "redirectURL": "",
+          "headersSize": 315,
+          "bodySize": 825,
+          "_transferSize": 1140
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 0.40602684020996094,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0.40602684020996094,
+          "wait": 6.367921829223633,
+          "receive": 0.18799304962158203
+        },
+        "serverIPAddress": "2600:1406:22:19f::1aca",
+        "connection": "20",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.325Z",
+        "time": 106.6659688949585,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp/wp-includes/css/dist/block-library/style.min.css?ver=5.0.3",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            },
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check; wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "text/css,*/*;q=0.1"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [
+            {
+              "name": "ver",
+              "value": "5.0.3"
+            }
+          ],
+          "headersSize": 499,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "text/css"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=100"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Thu, 14 Feb 2019 21:00:48 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "25658"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"643a-581e0f3e80221\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 25658,
+            "compression": 0,
+            "mimeType": "text/css",
+            "text": ".wp-block-audio figcaption{margin-top:.5em;margin-bottom:1em;color:#555d66;text-align:center;font-size:13px}.wp-block-audio audio{width:100%;min-width:300px}.editor-block-list__layout .reusable-block-edit-panel{align-items:center;background:#f8f9f9;color:#555d66;display:flex;flex-wrap:wrap;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif;font-size:13px;position:relative;top:-14px;margin:0 -14px;padding:8px 14px;position:relative;z-index:7}.editor-block-list__layout .editor-block-list__layout .reusable-block-edit-panel{margin:0 -14px;padding:8px 14px}.editor-block-list__layout .reusable-block-edit-panel .reusable-block-edit-panel__spinner{margin:0 5px}.editor-block-list__layout .reusable-block-edit-panel .reusable-block-edit-panel__info{margin-right:auto}.editor-block-list__layout .reusable-block-edit-panel .reusable-block-edit-panel__label{margin-right:8px;white-space:nowrap;font-weight:600}.editor-block-list__layout .reusable-block-edit-panel .reusable-block-edit-panel__title{flex:1 1 100%;font-size:14px;height:30px;margin:4px 0 8px}.editor-block-list__layout .reusable-block-edit-panel .components-button.reusable-block-edit-panel__button{flex-shrink:0}@media (min-width:960px){.editor-block-list__layout .reusable-block-edit-panel{flex-wrap:nowrap}.editor-block-list__layout .reusable-block-edit-panel .reusable-block-edit-panel__title{margin:0}.editor-block-list__layout .reusable-block-edit-panel .components-button.reusable-block-edit-panel__button{margin:0 0 0 5px}}.editor-block-list__layout .reusable-block-indicator{background:#fff;border-left:1px dashed #e2e4e7;color:#555d66;border-bottom:1px dashed #e2e4e7;top:-14px;height:30px;padding:4px;position:absolute;z-index:1;width:30px;right:-14px}.wp-block-button{color:#fff;margin-bottom:1.5em}.wp-block-button.aligncenter{text-align:center}.wp-block-button.alignright{text-align:right}.wp-block-button__link{background-color:#32373c;border:none;border-radius:28px;box-shadow:none;color:inherit;cursor:pointer;display:inline-block;font-size:18px;margin:0;padding:12px 24px;text-align:center;text-decoration:none;white-space:normal;overflow-wrap:break-word}.wp-block-button__link:active,.wp-block-button__link:focus,.wp-block-button__link:hover{color:inherit}.is-style-squared .wp-block-button__link{border-radius:0}.is-style-outline{color:#32373c}.is-style-outline .wp-block-button__link{background:0 0;border:2px solid currentcolor}.wp-block-categories.alignleft{margin-right:2em}.wp-block-categories.alignright{margin-left:2em}.wp-block-columns{display:flex;flex-wrap:wrap}@media (min-width:782px){.wp-block-columns{flex-wrap:nowrap}}.wp-block-column{flex:1;margin-bottom:1em;flex-basis:100%;min-width:0;word-break:break-word;overflow-wrap:break-word}@media (min-width:600px){.wp-block-column{flex-basis:50%;flex-grow:0}}@media (min-width:600px){.wp-block-column:nth-child(odd){margin-right:32px}.wp-block-column:nth-child(even){margin-left:32px}.wp-block-column:not(:first-child){margin-left:32px}.wp-block-column:not(:last-child){margin-right:32px}}.wp-block-cover,.wp-block-cover-image{position:relative;background-color:#000;background-size:cover;background-position:center center;min-height:430px;width:100%;margin:0 0 1.5em 0;display:flex;justify-content:center;align-items:center;overflow:hidden}.wp-block-cover-image.has-left-content,.wp-block-cover.has-left-content{justify-content:flex-start}.wp-block-cover-image.has-left-content .wp-block-cover-image-text,.wp-block-cover-image.has-left-content .wp-block-cover-text,.wp-block-cover-image.has-left-content h2,.wp-block-cover.has-left-content .wp-block-cover-image-text,.wp-block-cover.has-left-content .wp-block-cover-text,.wp-block-cover.has-left-content h2{margin-left:0;text-align:left}.wp-block-cover-image.has-right-content,.wp-block-cover.has-right-content{justify-content:flex-end}.wp-block-cover-image.has-right-content .wp-block-cover-image-text,.wp-block-cover-image.has-right-content .wp-block-cover-text,.wp-block-cover-image.has-right-content h2,.wp-block-cover.has-right-content .wp-block-cover-image-text,.wp-block-cover.has-right-content .wp-block-cover-text,.wp-block-cover.has-right-content h2{margin-right:0;text-align:right}.wp-block-cover .wp-block-cover-image-text,.wp-block-cover .wp-block-cover-text,.wp-block-cover h2,.wp-block-cover-image .wp-block-cover-image-text,.wp-block-cover-image .wp-block-cover-text,.wp-block-cover-image h2{color:#fff;font-size:2em;line-height:1.25;z-index:1;margin-bottom:0;max-width:610px;padding:14px;text-align:center}.wp-block-cover .wp-block-cover-image-text a,.wp-block-cover .wp-block-cover-image-text a:active,.wp-block-cover .wp-block-cover-image-text a:focus,.wp-block-cover .wp-block-cover-image-text a:hover,.wp-block-cover .wp-block-cover-text a,.wp-block-cover .wp-block-cover-text a:active,.wp-block-cover .wp-block-cover-text a:focus,.wp-block-cover .wp-block-cover-text a:hover,.wp-block-cover h2 a,.wp-block-cover h2 a:active,.wp-block-cover h2 a:focus,.wp-block-cover h2 a:hover,.wp-block-cover-image .wp-block-cover-image-text a,.wp-block-cover-image .wp-block-cover-image-text a:active,.wp-block-cover-image .wp-block-cover-image-text a:focus,.wp-block-cover-image .wp-block-cover-image-text a:hover,.wp-block-cover-image .wp-block-cover-text a,.wp-block-cover-image .wp-block-cover-text a:active,.wp-block-cover-image .wp-block-cover-text a:focus,.wp-block-cover-image .wp-block-cover-text a:hover,.wp-block-cover-image h2 a,.wp-block-cover-image h2 a:active,.wp-block-cover-image h2 a:focus,.wp-block-cover-image h2 a:hover{color:#fff}.wp-block-cover-image.has-parallax,.wp-block-cover.has-parallax{background-attachment:fixed}@supports (-webkit-overflow-scrolling:touch){.wp-block-cover-image.has-parallax,.wp-block-cover.has-parallax{background-attachment:scroll}}.wp-block-cover-image.has-background-dim::before,.wp-block-cover.has-background-dim::before{content:\"\";position:absolute;top:0;left:0;bottom:0;right:0;background-color:inherit;opacity:.5;z-index:1}.wp-block-cover-image.has-background-dim.has-background-dim-10::before,.wp-block-cover.has-background-dim.has-background-dim-10::before{opacity:.1}.wp-block-cover-image.has-background-dim.has-background-dim-20::before,.wp-block-cover.has-background-dim.has-background-dim-20::before{opacity:.2}.wp-block-cover-image.has-background-dim.has-background-dim-30::before,.wp-block-cover.has-background-dim.has-background-dim-30::before{opacity:.3}.wp-block-cover-image.has-background-dim.has-background-dim-40::before,.wp-block-cover.has-background-dim.has-background-dim-40::before{opacity:.4}.wp-block-cover-image.has-background-dim.has-background-dim-50::before,.wp-block-cover.has-background-dim.has-background-dim-50::before{opacity:.5}.wp-block-cover-image.has-background-dim.has-background-dim-60::before,.wp-block-cover.has-background-dim.has-background-dim-60::before{opacity:.6}.wp-block-cover-image.has-background-dim.has-background-dim-70::before,.wp-block-cover.has-background-dim.has-background-dim-70::before{opacity:.7}.wp-block-cover-image.has-background-dim.has-background-dim-80::before,.wp-block-cover.has-background-dim.has-background-dim-80::before{opacity:.8}.wp-block-cover-image.has-background-dim.has-background-dim-90::before,.wp-block-cover.has-background-dim.has-background-dim-90::before{opacity:.9}.wp-block-cover-image.has-background-dim.has-background-dim-100::before,.wp-block-cover.has-background-dim.has-background-dim-100::before{opacity:1}.wp-block-cover-image.alignleft,.wp-block-cover-image.alignright,.wp-block-cover.alignleft,.wp-block-cover.alignright{max-width:305px;width:100%}.wp-block-cover-image::after,.wp-block-cover::after{display:block;content:\"\";font-size:0;min-height:inherit}@supports ((position:-webkit-sticky) or (position:sticky)){.wp-block-cover-image::after,.wp-block-cover::after{content:none}}.wp-block-cover-image.aligncenter,.wp-block-cover-image.alignleft,.wp-block-cover-image.alignright,.wp-block-cover.aligncenter,.wp-block-cover.alignleft,.wp-block-cover.alignright{display:flex}.wp-block-cover__video-background{position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:100%;height:100%;z-index:0;-o-object-fit:cover;object-fit:cover}.editor-block-list__block[data-type=\"core/embed\"][data-align=left] .editor-block-list__block-edit,.editor-block-list__block[data-type=\"core/embed\"][data-align=right] .editor-block-list__block-edit,.wp-block-embed.alignleft,.wp-block-embed.alignright{max-width:360px;width:100%}.wp-block-embed{margin-bottom:1em}.wp-block-embed figcaption{margin-top:.5em;margin-bottom:1em;color:#555d66;text-align:center;font-size:13px}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-1 .wp-block-embed__wrapper,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-2 .wp-block-embed__wrapper,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-16-9 .wp-block-embed__wrapper,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-18-9 .wp-block-embed__wrapper,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-21-9 .wp-block-embed__wrapper,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-4-3 .wp-block-embed__wrapper,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-9-16 .wp-block-embed__wrapper{position:relative}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-1 .wp-block-embed__wrapper::before,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-2 .wp-block-embed__wrapper::before,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-16-9 .wp-block-embed__wrapper::before,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-18-9 .wp-block-embed__wrapper::before,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-21-9 .wp-block-embed__wrapper::before,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-4-3 .wp-block-embed__wrapper::before,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-9-16 .wp-block-embed__wrapper::before{content:\"\";display:block;padding-top:50%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-1 .wp-block-embed__wrapper iframe,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-2 .wp-block-embed__wrapper iframe,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-16-9 .wp-block-embed__wrapper iframe,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-18-9 .wp-block-embed__wrapper iframe,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-21-9 .wp-block-embed__wrapper iframe,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-4-3 .wp-block-embed__wrapper iframe,.wp-embed-responsive .wp-block-embed.wp-embed-aspect-9-16 .wp-block-embed__wrapper iframe{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-21-9 .wp-block-embed__wrapper::before{padding-top:42.85%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-18-9 .wp-block-embed__wrapper::before{padding-top:50%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-16-9 .wp-block-embed__wrapper::before{padding-top:56.25%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-4-3 .wp-block-embed__wrapper::before{padding-top:75%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-1 .wp-block-embed__wrapper::before{padding-top:100%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-9-6 .wp-block-embed__wrapper::before{padding-top:66.66%}.wp-embed-responsive .wp-block-embed.wp-embed-aspect-1-2 .wp-block-embed__wrapper::before{padding-top:200%}.wp-block-file{margin-bottom:1.5em}.wp-block-file.aligncenter{text-align:center}.wp-block-file.alignright{text-align:right}.wp-block-file .wp-block-file__button{background:#32373c;border-radius:2em;color:#fff;font-size:13px;padding:.5em 1em}.wp-block-file a.wp-block-file__button{text-decoration:none}.wp-block-file a.wp-block-file__button:active,.wp-block-file a.wp-block-file__button:focus,.wp-block-file a.wp-block-file__button:hover,.wp-block-file a.wp-block-file__button:visited{box-shadow:none;color:#fff;opacity:.85;text-decoration:none}.wp-block-file *+.wp-block-file__button{margin-left:.75em}.wp-block-gallery{display:flex;flex-wrap:wrap;list-style-type:none;padding:0}.wp-block-gallery .blocks-gallery-image,.wp-block-gallery .blocks-gallery-item{margin:0 16px 16px 0;display:flex;flex-grow:1;flex-direction:column;justify-content:center;position:relative}.wp-block-gallery .blocks-gallery-image figure,.wp-block-gallery .blocks-gallery-item figure{margin:0;height:100%}@supports ((position:-webkit-sticky) or (position:sticky)){.wp-block-gallery .blocks-gallery-image figure,.wp-block-gallery .blocks-gallery-item figure{display:flex;align-items:flex-end;justify-content:flex-start}}.wp-block-gallery .blocks-gallery-image img,.wp-block-gallery .blocks-gallery-item img{display:block;max-width:100%;height:auto}.wp-block-gallery .blocks-gallery-image img,.wp-block-gallery .blocks-gallery-item img{width:100%}@supports ((position:-webkit-sticky) or (position:sticky)){.wp-block-gallery .blocks-gallery-image img,.wp-block-gallery .blocks-gallery-item img{width:auto}}.wp-block-gallery .blocks-gallery-image figcaption,.wp-block-gallery .blocks-gallery-item figcaption{position:absolute;bottom:0;width:100%;max-height:100%;overflow:auto;padding:40px 10px 5px;color:#fff;text-align:center;font-size:13px;background:linear-gradient(0deg,rgba(0,0,0,.7) 0,rgba(0,0,0,.3) 60%,transparent)}.wp-block-gallery .blocks-gallery-image figcaption img,.wp-block-gallery .blocks-gallery-item figcaption img{display:inline}.wp-block-gallery.is-cropped .blocks-gallery-image a,.wp-block-gallery.is-cropped .blocks-gallery-image img,.wp-block-gallery.is-cropped .blocks-gallery-item a,.wp-block-gallery.is-cropped .blocks-gallery-item img{width:100%}@supports ((position:-webkit-sticky) or (position:sticky)){.wp-block-gallery.is-cropped .blocks-gallery-image a,.wp-block-gallery.is-cropped .blocks-gallery-image img,.wp-block-gallery.is-cropped .blocks-gallery-item a,.wp-block-gallery.is-cropped .blocks-gallery-item img{height:100%;flex:1;-o-object-fit:cover;object-fit:cover}}.wp-block-gallery .blocks-gallery-image,.wp-block-gallery .blocks-gallery-item{width:calc((100% - 16px)/ 2)}.wp-block-gallery .blocks-gallery-image:nth-of-type(even),.wp-block-gallery .blocks-gallery-item:nth-of-type(even){margin-right:0}.wp-block-gallery.columns-1 .blocks-gallery-image,.wp-block-gallery.columns-1 .blocks-gallery-item{width:100%;margin-right:0}@media (min-width:600px){.wp-block-gallery.columns-3 .blocks-gallery-image,.wp-block-gallery.columns-3 .blocks-gallery-item{width:calc((100% - 16px * 2)/ 3);margin-right:16px}.wp-block-gallery.columns-4 .blocks-gallery-image,.wp-block-gallery.columns-4 .blocks-gallery-item{width:calc((100% - 16px * 3)/ 4);margin-right:16px}.wp-block-gallery.columns-5 .blocks-gallery-image,.wp-block-gallery.columns-5 .blocks-gallery-item{width:calc((100% - 16px * 4)/ 5);margin-right:16px}.wp-block-gallery.columns-6 .blocks-gallery-image,.wp-block-gallery.columns-6 .blocks-gallery-item{width:calc((100% - 16px * 5)/ 6);margin-right:16px}.wp-block-gallery.columns-7 .blocks-gallery-image,.wp-block-gallery.columns-7 .blocks-gallery-item{width:calc((100% - 16px * 6)/ 7);margin-right:16px}.wp-block-gallery.columns-8 .blocks-gallery-image,.wp-block-gallery.columns-8 .blocks-gallery-item{width:calc((100% - 16px * 7)/ 8);margin-right:16px}.wp-block-gallery.columns-1 .blocks-gallery-image:nth-of-type(1n),.wp-block-gallery.columns-1 .blocks-gallery-item:nth-of-type(1n){margin-right:0}.wp-block-gallery.columns-2 .blocks-gallery-image:nth-of-type(2n),.wp-block-gallery.columns-2 .blocks-gallery-item:nth-of-type(2n){margin-right:0}.wp-block-gallery.columns-3 .blocks-gallery-image:nth-of-type(3n),.wp-block-gallery.columns-3 .blocks-gallery-item:nth-of-type(3n){margin-right:0}.wp-block-gallery.columns-4 .blocks-gallery-image:nth-of-type(4n),.wp-block-gallery.columns-4 .blocks-gallery-item:nth-of-type(4n){margin-right:0}.wp-block-gallery.columns-5 .blocks-gallery-image:nth-of-type(5n),.wp-block-gallery.columns-5 .blocks-gallery-item:nth-of-type(5n){margin-right:0}.wp-block-gallery.columns-6 .blocks-gallery-image:nth-of-type(6n),.wp-block-gallery.columns-6 .blocks-gallery-item:nth-of-type(6n){margin-right:0}.wp-block-gallery.columns-7 .blocks-gallery-image:nth-of-type(7n),.wp-block-gallery.columns-7 .blocks-gallery-item:nth-of-type(7n){margin-right:0}.wp-block-gallery.columns-8 .blocks-gallery-image:nth-of-type(8n),.wp-block-gallery.columns-8 .blocks-gallery-item:nth-of-type(8n){margin-right:0}}.wp-block-gallery .blocks-gallery-image:last-child,.wp-block-gallery .blocks-gallery-item:last-child{margin-right:0}.wp-block-gallery .blocks-gallery-item.has-add-item-button{width:100%}.wp-block-gallery.alignleft,.wp-block-gallery.alignright{max-width:305px;width:100%}.wp-block-gallery.aligncenter,.wp-block-gallery.alignleft,.wp-block-gallery.alignright{display:flex}.wp-block-gallery.aligncenter .blocks-gallery-item figure{justify-content:center}.wp-block-image{max-width:100%;margin-bottom:1em;margin-left:0;margin-right:0}.wp-block-image img{max-width:100%}.wp-block-image.aligncenter{text-align:center}.wp-block-image.alignfull img,.wp-block-image.alignwide img{width:100%}.wp-block-image .aligncenter,.wp-block-image .alignleft,.wp-block-image .alignright,.wp-block-image.is-resized{display:table;margin-left:0;margin-right:0}.wp-block-image .aligncenter>figcaption,.wp-block-image .alignleft>figcaption,.wp-block-image .alignright>figcaption,.wp-block-image.is-resized>figcaption{display:table-caption;caption-side:bottom}.wp-block-image .alignleft{float:left;margin-right:1em}.wp-block-image .alignright{float:right;margin-left:1em}.wp-block-image .aligncenter{margin-left:auto;margin-right:auto}.wp-block-image figcaption{margin-top:.5em;margin-bottom:1em;color:#555d66;text-align:center;font-size:13px}.wp-block-latest-comments__comment{font-size:15px;line-height:1.1;list-style:none;margin-bottom:1em}.has-avatars .wp-block-latest-comments__comment{min-height:36px;list-style:none}.has-avatars .wp-block-latest-comments__comment .wp-block-latest-comments__comment-excerpt,.has-avatars .wp-block-latest-comments__comment .wp-block-latest-comments__comment-meta{margin-left:52px}.has-dates .wp-block-latest-comments__comment,.has-excerpts .wp-block-latest-comments__comment{line-height:1.5}.wp-block-latest-comments__comment-excerpt p{font-size:14px;line-height:1.8;margin:5px 0 20px}.wp-block-latest-comments__comment-date{color:#8f98a1;display:block;font-size:12px}.wp-block-latest-comments .avatar,.wp-block-latest-comments__comment-avatar{border-radius:24px;display:block;float:left;height:40px;margin-right:12px;width:40px}.wp-block-latest-posts.alignleft{margin-right:2em}.wp-block-latest-posts.alignright{margin-left:2em}.wp-block-latest-posts.is-grid{display:flex;flex-wrap:wrap;padding:0;list-style:none}.wp-block-latest-posts.is-grid li{margin:0 16px 16px 0;width:100%}@media (min-width:600px){.wp-block-latest-posts.columns-2 li{width:calc((100% / 2) - 16px)}.wp-block-latest-posts.columns-3 li{width:calc((100% / 3) - 16px)}.wp-block-latest-posts.columns-4 li{width:calc((100% / 4) - 16px)}.wp-block-latest-posts.columns-5 li{width:calc((100% / 5) - 16px)}.wp-block-latest-posts.columns-6 li{width:calc((100% / 6) - 16px)}}.wp-block-latest-posts__post-date{display:block;color:#6c7781;font-size:13px}.wp-block-media-text{display:grid}.wp-block-media-text{grid-template-rows:auto;align-items:center;grid-template-areas:\"media-text-media media-text-content\";grid-template-columns:50% auto}.wp-block-media-text.has-media-on-the-right{grid-template-areas:\"media-text-content media-text-media\";grid-template-columns:auto 50%}.wp-block-media-text .wp-block-media-text__media{grid-area:media-text-media;margin:0}.wp-block-media-text .wp-block-media-text__content{word-break:break-word;grid-area:media-text-content;padding:0 8% 0 8%}.wp-block-media-text>figure>img,.wp-block-media-text>figure>video{max-width:unset;width:100%;vertical-align:middle}@media (max-width:600px){.wp-block-media-text.is-stacked-on-mobile{grid-template-columns:100%!important;grid-template-areas:\"media-text-media\" \"media-text-content\"}.wp-block-media-text.is-stacked-on-mobile.has-media-on-the-right{grid-template-areas:\"media-text-content\" \"media-text-media\"}}p.is-small-text{font-size:14px}p.is-regular-text{font-size:16px}p.is-large-text{font-size:36px}p.is-larger-text{font-size:48px}p.has-drop-cap:not(:focus)::first-letter{float:left;font-size:8.4em;line-height:.68;font-weight:100;margin:.05em .1em 0 0;text-transform:uppercase;font-style:normal}p.has-drop-cap:not(:focus)::after{content:\"\";display:table;clear:both;padding-top:14px}p.has-background{padding:20px 30px}p.has-text-color a{color:inherit}.wp-block-pullquote{padding:3em 0;margin-left:0;margin-right:0;text-align:center}.wp-block-pullquote.alignleft,.wp-block-pullquote.alignright{max-width:305px}.wp-block-pullquote.alignleft p,.wp-block-pullquote.alignright p{font-size:20px}.wp-block-pullquote p{font-size:28px;line-height:1.6}.wp-block-pullquote cite,.wp-block-pullquote footer{position:relative}.wp-block-pullquote .has-text-color a{color:inherit}.wp-block-pullquote:not(.is-style-solid-color){background:0 0}.wp-block-pullquote.is-style-solid-color{border:none}.wp-block-pullquote.is-style-solid-color blockquote{margin-left:auto;margin-right:auto;text-align:left;max-width:60%}.wp-block-pullquote.is-style-solid-color blockquote p{margin-top:0;margin-bottom:0;font-size:32px}.wp-block-pullquote.is-style-solid-color blockquote cite{text-transform:none;font-style:normal}.wp-block-pullquote cite{color:inherit}.wp-block-quote.is-large,.wp-block-quote.is-style-large{margin:0 0 16px;padding:0 1em}.wp-block-quote.is-large p,.wp-block-quote.is-style-large p{font-size:24px;font-style:italic;line-height:1.6}.wp-block-quote.is-large cite,.wp-block-quote.is-large footer,.wp-block-quote.is-style-large cite,.wp-block-quote.is-style-large footer{font-size:18px;text-align:right}.wp-block-separator.is-style-wide{border-bottom-width:1px}.wp-block-separator.is-style-dots{background:0 0;border:none;text-align:center;max-width:none;line-height:1;height:auto}.wp-block-separator.is-style-dots::before{content:\"\\00b7 \\00b7 \\00b7\";color:#191e23;font-size:20px;letter-spacing:2em;padding-left:2em;font-family:serif}p.wp-block-subhead{font-size:1.1em;font-style:italic;opacity:.75}.wp-block-table.has-fixed-layout{table-layout:fixed;width:100%}.wp-block-table.aligncenter,.wp-block-table.alignleft,.wp-block-table.alignright{display:table;width:auto}.wp-block-table.is-style-stripes{border-spacing:0;border-collapse:inherit;border-bottom:1px solid #f3f4f5}.wp-block-table.is-style-stripes tr:nth-child(odd){background-color:#f3f4f5}.wp-block-table.is-style-stripes td{border-color:transparent}.wp-block-text-columns{display:flex}.wp-block-text-columns.aligncenter{display:flex}.wp-block-text-columns .wp-block-column{margin:0 16px;padding:0}.wp-block-text-columns .wp-block-column:first-child{margin-left:0}.wp-block-text-columns .wp-block-column:last-child{margin-right:0}.wp-block-text-columns.columns-2 .wp-block-column{width:calc(100% / 2)}.wp-block-text-columns.columns-3 .wp-block-column{width:calc(100% / 3)}.wp-block-text-columns.columns-4 .wp-block-column{width:calc(100% / 4)}pre.wp-block-verse{white-space:nowrap;overflow:auto}.wp-block-video{margin-left:0;margin-right:0}.wp-block-video video{max-width:100%}@supports ((position:-webkit-sticky) or (position:sticky)){.wp-block-video [poster]{-o-object-fit:cover;object-fit:cover}}.wp-block-video.aligncenter{text-align:center}.wp-block-video figcaption{margin-top:.5em;margin-bottom:1em;color:#555d66;text-align:center;font-size:13px}.has-pale-pink-background-color.has-pale-pink-background-color{background-color:#f78da7}.has-vivid-red-background-color.has-vivid-red-background-color{background-color:#cf2e2e}.has-luminous-vivid-orange-background-color.has-luminous-vivid-orange-background-color{background-color:#ff6900}.has-luminous-vivid-amber-background-color.has-luminous-vivid-amber-background-color{background-color:#fcb900}.has-light-green-cyan-background-color.has-light-green-cyan-background-color{background-color:#7bdcb5}.has-vivid-green-cyan-background-color.has-vivid-green-cyan-background-color{background-color:#00d084}.has-pale-cyan-blue-background-color.has-pale-cyan-blue-background-color{background-color:#8ed1fc}.has-vivid-cyan-blue-background-color.has-vivid-cyan-blue-background-color{background-color:#0693e3}.has-very-light-gray-background-color.has-very-light-gray-background-color{background-color:#eee}.has-cyan-bluish-gray-background-color.has-cyan-bluish-gray-background-color{background-color:#abb8c3}.has-very-dark-gray-background-color.has-very-dark-gray-background-color{background-color:#313131}.has-pale-pink-color.has-pale-pink-color{color:#f78da7}.has-vivid-red-color.has-vivid-red-color{color:#cf2e2e}.has-luminous-vivid-orange-color.has-luminous-vivid-orange-color{color:#ff6900}.has-luminous-vivid-amber-color.has-luminous-vivid-amber-color{color:#fcb900}.has-light-green-cyan-color.has-light-green-cyan-color{color:#7bdcb5}.has-vivid-green-cyan-color.has-vivid-green-cyan-color{color:#00d084}.has-pale-cyan-blue-color.has-pale-cyan-blue-color{color:#8ed1fc}.has-vivid-cyan-blue-color.has-vivid-cyan-blue-color{color:#0693e3}.has-very-light-gray-color.has-very-light-gray-color{color:#eee}.has-cyan-bluish-gray-color.has-cyan-bluish-gray-color{color:#abb8c3}.has-very-dark-gray-color.has-very-dark-gray-color{color:#313131}.has-small-font-size{font-size:13px}.has-normal-font-size,.has-regular-font-size{font-size:16px}.has-medium-font-size{font-size:20px}.has-large-font-size{font-size:36px}.has-huge-font-size,.has-larger-font-size{font-size:42px}"
+          },
+          "redirectURL": "",
+          "headersSize": 449,
+          "bodySize": 25658,
+          "_transferSize": 26107
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 1.9320249557495117,
+          "dns": -1,
+          "connect": 49.99995231628418,
+          "ssl": 26.000022888183594,
+          "send": 0.09393692016601562,
+          "wait": 28.788089752197266,
+          "receive": 25.851964950561523
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "23",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.327Z",
+        "time": 79.2999267578125,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/scripts/global.js?ver=1.0",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "*/*"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [
+            {
+              "name": "ver",
+              "value": "1.0"
+            }
+          ],
+          "headersSize": 434,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "application/javascript"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=100"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Fri, 09 Nov 2018 22:34:48 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "4036"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"fc4-57a42f57a9ad0\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 4036,
+            "compression": 0,
+            "mimeType": "application/javascript",
+            "text": "document.addEventListener('DOMContentLoaded', function () {\n    var openClass = ' open-menu',\n        menuClass = 'menu-item-has-children',\n        menus = document.querySelectorAll('#site-nav > div > .menu > .menu-item'),\n        menuLinks = document.querySelectorAll('#site-nav > div > .menu > .menu-item > a'),\n        menuitems = document.querySelectorAll('#site-nav .menu-item-has-children .menu-item > a');\n\n    function findParentMenu (element, className) {\n        while ( (element = element.parentElement) && ! element.classList.contains(className) );\n        return element;\n    }\n\n    for (var i = 0; i < menuLinks.length; ++i) {\n        menuLinks[i].addEventListener('focus', function (e) {\n            var openMenus = findParentMenu(e.target, 'menu').getElementsByClassName(openClass.trim());\n            for (var m = 0; m < openMenus.length; ++m) {\n                openMenus[m].className = openMenus[m].className.replace(openClass, \"\");\n            }\n        });\n    }\n\n    for (var i = 0; i < menuitems.length; ++i) {\n        menuitems[i].addEventListener('focus', function (e) {\n            var targetMenu = findParentMenu(e.target, menuClass),\n                targetMenuClass = null;\n\n            if ( targetMenu != undefined )\n                targetMenuClass = targetMenu.className;\n\n            for (var m = 0; m < menus.length; ++m) {\n                menus[m].className.replace(openClass, \"\");\n                if (menus[m] == targetMenu) {\n                    if (targetMenuClass.indexOf(openClass) == -1) {\n                        targetMenu.className += openClass;\n                    }\n                } else {\n                    menus[m].className = menus[m].className.replace(openClass, \"\");\n                }\n            }\n        });\n    }\n\n    var latest = [], updating = false;\n    function inView(element) {\n        var box = element.getBoundingClientRect();\n        return ( (box.top >= 0 && box.left >= 0 && box.top) <= (window.innerHeight || document.documentElement.clientHeight));\n    }\n\n    function stageImage(element, src) {\n        element.style.backgroundImage = 'url(' + src + ')';\n        if (!element.parentElement.classList.contains('loaded'))\n            element.parentElement.classList.add('loaded');\n    }\n\n    function loadImage(element) {\n        var src = element.getAttribute('data-url');\n\n        if (sessionStorage.getItem(src)) {\n            setTimeout(function () { stageImage(element, src); }, 1);\n        } else {\n            var img = new Image();\n            img.src = src;\n            img.onload = function() {\n                stageImage(element,src);\n\n                try {\n                    sessionStorage.setItem(src, true);\n                } catch (error) {\n                    return false; // private browsing\n                }\n                img = undefined;\n            }\n        }\n\n    }\n\n    function onMovement() {\n        if (!updating)\n            requestAnimationFrame(updateImages);\n        updating = true;\n    }\n\n    function updateImages() {\n        updating = false;\n\n        for (var i = 0; i < imgs.length; i++) {\n            if ( inView(imgs[i]) )\n                loadImage(imgs[i]);\n        }\n\n    }\n\n    function enableScrollableTables () {\n        var tables = document.querySelectorAll('.bodycopy > table');\n        var tableCount = tables.length;\n\n        for (var i = 0; i < tableCount; i++) {\n            var scrollableDiv = document.createElement('div');\n            var paddingDiv = document.createElement('div');\n\n            scrollableDiv.classList.add('scrollable');\n            paddingDiv.classList.add('scrollable-padding');\n\n            scrollableDiv.appendChild(paddingDiv);\n            tables[i].parentNode.insertBefore(scrollableDiv, tables[i]);\n\n            paddingDiv.appendChild(tables[i]);\n        }\n    }\n\n    var imgs = document.querySelectorAll('div[data-url]');\n    document.addEventListener('scroll', onMovement);\n    document.addEventListener('resize', onMovement);\n\n    updateImages();\n    enableScrollableTables();\n\n});\n"
+          },
+          "redirectURL": "",
+          "headersSize": 461,
+          "bodySize": 4036,
+          "_transferSize": 4497
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 2.997875213623047,
+          "dns": -1,
+          "connect": 49.00002479553223,
+          "ssl": 24.99997615814209,
+          "send": 0.07402896881103516,
+          "wait": 25.675058364868164,
+          "receive": 1.5529394149780273
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "22",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.327Z",
+        "time": 75.59800148010254,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp/wp-includes/js/wp-embed.min.js?ver=5.0.3",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            },
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check; wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "*/*"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [
+            {
+              "name": "ver",
+              "value": "5.0.3"
+            }
+          ],
+          "headersSize": 466,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "application/javascript"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=100"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Tue, 08 Jan 2019 23:49:27 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "1403"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"57b-57efafee8bdca\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 1403,
+            "compression": 0,
+            "mimeType": "application/javascript",
+            "text": "!function(a,b){\"use strict\";function c(){if(!e){e=!0;var a,c,d,f,g=-1!==navigator.appVersion.indexOf(\"MSIE 10\"),h=!!navigator.userAgent.match(/Trident.*rv:11\\./),i=b.querySelectorAll(\"iframe.wp-embedded-content\");for(c=0;c<i.length;c++){if(d=i[c],!d.getAttribute(\"data-secret\"))f=Math.random().toString(36).substr(2,10),d.src+=\"#?secret=\"+f,d.setAttribute(\"data-secret\",f);if(g||h)a=d.cloneNode(!0),a.removeAttribute(\"security\"),d.parentNode.replaceChild(a,d)}}}var d=!1,e=!1;if(b.querySelector)if(a.addEventListener)d=!0;if(a.wp=a.wp||{},!a.wp.receiveEmbedMessage)if(a.wp.receiveEmbedMessage=function(c){var d=c.data;if(d)if(d.secret||d.message||d.value)if(!/[^a-zA-Z0-9]/.test(d.secret)){var e,f,g,h,i,j=b.querySelectorAll('iframe[data-secret=\"'+d.secret+'\"]'),k=b.querySelectorAll('blockquote[data-secret=\"'+d.secret+'\"]');for(e=0;e<k.length;e++)k[e].style.display=\"none\";for(e=0;e<j.length;e++)if(f=j[e],c.source===f.contentWindow){if(f.removeAttribute(\"style\"),\"height\"===d.message){if(g=parseInt(d.value,10),g>1e3)g=1e3;else if(~~g<200)g=200;f.height=g}if(\"link\"===d.message)if(h=b.createElement(\"a\"),i=b.createElement(\"a\"),h.href=f.getAttribute(\"src\"),i.href=d.value,i.host===h.host)if(b.activeElement===f)a.top.location.href=d.value}else;}},d)a.addEventListener(\"message\",a.wp.receiveEmbedMessage,!1),b.addEventListener(\"DOMContentLoaded\",c,!1),a.addEventListener(\"load\",c,!1)}(window,document);"
+          },
+          "redirectURL": "",
+          "headersSize": 461,
+          "bodySize": 1403,
+          "_transferSize": 1864
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 1.8349885940551758,
+          "dns": 1.000046730041504,
+          "connect": 46.99993133544922,
+          "ssl": 24.99997615814209,
+          "send": 0.1010894775390625,
+          "wait": 24.034976959228516,
+          "receive": 1.6269683837890625
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "21",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.438Z",
+        "time": 24.15597438812256,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/images/compass.svg",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 485,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "image/svg+xml"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=98"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Mon, 13 Nov 2017 17:49:55 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "5492"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"1574-55de0e5f6cc5e\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 5492,
+            "compression": 0,
+            "mimeType": "image/svg+xml",
+            "text": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright © 2017 Apple Inc. All rights reserved. -->\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1450 1450\">\n    <path d=\"M 725.000002 1447.03875 L 725.000002 1447.03875 C 1123.60498 1447.03875 1446.73816 1123.77099 1446.73816 725.000001 C 1446.73816 326.229011 1123.60498 2.96125272 725.000002 2.96125272 C 326.395019 2.96125272 3.26183556 326.229011 3.26183556 725.000001 C 3.26183556 1123.77099 326.395019 1447.03875 725.000002 1447.03875 L 725.000002 1447.03875 L 725.000002 1447.03875 Z\" stroke=\"white\" fill-rule=\"evenodd\" fill=\"none\"/>\n    <path d=\"M 562.84813 953.349909 C 591.496191 973.66411 624.145787 988.769366 659.394813 997.273047 L 725.961517 1208.84553 L 792.526922 997.27345 C 894.269986 972.728938 974.355877 893.184104 999.067337 792.12841 L 1212.07851 726.012715 L 1011.32358 663.700093 L 933.715581 733.260552 C 930.013119 843.927177 837.732412 932.850162 726.199411 932.457112 C 697.365092 932.72906 670.753732 926.587741 646.277521 916.690383 L 562.84813 953.349909 L 562.84813 953.349909 Z M 889.619426 498.977454 C 842.353604 465.376331 792.401124 454.619626 792.401124 454.619626 L 725.958556 243.17696 L 659.39315 454.749041 C 557.650085 479.293552 477.564195 558.838386 452.852735 659.894081 L 239.841563 726.009774 C 239.841563 726.009774 377.336053 768.686895 446.083297 790.025455 L 518.105575 724.21539 C 518.88254 610.97766 611.15129 520.230613 725.878523 519.678486 C 754.311916 517.820405 800.376259 531.70741 805.735165 535.334966 C 805.735159 535.334967 889.619426 498.977454 889.619426 498.977454 L 889.619426 498.977454 Z M 671.674231 642.356546 L 251.789169 1022.45099 L 774.594196 802.423012 L 1196.69162 426.027748 L 671.674231 642.356546 L 671.674231 642.356546 Z M 345.571131 962.390058 L 764.145471 786.333744 L 681.887232 657.993607 L 345.571131 962.390058 L 345.571131 962.390058 Z\" stroke=\"white\" fill-rule=\"evenodd\" fill=\"none\"/>\n    <path d=\"M 725.493385 86.2657049L 725.493385 22.8266657M 725.480154 1366.46552L 725.480154 1429.90456M 1368.62174 725L 1431.15002 725M 86.6488 725L 23.1218951 725M 1365.5407 663.680439L 1428.76225 657.467835 1365.5407 663.680439zM 89.6676327 788.419442L 26.446084 794.632045 89.6676327 788.419442zM 1356.30537 601.488314L 1418.61162 589.111972 1356.30537 601.488314zM 98.8412405 850.620707L 36.5349872 862.997049 98.8412405 850.620707zM 1341.00484 540.500963L 1401.79469 522.080284 1341.00484 540.500963zM 114.08124 911.623201L 53.291392 930.04388 114.08124 911.623201zM 1319.82955 481.409982L 1378.52076 457.132913 1319.82955 481.409982zM 135.197883 970.73514L 76.5066757 995.012209 135.197883 970.73514zM 1292.96124 424.673869L 1348.98958 394.773795 1292.96124 424.673869zM 162.009891 1027.49784L 105.98155 1057.39792 162.009891 1027.49784zM 1260.59604 370.745157L 1313.41673 335.500315 1260.59604 370.745157zM 194.321562 1081.45859L 141.500871 1116.70343 194.321562 1081.45859zM 1223.08903 320.247351L 1272.19247 279.997771M 231.778463 1131.99352L 182.675018 1172.2431M 1180.88115 273.746627L 1225.80146 228.888452 1180.88115 273.746627zM 273.940188 1178.53601L 229.019882 1223.39419 273.940188 1178.53601zM 1134.31602 231.597131L 1174.62135 182.561603 1134.31602 231.597131zM 320.463486 1220.73159L 280.158159 1269.76712 320.463486 1220.73159zM 1083.74827 194.14199L 1119.04193 141.394357 1083.74827 194.14199zM 370.994061 1258.23678L 335.700404 1310.98442 370.994061 1258.23678zM 790.407264 89.3424882L 796.628473 26.2083829 790.407264 89.3424882zM 664.231062 1363.32661L 658.009854 1426.46071 664.231062 1363.32661zM 1029.74487 161.821563L 1059.68636 105.870716 1029.74487 161.821563zM 424.96539 1290.61066L 395.023903 1346.56151 424.96539 1290.61066zM 972.930174 134.990409L 997.240868 76.3803791 972.930174 134.990409zM 481.753456 1317.49804L 457.442762 1376.10807 481.753456 1317.49804zM 913.650293 113.811979L 932.085875 53.1029969M 541.012318 1338.73514L 522.576736 1399.44412M 852.685528 98.5650451L 865.079012 36.3449692 852.685528 98.5650451zM 601.961951 1354.04241L 589.568467 1416.26249 601.961951 1354.04241zM 790.407264 1363.38873L 796.628473 1426.52284M 665.495493 89.2803621L 659.274285 26.1462568M 852.685528 1354.16618L 865.079012 1416.38625M 603.208076 98.4412817L 590.814592 36.2212058M 913.757349 1338.88681L 932.203541 1399.59258M 542.121091 113.660203L 523.674899 52.9544344M 972.930174 1317.74081L 997.240868 1376.35084M 482.92728 134.747638L 458.616586 76.1376084M 1029.74487 1290.90966L 1059.68636 1346.86051M 426.085956 161.522562L 396.14447 105.571715M 1083.74827 1258.58923L 1119.04193 1311.33686M 372.050475 193.789542L 336.756817 141.041908M 1134.31602 1221.13409L 1174.62135 1270.16962M 321.445555 231.194635L 281.140228 182.159107M 1180.88115 1178.9846L 1225.80146 1223.84277M 274.838594 273.298045L 229.918288 228.43987M 1223.08903 1132.48387L 1272.19247 1172.73345M 232.584569 319.756996L 183.481125 279.507416M 1260.59604 1081.98606L 1313.41673 1117.23091M 195.027435 370.217681L 142.206744 334.972839M 1365.5407 789.050783L 1428.76225 795.263386M 89.7920568 663.049098L 26.5705082 656.836494M 1292.96124 1028.05735L 1348.98958 1057.95743M 162.608721 424.11436L 106.580379 394.214287M 1319.82955 971.32124L 1378.52076 995.598309M 135.684097 480.823882L 76.9928895 456.546812M 1341.03731 912.123351L 1401.83038 930.533434M 114.417583 540.000781L 53.6245161 521.590698M 1356.30537 851.242908L 1418.61162 863.61925M 99.0891102 600.866113L 36.7828569 588.489771\" stroke=\"white\" fill-rule=\"evenodd\" fill=\"none\"/>\n</svg>\n"
+          },
+          "redirectURL": "",
+          "headersSize": 452,
+          "bodySize": 5492,
+          "_transferSize": 5944
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 0.23996829986572266,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0.23996829986572266,
+          "wait": 23.583054542541504,
+          "receive": 0.33295154571533203
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "19",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.439Z",
+        "time": 24.721980094909668,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/images/webkit.svg",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 484,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "image/svg+xml"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=99"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Mon, 02 Oct 2017 19:59:58 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "6049"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"17a1-55a95d1b80755\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 6049,
+            "compression": 0,
+            "mimeType": "image/svg+xml",
+            "text": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright © 2015 Apple Inc. All rights reserved. -->\n<svg viewBox=\"0 0 510 552\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <defs>\n        <linearGradient x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\" id=\"blues\">\n            <stop stop-color=\"#34AADC\" offset=\"0%\"/>\n            <stop stop-color=\"#007AFF\" offset=\"100%\"/>\n        </linearGradient>\n        <filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"shadow\">\n            <feOffset dx=\"0\" dy=\"5\" in=\"SourceAlpha\" result=\"offset\"/>\n            <feGaussianBlur stdDeviation=\"2.5\" in=\"offset\" result=\"blur\"/>\n            <feColorMatrix values=\"0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.07 0\" in=\"blur\" type=\"matrix\" result=\"matrix\"/>\n            <feMerge>\n                <feMergeNode in=\"matrix\"/>\n                <feMergeNode in=\"SourceGraphic\"/>\n            </feMerge>\n        </filter>\n    </defs>\n    <path d=\"M 477.861111 306.92819 C 512.046296 333.587507 512.046296 377.446382 477.861111 404.320693 L 317.015432 530.737452 C 282.830247 557.396768 227.169753 557.396768 192.984568 530.737452 L 32.1388889 404.535688 C -2.0462963 377.876371 -2.0462963 334.017496 32.1388889 307.143185 L 192.984568 180.726426 C 227.169753 154.06711 282.830247 154.06711 317.015432 180.726426 L 477.861111 306.92819 Z\" fill=\"rgb(255, 157, 0)\" id=\"base\"/>\n    <path d=\"M 193.370239 451.831773 L 31.8122232 324.860059 C 15.5243578 312.097996 6.5 295.009809 6.5 276.840092 C 6.5 258.670375 15.5243578 241.582189 31.8122232 228.820125 L 193.370239 101.632105 C 209.658105 88.8700422 231.668733 81.7319391 255 81.7319391 C 278.331267 81.7319391 300.121789 88.8700422 316.629761 101.632105 L 478.187777 228.603819 C 494.475642 241.365882 503.5 258.454069 503.5 276.623786 C 503.5 294.793503 494.475642 311.881689 478.187777 324.643753 L 316.629761 451.615467 C 300.121789 464.593836 278.331267 471.731939 255 471.731939 C 231.668733 471.731939 209.878211 464.593836 193.370239 451.831773 Z\" fill=\"rgba(0, 0, 0, 0.1)\" filter=\"url(#shadow)\" id=\"mid-shadow\"/>\n    <path d=\"M 193.370239 451.831773 L 31.8122232 324.860059 C 15.5243578 312.097996 6.5 295.009809 6.5 276.840092 C 6.5 258.670375 15.5243578 241.582189 31.8122232 228.820125 L 193.370239 101.632105 C 209.658105 88.8700422 231.668733 81.7319391 255 81.7319391 C 278.331267 81.7319391 300.121789 88.8700422 316.629761 101.632105 L 478.187777 228.603819 C 494.475642 241.365882 503.5 258.454069 503.5 276.623786 C 503.5 294.793503 494.475642 311.881689 478.187777 324.643753 L 316.629761 451.615467 C 300.121789 464.593836 278.331267 471.731939 255 471.731939 C 231.668733 471.731939 209.878211 464.593836 193.370239 451.831773 Z\" fill=\"rgb(255, 204, 0)\" id=\"mid\"/>\n    <path d=\"M 193.370239 371.831773 L 31.8122232 244.860059 C 15.5243578 232.097996 6.5 215.009809 6.5 196.840092 C 6.5 178.670375 15.5243578 161.582189 31.8122232 148.820125 L 193.370239 21.6321055 C 209.658105 8.87004222 231.668733 1.73193906 255 1.73193906 C 278.331267 1.73193906 300.121789 8.87004222 316.629761 21.6321055 L 478.187777 148.603819 C 494.475642 161.365882 503.5 178.454069 503.5 196.623786 C 503.5 214.793503 494.475642 231.881689 478.187777 244.643753 L 316.629761 371.615467 C 300.121789 384.593836 278.331267 391.731939 255 391.731939 C 231.668733 391.731939 209.878211 384.593836 193.370239 371.831773 Z\" fill=\"rgba(0, 0, 0, 0.1)\" filter=\"url(#shadow)\" id=\"top-shadow\"/>\n    <path d=\"M 193.370239 371.831773 L 31.8122232 244.860059 C 15.5243578 232.097996 6.5 215.009809 6.5 196.840092 C 6.5 178.670375 15.5243578 161.582189 31.8122232 148.820125 L 193.370239 21.6321055 C 209.658105 8.87004222 231.668733 1.73193906 255 1.73193906 C 278.331267 1.73193906 300.121789 8.87004222 316.629761 21.6321055 L 478.187777 148.603819 C 494.475642 161.365882 503.5 178.454069 503.5 196.623786 C 503.5 214.793503 494.475642 231.881689 478.187777 244.643753 L 316.629761 371.615467 C 300.121789 384.593836 278.331267 391.731939 255 391.731939 C 231.668733 391.731939 209.878211 384.593836 193.370239 371.831773 Z\" fill=\"url(#blues)\" id=\"top\"/>\n    <path d=\"M 255.557796 318.523438 L 255.557796 318.523438 C 338.113251 318.523438 405.03767 263.81823 405.03767 196.335938 C 405.03767 128.853645 338.113251 74.1484375 255.557796 74.1484375 C 173.002341 74.1484375 106.077922 128.853645 106.077922 196.335938 C 106.077922 263.81823 173.002341 318.523438 255.557796 318.523438 L 255.557796 318.523438 Z M 255.557796 331.101563 L 255.557796 331.101563 C 164.503985 331.101563 90.6902879 270.764937 90.6902879 196.335938 C 90.6902879 121.906938 164.503985 61.5703125 255.557796 61.5703125 C 346.611606 61.5703125 420.425304 121.906938 420.425304 196.335938 C 420.425304 270.764937 346.611606 331.101563 255.557796 331.101563 L 255.557796 331.101563 Z\" fill=\"white\" id=\"ring\"/>\n    <path d=\"M 266.575605 248.199383 C 274.839361 247.116964 282.893943 244.813421 290.267395 241.288755 L 337.32129 260.629992 L 312.674012 223.705812 C 325.63867 207.004736 325.63867 185.850561 312.674012 169.149485 L 337.32129 132.225305 L 292.974868 150.45365 L 291.700073 169.952942 C 309.829164 185.157289 309.365846 209.169068 290.527893 223.847168 C 285.721068 227.691529 280.20166 230.389527 274.405151 232.306091 L 266.575605 248.199383 Z M 244.579776 144.624146 C 230.931152 146.398682 220.701293 151.565675 220.701293 151.565675 L 173.690288 132.225305 L 198.337566 169.149485 C 185.372907 185.850561 185.372907 207.004736 198.337566 223.705812 L 173.690288 260.629992 L 219.248736 241.90345 L 220.218932 223.640565 C 201.161804 208.480714 201.314025 184.227967 220.529419 169.002319 C 224.999999 165.000001 235.105895 160.762757 236.622498 160.537354 C 236.622497 160.537354 244.579776 144.624146 244.579776 144.624146 Z\" fill=\"rgb(140, 200, 246)\" id=\"rosette\"/>\n    <path d=\"M 232.944378 192.304563 L 226.682617 303.302063 L 277.389053 200.3587 L 284.649978 89.5703125 L 232.944378 192.304563 Z M 232.289215 281.968558 L 272.904208 199.563458 L 237.312925 193.069439 L 232.289215 281.968558 Z\" fill=\"white\" fill-rule=\"evenodd\" id=\"needle\"/>\n</svg>\n"
+          },
+          "redirectURL": "",
+          "headersSize": 452,
+          "bodySize": 6049,
+          "_transferSize": 6501
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 0.7079839706420898,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0.7079839706420898,
+          "wait": 23.69403839111328,
+          "receive": 0.3199577331542969
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "21",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.439Z",
+        "time": 25.577068328857422,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/images/menu-down.svg",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 487,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "image/svg+xml"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=99"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Mon, 02 Oct 2017 19:59:58 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "324"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"144-55a95d1b80b3d\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 324,
+            "compression": 0,
+            "mimeType": "image/svg+xml",
+            "text": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright © 2015 Apple Inc. All rights reserved. -->\n<svg viewBox=\"0 0 16 10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <path d=\"M 0.066 1.615 L 1.233 0.449 L 8.001 7.217 L 14.767 0.449 L 15.934 1.615 L 8.001 9.551 L 0.066 1.615 L 0.066 1.615 Z\" fill=\"black\"/>\n</svg>"
+          },
+          "redirectURL": "",
+          "headersSize": 450,
+          "bodySize": 324,
+          "_transferSize": 774
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 0.5550384521484375,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0.5550384521484375,
+          "wait": 24.715065956115723,
+          "receive": 0.3069639205932617
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "23",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.439Z",
+        "time": 26.170015335083008,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/images/template.svg",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 486,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "image/svg+xml"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=99"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Mon, 13 Nov 2017 17:49:55 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "2116"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"844-55de0e5f6d046\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 2116,
+            "compression": 0,
+            "mimeType": "image/svg+xml",
+            "text": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1450\" height=\"1451\" viewBox=\"0 0 1450 1451\">\n  <g fill=\"none\" fill-rule=\"evenodd\">\n    <path stroke=\"#FFFFFF\" d=\"M98.6024246 3.12108458L98.6024246 1447.38377M1447.35194 1351.87414L3.1246209 1351.87414M1447.35194 97.1878967L3.1246209 97.1878967M1449.47656 725.238281L1 725.238281M1447.35194 1447.38306L3.1246209 3.12037731M1447.35194 3.12108458L3.1246209 1447.38377M1449.47656 995.413109L1 995.413109M1449.47656 453.648926L1 453.648926M1350.45961 1447.38306L1350.45961 3.12037731M725.238281 1449.50358L725.238281 1.02701748M993.998581 1449.50358L993.998581 1.02701748M455.063454 1449.50358L455.063454 1.02701748M994.965552 725.261055C994.965552 874.520624 874.207306 995.536314 725.237715 995.536314 576.269539 995.536314 455.511293 874.520624 455.511293 725.261055 455.511293 575.983098 576.269539 454.995698 725.237715 454.995698 874.207306 454.995698 994.965552 575.983098 994.965552 725.261055L994.965552 725.261055z\"/>\n    <path stroke=\"#FFFFFF\" d=\"M1107.53934,725.261055 C1107.53934,935.162849 936.370149,1105.32631 725.237715,1105.32631 C514.106697,1105.32631 342.937505,935.162849 342.937505,725.261055 C342.937505,515.350774 514.106697,345.188727 725.237715,345.188727 C936.370149,345.188727 1107.53934,515.350774 1107.53934,725.261055 L1107.53934,725.261055 Z\"/>\n    <path stroke=\"#FFFFFF\" d=\"M1351.77611,725.261055 C1351.77611,1071.60821 1071.26674,1352.37361 725.237857,1352.37361 C379.208971,1352.37361 98.7010172,1071.60821 98.7010172,725.261055 C98.7010172,378.896926 379.208971,98.1584043 725.237857,98.1584043 C1071.26674,98.1584043 1351.77611,378.896926 1351.77611,725.261055 L1351.77611,725.261055 Z\"/>\n    <path stroke=\"#FFFFFF\" d=\"M3.1246209,1122.37463 C3.1246209,1301.87539 149.494309,1447.38363 330.047478,1447.38363 L1120.42908,1447.24359 C1300.97377,1447.24359 1447.35194,1301.70847 1447.35194,1122.23459 L1447.35194,328.156821 C1447.35194,148.65606 1300.98367,3.12094312 1120.42908,3.12094312 L330.047478,3.27937025 C149.502796,3.27937025 3.1246209,148.796098 3.1246209,328.305346 L3.1246209,1122.37463 L3.1246209,1122.37463 Z\"/>\n  </g>\n</svg>\n"
+          },
+          "redirectURL": "",
+          "headersSize": 451,
+          "bodySize": 2116,
+          "_transferSize": 2567
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 0.4140138626098633,
+          "dns": -1,
+          "connect": -1,
+          "ssl": -1,
+          "send": 0.4140138626098633,
+          "wait": 25.10201930999756,
+          "receive": 0.6539821624755859
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "22",
+        "_fetchType": "Network Load"
+      },
+      {
+        "pageref": "page_0",
+        "startedDateTime": "2019-03-12T20:10:24.439Z",
+        "time": 77.3390531539917,
+        "request": {
+          "method": "GET",
+          "url": "https://webkit.org/wp-content/themes/webkit/images/chevron.svg",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [
+            {
+              "name": "wordpress_test_cookie",
+              "value": "WP+Cookie+check"
+            }
+          ],
+          "headers": [
+            {
+              "name": "Cookie",
+              "value": "wordpress_test_cookie=WP+Cookie+check"
+            },
+            {
+              "name": "Accept",
+              "value": "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"
+            },
+            {
+              "name": "Pragma",
+              "value": "no-cache"
+            },
+            {
+              "name": "Referer",
+              "value": "https://webkit.org/"
+            },
+            {
+              "name": "Cache-Control",
+              "value": "no-cache"
+            },
+            {
+              "name": "Host",
+              "value": "webkit.org"
+            },
+            {
+              "name": "User-Agent",
+              "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15"
+            },
+            {
+              "name": "Accept-Language",
+              "value": "en-us"
+            },
+            {
+              "name": "Accept-Encoding",
+              "value": "br, gzip, deflate"
+            },
+            {
+              "name": "Connection",
+              "value": "keep-alive"
+            }
+          ],
+          "queryString": [],
+          "headersSize": 485,
+          "bodySize": 0
+        },
+        "response": {
+          "status": 200,
+          "statusText": "OK",
+          "httpVersion": "HTTP/1.1",
+          "cookies": [],
+          "headers": [
+            {
+              "name": "Content-Type",
+              "value": "image/svg+xml"
+            },
+            {
+              "name": "Keep-Alive",
+              "value": "timeout=5, max=100"
+            },
+            {
+              "name": "Vary",
+              "value": "Host"
+            },
+            {
+              "name": "Last-Modified",
+              "value": "Thu, 20 Dec 2018 18:59:01 GMT"
+            },
+            {
+              "name": "Date",
+              "value": "Tue, 12 Mar 2019 20:10:24 GMT"
+            },
+            {
+              "name": "Content-Length",
+              "value": "332"
+            },
+            {
+              "name": "Connection",
+              "value": "Keep-Alive"
+            },
+            {
+              "name": "ETag",
+              "value": "\"14c-57d78b941418e\""
+            },
+            {
+              "name": "Accept-Ranges",
+              "value": "bytes"
+            },
+            {
+              "name": "X-Frame-Options",
+              "value": "SAMEORIGIN"
+            },
+            {
+              "name": "Server",
+              "value": "Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5"
+            },
+            {
+              "name": "Strict-Transport-Security",
+              "value": "max-age=63072000; includeSubdomains;"
+            }
+          ],
+          "content": {
+            "size": 332,
+            "compression": 0,
+            "mimeType": "image/svg+xml",
+            "text": "<!-- Copyright © 2017 Apple Inc. All rights reserved. -->\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"32\" viewBox=\"0 0 18 32\">\n  <style> polygon { color: hsl(200, 100%, 40%); } </style>\n  <polygon fill=\"currentColor\" fill-rule=\"evenodd\" points=\"17.177 16.198 3.084 0 0 2.649 11.296 16.198 0 29.226 3.084 32\"/>\n</svg>"
+          },
+          "redirectURL": "",
+          "headersSize": 451,
+          "bodySize": 332,
+          "_transferSize": 783
+        },
+        "cache": {},
+        "timings": {
+          "blocked": 1.8839836120605469,
+          "dns": -1,
+          "connect": 49.00002479553223,
+          "ssl": 25.999903678894043,
+          "send": 0.13899803161621094,
+          "wait": 24.58202838897705,
+          "receive": 1.734018325805664
+        },
+        "serverIPAddress": "54.190.50.171",
+        "connection": "24",
+        "_fetchType": "Network Load"
+      }
+    ]
+  }
+}
\ No newline at end of file
index b569560..b071d07 100644 (file)
@@ -1,3 +1,47 @@
+2019-03-14  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Network - HAR Import
+        https://bugs.webkit.org/show_bug.cgi?id=195642
+        <rdar://problem/34820974>
+
+        Reviewed by Devin Rousso.
+
+        * Localizations/en.lproj/localizedStrings.js
+        * UserInterface/Test.html:
+        * UserInterface/Test.html:
+        New strings and resources.
+
+        * UserInterface/Controllers/HARBuilder.js:
+        (WI.HARBuilder.dateFromHARDate):
+        (WI.HARBuilder.protocolFromHARProtocol):
+        (WI.HARBuilder.responseSourceFromHARFetchType):
+        Reverse parsers from HAR to WI.Resource types.
+
+        * UserInterface/Models/LocalResource.js: Added.
+        (WI.LocalResource):
+        (WI.LocalResource.headersArrayToHeadersObject):
+        (WI.LocalResource.fromHAREntry):
+        (WI.LocalResource.prototype.hasContent):
+        (WI.LocalResource.prototype.setContent):
+        (WI.LocalResource.prototype.requestContentFromBackend):
+        A Resource subclass with data fully supplied in the frontend.
+
+        * UserInterface/Controllers/NetworkManager.js:
+        (WI.NetworkManager):
+        (WI.NetworkManager.synthesizeImportError):
+        (WI.NetworkManager.prototype.localResourceForURL):
+        (WI.NetworkManager.prototype.processHAR):
+        Process a HAR and extract local resources.
+
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView):
+        (WI.NetworkTableContentView.prototype.reset):
+        (WI.NetworkTableContentView.prototype._handleResourceAdded):
+        (WI.NetworkTableContentView.prototype._importHAR):
+        Add an import button. When an import succeeds reset the
+        table and only show imported resources (ignoring page
+        loaded resources).
+
 2019-03-14  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Console: getEventListeners should work for any EventTarget
index da701a0..bba5a66 100644 (file)
@@ -513,6 +513,8 @@ localizedStrings["Group by Event"] = "Group by Event";
 localizedStrings["Group by Node"] = "Group by Node";
 localizedStrings["Grouping Method"] = "Grouping Method";
 localizedStrings["HAR Export (%s)"] = "HAR Export (%s)";
+localizedStrings["HAR Import"] = "HAR Import";
+localizedStrings["HAR Import Error: %s"] = "HAR Import Error: %s";
 localizedStrings["HTML"] = "HTML";
 localizedStrings["HTML Attributes"] = "HTML Attributes";
 localizedStrings["Headers"] = "Headers";
@@ -1164,6 +1166,7 @@ localizedStrings["\u201C%s\u201D Profile Recorded"] = "\u201C%s\u201D Profile Re
 localizedStrings["computed"] = "computed";
 localizedStrings["default"] = "default";
 localizedStrings["for changes to take effect"] = "for changes to take effect";
+localizedStrings["invalid HAR"] = "invalid HAR";
 localizedStrings["invalid JSON"] = "invalid JSON";
 localizedStrings["key"] = "key";
 localizedStrings["line "] = "line ";
@@ -1182,4 +1185,5 @@ localizedStrings["times before stopping"] = "times before stopping";
 localizedStrings["toggle"] = "toggle";
 localizedStrings["unknown %s \u0022%s\u0022"] = "unknown %s \u0022%s\u0022";
 localizedStrings["unsupported %s"] = "unsupported %s";
+localizedStrings["unsupported HAR version"] = "unsupported HAR version";
 localizedStrings["value"] = "value";
index 76bb8c4..1350dfc 100644 (file)
@@ -103,8 +103,10 @@ WI.HARBuilder = class HARBuilder
 
         if (resource.timingData.startTime && resource.timingData.responseEnd)
             entry.time = (resource.timingData.responseEnd - resource.timingData.startTime) * 1000;
-        if (resource.remoteAddress)
+        if (resource.remoteAddress) {
             entry.serverIPAddress = HARBuilder.ipAddress(resource.remoteAddress);
+            // FIXME: <https://webkit.org/b/195695> Web Inspector: HAR Extension for `serverIPAddress` port number
+        }
         if (resource.connectionIdentifier)
             entry.connection = "" + resource.connectionIdentifier;
 
@@ -112,6 +114,8 @@ WI.HARBuilder = class HARBuilder
         if (resource.responseSource !== WI.Resource.ResponseSource.Unknown)
             entry._fetchType = HARBuilder.fetchType(resource.responseSource);
 
+        // FIXME: <https://webkit.org/b/195693> Web Inspector: HAR Extension for Resource Priority
+
         return entry;
     }
 
@@ -241,6 +245,7 @@ WI.HARBuilder = class HARBuilder
 
     static timings(resource)
     {
+        // FIXME: <https://webkit.org/b/195694> Web Inspector: HAR Extension for Redirect Timing Info
         // Chrome has Custom Fields `_blocked_queueing` and `_blocked_proxy`.
 
         let result = {
@@ -313,4 +318,49 @@ WI.HARBuilder = class HARBuilder
         console.assert(false);
         return undefined;
     }
+
+    // Consuming.
+
+    static dateFromHARDate(isoString)
+    {
+        return Date.parse(isoString);
+    }
+
+    static protocolFromHARProtocol(protocol)
+    {
+        switch (protocol) {
+        case "HTTP/2":
+            return "h2";
+        case "HTTP/1.0":
+            return "http/1.0";
+        case "HTTP/1.1":
+            return "http/1.1";
+        case "SPDY/2":
+            return "spdy/2";
+        case "SPDY/3":
+            return "spdy/3";
+        case "SPDY/3.1":
+            return "spdy/3.1";
+        }
+
+        if (protocol)
+            console.warn("Unknown HAR Protocol value", protocol);
+        return null;
+    }
+
+    static responseSourceFromHARFetchType(fetchType)
+    {
+        switch (fetchType) {
+        case "Network Load":
+            return WI.Resource.ResponseSource.Network;
+        case "Memory Cache":
+            return WI.Resource.ResponseSource.MemoryCache;
+        case "Disk Cache":
+            return WI.Resource.ResponseSource.DiskCache;
+        }
+
+        if (fetchType)
+            console.warn("Unknown HAR Protocol _fetchType", fetchType);
+        return WI.Resource.ResponseSource.Other;
+    }
 };
index 444cd90..2877240 100644 (file)
@@ -43,6 +43,8 @@ WI.NetworkManager = class NetworkManager extends WI.Object
         this._sourceMapURLMap = new Map;
         this._downloadingSourceMaps = new Set;
 
+        this._localResourcesMap = new Map;
+
         WI.notifications.addEventListener(WI.Notification.ExtraDomainsActivated, this._extraDomainsActivated, this);
         WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
     }
@@ -54,6 +56,21 @@ WI.NetworkManager = class NetworkManager extends WI.Object
         return InspectorFrontendHost.supportsShowCertificate && window.NetworkAgent && NetworkAgent.getSerializedCertificate;
     }
 
+    static synthesizeImportError(message)
+    {
+        message = WI.UIString("HAR Import Error: %s").format(message);
+
+        if (window.InspectorTest) {
+            console.error(message);
+            return;
+        }
+
+        let consoleMessage = new WI.ConsoleMessage(WI.mainTarget, WI.ConsoleMessage.MessageSource.Other, WI.ConsoleMessage.MessageLevel.Error, message);
+        consoleMessage.shouldRevealConsole = true;
+
+        WI.consoleLogViewController.appendConsoleMessage(consoleMessage);
+    }
+
     // Target
 
     initializeTarget(target)
@@ -590,6 +607,11 @@ WI.NetworkManager = class NetworkManager extends WI.Object
         frame.addExecutionContext(executionContext);
     }
 
+    localResourceForURL(url)
+    {
+        return this._localResourcesMap.get(url);
+    }
+
     resourceForURL(url)
     {
         if (!this._mainFrame)
@@ -611,6 +633,50 @@ WI.NetworkManager = class NetworkManager extends WI.Object
             target.adoptResource(resource);
     }
 
+    processHAR({json, error})
+    {
+        if (error) {
+            WI.NetworkManager.synthesizeImportError(error);
+            return null;
+        }
+
+        if (typeof json !== "object" || json === null) {
+            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid JSON"));
+            return null;
+        }
+
+        if (typeof json.log !== "object" || typeof json.log.version !== "string") {
+            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid HAR"));
+            return null;
+        }
+
+        if (json.log.version !== "1.2") {
+            WI.NetworkManager.synthesizeImportError(WI.UIString("unsupported HAR version"));
+            return null;
+        }
+
+        if (!Array.isArray(json.log.entries) || !Array.isArray(json.log.pages) || !json.log.pages[0] || !json.log.pages[0].startedDateTime) {
+            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid HAR"));
+            return null;
+        }
+
+        let mainResourceSentWalltime = WI.HARBuilder.dateFromHARDate(json.log.pages[0].startedDateTime) / 1000;
+        if (isNaN(mainResourceSentWalltime)) {
+            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid HAR"));
+            return null;
+        }
+
+        let localResources = [];
+
+        for (let entry of json.log.entries) {
+            let localResource = WI.LocalResource.fromHAREntry(entry, mainResourceSentWalltime);
+            this._localResourcesMap.set(localResource.url, localResource);
+            localResources.push(localResource);
+        }
+
+        return localResources;
+    }
+
     // Private
 
     _addNewResourceToFrameOrTarget(url, frameIdentifier, resourceOptions = {}, frameOptions = {})
index 46131a2..d1c2605 100644 (file)
     <script src="Models/SourceCodeTextRange.js"></script>
     <script src="Models/SourceCodeTimeline.js"></script>
     <script src="Models/SourceMap.js"></script>
-    <script src="Models/SourceMapResource.js"></script>
     <script src="Models/StackTrace.js"></script>
     <script src="Models/StructureDescription.js"></script>
     <script src="Models/TextMarker.js"></script>
     <script src="Models/WebSocketResource.js"></script>
     <script src="Models/WrappedPromise.js"></script>
 
+    <script src="Models/LocalResource.js"></script>
+    <script src="Models/SourceMapResource.js"></script>
+
     <script src="Models/AuditTestBase.js"></script>
     <script src="Models/AuditTestCase.js"></script>
     <script src="Models/AuditTestGroup.js"></script>
diff --git a/Source/WebInspectorUI/UserInterface/Models/LocalResource.js b/Source/WebInspectorUI/UserInterface/Models/LocalResource.js
new file mode 100644 (file)
index 0000000..953dbe2
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2017-2019 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 NOEVENT SHALL APPLE INC. OR ITS 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.
+ */
+
+// LocalResource is a complete resource constructed by the frontend. It
+// does not need to be tied to an object in the backend. The local resource
+// does not need to be complete at creation and can get its content later.
+//
+// Construction values try to mimic protocol inputs to WI.Resource:
+//
+//     request: { url, method, headers, timestamp, walltime, finishedTimestamp data }
+//     response: { mimeType, headers, statusCode, statusText, failureReasonText, content, base64Encoded }
+//     metrics: { responseSource, protocol, priority, remoteAddress, connectionIdentifier, sizes }
+//     timing: { startTime, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd }
+
+WI.LocalResource = class LocalResource extends WI.Resource
+{
+    constructor({request, response, metrics, timing})
+    {
+        console.assert(request);
+        console.assert(typeof request.url === "string");
+        console.assert(response);
+
+        metrics = metrics || {};
+        timing = timing || {};
+
+        super(request.url, {
+            mimeType: response.mimeType || (response.headers || {}).valueForCaseInsensitiveKey("Content-Type") || null,
+            requestMethod: request.method,
+            requestHeaders: request.headers,
+            requestData: request.data,
+            requestSentTimestamp: request.timestamp,
+            requestSentWalltime: request.walltime,
+        });
+
+        // NOTE: This directly overwrites WI.Resource properties.
+        this._finishedOrFailedTimestamp = request.finishedTimestamp || NaN;
+        this._statusCode = response.statusCode || NaN;
+        this._statusText = response.statusText || null;
+        this._responseHeaders = response.headers || {};
+        this._failureReasonText = response.failureReasonText;
+        this._timingData = new WI.ResourceTimingData(this, timing);
+
+        this._responseSource = metrics.responseSource || WI.Resource.ResponseSource.Unknown;
+        this._protocol = metrics.protocol || null;
+        this._priority = metrics.priority || WI.Resource.NetworkPriority.Unknown;
+        this._remoteAddress = metrics.remoteAddress || null;
+        this._connectionIdentifier = metrics.connectionIdentifier || null;
+        this._requestHeadersTransferSize = !isNaN(metrics.requestHeaderBytesSent) ? metrics.requestHeaderBytesSent : NaN;
+        this._requestBodyTransferSize = !isNaN(metrics.requestBodyBytesSent) ? metrics.requestBodyBytesSent : NaN;
+        this._responseHeadersTransferSize = !isNaN(metrics.responseHeaderBytesReceived) ? metrics.responseHeaderBytesReceived : NaN;
+        this._responseBodyTransferSize = !isNaN(metrics.responseBodyBytesReceived) ? metrics.responseBodyBytesReceived : NaN;
+        this._responseBodySize = !isNaN(metrics.responseBodyDecodedSize) ? metrics.responseBodyDecodedSize : NaN;
+
+        // Access to the content.
+        this._localContent = response.content;
+        this._localContentIsBase64Encoded = response.base64Encoded;
+
+        // Finalize WI.Resource.
+        this._finished = true;
+        this._failed = false; // FIXME: How should we denote a failure? Assume from status code / failure reason?
+        this._cached = false; // FIXME: How should we denote cached? Assume from response source?
+    }
+
+    // Static
+
+    static headersArrayToHeadersObject(headers)
+    {
+        let result = {};
+        if (headers) {
+            for (let {name, value} of headers)
+                result[name] = value;
+        }
+        return result;
+    }
+
+    static fromHAREntry(entry, archiveStartWalltime)
+    {
+        // FIXME: <https://webkit.org/b/195695> Web Inspector: HAR Extension for `serverIPAddress` port number
+        // FIXME: <https://webkit.org/b/195694> Web Inspector: HAR Extension for Redirect Timing Info
+        // FIXME: <https://webkit.org/b/195693> Web Inspector: HAR Extension for Resource Priority
+
+        let {request, response, startedDateTime, timings} = entry;
+        let requestSentWalltime = WI.HARBuilder.dateFromHARDate(startedDateTime) / 1000;
+        let requestSentTimestamp = requestSentWalltime - archiveStartWalltime;
+        let finishedTimestamp = NaN;
+
+        let timing = {
+            startTime: NaN,
+            domainLookupStart: NaN,
+            domainLookupEnd: NaN,
+            connectStart: NaN,
+            connectEnd: NaN,
+            secureConnectionStart: NaN,
+            requestStart: NaN,
+            responseStart: NaN,
+            responseEnd: NaN,
+        };
+
+        if (!isNaN(requestSentWalltime) && !isNaN(archiveStartWalltime)) {
+            let hasBlocked = timings.blocked !== -1;
+            let hasDNS = timings.dns !== -1;
+            let hasConnect = timings.connect !== -1;
+            let hasSecureConnect = timings.ssl !== -1;
+
+            // FIXME: <https://webkit.org/b/195692> Web Inspector: ResourceTimingData should allow a startTime of 0
+            timing.startTime = requestSentTimestamp || Number.EPSILON;
+            timing.fetchStart = timing.startTime;
+
+            let accumulation = timing.startTime;
+
+            if (hasBlocked)
+                accumulation += (timings.blocked / 1000);
+
+            if (hasDNS) {
+                timing.domainLookupStart = accumulation;
+                accumulation += (timings.dns / 1000);
+                timing.domainLookupEnd = accumulation;
+            }
+
+            if (hasConnect) {
+                timing.connectStart = accumulation;
+                accumulation += (timings.connect / 1000);
+                timing.connectEnd = accumulation;
+
+                if (hasSecureConnect)
+                    timing.secureConnectionStart = timing.connectEnd - (timings.ssl / 1000);
+            }
+
+            accumulation += (timings.send / 1000);
+            timing.requestStart = accumulation;
+
+            accumulation += (timings.wait / 1000);
+            timing.responseStart = accumulation;
+
+            accumulation += (timings.receive / 1000);
+            timing.responseEnd = accumulation;
+
+            finishedTimestamp = timing.responseEnd;
+        }
+
+        return new WI.LocalResource({
+            request: {
+                url: request.url,
+                method: request.method,
+                headers: LocalResource.headersArrayToHeadersObject(request.headers),
+                timestamp: requestSentTimestamp,
+                walltime: requestSentWalltime,
+                finishedTimestamp: finishedTimestamp,
+                data: request.postData ? request.postData.text : null,
+            },
+            response: {
+                headers: LocalResource.headersArrayToHeadersObject(response.headers),
+                mimeType: response.content.mimeType,
+                statusCode: response.status,
+                statusText: response.statusText,
+                failureReasonText: response._error || null,
+                content: response.content.text,
+                base64Encoded: response.content.encoding === "base64",
+            },
+            metrics: {
+                responseSource: WI.HARBuilder.responseSourceFromHARFetchType(entry._fetchType),
+                protocol: WI.HARBuilder.protocolFromHARProtocol(response.httpVersion),
+                priority: null,
+                remoteAddress: entry.serverIPAddress || null,
+                connectionIdentifier: entry.connection ? parseInt(entry.connection) : null,
+                requestHeaderBytesSent: request.headersSize >= 0 ? request.headersSize : NaN,
+                requestBodyBytesSent: request.bodySize >= 0 ? request.bodySize : NaN,
+                responseHeaderBytesReceived: response.headersSize >= 0 ? response.headersSize : NaN,
+                responseBodyBytesReceived: response.bodySize >= 0 ? response.bodySize : NaN,
+                responseBodyDecodedSize: response.content.size || NaN,
+            },
+            timing,
+        });
+    }
+
+    // Public
+
+    hasContent()
+    {
+        return !!this._localContent;
+    }
+
+    setContent(content, base64Encoded)
+    {
+        console.assert(!this._localContent);
+
+        // The backend may send base64 encoded data for text resources.
+        // If that is the case decode them here and treat as text.
+        if (base64Encoded && WI.shouldTreatMIMETypeAsText(this._mimeType)) {
+            content = atob(content);
+            base64Encoded = false;
+        }
+
+        this._localContent = content;
+        this._localContentIsBase64Encoded = base64Encoded;
+    }
+
+    // Protected
+
+    requestContentFromBackend()
+    {
+        return Promise.resolve({
+            content: this._localContent,
+            base64Encoded: this._localContentIsBase64Encoded,
+        });
+    }
+};
index 2afdf8a..4cd0a12 100644 (file)
     <script src="Models/SourceCodeRevision.js"></script>
     <script src="Models/SourceCodeTimeline.js"></script>
     <script src="Models/SourceMap.js"></script>
-    <script src="Models/SourceMapResource.js"></script>
     <script src="Models/StackTrace.js"></script>
     <script src="Models/TextRange.js"></script>
     <script src="Models/TimelineMarker.js"></script>
     <script src="Models/WebSocketResource.js"></script>
     <script src="Models/WrappedPromise.js"></script>
 
+    <script src="Models/LocalResource.js"></script>
+    <script src="Models/SourceMapResource.js"></script>
+
     <script src="Models/AuditTestBase.js"></script>
     <script src="Models/AuditTestCase.js"></script>
     <script src="Models/AuditTestGroup.js"></script>
index 8ac436b..2e309f7 100644 (file)
@@ -36,6 +36,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         this._pendingUpdates = [];
         this._pendingFilter = false;
         this._showingRepresentedObjectCookie = null;
+        this._showingImportedResources = false;
 
         this._table = null;
         this._nameColumnWidthSetting = new WI.Setting("network-table-content-view-name-column-width", 250);
@@ -108,15 +109,24 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         this._clearOnLoadNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, () => { WI.settings.clearNetworkOnNavigate.value = !WI.settings.clearNetworkOnNavigate.value; });
         WI.settings.clearNetworkOnNavigate.addEventListener(WI.Setting.Event.Changed, this._clearNetworkOnNavigateSettingChanged, this);
 
+        this._harImportNavigationItem = new WI.ButtonNavigationItem("har-import", WI.UIString("Import"), "Images/Import.svg", 15, 15);
+        this._harImportNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
+        this._harImportNavigationItem.tooltip = WI.UIString("HAR Import");
+        this._harImportNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
+            this._importHAR();
+        });
+
         this._harExportNavigationItem = new WI.ButtonNavigationItem("har-export", WI.UIString("Export"), "Images/Export.svg", 15, 15);
         this._harExportNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
         this._harExportNavigationItem.tooltip = WI.UIString("HAR Export (%s)").format(WI.saveKeyboardShortcut.displayName);
-        this._harExportNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => { this._exportHAR(); });
+        this._harExportNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
+            this._exportHAR();
+        });
 
         this._checkboxesNavigationItemGroup = new WI.GroupNavigationItem([this._clearOnLoadNavigationItem, new WI.DividerNavigationItem]);
         this._checkboxesNavigationItemGroup.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
 
-        this._buttonsNavigationItemGroup = new WI.GroupNavigationItem([this._harExportNavigationItem, new WI.DividerNavigationItem]);
+        this._buttonsNavigationItemGroup = new WI.GroupNavigationItem([this._harImportNavigationItem, this._harExportNavigationItem, new WI.DividerNavigationItem]);
         this._buttonsNavigationItemGroup.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
 
         // COMPATIBILITY (iOS 10.3): Network.setDisableResourceCaching did not exist.
@@ -299,6 +309,8 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
             this._hidePopover();
             this._hideDetailView();
         }
+
+        this._showingImportedResources = false;
     }
 
     showRepresentedObject(representedObject, cookie)
@@ -1528,6 +1540,9 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
 
     _handleResourceAdded(event)
     {
+        if (this._showingImportedResources)
+            return;
+
         this._insertResourceAndReloadTable(event.data.resource);
     }
 
@@ -1941,6 +1956,23 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         });
     }
 
+    _importHAR()
+    {
+        WI.FileUtilities.importJSON((result) => {
+            let resources = WI.networkManager.processHAR(result);
+            if (!resources)
+                return;
+
+            this.reset();
+
+            this._showingImportedResources = true;
+
+            for (let resource of resources)
+                this._insertResourceAndReloadTable(resource);
+            this.needsLayout();
+        });
+    }
+
     _waterfallPopoverContent()
     {
         let contentElement = document.createElement("div");