/* =========================================================================
   invictus.aero — gateway portal
   Design: option 3a (ROUTE · LIGHT · BRAND-FORWARD · AAA)

   Contrast rule used throughout: the raw brand colours (--blue, --amber)
   appear only as fills and graphics (>= 3:1). All *text* uses the deepened
   AAA inks (>= 7:1), except the 42px headline accent, which uses the
   AAA-large-text blue. Maintain this when extending the design.
   ========================================================================= */

/* fonts.css is linked separately from each page rather than @import-ed here,
   so the font faces are discovered in the same round trip as this file. */

/* --- Design tokens ------------------------------------------------------ */

:root {
  /* Brand */
  --blue:            #0B72FF; /* arc, destination node, AMERICAS pill border — graphics only */
  --blue-aaa:        #0853AC; /* buttons, links, .AERO, overlines            (7.4:1 on white) */
  --blue-hover:      #063F83; /* button / link hover                                          */
  --blue-large:      #0961DB; /* "Nevada." headline accent         (AAA large text, 4.5:1)    */
  --blue-on-navy:    #6FAAFF; /* JSON values, AMERICAS pill text        (7.6:1 on navy)       */
  --amber:           #FF9B00; /* rule, origin node, EUROPA pill    (8.6:1 as navy-on-amber)   */
  --amber-outline:   #B36D00; /* origin node stroke        (3:1 graphics contrast on white)   */
  --navy:            #0A1628; /* ink, JSON chip bg, AMERICAS pill bg                          */

  /* Text */
  --muted:           #4B5766; /* secondary text on white                        (7.3:1)       */
  --muted-warm:      #5C564E; /* footer, mono labels, fine print                (7.5:1)       */
  --muted-navy:      #A9B8CA; /* JSON punctuation on the navy chip                            */
  --ink-warm:        #2D2A26; /* mono address blocks                                          */

  /* Surfaces */
  --white:           #FFFFFF;
  --hairline:        #D4DCE6; /* card / pill / toggle borders                                 */
  --hairline-light:  #E7ECF2; /* header + footer separators                                   */
  --callout:         #F4F6F9; /* Impressum notice box                                         */
  --grid-line:       rgba(10, 22, 40, 0.05);

  /* Type */
  --font-ui:   'Jost', 'Century Gothic', Futura, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Spacing (4px base, 48px blueprint module) */
  --gutter: 48px;
  --grid-module: 48px;

  /* Radii */
  --r-button: 6px;
  --r-card:   12px;
  --r-chip:   8px;
  --r-pill:   999px;

  /* Effects */
  --shadow-card: 0 4px 16px rgba(10, 22, 40, 0.06);

  /* Focus ring — dual-tone.
     The handoff specified a single translucent wash, 3px rgba(8,83,172,0.5).
     It reads well, but as a wash it measures only ~2.4:1 against the white
     page, short of the 3:1 that SC 1.4.11 and 2.4.13 require of the focus
     indicator itself — which the site's published AA claim depends on.

     Two solid rings instead, so one of them always contrasts with whatever
     sits behind it: a 2px white ring hugging the element (7.4:1 against the
     blue buttons) and a 3px AAA-blue ring outside it (7.4:1 against the white
     page). Total indicator thickness is 5px, comfortably over the 2px minimum
     perimeter that 2.4.13 asks for.

     The outline stays in the stack, transparent. It is invisible normally, but
     Windows High Contrast / forced-colors mode discards box-shadow and repaints
     outlines in a system colour — so this is what keeps the ring visible there. */
  --focus-ring:   3px solid transparent;
  --focus-offset: 2px;
  --focus-shadow: 0 0 0 2px #FFFFFF, 0 0 0 5px #0853AC;
}

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

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

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

body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 16px;
  color: var(--navy);
  background: var(--white);
}

h1, h2, h3, p, figure { margin: 0; }

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

a { color: var(--blue-aaa); text-decoration: none; }
a:hover { color: var(--blue-hover); }

/* Prose links keep an underline so they are not distinguished by colour
   alone (WCAG 1.4.1 Use of Color). */
.prose a { text-decoration: underline; text-underline-offset: 2px; }

/* --- Focus -------------------------------------------------------------- */

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  box-shadow: var(--focus-shadow);
}

