/* ═══════════════════════════════════════════════════════════════════════════
   EKOSYSTEMET — akt 3 till 5 i heron på /system

   Heron spelar fem akter: locket reser sig, glaset tänds tomt, ekosystemet
   byggs och växer ut ur ramen, det sjunker tillbaka in i skärmen, och copyn
   landar. Akt 1 och 2 bor i index.html (locket och glaset). Akt 3 till 5 bor
   här.

   VARFÖR SCENEN ÄR RITAD OCH INTE EN BILD
   Förlagan var en renderad PNG på 400 kB. En platt bild kan bara tona och
   skalas som ETT block: alla åtta apparna måste komma samtidigt, linjerna kan
   inte ritas, och ingen puls kan resa in mot navet. Ritad i DOM får varje del
   sin egen takt, och det är takten som är hela poängen — bilden säger "här är
   åtta appar", sekvensen säger "allt de vet rinner in i ett system".
   Bilden hade dessutom gått i samma fälla som laptopfotot en gång gjorde:
   inbakad glöd runt varje logotyp går inte att maska bort i CSS, den ligger
   delvis innanför formens egen kant. Se css/dator.css för den historien.

   ENHETERNA ÄR CONTAINERENHETER, INTE PROCENT ELLER PX
   .ekosystem är sin egen containerkontext, så 1cqw är 1 % av scenens bredd. Det
   betyder att EN uppsättning tal beskriver kompositionen vid varje
   fönsterstorlek: en chipdiameter på 9.6cqw är lika stor andel av bilden på en
   835 px laptop som på en 1320 px. Procent hade räckt för position men inte
   för translateX i en rotate-kedja (procent löses där mot elementets EGEN
   storlek), och px hade krävt en mediafråga per brytpunkt.

   GEOMETRIN ÄR RÄKNAD, INTE PROVAD FRAM
   Scenen har samma rektangel som skärmglaset: 69,84 % bredd och 54,02 % höjd
   av datorn, alltså kvoten 1,5327:1. Varje chip har en position i procent, och
   ur den positionen är vinkeln och avståndet till navet (50 %, 52 %) räknade i
   px-rymden — alltså med hänsyn till att 1 % på bredden inte är 1 % på höjden.
   Räknat med W=1532,7 och H=1000. Ändras en chipposition måste --vinkel och
   --langd räknas om, annars pekar linjen bredvid plattan.

   BARA TRANSFORM OCH OPACITY, SOM RESTEN AV HUSET
   Linjerna ritas med scaleX från navet, inte med stroke-dashoffset. Pulserna
   är translateX. Glöden andas i opacity. Ingenting här rör layouten, och hela
   scenen är absolut placerad ovanpå datorn — CLS är noll.

   EGNA EASINGKURVOR MED FLIT
   css/motion.css laddas med media="print" och kommer alltså fram EFTER första
   bilden. Heron är LCP-zon och får inte vänta på den, så kurvorna nedan är
   definierade här i stället för att lånas ur :root. Samma värden, egna namn.
   ═══════════════════════════════════════════════════════════════════════════ */

.laptop-scen{
  /* SCENEN ÄR CONTAINERKONTEXT FÖR COPYN.
     Måtten i .hero-innehall låg först i cqw mot .hero-innehall SJÄLV. Ett
     element kan inte fråga sig självt: dess egen padding löstes då mot
     viewporten (7cqw blev 106 px i stället för 51), innehållsboxen krympte
     till 522 px och rubriken föll ned på sin nedre clamp-gräns på 30,4 px och
     stannade där oavsett hur stor datorn blev. Uppmätt på tre bredder: samma
     30,4 px vid glas på 550, 629 och 734 px.

     Kontexten ligger därför här, på scenen, som aldrig transformeras och vars
     bredd är externt bestämd (width:100% plus max-width). Copyns tal är räknade
     mot SCENENS bredd, inte glasets: glaset är 69,84 % av scenen.
     .ekosystem har kvar sin egen kontext, så dess tal är oförändrade. */
  container-type:inline-size;
  --eko-ut-kurva:   cubic-bezier(.22, .61, .36, 1);
  --eko-mjuk:       cubic-bezier(.16, 1, .3, 1);
  /* Hur långt scenen växer förbi ramen i akt 3. 1,34 är taket, och talet
     räknas mot det chip som ligger ytterst: sedan ringen vidgades är det
     x = 6 %. Räknat: 50 + (6-50)*1,34 = -8,96 %, minus chipradien 6,43 % =
     -15,39 % av scenbredden, vilket mot glasets 69,84 % blir -10,75 % av
     datorns bredd. Scenen börjar på 15,32 %, så chipet landar på 4,57 % och
     har 4,57 procentenheter kvar till kanten. Vid 1,40 tar de slut. */
  --eko-vaxt: 1.34;
  --eko-lyft: -2%;      /* scenen lyfter samtidigt som den växer */
  --eko-steg: 118ms;     /* mellanrum mellan två chip i varvet */
  --eko-ord-tid: 620ms;  /* ett ords resa upp ur sin ruta */
  --eko-ord-steg: 100ms; /* mellanrum mellan två ord i rubriken */
}

