Author: Pedro Lucas Porcellis <porcellis@eletrotupi.com>
design: adopt new typography and theme switch
assets/style.scss | 509 ++++++++++++++++++++------- assets/typo.scss | 333 +---------------- i18n/en.toml | 2 i18n/pt-br.toml | 2 layouts/_partials/bio.html | 2 layouts/_partials/css/syntax-dark.css | 4 layouts/_partials/css/syntax-light.css | 2 layouts/_partials/head.html | 16 layouts/_partials/masthead.html | 9 layouts/_partials/site-title.html | 4 layouts/_partials/theme-toggle.html | 3 layouts/baseof.html | 17 layouts/home.html | 14 layouts/list.html | 20 layouts/single.html | 23
diff --git a/assets/style.scss b/assets/style.scss index a089747a87ce0b05fd001ea24afe06e525ffa6d8..9ea13c3cb1c28684d7fc4b77ec1cd89c08c49441 100644 --- a/assets/style.scss +++ b/assets/style.scss @@ -1,223 +1,450 @@ @import 'typo'; -:root { - --content-width: 98rem; - --body-padding: 6.4rem; - --page-padding: 1.6rem; - - --font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; +/* ------------------------------------------------------------------------- */ +/* Tokens */ +/* ------------------------------------------------------------------------- */ - --font-family-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; +:root { + color-scheme: light; - --font-size-base: 11px; - --base-space: 1.25em; + --bg-canvas: #f5f2eb; + --bg-surface: #ede8de; + --bg-code-header: #e5decfa0; + --text-primary: #1c1917; + --text-secondary: #44403c; + --text-muted: #78716c; + --accent-signal: #e05626; + --border-subtle: #e2dcce; + --border-dashed: #d6cfbf; + --code-keyword: #c0392b; + --code-string: #2e7d32; - // general colors - --rgb-black: 0, 0, 0; - --rgb-almost-black: 35, 28, 51; - --rgb-white: 255, 255, 255; - --rgb-almost-white: 236, 233, 230; - --rgb-navy: 28, 28, 40; - --rgb-blue: 80, 162, 255; + --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, + Consolas, 'Liberation Mono', monospace; + --font-serif: 'Lora', Georgia, Cambria, 'Times New Roman', Times, serif; - --rgb-ink: var(--rgb-almost-black); + --measure: 45rem; + --pad-block: 4rem; + --pad-inline: 1.5rem; +} - --color-border: rgba(var(--rgb-ink), 0.15); - --color-white: rgb(var(--rgb-white)); - --color-black: rgb(var(--rgb-black)); - --color-navy: rgb(var(--rgb-navy)); - --color-blue: rgb(var(--rgb-blue)); +.dark { + color-scheme: dark; - --bg-color: var(--color-white); - --color-txt: rgb(var(--rgb-ink)); - --color-txt-action: var(--color-blue); - --color-txt-subtle: rgba(var(--rgb-ink), 0.66); - --color-code-container: #ebebeb; + --bg-canvas: #121110; + --bg-surface: #1a1816; + --bg-code-header: #23201d; + --text-primary: #f2ede4; + --text-secondary: #c2bcb0; + --text-muted: #7e776e; + --accent-signal: #f16834; + --border-subtle: #2b2622; + --border-dashed: #38322b; + --code-keyword: #e27150; + --code-string: #81c784; } - -// sizes -@media (min-width: 60em) { +@media (max-width: 40em) { :root { - --font-size-x-small: 1.4rem; - --font-size-small: 1.6rem; - --font-size-medium: 1.8rem; - --font-size-large: 2rem; - --font-size-x-large: 2.8rem; + --pad-block: 2rem; + --pad-inline: 1.25rem; } } -@media (prefers-color-scheme: dark) { - :root:not([data-color-scheme="light"]) { - --rgb-almost-black: 27, 39, 51; - --rgb-ink: var(--rgb-almost-white); +/* ------------------------------------------------------------------------- */ +/* Base */ +/* ------------------------------------------------------------------------- */ - --bg-color: var(--color-navy); - --color-code-container: #2e2e2e; - } +*, +*::before, +*::after { + box-sizing: border-box; } html { - font-family: var(--font-family); - font-size: var(--font-size-base); - font-feature-settings: "kern" 1,"liga" 1,"calt" 1; - - color: var(--color-txt); - background-color: var(--bg-color); + font-size: 100%; + -webkit-text-size-adjust: 100%; } body { - font-size: var(--font-size-medium); - padding: 0 0 var(--body-padding); + margin: 0; + padding: var(--pad-block) var(--pad-inline); + background-color: var(--bg-canvas); + color: var(--text-secondary); + font-family: var(--font-serif); + font-size: 1.125rem; + line-height: 1.8; } -main { - width: 100%; - max-width: var(--content-width); - padding: var(--page-padding); +.page-content { + max-width: var(--measure); margin: 0 auto; - position: relative; } a { - color: var(--color-txt-action); + color: var(--accent-signal); + text-decoration-thickness: 1px; + text-underline-offset: 0.15em; } -.page-content { - max-width: var(--content-width); - margin: 0 auto; +a:hover { + color: var(--text-primary); +} - @media (min-width: 40em) { - max-width: 64rem; - } +a:focus-visible, +button:focus-visible { + outline: 2px solid var(--accent-signal); + outline-offset: 2px; } -.article { - min-height: 10em; - position: relative; - padding-bottom: 5em; +/* ------------------------------------------------------------------------- */ +/* Masthead */ +/* ------------------------------------------------------------------------- */ - .article-title { - text-align: center; +.site-header { + position: relative; + text-align: center; +} - .article-date { - display: flex; - align-items: center; - justify-content: center; - margin-left: 0; - margin-right: 0; - } +.masthead__link { + display: inline-flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; + color: inherit; + text-decoration: none; +} - a { - font-weight: bold; - font-size: var(--font-size-x-large); - h2 { - margin-top: 0 !important; - } - } - } +.masthead__link:hover { + color: inherit; } .avatar { - display: inline-flex; - width: 2.625em; - height: 2.625em; + width: 2.625rem; + height: 2.625rem; border-radius: 100%; } +.masthead__title { + margin: 0; + font-family: var(--font-mono); + font-size: clamp(1.75rem, 2.2vw, 2rem); + font-weight: 600; + line-height: 1.25; + letter-spacing: -0.02em; + color: var(--text-primary); +} + +.bio { + max-width: 34rem; + margin: 1.25rem auto 0; + font-size: 1rem; + line-height: 1.7; + color: var(--text-muted); +} + +.theme-toggle { + position: absolute; + top: 0; + right: 0; + padding: 0.25rem 0.5rem; + border: 1px solid var(--border-subtle); + border-radius: 0.25rem; + background-color: var(--bg-surface); + color: var(--text-muted); + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 500; + line-height: 1.4; + text-transform: lowercase; + cursor: pointer; +} + +.theme-toggle:hover { + border-color: var(--border-dashed); + color: var(--text-primary); +} + +.theme-toggle__dot { + color: var(--accent-signal); +} + +@media (max-width: 30em) { + .theme-toggle { + position: static; + margin-top: 1.25rem; + } +} + +/* ------------------------------------------------------------------------- */ +/* Dividers */ +/* ------------------------------------------------------------------------- */ + .divisor { - position: relative; + height: 0; + margin: 2rem 0; + border-top: 1px dashed var(--border-dashed); +} - &:after { - content: " "; - width: 12rem; - border-top: 1px solid var(--color-border); - top: 0; - margin: 0 -6rem; - position: absolute; - } +/* ------------------------------------------------------------------------- */ +/* Index */ +/* ------------------------------------------------------------------------- */ + +.languages, +.translations { + margin-top: 2.5rem; + font-family: var(--font-mono); + font-size: 0.75rem; + line-height: 1.4; + text-transform: uppercase; + letter-spacing: 0.08em; + text-align: center; + color: var(--text-muted); } -article { - .footnotes { - hr { - width: 12rem; - color: var(--color-border); - } - } +.languages h3, +.translations h4 { + margin: 0 0 0.5rem; + font-size: inherit; + font-weight: 500; } -.inner-article-title { - margin-top: 5rem; +.languages ul, +.translations ul { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 1rem; + margin: 0; + padding: 0; + list-style: none; } -// utils +.languages a, +.translations a { + text-decoration: none; +} -.text-small { - font-size: var(--font-size-small); +.article-list { + margin-top: 3.5rem; } -.text-x-small { - font-size: var(--font-size-small); +.article + .article { + margin-top: 3.5rem; } -.text-center { +.article-title { text-align: center; } -.text-spaced { - letter-spacing: .25rem; +.article-title a { + text-decoration: none; } -.text-uppercase { +.article-title h2 { + margin: 0; + font-family: var(--font-mono); + font-size: clamp(1.25rem, 1.6vw, 1.375rem); + font-weight: 600; + line-height: 1.3; + color: var(--text-primary); +} + +.article-date, +.inner-article-date { + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 500; + line-height: 1.4; text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--text-muted); } -.text-subtle { - color: var(--color-txt-subtle) !important; +.article-snippet { + margin-top: 0.875rem; + font-size: 1.0625rem; + line-height: 1.75; +} + +.article-snippet p { + margin: 0; } -.mt-5 { +/* ------------------------------------------------------------------------- */ +/* Article */ +/* ------------------------------------------------------------------------- */ + +.inner-article-title { margin-top: 5rem; + text-align: center; } -.pt-2 { - padding-top: 2rem; +.inner-article-title h1 { + margin: 0.75rem 0 0; + font-family: var(--font-mono); + font-size: clamp(2.25rem, 3vw, 2.75rem); + font-weight: 700; + line-height: 1.15; + letter-spacing: -0.02em; + color: var(--text-primary); +} + +.lede { + margin: 1rem 0 0; + font-size: clamp(1.25rem, 1.6vw, 1.375rem); + font-style: italic; + line-height: 1.6; +} + +article { + margin-top: 3.5rem; + font-size: 1.125rem; + line-height: 1.8; } -.mb-3 { - margin-bottom: 3rem; +article p { + margin: 0 0 1.5rem; +} + +article h2 { + margin: 3rem 0 1rem; + font-family: var(--font-mono); + font-size: 0.875rem; + font-weight: 600; + line-height: 1.4; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--text-primary); } -.mb-5 { - margin-bottom: 5rem; +article h3 { + margin: 2rem 0 0.75rem; + font-family: var(--font-mono); + font-size: 0.9375rem; + font-weight: 600; + line-height: 1.4; + color: var(--text-primary); +} + +article ul, +article ol { + margin: 0 0 1.5rem; + padding-left: 1.5rem; +} + +article li { + margin-bottom: 0.5rem; +} + +article strong { + font-weight: 600; + color: var(--text-primary); +} + +article blockquote { + margin: 2rem 0; + padding-left: 1.5rem; + border-left: 2px solid var(--accent-signal); + font-style: italic; + color: var(--text-muted); +} + +article img { + max-width: 100%; + height: auto; +} + +article hr { + margin: 3rem 0; + border: 0; + border-top: 1px dashed var(--border-dashed); +} + +article code, +article kbd, +article samp { + padding: 0.1em 0.35em; + border-radius: 0.2rem; + background-color: var(--bg-surface); + font-family: var(--font-mono); + font-size: 0.875em; +} + +article pre code { + padding: 0; + background: none; + font-size: inherit; } .highlight { - margin: 16px 0px; - border-radius: 6px; - border: 1px solid var(--color-code-container); + margin: 2rem 0; + border: 1px solid var(--border-subtle); + border-radius: 0.375rem; + background-color: var(--bg-surface); + overflow: hidden; } .chroma { - padding: 20px; margin: 0; - overflow-y: auto; - max-width: 100%; + padding: 1.25rem; + overflow-x: auto; + font-family: var(--font-mono); + font-size: 0.8125rem; + line-height: 1.6; counter-reset: line; } -code > .line { - &:before { - color: var(--color-txt-subtle); - flex-shrink: 0; - user-selection: none; - display: inline-block; - counter-increment: line; - content: counter(line); - width: 16px; - font-size: 13px; - text-align: right; - margin-right: 20px; - } +.chroma code > .line::before { + display: inline-block; + width: 1.5rem; + margin-right: 1.25rem; + color: var(--text-muted); + font-size: 0.8125rem; + text-align: right; + user-select: none; + counter-increment: line; + content: counter(line); +} + +.footnotes { + margin-top: 3rem; + font-size: 0.875rem; + line-height: 1.6; + color: var(--text-muted); +} + +.footnotes hr { + width: 4rem; + margin: 0 0 1.5rem; + border: 0; + border-top: 2px solid var(--text-primary); +} + +.article-footer { + margin-top: 4rem; + text-align: center; +} + +.article-footer__label { + margin: 1.5rem 0 0; + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--text-muted); +} + +footer { + margin-top: 4rem; + font-family: var(--font-mono); + font-size: 0.75rem; + line-height: 1.6; + text-align: center; + color: var(--text-muted); +} + +footer a { + text-decoration: none; } diff --git a/assets/typo.scss b/assets/typo.scss index 974a0c49f8d0f329dff4cf6ad43aabfd5f6f5a8c..43b55e182cb4a99d9091126378113db90e0f9f42 100644 --- a/assets/typo.scss +++ b/assets/typo.scss @@ -1,324 +1,53 @@ -/* cyrillic-ext */ @font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-italic.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; -} -/* cyrillic */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-italic.woff2) format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-italic.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-italic.woff2) format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-italic.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-italic.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* cyrillic-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold-italic.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; -} -/* cyrillic */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold-italic.woff2) format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold-italic.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold-italic.woff2) format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold-italic.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold-italic.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* cyrillic-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold-italic.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; -} -/* cyrillic */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold-italic.woff2) format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold-italic.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold-italic.woff2) format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold-italic.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold-italic.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* cyrillic-ext */ -@font-face { - font-family: 'IBM Plex Sans'; + font-family: 'JetBrains Mono'; font-style: normal; - font-weight: 400; + font-weight: 400 700; font-display: swap; - src: url(/fonts/ibmplexsans-regular.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; -} -/* cyrillic */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-regular.woff2) format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-regular.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-regular.woff2) format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-regular.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(/fonts/ibmplexsans-regular.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -/* cyrillic-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; -} -/* cyrillic */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold.woff2) format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(/fonts/ibmplexsans-semibold.woff2) format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; + src: url(/fonts/jetbrains-mono-normal-latin-ext.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } -/* latin-ext */ + @font-face { - font-family: 'IBM Plex Sans'; + font-family: 'JetBrains Mono'; font-style: normal; - font-weight: 600; + font-weight: 400 700; font-display: swap; - src: url(/fonts/ibmplexsans-semibold.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + src: url(/fonts/jetbrains-mono-normal-latin.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } -/* latin */ + @font-face { - font-family: 'IBM Plex Sans'; + font-family: 'Lora'; font-style: normal; - font-weight: 600; + font-weight: 400 700; font-display: swap; - src: url(/fonts/ibmplexsans-semibold.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + src: url(/fonts/lora-normal-latin-ext.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } -/* cyrillic-ext */ + @font-face { - font-family: 'IBM Plex Sans'; + font-family: 'Lora'; font-style: normal; - font-weight: 700; + font-weight: 400 700; font-display: swap; - src: url(/fonts/ibmplexsans-bold.woff2) format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + src: url(/fonts/lora-normal-latin.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } -/* cyrillic */ + @font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 700; + font-family: 'Lora'; + font-style: italic; + font-weight: 400 700; font-display: swap; - src: url(/fonts/ibmplexsans-bold.woff2) format('woff2'); - unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; + src: url(/fonts/lora-italic-latin-ext.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } -/* greek */ + @font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 700; + font-family: 'Lora'; + font-style: italic; + font-weight: 400 700; font-display: swap; - src: url(/fonts/ibmplexsans-bold.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold.woff2) format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold.woff2) format('woff2'); - unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(/fonts/ibmplexsans-bold.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + src: url(/fonts/lora-italic-latin.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } diff --git a/i18n/en.toml b/i18n/en.toml index d5e9c417d425277a2ea8725062a5d8da900d2749..5ee0474166c0783d9001d8aab15eb076459c4834 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -18,6 +18,8 @@ [availableIn] other = "Also available in" [aboutMe] other = "About me" +[toggleTheme] +other = "Toggle color scheme" [footer] other = """ Comments, questions? Send an email to \ diff --git a/i18n/pt-br.toml b/i18n/pt-br.toml index 30b141c97b50c61edbf784c67079770d1e0f33d9..60fd87b22929f8f38f13ebc56f20281bbed52260 100644 --- a/i18n/pt-br.toml +++ b/i18n/pt-br.toml @@ -18,6 +18,8 @@ [availableIn] other = "Também disponível em" [aboutMe] other = "Sobre mim" +[toggleTheme] +other = "Alternar esquema de cores" [footer] other = """ Comentários, dúvidas? Envie um email para \ diff --git a/layouts/_partials/bio.html b/layouts/_partials/bio.html index 06b2d35d56e6c400f42a386410f7efb8d9d3376c..f40d6ac0ccdd7a85c0df5350bcecead7bb461976 100644 --- a/layouts/_partials/bio.html +++ b/layouts/_partials/bio.html @@ -1,3 +1,3 @@ -<p class="bio text-small"> +<p class="bio"> {{ i18n "bio" | safeHTML }} </p> diff --git a/layouts/_partials/css/syntax-dark.css b/layouts/_partials/css/syntax-dark.css index 24168d48a6f1a0f7a3942f60ba539c9bf5bea1a9..8a8bf50d505615b49a8a4bcc7e1b53502fe7dbc3 100644 --- a/layouts/_partials/css/syntax-dark.css +++ b/layouts/_partials/css/syntax-dark.css @@ -1,5 +1,5 @@ -/* Background */ .bg { color: #c9d1d9; background-color: #0d1117; } -/* PreWrapper */ .chroma { color: #c9d1d9; background-color: #0d1117; } +/* Background */ .bg { color: #c9d1d9; } +/* PreWrapper */ .chroma { color: #c9d1d9; } /* Other */ .chroma .x { } /* Error */ .chroma .err { color: #f85149 } /* CodeLine */ .chroma .cl { } diff --git a/layouts/_partials/css/syntax-light.css b/layouts/_partials/css/syntax-light.css index 9018df907148662fc70a7233a558156255826726..2d5dbde69480e1a0d4d28794789d49f6667df709 100644 --- a/layouts/_partials/css/syntax-light.css +++ b/layouts/_partials/css/syntax-light.css @@ -1,5 +1,3 @@ -/* Background */ .bg { background-color: #ffffff; } -/* PreWrapper */ .chroma { background-color: #ffffff; } /* Other */ .chroma .x { } /* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 } /* CodeLine */ .chroma .cl { } diff --git a/layouts/_partials/head.html b/layouts/_partials/head.html index 3a451408f015836d0f6dc0e657ef283ec4e82128..c98f727757a715242af034915a973508dc794778 100644 --- a/layouts/_partials/head.html +++ b/layouts/_partials/head.html @@ -2,17 +2,25 @@ <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>{{ .Title }}</title> + <script> + (function () { + var stored = localStorage.getItem('theme'); + if (stored === 'dark' || (!stored && window.matchMedia('(prefers-color-scheme: dark)').matches)) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + })(); + </script> <link rel="alternate" type="application/rss+xml" title="RSS for {{ .Lang }}" href="{{ "index.xml" | absLangURL }}"> <link rel="icon" type="image/jpeg" href="/avatar.jpg"> {{ $style := resources.Get "style.scss" | css.Sass | resources.Minify | resources.Fingerprint }} <link rel="stylesheet" href="{{ $style.RelPermalink }}" /> <style type="text/css" media="screen"> - @media (prefers-color-scheme: dark) { + {{ partial "css/syntax-light.css" . | safeCSS }} + .dark { {{ partial "css/syntax-dark.css" . | safeCSS }} - } - @media (prefers-color-scheme: light) { - {{ partial "css/syntax-light.css" . | safeCSS }} } </style> </head> diff --git a/layouts/_partials/masthead.html b/layouts/_partials/masthead.html new file mode 100644 index 0000000000000000000000000000000000000000..36f287a5b9f52b7920c87abe61850b2aa004adeb --- /dev/null +++ b/layouts/_partials/masthead.html @@ -0,0 +1,9 @@ +<a class="masthead__link" href="{{ .Site.BaseURL }}"> + <img class="avatar" src="/avatar.jpg" alt="{{ .Site.Title }}"> + {{ if .IsHome }} + <h1 class="masthead__title">{{ .Site.Title }}</h1> + {{ else }} + <p class="masthead__title">{{ .Site.Title }}</p> + {{ end }} +</a> +{{ partial "theme-toggle.html" . }} diff --git a/layouts/_partials/site-title.html b/layouts/_partials/site-title.html deleted file mode 100644 index 199ec46c144647738a1c5b13fc042a8db617e3cf..0000000000000000000000000000000000000000 --- a/layouts/_partials/site-title.html +++ /dev/null @@ -1,4 +0,0 @@ -<a href="{{ .Site.BaseURL }}" class="header-text text-subtle"> - <img class="avatar" src="/avatar.jpg" alt="{{ .Site.Title }}"> - <p class="text-small text-uppercase text-spaced">{{ .Site.Title }}</p> -</a> diff --git a/layouts/_partials/theme-toggle.html b/layouts/_partials/theme-toggle.html new file mode 100644 index 0000000000000000000000000000000000000000..7430543f1e646630bec32d1e1145cb4dbaa144cb --- /dev/null +++ b/layouts/_partials/theme-toggle.html @@ -0,0 +1,3 @@ +<button id="theme-toggle" class="theme-toggle" type="button" aria-label="{{ i18n "toggleTheme" }}"> + [ <span class="theme-toggle__dot" aria-hidden="true">●</span> <span id="theme-label">light</span> ] +</button> diff --git a/layouts/baseof.html b/layouts/baseof.html index 551f513d5d076945892509fb4f2d9b65c5ee4549..57cc1288af677a0bd85d423254d9ca9964fdf43c 100644 --- a/layouts/baseof.html +++ b/layouts/baseof.html @@ -4,5 +4,22 @@ {{ partial "head.html" . }} <body> {{ block "main" . }}{{ end }} + + <script> + (function () { + var root = document.documentElement; + var button = document.getElementById('theme-toggle'); + var label = document.getElementById('theme-label'); + if (!button || !label) return; + + label.textContent = root.classList.contains('dark') ? 'dark' : 'light'; + + button.addEventListener('click', function () { + var dark = root.classList.toggle('dark'); + label.textContent = dark ? 'dark' : 'light'; + localStorage.setItem('theme', dark ? 'dark' : 'light'); + }); + })(); + </script> </body> </html> diff --git a/layouts/home.html b/layouts/home.html index f73ca973c160ea2a6fd09df2afcd4b1bcb606710..79a39b6ff256bad0fee0a6a1a6db6a477781ad2b 100644 --- a/layouts/home.html +++ b/layouts/home.html @@ -1,11 +1,11 @@ {{ define "main" }} -<main class="index"> +<main> <div class="page-content"> - <div class="index-header text-center"> - {{ partial "site-title.html" . }} + <header class="site-header"> + {{ partial "masthead.html" . }} {{ partial "bio.html" . }} <div class="divisor"></div> - </div> + </header> <div class="languages"> {{ partial "available-lang.html" . }} @@ -13,9 +13,9 @@