@supports not selector(:focus-visible) {
  :focus {
    outline: var(--focus-ring);
    outline-offset: var(--focus-offset);
    box-shadow: var(--focus-shadow);
  }
}

.skip-link {
  position: absolute;
  left: 8px;
  top: 8px;
  z-index: 10;
  padding: 10px 18px;
  border-radius: var(--r-button);
  background: var(--blue-aaa);
  color: var(--white);
  font-size: 15px;
  font-weight: 500;
  transform: translateY(-200%);
}

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

/* =========================================================================
   Language switching

   Both languages live in one document, each wrapped in an element carrying
   its own `lang` attribute, so screen readers announce every string with the
   right pronunciation regardless of which one is on screen.

   Two mechanisms, and only ever *hiding* — never re-showing — so each
   element keeps whatever `display` it was authored with:

   1. No JavaScript: the DE / EN toggle are real links to `#de` / `#en`, and
      `:target` decides which language is hidden. German is the default.
   2. With JavaScript: `boot.js` sets `.js` and `data-lang` on <html> before
      first paint, takes over the toggle, keeps <html lang> in sync and
      remembers the choice.
   ========================================================================= */

html:not(.js) #en:not(:target) ~ .page [data-l='en'] { display: none; }
html:not(.js) #en:target       ~ .page [data-l='de'] { display: none; }

html.js[data-lang='de'] [data-l='en'] { display: none; }
html.js[data-lang='en'] [data-l='de'] { display: none; }

.lang-anchor {
  display: block;
  height: 0;
  overflow: hidden;
}

/* --- Page shell ---------------------------------------------------------- */

.page {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
}

.page--landing {
  background-color: var(--white);
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: var(--grid-module) var(--grid-module);
}

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

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Safety net. "INVICTUS.AERO" is a single unbreakable token, so if the row
     ever runs out of room the wordmark overflows its own box and paints over
     whatever is beside it rather than wrapping or forcing a scrollbar. With
     wrap allowed, the toggle drops to its own line instead of colliding. */
  flex-wrap: wrap;
  gap: 24px;
  padding: 28px var(--gutter);
}

.site-header--doc {
  padding: 24px var(--gutter);
  border-bottom: 1px solid var(--hairline-light);
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--navy);
}

.brand:hover { color: var(--blue-aaa); }

.site-header--doc .brand { gap: 14px; }

.brand-mark { height: 42px; width: auto; }
.site-header--doc .brand-mark { height: 48px; }

.brand-word {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.12em;
}

.brand-word b {
  color: var(--blue-aaa);
  font-weight: inherit;
}

/* --- Language toggle ----------------------------------------------------- */

.lang-toggle {
  display: flex;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
}

.lang-toggle a {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 32px;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
}

.lang-toggle a:hover { color: var(--blue-aaa); }

/* The toggle pill is deliberately compact (32px tall), which is smaller than
   the 44px target the accessibility statement commits to. Extend the hit area
   vertically without touching the visual: the two links sit side by side, so
   growing them upward and downward cannot make them overlap each other. */
.lang-toggle a::after {
  content: '';
  position: absolute;
  inset: -7px 0;
}

/* Active state — with JS via aria-current, without JS via :target. */
.lang-toggle a[aria-current='true'],
html:not(.js) #en:not(:target) ~ .page .lang-toggle a[href='#de'],
html:not(.js) #en:target       ~ .page .lang-toggle a[href='#en'] {
  background: var(--blue-aaa);
  color: var(--white);
  font-weight: 500;
}

/* --- Coordinate labels (decorative) -------------------------------------- */

.coord {
  position: absolute;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--muted-warm);
}

.coord--origin { top: 88px; left: 24px; }
.coord--dest   { bottom: 88px; right: 24px; }

/* --- Landing main -------------------------------------------------------- */

.landing-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px var(--gutter) 48px;
}

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: 760px;
  text-align: center;
}

.overline {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.34em;
  color: var(--blue-aaa);
}

.hero h1 {
  font-size: clamp(30px, 5vw, 42px);
  font-weight: 500;
  line-height: 1.15;
  text-wrap: balance;
}

.hero h1 .accent { color: var(--blue-large); }

.rule {
  width: 64px;
  height: 2px;
  background: var(--amber);
}

