/*
 * Grunnformene: knapper, kort, piller, statuslinjer.
 *
 * Alt her følger oppskriftene i PALETT.md. To regler som er lette å bryte:
 *   - primærknapp har MØRK tekst på is, aldri hvit
 *   - aktiv tilstand er kant + hevet flate, aldri glød
 */

* { box-sizing: border-box; }

html {
  background: var(--navy);
  /* iOS: hindrer at teksten skalerer om når telefonen snus. */
  -webkit-text-size-adjust: 100%;
  /*
   * ┌─────────────────────────────────────────────────────────────────────────┐
   * │ UTEN DENNE ER AVKRYSSINGSBOKSEN HVIT PÅ EN MASKIN MED LYST OS.          │
   * │                                                                         │
   * │ Nettleseren tegner selv det vi ikke tegner: avkryssingsbokser,          │
   * │ radioknapper, datovelgeren, nedtrekkslister, rullefelt. Hvilken farge   │
   * │ den bruker, avgjøres av `color-scheme` — ikke av at flata under er      │
   * │ mørk.                                                                   │
   * │                                                                         │
   * │ Ti av elleve skjermer hadde `<meta name="color-scheme" content="dark">` │
   * │ i hodet. FORSIDA hadde det ikke, og det er forsida som har              │
   * │ innloggingens «Hold meg innlogget». Målt i Chrome 21.08.2026 med        │
   * │ `prefers-color-scheme: light` emulert: uten både meta og denne regelen  │
   * │ er ruta HELHVIT på navy. Med denne regelen alene, uten meta i det hele  │
   * │ tatt, er den mørk. Utviklermaskinen står i mørk modus, så feilen var    │
   * │ usynlig her og synlig hos alle andre.                                   │
   * │                                                                         │
   * │ Regelen hører her, ikke i elleve hoder der ett manglet. De ti meta-     │
   * │ taggene er overflødige nå, men de er ikke i veien og er ikke ryddet.    │
   * └─────────────────────────────────────────────────────────────────────────┘
   */
  color-scheme: dark;

  /*
   * Alt som rulles til topps, skal lande UNDER topplinja.
   *
   * Linja er klebrig og 113 px høy på telefon. Uten dette lander et anker i
   * adressen, en `element.focus()` fra kravruta og nettleserens egen «finn på
   * siden» BAK den — man ser toppen av linja der treffet skulle vært, og tror
   * søket bommet. `--topp-h` holdes lik linjas ekte høyde av topp.js.
   */
  scroll-padding-top: calc(var(--topp-h) + var(--rom-2));
}

body {
  margin: 0;
  background: var(--navy);
  color: var(--offwhite);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  /*
   * ┌───────────────────────────────────────────────────────────────────────────┐
   * │ HAKKET HÅNDTERES AV TOPPLINJA, IKKE AV `body`.                            │
   * │                                                                           │
   * │ Her sto `padding-top: env(safe-area-inset-top)` og `padding-bottom:       │
   * │ env(safe-area-inset-bottom)` også. Det virket så lenge topplinja rullet   │
   * │ bort med resten — men en `position: sticky`-linje fester seg til          │
   * │ RULLEPORTEN, ikke til `body`s innerkant. Med marga her ville linja        │
   * │ krøpet opp UNDER hakket i det man begynte å rulle, i stedet for å legge   │
   * │ seg pent under det. Marga hører derfor i `.topp`, som er den som faktisk  │
   * │ ligger der oppe.                                                          │
   * │                                                                           │
   * │ Bunnen på samme vis: `.wrap` bærer `env(safe-area-inset-bottom)` i sin    │
   * │ egen bunnmarg, og hvert `position: fixed`-element bærer sin. Sidene som   │
   * │ ikke har `.wrap` — innloggingen — er midtstilte og rører ikke kanten.     │
   * │                                                                           │
   * │ Venstre og høyre blir stående: de gjelder liggende telefon, der hakket    │
   * │ spiser av SIDEN, og der er det `body` som er riktig sted.                 │
   * └───────────────────────────────────────────────────────────────────────────┘
   */
  padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 600; line-height: 1.25; margin: 0; }
h1 { font-size: 22px; }
h2 { font-size: 18px; }
h3 { font-size: 16px; }

a { color: var(--ice); }

:focus-visible { outline: 2px solid var(--ice); outline-offset: 2px; }

/* ── Sidecontaineren ───────────────────────────────────────────────────────
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ `.wrap` VAR DEFINERT I TRETTEN FILER, MED SEKS ULIKE SVAR.                │
 * │                                                                           │
 * │ Talt 10.09.2026: hub.css sa `34px 22px 80px`, panel.css `14px 12px 56px`  │
 * │ på telefon, ringeliste.css `16px`, og de ni andre `20px 16px 64px` — med  │
 * │ maksbredder på 680, 760, 780, 820, 940. Ingen av forskjellene var          │
 * │ bestemt; de var arvet fra rekkefølgen filene ble skrevet i.               │
 * │                                                                           │
 * │ På telefon betyr det at innholdet HOPPER SIDELENGS når man bytter side:   │
 * │ 22 px marg på forsida, 16 i kundelista, 12 i panelet. Det er nøyaktig det │
 * │ som gjør at en app kjennes uferdig uten at man klarer å peke på hvorfor.  │
 * │                                                                           │
 * │ Nå står formen her, og en flate sier bare hvor bred den vil være:         │
 * │                                                                           │
 * │   .wrap { --wrap-maks: 680px; }                                           │
 * │                                                                           │
 * │ Bunnmargen bærer `env(safe-area-inset-bottom)` i tillegg til luft, så det │
 * │ siste kortet ikke ender under hjemindikatoren på iPhone.                  │
 * └───────────────────────────────────────────────────────────────────────────┘ */
.wrap {
  width: 100%;
  max-width: var(--wrap-maks, 760px);
  margin: 0 auto;
  padding: var(--rom-5) var(--marg) calc(var(--bunn) + env(safe-area-inset-bottom));
  display: grid;
  gap: var(--stabel);
  /* Innholdet skal bli høyere av lang tekst, aldri bredere. Uten denne kan et
     rutenett-barn med lang, ubrytelig tekst presse hele sida sidelengs. */
  min-width: 0;
}

/* ── Ikoner ────────────────────────────────────────────────────────────── */
.ikn {
  width: 1em; height: 1em;
  vertical-align: -0.125em;
  color: var(--ice);
  flex: none;
}

/* ── Kort ──────────────────────────────────────────────────────────────── */
.kort {
  background: var(--navy2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--elev-card);
  padding: var(--rom-4);
}

/*
 * Under 360 px er kromlaget for tykt.
 *
 * Regnet på 320: 14 px sidemarg + 16 px kortluft = 30 px per side før kortet
 * har ett tegn innhold — 60 av 320, altså 19 % av linja. Et kort inne i et
 * kort (løypa, kundeflatene) dobler det. 12 px her tar 8 px tilbake til
 * teksten uten at kortet slutter å være et kort.
 */
@media (max-width: 360px) {
  .kort { padding: var(--rom-3); }
}

/* ── Knapper ───────────────────────────────────────────────────────────── */
.knapp {
  min-height: var(--trykk);
  padding: 10px 18px;
  border-radius: var(--r-btn);
  border: 1px solid var(--border-strong);
  background: var(--fill-subtle);
  color: var(--offwhite);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* Hindrer at iOS zoomer inn ved dobbelttrykk. */
  touch-action: manipulation;
}
.knapp:hover { border-color: var(--border-hover); background: var(--navy3); }
.knapp:active { transform: scale(.985); }

/*
 * En knapp som er en LENKE, skal ikke være understreket.
 *
 * `a { color: var(--ice) }` lenger oppe gir hver `<a>` nettleserens understrek
 * i tillegg. Det spiller ingen rolle før noe som SER ut som en knapp er en
 * lenke — og det er den riktige semantikken hver gang knappen fører et sted:
 * «Ring og registrer samtale» i ringelista, `#til-kunde` i onboardingen og
 * `#prat-hel` på forsida. Alle tre sto med strek under teksten.
 *
 * Regelen hører HER og ikke i tre sideark. Ringelista hadde alt begynt på sin
 * egen `.ark-kort a.knapp`-utgave, og to av de tre andre ville blitt glemt —
 * det er nøyaktig mønsteret `topplinje.test.ts` finnes for.
 */
a.knapp { text-decoration: none; }

.knapp.primar {
  background: var(--ice);
  color: var(--navy);      /* ALDRI hvit tekst på is */
  font-weight: 700;
  border-color: transparent;
}

/*
 * Knappen som fjerner noe.
 *
 * RAMME OG TEKST, ikke fylt rødt. En fylt rød flate er en ALARM — «noe er
 * galt» — og det er ikke det som skjer her: brukeren er i ferd med å gjøre noe
 * med vilje. Fylt rødt ville dessuten konkurrert med `.pille.feil` og
 * `.status.feil`, som faktisk melder feil, om den samme betydningen.
 *
 * `--bad-text` på teksten og `--bad` på kanten, ikke omvendt: den røde er MÅLT
 * til 4,21:1 på tonet rødt og ryker AA. Kanten trenger ikke bestå den grensa,
 * teksten må. Samme fordeling som feilmeldingene ellers i huben.
 *
 * Bruk den bare på trykket som TAR NOE BORT. «Aktiver brukeren» gir tilgang
 * tilbake og skal ikke være rød — en farge som brukes på begge, betyr ingenting.
 *
 * Regelen sto HÅNDSKREVET TO STEDER — `admin.css` og `kundesider.css`, ord for
 * ord like — og en tredje kopi var på vei inn i `moter.css` da slett-knappen
 * kom 28.08.2026. Det er nøyaktig mønsteret som tok `.ikn`-fargen og
 * plassholderfargen: en regel som bor i sidearkene, gjelder de sidene noen
 * husket. Nå bor den her, og de to kopiene er fjernet.
 */
.knapp.farlig { color: var(--bad-text); border-color: var(--bad); }
.knapp.farlig:hover { background: var(--navy3); border-color: var(--bad); }
/*
 * Ikonet må følge TEKSTEN, ikke paletten.
 *
 * `.ikn` setter `color: var(--ice)` som standard, og en primærknapp har is som
 * BAKGRUNN. Uten denne linja tegnes ikonet i nøyaktig samme farge som flata det
 * ligger på, og forsvinner — knappen ser tom ut, og ingenting sier fra.
 *
 * Regelen var kjent: `.ring .ikn` i ringelista og `.valg .knapp.valgt .ikn` i
 * møtene gjør det samme, hver for seg. Den ble skrevet to ganger for hånd og
 * glemt to ganger — her og på chat-boblen, der den faktisk slo ut. Derfor
 * finnes `vakt_ikonfarge.test.ts`.
 */
