/*
 * NAIIAN marketing site.
 *
 * One stylesheet, no build step, no preprocessor. Tokens first, then elements,
 * then the few components this site has. Keep it in that order so a change has
 * an obvious home.
 *
 * CONVERGED PALETTE. This site now carries the product application's own token
 * values, not a parallel set. Every colour here is oklch(L 0 0) — chroma exactly
 * zero — because NAIIAN sells the same platform to opposing clients and a hue
 * that could read as party alignment is a product risk. The product expresses
 * that as achromatic restraint; so does this. The two semantic hues the product
 * permits (--destructive, --success) report state inside the app and have no
 * job on a marketing page, so they are not declared here.
 *
 * Light-first with a dark media block, matching the product's light-first theme.
 * A visitor who signs in no longer crosses from black to white at the door.
 *
 * With colour unavailable as a hierarchy tool, hierarchy is carried by weight,
 * by muting, by family (Geist Mono marks anything machine-issued), and by one
 * signature: the uppercase micro-label tracked to 0.14em.
 */

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

/*
 * Self-hosted, not fetched. No third-party host may appear in any reference on
 * this site and CI fails on one, so the product's typeface is served from our
 * own origin as two variable woff2 files (~138 KB combined). SIL OFL 1.1;
 * the license ships beside them in assets/fonts/.
 */
@font-face {
  font-family: "Geist";
  src: url("/assets/fonts/Geist-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

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

:root {
  color-scheme: light dark;

  /* Values are the product application's, verbatim from app/globals.css. */
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  --card: oklch(1 0 0);
  --primary: oklch(0.205 0 0);
  --primary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.54 0 0);
  --border: oklch(0.922 0 0);
  --ring: oklch(0.5 0 0);

  /* One seed rescales every corner in the system, exactly as the product does. */
  --radius: 0.625rem;
  --radius-md: calc(var(--radius) * 0.8);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) * 1.4);

  --tracking-label: 0.14em;

  --measure: 58ch;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --step: clamp(3.5rem, 9vw, 7rem);

  --font-body: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
    Consolas, "Liberation Mono", monospace;

  /* The product's chrome duration. It has three; a marketing page needs one. */
  --duration: 200ms;
}

/*
 * The product's .dark block, verbatim. Reached here by media query rather than
 * by class because this site ships no JavaScript and therefore has no toggle.
 */
@media (prefers-color-scheme: dark) {
  :root {
    --background: oklch(0.145 0 0);
    --foreground: oklch(0.985 0 0);
    --card: oklch(0.205 0 0);
    --primary: oklch(0.922 0 0);
    --primary-foreground: oklch(0.205 0 0);
    --muted: oklch(0.269 0 0);
    --muted-foreground: oklch(0.708 0 0);
    --border: oklch(1 0 0 / 10%);
    --ring: oklch(0.556 0 0);
  }
}

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

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

/* The column keeps the footer at the bottom on a short page. Without it the 404
   left ~110px of bare ground below the footer on desktop and ~230px on phone. */
body {
  margin: 0;
  padding: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

main {
  flex: 1;
}

/*
 * Weight tops out at 600. The product ships font-bold exactly twice and
 * font-light never; escalating emphasis with weight and colour before size is
 * the rule this site now shares.
 */
h1,
h2,
h3 {
  text-wrap: balance;
  line-height: 1.1;
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.025em;
}

p {
  text-wrap: pretty;
  margin: 0;
}

/*
 * Achromatic links. With no accent hue available, the underline is not a
 * redundant cue — it is the only cue, so it is never removed. Hover thickens
 * the rule rather than shifting a colour that does not exist.
 */
a {
  color: var(--foreground);
  text-decoration-color: var(--muted-foreground);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: text-decoration-color var(--duration) ease,
    color var(--duration) ease;
}

a:hover {
  text-decoration-color: var(--foreground);
  text-decoration-thickness: 2px;
}

::selection {
  background: var(--foreground);
  color: var(--background);
}

/*
 * :focus-visible rather than :focus, so a mouse click does not draw a ring.
 * The halo sits flush against the element: the product has zero ring-offset
 * anywhere by design, and this site now matches.
 *
 * The outline is SOLID, and that is load-bearing rather than a style choice.
 * It was previously drawn at 50% alpha, which measured 1.44:1 against the page
 * in light and 2.39:1 against a card in dark — below the 3:1 floor WCAG 1.4.11
 * puts under the visual information that identifies a control. No colour at
 * half alpha over white can reach 3:1, so the alpha had to go.
 *
 * The product solves the same problem differently: it keeps a decorative
 * half-alpha ring and swaps the control's *border* to a solid --ring, which is
 * what carries its 6.00:1. This site styles no bordered control, so it has no
 * border to swap and the outline itself must carry the requirement. That
 * divergence in mechanism is recorded in website-application-design-system;
 * the token does not diverge, --ring being the product's value in both themes.
 *
 * Solid now measures 6.00:1 in light and 4.18:1 in dark against the page.
 * `make website-application-check` recomputes it; do not reintroduce an alpha.
 */
:where(a, button, [tabindex]):focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 0;
  border-radius: var(--radius-md);
}

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

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

