/* Gaia Mesiah — static rebuild
   Increment 1: header / navigation.

   Tokens are the original's own :root custom properties, copied verbatim
   (see ../../DECISIONS.md). Only the ones the built sections use are
   listed; more are added as later sections are rebuilt.

   Values throughout this file come from the reference stylesheet
   (reference/assets/css/gaiamesiah-com.webflow.shared.b6d9408cd__6e003816.css)
   and, for the interactions, from the IX2 config extracted out of
   reference/assets/js/webflow.schunk.b11d4bded480e981__7dfff0f3.js.
   Both are documented in ../../DECISIONS.md. */

:root {
  --black: black;
  --white: white;
  --paragraph: #ffffffe6;
  --main-red: #be1522;
  --grey: #0e0e0e;
  --light-grey: #262626;
  --borders: #fff3;

  --heading-font: "Montserrat", sans-serif;
  --accent-font: "Barlow Condensed", sans-serif;

  /* Webflow's `outQuart`, used by every IX2 reveal preset on this site. */
  --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
}

/* The four social glyphs are Font Awesome 4 private-use codepoints set as
   literal text content in the markup — that is how the original does it. */
@font-face {
  font-family: "Fontawesome webfont";
  src: url("../fonts/fontawesome-webfont.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

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

/* `color: #333` is the original's, verbatim — dark grey on a black ground,
   which is only survivable because every text element on the site sets its
   own colour. Reproduced rather than "corrected": nothing built so far
   inherits it, and changing it would be a silent improvement. */
body {
  margin: 0;
  background-color: var(--black);
  color: #333;
  font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
  font-size: 14px;
  line-height: 20px;
}

/* The original's base img rule, matched exactly. `vertical-align: middle` is
   the load-bearing part: without it an inline-block image sits on the text
   baseline and its line box picks up ~5px of descender space, which showed
   up as the section heading measuring 207px instead of 202px. */
img {
  vertical-align: middle;
  max-width: 100%;
  display: inline-block;
}

/* The original's global base rules for links and paragraphs. Porting them is
   not cosmetic: the social icons take their 26px line box from here (which is
   the whole 96px-vs-90px difference in the drawer's social block), and every
   body paragraph on the site is 15px/26px. */
a {
  color: var(--paragraph);
  font-family: var(--heading-font);
  font-size: 15px;
  line-height: 26px;
  text-decoration: none;
}

/* `margin-top: 0` comes from the original's Webflow normalize layer, which is
   a *separate* `p` rule from the styled one. Porting only the styled rule
   left the UA default `margin-top: 1em` in place — 15px at this font size,
   which is exactly how much too tall the upcoming-concerts heading was. */
p {
  margin-top: 0;
  margin-bottom: 10px;
  color: var(--paragraph);
  font-family: var(--heading-font);
  font-size: 15px;
  line-height: 26px;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Absolute `bold`, matching the original's `b, strong { font-weight: bold }`.
   The browser default is `bolder`, which is relative — inside an h2 at
   weight 800 that would compute to 900. Measured on the original: the
   concert headings' <strong> computes to 700, so they render *lighter* than
   the gallery heading, which has no <strong> and stays at 800. */
b,
strong {
  font-weight: bold;
}

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

/* .navbar-main declares background-color: var(--grey), and IX2 action a-19
   ("Red Nawbar Scroll Animation", PAGE_SCROLL) overrides it to rgba(0,0,0,0)
   at keyframe 0, rgb(14,14,14) from keyframe 1 on. Despite the name, nothing
   in a-19 is red.

   On *this* page a-19 is bound with `mediaQueries: ["main"]` — so it only
   applies at >=992px, and below that the CSS colour stands and the bar is a
   solid --grey block. The EN home page binds the same action at every
   breakpoint, so its bar is transparent on mobile too. Confirmed by
   measurement: CZ is rgb(14,14,14) at 991px and 767px and rgba(0,0,0,0) at
   1440px; EN is rgba(0,0,0,0) at all three. See DECISIONS.md — the two
   locales genuinely differ here. */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100px;
  /* The stylesheet's own colour. Solid is the default because a-19 is bound
     on the two home pages only — measured: the navbar is rgb(14,14,14) at
     every width on /kontakt and /en/contact-us, desktop included. */
  background-color: var(--grey);
  box-shadow: 0 0 20px 1px #ffffff0d;
  transition: background-color 0.5s ease-in-out;
}

/* Home pages: a-19 overrides the colour to transparent at the very top of
   the page. `.is-scrolled` is the unverified half of that (see the
   navbar-scroll entry in DECISIONS.md) — the transparent-at-top state is
   measured and certain. */
.navbar--fade {
  background-color: transparent;
}

.navbar--fade.is-scrolled {
  background-color: var(--grey);
}

.navbar-inner {
  position: relative;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  max-width: 1720px;
  height: 100px;
  padding: 0 15px;
}

.brand {
  flex: none;
  display: flex;
}

.brand img {
  width: 70px;
}

/* Zero-width flex item, present only between 992px and 1279px — see the
   comment on it in index.html. */
.nav-spacer {
  display: none;
}

@media (min-width: 992px) and (max-width: 1279px) {
  .nav-spacer {
    display: block;
    width: 0;
  }
}

/* ---------- Burger ---------- */

/* The 24x14 burger bitmap is kept from the original rather than redrawn in
   CSS: it is 106 bytes, and its middle bar is deliberately offset, so the
   image is both smaller and more faithful than an equivalent rule set. */
/* Measured live at <=991px, the original's .menu-button-wrapper tap target
   is 42x56 with the bitmap flush to its right edge. */
.nav-toggle {
  display: none;
  justify-content: flex-end;
  align-items: center;
  width: 42px;
  height: 56px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

/* ---------- Nav ---------- */

/* Layout model, and why it is this one.

   In the original, the link block and the social block are *siblings* inside
   .navbar-wrapper, which is a `space-between` row. So the free space is split
   into equal gaps between brand / (tablet spacer) / links / social, and that
   is what fixes every element's x position.

   Wrapping both lists in a `flex: 1` <nav> instead does not reproduce it: the
   flex:1 child absorbs all the free space, `space-between` gets nothing to
   distribute, and the run drifts by up to 22px across the 992-1279px band.
   Measured, not assumed.

   So at >=992px .site-nav is `display: contents` — the <nav> stops generating
   a box and its two lists become direct flex items of .navbar-inner, giving
   the original's exact four-item distribution. Below 992px the <nav> becomes
   a real box again: the drawer. This keeps one social list in the markup
   (the original ships two, one of them a placeholder — see DECISIONS.md)
   and needs no layout JS.

   `display: contents` elements stay in the accessibility tree in all current
   engines, so the <nav> landmark and its aria-label are preserved. */
.site-nav {
  display: contents;
}

.nav-list {
  display: flex;
  align-items: center;
}

.social-list--nav {
  flex: none;
}

/* The original carries the horizontal padding and margin on the wrapper
   (.link-header), not on the link itself (.menu-link has `padding: 10px 0`),
   and the very first link sits in a .header-links-wrapper that adds another
   20px on the left. Keeping that split is what makes the run land on the
   same x positions as the original; folding the padding into the link
   instead shifts the whole run 17px left. */
.nav-item {
  display: flex;
  flex-direction: column;
  padding: 0 15px;
  transition: opacity 0.5s;
}

/* The original nests two wrappers around the first link only:
   .header-links-wrapper (padding-left 20) inside .link-header
   (padding-left 15) — 35px in total. At >=1280px .link-header's own
   horizontal padding drops to 5px, so the total becomes 25px. */
.nav-item:first-child {
  padding-left: 35px;
}

.nav-link,
.lang-toggle {
  display: flex;
  flex-direction: column;
  padding: 10px 0;
  border: 0;
  background: none;
  color: var(--white);
  white-space: nowrap;
  font-family: var(--heading-font);
  font-size: 17px;
  font-weight: 800;
  line-height: 20px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

/* IX2 a-15 / a-16: width animates 0% -> 100% over 300ms on hover and back
   over 300ms on mouse-out.

   The underline is a SIBLING of the link inside the row wrapper, which is
   how the original has it (`.button-border` next to `.menu-link` inside
   `.link-header`). Nesting it inside the link instead adds its 2px to the
   link's own height and lifts it toward the text: measured 45px-tall links
   with the rule sitting at y=60.5 against the original's 40px and y=69. */
.nav-underline {
  width: 0;
  height: 2px;
  background-color: var(--main-red);
  transition: width 0.3s;
}

.nav-item:hover .nav-underline,
.nav-item:focus-within .nav-underline {
  width: 100%;
}

@media (min-width: 1280px) {
  .nav-item {
    margin: 0 20px;
    padding: 23px 5px;
  }

  .nav-item:first-child {
    padding-left: 25px;
  }

  .nav-item.lang-switcher {
    margin: 0;
    padding: 0;
  }
}

/* ---------- Language switcher ---------- */

.lang-switcher {
  position: relative;
}

.lang-toggle {
  position: relative;
  flex-direction: row;
  align-items: center;
  margin-right: 10px;
  padding: 30px 20px 30px 15px;
}

.nav-item.lang-switcher {
  padding: 0;
}

/* Mirrors .link-header.dropdown: a column with the same 23px vertical
   padding the other nav rows use, holding the label and the red rule. */
.lang-inner {
  display: flex;
  flex-direction: column;
  padding: 23px 0;
}

.lang-current {
  padding: 10px 0;
  color: var(--white);
  font-size: 17px;
  font-weight: 800;
  line-height: 20px;
  white-space: nowrap;
}

/* The original renders the caret from Webflow's own icon font; a CSS
   triangle is visually equivalent and drops a font dependency.

   It must be absolutely positioned, because the original's is:
   `.w-icon-dropdown-toggle { position: absolute; right: 0; top: 0; bottom: 0 }`,
   with the site's own `.icon { margin-right: 0 }` overriding Webflow's 20px.
   Measured live, the caret glyph is 14x14 and sits flush with the toggle's
   right edge, centred at x=1104.5 of 1440. Letting the caret participate in
   layout instead made the whole link run 7px too wide on each side. */
.lang-caret {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 0;
  height: 0;
  margin: auto 3px auto auto;
  border-top: 5px solid currentcolor;
  border-right: 4px solid transparent;
  border-left: 4px solid transparent;
  transition: color 0.3s;
}

.lang-toggle:hover .lang-caret {
  color: var(--main-red);
}

.lang-list {
  position: absolute;
  top: 90px;
  left: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 180px;
  padding: 15px 20px;
  background-color: var(--grey);
  box-shadow: 0 0 13px 0 var(--grey);
}

.lang-list[hidden] {
  display: none;
}

.lang-list li {
  display: flex;
  align-items: center;
  width: 100%;
}

.lang-link {
  display: flex;
  align-items: center;
  padding: 8px 0;
  color: var(--white);
  font-weight: 600;
  text-decoration: none;
}

/* IX2 a-17 / a-18: width 0 -> 24px over 300ms on hover. */
.lang-marker {
  width: 0;
  height: 2px;
  margin-right: 5px;
  background-color: var(--main-red);
  transition: width 0.3s;
}

.lang-link:hover .lang-marker,
.lang-link:focus-visible .lang-marker {
  width: 24px;
}

/* ---------- Social icons ---------- */

.social-list {
  display: flex;
  justify-content: space-between;
}

/* No line-height of its own — it inherits 26px from the global `a` rule
   above, which is where the original gets it too. */
.social-link {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 10px;
  color: var(--white);
  font-family: "Fontawesome webfont", sans-serif;
  font-size: 18px;
  text-decoration: none;
  transition: color 0.3s;
}

.social-link:hover {
  color: var(--main-red);
}

/* Two blocks, mutually exclusive by breakpoint — matching the original's
   .social-icon-wrapper (desktop, real accounts) and
   .social-icon-wrapper-hidden (drawer, placeholders). */
.social-list--drawer {
  display: none;
}

/* The original scopes this to the shared `.social-icon-wrapper` class, so it
   applies to the footer block as well as the navbar one — which is where the
   footer's 56px height comes from (26px of icons plus 2x15px). Scoping it to
   the nav modifier left the footer block 30px short. */
@media (min-width: 1280px) {
  .social-list {
    justify-content: flex-end;
    padding: 15px 0;
  }
}

/* ---------- Below 992px: burger + left drawer ---------- */

/* 991 <-> 992 is the site's only categorical breakpoint. Webflow's own
   breakpoint map (main >=992 / medium 768-991 / small 480-767 / tiny <=479)
   was read out of the IX2 site config, not inferred. */
@media (max-width: 991px) {
  .navbar,
  .navbar-inner {
    height: 92px;
  }

  /* a-19 is bound with mediaQueries ["main"] on the CZ home page, so below
     992px the stylesheet's colour applies there and the bar is opaque from
     the start. The EN home page binds the same action at every breakpoint,
     which is what `.navbar--fade-mobile` marks. Measured on both. */
  .navbar--fade:not(.navbar--fade-mobile) {
    background-color: var(--grey);
  }

  .nav-toggle {
    display: flex;
  }

  /* Closed by default via `transform`, not `display`/`hidden`, so the slide
     can actually animate. Measured on the live drawer at 479px viewport:
     `.nav-menu-container` opens to 280x844 at x=0 - a left-anchored panel,
     not a full-width dropdown - while sliding in on the Y axis
     (`transform: translateY(-844px)` closed -> `translateY(0)` open) over
     ~400ms with the standard `ease` timing, matching the original's
     `data-duration="400" data-easing="ease"`. `hidden` still gets set, just
     after the close transition finishes (see nav.js), so keyboard/AT users
     can't reach it while it's off-screen. */
  .site-nav {
    display: flex;
    position: absolute;
    /* Starts below the 92px header row, not at its top — .site-nav is a
       child of .navbar-inner (itself only 92px tall), so top:0 here used
       to mean "top of the header", covering .brand with the drawer's own
       opaque background. Confirmed against the live reference: the logo
       stays visible above the open drawer. */
    top: 92px;
    left: 0;
    z-index: 5;
    flex-direction: column;
    align-items: stretch;
    width: 320px;
    height: calc(100vh - 92px);
    background-color: var(--grey);
    overflow-y: auto;
    transform: translateY(-100%);
    transition: transform 0.4s ease;
  }

  .site-nav.is-open {
    transform: translateY(0);
  }

  .site-nav[hidden] {
    display: none;
  }

  .nav-list {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }

  /* Measured on the open live drawer at 479px: .link-header is
     `padding: 0 15px 0 20px` and the link inside it is `padding: 20px 0`,
     245px wide, so each row is 60px plus a 1px bottom border = 61px pitch.
     Putting the 20px on the link instead gives the same text position but a
     full-width link box, which is not the original's box model. */
  .nav-item,
  .nav-item:first-child,
  .nav-item.lang-switcher {
    width: 100%;
    margin: 0;
    padding: 0 15px 0 20px;
    border-bottom: 1px solid var(--light-grey);
  }

  .nav-link,
  .lang-toggle {
    width: 100%;
    margin: 0;
    padding: 20px 0;
    color: #ffffffb3;
  }

  /* a-15 / a-16 do not run below 992px: the original hides .button-border. */
  .nav-underline {
    display: none;
  }

  .lang-switcher {
    position: static;
  }

  .lang-list {
    position: static;
    width: 100%;
    top: auto;
    box-shadow: none;
  }

  /* Below 992px the original hides every plain `.social-icon-wrapper` — the
     navbar's *and* the footer's — leaving only the drawer's placeholder
     block, at the original's measured 50px/20px/20px insets. */
  .social-list {
    display: none;
  }

  .social-list--drawer {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    padding: 50px 0 20px 20px;
  }
}

@media (max-width: 479px) {
  .brand img {
    width: 90px;
  }

  .site-nav {
    width: 280px;
  }
}

/* ---------- Hero (#Home) ---------- */

/* Every number here was measured on the original at 1440 / 1280 / 992 / 900
   / 767 / 500px; the layout model is the original's own:

     .home-banner-section   flex, centred both ways, viewport-relative height
       .container           flex column, centred, shrink-to-fit
         .banner-buttons-wrapper   flex row, space-between, huge margin-top

   The hero's height changes at four breakpoints and one of them is a `vw`,
   not a `vh` — verified: 731.7px at 1440 (90vh of an 813px viewport),
   813 at 992 (100vh), 650.4 at 900 (80vh), 767 at 767 and 500 at 500
   (100vw both times).

   The navbar is fixed and overlays the hero at every width — the hero starts
   at y=0 — which is why the bar's own background colour matters so much
   above. */
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  padding: 0 15px;
  background-image: url("../img/hero.webp");
  background-position: 50%;
  background-repeat: no-repeat;
  background-size: cover;
  background-attachment: scroll;
}

.hero-inner {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  max-width: 1170px;
  padding: 0 15px;
}

/* The 410px top margin is what pushes the buttons into the lower third of
   the photo; the container's height is exactly this margin plus the button
   row, which is why the whole block ends up where it does once the hero
   centres it. */
.hero-buttons {
  display: flex;
  justify-content: space-between;
  gap: 80px;
  margin: 410px auto 0;
}

.btn {
  display: block;
  padding: 13.5px 34px;
  border: 2px solid var(--main-red);
  background-color: transparent;
  color: var(--white);
  /* No font-family on purpose — the original's .primary-button declares none.
     An <a> picks up Montserrat from the global `a` rule; the submit <input>
     inherits the body's Arial stack via Webflow's `input { font: inherit }`,
     which is why the reference's submit button measures 186.7px wide and not
     200px. */
  font-size: 16px;
  font-weight: 800;
  line-height: 28px;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.3s;
}

.btn:hover,
.btn:focus-visible {
  background-color: var(--main-red);
  color: var(--white);
}

/* Wider padding, and the 25px gutter that the original puts on the in-flow
   half of its stacked pair.

   The padding is 53.85px rather than the original's 55px, and that 1.15px is
   deliberate. In the original the layout width comes from the *hidden* button,
   whose label is "Přehrát video" with a lower-case v, while the visible label
   on the overlay is "Přehrát Video" with a capital V. Merging the pair into
   one button makes the visible text drive the layout, and the capital V is
   2.3px wider — enough to push the row 2.4px wide and shift the second button
   by 1px. Trimming the padding by half that difference restores the
   original's measured 229.7px box exactly, and unlike a hard-coded width it
   still scales with the text if the font falls back. */
.btn--video {
  padding-left: 53.85px;
  padding-right: 53.85px;
  margin-right: 25px;
}

/* The EN home page carries the same quirk in a much louder form: its visible
   label is "Play Video", but the hidden button that does the layout still
   holds the Czech "Přehrát video". Measured on the original at 1440px, the
   EN button is 229.7px wide — the same box as the CZ one, driven by the same
   Czech string — while showing a label 27.3px narrower. Reproducing that box
   with the short label needs 67.5px of horizontal padding instead of 53.85px.

   This deliberately does NOT unify the two languages: the original's EN
   button really is sized by Czech text, and the row geometry depends on it.

   Declared before the <=991px block, which drops both buttons to a fixed
   250px and 34px of padding for either language. */
.btn--video-en {
  padding-left: 67.5px;
  padding-right: 67.5px;
}

@media (min-width: 1280px) {
  .hero {
    height: 90vh;
  }

  .hero-inner {
    padding: 0;
  }

  .hero-buttons {
    margin-top: 450px;
  }
}

@media (min-width: 1440px) {
  .hero-inner {
    max-width: 1250px;
  }
}

@media (min-width: 1920px) {
  .hero-inner {
    max-width: 1580px;
  }
}

@media (max-width: 991px) {
  .hero {
    height: 80vh;
  }

  .hero-buttons {
    width: 546px;
    /* The original's declared 80px gap never applies here, because its
       in-flow first child collapses to 0 width once the transparent button
       is hidden. With two real buttons, space-between distributes the
       remaining 46px instead — which is the spacing the original shows. */
    gap: 0;
  }

  .btn {
    width: 250px;
  }

  .btn--video {
    padding-left: 34px;
    padding-right: 34px;
    margin-right: 0;
  }
}

@media (max-width: 767px) {
  .hero {
    /* Not a typo: the original switches to a viewport-*width* height here. */
    height: 100vw;
  }

  .hero-buttons {
    flex-direction: column;
    align-items: flex-start;
    width: auto;
    /* 20px of padding plus a 21px gap reproduces the original's measured
       row: buttons at +20 and +100 from the wrapper top, 159px tall. */
    padding-top: 20px;
    gap: 21px;
  }
}

@media (max-width: 479px) {
  .hero {
    height: 70vh;
  }
}

/* ---------- Section shell ---------- */

.section {
  position: relative;
  padding-top: 100px;
  padding-bottom: 100px;
}

.section-heading {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 30px;
  margin: 0 auto;
  padding: 0 15px 45px;
}

.section-heading-icon {
  margin-bottom: 25px;
}

/* `margin: 0` is load-bearing on /404: the UA default for h1 is `0.67em 0`,
   which at that page's 180px heading is 120.6px of stray top margin. */
h1 {
  margin: 0 0 10px;
  color: var(--white);
  font-family: var(--heading-font);
  font-size: 60px;
  font-weight: 800;
  line-height: 72px;
}

h2 {
  margin: 0 0 10px;
  color: var(--white);
  font-family: var(--heading-font);
  font-size: 45px;
  font-weight: 800;
  line-height: 54px;
  text-align: left;
}
h3 {
  margin: 0 0 10px;
  color: var(--white);
  font-family: var(--heading-font);
  font-size: 34px;
  font-weight: 800;
  line-height: 40px;
}

h4 {
  margin: 0 0 10px;
  color: var(--white);
  font-family: var(--heading-font);
  font-size: 27px;
  font-weight: 800;
  line-height: 32px;
}

h5 {
  margin: 0 0 10px;
  color: var(--white);
  font-family: var(--heading-font);
  font-size: 23px;
  font-weight: 800;
  line-height: 30px;
}

h6 {
  margin: 0 0 10px;
  color: var(--white);
  font-family: var(--accent-font);
  font-size: 20px;
  font-weight: 600;
  line-height: 25px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}


.centered {
  text-align: center;
}

/* 2px red rule above the grid — only drawn at >=1280px in the original. */
.red-rule {
  display: none;
  width: 2px;
  height: 102px;
  margin-left: auto;
  margin-right: auto;
  background-color: var(--main-red);
}

/* The original reduces the plain `.section` padding twice on the way down.
   This is a general rule, not a contact-page one: on the homepage it reaches
   #galerie (the only plain `.section` there), while `.section--dark` and
   `.section--about` override it with their own values. */
@media (max-width: 991px) {
  .section {
    padding-top: 60px;
  }
}

@media (max-width: 767px) {
  .section {
    padding-top: 60px;
    padding-bottom: 60px;
  }
}

@media (min-width: 1280px) {
  .section {
    padding-top: 130px;
    padding-bottom: 130px;
  }

  .red-rule {
    display: block;
    position: absolute;
    top: -50px;
    left: 0;
    right: 0;
  }

  .tune-image {
    align-self: flex-start;
    display: inline-block;
  }
}

/* ---------- Gallery (#galerie) ---------- */

/* Column counts, gaps and paddings are the original's declarations, not a
   reading of its rendered output: 2 columns at base, 3 at >=1280px, 1 at
   <=991px. `grid-auto-rows: 1fr` is what makes every tile in the main grid
   the same height as the tallest one — measured 843.6px at 1440, 783.9 at
   1100, 633.9 at 900, 690.3 at 767. The "more" grid uses `auto` rows at base
   (so its tiles keep their own aspect ratios) and switches to `1fr` at
   >=1280px. */
.gallery-grid {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  /* From Webflow's own `.w-layout-grid` base, which the original's grid also
     carries. Without it the implicit column created by the span-2 tiles is
     `auto` and swallows the width: the columns resolved to `0px 845px`
     instead of the original's `422.5px 422.5px` at 900px. */
  grid-auto-columns: 1fr;
  gap: 10px;
  padding: 15px 15px 10px;
}

.gallery-grid--more {
  grid-template-rows: auto;
  grid-auto-rows: auto;
  padding: 0 15px 10px;
}

.gallery-grid--more[hidden] {
  display: none;
}

/* a-28 fades the revealed grid in over 300ms. */
.gallery-grid--more {
  opacity: 0;
  transition: opacity 0.3s;
}

.gallery-grid--more.is-revealed {
  opacity: 1;
}

/* The explicit `span 1` placement is transcribed from the original, where
   every non-wide tile carries it. It is tempting to drop as a redundant
   default — it is not. Leaving these tiles at `grid-column: auto` changes how
   the implicit column created by the span-2 tiles gets sized: at 900px the
   columns resolved to `0px 845px` instead of the original's
   `422.5px 422.5px`. */
.tile {
  position: relative;
  overflow: hidden;
  grid-area: span 1 / span 1 / span 1 / span 1;
}

/* Per-tile grid placement, transcribed from the original's #w-node rules:
   base `span 2` on tiles 1 and 4 and on the first "more" tile; `span 3` on
   tiles 1 and 5 at >=1280px; back to `span 1` for tiles 3 and 4 at >=1280px;
   everything back to `span 1` at <=767px. */
.tile--wide {
  grid-area: span 1 / span 2 / span 1 / span 2;
}

@media (min-width: 1280px) {
  .gallery-grid {
    grid-template-columns: 1fr 1fr 1fr;
    gap: 20px;
    padding: 55px 80px 20px;
  }

  .gallery-grid--more {
    grid-template-rows: 1fr;
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: 1fr;
    gap: 20px;
    padding: 0 80px 10px;
  }

  /* Order matters: tile 1 carries both classes and must end up spanning 3. */
  .tile--narrow-lg {
    grid-column: span 1 / span 1;
  }

  .tile--feature {
    grid-column: span 3 / span 3;
  }
}

/* The original's full set of responsive heading rules, ported together so
   this stops surfacing one page at a time. h5's <=991 `line-height: 1.3em`
   lives with the concert styles; h6 has none. */
@media (max-width: 991px) {
  h1 {
    font-size: 45px;
    line-height: 54px;
  }

  h2 {
    font-size: 40px;
    line-height: 48px;
  }

  .section-heading {
    padding-bottom: 20px;
  }

  .gallery-grid {
    grid-template-rows: 1fr 1fr 1fr 1fr;
    grid-template-columns: 1fr;
    grid-auto-flow: row;
  }

  .gallery-grid--more {
    grid-template-rows: auto auto;
    grid-template-columns: 1fr;
  }
}

@media (max-width: 767px) {
  h1 {
    font-size: 35px;
    line-height: 42px;
  }

  h2 {
    font-size: 30px;
    line-height: 36px;
  }

  h3 {
    font-size: 28px;
    line-height: 33px;
  }

  h4 {
    font-size: 25px;
    line-height: 30px;
  }

  /* Below 768px the tiles get an explicit viewport-relative height, so the
     rows stop being sized by the tallest image. 90vw is 690.3px at a 767px
     viewport and 351px at 390px — both exactly what the original measures. */
  .tile {
    height: 90vw;
  }

  .gallery-grid {
    padding-top: 0;
  }

  .gallery-grid--more {
    grid-template-rows: 1fr 1fr 1fr;
    grid-template-columns: 1fr;
  }

  .tile--wide {
    grid-area: span 1 / span 1 / span 1 / span 1;
  }
}

/* ---------- Tile contents ---------- */

/* Structure and display values transcribed from the original's measured
   chain: .overflow-hidden-item (block, relative) > a.w-inline-block
   (INLINE-block) > .gallery-grid-lightbox-wrapper (block, relative) > img.
   Both the missing wrapper level and the block-vs-inline-block link change
   how the image's intrinsic height reaches the grid: without them the rows
   sized to the tallest image (1105.8px at 767) instead of the original's
   690.3px. */
.tile-link {
  display: inline-block;
  max-width: 100%;
  width: 100%;
  height: 100%;
}

.tile-frame {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
}

.tile-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* IX2 a-35 / a-36: the image scales 1 -> 1.05 over 300ms on hover, clipped
   by the tile's `overflow: hidden`. */
.tile:hover .tile-image,
.tile-link:focus-visible .tile-image {
  transform: scale(1.05);
}

.tile-image {
  transition: transform 0.3s;
}

/* The "+" overlay is always in the DOM with transparent text; hovering gives
   it a colour and a 60%-black wash. The original switches it to `display:
   flex` only on hover, which is what centres the glyph. */
.tile-overlay {
  position: absolute;
  inset: 0;
  color: #0000;
  transition: color 0.3s, background-color 0.3s;
}

.tile-link:hover .tile-overlay,
.tile-link:focus-visible .tile-overlay {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #0e0e0e99;
  color: var(--white);
  font-size: 35px;
}

/* ---------- Load more ---------- */

.load-more {
  text-align: center;
}

.load-more[hidden] {
  display: none;
}

.inline-button {
  display: inline-block;
  margin-top: 14px;
  padding: 14px 0;
  border: 0;
  border-bottom: 2px solid var(--main-red);
  background-color: transparent;
  color: var(--paragraph);
  font-family: var(--heading-font);
  font-size: 16px;
  font-weight: 800;
  /* The original is an <a>, which inherits the body's 20px line-height. A
     <button> gets `line-height: normal` from the UA stylesheet instead,
     which made it 49.5px tall against the original's 50px. */
  line-height: inherit;
  cursor: pointer;
  transition: border-color 0.3s;
}

.inline-button:hover,
.inline-button:focus-visible {
  border-bottom-color: var(--white);
  color: var(--white);
}

/* ---------- Concerts (#koncerty, #koncerty-probehle) ---------- */

/* `.section.section--dark` is two classes on purpose, mirroring the
   original's `.section.dark-gray`: it has to beat the plain `.section`
   padding, including the 130px set inside the >=1280px media block. */
.section.section--dark {
  padding-top: 40px;
  padding-bottom: 40px;
  background-color: var(--grey);
}

.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding: 0 15px;
}

@media (min-width: 1280px) {
  .container {
    padding-left: 0;
    padding-right: 0;
  }
}

@media (min-width: 1440px) {
  .container {
    max-width: 1250px;
  }
}

@media (min-width: 1920px) {
  .container {
    max-width: 1580px;
  }
}

/* Below 480px the container goes full-bleed — its 15px side padding is
   dropped, so the concert rows run edge to edge. */
@media (max-width: 479px) {
  .container {
    padding-left: 0;
    padding-right: 0;
  }
}

/* The "no concerts planned" line — a plain paragraph at the base 15px/26px,
   centred only because the heading column centres its items. */
.shows-container {
  width: 100%;
}

.shows-container.is-hidden {
  display: none;
}

.show-wrapper {
  margin-top: 30px;
  margin-bottom: 30px;
}

.show-item {
  display: flex;
  align-items: center;
  margin-top: 15px;
}

.show-date {
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 160px;
  max-width: 285px;
  min-height: 60px;
  margin-right: 25px;
  padding-left: 15px;
  padding-right: 15px;
  background-color: #ffffff14;
  white-space: nowrap;
}

.h5-show-date {
  display: flex;
  align-items: center;
  margin-top: 10px;
  margin-bottom: 10px;
  font-size: 18px;
  text-align: center;
}

.show-place-wrapper {
  display: flex;
  justify-content: space-between;
  align-self: center;
  width: 100%;
  margin-right: 25px;
  background-color: #ffffff08;
}

.show-place {
  align-self: stretch;
  width: 50%;
  min-width: 160px;
}

.heading-h6-white {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 60px;
  margin-bottom: 0;
  padding: 5px 34px;
  white-space: nowrap;
}

.more-shows-container[hidden] {
  display: none;
}

@media (min-width: 1280px) {
  .show-date {
    justify-content: flex-start;
    min-width: 245px;
    padding-left: 35px;
    padding-right: 35px;
  }

  .h5-show-date {
    font-size: 23px;
  }

  .heading-h6-white {
    justify-content: flex-start;
  }
}

@media (max-width: 991px) {
  h5 {
    line-height: 1.3em;
  }

  .show-date {
    min-width: 145px;
    min-height: 88px;
    padding: 10px 15px;
  }

  .h5-show-date {
    text-align: center;
    white-space: normal;
  }

  .show-place-wrapper {
    padding-top: 14px;
    padding-bottom: 14px;
  }

  .show-place {
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .heading-h6-white {
    justify-content: center;
    align-items: center;
    line-height: 1em;
    text-align: center;
    white-space: normal;
  }
}

@media (max-width: 767px) {
  .show-item {
    flex-direction: column;
  }

  .show-date {
    width: 100%;
    max-width: none;
    min-height: auto;
    margin-right: 0;
  }

  .show-place-wrapper {
    flex-direction: column;
    width: 100%;
    margin-right: 0;
  }

  .show-place {
    width: 100%;
  }

  .h5-show-date {
    flex: 1;
    justify-content: center;
  }

  .heading-h6-white {
    padding-top: 15px;
    padding-bottom: 15px;
  }
}

@media (max-width: 479px) {
  .heading-h6-white {
    padding-left: 0;
    padding-right: 0;
  }
}

/* ---------- About (#o-nas) ---------- */

.section.section--about {
  padding-top: 140px;
}

@media (min-width: 1280px) {
  .section.section--about {
    padding-top: 140px;
    padding-bottom: 60px;
  }
}

@media (max-width: 991px) {
  .section.section--about {
    padding-top: 100px;
  }
}

/* `.w-layout-grid`'s own defaults apply underneath: display:grid and
   grid-auto-columns: 1fr. */
.columns-grid {
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: 1fr;
  grid-auto-columns: 1fr;
  gap: 40px;
  place-items: center start;
  width: 100%;
  padding-left: 15px;
  padding-right: 15px;
}

.about-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.paragraph-right-alignment {
  width: 70%;
  margin-top: 17px;
  text-align: center;
}

.heading-6-red {
  padding-top: 15px;
  padding-bottom: 5px;
  color: var(--main-red);
}

/* Not a blockquote despite the class name — an empty 42x2 white rule. */
.blockqoute-white {
  width: 42px;
  height: 2px;
  margin-top: 25px;
  margin-bottom: 18px;
  background-color: var(--white);
}

.grid-image {
  margin-left: auto;
  margin-right: auto;
}

@media (min-width: 1280px) {
  .columns-grid {
    grid-template-columns: 1fr 1fr;
    gap: 0;
    place-items: center end;
    padding-left: 0;
    padding-right: 0;
  }

  .about-text {
    justify-content: center;
    align-items: flex-end;
    margin-right: 70px;
    text-align: right;
  }

  .paragraph-right-alignment {
    width: 100%;
    text-align: left;
  }

  .blockqoute-white,
  .heading-6-red {
    align-self: flex-start;
  }

  .heading-6-red {
    text-align: left;
  }
}

@media (min-width: 1440px) {
  .columns-grid {
    grid-template-columns: 0.75fr 1fr;
  }

  .about-text {
    margin-right: 45px;
  }
}

@media (max-width: 991px) {
  .columns-grid {
    grid-template-rows: auto;
    grid-template-columns: 1fr;
    grid-auto-flow: row;
  }

  .grid-image {
    width: 100%;
    padding-left: 40px;
    padding-right: 40px;
  }
}

@media (max-width: 767px) {
  .columns-grid {
    gap: 20px;
  }

  .paragraph-right-alignment {
    width: 100%;
  }

  .grid-image {
    padding-left: 0;
    padding-right: 0;
  }
}

@media (max-width: 479px) {
  .heading-6-red {
    text-align: center;
  }
}

/* ---------- Contact CTA (#kontakt) ---------- */

.contact-us-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 60px auto 0;
}

.contact-us-button-wrapper {
  margin-top: 25px;
  padding: 10px;
}

@media (min-width: 1280px) {
  .contact-us-wrapper {
    margin-top: 40px;
  }
}

@media (max-width: 767px) {
  .contact-us-wrapper,
  .contact-us-button-wrapper {
    margin-top: 10px;
  }
}

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

.footer-section {
  padding: 100px 15px 60px;
}

.footer-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
}

.footer-info-wrapper {
  margin-top: 60px;
}

.footer-info {
  text-align: center;
}

.footer-icon-wrapper {
  display: flex;
  justify-content: space-between;
  margin-top: 40px;
}

.footer-paragraph {
  width: 385px;
  margin-top: 40px;
  line-height: 24px;
  text-align: center;
  text-transform: capitalize;
}

@media (max-width: 991px) {
  .footer-section {
    padding-top: 100px;
    padding-bottom: 40px;
  }
}

@media (max-width: 767px) {
  .footer-section {
    padding-top: 60px;
    padding-bottom: 40px;
  }
}

@media (max-width: 479px) {
  .footer-paragraph {
    width: 300px;
  }
}

/* ---------- Contact page (/kontakt) ---------- */

/* All of this band's height is padding — the original's container here is
   empty and there is no heading over the photo. */
.contact-us-section {
  padding: 350px 0 280px;
  background-image: url("../img/contact-hero.webp");
  background-position: 50%;
  background-size: cover;
  background-attachment: scroll;
}

@media (max-width: 991px) {
  .contact-us-section {
    padding-top: 200px;
    padding-bottom: 130px;
  }
}

@media (max-width: 767px) {
  .contact-us-section {
    padding-top: 180px;
    padding-bottom: 90px;
  }
}

.section.section--contact {
  padding-bottom: 60px;
}

/* Outer grid: contacts | form. 1.25fr/1fr with a 30px gap on desktop,
   stacked below 992px. */
.grid {
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: 1.25fr 1fr;
  grid-auto-columns: 1fr;
  gap: 16px;
}

@media (min-width: 1280px) {
  .grid {
    gap: 30px;
  }
}

@media (min-width: 1920px) {
  .grid {
    grid-template-rows: auto;
    grid-template-columns: 1fr 1fr;
    grid-auto-flow: column;
  }
}

@media (max-width: 991px) {
  .grid {
    grid-template-rows: auto auto;
    grid-template-columns: 1fr;
    justify-items: stretch;
    gap: 30px;
    width: 100%;
    margin-left: auto;
    margin-right: auto;
  }
}

/* `grid-template-rows: auto auto` comes from Webflow's `.w-layout-grid` base,
   which the original's grid also carries; `.contacts-grid` itself only sets
   columns. Without it the single row stretched and the info wrapper measured
   269px instead of the original's 185.5px. */
.contacts-grid {
  display: grid;
  grid-template-rows: auto auto;
  grid-template-columns: 1fr 1fr;
  grid-auto-columns: 1fr;
  gap: 0;
}

@media (max-width: 991px) {
  .contacts-grid {
    gap: 30px;
  }
}

@media (max-width: 767px) {
  .contacts-grid {
    grid-template-rows: auto auto auto auto;
    grid-template-columns: 1fr;
  }

  .contact-info-wrapper {
    margin-left: auto;
    margin-right: auto;
  }
}

.contact-info-wrapper {
  display: flex;
  width: 300px;
}

/* ---------- Contact form ---------- */

.form-con {
  width: 100%;
}

.form-block-2 {
  margin-bottom: 0;
}

.input-info-email {
  display: flex;
  justify-content: space-between;
  margin-bottom: 15px;
}

/* Declared before `.input-field` on purpose, matching the original's source
   order — and the order is the whole point. `.input-field`'s padding
   shorthand comes later at equal specificity, so it wins, and this rule's
   `padding-right: 70px` never actually applies. It is dead CSS in the
   original too; kept here so the cascade matches rather than silently
   "cleaned up". */
.text-field {
  min-height: 60px;
  margin-bottom: 0;
  margin-right: 16px;
  padding-left: 20px;
  padding-right: 70px;
}

/* Webflow's `.w-input` base is folded in here: width 100%, display block,
   and the `::placeholder` colour. The border is `1px #000` with no style
   keyword in the original, which resolves to `border-style: none` — so no
   border ever draws, focused or not. */
.input-field {
  display: block;
  width: 100%;
  height: 48px;
  margin-bottom: 0;
  margin-right: 20px;
  /* 8px vertical is Webflow's `.w-input { padding: 8px 12px }`; the original's
     `.input-field` only overrides the horizontal values. */
  padding: 8px 20px;
  border: 1px #000;
  background-color: var(--borders);
  color: var(--paragraph);
  font-family: var(--heading-font);
  font-size: 16px;
  vertical-align: middle;
}

.input-field::placeholder {
  color: #999;
}

/* The original's fields had no visible focus indicator at all (`border: 0px
   none`, `outline: none`). Mouse focus still shows nothing, as in the
   original; keyboard focus gets a ring in the brand red (see DECISIONS.md,
   2026-09-29). */
.input-field:focus {
  border-color: #3898ec;
  outline: 0;
}

.input-field:focus-visible {
  outline: 2px solid var(--main-red);
  outline-offset: 2px;
}

.input-field.last-item {
  margin-right: 0;
}

.input-field.text-field {
  min-height: 120px;
  margin-right: 0;
}

.submit-button-wrapper {
  margin-top: 15px;
}

/* Two classes, mirroring the original's `.primary-button._100`, so it beats
   the `.btn { width: 250px }` rule inside the <=991px block. */
.btn.btn--full {
  width: 100%;
}

@media (min-width: 1280px) {
  .input-field {
    height: 60px;
    margin-bottom: 0;
    padding: 5px 20px;
    font-size: 16px;
  }
}

@media (max-width: 991px) {
  .input-field {
    margin-bottom: 0;
  }

  .form-2 {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .input-info-email {
    width: 100%;
  }
}

@media (max-width: 767px) {
  /* The original moves this spacing onto the button itself here and zeroes
     the wrapper — which is how the submit ends up 20px below the textarea
     rather than 15px. */
  .btn {
    margin-top: 20px;
  }

  /* ...except in the hero, which reproduces its own spacing with padding and
     a gap. The original can use a per-button margin there because its first
     child is a zero-height absolutely-positioned overlay; the rebuild merges
     that stacked pair into one in-flow button, so the same margin would add
     20px to each. Documented deviation — see DECISIONS.md. */
  .hero-buttons .btn {
    margin-top: 0;
  }

  .submit-button-wrapper {
    margin-top: 0;
  }

  /* This is what stacks the name and e-mail fields: both are width:100%, so
     once the row is allowed to wrap they take a line each. */
  .input-info-email {
    flex-wrap: wrap;
  }

  .input-field {
    margin-right: 0;
  }

  .input-field.last-item {
    margin-top: 15px;
  }
}

/* Honeypot against contact-form spam (assets/js/contact.js) — hidden the
   same way sites/peaksolutions.cz's own .contact-form__hp is, off-screen
   rather than display:none/visibility:hidden so it still receives real
   pointer/keyboard interaction from a scripted filler that ignores CSS
   visibility, which is the point of a honeypot. */
.contact-form__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.cf-turnstile {
  margin: 15px 0;
}

.contact-form__verifying {
  margin: -10px 0 15px;
  color: var(--paragraph);
  font-size: 13px;
}

/* Same treatment as .contact-form__verifying — a small hint line, not
   part of the original form (which has no privacy link at all). */
.contact-form__privacy-note {
  margin: 10px 0 0;
  color: var(--paragraph);
  font-size: 13px;
}

.btn.btn--full:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn.btn--full:disabled:hover {
  background-color: transparent;
  color: var(--white);
}

.btn.is-loading {
  position: relative;
  color: transparent;
  pointer-events: none;
}

.btn.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid var(--white);
  border-top-color: transparent;
  border-radius: 50%;
  animation: contact-spin 0.6s linear infinite;
}

@keyframes contact-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Webflow's success/failure blocks. Both are display:none by default and
   the .is-visible toggle (assets/js/contact.js) is this rebuild's own
   addition — Webflow's runtime, which doesn't exist outside Webflow,
   used its own mechanism. Colors adapted from the reference stylesheet's
   light-template defaults (#ddd grey / #ffdede pink) to this site's dark
   palette: those defaults were never actually visible on the live
   reference either (the original's own backend was never observed
   succeeding or failing), so there was no verified dark-site look to
   preserve — see DECISIONS.md. */
.w-form-done {
  display: none;
  padding: 20px;
  background-color: var(--light-grey);
  border: 1px solid var(--main-green);
  color: var(--white);
  text-align: center;
}

.w-form-fail {
  display: none;
  margin-top: 10px;
  padding: 10px 20px;
  background-color: var(--light-grey);
  border: 1px solid var(--main-red);
  color: var(--white);
}

.w-form-done.is-visible,
.w-form-fail.is-visible {
  display: block;
}

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

.utility-page-wrap {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  max-width: 100%;
  height: 100vh;
  max-height: 100%;
  background-image: url("../img/404-noise.webp");
  background-position: 50%;
  background-size: cover;
}

.shadow {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-color: #0000008c;
}

.utility-page-content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 500px;
  padding-left: 15px;
  padding-right: 15px;
  text-align: center;
}

.heading-404 {
  margin-bottom: 30px;
  font-size: 180px;
  line-height: 1.1em;
}

.subheading-404 {
  margin-bottom: 20px;
  font-size: 30px;
  font-weight: 600;
  text-align: center;
}

.paragraph-404 {
  margin-bottom: 50px;
  color: var(--paragraph);
}

@media (max-width: 991px) {
  .heading-404 {
    font-size: 150px;
  }

  .subheading-404 {
    font-size: 27px;
  }

  .paragraph-404 {
    margin-bottom: 30px;
  }
}

@media (max-width: 767px) {
  .heading-404 {
    margin-bottom: 10px;
    font-size: 105px;
  }

  .subheading-404 {
    margin-bottom: 10px;
    font-size: 25px;
  }

  .paragraph-404 {
    margin-bottom: 10px;
  }
}

/* ---------- Videos (#videa / #videos) ---------- */

/* The original ships this section TWICE and swaps the two implementations at
   992px: a scroll-driven tab player for >=992px and a plain stack of five
   embeds below it. Both are reproduced, in the original's document order
   (mobile first), and only the desktop one carries the id.

   The 400vh section plus the sticky inner container is the scroll mechanism
   itself, and it is pure CSS. The part that is NOT implemented here is IX2
   a-26 - see DECISIONS.md. */

.videos {
  position: relative;
  /* Never applied: both variants override it at every breakpoint. Kept
     because the original declares it. */
  height: 310vh;
  padding-top: 80px;
}

.videos--mobile {
  display: none;
}

.videos--desktop {
  height: 100vh;
  display: block;
}

.video-sticky {
  width: 100%;
  height: 74vh;
  margin: 15px 0;
  padding: 0 15px;
  position: sticky;
  top: 120px;
  overflow: hidden;
}

.video-tabs {
  display: flex;
  height: 65vh;
}

.tabs {
  flex-direction: row;
  width: 100%;
  display: flex;
  position: relative;
}

.tab-panels {
  flex: 1;
  display: block;
  position: relative;
  overflow: hidden;
}

.tab-panel {
  display: none;
  position: relative;
  opacity: 1;
}

.tab-panel.is-active {
  display: block;
}

/* The original fades panels sequentially, not as a cross-dissolve: the
   outgoing panel fades to opacity 0 over 100ms while still in flow, THEN is
   hidden (display:none) at the same moment the incoming panel is shown at
   opacity 0 and fades to 1 over 300ms. Verified on the live reference by
   reading the inline `transition`/`opacity` Webflow sets during a real tab
   switch: the outgoing panel ends with its style attribute cleared and
   `display:none`, the incoming with
   `transition: all, opacity 300ms; opacity: 1`.

   Two classes, two directions: `videos.js` adds `.is-leaving` to fade the
   outgoing panel out, and separately adds/removes `.is-entering` on the
   incoming one across a frame boundary so it actually starts its
   transition from 0 instead of snapping straight to 1. */
.tab-panel.is-leaving {
  transition: opacity 0.1s;
  opacity: 0;
}

.tab-panel.is-entering {
  transition: none;
  opacity: 0;
}

.tab-panel.is-active:not(.is-entering) {
  transition: opacity 0.3s;
}

/* Load-bearing on the EN page and redundant on the CZ one. The EN first
   panel carries an extra empty .video-embed-placeholder whose :empty rule
   gives it a 612px aspect box; this fixed height plus .tab-panels'
   overflow:hidden is what keeps that box off the page. Measured on both
   references. */
.tab-panel--first {
  height: 65vh;
}

/* The original's Tab 5 rule. Redundant at every breakpoint measured, since
   the panel's height already comes from .video-embed. */
.tab-panel--last {
  height: 100%;
}

/* The 56.17% top padding is the aspect box, which the original carries as an
   inline style on every one of its ten embeds. It is what gives the mobile
   stack its height; the desktop panels override it with an explicit height,
   which is why omitting it stayed invisible until the <=991px measurement. */
.video-embed {
  width: 100%;
  height: 100%;
  padding: 56.17021276595745% 0 0;
  position: relative;
}

.video-embed iframe {
  border: none;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

/* Click-to-play thumbnail that stands in for the iframe until a visitor
   plays the video (assets/js/video-facade.js). Fills the same box the
   iframe does. The play button is a red rounded rectangle with a white
   triangle, drawn in CSS, no image. */
.video-facade {
  display: block;
  position: absolute;
  inset: 0;
  background-color: var(--black);
  cursor: pointer;
}

.video-facade-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.video-facade-play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 68px;
  height: 48px;
  margin: -24px 0 0 -34px;
  border-radius: 12px;
  background-color: var(--main-red);
  opacity: 0.9;
  transition: opacity 0.2s, transform 0.2s;
}

.video-facade-play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -10px 0 0 -7px;
  border-style: solid;
  border-width: 10px 0 10px 17px;
  border-color: transparent transparent transparent var(--white);
}