.knapp.primar .ikn { color: var(--navy); }

.knapp.primar:hover { background: var(--ice-light); }

.knapp[disabled] {
  opacity: .5;
  cursor: not-allowed;
  /* Med vilje IKKE pointer-events:none. I 1.0 nådde klikket aldri fram til noe
     som kunne forklart hvorfor knappen var grå — den bare satt der. */
}

/* ── Skjemafelter ──────────────────────────────────────────────────────── */
/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ EN `input`-REGEL UTEN UNNTAK TREFFER OGSÅ AVKRYSSINGSBOKSEN.              │
 * │                                                                           │
 * │ Onboardingsiden hadde `input, textarea { width:100%; min-height:          │
 * │ var(--trykk) }` for seg selv. Riktig for et tekstfelt, ødeleggende for    │
 * │ en sjekkboks: «Kontrakten er signert» ble en grå firkant på 44 × 44 px    │
 * │ midt i raden, teksten ble dyttet ut til høyre og brutt over to linjer,    │
 * │ og de to boksene sto ikke engang på linje med hverandre. Chipsene under   │
 * │ «Hva vi leverer» sprakk på samme vis — «SMS-oppfølging» sprengte pillen   │
 * │ sin. Kontraktsiden hadde nøyaktig samme feil gjennom                      │
 * │ `.felt-rutenett input`. Sett på skjermen 21.08.2026; i koden så begge     │
 * │ reglene helt fornuftige ut.                                               │
 * │                                                                           │
 * │ Derfor står unntaket i VELGEREN, ikke som en overstyring under. En        │
 * │ overstyring virker bare der noen husker å skrive den; en velger som ikke  │
 * │ treffer, kan ikke glemmes på neste flate. `vakt_skjema` holder på begge   │
 * │ deler: at regelen bor her, og at den slipper sjekkboksene forbi.          │
 * │                                                                           │
 * │ `:not(a, b)` og ikke `:not(a):not(b)` — med vilje. Listeformen arver      │
 * │ spesifisiteten til ETT argument, så velgeren blir (0,1,1). Kjedeformen    │
 * │ ville gitt (0,2,1) og dermed slått en sideregel som `.rett input` uansett │
 * │ hvilken rekkefølge stilarkene lastes i. Da flytter man feilen i stedet    │
 * │ for å fjerne den.                                                         │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
label {
  display: block;
  margin-bottom: 4px;
  font-size: 14px;
  color: var(--silver);
}

input:not([type="checkbox"], [type="radio"]),
textarea,
select {
  width: 100%;
  min-height: var(--trykk);
  padding: 10px 12px;
  border-radius: var(--r-btn);
  /*
   * `--kontroll-kant`, ikke `--border-strong`. Målt 10.09.2026: kanten på et
   * skjemafelt var 1,23:1 mot kortet det ligger i, mot kravet 3:1 i WCAG
   * 1.4.11 for grensa rundt en kontroll. Et TOMT felt var dermed nesten
   * usynlig — man så en tekst og en flate, ikke noe å skrive i. Utendørs på
   * en telefon er det forskjellen på å finne feltet og ikke. Begrunnelsen for
   * tallet står i tema.css.
   */
  border: 1px solid var(--kontroll-kant);
  background: var(--navy);
  color: var(--offwhite);
  font: inherit;
  /* 16px: alt under dette får iOS til å zoome inn når feltet får fokus. */
  font-size: 16px;
}

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ KALENDERIKONET ER DEN ENESTE VEIEN INN I VELGEREN — OG DET VAR 15 PX.    │
 * │                                                                           │
 * │ Resten av et `date`- eller `datetime-local`-felt skriver man i, ett       │
 * │ siffer om gangen i DD/MM/ÅÅÅÅ. Vil man ha kalenderen, er ikonet til       │
 * │ høyre det eneste målet — og nettleseren tegner det 15 × 15 px. Målt i     │
 * │ Chrome 10.09.2026 på «Utsett» i møtekortet: 11,5 × 13,5 px. Kravet er     │
 * │ 44, og dette er den kontrollen på hele flata som er vanskeligst å treffe. │
 * │                                                                           │
 * │ Flata blir 44 px av padding, og de negative margene tar paddingen ut      │
 * │ igjen av oppsettet — så ikonet står nøyaktig der det sto, mens flata      │
 * │ rundt det er fire ganger så stor. Ingen ny form, ingen ny farge.          │
 * │                                                                           │
 * │ På iOS gjør Safari dette selv: hele feltet åpner hjulet, og velgeren      │
 * │ finnes ikke som eget element. Regelen er derfor for Chrome, Android og    │
 * │ skrivebordet — der den ER problemet.                                      │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator,
input[type="month"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
  /*
   * `var(--trykk)` er HELE boksen, ikke ikonet. `* { box-sizing: border-box }`
   * står øverst i fila, så paddingen spises innenfra: 44 px boks minus 2 × 12
   * px padding gir et 20 px ikon midt i en 44 px flate. Skrev man i stedet
   * `width: 20px; padding: 12px`, ville border-box klemt ikonet til NULL —
   * og vakta som fanget nettopp det, hadde rett.
   *
   * De negative margene tar mesteparten av veksten ut igjen av oppsettet, så
   * ikonet står omtrent der det sto. Feltet har 10 px egen padding og tåler
   * resten.
   */
  width: var(--trykk); height: var(--trykk);
  padding: 12px;
  margin-block: -12px;
  margin-right: -6px;
  cursor: pointer;
}

/* Høyden kommer fra `rows`, ikke herfra. Et skrivefelt på én linje og et
   referatfelt på åtte skal ikke tvinges til samme mål. */
textarea { resize: vertical; line-height: 1.5; }

/*
 * Hjelpeteksten skal LESES som en hjelpetekst.
 *
 * Uten denne arver plassholderen nettleserens egen grå, som på kald navy er
 * nesten umulig å skille fra ekte skrevet tekst — og et felt som ser utfylt ut
 * uten å være det, sendes tomt. Regelen fantes ETT sted i hele hub2,
 * `.sok-rad input::placeholder` i ringelista, og gjaldt dermed ett av rundt
 * seksti felter.
 */
::placeholder { color: var(--muted); opacity: 1; }

/*
 * Et søkefelt er rundt. Et utfyllingsfelt er det ikke.
 *
 * Formen skiller «skriv for å lete» fra «skriv for å lagre», og den hører til
 * feltets TYPE, ikke til siden det står på. Sto som `.sok-rad input` i
 * ringelista — riktig utseende, feil sted: neste søkefelt et annet sted ville
 * blitt firkantet, og forskjellen ville ingen kunnet begrunne.
 */
input[type="search"] { border-radius: var(--r-pill); }

/*
 * Ruta er 18 px. TRYKKFLATA er `label.avkryss` under — 44 px høy, og hele
 * raden er klikkbar fordi etiketten omslutter både ruta og teksten. Ei rute på
 * 44 px er ikke en trykkflate, det er nettopp feilen vi kom fra.
 */
input[type="checkbox"],
input[type="radio"] {
  /*
   * TEGNET SELV, ikke nettleserens egen.
   *
   * `accent-color` farger bare HAKEN. Den tomme ruta ble stående som Chromes
   * nøytralgrå firkant — som på kald navy leses som en deaktivert kontroll, og
   * ikke som noe man skal trykke på. Med 27 løypepunkter under hverandre er
   * det 27 grå firkanter, og flata ser uferdig ut.
   *
   * Flata er `--navy`, haken `--navy` på `--ice` — samme par som primærknappen
   * bruker, og samme grunn (ALDRI hvit tekst på is). Radius er `--r-sm` for
   * avkryssing og full sirkel for radio.
   *
   * RAMMA er `--kontroll-kant`, ikke `--border-strong` som resten av feltene.
   * Her sto det at «ingen nye verdier» var en dyd — og det var feil dyd:
   * målt 10.09.2026 var den tomme ruta 1,23:1 mot kortflata, mot kravet 3:1
   * for en kontrollgrense. En kortkant skal så vidt anes; en rute man skal
   * treffe med tommelen skal ses. Begrunnelsen for tallet står i tema.css.
   *
   * `appearance: none` slår av nettleserens egen tegning. Da forsvinner OGSÅ
   * haken, så den må tegnes — her som to kanter rotert 45 grader, ikke som et
   * ikon: ikonsettet er strekikoner i `currentColor`, og en hake inni en
   * 18 px rute er en form, ikke et ikon.
   */
  appearance: none;
  -webkit-appearance: none;
  width: 18px; height: 18px;
  margin: 0;
  flex: none;              /* i en flex-rad presses den ellers til en strek */
  position: relative;
  border: 1.5px solid var(--kontroll-kant);
  border-radius: var(--r-rute);
  background: var(--navy);
  transition: background-color .12s ease, border-color .12s ease;
  cursor: pointer;
}

input[type="radio"] { border-radius: 50%; }

input[type="checkbox"]:hover,
input[type="radio"]:hover { border-color: var(--border-hover); }

input[type="checkbox"]:checked,
input[type="radio"]:checked {
  background: var(--ice);
  border-color: var(--ice);
}

/* Haken: to kanter i hjørnet, rotert. Navy på is — aldri hvit på is. */
input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px; top: 1px;
  width: 4px; height: 9px;
  border: solid var(--navy);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

input[type="radio"]:checked::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--navy);
}

/* En deaktivert rute skal se deaktivert ut, ikke bare føles det. */
input[type="checkbox"]:disabled,
input[type="radio"]:disabled { opacity: .5; cursor: not-allowed; }

/*
 * Feltet som IKKE skal ha en boks, fordi flata rundt det alt har en.
 *
 * Søkefeltet i topplinja er den ene i dag: `.topp-sok` har kant, bakgrunn og
 * 14 px luft, og lupa står til venstre for feltet. Uten dette får den boks
 * inni boks — 12 px ekstra innrykk som skyver skrivemerket vekk fra lupa, og
 * en ramme rundt en ramme. Modifikatoren hører HER og ikke i et sideark, fordi
 * det er base.css som maler hvert eneste felt; den som maler, må også kunne
 * la være.
 *
 * ELEMENTNAVNET MÅ STÅ I VELGEREN. `.felt-naken` alene er (0,1,0) og taper mot
 * feltregelen over, som er (0,1,1) — klassen så helt riktig ut i koden og
 * gjorde ingenting på skjermen. Sett i den gamle ⌘K-ruta 21.08.2026: boks inni
 * boks, akkurat den feilen klassen finnes for å hindre.
 */
input.felt-naken, textarea.felt-naken, select.felt-naken {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}

