/* =============================================================================
   Xandev V3 - fonts, reset, and element defaults
   Load after tokens.css.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   Fonts

   Self-hosted rather than loaded from Google. Three reasons: the CSP can then
   forbid every third-party origin outright, there is no third party logging
   visitors' IP addresses on our behalf (which the privacy policy would have to
   disclose), and the files are served from the same connection as the page.

   Both families are variable, so one file covers every weight - and for
   Archivo, every width too. Archivo and JetBrains Mono are both SIL Open Font
   License 1.1; see fonts/LICENSE.txt.
   -------------------------------------------------------------------------- */

@font-face {
    font-family: "Archivo Variable";
    src: url("../fonts/archivo-latin.woff2") format("woff2");
    font-weight: 100 900;
    font-stretch: 62% 125%;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
        U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
        U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Archivo Variable";
    src: url("../fonts/archivo-latin-ext.woff2") format("woff2");
    font-weight: 100 900;
    font-stretch: 62% 125%;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
        U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
        U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
        U+A720-A7FF;
}

@font-face {
    font-family: "JetBrains Mono Variable";
    src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2");
    font-weight: 100 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
        U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
        U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -----------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;

    /* Offset for the sticky header so anchor links do not land under it. */
    scroll-padding-top: 6rem;
    -moz-tab-size: 4;
    tab-size: 4;
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

body {
    min-height: 100dvh;
    background-color: var(--surface-page);
    color: var(--text-primary);

    font-family: var(--font-body);
    font-size: var(--text-md);
    font-stretch: 100%;
    font-weight: 400;
    line-height: var(--leading-normal);

    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-synthesis: none;

    /* Theme switching should feel like a light being dimmed, not a page
       reload - but only the two properties that actually change. */
    transition: background-color var(--duration-slow) var(--ease),
                color var(--duration-slow) var(--ease);
}

/* The switch is instant while the user is dragging the toggle; the transition
   above is disabled for that moment by the theme script to avoid a lag. */
body.theme-switching,
body.theme-switching * {
    transition: none !important;
}

img,
picture,
video,
canvas,
svg {
    display: block;
    max-width: 100%;
    height: auto;
}

input,
button,
textarea,
select {
    font: inherit;
    color: inherit;
}

button {
    background: none;
    border: none;
    cursor: pointer;
}

ul[role="list"],
ol[role="list"] {
    list-style: none;
}

/* -----------------------------------------------------------------------------
   Typography

   Headings run on the expanded width axis; body copy stays at normal width.
   That width contrast is what carries the personality here, so display type
   does not need a second typeface to feel distinct from the text around it.
   -------------------------------------------------------------------------- */

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-stretch: var(--width-display);
    font-weight: 700;
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    text-wrap: balance;
    color: var(--text-primary);
}

h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); letter-spacing: var(--tracking-tight); }
h4 { font-size: var(--text-xl);  letter-spacing: var(--tracking-tight); line-height: var(--leading-snug); }
h5 { font-size: var(--text-lg);  letter-spacing: var(--tracking-tight); line-height: var(--leading-snug); }
h6 { font-size: var(--text-base); letter-spacing: var(--tracking-tight); line-height: var(--leading-snug); }

p {
    text-wrap: pretty;
}

/* Long-form prose gets a measure cap; a full-width paragraph on a 27" monitor
   is unreadable no matter how good the type is. */
.prose {
    max-width: var(--measure);
    color: var(--text-secondary);
    line-height: var(--leading-relaxed);
}

.prose > * + * {
    margin-block-start: var(--space-4);
}

.prose h2,
.prose h3 {
    margin-block-start: var(--space-8);
    color: var(--text-primary);
}

/* A subheading inside a section rather than a new section, so it sits closer
   to what it introduces than an h3 does and is distinguished by weight and
   colour rather than by size. Used where a topic needs breaking into parts a
   reader can be pointed at, as the analytics section of the privacy policy is. */
.prose h4 {
    margin-block-start: var(--space-6);
    margin-block-end: calc(var(--space-4) * -1 + var(--space-2));
    color: var(--text-primary);
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: 700;
}

.prose ul,
.prose ol {
    padding-inline-start: var(--space-5);
}

.prose li + li {
    margin-block-start: var(--space-2);
}

.prose li::marker {
    color: var(--text-muted);
}

a {
    color: var(--brand-text);
    text-decoration-color: color-mix(in oklab, var(--brand-text) 40%, transparent);
    text-underline-offset: 0.2em;
    text-decoration-thickness: 1px;
    transition: color var(--duration) var(--ease),
                text-decoration-color var(--duration) var(--ease);
}

