/* ===========================================================================
   Innovators Creative — innovators.co.nz
   ===========================================================================

   Monochrome by brief: black, white, and greys. No colour anywhere, including
   the error state, which earns its emphasis from weight and a rule instead.

   THE COMPOSITION is alternating blocks — white header, black hero, white
   services, grey contact, black footer. On a one-pager with no photography
   that inversion is what creates rhythm and tells a scrolling visitor they
   have moved from one idea to the next.

   THE TYPE is a deliberate pairing, not a single voice:

     --font-display  Fredericka the Great. A distressed, hand-lettered inline
                     face. It IS the brand — there is no logo, so the wordmark
                     is the mark. Used ONLY at display sizes: the wordmark, the
                     hero headline, and section headings. It is genuinely hard
                     to read below about 1.5rem and must never carry body copy,
                     labels, buttons or form text. That restraint is what keeps
                     it feeling like a mark rather than a novelty.

     --font-body     A clean modern sans. Everything else. The tension between
                     the two — vintage hand-lettering against a stark modern
                     grid — is the whole idea.

   SELF-HOSTED FONT. The CSP forbids external origins, so there is no
   fonts.googleapis.com link and there must never be one: that request would
   send every visitor's IP to Google on page load, which is exactly the
   third-party disclosure privacy.php says this site does not make. The face is
   SIL Open Font Licensed and served from /assets/fonts. If the file is absent
   the stack below falls back and the site still reads correctly — degraded,
   not broken.

   Mobile-first throughout: base styles are the narrow viewport, and every
   media query is min-width. Bump ASSET_VERSION in includes/site.php after
   editing this file.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   Font
   --------------------------------------------------------------------------- */

/* Two formats listed, and the ORDER IS THE PRIORITY: the browser takes the
   first it supports and never requests the other. So dropping in either file
   works, and if both are present WOFF2 is the one actually downloaded.
   TTF alone is fine and supported everywhere — it is simply 2–3× the bytes,
   because WOFF2 carries Brotli compression and TTF is uncompressed.

   Only the file you actually have needs to exist. A src entry pointing at a
   missing file is skipped, not fatal — the browser moves down the list and
   then to the fallback stack. */
@font-face {
    font-family: 'Fredericka the Great';
    /* Relative to THIS stylesheet, not to the domain root. A CSS file cannot
       call url() in PHP, so an absolute '/assets/...' path would break the
       moment the site is served from a subfolder — which is exactly how a
       preview copy gets hosted. '../fonts/' resolves correctly either way. */
    src: url('../fonts/fredericka-the-great.woff2') format('woff2'),
         url('../fonts/fredericka-the-great.ttf')   format('truetype');
    font-weight: 400;
    font-style: normal;
    /* swap: show the fallback immediately rather than holding the headline
       blank while the file loads. A brand mark that appears late is better
       than a page that appears empty. */
    font-display: swap;
}

/* ---------------------------------------------------------------------------
   Tokens
   --------------------------------------------------------------------------- */

:root {
    --black:     #000000;
    --ink:       #111111;
    --ink-soft:  #6a6a6a;
    --rule:      #e2e2e2;
    --rule-dark: #333333;
    --paper:     #ffffff;
    --paper-alt: #f4f4f4;

    /* On black sections. */
    --on-black:      #ffffff;
    --on-black-soft: #a8a8a8;

    --font-display: 'Fredericka the Great', 'Papyrus', 'Brush Script MT', cursive;
    --font-body:    system-ui, -apple-system, 'Segoe UI', Roboto,
                    'Helvetica Neue', Arial, sans-serif;

    --s1: 0.25rem;
    --s2: 0.5rem;
    --s3: 1rem;
    --s4: 1.5rem;
    --s5: 2rem;
    --s6: 3rem;
    --s7: 4.5rem;
    --s8: 7rem;

    --measure: 34rem;
    --gutter:  1.25rem;
    --max:     70rem;
}

/* ---------------------------------------------------------------------------
   Reset and base
   --------------------------------------------------------------------------- */

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

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

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 { margin: 0 0 var(--s3); line-height: 1.15; font-weight: 600; }

