/* ============================================================
   Lav Et System - forside (produktion, CSP-ren).
   Selv-hostet IBM Plex, ingen CDN. Kun vaegte der faktisk findes
   lokalt bruges: Sans 400/600, Mono 400/600.
   ============================================================ */
@font-face { font-family:"IBM Plex Sans"; font-style:normal; font-weight:400; font-display:swap; src:url("fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Sans"; font-style:normal; font-weight:600; font-display:swap; src:url("fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:400; font-display:swap; src:url("fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:600; font-display:swap; src:url("fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2"); }

/* ============================================================
   Lav Et System — forside, retning C: eksperimentel
   Ét signaturmoment: ASCII-punktsky-drevet i heroen. Værktøjet
   arbejder kun, når det bliver brugt. Alt under heroen er roligt.
   Blueprint-ark. Monokromt blæk, én rust-accent. Sort, ikke blå.
   ============================================================ */

:root {
  --paper: #f4f4ef;
  --ink: #1a1a1a;
  --ink-soft: #4d4d4d;
  --line: rgba(26, 26, 26, 0.30);
  --line-faint: rgba(26, 26, 26, 0.15);
  --accent: #a63a24;
  --grid-minor: rgba(26, 26, 26, 0.05);
  --grid-major: rgba(26, 26, 26, 0.09);
  --sans: "IBM Plex Sans", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;

  --z-base: 0;
  --z-overlay: 5;
  --z-readout: 20;
  --z-focus: 30;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0e0e10;
    --ink: #e8e8e6;
    --ink-soft: #a4a4a1;
    --line: rgba(232, 232, 230, 0.30);
    --line-faint: rgba(232, 232, 230, 0.14);
    --accent: #ff9670;
    --grid-minor: rgba(232, 232, 230, 0.05);
    --grid-major: rgba(232, 232, 230, 0.09);
  }
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  /* Intet overflow-x-vaern her med vilje: Chromium propagerer ikke `clip`
     fra body til viewporten, saa reglen loeste ingenting. Vandret rulning
     holdes nede ved kilden (skaeremaerkernes plads, knappernes min-bredde,
     maallinjens nowrap) og vogtes af tests/vandret-rulning.spec.js. */
  color: var(--ink);
  background-color: var(--paper);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- levende tegneark ----------
   Millimetergitteret ligger paa ét dedikeret, fast fuldskaerms-lag
   bag alt indhold. Det driver uendeligt langsomt paa en diagonal —
   praecis én flise (64px) pr. cyklus, saa loopet er somloest — via
   transform alene (GPU-billigt, ingen sidebred repaint). Laget er
   64px stoerre til alle sider, saa driften aldrig blotter en kant.
   Samme opacitet/kontrast som foer: atmosfaere, ikke et feature. */
body::before {
  content: "";
  position: fixed;
  inset: -64px;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(var(--grid-major) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-major) 1px, transparent 1px),
    linear-gradient(var(--grid-minor) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-minor) 1px, transparent 1px);
  background-size: 64px 64px, 64px 64px, 8px 8px, 8px 8px;
  will-change: transform;
  /* driften + en indgang hvor arket RULES ind oppefra og ned (clip-path,
     komposit-venligt) i stedet for en flad optoning — som en T-vinkel,
     der traekker gitteret ned over bordet. */
  animation:
    grid-drift 64s linear infinite,
    grid-in 1700ms cubic-bezier(0.4, 0, 0.2, 1) 60ms both;
}
@keyframes grid-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(64px, 64px, 0); }
}
@keyframes grid-in {
  from { clip-path: inset(0 0 100% 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* ---------- den usynlige tegner ----------
   Signaturens rolige modstykke: ovenpaa den faste bed ligger et lag,
   hvor faa tekniske maerker plotter sig selv ét ad gangen og fader —
   registreringskryds, en dimensionslinje med maal, et vinkelmaerke og
   et koordinat-nulpunkt — som om en usynlig tegner annoterer arket rundt
   omkring, mens man laeser. Intet reagerer paa musen (drevet ejer musen).
   Rent transform/opacity/clip-path, ingen JS-loop, ingen sidebred repaint;
   faa smaa elementer paa lange, desynkroniserede loops. Bevidst hviskestille
   — samme atmosfaeriske vaegt som gitteret, aldrig et andet feature.
   Ved indgang traekker en T-vinkel gitteret ned (se .tsq nedenfor). */
.draft {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  contain: layout paint;
}
/* T-vinkel: én rust-tonet parallel-lineal glider ned én gang ved load og
   "laegger" arket — indgangsgestus, forsvinder bagefter. */
.draft .tsq {
  position: absolute;
  left: -64px; right: -64px; top: 0;
  height: 0;
  border-top: 1px solid color-mix(in srgb, var(--accent) 42%, var(--line));
  opacity: 0;
  transform: translateY(-40px);
  animation: tsq-lay 1700ms cubic-bezier(0.4, 0, 0.2, 1) 60ms both;
}
@keyframes tsq-lay {
  0%   { opacity: 0;   transform: translateY(-40px); }
  16%  { opacity: 0.5; }
  100% { opacity: 0;   transform: translateY(80vh); }
}

/* plottede maerker — hairlines i blaek, ét enkelt rust-datum */
.mk { position: absolute; opacity: 0; }
.mk-reg { width: 26px; height: 26px; --mk-line: var(--line); }
.mk-reg::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px; transform: translateY(-50%); background: var(--mk-line); }
.mk-reg::after  { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; width: 1px; transform: translateX(-50%); background: var(--mk-line); }
.mk-reg i { position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; transform: translate(-50%, -50%); border: 1px solid var(--mk-line); border-radius: 50%; }
.mk-rust { --mk-line: color-mix(in srgb, var(--accent) 62%, var(--line)); }

.mk-dim { width: 66px; height: 14px; }
.mk-dim::before { content: ""; position: absolute; left: 0; right: 0; top: 6px; height: 1px; background: var(--line); }
.mk-dim i { position: absolute; top: 0; bottom: 6px; width: 1px; background: var(--line); }
.mk-dim i:first-child { left: 0; } .mk-dim i:last-child { right: 0; }
.mk-dim b { position: absolute; left: 50%; top: 7px; transform: translateX(-50%); font-family: var(--mono); font-weight: 400; font-size: 8.5px; letter-spacing: 0.1em; color: var(--ink-soft); }

.mk-ang { width: 30px; height: 30px; }
.mk-ang::before { content: ""; position: absolute; left: 0; bottom: 0; width: 30px; height: 1px; background: var(--line); }
.mk-ang::after  { content: ""; position: absolute; left: 0; bottom: 0; width: 1px; height: 30px; background: var(--line); }
.mk-ang i { position: absolute; left: 0; bottom: 0; width: 15px; height: 15px; border: 1px solid transparent; border-top-color: var(--line); border-right-color: var(--line); border-radius: 0 100% 0 0; }

.mk-crd { width: 22px; height: 22px; --mk-line: var(--line); }
.mk-crd::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--mk-line); }
.mk-crd::after  { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 1px; background: var(--mk-line); }
.mk-crd b { position: absolute; left: 5px; top: 5px; font-family: var(--mono); font-weight: 400; font-size: 8.5px; letter-spacing: 0.08em; color: var(--ink-soft); }