.avkryss {
  /*
   * `flex-start`, ikke `center`.
   *
   * Med `center` sto den 18 px høye ruta LODDRETT MIDT i raden. Så lenge
   * etiketten er én linje er det riktig — men «Databehandleravtalen er
   * signert» brekker til to linjer på 320 px, og da havnet ruta i luftgapet
   * MELLOM linjene og så ut til å høre til ingen av dem.
   *
   * `padding` på 11 px holder trykkflata over 44 px uten at `min-height`
   * binder: 11 + 23 (én tekstlinje) + 11 = 45. Ruta står da i flukt med
   * første linje uansett hvor mange linjer etiketten har.
   */
  display: flex; align-items: flex-start; gap: 9px;
  min-height: var(--trykk);
  padding: 11px 0;
  margin: 0;
  color: var(--offwhite);
  font-size: 15px;
  cursor: pointer;
}

/*
 * MÅ dekke `select` og `textarea` også, ikke bare `input`.
 *
 * Feilmeldingene sier «se hva som er merket rødt i skjemaet». Sto regelen bare
 * på `input`, ble rollefeltet i admin merket i koden uten å bli rødt på
 * skjermen — og da peker meldinga på noe som ikke finnes. Sett i nettleseren
 * 18.08.2026.
 */
input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] { border-color: var(--bad); }

/* Et sperret felt skal SE sperret ut. Dempet TEKST, ikke dempet felt:
   `opacity` tar kanten med seg, og da ser feltet ut som om det mangler. */
input:disabled, textarea:disabled, select:disabled {
  color: var(--muted);
  cursor: not-allowed;
}