p, ul, ol, dl { margin: 0 0 var(--s3); }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }

/* Visible focus everywhere. currentColor so it stays visible on both the white
   and the black sections without a second rule. */
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ---------------------------------------------------------------------------
   Shared pieces
   --------------------------------------------------------------------------- */

.measure { max-width: var(--measure); }

/* The header is sticky, so an anchored section would otherwise scroll to sit
   underneath it. Roughly header height plus a little air. Applied to the
   sections themselves rather than :target so it works for the in-page nav,
   the hero's own button, and a link arriving from another page alike. */
#services, #contact { scroll-margin-top: 5.5rem; }

.eyebrow {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin: 0 0 var(--s3);
}

.section-head { margin-bottom: var(--s6); }

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: var(--black);
    color: var(--on-black);
    padding: var(--s2) var(--s3);
}
.skip-link:focus { left: 0; }

/* Buttons. Ghost by default, solid for the primary action. Square corners —
   the radius is 0 everywhere on purpose, to sit with the stark grid. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: var(--s2) var(--s5);
    border: 1px solid currentColor;
    background: transparent;
    color: inherit;
    font-family: var(--font-body);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.btn--solid { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn--solid:hover { background: var(--paper); color: var(--ink); }
.btn:hover { background: var(--ink); color: var(--paper); }

/* On a black section the ghost/solid roles invert. */
.hero .btn:hover { background: var(--on-black); color: var(--black); }
.hero .btn--solid { background: var(--on-black); border-color: var(--on-black); color: var(--black); }
.hero .btn--solid:hover { background: transparent; color: var(--on-black); }

/* ---------------------------------------------------------------------------
   Header
   --------------------------------------------------------------------------- */

.site-header {
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    position: sticky;
    top: 0;
    z-index: 50;
}

.site-header__inner {
    max-width: var(--max);
    margin-inline: auto;
    padding: var(--s3) var(--gutter);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
}

.site-header__brand { text-decoration: none; }

/* The wordmark. This is the logo. */
.site-header__wordmark {
    font-family: var(--font-display);
    font-size: 1.25rem;
    line-height: 1.1;
    letter-spacing: 0.01em;
    text-transform: uppercase;
    color: var(--black);
    display: block;
}

.nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
    min-height: 44px;
    padding: var(--s2) var(--s3);
    border: 1px solid var(--ink);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    cursor: pointer;
}

.nav-toggle__bars {
    width: 1rem;
    height: 1px;
    background: currentColor;
    box-shadow: 0 -5px 0 currentColor, 0 5px 0 currentColor;
}

.site-nav { flex-basis: 100%; }

.site-nav__list { list-style: none; margin: 0; padding: 0; }

.site-nav__list a,
.site-nav__aside a {
    display: block;
    min-height: 44px;
    padding: var(--s2) 0;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-decoration: none;
}

.site-nav__list a:hover, .site-nav__aside a:hover { text-decoration: underline; }

.site-nav__aside { margin: 0; padding-bottom: var(--s2); }

/* Collapsed only once nav.js has added .js to <html> and toggles .is-open.
   Without JavaScript neither appears and the nav stays a visible list.
   THE 62rem BREAKPOINT MUST MATCH the matchMedia query in assets/js/nav.js. */
.js .site-nav { display: none; }
.js .site-nav.is-open { display: block; }

@media (min-width: 62rem) {
    .nav-toggle { display: none; }

    .site-nav,
    .js .site-nav,
    .js .site-nav.is-open {
        display: flex;
        align-items: center;
        gap: var(--s6);
        flex-basis: auto;
    }

    .site-nav__list { display: flex; gap: var(--s5); }
    .site-nav__list a, .site-nav__aside a { padding: 0; min-height: 0; display: inline-block; }
    .site-nav__aside { padding: 0; }
}

/* ---------------------------------------------------------------------------
   Hero — the black block
   --------------------------------------------------------------------------- */

.hero {
    background: var(--black);
    color: var(--on-black);
    padding-block: var(--s7);
}

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

.hero__eyebrow {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--on-black-soft);
    margin: 0 0 var(--s5);
}