/* clip-path plotter maerket ind, holder kort, fader; lang stille pause */
@keyframes mk-c {
  0%   { opacity: 0; clip-path: inset(46% 46% 46% 46%); }
  8%   { opacity: var(--mk-peak, 0.5); clip-path: inset(0 0 0 0); }
  28%  { opacity: var(--mk-peak, 0.5); clip-path: inset(0 0 0 0); }
  40%  { opacity: 0; clip-path: inset(0 0 0 0); }
  100% { opacity: 0; clip-path: inset(0 0 0 0); }
}
@keyframes mk-x {
  0%   { opacity: 0; clip-path: inset(0 100% 0 0); }
  8%   { opacity: var(--mk-peak, 0.5); clip-path: inset(0 0 0 0); }
  28%  { opacity: var(--mk-peak, 0.5); }
  40%  { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes mk-y {
  0%   { opacity: 0; clip-path: inset(100% 0 0 0); }
  8%   { opacity: var(--mk-peak, 0.5); clip-path: inset(0 0 0 0); }
  28%  { opacity: var(--mk-peak, 0.5); }
  40%  { opacity: 0; }
  100% { opacity: 0; }
}

::selection { background: var(--accent); color: var(--paper); }

a { color: inherit; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}

/* skip-link */
.skip {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: var(--z-focus);
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 10px 16px;
  font-family: var(--mono);
  font-size: 0.8rem;
  text-decoration: none;
  transition: top 160ms ease;
}
.skip:focus { top: 12px; }

/* ---------- arket ---------- */

.sheet {
  position: relative;
  max-width: 1160px;
  /* skaeremaerkerne staar 25px uden for arket. Uden denne bredde ligger de
     uden for vinduet paa alt mellem 561px og 1210px, og siden kan rulles
     vandret. 68px = 2 x 34 giver dem plads, ogsaa naar arket er smallere
     end sin maksimale bredde. */
  width: calc(100% - 68px);
  margin: 40px auto 56px;
  border: 1px solid var(--line);
  background: transparent;
}

.cropmark { position: absolute; width: 17px; height: 17px; pointer-events: none; }
.cropmark::before, .cropmark::after { content: ""; position: absolute; background: var(--line); }
.cropmark::before { width: 17px; height: 1px; }
.cropmark::after  { width: 1px; height: 17px; }
.cm-tl { top: -25px; left: -25px; } .cm-tl::before { bottom: 0; left: 0; } .cm-tl::after { right: 0; top: 0; }
.cm-tr { top: -25px; right: -25px; } .cm-tr::before { bottom: 0; right: 0; } .cm-tr::after { left: 0; top: 0; }
.cm-bl { bottom: -25px; left: -25px; } .cm-bl::before { top: 0; left: 0; } .cm-bl::after { right: 0; bottom: 0; }
.cm-br { bottom: -25px; right: -25px; } .cm-br::before { top: 0; right: 0; } .cm-br::after { left: 0; bottom: 0; }

/* ---------- topbjælke ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 24px;
  padding: 20px 40px;
  border-bottom: 1px solid var(--line);
}

.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.brand-mark { color: var(--accent); flex: none; }
.brand-name {
  font-family: var(--mono);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.topbar nav { display: flex; flex-wrap: wrap; gap: 12px 26px; }
.topbar nav a {
  position: relative;
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* menupunkter med to ord (LES BOOKING) skal bryde som ét punkt til
     naeste raekke, ikke midt i navnet. */
  white-space: nowrap;
  text-decoration: none;
  color: var(--ink-soft);
  padding-bottom: 3px;
  transition: color 180ms ease;
}
.topbar nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 220ms cubic-bezier(0.22, 0.7, 0.3, 1);
}
.topbar nav a:hover, .topbar nav a:focus-visible { color: var(--ink); }
.topbar nav a:hover::after, .topbar nav a:focus-visible::after { transform: scaleX(1); }
.topbar nav a:active { color: var(--accent); }

