diff --git a/public/css/base.css b/public/css/base.css new file mode 100644 index 0000000..fd5bbf2 --- /dev/null +++ b/public/css/base.css @@ -0,0 +1,288 @@ +/** Variables */ + +:root { + --colour-primary-10: #060300; + --colour-primary-15: #150800; + --colour-primary-20: #1f1400; + --colour-primary-30: #3c2b00; + --colour-primary-40: #5c4300; + --colour-primary-50: #7f5d00; + --colour-primary-60: #a37800; + --colour-primary-70: #c89500; + --colour-primary-80: #efb300; + --colour-primary-90: #ffd98c; + --colour-primary-95: #ffecc8; + + --colour-hyperlink-10: #000409; + --colour-hyperlink-20: #001829; + --colour-hyperlink-30: #00314d; + --colour-hyperlink-40: #004d75; + --colour-hyperlink-50: #006a9f; + --colour-hyperlink-60: #1388c9; + --colour-hyperlink-70: #41a8ea; + --colour-hyperlink-80: #78c7ff; + --colour-hyperlink-90: #bfe3ff; + --colour-hyperlink-95: #e0f1ff; + + --colour-primary-fg: var(--colour-primary-90); + --colour-primary-fg-accent: var(--colour-primary-80); + --colour-primary-bg: var(--colour-primary-10); + --colour-code-fg: var(--colour-primary-90); + --colour-code-bg: var(--colour-primary-15); + --colour-hyperlink: var(--colour-hyperlink-80); + + --font-size-sm: 1rem; + --font-size-base: 1.125rem; + --font-size-md: 1.5rem; + --font-size-lg: 2rem; + --font-size-xl: 3rem; + + --spacing-block-xs: 0.5rem; + --spacing-block-sm: 1.75rem; + --spacing-block-md: 2.5rem; + --spacing-block-lg: 3.5rem; + --spacing-block-xl: 5rem; + --spacing-inline-xs: 0.25rem; + --spacing-inline-sm: 0.5rem; + --spacing-inline-md: 1.5rem; + --spacing-inline-lg: 3rem; + --spacing-inline-xl: 6rem; +} + +/** Light theme */ +@media (prefers-color-scheme: light) { + :root { + --colour-primary-fg: var(--colour-primary-20); + --colour-primary-fg-accent: var(--colour-primary-40); + --colour-primary-bg: var(--colour-primary-95); + --colour-hyperlink: var(--colour-hyperlink-40); + } +} + +/** Base typography */ + +body { + font-size: var(--font-size-base); + color: var(--colour-primary-fg); + font-weight: light; + background-color: var(--colour-primary-bg); + line-height: 1.5; + + /* Geometric Humanist stack from https://modernfontstacks.com */ + font-family: Avenir, Montserrat, Corbel, 'URW Gothic', source-sans-pro, sans-serif; +} + +small { + font-size: var(--font-size-sm); +} + +:is(p, h1, h2, h3, h4, h5, h6, hr, img, figure, ul, ol) { + margin-block-start: var(--spacing-block-sm); +} + +/** Base layout */ + +body { + --body-margin-inline-start: var(--spacing-inline-lg); + --body-margin-inline-end: var(--body-margin-inline-start); + --body-margin-block-end: var(--spacing-block-xl); + margin-inline: var(--body-margin-inline-start) var(--body-margin-inline-end); + margin-block-end: var(--body-margin-block-end); +} + +:is(h1, h2, h3, h4, h5, h6) { + text-align: center; +} + +img { + margin-inline: auto; + height: auto; +} + +@media (min-width: 48rem) { + body { + display: grid; + grid-template-columns: + [media-start] + var(--grid-margin-inline) + [content-start] + minmax(var(--grid-max-content-width), auto) + [content-end]; + column-gap: var(--spacing-block-sm); + max-width: var(--grid-total-width); + + --body-margin-inline-end: 6rem; + --grid-margin-inline: 6rem; + --grid-total-width: 48rem; + --grid-max-content-width: calc( + var(--grid-total-width) + - var(--body-margin-inline-start) + - var(--grid-margin-inline) + - var(--spacing-block-sm) + - var(--grid-margin-inline) + ); + } + + :is(main, article, nav) { + display: grid; + grid-column: media-start / content-end; + grid-template-columns: subgrid; + } + + :is(section, header, aside) { + grid-column: content-start / content-end; + } + + :is(h1, h2, h3, h4, h5, h6) { + text-align: start; + } +} + +/** Headings */ + +h1 { + font-size: var(--font-size-xl); + font-weight: 900; + margin-block-start: 0; +} + +h2 { + font-size: var(--font-size-lg); + font-weight: 900; + margin-block-start: var(--spacing-block-xl); +} + +h3, h4, h5, h6 { + font-size: var(--font-size-md); + font-weight: 600; + margin-block-start: var(--spacing-block-lg); +} + +/** Hyperlinks */ + +a:is(:link, :visited) { + color: var(--colour-hyperlink); + text-decoration: underline; + display: inline; +} + +a:hover { + text-decoration: wavy; +} + +/** Definition lists */ +dl { + margin-block-start: var(--spacing-block-md); +} + +dl dt { + font-weight: bold; +} + +dl dd + dt { + margin-block-start: var(--spacing-block-md); +} + +/** figcaptions */ + +figcaption { + font-size: var(--font-size-sm); + font-style: italic; + text-align: center; +} + +/** Lists */ + +:is(ol, ul) { + margin-inline-start: var(--spacing-inline-lg); +} + +/** Navigation bar */ + +nav { + margin-block: var(--spacing-block-sm); +} + +nav ul { + grid-column: media-start / content-end; + display: flex; + justify-content: center; + gap: var(--spacing-inline-md); + list-style: none; + margin: 0; +} + +@media (min-width: 36rem) { + nav { + display: grid; + grid-template-columns: subgrid; + } + + nav ul { + justify-content: end; + } +} + +/** Emphasis */ + +strong { + font-weight: bold; + font-style: italic; +} + +/** Blog feed */ + +.h-feed ul { + list-style: none; + margin-inline: 0; +} + +/** Block quotes */ +blockquote { + padding-inline-start: var(--spacing-inline-lg); + border-inline-start: 2px solid var(--colour-primary-fg); + font-style: italic; +} + + blockquote footer { + font-style: initial; +} + +blockquote :is(b, strong) { + font-style: italic; + font-weight: bold; +} + +blockquote :is(i, em) { + font-style: normal; +} + +/** Small caps */ +.small-caps { + font-variant: small-caps; +} + +/** Pre-formatted blocks */ +pre { + border: 2px solid var(--colour-primary-fg); + border-radius: 2px; + background-color: var(--colour-code-bg) !important; + margin-block-start: var(--spacing-block-sm); + padding-inline: var(--spacing-inline-sm); + padding-block: var(--spacing-block-xs); +} + +/** Code blocks */ +code { + border: 2px solid var(--colour-primary-fg); + border-radius: 2px; + padding-inline: var(--spacing-inline-xs); + color: var(--colour-code-fg); + background-color: var(--colour-code-bg); + font-size: var(--font-size-sm); +} +pre code { + border: none; + border-radius: none; + padding: none; +} diff --git a/public/css/blog.css b/public/css/blog.css new file mode 100644 index 0000000..436c13e --- /dev/null +++ b/public/css/blog.css @@ -0,0 +1,8 @@ +.p-summary { + font-style: italic; + font-size: var(--font-size-sm); +} + +h1 { + margin-block-start: var(--spacing-block-md); +} diff --git a/public/css/cv.css b/public/css/cv.css new file mode 100644 index 0000000..b481d05 --- /dev/null +++ b/public/css/cv.css @@ -0,0 +1,86 @@ +div:has(img) { + width: 6rem; + height: 6rem; + margin-inline: auto; +} + +div img { + width: 6rem; + height: 6rem; + border-radius: 1rem; + filter: contrast(1.25); +} + +div:has(img)::after { + /* Colour overlay */ + background-color: var(--colour-primary-80); + opacity: 0.3; + + /* Same size and shape as the img */ + border-radius: 1rem; + width: 6rem; + height: 6rem; + + /* Positioned on top of the img */ + display: block; + position: relative; + top: -6rem; + + /* A content value is needed to get the ::after to render */ + content: ''; +} + +header { + display: grid; + grid-template-columns: 1fr 1fr; + text-align: center; + border-block-end: 1px solid var(--colour-primary-fg); +} + +header h1 { + grid-column: 1 / 3; + text-align: center; +} + +.technical-skills h3 { + text-align: start; +} + +.technical-skills ul { + color: var(--colour-primary-fg-accent); + margin-inline-start: var(--spacing-inline-md); +} + +@media (min-width: 46rem) { + .technical-skills section { + display: flex; + gap: var(--spacing-inline-sm); + align-items: baseline; + } + + .technical-skills section h3::after { + content: '/'; + margin-inline: var(--spacing-inline-sm); + } + + .technical-skills section ul { + display: flex; + gap: var(--spacing-inline-sm); + list-style: none; + margin-inline-start: 0; + } + + .technical-skills section ul li + li::before { + content: '•'; + margin-inline-end: var(--spacing-inline-sm); + } +} + +:is(.experience, .passions) :is(ol, ul) { + list-style: none; + margin-inline: 0; +} + +:is(.experience, .passions) :is(ol, ul) li { + margin-block-start: var(--spacing-block-sm); +} diff --git a/public/css/feed.css b/public/css/feed.css new file mode 100644 index 0000000..fc665ec --- /dev/null +++ b/public/css/feed.css @@ -0,0 +1,16 @@ +/* Assumes there is at most one level of subheading for sub-dividing entries */ +.h-feed :is(h2, h3, h4, h5, h6) { + margin-block-start: var(--spacing-block-md); +} + +.h-feed .h-entry { + margin-block-start: var(--spacing-block-xs); +} + +.h-feed .full-feed-link { + text-align: end; +} + +.h-feed :is(a.full-feed-link, .full-feed-link a)::after { + content: ' >' +} diff --git a/public/css/hcard.css b/public/css/hcard.css new file mode 100644 index 0000000..c0e2280 --- /dev/null +++ b/public/css/hcard.css @@ -0,0 +1,57 @@ +.h-card div:has(img) { + width: 6rem; + height: 6rem; + margin-inline: auto; +} + +.h-card img { + width: 6rem; + height: 6rem; + border-radius: 1rem; + filter: contrast(1.25); +} + +.h-card div:has(img)::after { + /* Colour overlay */ + background-color: var(--colour-primary-80); + opacity: 0.3; + + /* Same size and shape as the img */ + border-radius: 1rem; + width: 6rem; + height: 6rem; + + /* Positioned on top of the img */ + display: block; + position: relative; + top: -6rem; + + /* A content value is needed to get the ::after to render */ + content: ''; +} + + +@media (min-width: 36rem) { + .h-card { + grid-column: media-start / content-end; + display: grid; + grid-template-columns: subgrid; /** Subgrid of main column layout */ + grid-template-rows: min-content 1fr; + grid-template-areas: + "empty heading" + "photo text"; + } + + .h-card div:has(img) { + grid-area: photo; + margin-block-start: var(--spacing-block-sm); + } + + .h-card header { + grid-area: heading; + } + + .h-card__text { + grid-area: text; + } +} diff --git a/public/css/reset.css b/public/css/reset.css new file mode 100644 index 0000000..6cb4c4f --- /dev/null +++ b/public/css/reset.css @@ -0,0 +1,73 @@ +/* Based on Andy Bell’s More Modern CSS Reset: https://piccalil.li/blog/a-more-modern-css-reset/ */ + +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Prevent font size inflation */ +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + +/* Remove default margin in favour of better control in authored CSS */ +body, h1, h2, h3, h4, p, +figure, blockquote, dl, dd { + margin-block: 0; +} + +/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ +ul[role='list'], +ol[role='list'] { + list-style: none; +} + +/* Set core body defaults */ +body { + min-height: 100vh; +} + +/* Set shorter line heights on headings and interactive elements */ +h1, h2, h3, h4, +button, input, label { + line-height: 1.1; +} + +/* Balance text wrapping on headings */ +h1, h2, +h3, h4 { + text-wrap: balance; +} + +/* Make images easier to work with */ +img, +picture { + max-width: 100%; + display: block; +} + +/* Inherit fonts for inputs and buttons */ +input, button, +textarea, select { + font: inherit; +} + +/* Make sure textareas without a rows attribute are not tiny */ +textarea:not([rows]) { + min-height: 10em; +} + +/* Anything that has been anchored to should have extra scroll margin */ +:target { + scroll-margin-block: 5ex; +} + +* { + margin: 0; + padding: 0; +} + diff --git a/public/images/blog/2024/05/02/beautiful_youtube_homepage.jpg b/public/images/blog/2024/05/02/beautiful_youtube_homepage.jpg new file mode 100644 index 0000000..b584611 Binary files /dev/null and b/public/images/blog/2024/05/02/beautiful_youtube_homepage.jpg differ diff --git a/public/images/blog/2024/06/30/ncuti-gatwa-promo-pic.webp b/public/images/blog/2024/06/30/ncuti-gatwa-promo-pic.webp new file mode 100644 index 0000000..cd74f23 Binary files /dev/null and b/public/images/blog/2024/06/30/ncuti-gatwa-promo-pic.webp differ diff --git a/public/images/headshot.webp b/public/images/headshot.webp new file mode 100644 index 0000000..0c2a15b Binary files /dev/null and b/public/images/headshot.webp differ diff --git a/public/images/headshot_large.jpg b/public/images/headshot_large.jpg new file mode 100644 index 0000000..2ca13cf Binary files /dev/null and b/public/images/headshot_large.jpg differ