/* ── Piller ────────────────────────────────────────────────────────────── */
.pille {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  font-size: 13px; font-weight: 500;
  background: var(--fill-subtle);
  border: 1px solid var(--border);
  color: var(--silver);
  /*
   * `nowrap` er riktig for det en pille ER — «Signert», «2 av 2», «Ikke ringt».
   * Men klassen brukes også på tekst som ikke er en pille: kundekortet legger
   * hele varselsetningen «Står som signert, men uten dato — bindingen kan ikke
   * regnes» (58 tegn, målt ~394 px) i en, og admin legger et brukernavn på
   * inntil 32 tegn i en. Uten et tak dytter da HELE SIDA sidelengs: målt 42 px
   * vannrett overflyt på 320 px 10.09.2026.
   *
   * Taket er en sikring, ikke en løsning: en pille som blir avkuttet er et
   * tegn på at teksten aldri skulle vært en pille. Men en avkuttet pille er
   * langt bedre enn en side som ruller sidelengs, og den er synlig — så feilen
   * blir funnet i stedet for å bli tilvent.
   */
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pille.is    { background: var(--ice-bg);                 color: var(--ice);      border-color: transparent; }
.pille.ok    { background: var(--green-svak);             color: var(--green);    border-color: transparent; }
.pille.varsel{ background: var(--warn-svak);              color: var(--warn);     border-color: transparent; }
.pille.feil  { background: var(--bad-svak);               color: var(--bad-text); border-color: transparent; }

/* ── Statuslinje ───────────────────────────────────────────────────────── */
/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ EN TOM KVITTERINGSLINJE SKAL TA NULL PLASS.                              │
 * │                                                                           │
 * │ `.status` brukes som `<p>` over hele huben — «Lagret», «Fikk ikke         │
 * │ kontakt», og oftest ingenting. Regelen satte bare farge og størrelse, så  │
 * │ elementet bar nettleserens egen `margin: 1em 0` = 32 px, OGSÅ når det var │
 * │ tomt. Målt 10.09.2026: admin har seks slike og kastet bort 84 px i        │
 * │ panelet; kundekortets topp ble 142,5 px høyt for et navn, en undertittel  │
 * │ og tre piller.                                                            │
 * │                                                                           │
 * │ `margin: 0` og en `gap` fra forelderen i stedet: da bestemmer den som     │
 * │ eier layouten avstanden, og en tom linje koster ingenting. `:empty`       │
 * │ tar den helt ut av flyten — i et rutenett teller et tomt barn fortsatt    │
 * │ som en rad, og to gap rundt ingenting er to gap for mye.                  │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
/*
 * `overflow-wrap: anywhere` fordi en feilmelding ikke alltid er pen norsk
 * prosa. `server/fiken.ts` sender inntil 200 tegn RÅ serverkropp inn i `hva`
 * («Fiken svarte noe som ikke er JSON: …»), og en URL eller en JSON-bit uten
 * mellomrom sprenger containeren sin og skyver hele sida sidelengs.
 */
.status { margin: 0; font-size: 14px; color: var(--silver); overflow-wrap: anywhere; }
.status:empty { display: none; }
.status.feil { color: var(--bad-text); }

/* ── Bolken man lander i fra et forsidevarsel ──────────────────────────── */
/*
 * Tegnes av `felles/avvik.js` på fire skjermer — ringelista, kunder, møter og
 * økonomi. Stilen hører HER og ikke i fire stilark, av samme grunn som koden
 * bor i én fil: fire kopier blir uenige, og den ene som ble glemt ser ut som
 * en halvferdig side.
 *
 * Bolken legges OPPÅ skjermens egen liste. Den skiller seg fra kortene rundt
 * med en is-kant til venstre — samme språk som forsidevarselet man kom fra,
 * uten å bruke rødt: her er man alt framme, og da haster ingenting mer.
 */
.avvikbolk {
  /*
   * Ingen bunnmarg. Bolken er direkte barn av `.wrap`, som er `display: grid`
   * med `gap: var(--stabel)` — og marger kollapser ikke i grid. 20 px marg
   * oppå 16 px gap ga 36 px under nettopp den bolken man kom for å se, og
   * ingen andre steder på sida.
   */
  margin: 0;
  padding: 14px 16px;
  background: var(--navy2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--ice);
  border-radius: var(--r-md);
}
.avvikbolk-tittel {
  margin: 0 0 4px;
  font-family: var(--font-display); font-weight: 600;
  font-size: 15px; color: var(--offwhite);
}
.avvikrader { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.avvikrad {
  width: 100%;
  min-height: var(--trykk);
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--fill-subtle);
  color: var(--offwhite);
  font: inherit; text-align: left;
  cursor: pointer;
  touch-action: manipulation;
}
.avvikrad:hover, .avvikrad:active { background: var(--navy3); border-color: var(--border-hover); }
.avvikrad .ikn { margin-left: auto; width: 15px; height: 15px; }
.avvikrad-midt { display: grid; gap: 2px; min-width: 0; }
.avvikrad-navn { font-weight: 600; font-size: 15px; }
.avvikrad-hva { font-size: 13px; color: var(--silver); line-height: 1.4; }

/* ── Tomme lister ──────────────────────────────────────────────────────── */
/* En tom liste skal se ut som en tom liste, aldri som en feil. */
.tomt {
  padding: 28px 20px;
  text-align: center;
  color: var(--silver);
  font-size: 15px;
  /*
   * Midtstilt er riktig for ÉN linje og feil for fire: da har hver linje sin
   * egen venstrekant, og øyet mister starten på neste. Flere av tomtekstene i
   * huben er to til fire linjer på 390 px («Ingen sider lagt inn. Legger du inn
   * nettsida og kontrollpanelet her, måles de hver time.»). Taket på 38 tegn
   * holder linjene korte nok til at midtstillingen fortsatt leses.
   */
  max-width: 38ch;
  margin-inline: auto;
  /* Samme grunn som på `.status`: flere flater skriver en feilmelding hit når
     lista ikke kunne hentes, og en rå serverstreng har ingen mellomrom. */
  overflow-wrap: anywhere;
}

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ TOMHETEN SOM ER HELE SVARET, SKAL SE UT SOM ET SVAR.                     │
 * │                                                                           │
 * │ `.tomt` alene er en løs setning midtstilt i luft. Det er riktig når den   │
 * │ står under en liste som ellers har innhold — panel.css skriver ned        │
 * │ hvorfor. Det er feil når den ER skjermen: målt på moter-320.png           │
 * │ 10.09.2026 lå «Ingen møter er avtalt ennå.» midt i ~180 px tomt felt,     │
 * │ uten ramme, uten ikon og uten noe å gjøre. Tre slike under hverandre på   │
 * │ samme side, og flata ser ut som den ikke er ferdig lastet.                │
 * │                                                                           │
 * │ `.figur` gir den en form: strekikon, setningen, og — når det finnes noe   │
 * │ fornuftig å gjøre — ÉN knapp. Stiplet ramme og ikke fylt kort: en stiplet │
 * │ ramme sier «her er det plass til noe», en fylt flate sier «her ER noe».   │
 * │ Forsida hadde sin egen utgave av nettopp denne formen, `.rolig` — den er  │
 * │ avviklet 11.09.2026, og `#avvik-rolig` bruker denne.                      │
 * │                                                                           │
 * │ Den er en VARIANT og ikke den nye standarden, med vilje. Tjueni steder    │
 * │ bruker `.tomt`, og de fleste av dem står under en liste der en ramme til  │
 * │ ville vært boks inni boks.                                                │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
.tomt.figur {
  display: grid; justify-items: center; gap: var(--rom-2);
  /*
   * `margin: 0` alene slo ut `margin-inline: auto` fra `.tomt` over, og da sto
   * den stiplede ramma VENSTRESTILT og ~13 px smalere enn kortet den ligger i
   * — målt på `#ingen` i kundelista, 390 px: boksen sluttet på 363 der
   * knappene over slutter på 374. Figuren skal fylle kortet sitt; det er
   * SETNINGEN inni som har lesebredde, ikke ramma.
   */
  margin: 0 auto;
  max-width: none;
  padding: var(--rom-5) var(--rom-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  font-size: 14.5px; line-height: 1.45;
}
.tomt.figur .ikn { width: 22px; height: 22px; color: var(--muted); }
/* Setningen skal kunne stå på to linjer uten å bli bredere enn den er lesbar. */
.tomt.figur .tomt-tekst { max-width: 34ch; }
.tomt.figur .knapp { margin-top: var(--rom-1); }

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ EN TOM LISTE INNE I ET KORT ER IKKE HELE SKJERMENS SVAR.                 │
 * │                                                                           │
 * │ `.tomt` er 28 px luft over og under, midtstilt. Det er riktig når         │
 * │ tomheten ER sida. Står den derimot i et kort som allerede har en          │
 * │ venstrestilt overskrift og sitt eget krom, blir «Ingen åpne innlogginger» │
 * │ en 80 px høy midtstilt blokk under en 22 px venstrestilt tittel — og et   │
 * │ tomt kort blir like høyt som et fullt. Målt 10.09.2026 av tre agenter    │
 * │ uavhengig av hverandre, på admin, økonomi og panelet.                     │
 * │                                                                           │
 * │ `:not(:only-child)` er hele skillet, og det er en ren avlesning av        │
 * │ virkeligheten: er setningen kortets ENESTE barn, er kortet tomt og        │
 * │ teksten er svaret. Har kortet en overskrift eller en liste ved siden av,  │
 * │ er setningen en fotnote til noe annet.                                    │
 * │                                                                           │
 * │ `panel.css` har hatt sin egen utgave av dette siden 23.08.2026, scopet   │
 * │ til `.brett .liste + .tomt`. Den blir stående — den er SNEVRERE enn       │
 * │ denne, og treffer et tilfelle denne ikke gjør (tom liste, ikke tomt kort).│
 * └───────────────────────────────────────────────────────────────────────────┘
 */
/*
 * En FEILMELDING i `.tomt` er ikke en tom tilstand.
 *
 * Flere flater skriver `${f.hva} ${f.hva_na}` inn i det samme elementet når
 * lista ikke kunne hentes. Da er teksten to setninger, ikke tre ord, og både
 * midtstillingen og lesebredden på 38 tegn er feil form for den. `.feil`
 * finnes fra før i admin.css og gir den ramme og rød tekst; her får den
 * bredden tilbake.
 */
.tomt.feil { max-width: none; margin-inline: 0; text-align: left; }

.kort > .tomt:not(.figur):not(:only-child),
.brett > .tomt:not(.figur):not(:only-child) {
  padding: var(--rom-3) 0 var(--rom-1);
  margin-inline: 0;
  max-width: none;
  text-align: left;
  font-size: 14px;
}

/* ── Lastetilstand ─────────────────────────────────────────────────────────
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ FØRSTE TEGNING VAR OVERSKRIFTER UTEN KROPP.                              │
 * │                                                                           │
 * │ Elleve flater henter ved sidelast, og ingen av dem sa fra at de holdt på. │
 * │ Fram til svaret landet sto sida med sine overskrifter og INGENTING under  │
 * │ — og så vokste den i ett hopp. Målt på panelet 10.09.2026: fra ti tomme   │
 * │ brett til 4 521 px i ett sprang. På 4G er det et par sekunder der flata   │
 * │ ser ut som den er tom, ikke som den laster.                               │
 * │                                                                           │
 * │ Et skjelett løser TO ting på én gang: det sier at noe er på vei, og det   │
 * │ RESERVERER høyden, så innholdet ikke dytter noe nedover når det kommer.   │
 * │ Det andre er det viktigste — en side som hopper mens man sikter på en     │
 * │ knapp, er verre enn en som er treg.                                       │
 * │                                                                           │
 * │ Formen er en flate i `--fill-subtle`, ikke et glimt som løper over. Et    │
 * │ løpende glimt er en gradient, og PALETT.md sier ingen gradient-fyll og    │
 * │ ingen glød. Pulsen er `opacity` alene — den eneste egenskapen som ikke    │
 * │ koster en ny layout — og den står stille for den som har bedt om mindre   │
 * │ bevegelse.                                                                │
 * └───────────────────────────────────────────────────────────────────────────┘ */
.skjelett {
  display: block;
  border-radius: var(--r-sm);
  background: var(--fill-subtle);
  /* Et skjelett er ikke tekst: det skal ikke kunne merkes med fingeren. */
  user-select: none;
  animation: skjelett 1.2s ease-in-out infinite;
}
/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ VARIANTENE ER PREFIKSET — FORDI `tall` OG `rad` ALT ER TATT.             │
 * │                                                                           │
 * │ Variantene sto som `.skjelett.tall` og `.skjelett.rad`. Begge ordene er   │
 * │ vanlige klassenavn som ALT finnes i huben: `.tall` er et rutenett med tre │
 * │ kolonner i ringelista og et auto-fit-rutenett i panelet, og `.rad` er en  │
 * │ køerad i ringelista. Et skjelett skrevet som `class="skjelett tall"` inne │
 * │ i panelet arvet dermed panelets eget rutenett, og plassholderen fikk en   │
 * │ form ingen hadde bestemt. Meldt av en agent 11.09.2026 før det rakk å bli │
 * │ en feil noen måtte lete etter.                                            │
 * │                                                                           │
 * │ `sk-` er derfor prefikset, og `.skjelett` blir stående som KROKEN: rundt  │
 * │ førti regler i sidearkene henger på den (`.moter li.skjelett`,            │
 * │ `.brukere li.skjelett`, `.rader li.skjelett` …) for å nulle kortdrakta og │
 * │ sette en høyde som er MÅLT mot det ekte innholdet. Prefikset løser        │
 * │ kollisjonen uten å rive opp det laget. hub.css brukte alt `sk-hei` og     │
 * │ `sk-dagslinje` — konvensjonen fantes, den var bare ikke tatt i bruk her.  │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
.skjelett.sk-linje { height: 1em; }
.skjelett.sk-tall  { height: 28px; width: 4.5ch; }
.skjelett.sk-rad   { height: var(--trykk); border-radius: var(--r-md); }

@keyframes skjelett { 50% { opacity: .45; } }

/*
 * Den som har bedt om mindre bevegelse, får en stille flate. Ikke usynlig —
 * da hadde skjelettet sluttet å si at noe er på vei.
 */
@media (prefers-reduced-motion: reduce) {
  .skjelett { animation: none; opacity: .7; }
}

/* Markøren sier det samme som skjelettet, for den som bruker mus. */
[aria-busy="true"] { cursor: progress; }

/* ── Ting du må gjøre ──────────────────────────────────────────────────────
   ┌───────────────────────────────────────────────────────────────────────────┐
   │ DEN ENESTE RUTA I HUBEN UTEN LUKKEKNAPP.                                  │
   │                                                                           │
   │ Formen bor her og ikke i tolv sideark, av samme grunn som topplinja:      │
   │ tegnes den av `felles/krav.js` på hver eneste flate, kan den ikke ha       │
   │ tolv utgaver. Den skal se ut som at den alltid har hørt hjemme — samme     │
   │ radius, samme flate, samme skygge og samme knappehierarki som `.kort` og   │
   │ resten av huben.                                                          │
   │                                                                           │
   │ ALVORET LIGGER I VENSTREKANTEN, ikke i tekstfargen — nøyaktig som          │
   │ `.varsler div` på kundekortet og `.avvikbolk` over. Gul, ikke rød: dette   │
   │ er noe som skal fylles ut, ikke noe som har gått galt.                     │
   │                                                                           │
   │ Ingen glød, ingen gradient, ingen frostet flate. `.krav` er solid          │
   │ `--navy2` og skiller seg fra sida med `--scrim` bak seg, som alle andre    │
   │ overlegg her.                                                             │
   └───────────────────────────────────────────────────────────────────────────┘ */
.krav {
  width: min(560px, calc(100vw - 24px));
  /*
   * Tastaturet trekkes fra høyden, og hakket med.
   *
   * Et modalt `<dialog>` ligger i top layer med `position: fixed; inset: 0`
   * fra nettleserens eget stilark, og arver derfor IKKE `body`-paddingen.
   * `100dvh` er dessuten den layoutbaserte høyden — den krymper ikke for
   * tastaturet på iOS. Ruta har felter i seg («Hva mangler»-skjemaene), så
   * uten `--tastatur` blir nederste halvdel liggende bak tastaturet i det man
   * begynner å skrive. Se klient/felles/tastatur.js.
   */
  max-height: calc(100dvh - 40px - var(--tastatur) - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  margin: auto;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--navy2);
  color: var(--offwhite);
  box-shadow: var(--elev-card);
  /* Et `<dialog>` er `display:none` når det er lukket. Skrives `display` uten
     `[open]`, står ruta framme fra første tegning — samme felle som `.prat`
     og `.nyark` alt har skrevet ned. */
  display: none;
  overflow: auto;
}
.krav[open] { display: block; }
.krav::backdrop { background: var(--scrim); }

/*
 * Bakgrunnen skal ikke kunne rulles mens ruta står.
 *
 * `showModal()` gjør resten av dokumentet inert og fanger fokus, men det
 * stopper IKKE rullingen: bakgrunnen glir under overlegget når man drar på
 * telefon, og da ser det ut som at ruta flyter løs. Regelen står her, knyttet
 * til at ruta faktisk er åpen, så det ikke finnes en klasse noen må huske å
 * ta av igjen.
 */
/*
 * Sida bak et åpent overlegg skal ikke kunne rulle.
 *
 * Sto som `dialog.krav[open]` — ÉN klasse — og måtte derfor skrives på nytt
 * for `.visning` i kontrakt.css og `.prat`/`.nyark` andre steder. Et modalt
 * `<dialog>` er alltid det samme problemet, uansett hva det heter, så
 * velgeren er nå formen og ikke navnet. `:modal` treffer bare dialoger åpnet
 * med `showModal()`, altså nøyaktig de som HAR et bakteppe å låse bak seg.
 */
html:has(dialog:modal) { overflow: hidden; }

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ KØEN BAK ER 24 591 px. DRAR MAN PÅ SCRIMEN, ER PLASSEN BORTE.            │
 * │                                                                           │
 * │ `overscroll-behavior: contain` på `.ark-kort` hindrer at rullingen KJEDER │
 * │ seg videre til lista når kortet er på bunnen — men den gjør ingenting mot │
 * │ et drag på den mørke flata rundt kortet. Der ruller køen fritt, og når    │
 * │ arket lukkes står man et helt annet sted i lista enn der man ringte fra.  │
 * │                                                                           │
 * │ Samme regel og samme form som `.krav` bruker i base.css. Målt før og      │
 * │ etter på 390 px: rullet til 4 000, åpnet arket, lukket det — 4 000 begge  │
 * │ ganger. Låsen tar altså ikke plassen med seg, som var den eneste grunnen  │
 * │ til å la være.                                                            │
 * │                                                                           │
 * │ `:has()` og ikke en klasse på `<html>`: da finnes regelen ETT sted og kan │
 * │ ikke bli glemt av en kodevei som åpner arket uten å sette klassen. Begge  │
 * │ arkene her (`#kort` og `#ark`) er `.ark`, så begge er dekket.             │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
html:has(.ark:not([hidden])) { overflow: hidden; }

.krav-inn { display: grid; gap: 14px; padding: 18px; }

.krav-tittel {
  display: flex; align-items: center; gap: 9px;
  font-size: 20px; color: var(--offwhite);
}
/* Gul, som venstrekanten. `.ikn` er is som standard, og is her ville sagt
   «du er framme» — det er nettopp det man ikke er ennå. */
.krav-tittel .ikn { color: var(--warn); font-size: 20px; }

.krav-hvorfor { margin: -4px 0 0; font-size: 14px; color: var(--silver); line-height: 1.5; }

.krav-rader { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.krav-rad {
  display: grid; gap: 8px;
  padding: 13px 14px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--warn);
  border-radius: var(--r-sm);
  background: var(--navy);
}
/* Anbefalingene blokkerer ingenting, og skal ikke rope som om de gjorde det.
   Skrevet som en etterkommer av bolken og ikke som en egen klasse: hvert
   klassenavn her legges oppå tolv flaters egne stilark, og en kort klasse
   treffer noe som allerede finnes. `.rolig` gjorde nettopp det — forsida har
   en fra før, for «en rolig dag», med midtstilt tekst. */
.krav-anbefalt .krav-rad { border-left-color: var(--border-strong); }

.krav-radtopp { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.krav-navn { font-weight: 600; font-size: 15px; min-width: 0; overflow-wrap: anywhere; }

.krav-mangler { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.krav-mangler li { font-size: 14px; color: var(--silver); line-height: 1.45; }

/* Knappen tar sin egen bredde, ikke hele raden: en knapp i full bredde leses
   som «neste steg» og ikke som «gå hit og rett dette». */
.krav-rad .knapp { justify-self: start; max-width: 100%; }

.krav-anbefalt {
  display: grid; gap: 10px;
  border-top: 1px solid var(--border);
  padding-top: 14px;
}
.krav-anbefalt h3 { color: var(--offwhite); }
.krav-anbefalt .status { margin: -6px 0 0; }

/*
 * Telleren som blir stående når ruta er undertrykt på retteskjermen.
 *
 * Ingenting skal være helt borte fra skjermen så lenge noe er utestående.
 * Den er en ren melding, ikke en knapp: en knapp som åpnet ruta igjen ville
 * satt deg fast, siden ruta ikke lar seg lukke og du står på skjermen der
 * feltet skal fylles ut.
 *
 * Nede til VENSTRE, fordi assistentboblen på forsida står nede til høyre.
 * `env(safe-area-inset-bottom)` må stå her: `position:fixed` arver ikke den
 * marga `body` har fått mot hjemindikatoren på iPhone.
 */
.kravteller {
  position: fixed;
  left: var(--marg); bottom: calc(var(--rom-3) + env(safe-area-inset-bottom)); z-index: 4;
  margin: 0;
  max-width: min(340px, calc(100vw - 100px));
  display: flex; align-items: center; gap: 8px;
  padding: 9px 13px;
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--warn);
  border-radius: var(--r-btn);
  background: var(--navy2);
  color: var(--offwhite);
  box-shadow: var(--elev-card);
  font-size: 13.5px; line-height: 1.35;
  /* Den er en MELDING, aldri et mål. Uten dette spiser den trykket på det som
     ligger under den — og på 390 px er «det som ligger under» like gjerne
     «Lagre» nederst i et skjema. Målt på skjermbildet 25.08.2026: teksten
     brytes over to linjer der og dekker et felt på ~340 × 60 px. */
  pointer-events: none;
}
.kravteller .ikn { color: var(--warn); font-size: 16px; }

/*
 * Sida får plass til telleren under seg.
 *
 * Uten denne dekker den de nederste ~70 pikslene FOR GODT: man kan rulle så
 * langt man vil, og det siste innholdet kommer aldri fram fra under den. Sett
 * på skjermbildet av kundekortet på 390 px 25.08.2026, der den la seg oppå to
 * løypepunkter. `pointer-events: none` gjør at trykket går gjennom — men et
 * trykk hjelper lite på noe man ikke kan lese.
 */
body:has(> .kravteller) { padding-bottom: calc(78px + env(safe-area-inset-bottom)); }
body:has(> .kravteller) .versjonslinje { bottom: calc(78px + env(safe-area-inset-bottom)); }

/*
 * Versjonslinja og assistentboblen sto oppå hverandre på telefon.
 *
 * Kommentaren under linja sier «midtstilt nede, fordi venstre hjørne er
 * kravtellerens og høyre er assistentboblas» — og det stemmer på et
 * skrivebord. På 390 px er linja `min(420px, 100vw − 24px)` = 366 px bred og
 * midtstilt, altså fra 12 til 378 px, mens boblen står på 320–374. De to
 * overlapper med 54 px, og linja har `pointer-events: none` — så den legger
 * seg oppå boblen uten engang å ta trykket.
 *
 * Løftet gjelder bare der boblen FINNES (forsida). Å heve linja på alle tolv
 * flatene for én flates skyld ville flyttet en melding vekk fra kanten der den
 * hører hjemme.
 */
body:has(.boble-knapp) .versjonslinje { bottom: calc(84px + env(safe-area-inset-bottom)); }

/*
 * Linja som sier at fanen er eldre enn serveren.
 *
 * Den vises bare når omlastingen IKKE kan tas automatisk — noen skriver i et
 * felt, eller en dialog står åpen — og da må den kunne trykkes, i motsetning
 * til kravtelleren over: knappen ER handlingen. Midtstilt nede, fordi venstre
 * hjørne er kravtellerens og høyre er assistentboblas.
 * Se `sjekkVersjon()` i felles/api.js for når den finnes i det hele tatt.
 */
.versjonslinje {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  /*
   * Over kravtelleren, ikke oppå den. Begge sto på samme bunnkant, og
   * versjonslinja (z-index 6) skjulte telleren (4) mens telleren fortsatt
   * skjøv sida ned med sin egen bunnpolstring. Nå står linja EN tellerhøyde
   * høyere når begge finnes.
   */
  bottom: calc(var(--rom-3) + env(safe-area-inset-bottom)); z-index: 6;
  margin: 0;
  max-width: min(420px, calc(100vw - 2 * var(--marg)));
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px;
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--ice);
  border-radius: var(--r-btn);
  background: var(--navy2);
  color: var(--offwhite);
  box-shadow: var(--elev-card);
  font-size: 13.5px; line-height: 1.35;
}

/*
 * Feltet ruta sendte deg til.
 *
 * «/kunder?kunde=102&felt=kontakt_telefon» åpnet riktig kunde og gjorde
 * ingenting med feltet. Knappen sa «Fullfør informasjon» og lot deg lete
 * gjennom tolv felter i retteskjemaet og 27 løypepunkter.
 *
 * IS, ikke rødt — samme resonnement som `.avvikbolk`: her er man alt framme,
 * og da haster ingenting mer. Kant og hevet flate, aldri glød.
 *
 * Regelen hører HER og ikke i kunder.css: utseendet på et skjemafelt bor ett
 * sted, og `vakt_skjema` håndhever det. Åtte flater hadde funnet opp hver sin
 * feltstil før den vakta fantes, allerede uenige om radius, bakgrunn og
 * padding. Det er dessuten riktig sted uansett — lenka med `?felt=` kommer fra
 * kravmotoren, som gjelder alle flatene, ikke bare kundekortet.
 */
input.pekt-felt, textarea.pekt-felt {
  border-color: var(--ice);
  background: var(--navy3);
}

/* ── Skjult er skjult ──────────────────────────────────────────────────── */
/*
 * ┌─────────────────────────────────────────────────────────────────────────┐
 * │ `hidden` MÅ SLÅ ENHVER display-REGEL. DEN HØRER HER, ETT STED.          │
 * │                                                                         │
 * │ Nettleserens egen regel er `[hidden] { display: none }`, men den taper  │
 * │ mot en hvilken som helst forfatterregel med samme spesifisitet. Én      │
 * │ `.inn { display: grid }` er nok til at `element.hidden = true` ikke gjør │
 * │ noe som helst — og JavaScript-en ser ut til å virke, for egenskapen ER  │
 * │ satt.                                                                   │
 * │                                                                         │
 * │ Den slo til to steder uavhengig av hverandre før den ble skrevet her:   │
 * │ assistentens «KI-laget er av»-banner sto framme selv når nøkkelen var    │
 * │ på plass, og HUBEN viste innloggingsskjemaet oppå seg selv etter en     │
 * │ vellykket innlogging — 200 fra serveren, riktig svar fra `/api/meg`,    │
 * │ og likevel en skjerm som så ut som at ingenting skjedde. Begge ble      │
 * │ lappet lokalt i hver sin fil. Elleve skjermer bruker `hidden`; de ni    │
 * │ andre ventet bare på sin egen display-regel.                            │
 * │                                                                         │
 * │ Målt i nettleseren, ikke gjettet.                                       │
 * └─────────────────────────────────────────────────────────────────────────┘
 */
[hidden] { display: none !important; }

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/*
 * En overskrift som sier nøyaktig det samme som skiltet i topplinja.
 *
 * Bare på telefon, og bare for ØYET: `.sr` beholder den i dokumentet for
 * skjermleseren. Merket settes av `riggTittel()` i felles/topp.js, som
 * sammenligner teksten — ikke bare at det finnes en h1. Se begrunnelsen der.
 */
@media (max-width: 560px) {
  h1.dublett {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
}

/* ── Topplinja ───────────────────────────────────────────────────────────────
   ┌───────────────────────────────────────────────────────────────────────────┐
   │ DEN FANTES I TOLV KOPIER, OG DE HADDE SKILT LAG.                          │
   │                                                                           │
   │ Hver flate hadde sin egen `.topp`, `.merke` og `.topp-hoyre` i sitt eget   │
   │ stilark. Huben ga linja 14px luft, kundesida 12px — så den flyttet seg     │
   │ litt hver gang man byttet side. Phillip 23.08.2026: «den topp linja er     │
   │ drit stygg nå».                                                           │
   │                                                                           │
   │ TO TING HAN BA OM, OG HVA DE BETYR:                                       │
   │                                                                           │
   │ «ikke hele navnet, bare den hvite logoen vår» — navnet sto som TEKST i to  │
   │ `<span>`-er. Nå står merket, `felles/merke.png`, klippet ut av den hvite   │
   │ logoen. Hvit på gjennomsiktig, så den bærer navy uten en egen utgave.      │
   │                                                                           │
   │ «bruk bare ikoner i topplinje ikke HUB» — ordknappene er borte. Og merket  │
   │ ER hub-lenka, så «Hub»-knappen trengs ikke i det hele tatt: den var en     │
   │ knapp for å komme dit logoen allerede peker.                              │
   │                                                                           │
   │ IDENTITETEN BLE STÅENDE, som en initialskive og ikke som en tekstknapp.    │
   │ To brukere ser ULIKE data — `selger` får felter maskert bort — og «hvem    │
   │ er jeg logget inn som» må kunne leses på et blikk, ellers feilsøker man    │
   │ en manglende kolonne som en feil.                                         │
   └───────────────────────────────────────────────────────────────────────────┘

   Målt i nettleser: ikon i hvile 6,78:1 mot navy, ved peking 15,47:1,
   initialene 11,44:1 mot skiva. Trykkflatene er 44×44. */

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ LINJA BLIR STÅENDE NÅR MAN RULLER.                                        │
 * │                                                                           │
 * │ Ringelista har 445 rader. Rullet man til nummer 200 og ville søke, gå     │
 * │ tilbake eller hjem, måtte man først rulle 200 rader opp igjen — søket,    │
 * │ tilbakepila og hjemknappen lå i en linje som var borte. På skrivebordet   │
 * │ merkes det knapt; på telefon er det den vanligste bevegelsen i huben.     │
 * │                                                                           │
 * │ `background` er SOLID navy, ikke frostet glass: PALETT.md sier ingen      │
 * │ gradient-fyll, ingen frostet glass, ingen glød. En klebrig linje man ser  │
 * │ innholdet gjennom, er dessuten vanskeligere å lese enn den er pen.        │
 * │                                                                           │
 * │ `--topp-h` er høyden linja faktisk får, og den er verdt et navn: to andre │
 * │ flater har sin egen klebrige rad (`.filtre` i ringelista, `.faner` i      │
 * │ manus) som må feste seg UNDER denne og ikke bak den. Tallene i tema.css   │
 * │ er regnet ut av paddingen og trykkflata her; `felles/topp.js` måler den   │
 * │ ekte høyden og skriver over dem, så de aldri kan drive fra hverandre.     │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
.topp {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px var(--marg);
  /* Hakket. Se begrunnelsen på `body`. */
  padding-top: calc(10px + env(safe-area-inset-top));
  border-bottom: 1px solid var(--border);
  background: var(--navy);
}

/* Merket er en lenke til huben. `min-height` gir den full trykkflate selv om
   bildet er lavere — en logo man må sikte på er en logo man bommer på. */
.merke {
  display: flex; align-items: center;
  min-height: var(--trykk);
  text-decoration: none;
}
.merke img { height: 26px; width: auto; display: block; }
.merke:focus-visible { outline: 2px solid var(--ice); outline-offset: 4px; border-radius: var(--r-sm); }
/* Merket er hjemlenka, og på telefon den eneste. Et trykk skal ses. */
.merke:active { opacity: .7; }

/* ── Søkefeltet i topplinja ──────────────────────────────────────────────────
   ┌───────────────────────────────────────────────────────────────────────────┐
   │ ET FELT, IKKE EN KNAPP. Phillip 25.08.2026: «i toppen har jeg lagt merke  │
   │ til at du ikke har et hub symbol eller et søkefelt som lar deg søke i     │
   │ hele databasen + ai».                                                     │
   │                                                                           │
   │ Forsida hadde en søkeKNAPP som åpnet en ⌘K-rute, med denne begrunnelsen   │
   │ i hub.css: «Et felt i toppen inviterer til å skrive der, og da må det     │
   │ virke der.» Den setningen er riktig — og svaret er at feltet virker der,  │
   │ ikke at feltet fjernes. Treffene legger seg rett under det man skrev i.   │
   │                                                                           │
   │ Boksen er PILLA, ikke feltet: `.felt-naken` tar bort feltets egen ramme,  │
   │ slik at lupa, skrivemerket og ⌘K-hintet står i samme boks uten boks-inni- │
   │ boks. Se `input.felt-naken` lenger nede i denne fila.                     │
   └───────────────────────────────────────────────────────────────────────────┘ */

.topp-sok {
  position: relative;                 /* treffruta henger under DENNE */
  flex: 1 1 auto; min-width: 0; max-width: 460px;
  display: flex; align-items: center; gap: 9px;
  min-height: var(--trykk); padding: 0 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--navy2);
  transition: border-color .12s ease;
}
/* Fokus vises på BOKSEN, ikke på feltet: feltet har ingen ramme igjen å tegne
   på, og to rammer i én pille leses som to felter. */
.topp-sok:focus-within { border-color: var(--ice); }
.topp-sok > .ikn { width: 17px; height: 17px; color: var(--muted); }
.topp-sok:focus-within > .ikn { color: var(--ice); }
.topp-sok input { flex: 1; min-width: 0; outline: none; }
/* Nettleserens egen kryssknapp hører til boksen `.felt-naken` nettopp fjernet.
   Escape tømmer feltet, og det er den veien tastaturet allerede går. */
.topp-sok input::-webkit-search-cancel-button,
.topp-sok input::-webkit-search-decoration { -webkit-appearance: none; display: none; }
.topp-sok kbd {
  flex: none;
  font-family: var(--font-mono); font-size: 11px; color: var(--muted);
  border: 1px solid var(--border-strong); border-radius: 5px; padding: 2px 6px;
}

/* ── Treffruta ───────────────────────────────────────────────────────────────
   Bygges av `felles/topp.js`, ikke av tolv sideark. Markupen for FELTET står i
   hver `index.html` — samme mønster som merket og initialskiva — men lista er
   ren tilstand og hører i koden som holder tilstanden. */

.topp-finn {
  position: absolute; z-index: 40;
  top: calc(100% + 8px); left: 0; right: 0;
  border: 1px solid var(--border-strong); border-radius: var(--r-md);
  background: var(--navy2); color: var(--offwhite);
  box-shadow: var(--elev-card);
  /*
   * `dvh`, ikke `vh`. `vh` er den STORE viewporten — høyden siden ville hatt
   * uten adresselinje. Treffruta åpnes derimot ALLTID med tastaturet oppe;
   * den henger under et søkefelt man nettopp skrev i. Målt på iPhone 14
   * (390 × 844): `66vh` = 557 px i en synlig høyde på ~380 px med tastatur,
   * altså en rute som er halvannen gang så høy som plassen den har.
   * `dvh` er høyden som faktisk er der akkurat nå.
   */
  max-height: min(60dvh, calc(100dvh - var(--topp-h) - var(--tastatur) - 24px), 560px);
  overflow-y: auto;
  /* Ruller man til bunnen her, skal ikke sida bak begynne å rulle. */
  overscroll-behavior: contain;
}

.finn-liste { list-style: none; margin: 0; padding: 6px; display: grid; gap: 1px; }

/* Gruppetittelen er en ETIKETT, ikke en rad. Den skal ikke kunne velges, og
   den skal ikke se ut som noe man kan trykke på. */
.finn-bolk {
  padding: 12px 12px 5px;
  font-size: 11px; font-weight: 500; text-transform: uppercase;
  letter-spacing: .12em; color: var(--muted);
}
.finn-liste > li:first-child .finn-bolk { padding-top: 6px; }

.finn-rad {
  width: 100%;
  display: flex; align-items: center; gap: 12px;
  min-height: var(--trykk); padding: 8px 12px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  background: none;
  color: var(--offwhite); text-decoration: none;
  font: inherit; text-align: left;
  cursor: pointer;
  touch-action: manipulation;
}
.finn-rad > .ikn { width: 17px; height: 17px; color: var(--muted); }
.finn-tekst { display: grid; gap: 1px; min-width: 0; }
/* Et filnavn er langt og et bedriftsnavn kan være det. Raden skal bli høyere
   av lang tekst, aldri bredere — ellers ruller ruta sidelengs. */
.finn-navn { font-size: 15px; line-height: 1.35; overflow-wrap: anywhere; }
.finn-under { font-size: 12.5px; color: var(--silver); line-height: 1.35; overflow-wrap: anywhere; }
.finn-rad .pille { margin-left: auto; flex: none; }

.finn-rad:hover, .finn-rad:active { background: var(--navy3); }
/* Raden piltastene står på. Kant OG flate — bare flate er for svakt å se når
   musepekeren tilfeldigvis ligger over en annen rad. */
.finn-rad.pa { background: var(--navy3); border-color: var(--ice); }
.finn-rad.pa > .ikn, .finn-rad:hover > .ikn { color: var(--ice); }
/*
 * Pilla må LØFTES sammen med raden, ellers faller den under AA.
 *
 * `.pille` er sølv på `--fill-subtle`. Over `--navy2` er det 5,09:1 og helt
 * greit — men den merkede raden bytter flate til `--navy3`, og da synker den
 * samme pilla til **4,33:1**, altså under kravet på 4,5:1 for 13 px tekst.
 * Målt i nettleseren 25.08.2026 og regnet etter for hånd; de to var enige.
 *
 * Det er ikke paletten som er feil — sølv på navy2 stemmer. Det er at raden
 * skifter underlag under pilla uten at pilla får vite det. Så løsningen er en
 * TILSTAND, ikke en ny farge: den merkede raden lyser opp, og alt i den lyser
 * opp med den. Å gjøre `.pille` lysere overalt ville dempet skillet mellom en
 * rolig pille og en som betyr noe.
 */
.finn-rad.pa .pille, .finn-rad:hover .pille { color: var(--offwhite); }

/* En rad uten et sted å gå er TEKST. Den skal ikke se ut som en lenke, og
   markøren skal ikke love at et trykk gjør noe — se `radlenke()`. */
.finn-rad.ute { cursor: default; color: var(--silver); }
.finn-rad.ute:hover { background: none; }

/* «Spør KI» står nederst i sin egen fot, med en tynn strek over: den er et
   annet slags svar enn radene over, ikke bare det siste treffet. Foten ligger
   UTENFOR lista, ellers blir lista aldri tom og «Ingen treff på …» får aldri
   vises — se `tegn()` i felles/finn.js. */
.finn-ki { padding: 6px; }
/* Streken kommer BARE når det står treff over. Er lista tom, er «Ingen treff
   på …» og «Spør KI» to deler av det samme svaret, og en strek mellom dem
   ville delt det i to. */
.finn-liste:not([hidden]) ~ .finn-ki { border-top: 1px solid var(--border); }
.finn-ki .finn-rad > .ikn { color: var(--ice); }

/* Tomt er tomt. Ingen feilfarge, ingen ikon, ingen ny form — en setning. */
.finn-tomt { margin: 0; padding: 20px 16px; text-align: center; color: var(--silver); font-size: 14px; }

.topp-hoyre { display: flex; align-items: center; gap: 4px; flex: none; }

/* Ikonknappen: 44px flate, 20px ikon. Flata er usynlig til man peker på den —
   sju rammer på rad ville laget et gjerde av topplinja. */
.ikonknapp {
  display: grid; place-items: center;
  width: var(--trykk); height: var(--trykk); padding: 0;
  /* Aldri smalere enn trykkflata, uansett hvor trangt det blir i linja. En
     knapp som krymper til 34 px er en knapp man bommer på. */
  flex: none;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-btn);
  color: var(--silver); cursor: pointer;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.ikonknapp svg { width: 20px; height: 20px; }
.ikonknapp:hover { color: var(--offwhite); background: var(--navy2); border-color: var(--border); }
/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ EN TELEFON HAR INGEN PEKER, OG DA GJØR `:hover` INGENTING.               │
 * │                                                                           │
 * │ Talt 10.09.2026: huben hadde 34 `:hover`-regler og fire `:active`. På     │
 * │ berøring er hover enten død eller KLEBRIG — den henger igjen på det man   │
 * │ sist trykket. Følgen er at et trykk på en ikonknapp i topplinja, en rad i │
 * │ søketreffene eller en avviksrad ga NULL tilbakemelding: man trykker, og   │
 * │ ingenting sier at trykket ble registrert før neste side er der.           │
 * │                                                                           │
 * │ `:active` er den tilstanden som faktisk finnes på en finger. Den er lagt  │
 * │ på de tre delte flatene man trykker mest på, med samme flate som hover    │
 * │ bruker — så det er den samme designbeslutningen, ikke en ny.              │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
.ikonknapp:active { color: var(--offwhite); background: var(--navy3); border-color: var(--border-hover); }
.ikonknapp:focus-visible { outline: 2px solid var(--ice); outline-offset: 2px; color: var(--offwhite); }
/* Sida du står på. Den eneste isen i linja, så den betyr noe. */
.ikonknapp[aria-current="page"] { color: var(--ice); }

.topp-hoyre .skille { width: 1px; height: 22px; background: var(--border); margin: 0 4px; }

.meg {
  display: grid; place-items: center;
  width: 32px; height: 32px; margin-left: 2px;
  flex: none;
  border-radius: 50%;
  background: var(--navy3); border: 1px solid var(--border-strong);
  color: var(--offwhite);
  font: 600 12px/1 var(--font-display, system-ui); letter-spacing: .04em;
}

/*
 * «Vi vet ikke hvem du er.» Gul kant og gul skrift — samme språk som `.pille
 * .varsel` og kravtelleren: noe krever tilsyn, men ingenting er ødelagt.
 * Se `catch`-blokka i felles/topp.js for hvorfor tegnet står der.
 */
.meg.ukjent { color: var(--warn); border-color: var(--warn); }

/* ── Nytt i huben ─────────────────────────────────────────────────────────
   Endringsloggen, bygget av `felles/nytt.js`. Knappen står i topplinja på
   hver flate; panelet henger under den. Markupen finnes ikke i noen
   `index.html` — innholdet ER svaret fra serveren, og en tom ramme i tolv
   filer er tolv filer å holde like. Samme svar som treffruta over. */

/* Prikken må ha noe å henge på, og knappen er ellers `.ikonknapp` uendret. */
.nytt-knapp { position: relative; }

/*
 * «Det er noe her du ikke har lest.»
 *
 * IS, ikke rødt. Rødt i topplinja betyr at noe er galt — det er språket
 * `.pille.feil` og avviksseksjonen alt har tatt. En endringslogg er aldri
 * galt, den er bare ulest, og is er den ene fargen linja bruker for «se
 * her». Kanten i flatefargen gjør at prikken leses som en prikk og ikke som
 * en flekk på ikonet, også når knappen står med hover-bakgrunnen sin.
 */
/*
 * Plasseringen er MÅLT, ikke plukket.
 *
 * Knappen er 44 px og ikonet 20, altså tegnet fra 12 til 32 i begge retninger.
 * En prikk på `top: 8px; right: 8px` blir 12 px med kanten, og dekker da et
 * felt på 8 × 8 px inne i ikonet — nøyaktig der rakettens nese er. Sett på
 * skjermbildet 29.09.2026, forstørret tre ganger: raketten så ut som den
 * manglet tuppen.
 *
 * 5 px legger prikken i hjørnet av knappen i stedet for i hjørnet av ikonet.
 * Overlappet er da 4 × 4 px, som er kanten og ikke tegningen.
 *
 * Kanten er linjas egen flate, ikke en farge valgt til anledningen: den
 * skiller prikken fra ikonet uten å legge til et element til på skjermen.
 */
.nytt-knapp.har-nytt::after {
  content: "";
  position: absolute; top: 5px; right: 5px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ice);
  border: 2px solid var(--navy);
}

.nytt {
  /*
   * Henger under topplinja i høyre kant, der knappen står. Et `<dialog>`
   * ligger i top layer med `inset: 0` fra nettleserens eget stilark, så
   * plasseringen gjøres med marger — `margin: auto` sentrerer, et tall
   * fester. Samme grep som `.prat` bruker for sitt nedre høyre hjørne.
   *
   * `--topp-h` holdes lik linjas EKTE høyde av `riggHoyde()` i topp.js, så
   * panelet følger med når linja brekker til to rader på telefon.
   */
  margin: calc(var(--topp-h) + var(--rom-2)) var(--marg) auto auto;
  width: min(460px, calc(100vw - 2 * var(--marg)));
  /*
   * `dvh`, ikke `vh` — samme grunn som treffruta skriver ned: `vh` er høyden
   * sida ville hatt uten adresselinje, og på en telefon er det ikke høyden
   * som faktisk er der.
   */
  max-height: calc(100dvh - var(--topp-h) - 2 * var(--rom-4) - env(safe-area-inset-bottom));
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--navy2);
  color: var(--offwhite);
  box-shadow: var(--elev-card);
  /* Hodet står, lista ruller. Et `<dialog>` er `display:none` når det er
     lukket — skrives `display` uten `[open]`, står panelet framme fra første
     tegning. Samme felle som `.prat` og `.krav` alt har skrevet ned. */
  /*
   * ┌───────────────────────────────────────────────────────────────────────┐
   * │ TRE RADER, FORDI PANELET HAR TRE BARN.                                │
   * │                                                                       │
   * │ Den sto på `auto 1fr` fra den hadde to — hodet og lista. Da            │
   * │ filterraden kom imellom 01.10.2026, havnet DEN i `1fr`-raden og lista  │
   * │ i en implisitt `auto` under. Får panelet en høyde større enn innholdet │
   * │ sitt, er det da filterraden som sluker slakken: fire piller strukket   │
   * │ til loddrette stolper, med dagene presset ned under.                   │
   * │                                                                       │
   * │ Phillip så det på panelet 01.10.2026 da han valgte «Kundene» — det     │
   * │ området har færrest linjer, og slakken blir derfor størst der.         │
   * │                                                                       │
   * │ Slakken hører i LISTA. Den er det eneste her som kan rulle.            │
   * └───────────────────────────────────────────────────────────────────────┘
   */
  display: none; grid-template-rows: auto auto 1fr;
  overflow: hidden;
}
.nytt[open] { display: grid; }
.nytt::backdrop { background: var(--scrim); }

