  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  /* Namntypsnitt från appens egen server, oförändrade från leverantörerna.
     Båda deklareras som 400, den vikt appen ber om, så att webbläsaren
     inte ritar en egen fet stil som får konturerna att växa ihop. */
  @font-face {
    font-family: 'JUST Sans Outline';
    src: url('typsnitt/just-sans-outline-exbold.woff2') format('woff2');
    font-weight: 400; font-style: normal; font-display: swap;
  }
  @font-face {
    font-family: 'Jaqin Fontin Heavy Outline';
    src: url('typsnitt/jaqin-fontin-heavy-outline.ttf') format('truetype');
    font-weight: 400; font-style: normal; font-display: swap;
  }

  :root {
    --blue:   #1a69d3;
    --dimma:  rgba(17,24,39,.55);   /* toningen bakom en öppen ruta */
    /* Krysset som stänger och tar bort, ett och samma överallt: maskeras i
       textfärgen där det står (se .ikon-kryss) */
    --kryss:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.4' stroke-linecap='round'%3E%3Cpath d='M5 5l14 14M19 5 5 19'/%3E%3C/svg%3E");
    --blue-d: #1455b0;
    --warm:   #F5F4F0;
    --white:  #ffffff;
    --text:   #111827;
    --muted:  #6B7280;
    --border: #E5E7EB;
    --rod:    #DC2626;
    /* Sandbandet bakom boken högst upp */
    --sand:   #F0EDE6;
    /* Vald ruta: ljusblå yta mot blå ram */
    --blaljus: #F0F5FD;
    /* Nedtonad text på blockerade knappar */
    --grabla: #9aa2ae;
    --nav-h:  76px;
  }

  html, body {
    height: 100%;
    /* dvh = den yta som faktiskt syns. På iOS betyder 100vh skärmen som
       om adressfältet och verktygsfältet inte fanns — då hamnar sidfoten
       med pilarna nedanför skärmkanten och kunden kommer inte vidare. */
    height: 100dvh;
    overflow: hidden;
    /* iOS zoomar in vid dubbeltryck och struntar i user-scalable=no i
       viewport-taggen sedan iOS 10. Den som bläddrar snabbt mellan sidorna
       råkar därför zooma in appen, och den blir kvar inzoomad. Det här
       stänger av just dubbeltrycket; rullning och nyp-zoom är kvar, och
       beskärningen behåller sitt eget grepp om fingrarna eftersom
       webbläsaren tar det snävaste värdet i kedjan.

       Regeln på html och body räcker inte i Safari: den tittar i första
       hand på elementet fingret träffar, så allt som går att trycka på
       måste säga samma sak. Se listan längre ned. */
    touch-action: manipulation;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    background: var(--warm); color: var(--text);
  }

  #app {
    display: flex; flex-direction: column;
    height: 100vh;            /* reserv för äldre webbläsare */
    height: 100dvh;
    width: 100%;
    max-width: 480px; margin: 0 auto;
  }

  /* ── PREVIEW ──
     Ett fast sandband överst med boken centrerad. Höjden är designens
     172 px, men ger vika på riktigt låga skärmar så att formuläret under
     aldrig kläms ihop till en remsa. */
  #preview {
    /* Krymper när formuläret under behöver plats – i handoffen är
       bandet 172 px på första steget och 112 px när fälten är många. */
    flex: 0 1 auto; min-height: 0;
    height: 172px; max-height: min(172px, 28dvh);
    display: flex; align-items: center; justify-content: center;
    padding: 12px 16px; overflow: hidden;
    background: var(--sand);
  }
  /* Omslags- och namnsteget: här är boken hela poängen med steget, så
     bandet får ta mer plats än på de steg där formuläret är huvudsaken. */
  #preview.stor {
    height: 373px; max-height: min(373px, 58dvh);
    /* Mockupbilden går kant i kant uppåt och nedåt: _fitBook skalar den
       efter bandets hela höjd, utan luft. */
    padding-top: 0; padding-bottom: 0;
  }
  /* Beskärningen är det enda steg där kunden gör ett hantverk, och det
     enda där bilden är viktigare än formuläret. Därför vänds bandet och
     formuläret här: bilden tar allt som blir över och kontrollerna bara
     sin egen höjd. Från 48 % av skärmen till drygt 70 %.

     Mörk botten som i en bildredigerare – fotot ska läsas som ett foto
     och inte flyta ihop med den vita sidan. */
  #preview.beskar {
    flex: 1 1 auto;
    height: auto; max-height: none; min-height: 0;
    padding: 0;                 /* bilden går kant i kant */
    position: relative;         /* räknaren ligger ovanpå */
    background: #23262b;
  }
  /* Kontrollerna tar bara sin egen höjd, så resten går till bilden. */
  #content:has(.krop-panel) { flex: 0 0 auto; min-height: 0; overflow: visible; }
  #content:has(.krop-panel) .ci { padding: 10px 14px 12px; }
  /* Namnsteget visar inte boken utan bara namnrutan, inzoomad så att den
     går kant i kant. Höjden räknas ut av _zoomaNamnruta efter rutans mått;
     den här gäller tills den hunnit räkna. */
  #preview.namnzoom { height: 120px; max-height: 30dvh; }
  /* Låg i bookEl:s style-attribut förut. Här kan _zoomaNamnruta släcka den
     med en inline-stil och den vanliga vyn tända den igen genom att ta bort
     sin – utan att skuggans värden står på två ställen. */
  .book-inner { filter: drop-shadow(0 10px 28px rgba(0, 0, 0, .22)); }
  /* Stegen som inte visar någon bok tömmer #preview. Utan detta blir
     paddingen kvar som en 24 px sandremsa högst upp. */
  #preview:empty { height: 0; padding: 0; }

  /* ── CONTENT ── */
  #content {
    /* Var 42vh, alltså en andel av en höjd som iOS överdriver. Nu växer
       rutan i stället med det utrymme som blir över, med en undre gräns
       så formuläret aldrig kläms ihop till en remsa. */
    flex: 1 1 auto;
    min-height: 210px;
    background: var(--white);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  #content::-webkit-scrollbar { display: none; }
  .ci { padding: 18px 16px; }
  /* Bildsidorna centrerar sitt innehåll och behöver därför hela höjden.
     min-height:100% räcker inte: #content sätts till height:auto av
     _tipsSkal, och då har procenten inget att räkna mot. En flexkedja hela
     vägen ner ger blocket en verklig höjd att centrera i. */
  #content:has(.tips-mitt) { display:flex; flex-direction:column; }
  #content:has(.tips-mitt) .ci {
    flex:1; display:flex; flex-direction:column; min-height:0;
  }

  /* ── LIGGANDE LÄGE ─────────────────────────────────────────────────
     En webbsida kan inte låsa telefonens riktning: screen.orientation.lock
     finns inte i Safari på iOS, så flödet vänder sig när telefonen vänds
     hur vi än gör. Det vi kan göra är att inte visa det på tvären utan be
     om att telefonen vänds tillbaka. Ingenting går förlorat – appen ligger
     kvar bakom rutan med kundens bilder och val, och kommer tillbaka som
     den var när telefonen vänds.

     Reglerna för att lägga bok och formulär bredvid varandra ligger kvar
     nedan. De används inte medan rutan visas, men gör att steget fungerar
     direkt om vi ändrar oss.
  ──────────────────────────────────────────────────────────────────── */
  #vand-tillbaka { display: none; }

  @media (orientation: landscape) and (max-height: 560px) {
    #app {
      max-width: none;
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      grid-template-rows: auto minmax(0, 1fr) auto;
      grid-template-areas:
        "rad  rad"
        "bok  form"
        "nav  nav";
    }
    /* Liggande: bandet blir en spalt och får ta den höjd som finns */
    #preview { grid-area: bok; padding: 12px 14px; min-height: 0;
               height: auto; max-height: none; }
    /* Namnsteget sätter en höjd i px för att klippa bandet runt namnrutan.
       I en spalt blir det i stället en kort remsa högst upp och en tom
       sandyta under, så här får spalten sin höjd tillbaka och rutan
       hamnar mitt i den. Inline-stilen kräver !important. */
    #preview.namnzoom { height: auto !important; max-height: none !important; }
    #content { grid-area: form; min-height: 0; }
    #nav     { grid-area: nav; }
    #bok-rad { grid-area: rad; }
    .ci      { padding: 14px 16px 12px; }
  }

  /* Rutan ligger efter reglerna ovan med flit: de sätter #app till grid,
     och den som står sist vinner när de väger lika tungt.

     pointer: coarse begränsar den till fingrar. Ett lågt datorfönster är
     också brett och lågt, och den som drar ner sitt fönster ska inte bli
     ombedd att vända på skärmen. */
  @media (orientation: landscape) and (max-height: 560px) and (pointer: coarse) {
    #app { display: none; }
    #vand-tillbaka {
      display: flex; flex-direction: column;
      align-items: center; justify-content: center; gap: 6px;
      position: fixed; inset: 0; padding: 24px;
      background: var(--warm); text-align: center;
    }
    .vt-ikon   { font-size: 34px; }
    .vt-rubrik { font-size: 19px; font-weight: 800; letter-spacing: -.01em; }
    .vt-text   { font-size: 14px; color: var(--muted); }
  }

  /* Safari avgör dubbeltryck-zoom utifrån elementet under fingret och
     struntar i vad sidan runtomkring säger, så värdet måste sitta på varje
     element – inte bara på html och body, och inte bara på knapparna.

     Det räckte nämligen inte att sätta det på knappar: en inaktiverad
     knapp hoppar Safari över och tittar på föräldern i stället, så pilarna
     på första och sista sidan zoomade fortfarande.

     Stjärnan är den svagaste väljaren som finns, så beskärningens egen
     .cropper-container { touch-action: none } vinner över den och behåller
     sitt grepp om fingrarna. */
  * { touch-action: manipulation; }

  /* ── BOTTOM NAV ── */
  #nav {
    flex-shrink: 0;
    height: var(--nav-h);
    /* Plats för hemknappsstrecket på telefoner utan hemknapp */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    height: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
    background: var(--white); border-top: 1px solid var(--border);
    display: flex; align-items: center; gap: 10px;
    padding-left: 14px; padding-right: 14px; position: relative;
    /* Plats åt framstegsraden överst. Utan den satt strecken 2 px från
       knapparnas överkant och läste ihop med dem. */
    padding-top: 16px;
  }
  /* Framstegsraden ur 2b: ett streck per steg i stället för en fylld
     linje, och innanför navets sidmarginal i stället för kant i kant. */
  #nav-prog {
    position: absolute; top: 6px; left: 14px; right: 14px;
    display: flex; gap: 3px;
  }
  #nav-prog span {
    flex: 1; height: 5px; border-radius: 999px;
    background: var(--border);
    transition: background .3s ease;
  }
  #nav-prog span.gjord { background: var(--blue); }
  /* Knapparna ur 1b: framåt säger vart man är på väg i stället för att bara
     peka. Bakåt är smal med tunn ram, framåt tar resten av bredden.
     Pilarna är tillbaka bredvid texten och visar åt vilket håll knappen
     går. De ligger i stilmallen, inte i texten: koden byter knapptext på
     många ställen, och en pil i texten hade fått följa med överallt.
     Pilen är en ritad bild som maskeras i knappens textfärg, så den blir
     grå när knappen är avstängd och blå när bakåt hovras. Tecknet → var
     för tunt och litet i systemtypsnittet. Skärmläsare hoppar över den –
     knapptexten säger redan vart knappen leder. */
  .nav-knapp {
    height: 48px; padding: 0 16px; border-radius: 12px;
    background: var(--white); border: 1px solid #d7dbe2; cursor: pointer;
    font-size: 15px; font-weight: 600; font-family: inherit; color: var(--text);
    flex-shrink: 0;
    transition: color .15s, background .15s, border-color .15s;
  }
  .nav-knapp:hover { color: var(--blue); background: #f5f8ff; border-color: var(--blue); }
  .nav-knapp:disabled {
    color: var(--grabla); border-color: transparent;
    background: none; pointer-events: none;
  }
  #btn-next {
    flex: 1; min-width: 0; height: 52px; padding: 0 14px;
    border: none; border-radius: 12px; cursor: pointer;
    background: var(--blue); color: #fff;
    font-size: 17px; font-weight: 700; font-family: inherit;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transition: background .15s;
  }
  #btn-next:hover { background: var(--blue-d); }
  #btn-next:disabled {
    background: var(--border); color: var(--grabla); pointer-events: none;
  }
  #btn-back::before,
  #btn-next::after {
    content: "";
    display: inline-block; width: 1.2em; height: 1.2em;
    vertical-align: -.26em;
    background-color: currentColor;
    -webkit-mask: var(--pil) center / contain no-repeat;
            mask: var(--pil) center / contain no-repeat;
  }
  #btn-back::before {
    --pil: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 12H5M11 5.5 4.5 12l6.5 6.5'/%3E%3C/svg%3E");
    margin-right: .35em;
  }
  #btn-next::after {
    --pil: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h15M13 5.5l6.5 6.5-6.5 6.5'/%3E%3C/svg%3E");
    margin-left: .4em;
  }

  /* ── Raden överst i en ny bok ──
     Bok två och senare: vilken bok kunden gör, och en väg ut till
     beställningen om det blev för dyrt. Avbryt är 44 px hög att träffa. */
  #bok-rad:not([hidden]) {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    flex-shrink: 0; min-height: 44px; padding: 0 6px 0 16px;
    background: var(--white); border-bottom: 1px solid var(--border);
  }
  .bok-rad-titel { font-size: 14px; font-weight: 700; color: var(--text); }
  .bok-rad-avbryt {
    display: inline-flex; align-items: center; gap: 7px;
    min-height: 44px; padding: 0 10px; border: none; border-radius: 10px;
    background: none; cursor: pointer;
    font-family: inherit; font-size: 14px; font-weight: 600; color: #000;
  }
  .bok-rad-avbryt::before {
    content: ""; width: 12px; height: 12px; background-color: currentColor;
    -webkit-mask: var(--kryss) center / contain no-repeat;
            mask: var(--kryss) center / contain no-repeat;
  }
  .ikon-kryss {
    display: inline-block; width: 12px; height: 12px; background-color: currentColor;
    -webkit-mask: var(--kryss) center / contain no-repeat;
            mask: var(--kryss) center / contain no-repeat;
  }
  .bok-rad-avbryt:hover { background: #f3f4f6; }

  /* ── COVER GRID ── */
  /* Alla fem omslagen på en rad. Mindre än förut, men rutnätet blir en
     enda rad i stället för två med tre tomma platser — och höjden som
     blir över går till boken överst, som är den kunden ska titta på.
     Läggs ett sjätte omslag till hamnar det på rad två. */
  /* Omslagen ligger på en rad som går att dra i sidled. Då sätter inte
     skärmbredden storleken längre, utan vi väljer den: drygt tre rutor
     syns, och den avhuggna visar att raden fortsätter.

     Remsan går ut i .ci:s sidmarginal och lägger tillbaka den som egen
     padding, så den sista rutan kan dras hela vägen ut till kanten.
     Vänsterkanten får åtta pixlar extra: rutorna är stora nog att den
     första annars ser inklämd ut intill rubriken. */
  .cover-grid {
    display: flex; gap: 8px;
    margin-inline: -16px;
    padding-left: 24px; padding-right: 16px;
    overflow-x: auto; overflow-y: hidden;
    /* Snappningen räknar från skrollportens kant, inte från paddingen. Utan
       scroll-padding klistrar sig första rutan mot skärmkanten så fort
       remsan rörts, och vänsterluften nedan är borta. */
    scroll-snap-type: x proximity;
    scroll-padding-left: 24px; scroll-padding-right: 16px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .cover-grid::-webkit-scrollbar { display: none; }
  .cover-opt {
    position: relative; cursor: pointer;
    /* Raka hörn: rundningen åt av teckningarnas egna hörn, och omslagen
       som går ut i kanten tappade en bit av motivet. */
    overflow: hidden;
    /* Kraftigare än formulärets --border, som är nästan vit. Omslagen är
       vita teckningar mot vit bakgrund, så en ljus ram syns inte alls och
       miniatyrerna flyter ihop med sidan. Designens grå --grabla räcker;
       mörkare eller tjockare börjar tävla med teckningarnas egna linjer. */
    border: 1px solid var(--grabla);
    transition: border-color .2s;
    /* Samma form som bildfilerna, 1024×1536. Med 3/4 fyllde object-fit
       bredden och skar bort en bit upptill och nedtill – kunden såg inte
       hela omslaget hon valde. */
    aspect-ratio: 1024 / 1536;
    flex: 0 0 calc((100% - 3 * 8px) / 3.33);
    scroll-snap-align: start;
  }
  /* fill, inte cover: raketomslaget är en aning bredare än 2:3, och cover
     klippte bort kanten på månarna. En procents sträckning syns inte. */
  .cover-opt img { width:100%; height:100%; object-fit:fill; display:block; }
  .cover-opt.sel { border: 2px solid var(--blue); }
  /* Bocken sitter uppe till höger så den inte skymmer namnrutan nedtill */
  .cover-chk {
    position:absolute; top:5px; right:5px;
    width:20px; height:20px; border-radius:999px;
    background:var(--blue); color:#fff;
    font-size:12px; display:none; align-items:center; justify-content:center;
  }
  .cover-opt.sel .cover-chk { display:flex; }

  /* ── FORM ── */
  .sec-title {
    font-size:21px; font-weight:800; line-height:1.25;
    letter-spacing:-0.015em; margin-bottom:6px;
  }
  .sec-sub   { font-size:13px; color:var(--muted); margin-bottom:16px; line-height:1.5; }
  .rabatt-not{ font-size:13px; color:var(--muted); margin:2px 0 12px; line-height:1.5; }
  /* Rubrik utan underrubrik: samma luft ner till innehållet som på sida 4,
     i stället för de 6 px som var tänkta ovanför en underrubrik */
  .sec-title.utan-under { margin-bottom:14px; }
  /* Rubrik utan underrubrik under sig får ärva underrubrikens luft, annars
     klistrar sig innehållet upp i rubriken. */
  .sec-title.ensam { margin-bottom:16px; }
  .f-label   { font-size:12px; font-weight:600; color:var(--muted);
               text-transform:uppercase; letter-spacing:.06em; margin-bottom:6px; }
  .txt-inp {
    width:100%; height:54px; padding:0 14px;
    /* 2 px som kopiornas fält. Den tunna ramen mot den ljusblå bakgrunden
       gjorde att fältet knappt lästes som ett fält. */
    border:2px solid #c3d4ee; border-radius:12px;
    font-size:17px; font-weight:600; color:var(--text);
    outline:none; transition:border-color .2s; background:var(--blaljus);
  }
  .txt-inp:focus { border-color:var(--blue); background:#fff; }
  .inp-hint { font-size:12px; color:var(--muted); margin-top:6px; }
  /* Tomt namn stoppar inte kunden, men första trycket på framåt pekar hit */
  .inp-hint-varning { color:var(--rod); font-weight:600; }
  /* Även vid fokus: varningen sätts samtidigt som fältet fokuseras, och
     .txt-inp:focus skulle annars måla ramen blå igen. */
  .txt-inp-varning,
  .txt-inp-varning:focus { border-color:var(--rod); background:#FEF3F2; }

  /* ── BILDSIDORNA ──
     Tre sidor med lite innehåll var. Blocket ligger mitt i ytan i stället för
     högst upp med en tom halva under. Auto-marginaler i stället för
     justify-content, så ingenting klipps när en rad fälls ut och innehållet
     blir högre än skärmen. */
  .tips-mitt {
    display:flex; flex-direction:column;
    flex:1;
  }
  .tips-mitt > :first-child { margin-top:auto; }
  .tips-mitt > :last-child  { margin-bottom:auto; }
  .tips-ikon {
    width:52px; height:52px; border-radius:999px; margin:0 auto 14px;
    color:#fff; font-size:24px; font-weight:700;
    display:flex; align-items:center; justify-content:center;
  }
  .tips-rubrik { text-align:center; }

  /* Introsidan har ingen lista under rubriken, så den får ta ut svängarna:
     stor cirkel med ett mjukt sken under, och en rubrik som är hela
     sidans budskap. Gäller bara .tips-stor — sidorna med råd har kvar
     den mindre skalan, annars ryms inte råden. */
  .tips-mitt.tips-stor .tips-ikon {
    width:96px; height:96px; margin-bottom:26px;
    box-shadow:0 12px 30px rgba(26,105,211,.30);
  }
  .tips-mitt.tips-stor .tips-ikon svg { width:44px; height:44px; display:block; }
  .tips-mitt.tips-stor .sec-title {
    font-size:31px; line-height:1.12; letter-spacing:-0.02em;
  }
  /* Inte margin-genvägen: den nollar margin-bottom:auto från
     .tips-mitt > :last-child, och då faller hela blocket till botten i
     stället för att stå i mitten. */
  .tips-mitt.tips-stor .sec-sub {
    font-size:18px; line-height:1.42; max-width:310px;
    margin-top:16px; margin-left:auto; margin-right:auto;
  }

  /* ── TYPSNITT ──
     Två spalter och två rader. Rutorna hade sina stilar inline och
     liveNameFont skrev om dem vid varje klick, så markeringen fanns på
     två ställen som kunde glida isär. Nu är den en klass.
     Provet är stort: konturtypsnitten som JUST Sans blev nästan osynliga
     i 18 px, och med fyra typsnitt i stället för åtta finns platsen.
     Typsnittens namn står inte i rutorna: kunden väljer på provet, och
     namnen är bara till för ordern (_Typsnitt) och skärmläsare. */
  .font-rutnat {
    display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:4px;
  }
  .font-opt {
    height:88px; cursor:pointer;
    border-radius:12px; border:1px solid var(--border); background:#fff;
    display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:1px;
    transition:border-color .15s, background .15s;
  }
  .font-opt.sel  { border:2px solid var(--blue); background:var(--blaljus); }
  .font-opt .prov { font-size:34px; color:var(--text); line-height:1.1; }

  /* ── EXEMPELBILDER ──
     Ett par per rad: fotot till vänster, målarbilden till höger. Paret
     ligger i samma fil, så etiketterna sätts en gång ovanför i stället för
     på varje bild. */
  .exempel-etiketter {
    display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:10px;
    font-size:11px; font-weight:700; letter-spacing:.06em;
    text-transform:uppercase; color:var(--grabla);
  }
  .exempel-etiketter span { text-align:center; }
  .exempel-galleri { display:flex; flex-direction:column; gap:8px; margin-top:5px; }
  /* Alla tio paren är 640x480. Med förhållandet satt håller rutan sin
     höjd även innan filen kommit fram — utan det klappade kortet ihop
     till noll och hela sidan hoppade vid varje bläddring. */
  .exempel-galleri img {
    width:100%; display:block; aspect-ratio:4/3; border-radius:8px;
    border:1px solid #c9cdd4; background:#fff;
  }
  /* display:block ovanför slår webbläsarens egen regel för hidden */
  .exempel-galleri img[hidden] { display:none; }

  .exempel-bladd {
    display:flex; align-items:center; justify-content:center; gap:14px;
    margin-top:9px;
  }
  /* Fylld blå med vit pil. Ljusblå botten som på ordningssidan syntes
     knappt mot kortets gröna, och en vit cirkel med tunn grå ram ännu
     mindre — de här är sidans enda reglage och ska gå att hitta direkt.
     44 px är också minsta vettiga träffyta för en tumme. */
  .exempel-pil {
    width:44px; height:44px; flex-shrink:0; padding:0;
    border:none; border-radius:50%; background:var(--blue);
    font-family:inherit; font-size:21px; font-weight:700; line-height:1;
    color:#fff; box-shadow:0 2px 6px rgba(26,105,211,.32);
    display:flex; align-items:center; justify-content:center;
    cursor:pointer; transition:background .15s, transform .1s;
  }
  .exempel-pil:hover:not(:disabled) { background:var(--blue-d); }
  .exempel-pil:active:not(:disabled) { transform:scale(.93); }
  /* Avstängd ska läsas som slut på raden, inte som en knapp att leta efter */
  .exempel-pil:disabled {
    background:#E3E5E9; color:#fff; box-shadow:none; cursor:default;
  }
  .exempel-raknare {
    font-size:13px; font-weight:700; color:var(--text);
    min-width:104px; text-align:center;
  }

  /* ── SPIRAL SWATCHES ── */
  .swatches { display:flex; gap:10px; flex-wrap:wrap; margin-top:8px; }
  .swatch {
    width:44px; height:44px; border-radius:50%; cursor:pointer;
    position:relative; border:3px solid transparent;
    transition:border-color .2s; box-shadow:0 1px 4px rgba(0,0,0,.15);
  }
  .swatch.sel { border-color:var(--blue); }
  .swatch-chk {
    position:absolute; inset:0;
    display:none; align-items:center; justify-content:center; font-size:14px;
  }
  .swatch.sel .swatch-chk { display:flex; }

  /* ── PHOTOS ── */
  #dz {
    height:100px; border:2px dashed #c3d4ee; border-radius:14px;
    display:flex; flex-direction:column; align-items:center;
    justify-content:center; gap:3px; cursor:pointer;
    background:var(--blaljus); transition:border-color .2s,background .2s;
    margin-top:12px;
  }
  #dz:hover { border-color:var(--blue); }
  .dz-title { font-size:16px; font-weight:700; color:var(--blue); }
  .dz-sub   { font-size:12px; color:var(--muted); }

  /* Hur långt kunden kommit med bilderna */
  .ph-rad {
    margin-top:12px; display:flex; align-items:center;
    justify-content:space-between; font-size:13px; font-weight:700;
  }
  .ph-rad .status { font-size:12px; font-weight:400; color:var(--muted); }
  .ph-stapel {
    margin-top:6px; height:6px; border-radius:999px;
    background:var(--border); overflow:hidden;
  }
  .ph-stapel > div {
    height:6px; border-radius:999px; background:var(--blue);
    transition:width .3s;
  }
  #file-inp { display:none; }
  /* Bilder från tidigare böcker: två rader med fem bilder i bredd, lika
     stora som miniatyrerna under. Förut var det en enda rad med 62 px
     bilder som knappt gick att se. Är det fler än tio bilder blir raderna
     längre och går att bläddra åt sidan – rad 1 tar första halvan, rad 2
     resten, så ordningen läses som vanligt. Då syns en bit av nästa bild i
     kanten: mobilen visar ingen rullningslist, och med exakt fem i bredd
     märktes det inte att det fanns fler. Antalet kolumner och hur många
     som syns kommer från bankHtml. */
  #bank-lista {
    display:grid; gap:7px;
    grid-template-columns:repeat(var(--bank-kol, 5), calc((100% - 28px) / var(--bank-synliga, 5)));
    overflow-x:auto; -webkit-overflow-scrolling:touch;
  }
  /* Rullningslisten, när det finns fler än tio bilder: 8 px luft mot
     bilderna, 8 px tjock och en ljusgrå bana. Med 3 px luft och
     webbläsarens tunna list syntes den knappt. Telefoner som bara visar
     listen medan man drar bryr sig inte om storleken – där är det biten av
     nästa bild i kanten som visar att det finns fler. */
  #bank-lista.rullar { padding-bottom:8px; }
  #bank-lista::-webkit-scrollbar { height:8px; }
  #bank-lista::-webkit-scrollbar-track { background:#eceef1; border-radius:999px; }
  #bank-lista::-webkit-scrollbar-thumb { background:#9aa1ab; border-radius:999px; }
  #bank-lista::-webkit-scrollbar-thumb:hover { background:#6b7280; }
  /* Firefox har inga ::-webkit-scrollbar, bara färgerna */
  @supports not selector(::-webkit-scrollbar) {
    #bank-lista { scrollbar-color:#9aa1ab #eceef1; }
  }
  /* Hela bilden på grå botten, som .thumb under: kunden ska se om bilden
     är stående, liggande eller kvadratisk. Med cover fylldes rutan och
     kanterna skars bort. */
  .bank-bild {
    position:relative; aspect-ratio:1; border-radius:8px; overflow:hidden;
    cursor:pointer; background:#e8e8e8; border:2px solid var(--border);
  }
  .bank-bild.vald { border-color:var(--blue); }
  .bank-bild img { width:100%; height:100%; object-fit:contain; display:block; opacity:.85; }
  .bank-bild.vald img { opacity:1; }
  .bank-markor {
    position:absolute; top:3px; right:3px; width:24px; height:24px; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    font-size:12px; font-weight:800; color:#fff; background:rgba(0,0,0,.35);
  }
  .bank-bild.vald .bank-markor { background:var(--blue); }
  #thumbs {
    display:grid; grid-template-columns:repeat(5,1fr); gap:7px;
    margin-top:12px; margin-bottom:0;
  }
  .thumb {
    aspect-ratio:1; border-radius:8px; overflow:hidden;
    position:relative; cursor:grab; user-select:none;
    transition: opacity .2s, transform .15s;
    background:#e8e8e8;
  }
  .thumb:active { cursor:grabbing; }
  .thumb.drag-over { outline: 2.5px dashed var(--blue); opacity:.7; }
  .thumb.dragging  { opacity:.35; transform:scale(.95); }
  .thumb img { width:100%;height:100%;object-fit:contain;display:block; }
  /* Träffytan är 44 px och genomskinlig, cirkeln man ser är 24. Hela
     miniatyren är bara omkring 66 px bred, så en synlig knapp på 44 hade
     tagit halva bilden. Ytan ligger innanför miniatyrens hörn och krockar
     inte med grannen.

     Draget för att sortera om påverkas inte: touchmove gör preventDefault,
     så webbläsaren skickar inget klick efter ett drag, och ett tryck som
     inte rör sig är ändå inget drag. */
  .tdel {
    position:absolute;top:0;right:0;
    width:44px;height:44px;padding:3px 3px 0 0;
    background:none;border:none;cursor:pointer;z-index:2;
    display:flex;align-items:flex-start;justify-content:flex-end;
    -webkit-tap-highlight-color:transparent;
  }
  .tdel span {
    width:24px;height:24px;border-radius:999px;
    background:rgba(17,24,39,.7);color:#fff;
    font-size:13px;line-height:1;
    display:flex;align-items:center;justify-content:center;
    transition:background .15s;
  }
  .tdel .ikon-kryss { width:11px; height:11px; }
  .tdel:hover span  { background:rgba(17,24,39,.88); }
  .tdel:active span { transform:scale(.92); }
  /* Sidnumret ligger direkt på bilden nere till vänster. Den svarta ramen
     runt siffran tog mer plats än den gav när rutnätet blev fem i bredd. */
  .thumb-num {
    position:absolute;bottom:3px;left:5px;
    color:#4b5563; font-size:12px; font-weight:700;
    text-shadow:0 1px 2px rgba(255,255,255,.9);
    pointer-events:none;
  }
  /* Crop modal */
  #crop-modal {
    position:fixed;inset:0;background:rgba(0,0,0,0.92);
    z-index:200;display:flex;flex-direction:column;
    align-items:center;
  }
  #crop-modal .crop-header {
    width:100%;padding:12px 16px;
    display:flex;align-items:center;justify-content:space-between;
    color:#fff;
  }
  #crop-modal .crop-header span { font-size:14px;font-weight:700; }
  #crop-modal .crop-header small { font-size:11px;opacity:.6; }
  #crop-wrap {
    flex:1;width:100%;min-height:0;
    display:flex;align-items:center;justify-content:center;
    overflow:hidden;
  }
  #crop-wrap img { max-width:100%;max-height:100%;display:block; }
  #crop-footer {
    width:100%;padding:12px 16px 24px;
    display:flex;gap:10px;
  }
  #crop-footer button {
    flex:1;padding:13px;border-radius:12px;
    border:none;font-size:15px;font-weight:700;cursor:pointer;
  }
  #crop-cancel { background:#333;color:#ccc; }
  #crop-confirm { background:var(--blue);color:#fff; }
  /* Processing indicator */
  .ph-processing {
    text-align:center;font-size:12px;color:var(--muted);
    padding:8px;
  }
  /* Filer som inte gick att använda – syns tills kunden väljer nya */
  .ph-processing.fel { color:var(--rod); font-size:12.5px; line-height:1.45; }

  /* Uppladdningens tillstånd i granskningssteget */
  .rv-spar { font-size:12.5px; line-height:1.45; text-align:center;
             color:var(--muted); margin-bottom:12px; }
  .rv-spar-fel { color:var(--rod); }
  .rv-spar-fel button {
    display:block; margin:9px auto 0; padding:9px 20px;
    background:var(--rod); color:#fff; border:none; border-radius:10px;
    font-size:14px; font-weight:700; font-family:inherit; cursor:pointer;
  }
  .thumb-fel { outline:2px solid var(--rod); outline-offset:-2px; }
  .ph-count { text-align:center; font-size:12px; color:var(--muted); }
  .ph-count b { color:var(--blue); }

  /* ── GENERATING ── */
  .gen-wrap { text-align:center; padding:8px 0; }
  .gen-spin {
    width:48px;height:48px;margin:0 auto 14px;
    border:4px solid #E5E7EB;border-top-color:var(--blue);
    border-radius:50%; animation:spin 1s linear infinite;
  }
  @keyframes spin { to { transform:rotate(360deg); } }
  .gen-pb-wrap {
    height:7px;background:#E5E7EB;border-radius:99px;overflow:hidden;margin:12px 0 6px;
  }
  .gen-pb {
    height:100%;
    background:linear-gradient(90deg,var(--blue),#60a5fa);
    border-radius:99px;transition:width .5s ease;
  }
  .gen-pages {
    display:grid;grid-template-columns:repeat(10,1fr);gap:4px;margin-top:14px;
  }

  /* ── PAGE COUNT CARDS ── */
  .pc-card {
    display:flex;justify-content:space-between;align-items:center;
    padding:14px 18px;border:2px solid var(--border);border-radius:14px;
    background:var(--white);cursor:pointer;transition:border-color .15s, background .15s;
    text-align:left;
  }
  .pc-card:hover { border-color:#93c5fd; background:#f0f7ff; }
  .pc-card.pc-selected { border-color:var(--blue); background:#EEF5FF; }
  .pc-num   { font-size:17px;font-weight:700;color:var(--text); }
  .pc-price { font-size:13px;color:var(--muted); }
  .gp {
    width:34px;height:46px;border-radius:4px;
    background:#F3F4F6;border:1.5px solid #E5E7EB;
    display:flex;align-items:center;justify-content:center;
    font-size:16px;transition:background .3s,border-color .3s;
  }
  .gp.done { background:#EEF5FF;border-color:var(--blue); }

  /* ── REVIEW ── */
  .rev-strip-wrap {
    position:relative;margin-bottom:14px;
  }
  .rev-strip-wrap::after {
    content:'';position:absolute;right:0;top:0;bottom:4px;width:40px;
    background:linear-gradient(to right,transparent,var(--white));
    pointer-events:none;
  }
  .rev-strip {
    display:flex;flex-wrap:nowrap;gap:8px;
    overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:6px;
  }
  .rev-strip::-webkit-scrollbar { height:3px; }
  .rev-strip::-webkit-scrollbar-thumb { background:var(--border);border-radius:2px; }
  .rev-strip::-webkit-scrollbar-track { background:transparent; }
  .rev-th {
    flex-shrink:0;width:58px;height:78px;border-radius:6px;overflow:hidden;
    border:2.5px solid var(--border);cursor:pointer;transition:border-color .2s;
    position:relative;
  }
  .rev-th.on { border-color:var(--blue); }
  .rev-th img { width:100%;height:100%;object-fit:cover; }
  .rev-th .thumb-num {
    position:absolute;bottom:3px;left:4px;
    background:none;color:#4b5563;
    font-size:11px;font-weight:700;
    border:none;padding:0;
    text-shadow:0 1px 2px rgba(255,255,255,.9);
  }

  /* Beskärningsrutan i granskningssteget.
     Fast höjd oavsett bildens form — annars flyttar sig knapparna under
     mellan varje bild, och kunden får leta efter "Nästa bild" tio gånger
     i rad. Cropper.js ritar bilden centrerad inuti rutan i stället. */
  /* Fyller bandet i stället för att ha en egen höjd. Förut var ytan byggd
     210-420 px men låg i standardbandets 172 px med overflow:hidden, så
     bara ungefär 148 px syntes på en telefon. */
  #rv-crop-wrap {
    width:100%;
    height:100%;
    display:flex;align-items:center;justify-content:center;
    overflow:hidden;
    /* Grå omgivning så att fotot syns som fotot och inte flyter ihop
       med den vita sidan runt omkring. */
    background:#6b6f76;
  }
  /* Medan beskäraren byggs om ligger den nakna img-taggen kvar och
     sträcker ut fotot över hela bandet. Göm ytan tills den är klar. */
  #rv-crop-wrap.bygger-om { visibility: hidden; }
  #rv-crop-wrap img {
    display:block;
    width:100%;height:100%;
    max-width:none;max-height:none;
  }
  #rv-crop-wrap .cropper-container { touch-action:none; }

  /* Beskärningsramen. Cropper.js ritar en 1 px tunn blå linje som knappt
     syns på en telefon, särskilt mot ljusa foton. Vit ram med blå kant
     utanför syns mot både ljust och mörkt, och det mörkare utanförläget
     gör det tydligt vad som kommer med i boken. */
  #rv-crop-wrap .cropper-view-box { outline: none; }

  /* Ramen ritas som ett eget lager ovanpå bilden. En skugga inuti rutan
     hamnar under fotot och syns inte, och en ram utanför klipps bort när
     beskärningen fyller hela ytan. */
  #rv-crop-wrap .cropper-crop-box::after {
    content: ''; position: absolute; inset: 0;
    pointer-events: none; z-index: 3;
    border: 3px solid var(--blue);
  }
  #rv-crop-wrap .cropper-modal {
    background: #0B1220; opacity: .58;
  }
  #rv-crop-wrap .cropper-dashed {
    border-color: rgba(255,255,255,.5);
    border-width: 1px;
  }
  #rv-crop-wrap .cropper-center { opacity: .5; }

  /* Handtag i hörnen. Ramen gick att flytta bilden under men det syntes
     inte att storleken gick att ändra – ingenting pekade på det. Fyra
     runda prickar gör det, på samma sätt som i telefonens egen
     bildredigerare.

     Bara hörnen. Cropper.js ritar också punkter mitt på varje sida; de är
     för små för en tumme och gör ramen rörig. */
  #rv-crop-wrap .cropper-point {
    width:18px; height:18px; border-radius:50%;
    background:#fff; border:2.5px solid var(--blue);
    box-shadow:0 1px 5px rgba(0,0,0,.5);
    opacity:1; z-index:4;
  }
  #rv-crop-wrap .cropper-point.point-n,
  #rv-crop-wrap .cropper-point.point-e,
  #rv-crop-wrap .cropper-point.point-s,
  #rv-crop-wrap .cropper-point.point-w { display:none; }
  /* Prickarna ligger innanför ramen, inte grensle över den. Ramen går
     kant i kant mot bandet i minst en led, och då kapar overflow:hidden
     den halva som hamnar utanför – två av hörnen blev halvmånar. */
  #rv-crop-wrap .cropper-point.point-nw { top:7px;    left:7px;  }
  #rv-crop-wrap .cropper-point.point-ne { top:7px;    right:7px; }
  #rv-crop-wrap .cropper-point.point-sw { bottom:7px; left:7px;  }
  #rv-crop-wrap .cropper-point.point-se {
    bottom:7px; right:7px; width:18px; height:18px;
  }
  /* Själva pricken är 16 px men greppytan 40 px, annars måste tummen
     träffa på pixeln. Cropper.js har en sådan yta men bara på ett av
     hörnen, och den ritas i blått. */
  #rv-crop-wrap .cropper-point::before,
  #rv-crop-wrap .cropper-point::after {
    content:''; position:absolute; inset:-12px;
    background:none; opacity:0; width:auto; height:auto;
  }

  .btn-rotate {
    flex:1;height:46px;padding:0;
    border:1px solid var(--border);border-radius:12px;
    background:var(--white);color:var(--text);font-size:14px;font-weight:600;
    font-family:inherit;cursor:pointer;
    display:flex;align-items:center;justify-content:center;gap:7px;
  }
  .btn-rotate:hover { background:var(--warm); }
  .btn-rotate:hover { background:var(--warm);border-color:#aaa; }

  .btn-aspect {
    flex:1;height:46px;padding:0;
    border:1px solid var(--border);border-radius:12px;
    background:var(--white);color:var(--text);font-size:14px;font-weight:600;
    font-family:inherit;cursor:pointer;transition:all .15s;
    display:flex;align-items:center;justify-content:center;gap:7px;
  }
  .btn-aspect:hover { background:var(--warm); }
  .btn-aspect.active {
    background:var(--blue);color:#fff;border-color:var(--blue);font-weight:700;
  }

  /* Format och vridning på en enda rad, som ikoner med en liten etikett
     under. Två rader med textknappar och två rubriker tog 150 px av
     skärmen — det utrymmet gör mer nytta som bild.

     Etiketterna står kvar trots att förebilden bara har ikoner: en
     testare förstod inte vad knapparna gjorde, och ett ord under ikonen
     kostar 11 px. */
  .krop-verktyg {
    display:flex; align-items:stretch; gap:4px;
  }
  .krop-vkt {
    flex:1 1 0; min-width:0;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:2px; height:54px; padding:0 2px;
    background:var(--white); border:1px solid var(--border); border-radius:11px;
    font-family:inherit; color:var(--text); cursor:pointer;
    transition:background .15s, border-color .15s, color .15s;
  }
  .krop-vkt .krop-ikon { font-size:17px; line-height:1; }
  .krop-vkt .krop-txt {
    font-size:10.5px; font-weight:600; letter-spacing:.01em;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;
  }
  .krop-vkt.active {
    background:var(--blue); border-color:var(--blue); color:#fff;
  }
  .krop-vkt:disabled { opacity:.4; pointer-events:none; }
  /* Skiljer formatvalen från vridningen utan att kosta en hel rad. */
  .krop-delare {
    flex:0 0 1px; align-self:center; height:32px;
    background:var(--border); margin:0 3px;
  }

  /* Sammanfattningens tre handlingar. Fulla bredder och 48 px höjd: de
     är sidans enda reglage sedan miniatyrraden togs bort. */
  /* Raden om målarbilderna står på en rad, som rubriken under: nowrap här
     och _passaRubrik krymper texten i små steg på smala telefoner. Luften
     inuti är knappare än i andra rutor just för att texten ska rymmas. */
  .klara-info {
    background:var(--blaljus); border:1px solid #dce6f6; border-radius:11px;
    padding:10px 11px; margin-bottom:4px;
    font-size:13.5px; line-height:1.45; color:var(--text); white-space:nowrap;
  }
  /* Sammanfattningens rubrik står på en rad. nowrap här, och _passaRubrik
     krymper texten i små steg på smala telefoner i stället för att den
     bryts. */
  .sec-title.klara-rubrik {
    text-align:center; margin-bottom:14px; white-space:nowrap;
  }

  /* Rubriken ovanför handlingarna i svart och något större än övriga
     f-label-rubriker. Den inleder sidans enda reglage och ska läsas, inte
     glida förbi. "Välj typsnitt" och de andra behåller grått och 12 px. */
  .f-label.klara-andra { color:var(--text); font-size:14px; margin-bottom:8px; }
  /* Ett kort med tre rader i stället för tre lösa lådor. Ramen och
     rundningen sitter på kortet; raderna skiljs bara av en tunn linje. */
  .klara-atgarder {
    background:#fff; border:1px solid var(--border); border-radius:14px;
    overflow:hidden;
  }
  .klara-atg {
    position:relative; width:100%; min-height:64px; padding:11px 12px;
    display:flex; align-items:center; gap:12px;
    background:#fff; border:none; border-radius:0;
    font-family:inherit; color:var(--text); text-align:left; cursor:pointer;
    transition:background .15s;
    -webkit-tap-highlight-color:transparent;
  }
  /* Linjen börjar vid texten, inte vid kanten: 12 px luft + 40 px ikon +
     12 px mellanrum. Ikonerna står då som en egen spalt och kortet läses
     som en lista. */
  .klara-atg + .klara-atg::before {
    content:''; position:absolute; top:0; left:64px; right:0;
    height:1px; background:var(--border);
  }
  .klara-atg:hover  { background:#F8FAFC; }
  .klara-atg:active { background:var(--blaljus); }
  .klara-atg:focus-visible { outline:2px solid var(--blue); outline-offset:-2px; }

  .klara-ikon {
    width:40px; height:40px; flex-shrink:0; border-radius:11px;
    background:var(--blaljus); color:var(--blue);
    display:flex; align-items:center; justify-content:center;
  }
  .klara-ikon svg, .klara-pil {
    fill:none; stroke:currentColor; stroke-width:2;
    stroke-linecap:round; stroke-linejoin:round;
  }
  .klara-ikon svg { width:20px; height:20px; }
  .klara-atg-text {
    flex:1; min-width:0; display:flex; flex-direction:column; gap:1px;
  }
  .klara-atg-titel { font-size:15px; font-weight:600; line-height:1.3; }
  .klara-atg-under { font-size:12.5px; color:var(--muted); line-height:1.35; }
  .klara-pil { width:18px; height:18px; flex-shrink:0; color:#9CA3AF; }

  /* ── Presentpaketet på tillvalssidan ─────────────────────────────────
     Ett kort som sticker ut från raderna under: blå ram och ett blått
     band överst med vad kunden sparar. */
  .paket {
    border:2px solid var(--blue); border-radius:14px; overflow:hidden;
    background:#fff; margin-bottom:14px;
  }
  .paket-topp {
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    background:var(--blue); color:#fff; padding:8px 14px;
  }
  .paket-namn {
    font-size:12.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
  }
  .paket-spar { font-size:13px; font-weight:700; white-space:nowrap; }
  .paket-kropp { display:flex; align-items:center; gap:12px; padding:14px 14px 4px; }
  /* ── Produktrutan på tillvalssidan ──────────────────────────────────
     Bilden i tillvalsraden är en knapp. Förstoringsglaset i hörnet visar
     att den går att trycka på, och en tryckning öppnar rutan i stället för
     att kryssa raden. */
  .tillval-bild-knapp {
    /* flex: annars står bilden på textens baslinje och knappen blir 4 px
       högre än bilden */
    display:flex; position:relative; flex-shrink:0; padding:0; border:none; background:none;
    border-radius:11px; cursor:zoom-in; font:inherit;
  }
  .tillval-bild-knapp:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
  .tillval-lupp {
    position:absolute; right:3px; bottom:3px; width:22px; height:22px; border-radius:50%;
    background:#fff; box-shadow:0 1px 4px rgba(17,24,39,.25);
    display:flex; align-items:center; justify-content:center;
  }
  .tillval-lupp svg {
    width:13px; height:13px; fill:none; stroke:var(--blue);
    stroke-width:2.6; stroke-linecap:round;
  }
  /* Det som skiljer produktrutan från de andra rutorna (dialog.ruta-kort
     längre ner): ingen luft i kanten, bredare, och krysset ligger i rutan
     med rullytan under, så det står kvar hur långt kunden än rullar. */
  dialog.ruta-kort.produkt-kort {
    padding:0; width:calc(100% - 32px); max-width:420px;
    max-height:calc(100vh - 32px); max-height:calc(100dvh - 32px);
    display:flex; flex-direction:column; overflow:hidden; text-align:left;
  }
  dialog.ruta-kort.produkt-kort:not([open]) { display:none; }
  .produkt-rull { overflow-y:auto; min-height:0; overscroll-behavior:contain; }
  .produkt-stang {
    position:absolute; top:10px; right:10px; z-index:1; width:44px; height:44px;
    border:none; border-radius:50%; background:rgba(255,255,255,.94);
    box-shadow:0 1px 6px rgba(17,24,39,.2); cursor:pointer;
    display:flex; align-items:center; justify-content:center;
  }
  .produkt-stang .ikon-kryss { width:16px; height:16px; color:var(--text); }
  /* Bilderna ligger bredvid varandra och bläddras med fingret; varje bild
     fyller rutan och visas hel på den varma bakgrunden */
  .produkt-bilder {
    display:flex; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none;
    aspect-ratio:1; max-height:min(420px, 52dvh); background:var(--warm);
  }
  .produkt-bilder::-webkit-scrollbar { display:none; }
  .produkt-ikon { display:flex; align-items:center; justify-content:center; height:160px; background:var(--warm); }
  .produkt-bilder img {
    flex:0 0 100%; width:100%; height:100%; object-fit:contain; scroll-snap-align:center;
  }
  .produkt-prickar { display:flex; justify-content:center; margin-bottom:-12px; }
  .produkt-prickar button {
    position:relative; width:44px; height:44px; padding:0; border:none;
    background:none; cursor:pointer;
  }
  .produkt-prickar button::after {
    content:''; position:absolute; left:18px; top:18px; width:8px; height:8px;
    border-radius:50%; background:#d5d8de;
  }
  .produkt-prickar button.aktiv::after { background:var(--blue); }
  .produkt-info { display:flex; flex-direction:column; gap:12px; padding:16px 18px 18px; }
  .produkt-rad { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; }
  .produkt-titel { margin:0; font-size:19px; font-weight:800; line-height:1.25; }
  .produkt-pris  { flex-shrink:0; padding-top:2px; }
  .produkt-text  { font-size:14.5px; line-height:1.5; color:#374151; }
  /* Luft mellan blocken, inte under varje block: då behövs ingen
     återställning för det sista */
  .produkt-text > * { margin:0; }
  .produkt-text > * + * { margin-top:8px; }
  .produkt-text ul, .produkt-text ol { padding-left:20px; }
  .produkt-text h3, .produkt-text h4 { font-size:15px; font-weight:800; }
  .produkt-text > * + :is(h3, h4) { margin-top:12px; }
  .produkt-text > :is(h3, h4) + * { margin-top:4px; }
  /* Samma knapp som i presentpaketets kort (.paket-knapp), i full bredd */
  .produkt-val { display:block; width:100%; min-height:52px; margin-top:4px; }
  .paket-bilder { display:flex; gap:6px; flex-shrink:0; }
  /* tillvalBildHtml sätter 46 px i stilattributet; i paketet står tre i rad */
  .paket-bilder > * { width:40px !important; height:40px !important; }
  .paket-text {
    flex:1; min-width:0; font-size:14px; line-height:1.35; color:var(--text);
  }
  .paket-fot {
    display:flex; align-items:center; justify-content:space-between; gap:12px;
    padding:10px 14px 14px;
  }
  .paket-priser { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; min-width:0; }
  .paket-styck { font-size:14px; color:var(--grabla); text-decoration:line-through; }
  .paket-pris {
    font-size:22px; font-weight:800; color:var(--blue); letter-spacing:-.01em;
    white-space:nowrap;
  }
  .paket-knapp {
    flex-shrink:0; min-height:48px; padding:0 22px; border:none; border-radius:14px;
    background:var(--blue); color:#fff;
    font-family:inherit; font-size:16px; font-weight:700;
    cursor:pointer; transition:background .15s, color .15s;
  }
  .paket-knapp:hover { background:var(--blue-d); }
  .paket-knapp:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
  /* Tillagt: knappen blir ljus så att det syns att valet redan är gjort,
     och ett tryck till tar bort paketet igen. */
  .paket.vald .paket-knapp, .paket-knapp.vald { background:var(--blaljus); color:var(--blue); }
  .paket.vald .paket-knapp:hover, .paket-knapp.vald:hover { background:#e2ecfb; }

  /* ── Tillvalssidan ───────────────────────────────────────────────────
     Varm bakgrund bakom hela formuläret, så att produktkorten står ut som
     vita kort. Samma nyans som bakom appen på datorn. */
  /* Totalen står längst ner i samma vita list som på beställningssidan
     (se .bestall-fot), fast utan "+ Skapa en till bok". Samma flexkedja
     håller den vid botten när korten är få. Innehållet ligger i ett eget
     block, så att marginalerna mellan korten beter sig som förut. */
  #content:has(.tillval-sida) { display:flex; flex-direction:column; background:var(--warm); }
  /* width:100% behövs för att sidan ska fylla spalten på plattor och
     datorer. Där centreras formuläret med margin-inline:auto, och i en
     flexkolumn slutar rutan då att sträcka sig och krymper till
     innehållets bredd – korten blev 265 px mitt på en 1120 px skärm. */
  #content:has(.tillval-sida) .ci {
    flex:1; display:flex; flex-direction:column; min-height:0; padding-bottom:0; width:100%;
  }
  .tillval-sida { flex:1; display:flex; flex-direction:column; }
  .tillval-innehall { padding-bottom:16px; }

  /* ── Beställningssidan ───────────────────────────────────────────────
     Efter mockupen med kryssrutor: en vit rubriklist överst, ett kort per
     bok med tillvalen som kryssrutor, tillval som räknas i antal på en egen
     rad under, och totalen fast längst ner ovanför navraden. Med kort
     innehåll står totalen ändå vid botten: sidan är en flexkolumn och foten
     har margin-top:auto. */
  /* Varm bakgrund bakom korten, som på tillvalssidan. */
  #content:has(.bestall) { display:flex; flex-direction:column; background:var(--warm); }
  /* width:100% av samma skäl som på tillvalssidan ovan */
  #content:has(.bestall) .ci {
    flex:1; display:flex; flex-direction:column; min-height:0; padding-top:0; padding-bottom:0; width:100%;
  }
  /* Kedjan hela vägen ner: var .bestall ett vanligt block blev den bara så
     hög som innehållet, och foten stod mitt på sidan med en bok. */
  .bestall { flex:1; display:flex; flex-direction:column; }

  /* Rubriklisten överst, vit kant i kant på samma sätt som foten (se
     .bestall-fot): skuggan fyller ut åt sidorna, ::after drar linjen. */
  .bestall-topp {
    position:sticky; top:0; z-index:2;
    display:flex; justify-content:space-between; align-items:baseline; gap:12px;
    background:var(--white);
    box-shadow:0 0 0 100vmax var(--white);
    clip-path:inset(0 -100vmax);
    padding:16px 0; margin-bottom:14px;
  }
  .bestall-topp::after {
    content:''; position:absolute; bottom:0; left:-100vmax; right:-100vmax;
    height:1px; background:var(--border);
  }
  .bestall-rubrik { font-size:18px; font-weight:800; }
  .bestall-antal { font-size:14px; color:var(--muted); white-space:nowrap; }

  .bok-kort {
    border:1px solid var(--border); border-radius:16px;
    padding:14px 16px 12px; margin-bottom:12px; background:#fff;
  }
  .bok-huvud { display:flex; justify-content:space-between; align-items:center; gap:12px; }
  .bok-info { min-width:0; display:flex; flex-direction:column; align-items:flex-start; gap:2px; }
  .bok-titel { font-size:17px; font-weight:800; line-height:1.25; }
  .bok-detalj { font-size:14px; color:var(--muted); line-height:1.3; }
  .bok-pris { flex-shrink:0; font-size:17px; font-weight:800; white-space:nowrap; }
  .bok-rader {
    display:flex; flex-direction:column; gap:8px;
    margin-top:12px; padding-top:12px; border-top:1.5px dashed var(--border);
  }
  /* Tillvalen under boken: samma kort som på tillvalssidan. Kryssruta,
     produktbild med lupp (öppnar produktrutan), namn och beskrivning, och
     priset med det ordinarie överstruket när tillvalet är nedsatt. */
  .bok-rad {
    display:flex; align-items:center; gap:12px; width:100%; min-height:44px;
    padding:7px 12px; border:1px solid var(--border); border-radius:14px; background:#fff;
    font-family:inherit; font-size:15px; color:var(--text); text-align:left; cursor:pointer;
    transition:border-color .15s, background .15s;
  }
  .bok-rad.vald { border-color:var(--blue); background:var(--blaljus); }
  .bok-rad:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
  .bok-rad-text { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .bok-rad-under { font-size:12px; color:var(--muted); line-height:1.4; }
  .bok-kryss {
    width:24px; height:24px; flex-shrink:0; border-radius:6px;
    border:2px solid #C9CFD8; background:#fff; color:#fff;
    display:flex; align-items:center; justify-content:center;
    font-size:15px; font-weight:800; line-height:1;
  }
  .bok-rad.vald .bok-kryss { background:var(--blue); border-color:var(--blue); }
  .bok-rad-namn { min-width:0; font-size:14px; font-weight:700; line-height:1.25; }
  .bok-rad > .bok-rad-namn { flex:1; }
  .bok-rad-pris { flex-shrink:0; text-align:right; white-space:nowrap; }
  /* Presentpaketet i bokkortet: hela blocket är kortet, med en kryssruta för
     paketet överst, det som ingår under med överstrukna styckpriser, och vad
     kunden sparar. Texten under står i linje med namnet. */
  .bok-paket {
    border:1px solid var(--blue); border-radius:14px; background:var(--blaljus);
    padding:0 12px 10px;
  }
  .bok-paket .bok-rad { border:none; border-radius:0; background:none; padding:7px 0; }
  .bok-paket-rad .bok-rad-namn { font-size:15px; font-weight:800; }
  .bok-paket-rad .bok-rad-pris { font-weight:800; }
  .bok-paket-lista {
    list-style:none; margin:0; padding:0 0 0 36px;
    display:flex; flex-direction:column; gap:4px;
  }
  .bok-paket-lista li {
    display:flex; justify-content:space-between; align-items:baseline; gap:12px;
    font-size:14.5px; color:var(--muted);
  }
  .bok-paket-lista s { color:var(--grabla); white-space:nowrap; }
  .bok-paket-spara { padding:8px 0 0 36px; font-size:14.5px; font-weight:800; color:#8A4B22; }

  /* Stegaren behåller 44 px. Det som får ge plats är bilden och luften,
     annars kapades namnet bakom knapparna. */
  .antal-rad {
    display:flex; align-items:center; gap:10px;
    border:1px solid var(--border); border-radius:16px;
    padding:12px 14px; margin-bottom:10px; background:#fff;
  }
  .antal-rad > img, .antal-rad > .antal-ikon {
    width:38px; height:38px; flex-shrink:0; border-radius:9px; object-fit:cover;
    display:flex; align-items:center; justify-content:center; font-size:20px;
    background:#F1F5F9;
  }
  .antal-info { flex:1; min-width:0; }
  .antal-titel { font-size:15px; font-weight:800; line-height:1.25; }
  .antal-per { font-size:13px; color:var(--muted); white-space:nowrap; }
  .stegare { display:flex; align-items:center; gap:6px; flex-shrink:0; }
  /* Smala telefoner: bilden göms så att namnet får plats bredvid stegaren */
  @media (max-width: 374px) {
    .antal-rad > img, .antal-rad > .antal-ikon { display:none; }
  }
  .steg-knapp {
    width:44px; height:44px; border-radius:12px; cursor:pointer;
    border:1px solid var(--border); background:#fff; color:var(--text);
    font-family:inherit; font-size:22px; line-height:1;
    display:flex; align-items:center; justify-content:center;
  }
  .steg-knapp.plus { background:var(--blaljus); border-color:#c3d4ee; color:var(--blue); }
  .steg-knapp:disabled { opacity:.4; cursor:default; }
  .steg-antal { min-width:14px; text-align:center; font-size:17px; font-weight:800; }
  .antal-summa { font-size:16px; font-weight:800; white-space:nowrap; text-align:right; }

  /* Totalen står fast längst ner ovanför navraden när listan är lång, i en
     vit list kant i kant mot den varma bakgrunden.

     Formulärets marginaler är olika på telefon, platta och dator, så listen
     kan inte räkna ut hur långt den ska sträcka sig. Skuggan fyller i stället
     ut vitt långt åt sidorna, och clip-path släpper bara igenom den i sidled.
     Innehållsytan klipper den vid sina egna kanter. Linjen upptill ritas av
     ::before, som sträcker sig lika långt. */
  .bestall-fot {
    margin-top:auto; position:sticky; bottom:0; z-index:2;
    background:var(--white);
    box-shadow:0 0 0 100vmax var(--white);
    clip-path:inset(0 -100vmax);
    padding:12px 0 14px;
  }
  .bestall-fot::before {
    content:''; position:absolute; top:0; left:-100vmax; right:-100vmax;
    height:1px; background:var(--border);
  }
  .fot-rad {
    display:flex; justify-content:space-between; align-items:baseline; gap:10px;
    margin-bottom:10px;
  }
  /* Utan knapp under, som på tillvalssidan, står raden sist i listen */
  .fot-rad:last-child { margin-bottom:0; }
  .fot-etikett { font-size:18px; font-weight:800; }
  /* Fraktraden bryter som en enhet: får den inte plats bredvid "Totalt"
     hamnar hela raden under, i stället för att delas mitt i. */
  .fot-etikett small { display:inline-block; font-size:13px; font-weight:500; color:var(--muted); }
  .fot-summa { font-size:28px; font-weight:800; letter-spacing:-.02em; white-space:nowrap; }
  .knapp-en-till {
    display:block; width:100%; min-height:52px; cursor:pointer;
    /* Tjock ram i samma blå som köpknappen: med 1,5 och 2,5 px, och i grått,
       syntes knappen för dåligt mot den vita listen */
    border:4px solid var(--blue); border-radius:14px; background:#fff;
    color:var(--blue); font-family:inherit; font-size:16px; font-weight:700;
  }
  .knapp-en-till:hover { background:var(--blaljus); border-color:var(--blue-d); }
  .knapp-en-till:disabled { opacity:.45; cursor:not-allowed; }

  /* Räknaren ligger ovanpå bilden i stället för att ta en egen rad.
     Den kostar då ingen höjd, och står ändå först i läsordningen. */
  .rev-progress {
    position:absolute; top:0; left:0; right:0; z-index:4;
    display:flex; align-items:center; gap:10px;
    padding:9px 14px; color:#fff;
    background:linear-gradient(rgba(0,0,0,.45), rgba(0,0,0,0));
    pointer-events:none;
  }
  .rev-progress-bar {
    flex:1;height:5px;background:rgba(255,255,255,.3);border-radius:999px;overflow:hidden;
  }
  .rev-progress-fill {
    height:100%;background:var(--blue);border-radius:999px;transition:width .3s;
  }

  /* ── PREV GRID (photo step preview) ── */
  .prev-grid {
    display:grid;grid-template-columns:repeat(3,1fr);gap:5px;
    width:100%;max-width:260px;
  }
  .prev-cell {
    aspect-ratio:3/4;border-radius:7px;overflow:hidden;
    background:#E5E7EB;display:flex;align-items:center;justify-content:center;font-size:22px;
  }
  .prev-cell img { width:100%;height:100%;object-fit:cover; }

  .fade-in { animation:fadeUp .3s ease both; }
  @keyframes fadeUp {
    from { opacity:0;transform:translateY(10px); }
    to   { opacity:1;transform:translateY(0); }
  }

  /* ── ORDNINGSSTEGET ──
     Listan låg förut i en overlay ovanpå bildsteget. Som eget steg behövs
     varken ram, stängkryss eller sparknapp – navets knappar räcker. */

  /* Listvy */
  .so-list { display:flex; flex-direction:column; gap:8px; }
  /* Raden växer med miniatyren i stället för att låsas till 64 px. En
     stående bild är 92 px hög och stack ut ur raden både uppåt och nedåt
     när ordningen låg i en overlay; som eget steg finns höjden. */
  .so-list-row {
    min-height:64px; display:flex; align-items:center; gap:12px;
    background:var(--white); border-radius:12px;
    border:1px solid var(--border); padding:8px 8px 8px 12px;
  }
  .so-list-num {
    width:26px; height:26px; border-radius:999px;
    background:var(--blue); color:#fff; font-size:13px; font-weight:800;
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
  }
  /* Listan är enda sättet att sortera, så bilden måste gå att känna igen.
     Miniatyrens mått sätts per bild i JS så att formen — stående,
     liggande eller kvadratisk — syns direkt. Platsen runt omkring är
     lika bred för alla rader, annars hoppar pilarna i sidled. */
  .so-list-slot {
    width:112px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
  }
  .so-list-thumb {
    border-radius:8px; overflow:hidden;
    background:#f1f2f4; flex-shrink:0;
  }
  .so-list-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
  .so-list-arrows { flex:1; display:flex; justify-content:flex-end; gap:8px; }
  /* Pilarna är blå så länge de går att trycka på och tonas ner helt när
     bilden ligger först eller sist – kunden ska se det utan att prova. */
  .so-updown {
    width:44px; height:44px; border-radius:10px;
    border:1px solid #c3d4ee; background:var(--blaljus);
    font-size:22px; font-weight:700; line-height:1;
    cursor:pointer; color:var(--blue);
    display:flex; align-items:center; justify-content:center;
    transition:all .15s;
  }
  .so-updown:hover:not(:disabled) { background:#e2ecfb; }
  .so-updown:disabled {
    border-color:#F1EFEA; background:#FAF9F7; color:#cfd3d9; cursor:default;
  }

  /* ── Rutorna ──
     Alla rutor är <dialog> öppnade med showModal (se _oppnaRuta): frågan
     när kunden kommer tillbaka, frågan om att avbryta en ny bok och
     produktrutan på tillvalssidan. Det här är det gemensamma skalet; en
     regel med display slår ut webbläsarens display:none för en stängd
     dialog, därav :not([open]). Höjden i vh är reserv för webbläsare utan
     dvh. */
  dialog.ruta-kort {
    position:fixed; inset:0; margin:auto; border:none; z-index:9999;
    max-height:calc(100vh - 48px); max-height:calc(100dvh - 48px);
    overflow:auto; color:var(--text);
    background:var(--white); border-radius:18px;
    box-shadow:0 12px 40px rgba(0,0,0,.25);
  }
  dialog.ruta-kort:not([open]) { display:none; }
  dialog.ruta-kort::backdrop { background:var(--dimma); }
  .forts-kort {
    padding:26px 22px 20px;
    width:calc(100% - 48px); max-width:340px; text-align:center;
  }
  .forts-ikon   { font-size:40px; line-height:1; margin-bottom:10px; }
  .forts-rubrik { font-size:19px; font-weight:800; margin-bottom:6px; }
  .forts-text   { font-size:14px; color:var(--muted); line-height:1.45; margin-bottom:20px; }
  .forts-kort button {
    display:block; width:100%; border-radius:13px; font-size:16px;
    font-weight:700; cursor:pointer; padding:15px; font-family:inherit;
  }
  .forts-ja  { background:var(--blue); color:#fff; border:none; margin-bottom:9px; }
  .forts-nej { background:none; color:var(--muted); border:none; font-size:14px; padding:12px; }

  #app { position:relative; }
  /* ── SURFPLATTA ────────────────────────────────────────────────────
     Telefonlayouten fungerar på en platta men ser tunn ut: en 480 px
     spalt mitt på en skärm med 170 px tomt på varje sida och halva höjden
     blank. Reglerna nedan rör bara skärmar som är minst 700 px breda och
     600 px höga. En telefon på tvären är som mest 430 px hög och slinker
     därför aldrig in här, så mobilen är orörd.

     Blocket ligger sist i filen med flit: reglerna väger lika tungt som
     basreglerna, och då vinner den som står sist.
  ──────────────────────────────────────────────────────────────────── */

  /* Stående platta: samma stapel som på mobilen, men bredare och med
     större bok. Alla sex omslagen får plats utan att dras i sidled. */
  @media (min-width: 700px) and (min-height: 600px) and (orientation: portrait) {
    #app { max-width: min(720px, 92vw); }
    #preview      { height: 260px; max-height: 260px; }
    #preview.stor { height: 480px; max-height: 480px; }
    .cover-opt    { flex: 0 0 calc((100% - 5 * 8px) / 6); }
    .ci           { padding: 22px 20px; }
    .sec-title    { font-size: 24px; }
  }

  /* Liggande platta: höjden är det som tryter, bredden finns det gott om.
     Bok och formulär bredvid varandra, som telefonens liggande läge fast
     i stor skala. Bandet får sin höjd av spalten, så både bokens och
     uppslagets uträknade px-höjder måste vika.

     Omslagen behåller mobilens mått och dras i sidled som där: formuläret
     är bara en halv skärm brett, och sex i bredd hade gjort dem mindre än
     på en telefon. */
  @media (min-width: 700px) and (min-height: 600px) and (orientation: landscape) {
    #app {
      max-width: none;
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      grid-template-rows: auto minmax(0, 1fr) auto;
      grid-template-areas:
        "rad  rad"
        "bok  form"
        "nav  nav";
    }
    #preview {
      grid-area: bok; min-height: 0; padding: 24px;
      height: auto !important; max-height: none !important;
    }
    #content   { grid-area: form; min-height: 0; }
    #nav       { grid-area: nav; }
    #bok-rad   { grid-area: rad; }
    .ci        { padding: 26px 28px; max-width: 560px; margin-inline: auto; }
    .sec-title { font-size: 24px; }

    /* Stegen utan bok – bilduppladdningen, tillvalen, beställningen – tömmer
       förhandsvisningen. Utan det här står en stor tom sandruta bredvid
       formuläret. Nu tar formuläret hela bredden i stället. */
    #app:has(#preview:empty) { grid-template-columns: 0 minmax(0, 1fr); }
  }

  /* ── DATOR ─────────────────────────────────────────────────────────
     Med mus och stor skärm blir helskärmslayouten fel: boken sväller till
     786 px, formuläret ligger i vänsterkanten av en 960 px spalt och
     resten är tomt. Flödet samlas i stället i ett kort mitt på skärman,
     som en dialog i butiken.

     hover och pointer: fine betyder mus eller styrplatta. En platta med
     finger går inte in här utan behåller sin egen layout ovan.
  ──────────────────────────────────────────────────────────────────── */
  @media (min-width: 1000px) and (hover: hover) and (pointer: fine) {
    body {
      display: flex; align-items: center; justify-content: center;
      background: var(--warm);
    }
    #app {
      width:  min(1120px, 94vw);
      height: min(840px, 94dvh);
      max-width: none;
      border-radius: 20px; overflow: hidden;
      box-shadow: 0 30px 60px -30px rgba(17, 24, 39, .35);
    }
    /* Formuläret mitt i sin spalt i stället för i vänsterkanten */
    .ci { margin-inline: auto; }
    /* Ingen sidledsdragning med mus: det finns ingen rullningslist att ta
       tag i och hjulet rullar åt fel håll. Omslagen radbryts i stället och
       blir samtidigt större än de var när de låg på rad. */
    .cover-grid {
      flex-wrap: wrap; overflow: visible;
      margin-inline: 0; padding-left: 0; padding-right: 0;
    }
    .cover-opt { flex: 0 0 calc((100% - 2 * 8px) / 3); }

    /* Typsnittsrutorna är dubbelt så breda här som på en telefon, så provet
       får bli större. Det är provet kunden väljer på. */
    .font-opt       { height: 110px; }
    .font-opt .prov { font-size: 46px; }
  }
