/* ============================================================
   sanghan.co — clone.css

   ALLT nedan är UPPMÄTT live mot https://sanghan.co/ med Playwright
   över 18 bredder (390–1920). Referensen är en Squarespace FLUID
   ENGINE: två CSS-rutnät där varje band ligger i en .fe-block med
   explicit grid-row/grid-column. Rutnätets radhöjd/kolumnbredd är den
   ENDA geometrikällan — inga handjusterade marginaler.

   UPPMÄTTA RUTNÄTSPARAMETRAR
     mobil  (<768):  10 kol x 41 rader, gap 11px, radhöjd 24px FAST
     desktop (>=768): 26 kol x 72 rader, gap 11px, radhöjd 1.97754vw
     footer-rutnät:  samma kolumner, gap 0, 5 rader (mobil) / 4 (desktop)
     rader = minmax(radhöjd, auto) -> textblock som är högre än sitt
     radspann växer och skjuter allt nedanför, precis som i facit.

   Modellen reproducerar facit inom ~1px: @800 ger den copy-blocket
   y=729 (facit 729) och work y=1136 (facit 1136); @390 docH 2068.6
   (facit 2068).  Se .replica/OPUSFIX.RAPPORT.md för full mättabell.
   ============================================================ */

/* ---- fonter: självhostade OFL-substitut (licensregeln, se FONT-SUBSTITUT.md).
     Instrument Serif är den officiella OFL-utgåvan MED HINTNINGEN BORTTAGEN: facit
     serverar samma version ohintad, och TrueType-hintningens pixelsnäppning av
     frammatningen gav annars fel radbrytning vid 390/900 och kumulativ textdrift.
     Copyright/OFL-posterna är bevarade i filerna. ---- */
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/instrument-serif-400.woff2") format("woff2");
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/instrument-serif-400-italic.woff2") format("woff2");
}
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/newsreader-400.woff2") format("woff2");
}
@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/newsreader-400-italic.woff2") format("woff2");
}

:root {
  --bg: rgb(0, 0, 0);
  --fg: rgb(245, 245, 243);
  --muted: rgb(145, 145, 145);
  --shape: rgb(250, 250, 250); /* uppmätt stroke-färg på facits TextShape-dekor */
  --font: "Instrument Serif", Georgia, "Times New Roman", serif;

  /* uppmätt: rutnätets gap är 11px vid ALLA bredder i huvudrutnätet */
  --gap: 11px;
  /* mobil radhöjd är FAST 24px 390..760; desktop skalar 1.97754vw
     (37.9688/1920 = 15.1875/768 = 0.0197754 vid samtliga 13 mätpunkter) */
  --row: 24px;
  /* uppmätt sidmarginal: 6vw under 768, 4vw från 768 */
  --edge: 6vw;
  /* headerhöjd = padding-block 6vw x2 + högsta barnet (burgern 37px).
     Overlayns padding-top måste vara exakt detta (uppmätt 83.78 @390). */
  --header-h: calc(12vw + 44px);
}

* { box-sizing: border-box; }

html {
  /* UPPMÄTT på facit: getComputedStyle(document.documentElement).scrollBehavior
     === "smooth" vid samtliga 18 bredder. Detta är också hela förklaringen till
     checklist.js SCROLL-MOTION (se rapporten): facit har ingen scroll-animation
     alls — dess "rörliga" element är mätartefakter av mjukrullningen. */
  scroll-behavior: smooth;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

/* uppmätt: docH - footer-rutnätets underkant = 4vw vid ALLA bredder
   (390 -> 15.6, 800 -> 32, 1200 -> 48, 1920 -> 77). Paddingen ligger på
   FOOTER-sektionen, inte på body: sections-gate mäter facits sista band som
   FOOTER.sections med höjd 229 @1920 = rutnätets 152 + 77 botten-padding.
   Med paddingen på body blev bandet bara 152 (-77). */
.footer-section { padding-bottom: 4vw; }

body.menu-open { overflow: hidden; }

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

/* ============================================================
   HEADER
   uppmätt höjd = HÖGSTA headerbarnets höjd + 2 * padding-block. Under 800
   är padding-block exakt 6vw; det högsta barnet är burgern (37px) på mobil
   och logotypen (50px) i 768–799-bandet:
     <=767   burger 37 + 12vw -> h 84@390, 95@480, 109@600, 121@700, 128@760
     768-799 logo   50 + 12vw -> h 142@768, 144@780
     >=800   logo   50, padding 2.1875vw -> h 85@800, 103@1200, 134@1920
   ============================================================ */
.header {
  position: relative;
  padding-inline: var(--edge);
  padding-block: 6vw;
  background: transparent;
  z-index: 10; /* facit: header#header z-index 10 */
  /* UPPMÄTT på facits header#header: transition transform .14s ease-in-out */
  transition: transform 0.14s ease-in-out;
}

/* facits .header-announcement-bar-wrapper: raden med logotyp/nav/social/burger,
   position relative + z-index 2 så den ligger ÖVER overlayns z-index 1. */
.header-bar {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
}

.skip-link,
.endast-skarmlasare {
  position: absolute;
  left: -16000px; /* facit: x -16000 = skärmläsar-endast */
  top: 0;
  font-size: 16px;
  font-family: "Newsreader", Georgia, serif; /* uppmätt: enda Newsreader-elementet i facit */
}

.logo {
  display: block;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  font-size: 0;
}
.logo img { width: 100%; height: 100%; }

/* PORT — logo: mallens .logo-slot är en KVADRATISK symbolplats och OF-märkets
   viewBox är 1:1, så märket sitter i donatorns egen uppmätta geometri.
   AVSTEG (Samis dom 2026-08-18): storleken höjd 30->44 / 50->76 px eftersom
   märket knappt syntes på 1080p. Headerhöjden räknas ur högsta barnet och
   följer med: 98 @390 och 160 @1920, mot donatorns 84/134.
   .logo-wordmark står kvar oanvänd som reserv. */
.logo .of-mark {
  display: block;
  width: 100%;
  height: 100%;
  color: var(--fg);
}
.logo-wordmark {
  display: flex;
  align-items: center;
  width: auto;
  font-size: 20px;
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--fg);
  white-space: nowrap;
}