.video-facade:hover .video-facade-play,
.video-facade:focus-visible .video-facade-play {
  opacity: 1;
  transform: scale(1.1);
}

.video-facade:focus-visible {
  outline: 2px solid var(--main-red);
  outline-offset: 2px;
}

/* Only on the EN page. Webflow's placeholder for an embed that never got a
   video; it is clipped away by .tab-panel--first, so it draws nothing. */
.video-embed-placeholder {
  background-image: url("https://d3e54v103j8qbb.cloudfront.net/static/youtube-placeholder.2b05e7d68d.svg");
  background-position: 50%;
  background-size: cover;
  width: 100%;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  position: relative;
}

.video-embed-placeholder:empty {
  min-height: 75px;
  padding-bottom: 56.25%;
}

.tab-list {
  flex-direction: column;
  width: 20%;
  margin-left: 15px;
  display: flex;
  position: relative;
}

/* Every tab, current or not, is the same flat black in the original - the
   active one is not marked by its background. The original's own
   .w--current rules restate the identical colour at every breakpoint. */
.tab {
  display: block;
  position: relative;
  padding: 0;
  background-color: var(--black);
  color: #222;
  text-align: left;
  vertical-align: top;
  text-decoration: none;
  cursor: pointer;
}

/* The original removes the focus ring on its tab links and marks the
   current tab nowhere. Keyboard focus now gets a ring and the current tab's
   title turns brand red (see DECISIONS.md, 2026-09-29). */