/* ---------- typografiske byggesten ---------- */

.annot {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 16px;
}

h1, h2, h3 { margin: 0; font-family: var(--sans); font-weight: 600; letter-spacing: -0.02em; text-wrap: balance; }

/* ============================================================
   HERO — signaturmoment
   ============================================================ */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  align-items: stretch;
  border-bottom: 1px solid var(--line);
}

.hero-copy {
  padding: 76px 44px 64px;
  min-width: 0;
  align-self: center;
}

.hero h1 {
  font-size: clamp(2.15rem, 5vw, 3.5rem);
  line-height: 1.06;
  max-width: 15ch;
  letter-spacing: -0.04em;
  text-wrap: balance;
}
.hero-sub-line { color: var(--ink-soft); }

.hero-lead {
  max-width: 46ch;
  margin: 28px 0 0;
  font-size: 1.04rem;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* dimensionslinje */
.dim { display: flex; align-items: center; gap: 14px; max-width: 440px; margin-top: 30px; }
.dim-line { flex: 1; height: 1px; background: var(--line); }
.dim-tick { width: 1px; height: 11px; background: var(--line); }
.dim-label {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  white-space: nowrap;
}

/* --- drev-panelet (lærred) --- */
.hero-visual {
  position: relative;
  border-left: 1px solid var(--line);
  min-height: 520px;
  overflow: hidden;
  /* diagonal-arceret felt bag drevet, meget diskret */
  background:
    repeating-linear-gradient(45deg, transparent 0 11px, var(--grid-minor) 11px 12px);
}
@media (prefers-color-scheme: dark) {
  .hero-visual { background: repeating-linear-gradient(45deg, transparent 0 11px, rgba(232,232,230,0.035) 11px 12px); }
}

.gear-stage {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none;
  outline-offset: -3px;
}
.gear-stage:active { cursor: grabbing; }
.gear-stage:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }

