/* ============================================================
   tomhermann.me — site stylesheet

   Concept: the homepage is a `git log --graph`. The main lane (ultramarine)
   holds profiles; the branch lane (teal) holds things Tom has built. Tool
   pages share the same tokens, type and form styles.

   Sections:  1 tokens · 2 base · 3 commit log · 4 page chrome · 5 tool pages · 6 motion · 7 résumé · 8 print
   ============================================================ */

/* ── 1. Tokens ───────────────────────────────────────────── */
:root {
    color-scheme: light dark;

    /* Colour — light is the primary composition */
    --bg:           #f3f5f9;
    --surface:      #ffffff;
    --ink:          #151c2c;
    --muted:        #485168;
    --rule:         #d6dbe6;
    --field-border: #6b748b;   /* ≥3:1 against --bg and --surface */

    --lane-main:    #2638d9;   /* the main lane, links on hover, primary buttons */
    --lane-branch:  #0a8577;   /* the branch lane */
    --signal:       #ffb224;   /* "you are here": HEAD ring and text selection */
    --focus:        #2638d9;
    --action:       #2638d9;
    --on-action:    #ffffff;
    --danger:       #b3261e;

    /* Type */
    --sans: 'Atkinson Hyperlegible Next', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
    --mono: 'Atkinson Hyperlegible Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

    /* Commit-graph geometry (shared by the head commit and every log row) */
    --x0:   0.95rem;                          /* centre of the main lane */
    --lane: 1.75rem;                          /* distance from main lane to branch lane; also the fork radius */
    --x1:   calc(var(--x0) + var(--lane));    /* centre of the branch lane */
    --gutter: calc(var(--x1) + 1.25rem);      /* width of the graph column */
    --node: 0.95rem;
    --lw:   2px;

    --page-width: 44rem;
    --page-top: clamp(2rem, 8vw, 5rem);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg:           #0e1524;
        --surface:      #16203a;
        --ink:          #e9edf7;
        --muted:        #a7b1c8;
        --rule:         #2a3656;
        --field-border: #7d88a6;

        --lane-main:    #8a9dff;
        --lane-branch:  #35d0b8;
        --signal:       #ffc857;
        --focus:        #ffc857;
        --action:       #8a9dff;
        --on-action:    #0e1524;
        --danger:       #ff9a90;
    }
}

@media (max-width: 30rem) {
    :root {
        --x0: 0.75rem;
        --lane: 1.4rem;
        --gutter: calc(var(--x1) + 1rem);
    }
}

/* ── 2. Base ─────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--sans);
    font-size: 1.0625rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

h1, h2, p, ol, ul { margin: 0; }

a {
    color: inherit;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}
a:hover { color: var(--lane-main); }

:focus-visible {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
}

::selection {
    background: var(--signal);
    color: #151c2c;
}

code, pre, kbd { font-family: var(--mono); }

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    left: 1rem;
    top: -4rem;
    z-index: 10;
    padding: 0.6rem 1rem;
    background: var(--action);
    color: var(--on-action);
    border-radius: 8px;
    font-weight: 600;
}
.skip-link:focus { top: 1rem; color: var(--on-action); }

/* ── 3. Commit log (home) ────────────────────────────────── */

/* One row of the graph. The head commit and every log entry use this grid. */
.commit {
    --node-y: 1.55rem;               /* vertical centre of the node, measured from the row's top */
    --lane-color: var(--lane-main);
    --nx: var(--x0);                 /* horizontal centre of this row's node */
    position: relative;
    display: grid;
    grid-template-columns: var(--gutter) minmax(0, 1fr);
}

.log { list-style: none; padding: 0; }

.graph { position: relative; }

/* Main lane: runs through every row. */
.graph::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--x0) - var(--lw) / 2);
    width: var(--lw);
    background: var(--lane-main);
    transform-origin: top;
}

/* Node */
.graph::after {
    content: '';
    position: absolute;
    top: calc(var(--node-y) - var(--node) / 2);
    left: calc(var(--nx) - var(--node) / 2);
    width: var(--node);
    height: var(--node);
    border-radius: 50%;
    background: var(--bg);
    border: var(--lw) solid var(--lane-color);
    transition: background-color 0.15s;
}

.log .commit:hover .graph::after,
.log .commit:focus-within .graph::after { background: var(--lane-color); }