/* ── Lagerordningen i scenen ───────────────────────────────────────────────
   .laptop-scen::before    dämpskivan            z 0   (index.html)
   .laptop                 datorn                z 1
     .lock-ram, .laptop-skarm  chassit och glaset
     .ekosystem                ekosystemet       z 3
   .hero-innehall          rubriken och texten   z 4

   SCENEN ÄR BARN TILL .laptop och inte till .laptop-scen. Deras mått är
   andelar av DATORN, och .laptop-scen är bara lika hög som datorn så länge
   copyn ligger absolut placerad. Under 760 px flödar copyn under datorn och
   scenen blir nästan dubbelt så hög. Se markupen i index.html för vad det
   kostade innan flytten.

   Datorn får ett eget z-index. Det skapar en stackningskontext på .laptop,
   men dämpskivan är SYSKON till den och inte barn, så den ligger kvar under.
   Villkoret i css/dator.css gäller .dator inuti — det rörs inte. */
.laptop{z-index:1}

/* ── DATORN VIKER UNDAN, DEN TÄCKS INTE ÖVER ───────────────────────────────
   Datorn ska sjunka tillbaka medan ekosystemet flyter fram över den.

   HÄR LÅG EN VIT SLÖJA, ett element med #fff som bottenskikt lagt över hela
   datorns box på 58 procents opacitet. Motiveringen i den här kommentaren löd
   att sidans egen bakgrund är vit, så slöjans kanter skulle vara osynliga.
   Det stämde inte. body::before lägger ett fast mönster med diagonala blå
   linjer och ljusstrimmor över hela sidan, och mot det blev slöjan en stor vit
   kvadrat med skarpa kanter, bredare än datorn eftersom boxen är hela scenen.

   Rätt grepp är att sänka opaciteten på DATORN i stället. Då finns ingen yta
   som kan ha en kant: chassit ljusnar, sidans mönster lyser igenom precis som
   överallt annars, och effekten blir densamma optiskt. Det är dessutom
   billigare, för det är ett element som redan är ett eget lager i stället för
   ett extra som ska komponeras ovanpå.

   Glaset (.laptop-skarm) är SYSKON till .lock-ram och dämpas alltså inte.
   Det ska det inte heller: scenen står på skärmen, och en skärm som bleknar
   samtidigt som innehållet växer läser som att den slocknar.

   En blur hade varit det självklara greppet och är fel av två skäl: filter är
   varken transform eller opacity, och en blur på ett element som samtidigt
   bär en 3D-roterad lock tvingar fram en ny rastrering per bildruta. */
/* .48 och inte .34: vid en tredjedel försvinner chassit nästan helt och
   datorn slutar läsa som ett föremål, den blir en kontur. Vid .48 finns
   tangentbordet och kanten kvar, bakgrundens linjer skymtar igenom, och
   ekosystemet ligger ändå tydligt framför. Provat mot .34 och .60. */
.js-enabled .laptop-scen.eko-in .lock-ram{
  opacity:.48;transition:opacity 992ms var(--eko-ut-kurva)}
.js-enabled .laptop-scen.eko-ut .lock-ram{
  opacity:1;transition:opacity var(--eko-ut-tid,1440ms) var(--eko-mjuk)}