.shell {
  width: 100%;
  max-width: 78rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
  /* Full-bleed sections still need to clear a notch in landscape. */
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  padding: 0.75rem 1rem;
  background: var(--card);
  color: var(--foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.skip-link:focus {
  left: 1rem;
  top: 1rem;
}

/* Buttons ----------------------------------------------------------------- */

/*
 * The product's two shipped variants. Both carry an always-present 1px
 * transparent border so outline and solid never shift by a pixel, and
 * bg-clip: padding-box so a fill cannot bleed under it.
 *
 * 44px minimum, not the product's 32px: this is a pointer-and-thumb marketing
 * page, not a dense operator instrument, and WCAG 2.5.5 governs here.
 */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding-inline: 1.25rem;
  border: 1px solid transparent;
  background-clip: padding-box;
  border-radius: var(--radius-lg);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  transition: background-color var(--duration) ease,
    border-color var(--duration) ease, color var(--duration) ease;
}

/* The one positional gesture the product permits, carried over verbatim. */
.button:active {
  transform: translateY(1px);
}

.button--primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-foreground);
  padding-inline: 1.75rem;
  font-size: 1rem;
  font-weight: 600;
}

.button--primary:hover {
  background: color-mix(in oklch, var(--primary) 80%, transparent);
  border-color: color-mix(in oklch, var(--primary) 80%, transparent);
  color: var(--primary-foreground);
}

.button--outline {
  background: var(--background);
  border-color: var(--border);
  color: var(--foreground);
}

.button--outline:hover {
  background: var(--muted);
  color: var(--foreground);
}

/* Masthead ---------------------------------------------------------------- */

.masthead {
  padding-block: 1rem;
  border-bottom: 1px solid var(--border);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/*
 * inline-flex + min-height so the only header control clears a 44px touch
 * target. The negative inline margin keeps the optical left edge on the shell
 * gutter despite the added padding.
 * The markup already carries NAIIAN in caps — the brand is uppercase, so the
 * accessible name should be too rather than being faked by a transform. The
 * text-transform only guards against a lowercase string slipping back in.
 */
.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 0.5rem;
  margin-inline-start: -0.5rem;
  border-radius: var(--radius-md);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--foreground);
  text-decoration: none;
}

/*
 * The masthead is the wordmark alone. The stacked NAI/IAN lockup used to sit
 * beside it and the pair read as the name printed twice, which is what a glyph
 * built out of the same six letters will always do next to the word itself. The
 * lockup keeps its jobs elsewhere — it is the share card — and the tab icon is
 * the product's single-N tile.
 */

/*
 * The brand is NAIIAN with the final N inverted — its diagonal mirrored. The
 * markup still spells the plain word, so the accessible name, the page title,
 * and a copy-paste all read NAIIAN; only the rendered glyph is flipped.
 *
 * letter-spacing is painted after a glyph, so an inline-block carrying the
 * inherited 0.14em would mirror that trailing space onto the left and open a
 * visible gap before the N. Zeroed here: the preceding A's own spacing already
 * does the separating, and the trailing space is invisible at the end of a line.
 */
.wordmark__n {
  display: inline-block;
  transform: scaleX(-1);
  letter-spacing: 0;
  /*
   * An optical kern, not a metric one. The advance widths are already even — the
   * boxes measure to within 0.02px of every other pair — but a mirrored N carries
   * its diagonal away from the top-left, leaving a void exactly where the
   * preceding A's pointed apex leaves another. The two voids stack and the eye
   * reads a gap that the metrics do not contain. Measured against the unmirrored
   * wordmark at 72px: -0.07em restores the rhythm, -0.10em starts to crowd.
   */
  margin-inline-start: -0.07em;
}