.nytt-topp {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 10px 10px 14px;
  border-bottom: 1px solid var(--border);
}
.nytt-tittel {
  display: flex; align-items: center; gap: 9px; margin-right: auto;
  font-family: var(--font-display); font-weight: 700; font-size: 15px;
}
.nytt-tittel .ikn { width: 17px; height: 17px; color: var(--ice); }

/*
 * Filterraden: hvilken del av NordicOps.
 *
 * Over kroppen og UNDER tittellinja: man velger hva man vil se, og leser så.
 * Knappene er `.pille` — de er et valg, ikke en handling, og skal ikke se ut
 * som de fire knappene i et ark.
 */
.nytt-filter {
  display: flex; flex-wrap: wrap; gap: 6px;
  /*
   * Pillene skal ALDRI strekke seg, uansett hvor høy raden blir.
   * `align-items` på en flex-rad står på `stretch` som standard, og det var
   * den andre halvdelen av stolpene over: selv med riktig rad ville en høyere
   * filterrad dratt knappene med seg. To linjer, to uavhengige vern.
   */
  align-items: center;
  padding: var(--rom-2) var(--rom-3);
  border-bottom: 1px solid var(--border);
}
.nytt-omrade {
  /*
   * ┌───────────────────────────────────────────────────────────────────────┐
   * │ 44 PIKSLER. FØRSTE UTGAVE STO PÅ 32 MED EN BORTFORKLARING.            │
   * │                                                                       │
   * │ Den sa at pillene «står i en rad man sikter i, ikke i en liste man    │
   * │ bommer i». Sveipen målte dem i ekte Chrome på 390 px og svarte med    │
   * │ fire funn: 38×32, 61×32, 71×32, 74×32. `--trykk` er ikke smak — og    │
   * │ det er nettopp slike resonnementer vakta finnes for å overprøve.      │
   * │                                                                       │
   * │ Bredden var aldri problemet: de fire måler 262 px med luft, og raden  │
   * │ har 296 å gi på 360 px. Høyden koster 12 piksler i et panel som       │
   * │ ruller.                                                               │
   * └───────────────────────────────────────────────────────────────────────┘
   */
  min-height: var(--trykk);
  cursor: pointer;
  border-color: var(--border);
  background: transparent;
  color: var(--silver);
  font: inherit; font-size: 12.5px;
}
.nytt-omrade:hover { color: var(--offwhite); border-color: var(--border-hover); }
.nytt-omrade:focus-visible { outline: 2px solid var(--ice); outline-offset: 2px; }
/* Den valgte er den ENESTE isen i raden, så den betyr noe. */
.nytt-omrade.valgt {
  background: var(--ice-bg); color: var(--ice); border-color: transparent;
}