/* The main lane trails off below the last row: more history to come. */
.log .commit:last-child .graph::before {
    bottom: -3rem;
    background: linear-gradient(to bottom, var(--lane-main) 55%, transparent);
}

/* Branch rows: node moves to the branch lane, and the branch lane gets its own line. */
.commit.is-branch {
    --nx: var(--x1);
    --lane-color: var(--lane-branch);
}

.commit.is-branch::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--x1) - var(--lw) / 2);
    width: var(--lw);
    background: var(--lane-branch);
    transform-origin: top;
}

/* Fork: a quarter-circle leaving the main lane at the top of the first branch row. */
.commit.is-fork::before { top: var(--lane); }

.commit.is-fork::after {
    content: '';
    position: absolute;
    top: calc(var(--lw) / -2);
    left: calc(var(--x0) - var(--lw) / 2);
    width: calc(var(--lane) + var(--lw));
    height: calc(var(--lane) + var(--lw) / 2);
    border-top: var(--lw) solid var(--lane-branch);
    border-right: var(--lw) solid var(--lane-branch);
    border-top-right-radius: var(--lane);
}

/* The branch is unmerged: it ends at its last node. */
.commit.is-tip::before { bottom: calc(100% - var(--node-y)); }

/* Head commit: the page's identity. History fades in from above the page. */
.commit-head {
    /* Scales with the viewport so "Tom Hermann" always fits on one line: the HEAD node's position
       below assumes a single-line name. 7 ≈ the name's width in em plus a safety margin. */
    --name-size: clamp(1.75rem, (100vw - 7.5rem) / 7, 5rem);
    /* name (line-height 1) + gap + half of the tagline line */
    --node-y: calc(var(--name-size) + 0.6rem + 0.9rem);
    --node: 1.3rem;
}

.commit-head .graph::before {
    top: calc(var(--page-top) * -1);
    background: linear-gradient(to bottom, transparent, var(--lane-main) var(--page-top));
}

.commit-head .graph::after {
    background: var(--lane-main);
    border-color: var(--lane-main);
    box-shadow: 0 0 0 3px var(--bg), 0 0 0 5px var(--signal);
}

.commit-head .commit-body { padding-block: 0 1.75rem; }

.name {
    font-size: var(--name-size);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.035em;
    margin-bottom: 0.6rem;
}

.tagline {
    font-size: 1.25rem;
    line-height: 1.4;
    font-weight: 600;
    text-wrap: balance;
}

.intro {
    color: var(--muted);
    margin-top: 0.25rem;
    text-wrap: pretty;
}

/* Log rows */
.commit-body {
    padding: 0.7rem 0.9rem 0.8rem;
    border-radius: 12px;
    transition: background-color 0.15s;
}
.log .commit:hover .commit-body { background: var(--surface); }

.commit-title {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.7rem;
    font-size: 1.2rem;
    line-height: 1.35;
    font-weight: 600;
}

.commit-title a { text-decoration: none; color: var(--ink); }
.commit-title a:hover { text-decoration: underline; text-decoration-thickness: 2px; color: var(--ink); }

/* Stretch the link over the whole row so the entire entry is one big tap target. */
.commit-title a::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 14px;
}
.commit-title a:focus-visible { outline: none; }
.commit-title a:focus-visible::after {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
}

.icon-external {
    width: 0.8em;
    height: 0.8em;
    margin-left: 0.2em;
    vertical-align: -0.05em;
    color: var(--muted);
}

.ref {
    font-size: 0.8125rem;
    font-weight: 400;
    color: var(--muted);
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 0 0.45rem;
    line-height: 1.5;
    white-space: nowrap;
}

.commit-desc {
    color: var(--muted);
    max-width: 36rem;
    text-wrap: pretty;
}

/* ── 4. Page chrome ──────────────────────────────────────── */
.page {
    flex: 1;
    width: min(100% - 2.5rem, var(--page-width));
    margin-inline: auto;
    padding-block: var(--page-top) 3rem;
}

.site-footer {
    width: min(100% - 2.5rem, var(--page-width));
    margin-inline: auto;
    padding-block: 1rem 2.5rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.5rem;
    font-family: var(--mono);
    font-size: 0.8125rem;
    color: var(--muted);
}
/* On the homepage, line the footer up with the log's text column. */
.home .site-footer { padding-left: calc(var(--gutter) + 0.9rem); }

.crumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 0 0.5rem;
    margin-bottom: 1.75rem;
    font-family: var(--mono);
    font-size: 0.9375rem;
    color: var(--muted);
}
.crumbs a { color: var(--ink); }
.crumbs a:hover { color: var(--lane-main); }

/* ── 5. Tool pages (ASCII, Base64) and error pages ───────── */
.page-title {
    font-size: clamp(1.9rem, 6vw, 2.5rem);
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.025em;
}

.lede {
    margin-top: 0.6rem;
    color: var(--muted);
    max-width: 36rem;
}

.panel {
    margin-top: 1.75rem;
    padding: 1.25rem;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: 12px;
}

.form { display: grid; gap: 1.1rem; }

.field { display: grid; gap: 0.4rem; }
.field > label,
.field-label {
    font-size: 0.9375rem;
    font-weight: 600;
}

.field input,
.field select,
.field textarea {
    width: 100%;
    padding: 0.6rem 0.75rem;
    min-height: 2.75rem;
    background: var(--bg);
    color: var(--ink);
    border: 1px solid var(--field-border);
    border-radius: 8px;
    font: inherit;
}
.field input,
.field textarea { font-family: var(--mono); font-size: 1rem; }
.field textarea { resize: vertical; line-height: 1.5; }
.field textarea[readonly] { background: transparent; }
.field input::placeholder,
.field textarea::placeholder { color: var(--muted); opacity: 1; }

.hint {
    font-size: 0.9375rem;
    color: var(--muted);
}
.panel + .hint { margin-top: 1.25rem; }

.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem;
    padding: 0.55rem 1.2rem;
    background: var(--action);
    color: var(--on-action);
    border: 1px solid var(--action);
    border-radius: 8px;
    font: inherit;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: filter 0.15s;
}
.btn:hover { color: var(--on-action); filter: brightness(1.12); }
.btn:active { filter: brightness(0.92); }

.btn-quiet {
    background: transparent;
    color: var(--ink);
    border-color: var(--field-border);
}
.btn-quiet:hover { color: var(--ink); background: var(--bg); filter: none; }

.alert {
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--danger);
    border-left-width: 4px;
    border-radius: 8px;
    color: var(--ink);
}
.alert strong { color: var(--danger); }

.output {
    margin: 0;
    padding: 1rem;
    overflow-x: auto;
    background: var(--bg);
    border: 1px solid var(--rule);
    border-radius: 8px;
    font-size: 0.9375rem;
    line-height: 1.2;
    tab-size: 4;
}

.result { margin-top: 1.5rem; display: grid; gap: 0.4rem; }

.error-page .error-code {
    font-family: var(--mono);
    font-size: clamp(4rem, 18vw, 8rem);
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.04em;
    color: var(--lane-main);
}
.error-page .page-title { margin-top: 0.75rem; }
.error-page .btn { margin-top: 1.75rem; }

/* ── 6. Motion ───────────────────────────────────────────── */
/* One moment: on load, the graph draws itself down the page, row by row.
   Text is never hidden — only the lines and nodes animate. */
@keyframes lane-grow { from { transform: scaleY(0); } }
@keyframes node-pop  { from { transform: scale(0.3); opacity: 0; } }
@keyframes fork-fade { from { opacity: 0; } }

@media (prefers-reduced-motion: no-preference) {
    .graph::before,
    .commit.is-branch::before {
        animation: lane-grow 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
        animation-delay: calc(var(--i, 0) * 90ms);
    }
    .graph::after {
        animation: node-pop 0.3s ease-out backwards;
        animation-delay: calc(var(--i, 0) * 90ms + 180ms);
    }
    .commit.is-fork::after {
        /* The fork reuses ::after on the row itself, so it can't also pop like a node. */
        animation: fork-fade 0.4s ease-out backwards;
        animation-delay: calc(var(--i, 0) * 90ms);
    }
}

@media (prefers-reduced-motion: reduce) {
    * { transition-duration: 0.01ms !important; }
}

/* ── 7. Résumé ───────────────────────────────────────────── */
.resume-head .tagline {
    margin-top: 0.35rem;
    font-family: var(--mono);
    font-size: 1.0625rem;
    color: var(--lane-main);
}

