/* Rikuna — Dala design variant (kb/design/templates/Dala)
   Void black canvas, Inter substitute for PPNeueMontreal.
   Hierarchy through scale + negative tracking, never weight.
   No cards, no borders, no shadows — whitespace only.

   Deviation from the Dala reference, deliberate: the single saturated
   accent is Rikuna's green, not Dala's violet — same role, same
   exclusivity (filled buttons and the brand mark only). Khipu did the
   same with its blue. Amber (#ffb829) stays as the second chromatic
   voice for labels and emphasis. */

:root {
  --color-void: #000000;
  --color-bone-white: #ffffff;
  --color-ash-gray: #9a9a9a;
  --color-silver-mist: #bdbdbd;
  --color-rikuna-green: #4FAE3C;
  --color-green-bright: #7BC443;
  --color-saffron-spark: #ffb829;
  --color-deep-verdant: #15846e;

  /* Rollen, die das helle Thema umkehrt. Die Namen oben bleiben, was sie
     immer waren -- void ist der Grund, bone-white die starke Schrift --
     und tragen im Hellen nur andere Werte. */
  --color-on-accent: #06140a;
  --color-scrim: rgba(0,0,0,0.85);
  --color-scrim-fade: rgba(0,0,0,0);
  --color-scrim-panel: rgba(0,0,0,0.97);
  --color-select-bg: #0a0a0a;
  /* Das Knotenfeld ist im Dunkeln das Motiv. Im Hellen bleibt es ein
     zarter Hintergrund: Physio-Besucher kommen von einer ruhigen Seite. */
  --field-opacity: 1;

  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --text-caption: 12px;
  --text-nav-label: 14px;
  --text-body: 18px;
  --text-lead: clamp(19px, 1.5vw, 22px);
  --text-heading-2xs: 24px;
  --text-heading-xs: 27px;
  /* floors are sized for a 360px viewport, not for the desktop cap */
  --text-heading-sm: clamp(25px, 3.4vw, 42px);
  --text-heading: clamp(27px, 3.9vw, 48px);
  --text-heading-lg: clamp(32px, 6.2vw, 68px);
  /* Der Deckel hält die erste Zeile der Hero-Überschrift einzeilig, in jeder
     angebotenen Sprache. Gemessen über en/de/es bei 900 bis 2560: mit 68px
     brachen "Your whole digital presence," und "Toda tu presencia digital,"
     ab 1440 um, mit 54px bleibt an der engsten Stelle 7% Luft. Der vw-Faktor
     ging mit herunter, sonst würde der Deckel erst so spät greifen, dass die
     mittleren Breiten wieder zu eng werden. */
  --text-display: clamp(32px, 4.0vw, 54px);

  --page-max-width: 1280px;
  --pad-x: clamp(20px, 4vw, 48px);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* ---------- helles Thema ----------
   Der Browser entscheidet, der Schalter in der Nav überschreibt. Beide
   Blöcke tragen dieselben Werte: reines CSS kann eine Wertegruppe nicht
   benennen, und ein gemeinsamer Selektor wuerde die Media-Query mit in
   den Schalterfall ziehen. Wer hier etwas ändert, ändert es zweimal. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --color-void: #fbfbfb;
    --color-bone-white: #101214;
    --color-ash-gray: #6c7276;
    --color-silver-mist: #3f4448;
    --color-rikuna-green: #3c8f2c;
    --color-green-bright: #2f7d22;
    --color-saffron-spark: #a86f08;
    --color-on-accent: #ffffff;
    --color-scrim: rgba(251,251,251,0.92);
    --color-scrim-fade: rgba(251,251,251,0);
    --color-scrim-panel: rgba(251,251,251,0.98);
    --color-select-bg: #ffffff;
    --field-opacity: 0.2;
  }
}
:root[data-theme="light"] {
  --color-void: #fbfbfb;
  --color-bone-white: #101214;
  --color-ash-gray: #6c7276;
  --color-silver-mist: #3f4448;
  --color-rikuna-green: #3c8f2c;
  --color-green-bright: #2f7d22;
  --color-saffron-spark: #a86f08;
  --color-on-accent: #ffffff;
  --color-scrim: rgba(251,251,251,0.92);
  --color-scrim-fade: rgba(251,251,251,0);
  --color-scrim-panel: rgba(251,251,251,0.98);
  --color-select-bg: #ffffff;
  --field-opacity: 0.2;
}