.gear-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* hjørne-annotation i panelet */
.visual-annot {
  position: absolute;
  top: 16px;
  left: 18px;
  z-index: var(--z-overlay);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  pointer-events: none;
}

/* aflæsning nederst — som en tællerværkstatus */
.readout {
  position: absolute;
  left: 18px;
  bottom: 16px;
  z-index: var(--z-readout);
  display: flex;
  align-items: baseline;
  gap: 14px;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  border: 1px solid var(--line-faint);
  padding: 7px 13px 6px;
  pointer-events: none;
  backdrop-filter: blur(2px);
}
.readout .r-key { text-transform: uppercase; font-size: 0.64rem; opacity: 0.8; }
.readout b { font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }

/* brugs-hint */
.gear-hint {
  position: absolute;
  right: 18px;
  bottom: 18px;
  z-index: var(--z-readout);
  max-width: 15ch;
  text-align: right;
  font-family: var(--mono);
  font-size: 0.66rem;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  pointer-events: none;
}
.gear-hint kbd {
  font-family: var(--mono);
  font-size: 0.62rem;
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 1px 5px;
  color: var(--ink);
}

/* ============================================================
   Sektioner — rolige
   ============================================================ */

.section { padding: 60px 44px 68px; border-bottom: 1px solid var(--line); }
/* rytme: komponenter faar luft, om strammes, kontakt aander ud mod titelblokken */
#komponenter { padding-top: 76px; padding-bottom: 60px; }
#om { padding-top: 58px; padding-bottom: 58px; }
#kontakt { padding-top: 56px; padding-bottom: 80px; }
.section-head { margin-bottom: 42px; }
.section-head .annot { margin-bottom: 10px; }
.section-head h2 { font-size: 1.65rem; letter-spacing: -0.02em; }

.component {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 48px;
  align-items: start;
}

.part-no {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 8px;
}

.component-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; margin-bottom: 14px; }
.component-title-row h3 { font-size: 1.4rem; }
.component-text > p { margin: 0 0 20px; max-width: 52ch; text-wrap: pretty; }
.component-next p, .om-grid > p, .section-kontakt p, .facts dd { text-wrap: pretty; }

.stamp {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1.5px solid var(--accent);
  padding: 4px 12px 3px;
  transform: rotate(-2deg);
}
.stamp-dashed { color: var(--ink-soft); border: 1.5px dashed var(--line); transform: rotate(0deg); }