.tab:focus {
  outline: 0;
}

.tab:focus-visible {
  outline: 2px solid var(--main-red);
  outline-offset: 4px;
}

.tab.is-current .tab-title {
  color: var(--main-red);
}

/* The background-image is the original's: the class carries the "Jeden hlas"
   thumbnail behind every tab, which shows as a native-size crop for as long
   as the real lazy-loaded <img> has not arrived. A Webflow leftover with a
   visible transient effect, so it is reproduced. */
.tab-thumb {
  width: 100%;
  margin-bottom: 20px;
  background-image: url("../img/videos/05.webp");
  background-position: 50%;
  background-repeat: no-repeat;
  background-size: auto;
}

.tab-title {
  margin-bottom: 8px;
}

.tab-duration {
  margin-bottom: 30px;
}

.tab-duration-value {
  color: var(--paragraph);
}

.scroll-track {
  background-color: var(--light-grey);
  width: 2px;
  margin-left: 15px;
}

/* Height is 0 in the CSS and 0 at a-26's keyframe 0 - the same value from
   two directions, which is why the untouched initial state is correct. */
.scroll-progress {
  background-color: var(--main-red);
  width: 2px;
  height: 0%;
}

.video-stack {
  display: none;
}

@media (min-width: 1280px) {
  .videos--desktop {
    height: 400vh;
  }

  .video-tabs {
    height: 75vh;
    overflow: hidden;
  }

  .tabs {
    overflow: hidden;
  }

  .tab-panel--first {
    height: 75vh;
  }

  .video-embed {
    height: 75vh;
  }
}