/*
   :where() contributes zero specificity, so this rule stays at element level
   (0,0,1) - the same weight as the `a` rule above it, winning only on source
   order.

   Written the obvious way as `a:hover` it scores (0,1,1) and outranks every
   component class (0,1,0). That meant a hovered `.btn` had its label repainted
   var(--brand) - amber text on an amber button, about 1.4:1 - and a hovered
   `.work-card` had its entire body text turn amber. Components should not each
   have to restate their own colour just to defend against the base link style.
*/
a:where(:hover) {
    color: var(--brand);
    text-decoration-color: currentColor;
}

strong, b { font-weight: 650; }

code, kbd, samp, pre {
    font-family: var(--font-mono);
    font-size: 0.9em;
    font-feature-settings: "liga" 0;
}

code {
    padding: 0.15em 0.4em;
    border-radius: var(--radius-xs);
    background: var(--surface-overlay);
    color: var(--accent-text);
}

pre {
    overflow-x: auto;
    padding: var(--space-4);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
}

pre code {
    padding: 0;
    background: none;
    color: inherit;
}

blockquote {
    padding-inline-start: var(--space-4);
    border-inline-start: 2px solid var(--brand);
    color: var(--text-secondary);
    font-size: var(--text-lg);
}

hr {
    height: 1px;
    border: 0;
    background: var(--line);
}

/* -----------------------------------------------------------------------------
   Utility type
   -------------------------------------------------------------------------- */

/* Small mono label above a section heading. Set in the monospace face because
   it reads as metadata - a category, a step, a status - rather than as prose.
   It is the one place uppercase is used. */
.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);

    font-family: var(--font-mono);
    font-size: var(--text-3xs);
    font-weight: 500;
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--text-muted);
}

/* The signature mark: a hairline carrying the brand gradient, used to open a
   section. Everything else on the page stays monochrome so this reads. */
.rule {
    width: 100%;
    height: 1px;
    border: 0;
    background: var(--brand-gradient);
    opacity: 0.9;
}

.rule--short { width: 3rem; }

.text-muted     { color: var(--text-muted); }
.text-secondary { color: var(--text-secondary); }
.text-brand     { color: var(--brand-text); }
.text-accent    { color: var(--accent-text); }
.text-success   { color: var(--success); }
.text-warning   { color: var(--warning); }
.text-danger    { color: var(--danger); }

.mono {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}

/* Numbers in tables and invoices must line up column-to-column. */
.tabular { font-variant-numeric: tabular-nums; }

/* -----------------------------------------------------------------------------
   Layout primitives
   -------------------------------------------------------------------------- */

.container {
    width: 100%;
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.container--wide { max-width: var(--container-wide); }
.container--narrow { max-width: 780px; }

.section {
    padding-block: var(--section-y);
}

.stack-tight > * + * { margin-block-start: var(--space-1); }
.stack > * + * { margin-block-start: var(--space-4); }
.stack-lg > * + * { margin-block-start: var(--space-6); }

.cluster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
}

/* -----------------------------------------------------------------------------
   Accessibility
   -------------------------------------------------------------------------- */

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

/* Remove the ring for pointer users without removing it for keyboard users. */
:focus:not(:focus-visible) {
    outline: none;
}

.skip-link {
    position: absolute;
    top: var(--space-3);
    left: var(--space-3);
    z-index: var(--z-toast);

    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--brand);
    color: var(--text-inverse);
    font-weight: 600;
    text-decoration: none;

    transform: translateY(-200%);
    transition: transform var(--duration) var(--ease);
}

.skip-link:focus {
    transform: translateY(0);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

::selection {
    background: color-mix(in oklab, var(--brand) 35%, transparent);
    color: var(--text-primary);
}

/* -----------------------------------------------------------------------------
   Scrollbars - themed, but only where the browser allows it without hurting
   usability. Width stays close to the platform default so it remains grabbable.
   -------------------------------------------------------------------------- */

@supports (scrollbar-color: red blue) {
    html {
        scrollbar-color: var(--line-strong) transparent;
        scrollbar-width: thin;
    }
}

/* -----------------------------------------------------------------------------
   Print
   -------------------------------------------------------------------------- */

@media print {
    :root {
        --surface-page: #fff;
        --surface-raised: #fff;
        --text-primary: #000;
        --text-secondary: #333;
    }

    .site-header,
    .site-footer,
    .skip-link,
    .theme-toggle {
        display: none !important;
    }

    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: 0.85em;
        color: #555;
    }
}