.specs {
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
  font-family: var(--mono);
  font-size: 0.84rem;
  color: var(--ink-soft);
}
.specs li { padding: 9px 0 9px 26px; border-top: 1px solid var(--line-faint); position: relative; }
.specs li:last-child { border-bottom: 1px solid var(--line-faint); }
.specs li::before {
  content: "";
  position: absolute; left: 4px; top: 50%;
  width: 9px; height: 9px;
  transform: translateY(-50%);
  border: 1.5px solid var(--accent);
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: var(--mono);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 13px 22px;
  /* en mailadresse er ét ubrudt ord i mono og er bredere end spalten paa
     de smalleste telefoner. Knappen maa aldrig blive bredere end sin
     spalte: hellere en etiket der bryder end et ark der kan trilles. */
  max-width: 100%;
  overflow-wrap: anywhere;
  transition: color 180ms ease, border-color 180ms ease, background-color 180ms ease, transform 120ms ease;
}
.cta svg { transition: transform 220ms cubic-bezier(0.22, 0.7, 0.3, 1); }
.cta:hover { color: var(--accent); border-color: var(--accent); background-color: color-mix(in srgb, var(--accent) 8%, transparent); }
.cta:hover svg { transform: translateX(5px); }
.cta:active { transform: translateY(1px); }

/* skematik */
.component-figure { margin: 0; min-width: 0; }
.schematic { width: 100%; height: auto; display: block; color: var(--ink); }
.schematic .s-line   { fill: none; stroke: currentColor; stroke-width: 1.4; }
.schematic .s-thin   { fill: none; stroke: currentColor; stroke-width: 0.9; opacity: 0.55; }
.schematic .s-acc    { fill: none; stroke: var(--accent); stroke-width: 1.6; }
.schematic .s-center { stroke: currentColor; stroke-width: 0.7; stroke-dasharray: 9 4 2 4; opacity: 0.3; }
.schematic .s-text   { fill: currentColor; font-family: var(--mono); font-size: 10px; stroke: none; }
.schematic .s-label  { fill: var(--ink-soft); font-family: var(--mono); font-size: 10px; letter-spacing: 0.12em; stroke: none; }
.schematic .s-dim-label { fill: var(--accent); letter-spacing: 0.06em; }
.component-figure .annot { margin: 14px 0 0; }

/* komponent 02 — staar under komponent 01 paa samme ark, adskilt af en
   linje i stedet for en ramme: to poster paa styklisten, ikke to kort. */
.component-02 {
  margin-top: 52px;
  padding-top: 34px;
  border-top: 1px solid var(--line);
}
.component-02 .component-text { max-width: 660px; }

/* komponent-boks til noget der endnu ikke er bygget (ubrugt paa forsiden nu,
   beholdt saa den kan tages i brug igen uden at genopfinde moenstret) */
.component-next {
  margin-top: 56px;
  padding: 28px 32px 30px;
  border: 1px dashed var(--line);
  max-width: 620px;
}
.component-next h3 { font-size: 1.12rem; }
.component-next p { margin: 0; max-width: 52ch; color: var(--ink-soft); }
.component-next .component-title-row { margin-bottom: 10px; }

/* om */
.om-grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 48px; align-items: start; }
.om-grid > p { margin: 0; max-width: 56ch; }
.facts { margin: 0; }
.facts > div {
  display: grid; grid-template-columns: 96px 1fr; gap: 16px;
  padding: 12px 0; border-top: 1px solid var(--line-faint);
}
.facts > div:last-child { border-bottom: 1px solid var(--line-faint); }
.facts dt {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-soft); padding-top: 3px;
}
.facts dd { margin: 0; font-size: 0.95rem; }

/* kontakt */
.section-kontakt p { margin: 0 0 26px; max-width: 52ch; color: var(--ink-soft); }

/* titelblok */
.titleblock {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
  gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
}
.tb-cell { padding: 12px 16px 14px; background: var(--paper); min-width: 0; }
.tb-wide { grid-column: span 2; }
.tb-label {
  display: block; font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-soft); margin-bottom: 3px;
}
.tb-value { display: block; font-family: var(--mono); font-size: 0.82rem; overflow-wrap: break-word; }
.tb-value a { text-decoration: none; border-bottom: 1px solid var(--line); transition: color 180ms ease, border-color 180ms ease; }
.tb-value a:hover { color: var(--accent); border-bottom-color: var(--accent); }
/* Registreringsnumre saettes med ens cifferbredde, som paa en rigtig tegning. */
.tb-tal { font-variant-numeric: tabular-nums; letter-spacing: 0.06em; }