#field { opacity: var(--field-opacity); }


/* overflow-x on <body> alone does not hold on iOS — the viewport still
   rubber-bands sideways. clip is preferred over hidden because it does not
   turn the element into a scroll container. */
html { overflow-x: hidden; scroll-behavior: smooth; }
@supports (overflow: clip) { html { overflow-x: clip; } }

body {
  background: var(--color-void);
  color: var(--color-bone-white);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  font-weight: 200;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
@supports (overflow: clip) { body { overflow-x: clip; } }

::selection { background: var(--color-rikuna-green); color: var(--color-on-accent); }

a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
em { font-style: normal; color: var(--color-rikuna-green); }

.wrap {
  max-width: var(--page-max-width);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

/* ---------- type ---------- */

h1, h2, h3 { font-weight: 400; }

.t-display  { font-size: var(--text-display);    line-height: 1.02; letter-spacing: -0.04em; }
.t-lg       { font-size: var(--text-heading-lg); line-height: 1.06; letter-spacing: -0.04em; }
.t-heading  { font-size: var(--text-heading);    line-height: 1.1;  letter-spacing: -0.035em; }
.t-sm       { font-size: var(--text-heading-sm); line-height: 1.15; letter-spacing: -0.03em; }
.t-xs       { font-size: var(--text-heading-xs); line-height: 1.2;  letter-spacing: -0.015em; }

.label {
  display: block;
  font-size: var(--text-nav-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-saffron-spark);
}

/* Where the lines fall is not left to the viewport. Measured across EN, DE and
   ES at seven widths, the body blocks dropped two or three words onto a line of
   their own under a full paragraph, 151 times.

   Every one of these is a short block of three to five lines, so they all get
   `balance`: the lines come out the same length and there is no tail. `pretty`
   was tried first on the copy inside the areas and only removed 65 of the 151,
   because it does no more than pull a word down when the last line would be an
   orphan. Falls back to today's behaviour where the property is unsupported,
   so nothing gets worse anywhere. */
.hero .body-copy,
.section-head .body-copy,
.cta p,
.value-item p,
.area p,
.svc-item p { text-wrap: balance; }

/* The bullets are one line each at most widths; pretty is enough and cheaper. */
.area li { text-wrap: pretty; }

.body-copy { color: var(--color-silver-mist); font-weight: 200; max-width: 52ch; }
.body-copy strong { color: var(--color-bone-white); font-weight: 400; }

/* The lead under a heading is a sub-headline, not running text: it carries
   the claim the heading only names, and at silver-mist it read as a caption
   the eye skips (Owner S2184, "nicht deutlich genug"). It gets the strong
   text colour and a step up in size. Not a step up in weight -- the rule at
   the top of this file is that hierarchy here is scale and colour, never
   weight -- and not in the four short blocks inside value, areas and
   service, which are running text and stay silver. */
.hero .body-copy,
.section-head .body-copy,
.cta .body-copy { color: var(--color-bone-white); font-size: var(--text-lead); }

/* ---------- buttons ---------- */

.btn-pill {
  display: inline-block;
  background: var(--color-rikuna-green);
  color: var(--color-on-accent);
  font-size: var(--text-nav-label);
  font-weight: 600;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  padding: 14px 24px;
  border-radius: 24px;
  border: 0;
  cursor: pointer;
  transition: transform 0.35s var(--ease), background 0.35s;
}
.btn-pill:hover { transform: translateY(-2px); background: var(--color-green-bright); }

.btn-ghost {
  display: inline-block;
  color: var(--color-ash-gray);
  font-size: var(--text-nav-label);
  font-weight: 600;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  padding: 14px 6px;
  transition: color 0.3s;
}
.btn-ghost:hover { color: var(--color-bone-white); }
.btn-ghost .arrow { color: var(--color-saffron-spark); margin-left: 6px; }

/* ---------- canvas ---------- */

#field {
  position: fixed;
  inset: 0;
  /* A canvas is a replaced element: without an explicit size it takes its
     intrinsic width/height attributes (W * dpr) and ignores inset. */
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

main { position: relative; z-index: 1; }

/* ---------- nav ---------- */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  transition: background 0.4s;
}
.nav.scrolled { background: linear-gradient(var(--color-scrim), var(--color-scrim-fade)); }
.nav-inner {
  max-width: var(--page-max-width);
  margin: 0 auto;
  padding: 22px var(--pad-x);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
/* Reine Wortmarke in der Seitenschrift. Die R-Bildmarke aus 5096684 ist
   am 2026-09-03 (Owner S1781) zurückgenommen worden: sie war nie
   freigegeben und stand nicht in der Schrift der Seite.

   Das R trägt den Akzent, wie der Kopf dieser Datei ihn vergibt: gefüllte
   Knöpfe und die Marke, sonst nichts. In Nav-Größe war die Wortmarke von
   den Menülabels daneben nicht zu unterscheiden, deshalb steht sie eine
   Stufe über ihnen. Im Footer bleibt die Größe, dort steht sie allein. */
.logo { position: relative; z-index: 2; display: flex; align-items: baseline; font-size: 23px; font-weight: 400; letter-spacing: -0.01em; }
/* The glass R stands in as the first letter of "ikuna": cap height, sitting on the baseline. */
.r-glyph { height: .94em; width: auto; position: relative; top: .11em; margin-right: .02em; }
.logo b, .foot-brand b { color: var(--color-rikuna-green); font-weight: 400; }
.nav-links { display: flex; align-items: center; gap: clamp(14px, 2.4vw, 30px); }
.nav-links a:not(.btn-pill) {
  font-size: var(--text-nav-label);
  font-weight: 600;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  color: var(--color-ash-gray);
  transition: color 0.3s;
}
.nav-links a:not(.btn-pill):hover { color: var(--color-bone-white); }

.lang-select {
  background: transparent;
  border: 0;
  color: var(--color-ash-gray);
  font-family: inherit;
  font-size: var(--text-nav-label);
  font-weight: 600;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 6px 2px;
  transition: color 0.3s;
}
.lang-select:hover { color: var(--color-bone-white); }

/* Kein Rahmen wie in website/index.html: der Kopf dieser Datei verbietet
   Karten, Rahmen und Schatten. Bleibt das blanke Icon, das wie die
   Nav-Labels von Ash nach Bone aufhellt. */
.theme-toggle {
  background: transparent;
  border: 0;
  color: var(--color-ash-gray);
  cursor: pointer;
  padding: 6px 2px;
  display: flex;
  align-items: center;
  transition: color 0.3s;
}
.theme-toggle:hover { color: var(--color-bone-white); }
.theme-icon { display: block; width: 18px; height: 18px; }
.lang-select option { background: var(--color-select-bg); color: var(--color-bone-white); }

/* burger: hidden until the links collapse into the panel */
.nav-toggle {
  display: none;
  position: relative;
  z-index: 2;
  width: 44px;
  height: 44px;
  margin: -11px -12px -11px 0;
  align-items: center;
  justify-content: flex-end;
  background: none;
  border: 0;
  padding: 0;
  color: var(--color-bone-white);
  cursor: pointer;
}
.nav-toggle i, .nav-toggle i::before, .nav-toggle i::after {
  display: block;
  width: 22px;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.35s var(--ease), background 0.15s;
}
.nav-toggle i { position: relative; }
.nav-toggle i::before, .nav-toggle i::after { content: ""; position: absolute; left: 0; }
.nav-toggle i::before { top: -7px; }
.nav-toggle i::after { top: 7px; }
.nav.open .nav-toggle i { background: transparent; }
.nav.open .nav-toggle i::before { transform: translateY(7px) rotate(45deg); }
.nav.open .nav-toggle i::after { transform: translateY(-7px) rotate(-45deg); }

body.nav-open { overflow: hidden; }

/* ---------- hero ---------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-top: 120px;
  padding-bottom: 80px;
}
.hero-copy { max-width: min(900px, 70vw); }
.hero .label { margin-bottom: 24px; }
.hero h1 { margin-bottom: 30px; }
.hero .body-copy { max-width: 46ch; margin-bottom: 36px; }
.hero-ctas { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

/* the four proof points, set as a quiet type row under the CTAs */
.hero-points {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin-top: 40px;
  font-size: 15px;
  color: var(--color-ash-gray);
}
.hero-points span { display: inline-flex; align-items: center; gap: 9px; }
.hero-points span::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--color-rikuna-green);
  flex: none;
}