@media (max-width: 991px) {
  .videos {
    height: 400vw;
    margin-bottom: 65px;
  }

  .videos--mobile {
    height: 320vw;
    display: block;
  }

  .videos--desktop {
    display: none;
  }

  .video-tabs {
    flex-direction: column;
    height: auto;
    overflow: visible;
  }

  .tabs {
    flex-direction: column;
    width: auto;
    height: auto;
    overflow: hidden;
  }

  .tab-panels {
    display: none;
    overflow: visible;
  }

  .tab-panel--first {
    height: auto;
  }

  /* The tab list is hidden here, so these three are dead in practice. Kept
     because the original declares them. */
  .tab-list {
    flex-direction: row;
    width: 400%;
    margin-left: 0;
    display: none;
  }

  .tab {
    flex: 1;
  }

  .tab-thumb {
    display: none;
  }

  .tab-title {
    margin-top: 8px;
  }

  .tab-duration {
    margin-bottom: 12px;
  }

  .scroll-track {
    width: 100%;
    height: 2px;
    margin-left: 0;
  }

  .scroll-progress {
    height: 2px;
  }

  .video-stack {
    display: flex;
    flex-flow: column;
    gap: 25px;
  }

  .video-embed {
    display: block;
  }
}

@media (max-width: 767px) {
  .videos {
    margin-bottom: 30px;
  }

  .videos--mobile {
    height: 340vw;
  }
}