/* Ögat: ett ögonlock som stängs gör TVÅ saker samtidigt — formen pressas ihop
   på höjden OCH hålet försvinner. Enbart scaleY lämnade en svart springa kvar
   mitt i (Samis anmärkning), så ringens stroke-width växer i samma rörelse:
   vid 30 är innerradien 15-15 = 0 och hålet är helt slutet. scaleX 0,73 gör
   den slutna linsen något BREDARE än vilo-O:et (halvbredd 21,9 mot 20) —
   ögonlock breddar sig när de stängs. Marginalen till F-stammen (x=53) är kvar.
   transform-box: view-box krävs för att origo ska kunna anges i
   viewBox-koordinater; utan den räknas det ur bounding box och ögat glider
   i sidled i stället för att blinka. */
.of-oga {
  transform-box: view-box;
  transform-origin: 22px 50px;
}
.logo:hover .of-oga,
.logo:focus-visible .of-oga { animation: of-blink 720ms ease-in-out; }

/* Ett riktigt ögonlock stänger snabbt och öppnar långsammare. */
@keyframes of-blink {
  0%,  14% { transform: scale(1, 1);       stroke-width: 10; }
  26%      { transform: scale(0.73, 0.08); stroke-width: 30; }
  34%      { transform: scale(0.73, 0.08); stroke-width: 30; }
  62%      { transform: scale(1, 1);       stroke-width: 10; }
  100%     { transform: scale(1, 1);       stroke-width: 10; }
}

/* desktopnavet döljs under 800px — se brytpunktsavsnittet nedan */
.nav-primary,
.social { display: none; }

.nav-primary a {
  /* AVSTEG (Samis dom): donatorns uppmätta 16/27 syntes knappt på 1080p.
     Uppskalat i samma förhållande, i två omgångar (16 -> 23 -> 28). */
  font-size: 28px;
  line-height: 41px;
  color: var(--muted);
  letter-spacing: normal;
  text-transform: none;
  text-align: right; /* uppmätt i facit (sections-gate band[0]: align right) */
}

.social-link {
  display: block;
  width: 20px;
  height: 20px;
  border-style: none;
  border-color: rgb(40, 40, 42);
  color: var(--muted); /* uppmätt fill: rgb(145,145,145) */
}
.social-link svg { display: block; width: 100%; height: 100%; fill: currentColor; }

/* uppmätt @390/600/760/780: .burger 47x37, högerkant vid w - 6vw, lodrätt centrerad.
   Inuti ligger en 35x35-box med tre absolut placerade 1px-streck ("halfLineHamburger"):
     stängd  top-bun 35px translateY(-9.5) · patty 35px translateX(8.75) scaleX(.5)
             · bottom-bun 35px translateY(9.5) · färg rgb(145,145,145)
     öppen   bunsen 28px roterade till X (225deg / 135deg, translateX 3.5)
             · patty scale(0) · färg rgb(245,245,243)
   Övergång uppmätt: transform+width 0.25s cubic-bezier(0.2, 0.6, 0.3, 1). */
.burger {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  width: 47px;
  height: 37px;
  background: transparent;
  border-style: none;
  border-color: rgb(145, 145, 145);
  padding: 0;
  font-size: 16px;
  font-family: inherit;
  cursor: pointer;
}
.burger-box {
  position: relative;
  display: block;
  width: 35px;
  height: 35px;
}
.burger-box > span {
  position: absolute;
  inset: 0;
  margin-block: auto;
  height: 1px;
  width: 35px;
  background: var(--muted);
  transition:
    transform 0.25s cubic-bezier(0.2, 0.6, 0.3, 1),
    width 0.25s cubic-bezier(0.2, 0.6, 0.3, 1),
    background-color 0.25s cubic-bezier(0.2, 0.6, 0.3, 1);
}
.top-bun { transform: translateY(-9.5px); }
.patty { transform: translateX(8.75px) scaleX(0.5); }
.bottom-bun { transform: translateY(9.5px); }

body.menu-open .top-bun {
  width: 28px;
  background: var(--fg);
  transform: translateX(3.5px) rotate(225deg);
}
body.menu-open .patty { transform: scaleX(0); background: var(--fg); }
body.menu-open .bottom-bun {
  width: 28px;
  background: var(--fg);
  transform: translateX(3.5px) rotate(135deg);
}