/* ---------- hero figure: the dashboard itself ----------

   The one place on this page that carries a frame and a fill. The Dala rule
   at the top of this file ("no cards, no borders, no shadows") is about
   chrome around content; this is not chrome, it is the picture of the
   product, and a window without an edge is not a window. It stays hairline
   and unlit: one 1px border, a 3.5% fill, no shadow anywhere.

   The tints are color-mix over the existing tokens rather than literal rgba,
   so the figure follows the light theme on its own. Both theme blocks above
   carry the same values by hand and the comment there warns that a change has
   to be made twice; mixing off --color-bone-white keeps this section out of
   that duplication for good.

   Sizes are em against .shell-stage's own font-size, so the whole figure
   scales with its column instead of needing a breakpoint per part. */

.shell { position: relative; z-index: 2; }
/* Until shell.js has built its timeline the figure keeps its place but is not
   painted: the scripts sit at the end of the body, and without this the
   finished photograph showed first and then vanished into the intro. The
   class comes from the head script and leaves in shell.js. */
.shell-pending .shell { visibility: hidden; }

/* The stage is the photograph and nothing else; its height comes from the
   picture's own proportion. */
.shell-stage {
  position: relative;
  padding: 0.95em;
  font-size: clamp(10px, 1.05vw, 12.5px);
  font-weight: 400;
  letter-spacing: -0.01em;
}

