/* ==========================================================================
   ЦРВЕНО СЛОВО — небо над храмом
   ONE CONTINUOUS WORLD. The chapters are stations placed along a winding
   flight path through the sky; scroll moves the camera along that path and
   the guide swallow flies ahead of it. Frames never "animate in" — the
   reader ARRIVES at them, through deliberate stretches of empty sky.
   Vanilla CSS, no build step, transform/opacity only.
   ========================================================================== */

/* ---------- Fonts (self-hosted, cyrillic + latin subsets) ---------- */
@font-face{font-family:'Oswald';src:url('../fonts/oswald-cyrillic-500.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Oswald';src:url('../fonts/oswald-cyrillic-700.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Oswald';src:url('../fonts/oswald-latin-700.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+2122,U+2191,U+2193,U+2212,U+2215}
@font-face{font-family:'Prata';src:url('../fonts/prata-cyrillic-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'InterVar';src:url('../fonts/inter-cyrillic-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'InterVar';src:url('../fonts/inter-cyrillic-600.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'InterVar';src:url('../fonts/inter-cyrillic-700.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap;unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'InterVar';src:url('../fonts/inter-latin-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+2122,U+2212,U+2215}
@font-face{font-family:'InterVar';src:url('../fonts/inter-latin-600.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+2122,U+2212,U+2215}

/* ---------- Camera-fed custom properties ---------- */
/* --p: progress through a station's plateau (its internal life)
   --e: arrival — ramps up over the last half of the flight leg INTO a station
   --x: departure — ramps up over the first half of the leg OUT of it */
@property --p{syntax:'<number>';initial-value:0;inherits:true}
@property --e{syntax:'<number>';initial-value:1;inherits:true}
@property --x{syntax:'<number>';initial-value:0;inherits:true}
@property --ep{syntax:'<number>';initial-value:0;inherits:false}

/* ---------- Design tokens (sampled from the app itself) ---------- */
:root{
  --blush:#FDE8E9;   --blush-2:#FCEFEF;  --cream:#FEFAF8;
  --rose:#F0B1B1;    --rose-2:#D27171;
  --crimson:#C43434; --crimson-2:#AE4141; --deep:#8E2A2A;
  --coral:#F2664B;   --coral-2:#E8503A;
  --night:#2A0F14;   --void:#180A0D;     --void-2:#0E0507;
  --amber:#E79047;   --amber-2:#E07F39;  --gold:#D9A441;
  --ink:#1A0E10;     --ink-2:#4A3034;    --ink-soft:#6B4A4E;
  --paper-ink:#121210;

  --font-display:'Oswald','Oswald Fallback',ui-sans-serif,system-ui,'Segoe UI',Roboto,sans-serif;
  --font-serif:'Prata',Georgia,'Times New Roman',serif;
  --font-body:'InterVar',ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;

  --e-out:cubic-bezier(.16,.84,.34,1);
  --e-io:cubic-bezier(.66,0,.34,1);

  --gut:clamp(20px,5vw,64px);
  --measure:min(100% - var(--gut)*2, 1180px);

  --r-lg:28px; --r-md:18px; --r-sm:12px;
  /* svh: a station never resizes when the mobile URL bar collapses */
  --stage-h:100vh;
}
@supports (height:100svh){:root{--stage-h:100svh}}

*,*::before,*::after{box-sizing:border-box}
/* no rubber-band past the ends of the journey — the world must not bounce
   off the footer (this also stills the bounce at the very top) */
html{-webkit-text-size-adjust:100%;overscroll-behavior-y:none}
body{overscroll-behavior-y:none}
body{
  margin:0;background:var(--void-2);color:var(--blush);
  font-family:var(--font-body);font-size:clamp(16px,1.05vw,17.5px);line-height:1.62;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:clip;
}
img{max-width:100%;display:block}
a{color:inherit}
::selection{background:var(--coral);color:#fff}
:focus-visible{outline:2.5px solid var(--coral);outline-offset:3px;border-radius:6px}

/* ==========================================================================
   СВЕТ · layer 1 — ambient sky. Cross-fades between the acts of the day.
   ========================================================================== */
.ambient{position:fixed;inset:0;z-index:-6;background:var(--void-2)}
.ambient i{position:absolute;inset:0;opacity:0;
  transition:opacity 1100ms var(--e-io);will-change:opacity}
.ambient i.on{opacity:1}
.ambient::after{content:'';position:absolute;inset:0;
  background:radial-gradient(120% 85% at 50% -10%, rgba(255,255,255,.14), transparent 62%);
  opacity:.9}
/* the prelude is PRE-dawn, not dead night: a faint first light sits low in
   the east, in the direction the first leg will fly */
.ambient::before{content:'';position:absolute;inset:0;opacity:0;
  transition:opacity 1100ms var(--e-io);
  background:radial-gradient(90% 46% at 62% 104%, rgba(222,118,66,.30), transparent 68%)}
body[data-act="void"] .ambient::before{opacity:1}
body[data-act="void"]{--amb:radial-gradient(120% 100% at 50% 0%,#7A3441 0%,#45202B 48%,#271419 100%)}
body[data-act="dawn"]{--amb:linear-gradient(178deg,#8E2A2A 0%,#C4595B 42%,#F0B1B1 78%,#FDE8E9 100%)}
body[data-act="day"]{--amb:linear-gradient(180deg,#FDE8E9 0%,#F6D3D4 45%,#E7A9AB 100%)}
body[data-act="letter"]{--amb:linear-gradient(180deg,#D8524A 0%,#C13A38 55%,#8E2A2A 100%)}
body[data-act="fast"]{--amb:linear-gradient(180deg,#F3DEDA 0%,#F7E4D6 50%,#FBEADC 100%)}
body[data-act="table"]{--amb:linear-gradient(180deg,#FEFAF8 0%,#FBECE1 45%,#F4D2BD 100%)}
body[data-act="prayer"]{--amb:radial-gradient(90% 70% at 50% 42%,#4A1B22 0%,#260D12 52%,#0C0406 100%)}
body[data-act="slava"]{--amb:radial-gradient(100% 80% at 50% 30%,#7A3418 0%,#3E1512 55%,#170708 100%)}
body[data-act="gift"]{--amb:linear-gradient(180deg,#2A0F14 0%,#5E1F27 50%,#8E2A2A 100%)}
body[data-act="hue"]{--amb:linear-gradient(180deg,var(--hue-a,#EEA8A6) 0%,var(--hue-m,#C25756) 52%,var(--hue-b,#881D1C) 100%)}
body[data-act="word"]{--amb:linear-gradient(180deg,#7E4152 0%,#53283A 55%,#2E1622 100%)}
body[data-act="night"]{--amb:radial-gradient(110% 80% at 50% 50%,#331520 0%,#1A0910 55%,#0A0406 100%)}
body[data-act="finale"]{--amb:radial-gradient(120% 90% at 50% 60%,#C43434 0%,#8E2A2A 40%,#2A0F14 100%)}

/* ==========================================================================
   СВЕТ · layer 2 — stars (canvas painted once; act controls visibility)
   ========================================================================== */
.stars{position:fixed;inset:0;z-index:-5;pointer-events:none;
  opacity:0;transition:opacity 1400ms var(--e-io)}
.stars canvas{position:absolute;inset:0;width:100%;height:100%;
  animation:twinkle 5.5s ease-in-out infinite}
body[data-act="void"] .stars{opacity:.9}
body[data-act="prayer"] .stars{opacity:.75}
body[data-act="slava"] .stars{opacity:.45}
body[data-act="word"] .stars{opacity:.5}
body[data-act="night"] .stars,
body[data-act="finale"] .stars{opacity:.95}
@keyframes twinkle{0%,100%{opacity:.78}50%{opacity:1}}

/* ==========================================================================
   СВЕТ · layer 3 — the day star (sun / moon), positioned by the engine
   ========================================================================== */
.daystar{position:fixed;left:0;top:0;z-index:-4;pointer-events:none;
  width:clamp(64px,7vw,96px);aspect-ratio:1;opacity:0;
  transition:opacity 900ms var(--e-io);will-change:transform}
/* a smaller disc on a narrow sky reads as farther away — more natural */
@media (max-width:900px){.daystar{width:52px}}
.daystar.is-on{opacity:1}
.daystar i{position:absolute;inset:0;border-radius:50%;opacity:0;
  transition:opacity 900ms var(--e-io)}
.daystar__sun{background:radial-gradient(circle at 42% 38%,#FFF3D6,#FFD9A0 45%,#F2A54B 78%);
  box-shadow:0 0 60px 22px rgba(255,190,120,.55),0 0 140px 60px rgba(242,165,75,.28)}
.daystar__moon{background:radial-gradient(circle at 42% 38%,#FFFFFF,#E9ECF6 55%,#C9CFE2 100%);
  box-shadow:0 0 44px 14px rgba(220,228,255,.35);
  -webkit-mask:radial-gradient(circle at 70% 26%, transparent 0 46%, #000 51%);
  mask:radial-gradient(circle at 70% 26%, transparent 0 46%, #000 51%)}
.daystar.is-sun .daystar__sun{opacity:1}
.daystar.is-moon .daystar__moon{opacity:.94}

/* ==========================================================================
   СЦЕНОГРАФИЈА — world-anchored scenery in three parallax depths, dressed
   by the engine along the flight path. Every leg has its own clouds, hills
   and distant flocks, so the viewport backdrop keeps changing as the
   reader travels. The temple is a PLACE now, not wallpaper: it stands at
   the end of the road, appears in the distance on the last legs, and grows
   until the finale parks in front of it. Each layer is a single composited
   transform; the children never move on their own.
   ========================================================================== */
.scenery{position:absolute;left:0;top:0;pointer-events:none;will-change:transform}
/* the triggered ending: each consumer carries its own --ep transition, so
   firing the ending invalidates exactly two elements, not the whole tree */
.ground-foot{--ep:0;transition:--ep 1s var(--e-io) .1s}
body.is-end .ground-foot{--ep:1}
.sc-hram b{--ep:0;transition:--ep 1.5s var(--e-io) .15s}
body.is-end .sc-hram b{--ep:1}
/* how present the clouds are in each act of the day */
body{--cact:.22}
body[data-act="dawn"]{--cact:.8}
body[data-act="day"],body[data-act="fast"],
body[data-act="table"]{--cact:.85}
body[data-act="letter"],body[data-act="gift"],body[data-act="word"]{--cact:.3}
body[data-act="prayer"],body[data-act="slava"]{--cact:.16}
body[data-act="night"],body[data-act="finale"]{--cact:.12}
.sc-cloud{position:absolute;translate:-50% -50%;aspect-ratio:112/60;fill:#fff;
  opacity:calc(var(--o,.8) * var(--cact,.3));transition:opacity 1200ms var(--e-io)}
/* haze per depth: sharp vector geometry at 300px reads as a diagram, not a
   cloud. Static children of a composited layer — the blur renders once. */
@media (min-width:901px){
  .scenery--far .sc-cloud{filter:blur(5px)}
  .scenery--mid .sc-cloud{filter:blur(3px)}
  .scenery--near .sc-cloud{filter:blur(9px)}
}
.sc-jato{position:absolute;translate:-50% -50%;aspect-ratio:52/36;
  fill:rgba(249,230,226,.5)}
.sc-hram{position:absolute;translate:-50% -100%;color:#0D0407;opacity:.92}
.sc-hram img{display:block;width:100%;height:auto}
/* the shelf overshoots far below the frame: iOS grows the viewport when
   Safari collapses its bar (the engine ignores height-only resizes on
   purpose), and the ground must still reach the screen's true bottom */
.sc-hram i{position:absolute;left:50%;bottom:-75%;translate:-50% 0;width:440%;height:86%;
  background:currentColor;border-radius:100% 100% 0 0 / 48.6% 48.6% 0 0}
/* the kandilo: a warm halo behind the dome — the one light of the night */
.sc-hram b{position:absolute;left:50%;top:2%;translate:-50% 0;width:66%;aspect-ratio:1;
  border-radius:50%;pointer-events:none;
  opacity:calc(.82 + var(--ep,0) * .18);
  transform:scale(calc(1 + var(--ep,0) * .14));
  background:radial-gradient(circle,rgba(255,196,120,.30),rgba(217,164,65,.12) 45%,transparent 72%)}
html:not(.js) .scenery,body.flat .scenery{display:none}

/* film grain — static, cheap, no repaint */
.grain{position:fixed;inset:-120%;z-index:-1;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.55'/></svg>");
  mix-blend-mode:overlay}

/* ==========================================================================
   ЛАСТАВИЦА — the guide. The engine flies her ahead of the camera along the
   path tangent; she moves whenever the reader scrolls, and only then.
   ========================================================================== */
.lasta-layer{position:fixed;inset:0;z-index:40;pointer-events:none;overflow:clip}
.lasta-trail{position:absolute;inset:0;width:100%;height:100%}
.lasta{position:absolute;left:0;top:0;width:clamp(40px,4.6vw,62px);opacity:0;
  transition:opacity 1.1s var(--e-out);will-change:transform}
.lasta.is-on{opacity:1}
.lasta__bob{animation:lasta-bob 3.6s ease-in-out infinite}
.lasta__flap{animation:lasta-flap .62s ease-in-out infinite;
  animation-play-state:paused;transform-origin:50% 34%}
.lasta.is-flying .lasta__flap{animation-play-state:running}
.lasta__bird{display:block;width:100%;height:auto;
  transition:transform .5s var(--e-out);
  filter:drop-shadow(0 10px 16px rgba(0,0,0,.32))}
.lasta.is-left .lasta__bird{transform:scaleX(-1)}
.lasta__bird path{fill:#F9E6E2;transition:fill .9s var(--e-io)}
body.act-light .lasta__bird path{fill:var(--deep)}
body.act-light .lasta__bird{filter:drop-shadow(0 8px 14px rgba(142,42,42,.28))}
@keyframes lasta-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(7px)}}
@keyframes lasta-flap{0%,100%{transform:scaleY(1)}45%{transform:scaleY(.72)}}
@media (max-width:900px){.lasta{width:36px}}

/* ==========================================================================
   Chrome: top bar, chapter rail, sticky CTA, progress wick
   ========================================================================== */
.topbar{position:fixed;top:0;left:0;right:0;z-index:60;display:flex;align-items:center;
  justify-content:space-between;gap:16px;
  padding:calc(14px + env(safe-area-inset-top,0px)) clamp(16px,4vw,40px) 14px;
  transition:background .5s var(--e-out),backdrop-filter .5s,border-color .5s;
  border-bottom:1px solid transparent}
.topbar.is-stuck{background:rgba(18,7,9,.72);backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);border-bottom-color:rgba(255,255,255,.10)}
body.act-light .topbar.is-stuck{background:rgba(255,247,247,.78);border-bottom-color:rgba(142,42,42,.14)}

.brand{display:flex;align-items:center;gap:11px;text-decoration:none;font-family:var(--font-display);
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:15px;color:#fff;
  transition:color .5s var(--e-out)}
.brand img{width:34px;height:34px;border-radius:9px;box-shadow:0 4px 14px rgba(0,0,0,.35)}
body.act-light .brand{color:var(--deep)}

.topnav{display:flex;align-items:center;gap:6px}
.topnav a{font-size:13.5px;font-weight:600;text-decoration:none;padding:9px 13px;border-radius:10px;
  color:rgba(255,255,255,.78);transition:background .25s,color .25s}
.topnav a:hover{background:rgba(255,255,255,.12);color:#fff}
body.act-light .topnav a{color:var(--ink-2)}
body.act-light .topnav a:hover{background:rgba(142,42,42,.10);color:var(--deep)}
@media (max-width:800px){.topnav{display:none}}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;text-decoration:none;
  font-weight:700;font-size:14.5px;letter-spacing:.01em;padding:12px 20px;border-radius:999px;
  border:0;cursor:pointer;transition:transform .22s var(--e-out),box-shadow .22s,filter .22s;
  background:linear-gradient(140deg,var(--coral),var(--crimson));color:#fff;
  box-shadow:0 10px 26px -8px rgba(196,52,52,.75),inset 0 1px 0 rgba(255,255,255,.28)}
.btn:hover{transform:translateY(-2px);box-shadow:0 16px 34px -10px rgba(196,52,52,.85)}
.btn:active{transform:translateY(0)}
.btn--ghost{background:rgba(255,255,255,.10);box-shadow:inset 0 0 0 1px rgba(255,255,255,.24)}
body.act-light .btn--ghost{background:rgba(142,42,42,.07);color:var(--deep);
  box-shadow:inset 0 0 0 1px rgba(142,42,42,.22)}
.topbar .btn{padding:10px 17px;font-size:13.5px}

.rail{position:fixed;right:clamp(12px,2vw,26px);top:50%;transform:translateY(-50%);z-index:55;
  display:flex;flex-direction:column;gap:11px;align-items:center}
.rail button{appearance:none;border:0;padding:0;background:transparent;cursor:pointer;
  width:22px;height:22px;display:grid;place-items:center}
.rail button::after{content:'';width:7px;height:7px;border-radius:50%;
  background:rgba(255,255,255,.30);transition:all .35s var(--e-out)}
.rail button[aria-current="true"]::after{background:var(--coral);width:9px;height:9px;
  box-shadow:0 0 0 4px rgba(242,102,75,.22),0 0 14px rgba(242,102,75,.7)}
.rail button:hover::after{background:rgba(255,255,255,.7)}
body.act-light .rail button::after{background:rgba(142,42,42,.28)}
body.act-light .rail button:hover::after{background:rgba(142,42,42,.6)}
@media (max-width:900px),(pointer:coarse){.rail{display:none}}

.wick{position:fixed;top:0;left:0;height:2.5px;z-index:70;width:100%;
  transform-origin:0 50%;transform:scaleX(0);
  background:linear-gradient(90deg,var(--coral),var(--gold));box-shadow:0 0 12px rgba(242,102,75,.8)}

/* ==========================================================================
   THE WORLD — a fixed viewport onto one big canvas. The engine translates
   (and sometimes scales) .world; stations are pinned to world coordinates.
   The .track spacer below the world is what gives the document its scroll.
   ========================================================================== */
.skyworld{position:fixed;inset:0;z-index:1;overflow:clip}
.world{position:absolute;left:0;top:0;will-change:transform}
.track{width:1px}

/* PRVA SLIKA — pre nego što boot() pozove measure(), svaka .station je
   absolute bez top/left, pa svih 13 padne na istu statičku poziciju i
   iscrta se jedna preko druge (a `--e` fallback = 1, dakle pune vidljive).
   Ovaj gate drži tu gomilu van prvog paint-a; site.js skida .ready čim je
   svet postavljen. Namerno `visibility`, ne `display` — layout ostaje, pa
   measure() i fitStations() i dalje čitaju prave visine kutija. */
html.js body:not(.flat):not(.ready) .world{visibility:hidden}

/* A station is one viewport-sized clearing in the sky. */
.station{position:absolute;width:100vw;height:var(--stage-h);
  display:grid;place-items:center;grid-template-rows:minmax(0,1fr);
  padding:clamp(58px,7vh,72px) 0 clamp(16px,3vh,28px);
  perspective:1400px;perspective-origin:50% 45%;
  /* Arrival: the station materialises over the second half of the flight
     leg toward it. Opacity on the perspective holder is safe — the 3D
     lives inside and is grouped whole (same pattern the old stage used). */
  opacity:min(var(--e,1) * 1.9, 1)}
/* stations the camera is nowhere near are culled entirely */
.station[data-idle]{visibility:hidden}
.st-inner{width:var(--measure);height:100%;margin-inline:auto;transform-style:preserve-3d;
  display:grid;place-items:center;align-content:center;position:relative;
  scale:var(--fit,1)}
@media (max-width:900px){.station{perspective:900px}}

/* two-column film frame: copy on one side, device on the other */
.frame{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(28px,5vw,72px);
  align-items:center;width:100%;transform-style:preserve-3d}
.frame__art{position:relative;display:grid;place-items:center;transform-style:preserve-3d;
  min-width:0}
.frame__copy{position:relative;min-width:0;max-width:100%;
  /* copy resolves first as you arrive; the artwork lands after it */
  opacity:min(var(--e,1) * 1.5, 1)}
.frame--flip{grid-template-columns:.98fr 1.02fr}
.frame--flip .frame__copy{order:2}
.frame--flip .frame__art{order:1}

/* ==========================================================================
   Typography
   ========================================================================== */
.eyebrow{display:inline-flex;align-items:center;gap:9px;font-family:var(--font-display);
  font-weight:500;font-size:clamp(11px,1.1vw,12.5px);letter-spacing:.24em;text-transform:uppercase;
  color:var(--coral);margin:0 0 16px}
.eyebrow::before{content:'';width:26px;height:1.5px;background:currentColor;opacity:.6}
body.act-light .eyebrow{color:var(--crimson)}

h1,h2,h3{margin:0;font-family:var(--font-display);font-weight:700;line-height:.98;
  letter-spacing:-.015em;text-transform:uppercase;color:#fff}
body.act-light h2,body.act-light h3{color:var(--deep)}
body.act-light .chip{color:var(--deep)}
h1{font-size:clamp(46px,10.5vw,132px)}
h2{font-size:clamp(32px,min(5.6vw,8.2vh),74px)}
h3{font-size:clamp(19px,2vw,25px);line-height:1.12;letter-spacing:0}
.lede{margin:20px 0 0;font-size:clamp(16px,1.35vw,19px);line-height:1.66;
  color:rgba(255,255,255,.80);max-width:46ch}
body.act-light .lede{color:var(--ink-2)}
@media (max-width:900px){.lede{margin-inline:auto}}

.serif{font-family:var(--font-serif);text-transform:none;letter-spacing:0;font-weight:400}

/* ==========================================================================
   Device — pure CSS bezel, screenshots inside, real 3D
   ========================================================================== */
/* The screen owns the 1206/2622 ratio. With border-box sizing, putting it
   on the padded outer shell squeezed the screen narrower than the image and
   cover-cropped away the app's own side gutters. */
.device{position:relative;width:var(--dw,300px);
  border-radius:calc(var(--dw,300px) * .132);
  background:linear-gradient(150deg,#4A3B3E,#181113 32%,#221719 70%,#3A2C2F);
  padding:calc(var(--dw,300px) * .0225);
  box-shadow:
    0 2px 3px rgba(255,255,255,.16) inset,
    0 -2px 3px rgba(0,0,0,.5) inset,
    0 40px 90px -26px rgba(0,0,0,.72),
    0 10px 30px -12px rgba(0,0,0,.5);
  transform-style:preserve-3d;flex:none}
.device__screen{width:100%;aspect-ratio:1206/2622;border-radius:calc(var(--dw,300px) * .112);
  overflow:hidden;background:#C43434;position:relative;isolation:isolate}
.device__screen img{width:100%;height:100%;object-fit:cover;object-position:top center}
.device::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(118deg,rgba(255,255,255,.20) 0%,rgba(255,255,255,.05) 24%,
    transparent 46%,transparent 78%,rgba(255,255,255,.09) 100%);
  opacity:.75;mix-blend-mode:screen}
.device--lg{--dw:min(30vw,340px,calc(100svh * .285))}
.device--md{--dw:min(24vw,290px,calc(100svh * .250))}
.device--sm{--dw:min(17vw,215px,calc(100svh * .180))}
/* On phones a station is still exactly one viewport, so devices are sized
   from the height budget left under the stacked copy. */
@media (max-width:900px){
  .device--lg,.device--md{--dw:min(72vw,320px,calc(100svh * .26))}
  .device--sm{--dw:min(42vw,200px,calc(100svh * .17))}
}

/* Every chapter's artwork stands in a pool of warm light — it ties the
   composition to the sky instead of leaving it floating on nothing. */
.frame__art::before{content:'';position:absolute;left:50%;top:56%;
  width:min(70vw,560px);aspect-ratio:1;translate:-50% -50%;border-radius:50%;
  pointer-events:none;z-index:-1;
  background:radial-gradient(circle,rgba(242,102,75,.30),rgba(196,52,52,.12) 42%,transparent 68%);
  filter:blur(28px)}
body.act-light .frame__art::before{
  background:radial-gradient(circle,rgba(224,127,57,.22),rgba(217,164,65,.10) 42%,transparent 68%)}

/* ==========================================================================
   ПРЕЛУДИЈУМ — hero under the pre-dawn sky
   ========================================================================== */
.hero{position:relative;display:grid;place-items:center;text-align:center;
  transform-style:preserve-3d;width:100%}
/* The hero says goodbye on --x — it dissolves as the camera actually
   departs, not while the reader is still with it. */
.hero__mark{width:clamp(74px,11vw,116px);height:auto;border-radius:24px;
  box-shadow:0 26px 60px -18px rgba(0,0,0,.75),0 0 0 1px rgba(255,255,255,.10);
  transform:translate3d(0,calc(var(--x,0) * -60px),calc(var(--x,0) * 190px)) rotate(calc(var(--x,0) * -6deg));
  transition:none}
.hero__title{margin:clamp(20px,3.4vh,34px) 0 0;color:#fff;
  text-shadow:0 22px 60px rgba(0,0,0,.5);
  transform:translate3d(0,calc(var(--x,0) * -34px),calc(var(--x,0) * 320px));
  opacity:calc(1 - var(--x,0) * 1.25)}
.hero__title span{display:block}
/* Ц carries a descender; at line-height .98 its tail lands ON the С below
   it — measured overlap of 3.1% of the font size at every clamp step. A
   margin in em opens a hairline of sky between the two words and scales
   with the title instead of being tuned per breakpoint. */
.hero__title .l2{margin-top:.07em;color:var(--coral);
  background:linear-gradient(180deg,#FFC9BB,#F2664B 55%,#C43434);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.hero__sub{margin:18px auto 0;max-width:44ch;color:rgba(255,255,255,.72);
  font-size:clamp(15px,1.25vw,18px);
  transform:translate3d(0,calc(var(--x,0) * -20px),calc(var(--x,0) * 220px));
  opacity:calc(1 - var(--x,0) * 1.6)}
.hero__badges{margin-top:clamp(22px,3.4vh,34px);display:flex;gap:12px;justify-content:center;
  flex-wrap:wrap;opacity:calc(1 - var(--x,0) * 1.9);
  transform:translate3d(0,0,calc(var(--x,0) * 160px))}
@media (min-width:901px){
  /* equal pill widths: the pulsing cue sits on the viewport centre line,
     so the gap between the pair must sit there too */
  .hero__badges .btn{width:212px;white-space:nowrap}
}

.hero__jato{position:absolute;inset:-8% -4%;pointer-events:none;z-index:-1}
.hero__jato .j{position:absolute;width:30px;aspect-ratio:52/36;fill:rgba(249,230,226,.6);
  animation:jato-f 7s ease-in-out infinite}
.hero__jato .j1{left:12%;top:8%;animation-delay:0s}
.hero__jato .j2{left:78%;top:16%;width:22px;animation-delay:-2.4s;fill:rgba(249,230,226,.42)}
.hero__jato .j3{left:64%;top:2%;width:17px;animation-delay:-4.6s;fill:rgba(249,230,226,.30)}
@keyframes jato-f{0%,100%{transform:translate(0,0) rotate(-3deg)}
  50%{transform:translate(10px,-12px) rotate(4deg)}}

.rays{position:absolute;left:50%;top:42%;width:min(120vw,1100px);aspect-ratio:1;
  translate:-50% -50%;pointer-events:none;z-index:-1;opacity:calc(.65 - var(--x,0) * .6);
  background:
    conic-gradient(from 0deg,transparent 0deg,rgba(255,190,170,.16) 6deg,transparent 12deg,
      transparent 42deg,rgba(255,190,170,.13) 48deg,transparent 54deg,
      transparent 90deg,rgba(255,190,170,.16) 96deg,transparent 102deg,
      transparent 138deg,rgba(255,190,170,.11) 144deg,transparent 150deg,
      transparent 186deg,rgba(255,190,170,.15) 192deg,transparent 198deg,
      transparent 234deg,rgba(255,190,170,.12) 240deg,transparent 246deg,
      transparent 282deg,rgba(255,190,170,.15) 288deg,transparent 294deg,
      transparent 330deg,rgba(255,190,170,.12) 336deg,transparent 342deg);
  transform:rotate(calc(var(--p) * 26deg));
  mask-image:radial-gradient(circle,#000 12%,transparent 68%);
  -webkit-mask-image:radial-gradient(circle,#000 12%,transparent 68%)}

/* width:max-content — the abspos box at left:50% otherwise only gets the
   right half of .st-inner and the caption wraps into the buttons above */
.scroll-cue{position:absolute;left:50%;bottom:clamp(18px,4vh,42px);translate:-50% 0;
  width:max-content;
  display:grid;justify-items:center;gap:9px;font-family:var(--font-display);font-size:10.5px;
  letter-spacing:.28em;text-transform:uppercase;color:rgba(255,255,255,.55);
  opacity:calc(1 - var(--p) * 3)}
.scroll-cue i{width:1.5px;height:38px;background:linear-gradient(180deg,transparent,var(--coral));
  animation:wick 2.1s var(--e-io) infinite}
@keyframes wick{0%,100%{transform:scaleY(.35);opacity:.35;transform-origin:50% 0}
  50%{transform:scaleY(1);opacity:1;transform-origin:50% 0}}

/* ==========================================================================
   Arrivals — devices land a beat after the copy
   ========================================================================== */
.fly{transform:
    translate3d(0, calc((1 - var(--e)) * 5vh), calc(-500px + var(--e) * 500px))
    rotateY(calc((1 - var(--e)) * -20deg))
    rotateX(calc((1 - var(--e)) * 8deg));
  opacity:clamp(0, calc((var(--e) - .25) * 2.6), 1)}
@media (max-width:900px){
  .fly{transform:
    translate3d(0, calc((1 - var(--e)) * 4vh), calc(-520px + var(--e) * 520px))
    rotateY(calc((1 - var(--e)) * -14deg))
    rotateX(calc((1 - var(--e)) * 7deg))}
}

/* Scrubbed reveals — the journey's own language. Every element resolves on
   --e (arrival), staggered by data-d, as a pure fade with a breath of
   scale: no direction (nothing "comes from below" any more), and fully
   reversible — scroll back and the chapter un-resolves, like everything
   else in the world. No observers, no timers. */
.rise{--d:0;--rv:min(max((var(--e,1) - var(--d)) * 3.2, 0), 1);
  opacity:var(--rv);
  transform:scale(calc(.985 + var(--rv) * .015))}
.rise[data-d="1"]{--d:.08}
.rise[data-d="2"]{--d:.16}
.rise[data-d="3"]{--d:.24}
.rise[data-d="4"]{--d:.32}
.rise[data-d="5"]{--d:.40}

/* ==========================================================================
   II · ЈУТРО — the saint: arched icon + day detail
   ========================================================================== */
.arch{position:relative;width:min(44%,300px);aspect-ratio:3/4.1;flex:none;
  border-radius:999px 999px 22px 22px;overflow:hidden;
  box-shadow:0 40px 80px -30px rgba(0,0,0,.6),0 0 0 10px rgba(255,255,255,.9),
    0 0 0 11px rgba(142,42,42,.16);
  transform:rotateY(calc((var(--p) - .5) * -14deg))
            translateZ(calc(-260px + var(--e) * 320px))
            translateY(calc((1 - var(--e)) * 5vh));
  opacity:clamp(0, calc((var(--e) - .25) * 2.6), 1)}
.arch img{width:100%;height:100%;object-fit:cover}
/* chips are typography now, not glass pills — a word with a thin keel,
   standing directly on the sky */
.chips{display:flex;flex-wrap:wrap;gap:8px 22px;margin-top:22px;justify-content:inherit}
@media (max-width:900px){.chips{justify-content:center}}
.chip{display:inline-flex;align-items:center;gap:7px;padding:6px 1px;
  font-size:13.5px;font-weight:600;color:rgba(255,255,255,.92);
  border-bottom:1.5px solid rgba(255,255,255,.30)}
body.act-light .chip{color:var(--deep);border-bottom-color:rgba(142,42,42,.34)}
.chip--ok{color:#E8F0D4;border-bottom-color:rgba(158,182,98,.65)}
body.act-light .chip--ok{color:#3F4C1E;border-bottom-color:rgba(122,142,74,.6)}
.chip--no{color:#F3C9C9;border-bottom-color:rgba(196,74,74,.6)}
body.act-light .chip--no{color:#7C2A2A;border-bottom-color:rgba(142,42,42,.45)}

/* ==========================================================================
   III · ПРЕПОДНЕ — red letter / black letter
   ========================================================================== */
.letterstage{position:relative;display:grid;place-items:center;width:100%;
  transform-style:preserve-3d;text-align:center;
  opacity:min(var(--e,1) * 1.5, 1)}
.letterstage h2{font-size:clamp(27px,min(4.5vw,6.4vh),56px)}
.letterstage .lede{margin-top:12px;max-width:58ch;font-size:clamp(14px,1.15vw,16.5px);
  line-height:1.55}
.letterstage .eyebrow{margin-bottom:10px}
@media (max-height:820px) and (min-width:901px){
  .letterstage h2{font-size:clamp(26px,3.6vw,44px)}
  .letterstage .lede{font-size:14.5px}
}
.bigletter{font-family:var(--font-serif);font-size:clamp(210px,44vw,560px);line-height:.78;
  color:#fff;opacity:.10;position:absolute;left:50%;top:50%;pointer-events:none;
  user-select:none;-webkit-user-select:none;translate:-50% -50%;
  transform:translateZ(-420px) scale(calc(1 + var(--p) * .30)) rotate(calc(var(--p) * 4deg))}
.duo{display:flex;gap:clamp(14px,3vw,42px);align-items:center;justify-content:center;
  transform-style:preserve-3d}
.duo .device{opacity:clamp(0, calc((var(--e) - .25) * 2.6), 1)}
.duo .device:nth-child(1){transform:
  rotateY(calc(20deg - var(--p) * 26deg))
  translateZ(calc(-420px + var(--e) * 490px + var(--p) * 70px))
  translateX(calc(var(--p) * -12px))}
.duo .device:nth-child(2){transform:
  rotateY(calc(-20deg + var(--p) * 26deg))
  translateZ(calc(-420px + var(--e) * 490px + var(--p) * 70px))
  translateX(calc(var(--p) * 12px))}
.legend{display:flex;gap:clamp(12px,2.4vw,30px);flex-wrap:wrap;justify-content:center;
  margin-top:clamp(30px,4.6vh,52px)}
.legend div{display:flex;align-items:center;gap:9px;font-size:13.5px;font-weight:600;color:#fff}
.dot{width:13px;height:13px;border-radius:50%;flex:none;box-shadow:0 0 0 3px rgba(255,255,255,.14)}
.dot--red{background:#C43434}
.dot--black{background:#2E2426}
.dot--plain{background:#FDE8E9}

/* ==========================================================================
   VI · ВЕЧЕРЊЕ — prayer (candlelit)
   ========================================================================== */
.candle{position:absolute;left:50%;top:50%;translate:-50% -50%;width:min(90vw,760px);
  aspect-ratio:1;pointer-events:none;z-index:-1;
  background:radial-gradient(circle,rgba(255,196,120,.30),rgba(217,164,65,.12) 34%,transparent 64%);
  filter:blur(20px);
  transform:scale(calc(.75 + var(--p) * .5));opacity:calc(.35 + var(--p) * .55)}
.flame{width:13px;height:26px;border-radius:50% 50% 46% 46%;margin:0 auto 16px;
  background:radial-gradient(ellipse at 50% 72%,#FFF3D0,#FFB44D 42%,#E8503A 78%,transparent);
  box-shadow:0 0 26px 8px rgba(255,170,80,.55);animation:flicker 2.6s ease-in-out infinite}
@keyframes flicker{0%,100%{transform:scaleY(1) scaleX(1);opacity:1}
  35%{transform:scaleY(1.10) scaleX(.94);opacity:.9}
  62%{transform:scaleY(.95) scaleX(1.04);opacity:1}}


/* ==========================================================================
   VII · СЛАВА — 3D ring of icons around the phone
   ========================================================================== */
.ring{position:absolute;left:50%;top:50%;translate:-50% -50%;--rad:212px;
  width:min(86vw,470px);aspect-ratio:1;transform-style:preserve-3d;pointer-events:none;
  transform:rotateX(72deg) rotateZ(calc(var(--p) * 300deg))}
.ring span{position:absolute;left:50%;top:50%;width:66px;height:66px;margin:-33px 0 0 -33px;
  transform-style:preserve-3d;
  transform:rotateZ(calc(var(--a) * 1deg)) translateX(var(--rad,150px))}
.ring span img{width:100%;height:100%;object-fit:cover;border-radius:50%;opacity:.92;
  box-shadow:0 0 0 3px rgba(255,255,255,.85),0 16px 30px -12px rgba(0,0,0,.7);
  transform:rotateZ(calc((0 - var(--a) - var(--p) * 300) * 1deg)) rotateX(-72deg)}
@media (max-width:900px){
  .ring{position:static;translate:none;transform:none;width:auto;aspect-ratio:auto;
    display:flex;gap:10px;justify-content:center;margin:0 0 18px}
  .ring span{position:static;width:52px;height:52px;margin:0;transform:none}
  .ring span img{transform:none;opacity:1}
}


/* ==========================================================================
   VIII · РАДОСТ — greeting card flip beside the real screen
   ========================================================================== */
.flipper{--flip:clamp(0,calc((var(--p) - .26) * 2.6),1);
  width:min(58vw,250px);aspect-ratio:3/4.4;position:relative;transform-style:preserve-3d;
  transform:rotateY(calc(var(--flip) * 180deg)) translateZ(calc(var(--p) * 40px));
  flex:none}
.flipper > div{position:absolute;inset:0;border-radius:24px;backface-visibility:hidden;
  -webkit-backface-visibility:hidden;display:grid;align-content:center;justify-items:center;
  gap:11px;padding:26px 20px;text-align:center;overflow:hidden;
  box-shadow:0 40px 80px -30px rgba(0,0,0,.7),inset 0 0 0 1px rgba(255,255,255,.18)}
.flip-front{background:linear-gradient(168deg,#3E6BEF 0%,#2547CD 52%,#15239E 100%)}
/* the card's own little sky: two swallows, two clouds, a scatter of stars —
   drawn from the same symbols the world uses */
.fc-deko{position:absolute;inset:0;pointer-events:none;overflow:hidden;border-radius:inherit}
.fc-deko .d{position:absolute;aspect-ratio:52/36;fill:#fff;opacity:.85}
.fc-deko .d1{left:9%;top:7%;width:26px}
.fc-deko .d2{left:23%;top:14%;width:16px;opacity:.65}
.fc-deko .d3{right:-11%;top:4%;width:64px;aspect-ratio:112/60;opacity:.14}
.fc-deko .d4{left:-12%;bottom:-14%;width:96px;aspect-ratio:112/60;opacity:.13}
.fc-deko i{position:absolute;left:0;top:0;width:3px;height:3px;border-radius:50%;
  background:rgba(255,255,255,.75);
  box-shadow:44px 34px 0 -1px rgba(255,255,255,.5),198px 26px 0 -1px rgba(255,255,255,.65),
    176px 96px 0 -1.4px rgba(255,255,255,.45),226px 152px 0 -1px rgba(255,255,255,.6),
    18px 176px 0 -1.4px rgba(255,255,255,.4),214px 268px 0 -1px rgba(255,255,255,.55),
    36px 300px 0 -1.4px rgba(255,255,255,.45),118px 332px 0 -1px rgba(255,255,255,.5)}
.flip-back{background:linear-gradient(168deg,#2C50D8 0%,#16249C 100%);transform:rotateY(180deg)}
.flipper img{width:64px;height:64px;border-radius:50%;object-fit:cover;
  box-shadow:0 0 0 3px rgba(255,255,255,.85)}
.flipper .k{font-family:var(--font-display);font-size:10.5px;letter-spacing:.26em;
  text-transform:uppercase;color:rgba(255,255,255,.72)}
.flipper .t{font-family:var(--font-display);font-size:21px;line-height:1.12;color:#fff}
.flipper .b{font-size:13px;line-height:1.5;color:rgba(255,255,255,.9)}
.flipper .f{display:flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--font-display);font-size:9.5px;letter-spacing:.24em;
  text-transform:uppercase;color:rgba(255,255,255,.78);padding-top:4px;width:100%}
.flipper .f::before,.flipper .f::after{content:'';flex:1;max-width:42px;height:1px;
  background:rgba(255,255,255,.38)}
.flipper .f img{width:12px;height:auto;border-radius:0;box-shadow:none}

/* ==========================================================================
   IX · ВАША БОЈА — palettes
   ========================================================================== */

.hue-name{margin:20px 0 0;font-family:var(--font-serif);
  font-size:clamp(30px,3.4vw,46px);line-height:1;color:#fff;opacity:.95}
.hue-name.tick{animation:hue-tick .45s var(--e-out)}
@keyframes hue-tick{from{opacity:.15;translate:0 8px}to{opacity:.95;translate:0 0}}

/* ==========================================================================
   X · РЕЧ ПО РЕЧ — manuscript
   ========================================================================== */
.paper{background:linear-gradient(180deg,#FFFDFB,#FBF2EC);border-radius:var(--r-lg);
  padding:clamp(24px,3.6vw,44px);color:var(--paper-ink);text-align:left;
  box-shadow:0 40px 80px -34px rgba(120,60,40,.5),inset 0 0 0 1px rgba(255,255,255,.9);
  max-width:560px;width:100%;position:relative;overflow:hidden}
.paper::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,var(--crimson),var(--gold))}
.paper h3{color:var(--deep)}
.paper p{margin:12px 0 0;font-size:15px;line-height:1.66;color:#5C4741}
.paper .drop{float:left;font-family:var(--font-serif);font-size:62px;line-height:.82;
  color:var(--crimson);margin:4px 12px 0 0}
.marginalia{margin-top:20px;padding:13px 16px;border-left:3px solid var(--crimson);
  background:rgba(196,52,52,.06);border-radius:0 12px 12px 0}
.marginalia b{display:block;font-family:var(--font-display);font-size:10.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--crimson);margin-bottom:5px}
.marginalia span{font-size:14px;color:#5C4741}


/* ==========================================================================
   XI · ПРЕД СПАВАЊЕ — the real home-screen widget, cut straight from the
   simulator screenshot: one widget, centred and generous, not a collage.
   ========================================================================== */
.nightdesk{position:relative;display:grid;place-items:center;width:100%}
.nightdesk .w-md{width:min(30vw,420px);height:auto;border-radius:11%/24%;
  box-shadow:0 30px 60px -24px rgba(0,0,0,.78),0 0 0 1px rgba(255,255,255,.10)}

.notif-img{margin-top:22px;width:min(100%,430px);height:auto;
  border-radius:4.4%/25%;
  box-shadow:0 18px 40px -18px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.08)}
@media (max-width:900px){.notif-img{margin-inline:auto}}

/* ==========================================================================
   ФИНАЛЕ — nineteen screens on the night ring, the flock over the dome
   ========================================================================== */
/* the flock at home — the app's own church-sky composition: swallows stand
   in the air around the dome and drift gently. Nothing orbits, nothing
   loops; each bird has its own pose, tilt and side. */
/* UGAŠENO. Ovo jato je živelo UNUTAR `.st-inner`, dakle u tekstualnom bloku, a
   ne u sceni — pa se pomeralo sa tekstom i padalo tačno preko njega. Mereno na
   375×812: blok je stajao od 185 do 303 po visini, a tekst zauzima 127 do 377.
   Sve dok postoji, dva odvojena izvora ptica se otimaju oko istog mesta i
   nijedno podešavanje u `site.js` ne može da ga dohvati.
   Lastavice oko hrama sada dolaze ISKLJUČIVO iz scene (`buildScenery`), gde su
   vezane za samu siluetu i provereno padaju iznad nje, van teksta i u kadru.
   Stilovi ostaju da bi povratak bio jedan red. */
.finale-jato{position:absolute;left:54%;top:30%;translate:-50% -50%;
  width:min(30vw,340px);aspect-ratio:1.4;
  pointer-events:none;opacity:calc(min(var(--e,1) * 1.3, 1) * .6);
  display:none}
.finale-jato .fj{position:absolute;aspect-ratio:52/36;fill:rgba(249,230,226,.75);
  animation:jato-f 7s ease-in-out infinite}
.finale-jato .fj1{left:4%;top:40%;width:26px;rotate:-8deg}
.finale-jato .fj2{left:26%;top:10%;width:21px;rotate:6deg;animation-delay:-2.1s}
.finale-jato .fj3{left:56%;top:2%;width:24px;rotate:-5deg;scale:-1 1;animation-delay:-3.4s}
.finale-jato .fj4{left:80%;top:26%;width:18px;rotate:10deg;animation-delay:-4.8s;
  fill:rgba(249,230,226,.6)}
.finale-jato .fj5{left:42%;top:56%;width:16px;rotate:-12deg;scale:-1 1;
  animation-delay:-5.9s;fill:rgba(249,230,226,.5)}

/* The closing shot mirrors the opening: words directly on the sky, no box.
   The journey ends at the temple — nothing may stand in front of it but
   the title and the two badges. A soft pool of shadow keeps the type
   readable; it is light and air, not a panel. */
.finale{position:relative;z-index:2;text-align:center;display:grid;justify-items:center;gap:8px;
  padding:clamp(10px,2vw,20px);max-width:min(92vw,760px)}
.finale::before{content:'';position:absolute;inset:-14% -20%;z-index:-1;pointer-events:none;
  background:radial-gradient(58% 54% at 50% 44%,rgba(10,3,5,.52),transparent 72%)}
.finale h2{text-shadow:0 14px 54px rgba(0,0,0,.7),0 3px 14px rgba(0,0,0,.55)}
.finale .lede{color:rgba(255,255,255,.88);text-shadow:0 2px 16px rgba(0,0,0,.6)}
/* NA ŠIROKOM EKRANU tekst i hram dele kadar po širini: hram je u site.js
   izmaknut udesno (hox 0.26), a tekst se ovde povlači ulevo i sužava. Pomeraj
   je `translate`, ne margina — blok ostaje centriran u rasporedu, pa se ništa
   ispod njega ne pomera. Merenje na 1280: hram zauzima od -7 do +673 od ose
   stanice, tekst od -560 do -80, dakle 73px vazduha između. */
@media (min-width:901px){
  .finale{max-width:min(40vw,480px);translate:calc(-1 * min(25vw,320px)) 0}
}
/* NA TELEFONU se razdvajaju po VISINI: hram ostaje gde je bio, a tekst se
   diže iznad njegovog vrha.
   Mereno na snimku, iPhone X 375×812, sa podizanjem od 110px: vrh krsta je
   pao na 419px od vrha prozora, a donja ivica značaka na 441 — dakle 22px
   preklopa, krst je ulazio među značke. 160px podiže tekst za još 49 i daje
   oko 30px vazduha. Gore je bezbedno: gornja ivica teksta ide sa 188 na 139,
   a zaglavlje se završava na 73. Ako zatreba više, menja se SAMO ovaj broj. */
@media (max-width:900px){
  .finale{translate:0 calc(-1 * min(19vh,160px))}
}

.stores{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:26px}
/* the quiet close: the footer is RENDERED INTO THE GROUND — the dark
   earth band at the foot of the temple carries the legal and credit lines,
   like an inscription at the base of the final frame */
.ground-foot{position:absolute;left:0;right:0;text-align:center;z-index:3;
  bottom:calc(6px + env(safe-area-inset-bottom,0px));
  opacity:min(var(--ep,0) * 2.2, 1);
  -webkit-mask-image:linear-gradient(90deg,#000 calc(var(--ep,0) * 118%),
    transparent calc(var(--ep,0) * 118% + 14%));
  mask-image:linear-gradient(90deg,#000 calc(var(--ep,0) * 118%),
    transparent calc(var(--ep,0) * 118% + 14%))}
.fine{margin:0 0 5px;font-size:11.5px;letter-spacing:.04em;color:rgba(255,255,255,.55);
  text-shadow:0 1px 8px rgba(0,0,0,.5)}
.fine a{text-decoration:none;color:rgba(255,255,255,.72)}
.fine a:hover{color:#fff;text-decoration:underline}
.fine--dim{margin-bottom:0;font-size:10.5px;color:rgba(255,255,255,.36)}
.stores a{display:block;transition:transform .25s var(--e-out),filter .25s}
.stores a:hover{transform:translateY(-3px) scale(1.02)}
.stores img{height:clamp(44px,5.4vw,54px);width:auto}


/* ==========================================================================
   Motion safety
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important}
  .ring,.stars,.lasta-layer,.daystar,.finale-jato,.hero__jato{display:none}
  .scroll-cue i{animation:none}
  .flip-back{display:none}
}

/* devices without hover: kill hover lifts so taps don't stick */
@media (hover:none){
  .btn:hover,.stores a:hover{transform:none}
}

/* ==========================================================================
   Static fallback — no JavaScript, or reduced motion (body.flat is added by
   the engine when the user prefers reduced motion). The world unrolls into
   a plain, complete, scrollable document.
   ========================================================================== */
html:not(.js) .skyworld,body.flat .skyworld{position:static;inset:auto;overflow:visible}
html:not(.js) .world,body.flat .world{position:static;transform:none !important}
html:not(.js) .station,body.flat .station{position:static;width:auto;height:auto;
  opacity:1;visibility:visible;padding:clamp(48px,9vh,104px) var(--gut);perspective:none}
html:not(.js) .st-inner,body.flat .st-inner{height:auto;scale:1;width:min(100%,1180px)}
html:not(.js) .track,body.flat .track{display:none}
html:not(.js) .rise,body.flat .rise,
html:not(.js) .fly,body.flat .fly,
html:not(.js) .device,body.flat .device,
html:not(.js) .arch,body.flat .arch,
html:not(.js) .flipper,body.flat .flipper,
html:not(.js) .hero__mark,body.flat .hero__mark,
html:not(.js) .hero__title,body.flat .hero__title,
html:not(.js) .hero__sub,body.flat .hero__sub,
html:not(.js) .hero__badges,body.flat .hero__badges,
html:not(.js) .frame__copy,body.flat .frame__copy,
html:not(.js) .letterstage,body.flat .letterstage,
html:not(.js) .duo .device,body.flat .duo .device{opacity:1;transform:none}
html:not(.js) .ring,body.flat .ring,
html:not(.js) .flip-back,body.flat .flip-back,
html:not(.js) .bigletter,body.flat .bigletter,
html:not(.js) .scroll-cue,body.flat .scroll-cue,
html:not(.js) .rays,body.flat .rays,
html:not(.js) .lasta-layer,body.flat .lasta-layer,
html:not(.js) .daystar,body.flat .daystar,
html:not(.js) .stars,body.flat .stars,
html:not(.js) .finale-jato,body.flat .finale-jato,
html:not(.js) .hero__jato,body.flat .hero__jato{display:none}
html:not(.js) .ambient,body.flat .ambient{background-image:var(--amb)}
html:not(.js) .nightdesk img,body.flat .nightdesk img{position:static;transform:none;
  margin:8px auto 0}
html:not(.js) .ground-foot,body.flat .ground-foot{position:static;margin-top:24px;
  opacity:1;-webkit-mask:none;mask:none}

/* ==========================================================================
   Lightbox — tap a screenshot on a phone, see it full screen. One layer,
   opacity only: the story engine keeps running untouched behind it.
   ========================================================================== */
/* cursor on the tap target also makes old iOS synthesise click events for
   delegated listeners */
@media (max-width:900px){.device__screen{cursor:zoom-in}}
.lightbox{position:fixed;inset:0;z-index:90;display:grid;place-items:center;
  padding:6vw;background:rgba(12,4,7,.9);touch-action:none;
  opacity:0;transition:opacity .24s var(--e-out)}
/* author display beats the UA [hidden] rule — without this the closed
   overlay kept swallowing every touch and the page stopped scrolling */
.lightbox[hidden]{display:none}
.lightbox.on{opacity:1}
.lightbox img{max-width:100%;max-height:86svh;border-radius:14px;
  box-shadow:0 30px 80px -20px rgba(0,0,0,.85);
  transform:scale(.96);transition:transform .24s var(--e-out)}
.lightbox.on img{transform:none}

/* A trailing sentence per chapter: carried on desktop, dropped on phones. */
@media (max-width:900px){ .long{display:none} }

/* ==========================================================================
   PHONE OVERRIDES — deliberately last. The camera engine is identical on
   phones; only sizing and density change here.
   ========================================================================== */
@media (max-width:900px){
  /* the fixed topbar is 71px tall: the top reserve is its height plus real
     breathing room, so chapters centre BETWEEN the bar and the floor
     instead of kissing the bar edge-to-edge. The prelude keeps its own
     tighter reserve — its stack plus the scroll cue already spend every
     pixel of a short phone, and it never had the kissing problem. */
  .station{padding:96px 0 56px}
  #pocetak.station{padding-top:64px}
  .st-inner{width:calc(100% - 15vw)}

  /* ONE chapter = ONE message + ONE visual on a phone. The secondary item
     of every pair is dropped instead of shrinking everything to fit. */
  .duo > :nth-child(2){display:none}
  /* chapter II keeps the FULL day screenshot on phones, not the cropped
     arch icon — the phone frame carries the whole scene there */
  #svetitelj .duo > :nth-child(2){display:block}
  #svetitelj .arch{display:none}
  #svetitelj .duo .device--sm{--dw:min(62vw,270px,calc(100svh * .27))}
  .marginalia{display:none}
  .chips .chip:nth-child(n+5){display:none}

  .duo{gap:8px;width:100%;justify-content:center;flex-wrap:wrap}
  .duo .device--sm{--dw:min(56vw,240px,calc(100svh * .24))}
  .duo .device--md{--dw:min(60vw,270px,calc(100svh * .27))}
  .duo .device:nth-child(1),
  .duo .device:nth-child(2){transform:none}
  .arch{width:min(38vw,180px)}
  .legend{margin-top:18px}
  .letterstage .lede{margin-bottom:4px}

  .frame,.frame--flip{grid-template-columns:1fr;gap:clamp(16px,3vh,28px);
    justify-items:center;text-align:center}
  .frame--flip .frame__copy,.frame--flip .frame__art{order:initial}
  .frame__copy{order:1}
  .frame__art{order:2}

  h2{font-size:clamp(26px,7.2vw,36px);line-height:1.0}
  .lede{font-size:14.5px;line-height:1.55;margin-top:11px;max-width:34ch}
  .eyebrow{margin-bottom:10px;font-size:11px;letter-spacing:.2em}
  .chips{gap:7px;margin-top:14px;flex-wrap:wrap;justify-content:center}
  .chip{font-size:12px;padding:6px 12px}
  .paper{padding:18px}
  .paper p{font-size:13.5px}
  .flipper{width:min(48vw,200px)}
  /* the flip card's content must fit ITS box on a narrow screen — scaled
     type and icon, or the saint's image pushes out through the card edge */
  .flipper > div{padding:18px 14px;gap:7px}
  .flipper img{width:44px;height:44px}
  .flipper .k{font-size:9px;letter-spacing:.2em}
  .flipper .t{font-size:16px}
  .flipper .b{font-size:11.5px;line-height:1.45}
  .flipper .f{font-size:8.5px;padding-top:8px;gap:5px}
  /* the wordmark glyph is 61x90 — a forced square squashed the letter */
  .flipper .f img{width:10px;height:auto}
  /* the manuscript is a desktop pleasure — on a phone it is a wall of text */
  .paper{display:none}
  .nightdesk .w-md{width:min(80vw,380px)}


  .hero__mark{width:clamp(64px,17vw,84px)}
  .hero__title{font-size:clamp(44px,15vw,68px)}
  .hero__sub{font-size:15.5px;margin-top:14px}
  .hero__badges{margin-top:26px;flex-direction:column;align-items:center;gap:10px}
  .hero__badges .btn{width:min(78vw,300px)}
  /* a shorter wick keeps the cue clear of the stacked buttons on short svh */
  .scroll-cue i{height:26px}
  /* reserve the cue's zone inside the centering box: the hero content
     centers above it instead of descending into the caption on short svh.
     The absolutely positioned cue itself is anchored to the padding box
     edge, so this padding lifts the buttons without moving the cue. */
  #pocetak .st-inner{padding-bottom:104px}

  /* the finale sky on a tall screen: light stays low, behind the temple,
     so the silhouette reads instead of sinking into near-black maroon */
  body[data-act="finale"]{--amb:radial-gradient(150% 72% at 50% 74%,#D9463F 0%,#98302B 50%,#4A1720 100%)}
  /* no kandilo on phones: approaching the finale it enters the frame ahead
     of the silhouette and hangs as a bare blob of light. The brighter
     finale gradient carries the dome by itself here. */
  .sc-hram b{display:none}
  /* Full ink on phones. NO filter here: iOS WebKit combines a CSS filter
     with the SVG mask by drawing only the drop-shadow and losing the
     source itself — the temple rendered as a ghost outline of its own
     shadow. Contrast comes from the brighter finale gradient instead. */
  .sc-hram{opacity:1}

  /* GPU diet: a full-screen blend mode is invisible on a small screen and
     expensive on a mobile GPU */
  .grain{display:none}
  /* backdrop-filter re-blurs the moving world under the bar EVERY frame on
     iOS — the verified top jank source on iPhone. Phones get a denser flat
     bar instead; the glass stays on desktop. */
  .topbar{transition:background .5s var(--e-out),border-color .5s}
  .topbar.is-stuck{background:rgba(18,7,9,.9);
    backdrop-filter:none;-webkit-backdrop-filter:none}
  body.act-light .topbar.is-stuck{background:rgba(255,247,247,.92)}
  /* two cloud depths on phones — a light haze tells them apart, rendered
     once (static children of a composited layer) */
  .scenery--far .sc-cloud{filter:blur(3px)}
  .scenery--mid .sc-cloud{filter:blur(2px)}

  /* ГЛАТКИ ПРЕЛАЗИ — proven on WebKit at DPR 3: the leg jank is raster
     volume, not JS. Three moves, measured together:
     1. every live station is its own compositor layer, rasterised ONCE on
        the plateau (where materialisation already happens) — the flight
        then composites finished textures instead of rasterising fresh
        tiles mid-leg;
     2. arrivals stop being scroll-scrubbed: a .lit class fires a normal
        CSS transition, which WebKit promotes to the compositor for its
        duration — nothing dirties the station layer while the camera
        flies;
     3. the two per-frame repainters are silenced: the candle's blurred
        halo no longer re-scales with --p (opacity still breathes, that is
        compositor-free on its filtered layer), and the sun and moon get
        their own layer for the per-frame transform. */
  html.js body:not(.flat) .station:not([data-idle]){will-change:transform}
  html.js body:not(.flat) .daystar{will-change:transform}
  html.js body:not(.flat) .rays{transform:none}
  /* the candle's blur(20px) halo re-renders on EVERY scrubbed change —
     frozen entirely on phones, it rasterises once (the flame keeps its
     живи flicker: transform/opacity animations composite for free) */
  html.js body:not(.flat) .candle{transform:scale(1.05);opacity:.62}
  html.js body:not(.flat) .rise{opacity:0;transform:translate3d(0,10px,0);
    transition:opacity .5s var(--e-out),transform .5s var(--e-out);
    transition-delay:calc(var(--d) * 120ms)}
  html.js body:not(.flat) .station.lit .rise{opacity:1;transform:none}
  html.js body:not(.flat) .frame__copy{opacity:0;transition:opacity .45s var(--e-out)}
  html.js body:not(.flat) .station.lit .frame__copy{opacity:1}
  html.js body:not(.flat) .fly{transform:translate3d(0,18px,0);opacity:0;
    transition:transform .6s var(--e-out) .12s,opacity .6s var(--e-out) .12s}
  html.js body:not(.flat) .station.lit .fly{transform:none;opacity:1}
  html.js body:not(.flat) .duo .device{opacity:0;transition:opacity .5s var(--e-out)}
  html.js body:not(.flat) .station.lit .duo .device{opacity:1}
}

/* Landscape phones report >900px width but have no height for a two-column
   film frame — treat "short" like a phone where it counts. */
@media (min-width:901px) and (max-height:520px){
  .station{padding-top:50px}
  h2{font-size:clamp(24px,6vh,40px)}
  .lede{font-size:14px;margin-top:10px}
  .frame{gap:clamp(20px,3vw,40px)}
}