/* Scoped to a class, not `.hero p` — the overline is a <p> in the same block
   and a descendant selector would outrank `.overline` on size and colour. */
.subline {
  font-size: clamp(14.5px, 1.4vw, 16px);
  line-height: 1.6;
  color: var(--muted);
  text-wrap: balance;
}

/* --- Flight arc ---------------------------------------------------------- */

.arc {
  width: min(960px, 100%);
  height: auto;
  overflow: visible;
}

/* --- Company cards ------------------------------------------------------- */

.cards {
  display: flex;
  justify-content: space-between;
  gap: 32px;
  width: min(1024px, 100%);
  margin-top: -8px;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 440px;
  max-width: 100%;
  padding: 32px 36px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--white);
  box-shadow: var(--shadow-card);
}

.card--americas {
  align-items: flex-end;
  text-align: right;
}

.pill {
  align-self: flex-start;
  padding: 5px 14px;
  border-radius: var(--r-pill);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
}

.card--americas .pill { align-self: flex-end; }

.pill--europe {
  background: var(--amber);
  color: var(--navy);
}

.pill--americas {
  border: 1px solid var(--blue);
  background: var(--navy);
  color: var(--blue-on-navy);
}

/* The lockup *is* the card heading: one accessible name, no duplicate
   "Invictus Flugtechnik GmbH heading / Invictus Flugtechnik GmbH image". */
.card-title {
  align-self: flex-start;
  font-size: 0;
  line-height: 0;
}

.card--americas .card-title { align-self: flex-end; }

.card-logo {
  height: 34px;
  width: auto;
  max-width: 100%;
}

/* The AeroTech lockup is inlined (its wordmark is live text, not outlines),
   so it needs its intrinsic ratio declared for `width: auto` to resolve. */
.card-logo--iat { aspect-ratio: 1420 / 200; }

.card-logo--iat text {
  font-family: var(--font-ui);
  letter-spacing: 10px;
}

.card p {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--muted);
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  min-height: 44px;
  padding: 10px 22px;
  border-radius: var(--r-button);
  background: var(--blue-aaa);
  color: var(--white);
  font-size: 15px;
  font-weight: 500;
}

.card--americas .cta { align-self: flex-end; }

.cta:hover,
.cta:focus { background: var(--blue-hover); color: var(--white); }

.cta:active { background: #05336B; } /* darkens further; never scales */

/* --- JSON telemetry chip ------------------------------------------------- */

.telemetry {
  max-width: 100%;
  margin-top: 28px;
  overflow-x: auto;
}

.telemetry code {
  display: inline-block;
  padding: 12px 22px;
  border-radius: var(--r-chip);
  background: var(--navy);
  font-family: var(--font-mono);
  font-size: 13px;
  white-space: nowrap;
  color: var(--muted-navy);
}

.telemetry .k { color: var(--amber); }
.telemetry .v { color: var(--blue-on-navy); }

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

.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 20px var(--gutter);
  border-top: 1px solid var(--hairline-light);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted-warm);
}

.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.site-footer a { color: var(--muted-warm); }
.site-footer a:hover { color: var(--blue-aaa); }

.site-footer a[aria-current='page'] {
  color: var(--navy);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- Document pages ------------------------------------------------------ */

.doc {
  flex: 1;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: 64px 32px 96px;
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-bottom: 32px;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
}

.doc-head {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 48px;
}

.doc-head .overline {
  font-size: 12px;
  color: var(--muted-warm);
}

.doc-head h1 {
  font-size: clamp(28px, 4.5vw, 36px);
  font-weight: 500;
  line-height: 1.2;
}

.doc-note {
  font-size: 14px;
  color: var(--muted-warm);
}

.prose {
  display: flex;
  flex-direction: column;
  gap: 32px;
  font-size: 15.5px;
  line-height: 1.65;
}

.prose section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.prose h2 {
  font-size: 19px;
  font-weight: 500;
  line-height: 1.35;
}

.prose .mono {
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink-warm);
  overflow-wrap: anywhere;
}

.callout {
  padding: 24px 28px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-chip);
  background: var(--callout);
}

.stand {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--muted-warm);
}

/* --- 404 ----------------------------------------------------------------- */

.notfound {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 64px 32px 96px;
  text-align: center;
}