.shell-plate {
  position: absolute;
  inset: 0;
  border: 1px solid color-mix(in oklab, var(--color-bone-white) 13%, transparent);
  border-radius: 0.95em;
  /* Opaque, mixed over the page ground rather than laid on it with alpha:
     the node field behind is position: fixed and would otherwise draw its
     lines straight through the window like scratches on the glass. */
  background: color-mix(in oklab, var(--color-bone-white) 3.5%, var(--color-void));
}

/* The pane holds a photograph of the whole dashboard window, shown entire
   rather than cropped: the claim the hero makes is "one window instead of
   five tools", and a crop of one pane cannot make it. The picture keeps its
   own proportion and the stage takes its height from it. */
.shell-pane { position: relative; border-radius: 0.5em; }

/* The intro's six pieces of that same photograph (shell.js). They exist only
   while they fly and lie exactly over the picture, so removing them moves
   nothing. */
.shell-pieces { position: absolute; inset: 0; pointer-events: none; }
.shell-piece { position: absolute; background-repeat: no-repeat; }

.shell-shot {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid color-mix(in oklab, var(--color-bone-white) 8%, transparent);
  border-radius: 0.5em;
}

/* The figure gets its own column beside the copy. Below the breakpoint it
   goes under the copy instead, which is the band the hero already frees by
   going to the top of the screen (see the max-width: 900px block). */