/* ============================================================
   Indgangskoreografi — "arket plottes selv" (~1,9 s)
   Ét koordineret forlob: beskaeringsmaerker tikker ind, rammen
   traekkes med en rust-pen, topbjaelke og titelblok saetter sig,
   heroteksten stiger i raekkefolge, dimensionslinjen maaler sig
   selv udad fra midten, konturfeltet toner op, og drevet spinner
   op fra hvile (styret i JS).

   Alt er KUN forbedring af noget allerede synligt: intet element
   har opacity:0 i grundtilstand, saa siden staar faerdig uden JS
   og uden animationsstotte. Reduceret bevaegelse nulstiller bade
   varighed OG forsinkelse laengere nede — alt staar med det samme.
   ============================================================ */
@keyframes ls-rise   { from { opacity: 0; transform: translateY(12px); } }
@keyframes ls-fade   { from { opacity: 0; } }
@keyframes ls-settle { from { opacity: 0; transform: translateY(-6px); } }
@keyframes ls-draw-x { from { transform: scaleX(0); } }
@keyframes cm-pop    { from { opacity: 0; transform: scale(0.35); } }
@keyframes fp-life   { 0% { opacity: 1; } 84% { opacity: 1; } 100% { opacity: 0; } }
@keyframes fp-draw-x { from { transform: scaleX(0); } }
@keyframes fp-draw-y { from { transform: scaleY(0); } }
@keyframes ls-stamp {
  0%   { opacity: 0; transform: rotate(-10deg) scale(2.1); }
  55%  { opacity: 1; }
  78%  { transform: rotate(-1.2deg) scale(0.96); }
  100% { transform: rotate(-2deg) scale(1); }
}
@keyframes ls-revbump {
  0%   { transform: translateY(0); }
  35%  { transform: translateY(-3px); }
  100% { transform: translateY(0); }
}

/* 1 · beskaeringsmaerker tikker ind fra deres hjorne */
.cropmark { animation: cm-pop 360ms cubic-bezier(0.22, 0.7, 0.3, 1) backwards; }
.cm-tl { transform-origin: top left;     animation-delay: 40ms; }
.cm-tr { transform-origin: top right;    animation-delay: 100ms; }
.cm-bl { transform-origin: bottom left;  animation-delay: 160ms; }
.cm-br { transform-origin: bottom right;  animation-delay: 220ms; }

/* 2 · rammen traekkes: rust-pen tracer arkets kant og forsvinder,
   saa den permanente 1px-ramme staar tilbage. Overlay er usynlig
   som grundtilstand (opacity:0) -> intet spor uden animation. */
.frame-plot { position: absolute; inset: 0; pointer-events: none; z-index: var(--z-focus); opacity: 0; animation: fp-life 1200ms ease-out 140ms both; }
.frame-plot i { position: absolute; background: var(--accent); }
.frame-plot .fp-t { top: -1px; left: -1px; right: -1px; height: 1px; transform-origin: left center;   animation: fp-draw-x 240ms cubic-bezier(0.4, 0, 0.2, 1) 140ms backwards; }
.frame-plot .fp-r { top: -1px; right: -1px; bottom: -1px; width: 1px; transform-origin: center top;    animation: fp-draw-y 220ms cubic-bezier(0.4, 0, 0.2, 1) 360ms backwards; }
.frame-plot .fp-b { bottom: -1px; left: -1px; right: -1px; height: 1px; transform-origin: right center; animation: fp-draw-x 240ms cubic-bezier(0.4, 0, 0.2, 1) 560ms backwards; }
.frame-plot .fp-l { top: -1px; left: -1px; bottom: -1px; width: 1px; transform-origin: center bottom;   animation: fp-draw-y 240ms cubic-bezier(0.4, 0, 0.2, 1) 780ms backwards; }