/* facits burgertitlar: skärmläsartext som växlar med hidden-attributet */
.burger-title-open,
.burger-title-close {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ============================================================
   FLUID ENGINE — mobilrutnätet (bas, <768)
   uppmätt: 10 kolumner (2 rännor + 8 innehållskolumner), 41 rader,
   gap 11px, radhöjd 24px fast. Ytterkolumnen = 6vw - gap så att
   innehållets vänsterkant hamnar exakt på 6vw.
   ============================================================ */
.fluid-engine {
  display: grid;
  grid-template-columns: calc(var(--edge) - var(--gap)) repeat(8, 1fr) calc(var(--edge) - var(--gap));
  /* radantalet följer innehållet: fe-years slutar på 37 (donatorn: 41).
     Lämnas det för högt blir sidans svans ren tomyta. */
  grid-template-rows: repeat(40, minmax(var(--row), auto));
  gap: var(--gap);
}

/* uppmätta grid-spann i facit (mobil) */
.fe-hero-media { grid-row: 2 / 17;  grid-column: 1 / 11; }
.fe-hero-copy  { grid-row: 19 / 30; grid-column: 2 / 10; }
/* AVSTEG (Samis dom): 129px gav bandet ingen verkan pa mobil. Hojt i tva steg
   - 7 rader (234px) 2026-08-18, sedan 9 rader (304px) 2026-08-19 for att
   bandet fortfarande last for litet. Videon ar 2,85:1 och beskars pa bredden
   av object-fit: cover - men innehallet ar redan utsnitt, sa en centrerad
   beskarning tar inte bort nagot motiv.
   TAKET AR MATT, inte gissat: bredaste market i bildspelet (Hogbergs) ligger
   inom x 448-816 av 1280, alltsa 192px fran mitten. Synlig bildbredd vid
   hojden H och skarmbredden W ar W*450/H - vid 320px skarm och 304px hojd
   blir det 474px, sa market har ~53px luft pa varje sida. Hojer man over
   ~330px bors market i kanten pa smala telefoner. */
.fe-work       { grid-row: 32 / 41; grid-column: 1 / 11; }  /* 304px, var 234 */
.fe-years      { grid-row: 40 / 41; grid-column: 2 / 10; }

/* Bilderna ligger absolut i sitt block: annars skulle deras egen
   intrinsiska höjd blåsa upp minmax(row, auto)-raderna. Med inset:0
   blir blockhöjden EXAKT radspannet — facit: 514px (hero) och 269px
   (work) oavsett bredd under 768. */
.fe-hero-media,
.fe-work {
  position: relative;
  overflow: hidden;
}
/* Donatorns uppmätta mobilhero är 390x514. Utan proportionslås blir samma
   block 600x514 på en bredare telefon — alltså LIGGANDE, fast bilden är ett
   stående porträtt. Kvoten är donatorns egen. */
.fe-hero-media { aspect-ratio: 390 / 514; }
.fe-hero-media .image-link,
.fe-work .image-link,
.fe-work picture,
.fe-work video {
  position: absolute;
  inset: 0;
  display: block;
}
.fe-hero-media img,
.fe-work img,
.fe-work video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  max-width: none;
}

.fe-hero-media img { object-position: 50% 100%; }

/* ---- footer-rutnätet: samma kolumner men gap 0 (uppmätt), 5 rader mobil ---- */
.fe-footer {
  grid-template-columns: var(--edge) repeat(8, 1fr) var(--edge);
  grid-template-rows: repeat(5, minmax(var(--row), auto));
  gap: 0;
}
.fe-copyright { grid-row: 4 / 5; grid-column: 2 / 6; }
.fe-email     { grid-row: 4 / 6; grid-column: 7 / 10; }

/* ============================================================
   TYPOGRAFI
   Under 768 styrs h1 av VIEWPORTENS STÖRSTA MÅTT, inte av bredden:
   uppmätt fs = 16px + 3.6vmax, klampad vid 48.4px (nås vid vmax 900).
   Mätrutnät (bredd x höjd -> fs) som utesluter både ren vw och ren vh:

       390x600 -> 37.60   (16+3.6vw = 30.04 ✗, 16+3.6vmax = 37.60 ✓)
       390x844 -> 46.384  (vmax = höjden)
       390x900 -> 48.40   (klampen slår till)
       390x1200-> 48.40   (klampad)
       600x700 -> 41.20   (vmax = höjden)
       760x700 -> 43.36   (vmax = BREDDEN här, 760 > 700)
       760x844 -> 46.384  (vmax = höjden igen)

   Det var detta som gjorde docH höjdberoende i facit men inte i klonen
   (390x844: facit 1987, klon 2068): rubriken krymper -> stycket bryter på
   färre rader -> hela sidan blir kortare. Bilderna är fortsatt FASTA
   (514/269) — de var aldrig höjdberoende.

   Från 768 är den däremot ren BREDD: 16px + 3.6vw klampad vid 80.8px
   (=1800px), verifierat höjdoberoende (768/900/1920 ger samma fs vid
   höjd 700, 844, 1000 och 1200).

   lh-kvoten 51.1104/48.4 = 39.7056/37.6 = 85.3248/80.8 = 1.056 överallt.
   ============================================================ */
