:root{
    --plum:#771473;
    --plum-ink:#2A0F29;
    --plum-deep:#4A0D48;
    --green:#49B848;
    --green-ink:#2C7E2B;
    --paper:#FBF8FB;
    --mist:#F1E9F1;
    --line:#E3D6E3;
    --stone:#6E5F6D;
    --ink:#1E141E;
    --white:#FFFFFF;
    /* ── Typeface set ──────────────────────────────────────────────────
       Change the FIRST name on each line to change the whole site's
       typography. Both sets are self-hosted and both are present in
       assets/fonts, so this is a one-line revert in either direction.

         Canada's set (current) : Oswald / Catamaran
         Original .se design    : "Bricolage Grotesque" / "Instrument Sans"

       The second name on each line is the fallback, which means a revert is
       literally deleting the first name. If you switch back, also update the
       preload list in functions.php — it names the two files that paint
       first, and preloading the wrong pair costs a flash of fallback text. */
    --display:Oswald,"Bricolage Grotesque",system-ui,sans-serif;
    --body:Catamaran,"Instrument Sans",system-ui,sans-serif;
    --mono:"JetBrains Mono",ui-monospace,monospace;
    --max:1180px;
    --r:14px;
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html{scroll-behavior:smooth}
  body{font-family:var(--body);color:var(--ink);background:var(--paper);line-height:1.55;-webkit-font-smoothing:antialiased}
  a{color:inherit;text-decoration:none}
  img{max-width:100%;display:block}
  .wrap{max-width:var(--max);margin:0 auto;padding:0 24px}
  h1,h2,h3{font-family:var(--display);line-height:1.05;letter-spacing:-0.02em;color:var(--plum-ink)}
  h1{font-size:clamp(2.4rem,5.2vw,4.4rem);font-weight:800}
  h2{font-size:clamp(1.9rem,3.4vw,2.8rem);font-weight:700}
  h3{font-size:1.25rem;font-weight:700;letter-spacing:-0.01em}
  p{max-width:58ch}
  .eyebrow{font-family:var(--mono);font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--plum);display:inline-flex;align-items:center;gap:.5rem}
  .eyebrow::before{content:"";width:18px;height:2px;background:var(--green);display:inline-block}
  .muted{color:var(--stone)}
  .btn{display:inline-flex;align-items:center;gap:.55rem;padding:.9rem 1.35rem;border-radius:999px;font-weight:600;font-size:.98rem;border:1.5px solid transparent;transition:transform .15s ease,background .15s,color .15s,border-color .15s;cursor:pointer;font-family:var(--body)}
  .btn:focus-visible{outline:3px solid var(--green);outline-offset:3px}
  .btn-primary{background:var(--plum);color:#fff}
  .btn-primary:hover{background:var(--plum-deep);transform:translateY(-1px)}
  .btn-ghost{border-color:var(--line);color:var(--plum-ink);background:transparent}
  .btn-ghost:hover{border-color:var(--plum);color:var(--plum)}
  .btn-green{background:var(--green);color:#fff}
  .btn-green:hover{background:var(--green-ink)}
  section{padding:96px 0}
  @media(max-width:760px){section{padding:64px 0}}

  /* NAV */
  header{position:sticky;top:0;z-index:50;background:rgba(251,248,251,.86);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
  nav{display:flex;align-items:center;justify-content:space-between;height:72px}
  .logo{display:flex;align-items:center;gap:.35rem;font-family:var(--display);font-weight:800;font-size:1.35rem;color:var(--plum);letter-spacing:-.02em}
  .logo .mm{color:var(--green);font-weight:700}
  .logo .se{font-family:var(--mono);font-size:.7rem;font-weight:500;color:var(--stone);margin-left:.45rem;letter-spacing:.08em;border:1px solid var(--line);padding:.15rem .4rem;border-radius:6px}
  .nav-links{display:flex;gap:2rem;font-size:.95rem;font-weight:500}
  .nav-links a:hover{color:var(--plum)}
  .nav-cta{display:flex;align-items:center;gap:1.2rem}
  .nav-phone{font-family:var(--mono);font-size:.85rem;color:var(--stone)}
  @media(max-width:960px){.nav-links,.nav-phone{display:none}.nav-cta .btn{padding:.65rem 1rem;font-size:.88rem;white-space:nowrap}.logo .se{display:none}}

  /* HERO */
  .hero{padding:72px 0 56px;position:relative;overflow:hidden}
  .hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:center}
  @media(max-width:900px){.hero-grid{grid-template-columns:1fr;gap:48px}}
  .hero h1 .hl{color:var(--plum);position:relative;white-space:nowrap}
  .hero h1 .hl::after{content:"";position:absolute;left:0;right:0;bottom:.06em;height:.16em;background:var(--green);opacity:.35;z-index:-1;border-radius:2px}
  .hero p.lead{font-size:1.15rem;color:var(--stone);margin:24px 0 32px;max-width:52ch}
  .hero-actions{display:flex;gap:.8rem;flex-wrap:wrap;align-items:center}
  .hero-note{margin-top:18px;font-size:.85rem;color:var(--stone);display:flex;gap:1.2rem;flex-wrap:wrap}
  .hero-note span::before{content:"✓ ";color:var(--green);font-weight:700}
  .trust{margin-top:44px;padding-top:24px;border-top:1px solid var(--line);display:flex;gap:2.2rem;flex-wrap:wrap}
  .trust b{font-family:var(--display);font-size:1.5rem;color:var(--plum-ink);display:block;line-height:1}
  .trust small{font-size:.8rem;color:var(--stone)}

  /* SIGNATURE: Maps local pack */
  .pack{background:var(--white);border:1px solid var(--line);border-radius:22px;box-shadow:0 30px 60px -30px rgba(119,20,115,.35),0 2px 0 rgba(119,20,115,.05);padding:18px;max-width:460px;margin-left:auto;position:relative}
  @media(max-width:900px){.pack{margin:0 auto}}
  .pack .search{display:flex;align-items:center;gap:.6rem;background:var(--mist);border-radius:999px;padding:.65rem 1rem;font-size:.9rem;color:var(--ink)}
  .pack .search svg{flex:none}
  .pack .search .q{font-weight:500}
  .pack .map{margin-top:14px;height:120px;border-radius:14px;background:
    radial-gradient(circle at 30% 40%,rgba(73,184,72,.18),transparent 40%),
    repeating-linear-gradient(0deg,#F3EDF3 0 18px,#E9DFE9 18px 19px),
    repeating-linear-gradient(90deg,#F3EDF3 0 26px,#E9DFE9 26px 27px);position:relative;overflow:hidden}
  .pin{position:absolute;width:14px;height:14px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);background:#C9B7C8}
  .pin.you{background:var(--green);box-shadow:0 0 0 6px rgba(73,184,72,.22)}
  .pack ol{list-style:none;margin-top:14px;display:flex;flex-direction:column;gap:8px}
  .pack li{display:grid;grid-template-columns:28px 1fr auto;gap:10px;align-items:center;padding:10px 12px;border-radius:12px;border:1px solid var(--line);background:var(--white);transition:transform .6s cubic-bezier(.2,.8,.2,1),background .4s}
  .pack li .rank{font-family:var(--mono);font-size:.8rem;color:var(--stone);text-align:center}
  .pack li .name{font-weight:600;font-size:.93rem;color:var(--plum-ink)}
  .pack li .meta{font-size:.78rem;color:var(--stone)}
  .pack li .stars{color:#E8A900;font-size:.78rem}
  .pack li .tag{font-family:var(--mono);font-size:.66rem;letter-spacing:.08em;text-transform:uppercase;padding:.25rem .5rem;border-radius:6px;background:var(--mist);color:var(--stone)}
  .pack li.you{border-color:var(--green);background:#F3FBF3}
  .pack li.you .tag{background:var(--green);color:#fff}
  .pack li.you .rank{color:var(--green-ink);font-weight:600}
  .pack .cap{margin-top:12px;font-family:var(--mono);font-size:.7rem;color:var(--stone);display:flex;justify-content:space-between;gap:.6rem;flex-wrap:wrap}
  .pack .cap em{font-style:normal;color:var(--green-ink)}
  /* reorder animation: "you" starts low, rises */
  .pack li.you{order:0}
  @media(prefers-reduced-motion:no-preference){
    .pack ol{--shift:0}
    .pack li.you{animation:rise 1.6s cubic-bezier(.2,.8,.2,1) .6s both}
    @keyframes rise{0%{transform:translateY(132px);opacity:.6}40%{opacity:1}100%{transform:translateY(0)}}
    .pack li:not(.you){animation:drop 1.6s cubic-bezier(.2,.8,.2,1) .6s both}
    @keyframes drop{0%{transform:translateY(-66px)}100%{transform:translateY(0)}}
    .pack .cap em{animation:blink 1s steps(2) .9s 3}
    @keyframes blink{50%{opacity:.3}}
  }

  /* WHO */
  .who{padding:0}
  .who-row{display:flex;align-items:center;gap:2rem;flex-wrap:wrap;border:1px solid var(--line);border-radius:var(--r);padding:22px 26px;background:var(--white)}
  .who-row p{font-size:.95rem;color:var(--stone);max-width:34ch;margin:0}
  .chips{display:flex;gap:.5rem;flex-wrap:wrap}
  .chip{padding:.45rem .85rem;border-radius:999px;background:var(--mist);font-size:.88rem;font-weight:500;color:var(--plum-ink)}

  /* SERVICES */
  .sec-head{display:flex;justify-content:space-between;align-items:flex-end;gap:2rem;margin-bottom:44px;flex-wrap:wrap}
  .sec-head p{margin-top:12px;color:var(--stone);font-size:1.05rem}
  .services{display:grid;grid-template-columns:repeat(5,1fr);gap:14px}
  @media(max-width:1100px){.services{grid-template-columns:repeat(3,1fr)}}
  @media(max-width:760px){.services{grid-template-columns:repeat(2,1fr)}}
  @media(max-width:560px){.services{grid-template-columns:1fr}}
  .svc{background:var(--white);border:1px solid var(--line);border-radius:var(--r);padding:24px 20px 20px;display:flex;flex-direction:column;gap:12px;position:relative;transition:transform .2s,border-color .2s}
  .svc:hover{transform:translateY(-3px);border-color:var(--plum)}
  .svc .ico{width:40px;height:40px;border-radius:10px;background:var(--mist);display:grid;place-items:center;color:var(--plum)}
  .svc p{font-size:.9rem;color:var(--stone);flex:1}
  .svc .price{font-family:var(--mono);font-size:.8rem;color:var(--plum-ink);border-top:1px solid var(--line);padding-top:12px}
  .svc .price b{color:var(--plum)}
  .svc.lead-svc{border-color:var(--plum);background:linear-gradient(180deg,#fff,#F8F2F8)}
  .svc .pill{position:absolute;top:-11px;left:20px;background:var(--green);color:#fff;font-family:var(--mono);font-size:.66rem;letter-spacing:.08em;text-transform:uppercase;padding:.3rem .6rem;border-radius:6px}
  .svc a.more{font-weight:600;font-size:.9rem;color:var(--plum)}
  .svc a.more::after{content:" →"}

  /* HOW */
  .how{background:var(--white);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
  .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:44px;counter-reset:step}
  @media(max-width:760px){.steps{grid-template-columns:1fr}}
  .step{padding:28px 24px;border-radius:var(--r);background:var(--paper);border:1px solid var(--line);position:relative}
  .step .n{font-family:var(--display);font-size:2.6rem;font-weight:800;color:var(--mist);line-height:1;-webkit-text-stroke:1.5px var(--plum);color:transparent;margin-bottom:10px}
  .step .t{font-family:var(--mono);font-size:.7rem;color:var(--green-ink);letter-spacing:.1em;text-transform:uppercase;margin-bottom:6px}
  .step p{font-size:.93rem;color:var(--stone);margin-top:8px}

  /* PROOF + PRICING (dark band) */
  .band{background:var(--plum-ink);color:#EFE3EE;position:relative;overflow:hidden}
  .band::before{content:"";position:absolute;inset:auto -10% -40% auto;width:60vw;height:60vw;border-radius:50%;border:1px solid rgba(255,255,255,.06);pointer-events:none}
  .band h2,.band h3{color:#fff}
  .band .eyebrow{color:#D9A7D6}
  .band-grid{display:grid;grid-template-columns:1fr 1.1fr;gap:64px;align-items:start}
  @media(max-width:900px){.band-grid{grid-template-columns:1fr}}
  .quote{border-left:2px solid var(--green);padding-left:18px;margin-top:28px}
  .quote p{font-family:var(--display);font-size:1.2rem;font-weight:500;line-height:1.35;color:#fff;max-width:40ch}
  .quote cite{display:block;font-style:normal;font-size:.85rem;color:#C8B3C6;margin-top:10px}
  .logos{display:flex;gap:1.6rem;flex-wrap:wrap;margin-top:32px;font-family:var(--mono);font-size:.75rem;letter-spacing:.06em;color:#B897B6}
  .logos span{border:1px solid rgba(255,255,255,.14);padding:.45rem .7rem;border-radius:8px}
  .price-card{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.12);border-radius:18px;padding:28px}
  .price-card .row{display:grid;grid-template-columns:1fr auto;gap:14px;align-items:baseline;padding:16px 0;border-bottom:1px solid rgba(255,255,255,.1)}
  .price-card .row:last-of-type{border-bottom:0}
  .price-card .row .n{font-weight:600;color:#fff}
  .price-card .row .d{font-size:.85rem;color:#C8B3C6;margin-top:2px}
  .price-card .row .p{font-family:var(--display);font-weight:700;font-size:1.35rem;color:#fff;white-space:nowrap}
  .price-card .row .p small{font-family:var(--mono);font-size:.7rem;color:#B897B6;font-weight:400;margin-left:.25rem}
  .price-card .row.best{margin:0 -12px;padding:16px 12px;background:rgba(73,184,72,.1);border-radius:12px;border-bottom:0}
  .price-card .row.best .n::after{content:"populärast";font-family:var(--mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--green);margin-left:.6rem}
  .price-card .foot{margin-top:18px;font-family:var(--mono);font-size:.72rem;color:#B897B6;display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;align-items:center}

  /* ABOUT */
  .about-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
  @media(max-width:900px){.about-grid{grid-template-columns:1fr}}
  .photo{aspect-ratio:4/5;border-radius:18px;background:linear-gradient(160deg,var(--mist),#E1CFE0);position:relative;overflow:hidden;border:1px solid var(--line)}
  .photo .ph{position:absolute;inset:0;display:grid;place-items:center;font-family:var(--mono);font-size:.75rem;color:var(--plum);text-align:center;padding:20px}
  .photo .ring{position:absolute;width:70%;aspect-ratio:1;border-radius:50%;border:1.5px solid var(--plum);opacity:.25;left:15%;top:12%}
  .photo .ring::after{content:"";position:absolute;inset:12%;border-radius:50%;border:1px dashed var(--plum)}
  .about p{color:var(--stone);margin-top:16px}
  .facts{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:28px}
  .fact{padding:14px 16px;border:1px solid var(--line);border-radius:12px;background:var(--white)}
  .fact b{display:block;font-family:var(--display);font-size:1.2rem;color:var(--plum-ink)}
  .fact small{color:var(--stone);font-size:.8rem}

  /* CTA FORM */
  .cta{background:var(--white);border-top:1px solid var(--line)}
  .cta-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
  @media(max-width:900px){.cta-grid{grid-template-columns:1fr}}
  .cta ul{list-style:none;margin-top:20px;display:flex;flex-direction:column;gap:10px;color:var(--stone)}
  .cta ul li::before{content:"→ ";color:var(--green);font-weight:700}
  form{background:var(--paper);border:1px solid var(--line);border-radius:18px;padding:28px;display:grid;gap:14px}
  label{font-size:.85rem;font-weight:600;color:var(--plum-ink);display:grid;gap:6px}
  input,select{font:inherit;font-size:.95rem;padding:.8rem .95rem;border-radius:10px;border:1.5px solid var(--line);background:#fff;color:var(--ink)}
  input:focus,select:focus{outline:none;border-color:var(--plum);box-shadow:0 0 0 3px rgba(119,20,115,.12)}
  form .fine{font-size:.78rem;color:var(--stone)}

  /* FOOTER */
  footer{padding:56px 0 32px;border-top:1px solid var(--line);font-size:.88rem;color:var(--stone)}
  .foot-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:32px}
  @media(max-width:760px){.foot-grid{grid-template-columns:1fr 1fr}}
  footer h4{font-family:var(--mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--plum);margin-bottom:14px}
  footer ul{list-style:none;display:grid;gap:8px}
  footer a:hover{color:var(--plum)}
  .legal{margin-top:40px;padding-top:20px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;font-family:var(--mono);font-size:.72rem}

  /* v2 additions */
  /* .hero-grid columns are NOT restated here. This block sits after the
     @media(max-width:900px) rule above, so repeating the property at the
     same specificity overrode the mobile stack at every width — the hero
     text column was 164px on a phone. Set columns at line 58 only. */
  .collage{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:12px;aspect-ratio:1/1;max-width:520px;margin-left:auto}
  @media(max-width:900px){.collage{margin:0 auto}}
  .collage img{width:100%;height:100%;object-fit:cover;border-radius:16px}
  .collage .tall{grid-row:span 2}
  .collage .lbl{position:relative}
  .collage .lbl span{position:absolute;left:12px;bottom:12px;background:rgba(42,15,41,.78);color:#fff;font-family:var(--mono);font-size:.66rem;letter-spacing:.08em;text-transform:uppercase;padding:.3rem .55rem;border-radius:6px}
  .groups{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
  @media(max-width:900px){.groups{grid-template-columns:1fr}}
  .group{background:var(--white);border:1px solid var(--line);border-radius:var(--r);padding:26px 24px 22px;display:flex;flex-direction:column;gap:14px}
  .group .gh{display:flex;align-items:center;gap:12px}
  .group .ico{width:40px;height:40px;border-radius:10px;background:var(--mist);display:grid;place-items:center;color:var(--plum);flex:none}
  .group .sub{font-size:.9rem;color:var(--stone)}
  .group ul{list-style:none;display:grid;gap:0;border-top:1px solid var(--line);margin-top:4px}
  .group li{display:flex;justify-content:space-between;gap:1rem;align-items:baseline;padding:11px 0;border-bottom:1px solid var(--line);font-size:.93rem}
  .group li a{font-weight:600;color:var(--plum-ink)}
  .group li a:hover{color:var(--plum)}
  .group li .pr{font-family:var(--mono);font-size:.74rem;color:var(--stone);white-space:nowrap}
  .group li.start{flex-wrap:wrap;background:#F3FBF3;margin:0 -10px;padding:11px 10px;border-radius:8px;border-color:#D6EFD5}
  .group li.start .badge{font-family:var(--mono);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:#fff;background:var(--green);padding:.2rem .45rem;border-radius:5px;order:-1;flex-basis:100%}
  .group .more{font-weight:600;font-size:.9rem;color:var(--plum);margin-top:auto}
  .group .more::after{content:" →"}
  .vis{background:var(--white);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
  .vis-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
  @media(max-width:900px){.vis-grid{grid-template-columns:1fr}}
  .vis p{color:var(--stone);margin-top:16px}
  .vis .pack{margin:0}
  .work{padding-bottom:0}
  .strip{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-top:36px}
  @media(max-width:760px){.strip{grid-template-columns:repeat(3,1fr)}}
  .strip figure{aspect-ratio:1/1;border-radius:12px;overflow:hidden;position:relative;background:var(--mist)}
  .strip img{width:100%;height:100%;object-fit:cover;transition:scale .4s cubic-bezier(.2,0,0,1)}
  .strip figure:hover img{scale:1.05}
  .strip figcaption{position:absolute;left:10px;bottom:10px;font-family:var(--mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:#fff;background:rgba(42,15,41,.7);padding:.25rem .5rem;border-radius:5px}
  .strip .ph{display:grid;place-items:center;font-family:var(--mono);font-size:.62rem;color:var(--plum);text-align:center;padding:10px;border:1px dashed var(--line)}
  .how{background:transparent;border:0}
/* ---------- shared page chrome (subpages) ---------- */
.page-hero{padding:64px 0 48px;border-bottom:1px solid var(--line);background:linear-gradient(180deg,#fff,var(--paper))}
.page-hero .inner{display:grid;grid-template-columns:1.1fr .9fr;gap:56px;align-items:center}
@media(max-width:900px){.page-hero .inner{grid-template-columns:1fr;gap:36px}}
.page-hero h1{font-size:clamp(2.1rem,4.2vw,3.4rem)}
.page-hero p.lead{font-size:1.1rem;color:var(--stone);margin:20px 0 28px;max-width:52ch}
.crumbs{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--stone);margin-bottom:18px}
.crumbs a:hover{color:var(--plum)}
.page-hero .art{border-radius:18px;overflow:hidden;aspect-ratio:4/3;background:var(--mist)}
.page-hero .art img{width:100%;height:100%;object-fit:cover}

/* ── Hero illustration (hemsida som tjänst) ──────────────────────────────
   A photograph on this page announces "photographer" — the same reasoning
   that replaced the portrait og:image, see DECISIONS.md §3. Drawn inline
   instead of sourced: no licence to track, nothing downloaded, no
   third-party asset on a theme that deliberately self-hosts everything, and
   it stays sharp at any size because it is vector rather than a 4:3 crop.

   Every colour is a brand token, so changing the palette moves the
   illustration with it. The viewBox is 4:3 to match the .art frame exactly,
   so nothing is cropped. */
.art-illus{background:linear-gradient(160deg,var(--mist),var(--white))}
.art-illus svg{width:100%;height:100%;display:block}
.wf-win{fill:var(--white);stroke:var(--line);stroke-width:1.5}
.wf-chrome{fill:var(--paper)}
.wf-rule{stroke:var(--line);stroke-width:1.5}
.wf-dot{fill:var(--line)}
.wf-url{fill:var(--mist)}
.wf-live{fill:var(--green)}
.wf-mark{fill:var(--plum)}
.wf-nav{fill:var(--line)}
.wf-head{fill:var(--plum-ink)}
.wf-accent{fill:var(--green)}
.wf-cta{fill:var(--plum)}
.wf-media{fill:var(--mist)}
.wf-media-dot{fill:var(--white);opacity:.9}
.wf-media-hill{fill:var(--white);opacity:.75}
.wf-card{fill:var(--white);stroke:var(--line);stroke-width:1.25}
.wf-line{fill:var(--line)}
.wf-line-strong{fill:var(--plum-ink);opacity:.5}

/* Two ambient motions only, both slow, both saying the same thing the page
   says: the site is live, and someone is still editing it. The house easing
   curve, and nothing moves for a reader who asked for stillness. */
@media (prefers-reduced-motion: no-preference){
  @keyframes wf-breathe{0%,100%{opacity:1}50%{opacity:.3}}
  @keyframes wf-edit{0%,55%,100%{transform:scaleX(1)}28%{transform:scaleX(.5)}}
  .wf-live{animation:wf-breathe 6s cubic-bezier(.16,1,.3,1) infinite}
  .wf-update{
    transform-box:fill-box;transform-origin:left center;
    animation:wf-edit 9s cubic-bezier(.16,1,.3,1) infinite
  }
}
.cols{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.cols.two{grid-template-columns:repeat(2,1fr)}
@media(max-width:860px){.cols,.cols.two{grid-template-columns:1fr}}
.card{background:var(--white);border:1px solid var(--line);border-radius:var(--r);padding:26px 24px}
.card h3{margin-bottom:10px}
.card p{font-size:.93rem;color:var(--stone)}
.card ul{list-style:none;display:grid;gap:9px;margin-top:12px;font-size:.93rem;color:var(--stone)}
.card ul li::before{content:"✓ ";color:var(--green);font-weight:700}
.tiers{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:36px}
@media(max-width:860px){.tiers{grid-template-columns:1fr}}
.tier{background:var(--white);border:1px solid var(--line);border-radius:16px;padding:26px 24px;display:flex;flex-direction:column;gap:12px}
.tier.hot{border-color:var(--plum);box-shadow:0 24px 50px -34px rgba(119,20,115,.5);position:relative}
.tier.hot::before{content:"populärast";position:absolute;top:-10px;left:22px;background:var(--green);color:#fff;font-family:var(--mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;padding:.28rem .55rem;border-radius:6px}
.tier .amt{font-family:var(--display);font-size:2rem;font-weight:800;color:var(--plum-ink);line-height:1}
.tier .amt small{font-family:var(--mono);font-size:.75rem;font-weight:400;color:var(--stone);margin-left:.3rem}
.tier ul{list-style:none;display:grid;gap:8px;font-size:.9rem;color:var(--stone);flex:1}
.tier ul li::before{content:"✓ ";color:var(--green);font-weight:700}
.faq{display:grid;gap:0;margin-top:32px;max-width:820px}
.faq details{border-bottom:1px solid var(--line);padding:18px 0}
.faq summary{cursor:pointer;font-weight:600;color:var(--plum-ink);list-style:none;display:flex;justify-content:space-between;gap:1rem;font-size:1.02rem}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";color:var(--plum);font-weight:700;font-size:1.2rem;line-height:1}
.faq details[open] summary::after{content:"–"}
.faq p{margin-top:10px;color:var(--stone);font-size:.95rem}
.incl{display:grid;grid-template-columns:repeat(2,1fr);gap:0 40px;margin-top:26px}
@media(max-width:760px){.incl{grid-template-columns:1fr}}
.incl div{padding:16px 0;border-bottom:1px solid var(--line)}
.incl b{display:block;color:var(--plum-ink);font-size:.98rem;margin-bottom:4px}
.incl span{font-size:.9rem;color:var(--stone)}
.endcta{background:var(--plum-ink);color:#EFE3EE;text-align:center}
.endcta h2{color:#fff}
.endcta p{color:#C8B3C6;margin:14px auto 26px;max-width:52ch}
.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:32px}
@media(max-width:760px){.gallery{grid-template-columns:repeat(2,1fr)}}
.gallery figure{aspect-ratio:1/1;border-radius:14px;overflow:hidden;background:var(--mist)}
.gallery img{width:100%;height:100%;object-fit:cover}
.note{font-family:var(--mono);font-size:.75rem;color:var(--stone);margin-top:18px}
.svc-nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:34px}
.svc-nav a{padding:.5rem .9rem;border-radius:999px;border:1px solid var(--line);font-size:.88rem;font-weight:500;background:var(--white)}
.svc-nav a:hover{border-color:var(--plum);color:var(--plum)}
.svc-nav a[aria-current]{background:var(--plum);color:#fff;border-color:var(--plum)}

/* ============================================================
   Theme additions — mobile nav, motion, form states, a11y.
   Appended to the approved design; nothing above is altered.
   ============================================================ */

/* --- skip link ------------------------------------------------ */
.skip-link{position:absolute;left:-9999px;top:0;z-index:999;background:var(--plum);color:#fff;padding:.75rem 1.1rem;border-radius:0 0 var(--r) 0;font-weight:600}
.skip-link:focus{left:0}

/* --- contrast fix --------------------------------------------
   White on --green (#49B848) is 2.55:1 — below WCAG AA. The button
   face uses --green-ink (5.09:1); --green stays for accents and the
   "BÖRJA HÄR" banner, where it is not carrying text at small size. */
.btn-green{background:var(--green-ink)}
.btn-green:hover{background:#256B24}

/* --- mobile nav ----------------------------------------------- */
.nav-toggle{display:none;background:none;border:0;padding:.55rem;margin-left:.35rem;cursor:pointer;border-radius:10px;line-height:0}
.nav-toggle:focus-visible{outline:3px solid var(--green);outline-offset:2px}
.nav-toggle-bars{display:block;width:24px;height:16px;position:relative}
.nav-toggle-bars span{position:absolute;left:0;width:100%;height:2px;background:var(--plum-ink);border-radius:2px;transition:transform .28s cubic-bezier(.2,0,0,1),opacity .2s ease,top .28s cubic-bezier(.2,0,0,1)}
.nav-toggle-bars span:nth-child(1){top:0}
.nav-toggle-bars span:nth-child(2){top:7px}
.nav-toggle-bars span:nth-child(3){top:14px}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(1){top:7px;transform:rotate(45deg)}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(3){top:7px;transform:rotate(-45deg)}

.mobilmeny{border-top:1px solid var(--line);background:var(--white);overflow:hidden;max-height:0;opacity:0;transition:max-height .44s cubic-bezier(.2,0,0,1),opacity .24s cubic-bezier(.2,0,0,1)}
.mobilmeny.in{max-height:80vh;opacity:1;overflow-y:auto}
.mobilmeny .wrap{padding-top:1.1rem;padding-bottom:1.4rem;display:flex;flex-direction:column;gap:.15rem}
.mobilmeny>.wrap>a{font-family:var(--display);font-weight:700;font-size:1.3rem;color:var(--plum-ink);padding:.6rem 0;border-bottom:1px solid var(--line)}
.mobilmeny>.wrap>a:hover{color:var(--plum)}
.mobilmeny-tjanster{display:flex;flex-direction:column;gap:.1rem;padding:1rem 0 .4rem}
.mobilmeny-tjanster .eyebrow{margin-bottom:.5rem}
.mobilmeny-tjanster a{color:var(--stone);padding:.42rem 0;font-size:.98rem}
.mobilmeny-tjanster a:hover{color:var(--plum)}
.mobilmeny-foot{display:flex;align-items:center;gap:1rem;flex-wrap:wrap;padding-top:1rem;border-top:1px solid var(--line);margin-top:.5rem}
.mobilmeny-tel{font-family:var(--mono);font-size:.92rem;color:var(--plum-ink)}
body.meny-oppen{overflow:hidden}

@media(max-width:960px){
  .nav-toggle{display:inline-flex;align-items:center;justify-content:center}
  .nav-cta .btn-primary{display:none}
}
@media(min-width:961px){
  .mobilmeny{display:none}
}

/* --- scroll reveals ------------------------------------------- */
/* Hiding is gated on .js-reveal, which the script sets on <html> before it
   hides anything. No script, no hiding — the page is readable regardless. */
.js-reveal .reveal{opacity:0;transform:translateY(26px);transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
.js-reveal .reveal.in{opacity:1;transform:none}
/* Nested reveals would multiply their opacities into a permanent haze. */
.js-reveal .reveal .reveal{opacity:1;transform:none;transition:none}
@media(prefers-reduced-motion:reduce){
  .reveal{opacity:1;transform:none;transition:none}
  html{scroll-behavior:auto}
}

/* --- form ------------------------------------------------------ */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.field-error{display:block;margin-top:.35rem;font-size:.86rem;color:#B3261E;font-weight:500}
[aria-invalid="true"]{border-color:#B3261E !important}
.form-status{margin:.2rem 0 0;font-size:.92rem;font-weight:500}
.form-status-fel{color:#B3261E}
.form-tack{font-family:var(--display);font-weight:700;font-size:1.35rem;color:var(--plum-ink);background:var(--mist);border-radius:var(--r);padding:1.4rem 1.5rem;margin:0}
form button[disabled]{opacity:.65;cursor:progress}

/* --- prose (legal pages, generic content) ---------------------- */
.prose{max-width:72ch}
.prose h2{margin:2.2rem 0 .8rem;font-size:1.5rem}
.prose h3{margin:1.6rem 0 .5rem}
.prose p,.prose li{color:var(--stone);margin-bottom:.9rem}
.prose ul,.prose ol{padding-left:1.2rem;margin-bottom:1.2rem}
.prose li{margin-bottom:.45rem}
.prose a{color:var(--plum);text-decoration:underline;text-underline-offset:2px}
.prose strong{color:var(--ink)}
.prose table{width:100%;border-collapse:collapse;margin:1.2rem 0}
.prose th,.prose td{text-align:left;padding:.7rem 0;border-bottom:1px solid var(--line);vertical-align:top}
.prose th{font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--stone);font-weight:500}

/* --- nav underline + services dropdown --------------------------
   Motion values taken from whatsapp.com: opacity 0.33s, transform 0.67s,
   both on cubic-bezier(.2,0,0,1). The transform running twice as long as
   the fade is the whole trick — the panel is visible early but keeps
   gliding into place, which reads as weight rather than speed. */

/* Underline that grows from the left, on every nav item. */
.nav-links a,.has-drop>a{position:relative;padding-bottom:4px}
.nav-links a::after,.has-drop>a::after{
  content:"";position:absolute;left:0;bottom:0;
  width:100%;height:2px;background:var(--green);border-radius:2px;
  transform:scaleX(0);transform-origin:left center;
  transition:transform .34s cubic-bezier(.2,0,0,1);
}
.nav-links a:hover::after,.nav-links a:focus-visible::after,
.has-drop>a:hover::after{transform:scaleX(1)}
/* Retract towards the right, so it leaves the way a real object would. */
.nav-links a::after{transition-timing-function:cubic-bezier(.2,0,0,1)}
.nav-links a:not(:hover)::after{transform-origin:right center}
/* The trigger keeps its underline for as long as the panel is open. */
.has-drop:hover>a::after,.has-drop:focus-within>a::after{transform:scaleX(1);transform-origin:left center}

.has-drop{position:relative}
.has-drop>a{display:inline-flex;align-items:center;gap:.4rem}
.has-drop .caret{transition:transform .34s cubic-bezier(.2,0,0,1);opacity:.55}
.has-drop:hover .caret,.has-drop:focus-within .caret{transform:rotate(180deg);opacity:1}

.drop{
  position:absolute;top:100%;left:0;margin-top:.75rem;
  min-width:340px;background:var(--white);border:1px solid var(--line);
  border-radius:var(--r);padding:.55rem;
  box-shadow:0 24px 48px -20px rgba(42,15,41,.26),0 2px 8px -2px rgba(42,15,41,.07);
  opacity:0;visibility:hidden;transform:translateY(20px);
  transition:
    opacity .33s cubic-bezier(.2,0,0,1),
    transform .67s cubic-bezier(.2,0,0,1),
    visibility 0s linear .4s;
  z-index:60;isolation:isolate;
}
.drop::before{content:"";position:absolute;top:-.75rem;left:0;right:0;height:.75rem}
.has-drop:hover .drop,.has-drop:focus-within .drop{
  opacity:1;visibility:visible;transform:translateY(0);
  transition:
    opacity .33s cubic-bezier(.2,0,0,1),
    transform .67s cubic-bezier(.2,0,0,1),
    visibility 0s;
}

/* Items rise in sequence behind the panel, so the menu assembles
   rather than simply appearing. */
.drop a{
  display:flex;flex-direction:column;gap:.15rem;
  padding:.7rem .85rem;border-radius:10px;position:relative;z-index:1;
  opacity:0;transform:translateY(10px);
  transition:opacity .3s cubic-bezier(.2,0,0,1),transform .5s cubic-bezier(.2,0,0,1);
}
.has-drop:hover .drop a,.has-drop:focus-within .drop a{opacity:1;transform:none}
.has-drop:hover .drop a:nth-child(2),.has-drop:focus-within .drop a:nth-child(2){transition-delay:.04s}
.has-drop:hover .drop a:nth-child(3),.has-drop:focus-within .drop a:nth-child(3){transition-delay:.08s}
.has-drop:hover .drop a:nth-child(4),.has-drop:focus-within .drop a:nth-child(4){transition-delay:.12s}
.has-drop:hover .drop a:nth-child(5),.has-drop:focus-within .drop a:nth-child(5){transition-delay:.16s}
.has-drop:hover .drop a:nth-child(6),.has-drop:focus-within .drop a:nth-child(6){transition-delay:.20s}
.has-drop:hover .drop a:nth-child(7),.has-drop:focus-within .drop a:nth-child(7){transition-delay:.24s}
.has-drop:hover .drop a:nth-child(8),.has-drop:focus-within .drop a:nth-child(8){transition-delay:.28s}

.drop a:focus-visible{outline:2px solid var(--plum);outline-offset:-2px}
.drop-t{font-weight:600;font-size:.95rem;color:var(--plum-ink);transition:color .2s ease}
.drop a:hover .drop-t{color:var(--plum)}
.drop-p{font-family:var(--mono);font-size:.72rem;letter-spacing:.04em;color:var(--stone)}
.drop-all{
  border-top:1px solid var(--line);margin-top:.35rem;border-radius:0 0 10px 10px;
  font-weight:600;font-size:.88rem;color:var(--plum);position:relative;z-index:1;
}

/* --- magnetic highlight ---------------------------------------
   One element that travels between items instead of each lighting up on
   its own. It arrives with a slight overshoot — stuck, then released. */
.drop-hl{
  position:absolute;left:.55rem;right:.55rem;top:0;height:0;
  background:var(--mist);border-radius:10px;
  opacity:0;pointer-events:none;z-index:0;transform:translateY(0);
  transition:
    transform .42s cubic-bezier(.34,1.4,.5,1),
    height    .42s cubic-bezier(.34,1.4,.5,1),
    opacity   .22s ease;
}
.drop-hl.on{opacity:1}
.drop-hl.instant{transition:opacity .22s ease}

@media(max-width:960px){.drop{display:none}}

/* Mobile menu links get the same underline treatment. */
.mobilmeny>.wrap>a{position:relative}
.mobilmeny>.wrap>a::after{
  content:"";position:absolute;left:0;bottom:-1px;width:100%;height:2px;
  background:var(--green);transform:scaleX(0);transform-origin:left center;
  transition:transform .34s cubic-bezier(.2,0,0,1);
}
.mobilmeny>.wrap>a:hover::after,.mobilmeny>.wrap>a:focus-visible::after{transform:scaleX(1)}

/* --- hover lift ------------------------------------------------- */
/* Every card-like class the design already defines. Nothing new is
   introduced — these are the same surfaces, they just respond now. */
.card,.tier,.step,.group,.pack,.price-card,.svc,.fact,.who-row{
  transition:transform .32s cubic-bezier(.16,1,.3,1),
             box-shadow .32s cubic-bezier(.16,1,.3,1),
             border-color .32s ease;
}
.card:hover,.tier:hover,.step:hover,.group:hover,.pack:hover,
.price-card:hover,.svc:hover,.fact:hover,.who-row:hover{
  transform:translateY(-5px);
  box-shadow:0 20px 40px -18px rgba(42,15,41,.22);
  border-color:#d3c2d3;
}

/* Photos lift and lean in slightly — the image is the product here. */
.photo{transition:transform .4s cubic-bezier(.16,1,.3,1),box-shadow .4s cubic-bezier(.16,1,.3,1)}
.photo:hover{transform:translateY(-6px) scale(1.012);box-shadow:0 26px 50px -22px rgba(42,15,41,.34)}

/* Chips are small; a big lift would look like a bug. */
.chip{transition:transform .25s cubic-bezier(.16,1,.3,1),background .2s ease,border-color .2s ease}
.chip:hover{transform:translateY(-2px)}

.btn{transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s ease,background .2s,color .2s,border-color .2s}
.btn-primary:hover{box-shadow:0 12px 26px -12px rgba(119,20,115,.6)}
.btn-green:hover{box-shadow:0 12px 26px -12px rgba(44,126,43,.55)}
.btn-ghost:hover{transform:translateY(-2px)}

/* Table-style rows inside cards: nudge instead of lift, so the card
   itself stays still while the row responds. */
.card a:hover,.group a:hover,.pack a:hover{transition:color .2s ease}

@media(prefers-reduced-motion:reduce){
  .card,.tier,.step,.group,.pack,.price-card,.svc,.fact,.who-row,
  .photo,.chip,.btn,.drop,.drop a,.has-drop .caret{transition:none}
  .card:hover,.tier:hover,.step:hover,.group:hover,.pack:hover,
  .price-card:hover,.svc:hover,.fact:hover,.who-row:hover,
  .photo:hover,.chip:hover,.btn:hover,.btn-ghost:hover{transform:none}
}


/* --- looping Maps ranking demo ---------------------------------
   The design animated the reorder once on load. Looping it makes the point
   continuously: your listing climbs into the top three. The fade at the end
   of each cycle is what hides the reset — without it the list would snap. */
@media(prefers-reduced-motion:no-preference){
  .pack li.you{animation:fmp-rise 7s cubic-bezier(.2,.8,.2,1) 0.4s infinite both}
  @keyframes fmp-rise{
    0%,6%   {transform:translateY(132px);opacity:0}
    12%     {opacity:1}
    32%,86% {transform:translateY(0);opacity:1}
    96%,100%{transform:translateY(0);opacity:0}
  }
  .pack li:not(.you){animation:fmp-drop 7s cubic-bezier(.2,.8,.2,1) 0.4s infinite both}
  @keyframes fmp-drop{
    0%,6%   {transform:translateY(-66px);opacity:0}
    12%     {opacity:1}
    32%,86% {transform:translateY(0);opacity:1}
    96%,100%{transform:translateY(0);opacity:0}
  }
  .pack .cap em{animation:fmp-blink 7s steps(2) 0.4s infinite}
  @keyframes fmp-blink{
    0%,28%  {opacity:1}
    30%,34% {opacity:.25}
    36%,100%{opacity:1}
  }
  /* The "you" pin on the map pulses in time with the list settling. */
  .pack .pin.you{animation:fmp-pin 7s ease-in-out 0.4s infinite}
  @keyframes fmp-pin{
    0%,26%  {transform:scale(1)}
    32%     {transform:scale(1.35)}
    40%,100%{transform:scale(1)}
  }
}

/* ── You are here ────────────────────────────────────────────────────────
   The dropdown trigger already holds its underline for as long as the panel
   is open. This extends that to the page you are actually on — in plum, not
   the green used for hover, so "where I am" and "where I could go" are not
   the same signal. [aria-current] outranks the hover rules on specificity,
   so the bar stays put when the pointer leaves. */
.nav-links a[aria-current="page"],.has-drop>a[aria-current="page"]{color:var(--plum)}
.nav-links a[aria-current="page"]::after,.has-drop>a[aria-current="page"]::after{
  transform:scaleX(1);transform-origin:left center;background:var(--plum)
}
.drop a[aria-current="page"] .drop-t{color:var(--plum)}
.mobilmeny>.wrap>a[aria-current="page"]{color:var(--plum)}
.mobilmeny>.wrap>a[aria-current="page"]::after{transform:scaleX(1);background:var(--plum)}
.mobilmeny-tjanster a[aria-current="page"]{color:var(--plum);font-weight:600}

/* ── Mobile menu: items rise in sequence ─────────────────────────────────
   The desktop dropdown staggers its rows; the mobile menu opened everything
   at once, and mobile is where nearly all of this traffic is. Same curve and
   step as the dropdown.

   Safe without JS: .mobilmeny carries the [hidden] attribute until the
   toggle script removes it, so these rules cannot hide content on their own
   — the same gate used for the scroll reveals. */
.mobilmeny .wrap>*{
  opacity:0;transform:translateY(12px);
  transition:opacity .34s cubic-bezier(.2,0,0,1),transform .34s cubic-bezier(.2,0,0,1)
}
.mobilmeny.in .wrap>*{opacity:1;transform:none}
.mobilmeny.in .wrap>*:nth-child(1){transition-delay:.05s}
.mobilmeny.in .wrap>*:nth-child(2){transition-delay:.09s}
.mobilmeny.in .wrap>*:nth-child(3){transition-delay:.13s}
.mobilmeny.in .wrap>*:nth-child(4){transition-delay:.17s}
.mobilmeny.in .wrap>*:nth-child(5){transition-delay:.21s}
.mobilmeny.in .wrap>*:nth-child(6){transition-delay:.25s}

@media(prefers-reduced-motion:reduce){
  .mobilmeny .wrap>*{opacity:1;transform:none;transition:none;transition-delay:0s}
  .mobilmeny.in .wrap>*{transition-delay:0s}
  .nav-links a::after,.has-drop>a::after,.mobilmeny>.wrap>a::after,
  .nav-toggle-bars span{transition:none}
}

/* ── Parallax ────────────────────────────────────────────────────────────
   Real depth, not a hint of it: the photograph travels ±6% of its own height
   inside a frame that never moves, against a 1.2 overscale that leaves 10%
   of headroom on each edge so the frame is never exposed.

   Applied to every framed photograph on the site — the hero collage, the
   service-page hero, the work strip, the galleries and the portrait blocks.
   Neighbouring frames run in opposite directions, so a row of images
   separates into layers instead of sliding as one slab.

   Why this cannot hurt layout: every frame below is a fixed aspect-ratio box
   with overflow:hidden. Only the image inside translates, so not one pixel of
   layout moves — which matters, because 1.3.0 went to the trouble of giving
   all 31 images intrinsic dimensions to stop exactly that.

   Why it is safe on phones: this is a scroll-driven CSS animation, so the
   browser runs it on the compositor with no scroll listener and no
   main-thread work. That is the opposite of JS parallax and
   background-attachment:fixed, which are what actually judder on iOS — so
   this deliberately is NOT gated to desktop. Phones are most of this traffic
   and should see it.

   TWO TRAPS, both measured, do not undo either:

   1. `animation-timeline: view()` set directly on the <img> is silently
      inert — a constant -0.0002% at every scroll position, while it parses,
      @supports passes, and getAnimations() reports a running ViewTimeline.
      The timeline has to be NAMED on the frame and referenced from the image.

   2. A scroll container ANYWHERE above the frame silently degenerates its
      timeline. `.hero` and `.band` are overflow:hidden, which makes them
      scroll containers, and the hero collage inside .hero sat frozen at
      49.3996% forever. The tell is the units: a degenerate timeline reports
      a percentage that never changes, while a healthy one reports plain
      progress numbers (-165.6, -76.4) that move with scroll. `overflow:clip`
      clips identically but does NOT create a scroll container, which is why
      the two rules below exist. They are inside @supports so browsers
      without scroll timelines keep the original overflow:hidden.

   Also: @supports (animation-timeline: --name) is false even where named
   timelines work, so the guard below has to test view().

   AMPLITUDE: ±11% against a 1.35 overscale gives ~30% of the frame's height
   in total travel — roughly 75px on a collage tile, 150px on the tall one.
   The first attempt used ±6% at 1.2 and was imperceptible (~43px spread over
   a whole screen of scrolling). The ceiling is the overscale: visible travel
   is translate × scale, and it must stay under (scale − 1) ÷ 2 or the frame
   edge is exposed. At 1.35 that ceiling is 17.5% and this sits at 14.85%. */

/* The collage tiles have no clip of their own — give them one, or a scaled
   image spills past the rounded corner. Outside @supports on purpose: the JS
   fallback below needs it too. Harmless without parallax, where the image
   fits its frame exactly. */
.collage .lbl { overflow: hidden; border-radius: 16px }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes fmp-drift { from { translate: 0 -11% } to { translate: 0 11% } }

    /* Clip without becoming a scroll container — see trap 2 above. */
    .hero, .band { overflow: clip }

    .collage .lbl,
    .page-hero .art,
    .strip figure,
    .gallery figure,
    .photo { view-timeline-name: --fmpframe }

    .collage .lbl img,
    .page-hero .art img,
    .strip figure img,
    .gallery figure img,
    .photo img {
      scale: 1.35;
      animation: fmp-drift linear both;
      /* must follow the shorthand, which resets animation-timeline */
      animation-timeline: --fmpframe;
      animation-range: cover 0% cover 100%;
    }

    .collage .lbl:nth-child(even) img,
    .strip figure:nth-child(even) img,
    .gallery figure:nth-child(even) img { animation-direction: reverse }

    /* Base scale is now 1.35, so the hover zoom moves up to match. */
    .strip figure:hover img { scale: 1.43 }

    /* ── Everything else ──────────────────────────────────────────────────
       Photographs move inside their frames; blocks move themselves. These
       elements have no frame to hide in, so the amounts are small and in
       pixels rather than percentages — the point is that a section stops
       arriving as one flat slab and separates into layers.

       Cards and panels get 16px, type gets 8px. Above roughly 20px, text
       stops reading as depth and starts reading as a page that has not
       finished loading.

       Each element carries its own timeline: `view-timeline-name` and
       `animation-timeline` on the same element resolves against itself,
       which is what avoids the ancestor-scroll-container trap above.

       These use `translate`, while the scroll reveals use `transform` and
       the card hovers use `transform` too — independent properties, so all
       three compose instead of overwriting each other. */
    @keyframes fmp-lift  { from { translate: 0 -16px } to { translate: 0 16px } }
    @keyframes fmp-lift-r{ from { translate: 0  16px } to { translate: 0 -16px } }
    @keyframes fmp-type  { from { translate: 0  -8px } to { translate: 0  8px } }

    .group, .card, .tier, .step, .pack, .price-card, .svc, .fact, .who-row,
    .waas-arc,
    main section h2, main section .eyebrow, main section p.lead {
      view-timeline-name: --fmpblock;
      animation-timeline: --fmpblock;
      animation-range: cover 0% cover 100%;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-duration: auto;
    }
    .group, .card, .tier, .step, .pack, .price-card, .svc, .fact, .who-row {
      animation-name: fmp-lift;
    }
    /* Neighbours in a row drift against each other, so the row splits into
       layers instead of sliding as one piece. */
    .group:nth-child(even), .card:nth-child(even), .tier:nth-child(even),
    .step:nth-child(even), .svc:nth-child(even), .fact:nth-child(even),
    .who-row:nth-child(even) {
      animation-name: fmp-lift-r;
    }
    main section h2, main section .eyebrow, main section p.lead {
      animation-name: fmp-type;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .strip img { transition: none }
  .strip figure:hover img { scale: 1 }
}

/* Overscale for the JavaScript parallax fallback (main.js sets this class only
   when scroll-driven animations are unsupported — iOS Safari below 26, Firefox
   below 157). The translate is written by the script; only the headroom is
   declared here. */
@media (prefers-reduced-motion: no-preference) {
  .fmp-js-parallax .collage .lbl img,
  .fmp-js-parallax .page-hero .art img,
  .fmp-js-parallax .strip figure img,
  .fmp-js-parallax .gallery figure img,
  .fmp-js-parallax .photo img { scale: 1.35 }
  .fmp-js-parallax .strip figure:hover img { scale: 1.43 }
}

/* ── Package saving ──────────────────────────────────────────────────────
   The struck-through à la carte total under a bundle price, and the small
   per-item prices inside it. The saving only reads as a saving if the
   visitor can see what the parts cost separately. */
.pkg-save{
  font-family:var(--mono);font-size:.72rem;letter-spacing:.04em;
  color:var(--stone);margin:.35rem 0 0
}
.pkg-save s{opacity:.75}
/* .tier.hot is white with a plum border, NOT a dark tier — do not add
   white-text overrides here, they render invisible. */
.pkg-part{
  font-family:var(--mono);font-size:.7rem;color:var(--stone);
  opacity:.85;white-space:nowrap
}
.pkg-part::before{content:"· "}

/* Add-ons named on the price card itself. An upsell nobody can see is an
   upsell nobody buys — the FAQ is where people go when confused, not when
   they are deciding what to order. */
.addons{
  font-size:.82rem;line-height:1.5;color:var(--stone);
  margin:.9rem 0 0;padding-top:.8rem;border-top:1px dashed var(--line)
}
.addons b{color:var(--plum-ink);font-weight:600}

/* ── The instalment arc ──────────────────────────────────────────────────
   Hemsida som tjänst is a financing product, not a subscription, and the
   only way to say that honestly is to print the arithmetic: monthly price,
   term, total. Hairline rows with oversized numerals, because publishing
   what a thing actually costs is the strongest trust move this site has.
   The last row is plum -- it is the payoff the whole offer turns on, so it
   should not sit at the same weight as the other two. */
.waas-arc{max-width:860px;margin-top:40px}
.waas-arc .arc{list-style:none;display:grid;margin-top:16px}
.waas-arc .arc li{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  align-items:baseline;gap:0 20px;padding:16px 0;
  border-bottom:1px solid var(--line)
}
.waas-arc .arc li:first-child{border-top:1px solid var(--line)}
.waas-arc .arc b{
  font-family:var(--display);font-weight:800;line-height:1;
  font-size:clamp(1.7rem,3.2vw,2.6rem);letter-spacing:-.02em;
  color:var(--plum-ink);min-width:6.5ch;white-space:nowrap
}
.waas-arc .arc li:last-child b{color:var(--plum)}
.waas-arc .arc span{font-size:.92rem;color:var(--stone)}
@media(max-width:520px){
  .waas-arc .arc li{grid-template-columns:1fr;gap:4px}
  .waas-arc .arc b{min-width:0}
}

/* ── Form motion ─────────────────────────────────────────────────────────
   Motion here is state, not decoration: a field that appears, a button that
   is working, an answer that was rejected, a form that is done. Nothing
   animates that does not tell the visitor something. */

/* THE FIX: the browser's own [hidden] rule is a UA style, and ANY author rule
   beats it — `label{display:grid}` above was rendering hidden fields in full
   view. Checking element.hidden in the console says true while the field is
   plainly on screen, which is exactly how this got missed. */
[hidden]{display:none !important}

/* Conditional field: grows out of nothing rather than popping in, so it reads
   as an answer to what you just picked. 0fr→1fr is the only way to transition
   to an unknown height without measuring it in JS. */
.cond{
  display:grid;grid-template-rows:0fr;opacity:0;
  transition:grid-template-rows .34s cubic-bezier(.2,0,0,1),opacity .22s cubic-bezier(.2,0,0,1);
}
.cond > label{overflow:hidden;min-height:0}
.cond.in{grid-template-rows:1fr;opacity:1}

/* Focus: the border colour already moved instantly — give it the site's easing
   so the field feels picked up rather than switched on. */
form input,form select{
  transition:border-color .2s cubic-bezier(.2,0,0,1),box-shadow .2s cubic-bezier(.2,0,0,1)
}

/* A rejected field says so twice: colour, and a short shake. The shake is
   3 movements over 0.3s — long enough to notice, too short to annoy. */
form [aria-invalid="true"]{border-color:#B3261E;box-shadow:0 0 0 3px rgba(179,38,30,.12)}
@keyframes fmp-shake{
  0%,100%{translate:0}
  25%{translate:-4px}
  60%{translate:3px}
}
form [aria-invalid="true"]{animation:fmp-shake .3s cubic-bezier(.2,0,0,1)}
[data-error]{
  font-size:.78rem;color:#B3261E;font-weight:500;
  animation:fmp-err-in .24s cubic-bezier(.2,0,0,1) both
}
@keyframes fmp-err-in{from{opacity:0;translate:0 -4px}to{opacity:1;translate:0}}

/* Sending: the button reports work with a moving dot, not a frozen label. */
form button[type="submit"]{position:relative;transition:opacity .2s}
form button[type="submit"][disabled]{opacity:.85;cursor:progress}
form button[type="submit"][disabled]::after{
  content:"";width:.62em;height:.62em;margin-left:.1em;border-radius:50%;
  background:currentColor;display:inline-block;
  animation:fmp-pulse .9s cubic-bezier(.2,0,0,1) infinite
}
@keyframes fmp-pulse{0%,100%{opacity:.25;scale:.7}50%{opacity:1;scale:1}}

/* Done: the confirmation rises into the space the form occupied. */
.form-tack{animation:fmp-tack-in .5s cubic-bezier(.2,0,0,1) both}
@keyframes fmp-tack-in{from{opacity:0;translate:0 12px;scale:.98}to{opacity:1;translate:0;scale:1}}

@media (prefers-reduced-motion: reduce){
  .cond{transition:none}
  form [aria-invalid="true"],[data-error],.form-tack,
  form button[type="submit"][disabled]::after{animation:none}
}
