/* ============================================================ * Owen Rummage — design tokens & global styles * ============================================================ */ :root { /* Dark theme (default). Warm-tinted near-black surface kept for human warmth; magenta-purple accent reads as deliberate task-light against it (warm room, cool focused light). */ --color-surface: oklch(0.178 0.006 70); --color-surface-rise: oklch(0.225 0.007 72); --color-ink: oklch(0.935 0.008 90); --color-ink-soft: oklch(0.86 0.008 88); --color-muted: oklch(0.69 0.008 82); --color-faint: oklch(0.45 0.008 78); --color-accent: oklch(0.72 0.21 325); --color-accent-strong: oklch(0.78 0.22 325); --color-rule: color-mix(in oklch, var(--color-ink) 14%, transparent); --color-rule-strong: color-mix(in oklch, var(--color-ink) 28%, transparent); --color-focus-ring: color-mix( in oklch, var(--color-accent) 70%, transparent ); --color-accent-wash: color-mix( in oklch, var(--color-accent) 14%, transparent ); /* Type */ --font-sans: "Geist Variable", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; --font-mono: "Geist Mono Variable", ui-monospace, SFMono-Regular, "JetBrains Mono", "IBM Plex Mono", "Cascadia Code", Menlo, Consolas, monospace; /* Type scale */ --fs-display: clamp(2.5rem, 1.6rem + 3.6vw, 3.875rem); --fs-statement: clamp(1.0625rem, 0.96rem + 0.45vw, 1.1875rem); --fs-role-title: 1.25rem; --fs-role-company: 1rem; --fs-body: 1rem; --fs-meta: 0.8125rem; --fs-contact: 0.9375rem; --fs-tiny: 0.75rem; /* Rhythm */ --leading-display: 1.04; --leading-statement: 1.45; --leading-body: 1.6; --leading-tight: 1.2; --tracking-display: -0.032em; --tracking-tight: -0.012em; --tracking-mono: -0.01em; --tracking-label: 0.04em; /* Layout */ --container-max: 760px; --container-pad-x: clamp(1.5rem, 4vw, 2.5rem); --container-pad-top: clamp(3.5rem, 8vw, 6rem); --container-pad-bottom: clamp(5rem, 12vw, 8rem); --col-meta: 124px; --gap-meta: 2rem; /* Motion */ --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --dur-fast: 160ms; --dur-base: 240ms; --dur-slow: 420ms; /* z-index scale */ --z-base: 1; --z-toggle: 10; --z-focus: 20; color-scheme: dark; } [data-theme="light"] { --color-surface: oklch(0.97 0 0); --color-surface-rise: oklch(0.93 0 0); --color-ink: oklch(0.2 0 0); --color-ink-soft: oklch(0.32 0 0); --color-muted: oklch(0.45 0 0); --color-faint: oklch(0.62 0 0); --color-accent: oklch(0.45 0.23 322); --color-accent-strong: oklch(0.4 0.24 318); --color-rule: color-mix(in oklch, var(--color-ink) 14%, transparent); --color-rule-strong: color-mix(in oklch, var(--color-ink) 26%, transparent); --color-focus-ring: color-mix( in oklch, var(--color-accent) 70%, transparent ); --color-accent-wash: color-mix( in oklch, var(--color-accent) 12%, transparent ); color-scheme: light; } /* ============================================================ * Reset (tight, no bloat) * ============================================================ */ *, *::before, *::after { box-sizing: border-box; } * { margin: 0; } html { -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; font-feature-settings: "kern", "liga", "calt", "ss01", "ss02"; font-variant-ligatures: common-ligatures contextual; background: var(--color-surface); } body { background: var(--color-surface); color: var(--color-ink); font-family: var(--font-sans); font-size: var(--fs-body); line-height: var(--leading-body); font-weight: 400; font-synthesis: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; min-height: 100vh; min-height: 100dvh; transition: background var(--dur-base) var(--ease-out-quint), color var(--dur-base) var(--ease-out-quint); } img, svg, video, canvas { display: block; max-width: 100%; height: auto; } input, button, textarea, select { font: inherit; color: inherit; } button { background: none; border: none; padding: 0; cursor: pointer; } :focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; border-radius: 1px; } /* ============================================================ * Page shell * ============================================================ */ .page { max-width: var(--container-max); margin: 0 auto; padding: var(--container-pad-top) var(--container-pad-x) var(--container-pad-bottom); } /* ============================================================ * Theme toggle (fixed corner) * ============================================================ */ .theme-toggle { position: fixed; top: clamp(1rem, 2.4vw, 1.75rem); right: clamp(1.25rem, 3vw, 2rem); z-index: var(--z-toggle); display: inline-flex; align-items: center; gap: 0.5ch; font-family: var(--font-mono); font-size: var(--fs-tiny); letter-spacing: var(--tracking-mono); color: var(--color-muted); } .theme-toggle button { font: inherit; color: inherit; padding: 0.25rem 0.125rem; transition: color var(--dur-fast) var(--ease-out-quint); position: relative; } .theme-toggle button:hover { color: var(--color-ink); } .theme-toggle button[aria-pressed="true"] { color: var(--color-accent); } .theme-toggle__sep { color: var(--color-faint); user-select: none; } /* ============================================================ * Hero (identity) * ============================================================ */ .hero { display: flex; flex-direction: column; gap: clamp(1.25rem, 3vw, 1.75rem); } .hero__name { font-family: var(--font-sans); font-size: var(--fs-display); font-weight: 500; line-height: var(--leading-display); letter-spacing: var(--tracking-display); color: var(--color-ink); text-wrap: balance; font-feature-settings: "kern", "ss01"; font-variation-settings: "wght" 540; } .hero__statement { font-size: var(--fs-statement); line-height: var(--leading-statement); letter-spacing: var(--tracking-tight); color: var(--color-ink-soft); max-width: 58ch; text-wrap: pretty; } .hero__contact { font-family: var(--font-mono); font-size: var(--fs-contact); letter-spacing: var(--tracking-mono); color: var(--color-muted); margin-top: 0.25rem; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 1.25rem; } /* ============================================================ * Link grammar * ============================================================ */ .link { color: var(--color-accent); text-decoration: none; position: relative; padding-bottom: 0.15em; background-image: linear-gradient( to right, var(--color-accent), var(--color-accent) ); background-position: 0 100%; background-repeat: no-repeat; background-size: 100% 1px; transition: color var(--dur-fast) var(--ease-out-quint), background-size var(--dur-base) var(--ease-out-quint); } .link:hover { color: var(--color-accent-strong); background-size: 100% 2px; } .link:focus-visible { outline-offset: 4px; } .link--ink { color: var(--color-ink); background-image: linear-gradient( to right, var(--color-rule-strong), var(--color-rule-strong) ); } .link--ink:hover { color: var(--color-accent); background-image: linear-gradient( to right, var(--color-accent), var(--color-accent) ); } /* ============================================================ * Hairline divider * ============================================================ */ .rule { border: 0; height: 1px; background: var(--color-rule); margin-block: clamp(3rem, 6vw, 4.5rem); width: 100%; } /* ============================================================ * Work index (marginalia grid) * ============================================================ */ .work { display: flex; flex-direction: column; } .role { display: grid; grid-template-columns: var(--col-meta) 1fr; gap: var(--gap-meta); padding-block: clamp(1.75rem, 3.5vw, 2.5rem); border-top: 1px solid transparent; transition: border-color var(--dur-base) var(--ease-out-quint); } .role + .role { border-top-color: var(--color-rule); } .role__meta { display: flex; flex-direction: row; flex-wrap: wrap; align-items: baseline; column-gap: 0.625rem; row-gap: 0.35rem; font-family: var(--font-mono); font-size: var(--fs-meta); letter-spacing: var(--tracking-mono); color: var(--color-muted); padding-top: 0.35rem; /* optical align with role title baseline */ white-space: nowrap; } .role--current .role__meta { column-gap: 0.3rem; } .role__years { font-variant-numeric: tabular-nums; } .role__live { display: inline-flex; align-items: center; gap: 0.45rem; color: var(--color-accent); font-family: var(--font-mono); font-size: var(--fs-tiny); letter-spacing: var(--tracking-label); text-transform: uppercase; font-variation-settings: "wght" 500; } .role__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-accent); display: inline-block; box-shadow: 0 0 0 0 var(--color-accent); animation: pulse 2s var(--ease-out-quint) infinite; } .role__body { display: flex; flex-direction: column; gap: 0.875rem; max-width: 64ch; } .role__title { font-family: var(--font-sans); font-size: var(--fs-role-title); font-weight: 500; letter-spacing: var(--tracking-tight); line-height: var(--leading-tight); color: var(--color-ink); text-wrap: balance; font-variation-settings: "wght" 520; } .role__company { font-family: var(--font-sans); font-size: var(--fs-role-company); color: var(--color-muted); letter-spacing: var(--tracking-tight); line-height: 1.35; } .role__bullets { list-style: none; padding: 0; margin: 0.5rem 0 0; display: flex; flex-direction: column; gap: 0.75rem; color: var(--color-ink-soft); } .role__bullets li { font-size: var(--fs-body); line-height: var(--leading-body); text-wrap: pretty; } .role--current .role__title { color: var(--color-ink); } /* ============================================================ * Practice (areas of competence — marginalia grid) * ============================================================ */ .practice { display: flex; flex-direction: column; } .area { display: grid; grid-template-columns: var(--col-meta) 1fr; gap: var(--gap-meta); padding-block: clamp(1.5rem, 3vw, 2.25rem); border-top: 1px solid transparent; transition: border-color var(--dur-base) var(--ease-out-quint); } .area + .area { border-top-color: var(--color-rule); } .area__meta { font-family: var(--font-mono); font-size: var(--fs-meta); letter-spacing: var(--tracking-mono); color: var(--color-muted); padding-top: 0.35rem; } .area__label { display: inline-block; } .area__body { display: flex; flex-direction: column; gap: 0.625rem; max-width: 64ch; } .area__title { font-family: var(--font-sans); font-size: var(--fs-role-title); font-weight: 500; letter-spacing: var(--tracking-tight); line-height: var(--leading-tight); color: var(--color-ink); text-wrap: balance; font-variation-settings: "wght" 520; } .area__desc { font-size: var(--fs-body); line-height: var(--leading-body); color: var(--color-ink-soft); text-wrap: pretty; } /* ============================================================ * Tools (single dense row in marginalia grid) * ============================================================ */ .toolset { display: grid; grid-template-columns: var(--col-meta) 1fr; gap: var(--gap-meta); padding-block: clamp(1.75rem, 3.5vw, 2.5rem); border-top: 1px solid var(--color-rule); } .toolset__meta { font-family: var(--font-mono); font-size: var(--fs-meta); letter-spacing: var(--tracking-mono); color: var(--color-muted); padding-top: 0.35rem; } .toolset__list { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--color-ink-soft); letter-spacing: var(--tracking-mono); align-items: baseline; } .toolset__list li { position: relative; display: inline-flex; align-items: baseline; padding: 0.25em 0.5em; margin: -0.25em 0; border-radius: 3px; color: var(--color-ink-soft); cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; font-variant-numeric: tabular-nums; transition: background-color var(--dur-base) var(--ease-out-quint), color var(--dur-fast) var(--ease-out-quint), transform var(--dur-base) var(--ease-out-quint), box-shadow var(--dur-base) var(--ease-out-quint); will-change: transform; } .toolset__list li:active { cursor: grabbing; } .toolset__list li.is-dragging { cursor: grabbing; z-index: 5; background-color: var(--color-accent-wash); color: var(--color-accent); box-shadow: 0 14px 36px color-mix(in oklch, var(--color-accent) 22%, transparent), 0 2px 8px color-mix(in oklch, var(--color-accent) 30%, transparent); /* JS owns transform / transition during drag */ transition: none !important; } .toolset__list li.is-dragging::before { color: var(--color-accent); } /* Suppress hover styles on other chips while a drag is in flight, so * they don't flash as the dragged chip sweeps over them. */ .toolset__list.is-dragging-list li:not(.is-dragging):hover { background-color: transparent; color: var(--color-ink-soft); transform: none; } .toolset__list.is-dragging-list li:not(.is-dragging):hover::before { color: var(--color-faint); transform: none; } body.is-toolset-dragging, body.is-toolset-dragging * { cursor: grabbing !important; } .toolset__list li::before { content: "#"; color: var(--color-faint); margin-right: 0.06em; display: inline-block; transform-origin: 50% 65%; transition: color var(--dur-fast) var(--ease-out-quint), transform var(--dur-base) var(--ease-out-quint); } .toolset__list li:hover { color: var(--color-accent); background-color: var(--color-accent-wash); transform: translateY(-1px); } .toolset__list li:hover::before { color: var(--color-accent); transform: rotate(-14deg) translate(-1px, -1px); } /* ============================================================ * Motto (closing reflection — marginalia grid) * ============================================================ */ .motto { display: grid; grid-template-columns: var(--col-meta) 1fr; gap: var(--gap-meta); margin-top: clamp(2.75rem, 5.5vw, 4rem); } .motto__meta { font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--color-muted); letter-spacing: var(--tracking-mono); padding-top: 0.4rem; user-select: none; } .motto__text { font-family: var(--font-sans); font-style: italic; font-size: var(--fs-statement); color: var(--color-ink-soft); line-height: var(--leading-statement); letter-spacing: var(--tracking-tight); max-width: 56ch; text-wrap: balance; font-variation-settings: "wght" 420, "slnt" -10; } /* ============================================================ * Footer * ============================================================ */ .foot { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 1rem; font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--color-muted); letter-spacing: var(--tracking-mono); } .foot__build { display: inline-flex; align-items: center; gap: 0.5rem; } .foot__build::before { content: ""; width: 4px; height: 4px; border-radius: 50%; background: var(--color-rule-strong); } .foot__home { font-variant-numeric: tabular-nums; } .foot__handle { color: var(--color-muted); } /* ============================================================ * Motion: live dot pulse + theme transitions * ============================================================ */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--color-accent) 50%, transparent); } 70% { box-shadow: 0 0 0 7px color-mix(in oklch, var(--color-accent) 0%, transparent); } 100% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--color-accent) 0%, transparent); } } /* ============================================================ * Responsive: stack the marginalia grid on narrow screens * ============================================================ */ @media (max-width: 640px) { .role, .area, .toolset, .motto { grid-template-columns: 1fr; gap: 0.875rem; } .motto__meta { display: none; } .role__meta { flex-direction: row; align-items: center; gap: 0.875rem; padding-top: 0; flex-wrap: wrap; } .role--current .role__meta { gap: 0.3rem; } .area__meta:empty { display: none; } .area__meta, .toolset__meta { padding-top: 0; } .hero__statement { max-width: 100%; } } @media (min-width: 1024px) { :root { --container-max: 800px; --col-meta: 132px; } } /* ============================================================ * Reduced motion * ============================================================ */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; } .role__dot { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-accent) 25%, transparent); } .toolset__list li:hover, .toolset__list li:hover::before { transform: none; } } /* ============================================================ * Print * ============================================================ */ @media print { :root { --color-surface: #ffffff; --color-ink: #111111; --color-muted: #444444; --color-faint: #777777; --color-accent: #6b2d7a; --color-rule: #cccccc; } .theme-toggle { display: none; } .role__dot { animation: none; } body { background: #fff; color: #111; } } /* ============================================================ * Selection * ============================================================ */ ::selection { background: var(--color-accent-wash); color: var(--color-ink); }