/* Site chrome — shared by index.html and 404.html.
 *
 * These two pages used to carry independent copies of the header and footer, and
 * nothing detected when the copies disagreed. They drifted badly: the 404 had no
 * nav, a non-sticky header, a differently-coloured and differently-sized footer,
 * no `img { max-width }`, and a :root that was silently missing --brown-light.
 * All of it shipped through a green bin/verify.
 *
 * So the chrome lives here, in one file, and cannot drift. What could not move —
 * page-specific body layout, buttons, heading scales — stays inline on each page,
 * and scripts/check_chrome_parity.py guards the header/footer MARKUP that is still
 * necessarily duplicated. That gate also forbids these selectors from reappearing
 * in a page's inline <style>, which is exactly how the drift started.
 *
 * Load order matters: each page links this file BEFORE its own <style>, so
 * page-specific rules win ties on purpose.
 *
 * Tokens are documented in brand-book.html, which remains the single source for
 * what the values mean. */

/* ---------- tokens, resets, globals ---------- */
:root {
    --orange: #df762f;
    --orange-bright: #f08b43;
    --orange-soft: #efb07c;
    --ink: #2c2017;
    --brown: #4b3527;
    --brown-mid: #70523d;
    --brown-light: #a5876d;
    --sand: #d8c6ae;
    --sand-light: #e6d9c8;
    --cream: #f3ece1;
    --paper: #fbf8f3;
    --white: #ffffff;
    --page: 1180px;
    --rule: rgba(75, 53, 39, 0.28);
    /* The two typefaces, declared once. Both stacks were previously written
       out by hand at each use site — the serif four times — which is how a
       display rule drifts from the rest. Loaded via the Google Fonts link
       in <head>; the fallbacks cover the swap window and a blocked request. */
    --font-sans: "Hanken Grotesk", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --font-serif: "Bree Serif", Georgia, serif;
    /* Radius scale matches the business-card sheet (4px controls, 8px surfaces).
       The 240px sweep on the process shape stays a deliberate brand exception. */
    --radius-control: 4px;
    --radius-surface: 8px;
    --radius-pill: 999px;
    /* Shadows are tinted with the ink brown, never neutral black;
       a grey shadow reads cold against this warm paper. */
    --shadow-sm: 0 1px 2px rgba(44, 32, 23, 0.04), 0 2px 6px rgba(44, 32, 23, 0.05);
    --shadow-md: 0 2px 4px rgba(44, 32, 23, 0.05), 0 10px 22px rgba(44, 32, 23, 0.08);
    --shadow-lg: 0 4px 10px rgba(44, 32, 23, 0.07), 0 18px 40px rgba(44, 32, 23, 0.11);
    --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
}

* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    margin: 0;
    color: var(--ink);
    background: var(--paper);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.6;
    text-rendering: optimizeLegibility;
}

body.menu-open {
    overflow: hidden;
}

img {
    display: block;
    max-width: 100%;
}

a {
    color: inherit;
}

button,
input,
textarea {
    font: inherit;
}

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

.skip-link {
    position: fixed;
    top: 12px;
    left: 12px;
    z-index: 100;
    padding: 10px 14px;
    color: var(--ink);
    background: var(--orange-bright);
    font-weight: 700;
    text-decoration: none;
    transform: translateY(-160%);
}

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

.sr-only {
    width: 1px;
    height: 1px;
    position: absolute;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    clip-path: inset(50%);
}

.container {
    width: min(calc(100% - 48px), var(--page));
    margin: 0 auto;
}

/* ---------- header, nav, mobile nav ---------- */
.site-header {
    position: sticky;
    top: 0;
    z-index: 30;
    background: rgba(251, 248, 243, 0.96);
    border-bottom: 1px solid var(--rule);
    backdrop-filter: blur(12px);
    transition: box-shadow 260ms var(--ease-out), border-color 260ms var(--ease-out);
}

/* The header only earns a shadow once it is actually overlapping content. */
.site-header.is-stuck {
    border-bottom-color: transparent;
    box-shadow: var(--shadow-md);
}

.header-inner {
    min-height: 76px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 32px;
}

.site-logo {
    display: inline-flex;
    align-items: center;
}

.site-logo img {
    width: 206px;
    height: auto;
}

.desktop-nav {
    display: flex;
    align-items: center;
    gap: 30px;
}

.desktop-nav a,
.mobile-nav a {
    color: var(--brown);
    font-size: 0.88rem;
    font-weight: 600;
    text-decoration: none;
    transition: color 180ms ease;
}

.desktop-nav a:hover,
.mobile-nav a:hover {
    color: var(--orange);
}

/* Nav underline grows from the left rather than fading in. */
.desktop-nav a:not(.nav-action) {
    position: relative;
    padding-bottom: 4px;
}

.desktop-nav a:not(.nav-action)::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 2px;
    background: var(--orange);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 220ms var(--ease-out);
}

.desktop-nav a:not(.nav-action):hover::after,
.desktop-nav a:not(.nav-action):focus-visible::after {
    transform: scaleX(1);
}