/* 3 · topbjaelke + titelblok saetter sig */
.topbar     { animation: ls-settle 520ms cubic-bezier(0.22, 0.7, 0.3, 1) 260ms backwards; }
.titleblock { animation: ls-fade 640ms ease 340ms backwards; }

/* 4 · heroteksten stiger i raekkefolge */
.hero-copy .annot { animation: ls-fade 480ms ease 600ms backwards; }
.hero-copy h1     { animation: ls-rise 660ms cubic-bezier(0.22, 0.7, 0.3, 1) 700ms backwards; }
.hero-lead        { animation: ls-rise 660ms cubic-bezier(0.22, 0.7, 0.3, 1) 1120ms backwards; }

/* 4b · dimensionslinjen maaler sig selv: label staar, linjerne
   traekkes udad fra midten, yderste ticks toner ind til sidst */
.dim .dim-label            { animation: ls-fade 360ms ease 940ms backwards; }
.dim .dim-line:nth-child(2){ transform-origin: right center; animation: ls-draw-x 440ms cubic-bezier(0.4, 0, 0.2, 1) 1000ms backwards; }
.dim .dim-line:nth-child(4){ transform-origin: left center;  animation: ls-draw-x 440ms cubic-bezier(0.4, 0, 0.2, 1) 1000ms backwards; }
.dim .dim-tick:first-child { animation: ls-fade 220ms ease 1420ms backwards; }
.dim .dim-tick:last-child  { animation: ls-fade 220ms ease 1420ms backwards; }

/* 5 · drev-panelet toner op (drevet selv spinner op i JS) */
.hero-visual { animation: ls-fade 900ms ease 760ms backwards; }

/* ---------- scroll-reveals: forbedrer allerede synligt indhold ----------
   Grundtilstand = fuldt synlig (uden JS, eller off-screen der aldrig
   naaes, staar indholdet blot der). NAAR JS koerer og bevaegelse er
   tilladt, saetter det .ls-reveal-ready paa <html> FOER elementet
   ruller i syne — saa forudtilstanden (let daempet + 8px) staar klar
   inden reveal'en, og indgangen glider ind UDEN et spring. Indgangs-
   keyframens fra-tilstand er identisk med forudtilstanden, saa der er
   ingen omraster/hop naar animationen begynder. Fyres én gang. */
@keyframes ls-reveal { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }

.ls-reveal-ready .reveal,
.ls-reveal-ready .reveal-row { opacity: 0; transform: translateY(18px); }

/* glide, ikke pop: laengere varighed + ease-out quint, saa indholdet
   sejler roligt paa plads. Fra-tilstand = forudtilstand => intet spring. */
.reveal.is-in         { animation: ls-reveal 1080ms cubic-bezier(0.33, 1, 0.68, 1) both; will-change: opacity, transform; }
.reveal-row.is-in     { animation: ls-reveal 960ms cubic-bezier(0.33, 1, 0.68, 1) both; will-change: opacity, transform; }

/* naar indgangen er faerdig: laas synlig, ryd transform + will-change,
   saa teksten ikke bliver haengende paa et komposit-lag (blur-risiko) */
.reveal.is-done,
.reveal-row.is-done { opacity: 1; transform: none; will-change: auto; animation: none; }

/* "I drift"-stemplet slaas i, naar det naar syne */
.stamp.is-stamped { animation: ls-stamp 460ms cubic-bezier(0.2, 0.9, 0.3, 1.15) 40ms backwards; }

/* OMDR-tael giver et lille nik hver gang en omdrejning logges */
.readout b.is-bump { animation: ls-revbump 340ms ease; }

/* ============================================================
   Responsivt
   ============================================================ */