@media (min-width: 901px) {
  .hero-inner {
    display: grid;
    /* The figure holds a whole dashboard window now, not a crop of one pane,
       so it is wider than the clamp(288px, 29vw, 424px) it had while it held
       a crop: measured across de/en/es, 424px put the sidebar and the three
       stat tiles into 392 pixels and the picture read as a grey mosaic.

       A share of the row, not of the viewport, and that is the repair of a
       real defect rather than a preference. The page stops growing at
       --page-max-width, the viewport does not, so a vw column kept taking
       room after the row had none left to give: the copy column got
       *narrower* the wider the window went (705px at 1280, 626px at 1728),
       and the headline broke into two lines only on large screens. The gap
       was doing the same thing and is capped lower for the same reason. */
    grid-template-columns: minmax(0, 1fr) clamp(340px, 43%, 560px);
    align-items: center;
    gap: clamp(28px, 3.4vw, 44px);
  }
}

.scroll-hint {
  position: absolute;
  bottom: 30px;
  left: var(--pad-x);
  z-index: 2;
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-ash-gray);
  display: flex;
  align-items: center;
  gap: 10px;
}
.scroll-hint::after {
  content: "";
  width: 48px; height: 1px;
  background: var(--color-ash-gray);
  display: block;
  animation: hintPulse 2.4s ease-in-out infinite;
  transform-origin: left;
}
@keyframes hintPulse { 0%,100% { transform: scaleX(0.3); opacity: 0.4; } 50% { transform: scaleX(1); opacity: 1; } }

/* ---------- sections ---------- */

section { position: relative; padding: clamp(80px, 10vw, 150px) 0; }

.section-head { max-width: 820px; margin-bottom: clamp(48px, 6vw, 90px); }
.section-head .label { margin-bottom: 20px; }
.section-head .body-copy { margin-top: 24px; }

/* value — four statements, no boxes */
.value-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(44px, 5vw, 76px);
  max-width: 1000px;
}
.value-item h3 { font-size: var(--text-heading-2xs); letter-spacing: -0.02em; margin-bottom: 12px; }
.value-item p { color: var(--color-silver-mist); }

/* the six areas — numbered typographic list, the figure sits right */
.areas { display: grid; gap: clamp(52px, 6vw, 84px); }
.area { display: grid; grid-template-columns: 62px 1fr; gap: 26px; align-items: baseline; }
.area .num {
  font-size: var(--text-heading-xs);
  font-weight: 200;
  color: transparent;
  -webkit-text-stroke: 1px rgba(79, 174, 60, 0.75);
  text-shadow: 0 0 22px rgba(79, 174, 60, 0.35);
}
.area h3 { font-size: var(--text-heading-2xs); letter-spacing: -0.02em; margin-bottom: 12px; }
.area p { color: var(--color-silver-mist); max-width: 46ch; }
.area ul { margin-top: 18px; display: grid; gap: 9px; }
.area li {
  font-size: 15px;
  color: var(--color-ash-gray);
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 10px;
}
/* a drawn rule, not a dash character: an em dash set at list-item size
   reads as a stray line of body text rather than as a bullet. */
.area li::before {
  content: "";
  align-self: start;
  justify-self: start;
  width: 9px;
  height: 1px;
  margin-top: 12px;
  background: var(--color-rikuna-green);
}

/* The picture of the area. In the resting state it sits under the copy it
   belongs to, in the same column, so the list reads as six areas with six
   screens and needs no script to be right. */
.area-shot {
  grid-column: 2;
  margin-top: 26px;
  max-width: 760px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid color-mix(in oklab, var(--color-bone-white) 11%, transparent);
  background: color-mix(in oklab, var(--color-bone-white) 3%, var(--color-void));
}
.area-shot img { display: block; width: 100%; height: auto; }