/* ── Scenen ────────────────────────────────────────────────────────────────
   Exakt samma rektangel som .laptop-skarm. Talen är uppmätta i datorns
   silhuett och står också i index.html — ändras de på ett ställe måste de
   ändras på båda, annars glider scenen ur glaset när den sjunker tillbaka.

   VILOLÄGET ÄR BASEN. Utan JS, vid reducerad rörelse och när sekvensen spelat
   klart står scenen i skärmens storlek med de dämpade värdena. Klasserna
   nedan beskriver bara avvikelserna. Det är samma disciplin som resten av
   heron: ingenting är osynligt utan JavaScript.

   container-type:inline-size och inte size: scenen har definit höjd här, men
   inline-size räcker för allt som mäts (bara cqw används) och kan inte
   kollapsa något om reglerna en dag flyttar. */
.ekosystem{
  position:absolute;left:15.32%;top:12.91%;width:69.84%;height:54.02%;
  z-index:3;pointer-events:none;
  container-type:inline-size;
  opacity:1;transform:none}

/* GLAPPET FÖRE REGIN, OCH TAKTEN I LOCKÖPPNINGEN.
   Reglerna som bygger upp scenen kräver .eko-in, som sätts först när
   regissören kommit dit. Mellan att routern visar vyn och att akt 3 börjar
   hade hela ekosystemet stått färdigt på skärmen för att sedan tonas bort,
   samma blink som CRM-demot en gång gav.

   VISIBILITY OCH INTE BARA OPACITY, och det är skillnaden mellan en mjuk och
   en hackig locköppning. Locket roterar i 3D och vill ha ett eget
   kompositionslager. Det kan det bara få om ingenting som ligger ÖVER det och
   överlappar det måste målas om i samma veva, och scenen är ett femtiotal
   element med masker, suddade skuggor och gradienter rakt ovanpå locket. Med
   opacity:0 låg allt kvar i målningsträdet och locket föll tillbaka på
   huvudtråden med en ommålning per bildruta.
   Uppmätt i spår över akt 1: 83 Paint-poster med enbart opacity, 18 med
   visibility. Layouten och de beräknade stilarna finns kvar, så övergångarna
   in i akt 3 har fortfarande ett läge att animera FRÅN.

   :not(.eko-ut) är livlinan: slutlage() sätter eko-ut UTAN att spela, och
   utan det villkoret hade scenen blivit permanent osynlig vid reducerad
   rörelse och dold flik. */
.js-enabled .laptop-scen:not(.eko-in):not(.eko-ut) .ekosystem{opacity:0;visibility:hidden}
.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .ekosystem{transform:scale(.94)}

/* Akt 3: scenen växer förbi ramen. Tillväxten går över HELA akten och inte i
   en snärt på slutet — det är den långsamma driften som får det att läsa som
   att något lyfter ur skärmen i stället för att en bild zoomas. */
.js-enabled .laptop-scen.eko-in .ekosystem{
  opacity:1;visibility:visible;transform:translateY(var(--eko-lyft)) scale(var(--eko-vaxt));
  transition:transform var(--eko-in-tid,2688ms) var(--eko-ut-kurva),
             opacity 672ms linear}

/* Akt 4: tillbaka in i glaset. */
.js-enabled .laptop-scen.eko-ut .ekosystem{
  opacity:1;transform:none;
  transition:transform var(--eko-ut-tid,1440ms) var(--eko-mjuk)}

/* ── Ringarna ──────────────────────────────────────────────────────────────
   Bakgrundens ekon. Ellipser och inte cirklar: kompositionen är 1,53:1 och en
   cirkel hade läst som en boll i stället för som ett fält sett snett uppifrån.
   De ligger under allt annat och bär ingen information — de finns för att
   ögat ska ha något att läsa avståndet mot när chipsen kommer in. */
.eko-ring{
  position:absolute;left:50%;top:54%;border-radius:50%;
  border:1px solid rgba(92,141,255,.42);
  transform:translate(-50%,-50%) scale(1);opacity:.42}
.eko-ring--1{width:96cqw;height:44cqw;opacity:.22}
.eko-ring--2{width:74cqw;height:34cqw;opacity:.30}
.eko-ring--3{width:52cqw;height:24cqw;opacity:.38}
.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .eko-ring{
  opacity:0;transform:translate(-50%,-50%) scale(.82)}
.js-enabled .laptop-scen.eko-in .eko-ring{
  transition:opacity 1440ms linear 192ms, transform 1440ms var(--eko-ut-kurva) 192ms}
.js-enabled .laptop-scen.eko-ut .eko-ring{
  transition:opacity var(--eko-ut-tid,1440ms) linear,
             transform var(--eko-ut-tid,1440ms) var(--eko-mjuk)}

