/* ECO POWERTECH — base
   Reset, fonts, type scale, bands, and the components shared across sections.

   RULE 1: no colour, size, duration or easing literal in this file. Everything
   resolves through design/tokens.css. The only bare numbers permitted are 0,
   unitless line-heights that are themselves tokens, and structural integers
   (grid spans, z-index steps, opacity 1).
   RULE 2: components read semantic tokens only — --bg, --fg, --accent,
   --hairline, --focus. Never --magenta-lit or --cotton directly.
   ------------------------------------------------------------------------- */

/* ---- Fonts ---------------------------------------------------------------
   Two families, self-hosted, one file each. Archivo's single variable file
   carries wdth 62-125 and wght 100-900, so the expanded display face and the
   regular body face cost one request between them. */

@font-face {
  font-family: 'Archivo';
  src: url('../../assets/fonts/archivo-var-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('../../assets/fonts/jetbrains-mono-500-latin.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}


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

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

/* NO `scroll-behavior: smooth` here.

   Two reasons, both load-bearing. It smooth-scrolls THROUGH the 3240px hero
   scrub on every nav anchor click, which forces the whole clip to be seeked in
   one animation. And it fights Lenis, which owns smooth scrolling on this page
   and disables native smooth behaviour for exactly that reason. Anchor easing
   is Lenis's job now; with Lenis absent, anchors jump, which is the correct
   accessible default. */
html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--body);
  font-weight: var(--wt-regular);
  line-height: var(--lh-body);
  font-stretch: var(--wd-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

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

/* German compounds — "Anforderungsprofil", "Personalverrechner:in",
   "Arbeitskräfteüberlassung" — are single words wider than a phone viewport at
   display size, and no amount of wrapping helps a word that cannot break.
   overflow-wrap is the last resort for exactly that case.

   hyphens is `manual`, NOT `auto`. Auto-hyphenation is right for running text
   and wrong for display type: reading lang="de-AT", the hyphenator broke
   "gemessen" to "ge-messen" in a 49px headline and "Projektbasierende" to
   "Projektbasie-rende" in a service title. Both are legal German breaks and
   both read as typographic accidents at that size. Headings wrap; they do not
   hyphenate. A compound that genuinely cannot fit is still caught by
   overflow-wrap below. */
h1, h2, h3 {
  hyphens: manual;
  overflow-wrap: break-word;
}

/* A grid or flex child defaults to min-width:auto, which refuses to shrink
   below its longest unbreakable word and pushes the whole track wide. */
.wrap > *, .form__row > *, .proc__inner > *, .co__grid > *, .enq__grid > * {
  min-width: 0;
}
ul, ol { margin: 0; padding: 0; list-style: none; }

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

a { color: inherit; text-decoration: none; }
abbr[title] { text-decoration: none; }

button, input, textarea, select {
  font: inherit;
  color: inherit;
  border-radius: var(--radius);
}


/* ---- Focus ---------------------------------------------------------------
   One visible focus treatment for the whole page. --focus is the only token
   that never changes across bands, because a focus ring that changes contrast
   with the background is a focus ring you can lose. */

:focus-visible {
  outline: var(--hairline-w) solid var(--focus);
  outline-offset: var(--s-2);
}
:focus:not(:focus-visible) { outline: none; }

/* ---- Document scroll progress -------------------------------------------
   A hairline across the top of the viewport. It sits ABOVE the nav in stacking
   order but is one pixel tall and pointer-inert, so it never intercepts a
   click. The bar itself only animates under the motion guard; with no
   scroll-driven animation support it simply stays at scaleX(0) and is
   invisible, which is the correct nothing. */
.page-progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: calc(var(--z-nav) + 1);
  height: var(--hairline-w);
  pointer-events: none;
  background: transparent;
}
.page-progress__bar {
  display: block;
  height: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
}

.skip {
  position: absolute;
  left: var(--s-4);
  top: calc(var(--s-4) * -6);
  z-index: var(--z-overlay);
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: var(--s-3) var(--s-4);
  background: var(--accent);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: var(--eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  transition: top var(--dur-hover) var(--ease-out);
}
.skip:focus { top: var(--s-4); }


/* ---- Bands ---------------------------------------------------------------
   A band paints its own ground and re-points the semantic tokens (the mapping
   itself lives in tokens.css). Every section is full-bleed; the .wrap inside
   holds the measure. */

[data-band] {
  background: var(--bg);
  color: var(--fg);
}

/* The nav is sticky, so an in-page anchor lands with its heading underneath it.
   scroll-margin moves the landing point down by the nav's height. */
[id] { scroll-margin-top: calc(var(--s-16) + var(--s-4)); }

/* Full-bleed. There is no fixed container: the gutter is the layout, and it
   keeps growing to 7rem so the content never runs to the screen edge.

   The previous `max-width: calc(var(--s-48) * 8)` capped the page at 1536px,
   which left a 1920 display with a 1408px column inside 192px of dead margin on
   each side and nothing growing above ~1536px. Line length is still protected
   where it matters — --measure governs .lead and .body — so removing the cap
   widens the GRID without ever widening a paragraph. */
.wrap {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--gutter);
}