@media (max-width: 479px) {
  .videos--mobile {
    height: 380vw;
  }
}

/* ---------- Reveal-on-scroll (homepages only) ----------

   Hidden only once assets/js/reveal.js has confirmed IntersectionObserver
   support and added `.js-reveal` to <html> — see that file for why. Without
   it, [data-reveal] is plain markup with no visual effect, so content stays
   visible with no JS at all.

   The four values matching the original's four actually-used IX2 presets,
   1000ms outQuart, confirmed by sampling a live reveal frame-by-frame
   rather than assumed from the preset names. */

html.js-reveal [data-reveal] {
  opacity: 0;
  transition: opacity 1s cubic-bezier(0.165, 0.84, 0.44, 1),
    transform 1s cubic-bezier(0.165, 0.84, 0.44, 1);
}

html.js-reveal [data-reveal="slide-bottom"] {
  transform: translateY(100px);
}

html.js-reveal [data-reveal="slide-left"] {
  transform: translateX(-100px);
}

html.js-reveal [data-reveal="slide-right"] {
  transform: translateX(100px);
}

html.js-reveal [data-reveal].is-revealed {
  opacity: 1;
  transform: translate(0, 0);
}

/* ---------- Lightbox (hero video + gallery) ---------- */
/* assets/js/lightbox.js builds this markup entirely; see that file's header
   comment for the audited reference behaviour this reproduces. */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.9);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.lightbox.is-visible {
  display: flex;
}

