commit d1691066aa80e2679b55fc11329dfa297d46e718 Author: TheThomaas Date: Thu Aug 31 22:26:14 2023 +0200 Init 11ty project diff --git a/.eleventy.js b/.eleventy.js new file mode 100644 index 0000000..69e3acd --- /dev/null +++ b/.eleventy.js @@ -0,0 +1,43 @@ +const inspect = require("util").inspect; + +module.exports = config => { + config.setUseGitIgnore(false); + + config.addPassthroughCopy({"./src/_includes/js/" : "/js"}); + + config.addLayoutAlias('base', 'layouts/base.html'); + + + config.addCollection("subpages", (collectionApi) => { + // const sections = collectionApi.getFilteredByTag( "subpage" ) + const sections = collectionApi.getFilteredByGlob("./src/pages/subpages/**") + .sort((a, b) => a.data.pageOrderId - b.data.pageOrderId); + process.env.DEBUG && console.log(inspect(sections)); + return sections; + }); + config.addCollection("projects", (collectionApi) => { + // const sections = collectionApi.getFilteredByTag( "subpage" ) + const sections = collectionApi.getFilteredByGlob("./src/projects/**") + .sort((a, b) => a.data.pageOrderId - b.data.pageOrderId); + process.env.DEBUG && console.log(inspect(sections)); + return sections; + }); + + + // config.addCollection('projects', collection => { + // return [...collection.getFilteredByGlob('./src/projects/*.md')].reverse(); + // }); + config.addCollection('experiences', collection => { + return [...collection.getFilteredByGlob('./src/experiences/*.md')].reverse(); + }); + + return { + markdownTemplateEngine: 'liquid', + dataTemplateEngine: 'liquid', + htmlTemplateEngine: 'liquid', + dir: { + input: 'src', + output: 'dist' + } + }; +}; \ No newline at end of file diff --git a/.eleventyignore b/.eleventyignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.eleventyignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9de76cf --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Misc +*.log +npm-debug.* +*.scssc +*.swp +.DS_Store +Thumbs.db +.sass-cache +.env +.cache + +# Node modules and output +node_modules +dist +src/_includes/css \ No newline at end of file diff --git a/gulp-tasks/sass.js b/gulp-tasks/sass.js new file mode 100644 index 0000000..ca98ff2 --- /dev/null +++ b/gulp-tasks/sass.js @@ -0,0 +1,50 @@ +const {dest, src} = require('gulp'); +const cleanCSS = require('gulp-clean-css'); +const sassProcessor = require('gulp-sass')(require('sass')); + +// We want to be using canonical Sass, rather than node-sass +sassProcessor.compiler = require('sass'); + +// Flags whether we compress the output etc +const isProduction = process.env.NODE_ENV === 'production'; + +// An array of outputs that should be sent over to includes +const criticalStyles = ['critical.scss', 'home.scss', 'page.scss', 'work-item.scss']; + +// Takes the arguments passed by `dest` and determines where the output file goes +const calculateOutput = ({history}) => { + // By default, we want a CSS file in our dist directory, so the + // HTML can grab it with a + let response = './dist/css'; + + // Get everything after the last slash + const sourceFileName = /[^(/|\\)]*$/.exec(history[0])[0]; + + // If this is critical CSS though, we want it to go + // to the _includes directory, so nunjucks can include it + // directly in a diff --git a/src/_includes/partials/post-list.html b/src/_includes/partials/post-list.html new file mode 100644 index 0000000..657c074 --- /dev/null +++ b/src/_includes/partials/post-list.html @@ -0,0 +1,9 @@ +
+
    + {%- for posts in postslist -%} +
  1. +

    {{ posts.data.title }}

    +
  2. + {%- endfor -%} +
+
\ No newline at end of file diff --git a/src/_includes/partials/project.liquid b/src/_includes/partials/project.liquid new file mode 100644 index 0000000..9b246b8 --- /dev/null +++ b/src/_includes/partials/project.liquid @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/src/_includes/partials/skip-link.html b/src/_includes/partials/skip-link.html new file mode 100644 index 0000000..4d7b7ce --- /dev/null +++ b/src/_includes/partials/skip-link.html @@ -0,0 +1 @@ +Main content \ No newline at end of file diff --git a/src/_includes/title.liquid b/src/_includes/title.liquid new file mode 100644 index 0000000..b7406e3 --- /dev/null +++ b/src/_includes/title.liquid @@ -0,0 +1,4 @@ +
+

{{ subpage.data.title }}

+ {{ subpage.templateContent }} +
\ No newline at end of file diff --git a/src/experiences/experiences.11tydata.js b/src/experiences/experiences.11tydata.js new file mode 100644 index 0000000..89b033f --- /dev/null +++ b/src/experiences/experiences.11tydata.js @@ -0,0 +1,3 @@ +module.exports = { + permalink: false +}; \ No newline at end of file diff --git a/src/experiences/post1.md b/src/experiences/post1.md new file mode 100644 index 0000000..c7fcab4 --- /dev/null +++ b/src/experiences/post1.md @@ -0,0 +1,6 @@ +--- +title: Post 1 +description: desc +startDate: 2019 +endDate: 2020 +--- \ No newline at end of file diff --git a/src/experiences/post2.md b/src/experiences/post2.md new file mode 100644 index 0000000..b79ec90 --- /dev/null +++ b/src/experiences/post2.md @@ -0,0 +1,6 @@ +--- +title: Post 2 +description: desc +startDate: 2020 +endDate: 2023 +--- \ No newline at end of file diff --git a/src/pages/index.liquid b/src/pages/index.liquid new file mode 100644 index 0000000..550c72a --- /dev/null +++ b/src/pages/index.liquid @@ -0,0 +1,28 @@ +--- +title: 'Home' +layout: 'base' +permalink: / +--- + +{% for subpage in collections.subpages %} + {% if subpage.data.excludeFromList != true %} + {% if subpage.data.pageOrderId == 0 %} + {% include 'title.liquid' %} + {% else %} + {% include 'page.liquid' %} + {% endif %} + {% endif %} +{% endfor %} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/subpages/about.liquid b/src/pages/subpages/about.liquid new file mode 100644 index 0000000..20a8db4 --- /dev/null +++ b/src/pages/subpages/about.liquid @@ -0,0 +1,10 @@ +--- +title: About me +pageOrderId: 1 +classes: 'wrapper about-section' +img: test.jpg +socials: + github: https://github.com +--- + +

Lorem ipsum dolor sit amet consectetur, adipisicing elit. Velit culpa dignissimos laborum, dolor voluptatem perspiciatis earum placeat modi minus officia perferendis rerum alias maiores deleniti et quia provident quo doloribus.

\ No newline at end of file diff --git a/src/pages/subpages/contact.liquid b/src/pages/subpages/contact.liquid new file mode 100644 index 0000000..de730b5 --- /dev/null +++ b/src/pages/subpages/contact.liquid @@ -0,0 +1,10 @@ +--- +title: Contact me +pageOrderId: 5 +classes: 'wrapper-full contact-section' +excludeFromNav: true +excludeFromList: true +--- + +

This is some "{{ title }}" content.

+

Please don't

\ No newline at end of file diff --git a/src/pages/subpages/download.liquid b/src/pages/subpages/download.liquid new file mode 100644 index 0000000..0471a3c --- /dev/null +++ b/src/pages/subpages/download.liquid @@ -0,0 +1,12 @@ +--- +title: Download +showTitle: false +pageOrderId: 4 +classes: 'wrapper-full download-section' +--- + +
+

You want to print this document ?

+ + Download as PDF +
\ No newline at end of file diff --git a/src/pages/subpages/experiences.liquid b/src/pages/subpages/experiences.liquid new file mode 100644 index 0000000..3203271 --- /dev/null +++ b/src/pages/subpages/experiences.liquid @@ -0,0 +1,8 @@ +--- +title: Experiences +pageOrderId: 3 +classes: 'wrapper-full experiences-section' +--- + +{% assign experiences = collections.experiences %} +{% include 'partials/experience.liquid' %} \ No newline at end of file diff --git a/src/pages/subpages/hero.liquid b/src/pages/subpages/hero.liquid new file mode 100644 index 0000000..36d1ad0 --- /dev/null +++ b/src/pages/subpages/hero.liquid @@ -0,0 +1,10 @@ +--- +title: Hi! I'm Thomas +description: Welcome to my website +pageOrderId: 0 +classes: 'wrapper-full hero-section' +excludeFromNav: true +excludeFromList: false +--- + +

{{ description }}

\ No newline at end of file diff --git a/src/pages/subpages/projects.liquid b/src/pages/subpages/projects.liquid new file mode 100644 index 0000000..40f2b26 --- /dev/null +++ b/src/pages/subpages/projects.liquid @@ -0,0 +1,8 @@ +--- +title: Projects +pageOrderId: 2 +classes: 'wrapper-full projects-section' +--- + +{% assign projects = collections.projects %} +{% include 'partials/project.liquid' %} \ No newline at end of file diff --git a/src/pages/subpages/subpages.11tydata.js b/src/pages/subpages/subpages.11tydata.js new file mode 100644 index 0000000..9196fac --- /dev/null +++ b/src/pages/subpages/subpages.11tydata.js @@ -0,0 +1,4 @@ +module.exports = { + permalink: false, + tags: ["subpage"] +}; \ No newline at end of file diff --git a/src/projects/cancre-simulator.md b/src/projects/cancre-simulator.md new file mode 100644 index 0000000..0218775 --- /dev/null +++ b/src/projects/cancre-simulator.md @@ -0,0 +1,7 @@ +--- +title: Cancre Simulator +description: Un jeu fait pour les Portes Ouvertes 2020 +github: + title: Voir sur Github + link: https://github.com +--- \ No newline at end of file diff --git a/src/projects/guess-who.md b/src/projects/guess-who.md new file mode 100644 index 0000000..b409dc2 --- /dev/null +++ b/src/projects/guess-who.md @@ -0,0 +1,7 @@ +--- +title: Qui est-ce ? +description: Un "Qui est-ce ?" fait en Python et avec des LEGO Mindstorms +github: + title: Voir sur Github + link: https://github.com +--- \ No newline at end of file diff --git a/src/projects/ldap.md b/src/projects/ldap.md new file mode 100644 index 0000000..f9be5e4 --- /dev/null +++ b/src/projects/ldap.md @@ -0,0 +1,10 @@ +--- +title: LDAP +description: Ajouter, voir et se connecter à des utilisateurs LDAP depuis un site +github: + title: Voir sur Github + link: https://github.com +website: + title: Voir sur Github + link: https://github.com +--- \ No newline at end of file diff --git a/src/projects/projects.11tydata.js b/src/projects/projects.11tydata.js new file mode 100644 index 0000000..89b033f --- /dev/null +++ b/src/projects/projects.11tydata.js @@ -0,0 +1,3 @@ +module.exports = { + permalink: false +}; \ No newline at end of file diff --git a/src/projects/sigfox.md b/src/projects/sigfox.md new file mode 100644 index 0000000..d6a99b1 --- /dev/null +++ b/src/projects/sigfox.md @@ -0,0 +1,10 @@ +--- +title: Sigfox Temperature +description: Des capteurs de température affichés sur un tableau de bord +github: + title: Voir sur Github + link: https://github.com +website: + title: Voir le site + link: https://google.com +--- \ No newline at end of file diff --git a/src/projects/snake.md b/src/projects/snake.md new file mode 100644 index 0000000..d8fcd39 --- /dev/null +++ b/src/projects/snake.md @@ -0,0 +1,8 @@ +--- +title: Snake +description: Un snake réalisé en Java +background: rgb(255, 143, 143) +github: + title: Voir le site + link: https://google.com +--- \ No newline at end of file diff --git a/src/scss/components/_button.scss b/src/scss/components/_button.scss new file mode 100644 index 0000000..853643e --- /dev/null +++ b/src/scss/components/_button.scss @@ -0,0 +1,50 @@ +.btn { + --hover: var(--dark-2); + --active: var(--dark-2); + text-decoration: none; + transition: background-color .1s ease-in-out; + display: inline-flex; + flex-direction: row; + font-size: 1rem; + line-height: 1.5rem; + min-height: 2.5rem; + padding: .5rem 1rem; + width: fit-content; + align-items: center; + max-height: none; + max-width: 100%; + cursor: pointer; + border: none; + + &:disabled { + --hover: inherit; + --active: inherit; + background-color: #e5e5e5; + color: #929292; + cursor: not-allowed; + } + + &[class*="btn-icon"]:before { + --icon-size: 1.4rem; + content: ''; + display: block; + flex: 0 0 auto; + background-color: currentColor; + mask-size: 100% 100%; + height: var(--icon-size); + width: var(--icon-size); + margin-left: -.125rem; + margin-right: .5rem; + } + + &.btn-icon--download:before { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ctitle%3Etray-arrow-down%3C/title%3E%3Cpath d='M2 12H4V17H20V12H22V17C22 18.11 21.11 19 20 19H4C2.9 19 2 18.11 2 17V12M12 15L17.55 9.54L16.13 8.13L13 11.25V2H11V11.25L7.88 8.13L6.46 9.55L12 15Z' /%3E%3C/svg%3E"); + } + + &:not(:disabled):hover { + background-color: var(--hover); + } + &:not(:disabled):active { + background-color: var(--active); + } +} \ No newline at end of file diff --git a/src/scss/components/_focus.scss b/src/scss/components/_focus.scss new file mode 100644 index 0000000..c795940 --- /dev/null +++ b/src/scss/components/_focus.scss @@ -0,0 +1,9 @@ +* { + outline-color: #0a76f6; + outline-offset: 2px; + outline-width: 2px; +} + +*:focus, *:focus-visible { + outline-style: solid; +} \ No newline at end of file diff --git a/src/scss/components/_reset.scss b/src/scss/components/_reset.scss new file mode 100644 index 0000000..de74a35 --- /dev/null +++ b/src/scss/components/_reset.scss @@ -0,0 +1,50 @@ +/* + Josh's Custom CSS Reset + https://www.joshwcomeau.com/css/custom-css-reset/ +*/ +*, *::before, *::after { + box-sizing: border-box; +} +* { + margin: 0; +} +:where(html) { + overflow-x: hidden; +} +// :where(html, body) { +// block-size: 100%; +// } +:where(body) { + text-rendering: optimizeSpeed; + line-height: 1.5; +} +:where(img, picture, video, canvas) { + display: block; + max-inline-size: 100%; +} +:where(input, button, textarea, select, a) { + font: inherit; +} +:where(p, h1, h2, h3, h4, h5, h6) { + overflow-wrap: break-word; +} +:where(ul, ol):where([role='list'], [class]) { + list-style: none; +} +:where(html:focus-within) { + scroll-behavior: smooth; +} +:where(img, picture) { + block-size: auto; +} + +@media (prefers-reduced-motion: reduce) { + * { + animation-play-state: paused !important; + transition: none !important; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} \ No newline at end of file diff --git a/src/scss/components/_superminimal.scss b/src/scss/components/_superminimal.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/scss/components/_utilities.scss b/src/scss/components/_utilities.scss new file mode 100644 index 0000000..3819abe --- /dev/null +++ b/src/scss/components/_utilities.scss @@ -0,0 +1,86 @@ +.wrapper { + $wrapper-gap: var(--gutter); + display: grid; + grid-template-columns: + 1fr + min(var(--wrapper-max-length, var(--line-length)), calc(100% - var(--wrapper-gap, $wrapper-gap) * 2)) + 1fr; + grid-column-gap: var(--wrapper-gap, $wrapper-gap); + + > * { + grid-column: 2; + } +} + +.wrapper-full { + @extend .wrapper; + $wrapper-gap: var(--gutter); + grid-template-columns: + 1fr + min(var(--wrapper-max-length, var(--line-length-large)), calc(100% - var(--wrapper-gap, $wrapper-gap) * 2)) + 1fr; +} + +.full-bleed { + inline-size: 100%; + grid-column: 1 / -1; + padding: var(--padding-block, 1rem) var(--padding-inline, 2rem); + background-color: var(--background-color, none); +} + +.flex-container { + display: inline-flex; + align-items: center; + + &.column { + flex-direction: column; + } +} + +.sr-only { + position: absolute !important; + block-size: 1px !important; + inline-size: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} + +.invisible { + visibility: hidden !important; +} + +.list-inline { + $item-gap : 1ch; + display: flex; + flex-wrap: wrap; + padding-left: 0; + list-style: none; + margin-left: calc(var(--item-gap, $item-gap) * 3 * -1); + clip-path: inset(0 0 0 calc(var(--item-gap, $item-gap) * 3)); + align-items: center; + color: var(--item-color, var(--text)); + + li { + padding-left: var(--item-gap, $item-gap); + &::before { + content: var(--item-separator, '•'); + display: inline-block; + margin-right: var(--item-gap, $item-gap); + width: var(--item-gap, $item-gap); + text-align: center; + } + } + + a { + color: var(--item-color, var(--text)); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } +} \ No newline at end of file diff --git a/src/scss/components/_variables.scss b/src/scss/components/_variables.scss new file mode 100644 index 0000000..8e3a898 --- /dev/null +++ b/src/scss/components/_variables.scss @@ -0,0 +1,31 @@ +:root { + --light-1: #efefef; + --dark-1: #1e1e1e; + --dark-2: #0f0f0f; + --primary: #C2B280; + --primary-light: #D3C7A2; + --primary-dark: #BAB298; + --secondary: #B3CF99; + --secondary-light: #C2D9AD; + --secondary-dark: #9FAF8F; + + --background: var(--primary-light); + --text: var(--dark-1); + --text-2: var(--dark-2); + + --font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", sans-serif; + --font-italic: "Georgia", serif; + --font-code: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; + --font-size: 1.2rem; + --font-weight-semibold: 700; + --font-weight-bold: 900; + --leading: 1.45; + --gutter: clamp(1ch, 2.5vmax, 3ch); + --stack: clamp(1.25ex, 1ex + 2.5vmax, 1.75ex); + --line-length-small: 30ch; + --line-length: 75ch; + --line-length-large: 115ch; + --page-padding-inline: calc((100vw - min(var(--line-length), 80vw)) / 2); + --border-width: 1px; + --border-radius: 4px; + } \ No newline at end of file diff --git a/src/scss/critical.scss b/src/scss/critical.scss new file mode 100644 index 0000000..4ca4e29 --- /dev/null +++ b/src/scss/critical.scss @@ -0,0 +1,694 @@ +@use './components/variables'; +@use './components/reset'; +@use './components/superminimal'; +@use './components/utilities'; +@use './components/focus'; +@use './components/button'; + + + + + + + + + + + + + + + + + /* ------------------------------------ *\ + https://codepen.io/mikemai2awesome/full/KKvMZVz + \* ------------------------------------ */ + + :root { + color: var(--text); + background-color: var(--background); + accent-color: var(--text); + } + + :where(a) { + color: var(--text); + } + + :where(input, textarea, select) { + color: var(--text); + background-color: var(--background); + } + + :where(button, .btn) { + color: var(--primary-light); + background-color: var(--text); + } + + :where(code) { + color: var(--text); + background-color: var(--primary-dark); + } + + /* ------------------------------------ *\ + Typography + \* ------------------------------------ */ + + :root { + font-size: clamp( + var(--font-size), + var(--font-size) * 0.9 + 0.25vw, + var(--font-size) * 2 + ); // % ensures browser zoom is supported. + font-family: var(--font); // Use system UI font. + font-weight: var(--font-weight-regular); + line-height: var(--leading); // Standard leading for good legibility. + letter-spacing: var(--tracking); + } + + :where(a) { + text-decoration: underline; + text-decoration-thickness: var(--border-width); + text-underline-offset: calc(var(--border-width) * 2); + } + + :where(a):hover { + text-decoration-thickness: calc(var(--border-width) * 2); + } + + :where(pre, code, kbd, dl, figcaption, abbr, table) { + font-family: var( + --font-code + ); // Differentiate preformatted, code, description, and table text from body text. + + font-size: 0.8em; // Make monospace and small text smaller than body text. + } + + :where(big) { + font-size: 1.2em; // is technically deprecated, but I love using it. This creates a fallback if a browser doesn't support it. + letter-spacing: 0.006em; + } + + :where(pre code) { + display: block; // Define block code. + font-size: 1em; // Prevent cascading. + } + + :where(blockquote, em, i, cite) { + font-family: var( + --font-italic + ); // Differentiate blockquote, citation, idiomatic, and emphasisized text from body text. Also, sans-serif italic is ugly. + font-weight: var( + --font-weight-regular + ); // Prevent italics to be bold. Bold italic is also ugly and unnecessary. + } + + :where(blockquote) { + font-size: clamp(1.5rem, 1.25rem + 1vw, 3rem); + letter-spacing: 0; + } + + :where(blockquote p) { + max-inline-size: 35ch; + } + + :where(blockquote q):before { + position: absolute; + transform: translateX(-100%); + } + + :where(strong, b, th, button, .btn) { + font-weight: var( + --font-weight-semibold + ); // Make non-heading emphasized text less bold than heading text. + } + + :where(h1, h2, h3, h4, h5, h6, summary strong, legend) { + font-weight: var(--font-weight-semibold); + } + + :where(h1, h2, h3, h4, h5, h6, summary strong, legend, big) { + font-stretch: var(--font-stretch, expanded); + } + + :where(button, .btn, input[type="file"]) { + font-stretch: var(--font-stretch, condensed); + } + + :where(abbr) { + text-decoration: underline; + text-decoration-style: dotted; // Differentiate abbreviaions from links. + text-underline-offset: calc(var(--border-width) * 2); + } + + :where(button, label, select, summary) { + cursor: pointer; + } + + :where(summary:hover > *) { + text-decoration: underline; + text-underline-offset: calc(var(--border-width) * 2); + } + + :where(figcaption) { + text-align: center; + } + + :where(th) { + text-align: start; + } + + :where(th, td) { + vertical-align: baseline; + } + + :where(fieldset > ol) { + list-style: none; + } + + /* ------------------------------------ *\ + Spacing + \* ------------------------------------ */ + + :where(h1, h2, h3, h4, h5, h6, p, figure, form, pre, blockquote, ul, ol, dl, li, details) { + margin-block-end: 0; + } + + :where(h1, h2, h3, h4, h5, h6) { + margin-block-start: calc(var(--stack) * 1.75); + } + + :where(p, figure, form, fieldset, pre, blockquote, ul, ol, dl, details) { + margin-inline: 0; + margin-block-start: var(--stack); + } + + :where(h1, h2, h3, h4, h5, h6, p, figure, form, fieldset, pre, blockquote, ul, ol, dl, details):first-child, + :where(legend + *) { + margin-block-start: 0; + } + + :where(h1, h2, h3, h4, h5, h6) + * { + margin-block-start: calc(var(--stack) / 5); + } + + // :where(ul, ol) { + // padding: 0; + // } + + :where(li > ul, li > ol) { + margin-block-start: calc(var(--stack) / 5); + } + + :where(details ul, details ol) { + margin-inline-start: 4ch; // Unify indent for all lists inside details. + } + + :where(li > ul, li > ol, fieldset ul, fieldset ol) { + margin-inline-start: 2.25ch; // Unify indent for all nested lists. + } + + :where(li + li) { + margin-block-start: calc(var(--stack) / 5); + } + + :where(fieldset > ol li + li) { + margin-block-start: calc(var(--stack) / 2); + } + + :where(fieldset > ol) { + margin-inline: 0; + } + + :where(hr) { + margin-block-start: calc(var(--stack) * 3); + margin-block-end: calc(var(--stack) * 3); + } + + :where(hr + *) { + margin-block-start: 0; + } + + :where(figure > img, table) { + margin-inline: auto; + } + + :where(blockquote > *) { + margin-block-start: calc(var(--stack) / 4); + } + + :where(blockquote:not(:last-child)) { + padding-block-end: calc(var(--stack) / 2); + } + + :where(button, .btn, dd, th, td) { + // Unify inset spacing on bordered elements. + padding-block: calc(var(--stack) / 6); + padding-inline: calc(var(--gutter) / 3); + } + + :where(input, textarea) { + padding-inline: 2px; + } + + :where(caption, figcaption) { + padding-block: calc(var(--stack) / 2); + } + + :where(code, kbd) { + padding-block: 0.25ex; + padding-inline: 0.5ch; + } + + :where(figure, pre) { + padding-block-start: calc( + var(--stack) / 2.5 + ); // Line up top of images/codeblocks with text in an adjacent column layout. + } + + :where(pre) { + padding-block-end: calc(var(--stack) / 2.5); + } + + :where(pre code) { + padding-block: var(--stack); + padding-inline: var(--gutter); + } + + details[open] summary + * { + margin-block-start: calc(var(--stack) / 4); + } + + /* ------------------------------------ *\ + General + \* ------------------------------------ */ + + *, + *:before, + *:after { + font-feature-settings: "kern"; + font-kerning: normal; + -moz-osx-font-smoothing: grayscale !important; + -webkit-font-smoothing: antialiased !important; + box-sizing: border-box; + } + + :where(input, textarea, select, fieldset, button, kbd, dd, table, th, td) { + // Unify border styles. + border: var(--border-width) solid var(--text); + } + + :where(input, textarea, select, fieldset, button, .btn, kbd) { + // Unify interactive elements border radius. + border-radius: var(--border-radius); + } + + :where(pre) { + white-space: -moz-pre-wrap; + white-space: -o-pre-wrap; + white-space: pre-wrap; + word-spacing: normal; + word-break: normal; + word-wrap: break-word; + } + + :where(dl) { + display: grid; + grid-template-columns: auto minmax(75%, 1fr); + gap: calc(var(--gutter) / 2); + align-items: baseline; + } + + :where(dt) { + border-block-end: var(--border-width) dotted; + } + + :where(dd) { + block-size: 100%; + margin-inline-start: 0; + } + + :where(input:not([type="checkbox"]):not([type="radio"]), select, textarea) { + display: block; + inline-size: 100%; + } + + :where(input[type="radio"], input[type="checkbox"]) { + size: 1.5ex; + vertical-align: baseline; + } + + :where(input[type="file"]) { + padding-inline: 0; + border: 0; + } + + ::-webkit-file-upload-button { + appearance: button; + cursor: pointer; + font: inherit; + } + + :where(input, textarea, select) ~ * { + margin-block-start: 0; + font-size: 0.8em; + } + + :where(input:required + mark) { + display: none; + color: var(--text); + background-color: transparent; + } + + :where(input:required:invalid + mark) { + display: block; + } + + :where(hr) { + block-size: 0; + border: 0; + border-block-start: var(--border-width) dashed var(--text); + } + + :where(figure, figure table) { + inline-size: 100%; + } + + :where(figure) { + overflow-x: auto; + } + + :where(figure > img) { + display: block; + } + + :where(table) { + caption-side: bottom; + border-collapse: collapse; + border-spacing: 0; + } + + :where(tr > *:first-child) { + white-space: nowrap; + } + + :where(summary > *) { + display: inline; + vertical-align: middle; + } + + /* ------------------------------------ *\ + Add-ons + - Requires data attributes. + - Remove to do your own layouts. + \* ------------------------------------ */ + + :where(body main) { + padding-block-start: clamp(var(--stack) * 1, 10vmax, var(--stack) * 2); + } + + + + + + + + + + body { + --start: var(--primary-light); + --end: var(--secondary); + background: var(--start); + background: linear-gradient(180deg, var(--start) 0%, var(--start) 35%, var(--end) 100%); + + header, footer { + padding: .5rem clamp(.2rem, 3vw, 2rem); + } + } + header { + background-color: var(--primary); + position: fixed; + z-index: 10; + inset-block-start: 0; + inset-inline: 0; + + @media screen and (max-width: 767px) { + &.wrapper-full { + nav { + grid-column: 1 / -1; + } + } + } + + nav { + ul { + display: flex; + justify-content: flex-end; + padding: 0; + list-style: none; + + @media screen and (max-width: 767px) { + justify-content: start; + } + } + + li { + padding: 6px 20px; + padding: 6px clamp(10px, 3vw, 20px); + margin: 0; + + @media screen and (min-width: 768px) { + display: inline-block; + } + } + + a[aria-current="page"] { + color: var(--text-2); + text-decoration: underline; + font-weight: var(--font-weight-semibold) + } + } + } + main { + margin: 0; + padding: 0; + h2 { + margin-block: 2rem 1rem; + font-size: calc(var(--font-size) * 1.6); + } + .list-inline { + --item-gap: 0; + margin: 0; + padding: 0; + } + ul:not(.list-inline) { + margin: 0; + padding: 0; + list-style-type: none; + } + li { + --item-separator: none; + margin: 0; + padding: 0; + } + } + footer { + background-color: var(--secondary); + justify-items: center; + margin-block-start: 1.5rem; + .list-inline { + a { + text-decoration: underline; + --item-color: var(--text-2); + } + } + } + + i { + vertical-align: text-top; + fill: var(--fill-color, var(--primary-light)); + display: inline-block; + block-size: 1.5rem; + aspect-ratio: 1; + + svg { + aspect-ratio: 1; + block-size: 1.5rem; + } + } + + .hero-section { + height: 65vh; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + .projects-section { + ul { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); + gap: 1rem; + } + + li { + border-radius: var(--border-radius); + overflow: hidden; + } + + article { + --background: url('https://placehold.co/200x150'); + position: relative; + height: 100%; + padding: .4rem; + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 2.5rem; + z-index: 1; + background: var(--background); + background-repeat: no-repeat; + background-size: cover; + } + + a { + &:hover { + i { + fill: #3a3a3a; + } + } + } + + i { + --fill-color: var(--text); + transition: fill .2s ease-in-out; + } + + .top { + width: 100%; + display: flex; + justify-content: space-between; + } + + .links { + display: flex; + gap: .2rem; + align-self: flex-end; + } + + .content { + padding: 1rem .4rem 0 .4rem; + } + } + + .about-section, + .projects-section, + .experiences-section { + padding-block: 2rem; + } + .about { + display: flex; + gap: 2rem; + align-items: center; + + & > div:first-child { + inline-size: 30%; + } + & > div:last-child { + inline-size: 60%; + } + img { + margin: 1rem auto; + inline-size: 100%; + inline-size: clamp(200px, 100%, 400px); + aspect-ratio: 1; + border-radius: 100%; + border: 4px solid var(--primary-dark) + } + ul { + margin-block-start: 1rem; + gap: .2rem; + } + + @media screen and (max-width: 767px) { + flex-direction: column; + + & > div:first-child, & > div:last-child { + inline-size: 100%; + } + + img { + inline-size: clamp(200px, 50vw, 300px); + margin: 0 auto; + } + } + } + + .timeline { + display: flex; + flex-direction: column; + position: relative; + padding: 0; + + &:before { + content: ''; + position: absolute; + inline-size: 6px; + background-color: var(--light-1); + inset: 0 0 0 1.5rem; + margin-inline-start: -3px; + } + + li { + --size: 3rem; + position: relative; + margin: 1.4rem 0; + padding: 0 0 0 calc(var(--size) + .8rem); + + &:first-child { + margin-top: 3rem; + } + + &:last-child { + margin-bottom: 0; + margin-bottom: -10px; + } + + &:after { + content: ''; + position: absolute; + aspect-ratio: 1; + inline-size: var(--size); + background-color: var(--light-1); + border: 6px solid var(--secondary-dark); + inset-inline-start: 0; + // inset-inline-start: .9rem; + inset-block-end: 50%; + transform: translateY(50%); + // inset-block-end: 0; + // inset-block-start: 1.5rem; + border-radius: 50%; + z-index: 1; + } + } + } + + .experiences-section { + p { + margin: 0; + } + } + +.download-section { + text-align: center; + margin-block: 3.5rem; + + .btn { + color: var(--secondary-light); + } + + p { + font-size: 1.4rem; + } +} \ No newline at end of file