.notfound .code {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.34em;
  color: var(--blue-aaa);
}

.notfound h1 {
  font-size: clamp(28px, 4.5vw, 36px);
  font-weight: 500;
}

/* Same reasoning as `.subline` above: `.notfound p` would also match the
   `.code` overline and win on source order. */

/* =========================================================================
   Responsive

   The design is a 1280px desktop reference. Below that: cards stack, the
   arc scales and then drops out, the absolute coordinate labels are removed
   and the footer wraps into stacked rows.
   ========================================================================= */

@media (max-width: 1100px) {
  :root { --gutter: 32px; }

  /* The corner flourishes cannot stay absolutely positioned once the page
     narrows — they would sit on top of the hero. Bring them into the flow
     instead of dropping them, keeping the origin below the header and the
     destination above the footer so they still read top-to-bottom in the
     direction of travel.

     `order` moves the destination past <main>. Reordering visual against DOM
     sequence normally risks SC 1.3.2 / 2.4.3, but these are decorative,
     aria-hidden and not focusable, so nothing in the reading or tab order
     moves with them. */
  .coord {
    position: static;
    padding: 0 var(--gutter);
  }

  /* Breathing room on both sides, or it reads as an orphan wedged between
     the header and the route overline. */
  .coord--origin { margin: 4px 0 18px; }

  .coord--dest {
    order: 1;
    margin-bottom: 12px;
    text-align: right;
  }

  .site-footer { order: 2; }
}

@media (max-width: 900px) {
  .cards {
    flex-direction: column;
    align-items: center;
    gap: 24px;
    margin-top: 8px;
  }

  /* Once the pair is stacked, the two cards present identically. The
     mirroring exists only so the desktop pair reads outward from the ends of
     the flight arc; with one card above the other that reference is gone, and
     a mirrored card just looks like a mistake.

     Centred rather than left-aligned, because the hero directly above is
     centred at every width — overline, headline, rule and subline — so this
     keeps one axis down the whole page.

     Selectors are scoped to `.card`, not `.card--americas`: every child that
     needs re-aligning sets its own `align-self`, so the parent's
     `align-items` cannot reach them. Aligning the wrapper alone is what broke
     this before, when the logo was wrapped in an <h2> and the old rule went
     on targeting the inner <img>. */
  .card {
    width: min(440px, 100%);
    align-items: center;
    text-align: center;
  }

  .card .pill,
  .card .card-title,
  .card .cta { align-self: center; }
}