.lightbox.is-open {
  opacity: 1;
}

.lightbox-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 90vw;
  max-height: 80vh;
}

.lightbox.has-strip .lightbox-frame {
  max-height: 65vh;
}

.lightbox.has-strip .lightbox-image {
  max-height: 65vh;
}

.lightbox-image {
  max-width: 90vw;
  max-height: 80vh;
  width: auto;
  height: auto;
  object-fit: contain;
}

.lightbox-video {
  width: min(940px, 90vw);
  aspect-ratio: 940 / 705;
}

.lightbox-video iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.lightbox-close {
  position: absolute;
  top: 16px;
  right: 24px;
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  color: var(--white);
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
}

.lightbox-close:hover,
.lightbox-close:focus-visible {
  color: var(--main-red);
}

.lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  border: 2px solid var(--borders);
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.4);
  color: var(--white);
  font-size: 0;
  cursor: pointer;
}

.lightbox-arrow::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 10px;
  border-top: 2px solid var(--white);
  border-right: 2px solid var(--white);
}

.lightbox-arrow--prev {
  left: 24px;
}

.lightbox-arrow--prev::before {
  transform: translate(-30%, -50%) rotate(-135deg);
}

.lightbox-arrow--next {
  right: 24px;
}

.lightbox-arrow--next::before {
  transform: translate(-70%, -50%) rotate(45deg);
}

