/*
    Sanderwell brand tokens.

    Palette, type scale, focus treatment, and motion preferences. Everything else in the site
    styles from these values, so a brand change happens here and nowhere else.

    Contrast notes (WCAG 2.1 AA needs 4.5:1 for body text, 3:1 for large text and UI borders):
      --ink         on --surface  16.43:1
      --ink-2       on --surface   8.29:1
      --accent-deep on --surface   9.30:1   (links, eyebrows, and the primary button fill)
      --accent      on --surface   6.05:1
      --muted       on --surface   6.09:1
      --muted       on --paper     5.51:1
      --error       on --surface   7.33:1
      --on-ink      on --ink      13.92:1   (reversed sections)
    Values below the 4.5 threshold are not used for text anywhere. --hairline is 1.37:1 and is
    deliberately not held to that: a rule that clears text contrast is a border, not a hairline.
*/

:root {
    /*
        Core palette -- oxblood on warm near-neutral. Both the brand accent and the error state are
        red, which is the one thing to know before editing here. They are 34.5 dE apart, which is
        clear separation, but the separation is carried by the accent being a desaturated brick and
        the error a saturated crimson: lighten --accent-deep or desaturate --error and the contact
        form starts reading as though its links have failed validation. Every error signal is
        redundantly coded anyway (2px border, bold weight, aria-invalid, the error summary), so the
        colour is never the only thing saying so.
    */
    --ink: #241E1D;
    --ink-2: #42505C;
    --accent: #9C4A42;
    --accent-deep: #7A2E2E;
    --muted: #6B605B;
    --paper: #F6F3F1;
    --hairline: #E2DBD7;
    --surface: #FFFFFF;

    /* Validation failures only. Clears AA as text on white (7.33:1) and on paper (6.63:1). */
    --error: #B00020;

    /* Reversed-section aliases, so dark blocks do not hard-code hex values */
    --on-ink: #F1EBE9;
    --on-ink-muted: #B2A7A4;
    --on-ink-hairline: #70625F80;

    /*
        Self-hosted face first, then system fallbacks. The woff2 files are optional: an empty
        wwwroot/fonts renders in the fallbacks without layout breakage. See that folder's README.
    */
    --font-display: "Source Serif 4", "Source Serif Pro", Georgia, "Iowan Old Style",
        "Times New Roman", serif;
    --font-body: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
        Arial, sans-serif;

    /*
        Type scale. Body is 16px and the smallest step is 12px -- the mockup used 10-11px for
        eyebrow labels, which is too small to read regardless of how well it contrasts.
    */
    --text-eyebrow: 0.75rem;   /* 12px floor */
    --text-sm: 0.9375rem;      /* 15px */
    --text-base: 1rem;         /* 16px */
    --text-lg: 1.125rem;       /* 18px */
    --text-xl: 1.375rem;       /* 22px */
    --text-2xl: 1.75rem;       /* 28px */
    --text-3xl: 2.25rem;       /* 36px */
    --text-4xl: 3rem;          /* 48px */

    --leading-tight: 1.15;
    --leading-snug: 1.35;
    --leading-normal: 1.6;

    /* Spacing */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;
    --space-8: 4rem;
    --space-9: 6rem;

    --measure: 68ch;
    --page-max: 1140px;
    --radius: 2px;
}

/* ---------------------------------------------------------------- reset */

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

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

/*
    Keeps anything scrolled into view clear of the sticky header, which would otherwise land a
    keyboard user following the skip link underneath an opaque bar. Scoped to the breakpoint where
    the header actually becomes sticky; see site.css.
*/
@media (min-width: 720px) {
    html {
        /* Must stay above the header's height; 6.5rem leaves headroom over the measured row. */
        scroll-padding-top: 6.5rem;
    }
}

body {
    margin: 0;
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    /* Long words and URLs must not force the page to scroll sideways at 360px. */
    overflow-wrap: break-word;
}

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

/* ------------------------------------------------------------ focus ring */

/*
    One ring, defined once. :focus-visible rather than :focus so a mouse click leaves no ring but
    every keyboard tab stop shows one. The offset keeps it visible on filled buttons.
*/
:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius);
}

/* Reversed sections need a ring that is visible against the dark ink ground. */
.reversed :focus-visible,
.site-footer :focus-visible {
    outline-color: var(--on-ink);
}

/* --------------------------------------------------------------- skip link */

/*
    Visually hidden until focused, then pinned to the top-left. This is the first focusable
    element in the document, so it is what a keyboard user reaches on their first Tab.
*/
.skip-to-main {
    position: absolute;
    left: var(--space-4);
    top: var(--space-4);
    z-index: 100;
    padding: var(--space-3) var(--space-5);
    background: var(--ink);
    color: var(--on-ink);
    font-weight: 600;
    text-decoration: none;
    border-radius: var(--radius);
    transform: translateY(-200%);
}

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

/*
    The skip target takes focus programmatically via tabindex="-1". Suppress its ring: the
    heading it lands on is the confirmation, and a box around the whole page reads as an error.
*/
.skip-target:focus {
    outline: none;
}

/* ------------------------------------------------------------ reduced motion */

/*
    Defined here so no component has to remember it. Anything that animates later inherits the
    opt-out automatically.
*/
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ------------------------------------------------------------- screen reader */

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