/* ---------- the camera flight ----------

   static/camera.js sets `is-cam` on #what once it has WebGL and the visitor
   has not asked for less motion, and only then does any of this apply. The
   six screens become a row in a 3D scene behind the copy, and the head, the
   six areas and the closing line become stations of a camera: each one a
   screen high, so the camera rests while its text is read. Everything that
   hides a picture or changes the layout lives behind this class, so the
   resting state above cannot be hidden by a rule that did not run. */
.cam-stage, .cam-outro { display: none; }
#what.is-cam { padding-top: 0; padding-bottom: 0; }
#what.is-cam .cam-stage {
  display: block;
  position: sticky;
  top: 0;
  height: 100svh;
  margin-bottom: -100svh;
  pointer-events: none;
}
.cam-stage canvas { display: block; width: 100%; height: 100%; }
#what.is-cam .wrap { position: relative; z-index: 1; }
#what.is-cam .areas { display: block; }
#what.is-cam .area-shot { display: none; }
#what.is-cam .cam-intro,
#what.is-cam .area,
#what.is-cam .cam-outro { min-height: 100svh; }
/* the two ends show the whole row, under the copy rather than beside it */
#what.is-cam .cam-intro { margin-bottom: 0; padding-top: 16svh; }
#what.is-cam .cam-outro { display: block; padding-top: 16svh; }
#what.is-cam .area { align-content: center; }
#what.is-cam .area > div { max-width: min(440px, 34vw); }
/* the copy reads over a lit scene here, not over the plain ground: full
   strength, and a shadow in the ground colour that keeps it off the screens */
#what.is-cam .area h3,
#what.is-cam .area p,
#what.is-cam .area li {
  color: var(--color-bone-white);
  text-shadow: 0 0 14px var(--color-void), 0 0 4px var(--color-void);
}
#what.is-cam .area li { font-size: 16px; }
#what.is-cam .area .num { -webkit-text-stroke: 1px var(--color-rikuna-green); }

/* On a phone the scene sits in the upper part of the screen and the copy
   goes to the bottom, on a plate of its own so the screens never run
   through the text. */
@media (max-width: 900px) {
  #what.is-cam .area { align-content: end; padding-bottom: 6svh; }
  #what.is-cam .area > div {
    max-width: none;
    padding: 14px 16px;
    border-radius: 12px;
    background: color-mix(in oklab, var(--color-void) 84%, transparent);
    backdrop-filter: blur(6px);
  }
}

/* service — four columns of plain type */
.svc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(40px, 4.5vw, 64px);
}
.svc-item h3 { font-size: var(--text-heading-2xs); letter-spacing: -0.02em; margin-bottom: 12px; }
.svc-item p { color: var(--color-silver-mist); font-size: 16px; }

/* final cta */
.cta { text-align: center; padding-bottom: clamp(96px, 12vw, 170px); }
.cta h2 { margin: 0 auto 24px; max-width: 14ch; }
.cta .body-copy { margin: 0 auto 40px; max-width: 46ch; }
.cta-ctas { display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap; }

/* footer */
footer {
  position: relative;
  z-index: 1;
  padding: 60px 0 70px;
  font-size: var(--text-nav-label);
  color: var(--color-ash-gray);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: clamp(32px, 4vw, 60px);
}
.foot-brand { display: flex; align-items: baseline; font-size: 17px; color: var(--color-bone-white); margin-bottom: 14px; }
.footer-tagline { color: var(--color-ash-gray); }
.footer-copy { margin-top: 10px; color: #6d6d6d; font-size: var(--text-caption); }
.footer-col-label {
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-silver-mist);
  margin-bottom: 16px;
}
.footer-col-links { display: grid; gap: 10px; }
.footer-col-links a { color: var(--color-ash-gray); transition: color 0.3s; }
.footer-col-links a:hover { color: var(--color-saffron-spark); }

/* ---------- reveals ---------- */