.lightbox-arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

.lightbox-arrow:hover:not(:disabled),
.lightbox-arrow:focus-visible:not(:disabled) {
  border-color: var(--main-red);
}

.lightbox-strip {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  gap: 4px;
  overflow-x: auto;
  padding: 12px;
  background-color: rgba(0, 0, 0, 0.6);
}

.lightbox-strip-item {
  flex: 0 0 auto;
  width: 80px;
  height: 60px;
  padding: 0;
  border: 2px solid transparent;
  background: none;
  cursor: pointer;
  opacity: 0.6;
}

.lightbox-strip-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.lightbox-strip-item.is-active,
.lightbox-strip-item:hover,
.lightbox-strip-item:focus-visible {
  opacity: 1;
  border-color: var(--main-red);
}

@media (max-width: 767px) {
  .lightbox-frame {
    max-height: 65vh;
  }

  .lightbox-image {
    max-height: 65vh;
  }

  .lightbox-arrow {
    width: 36px;
    height: 36px;
  }

  .lightbox-strip-item {
    width: 56px;
    height: 42px;
  }
}

/* ---------- Privacy policy page ---------- */

/* A new page type, not part of the original — there is no reference to
   match, so this is deliberately minimal: reuses .section/.container and
   the site's own h1/h2/p/a rules for everything except text measure,
   which .container alone (1170px, flex-start) leaves too wide for
   comfortable long-form reading. */
.legal-page__inner {
  max-width: 720px;
}

.legal-page__inner h2 {
  margin-top: 40px;
  font-size: 22px;
}

/* Unlike every other .section on this site, this page's section is the
   first (only) thing after the fixed header — the generic .section
   padding-top (60px ≤991px) sits well under the 92px header there,
   which clipped the heading. Same fix, same values already used for
   .section--about (the site's other "content starts right under the
   nav" case). */
.section.section--legal {
  padding-top: 140px;
}

@media (max-width: 991px) {
  .section.section--legal {
    padding-top: 100px;
  }
}

/* ---------- Visually hidden ---------- */

/* Text for screen readers and search engines only, e.g. the pages' <h1>s,
   which have no visible counterpart in the original design. */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Reduced motion ---------- */

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

  /* The rule above alone would still leave [data-reveal] content sitting at
     opacity:0/offset until scrolled to, just snapping in near-instantly
     instead of easing in — a "pop" rather than the requirement that
     reduced-motion content is visible immediately. Force the revealed state
     unconditionally instead. */
  html.js-reveal [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }
}
