/* ==========================================================================
   GeoBlockr website
   Hand-written CSS. No build step, no framework, no external resources.
   Mobile-first: the default rules are the phone layout. One breakpoint at
   769px widens the hero into two columns for iPad and desktop.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   Every spacing value below is a multiple of 8 (with 4 available for fine
   work) and is named after its own pixel value, so nothing is ever eyeballed.
   -------------------------------------------------------------------------- */

:root {
  /* Palette, carried over from the app */
  --canvas: #0a0a0a;
  --accent: #48e291;
  --accent-bright: #86efb8;
  --accent-deep: #2ca96a;

  /* Text hierarchy is three tiers of grey, not three hues. The accent is
     reserved for the logo and the call to action. All values clear WCAG AA
     against the canvas: 19:1, 7.7:1, 5.7:1 and 4.8:1 respectively. */
  --text-primary: #fafafa;
  --text-secondary: #a1a1a1;
  --text-muted: #8a8a8a;
  --text-faint: #7d7d7d;

  --hairline: rgba(255, 255, 255, 0.08);
  --hairline-soft: rgba(255, 255, 255, 0.06);

  --space-4: 4px;
  --space-8: 8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-24: 24px;
  --space-32: 32px;
  --space-40: 40px;
  --space-48: 48px;
  --space-56: 56px;
  --space-64: 64px;
  --space-80: 80px;
  --space-96: 96px;

  --page-max: 1140px;

  /* SF Pro Rounded, the same face the app uses (design: .rounded in SwiftUI).
     'ui-rounded' is a system generic family, so the font comes from the
     visitor's own device and nothing is downloaded from anyone's servers.
     Safari on macOS and iOS resolves it; Chrome and Firefox do not, and fall
     back to regular San Francisco or Segoe UI, which is a graceful landing. */
  --font: ui-rounded, "SF Pro Rounded", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* --------------------------------------------------------------------------
   2. Reset
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  /* The canvas colour has to live here, not only on body. Without it <html>
     computes to rgba(0,0,0,0), and the overscroll area above the page renders
     pure black rather than #0a0a0a. */
  background-color: var(--canvas);
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;

  font-family: var(--font);
  color: var(--text-primary);
  background-color: var(--canvas);

  /* Light text on a dark ground optically blooms. Antialiasing thins the
     strokes back and keeps it crisp on macOS. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  /* No top glow on phones, deliberately. A glow that runs to y=0 leaves the
     page's first row tinted green while the browser chrome above it stays a
     flat colour, and that boundary is visible. theme-color cannot be a
     gradient, so there is no way to blend the two. Dropping the glow at phone
     widths makes the page's top row plain #0a0a0a, identical to the chrome,
     and the seam simply does not exist. The glow is declared in the 769px
     block instead, where there is no such adjacency problem. */
  background-repeat: no-repeat;
}

/* Match scrollbars and any form controls to the canvas */
:root {
  color-scheme: dark;
}

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

/* --------------------------------------------------------------------------
   3. Layout container
   -------------------------------------------------------------------------- */

.page {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-24);
}

/* --------------------------------------------------------------------------
   4. Header
   Identity, not a headline. Small and quiet on every page.
   -------------------------------------------------------------------------- */

.site-header {
  padding-top: var(--space-32);
}

.brand {
  display: inline-flex;
  align-items: center;
  /* The logo PNG carries ~11% transparent padding on the sides, which adds
     about 5px of optical space of its own, so 8px here lands at ~13px to the
     eye. */
  gap: var(--space-8);
  text-decoration: none;
  color: inherit;
}

.brand img {
  width: 36px;
  height: 36px;
}

/* That 36px box draws a padlock 32px tall, once its transparent padding is
   discounted. 30px type puts the cap height at roughly 21px against it, which
   reads as matched. Type set to a mark's literal full height looks oversized,
   because the eye compares cap height to the mark's mass rather than the two
   bounding boxes. */
.brand span {
  font-size: 1.875rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text-primary);
}

/* --------------------------------------------------------------------------
   5. Hero
   The governing idea: the call to action wins by isolation, not decoration.
   The gap above the badge is the largest in the hero, so the eye lands there.
   -------------------------------------------------------------------------- */

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* Phone rhythm, loosened: the previous 40/24/48/64/64 read as cramped. Now
     56 above the headline, 32 binding headline to subtitle, 64 above the badge
     and 80 below it. The badge keeps more air than anything else, which is what
     makes the eye land on it. */
  gap: var(--space-64); /* Button zu Video, enger zugunsten des Videos */
  padding-top: var(--space-96); /* whole block sits lower on the phone */
  padding-bottom: var(--space-80);

  /* Stay the height of the content and centre with auto margins, rather than
     growing to fill. Growing is what made the page bottom-heavy: with
     align-items: flex-end on desktop, a grown box pins both columns to the
     very bottom of all the leftover space. Auto margins split that space
     evenly above and below instead, and still solve the iPad dead-band the
     grow was originally added for. Shrink 0 so it never squashes. */
  flex: 0 0 auto;
  margin-block: auto;
}