/* ── Glöden under plattan ──────────────────────────────────────────────────
   Sista stoppet på 76 % av en radie på 50 % ligger på 38 % från mitten, alltså
   innanför boxen. Se kommentaren vid slöjan för varför det inte är valfritt.

   HÄR LÅG EN ANDNING i vila, en oändlig opacity-animation på sju sekunder.
   Den är borttagen. Motiveringen var att en scen som fryser läser som en bild,
   och det stämmer, men priset var att sidan aldrig blev stilla: en oändlig
   animation håller kompositören igång så länge fliken är öppen, och glöden är
   en gradient på ungefär 570x340 px inne i en container med masker ovanpå.
   Det märktes som att hela sidan gick trögt, inte bara heron. En stillastående
   scen med copyn i mitten är billigare och lika bra. */
.eko-glod{
  position:absolute;left:50%;top:56%;width:78cqw;height:46cqw;
  transform:translate(-50%,-50%);border-radius:50%;opacity:.55;
  background:radial-gradient(50% 50% at 50% 50%,
    rgba(58,109,240,.34) 0 26%, rgba(92,141,255,.15) 52%, rgba(92,141,255,0) 76%)}
.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .eko-glod{opacity:0}
.js-enabled .laptop-scen.eko-in .eko-glod{
  opacity:1;transition:opacity 1440ms var(--eko-ut-kurva)}
.js-enabled .laptop-scen.eko-ut .eko-glod{
  opacity:.55;transition:opacity var(--eko-ut-tid,1440ms) linear}
/* TÄNDNINGEN. Ett enda andetag ljus underifrån, tajmat mot "vet allt" och inte
   mot första ordet: det är där meningen får sin poäng, och då ska systemet lysa
   upp den. 700 ms är --o:7 gånger ordsteget, alltså exakt samma tal som ordet.
   Engångs, med both-fyllning som slutar på vilovärdet. Ingen infinite: en sådan
   låg här förut och höll kompositören igång så länge fliken var öppen. */
@keyframes eko-tandning{
  0%{opacity:.55}
  34%{opacity:.92}
  100%{opacity:.55}}
.js-enabled .laptop-scen.text-in .eko-glod{
  animation:eko-tandning 1500ms var(--eko-ut-kurva) 700ms both}

/* ── Banden: linjen in mot navet och pulsen som reser längs den ────────────
   ETT element bär vinkeln och avståndet, två barn delar på dem. Linjen skalas
   med scaleX och skulle ha dragit ut pulsen till en streck om de suttit i
   samma box; pulsen bor därför i bandet och inte i linjen.

   Origo är bandets vänsterkant, alltså navet. Linjen växer utåt, pulsen reser
   inåt. Det är avsiktligt och det är hela budskapet: systemet bygger ut sina
   kopplingar, och det som kommer tillbaka är kunskap. */
.eko-band{
  position:absolute;left:50%;top:52%;width:var(--langd);height:0;
  transform-origin:0 50%;transform:rotate(var(--vinkel))}

.eko-lina{
  position:absolute;left:0;top:-.75px;width:100%;height:1.5px;border-radius:1px;
  transform-origin:0 50%;transform:scaleX(1);opacity:0;
  background:linear-gradient(90deg,
    rgba(58,109,240,0) 3%, rgba(58,109,240,.46) 24%,
    rgba(58,109,240,.46) 76%, rgba(58,109,240,0) 97%)}
.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .eko-lina{transform:scaleX(0)}
.js-enabled .laptop-scen.eko-in .eko-lina{
  opacity:1;
  transition:transform 608ms var(--eko-ut-kurva) calc(var(--i) * var(--eko-steg) + 416ms),
             opacity 352ms linear calc(var(--i) * var(--eko-steg) + 416ms)}
/* I vila tonar linjerna bort helt. Kvar blir chipsen och glöden, och texten
   får en ren yta att stå på. Ett nät av strålar bakom en rubrik läser som
   brus, hur svagt det än är. */
.js-enabled .laptop-scen.eko-ut .eko-lina{
  opacity:0;transition:opacity var(--eko-ut-tid,1440ms) linear}