.hero__title {
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 11vw, 6rem);
    line-height: 1.02;
    letter-spacing: -0.01em;
    font-weight: 400;
    margin: 0 0 var(--s5);
    text-transform: uppercase;
}

/* The one italic in the design, marking the payoff line of the headline. */
.hero__title em { font-style: italic; color: var(--on-black-soft); }

.hero__lede {
    max-width: var(--measure);
    font-size: 1.0625rem;
    color: var(--on-black-soft);
    margin-bottom: var(--s6);
}

.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin: 0; }

@media (min-width: 48rem) {
    .hero { padding-block: var(--s8); }
    .hero__lede { font-size: 1.1875rem; }
}

/* ---------------------------------------------------------------------------
   Services — numbered, hairline-separated
   --------------------------------------------------------------------------- */

.services { padding-block: var(--s7); }

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

.section-head h2 {
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 6vw, 3rem);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -0.005em;
    margin: 0;
}

.services__list { list-style: none; margin: 0; padding: 0; }

.service {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--s4);
    row-gap: var(--s1);
    padding-block: var(--s5);
    border-top: 1px solid var(--rule);
}

.service:last-child { border-bottom: 1px solid var(--rule); }

/* The number is decoration, hidden from screen readers — the ordered list
   already conveys the sequence, and "01 Web" read aloud is noise. */
.service__num {
    grid-row: 1 / span 2;
    margin: 0;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--ink-soft);
    padding-top: 0.35rem;
}

.service__title {
    margin: 0;
    font-family: var(--font-body);
    font-size: 1.375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.service__text { margin: 0; max-width: var(--measure); color: var(--ink-soft); }

@media (min-width: 48rem) {
    .services { padding-block: var(--s8); }

    .service {
        grid-template-columns: 4rem 14rem 1fr;
        column-gap: var(--s5);
        align-items: start;
    }
    .service__num   { grid-row: 1; font-size: 0.875rem; padding-top: 0.5rem; }
    .service__title { font-size: 1.5rem; padding-top: 0.15rem; }
}

/* ---------------------------------------------------------------------------
   Contact — grey block, intro beside form
   --------------------------------------------------------------------------- */

.contact {
    background: var(--paper-alt);
    padding-block: var(--s7);
}

.contact__inner {
    max-width: var(--max);
    margin-inline: auto;
    padding-inline: var(--gutter);
    display: grid;
    gap: var(--s6);
}

.contact__intro h2 {
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 6vw, 3rem);
    font-weight: 400;
    text-transform: uppercase;
    margin: 0 0 var(--s3);
}

.contact__intro p { max-width: var(--measure); color: var(--ink-soft); }

.contact__details { margin: var(--s5) 0 0; }
.contact__details dt {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-top: var(--s3);
}
.contact__details dd { margin: 0; font-size: 1.125rem; }

@media (min-width: 56rem) {
    .contact { padding-block: var(--s8); }
    .contact__inner { grid-template-columns: 1fr 1fr; gap: var(--s8); align-items: start; }
}

/* ---------------------------------------------------------------------------
   Forms
   --------------------------------------------------------------------------- */

/* HONEYPOT — LOAD-BEARING. DO NOT DELETE THIS RULE.
 *
 * spam_trap_fields() in includes/security.php emits a decoy field wrapped in
 * .hp. Bots fill it in; people never see it. If this rule goes missing the
 * field becomes visible, and a visitor who dutifully completes every field is
 * treated as a bot — spam_trap_reason() returns 'honeypot', the page reports
 * success to them, and the enquiry is discarded without ever being sent. The
 * failure is silent on both sides, which is what makes it dangerous.
 *
 * Off-screen rather than display:none, which some bots detect and skip. Must
 * be a class, never an inline style — the CSP forbids those. aria-hidden on
 * the wrapper keeps it out of the accessibility tree, and tabindex="-1" keeps
 * it off the keyboard path, so nobody using a screen reader meets it either. */
.hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

label {
    display: block;
    margin-bottom: var(--s1);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

input[type="text"],
input[type="email"],
input[type="tel"],
textarea {
    width: 100%;
    min-height: 48px;
    padding: var(--s2) var(--s3);
    margin-bottom: var(--s4);
    border: 1px solid var(--rule);
    border-radius: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-body);
    /* 16px minimum, or iOS zooms the page when the field takes focus. */
    font-size: 1rem;
}