.contact {
    list-style: none;
    padding: 0;
    margin-top: 1rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
    font-family: var(--mono);
    font-size: 0.9375rem;
    color: var(--muted);
}
.contact a { color: var(--ink); }
.contact a:hover { color: var(--lane-main); }

.resume-section { margin-top: 2.75rem; }

.section-title {
    margin-bottom: 1.1rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--rule);
    font-family: var(--mono);
    font-size: 1rem;
    font-weight: 600;
    color: var(--muted);
}

.skills { display: grid; gap: 1rem 2rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.skill-name { margin: 0 0 0.4rem; font-size: 1.0625rem; font-weight: 600; }
.skill-level { margin-left: 0.5rem; font-family: var(--mono); font-size: 0.875rem; font-weight: 400; color: var(--muted); }

.tags {
    list-style: none;
    padding: 0;
    margin: 0.6rem 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}
.skill .tags { margin-top: 0; }
.tags li {
    padding: 0.05rem 0.55rem;
    border: 1px solid var(--rule);
    border-radius: 999px;
    background: var(--surface);
    font-family: var(--mono);
    font-size: 0.8125rem;
    line-height: 1.6;
}

/* Employers: a lane segment with a node, like a row of the homepage graph. */
.employer {
    position: relative;
    margin-left: 0.45rem;
    padding: 0 0 2rem 1.6rem;
    border-left: var(--lw) solid var(--lane-main);
}
.employer:last-child { padding-bottom: 0; }
.employer::before {
    content: '';
    position: absolute;
    top: 0.45rem;
    left: calc(var(--node) / -2 - var(--lw) / 2);
    width: var(--node);
    height: var(--node);
    border-radius: 50%;
    background: var(--bg);
    border: var(--lw) solid var(--lane-main);
}

.employer-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 1rem; }
.employer-name { margin: 0; font-size: 1.25rem; font-weight: 800; letter-spacing: -0.015em; }

.period { font-family: var(--mono); font-size: 0.875rem; color: var(--muted); }

.job { margin-top: 1.25rem; }
.employer-head + .job { margin-top: 0.6rem; }
.job-title { margin: 0; font-size: 1.0625rem; font-weight: 600; }
.job-desc { margin-top: 0.3rem; max-width: 40rem; }

@media (max-width: 30rem) {
    .employer { padding-left: 1.25rem; }
}

/* ── 8. Print ────────────────────────────────────────────── */
/* The PDF is rendered from this stylesheet (see scripts/build-resume-pdf.sh), so the two always match.
   Always light and ink-friendly, whatever the screen scheme was. */
@page { size: Letter; margin: 0.5in 0.6in; }

@media print {
    :root {
        --bg: #ffffff;
        --surface: #ffffff;
        --ink: #111827;
        --muted: #374151;
        --rule: #b6bdcb;
        --lane-main: #2638d9;
    }

    body { display: block; min-height: 0; font-size: 9.5pt; line-height: 1.4; -webkit-print-color-adjust: exact; print-color-adjust: exact; }

    .skip-link, .crumbs, .site-footer, .no-print, .icon-external, .sr-only { display: none; }

    .page { width: 100%; padding: 0; }
    .page-title { font-size: 22pt; }
    .lede { max-width: none; margin-top: 0.3rem; color: var(--ink); }
    .resume-head .tagline { font-size: 11pt; }
    .contact { font-size: 9pt; color: var(--ink); }

    .resume-section { margin-top: 0.9rem; }
    .section-title { margin-bottom: 0.6rem; font-size: 10pt; break-after: avoid; }
    .skills { grid-template-columns: repeat(2, 1fr); gap: 0.6rem 1.5rem; }
    .skill-name { font-size: 9.5pt; margin-bottom: 0.25rem; }
    .skill-level { font-size: 8.5pt; }

    .employer { padding-bottom: 0.7rem; break-inside: auto; }
    .employer-head { break-after: avoid; }
    .employer-name { font-size: 12pt; }
    .job { margin-top: 0.5rem; break-inside: avoid; }
    .job-title { font-size: 10pt; break-after: avoid; }
    .period { font-size: 8.5pt; }
    .job-desc { max-width: none; margin-top: 0.15rem; }
    .tags { margin-top: 0.35rem; gap: 0.25rem; }
    .tags li { font-size: 7pt; padding: 0 0.4rem; line-height: 1.5; }

    a { color: inherit; text-decoration: none; }
}