.fe-hero-copy h1 {
  margin: 0;
  font-weight: 400;
  font-size: min(calc(16px + 3.6vmax), 48.4px);
  line-height: 1.056;
  letter-spacing: -0.02em; /* -0.968/48.4 = -1.6/80.8 = -0.02em */
  color: var(--fg);
  white-space: pre-wrap; /* uppmätt på facits båda h1: white-space = pre-wrap */
}
/* uppmätt: avståndet rubrik-underkant -> stycke-överkant är 32px vid ALLA bredder */
.fe-hero-copy .copy-body { margin-top: 32px; }

/* uppmätt: H4 fs16 lh19.2 ls-0.32px (= -0.02em) */
.fe-years h4,
.fe-copyright h4,
.fe-email h4 {
  margin: 0;
  font-weight: 400;
  /* Donatorns uppmätta 16px. Uppskalas till 22 först vid 768 (se nedan):
     på 390 bryter både "OLSSON-FRAMÅT" och e-postadressen på två rader
     i sina uppmätta kolumnspann. */
  font-size: 16px;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.fe-email h4 { text-align: right; }
.fe-email a {
  display: inline-block;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3.2px;
}

/* Mallens Apple/Google-dekor är två SVG "TextShape"-överlägg ovanpå texten,
   uppmätta @1920: rak linje 8px stroke rgb(250,250,250) under "Apple"
   (x1187 y1417 w159) och VÅGIG linje 4px under "Google" (x723 y1503 w193).
   Återskapas som text-decoration i em (8/80.8 = 0.099em, 4/80.8 = 0.0495em)
   så de skalar med den fluida rubrikstorleken.

   PORT: dekoren följer med de två markerade orden i kundens egen text —
   studions två poler i "mellan design, teknologi och experiment".
   Rak linje = design, vågig linje = experiment. Måtten är mallens, orörda.

   Bärarna är SPAN, inte länk: mallens dekor är två SVG-överlägg ovanpå
   texten och råkade ligga över länkade arbetsgivarnamn. Här är orden
   ingen destination, och en länk hade blivit ett dött länkmål. */
.text-mark {
  text-decoration: underline;
  text-decoration-color: var(--shape);
}
.mark-design {
  text-decoration-thickness: 0.099em;
  text-underline-offset: 0.14em;
}
.mark-experiment {
  text-decoration-style: wavy;
  text-decoration-thickness: 0.0495em;
  /* AVSTEG från mallens uppmätta 0.19em -> 0.11em, dokumenterat.
     Mallens dekor är ett SVG-överlägg på en FAST position; vår återskapning
     är text-decoration som flyter med radbrytningen. Mallens vågiga linje
     ligger över korta gemener ("the most") och klarar sig; kundens text har
     "Ibland en webbplats" under bäraren, och vid 0.19em skar linjen rakt
     genom versalen I och staplarna i b/d. 0.11em drar linjen upp mot sitt
     EGET ord — samma läge som mallen har mot "Google"s g-stapel. */
  text-underline-offset: 0.11em;
}

/* ============================================================
   DESKTOPRUTNÄTET — brytpunkt 768 (uppmätt: 760 = 10x41, 768 = 26x72)
   ============================================================ */
@media (min-width: 768px) {
  :root {
    --edge: 4vw;   /* uppmätt: RUTNÄTETS vänsterkant = 4vw vid 768..1920 */
    --row: 1.97754vw; /* uppmätt radhöjd, konstant kvot över 13 mätpunkter */
  }

  /* HEADERN följer INTE rutnätets 4vw förrän vid 800: uppmätt @768 ligger
     logotypen på x46 och burgerns högerkant på 722 (= 768 - 46), dvs 6vw —
     samma sidmarginal som mobilheadern. Först vid 800 (samma brytpunkt som
     desktopnavet) går headern över till rutnätets 4vw. diff.js @768 fällde
     ctrl:icon#0 (x46 vs 31) och ctrl:open menu (x675 vs 690) på just detta. */
  .header { padding-inline: 6vw; }

  .logo { width: 92px; height: 92px; }
  /* wordmarken behåller mallens 50px logotyphöjd men får fri bredd */
  .logo-wordmark { width: auto; font-size: 26px; }
  /* 768-799: logotypen (50px) är högsta headerbarnet, inte burgern */
  :root { --header-h: calc(12vw + 92px); }

  .fluid-engine {
    grid-template-columns: calc(var(--edge) - var(--gap)) repeat(24, 1fr) calc(var(--edge) - var(--gap));
    /* 46 rader: fe-years slutar på 47 (donatorn: 72, men dennes hero och
       arbetsprov var mycket högre). Överblivna rader blir tomyta. */
    grid-template-rows: repeat(40, minmax(var(--row), auto));
  }

  /* uppmätta grid-spann i facit (desktop) */
  /* AVSTEG (Samis dom): donatorn har 3/22 x 2/13 = 804x919. Krympt till
     8 spalter x 14 rader = 582x675 så ledradens början ryms i första vyn
     på 1080p. Proportionen 0,86 ligger nära donatorns 0,875, så
     beskärningen av porträttet beter sig likadant. */
  /* Heron ett STEG åt höger, inte hela vägen (Samis rättelse 2026-08-18):
     rutnätets spaltpitch är 74px vid 1920, så 3/11 flyttar bilden 74px in
     från vänstermarginalen — kanten ligger då på x=151 i stället för 77.
     Bredden (8 spalter) är oförändrad. */
  /* ~20% mindre (Samis dom). Bredden ar FLYTANDE, inte ett spaltantal:
     rutnatets gap ar fasta 11px vid alla bredder, sa ett fast spaltantal ger
     168px vid 768 och 433px vid 1920 - och rader och spalter krymper i olika
     takt, vilket vid 768/1024 gjorde det STAENDE portrattet liggande.
     Vanterkanten ligger kvar pa spalt 4; hojden kommer ur bildens eget
     format i stallet for ur radantalet. */
  .fe-hero-media {
    grid-row: 2 / 13;
    grid-column: 4 / 16;
    /* Samis dom: större igen. 576px vid 1920. */
    width: clamp(270px, 30vw, 576px);
    aspect-ratio: 4 / 5;
  }
  /* två rader extra luft mellan bild och text (Samis dom) */
  .fe-hero-copy  { grid-row: 14 / 24; grid-column: 2 / 26; }
  /* AVSTEG (Samis dom): 14 rader = 675px @1920 -> 2,85:1.
     Donatorns tal var 33 rader / 1605px, alltså nästan kvadratiskt. */
  /* Två rader närmare texten (Samis dom): glappet mellan textens sista rad
     och bandets överkant gick från 178px till 80px. */
  .fe-work       { grid-row: 25 / 39; grid-column: 1 / 27; }
  .fe-years      { grid-row: 40 / 41; grid-column: 2 / 5; }

  .fe-footer {
    grid-template-columns: var(--edge) repeat(24, 1fr) var(--edge);
    grid-template-rows: repeat(4, minmax(var(--row), auto));
  }
  .fe-copyright { grid-row: 4 / 5; grid-column: 2 / 5; }
  .fe-email     { grid-row: 4 / 5; grid-column: 23 / 26; }

  .fe-hero-copy h1 {
    /* uppmätt: 768->44.08, 800->44.8, 900->48.4, 1200->59.2, 1440->67.84,
       klampad vid 80.8 från 1800px (16 + 3.6*18 = 80.8) */
    font-size: min(calc(16px + 3.6vw), 80.8px);
  }
}

/* ============================================================
   DESKTOPNAVET — brytpunkt 800 (binärsökt: dolt t.o.m. 799, synligt vid 800)
   uppmätt @800..1920: nav lodrätt centrerad, lucka 1.5vw mellan poster,
   2.5vw mellan navet och ikonerna, ikonernas högerkant på 96vw.
   ============================================================ */
@media (min-width: 800px) {
  .header {
    padding-block: 2.1875vw; /* h = 4.375vw + logotypens höjd */
    /* AVSTEG (Samis dom): donatorns headermarginal är uppmätt 4vw, lika med
       innehållets. Dragen till 7vw så logotypen sitter längre in från vänster
       och menyn längre in från höger — headern ligger alltså INTE längre i
       linje med innehållets kanter. Medvetet. */
    padding-inline: 7vw;
  }

  .burger { display: none; }

  .nav-primary {
    display: flex;
    margin-left: auto;
    gap: 1.5vw;
  }
  .social {
    display: flex;
    align-items: center;
    gap: 1.5vw;
    margin-left: 2.5vw;
  }
}

/* ============================================================
   MOBILMENY = FULLSKÄRMSOVERLAY (<800)

   Byggd ur reference/states/open-menu/{dom-390.html,style-390.json,shot-390.png}
   plus live-mätning av det öppna läget vid 390x844.

   VARNING till framtida varv: state-packets manifest anger den skördade panelen
   som rect 390x84 med orientation "horizontal" — det är HEADER-elementet, inte
   overlayn. En tidigare byggrunda byggde en horisontell rad inklämd i headern ur
   just den metadatan och fick meny-gate grön, eftersom grinden jämförde samma
   felaktiga region på båda sidor. shot-390.png är facit: en svart fullskärms-
   overlay med stora centrerade länkar och sociala ikoner nedtill.

   UPPMÄTT @390x844 (öppet läge):
     .header-menu        fixed inset 0, 390x844, flex column, z-index 1,
                         padding-top 83.78 (= headerhöjden), bg transparent
                         stängd: opacity 0 + visibility hidden
                         transition: visibility .6s / opacity .4s
                                     cubic-bezier(0.4, 0, 0.2, 1)
     .header-menu-bg     absolute inset 0, rgb(0,0,0)   <- den solida svartan
     .header-menu-nav-list  translateY(20px) -> 0, transform .6s samma kurva
     folder-content      flex column, justify-content center  (h682)
     nav-wrapper         h170, centrerad -> y340
     länk                inline-flex, margin-block 11.7px, fs 8.5vw, lh 1,
                         color rgb(245,245,243), centrerad
                         -> Canvas y352, Screen y408, Journal y465 (facit exakt)
     sociala ikoner      25x25, fill rgb(245,245,243), gap 15px, centrerade,
                         blockhöjd 78 med padding-top 15 -> y781
     body                overflow hidden

   Länkstorleken är breddstyrd med två uppmätta brytpunkter (binärsökt: 575 ger
   8.5vw, 576 ger 6.6vw):
       <576      8.5vw   (390 -> 33.15px = facit)
       576-767   6.6vw
       768-799   6.0vw
   ============================================================ */
@media (max-width: 799px) {
  .header-menu {
    position: fixed;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    padding-top: var(--header-h);
    background: transparent;
    opacity: 0;
    visibility: hidden;
    transition:
      visibility 0.6s cubic-bezier(0.4, 0, 0.2, 1),
      opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
  body.menu-open .header-menu {
    opacity: 1;
    visibility: visible;
  }

  .header-menu-bg {
    position: absolute;
    inset: 0;
    background: rgb(0, 0, 0);
  }

  .header-menu-nav {
    position: relative;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
  }
  .header-menu-nav-list {
    position: relative;
    flex: 1 1 auto;
    transform: translateY(20px);
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  }
  body.menu-open .header-menu-nav-list { transform: translateY(0); }

  .header-menu-nav-folder {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
  }
  .header-menu-nav-folder-content {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .header-menu-nav-item { text-align: center; }
  .header-menu-nav-item a {
    display: inline-flex;
    align-items: center;
    margin-block: 11.7px;
    font-size: 8.5vw;
    line-height: 1;
    letter-spacing: normal;
    color: var(--fg);
    text-decoration: none;
  }
  @media (min-width: 576px) {
    .header-menu-nav-item a { font-size: 6.6vw; }
  }
  @media (min-width: 768px) {
    .header-menu-nav-item a { font-size: 6vw; }
  }

  /* uppmätt: blocket är 78px högt, ikonerna 25x25 med 15px luft ovanför -> y781 */
  .header-menu-social {
    flex: 0 0 auto;
    height: 78px;
    padding-top: 15px;
    display: flex;
    justify-content: center;
    gap: 15px;
  }
  .header-menu-social a {
    display: block;
    width: 25px;
    height: 25px;
    color: var(--fg); /* uppmätt fill rgb(245,245,243) — ljusare än headerns muted */
  }
  .header-menu-social svg { display: block; width: 100%; height: 100%; fill: currentColor; }
}

@media (min-width: 800px) {
  .header-menu { display: none; }
}

/* ============================================================
   UNDERSIDOR — PORTENS TILLÄGG

   ALLT nedan är UPPMÄTT LIVE på donatorns egna undersidor 2026-08-10
   (www.sanghan.co/canvas och /journal, 1920x1080 + 390x844).
   Rådata: matning/subpages-probe.json, sammanfattning i PORT.RAPPORT.md.

   Mätfyndet: båda undersidorna är SAMMA konstruktion — header, ETT
   fluid-engine-rutnät med helbreddsbilder staplade på varandra, footer.
   Ingen rubrik, ingen bildtext, ingen brödtext någonstans. Det enda som
   skiljer sidorna åt är blockens RADSPANN, alltså bildhöjden:

     canvas  (-> PROJEKT):  22 rader desktop = 1066px @1920
                             7 rader mobil   =  234px @390
     journal (-> ARKIV):    25 rader desktop = 1213px @1920
                             8 rader mobil   =  269px @390

   Höjden räknas i rutnätets egna enheter, span*rad + (span-1)*gap, vilket
   reproducerar de uppmätta talen inom 0,3px. Därför sätts höjden med den
   formeln i stället för med hårda pixlar — då följer den rutnätet vid alla
   bredder, precis som donatorns gör.

   Sektionspaddingen är uppmätt SYMMETRISK (samma över som under stapeln):
     canvas  192px @1920 = 10,000vw · 84px @390 = 21,5vw
     journal 127px @1920 =  6,615vw · 55px @390 = 14,1vw
   ============================================================ */

.fe-stack {
  display: grid;
  grid-template-columns: calc(var(--edge) - var(--gap)) repeat(8, 1fr) calc(var(--edge) - var(--gap));
  gap: var(--gap);
}
.fe-stack .fe-block { grid-column: 1 / 11; }

/* bildblocken: samma absolutmodell som startsidans bildband, så att blockets
   höjd blir EXAKT radspannet och bildens egen höjd inte blåser upp raden */
.stack-media { position: relative; overflow: hidden; }
.stack-media .image-link { position: absolute; inset: 0; display: block; }
.stack-media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 50%;
  max-width: none;
}

/* uppmätt bildhöjd = radspann (mobil: rad 24px fast) */
/* AVSTEG (Samis dom 2026-08-18): donatorns canvas-bilder är 7 spann @390 /
   22 @1920. Sami vill ha bredare format. 5 spann = 164px -> 2,38:1, nära
   desktopens 2,34:1 så blocken håller samma proportion vid båda bredderna. */
.stack-projekt .stack-media { height: calc(4 * var(--row) + 3 * var(--gap)); }   /* 129px @390 */
.stack-arkiv   .stack-media { height: calc(8 * var(--row) + 7 * var(--gap)); }   /* 269px @390 */

/* Halverad mot donatorns uppmätta 21,5 / 10vw (Samis dom): för mycket luft
   mellan headern och första bilden. */
.stack-projekt { padding-block: 10vw; }
.stack-arkiv   { padding-block: 14.1vw; }

/* Luft runt bildtexten. Rutnätets 11px-gap ensamt klämmer in raden mot
   bildkanten; marginalen grupperar texten med bilden OVANFÖR och skiljer den
   från nästa projekt. Rör inga uppmätta värden — bildhöjder och
   sektionspadding är oförändrade, det är bara textradens egen luft. */
.fe-stack .stack-caption { margin-top: 8px; margin-bottom: 28px; }

/* Bildtext under varje projekt. DESIGNANPASSNING, bokförd: donatorns canvas-sida
   har INGEN bildtext alls. Kundens projekt måste kunna namnges, så raden sätts i
   donatorns enda uppmätta smårubriksstil (H4 fs16 lh1.2 ls-0.02em — samma som
   "2013 - Present" och footern) i startsidans uppmätta textkolumn. */
.fe-stack .stack-caption { grid-column: 2 / 10; }
.stack-caption h4 {
  margin: 0;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.stack-caption .caption-meta { color: var(--muted); }

/* KONTAKTSIDAN: donatorn HAR ingen kontaktsida (uppmätt: 404). Sidan byggs
   därför på startsidans uppmätta textslot — h1-graden och kolumnspannet är
   donatorns, innehållet är kundens e-post. Bokförd designanpassning. */
.fe-contact,
.fe-arkiv { padding-block: 21.5vw; }
.fe-stack.fe-contact .contact-block,
.fe-stack.fe-arkiv .arkiv-block { grid-column: 2 / 10; }
/* Kontaktuppgifterna centrerade (Samis dom). */
.fe-contact .contact-block { text-align: center; }
.fe-contact .kontakt-telefon { margin-top: 0.35em; }
.fe-contact h1,
.fe-arkiv h1 {
  margin: 0;
  font-weight: 400;
  font-size: min(calc(16px + 3.6vmax), 48.4px);
  line-height: 1.056;
  letter-spacing: -0.02em;
  color: var(--fg);
}
/* footerns uppmätta understrykning (1px @ fs16 -> 0.0625em, offset 3.2px -> 0.2em)
   uttryckt i em så den skalar med den fluida rubrikgraden */
.fe-arkiv .arkiv-vantar { color: var(--muted); }
.fe-contact a {
  text-decoration: underline;
  text-decoration-thickness: 0.0625em;
  text-underline-offset: 0.2em;
}

@media (min-width: 768px) {
  .fe-stack {
    grid-template-columns: calc(var(--edge) - var(--gap)) repeat(24, 1fr) calc(var(--edge) - var(--gap));
  }
  .fe-stack .fe-block { grid-column: 1 / 27; }

  /* uppmätt: 22 rader -> 1066px @1920 · 25 rader -> 1213px @1920 */
  /* 17 spann = 821px @1920 -> 2,34:1 (donatorns tal var 22 spann / 1066px) */
  /* 14 spann = 675px @1920 -> 2,85:1, samma format som arbetsprovsbandet
     på startsidan (Samis dom: ännu bredare). Donatorns tal var 22 spann. */
  .stack-projekt .stack-media { height: calc(14 * var(--row) + 13 * var(--gap)); }
  .stack-arkiv   .stack-media { height: calc(25 * var(--row) + 24 * var(--gap)); }

  .stack-projekt { padding-block: 5vw; }
  .stack-arkiv   { padding-block: 6.615vw; }

  .fe-stack .stack-caption { grid-column: 2 / 26; }

  .fe-contact,
  .fe-arkiv { padding-block: 10vw; }
  .fe-stack.fe-contact .contact-block,
  .fe-stack.fe-arkiv .arkiv-block { grid-column: 2 / 26; }
  .fe-contact h1,
  .fe-arkiv h1 { font-size: min(calc(16px + 3.6vw), 80.8px); }
}

/* Den som bett om mindre rörelse ska varken få blinkning eller reveal. */
@media (prefers-reduced-motion: reduce) {
  .logo:hover .of-oga,
  .logo:focus-visible .of-oga { animation: none; }
}

/* ═══════ FOTOSIDAN ═══════
   Arkivet är Samis egna fotoserier. Bilderna är 2:3-porträtt, så ett rutnät
   som behåller det formatet visar dem hela — donatorns helbreddsstapel hade
   beskurit varje porträtt till en liggande remsa. Ingen bildtext: bilderna
   är innehållet. */
.foto-rutnat {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
  padding-inline: var(--edge);
  /* Halverad mot donatorns uppmätta 14,1 / 6,615vw (Samis dom): luften mellan
     headern och första bildraden tog för mycket plats. */
  padding-block: 7vw;
}
/* Varje bild är en knapp (öppnar ljuslådan) — nollställ knapputseendet. */
.foto-ruta {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  display: block;
  overflow: hidden;
  cursor: zoom-in;
  -webkit-tap-highlight-color: transparent;
}
.foto-ruta img {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  display: block;
  transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1),
              filter 700ms cubic-bezier(0.16, 1, 0.3, 1);
}
.foto-ruta:hover img,
.foto-ruta:focus-visible img { transform: scale(1.035); filter: brightness(1.06); }
.foto-ruta:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }

/* Liggande bild tar två spalter och behåller sitt eget format i stället för
   att beskäras till porträtt (Samis dom). */
.foto-ruta.liggande, .media-bred { grid-column: 1 / -1; }
.foto-ruta.liggande img { aspect-ratio: 3 / 2; }

@media (min-width: 768px) {
  .foto-rutnat { grid-template-columns: repeat(3, 1fr); padding-block: 3.3vw; }
}

/* ═══════ LJUSLÅDAN ═══════
   Bilderna är små på mobil; ett tryck öppnar dem i full storlek (Samis dom).
   Fullstorleksfilen ligger i assets/foto/stor/ och hämtas först vid klick. */
.ljuslada {
  position: fixed;
  inset: 0;
  z-index: 9998;
  background: rgba(0, 0, 0, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vw;
  opacity: 0;
  transition: opacity 260ms ease;
}
.ljuslada[hidden] { display: none; }
.ljuslada.pa { opacity: 1; }
.ljuslada-bild {
  max-width: 100%;
  max-height: 92vh;
  object-fit: contain;
  display: block;
}
.ljuslada-knapp {
  position: fixed;
  background: none;
  border: 0;
  color: var(--fg);
  font-family: var(--font);
  font-size: 34px;
  line-height: 1;
  padding: 14px 18px;
  cursor: pointer;
  opacity: 0.65;
  transition: opacity 200ms ease;
}
.ljuslada-knapp:hover,
.ljuslada-knapp:focus-visible { opacity: 1; }
.ljuslada-stang { top: 2vw; right: 3vw; }
.ljuslada-bak   { left: 2vw;  top: 50%; transform: translateY(-50%); }
.ljuslada-fram  { right: 2vw; top: 50%; transform: translateY(-50%); }
body.ljuslada-oppen { overflow: hidden; }

/* ═══════ SIDÖVERGÅNGAR ═══════
   View Transitions för flersidiga sajter: webbläsaren tar en bild av den
   gamla sidan, låter den ligga kvar över den nya och animerar ut den. Kräver
   ingen JS och inget bibliotek. Webbläsare utan stöd (Firefox i dag) byter
   sida direkt som vanligt — inget går sönder.
   Rörelsen är den Sami redan valt i ett annat projekt: gamla sidan tonas ned
   och LYFTER, nya ligger under och kommer fram. */
@view-transition { navigation: auto; }

::view-transition-old(root) {
  animation: sida-ut 620ms cubic-bezier(0.65, 0, 0.35, 1) forwards;
  z-index: 2;                 /* gamla sidan ligger ÖVER, nya kommer under */
}
::view-transition-new(root) {
  animation: sida-in 620ms cubic-bezier(0.33, 1, 0.68, 1);
  z-index: 1;
}
@keyframes sida-ut {
  to { transform: translateY(-6%); filter: brightness(0.55); opacity: 0; }
}
@keyframes sida-in {
  from { transform: translateY(2%); opacity: 0.6; }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ═══════ MELLANBREDDER ═══════
   Rutnätets gap är FASTA 11px vid alla bredder (donatorns eget värde). Vid
   768-1199 äter de 25 gapen en tredjedel av raden, så en spalt är bara ~19px
   och heron kollapsar till 168px. Den får därför fler spalter här — samma
   bredd i px, uttryckt i det rutnät som råder. */
@media (min-width: 768px) {
  /* Footerns uppmätta spann är 3 spalter. Det rymmer donatorns 16px men inte
     Samis 22px — "© 2026 OLSSON-FRAMÅT" bryter på två rader ända upp i 1440.
     Spannen breddas därför på hela desktop. Placeringen (yttersta vänster
     respektive höger) är oförändrad; bara utrymmet är större. */
  .fe-copyright { grid-column: 2 / 11; }
  .fe-email     { grid-column: 17 / 26; }
}

/* Footerns 22px hör hemma först när kolumnerna är breda nog. Vid 768 bryter
   "© 2026 OLSSON-FRAMÅT" på tre rader i sitt uppmätta spann. */
@media (min-width: 1200px) {
  .fe-copyright h4,
  .fe-email h4 { font-size: 22px; }
}

/* Tvåspaltshero PRÖVAT OCH FÖRKASTAT 2026-08-18. Texten bredvid bilden
   tvingade ner rubrikgraden från 80,8px till 46 — och Samis dom blev att den
   gamla graden och placeringen under bilden var bättre. Bilden behåller
   däremot sin nya, större bredd. */

/* ═══════ LJUSLÅDANS KNAPPAR ═══════
   Samis dom: enklare, mer brutalistiskt. Ingen intoning, ingen halvgenomskinlig
   vila — tecknet står i full styrka eller inte alls. Kvadratisk träffyta. */
.ljuslada-knapp {
  opacity: 1;
  font-size: 22px;
  line-height: 1;
  width: 56px;
  height: 56px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: none;
}
.ljuslada-knapp:hover,
.ljuslada-knapp:focus-visible { opacity: 1; background: var(--fg); color: var(--bg); }
.ljuslada-stang { top: 0; right: 0; }
.ljuslada-bak   { left: 0;  top: 50%; transform: translateY(-50%); }
.ljuslada-fram  { right: 0; top: 50%; transform: translateY(-50%); }

/* Media: liggande material använder alla tre desktopkolumnerna. */
.media-film { margin: 0; min-width: 0; background: #000; }
.media-film video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; }
.stack-projekt .projekt-logotyp { background: #fff; }
.stack-projekt .projekt-logotyp img {
  object-fit: contain;
  box-sizing: border-box;
  padding: clamp(12px, 3vw, 56px);
}

.work-pause { position:absolute; right:16px; bottom:16px; z-index:2; width:36px; height:36px; border:1px solid #ffffff66; border-radius:50%; background:#0009; color:white; font:16px sans-serif; cursor:pointer; }
.work-pause[hidden] { display:none; }
.work-pause:focus-visible { outline:2px solid white; outline-offset:3px; }