.nytt-kropp {
  padding: var(--rom-2);
  overflow-y: auto;
  /* Ruller man til bunnen her, skal ikke sida bak ta over og flytte en til et
     annet sted enn der man leste. Samme svar som treffruta og samtalen. */
  overscroll-behavior: contain;
  display: grid; gap: 2px; align-content: start;
}

.nytt-bolk { border-radius: var(--r-sm); }
/* Den åpne dagen skal skille seg fra de lukkede uten en strek mellom hver:
   en liste med seks streker leses som en tabell. */
.nytt-bolk[open] { background: var(--fill-subtle); }

/*
 * Dagen man klapper opp og igjen.
 *
 * `list-style: none` OG `::-webkit-details-marker` — den innebygde trekanten
 * tegnes av to ulike mekanismer, og Safari hører bare på den siste. Uten
 * begge står systemets egen trekant ved siden av vårt eget ikon, i en annen
 * strektykkelse enn de 29 strekikonene rundt den.
 */
.nytt-dag {
  display: flex; align-items: center; gap: 10px;
  min-height: var(--trykk);
  padding: 0 12px;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: 13.5px;
  color: var(--silver);
  list-style: none;
  -webkit-tap-highlight-color: transparent;
}
.nytt-dag::-webkit-details-marker { display: none; }
.nytt-dag:hover, .nytt-dag:active { color: var(--offwhite); }
.nytt-dag:focus-visible { outline: 2px solid var(--ice); outline-offset: -2px; }
.nytt-bolk[open] > .nytt-dag { color: var(--offwhite); }