.wordmark:hover {
  color: var(--muted-foreground);
}

/*
 * A state, not a control. The platform is not publicly reachable, so the
 * masthead says so rather than offering a sign-in that would lead nowhere — a
 * control that fails is worse than no control. It takes the framing-label
 * treatment precisely because that register reads as non-interactive: a status
 * marker must never fake an affordance, so this is deliberately not a button,
 * not a link, and not focusable.
 */
.masthead__status {
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1rem;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted-foreground);
  text-align: right;
  text-wrap: balance;
}

/* Hero -------------------------------------------------------------------- */

.hero {
  padding-block: var(--step);
  border-bottom: 1px solid var(--border);
}

/*
 * Sentence case, not uppercase. The product permits exactly one uppercase
 * treatment — the 0.14em eyebrow — and a 4.75rem shouted headline is both off
 * that system and measurably harder to read.
 */
.hero__title {
  font-size: clamp(2.25rem, 1.4rem + 4.2vw, 4.75rem);
  max-width: 20ch;
  letter-spacing: -0.03em;
}

/*
 * Two columns from 56rem: the prose keeps its 58ch measure on the left and the
 * decision moves into a rail on the right, separated by the site's structural
 * hairline. This is the product's own page-heading composition — title, then
 * content with a shrink-0 action cluster opposite — and it is what lifts the
 * call to action above the fold on a 900px-tall desktop viewport.
 */
.hero__body {
  margin-top: 2.5rem;
  display: grid;
  gap: 2.5rem;
}

@media (min-width: 56rem) {
  .hero__body {
    grid-template-columns: minmax(0, 1fr) minmax(17rem, 20rem);
    gap: clamp(2.5rem, 5vw, 4.5rem);
    /* Stretch, not start: the rail's hairline is structural, so it runs the
       full height of the row. Aligned to start it stopped under the button and
       read as a stray rule rather than as the column's edge. */
    align-items: stretch;
  }
}

.hero__lede {
  max-width: var(--measure);
  color: var(--muted-foreground);
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.3125rem);
}

.hero__lede > p + p {
  margin-top: 1.25rem;
}

.hero__decision {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
}

@media (min-width: 56rem) {
  .hero__decision {
    border-left: 1px solid var(--border);
    padding-left: clamp(2rem, 3vw, 3rem);
  }
}

/* No max-width: at 24ch the antithesis broke between "isn't" and "guessed" at
   every viewport, splitting the one line the sentence is built on. */
.hero__closer {
  font-size: clamp(1.125rem, 1rem + 0.4vw, 1.375rem);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.025em;
  color: var(--foreground);
  text-wrap: balance;
}

.hero__cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
}

.cta__aside {
  color: var(--muted-foreground);
  font-size: 0.875rem;
  line-height: 1.5;
}

/* Section headings -------------------------------------------------------- */

/*
 * The product's one typographic signature, at its exact value: 0.75rem,
 * semibold, uppercase, 0.14em, muted. Sans, not mono — the monospace form of
 * this label is reserved for ordinals, which is what .directive__index is.
 */
.eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted-foreground);
  margin: 0 0 2rem;
  line-height: 1rem;
}

/* Directives -------------------------------------------------------------- */

.directives {
  padding-block: var(--step);
}

.directives__list {
  display: grid;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 56rem) {
  .directives__list {
    grid-template-columns: repeat(2, 1fr);
  }
}

/*
 * The product's canonical surface: rounded-xl, a themed hairline, the card
 * ground, and nothing heavier than its smallest shadow. In light mode --card
 * and --background are the same value, so the hairline is doing all of the
 * separation work; in dark mode the tonal step engages as well.
 */
