Mostly works, missing some things

This commit is contained in:
Jean Viscogliosi-Pate 2024-07-31 10:10:37 -07:00
parent 874bd98647
commit 224268bbbd
407 changed files with 7400 additions and 525 deletions

View File

@ -1,12 +1,10 @@
# Solo # Bifocal
Solo is a minimal theme for [Ghost](https://github.com/TryGhost/Ghost) focused on showcasing the work of an individual writer or creator. This theme is highly customizable, with a few simple settings that allow you to quickly apply your own personal style to your site. Bifocal is is a minimal theme for [Ghost](https://github.com/TryGhost/Ghost) based on Solo. It features a two-column layout when screen width allows and displays internal tags to the user.
**Demo: https://solo.ghost.io**
# Instructions # Instructions
1. [Download this theme](https://github.com/TryGhost/Solo/archive/main.zip) 1. Download this theme
2. Log into Ghost, and go to the `Design` settings area to upload the zip file 2. Log into Ghost, and go to the `Design` settings area to upload the zip file
# Development # Development
@ -29,10 +27,9 @@ The `zip` Gulp task packages the theme files into `dist/solo.zip`, which you can
yarn zip yarn zip
``` ```
# Contribution Note that GIF files processed by Gulp become corrupted, so you will either have to use another file type or replace those files and re-zip manually in order to use GIF images.
This repo is synced automatically with [TryGhost/Themes](https://github.com/TryGhost/Themes) monorepo. If you're looking to contribute or raise an issue, head over to the main repository [TryGhost/Themes](https://github.com/TryGhost/Themes) where our official themes are developed.
## Copyright & License ## Copyright & License
Copyright (c) 2013-2023 Ghost Foundation - Released under the [MIT license](LICENSE). Copyright (c) 2024 Jean Viscogliosi-Pate - Released under the [MIT license](LICENSE).
Original Solo theme relased 2013-2023 Ghost Foundation under the MIT license.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,9 @@
@import "@tryghost/shared-theme-assets/assets/css/v1/screen.css"; @import "@tryghost/shared-theme-assets/assets/css/v1/screen.css";
@import "fonts.css"; @import "fonts.css";
@import "tocbot.css"
:root { :root {
--font-sans: Wanted Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif; --font-sans: Wanted Sans, Century Gothic, Frutiger, Futura, Montserrat, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif;
--color-primary-text: var(--color-darker-gray); --color-primary-text: var(--color-darker-gray);
--color-secondary-text-dark: rgba(0, 0, 0, 0.4); --color-secondary-text-dark: rgba(0, 0, 0, 0.4);
--color-secondary-text-light: rgba(255, 255, 255, 0.64); --color-secondary-text-light: rgba(255, 255, 255, 0.64);
@ -11,8 +12,10 @@
--gap: clamp(24px, 1.7032rem + 1.9355vw, 48px); --gap: clamp(24px, 1.7032rem + 1.9355vw, 48px);
--head-nav-gap: 32px; --head-nav-gap: 32px;
--container-width: 1440px; --container-width: 1440px;
--title-font-size: clamp(3.2rem, 2.7rem + 1.5625vw, 5.2rem);
--content-font-size: clamp(1.7rem, 0.38vw + 1.4rem, 2rem); --content-font-size: clamp(1.7rem, 0.38vw + 1.4rem, 2rem);
--header-spacing: clamp(4.8rem, 4rem + 2.5vw, 8rem); --header-spacing: clamp(4.8rem, 4rem + 2.5vw, 8rem);
--background-color: #fff;
} }
:root.has-light-text { :root.has-light-text {
@ -141,12 +144,7 @@ hr {
margin-bottom: 40px; margin-bottom: 40px;
} }
.gh-about-content {
word-break: break-word;
}
.gh-about-primary { .gh-about-primary {
max-width: 1200px;
font-size: clamp(3.2rem, 2.4452rem + 2.0968vw, 5.8rem); font-size: clamp(3.2rem, 2.4452rem + 2.0968vw, 5.8rem);
font-weight: 800; font-weight: 800;
line-height: 1.2; line-height: 1.2;
@ -157,14 +155,12 @@ hr {
} }
.gh-about-secondary { .gh-about-secondary {
max-width: 840px;
font-size: clamp(2.4rem, 0.54vw + 2.14rem, 3rem); font-size: clamp(2.4rem, 0.54vw + 2.14rem, 3rem);
font-weight: 500; font-weight: 500;
letter-spacing: -0.008em; letter-spacing: -0.008em;
} }
.gh-about-primary + .gh-about-secondary { .gh-about-primary + .gh-about-secondary {
max-width: 640px;
margin-top: 20px; margin-top: 20px;
font-size: clamp(2rem, 0.36vw + 1.83rem, 2.4rem); font-size: clamp(2rem, 0.36vw + 1.83rem, 2.4rem);
font-weight: 450; font-weight: 450;
@ -174,138 +170,6 @@ hr {
text-decoration: underline; text-decoration: underline;
} }
/* Side by side about section
/* ---------------------------------------------------------- */
.has-side-about .gh-about {
margin-top: 48px;
}
.has-side-about .gh-about.no-image {
margin-top: 80px;
margin-bottom: 48px;
}
.has-side-about .gh-about-inner {
display: grid;
grid-template-columns: 1fr 1fr;
gap: clamp(4rem, 0.0842rem + 3.9474vw, 6.4rem);
}
.has-side-about .gh-about.no-image .gh-about-inner {
grid-template-columns: 1fr;
}
.has-side-about .gh-about-content-inner {
position: sticky;
top: 40px;
}
@media (max-width: 840px) {
.has-side-about .gh-about-inner {
display: flex;
flex-direction: column-reverse;
gap: 64px;
}
}
/* Large background about section
/* ---------------------------------------------------------- */
.has-background-about .gh-about {
position: relative;
}
.has-background-about .gh-about::before {
position: absolute;
inset: 0;
content: "";
background-color: var(--color-black);
transition: opacity 1.5s ease;
}
.has-background-about .gh-about.initialized::before {
opacity: 0.4;
}
.has-background-about .gh-about-inner {
display: flex;
align-items: flex-end;
min-height: var(--about-height, 100vh);
}
.has-background-about .gh-about-image {
position: absolute;
inset: 0;
z-index: -1;
width: 100%;
height: 100%;
object-fit: cover;
}
.has-background-about .gh-about-content {
position: sticky;
bottom: calc(var(--gap) + 24px);
display: flex;
flex-direction: column;
align-items: flex-start;
max-width: 50%;
margin-top: 200px;
margin-bottom: calc(var(--gap) + 24px);
text-align: left;
}
.has-background-about .gh-about-primary {
color: #fff;
}
.has-background-about .gh-about-secondary {
color: #fff;
opacity: 0.7;
}
.has-background-about .gh-subscribe-input {
color: var(--color-secondary-text-dark);
background-color: #fff;
border: 0;
}
@media (max-width: 991px) {
.has-background-about .gh-about-content {
max-width: none;
}
}
/* Typographic profile about section
/* ---------------------------------------------------------- */
.has-typographic-about .gh-about {
display: flex;
min-height: calc(100vh - 110px);
padding-top: 64px;
padding-bottom: 64px;
}
.has-typographic-about .gh-about-inner {
display: flex;
flex-direction: column;
gap: 48px;
justify-content: flex-end;
width: 100%;
padding-bottom: clamp(2.4rem, 2rem + 1.25vw, 4rem);
}
.has-typographic-about .gh-about-image {
width: 128px;
height: 128px;
border-radius: 50%;
object-fit: cover;
}
.has-typographic-about .gh-subscribe-input {
margin-top: 48px;
}
/* Post card /* Post card
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
@ -374,16 +238,18 @@ hr {
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
.tag-list { .tag-list {
display: flex; display: flex;
flex-flow: row nowrap; flex-flow: row wrap;
justify-content: space-around; justify-content: space-around;
list-style: none; list-style: none;
align-items: center; align-items: center;
padding-left: 0; padding-left: 0;
column-gap: 15px;
} }
.tag-icon { .tag-icon {
float: left; float: left;
width: 32px; width: 32px;
height: 32px;
margin-right: 10px; margin-right: 10px;
} }
@ -392,9 +258,26 @@ hr {
line-height: 32px; line-height: 32px;
} }
.tag-desc {
color: var(--color-secondary-text);
font-weight: 600;
font-size: calc(var(--title-font-size) * 0.7);
display: inline-block;
vertical-align: middle;
block-size: var(--title-font-size);
}
/* Feed /* Feed
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
.feed-cta {
display: flex;
justify-content: right;
padding-bottom: var(--gap);
column-gap: 10px;
align-items: center;
}
.gh-card.no-image { .gh-card.no-image {
max-width: 1200px; max-width: 1200px;
} }
@ -424,7 +307,7 @@ hr {
} }
.gh-card-title { .gh-card-title {
font-size: clamp(3.2rem, 2.7rem + 1.5625vw, 5.2rem); font-size: var(--title-font-size);
text-align: center; text-align: center;
} }
@ -624,34 +507,6 @@ hr {
} }
} }
/* Custom CTA
/* ---------------------------------------------------------- */
.gh-cta {
position: relative;
z-index: 20;
grid-column: 1 / span 12 !important;
padding: clamp(8rem, 10.71vw + 2.86rem, 20rem) clamp(4.8rem, 4.64vw + 2.57rem, 10rem);
margin-top: clamp(8rem, 7.14vw + 4.57rem, 16rem);
background-color: var(--color-lighter-gray);
transform: translate3d(0, 0, 0);
}
.gh-cta-title {
margin-bottom: 24px;
font-size: clamp(3rem, 0.71vw + 2.66rem, 3.8rem);
font-weight: 800;
letter-spacing: -0.03em;
}
.gh-cta .gh-btn {
height: 48px;
padding-right: 24px;
padding-left: 24px;
font-size: 1.8rem;
letter-spacing: -0.005em;
}
/* Navigation /* Navigation
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */

90
assets/css/tocbot.css Normal file
View File

@ -0,0 +1,90 @@
/* Style from Tocbot */
.toc {
overflow-y: auto
}
.toc>.toc-list {
overflow: hidden;
position: relative
}
.toc>.toc-list li {
list-style: none
}
.toc-list {
margin: 0;
padding-left: 10px
}
a.toc-link {
color: currentColor;
height: 100%
}
.is-collapsible {
max-height: 1000px;
overflow: hidden;
transition: all 300ms ease-in-out
}
.is-collapsed {
max-height: 0
}
.is-position-fixed {
position: fixed !important;
top: 0
}
.is-active-link {
font-weight: 700
}
.toc-link::before {
background-color: #EEE;
content: ' ';
display: inline-block;
height: inherit;
left: 0;
margin-top: -1px;
position: absolute;
width: 2px
}
.is-active-link::before {
background-color: #54BC4B
}
/* Style from Ghost Foundation */
.gh-content {
position: relative;
}
.gh-toc > .toc-list {
position: relative;
}
.toc-list {
overflow: hidden;
list-style: none;
}
@media (min-width: 1300px) {
.gh-sidebar {
position: absolute;
top: 0;
bottom: 0;
margin-top: 4vmin;
grid-column: wide-start / main-start; /* Place the TOC to the left of the content */
}
.gh-toc {
position: sticky; /* On larger screens, TOC will stay in the same spot on the page */
top: 4vmin;
}
}
.gh-toc .is-active-link::before {
background-color: var(--ghost-accent-color); /* Defines TOC accent color based on Accent color set in Ghost Admin */
}

0
assets/fonts/WantedSans_LICENSE.txt Executable file → Normal file
View File

0
assets/images/default-skin.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 547 B

0
assets/images/default-skin.svg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/images/oneko.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

0
assets/images/preloader.gif Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 866 B

After

Width:  |  Height:  |  Size: 866 B

239
assets/js/oneko.js Normal file
View File

@ -0,0 +1,239 @@
// oneko.js: https://github.com/adryd325/oneko.js
(function oneko() {
const isReducedMotion =
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
if (isReducedMotion) return;
const nekoEl = document.createElement("div");
let nekoPosX = 32;
let nekoPosY = 32;
let mousePosX = 0;
let mousePosY = 0;
let frameCount = 0;
let idleTime = 0;
let idleAnimation = null;
let idleAnimationFrame = 0;
const nekoSpeed = 10;
const spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "fixed";
nekoEl.style.pointerEvents = "none";
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
nekoEl.style.zIndex = Number.MAX_VALUE;
let nekoFile = "/assets/images/oneko.gif"
const curScript = document.currentScript
if (curScript && curScript.dataset.cat) {
nekoFile = curScript.dataset.cat
}
nekoEl.style.backgroundImage = `url(${nekoFile})`;
document.body.appendChild(nekoEl);
document.addEventListener("mousemove", function (event) {
mousePosX = event.clientX;
mousePosY = event.clientY;
});
window.requestAnimationFrame(onAnimationFrame);
}
let lastFrameTimestamp;
function onAnimationFrame(timestamp) {
// Stops execution if the neko element is removed from DOM
if (!nekoEl.isConnected) {
return;
}
if (!lastFrameTimestamp) {
lastFrameTimestamp = timestamp;
}
if (timestamp - lastFrameTimestamp > 100) {
lastFrameTimestamp = timestamp
frame()
}
window.requestAnimationFrame(onAnimationFrame);
}
function setSprite(name, frame) {
const sprite = spriteSets[name][frame % spriteSets[name].length];
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime += 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
if (nekoPosX < 32) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < 32) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - 32) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - 32) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame += 1;
}
function frame() {
frameCount += 1;
const diffX = nekoPosX - mousePosX;
const diffY = nekoPosY - mousePosY;
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime -= 1;
return;
}
let direction;
direction = diffY / distance > 0.5 ? "N" : "";
direction += diffY / distance < -0.5 ? "S" : "";
direction += diffX / distance > 0.5 ? "W" : "";
direction += diffX / distance < -0.5 ? "E" : "";
setSprite(direction, frameCount);
nekoPosX -= (diffX / distance) * nekoSpeed;
nekoPosY -= (diffY / distance) * nekoSpeed;
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
}
init();
})();

View File

@ -1,38 +0,0 @@
{{!< default}}
<main class="gh-main gh-outer">
{{#author}}
<section class="gh-article gh-inner">
<header class="gh-article-header">
{{#if profile_image}}
<img class="gh-author-image" src="{{img_url profile_image size="s"}}" alt="{{name}}">
{{/if}}
<h1 class="gh-article-title">{{name}}</h1>
{{#if bio}}
<p class="gh-article-excerpt">{{bio}}</p>
{{/if}}
</header>
<footer class="gh-author-meta">
{{#if location}}
<div class="gh-author-location">{{location}}</div>
{{/if}}
<div class="gh-author-social">
{{#if website}}
<a class="gh-author-social-link" href="{{website}}" target="_blank" rel="noopener">{{website}}</a>
{{/if}}
{{#if twitter}}
<a class="gh-author-social-link" href="{{twitter_url}}" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
{{/if}}
{{#if facebook}}
<a class="gh-author-social-link" href="{{facebook_url}}" target="_blank" rel="noopener">{{> "icons/facebook"}}</a>
{{/if}}
</div>
</footer>
</section>
{{/author}}
<div class="gh-feed{{#match @custom.header_section_layout "!=" "Large background"}} gh-inner{{/match}}">
{{#foreach posts}}
{{> "loop"}}
{{/foreach}}
</div>
</main>

View File

@ -54,41 +54,18 @@
{{@custom.footer_text}} {{@custom.footer_text}}
{{/if}} {{/if}}
</div> </div>
<div class="social-media"> {{> "social-media"}}
{{#if @custom.email_address}}
<a class="social-icon" alt="Email" href={{@custom.email_address}}>
{{> "icons/email"}}
</a>
{{/if}}
{{#if @custom.mastodon_link}}
<a class="social-icon" alt="Mastodon" href={{@custom.mastodon_link}}>
{{> "icons/mastodon"}}
</a>
{{/if}}
{{#if @custom.matrix_contact}}
<a class="social-icon" alt="Matrix" href={{@custom.matrix_contact}}>
{{> "icons/matrix"}}
</a>
{{/if}}
{{#if @custom.linkedin_contact}}
<a class="social-icon" alt="LinkedIn" href={{@custom.linkedin_contact}}>
{{> "icons/linkedin"}}
</a>
{{/if}}
</div>
</div> </div>
</footer> </footer>
</div> </div>
{{#is "post, page"}} {{#is "post, page"}}
{{> "box-info"}} {{> "pswp"}}
{{/is}} {{/is}}
<script src="{{asset "built/main.min.js"}}"></script> <script src="{{asset "built/main.min.js"}}"></script>
<script src="{{asset "js/oneko.js"}}"></script>
{{ghost_foot}} {{ghost_foot}}

BIN
dist/bifocal.zip vendored

Binary file not shown.

22
dist/bifocal/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2024 Jean Viscogliosi-Pate
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

35
dist/bifocal/README.md vendored Normal file
View File

@ -0,0 +1,35 @@
# Bifocal
Bifocal is is a minimal theme for [Ghost](https://github.com/TryGhost/Ghost) based on Solo. It features a two-column layout when screen width allows and displays internal tags to the user.
# Instructions
1. Download this theme
2. Log into Ghost, and go to the `Design` settings area to upload the zip file
# Development
Edition styles are compiled using Gulp/PostCSS to polyfill future CSS spec. You'll need [Node](https://nodejs.org/), [Yarn](https://yarnpkg.com/) and [Gulp](https://gulpjs.com) installed globally. After that, from the theme's root directory:
```bash
# Install
yarn
# Run build & watch for changes
yarn dev
```
Now you can edit `/assets/css/` files, which will be compiled to `/assets/built/` automatically.
The `zip` Gulp task packages the theme files into `dist/solo.zip`, which you can then upload to your site.
```bash
yarn zip
```
Note that GIF files processed by Gulp become corrupted, so you will either have to use another file type or replace those files and re-zip manually in order to use GIF images.
## Copyright & License
Copyright (c) 2024 Jean Viscogliosi-Pate - Released under the [MIT license](LICENSE).
Original Solo theme relased 2013-2023 Ghost Foundation under the MIT license.

1
dist/bifocal/assets/built/main.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/bifocal/assets/built/screen.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

49
dist/bifocal/assets/css/fonts.css vendored Normal file
View File

@ -0,0 +1,49 @@
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 1000;
src: local("Wanted Sans ExtraBlack"), url("../fonts/WantedSans-ExtraBlack.woff2") format("woff2");
}
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 900;
src: local("Wanted Sans Black"), url("../fonts/WantedSans-Black.woff2") format("woff2");
}
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 800;
src: local("Wanted Sans ExtraBold"), url("../fonts/WantedSans-ExtraBold.woff2") format("woff2");
}
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 700;
src: local("Wanted Sans Bold"), url("../fonts/WantedSans-Bold.woff2") format("woff2");
}
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 600;
src: local("Wanted Sans SemiBold"), url("../fonts/WantedSans-SemiBold.woff2") format("woff2");
}
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 500;
src: local("Wanted Sans Medium"), url("../fonts/WantedSans-Medium.woff2") format("woff2");
}
@font-face {
font-family: "Wanted Sans";
font-style: normal;
font-display: swap;
font-weight: 400;
src: local("Wanted Sans Regular"), url("../fonts/WantedSans-Regular.woff2") format("woff2");
}

552
dist/bifocal/assets/css/screen.css vendored Normal file
View File

@ -0,0 +1,552 @@
@import "@tryghost/shared-theme-assets/assets/css/v1/screen.css";
@import "fonts.css";
:root {
--font-sans: Wanted Sans, Century Gothic, Frutiger, Futura, Montserrat, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif;
--color-primary-text: var(--color-darker-gray);
--color-secondary-text-dark: rgba(0, 0, 0, 0.4);
--color-secondary-text-light: rgba(255, 255, 255, 0.64);
--color-secondary-text: var(--color-secondary-text-dark);
--color-border: rgba(0, 0, 0, 0.08);
--gap: clamp(24px, 1.7032rem + 1.9355vw, 48px);
--head-nav-gap: 32px;
--container-width: 1440px;
--title-font-size: clamp(3.2rem, 2.7rem + 1.5625vw, 5.2rem);
--content-font-size: clamp(1.7rem, 0.38vw + 1.4rem, 2rem);
--header-spacing: clamp(4.8rem, 4rem + 2.5vw, 8rem);
--background-color: #fff;
}
:root.has-light-text {
--color-lighter-gray: rgba(0, 0, 0, 0.1);
--color-darker-gray: #fff;
--color-secondary-text: var(--color-secondary-text-light);
--color-border: rgba(255, 255, 255, 0.2);
}
body {
background-color: var(--background-color);
}
.gh-main {
padding-top: clamp(4.8rem, 4rem + 2.5vw, 8rem);
}
figcaption {
font-size: 1.3rem;
text-align: right;
}
.kg-width-full figcaption {
padding: 0;
}
hr {
background-color: var(--color-border);
}
.gh-content h2 {
font-size: 2.25em;
letter-spacing: -0.03em;
}
.gh-content h3 {
font-size: 1.6em;
}
.gh-canvas {
grid-template-columns: repeat(12, minmax(0, 1fr));
}
.gh-canvas > * {
grid-column: 4 / span 6;
}
.gh-canvas > .kg-width-wide {
grid-column: 4 / span 9;
}
.gh-canvas > .kg-width-full,
.gh-canvas > .kg-gallery-card.kg-width-wide {
position: relative;
z-index: 20;
grid-column: 1 / span 12;
transform: translate3d(0, 0, 0);
}
@media (max-width: 991px) {
.gh-canvas > * {
grid-column: 3 / span 8;
}
.gh-canvas > .kg-width-wide {
grid-column: 3 / span 10;
}
}
@media (max-width: 767px) {
.gh-canvas > * {
grid-column: 2 / span 10;
}
.gh-canvas > .kg-width-wide {
grid-column: 1 / span 12;
}
}
@media (max-width: 480px) {
.gh-canvas > * {
grid-column: 1 / span 12;
}
}
/* Header
/* ---------------------------------------------------------- */
.gh-head {
font-size: 1.6rem;
background-color: transparent;
}
.gh-head-logo {
font-weight: 800;
}
.gh-head-logo img {
max-height: 48px;
}
.gh-head-menu,
.gh-head-link {
font-weight: 700;
}
.is-head-stacked .gh-head-menu::before,
.is-head-stacked .gh-head-menu::after {
background-color: var(--color-border);
}
.gh-head-menu a {
color: inherit;
}
@media (max-width: 991px) {
.is-head-open:not(.is-head-brand):not(.is-head-dark):not(.is-head-transparent) :is(#gh-head, #gh-head .gh-head-actions) {
background-color: var(--background-color);
}
}
/* About section
/* ---------------------------------------------------------- */
.gh-about {
margin-bottom: 40px;
}
.gh-about-primary {
font-size: clamp(3.2rem, 2.4452rem + 2.0968vw, 5.8rem);
font-weight: 800;
line-height: 1.2;
}
.gh-about-primary a {
text-decoration: underline;
}
.gh-about-secondary {
font-size: clamp(2.4rem, 0.54vw + 2.14rem, 3rem);
font-weight: 500;
letter-spacing: -0.008em;
}
.gh-about-primary + .gh-about-secondary {
margin-top: 20px;
font-size: clamp(2rem, 0.36vw + 1.83rem, 2.4rem);
font-weight: 450;
}
.gh-about-secondary a {
text-decoration: underline;
}
/* Post card
/* ---------------------------------------------------------- */
.gh-card-link:hover {
opacity: 1;
}
.gh-card-wrapper {
display: flex;
flex-direction: column;
flex-grow: 1;
justify-content: center;
}
.gh-card-title {
font-weight: 800;
word-break: break-word;
}
.gh-card-link:hover .gh-card-title {
opacity: 0.8;
}
.gh-card-meta {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
margin-top: 16px;
font-size: 1.4rem;
font-weight: 500;
color: var(--color-secondary-text);
}
.gh-card-meta > * {
display: flex;
gap: 8px;
align-items: center;
}
.gh-card-meta > * + *:not(script):not(.gh-card-access)::before {
width: 2px;
height: 2px;
content: "";
background-color: currentColor;
border-radius: 50%;
}
.gh-card-access {
padding: 0 10px 0 8px;
margin-left: 4px;
background-color: var(--color-border);
border-radius: 40px;
}
.has-parallax-feed .gh-card-access {
color: var(--color-darker-gray);
background-color: var(--color-white);
}
.gh-card-access svg {
margin-right: -5px;
}
/* Tag display
/* ---------------------------------------------------------- */
.tag-list {
display: flex;
flex-flow: row wrap;
justify-content: space-around;
list-style: none;
align-items: center;
padding-left: 0;
column-gap: 15px;
}
.tag-icon {
float: left;
width: 32px;
height: 32px;
margin-right: 10px;
}
.tag-text {
overflow: auto;
line-height: 32px;
}
.tag-desc {
color: var(--color-secondary-text);
font-weight: 600;
font-size: calc(var(--title-font-size) * 0.7);
display: inline-block;
vertical-align: middle;
block-size: var(--title-font-size);
}
/* Feed
/* ---------------------------------------------------------- */
.feed-cta {
display: flex;
justify-content: right;
padding-bottom: var(--gap);
column-gap: 10px;
align-items: center;
}
.gh-card.no-image {
max-width: 1200px;
}
.gh-card-image {
position: relative;
flex: 1;
}
.gh-card-image::before {
display: block;
padding-bottom: 18.75%;
content: "";
}
.no-image .gh-card-image {
display: none;
}
.gh-card-image img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 10px;
}
.gh-card-title {
font-size: var(--title-font-size);
text-align: center;
}
.gh-card-excerpt {
text-align: center;
padding-top: 10px;
}
.kg-width-full .gh-card-title {
font-size: clamp(3.2rem, 2.4rem + 2.5vw, 6.4rem);
}
.gh-feed {
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: var(--gap);
row-gap: calc(var(--gap) * 2);
}
@media (max-width: 991px) {
.gh-feed {
display: grid;
grid-template-columns: 1fr;
row-gap: calc(var(--gap) * 2);
}
}
/* Article
/* ---------------------------------------------------------- */
.gh-article-meta {
top: 0;
bottom: 0;
z-index: 10;
grid-row-start: 1;
width: 100%;
margin: 0 !important;
}
.gh-article-meta-inner {
position: sticky;
top: 48px;
display: flex;
flex-direction: column;
}
.gh-article-meta .gh-author-image {
width: 72px;
height: 72px;
margin-bottom: 16px;
}
.gh-article-meta .gh-author-name {
font-size: 1.9rem;
letter-spacing: -0.01em;
}
.gh-article-meta .gh-author-name a {
color: var(--color-darker-gray);
text-decoration: none;
}
.gh-article-date {
margin-top: 4px;
font-size: 1.4rem;
font-weight: 480;
color: var(--color-secondary-text);
}
.gh-article-tag {
width: fit-content;
padding: 2px 12px;
margin-top: 20px;
font-size: 1.5rem;
font-weight: 700;
color: var(--tag-color, var(--color-darker-gray)) !important;
text-decoration: none !important;
letter-spacing: -0.01em;
border: 2px solid var(--color-border);
border-radius: 24px;
}
.gh-content .gh-article-header {
grid-row-start: 1;
grid-column: 4 / span 9;
margin-top: 0;
margin-bottom: clamp(4.8rem, 1.43vw + 4.11rem, 6.4rem);
}
.gh-article-title {
grid-column: 1 / span 9;
font-size: clamp(4rem, 2.86vw + 2.63rem, 7.2rem);
font-weight: 800;
line-height: 1;
letter-spacing: -0.03em;
}
.page-template .no-image .gh-article-title {
grid-column: 4 / span 6;
}
.gh-article-excerpt {
grid-column: 1 / span 9;
max-width: 840px;
font-size: clamp(1.8rem, 0.54vw + 1.54rem, 2.4rem);
font-weight: 500;
line-height: 1.45;
}
.page-template .no-image .gh-article-excerpt {
grid-column: 4 / span 6;
}
.gh-article-excerpt .emoji {
color: initial;
}
.gh-article-image {
grid-column: 1 / span 12;
margin-top: clamp(4rem, 3rem + 3.125vw, 8rem);
}
.gh-content {
--content-spacing-multiplier: 1.5;
position: relative;
margin-top: clamp(4rem, 3rem + 3.125vw, 8rem);
line-height: 1.7;
}
:is(.post-template, .page-template) .no-image .gh-content {
margin-top: clamp(4rem, 2.14vw + 2.97rem, 6.4rem);
}
.gh-content > [id] {
font-weight: 800;
}
.gh-content > :is(p, ul, ol) {
font-weight: 480;
}
.gh-article-footer {
margin-top: clamp(6.4rem, 3rem + 10.625vw, 20rem);
}
@media (min-width: 992px) {
.gh-article-meta {
position: absolute;
grid-column: 1 / span 3;
}
}
@media (max-width: 991px) {
:is(.gh-article-title, .gh-article-excerpt),
.gh-content > .gh-article-header {
grid-column: 1 / span 10;
}
.gh-article-meta {
margin-bottom: 32px !important;
}
.no-image .gh-article-meta {
grid-row-start: 2;
}
.gh-article-meta-inner {
flex-direction: row;
align-items: center;
}
.gh-article-meta .gh-author-image {
width: 64px;
height: 64px;
margin-right: 12px;
margin-bottom: 0;
}
.gh-article-meta-wrapper {
flex-grow: 1;
}
.gh-article-tag {
margin-top: 0;
}
}
@media (max-width: 767px) {
:is(.gh-article-title, .gh-article-excerpt),
.gh-content > .gh-article-header {
grid-column: 1 / span 12;
}
.gh-content {
font-size: var(--content-font-size);
}
}
/* Navigation
/* ---------------------------------------------------------- */
.gh-navigation {
grid-column: 1 / span 12;
font-size: clamp(2rem, 1.7rem + 0.9375vw, 3.2rem);
font-weight: 800;
letter-spacing: -0.02em;
}
/* Footer
/* ---------------------------------------------------------- */
.gh-foot {
padding-top: clamp(8rem, 4.55vw + 6.18rem, 12rem);
padding-bottom: clamp(8rem, 4.55vw + 6.18rem, 12rem);
}
.gh-foot-inner {
display: flex;
flex-direction: column;
gap: 24px;
align-items: center;
}
.gh-foot-menu {
font-size: 1.6rem;
font-weight: 700;
}
.gh-copyright {
font-size: 1.4rem;
}
.social-media {
display: flex;
flex-flow: row nowrap;
column-gap: 10px;
}
.social-icon {
height: 32px;
width: 32px;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,93 @@
Copyright 2024 The Wanted Sans Project Authors (https://github.com/wanteddev/wanted-sans)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

5
dist/bifocal/assets/icons/email.svg vendored Normal file
View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="30" height="30" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-mail" id="email">
<title>Mail</title>
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>

After

Width:  |  Height:  |  Size: 401 B

13
dist/bifocal/assets/icons/linkedin.svg vendored Normal file
View File

@ -0,0 +1,13 @@
<svg id="linkedin" fill="currentColor" height="800px" width="800px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 310 310" xml:space="preserve">
<g id="XMLID_801_">
<path id="XMLID_802_" d="M72.16,99.73H9.927c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5H72.16c2.762,0,5-2.238,5-5V104.73
C77.16,101.969,74.922,99.73,72.16,99.73z"/>
<path id="XMLID_803_" d="M41.066,0.341C18.422,0.341,0,18.743,0,41.362C0,63.991,18.422,82.4,41.066,82.4
c22.626,0,41.033-18.41,41.033-41.038C82.1,18.743,63.692,0.341,41.066,0.341z"/>
<path id="XMLID_804_" d="M230.454,94.761c-24.995,0-43.472,10.745-54.679,22.954V104.73c0-2.761-2.238-5-5-5h-59.599
c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5h62.097c2.762,0,5-2.238,5-5v-98.918c0-33.333,9.054-46.319,32.29-46.319
c25.306,0,27.317,20.818,27.317,48.034v97.204c0,2.762,2.238,5,5,5H305c2.762,0,5-2.238,5-5V194.995
C310,145.43,300.549,94.761,230.454,94.761z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 979 B

View File

@ -0,0 +1,5 @@
<svg id="mastodon" role="img" viewBox="0 0 24 24" width="30" height="30" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<title>Mastodon</title>
<path
d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

5
dist/bifocal/assets/icons/matrix.svg vendored Normal file
View File

@ -0,0 +1,5 @@
<svg id="matrix" role="img" viewBox="0 0 24 24" width="30" height="30" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<title>Matrix</title>
<path
d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z" />
</svg>

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

View File

@ -0,0 +1 @@
<svg width="264" height="88" viewBox="0 0 264 88" xmlns="http://www.w3.org/2000/svg"><title>default-skin 2</title><g fill="none" fill-rule="evenodd"><g><path d="M67.002 59.5v3.768c-6.307.84-9.184 5.75-10.002 9.732 2.22-2.83 5.564-5.098 10.002-5.098V71.5L73 65.585 67.002 59.5z" id="Shape" fill="#fff"/><g fill="#fff"><path d="M13 29v-5h2v3h3v2h-5zM13 15h5v2h-3v3h-2v-5zM31 15v5h-2v-3h-3v-2h5zM31 29h-5v-2h3v-3h2v5z" id="Shape"/></g><g fill="#fff"><path d="M62 24v5h-2v-3h-3v-2h5zM62 20h-5v-2h3v-3h2v5zM70 20v-5h2v3h3v2h-5zM70 24h5v2h-3v3h-2v-5z"/></g><path d="M20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66z" fill="#fff"/><path d="M111.785 65.03L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03z" fill="#fff"/><path d="M152.215 65.03L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03z" fill="#fff"/><g><path id="Rectangle-11" fill="#fff" d="M160.957 28.543l-3.25-3.25-1.413 1.414 3.25 3.25z"/><path d="M152.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" id="Oval-1" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M150 21h5v1h-5z"/></g><g><path d="M116.957 28.543l-1.414 1.414-3.25-3.25 1.414-1.414 3.25 3.25z" fill="#fff"/><path d="M108.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M106 21h5v1h-5z"/><path fill="#fff" d="M109.043 19.008l-.085 5-1-.017.085-5z"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
dist/bifocal/assets/images/oneko.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
dist/bifocal/assets/images/preloader.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

File diff suppressed because one or more lines are too long

54
dist/bifocal/assets/js/main.js vendored Normal file
View File

@ -0,0 +1,54 @@
function initParallax() {
jarallax(document.querySelectorAll('.has-parallax-feed .gh-card'), {
speed: 0.8,
});
}
(function () {
if (!document.body.classList.contains('has-background-about')) return;
const about = document.querySelector('.gh-about');
if (!about) return;
const image = about.querySelector('.gh-about-image');
if (!image.naturalWidth) {
imagesLoaded(image, function () {
about.style.setProperty('--about-height', image.clientWidth * image.naturalHeight / image.naturalWidth + 'px');
});
}
})();
(function () {
initParallax();
})();
(function () {
const toggle = document.querySelector('[data-toggle-comments]');
if (!toggle) return;
toggle.addEventListener('click', function () {
document.body.classList.toggle('comments-opened');
});
})();
(function () {
const element = document.querySelector('.gh-article-excerpt');
if (!element) return;
let text = element.textContent;
const emojiRE = /\p{EPres}|\p{ExtPict}/gu;
const emojis = text.match(emojiRE);
if (!emojis) return;
emojis.forEach(function (emoji) {
text = text.replace(emoji, `<span class="emoji">${emoji}</span>`);
});
element.innerHTML = text;
})();
(function () {
pagination(true, initParallax);
})();

239
dist/bifocal/assets/js/oneko.js vendored Normal file
View File

@ -0,0 +1,239 @@
// oneko.js: https://github.com/adryd325/oneko.js
(function oneko() {
const isReducedMotion =
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
if (isReducedMotion) return;
const nekoEl = document.createElement("div");
let nekoPosX = 32;
let nekoPosY = 32;
let mousePosX = 0;
let mousePosY = 0;
let frameCount = 0;
let idleTime = 0;
let idleAnimation = null;
let idleAnimationFrame = 0;
const nekoSpeed = 10;
const spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "fixed";
nekoEl.style.pointerEvents = "none";
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
nekoEl.style.zIndex = Number.MAX_VALUE;
let nekoFile = "/assets/images/oneko.gif"
const curScript = document.currentScript
if (curScript && curScript.dataset.cat) {
nekoFile = curScript.dataset.cat
}
nekoEl.style.backgroundImage = `url(${nekoFile})`;
document.body.appendChild(nekoEl);
document.addEventListener("mousemove", function (event) {
mousePosX = event.clientX;
mousePosY = event.clientY;
});
window.requestAnimationFrame(onAnimationFrame);
}
let lastFrameTimestamp;
function onAnimationFrame(timestamp) {
// Stops execution if the neko element is removed from DOM
if (!nekoEl.isConnected) {
return;
}
if (!lastFrameTimestamp) {
lastFrameTimestamp = timestamp;
}
if (timestamp - lastFrameTimestamp > 100) {
lastFrameTimestamp = timestamp
frame()
}
window.requestAnimationFrame(onAnimationFrame);
}
function setSprite(name, frame) {
const sprite = spriteSets[name][frame % spriteSets[name].length];
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime += 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
if (nekoPosX < 32) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < 32) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - 32) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - 32) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame += 1;
}
function frame() {
frameCount += 1;
const diffX = nekoPosX - mousePosX;
const diffY = nekoPosY - mousePosY;
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime -= 1;
return;
}
let direction;
direction = diffY / distance > 0.5 ? "N" : "";
direction += diffY / distance < -0.5 ? "S" : "";
direction += diffX / distance > 0.5 ? "W" : "";
direction += diffX / distance < -0.5 ? "E" : "";
setSprite(direction, frameCount);
nekoPosX -= (diffX / distance) * nekoSpeed;
nekoPosY -= (diffY / distance) * nekoSpeed;
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
}
init();
})();

74
dist/bifocal/default.hbs vendored Normal file
View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="{{@site.locale}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{meta_title}}</title>
<link rel="stylesheet" href="{{asset "built/screen.css"}}">
{{#is "home"}}
{{#if @site.cover_image}}
<link rel="preload" as="image" href="{{@site.cover_image}}">
{{/if}}
{{/is}}
{{ghost_head}}
</head>
<body class="{{body_class}}{{{block "body_class"}}} is-head-{{#match @custom.navigation_layout "Logo on the left"}}left-logo{{else match @custom.navigation_layout "Logo in the middle"}}middle-logo{{else}}stacked{{/match}}">
<div class="gh-site">
<header id="gh-head" class="gh-head gh-outer">
<div class="gh-head-inner gh-inner">
<div class="gh-head-brand">
<div class="gh-head-brand-wrapper">
<a class="gh-head-logo" href="{{@site.url}}">
{{#if @site.logo}}
<img src="{{@site.logo}}" alt="{{@site.title}}">
{{else}}
{{@site.title}}
{{/if}}
</a>
</div>
<button class="gh-search gh-icon-btn" aria-label="Search this site" data-ghost-search>{{> "icons/search"}}</button>
<button class="gh-burger"></button>
</div>
<nav class="gh-head-menu">
{{navigation}}
</nav>
<div class="gh-head-actions">
<button class="gh-search gh-icon-btn" aria-label="Search this site" data-ghost-search>{{> "icons/search"}}</button>
</div>
</div>
</header>
{{{body}}}
<footer class="gh-foot gh-outer">
<div class="gh-foot-inner gh-inner">
<div class="gh-copyright">
{{#if @custom.footer_text}}
{{@custom.footer_text}}
{{/if}}
</div>
{{> "social-media"}}
</div>
</footer>
</div>
{{#is "post, page"}}
{{> "pswp"}}
{{/is}}
<script src="{{asset "built/main.min.js"}}"></script>
<script src="{{asset "js/oneko.js"}}"></script>
{{ghost_foot}}
</body>
</html>

101
dist/bifocal/gulpfile.js vendored Normal file
View File

@ -0,0 +1,101 @@
const {series, parallel, watch, src, dest} = require('gulp');
const pump = require('pump');
const fs = require('fs');
const order = require('ordered-read-streams');
// gulp plugins and utils
const livereload = require('gulp-livereload');
const postcss = require('gulp-postcss');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const beeper = require('beeper');
const zip = require('gulp-zip');
// postcss plugins
const easyimport = require('postcss-easy-import');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
function serve(done) {
livereload.listen();
done();
}
function handleError(done) {
return function (err) {
if (err) {
beeper();
}
return done(err);
};
};
function hbs(done) {
pump([
src(['*.hbs', 'partials/**/*.hbs']),
livereload()
], handleError(done));
}
function css(done) {
pump([
src('assets/css/screen.css', {sourcemaps: true}),
postcss([
easyimport,
autoprefixer(),
cssnano()
]),
dest('assets/built/', {sourcemaps: '.'}),
livereload()
], handleError(done));
}
function getJsFiles(version) {
const jsFiles = [
src(`node_modules/@tryghost/shared-theme-assets/assets/js/${version}/lib/**/*.js`),
src(`node_modules/@tryghost/shared-theme-assets/assets/js/${version}/main.js`),
];
if (fs.existsSync(`assets/js/lib`)) {
jsFiles.push(src(`assets/js/lib/*.js`));
}
jsFiles.push(src(`assets/js/main.js`));
return jsFiles;
}
function js(done) {
pump([
order(getJsFiles('v1'), {sourcemaps: true}),
concat('main.min.js'),
uglify(),
dest('assets/built/', {sourcemaps: '.'}),
livereload()
], handleError(done));
}
function zipper(done) {
const filename = require('./package.json').name + '.zip';
pump([
src([
'**',
'!node_modules', '!node_modules/**',
'!dist', '!dist/**',
'!yarn-error.log'
]),
zip(filename),
dest('dist/')
], handleError(done));
}
const hbsWatcher = () => watch(['*.hbs', 'partials/**/*.hbs'], hbs);
const cssWatcher = () => watch('assets/css/**/*.css', css);
const jsWatcher = () => watch('assets/js/**/*.js', js);
const watcher = parallel(hbsWatcher, cssWatcher, jsWatcher);
const build = series(css, js);
exports.build = build;
exports.zip = series(build, zipper);
exports.default = series(build, serve, watcher);

24
dist/bifocal/index.hbs vendored Normal file
View File

@ -0,0 +1,24 @@
{{!< default}}
<section class="gh-about gh-outer">
<div class="gh-about-inner gh-inner">
{{#if @custom.primary_header}}
<h1 class="gh-about-primary">{{{@custom.primary_header}}}</h1>
{{/if}}
{{#if @custom.secondary_header}}
<p class="gh-about-secondary">{{{@custom.secondary_header}}}</p>
{{/if}}
</div>
</section>
<main class="gh-main gh-outer">
<div class="gh-feed gh-inner">
{{#foreach posts}}
{{#if featured}}
{{> "loop"}}
{{/if}}
{{/foreach}}
</div>
</main>

97
dist/bifocal/package.json vendored Normal file
View File

@ -0,0 +1,97 @@
{
"name": "bifocal",
"description": "A Ghost theme, based on Solo",
"version": "1.0.0",
"private": true,
"engines": {
"ghost": ">=5.0.0"
},
"license": "MIT",
"author": {
"name": "Jean Viscogliosi-Pate",
"email": "jean@viscogliosi-pate.com",
"url": "viscogliosi-pate.com"
},
"keywords": [
"ghost",
"theme",
"ghost-theme"
],
"config": {
"posts_per_page": 6,
"image_sizes": {
"xs": {
"width": 150
},
"s": {
"width": 300
},
"m": {
"width": 720
},
"l": {
"width": 960
},
"xl": {
"width": 1200
},
"xxl": {
"width": 2000
}
},
"card_assets": true,
"custom": {
"navigation_layout": {
"type": "select",
"options": ["Logo on the left", "Logo in the middle", "Stacked"],
"default": "Logo on the left"
},
"primary_header": {
"type": "text",
"default": "Hi! Welcome."
},
"secondary_header": {
"type": "text",
"default": "I had wondered, \"Why do I continue?\" It must be worth the effort, since I do not hesitate. I now know the answer: because there is ice cream waiting for me."
},
"footer_text": {
"type": "text",
"default": "Contact me!"
},
"email_address": {
"type": "text"
},
"mastodon_link": {
"type": "text"
},
"matrix_contact": {
"type": "text"
},
"linkedin_contact": {
"type": "text"
}
}
},
"scripts": {
"dev": "gulp",
"test": "gscan .",
"zip": "gulp zip"
},
"devDependencies": {
"@tryghost/shared-theme-assets": "2.4.3",
"autoprefixer": "10.4.19",
"beeper": "2.1.0",
"cssnano": "7.0.2",
"gscan": "4.43.1",
"gulp": "5.0.0",
"gulp-concat": "2.6.1",
"gulp-livereload": "4.0.2",
"gulp-postcss": "10.0.0",
"gulp-uglify": "3.0.2",
"gulp-zip": "5.1.0",
"ordered-read-streams": "2.0.0",
"postcss": "8.4.38",
"postcss-easy-import": "4.0.0",
"pump": "3.0.0"
}
}

24
dist/bifocal/page.hbs vendored Normal file
View File

@ -0,0 +1,24 @@
{{!< default}}
{{#post}}
<main class="gh-main gh-outer">
<div class="gh-inner">
<article class="gh-article {{post_class}}">
{{#match @page.show_title_and_feature_image}}
<header class="gh-article-header gh-canvas">
<h1 class="gh-article-title">{{title}}</h1>
{{#if custom_excerpt}}
<p class="gh-article-excerpt">{{custom_excerpt}}</p>
{{/if}}
</header>
{{/match}}
<section class="gh-content gh-canvas">
{{content}}
</section>
</article>
</div>
</main>
{{/post}}

18
dist/bifocal/partials/feature-image.hbs vendored Normal file
View File

@ -0,0 +1,18 @@
{{#if feature_image}}
<figure class="gh-article-image{{#if feature_image_caption}} has-caption{{/if}}">
<img
srcset="{{img_url feature_image size="s"}} 300w,
{{img_url feature_image size="m"}} 720w,
{{img_url feature_image size="l"}} 960w,
{{img_url feature_image size="xl"}} 1200w,
{{img_url feature_image size="xxl"}} 2000w,
{{img_url feature_image}}"
sizes="(max-width: 1200px) 100vw, 1200px"
src="{{img_url feature_image size="xl"}}"
alt="{{title}}"
>
{{#if feature_image_caption}}
<figcaption>{{feature_image_caption}}</figcaption>
{{/if}}
</figure>
{{/if}}

View File

@ -0,0 +1,9 @@
{{!-- Outputs the descriptions of ONLY internal tags with NO icon --}}
{{#if tags}}
{{#foreach tags visibility="internal"}}
{{^if feature_image}}
{{description}}
{{/if}}
{{/foreach}}
{{/if}}

19
dist/bifocal/partials/get-meta-tags.hbs vendored Normal file
View File

@ -0,0 +1,19 @@
{{!-- Outputs a bullet list of icons and descriptions for ONLY internal tags with an icon --}}
{{#if tags}}
<ul class="tag-list">
{{#foreach tags visibility="internal"}}
{{#if feature_image}}
<li>
<svg class="tag-icon" role="img" title="{{meta_title}}" alt="{{meta_title}}">
<use href="{{img_url feature_image}}#{{meta_description}}">
</svg>
<div class=tag-text>
<p>{{description}}</p>
</div>
</li>
{{/if}}
{{/foreach}}
</ul>
{{/if}}

5
dist/bifocal/partials/icons/email.hbs vendored Normal file
View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-mail">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M22 7.535v9.465a3 3 0 0 1 -2.824 2.995l-.176 .005h-14a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-9.465l9.445 6.297l.116 .066a1 1 0 0 0 .878 0l.116 -.066l9.445 -6.297z" />
<path d="M19 4c1.08 0 2.027 .57 2.555 1.427l-9.555 6.37l-9.555 -6.37a2.999 2.999 0 0 1 2.354 -1.42l.201 -.007h14z"/>
</svg>

After

Width:  |  Height:  |  Size: 505 B

View File

@ -0,0 +1,12 @@
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 310 310" xml:space="preserve">
<g id="XMLID_801_">
<path id="XMLID_802_" d="M72.16,99.73H9.927c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5H72.16c2.762,0,5-2.238,5-5V104.73
C77.16,101.969,74.922,99.73,72.16,99.73z"/>
<path id="XMLID_803_" d="M41.066,0.341C18.422,0.341,0,18.743,0,41.362C0,63.991,18.422,82.4,41.066,82.4
c22.626,0,41.033-18.41,41.033-41.038C82.1,18.743,63.692,0.341,41.066,0.341z"/>
<path id="XMLID_804_" d="M230.454,94.761c-24.995,0-43.472,10.745-54.679,22.954V104.73c0-2.761-2.238-5-5-5h-59.599
c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5h62.097c2.762,0,5-2.238,5-5v-98.918c0-33.333,9.054-46.319,32.29-46.319
c25.306,0,27.317,20.818,27.317,48.034v97.204c0,2.762,2.238,5,5,5H305c2.762,0,5-2.238,5-5V194.995
C310,145.43,300.549,94.761,230.454,94.761z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 938 B

View File

@ -0,0 +1,5 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<title>Mastodon</title>
<path
d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,5 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<title>Matrix</title>
<path
d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z" />
</svg>

After

Width:  |  Height:  |  Size: 980 B

5
dist/bifocal/partials/icons/rss.hbs vendored Normal file
View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rss">
<path d="M4 11a9 9 0 0 1 9 9"></path>
<path d="M4 4a16 16 0 0 1 16 16"></path>
<circle cx="5" cy="19" r="1"></circle>
</svg>

After

Width:  |  Height:  |  Size: 324 B

View File

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.5 17.5L12.5 12.5L17.5 17.5ZM14.1667 8.33333C14.1667 9.09938 14.0158 9.85792 13.7226 10.5657C13.4295 11.2734 12.9998 11.9164 12.4581 12.4581C11.9164 12.9998 11.2734 13.4295 10.5657 13.7226C9.85792 14.0158 9.09938 14.1667 8.33333 14.1667C7.56729 14.1667 6.80875 14.0158 6.10101 13.7226C5.39328 13.4295 4.75022 12.9998 4.20854 12.4581C3.66687 11.9164 3.23719 11.2734 2.94404 10.5657C2.65088 9.85792 2.5 9.09938 2.5 8.33333C2.5 6.78624 3.11458 5.30251 4.20854 4.20854C5.30251 3.11458 6.78624 2.5 8.33333 2.5C9.88043 2.5 11.3642 3.11458 12.4581 4.20854C13.5521 5.30251 14.1667 6.78624 14.1667 8.33333Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 802 B

View File

@ -20,7 +20,14 @@
<div class="post-card-tags"> <div class="post-card-tags">
{{> "get-meta-tags"}} {{> "get-meta-tags"}}
</div> </div>
<h2 class="gh-card-title">{{title}}</h2>
<h2 class="gh-card-title">
{{title}}
<div class="tag-desc">
{{> "get-desc-tags"}}
</div>
</h2>
{{#if custom_excerpt}} {{#if custom_excerpt}}
<p class="gh-card-excerpt">{{excerpt}}</p> <p class="gh-card-excerpt">{{excerpt}}</p>
{{/if}} {{/if}}

41
dist/bifocal/partials/pswp.hbs vendored Normal file
View File

@ -0,0 +1,41 @@
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<div class="pswp__bg"></div>
<div class="pswp__scroll-wrap">
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>

25
dist/bifocal/partials/social-media.hbs vendored Normal file
View File

@ -0,0 +1,25 @@
<div class="social-media">
{{#if @custom.email_address}}
<a class="social-icon" alt="Email" href={{@custom.email_address}}>
{{> "icons/email"}}
</a>
{{/if}}
{{#if @custom.mastodon_link}}
<a class="social-icon" alt="Mastodon" href={{@custom.mastodon_link}}>
{{> "icons/mastodon"}}
</a>
{{/if}}
{{#if @custom.matrix_contact}}
<a class="social-icon" alt="Matrix" href={{@custom.matrix_contact}}>
{{> "icons/matrix"}}
</a>
{{/if}}
{{#if @custom.linkedin_contact}}
<a class="social-icon" alt="LinkedIn" href={{@custom.linkedin_contact}}>
{{> "icons/linkedin"}}
</a>
{{/if}}
</div>

34
dist/bifocal/post.hbs vendored Normal file
View File

@ -0,0 +1,34 @@
{{!< default}}
<main class="gh-main gh-outer">
<div class="gh-inner">
{{#post}}
<article class="gh-article {{post_class}}">
<div class="post-card-tags">
{{> "get-meta-tags"}}
</div>
{{#if feature_image}}
<header class="gh-article-header gh-canvas">
<h1 class="gh-article-title">{{title}}</h1>
{{#if custom_excerpt}}
<p class="gh-article-excerpt">{{custom_excerpt}}</p>
{{/if}}
</header>
{{/if}}
<section class="gh-content gh-canvas">
{{content}}
{{#unless feature_image}}
<header class="gh-article-header">
<h1 class="gh-article-title">{{title}}</h1>
{{#if custom_excerpt}}
<p class="gh-article-excerpt">{{custom_excerpt}}</p>
{{/if}}
</header>
{{/unless}}
</section>
</article>
{{/post}}
</div>
</main>

112
dist/bifocal/robots.txt vendored Normal file
View File

@ -0,0 +1,112 @@
# Blocks AI web scrapers
# Crawlers sourced from Dark Visitors and https://github.com/ai-robots-txt/ai.robots.txt
# Used by Google, for Gemini assistant and Vertex AI
User-agent: AdsBot-Google
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: GoogleOther
Disallow: /
# Used by Anthropic, for Claude
User-agent: anthropic-ai
Disallow: /
User-agent: Claude-Web
Disallow: /
User-agent: ClaudeBot
Disallow: /
# Used by ByteDance for Doubao
User-agent: Bytespider
Disallow: /
# Used by Common Crawl for open source repository of web crawl data
User-agent: CCBot
Disallow: /
# Used by OpenAI GPT for updating content and ChatGPT plug-ins
User-agent: ChatGPT-User
Disallow: /
User-agent: GPTBot
Disallow: /
# Sells crawled data to LLM companies
User-agent: Diffbot
Disallow: /
# For speech recognition language models by Meta
User-agent: FacebookBot
Disallow: /
# Used by Omigli, sells crawled data to LLM companies
User-agent: omgilibot
Disallow: /
User-agent: omgili
Disallow: /
# Undocumented
User-agent: Amazonbot
Disallow: /
User-agent: Applebot
Disallow: /
User-agent: AwarioRssBot
Disallow: /
User-agent: AwarioSmartBot
Disallow: /
User-agent: cohere-ai
Disallow: /
User-agent: DataForSeoBot
Disallow: /
User-agent: FriendlyCrawler
Disallow: /
User-agent: img2dataset
Disallow: /
User-agent: ImagesiftBot
Disallow: /
User-agent: magpie-crawler
Disallow: /
User-agent: Meltwater
Disallow: /
User-agent: peer39_crawler
Disallow: /
User-agent: peer39_crawler/1.0
Disallow: /
User-agent: PerplexityBot
Disallow: /
User-agent: PiplBot
Disallow: /
User-agent: Seekr
Disallow: /
User-agent: YouBot
Disallow: /

21
dist/bifocal/tag.hbs vendored Normal file
View File

@ -0,0 +1,21 @@
{{!< default}}
<main class="gh-main gh-outer">
<div class="gh-inner">
{{#tag}}
<h1 class="gh-article-title">{{name}}</h1>
<a class="feed-cta" href="feed">
<p>Subscribe to updates by RSS</p>
<div class="social-icon" alt="RSS">
{{> "icons/rss"}}
</div>
</a>
{{/tag}}
<div class="gh-feed">
{{#foreach posts}}
{{> "loop"}}
{{/foreach}}
</div>
</div>
</main>

5129
dist/bifocal/yarn.lock vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,24 @@
{{!< default}} {{!< default}}
<section class="gh-about gh-outer">
<div class="gh-about-inner gh-inner">
{{#if @custom.primary_header}}
<h1 class="gh-about-primary">{{{@custom.primary_header}}}</h1>
{{/if}}
{{#if @custom.secondary_header}}
<p class="gh-about-secondary">{{{@custom.secondary_header}}}</p>
{{/if}}
</div>
</section>
<main class="gh-main gh-outer"> <main class="gh-main gh-outer">
<div class="gh-feed gh-inner"> <div class="gh-feed gh-inner">
{{#foreach posts}} {{#foreach posts}}
{{> "box-info"}} {{#if featured}}
{{> "loop"}}
{{/if}}
{{/foreach}} {{/foreach}}
</div> </div>
</main> </main>

1
node_modules/.bin/autoprefixer generated vendored
View File

@ -1 +0,0 @@
../autoprefixer/bin/autoprefixer

1
node_modules/.bin/browserslist generated vendored
View File

@ -1 +0,0 @@
../browserslist/cli.js

1
node_modules/.bin/bunyan generated vendored
View File

@ -1 +0,0 @@
../bunyan/bin/bunyan

1
node_modules/.bin/color-support generated vendored
View File

@ -1 +0,0 @@
../color-support/bin.js

1
node_modules/.bin/convert-path generated vendored
View File

@ -1 +0,0 @@
../@stdlib/utils-convert-path/bin/cli

1
node_modules/.bin/crc32 generated vendored
View File

@ -1 +0,0 @@
../crc-32/bin/crc32.njs

1
node_modules/.bin/css-beautify generated vendored
View File

@ -1 +0,0 @@
../js-beautify/js/bin/css-beautify.js

1
node_modules/.bin/cssesc generated vendored
View File

@ -1 +0,0 @@
../cssesc/bin/cssesc

1
node_modules/.bin/cwd generated vendored
View File

@ -1 +0,0 @@
../@stdlib/process-cwd/bin/cli

1
node_modules/.bin/editorconfig generated vendored
View File

@ -1 +0,0 @@
../editorconfig/bin/editorconfig

1
node_modules/.bin/exists generated vendored
View File

@ -1 +0,0 @@
../@stdlib/fs-exists/bin/cli

1
node_modules/.bin/extract-zip generated vendored
View File

@ -1 +0,0 @@
../extract-zip/cli.js

1
node_modules/.bin/gscan generated vendored
View File

@ -1 +0,0 @@
../gscan/bin/cli.js

1
node_modules/.bin/gulp generated vendored
View File

@ -1 +0,0 @@
../gulp/bin/gulp.js

1
node_modules/.bin/handlebars generated vendored
View File

@ -1 +0,0 @@
../handlebars/bin/handlebars

View File

@ -1 +0,0 @@
../@stdlib/assert-has-float32array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-float64array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-int16array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-int32array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-int8array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-node-buffer-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-symbol-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-tostringtag-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-uint16array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-uint32array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-uint8array-support/bin/cli

View File

@ -1 +0,0 @@
../@stdlib/assert-has-uint8clampedarray-support/bin/cli

1
node_modules/.bin/html-beautify generated vendored
View File

@ -1 +0,0 @@
../js-beautify/js/bin/html-beautify.js

1
node_modules/.bin/is-regexp-string generated vendored
View File

@ -1 +0,0 @@
../@stdlib/assert-is-regexp-string/bin/cli

1
node_modules/.bin/js-beautify generated vendored
View File

@ -1 +0,0 @@
../js-beautify/js/bin/js-beautify.js

1
node_modules/.bin/library-manifest generated vendored
View File

@ -1 +0,0 @@
../@stdlib/utils-library-manifest/bin/cli

1
node_modules/.bin/lowercase generated vendored
View File

@ -1 +0,0 @@
../@stdlib/string-lowercase/bin/cli

1
node_modules/.bin/mime generated vendored
View File

@ -1 +0,0 @@
../mime/cli.js

1
node_modules/.bin/mkdirp generated vendored
View File

@ -1 +0,0 @@
../mkdirp/bin/cmd.js

1
node_modules/.bin/nanoid generated vendored
View File

@ -1 +0,0 @@
../nanoid/bin/nanoid.cjs

Some files were not shown because too many files have changed in this diff Show More