@media (max-width: 1000px) {
  .hero { grid-template-columns: 1fr; }
  .hero-copy { padding: 60px 36px 44px; order: 1; }
  .hero-visual { order: 2; border-left: none; border-top: 1px solid var(--line); min-height: 400px; }
  .component, .om-grid { grid-template-columns: 1fr; gap: 40px; }
  .component-figure { max-width: 420px; }
  .section { padding: 52px 36px 60px; }
  .topbar { padding: 16px 32px; }
  .titleblock { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .sheet { width: auto; margin: 20px 14px 36px; }
  .cropmark { display: none; }
  .topbar { flex-direction: column; align-items: flex-start; gap: 14px; padding: 16px 20px; }
  .topbar nav { gap: 18px; flex-wrap: wrap; }
  .hero-copy { padding: 44px 20px 36px; }
  .hero-visual { min-height: 340px; }
  .section { padding: 44px 20px 48px; }
  .component-next { padding: 22px 20px 24px; }
  .gear-hint { display: none; }
  .titleblock { grid-template-columns: 1fr; }
  .tb-cell, .tb-wide { grid-column: span 1; }
  .dim { max-width: 100%; }
  .draft { display: none; } /* smalt: gitter + heltfelt baerer stemningen alene */
}

/* ---------- de smalleste telefoner ----------
   To ting paa arket kan ikke ombryde sig selv: maallinjens tekst (sat i ét
   stykke, saa et maal ikke braekkes midt over) og en mailadresse i en knap
   (ét ubrudt ord i mono). Begge er bredere end spalten paa en lille telefon
   og skoed derfor arket ud af vinduet. De faar hver sin graense — praecis
   der hvor de ikke kan vaere i spalten laengere. */

/* Under 400px er maallinjens laengste tekster (fx "skala 1:1 · dit sted,
   ikke en skabelon" = 315px) bredere end de 250-330px, spalten giver.
   Saa maa teksten bryde i to linjer mellem maerkerne — den skal kunne
   laeses, og maallinjen holder sin form. */
@media (max-width: 400px) {
  .dim-label { white-space: normal; }
}

/* Under 360px er spalten 250-290px, mens knappen med mailadressen maaler
   291px: adressen (213px) plus luft, mellemrum og pil. Adressen kan ikke
   brydes paent over to linjer, saa i stedet faar knappen hele spaltens
   bredde, strammere luft, og den dekorative pil staar af. Adressen er det,
   der skal med — pilen er pynt. Samme greb som booking-siden allerede
   bruger paa sin kontaktknap. */
@media (max-width: 360px) {
  .cta[href^="mailto"] {
    display: flex;
    width: 100%;
    padding: 13px 14px;
  }
  .cta[href^="mailto"] svg { display: none; }
}

/* ============================================================
   Reduceret bevægelse: intet løber. Statisk drev-ramme tegnes
   én gang i JS. Alle indgangsanimationer slås fra.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0s !important;
  }
  /* koreografi-lag der ellers ville efterlade et spor: hold dem skjult */
  .frame-plot { display: none !important; }
  .gear-stage { cursor: default; }
}

/* ============================================================
   Kontur-felt ("bolgerne") — ambient baggrund bag heroen.
   Ligger bag indholdet; drev-panel og tekst staar ovenpaa.
   ============================================================ */
.hero { position: relative; }
.hero-field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: var(--z-base);
  pointer-events: none;
  /* toner op efter heroteksten er sat — sidste led i indgangen */
  animation: ls-fade 1100ms ease 920ms backwards;
}
.hero-copy, .hero-visual { position: relative; z-index: var(--z-overlay); }

/* ---------- inline-positioner flyttet fra markup (CSP: ingen style="") ---------- */
.mk-p1 { top: 20%; left: 5%; --mk-peak: 0.50; animation: mk-c 21s ease -3s infinite both; }
.mk-p2 { top: 42%; left: 4%; --mk-peak: 0.50; animation: mk-c 24s ease -6s infinite both; }
.mk-p3 { bottom: 19%; left: 6.5%; --mk-peak: 0.50; animation: mk-y 23s ease -9s infinite both; }
.mk-p4 { bottom: 11%; left: 31%; --mk-peak: 0.50; animation: mk-x 25s ease -14s infinite both; }
.mk-p5 { bottom: 11%; right: 8%; --mk-peak: 0.55; animation: mk-c 27s ease -19s infinite both; }