.hero-copy {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero h1 {
  margin: 0;
  /* Ceiling 72 -> 76px. 80px was measured and rejected: at this column width it
     pushes the headline to three lines, which is what threw the proportions off
     last time. */
  font-size: clamp(2.5rem, 5.75vw, 4.75rem);
  /* 450, a half step above regular. The system font is variable on Apple
     platforms, so Safari renders this as a genuine intermediate weight. Where
     ui-rounded is unavailable and a static face is substituted, CSS weight
     matching rounds it down to 400, which is the previous look and a fine
     landing. */
  font-weight: 450;
  line-height: 1.02; /* bigger type, tighter leading still */
  letter-spacing: -0.035em; /* large type at default tracking looks slack */
  color: var(--text-primary);
  text-wrap: balance; /* evens out the line lengths where supported */
}

.hero-subtitle {
  margin: var(--space-48) 0 0; /* groups with the headline, without crowding */
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  line-height: 1.45; /* 28px text at 1.55 leaves the lines floating apart */
  /* Pure white. Hierarchy against the headline rests entirely on size and
     weight (72px/600 against 28px/400), which is ample on its own. */
  color: #ffffff;
  max-width: 44ch; /* never let a subtitle run the full column width */
  /* 'balance' evens the line lengths; 'pretty' only prevents single-word
     orphans and left a 133px stub third line against 552px neighbours, 24% of
     the longest. Balance takes that to 92%. It is also the only fix robust to
     the typeface: column tuning gives two lines here but collapses back to the
     stub as soon as the real font renders a few percent wider, which SF Pro
     Rounded does. */
  text-wrap: balance;
}

/* The accented phrases: the payoff in the headline, the action in the subtitle.
   Scoped under .hero deliberately, so it cannot leak into the monochrome legal
   pages. */
.hero .accent {
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   6. Call to action
   Apple's badge may be scaled proportionally but not recoloured or altered,
   so every effect here applies to the link around it, never to the artwork.
   Apple also requires clear space of at least 10% of the badge height on all
   sides; the margins below are far beyond that.
   -------------------------------------------------------------------------- */

.cta {
  display: inline-block;
  /* 48. Enger als vorher, damit das Demo-Video weiter nach oben rueckt und auf
     dem Handy mehr davon sichtbar ist. Gleichauf mit dem Abstand Titel zu
     Untertitel, darunter sollte es nicht gehen, sonst bindet sich der Button
     enger an den Untertitel als der Untertitel an den Titel. */
  margin-top: var(--space-48);
  align-self: center; /* centred under the subtitle at every width */
  border-radius: 8px;
  transition: transform 160ms ease;
}

.cta img {
  height: 72px;
  width: auto;
}

/* No glow. A small proportional scale is the only hover cue, which Apple
   permits: the badge may be resized proportionally, just not recoloured. */
.cta:hover {
  transform: scale(1.02);
}

/* --------------------------------------------------------------------------
   7. Demo-Video

   Gemessen am ersten Bild der Aufnahme: das Geraet fuellt 76,9% der Breite und
   86,3% der Hoehe, der Rand ringsum ist #0e0e0e statt der gesetzten #0a0a0a.
   Das ist kein Exportfehler, sondern limited range in H.264: aus 10 wird beim
   Dekodieren 14. Der Wrapper schneidet diesen Rand weg, damit verschwindet die
   hellere Flaeche und das Geraet fuellt den Kasten.
   -------------------------------------------------------------------------- */

.hero-shot-frame {
  /* Der Rahmen ist ein <a>. Ohne display: block bliebe er inline und
     aspect-ratio zusammen mit width: 100% griffe nicht zuverlaessig. Die Zeile
     sorgt also dafuer, dass er trotz Linkrolle exakt so aussieht wie zuvor. */
  display: block;
  position: relative;
  width: 100%;
  max-width: 300px; /* Handy; Desktop siehe 769px-Block */
  aspect-ratio: 233 / 466; /* das Geraet selbst, praktisch 1:2 */
  overflow: hidden;
  flex: 0 0 auto;

  /* Das Geraet hat runde Ecken, der Beschnitt war rechteckig. In den vier
     Ecken schaute dadurch die #0e0e0e-Flaeche des Videos durch, oben besonders
     auffaellig gegen den hellsten Teil des Glows.

     Am Standbild gemessen: Eckradius 37px bei 233px Geraetebreite, also 15,9%.
     Die Einzugswerte folgen exakt einem Kreisbogen (bei 10px unter der Kante
     gerechnet 11,7px, gemessen 12px).

     Zwei Werte, weil der Kasten 1:2 steht: 16% der Breite waagerecht und 8%
     der Hoehe senkrecht ergeben denselben Betrag in px, also eine runde statt
     einer ovalen Ecke. Skaliert automatisch mit der Kastenbreite. */
  border-radius: 16% / 8%;
}

/* Gegenprobe: bei Wrapperbreite W ist die Hoehe 2W. Das Video ist dann 1,30W
   breit und 2,31W hoch, das Geraet darin 86,3% davon, also 1,995W. Deckt sich
   mit den 2W des Wrappers, der Rand liegt exakt ausserhalb. */
.hero-shot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 130%; /* 100 / 0,769 schneidet 11,6% je Seite weg */
  height: auto;
  transform: translate(-50%, -50%);
  /* Reine Ansicht: kein Antippen, kein Pausieren, kein Kontextmenue. */
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   8. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  padding-top: var(--space-32);
  /* Clears the home indicator on a notched iPhone, falls back to 48px
     everywhere else. */
  padding-bottom: max(var(--space-48), env(safe-area-inset-bottom));
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-4) var(--space-12);
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-nav li {
  display: flex;
  align-items: center;
  gap: var(--space-12);
}

.footer-nav li:not(:last-child)::after {
  content: "\00B7";
  color: rgba(255, 255, 255, 0.22);
}

.footer-nav a {
  font-size: 0.9375rem; /* 15px, so the footer is not stranded under a big hero */
  line-height: 1.4;
  color: var(--text-muted);
  text-decoration: none;
}

/* Brightens rather than changing hue. Removing the hover state altogether
   would leave links with no response at all, which reads as a broken page. */
.footer-nav a:hover {
  color: var(--text-primary);
}

/* --------------------------------------------------------------------------
   9. Legal pages
   Monochrome by request: white and grey text, no accent anywhere. The green
   padlock in the header stays, because that is the mark rather than styling.
   -------------------------------------------------------------------------- */

body.doc {
  background-image: none; /* drop the green glow behind these pages */
}

body.doc :focus-visible {
  outline-color: var(--text-primary); /* white ring, not the accent */
}

/* The landing page pins its footer via the hero's auto margins. These pages
   have no hero, so they need the footer pinned directly, otherwise a short
   Impressum leaves it floating mid-screen. */
body.doc .site-footer {
  margin-top: auto;
}

/* Nur fuer kurze Seiten wie das Impressum. Zentrierter Flattersatz ist bei
   wenigen Zeilen ruhig, bei langen Absaetzen aber schwer zu lesen, weil das
   Auge jede Zeile neu suchen muss. Die Datenschutzerklaerung bleibt deshalb
   linksbuendig. */
.prose--centered {
  margin-inline: auto;
  text-align: center;
}

.prose--centered address {
  font-size: 1.0625rem;
}

.prose {
  /* Block mittig, Text darin linksbuendig. Zentrierter Flattersatz waere bei
     dieser Laenge schwer lesbar, ein linksbuendiger Block am linken Rand einer
     1140px-Seite aber unruhig. */
  margin-inline: auto;
  max-width: 68ch; /* a comfortable reading measure */
  padding-top: var(--space-56);
  padding-bottom: var(--space-96);
}

.prose h1 {
  /* 40px Abstand nach unten. Vorher 0, dadurch klebte die Ueberschrift am
     folgenden Text, was bei einer grossen H1 besonders auffaellt. */
  margin: 0 0 var(--space-40);
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.prose h2 {
  margin: var(--space-48) 0 var(--space-16);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-primary);
}

.prose p,
.prose li {
  font-size: 1.0625rem;
  line-height: 1.65;
  /* Heller als das bisherige #a1a1a1. Auf dem fast schwarzen Grund wirkte das
     gedaempft; #c9c9c9 liest sich ruhiger, ohne mit den weissen
     Ueberschriften gleichzuziehen. */
  color: #c9c9c9;
  text-wrap: pretty;
}

.prose p {
  margin: 0 0 var(--space-16);
}

.prose ul {
  margin: 0 0 var(--space-16);
  padding-left: var(--space-24);
}

.prose li {
  margin-bottom: var(--space-8);
}

.prose a {
  color: var(--text-primary);
  text-decoration-color: rgba(255, 255, 255, 0.4);
  text-underline-offset: 3px;
}

.prose a:hover {
  text-decoration-color: var(--text-primary);
}

.prose .lede {
  font-size: 1.0625rem;
  color: var(--text-muted);
  margin-top: var(--space-16);
}

/* Ereignisnamen und Hostnamen im Fliesstext. Kein Kasten, nur eine ruhige
   Auszeichnung, damit sie als technische Bezeichner lesbar bleiben. */
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9375em;
  color: var(--text-primary);
}