.directive {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: 0 1px 2px 0 oklch(0 0 0 / 5%);
  padding: clamp(1.5rem, 2.5vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

@media (prefers-color-scheme: dark) {
  .directive {
    box-shadow: none;
  }
}

/* Mono marks anything machine-issued, and an ordinal is exactly that. */
.directive__index {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}

.directive__title {
  font-size: clamp(1.125rem, 1.05rem + 0.35vw, 1.375rem);
  letter-spacing: -0.02em;
}

/*
 * The lead sentence carries full ink and a weight step; the rest is muted.
 * The copy is unchanged — this is hierarchy inside a paragraph that previously
 * ran as an undifferentiated 100-word block.
 */
.directive__lead {
  color: var(--foreground);
  font-weight: 500;
  max-width: 56ch;
}

/* `ch` measures the narrow `0` glyph, so a ch value renders ~25% more characters
   than its number suggests: 56ch is roughly a 70-character line. */
.directive__body {
  color: var(--muted-foreground);
  max-width: 56ch;
  font-size: 0.9375rem;
}

/* Prose (privacy notice, 404) --------------------------------------------- */

/* The measure constrains the text, not the container. Setting it on .prose
   itself overrode .shell's max-width and re-centred the column, so body copy
   started at x=399 while the masthead and footer started at x=160 — a visible
   jog in the page's left spine. */
.prose {
  padding-block: var(--step);
}

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

.prose__title {
  font-size: clamp(1.875rem, 1.4rem + 2vw, 3rem);
}

/* Specificity 0,2,0 so it beats `.prose p` (0,1,1). As `.prose__meta` alone it
   lost, and the effective date silently rendered as --muted-foreground. */
.prose .prose__meta {
  margin-top: 1rem;
  color: var(--muted-foreground);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
}

.prose section {
  margin-top: 3rem;
}

.prose h2 {
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
  margin-bottom: 1rem;
}

.prose p,
.prose ul {
  color: var(--muted-foreground);
}

.prose p + p,
.prose p + ul,
.prose ul + p {
  margin-top: 1rem;
}

.prose ul {
  padding-left: 1.25rem;
  margin-block: 0;
}

.prose li + li {
  margin-top: 0.5rem;
}

.prose strong {
  color: var(--foreground);
  font-weight: 600;
}

/* Not found --------------------------------------------------------------- */

.notfound {
  padding-block: clamp(5rem, 14vw, 10rem);
}

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

.notfound__code {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted-foreground);
}

.notfound__title {
  margin-top: 1rem;
  font-size: clamp(1.875rem, 1.4rem + 2vw, 3rem);
}

.notfound__body {
  margin-top: 1.25rem;
  color: var(--muted-foreground);
}

.notfound__actions {
  margin-top: 2rem;
}

/* Footer ------------------------------------------------------------------ */

.colophon {
  border-top: 1px solid var(--border);
  padding-block: 3rem 4rem;
  padding-bottom: max(4rem, env(safe-area-inset-bottom));
  color: var(--muted-foreground);
  font-size: 0.875rem;
}

.colophon__contact {
  margin-bottom: 1.5rem;
  color: var(--foreground);
  font-size: 1rem;
}

.colophon__nav {
  margin-bottom: 1.5rem;
}

/* Standalone navigation links, not prose links: they get a real target. The
   inline links inside the privacy notice stay inline, which WCAG 2.5.5 exempts. */
.colophon__nav a,
.colophon__contact a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* 62ch, not 72ch: `ch` is the width of the `0` glyph, so 72ch rendered ~91
   characters per line. */
.colophon__legal {
  max-width: 62ch;
}

.colophon__legal + .colophon__legal {
  margin-top: 0.75rem;
}

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

/*
 * The privacy notice is the page a procurement reader prints and files. A
 * light-first palette already prints correctly, so this block no longer has to
 * rescue a dark ground — it only pins pure values and drops what has no meaning
 * on paper.
 */
@media print {
  :root {
    --background: #ffffff;
    --foreground: #000000;
    --card: #ffffff;
    --muted: #f2f2f2;
    --muted-foreground: #3a3f45;
    --border: #999999;
  }

  body {
    background: #ffffff;
    color: #000000;
  }

  .directive {
    box-shadow: none;
  }

  /* An off-screen jump link has no meaning on paper. */
  .skip-link {
    display: none;
  }
}

/* Motion ------------------------------------------------------------------ */

/*
 * The only motion on this site is a state transition on a control the visitor
 * is already touching. There is no scroll-triggered entrance and no hover-lift:
 * the product forbids both, and a page about operating under a countdown should
 * not perform for the reader.
 */
@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;
  }
}