/* Pila peker HØYRE når dagen er lukket og NED når den er åpen. Ett ikon fra
   settet, dreid — ikke to tegninger som kan bli uenige. */
.nytt-dag .ikn {
  width: 15px; height: 15px; margin-left: auto;
  color: var(--muted);
  transition: transform .15s ease;
}
.nytt-bolk[open] > .nytt-dag .ikn { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
  .nytt-dag .ikn { transition: none; }
}

.nytt-rader {
  list-style: none; margin: 0;
  padding: 2px var(--rom-3) var(--rom-3);
  display: grid; gap: 10px;
}
.nytt-rad {
  display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: start;
  min-width: 0;
}

/*
 * Arten, som en pille.
 *
 * Fargene speiler `.pille.is`, `.pille.ok` og `.pille.varsel` med vilje, og
 * mappingen bor HER og ikke i `nytt.js`: hvilken art en endring har, er en
 * opplysning om endringen og står i fasit. Hvilken farge arten skal ha, er
 * en designbeslutning og hører i stilarket.
 *
 * Gult for «rettet», ikke rødt. Rødt sier at noe er ødelagt NÅ. Dette er
 * tvert imot listen over det som ikke er det lenger.
 */
.nytt-art {
  flex: none;
  margin-top: 1px;
  border-color: transparent;
  font-size: 11px;
}
.nytt-art.art-nytt   { background: var(--ice-bg);    color: var(--ice); }
.nytt-art.art-bedre  { background: var(--green-svak); color: var(--green); }
.nytt-art.art-rettet { background: var(--warn-svak);  color: var(--warn); }

