/* Landing: the production line. Loaded only on the landing page. */

.has-line .site-header { position: sticky; top: 0; z-index: 5; background: color-mix(in srgb, var(--paper) 88%, transparent); backdrop-filter: blur(6px); }

.line { position: relative; width: 100%; min-height: 440vh; overflow: hidden; }

.line__canvas { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
.line__canvas canvas { display: block; width: 100%; height: 100%; }

.line__belt { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; overflow: visible; }
.line__belt path { fill: none; stroke: var(--ink); stroke-width: 7; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.line__belt .line__belt-dots { stroke: var(--accent); stroke-width: 2; stroke-dasharray: 0 14; }
.line__anchor { fill: none; }

.line__fallback { position: absolute; z-index: 1; width: clamp(180px, 22vw, 320px); height: auto; }
/* Station 0's stand-in is the hero of the fallback page, so it must sit ON
   the belt, not near it: 52%/4vh put the disc ~190 px right and ~95 px above
   the belt's first point at 1440x900, i.e. floating off the start of the
   machine it is supposed to be riding.
   These two numbers are exact rather than eyeballed, and stay exact at every
   desktop width. The belt SVG covers .line with preserveAspectRatio="none",
   so an SVG x of 500/1000 IS 50% of .line's width; and .line is 440vh tall,
   so an SVG y of 160/2200 is 0.0727 * 440vh = 32vh. The translate centres the
   disc (which is itself centred in the 640px render) on that point.
   Re-derive both if DESKTOP_D's first point or .line's min-height change. */
.line__fallback[data-station="0"] { left: 50%; top: 32vh; transform: translate(-50%, -50%); }
.line__fallback[data-station="1"] { left: 62%; top: 88vh; }
.line__fallback[data-station="2"] { left: 12%; top: 180vh; }
.line__fallback[data-station="3"] { left: 55%; top: 272vh; }
.line__fallback[data-station="4"] { left: 12%; top: 360vh; }

/* The tops are not decoration: each one is derived from where the belt puts the
   object at that station's dwell (path.js STATIONS[n].at mapped through the
   stretched viewBox), so the text lands beside the machine that is acting and
   is still on screen through the roll-out. Re-derive them if the belt path, the
   dwells or `.line`'s min-height change. Widths are capped so the column clears
   the disc (and, at 4, the lifted sleeve) horizontally at every station. */
.station { position: absolute; z-index: 2; width: min(28rem, 40%); }
.station--0 { left: 6%; top: 8vh; width: min(30rem, 40%); }
.station--1 { left: 6%; top: 120vh; }
.station--2 { right: 6%; top: 208vh; }
.station--3 { left: 6%; top: 288vh; }
.station--4 { right: 6%; top: 366vh; }

/* Visible by default: this page must be fully readable with zero JS, and in the
   fallback mode (no WebGL / reduced motion), which never sets `line-3d`.
   The reveal choreography is opt-in: main.js adds `line-3d` to <body> only once
   the Three.js scene is actually running, and from then on a station's text is
   hidden until the disc reaches it (`is-active`). Hiding is therefore never
   reachable by a visitor who cannot see the scene reveal it. */
.station__text { position: relative; opacity: 1; transform: none; transition: opacity .5s ease, transform .5s ease; }
.station.is-active .station__text,
.no-motion .station__text { opacity: 1; transform: none; }
body.line-3d .station:not(.is-active) .station__text { opacity: 0; transform: translateY(12px); }

.station__eyebrow { font-size: .75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); margin: 0 0 .5rem; }
.station h1 { font-size: clamp(2.6rem, 6vw, 4.6rem); margin: 0 0 1rem; }
.station h2 { font-size: clamp(1.8rem, 3.6vw, 2.6rem); margin: 0 0 .75rem; }
.station__note { border-left: 3px solid var(--accent); padding: .5rem .9rem; background: var(--paper-2); }
.station__cue { font-size: .75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.station__error { color: #b3261e; }

.dropzone { display: grid; place-items: center; gap: .25rem; width: min(20rem, 100%); min-height: 6.5rem; padding: 1rem; border: 1.5px dashed var(--accent); border-radius: .75rem; background: color-mix(in srgb, #fff 45%, transparent); color: var(--accent); cursor: pointer; text-align: center; }
.dropzone.is-over { background: #fff; }
/* The file input inside the zone is visually hidden, not display:none, so it
   takes focus — but it has no box to draw a ring around. Put the ring on the
   zone, which is the thing a keyboard visitor is actually aiming at. */
.dropzone:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Fallback only. With no scroll choreography to carry it away, a dropped photo
   rests permanently in the centre of its zone; its own label would sit behind
   the picture. The photo IS the state once it is there, and the zone stays
   clickable to change it. */
.no-motion .dropzone.is-filled .dropzone__label,
.no-motion .dropzone.is-filled .dropzone__hint { visibility: hidden; }
.dropzone__label { font-weight: 600; }
.dropzone__hint { font-size: .8rem; color: var(--muted); }

/* top/left: 0 pins the tile's untransformed origin to .station__text's top-left corner —
   photos.js positions it purely with translate() computed from that same corner. */
.tile { position: absolute; top: 0; left: 0; width: 5.5rem; height: 5.5rem; border-radius: .4rem; overflow: hidden; box-shadow: 0 14px 24px -14px rgba(0,0,0,.45); opacity: 0; pointer-events: none; }
.tile img { width: 100%; height: 100%; object-fit: cover; display: block; }

.line__demo-cta { margin-right: .5rem; }

/* Below the belt: normal flow, normal measure. */
.rail, .faq { max-width: var(--measure); margin: 0 auto; padding: 3rem 1.25rem; }
.rail__list { list-style: none; margin: 1.5rem 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 1rem; }
.rail__item { min-width: 0; overflow-wrap: anywhere; }
.rail__item a { display: block; padding: 1.25rem; border: 1px solid var(--rule); border-radius: .5rem; text-decoration: none; color: inherit; background: var(--paper-2); }
.rail__name { display: block; font-weight: 600; }
.rail__kind { display: block; color: var(--muted); font-size: .9rem; }
.faq__list dt { font-weight: 600; margin-top: 1rem; }
.faq__list dd { margin: .25rem 0 0; color: var(--muted); }

/* Phone: the S narrows, text stacks under each station, the page grows taller. */
@media (max-width: 47.9rem) {
  .line { min-height: 620vh; }
  .station, .station--0, .station--1, .station--2, .station--3, .station--4 { left: 1.25rem; right: 1.25rem; width: auto; }
  /* Same derivation as desktop, against the phone viewBox and the 620vh
     section. The column is full width here, so the text sits ABOVE the object
     instead of beside it — except at the hero, where at scroll 0 the belt puts
     the record at 18-42vh and the 41vh-tall hero copy cannot clear it above,
     so the copy goes below the record instead. */
  .station--0 { top: 46vh; }
  .station--1 { top: 143vh; }
  /* 232vh and 492vh: sampled the belt path (belt-path.getPointAtLength) at
     5vh steps down its whole phone length — most of the curve sweeps clean
     across the full text width, but there are two ~35vh windows where it
     hugs x=14-17% (near the left edge) instead: 220-265vh and 480-515vh.
     Landing each station's whole text block inside one of those, plus a
     left inset past the belt's worst case there, is what keeps the belt
     off the heading glyphs — the previous 275vh/516vh tops sat in the wide
     middle of a sweep (belt crossing 15%-50% width across the block's own
     height) and cut straight through "Fotka na obal" and "1190 Kč". */
  .station--2 { top: 232vh; left: 5rem; }
  .station--3 { top: 408vh; }
  .station--4 { top: 492vh; left: 5rem; }
  .line__fallback { width: 46vw; }
  /* Same derivation against the phone belt: PHONE_D starts at 500,120 in a
     1000x3100 viewBox over a 620vh section -> 50% and 0.0387 * 620vh = 24vh.
     The old 40%/46vh sat the disc squarely on top of the hero copy (which is
     at 46vh on phones, below the record rather than beside it). */
  .line__fallback[data-station="0"] { left: 50%; top: 24vh; transform: translate(-50%, -50%); }
  .line__fallback[data-station="1"] { left: 40%; top: 170vh; }
  .line__fallback[data-station="2"] { left: 10%; top: 300vh; }
  .line__fallback[data-station="3"] { left: 40%; top: 430vh; }
  .line__fallback[data-station="4"] { left: 10%; top: 556vh; }
  .dropzone { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .station__text { transition: none; }
}
