N. E. Karantanis — Site Docs View live site ↗
Documentation

Design System

Everything visual on the site traces back to css/custom.css — one hand-written stylesheet, no CSS framework beyond Bootstrap’s grid/utility classes for layout. This page covers the palette, type scale, and the small utility/component classes built on top of them.

Color palette

Every color on the site is a CSS custom property defined once on :root, named --nk-c0 through --nk-c4 (dark to light) plus a gold accent. Nothing else hardcodes a hex value — components reference these variables so a palette change only ever happens in one place. --nk-c1 (sky) has strong contrast on dark sections but fails AA on light ones, so it’s only ever used on dark backgrounds or as a solid button’s own fill; --nk-c2 (cobalt) is the accent used against paper/stone.

--nk-c0
#10141F · ink / body text
--nk-c1
#6FC2FF · sky accent, dark sections only
--nk-c2
#2653D9 · cobalt accent
--nk-c3
#E4DFD3 · stone surface
--nk-c4
#F7F6F1 · paper surface
--nk-gold
#FF7A33 · tangerine, eyebrow/accent on dark

--nk-c1 and --nk-c2 each have a -h hover variant (--nk-c1h, --nk-c2h) that’s a slightly darker shade, used on :hover states instead of relying on opacity or filter. There are also -rgb variants (--nk-c0-rgb, --nk-c1-rgb, --nk-c4-rgb) holding the same colors as comma-separated R,G,B numbers, so they can be dropped into rgba(var(--nk-c0-rgb), 0.1) wherever a translucent tint is needed (borders, subtle fills) — a plain custom property can’t be given an alpha channel on its own.

Beyond the five core surfaces, there’s a small set of muted text tones for body copy (--nk-text-muted, --nk-text-faint, --nk-text-faint-dark, --nk-text-cream, --nk-text-cream-strong, --nk-text-body-dark) and three shadow presets (--nk-shadow-btn, --nk-shadow-pill, --nk-shadow-card) used by every hover-lift and card.

Utility classes, all just aliasing a variable:

.bg-c0 / .bg-c1 / .bg-c2 / .bg-c3 / .bg-c4        /* background-color */
.text-c0 / .text-c1 / .text-c2 / .text-c3 / .text-c4  /* color */
.text-muted-warm / .text-faint / .text-faint-dark
.text-cream / .text-cream-strong / .text-body-dark / .text-gold
.fill-c0 / .fill-c1 / .fill-c3 / .fill-c4          /* SVG fill */

Typography

Two font families, both loaded from Google Fonts in _layouts/default.html:

  • Space Grotesk (500/600/700) — every heading (h1h4 are set to it globally), plus anywhere .ff-grotesk is applied to a non-heading element.
  • Inter (400/500/600/700) — body text, the default on <body>.

Font sizes are all utility classes rather than one-off inline styles, named .fs-<size> after their pixel value (each also sets a matching line-height):

Aa.fs-13
Aa.fs-16
Aa.fs-19
Aa.fs-24
Aa.fs-30
Aa.fs-42

Two sizes are fluid (clamp()) rather than fixed, so headline text scales smoothly with viewport width instead of jumping at breakpoints:

.fs-hero       { font-size: clamp(36px, 6vw, 64px); }  /* home hero h1 */
.fs-post-title { font-size: clamp(28px, 4.5vw, 44px); } /* post title, CMS preview */

Letter-spacing utilities (.ls-02, .ls-1, .ls-15, .ls-2) exist mainly for the all-caps “eyebrow” labels and uppercase nav text, where a little extra tracking reads better.

Buttons

Every button on the site is .btn-nk plus a color modifier and an optional size modifier:

<a href="#" class="btn-nk btn-nk-solid-c1">View Full Credentials</a>
<a href="#" class="btn-nk btn-nk-outline btn-nk--lg">Read the Blog</a>
  • Color: .btn-nk-solid-c1 (sky fill), .btn-nk-solid-c2 (cobalt fill), .btn-nk-outline (transparent, for dark backgrounds)
  • Size: .btn-nk--nav (compact, for the nav bar), .btn-nk--sm, .btn-nk--lg (default padding needs no modifier)

Every button lifts 3px and gains a drop shadow on :hover via a shared transform/box-shadow transition on the base .btn-nk class — colors only change the fill/border, never the hover motion, so the lift feels consistent everywhere. (This is also the interaction that the hero’s entrance animation once silently broke — see the animation-fill-mode note on the JavaScript page.)

Tags & pills

.tag-pill is the small rounded label used on post cards and the About page’s certifications list; .tag-pill.on-card swaps its background for use on a card that’s already --nk-c4, and .tag-pill--dark is the cream-on-translucent-white variant for dark sections. .pill-link is the larger, bordered pill used for the About page’s section jump-nav — it lifts on hover the same way buttons do.

Reveal-on-scroll utilities

Three attribute-based classes control the fade/slide-in-on-scroll animation (the actual triggering logic lives in site.js — see JavaScript):

<div data-reveal>...</div>              <!-- fades up, no direction -->
<div data-reveal-grid>...</div>          <!-- direction assigned at runtime from its row position -->
<div data-reveal-split="left">...</div>  <!-- fixed left/right column, direction never changes -->

[data-reveal-grid] is for card grids (stats, pillars, blog posts) where which card is “leftmost” depends on however many columns actually fit at the current viewport width — so JavaScript works that out live rather than the class being hardcoded per card. [data-reveal-split] is for the About page’s two-column timeline rows, where the left/right assignment is fixed by the layout and never needs to be recalculated.

Stagger delay classes (.td-0 through .td-24) sit alongside these to offset a row of cards’ entrance by a few hundredths of a second each, so a row cascades in rather than all appearing in one frame.