.nytt-midt { display: grid; gap: 4px; min-width: 0; }
.nytt-hva { font-size: 14.5px; line-height: 1.45; overflow-wrap: anywhere; }
/* Hvor endringen hører hjemme, som en innledning i samme linje. Dempet, fordi
   det er en opplysning om linja og ikke linja selv — og halvfet, så øyet
   finner den når man skanner etter ett sted. */
.nytt-sted { color: var(--silver); font-weight: 600; }
.nytt-detalj { font-size: 13px; line-height: 1.5; color: var(--silver); overflow-wrap: anywhere; }

/* Stående på telefon er det lite bredde å ta av. Merket krymper litt, luften
   mer — ikonene selv rører vi ikke, de er allerede på minstemålet. */
/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ PÅ TELEFON BREKKER LINJA, OG SØKEFELTET FÅR EN RAD FOR SEG SELV.          │
 * │                                                                           │
 * │ Regnet på 390 px: merket tar 41, ikonknappene og initialskiva 127, luften │
 * │ 28. Da er det 194 px igjen til feltet — nok til å skrive i, for lite til  │
 * │ å SE hva man skrev når treffruta under er full bredde likevel. Og et      │
 * │ søkefelt som er smalere enn svaret sitt, ser ut som en feil.              │
 * │                                                                           │
 * │ Alternativet var å skjule feltet bak en lupeknapp under 560 px. Det er    │
 * │ nøyaktig knappen Phillip ba om å få erstattet med et felt.                │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ HVOR DU ER — I DEN TOMME MIDTEN AV FØRSTE RAD.                            │
 * │                                                                           │
 * │ På telefon brekker linja i to: merket og ikonknappene på rad én, søket i  │
 * │ full bredde på rad to. Målt på skjermbildet 10.09.2026 (390 px) sto det   │
 * │ da igjen ~200 px HELT TOM plass midt i rad én — en fjerdedel av           │
 * │ topplinjas areal, brukt til ingenting.                                    │
 * │                                                                           │
 * │ Skrivebordet har ikke det problemet: der er søket i midten, og h1-en      │
 * │ under sier hva sida heter. På telefon ruller den h1-en bort med én        │
 * │ gang — og da er det ingenting igjen som sier hvor man er.                 │
 * │                                                                           │
 * │ Så midten får sidenavnet. Det fyller hullet med det ene man mangler, og   │
 * │ det er det eneste som gjør en klebrig linje verdt sin egen høyde.         │
 * │                                                                           │
 * │ Navnet TEGNES AV `felles/topp.js` fra `<title>`, ikke skrevet i tolv      │
 * │ index.html: tittelen finnes allerede, og en tekst skrevet to steder blir  │
 * │ to ulike tekster. Det er en `<span>` og ikke en knapp — `topplinje.test`  │
 * │ nekter ordknapper i linja, og med rette: merket ER hjemlenka.             │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
.topp-tittel {
  display: none;                       /* bare på telefon; se under */
  /*
   * `flex-basis: 0`, ikke `auto` — og det er ikke pirk.
   *
   * Linja er `flex-wrap: wrap`. En flex-boks bryter linja ut fra elementenes
   * BASISBREDDE, ikke ut fra hvor små de kunne blitt. Med `auto` er basisen
   * hele tittelen, og på panelet — som har fem ikonknapper og «Oppdatert
   * 10:15» i høyresida — brakk linja i TRE rader på 390 px: merke + tittel,
   * så knappene, så søket. 166 px topplinje på en 844 px skjerm.
   * Med basis 0 teller tittelen ingenting når linja deles, og krymper i
   * stedet til det som er igjen. `overflow: hidden` gjør resten.
   */
  min-width: 0; flex: 1 1 0;
  font-family: var(--font-display); font-weight: 600; font-size: 15px;
  letter-spacing: -.01em; color: var(--offwhite);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ PÅ TELEFON BREKKER LINJA, OG SØKEFELTET FÅR EN RAD FOR SEG SELV.          │
 * │                                                                           │
 * │ Regnet på 390 px: merket tar 41, ikonknappene og initialskiva 127, luften │
 * │ 28. Da er det 194 px igjen til feltet — nok til å skrive i, for lite til  │
 * │ å SE hva man skrev når treffruta under er full bredde likevel. Og et      │
 * │ søkefelt som er smalere enn svaret sitt, ser ut som en feil.              │
 * │                                                                           │
 * │ Alternativet var å skjule feltet bak en lupeknapp under 560 px. Det er    │
 * │ nøyaktig knappen Phillip ba om å få erstattet med et felt.                │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
@media (max-width: 560px) {
  .topp {
    flex-wrap: wrap; row-gap: 8px; gap: 8px;
    padding: 8px var(--marg);
    padding-top: calc(8px + env(safe-area-inset-top));
  }
  /* Rekkefølgen skrives ut, ellers avgjør markupen den — og markupen har
     søket i midten fordi det er der det hører hjemme på et skrivebord. */
  /*
   * `.topp .merke`, ikke `.merke`.
   *
   * `order` er skrevet for topplinja, men `.merke` finnes ETT sted til: i
   * innloggingskortet, som `.merke.stor`. Det kortet er `display: grid`, og
   * `order: 1` der dyttet LOGOEN NEDERST i skjemaet — under passordfeltet og
   * under knappen, på hver eneste telefon. Sett av hub-agenten 10.09.2026
   * samme dag regelen ble skrevet.
   *
   * Samme innsnevring gjelder høyderegelen under, og DPR-regelen nederst i
   * fila: innloggingsmerket skal stå i sin egen størrelse.
   */
  .topp .merke { order: 1; }
  .topp-tittel { display: block; order: 2; }
  .topp-hoyre { order: 3; gap: 0; }
  .topp-sok { order: 4; flex-basis: 100%; max-width: none; }
  .topp-hoyre .skille { margin: 0 2px; }
  .topp .merke img { height: 22px; }
  /*
   * ┌───────────────────────────────────────────────────────────────────────┐
   * │ HUSIKONET GÅR UT PÅ TELEFON — MERKET GJØR DEN JOBBEN ALLEREDE.        │
   * │                                                                       │
   * │ `topplinje.test.ts` skriver det selv, om «Hub»-ordknappen som ble      │
   * │ fjernet 23.08.2026: «Merket ER hub-lenka, så en Hub-knapp er en knapp  │
   * │ for å komme dit logoen allerede peker.» Husikonet er nøyaktig den      │
   * │ knappen, tegnet på nytt. På skrivebordet er den gratis og blir         │
   * │ stående — der er linja fasit, og en snarvei til venstre og en til      │
   * │ høyre koster ingenting.                                               │
   * │                                                                       │
   * │ På 320 px koster den derimot alt: målt 10.09.2026 er høyresida med     │
   * │ fem mål 221 px, og med merket og margene blir linja 289 px i et 288    │
   * │ px vindu. Ett piksel for bredt, og hele linja brekker til TRE rader.   │
   * └───────────────────────────────────────────────────────────────────────┘
   */
  .topp-hoyre a.ikonknapp[href="/"] { display: none; }
  /* Det er ikke plass som mangler — feltet er full bredde her. Det er tasten:
     en telefon har ingen ⌘, og et hint om en snarvei man ikke kan bruke er en
     løgn i topplinja på den flata som brukes mest. */
  .topp-sok kbd { display: none; }
}

/*
 * ┌───────────────────────────────────────────────────────────────────────────┐
 * │ MERKET ER ET BILDE PÅ 108 × 58 PIKSLER, OG DET ER HELE SANNHETEN.        │
 * │                                                                           │
 * │ Tegnet 22 px høyt blir det 41 × 22 CSS-piksler. På en iPhone med tre      │
 * │ device-piksler per CSS-piksel er det 123 × 66 EKTE piksler nettleseren    │
 * │ må fylle — av en fil som bare har 108 × 58. Bildet skaleres da opp 14 %,  │
 * │ og en logo som er to diagonale streker blir myk i kantene. På skrivebord  │
 * │ (én eller to device-piksler) skjer det motsatte og alt er skarpt.         │
 * │                                                                           │
 * │ 19 px gir 35 × 19 CSS = 106 × 57 ekte piksler, altså INNENFOR fila. Det   │
 * │ er tre piksler lavere logo, byttet mot en skarp en — og forskjellen på 22 │
 * │ og 19 px ser ingen, mens forskjellen på skarp og myk ser alle.            │
 * │                                                                           │
 * │ Den ekte rettelsen er en `merke.svg`. Den finnes ikke i treet: både       │
 * │ `logo-ice.png` (90 × 82 blekk) og `ikon-512.png` (253 × 233) er en ANNEN  │
 * │ lockup enn merket — målt 10.09.2026, gjennomsnittlig avvik 104 per kanal  │
 * │ mot beste beskjæring. Å tegne merket på nytt etter øyemål er ikke en      │
 * │ oppgave for en maskin.                                                    │
 * └───────────────────────────────────────────────────────────────────────────┘
 */
/*
 * Bredden er tatt UT av vilkåret. Regelen sto på `and (max-width: 560px)`, og
 * falt derfor bort så snart telefonen ble snudd — en iPhone 14 Pro i landskap
 * er 852 CSS px bred, og da tegnet merket seg 26 px og mykt igjen. Tre
 * device-piksler per CSS-piksel finnes i praksis bare på en telefon, så
 * oppløsningen alene er det ærlige vilkåret.
 */
@media (min-resolution: 2.5dppx) {
  .topp .merke img { height: 19px; }
}

/* Adressen Fiken skal ha ordrett. Må kunne merkes og kopieres uten at et
   linjeskift sniker seg inn — en Redirect URI med et mellomrom i avvises av
   Fiken med en feil som ikke sier hvorfor. */
.kode {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  background: var(--navy3);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 6px 10px;
  word-break: break-all;
  user-select: all;
}