input:focus, textarea:focus { border-color: var(--ink); }

textarea { min-height: 10rem; resize: vertical; }

.hint {
    font-size: 0.6875rem;
    font-weight: 400;
    letter-spacing: 0.08em;
    color: var(--ink-soft);
    text-transform: none;
}

.privacy {
    margin: var(--s4) 0 0;
    font-size: 0.8125rem;
    color: var(--ink-soft);
}

/* Notices. Monochrome by brief, so emphasis comes from a heavy rule and
   weight rather than red and green. The role="alert"/"status" attributes in
   the markup are what actually announce these, so nothing is lost. */
.notice {
    padding: var(--s3) var(--s4);
    margin-bottom: var(--s4);
    background: var(--paper);
    border-left: 4px solid var(--ink);
}
.notice--ok    { border-left-color: var(--ink); font-weight: 600; }
.notice--error { border-left-color: var(--black); }
.notice ul { margin: 0; padding-left: var(--s4); }
.notice li + li { margin-top: var(--s1); }

/* ---------------------------------------------------------------------------
   Interior pages — privacy, 404
   --------------------------------------------------------------------------- */

.page-head { padding-block: var(--s6) var(--s4); }

.page-head__inner,
.prose,
.band__inner {
    max-width: var(--max);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.page-head h1 {
    font-family: var(--font-display);
    font-size: clamp(2rem, 8vw, 3.5rem);
    font-weight: 400;
    text-transform: uppercase;
    margin: 0 0 var(--s3);
}

.page-head__lede { max-width: var(--measure); color: var(--ink-soft); margin: 0; }

.prose {
    max-width: calc(var(--measure) + var(--gutter) * 2);
    padding-block: var(--s3) var(--s7);
}
.prose h2 {
    font-size: 1.25rem;
    font-weight: 600;
    margin-top: var(--s6);
    padding-top: var(--s3);
    border-top: 1px solid var(--rule);
}
.prose code {
    font-size: 0.875em;
    background: var(--paper-alt);
    padding: 0.1em 0.35em;
}

.band { padding-block: var(--s5); }
.band--lift { background: var(--paper-alt); }

.detail-list dt { font-weight: 600; margin-top: var(--s3); }
.detail-list dd { margin: 0; }

.quicklinks {
    list-style: none;
    max-width: var(--max);
    margin: 0 auto var(--s6);
    padding-inline: var(--gutter);
    display: grid;
    gap: 0;
}

.quicklinks__link {
    display: block;
    min-height: 48px;
    padding: var(--s3) 0;
    border-top: 1px solid var(--rule);
    text-decoration: none;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-size: 0.9375rem;
}
.quicklinks li:last-child .quicklinks__link { border-bottom: 1px solid var(--rule); }
.quicklinks__link:hover { padding-inline: var(--s3); background: var(--paper-alt); }

/* ---------------------------------------------------------------------------
   Footer — the closing black block
   --------------------------------------------------------------------------- */

.site-footer {
    background: var(--black);
    color: var(--on-black-soft);
    padding-block: var(--s6) var(--s4);
    margin-top: 0;
}

.site-footer a { color: var(--on-black); }

.site-footer__inner {
    max-width: var(--max);
    margin-inline: auto;
    padding-inline: var(--gutter);
    display: grid;
    gap: var(--s5);
}

.site-footer .eyebrow { color: var(--on-black-soft); }

.site-footer__block address { font-style: normal; }
.site-footer__list { list-style: none; margin: 0; padding: 0; }
.site-footer__list a,
.site-footer__social a { display: inline-block; padding-block: var(--s1); }
.site-footer__social a + a { margin-left: var(--s4); }

.site-footer__legal {
    max-width: var(--max);
    margin: var(--s6) auto 0;
    padding: var(--s4) var(--gutter) 0;
    border-top: 1px solid var(--rule-dark);
    font-size: 0.8125rem;
}

@media (min-width: 40rem) {
    .site-footer__inner { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
}