/* The primary action is a compact button, not an underlined link: a permanent
   underline collides with the sibling links' hover underline (it reads as a
   stuck hover or a current-page marker). Hover keeps the label ink — the
   nav-wide hover rule above would turn it orange-on-orange — and draws the
   same grow-from-left underline as the siblings, in brown to survive the
   orange fill. */
.desktop-nav .nav-action {
    position: relative;
    padding: 9px 18px;
    color: var(--ink);
    background: var(--orange-bright);
    border: 1px solid var(--orange-bright);
    border-radius: var(--radius-control);
    transition: background 180ms ease, border-color 180ms ease;
}

.desktop-nav .nav-action:hover,
.desktop-nav .nav-action:focus-visible {
    color: var(--ink);
    background: var(--orange);
    border-color: var(--orange);
}

.desktop-nav .nav-action::after {
    content: "";
    position: absolute;
    left: 18px;
    right: 18px;
    bottom: 6px;
    height: 2px;
    background: var(--brown);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 220ms var(--ease-out);
}

.desktop-nav .nav-action:hover::after,
.desktop-nav .nav-action:focus-visible::after {
    transform: scaleX(1);
}

.menu-button {
    width: 44px;
    height: 44px;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 0;
    color: var(--ink);
    background: transparent;
    border: 1px solid var(--brown-light);
    border-radius: var(--radius-control);
    cursor: pointer;
}

.menu-icon,
.menu-icon::before,
.menu-icon::after {
    width: 20px;
    height: 2px;
    display: block;
    position: relative;
    background: currentColor;
}

.menu-icon::before,
.menu-icon::after {
    content: "";
    position: absolute;
    left: 0;
}

.menu-icon::before {
    top: -6px;
}

.menu-icon::after {
    top: 6px;
}

.menu-button[aria-expanded="true"] .menu-icon {
    background: transparent;
}

.menu-button[aria-expanded="true"] .menu-icon::before {
    top: 0;
    transform: rotate(45deg);
}

.menu-button[aria-expanded="true"] .menu-icon::after {
    top: 0;
    transform: rotate(-45deg);
}

.mobile-nav[hidden] {
    display: none;
}

.mobile-nav {
    position: fixed;
    inset: 77px 0 0;
    z-index: 29;
    padding: 30px 0;
    background: var(--paper);
}

.mobile-nav .container {
    display: grid;
}

.mobile-nav a {
    padding: 17px 0;
    border-bottom: 1px solid var(--rule);
    font-size: 1.12rem;
}

/* ---------- footer ---------- */
/* The link wraps the artwork only, so it takes no underline; the global
   :focus-visible outline still rings it for keyboard users. */
.ssfw-mark {
    display: inline-flex;
    text-decoration: none;
}

.site-footer {
    color: var(--sand);
    background: var(--ink);
    border-top: 1px solid var(--brown-mid);
}

.footer-inner {
    min-height: 86px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 28px;
    font-size: 0.78rem;
}

.footer-inner p {
    margin: 0;
}

.footer-inner a {
    text-decoration-color: var(--orange);
    text-underline-offset: 4px;
}

/* The wrapper dissolves here so its children become footer-row items in
   their own right and the row spaces evenly. The element is kept rather than
   deleted because the ≤760px column below re-forms it — stacked, the state
   needs to travel with the sentence, not strand on a row of its own. */
.footer-wisconsin {
    display: contents;
}

/* Wisconsin silhouette closing the footer line — the same solved path as the
   contact block, filled rather than outlined (picked from a side-by-side).

   The two instances differ deliberately: the contact block is OUTLINED at 300px,
   this is FILLED at 48px. A stroke needs size to read; a fill does not. They
   share one path, so re-simplifying the geometry moves both at once. */
.footer-state {
    flex: none;
    width: auto;
    height: 48px;
    fill: var(--brown-light);
}

/* ---------- responsive ---------- */
@media (max-width: 760px) {
    .container {
        width: min(calc(100% - 36px), var(--page));
    }

    .desktop-nav {
        display: none;
    }

    .menu-button {
        display: inline-flex;
    }

    .site-logo img {
        width: 184px;
    }

    .footer-inner {
        padding: 24px 0;
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }

    /* Re-form the group the desktop rule dissolved. In a column, five separate
       items would put the lockup and the state on rows of their own; as one
       flex item they stay on the sentence's line. */
    .footer-wisconsin {
        display: flex;
        align-items: center;
        gap: 14px;
    }
}

@media (max-width: 420px) {
    .container {
        width: min(calc(100% - 28px), var(--page));
    }

    .site-logo img {
        width: 166px;
    }
}

/* Reduced motion — the chrome half. index.html keeps its own block for page motion
   (.tech-track, .reveal, .product-card, .button); these three are chrome and apply
   to every page. The .desktop-nav rule matters on the 404 too, now that it has a nav. */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    .desktop-nav a:not(.nav-action):hover::after,
    .desktop-nav a:not(.nav-action):focus-visible::after {
        transform: scaleX(1);
    }

    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}