@media (max-width: 720px) {
  :root { --gutter: 20px; }

  .site-header { padding: 20px var(--gutter); }

  .landing-main { padding: 8px var(--gutter) 40px; }

  .card { padding: 24px 24px; }

  .doc { padding: 40px 20px 72px; }

  .doc-head { margin-bottom: 32px; }

  .telemetry code { font-size: 11.5px; padding: 10px 16px; }

  .site-footer {
    flex-direction: column;
    align-items: center;
    gap: 12px;
    text-align: center;
    padding: 24px var(--gutter);
  }

  .site-footer nav {
    justify-content: center;
    gap: 8px 20px;
  }

  .site-footer nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

@media (max-width: 640px) {
  .arc { display: none; }

  .cards { margin-top: 24px; }
}

/* Pretty-print the chip rather than let it scroll sideways. Horizontal
   scrolling inside a decorative element is easy to miss entirely — the
   right-hand keys were simply invisible.

   The threshold is measured, not guessed. The one-line chip is 691px wide at
   13px type and 605px at the 11.5px used below 720px; with the gutters of the
   day that means it stops fitting under 755px and again under 645px. A single
   cut at 780px covers both bands and leaves ~26px spare for font-rendering
   differences between platforms.

   `2ch` is exactly a two-space indent in a monospace face. */
@media (max-width: 780px) {
  .telemetry code {
    white-space: normal;
    text-align: left;
  }

  .telemetry .brace,
  .telemetry .entry { display: block; }

  .telemetry .entry { padding-left: 2ch; }
}

/* The header row needs roughly 430px before the brand and the toggle collide:
   the mark is 2.58:1, so at 42px tall it is already 108px wide, and the
   wordmark adds another 143px that cannot be broken or hyphenated. Below that
   put the toggle on its own line, centred, matching the hero and the stacked
   cards. Doc pages set the mark at 48px, so they run out ~45px sooner — one
   breakpoint at 480px clears both with room to spare. */
@media (max-width: 480px) {
  .site-header {
    flex-direction: column;
    justify-content: center;
    gap: 16px;
  }

  .brand { justify-content: center; }
}

/* =========================================================================
   Scale-up tiers

   The handoff's reference is a 1280px desktop, and everything above that was
   simply centred — which leaves the page looking undersized on a 1920px or
   wider display. Two steps up from the reference.

   Only scale changes. Every colour, ratio and proportion is carried over
   from the 1280px design: the card row grows by the same factor as the cards
   inside it, so the gutter between them stays proportional, and the arc
   grows with the row so its end nodes keep meeting the card corners.

   Type is scaled a little more gently than layout — headlines that track
   layout growth exactly start to feel shouty — so 1.15x of layout is about
   1.14x of type here, and 1.30x / 1.28x at the upper tier.

   Nothing in this section applies at or below 1280px.
   ========================================================================= */

@media (min-width: 1600px) {
  :root { --gutter: 64px; }

  .brand-mark  { height: 48px; }
  .brand-word  { font-size: 18px; }
  .coord       { font-size: 12px; }

  .hero        { max-width: 880px; gap: 18px; }
  .overline    { font-size: 14px; }
  .hero h1     { font-size: clamp(30px, 5vw, 48px); }
  .rule        { width: 74px; }
  .subline     { font-size: 17px; }

  .arc         { width: min(1104px, 100%); }

  .cards       { width: min(1180px, 100%); }
  .card        { width: 506px; padding: 38px 42px; gap: 18px; }
  .card p      { font-size: 16px; }
  .card-logo   { height: 39px; }
  .pill        { font-size: 12px; padding: 6px 16px; }
  .cta         { font-size: 16px; padding: 12px 26px; }

  .telemetry code { font-size: 14px; padding: 14px 26px; }

  .site-footer { font-size: 13px; }

  .doc         { max-width: 840px; }
  .doc-head h1 { font-size: clamp(28px, 4.5vw, 40px); }
  .prose       { font-size: 16.5px; }
  .prose h2    { font-size: 20px; }
  .prose .mono { font-size: 15px; }
}

@media (min-width: 2000px) {
  :root { --gutter: 80px; }

  .brand-mark  { height: 54px; }
  .brand-word  { font-size: 20px; }
  .coord       { font-size: 13px; }

  .hero        { max-width: 980px; gap: 20px; }
  .overline    { font-size: 15px; }
  .hero h1     { font-size: clamp(30px, 5vw, 54px); }
  .rule        { width: 84px; }
  .subline     { font-size: 18.5px; }

  .arc         { width: min(1248px, 100%); }

  .cards       { width: min(1332px, 100%); }
  .card        { width: 572px; padding: 42px 48px; gap: 20px; }
  .card p      { font-size: 17px; }
  .card-logo   { height: 44px; }
  .pill        { font-size: 13px; padding: 7px 18px; }
  .cta         { font-size: 17px; padding: 14px 30px; }

  .telemetry code { font-size: 15px; padding: 16px 30px; }

  .site-footer { font-size: 14px; }

  .doc         { max-width: 900px; }
  .doc-head h1 { font-size: clamp(28px, 4.5vw, 44px); }
  .prose       { font-size: 17.5px; }
  .prose h2    { font-size: 21px; }
  .prose .mono { font-size: 16px; }
}

/* --- Motion --------------------------------------------------------------
   There is no animation anywhere on this site; that is deliberate and is
   part of the published accessibility statement. This block is a guard for
   anything added later.                                                     */

@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;
  }
}

/* --- Print ---------------------------------------------------------------
   The legal pages get printed and filed. Drop the chrome, keep the text.   */

@media print {
  .lang-toggle,
  .skip-link,
  .back-link,
  .arc,
  .coord,
  .site-footer nav { display: none; }

  .page--landing { background-image: none; }

  body { font-size: 11pt; color: #000; }

  .doc { padding: 0; max-width: none; }

  .prose a::after {
    content: ' (' attr(href) ')';
    font-family: var(--font-mono);
    font-size: 0.85em;
  }

  .callout { border: 1px solid #999; background: none; }
}