.eko-puls{
  position:absolute;left:0;top:0;width:1.7cqw;height:1.7cqw;
  margin:-.85cqw 0 0 -.85cqw;border-radius:50%;opacity:0;
  transform:translateX(var(--langd));
  background:radial-gradient(circle,
    #ffffff 0 20%, #5c8dff 38%, rgba(92,141,255,0) 72%)}
.js-enabled .laptop-scen.eko-in .eko-puls{
  animation:eko-puls 896ms var(--eko-mjuk) calc(var(--i) * var(--eko-steg) + 768ms) both}
@keyframes eko-puls{
  0%  {transform:translateX(var(--langd));opacity:0}
  14% {opacity:1}
  74% {opacity:1}
  100%{transform:translateX(0);opacity:0}}

/* ── Plattan ───────────────────────────────────────────────────────────────
   Fem skivor sedda snett uppifrån plus en svävande kub. Formen är en kvadrat
   som först roteras 45 grader och sedan pressas ihop på höjden — i SVG blir
   det scale(1 .42) rotate(45), i den ordningen, eftersom listan appliceras
   utifrån och in. Vänder man på dem får man en lutande rektangel i stället för
   en romb, vilket var första försöket och såg ut som ett fel.

   Hörnradien pressas med och blir elliptisk. Det är rätt: en isometrisk kub
   HAR elliptiska hörn sedd så här. Inga streck någonstans, bara fyllningar —
   en stroke hade pressats ihop lodrätt och blivit olika tjock på ovansidan
   och sidan.

   Plattan reser sig underifrån i akt 3 och är HELT borta i vila. Kvar blir
   glöden, så mitten av skärmen är ren yta när rubriken landar. */
.eko-platta{
  position:absolute;left:50%;top:52%;width:62cqw;height:auto;
  transform:translate(-50%,-50%) translateY(0cqw) scale(.9);opacity:0}
.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .eko-platta{
  transform:translate(-50%,-50%) translateY(9cqw) scale(.82)}
.js-enabled .laptop-scen.eko-in .eko-platta{
  opacity:1;transform:translate(-50%,-50%) translateY(0cqw) scale(1);
  transition:transform 992ms var(--eko-ut-kurva), opacity 672ms linear}
.js-enabled .laptop-scen.eko-ut .eko-platta{
  /* .62 och inte .9: plattan ska KRYMPA IN mot texten som tar dess plats, inte
     bara blekna på stället. Samma mitt, så det läser som att meningen kommer
     ur navet. */
  opacity:0;transform:translate(-50%,-50%) translateY(0cqw) scale(.62);
  transition:transform var(--eko-ut-tid,1440ms) var(--eko-mjuk),
             opacity var(--eko-ut-tid,1440ms) linear}

/* ── Märket ────────────────────────────────────────────────────────────────
   logo-marke.png som mask, inte som bild: filen är monokrom och 126 px bred,
   och som mask spelar upplösningen mindre roll än som bild — det är formens
   kant som ska hålla, inte dess innehåll.

   126 px räcker ändå bara till ungefär 63 px på en 2x-skärm, och märket
   renderas som störst 88 px när scenen står på 1,34. Det spelar ingen roll
   här och bara här: märket syns ENBART medan scenen rör sig och är borta
   innan texten landar. Ska det någon gång stå stilla behöver det ritas som
   SVG först. */
.eko-marke{
  position:absolute;left:50%;top:16%;width:8.5cqw;aspect-ratio:126/119;
  transform:translate(-50%,-50%) translateY(0cqw) scale(.86);opacity:0;
  background:linear-gradient(150deg,#2a55c8,#1f6fd0 55%,#3a6df0);
  -webkit-mask:url("/logo-marke.png") center/contain no-repeat;
          mask:url("/logo-marke.png") center/contain no-repeat}
.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .eko-marke{
  transform:translate(-50%,-50%) translateY(-7cqw) scale(.8);opacity:0}
.js-enabled .laptop-scen.eko-in .eko-marke{
  opacity:1;transform:translate(-50%,-50%) translateY(0cqw) scale(1);
  transition:transform 832ms var(--eko-ut-kurva) 352ms, opacity 608ms linear 352ms}
.js-enabled .laptop-scen.eko-ut .eko-marke{
  opacity:0;transform:translate(-50%,-50%) translateY(0cqw) scale(.86);
  transition:transform var(--eko-ut-tid,1440ms) var(--eko-mjuk),
             opacity 832ms linear}

/* ── Chipsen ───────────────────────────────────────────────────────────────
   Vita brickor med märkesfärgad logotyp. De kommer in RADIELLT utifrån: först
   flyttas brickan till sin plats i ringen, sedan skjuts den utåt längs sin
   egen vinkel med translateX i en rotate-sandwich, och sist skalas den. Utan
   den sista rotate(-vinkel) hade brickan kommit in på skrå och tippat.

   I VILA STANNAR RINGEN KVAR, dämpad. Det var det enda alternativet som
   svarade på frågan vad skärmen ska vara när sekvensen är slut: en svart ruta
   med en rubrik i, eller en rubrik som står mitt i sitt eget ekosystem.
   Chipsen sitter på 8-92 % i sidled och 16-89 % på höjden, alltså utanför den
   yta texten tar. De krockar aldrig. */
.eko-chip{
  --s:1;
  position:absolute;left:var(--x);top:var(--y);
  width:9.6cqw;aspect-ratio:1;border-radius:50%;
  display:grid;place-items:center;
  background:#fff;
  /* TVÅ SKUGGOR, INTE TRE. Den tredje var en halo på .62cqw som knappt syns
     mot det ljusa glaset men kostar en suddad yta per bricka i varje
     ommålning, gånger åtta. Suddan i den första är också nedskruvad från
     1,8cqw till 1,3: den läser likadant och rastreras billigare. */
  box-shadow:
    0 .5cqw 1.3cqw rgba(16,38,110,.14),
    0 0 0 .14cqw rgba(120,160,255,.34);
  /* TRANSFORMLISTAN ÄR IDENTISK I ALLA TRE LÄGENA, och det är inte pedanteri.
     Skiljer sig funktionerna mellan från- och till-läget kan webbläsaren inte
     interpolera funktion för funktion, utan faller tillbaka på att dekomponera
     matriser. Det såg ut som ett paintfel: ordmärkena målades en extra gång i
     en gammal transform under hela övergången, som en blå spökkopia snett
     under sitt chip. Uppmätt i DOM:en fanns bara ETT element med texten.
     Med lika listor sker interpolationen per funktion och spöket är borta.
     translateX(0cqw) och rotate() ser överflödiga ut här. De är inte det. */
  transform:translate(-50%,-50%)
            rotate(var(--vinkel)) translateX(0cqw) rotate(calc(-1 * var(--vinkel)))
            scale(.8);
  /* .24 och inte .32: copyn står mitt i ringen, och där de kommer nära ska
     brickorna läsa som vattenstämpel och inte som något texten krockar med. */
  opacity:.24}
.eko-chip img{width:46%;height:46%;object-fit:contain;display:block}
/* EN AVVIKARE BLAND ÅTTA. .eko-chip--farg är Swish: deras märke ÄR sin
   gradient, och en enfärgad silhuett av virveln är inte Swishmärket utan en
   grå ring. Chipet bär därför bilden i full färg och hoppar över masken nedan.
   58 och inte symbolernas 46: virveln är en RING och inte en fylld form, så
   den väger optiskt lättare vid samma ytterdiameter.

   HÄR LÅG OCKSÅ .eko-chip--ord, en bredare maskyta för Fortnox ordmärke.
   Fortnox är utbytt mot Microsoft Teams, som har en symbol, så varianten
   behövs inte längre. */
.eko-chip--farg img{width:58%;height:58%}

.js-enabled .laptop-scen.regi:not(.eko-in):not(.eko-ut) .eko-chip{
  opacity:0;
  transform:translate(-50%,-50%)
            rotate(var(--vinkel)) translateX(7cqw) rotate(calc(-1 * var(--vinkel)))
            scale(.55)}
.js-enabled .laptop-scen.eko-in .eko-chip{
  opacity:1;
  transform:translate(-50%,-50%)
            rotate(var(--vinkel)) translateX(0cqw) rotate(calc(-1 * var(--vinkel)))
            scale(1);
  transition:transform 768ms var(--eko-ut-kurva) calc(var(--i) * var(--eko-steg)),
             opacity 512ms linear calc(var(--i) * var(--eko-steg))}
.js-enabled .laptop-scen.eko-ut .eko-chip{
  transition:transform var(--eko-ut-tid,1440ms) var(--eko-mjuk),
             opacity var(--eko-ut-tid,1440ms) linear}
/* ÖVERLÄMNINGEN. Brickorna dämpades förut till sitt viloläge i akt 4, alltså
   INNAN copyn kom, och det blev två skilda händelser: ringen slocknade, och en
   stund senare tändes en text. Nu stannar de ljusa hela akt 4 och släcker ned i
   takt med att orden sätts. Ringen lämnar över sitt ljus till meningen i
   stället för att lämna scenen tom åt den.
   :not(.text-in) är det som gör det: så fort copyn börjar tar regeln under
   över, och den har samma specificitet men står senare. */
.js-enabled .laptop-scen.eko-ut:not(.text-in) .eko-chip{opacity:.55}
.js-enabled .laptop-scen.text-in .eko-chip{
  opacity:.24;transition:opacity 1300ms linear}

/* Ikonfilerna är monokroma (Simple Icons) och en <img> går inte att färglägga
   med CSS. Formen används därför som mask med märkesfärgen under, precis som
   verktygsringen längre ner på sidan gör. @supports gör det till en ren
   förbättring: utan stöd ligger <img> kvar och logotypen visas svart, vilket
   också är läsbart. */
@supports (mask-image: url(/logos/gmail.svg)) or (-webkit-mask-image: url(/logos/gmail.svg)){
  .eko-chip:not(.eko-chip--farg) img{visibility:hidden}
  .eko-chip:not(.eko-chip--farg)::after{
    content:"";position:absolute;width:46%;height:46%;
    background:var(--f);
    -webkit-mask:var(--m) center/contain no-repeat;
            mask:var(--m) center/contain no-repeat}
}

/* ── Copyn på glaset ───────────────────────────────────────────────────────
   Rubriken ÄR sidans h1 och står i markupen som riktig text. Den flyttar
   ingenstans: skärmen är dess plats, inte en station på vägen. Därför är
   FLIP-mätningen i app.js borta — den fanns för att morfa texten mellan glaset
   och ett viloläge under datorn, och det viloläget finns inte längre.

   Storleken blandar cqw med rem-gränser. Ren cqw ger en fast andel av glaset,
   och glaset varierar mellan 583 px (kort fönster) och 922 px (högt): ingressen
   hade landat på 13 px i det ena läget eller 25 px i det andra. clamp håller
   den mellan 15,7 och 20,5 px och låter rubriken svinga fritt däremellan. */
.hero-innehall{
  position:absolute;left:15.32%;top:12.91%;width:69.84%;height:54.02%;
  z-index:4;
  display:flex;flex-direction:column;justify-content:center;
  padding:0 5cqw;text-align:center}
.hero-innehall .laptop-rubrik{
  font-size:clamp(1.9rem,4.4cqw,3.4rem);line-height:1.1;letter-spacing:-.025em;
  /* Avstavningen ärvs från basregeln i index.html och ska INTE gälla här:
     raderna är korta och satta för hand, och ett bindestreck mitt i "levererar"
     hade varit det enda ögat såg. */
  -webkit-hyphens:none;hyphens:none}
.hero-innehall .laptop-under{
  font-size:clamp(.98rem,1.7cqw,1.28rem);line-height:1.6;
  margin-top:clamp(.8rem,1.9cqw,1.5rem);
  /* 52ch och inte 44: bredare rader ger FÄRRE rader, och höjden är det som är
     ont om i glaset. Kolla om vid varje textändring. */
  max-width:52ch;margin-inline:auto;text-wrap:balance}
/* ── ORDEN SÄTTS, DE TONAS INTE IN ─────────────────────────────────────────
   Varje ord bor i en ruta som klipper, och ordet stiger upp underifrån inom
   den. Rörelsen bär avtäckningen, opaciteten är bara en mjukning på de första
   tiondelarna. Skillnaden mot en ren toning är att en riktning läses fortare:
   hela copyn landar på 1,9 s mot 2,1 för blocken, och känns ändå lugnare.

   PADDINGEN ÄR INTE DEKOR. overflow:hidden klipper mot paddingboxen, och utan
   de här tiondelarna av ett em kapas underhänget i "företag" och prickarna
   över Ä och Ö. Den negativa marginalen tar tillbaka exakt lika mycket, så
   raden är på pixeln densamma som utan rutorna. Ändras rubrikens teckensnitt
   eller radavstånd måste båda talen provas om.

   vertical-align:top: inline-block linjeras mot baslinjen som standard, och en
   ruta med padding under baslinjen sköt då hela raden nedåt. */
.eko-ord{
  display:inline-block;overflow:hidden;vertical-align:top;
  padding:.09em 0 .17em;margin:-.09em 0 -.17em}
.eko-ord > i{display:block;font-style:normal}
/* Ingressens stycken: samma mekanik, men ett svep per stycke i stället för per
   ord. Ord för ord i brödtext blir pilligt och drar ut på tiden. */
.eko-ord--block{display:block}

.js-enabled .laptop-scen:not(.text-in) .eko-ord > i{
  transform:translateY(108%);opacity:0}
.js-enabled .laptop-scen.text-in .eko-ord > i{
  transform:none;opacity:1;
  transition:transform var(--eko-ord-tid) var(--eko-ut-kurva)
               calc(var(--o) * var(--eko-ord-steg)),
             opacity calc(var(--eko-ord-tid) * .45) linear
               calc(var(--o) * var(--eko-ord-steg))}
/* Styckena reser en längre väg och får en längre resa. */
.js-enabled .laptop-scen.text-in .eko-ord--block > i{
  transition-duration:760ms, 342ms}

/* ── Under 760 px ──────────────────────────────────────────────────────────
   Samma brytpunkt som app.js och hero-CSS:en i index.html. Tre gränser för
   samma beslut var precis där en bugg bodde.

   Glaset är omkring 230 px brett på en telefon. En rubrik i 5,4cqw hade blivit
   12 px, alltså under läsbarhetsgolvet, och ingressen hade inte gått att läsa
   alls. Texten lämnar därför glaset och blir ett vanligt block under datorn,
   i sin fulla storlek. Samma utbrytning som instrumentpanelen gjorde före den.

   Scenen stannar kvar i glaset men växer MER: på en telefon finns inget
   sidoutrymme att bryta ut i, så tillväxten får ske över chassit i stället.
   1,45 är taket — vid 1,50 går vänstra chipet utanför scenens kant.

   Blocket måste stå EFTER reglerna ovan: samma specificitet, så källordningen
   avgör vem som vinner. Den fällan låg bakom att mobilvyn en gång stod trasig
   live i flera veckor. */
@media(max-width:760px){
  .laptop-scen{--eko-vaxt:1.45;--eko-lyft:0%}
  /* Chipsen större i andel av ett glas som bara är omkring 272 px: vid 13cqw
     blir brickan 35 px och ordmärket 27 px brett, alltså en femradig
     bokstavshöjd. 16cqw ger 44 respektive 33. Ordmärkena blir ändå inte
     läsbara på en telefon och ska inte vara det — scenen är stämning där,
     budskapet står i full storlek under datorn. */
  .eko-chip{width:16cqw}
  .hero-innehall{
    position:static;width:100%;height:auto;
    padding:2.2rem 1.5rem 0;text-align:center}
  .hero-innehall .laptop-rubrik{font-size:clamp(1.55rem,7.4vw,2.15rem)}
  .hero-innehall .laptop-under{font-size:1.02rem;margin-top:.9rem}
}

/* ── Reducerad rörelse ─────────────────────────────────────────────────────
   Sluttillståndet direkt: scenen i skärmens storlek, chipsen dämpade i sin
   ring, glöden stilla, texten framme. Ingen rörelse, ingen andning, inga
   transformer utöver de som placerar saker. */
@media(prefers-reduced-motion:reduce){
  .laptop-scen .ekosystem,
  .laptop-scen .eko-ring,
  .laptop-scen .eko-chip,
  .laptop-scen .eko-glod,
  .laptop-scen .eko-marke,
  .laptop-scen .eko-platta,
  .laptop-scen .eko-lina,
  .laptop-scen .eko-puls,
  .laptop-scen .eko-ord > i,
  .laptop-scen .lock-ram{transition:none!important;animation:none!important}
  .laptop-scen .eko-ord > i{opacity:1!important;transform:none!important}
  .laptop-scen .ekosystem{opacity:1!important;transform:none!important}
  .laptop-scen .lock-ram{opacity:1!important}
  .laptop-scen .eko-platta,.laptop-scen .eko-marke,.laptop-scen .eko-lina,
  .laptop-scen .eko-puls{opacity:0!important}
}

/* Utan JS: samma sluttillstånd. Klasserna som döljer saker kräver .js-enabled,
   så det här är bara en försäkring. */
html:not(.js-enabled) .ekosystem,
html:not(.js-enabled) .eko-ord > i{opacity:1;transform:none}
html:not(.js-enabled) .eko-platta,
html:not(.js-enabled) .eko-marke,
html:not(.js-enabled) .eko-lina,
html:not(.js-enabled) .eko-puls{opacity:0}