/* Address block in the Impressum */
.prose address {
  font-style: normal;
  /* 1.45 statt 1.65: eine Anschrift gehoert als Block zusammen, weite
     Zeilenabstaende zerreissen sie. */
  line-height: 1.45;
  color: #c9c9c9;
  margin-bottom: var(--space-16);
}

/* --------------------------------------------------------------------------
   10. Accessibility
   -------------------------------------------------------------------------- */

/* Kein border-radius hier. Diese Regel steht spaeter im Stylesheet als
   .hero-shot-frame und hat dieselbe Spezifitaet, wuerde dessen 16% / 8% beim
   Tastaturfokus also auf 2px ueberschreiben: die runden Ecken sprangen auf
   eckig und die dunklen Video-Ecken blitzten auf. Outlines folgen ohnehin dem
   Radius des jeweiligen Elements. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.cta:focus-visible {
  outline-offset: 6px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }

  .cta:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   11. The one breakpoint
   iPad and desktop. Everything above this line is the phone layout.
   -------------------------------------------------------------------------- */

@media (min-width: 769px) {
  /* The top glow lives here, desktop only. Anchored to the top edge and
     weighted toward the two corners, faint through the middle, matching the
     app's onboarding screens.

     The radials are sized in vw rather than pixels: at a fixed width they
     would overlap and make the centre BRIGHTER than the corners, inverting the
     effect. At 50vw each reaches half the width, leaving a darker band down the
     middle at every desktop size. The height stays a fixed 380px so it does not
     stretch on long pages. The linear wash lights the top centre, where the
     corner radials have already faded out, so the corners read as brighter
     rather than as two separate spotlights.

     body.doc keeps its own background-image: none and still wins here on
     specificity, so the legal pages stay flat at every width. */
  body {
    background-image: radial-gradient(
        50vw 380px at 0% 0%,
        rgba(72, 226, 145, 0.14),
        transparent 70%
      ),
      radial-gradient(
        50vw 380px at 100% 0%,
        rgba(72, 226, 145, 0.14),
        transparent 70%
      ),
      linear-gradient(180deg, rgba(72, 226, 145, 0.1), transparent 320px);
  }

  .page {
    padding-inline: var(--space-48);
  }

  .hero {
    flex-direction: row;
    /* flex-end, so the two columns share a baseline at the bottom. The badge is
       the last child of .hero-copy with no trailing margin, so the column's
       bottom edge is the badge's bottom edge, and it lands level with the
       bottom of the phone mockup. */
    align-items: flex-end;
    justify-content: space-between;
    text-align: left;
    gap: var(--space-64);
    padding-top: var(--space-64);
    padding-bottom: var(--space-80); /* desktop keeps its existing rhythm */
  }


  /* Statt einer festen Breite an die Fensterhoehe gekoppelt. Der Kasten steht
     1:2, die Hoehe ist also der begrenzende Faktor, und eine feste Breite war
     entweder auf kleinen Fenstern zu gross oder auf grossen unnoetig klein.
     260px sind Hero-Polster (144) plus Footer (101) plus etwas Luft. */
  .hero-shot-frame {
    /* Die Breite direkt aus der verfuegbaren Hoehe rechnen, nicht per
       max-height begrenzen: max-height kuerzt nur die Hoehe, die Breite bleibt
       stehen, das Seitenverhaeltnis kippt und das Geraet wird oben und unten
       angeschnitten. Der Kasten steht 1:2, also ist die Breite die halbe
       verfuegbare Hoehe. */
    max-width: min(320px, calc((100vh - 260px) / 2));
  }

  /* Mehr Luft unter dem Titel. Weil die Textspalte unten buendig sitzt,
     schiebt ein groesserer Abstand hier den Titel zugleich nach oben. */
  .hero-subtitle {
    margin-top: var(--space-48);
  }

  /* Kein .cta-Override mehr noetig: die Basis steht jetzt selbst auf 48. */

  /* The logo, headline, subtitle and badge all sit on one shared left edge.
     That single constraint does most of the work of looking tidy. */
  /* 520px, not 620: the headline and subtitle both wrap well short of a 620px
     box, so the box centre sat 43px right of where the text visually ends and
     the centred badge looked adrift. At 520 the box centre and the inked centre
     agree to within 6px. Tuned to the current copy, so re-measure if the
     subtitle changes length substantially. */
  .hero-copy {
    align-items: flex-start;
    max-width: 560px;
    /* Hebt die Textspalte als Ganzes an. Sie sitzt unten buendig am Video, ein
       Aussenabstand unten schiebt also Titel, Untertitel und Button gemeinsam
       nach oben. Damit steht der Button bewusst nicht mehr exakt auf der
       Unterkante des Videos. */
    margin-bottom: var(--space-48);
  }

  .cta img {
    height: 78px; /* 1.5x the previous 52px */
  }

  .prose {
    padding-top: var(--space-64);
  }
}