/* ---- Type ----------------------------------------------------------------
   Leading climbs one step per tier: display 0.92, heading 1.08, lead 1.30,
   body 1.65. Tracking tightens as size grows. */

.h2 {
  font-size: var(--h2);
  font-weight: var(--wt-semi);
  font-stretch: var(--wd-display);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
  text-wrap: balance;
}

.h3 {
  font-size: var(--h3);
  font-weight: var(--wt-semi);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
}

.lead {
  max-width: var(--measure);
  font-size: var(--body-l);
  line-height: var(--lh-lead);
  letter-spacing: var(--tr-lead);
  text-wrap: pretty;
}

.body {
  max-width: var(--measure);
  color: var(--fg-muted);
  text-wrap: pretty;
}

/* Mono label over a hairline rule. Names the section — never numbers it. */
.eyebrow {
  font-family: var(--font-mono);
  font-weight: var(--wt-medium);
  font-size: var(--eyebrow);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
/* The rule is a pseudo-element rather than a border-top so motion.css can draw
   it in with scaleX, which is a compositor property; a border cannot be
   animated without paint. The padding absorbs the hairline the border used to
   contribute, so the box height and the text offset are unchanged from Phase 4
   and the static rendering is pixel-identical. */
.eyebrow--rule {
  position: relative;
  padding-top: calc(var(--s-3) + var(--hairline-w));
}
.eyebrow--rule::after {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: var(--hairline-w);
  background: var(--hairline);
}
.eyebrow__sep {
  color: var(--fg-muted);
  padding-inline: var(--s-2);
}


/* ---- Buttons -------------------------------------------------------------
   Hairline box, mono caps label, sharp corners, scale(0.97) on :active.
   The `↳` glyph specified in DIRECTION.md §4 does not exist in either font
   (U+21B3 is absent from Archivo and JetBrains Mono), so it is drawn as SVG.
   That also lets it share the hairline stroke weight of the diagrams, which a
   text glyph never would. */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--tap-min);
  padding: var(--s-3) var(--s-6);
  /* --control-edge, not --hairline: this box is the whole affordance for a
     ghost button, and at --hairline it measured 1.35:1 on ink — a control
     boundary WCAG 1.4.11 requires to clear 3:1. See design/tokens.css. */
  border: var(--hairline-w) solid var(--control-edge);
  border-radius: var(--radius);
  background: transparent;
  color: var(--fg);
  font-family: var(--font-mono);
  font-weight: var(--wt-medium);
  font-size: var(--eyebrow);
  letter-spacing: var(--tr-eyebrow);
  line-height: var(--lh-heading);
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background-color var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color var(--dur-hover) var(--ease-out),
    transform var(--dur-press) var(--ease-out);
}

.btn__glyph, .btn__ext {
  width: var(--s-3);
  height: var(--s-3);
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: var(--hairline-w);
  vector-effect: non-scaling-stroke;
}
.btn__glyph { width: var(--s-4); height: var(--s-4); }

.btn--solid {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}
.btn--ghost { border-color: var(--control-edge); }

/* --tap-min, not padding alone: at --s-2 the small nav buttons measured 30px
   tall on a phone. The padding still sets the optical size; the min-height
   guarantees the hit box. */
.btn--sm { padding: var(--s-2) var(--s-4); min-height: var(--tap-min); }

/* "Anforderungsprofil senden" in mono caps at 0.18em tracking is wider than a
   375px viewport can spare next to the logo. The label shortens; the
   destination and the intent do not. */
.btn__narrow { display: none; }
@media (max-width: 719px) {
  .btn__wide   { display: none; }
  .btn__narrow { display: inline; }
}
.btn--block { display: flex; width: 100%; justify-content: center; }

@media (hover: hover) and (pointer: fine) {
  .btn--solid:hover { background: var(--focus); border-color: var(--focus); }
  .btn--ghost:hover { border-color: var(--accent); color: var(--accent); }
}
.btn:active { transform: scale(0.97); }


/* ---- Section heads -------------------------------------------------------- */

.sec-head { margin-bottom: var(--s-16); }
.sec-head .eyebrow { margin-bottom: var(--s-4); }
.sec-head__lead { margin-top: var(--s-6); color: var(--fg-muted); }

.sec-head--split {
  display: grid;
  gap: var(--s-8);
  align-items: end;
}
/* 1080, not 900: at 900 the auto track resolved to 421.7px against a 374.3px
   headline column - the supporting note wider than the display heading it
   supports, the same weighting inversion .pos__grid was fixed for in Phase 8.
   Below 1080 the two stack, which is the honest answer at that width.

   The selector read `.roles__note` until Phase 9. `.roles` was replaced by
   `#berufsfelder` in Phase 8 and nothing has carried that class since; the note
   kept a sane measure only by coincidence, from .fields__note's own 46ch. */
@media (min-width: 1080px) {
  .sec-head--split { grid-template-columns: 1fr auto; }
  .sec-head--split .fields__note { max-width: calc(var(--measure) / 2); }
}


/* ---- Utilities ------------------------------------------------------------ */

.u-sr {
  position: absolute;
  width: var(--hairline-w);
  height: var(--hairline-w);
  padding: 0;
  margin: calc(var(--hairline-w) * -1);
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.u-defs { position: absolute; }