.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
  transition-delay: var(--d, 0s);
}
.reveal.in { opacity: 1; transform: none; }

/* the hero rises on load, in step with the aperture assembling behind it */
.rise > * { opacity: 0; transform: translateY(24px); animation: rise 1s var(--ease) forwards; }
.rise > *:nth-child(1) { animation-delay: 0.15s; }
.rise > *:nth-child(2) { animation-delay: 0.28s; }
.rise > *:nth-child(3) { animation-delay: 0.41s; }
.rise > *:nth-child(4) { animation-delay: 0.54s; }
.rise > *:nth-child(5) { animation-delay: 0.67s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* ---------- responsive ---------- */

/* A 1280x720 laptop is wide enough for the desktop type scale but not tall
   enough for it: the display plus the lead pushed the CTA under the fold.
   Trim the scale against the height, not the width. */
@media (min-width: 901px) and (max-height: 820px) {
  :root { --text-display: clamp(32px, 3.6vw, 48px); }
  .hero-inner { padding-top: 96px; padding-bottom: 56px; }
  .hero .label { margin-bottom: 18px; }
  .hero h1 { margin-bottom: 22px; }
  .hero .body-copy { margin-bottom: 28px; }
  .hero-points { margin-top: 28px; }
}

@media (max-width: 900px) {
  .nav-toggle { display: flex; }
  /* full-screen panel instead of dropping the links entirely */
  .nav-menu {
    position: fixed;
    inset: 0;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 2px;
    background: var(--color-scrim-panel);
    padding: 0 var(--pad-x);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-14px);
    transition: opacity 0.35s ease, transform 0.35s var(--ease), visibility 0.35s;
  }
  .nav.open .nav-menu { opacity: 1; visibility: visible; transform: none; }
  .nav-menu a:not(.btn-pill) {
    display: block;
    font-size: var(--text-heading-sm);
    font-weight: 400;
    letter-spacing: -0.03em;
    text-transform: none;
    color: var(--color-bone-white);
    padding: 12px 0;
  }
  .nav-menu .btn-pill { margin-top: 26px; }
  .nav-menu .lang-select { font-size: 16px; margin-top: 20px; }
  /* In der Leiste steht das Icon zwischen Labels und darf klein sein. Im
     Panel steht es allein und braucht dieselbe Tap-Flaeche wie die Links
     darueber. */
  .nav-menu .theme-toggle { margin-top: 12px; padding: 10px 0; }
  .nav-menu .theme-icon { width: 24px; height: 24px; }

  .hero-copy { max-width: 100%; }
  /* Mobile runs one figure, the hero's, and it stands under the copy
     (dala.js). The room for it comes from here: the hero stops centring
     itself in the viewport and goes to the top instead. */
  .hero { align-items: flex-start; }
  .hero-inner { padding-top: 88px; padding-bottom: 44px; }
  .shell { margin-top: 38px; max-width: 420px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  .nav-inner { padding: 16px var(--pad-x); gap: 14px; }
  /* 26px of glyph is not a tap target; grow it without growing the bar */
  .logo { padding: 9px 0; margin: -9px 0; }
  .hero-inner { padding-top: 76px; padding-bottom: 36px; }
  .hero .label { margin-bottom: 18px; }
  .hero h1 { margin-bottom: 22px; }
  .hero .body-copy { margin-bottom: 28px; }
  .hero-ctas { gap: 10px; }
  .btn-ghost { padding-left: 0; padding-right: 0; }
  /* would sit under the mobile browser chrome, and the space is needed */
  .scroll-hint { display: none; }

  .area { grid-template-columns: 40px 1fr; gap: 14px; }
  /* minmax floors above exceed the content box at 360px and force overflow */
  .value-grid, .svc-grid { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; gap: 34px; }
  .cta h2 { max-width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .scroll-hint::after { animation: none; }
  .rise > * { opacity: 1; transform: none; animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
}
