/* =========================================================================
   Design system «Arbeidstegning» — tokens + components.
   Source of truth for all UI. Brand color is injected per company profile
   as --brand in base templates; every tint derives from it via color-mix.
   ========================================================================= */

/* ---- Fonts (self-hosted) ------------------------------------------------ */
/* Schibsted Grotesk and Azeret Mono, from the Sonida design. Variable woff2, so
   one file per family covers every weight the design uses — 116 kB for both,
   against 1,4 MB of IBM Plex TTF before. Self-hosted from static/fonts/, never
   fetched from Google: a request to fonts.gstatic.com would carry the visitor's
   IP address to a third party on every page, including the accept page a
   customer opens.

   Split latin / latin-ext by unicode-range, exactly as Google serves them. The
   latin subset carries Æ Ø Å; latin-ext covers Polish, Czech and the rest, and
   is only downloaded if a name on the page actually needs it. */
@font-face {
  font-family: "Schibsted Grotesk";
  src: url("../fonts/SchibstedGrotesk-latin.c5e9a9901938.woff2") format("woff2");
  font-weight: 400 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Schibsted Grotesk";
  src: url("../fonts/SchibstedGrotesk-latin-ext.52c63824a8f6.woff2") format("woff2");
  font-weight: 400 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Azeret Mono";
  src: url("../fonts/AzeretMono-latin.05fe8a15c48a.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Azeret Mono";
  src: url("../fonts/AzeretMono-latin-ext.1781949e9c46.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* IBM Plex stays as the fallback while other screens are still on the old
   design — remove these four once every surface is on Sonida. */
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBMPlexSans-Variable.335a2b2a3a64.ttf") format("truetype-variations");
  font-weight: 100 900;
  font-display: swap;
}
@font-face { font-family: "IBM Plex Mono"; src: url("../fonts/IBMPlexMono-Regular.560033d0c7f2.ttf"); font-weight: 400; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("../fonts/IBMPlexMono-Medium.63c2dc54dd9c.ttf"); font-weight: 500; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("../fonts/IBMPlexMono-SemiBold.4c2f3714b6a4.ttf"); font-weight: 600; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("../fonts/IBMPlexMono-Bold.bb4d12d9aeeb.ttf"); font-weight: 700; font-display: swap; }

/* ---- Tokens ------------------------------------------------------------- */
/* The neutrals turned cool on 19 August 2026, from the Sonida design system.
   They were warm before (--paper #FAF9F7, --line #E7E4DE); the values below are
   the design's own. It is a temperature shift, not a redesign - every one of
   them is a near-neutral at nearly the same lightness - but it reaches every
   screen at once, because tailwind.config in base.html maps bg-paper,
   border-line and text-ink straight onto these variables. That is deliberate:
   one place to change, and no second palette living alongside the first. */
:root {
  --paper: #F2F4F7;      /* app surface, the ground everything sits on */
  --surface: #FFFFFF;    /* cards, sidebar, top bar */
  --ink: #111827;        /* titles, strongest text */
  --ink-2: #374151;      /* body text, inactive nav */
  --ink-3: #4B5563;      /* labels, metadata, units - 7.6:1 on white */
  --line: #DDE2EA;       /* the standard hairline, card edges */
  --line-soft: #EDF0F4;  /* between rows INSIDE a card - never an outer edge */
  --line-strong: #C9CFD8;

  /* The design's own blues, as literal values — not derived from the company
     colour, and not overridden per tenant. Anders' call 19. august 2026: the
     internal app is to match the Sonida design exactly, and it cannot do that
     while every tenant tints it differently.
     
     These are the exact hexes from «Sonida portal.dc.html», not approximations
     from color-mix: #1740B4 is a hand-picked text blue that a mix of #1D4ED8
     with black does not land on.
     
     NOTE: base.html still injects :root { --brand: … } from the company profile,
     which would win the cascade. That injection is removed from the internal
     shell (see the comment there). The public shells keep it — what a
     håndverker's own customer sees is a separate decision. */
  --brand: #1D4ED8;        /* action: primary button, active nav, the card edge */
  --brand-hover: #1740B4;
  --brand-ink: #1740B4;    /* text on a tinted fill, never on white */
  --brand-03: #F7FAFF;     /* faintest fill: secondary button, active counter */
  --brand-06: #EEF3FE;     /* badge fill, active tab */
  --brand-10: #EEF3FE;
  --brand-16: #C9DAFB;
  --brand-22: #C9DAFB;     /* hairline on a tinted fill */
  --brand-30: #C9DAFB;

  /* Status colours never follow the brand: they carry meaning, and an amber
     that turned into someone's corporate green would say the wrong thing. */
  --ok: #065F46;
  --ok-bg: #D1FAE5;
  --bad: #991B1B;
  --bad-bg: #FEE2E2;
  --warn: #92400E;
  --warn-bg: #FEF3C7;
  --neutral: #374151;    /* «Sendt» - a state with nothing to say about it */
  --neutral-bg: #EEF1F6;

  --radius-ctl: 6px;
  --radius-card: 10px;
  --shadow-1: 0 1px 2px rgb(29 31 36 / 0.05), 0 1px 1px rgb(29 31 36 / 0.03);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);

  --font-sans: "Schibsted Grotesk", "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Azeret Mono", "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
}

html { font-family: var(--font-sans); color: var(--ink); background: var(--paper); }
body { font-size: 14px; line-height: 1.55; }
::selection { background: var(--brand-16); }

h1, h2, h3 { letter-spacing: -0.01em; font-weight: 600; }

a.link { color: var(--brand); text-decoration: none; border-bottom: 1px solid var(--brand-30); }
a.link:hover { border-bottom-color: var(--brand); }

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Numbers: always tabular mono */
.font-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Small technical label (title-block fields, KPI labels, table headers ONLY) */
.tech-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-3);
}

/* ---- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 13.5px; font-weight: 500; line-height: 1;
  padding: 9px 14px; border-radius: var(--radius-ctl);
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: background-color 130ms ease, border-color 130ms ease,
              color 130ms ease, transform 120ms var(--ease-out);
  text-decoration: none;
}
.btn:active { transform: scale(0.98); }
.btn svg { width: 16px; height: 16px; }

.btn-primary { background: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-hover); }

.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn-secondary:hover { border-color: var(--ink-3); background: var(--paper); }

.btn-ghost { background: transparent; color: var(--ink-2); }
.btn-ghost:hover { background: var(--brand-06); color: var(--ink); }

.btn-danger { background: var(--surface); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, white); }
.btn-danger:hover { background: var(--bad-bg); }

.btn[disabled], .btn.is-loading { opacity: 0.55; pointer-events: none; }

/* A quiet inline text action for secondary helpers (re-open the mail draft,
   re-send) that must not read as a call-to-action button. Small, no chrome, a
   touch of vertical padding so it is still a comfortable tap target. */
.link-btn {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; padding: 4px 0; cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--brand); text-decoration: none; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.link-btn:hover { text-decoration: underline; }
.link-btn:active { opacity: 0.6; }

/* ---- Forms -------------------------------------------------------------- */
.label { display: block; font-size: 13px; font-weight: 500; color: var(--ink); margin-bottom: 5px; }
.help { font-size: 12.5px; color: var(--ink-3); margin-top: 4px; }
.error-text { font-size: 12.5px; color: var(--bad); margin-top: 4px; }

.input, .select, .textarea {
  /* Skjemafelt arver IKKE dokumentskriften av seg selv: nettlesere gir textarea
     monospace og input/select sin egen UI-skrift. inherit gir alle tre husets
     skrift; .input-num under overstyrer fortsatt bevisst med mono. */
  width: 100%; font-family: inherit; font-size: 14px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-ctl); padding: 8px 11px;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}
.input::placeholder, .textarea::placeholder { color: var(--ink-3); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--ink-3); }
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-16);
}
.input.has-error, .select.has-error, .textarea.has-error, .cell-input.has-error { border-color: var(--bad); }
.textarea { line-height: 1.55; min-height: 88px; }
.input-num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---- Cards -------------------------------------------------------------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px;
}
.card-pad { padding: 20px; }

/* ---- Tables ------------------------------------------------------------- */
.tbl { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.tbl thead th {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3);
  text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}
.tbl tbody td { padding: 11px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: none; }
.tbl tbody tr { transition: background-color 120ms ease; }
.tbl.is-clickable tbody tr:hover { background: var(--brand-06); cursor: pointer; }
.tbl .num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tbl th.num { text-align: right; }

/* Line-item tables fold to «description + compact meta + sum» on phones; the
   meta line is hidden on desktop, where the real columns carry the numbers. */
.tbl-lines .line-meta { display: none; }

/* Optional room/section grouping in the quote detail line table: a heading row
   per room and a discreet subtotal row. Only shown when a quote uses sections;
   an ungrouped quote renders without either. */
.tbl-lines tr.line-group-head td {
  padding-top: 16px; padding-bottom: 8px;
  font-size: 12.5px; font-weight: 600; color: var(--ink); letter-spacing: 0.01em;
  border-bottom: 1px solid var(--line-strong);
}
.tbl-lines tr.line-group-head:first-child td { padding-top: 11px; }
.tbl-lines tr.line-group-sub td {
  padding-top: 8px; padding-bottom: 12px;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 12.5px; color: var(--ink-2); text-align: right;
  border-bottom: 1px solid var(--line-strong);
}

/* ---- Status badges ------------------------------------------------------ */
/* Mono, uppercase, tight — from the Sonida design (19. august 2026). The shape
   changed from a rounded pill to a 4 px chip: every status in the design shares
   one form and one size, and only the colour pair separates them, so a row of
   them reads as a legend rather than as decoration. The mono face is the same
   one the numbers use — a status is a fact about the record, not prose. */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono);
  font-size: 9.5px; font-weight: 500; line-height: 1;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 5px 7px; border-radius: 4px; white-space: nowrap;
}
.badge-utkast   { background: var(--neutral-bg); color: var(--neutral); }
.badge-sendt    { background: var(--neutral-bg); color: var(--neutral); }
.badge-akseptert{ background: var(--ok-bg); color: var(--ok); }
.badge-avslått  { background: var(--bad-bg); color: var(--bad); }
.badge-utløpt   { background: var(--warn-bg); color: var(--warn); }
/* Withdrawn is closed, not a decision — a quiet grey like utkast. */
.badge-trukket  { background: var(--neutral-bg); color: var(--neutral); }
/* Job stage on an accepted quote. The design gives the stages their own colours
   rather than one grey chip: «Ferdig utført» is the one that needs acting on
   (the work is done, the invoice is not sent), so it carries the finished green,
   and «Under arbeid» takes the brand tint to say something is moving. The two
   ends — not started and invoiced — stay neutral, because neither asks anything
   of you today. */
.badge-steg,
.badge-steg-ikke_startet,
.badge-steg-fakturert     { background: var(--neutral-bg); color: var(--neutral); }
.badge-steg-under_arbeid  { background: var(--brand-06); color: var(--brand-ink); }
.badge-steg-ferdig        { background: var(--ok-bg); color: var(--ok); }
/* Needs follow-up: a sent quote gone quiet or about to lapse. A quiet attention
   tone (shared with utløpt); the text and the reason beside it carry the why. */
.badge-followup { background: var(--warn-bg); color: var(--warn); }

/* ---- Stamp (decided quotes: detail page, accept page) ------------------- */
.stamp {
  display: inline-block; transform: rotate(-2deg);
  font-family: var(--font-mono); font-weight: 700; font-size: 15px;
  text-transform: uppercase; letter-spacing: 0.14em;
  padding: 8px 16px; border: 2.5px solid currentColor; border-radius: 4px;
}
.stamp small { display: block; font-size: 10px; font-weight: 500; letter-spacing: 0.08em; margin-top: 2px; }
.stamp-ok { color: var(--ok); }
.stamp-bad { color: var(--bad); }
.stamp-warn { color: var(--warn); }

/* ---- Oppdrag: job-stage segmented control (accepted quotes) -------------- */
.stage-control { display: flex; flex-wrap: wrap; gap: 6px; }
.stage-btn {
  flex: 1 1 auto; min-width: 0;
  font-size: 12.5px; font-weight: 500; line-height: 1;
  padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--paper);
  color: var(--ink-2); cursor: pointer; white-space: nowrap;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.stage-btn:hover { background: var(--brand-06); border-color: var(--brand-30, var(--line)); }
.stage-btn.is-active {
  background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600;
}

/* ---- Title block (tegningshode) ----------------------------------------- */
.titleblock {
  display: grid; border: 1px solid var(--line-strong);
  border-radius: var(--radius-card); overflow: hidden; background: var(--surface);
}
.tb-cell { padding: 10px 14px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.tb-label { font-family: var(--font-mono); font-size: 10px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.09em; color: var(--ink-3); margin-bottom: 3px; }
.tb-value { font-size: 14px; font-weight: 500; }
.tb-value.font-num { font-size: 14px; }

/* A customer question is waiting for a reply, so its card wears a brand top
   rule to stand out from the calmer cards around it — on the dashboard and at
   the top of the quote. */
/* Den gamle blå toppkanten er fjernet: portalen gir kortet en blå VENSTRE-
   kant og en blå ramme, ingen stripe på tvers. Se .quest-card lenger nede. */

/* The company's own data is missing something the withdrawal forms legally
   need (address, e-post) - a fault to fix, not a notification to read, so it
   gets the warm warn background rather than the quiet quest-card treatment. */
.warn-card { border-top: 2px solid var(--warn); background: var(--warn-bg); }

/* ---- KPI tiles (dashboard) ---------------------------------------------- */
/* Målt fra portaldesignet: etiketten 10px mono med 0,14em sporing, tallet 26px
   SANS (ikke mono) med tabulære siffer og stram sporing, fotnoten 11,5px mono.
   Kortet var halvannen gang for høyt og tallet nesten dobbelt så stort før. */
.kpi { padding: 15px 17px; }
.kpi-label { font-family: var(--font-mono); font-size: 10px; font-weight: 500; line-height: 1;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink-3); }
/* Ikke tabulært: se begrunnelsen over .acc-amount. Under tabular-nums får
   kommaet full sifferbredde, og «221 336,50» leses «221 336 , 50». Et
   enkeltstående display-tall har ingen kolonne å flukte med. */
.kpi-value { font-variant-numeric: normal;
  font-size: 26px; font-weight: 500; letter-spacing: -0.04em; margin-top: 10px; line-height: 1; }
.kpi-context { font-family: var(--font-mono); font-size: 11.5px; line-height: 1.4;
  color: var(--ink-3); margin-top: 7px; }

/* Tiny stacked bar for hit rate: segments with 2px gap, text is the legend */
.minibar { display: flex; gap: 2px; height: 6px; margin-top: 10px; border-radius: 3px; overflow: hidden; }
.minibar > span { display: block; height: 100%; border-radius: 3px; min-width: 3px; }
.minibar .seg-ok { background: #2E9E68; }
.minibar .seg-bad { background: #D6604F; }

/* ---- Receipt (totals summary) ------------------------------------------- */
.receipt { padding: 18px 20px; }
.receipt-row { display: flex; justify-content: space-between; align-items: baseline;
  font-size: 13.5px; color: var(--ink-2); padding: 4px 0; }
.receipt-row .font-num { color: var(--ink); }
.receipt-total { display: flex; justify-content: space-between; align-items: baseline;
  margin-top: 10px; padding-top: 12px; border-top: 1.5px dashed var(--line-strong);
  font-weight: 600; font-size: 15px; }
.receipt-total .font-num { font-size: 18px; font-weight: 600; }
/* Quiet disclosure, not a warning - same treatment as .help. Follows the
   receipt inside the same card, so it reads as a note on the total. */
.estimate-note { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
  font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }

/* ---- Empty states (mm-paper) -------------------------------------------- */
.empty {
  border: 1.5px dashed var(--line-strong); border-radius: var(--radius-card);
  padding: 44px 24px; text-align: center; color: var(--ink-2);
  background-image:
    repeating-linear-gradient(0deg, transparent, transparent 15px, rgb(29 31 36 / 0.025) 15px, rgb(29 31 36 / 0.025) 16px),
    repeating-linear-gradient(90deg, transparent, transparent 15px, rgb(29 31 36 / 0.025) 15px, rgb(29 31 36 / 0.025) 16px);
}
.empty p { margin-bottom: 14px; }

/* mm-grid backdrop utility (login page) */
.mm-grid {
  background-image:
    repeating-linear-gradient(0deg, transparent, transparent 15px, rgb(29 31 36 / 0.03) 15px, rgb(29 31 36 / 0.03) 16px),
    repeating-linear-gradient(90deg, transparent, transparent 15px, rgb(29 31 36 / 0.03) 15px, rgb(29 31 36 / 0.03) 16px);
}

/* ---- Navigation (sidebar) ----------------------------------------------- */
/* Sonida-portalen: det aktive punktet er en FYLT pille i handlingsfargen med
   hvit tekst — ikke en tint med kantstrek. Det er den eneste fylte flaten i
   sidemenyen, så du ser hvor du er uten å lete. */
.navlink {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; font-weight: 400; line-height: 1; color: var(--ink-2);
  padding: 11px 12px; border-radius: 7px;
  transition: background-color 120ms ease, color 120ms ease;
  text-decoration: none;
}
.navlink svg { width: 17px; height: 17px; }
.navlink:hover { background: var(--brand-03); color: var(--ink); }
.navlink.is-active {
  background: var(--brand); color: #FFFFFF; font-weight: 600;
}
.navlink.is-active svg { color: #FFFFFF; }

/* ---- Toasts ------------------------------------------------------------- */
.toast {
  display: flex; align-items: center; gap: 10px;
  background: var(--ink); color: #fff; font-size: 13.5px;
  padding: 11px 16px; border-radius: 8px; box-shadow: 0 6px 20px rgb(29 31 36 / 0.18);
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
  @starting-style { opacity: 0; transform: translateY(6px); }
}
.toast.is-leaving { opacity: 0; transform: translateY(4px); transition-duration: 130ms; }
.toast-ok { background: var(--ok); }
.toast-bad { background: var(--bad); }

/* Stabelen sto som rene Tailwind-klasser («fixed bottom-6 right-6») uten
   mobilhåndtering: 24 px fra bunnen lander midt i fanelinja, og uten et tak på
   bredden vokste boksen helt ut til venstre skjermkant. */
.toast-stack {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
}
@media (max-width: 1023.98px) {
  .toast-stack {
    left: 16px; right: 16px; align-items: stretch;
    bottom: calc(69px + env(safe-area-inset-bottom));
  }
}

/* ---- Modal -------------------------------------------------------------- */
.modal-backdrop {
  position: fixed; inset: 0; background: rgb(29 31 36 / 0.42); z-index: 50;
  transition: opacity 160ms var(--ease-out);
  @starting-style { opacity: 0; }
}
.modal-panel {
  background: var(--surface); border-radius: var(--radius-card);
  box-shadow: 0 16px 48px rgb(29 31 36 / 0.22); width: 100%; max-width: 480px;
  transition: opacity 170ms var(--ease-out), transform 170ms var(--ease-out);
  @starting-style { opacity: 0; transform: scale(0.97) translateY(6px); }
}

/* ---- Filter pills -------------------------------------------------------- */
/* Sonida-designets pille (skjerm 07): den aktive er nesten-svart, ikke blå.
   Blått er handlingsfargen — en pille er et valg om hva du ser på, ikke en
   handling, og to blå flater ved siden av «Nytt tilbud» ville konkurrert.
   Tallet står i samme skrift som teksten; mono her ville gjort pilla til to
   forskjellige ting. */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 500; line-height: 1; color: var(--ink-2);
  padding: 9px 13px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface); text-decoration: none; white-space: nowrap;
  transition: border-color 120ms ease, color 120ms ease, background-color 120ms ease;
}
.pill:hover { border-color: var(--ink-3); color: var(--ink); }
.pill.is-active { background: var(--ink); border-color: var(--ink); color: #fff; }
/* Tallet er samme tekst som etiketten: samme farge, samme siffer. Fasiten
   skriver «Alle 312» som en tekstnode — verken nedtoning eller tabulære
   siffer, som hører hjemme i en tabellkolonne. */
.pill .font-num {
  font-family: var(--font-sans); font-size: 11.5px; letter-spacing: 0;
  font-variant-numeric: normal;
}

/* ---- Reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---- Additions: build package 2 ---- */
/* Internal pages only. Nothing above this marker is modified. */

/* Page head: title left, one primary action right ------------------------- */
/* Tittel til venstre, handling til høyre, på en linje — som i Sonida-portalen.
   Topplinja er hvit i designfila, men der er hele skjermbildet en mock av et
   app-vindu der sidemeny og topplinje er en sammenhengende hvit flate; i den
   ekte appen ble den en søm mot sidemenyen som aldri satt riktig (Anders,
   19. august). Tittelen ligger derfor rett på flaten.

   MERK: telefonoverstyringen lenger nede setter flex-direction: column og
   align-items: stretch. Endres denne regelen, må den fortsatt stå FØR den —
   en kopi lagt til nederst i filen slår mobilregelen og midtstiller tittelen. */
.page-head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  margin-bottom: 20px;
}
.page-title { font-size: 17px; font-weight: 600; letter-spacing: -0.03em; line-height: 1.2; }
.page-sub { font-size: 13.5px; color: var(--ink-2); margin-top: 5px; }
.page-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

.backlink {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 500; color: var(--ink-3);
  text-decoration: none; margin-bottom: 7px;
  transition: color 120ms ease;
}
.backlink:hover { color: var(--ink); }
.backlink svg { width: 14px; height: 14px; }

/* Card head: binds a title (and optional meta) to the panel below it ------- */
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 18px; border-bottom: 1px solid var(--line-soft);
}
/* Alt som er en handling i korttoppen skyves til høyre kant, uansett hvor mange
   opplysninger som står til venstre for det. */
.card-head > a:last-child { margin-left: auto; }
.card-title { font-size: 14px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.2; }
.card-meta { font-size: 12.5px; color: var(--ink-3); }

/* Toolbar row above tables (filters left, search right) ------------------- */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 16px; }
.toolbar-end { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* Search field with a leading icon ---------------------------------------- */
.search { position: relative; }
.search > svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--ink-3); pointer-events: none; }
.search .input { padding-left: 32px; }

/* Compact icon-only button ------------------------------------------------- */
.btn-icon { padding: 0; width: 30px; height: 30px; }
.btn-icon svg { width: 16px; height: 16px; }

/* Row actions reveal on hover, always visible to keyboard ----------------- */
.row-actions { display: flex; justify-content: flex-end; gap: 2px; }
@media (hover: hover) and (pointer: fine) {
  .tbl tbody tr .row-actions { opacity: 0; transition: opacity 120ms ease; }
  .tbl tbody tr:hover .row-actions,
  .tbl tbody tr:focus-within .row-actions { opacity: 1; }
}

/* Group divider row inside a table (materials by category) ---------------- */
.tbl tbody tr.row-group td {
  background: var(--paper); padding: 7px 12px;
  border-bottom: 1px solid var(--line-strong); border-top: 1px solid var(--line-strong);
}
.tbl tbody tr.row-group:first-child td { border-top: none; }
.row-group-label {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-2);
}

/* Line number gutter in document-like tables ------------------------------ */
.lineno { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; color: var(--ink-3); width: 34px; }
.linetype { font-size: 12px; color: var(--ink-3); margin-top: 1px; }

/* Editable table cell: reads as a document until touched ------------------ */
.cell-input {
  width: 100%; font-size: 13.5px; color: var(--ink);
  background: transparent; border: 1px solid transparent;
  border-radius: var(--radius-ctl); padding: 6px 8px;
  transition: border-color 130ms ease, background-color 130ms ease, box-shadow 130ms ease;
}
.cell-input::placeholder { color: var(--ink-3); }
.cell-input:hover { border-color: var(--line-strong); }
.cell-input:focus {
  outline: none; background: var(--surface);
  border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16);
}
.cell-num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* Combobox panel for material search -------------------------------------- */
.combo-panel {
  position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 4px);
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-card); box-shadow: 0 10px 30px rgb(29 31 36 / 0.12);
  max-height: 296px; overflow-y: auto; overflow-x: hidden; padding: 4px;
  transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out);
  @starting-style { opacity: 0; transform: translateY(-4px); }
}
.combo-item {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; padding: 7px 10px; border-radius: var(--radius-ctl);
  background: transparent; border: none; cursor: pointer;
  transition: background-color 100ms ease;
}
.combo-item.is-active { background: var(--brand-06); }
.combo-name { font-size: 13.5px; color: var(--ink); }
.combo-meta { font-size: 11.5px; color: var(--ink-3); font-family: var(--font-mono); }
.combo-price { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 12.5px; color: var(--ink-2); white-space: nowrap; }
.combo-empty { padding: 12px 10px; font-size: 13px; color: var(--ink-3); }

/* Form layout ------------------------------------------------------------- */
.form-section + .form-section { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--line); }
.form-legend { font-size: 13.5px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 14px; }
.field-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 14px 16px; }
.f2 { grid-column: span 2; } .f3 { grid-column: span 3; } .f4 { grid-column: span 4; }
.f5 { grid-column: span 5; } .f6 { grid-column: span 6; } .f7 { grid-column: span 7; }
.f8 { grid-column: span 8; } .f9 { grid-column: span 9; } .f12 { grid-column: span 12; }
@media (max-width: 860px) { .field-grid > * { grid-column: span 12; } }

.textarea-sm .textarea { min-height: 92px; height: 92px; }
.textarea-md .textarea { min-height: 132px; height: 132px; }
.textarea-lg .textarea { min-height: 200px; height: 200px; }

/* Native select gets the same chevron everywhere -------------------------- */
select.select {
  appearance: none; -webkit-appearance: none; padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2382878F' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; background-size: 16px 16px;
}

/* Checkbox row ------------------------------------------------------------ */
.check-row { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--ink); cursor: pointer; }
.check-row input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--brand); cursor: pointer; }
.check-row input[type="radio"] { width: 15px; height: 15px; accent-color: var(--brand); cursor: pointer; }

/* Form action row --------------------------------------------------------- */
.actionbar { display: flex; align-items: center; gap: 8px; margin-top: 18px; }
.actionbar .spacer { margin-left: auto; }

/* Copy field (accept link) ------------------------------------------------- */
.copyrow { display: flex; align-items: center; gap: 8px; }
.copyrow .input { font-family: var(--font-mono); font-size: 12.5px; }

/* KPI unit suffix ---------------------------------------------------------- */
.kpi-unit { font-size: 13px; font-weight: 400;
  color: var(--ink-3); margin-left: 4px; letter-spacing: 0; }

/* Compact empty state inside a panel --------------------------------------- */
.empty-sm { padding: 30px 20px; }
.empty-sm p { margin-bottom: 0; }

/* Stamp placement on the quote detail sheet -------------------------------- */
.stamp-slot { display: flex; justify-content: center; padding: 6px 0 2px; }

/* Sidebar identity block --------------------------------------------------- */
.side-user { display: flex; align-items: center; gap: 9px; min-width: 0; }
.side-avatar {
  width: 26px; height: 26px; border-radius: 999px; flex: none;
  display: grid; place-items: center; background: var(--brand-10); color: var(--brand);
  font-size: 11.5px; font-weight: 600; text-transform: uppercase;
}
.side-name { font-size: 12.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Login sheet -------------------------------------------------------------- */
.login-card { width: 100%; max-width: 372px; border-top: 2px solid var(--brand); }

/* File input: quiet control with a button-shaped picker --------------------- */
.filefield { font-size: 12.5px; color: var(--ink-3); }
.filefield a { color: var(--ink-2); }
input[type="file"].input { padding: 5px 8px; font-size: 13px; color: var(--ink-2); cursor: pointer; }
input[type="file"].input::file-selector-button {
  font-family: var(--font-sans); font-size: 13px; font-weight: 500; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-ctl); padding: 5px 11px; margin-right: 10px; cursor: pointer;
  transition: border-color 130ms ease, background-color 130ms ease;
}
input[type="file"].input:hover::file-selector-button { border-color: var(--ink-3); background: var(--paper); }

/* Colour swatch control ---------------------------------------------------- */
input[type="color"] { cursor: pointer; background: var(--surface); }

/* Editable line table: tighter cells so inputs get the room --------------- */
.tbl-edit thead th { padding: 9px 8px; }
.tbl-edit tbody td { padding: 5px 6px; }
.tbl-edit tbody td.lineno { padding-left: 12px; }

/* Room/section heading row in the builder: a quiet full-width band that reads
   as a subheading over the lines beneath it. Optional — a quote never using it
   never shows one. */
.tbl-edit tbody tr.line-section-row td.line-section-cell {
  background: var(--brand-06); padding: 6px 8px 6px 12px;
  border-bottom: 1px solid var(--line);
}
.line-section-inner { display: flex; align-items: center; gap: 8px; }
.line-section-tag {
  font-family: var(--font-mono); font-size: 10px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--brand);
  flex: none;
}
.line-section-input { font-weight: 600; color: var(--ink); }
.line-section-input::placeholder { font-weight: 400; }

/* Reorder controls in the builder line table -------------------------------
   Up/down arrows work on every device (the reliable, touch-friendly path); the
   grip handle is a mouse-only enrichment, gated to fine-pointer devices below.
   HTML5 drag-and-drop is inert on touch anyway, so the handle is simply hidden
   there and the arrows carry the whole feature. */
.line-reorder { display: inline-flex; flex-direction: column; gap: 1px; flex: none; }
.line-reorder button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 15px; padding: 0; border: 0; border-radius: 5px;
  background: transparent; color: var(--ink-3); cursor: pointer;
  transition: color 120ms ease, background-color 120ms ease;
}
.line-reorder button svg { width: 14px; height: 14px; }
.line-reorder button:hover:not(:disabled) { background: var(--brand-06); color: var(--ink); }
.line-reorder button:disabled { opacity: 0.3; cursor: default; }

.drag-handle { display: none; }  /* touch: the arrows are the way */
@media (hover: hover) and (pointer: fine) {
  .drag-handle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 28px; flex: none; color: var(--ink-3); cursor: grab;
    -webkit-tap-highlight-color: transparent; transition: color 120ms ease;
  }
  .drag-handle:hover { color: var(--ink-2); }
  .drag-handle:active { cursor: grabbing; }
  .drag-handle svg { width: 15px; height: 15px; }
}

/* The row being dragged, and the row it would drop onto (a quiet top rule). */
.tbl-edit tbody tr.row-dragging { opacity: 0.4; }
.tbl-edit tbody tr.row-drag-over td {
  box-shadow: inset 0 2px 0 0 var(--brand); transition: box-shadow 120ms ease;
}

/* Group rows never behave like clickable rows ----------------------------- */
.tbl.is-clickable tbody tr.row-group:hover { background: var(--paper); cursor: default; }

/* ---- Additions: drift ---- */
/* The operations panel. Nothing above this marker is modified, and nothing
   here introduces a colour: every value is an existing token. */

/* Sidebar section: hairline + label above the Drift group ------------------ */
/* padding, not margin: the nav uses Tailwind's space-y, which owns margin-top. */
/* Ingen skillestrek: designet skiller bolkene med luft, ikke med en hårlinje
   tvers over sidemenyen. */
.nav-section { margin-top: 12px; }
.nav-section-label {
  padding: 6px 12px 4px;
  font-size: 9.5px; line-height: 1; letter-spacing: 0.14em;
}

/* Status card: dot + label + value + one short sentence -------------------- */
.statuscard { display: flex; align-items: flex-start; gap: 11px; padding: 14px 16px; }
.status-dot {
  width: 9px; height: 9px; border-radius: 999px; flex: none; margin-top: 5px;
  background: var(--line-strong);
}
.status-dot.is-ok { background: var(--ok); }
.status-dot.is-warn { background: var(--warn); }
.status-dot.is-bad { background: var(--bad); }
/* Fourth state, on purpose: «ikke satt opp her» is neither good nor a fault
   (no backup directory on a laptop, no SMTP configured yet). Same grey as the
   bare .status-dot above, written out so the intent is not read as a fallback
   for a typo in the state name. */
.status-dot.is-neutral { background: var(--line-strong); }
.statuscard-label {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3);
}
.statuscard-value { font-size: 14.5px; font-weight: 600; letter-spacing: -0.01em; margin-top: 3px; }
.statuscard-note { font-size: 12.5px; color: var(--ink-2); margin-top: 3px; }

/* Level badge on log rows (never colour alone - the word is the label) ----- */
.lvl {
  display: inline-block; font-family: var(--font-mono);
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 4px; white-space: nowrap;
}
.lvl-info { background: #EFEDE9; color: #4F545D; }
.lvl-warn { background: var(--warn-bg); color: var(--warn); }
.lvl-bad  { background: var(--bad-bg); color: var(--bad); }

/* Role and state badges reuse the badge shape ----------------------------- */
.badge-brand { background: var(--brand-10); color: var(--brand); }
.badge-ok    { background: var(--ok-bg); color: var(--ok); }
.badge-muted { background: #EFEDE9; color: #4F545D; }
/* Delivery-signal dot: a quiet, PII-free marker of what became of the quote on
   its way to the customer. In the list it follows the status badge with its
   meaning in the title attribute; in the detail title block it leads the label
   text. Inline and vertically centred; the tones reuse the status tokens. */
.sig-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 999px;
  vertical-align: middle; background: var(--line-strong);
}
.sig-dot.is-ok { background: var(--ok); }
.sig-dot.is-bad { background: var(--bad); }
.sig-dot.is-neutral { background: var(--line-strong); }

/* Log rows ---------------------------------------------------------------- */
.log-time { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 12px; color: var(--ink-3); white-space: nowrap; }
.log-message { font-family: var(--font-mono); font-size: 12.5px; line-height: 1.5; word-break: break-word; }
.log-logger { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-3); }
.log-trace {
  font-family: var(--font-mono); font-size: 12px; line-height: 1.5;
  white-space: pre-wrap; overflow-x: auto; color: var(--ink-2);
  border: 1px solid var(--line); border-radius: var(--radius-ctl);
  background: var(--paper); padding: 12px 14px; margin-top: 10px;
}
.log-expand {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 500; color: var(--ink-3);
  background: none; border: none; cursor: pointer; padding: 0;
  transition: color 120ms ease;
}
.log-expand:hover { color: var(--ink); }
.log-expand svg { width: 13px; height: 13px; transition: transform 150ms var(--ease-out); }
.log-expand.is-open svg { transform: rotate(180deg); }

/* Actor chip on activity rows --------------------------------------------- */
.actor { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.ava {
  width: 22px; height: 22px; border-radius: 999px; flex: none;
  display: grid; place-items: center; background: var(--brand-10); color: var(--brand);
  font-size: 10.5px; font-weight: 600; text-transform: uppercase;
}
.ava-system { background: #EFEDE9; color: #4F545D; }
.actor-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Detail chips under an activity row -------------------------------------- */
.detail-chip {
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-3);
  border: 1px solid var(--line); border-radius: 4px; padding: 1px 6px; white-space: nowrap;
}

/* Pagination --------------------------------------------------------------- */
.pager { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 16px; }
.pager-info { font-size: 12.5px; color: var(--ink-3); }
.pager-links { display: flex; gap: 8px; }

/* Quiet note under a panel (retention, automatic jobs) --------------------- */
.note-quiet { font-size: 12.5px; color: var(--ink-3); }

/* ---- Bedrifter (Drift) --------------------------------------------------- */
/* Logo thumbnail in the company list. A company without a logo gets its own
   initial in the brand tint rather than an empty box - the row must never
   look broken just because the profile is not finished yet. */
.logo-thumb {
  width: 30px; height: 30px; border-radius: 6px; flex: none; overflow: hidden;
  display: grid; place-items: center;
  background: var(--brand-10); color: var(--brand);
  border: 1px solid var(--line);
  font-size: 12px; font-weight: 600; text-transform: uppercase;
}
.logo-thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Samme grep som .login-brandmark.has-logo: en vanlig, bred logo (384 x 121)
   klemt inn i 30 x 30 ble 30 x 9,5 px grå grøt ved siden av knivskarpe
   bokstavfliser. Logoen får bredde og beholder sitt eget forhold. Hvit bunn,
   ikke merketonen: den snur med bedriftsfargen. */
.logo-thumb.has-logo {
  width: auto; max-width: 60px; padding: 0 5px; background: #fff;
}
.logo-thumb.has-logo img { max-height: 22px; max-width: 50px; }
/* Merkefeltet er like bredt i alle radene, ellers ville bedriftsnavnet i
   logo-raden startet 30 px lenger inne enn i bokstavflis-radene — ett avvik
   byttet mot et annet. Flisen står til venstre i feltet, som før. */
@media (min-width: 768px) {
  .dr-companies .rowlink {
    display: grid; grid-template-columns: 60px minmax(0, 1fr); gap: 10px;
  }
  .dr-companies .rowlink > .logo-thumb { justify-self: start; }
}

/* The whole first cell is the link into the company. */
.rowlink { display: inline-flex; align-items: center; gap: 10px; min-width: 0; color: inherit; text-decoration: none; }
.rowlink:hover .actor-name { color: var(--brand); }

/* Company chip on a global activity row ------------------------------------ */
.company-chip {
  font-size: 11.5px; color: var(--ink-2);
  background: var(--brand-06); border: 1px solid var(--line);
  border-radius: 999px; padding: 2px 8px; white-space: nowrap;
}

/* ---- Vendor inside a company --------------------------------------------- */
/* The one piece of chrome that says «you are not where you normally are».
   Sticky at the top of the content column so it survives scrolling, brand
   tinted so it reads as the company's colour, and quiet enough not to be
   mistaken for an error. Members never see it: they cannot be anywhere else. */
.vendorbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 8px 32px;
  background: var(--brand-10);
  border-bottom: 1px solid var(--brand-30);
  font-size: 12.5px; color: var(--ink);
}
.vendorbar strong { font-weight: 600; }

.verifybar {
  /* Not sticky like .vendorbar above: the two can appear stacked at once (a
     vendor entering a company it created for itself before verifying), and a
     second `position: sticky; top: 0` sibling would fight the first one on
     scroll rather than stack cleanly under it. */
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap;
  padding: 8px 32px;
  background: var(--warn-bg);
  border-bottom: 1px solid color-mix(in srgb, var(--warn) 40%, white);
  font-size: 12.5px; color: var(--ink);
}
.verifybar strong { font-weight: 600; }

/* ==========================================================================
   ---- Additions: mobile + PWA ----
   Everything below this marker is ADDITIVE. Desktop (>= 1024px / lg) is
   unchanged: every phone element is display:none by default and only switched
   on under a max-width breakpoint. Breakpoints follow DESIGN.md / Tailwind:
   phone chrome flips at lg (1024px), tables become cards at md (768px).
   Reflow, don't restyle — the Arbeidstegning tokens above are reused as-is.
   apple-design mechanics: 44px+ targets, translucent chrome with
   backdrop-filter + safe-area insets, spring sheets, :active feedback,
   prefers-reduced-motion honoured (the global rule near the top covers motion).
   ========================================================================== */

/* Phone chrome and the pull-to-refresh badge are off on desktop. */
.app-topbar,
.app-mobilenav,
.quote-summarybar { display: none; }

.ptr-indicator {
  position: fixed; top: 0; left: 50%; z-index: 55;
  transform: translateX(-50%) translateY(-46px); opacity: 0;
  margin-top: env(safe-area-inset-top);
  width: 40px; height: 40px; border-radius: 999px;
  display: grid; place-items: center; pointer-events: none;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 4px 14px rgb(29 31 36 / 0.12); color: var(--ink-2);
}
.ptr-indicator .ptr-spinner { width: 20px; height: 20px; }
.ptr-indicator.is-loading .ptr-spinner { animation: ptr-spin 0.8s linear infinite; }
@keyframes ptr-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Notifications (Varsler): the unread badge in the chrome + the push prompt.
   The badge wears the brand tint so it stays on-system and white-label safe.
   ========================================================================== */
/* Sidebar «Varsler» count (desktop). Pushed to the right edge of the navlink. */
.nav-badge {
  margin-left: auto; flex: none;
  min-width: 18px; padding: 4px 7px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; line-height: 1;
  color: #fff; background: var(--brand); border-radius: 999px;
}
.navlink.is-active .nav-badge { background: var(--brand); }

/* Feed rows: an unread row carries a brand dot and a faint brand wash. */
.notif-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; border-bottom: 1px solid var(--line);
  text-decoration: none; color: var(--ink);
  transition: background-color 120ms ease;
}
.notif-row:last-child { border-bottom: 0; }
.notif-row:hover { background: var(--brand-06); }
.notif-icon { flex: none; width: 34px; height: 34px; border-radius: 999px;
  display: grid; place-items: center; background: var(--brand-06); color: var(--brand); }
.notif-icon svg { width: 18px; height: 18px; }
.notif-main { min-width: 0; flex: 1; }
.notif-text { font-size: 14px; font-weight: 500; }
.notif-meta { font-family: var(--font-mono); font-size: 11px; color: var(--ink-3); margin-top: 2px; }
.notif-dot { flex: none; width: 8px; height: 8px; border-radius: 999px; background: var(--brand); margin-top: 6px; }
.notif-row.is-read { color: var(--ink-2); }
.notif-row.is-read .notif-icon { background: var(--paper); color: var(--ink-3); }
.notif-row.is-unread { background: color-mix(in srgb, var(--brand) 4%, transparent); }

/* Push permission prompt: a subtle, dismissible card. Off until JS reveals it. */
.push-prompt {
  position: fixed; z-index: 56; left: 16px; right: 16px; bottom: 16px;
  max-width: 380px; margin-left: auto;
  bottom: calc(16px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 12px;
  padding: 14px 16px; border-radius: var(--radius-card);
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 10px 34px rgb(29 31 36 / 0.16);
}
.push-prompt[hidden] { display: none; }
.push-prompt-body { display: flex; align-items: flex-start; gap: 12px; }
.push-prompt-icon { flex: none; width: 34px; height: 34px; border-radius: 999px;
  display: grid; place-items: center; background: var(--brand-06); color: var(--brand); }
.push-prompt-icon svg { width: 18px; height: 18px; }
.push-prompt-title { font-size: 14px; font-weight: 600; }
.push-prompt-sub { font-size: 13px; color: var(--ink-2); margin-top: 2px; }
.push-prompt-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* The app shell owns its own padding — never a Tailwind `p-*` utility. The
   Tailwind Play CDN injects its CSS AFTER app.css, so a padding utility on the
   shell would win the cascade and silently override the phone padding below
   (which clears the fixed bottom tab bar). Every page renders inside
   .app-content, so owning the padding here fixes the overlap for all pages,
   present and future. Desktop keeps the 2rem it always had. */
.app-content { padding: 2rem; }

/* ==========================================================================
   Phone layout (< lg / 1024px): sidebar off, top bar + bottom tab bar on.
   ========================================================================== */
@media (max-width: 1023.98px) {
  .app-sidebar { display: none !important; }

  /* Translucent top bar: company mark left, page context right. */
  .app-topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    position: sticky; top: 0; z-index: 30;
    /* Solid and transform-free on purpose. A frosted (backdrop-filter) bar
       repaints only when scrolling settles on iOS WebKit and appears to float
       mid-content during momentum scroll — so the bar is opaque. And it carries
       NO transform: a `transform` (even translateZ(0)) on a fixed/sticky bar is
       an iOS foot-gun that makes it scroll with the page. Opaque + no transform
       is the combination that stays pinned on iOS. */
    min-height: 52px; padding: 8px 16px;
    padding-top: calc(8px + env(safe-area-inset-top));
    background: var(--surface);
    border-bottom: 1px solid var(--line);
  }
  .app-topbar-mark { display: flex; align-items: center; min-width: 0; text-decoration: none; color: var(--ink); }
  .app-topbar-mark img { max-height: 26px; max-width: 150px; width: auto; display: block; }
  .app-topbar-name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .app-topbar-context {
    font-family: var(--font-mono); font-size: 11px; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3); white-space: nowrap;
  }
  /* Right cluster: page context + the notification bell. */
  .app-topbar-end { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .app-topbar-bell {
    position: relative; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    /* 44x44, ikke 40: minste trykkflate på berøring. Den negative margen
       vokser fra -6 til -8 så ikonet står optisk på samme sted som før -
       glyfen er 22 px, resten er luft rundt fingeren. */
    width: 44px; height: 44px; margin-right: -8px;
    color: var(--ink-2); border-radius: var(--radius-ctl);
    -webkit-tap-highlight-color: transparent;
  }
  .app-topbar-bell svg { width: 22px; height: 22px; }
  .app-topbar-bell:active { background: var(--brand-06); }
  .topbar-badge {
    position: absolute; top: 3px; right: 3px;
    min-width: 16px; height: 16px; padding: 0 4px;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-mono); font-size: 10px; font-weight: 700; line-height: 1;
    color: #fff; background: var(--brand); border-radius: 999px;
    border: 1.5px solid var(--surface);
  }

  /* Content clears the fixed bottom tab bar (+ safe area). */
  .app-content {
    padding: 18px 16px;
    padding-bottom: calc(58px + env(safe-area-inset-bottom) + 18px);
  }

  /* Telefonen har allerede en topplinje med bedriftsnavn og bjelle, så sidens
     egen tittel trenger mindre luft under seg her. */
  .page-head { margin-bottom: 16px; }

  /* The vendor bar stops being sticky so it doesn't fight the top bar. */
  .vendorbar { position: static; padding-left: 16px; padding-right: 16px; }
  .verifybar { padding-left: 16px; padding-right: 16px; }

  /* ---- Bottom tab bar (max 5, translucent, safe-area) ------------------ */
  .app-mobilenav { display: block; }
  .app-tabbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
    /* Solid AND transform-free (see .app-topbar). Opaque so a blurred layer
       cannot lag mid-content on iOS, and with NO transform: a `transform` — even
       translateZ(0) — on a `position: fixed` element is an iOS WebKit foot-gun
       that makes the bar scroll with the page instead of staying pinned to the
       bottom edge (the «floating menu» this repeatedly caused). */
    display: grid; grid-template-columns: repeat(5, 1fr);
    background: var(--surface);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .app-tabbar .tab {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    min-height: 52px; padding: 7px 4px 6px;
    font-size: 10px; font-weight: 500; letter-spacing: 0.01em; color: var(--ink-3);
    background: none; border: 0; cursor: pointer; text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: color 120ms ease, transform 120ms var(--ease-out);
  }
  .app-tabbar .tab svg { width: 22px; height: 22px; }
  .app-tabbar .tab.is-active { color: var(--brand); }
  .app-tabbar .tab:active { transform: scale(0.94); }

  /* ---- «Mer» bottom sheet ---------------------------------------------- */
  .sheet-backdrop { position: fixed; inset: 0; z-index: 48; background: rgb(29 31 36 / 0.42); }
  .sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 49;
    background: var(--surface);
    border-top-left-radius: 18px; border-top-right-radius: 18px;
    box-shadow: 0 -12px 40px rgb(29 31 36 / 0.22);
    padding-bottom: env(safe-area-inset-bottom);
    max-height: 82vh; overflow-y: auto;
  }
  /* Arket glir opp fra kanten det ligger på. Klassene er referert fra
     templates/base.html siden arket ble bygget, men reglene har aldri stått
     her - Alpine la på fire klasser som ikke gjorde noe, og arket blinket fram.

     translateY i PROSENT, ikke piksler: arket har ingen fast høyde, og 100%
     er nøyaktig dets egen, uansett hvor mange rader menyen har.

     Utgangen er raskere enn inngangen (180 mot 260). Man venter gjerne på at
     noe skal komme; man venter aldri på at det skal gå.

     prefers-reduced-motion dekkes av den globale regelen øverst i fila. */
  .sheet-enter       { transition: transform 260ms var(--ease-out); }
  .sheet-enter-start { transform: translateY(100%); }
  .sheet-leave       { transition: transform 180ms var(--ease-out); }
  .sheet-leave-start { transform: translateY(0); }
  .sheet-leave-end   { transform: translateY(100%); }

  .sheet-grip { width: 40px; height: 4px; border-radius: 999px; background: var(--line-strong); margin: 9px auto 2px; }
  .sheet-body { padding: 6px 12px 14px; }
  .sheet-label { padding: 13px 12px 3px; }
  .sheet-item {
    display: flex; align-items: center; gap: 13px; width: 100%;
    min-height: 50px; padding: 12px; border-radius: var(--radius-ctl);
    font-size: 15px; font-weight: 500; color: var(--ink); text-decoration: none;
    background: none; border: 0; cursor: pointer; text-align: left;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 120ms ease;
  }
  .sheet-item svg { width: 20px; height: 20px; color: var(--ink-2); flex: none; }
  .sheet-item.is-active { color: var(--brand); background: var(--brand-06); }
  .sheet-item.is-active svg { color: var(--brand); }
  .sheet-item:active { background: var(--brand-06); }
  .sheet-item-quiet { color: var(--ink-2); }
  .sheet-foot { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
  .sheet-foot form { width: 100%; }
  /* Samme signatur som sidemenyens .side-foot-by - ikke .tech-label, som ville
     satt navnet i versaler og dermed sluppet ordmerket. */
  .sheet-credit {
    padding: 12px 12px 4px;
    font-family: var(--font-mono);
    font-size: 11px; font-weight: 400; line-height: 1.4;
    text-transform: none; letter-spacing: 0;
    color: var(--ink-3);
  }

  /* Shared spring transitions for the sheets (Alpine x-transition classes). */
  .sheet-t { transition: transform 260ms var(--ease-out), opacity 200ms ease; }
  .sheet-t-out { transition: transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 160ms ease; }
  .sheet-hidden { transform: translateY(100%); opacity: 0; }
  .sheet-shown { transform: translateY(0); opacity: 1; }

  /* ---- Touch-friendly controls (16px kills the iOS focus-zoom) --------- */
  .input, .select, .textarea { font-size: 16px; min-height: 44px; }
  .btn { min-height: 44px; }
  .btn-icon { width: 40px; height: 40px; min-height: 40px; }
  /* Reorder arrows: taller for the thumb, still compact enough for the row. */
  .line-reorder button { width: 30px; height: 21px; }
  .line-reorder button svg { width: 16px; height: 16px; }
  .check-row input[type="checkbox"] { width: 20px; height: 20px; }
  .check-row input[type="radio"] { width: 20px; height: 20px; }
  .combo-item { min-height: 44px; }
  select.select { min-height: 44px; }
  input[type="file"].input { min-height: 44px; }

  /* Modals dock to the bottom as full-width sheets. */
  .modal-backdrop { align-items: flex-end !important; padding: 0 !important; }
  /* Taket og den indre rullinga er ikke pynt: arket er festet til BUNNEN, så et
     panel som er høyere enn skjermen vokser oppover og ut av den — og siden
     bakteppet er position:fixed er det ingen sideruling som henter det ned
     igjen. Da forsvinner hodet med tittelen og Lukk-knappen, mens Avbryt og
     Lagre blir stående pent nederst; det ser helt friskt ut, og du oppdager det
     ikke før du leter etter krysset. Målt: «Lagre som vare» ble 594 px på en
     320x568-skjerm og la de øverste 26 px utenfor. Skjermen trenger ikke være
     liten for at dette slår til — Android krymper viewporten når tastaturet
     kommer opp, og da gjør ethvert skjema med noen felt i det samme.
     dvh og ikke vh: vh måler skjermen som om adresselinja var borte. */
  .modal-panel {
    max-width: none; width: 100%;
    max-height: 92dvh; overflow-y: auto;
    border-radius: 18px 18px 0 0;
    padding-bottom: calc(20px + env(safe-area-inset-bottom));
  }

  /* ---- Quote builder: single column + sticky summary bar --------------- */
  /* The desktop right-column receipt and the save/cancel block are replaced
     by a sticky bottom summary bar; the discount card stays in flow. */
  .quote-receipt-desk, .quote-actions-desk { display: none; }
  /* Room to scroll the last lines clear of BOTH the summary bar and tab bar. */
  .quote-form { padding-bottom: calc(150px + env(safe-area-inset-bottom)); }

  .quote-summarybar { display: block; }
  .qs-bar {
    position: fixed; left: 0; right: 0; z-index: 44;
    bottom: calc(52px + env(safe-area-inset-bottom));
    display: flex; align-items: stretch; gap: 10px;
    padding: 9px 14px;
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    -webkit-backdrop-filter: saturate(1.7) blur(14px);
    backdrop-filter: saturate(1.7) blur(14px);
    border-top: 1px solid var(--line-strong);
  }
  .qs-total {
    flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
    background: none; border: 0; padding: 4px 2px; cursor: pointer; text-align: left;
    -webkit-tap-highlight-color: transparent;
  }
  .qs-total-label {
    font-family: var(--font-mono); font-size: 10px; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3);
  }
  .qs-total-value { display: flex; align-items: center; gap: 6px; font-size: 18px; font-weight: 600; color: var(--ink); }
  .qs-total-value .font-num { font-size: 18px; }
  /* Sjevronen er søsken til tallet, ikke barn av det (se form.html) — derfor
     `.qs-total svg` og ikke `.qs-total-value svg`. */
  .qs-total svg { width: 15px; height: 15px; color: var(--ink-3); transition: transform 180ms var(--ease-out); }
  .qs-total[aria-expanded="true"] svg { transform: rotate(180deg); }
  .qs-save { flex: none; min-width: 108px; }

  .qs-backdrop { position: fixed; inset: 0; z-index: 48; background: rgb(29 31 36 / 0.42); }
  .qs-sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 49;
    background: var(--surface);
    border-top-left-radius: 18px; border-top-right-radius: 18px;
    box-shadow: 0 -12px 40px rgb(29 31 36 / 0.22);
    padding: 0 18px calc(20px + env(safe-area-inset-bottom));
  }
  .qs-sheet-body { padding-top: 4px; }
}

/* ==========================================================================
   Tables -> cards (< md / 768px). Opt-in via .tbl-cards: the <table> markup is
   kept (DRY), each row becomes a card and each cell a labelled line via
   data-label. Desktop and >= md render the normal table.
   ========================================================================== */
@media (max-width: 767.98px) {
  table.tbl-cards,
  table.tbl-cards thead,
  table.tbl-cards tbody,
  table.tbl-cards tr,
  table.tbl-cards td { display: block; width: 100%; }

  /* Header row is gone; its labels live on each cell via ::before. */
  table.tbl-cards thead { display: none; }

  table.tbl-cards tbody tr {
    border: 1px solid var(--line); border-radius: var(--radius-card);
    background: var(--surface); box-shadow: var(--shadow-1);
    padding: 4px 14px; margin-bottom: 10px;
  }
  table.tbl-cards.is-clickable tbody tr { cursor: pointer; transition: background-color 120ms ease; }
  table.tbl-cards.is-clickable tbody tr:active { background: var(--brand-06); }

  table.tbl-cards tbody td {
    display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
    padding: 9px 0; border-bottom: 1px solid var(--line);
    text-align: right; white-space: normal; min-height: 0;
  }
  table.tbl-cards tbody td:last-child { border-bottom: none; }
  /* En celle uten verdi er en kolonne på skrivebordet, men en hel etikettlinje
     på telefon. På en vanlig «hrs logget inn» var tre av seks linjer «–», og
     aktivitetsloggen ble 15 800 px lang av tomme streker. */
  table.tbl-cards tbody td.is-blank { display: none; }
  table.tbl-cards tbody td::before {
    content: attr(data-label);
    font-family: var(--font-mono); font-size: 10px; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3);
    text-align: left; white-space: nowrap; flex: none;
  }
  /* Amount cell reads as the headline of the card. */
  table.tbl-cards tbody td.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

  /* Cells with no data-label (actions, spacer columns) go full-width right. */
  table.tbl-cards tbody td:not([data-label]) { justify-content: flex-end; }
  table.tbl-cards tbody td:not([data-label])::before { content: none; }

  /* The reveal-on-hover row actions are always shown as a card footer. */
  table.tbl-cards tbody tr .row-actions { opacity: 1 !important; gap: 6px; }
  table.tbl-cards tbody td .row-actions .btn-icon { width: 40px; height: 40px; }

  /* Group divider rows (materials by category) become a plain section label. */
  table.tbl-cards tbody tr.row-group {
    border: none; background: none; box-shadow: none;
    padding: 6px 2px 2px; margin: 4px 0 0;
  }
  table.tbl-cards tbody tr.row-group td { padding: 0; border: none; display: block; text-align: left; }
  table.tbl-cards tbody tr.row-group td::before { content: none; }

  /* A wide diagnostic table that is not opted-in scrolls inside its own box. */
  .tbl-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* 820, ikke 560: systemloggen er den ene tabellen som ruller sidelengs i
     stedet for å folde seg til kort (en kuttet traceback er verdiløs). Med 560
     — knapt bredere enn telefonen — ble MELDING-kolonnen klemt til ~60 px, og
     teksten rant ned som en stripe på fem tegn. Sidelengsrullingen skal gi en
     lesbar linje, ikke bare en bredere tabell. */
  .tbl-scroll > table { min-width: 820px; }

  /* Stack the page head so the title gets its own full-width row instead of
     being crushed to a sliver beside the wrapping action buttons. */
  .page-head { flex-direction: column; align-items: stretch; gap: 12px; }
  .page-actions { width: 100%; }

  /* Line-item tables (quote detail): fold Nr/Type/Antall/Enhet/Enhetspris into
     one compact meta line under the description, keeping only Beskrivelse + Sum
     — the same tight two-line shape the public accept page uses, instead of a
     tall labelled card per line. */
  .tbl-lines .c-nr, .tbl-lines .c-type, .tbl-lines .c-qty,
  .tbl-lines .c-unit, .tbl-lines .c-price { display: none; }
  .tbl-lines tbody td { vertical-align: top; }
  .tbl-lines td.c-sum { white-space: nowrap; }
  .tbl-lines .line-meta {
    display: block; margin-top: 3px;
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    font-size: 12px; color: var(--ink-2);
  }

  /* List tables: any column tagged .sm-hide drops out on phones so each card
     stays a short glance, not a tall stack of every field. */
  table.tbl-cards tbody td.sm-hide { display: none; }

  /* Toolbars stack and their fixed-width search fields go full width, so a
     300px input never pushes the page past the viewport. */
  .toolbar { flex-direction: column; align-items: stretch; }
  /* Stack the filter form so the search field gets a full row instead of being
     squeezed on one line between the checkbox and the button (which clipped its
     placeholder). */
  .toolbar-end { margin-left: 0; flex-direction: column; align-items: stretch; }
  .toolbar form { width: 100%; }
  .toolbar .search { width: 100%; }
  .toolbar .search .input,
  .toolbar .input[type="search"] { width: 100%; }
}

/* === Åpnings-tidslinje (pakke A) === */
/* Sendinger-kortet på tilbudsdetaljen (internt skall). Lagt til additivt:
   ingenting over denne markøren er endret. Linjen «Tilbudslenken åpnet …» er
   en knapp som folder ut når hver åpning skjedde - tidspunkt og antall, aldri
   hvem eller hvorfra (PRIVACY.md). */

.link-opens-toggle {
  display: flex; align-items: baseline; gap: 6px; width: 100%;
  margin: 0; padding: 0; border: none; background: none;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.link-opens-toggle svg {
  width: 13px; height: 13px; flex: none; color: var(--ink-3);
  transition: transform 200ms var(--ease-out);
}
.link-opens-toggle.is-open svg { transform: rotate(180deg); }
@media (hover: hover) and (pointer: fine) {
  .link-opens-toggle:hover svg { color: var(--ink-2); }
}

/* The unfold itself: a quiet margin note beside the line it belongs to. */
.link-opens { margin-top: 8px; padding-left: 10px; border-left: 1px solid var(--line); }
.link-opens-day + .link-opens-day { margin-top: 8px; }
.link-opens-label {
  font-family: var(--font-mono); font-size: 10px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3);
}
.link-opens-times {
  display: flex; flex-wrap: wrap; gap: 3px 12px;
  margin-top: 2px; font-size: 12.5px; color: var(--ink-2);
}
.link-opens-note { margin-top: 10px; font-size: 12px; color: var(--ink-3); }

/* === Meldingstråd (pakke B) === */
/* Delt av BEGGE skall: akseptsiden (offentlig, kun app.css) og tilbudsdetaljen
   (internt). Derfor ingen Alpine-avhengighet og ingen Tailwind her - klassene må
   stå på egne ben på den offentlige flaten. Lagt til additivt: ingenting over
   denne markøren er endret.

   Arbeidstegning-ånd: radene er dokumentlinjer - avsender, tidspunkt og tekst
   under hverandre, skilt av hårstreker, med en diskré aksentkant på ens EGNE
   meldinger (kundens egne på akseptsiden, bedriftens egne på detaljsiden). Ingen
   fargede chatbobler. Bevegelse: ingen ny - send-knappene er husets .btn, som
   allerede har `:active { transform: scale(0.98) }` med en eksplisitt
   transform-transition (og den globale prefers-reduced-motion-regelen over
   slår den av). */

/* Kortet rundt tråden på den offentlige akseptsiden (samme rytme som .decide). */
.msg-card { margin-top: 24px; }
.msg-heading-row { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; }
.msg-heading { font-size: 16px; font-weight: 600; margin: 0; }
/* «Nytt svar»: samme diskré grå «Nytt»-badge som resten av produktet bruker for
   et ulest varsel (aldri en varselfarge) — se badge-utkast på dashbordet og
   tilbudsdetaljen. Vises kun til kunden faktisk har åpnet siden en gang etter
   svaret, se has_new_company_reply i core/views/accept.py. */

.msg-thread { list-style: none; margin: 0; padding: 0; }
.msg-row { padding: 12px 0 12px 12px; border-left: 2px solid var(--line); }
.msg-row + .msg-row { border-top: 1px solid var(--line); }
/* Ens egne meldinger: samme rad, bare merket i kanten. */
.msg-row.is-own { border-left-color: var(--brand); }

.msg-meta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 10px; margin: 0;
}
.msg-from { font-size: 13px; font-weight: 600; color: var(--ink); }
.msg-time { font-size: 11.5px; color: var(--ink-3); }
.msg-text {
  margin: 5px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--ink);
  white-space: pre-line; overflow-wrap: anywhere;
}
.msg-seen { margin: 6px 0 0; font-size: 11.5px; color: var(--ink-3); }

/* Skrivefeltet under siste linje i tråden. Streken/mellomrommet skal kun
   skille skjemaet FRA tråden - uten en tråd over (tom tråd, elektrikerens
   disclosure-skjema for å STARTE en samtale) ville den tegnet en løs strek
   rett under korthodet i stedet. */
.msg-form { max-width: 420px; }
.msg-thread + .msg-form { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.msg-form .textarea { width: 100%; }
.msg-form .btn-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.msg-fallback { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.msg-closed { margin: 16px 0 0; font-size: 12.5px; color: var(--ink-3); }

/* Telefon: full bredde og 16px i feltet, så iOS ikke zoomer inn ved fokus. */
@media (max-width: 640px) {
  .msg-form { max-width: none; }
  .msg-form .textarea { font-size: 16px; }
  .msg-form .btn-row .btn { width: 100%; min-height: 46px; }
  /* Tom tråd på akseptsiden bruker fortsatt disclosure-skjemaet. Det lå før inne
     i beslutnings-kortet og arvet berøringsmålene derfra; nå står det i sitt eget
     kort og trenger de samme målene her. */
  .msg-card .question-form { max-width: none; }
  .msg-card .question-form .textarea { font-size: 16px; }
  .msg-card .btn-row .btn { width: 100%; min-height: 46px; }
}

/* === Akseptbevis (tilbudsdetaljen, kun på et akseptert tilbud) === */
/* Samme rolige chevron-utfoldingsidiom som åpnings-tidslinjen over, men på
   egne klasser: de to funksjonene deler ikke selectors, så ingen kan
   utilsiktet endre den andre. */
.evidence-block + .evidence-block {
  margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line);
}
.evidence-consent { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.evidence-sig {
  flex: none; display: block; max-width: 180px; max-height: 72px;
  width: auto; height: auto; border-bottom: 1px solid var(--line); padding-bottom: 6px;
}

.evidence-toggle {
  display: flex; align-items: baseline; gap: 6px; width: 100%;
  margin: 0; padding: 0; border: none; background: none;
  font: inherit; font-weight: 500; color: inherit; text-align: left; cursor: pointer;
}
.evidence-toggle svg {
  width: 13px; height: 13px; flex: none; color: var(--ink-3);
  transition: transform 200ms var(--ease-out);
}
.evidence-toggle.is-open svg { transform: rotate(180deg); }
@media (hover: hover) and (pointer: fine) {
  .evidence-toggle:hover svg { color: var(--ink-2); }
}

.evidence-panel {
  margin-top: 10px; padding-left: 10px; border-left: 1px solid var(--line);
  font-size: 13px; line-height: 1.6; color: var(--ink-2);
}
.evidence-panel p { margin: 0 0 8px; }
.evidence-panel p:last-child { margin-bottom: 0; }

/* ---- Dashbord: todelt hovedområde + «Verdt å vite» ---------------------- */
/* Fra Sonida-designet, 19. august 2026. «Venter på svar» er sidens tyngste
   liste og får den brede spalten; «Under arbeid» og «Verdt å vite» er korte og
   deler den smale. Under 1100 px stables de, som på telefonen i designet.

   Merk: her brukes IKKE Tailwinds grid-utilities. Skallet eier sin egen layout
   (samme regel som .app-content, se kommentaren over den) — Tailwind injiseres
   etter app.css, så en konkurrerende utility ville vunnet kaskaden i stillhet. */
/* Kortene står i en kolonne med 13 px mellom seg, som i designet — avstanden
   eies av flaten, ikke av margin-bottom på hvert kort. */
#innhold-stabel { display: flex; flex-direction: column; gap: 13px; }
.dash-split { display: grid; grid-template-columns: 1fr; gap: 13px; }
.dash-col { min-width: 0; display: flex; flex-direction: column; gap: 13px; }
@media (min-width: 1100px) {
  .dash-split { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}

/* ---- Kom i gang --------------------------------------------------------- */
/* Den ferske bedriftens vei: varer → satser → første tilbud. Samme kortstil som
   resten av dashbordet (.card gir flate, kant og radius) — dette er bare
   innmaten.

   INGEN transition og ingen animasjon noe sted i blokka, med vilje: kortet står
   på en flate som leses mange ganger om dagen, og bevegelse på en slik flate
   blir fort noe man venter på i stedet for noe man legger merke til. Hover er
   en ren fargeendring uten overgang. */
.kig { padding: 15px 18px; }
.kig-head { display: flex; align-items: baseline; gap: 10px; }
/* Framdriften er en opplysning, ikke en poengsum: liten, grå, ytterst. Mono og
   tabulær som alle tall i huset, så «1 av 3» og «2 av 3» ikke skifter bredde. */
.kig-count {
  margin-left: auto;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11px; color: var(--ink-3); white-space: nowrap;
}
.kig-lead { margin-top: 7px; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
/* list-style og padding nullstilles her og ikke overlates til Tailwinds
   preflight: den lastes etter app.css, men på elementvelger — og en dag den
   ikke er der, ville lista fått både et punktum-nummer og vårt eget merke. */
.kig-list {
  margin-top: 13px; padding-left: 0; list-style: none;
  display: flex; flex-direction: column; gap: 11px;
}
.kig-step { display: flex; gap: 10px; align-items: flex-start; }
/* Merket: nummeret mens det gjenstår, haken når det er gjort. Samme diameter i
   begge tilstander, så lista ikke rykker når et steg blir ferdig. */
.kig-mark {
  flex: none;
  width: 19px; height: 19px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  margin-top: 1px;
  border: 1px solid var(--line-strong);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 10.5px; color: var(--ink-3);
}
.kig-step.is-done .kig-mark {
  border-color: transparent; background: var(--ok-bg); color: var(--ok);
}
.kig-mark svg { width: 11px; height: 11px; }
.kig-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kig-title { font-size: 13px; font-weight: 600; color: var(--ink); text-decoration: none; }
a.kig-title:hover { color: var(--brand); text-decoration: underline; }
.kig-text { font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
/* Hvorfor steget ikke er ditt å gjøre. Egen linje og litt mindre enn
   beskrivelsen: det er en fotnote om tilgang, ikke en del av forklaringen. */
.kig-hint { margin-top: 3px; font-size: 12px; line-height: 1.45; color: var(--ink-3); }
/* Gjort er gjort: tonet ned, men ikke strøket over. En strek gjennom en linje
   leser som «avlyst», og dette er det motsatte. */
.kig-step.is-done .kig-title { color: var(--ink-3); font-weight: 500; }

/* Innsiktene: prikk, påstand, og hva du gjør med den. Påstanden er lenken —
   handlingsteksten er forklaring, ikke et andre klikkmål. */
.insight-card { padding: 15px 18px; }
.insight-list { display: flex; flex-direction: column; gap: 11px; margin-top: 13px; }
.insight {
  display: flex; gap: 10px; align-items: baseline;
}
/* Prikkene er designets egne tre toner, ikke statusfargene: rav for det som
   haster, blått for det som er verdt å vite, grått for det som bare er sant.
   --warn (#92400E) er for mørk her — den er en tekstfarge på lys flate. */
.insight-dot {
  flex: none;
  width: 5px; height: 5px; border-radius: 50%;
  transform: translateY(-3px);
}
.insight-dot.is-varsel { background: #D97706; }
.insight-dot.is-info { background: var(--brand); }
.insight-dot.is-rolig { background: var(--ink-3); }
.insight p { font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.insight-text {
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
}
.insight-text:hover { color: var(--brand); text-decoration: underline; }
.insight-action { color: var(--ink-2); }
/* Kortet står også når det ikke er noe å si (21. august 2026). Ingen prikk
   foran: de tre prikkene over betyr alle «her er en sak», og en fjerde foran
   «ingenting å melde» ville lest som ett punkt til. Ingen grønn hake heller —
   en hake for at du ikke har problemer er å skryte på kundens vegne.
   margin-top er .insight-list sin egen, så tittelen står i samme høyde
   uansett hvilken av de tre tilstandene kortet viser. */
.insight-empty { margin-top: 13px; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.insight-empty-sub { margin-top: 6px; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }

/* ---- Portalrad: navn · tittel, merke, beløp, handling ------------------- */
/* Fra Sonida-portalen (19. august 2026). En radform gjennom hele appen: kunde og
   tittel på EN linje skilt med «·», statusmerket og forklaringen under, beløpet
   og knappen til høyre. Telefon og skrivebord er samme komponent — telefonen
   stabler beløp og knapp under, den bytter ikke layout.

   Layouten ligger her og ikke som Tailwind-grid, av samme grunn som .app-content
   og .dash-split: Tailwind injiseres etter app.css og ville vunnet i stillhet. */
.prow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 0 12px;
  align-items: center;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line-soft);
  cursor: pointer;
  transition: background 120ms var(--ease-out);
}
.prow:last-child { border-bottom: 0; }
.prow:hover { background: var(--brand-03); }

.prow-name {
  grid-column: 1;
  font-size: 13.5px; font-weight: 500; line-height: 1.4;
  color: var(--ink);
  min-width: 0;
}
/* Tittelen er ikke en egen linje: den henger på navnet med en prikk, slik at
   raden leser som en setning og ikke som et skjema. */
.prow-title { color: var(--ink-3); font-weight: 400; }

.prow-meta {
  grid-column: 1;
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 8px; margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 11.5px; line-height: 1; color: var(--ink-3);
}

/* Beløp og knapp står ved siden av hverandre til høyre, midtstilt mot begge
   tekstlinjene — ikke beløp oppe og knapp under. */
.prow-sum {
  grid-column: 2; grid-row: 1 / span 2;
  font-variant-numeric: tabular-nums;
  font-size: 13.5px; font-weight: 500; line-height: 1;
  white-space: nowrap; text-align: right;
}
.prow-act { grid-column: 3; grid-row: 1 / span 2; justify-self: end; }

/* Handlingsknappen i en rad: rolig, hvit, og alltid samme høyde uansett tekst.
   Het .btn-row til 19. august 2026 — det navnet var allerede i bruk som en
   LAYOUT-wrapper (.msg-form .btn-row, .decide .btn-row, .start-choice .btn-row),
   og siden denne regelen står lenger ned i fila arvet wrapperne ramme, hvit
   flate og padding de aldri skulle hatt. Det traff også akseptsiden, som er
   kundens side. Navnet er derfor entydig nå. */
.rowbtn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 36px; padding: 0 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 12.5px; font-weight: 500; line-height: 1; color: var(--ink-2);
  white-space: nowrap; text-decoration: none;
  transition: border-color 120ms var(--ease-out), background 120ms var(--ease-out);
}
.rowbtn:hover { border-color: var(--ink-3); background: var(--paper); color: var(--ink); }

@media (max-width: 560px) {
  /* Telefonen stabler alt i kildekodens rekkefølge — navn, beløp, merke, knapp.
     grid-row MÅ nullstilles her: skrivebordsregelen låser knappen til rad 2, og
     uten dette hoppet den opp foran beløpet og merkelappen på telefonen. */
  .prow { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .prow-sum { grid-column: 1; grid-row: auto; text-align: left; }
  .prow-act { grid-column: 1; grid-row: auto; justify-self: stretch; }
  .prow-act .rowbtn,
  .prow-act .btn { width: 100%; }
}

/* Leveringssignalet som statusmerke i stedet for prikk + tekst: designet gir det
   samme form som alle andre statuser, så en rad leser som en tegnforklaring. */
.badge-signal-bad  { background: var(--bad-bg);  color: var(--bad); }
.badge-signal-ok   { background: var(--brand-06); color: var(--brand-ink); }
.badge-signal-warn { background: var(--warn-bg); color: var(--warn); }
.badge-signal-neutral,
.badge-signal-muted { background: var(--neutral-bg); color: var(--neutral); }

/* ---- Spørsmål fra kunder ------------------------------------------------ */
/* Blå venstrekant: den eneste flaten i portalen der handlingsfargen brukes som
   flate og ikke som tekst eller knapp. Det er med vilje sjeldent — kortet er det
   ene stedet på dashbordet der et menneske står og venter. */
.quest-card {
  border-color: var(--brand-16);
  border-left: 3px solid var(--brand);
}
.quest-hint {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11.5px; line-height: 1; color: var(--ink-3);
}
.badge-ulest { background: var(--brand-06); color: var(--brand-ink); padding: 5px 8px; }
/* Sitatet ligger på egen rad under navnet, over hele bredden — et spørsmål skal
   kunne leses ferdig uten å bli kuttet av en beløpskolonne. */
.quest-quote {
  grid-column: 1; grid-row: 2;
  margin-top: 4px;
  font-size: 13px; line-height: 1.45; color: var(--ink-2);
}
/* Tidsstempelet i meldingsraden er mono, som all annen metadata i portalen. */
.quest-card .prow-sum {
  font-family: var(--font-mono); font-weight: 400;
  font-size: 11.5px; line-height: 1; color: var(--ink-3);
}
.btn-svar { min-height: 36px; padding: 0 14px; border-radius: 6px; font-size: 12.5px; }
@media (max-width: 560px) {
  .quest-hint { display: none; }
  .btn-svar { width: 100%; }
}

/* ---- Oppdragsstegene som fliser ----------------------------------------- */
.stage-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 9px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.stage-tile {
  display: block;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 8px;
  text-decoration: none;
  transition: border-color 120ms var(--ease-out), background 120ms var(--ease-out);
}
.stage-tile:hover { border-color: var(--ink-3); background: var(--brand-03); }
.stage-tile.is-active { border-color: var(--brand-22); background: var(--brand-03); }
.stage-count {
  display: block; margin-top: 6px;
  font-variant-numeric: tabular-nums;
  font-size: 18px; font-weight: 500; line-height: 1;
  color: var(--ink);
}
.stage-tile.is-active .stage-count,
.stage-tile.is-active .stage-label { color: var(--brand-ink); }
.stage-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px; line-height: 1.3; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-3);
}

/* ---- KPI-raden ---------------------------------------------------------- */
/* Samme rad på telefon og skrivebord, som i portalen. Stablet tok tallene tre
   skjermhøyder før noe handlingsbart kom til syne; her ligger de side om side og
   kan dras på når de ikke får plass. Kantene er trukket ut med negativ marg så
   raden når helt ut til skjermkanten mens kortene beholder sin luft. */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 13px;
  margin-bottom: 13px;
}
@media (max-width: 820px) {
  .kpi-row {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    margin-inline: -1rem;
    padding-inline: 1rem;
    /* Uten dette snapper nettleseren første kort til selve rulleflatens kant
       ved innlasting (scrollLeft blir 16), og «Åpne tilbud» starter på 0 mens
       tittelen og knappen over står på 16. Snappunktet må ligge på polstringen. */
    scroll-padding-left: 1rem;
    /* Rullefeltet er støy på en flate med tre kort. */
    scrollbar-width: none;
  }
  .kpi-row::-webkit-scrollbar { display: none; }
  .kpi-row > .kpi {
    /* Fast bredde, ikke `auto` med et minimum. Med `flex: 0 0 auto` vokste et
       kort med lengre tekst forbi naboene — målt 342 px mot 208 på det TOMME
       dashbordet, der treffprosenten sier «Ingen avgjorte tilbud de siste 90
       dagene» i stedet for «90 dager · 4 ja, 1 nei». Stripa snapper, og
       ujevne kortbredder gjør snappunktene uforutsigbare: du sveiper likt og
       lander ulikt. At det bare slo ut på tom tilstand er nettopp grunnen til
       at det sto uoppdaget — det er skjermen en ny kunde ser først. */
    flex: 0 0 208px;
    scroll-snap-align: start;
  }
}

/* ---- Sidemenyens topp og bunn (Sonida-portalen) ------------------------- */
/* Sidemenyens toppfelt og topplinja over innholdet må ha NØYAKTIG samme høyde:
   begge har en hårlinje under seg, og møtes de ikke, leser øyet det som en feil
   selv om ingen av dem er gale hver for seg. 64 px er topplinjas høyde — den er
   gitt av knappen (38 px) pluss 13 px luft over og under — så toppfeltet får den
   som fast høyde i stedet for å bli så høyt som innholdet tilfeldigvis blir. */
.side-brand {
  min-height: 65px;
  display: flex; align-items: center;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
}
.side-brand-link {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: var(--ink);
  min-width: 0;
}
/* Har bedriften lastet opp en logo, er DEN identiteten og får plassen — større
   enn flisen, og alene på linja. Navnet står i tittelen og i topplinja på
   telefon, så det gjentas ikke ved siden av en logo som allerede sier det. */
.side-brand-link.has-logo { justify-content: center; }
/* Logoen får plassen den trenger og ikke mer: 34 px lar den puste inne i de
   64 px uten at feltet blir en tom boks rundt et lite merke. */
.side-logo { max-height: 34px; max-width: 100%; width: auto; }
/* Bedriftsflisen: forbokstaven i bedriftens egen farge. Firkanten er det ene
   stedet i portalen der leietakerfargen fortsatt vises — den svarer på «hvem er
   jeg logget inn som», ikke på «hvordan ser produktet ut». */
/* Bunnen sto tidligere som inline style i base.html, i bedriftens egen farge.
   Etter J2 er den fast og nøytral - og den MÅ stå her: uten den ble flisen
   gjennomsiktig med hvit bokstav, altså usynlig. */
.side-tile {
  flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; color: #FFFFFF;
  background: var(--ink);
  text-transform: uppercase;
}
/* Designet bryter navnet over to linjer. balance holder linjene like lange i
   stedet for å la den andre bli ett ord. */
.side-company {
  font-size: 13px; font-weight: 600; line-height: 1.25;
  letter-spacing: -0.02em;
  min-width: 0; text-wrap: balance;
}

.side-foot { padding: 14px; border-top: 1px solid var(--line); }
/* position: relative er bærende - menyen under er absolutt plassert mot denne.
   align-items: center, ikke baseline: knappen er en 28 px flate, ikke tekst. */
.side-foot-top {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.side-foot-id { min-width: 0; }
.side-foot-name {
  display: block; font-size: 13px; font-weight: 500; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-foot-role {
  font-family: var(--font-mono);
  font-size: 11px; line-height: 1.4; color: var(--ink-3);
  margin-top: 2px;
}
/* Den diskrete inngangen til «Endre passord» og «Logg ut». Rolig til den
   trengs: ingen ramme, ingen understrek - bare tre prikker som våkner på
   hover og fokus. 28 px flate, så den er til å treffe med musa. */
.side-foot-menubtn {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  background: none; border: 0; border-radius: 7px; cursor: pointer;
  color: var(--ink-3);
  transition: background-color 120ms ease, color 120ms ease;
}
.side-foot-menubtn:hover { background: var(--brand-03); color: var(--ink); }
.side-foot-menubtn svg { width: 17px; height: 17px; display: block; }
/* Åpner OPPOVER: foten er nederst i skjermen, og en meny som falt nedover
   ville havnet utenfor vinduet. Arver resten av formen fra .qb-menu.

   Velgeren tar MED .qb-menu med vilje: .qb-menu står lenger ned i denne fila
   og setter `top: calc(100% + 6px)`. Med bare .side-foot-pop (like sterk, men
   tidligere) vant .qb-menu, og menyen falt ned gjennom skjermkanten. */
.qb-menu.side-foot-pop {
  top: auto; bottom: calc(100% + 6px); right: 0; min-width: 172px;
}

/* Topplinja i portalen: tittel og handling på samme linje, ikke tittel over
   undertittel over knapp. Bryter først når knappene ikke får plass. */

/* ---- Oppdragsrad («Under arbeid») --------------------------------------- */
/* Merkekolonnen er fast bred, ikke «auto»: hver rad er sitt eget rutenett, så
   «auto» fant aldri en felles bredde, og «Ikke startet» (97 px) skjøv navnet
   42 px lenger inn enn «Ferdig» (56 px) gjorde. Fire rader med hakkete
   venstrekant. Merket beholder sin egen bredde via justify-self. */
.jrow {
  display: grid;
  grid-template-columns: 98px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line-soft);
  cursor: pointer;
  transition: background 120ms var(--ease-out);
}
.jrow:last-child { border-bottom: 0; }
.jrow:hover { background: var(--brand-03); }
.jrow > .badge { justify-self: start; }
.jrow-name { font-size: 13px; font-weight: 500; line-height: 1.4; min-width: 0; }
.jrow-note { font-size: 12px; color: var(--ink-3); margin-left: 6px; white-space: nowrap; }
.jrow-act {
  font-size: 12px; font-weight: 500; line-height: 1; color: var(--brand-ink);
  text-decoration: none; white-space: nowrap;
}
.jrow-act:hover { text-decoration: underline; }
.jrow-act.is-quiet {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; color: var(--ink-3); font-weight: 400;
}
@media (max-width: 560px) {
  .jrow { grid-template-columns: 98px minmax(0, 1fr); }
  .jrow-act { grid-column: 2; justify-self: start; }
}

/* «Levert av Sonida» i sidemenyens bunn: vanlig skrift, ikke versaler — det er
   en signatur, ikke en etikett. Svakere enn rolleteksten over. */
.side-foot-by {
  font-family: var(--font-mono);
  font-size: 10.5px; line-height: 1.4; color: var(--faint, var(--ink-3));
  margin-top: 10px;
}

/* Selve navnet står i ordmerkets form over alt det opptrer - sidemenyen,
   «Mer»-arket, innlogging, de offentlige sidene, e-postene og PDF-en. «Levert
   av» beholder flatens egen skrift; bare navnet bytter. 1.02em fordi Schibsted
   Grotesk har lavere x-høyde enn Azeret Mono og ellers ser mindre ut ved 10,5
   px. Egen letter-spacing, siden .credit sperrer linja med +0.04em. */
.sonida {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.02em;
  letter-spacing: -0.03em;
  color: inherit;
}

/* Korttittelens følgesvenner: antallet står tett på tittelen som en opplysning,
   «Se alle» skyves helt ut til høyre som handling. */
.card-count {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; font-weight: 400; line-height: 1; color: var(--ink-3);
}
.card-more {
  margin-left: auto;
  font-size: 12px; font-weight: 500; line-height: 1;
  color: var(--brand-ink);
  text-decoration: none; white-space: nowrap;
}
.card-more:hover { text-decoration: underline; }

/* Primærknappen med designets mål: 38 px høy, 16 px sideluft, radius 7 px,
   13 px halvfet. Ingen ikon — portalens knapper er ren tekst. */
.btn { min-height: 38px; padding: 0 16px; border-radius: 7px; font-size: 13px; font-weight: 600; }
.btn-primary { background: var(--brand); color: #FFFFFF; border-color: var(--brand); }
.btn-primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }

/* Sidemenyens nav med designets mål: 12/10 luft, 2 px mellom punktene. */
.app-nav {
  padding: 12px 10px;
  display: flex; flex-direction: column; gap: 2px;
}

/* ==========================================================================
   Tilbudsbyggeren (skjerm 02 i Sonida-portalen)
   --------------------------------------------------------------------------
   Bygget mot «Sonida portal EKSPORT.html», seksjon 02, med designets egne
   verdier: rutenettet 22px 1fr 70px 96px 110px, radhøydene, mono-etikettene og
   den 312 px brede høyreskinna. Skrivebord og telefon er to presentasjoner av
   SAMME Alpine-tilstand (quoteBuilder()), på samme måte som kvitteringen har
   vært det siden pakke 2: .qb-desk vises fra 1024 px, .qb-phone under.

   Designet forutsetter autolagring («lagres mens du skriver»). Det finnes ikke
   — hele linjelista postes som ett felt og serveren gjenskaper linjene ved hver
   lagring — så topplinja har en ærlig lagre-knapp og en tilstandstekst i stedet.
   Se docs/design-utelatt.md.
   ========================================================================== */

:root {
  /* Radtonen designet bruker bak tabellhodet og romradene. Ikke --paper: den
     er et hakk kaldere og lysere, og ligger PÅ hvitt, ikke under det. */
  --row-tint: #F7F9FC;
}

.qb {
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  overflow: hidden;
}

/* ---- Topplinja ----------------------------------------------------------- */
.qb-top {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding: 14px 22px;
  display: flex; align-items: center; gap: 16px;
}
.qb-back { display: inline-flex; color: var(--ink-2); }
.qb-back svg { width: 18px; height: 18px; }
.qb-top-id { flex: 1 1 auto; min-width: 0; }
.qb-top-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qb-menu-phone { display: none; }
.qb-top-title {
  font-size: 16.5px; font-weight: 600; line-height: 1.2; letter-spacing: -0.03em;
  color: var(--ink);
}
.qb-top-sub {
  margin-top: 4px;
  font: 400 11.5px/1 var(--font-mono); color: var(--ink-3);
}
.qb-top-act { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.qb-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 38px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 7px;
  background: var(--surface); color: var(--ink-2);
  font-size: 13px; font-weight: 500; line-height: 1;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: border-color 130ms ease, background-color 130ms ease;
}
.qb-btn:hover { border-color: var(--ink-3); }
.qb-btn-primary {
  padding: 0 16px; border-color: var(--brand);
  background: var(--brand); color: #fff; font-weight: 600;
}
.qb-btn-primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }
.qb-btn svg { width: 15px; height: 15px; }

/* «Mer»: ren tekst med chevron, ingen ramme — designets tredje handling. */
.qb-more {
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 0; padding: 6px 2px; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 500; color: var(--ink-2);
}
.qb-more svg { width: 15px; height: 15px; transition: transform 160ms var(--ease-out); }
.qb-more[aria-expanded="true"] svg { transform: rotate(180deg); }
.qb-menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  min-width: 190px; padding: 5px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; box-shadow: 0 14px 34px -18px rgb(17 24 39 / 0.35);
  /* Origo i hjørnet menyen faktisk henger fra. Den er forankret med right: 0
     og top: 100%, men vokste fra sin egen midte - så sammenhengen mellom
     knappen du trykket og panelet som kom var ikke synlig. */
  transform-origin: top right;
}
/* scale(0.97), ikke scale(0): ingenting i virkeligheten dukker opp fra
   ingenting. 0.97 er nok til at øyet leser en vekst, lite nok til at det
   ikke blir et sprett. Samme kurve og varighet som resten av husets
   innganger (se app.css:580). */
.qb-menu-enter       { transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out); }
.qb-menu-enter-start { opacity: 0; transform: scale(0.97); }
.qb-menu-leave       { transition: opacity 120ms var(--ease-out), transform 120ms var(--ease-out); }
.qb-menu-leave-end   { opacity: 0; transform: scale(0.97); }
.qb-menu a, .qb-menu button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 6px; background: none;
  font-family: inherit; font-size: 13px; color: var(--ink-2); text-align: left;
  text-decoration: none; cursor: pointer;
}
.qb-menu a:hover, .qb-menu button:hover { background: var(--brand-06); color: var(--ink); }
.qb-menu svg { width: 15px; height: 15px; color: var(--ink-3); }

/* ---- Kroppen: venstrespalte + høyreskinne -------------------------------- */
.qb-body { display: flex; align-items: stretch; }
.qb-main {
  flex: 1; min-width: 0; padding: 20px 22px;
  display: flex; flex-direction: column; gap: 12px;
}
.qb-rail {
  width: 312px; flex: none;
  border-left: 1px solid var(--line); background: var(--surface);
  padding: 20px;
}

.qb-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px;
}

/* ---- Toppkortet: kunde · tittel · gyldig til · prisform ------------------ */
.qb-facts { display: flex; flex-wrap: wrap; align-items: stretch; }
.qb-fact { padding: 15px 18px; min-width: 0; border-left: 1px solid var(--line-soft); }
.qb-fact:first-child { border-left: 0; }
.qb-fact-wide { flex: 1 1 230px; }
.qb-fact-mid { flex: 1 1 240px; }
.qb-fact-sm { flex: 0 1 150px; }
.qb-flabel {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
}
.qb-fvalue {
  margin-top: 8px; display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  font-size: 14.5px; line-height: 1.3; color: var(--ink);
}
.qb-suffix { font: 400 11.5px/1 var(--font-mono); color: var(--ink-3); white-space: nowrap; }
/* Kundenavn er lengre i virkeligheten enn i designets «Ola Nordmann». Selecten
   får en min-bredde, og typen + «Ny» flytter seg samlet ned på egen linje når
   navnet trenger plassen — heller to linjer enn et avkortet kundenavn. */
.qb-fmeta { display: inline-flex; align-items: baseline; gap: 7px; flex: none; }
.qb-fact-wide .qb-flat-grow { min-width: 150px; }

/* Kundesøket: feltet og trefflista deler en posisjonert boks, så panelet
   henger under inputen og ikke under hele cellen. Selve <select>-en står
   skjult ved siden av og er fortsatt det som postes. */
.qb-custpick { position: relative; flex: 1 1 auto; min-width: 150px; display: flex; }
.qb-custpick .qb-combo { max-width: min(420px, 76vw); }
.qb-hidden-field { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.qb-terms-field {
  width: 100%; padding: 9px 10px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--surface);
  font-family: inherit; font-size: 12.5px; line-height: 1.55; color: var(--ink);
  resize: vertical;
}
.qb-terms-field:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16); }

/* Feltene ser ut som tekst, men ER felt. Designet tegner verdiene som ren
   tekst; en tilbudsbygger der kunden ikke kan velges er ikke en tilbudsbygger,
   så rammen er fjernet i stedet for redigerbarheten. */
.qb-flat {
  min-width: 0; max-width: 100%;
  border: 0; background: transparent; padding: 0; margin: 0;
  font: inherit; color: inherit; border-radius: 3px;
  /* En vanlig tittel på 35 tegn ble hugget midt i siste bokstav, klint inntil
     cellens skillelinje — uten ellipse ser det ut som siden er ødelagt, ikke
     som at teksten fortsetter. Feltet ser ut som tekst, så det skal kuttes som
     tekst. Nettleseren viser hele verdien igjen så snart feltet får fokus. */
  text-overflow: ellipsis;
}
.qb-flat::placeholder { color: var(--ink-3); }
.qb-flat:focus { outline: none; }
.qb-flat:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.qb-flat-grow { flex: 1 1 auto; width: 100%; }
select.qb-flat, .qb-flat-select {
  appearance: none; -webkit-appearance: none;
  padding-right: 19px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%234B5563' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right center; background-size: 15px 15px;
}
.qb-fvalue .qb-mono { font-family: var(--font-mono); font-size: 13.5px; }
.qb-fnote { margin-top: 6px; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
.qb-fnote-warn { color: var(--warn); }

/* ---- Jobbadresse-raden --------------------------------------------------- */
.qb-jobrow {
  border-top: 1px solid var(--line-soft);
  padding: 13px 18px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.qb-jobtext { font-size: 13.5px; line-height: 1.4; color: var(--ink); min-width: 0; }
.qb-jobtext .qb-suffix { margin-left: 6px; }
/* Samme luft i skinnaradene: etiketten er sans og verdien mono, og med bare et
   vanlig mellomrom klistret de seg sammen — «Vilkår standard» leste som en
   skrivefeil, ikke som en etikett med en verdi. */
.qb-srow-label .qb-suffix { margin-left: 6px; }
.qb-link {
  margin-left: auto;
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500; line-height: 1;
  color: var(--brand-ink); text-decoration: none; white-space: nowrap;
}
.qb-link:hover { text-decoration: underline; }
.qb-link-plain { margin-left: 0; }

/* ---- Innledningskortet --------------------------------------------------- */
.qb-intro { padding: 15px 18px; }
.qb-intro-head { display: flex; align-items: center; gap: 12px; }
.qb-intro-text {
  display: block; width: 100%; margin-top: 11px;
  border: 0; background: transparent; padding: 0; resize: vertical;
  font-family: var(--font-sans); font-size: 13.5px; line-height: 1.62;
  color: var(--ink); min-height: 92px; text-wrap: pretty;
}
.qb-intro-text:focus { outline: none; }
.qb-intro-text:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 3px; }

/* ---- Linjekortet --------------------------------------------------------- */
/* IKKE overflow:hidden: det klipper materiellsøkets trefflista mot kortkanten
   (den lå avskåret midt i lista før 20. august 2026). Ingen barneflate ligger
   inntil kanten, så hjørnene klarer seg uten. */
.qb-lines { background: var(--surface); border: 1px solid var(--line); border-radius: 9px; }
.qb-lines-top {
  padding: 12px 18px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
}
.qb-search {
  flex: 1 1 240px; min-width: 0; position: relative;
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--line); border-radius: 7px; padding: 11px 13px;
  background: var(--surface);
  transition: border-color 130ms ease, box-shadow 130ms ease;
}
.qb-search:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16); }
.qb-search > svg { width: 17px; height: 17px; color: var(--ink-3); flex: none; }
.qb-search input {
  flex: 1; min-width: 0; border: 0; background: transparent; padding: 0;
  font-family: inherit; font-size: 13px; line-height: 1; color: var(--ink);
}
.qb-search input:focus { outline: none; }
.qb-search input::placeholder { color: var(--ink-3); }

.qb-chips { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.qb-chip {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 38px; padding: 0 13px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--surface);
  font-family: inherit; font-size: 12.5px; font-weight: 500; line-height: 1;
  color: var(--ink-2); cursor: pointer; white-space: nowrap;
  transition: border-color 130ms ease, background-color 130ms ease;
}
.qb-chip:hover { border-color: var(--ink-3); }
.qb-chip svg { width: 15px; height: 15px; color: var(--ink-3); }
.qb-chip[disabled] { opacity: 0.5; pointer-events: none; }

.qb-grid { display: grid; grid-template-columns: 22px 1fr 70px 96px 110px; gap: 14px; }
.qb-thead { padding: 9px 18px; background: var(--row-tint); border-bottom: 1px solid var(--line); }
.qb-thead span {
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.qb-thead .qb-r { text-align: right; }

.qb-room {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 18px; background: var(--row-tint);
  border-bottom: 1px solid var(--line-soft);
}
.qb-room-name {
  flex: 1 1 auto; min-width: 0;
  font: 600 11.5px/1 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.qb-room-name::placeholder { text-transform: none; letter-spacing: 0; }
.qb-room-sum {
  font: 400 12px/1 var(--font-mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.qb-row { padding: 12px 18px; align-items: center; border-bottom: 1px solid var(--line-soft); }
.qb-row.is-open { background: var(--row-tint); }
.qb-grip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: -3px;
  border: 0; background: none; padding: 0; cursor: pointer; color: #6B7280;
  border-radius: 4px;
}
.qb-grip:hover { background: var(--brand-06); color: var(--ink-2); }
.qb-grip svg { width: 14px; height: 14px; }
.qb-desc { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.qb-desc input { font-size: 13.5px; line-height: 1.35; }
.qb-subtext { font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }

.qb-num {
  width: 100%; min-width: 0; text-align: right;
  border: 0; background: transparent; padding: 0; margin: 0;
  font-family: var(--font-mono); font-size: 13px; line-height: 1.2;
  font-variant-numeric: tabular-nums; color: var(--ink); border-radius: 3px;
}
.qb-num:focus { outline: none; }
.qb-num:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.qb-num.has-error { outline: 1.5px solid var(--bad); outline-offset: 2px; }
.qb-qty { display: flex; align-items: baseline; justify-content: flex-end; gap: 4px; }
.qb-qty .qb-num { flex: 1 1 auto; }
.qb-unit { font: 400 13px/1 var(--font-mono); color: var(--ink-3); flex: none; }
.qb-price .qb-num { color: var(--ink-3); }
.qb-sum {
  font-size: 13.5px; font-weight: 500; line-height: 1; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap;
}

/* «rabatt per linje ligger bak raden» — designets egen setning. Bak raden er
   dette: enhet, rabatt, linjetype, flytting og sletting, åpnet fra grepet. */
.qb-drawer {
  padding: 12px 18px 14px 54px;
  background: var(--row-tint); border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap;
}
.qb-dfield { display: flex; flex-direction: column; gap: 5px; }
.qb-dlabel {
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.qb-dinput {
  width: 88px; padding: 6px 9px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--surface);
  font-family: var(--font-mono); font-size: 12.5px; color: var(--ink);
}
.qb-dinput:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16); }
.qb-dtype { font: 400 12.5px/1 var(--font-mono); color: var(--ink-3); padding-bottom: 7px; }
.qb-dact { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.qb-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--surface); color: var(--ink-2); cursor: pointer;
}
.qb-iconbtn:hover { border-color: var(--ink-3); }
.qb-iconbtn[disabled] { opacity: 0.4; pointer-events: none; }
.qb-iconbtn svg { width: 15px; height: 15px; }
.qb-iconbtn.is-danger { color: var(--bad); }
.qb-iconbtn.is-danger:hover { background: var(--bad-bg); border-color: color-mix(in srgb, var(--bad) 40%, white); }

.qb-lines-foot { padding: 12px 18px; display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.qb-foot-note {
  margin-left: auto; text-align: right;
  font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3);
}
.qb-empty { padding: 26px 18px 24px; text-align: center; }
.qb-empty p { font-size: 13.5px; color: var(--ink-3); }
.qb-formerror { padding: 0 18px 14px; font-size: 12.5px; color: var(--bad); }

/* Trefflista i materiellsøket: designet tegner bare det lukkede feltet, så
   panelet arver husets combo-språk med byggerens egne mål. */
.qb-combo {
  /* Bredere enn feltet den henger under: et varenavn med varenummer og pris
     trenger mer plass enn søkeruta, og panelet får gå utover kortet. */
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 32;
  min-width: 100%; width: max-content; max-width: min(560px, 78vw);
  max-height: 340px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; box-shadow: 0 14px 34px -18px rgb(17 24 39 / 0.35);
  padding: 5px;
}
.qb-combo-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 9px 10px; border: 0; border-radius: 6px; background: none;
  text-align: left; cursor: pointer;
}
.qb-combo-item.is-active { background: var(--brand-06); }
.qb-combo-name { font-size: 13.5px; color: var(--ink); }
.qb-combo-item > .min-w-0 { flex: 1 1 auto; }
.qb-combo-meta { font: 400 11px/1.4 var(--font-mono); color: var(--ink-3); }
.qb-combo-price {
  margin-left: auto; flex: none;
  font: 400 12.5px/1 var(--font-mono); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.qb-combo-empty { padding: 10px; font-size: 12.5px; color: var(--ink-3); }

/* ---- Høyreskinna --------------------------------------------------------- */
.qb-rrows { display: flex; flex-direction: column; gap: 9px; }
.qb-rrow { display: flex; justify-content: space-between; gap: 10px; }
.qb-rrow-label { font-size: 13px; line-height: 1.3; color: var(--ink-2); }
.qb-rrow-val {
  font: 400 13px/1 var(--font-mono); color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.qb-rrow-rule { padding-top: 10px; border-top: 1px solid var(--line-soft); }
.qb-rrow-rule .qb-rrow-val { font-weight: 500; font-size: 13.5px; }
.qb-total {
  margin-top: 14px; padding-top: 14px; border-top: 2px solid var(--ink);
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.qb-total-label { font-size: 14px; font-weight: 600; line-height: 1.2; }
.qb-total-val {
  font-size: 24px; font-weight: 500; line-height: 1; letter-spacing: -0.04em;
  font-variant-numeric: normal; white-space: nowrap;
}
.qb-rail-block {
  margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line-soft);
  display: flex; flex-direction: column; gap: 12px;
}
.qb-srow { display: flex; align-items: center; gap: 10px; }
.qb-srow-label { flex: 1; min-width: 0; font-size: 13px; line-height: 1.3; color: var(--ink-2); }
.qb-srow .qb-link { margin-left: 0; }
.qb-panelbox {
  padding: 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--row-tint);
  display: flex; flex-direction: column; gap: 9px;
}
.qb-panelbox .qb-dinput { width: 100%; }
.qb-panelrow { display: flex; gap: 8px; }
.qb-panelrow .qb-dinput:first-child { width: 74px; flex: none; }
.qb-terms {
  max-height: 190px; overflow-y: auto; white-space: pre-line;
  font-size: 12.5px; line-height: 1.6; color: var(--ink-2);
}
.qb-note { font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
.qb-note-warn { color: var(--warn); }

/* Designets ramme er 1240 px BREDT INNHOLD ved siden av sidemenyen. Under det
   blir beskrivelseskolonnen (1fr) klemt av skinnas faste 312 px — 114 px igjen
   ved 1100 px viewport. Skinna legger seg derfor under fra 1280 og ned, og
   linjene får hele bredden. Rutenettet og radhøydene er uendret. */
@media (min-width: 1024px) and (max-width: 1279.98px) {
  .qb-body { flex-direction: column; }
  .qb-rail {
    width: auto; border-left: 0; border-top: 1px solid var(--line);
    display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; align-items: start;
  }
  .qb-rail-block { margin-top: 0; padding-top: 0; border-top: 0; }
}

/* ---- Telefonvarianten ---------------------------------------------------- */
.qb-phone { display: none; }

@media (max-width: 1023.98px) {
  /* Rammen rundt byggeren er skjermrammen i designet, ikke en flate i appen:
     på telefon ligger kortene rett på papiret. */
  .qb { border: 0; border-radius: 0; background: transparent; }
  .qb-desk { display: none; }
  .qb-phone { display: block; }

  /* Designets telefonvariant har ingen ramme rundt linjelista: søkefeltet og
     romkortene ligger fritt på papiret, hvert med sin egen kant. Kortet som
     holder dem sammen på skrivebordet blir derfor gjennomsiktig her. */
  .qb-lines {
    background: transparent; border: 0; border-radius: 0;
    gap: 11px; padding-bottom: 4px;
  }
  .qb-search { margin: 0; }
  .qb-proom { margin: 0; }
  .qb-chips { padding: 0; }
  .qb-lines-foot { padding: 0; }
  .qb-empty {
    background: var(--surface); border: 1px solid var(--line); border-radius: 11px;
    padding: 22px 16px;
  }
  .qb-formerror { padding: 0; }

  /* Telefonens topplinje er designets: tilbake, nummer og status, «Mer».
     Lagre og Forhåndsvis hører hjemme i bunnfeltet og i menyen — tre knapper
     her presser tittelen i stykker på 375 px. */
  .qb-top { padding: 12px 16px; gap: 11px; }
  .qb-top-act .qb-btn { display: none; }
  .qb-menu-phone { display: flex; }
  .qb-top-title { font-size: 13.5px; letter-spacing: -0.02em; }
  .qb-top-sub { margin-top: 3px; font-size: 10.5px; }
  .qb-back svg { width: 19px; height: 19px; }

  .qb-body { flex-direction: column; }
  .qb-main { padding: 16px 16px 6px; gap: 11px; }
  .qb-rail { width: auto; border-left: 0; border-top: 1px solid var(--line); }

  .qb-card, .qb-lines { border-radius: 11px; }
  .qb-facts { flex-direction: column; }
  .qb-fact { flex: 1 1 auto; width: 100%; border-left: 0; padding: 13px 15px; }
  .qb-fact + .qb-fact { border-top: 1px solid var(--line-soft); }
  .qb-jobrow { padding: 12px 15px; }
  .qb-intro { padding: 14px 15px; }
  .qb-intro-text { margin-top: 9px; font-size: 13px; line-height: 1.55; }

  /* Designets telefonflyt: søkefeltet øverst, romkortene, og først DERETTER
     knappene som legger til noe. .qb-lines-top løses opp med display:contents
     så de to radene kan sorteres hver for seg — en markering, to rekkefølger. */
  .qb-lines { display: flex; flex-direction: column; }
  .qb-lines-top { display: contents; }
  .qb-search {
    order: 0; flex: 1 1 auto; width: auto;
    border-radius: 11px; padding: 13px 14px;
  }
  .qb-search > svg { width: 18px; height: 18px; }
  .qb-search input { font-size: 13.5px; }
  .qb-chips { order: 3; }
  .qb-foot-note { margin-left: 0; text-align: left; width: 100%; }
  .qb-phone, .qb-empty { order: 1; }
  .qb-phone { display: flex; flex-direction: column; gap: 11px; }
  .qb-lines-foot { order: 4; }
  .qb-formerror { order: 5; }

  .qb-proom {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: 11px; overflow: hidden;
  }
  .qb-proom-head {
    padding: 10px 15px; background: var(--row-tint);
    border-bottom: 1px solid var(--line-soft);
    display: flex; align-items: center; gap: 9px;
  }
  .qb-proom-name {
    flex: 1 1 auto; min-width: 0;
    font: 600 11px/1 var(--font-mono);
    letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
  }
  .qb-proom-name::placeholder { text-transform: none; letter-spacing: 0; }
  .qb-proom-sum {
    font: 400 11px/1 var(--font-mono); color: var(--ink-3);
    font-variant-numeric: tabular-nums; white-space: nowrap;
  }
  .qb-pline { padding: 13px 15px; border-bottom: 1px solid var(--line-soft); }
  .qb-pline:last-child { border-bottom: 0; }
  .qb-pline-head {
    display: flex; align-items: baseline; gap: 10px; width: 100%;
    background: none; border: 0; padding: 0; text-align: left; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .qb-pline-name {
    flex: 1; min-width: 0; font-size: 14px; font-weight: 500; line-height: 1.35;
    color: var(--ink);
  }
  .qb-pline-name input { width: 100%; }
  .qb-pline-sum {
    font-size: 14px; font-weight: 500; line-height: 1;
    font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap;
  }
  .qb-pline-meta { margin-top: 6px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }

  /* Den åpne linja: teller med store trykkflater, pris og de sjeldne feltene. */
  .qb-pedit { margin-top: 10px; display: flex; flex-direction: column; gap: 10px; }
  .qb-stepper { display: flex; align-items: center; gap: 9px; }
  .qb-step {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; flex: none;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--surface); color: var(--ink-2); cursor: pointer;
  }
  .qb-step:active { background: var(--paper); }
  .qb-step svg { width: 18px; height: 18px; }
  .qb-stepval {
    min-width: 56px; display: flex; align-items: baseline; justify-content: center; gap: 3px;
    font: 500 15px/1 var(--font-mono); font-variant-numeric: tabular-nums;
  }
  .qb-stepval .qb-num { text-align: center; font-size: 15px; font-weight: 500; }
  .qb-steprate { margin-left: auto; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
  .qb-pfields { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
  .qb-pfields .qb-dinput { width: 92px; }

  .qb-pchips { display: flex; gap: 9px; flex-wrap: wrap; }
  .qb-pchips .qb-chip { min-height: 46px; }

  /* Tallene bor i bunnfeltet på telefon, ikke i en skinne — men de rolige
     radene (rabatt, angrerett, vilkår) må fortsatt være å nå, så skinna blir
     stående og mister bare totalene. */
  .qb-rail { padding: 16px; }
  .qb-rail-totals { display: none; }
  .qb-rail-block { margin-top: 0; padding-top: 0; border-top: 0; }
  .qb-total-val { font-size: 22px; }
}

/* Akseptbeviset i skinna: signaturbildet og de utfellbare vilkårene må holde
   seg innenfor 340 px, ikke sprenge spalta. */
.qd-evidence .evidence-block { max-width: 100%; }
.qd-evidence .evidence-sig { max-width: 100%; height: auto; }
.qd-evidence .evidence-panel { max-height: 220px; overflow-y: auto; }

/* En høy dialog (jobbadresse og kjøring) må kunne rulle i seg selv. */
.modal-panel-tall { max-width: 540px; max-height: min(86vh, 800px); overflow-y: auto; }

/* Bunnfeltet på telefon: handlingspilla.
   --------------------------------------------------------------------------
   Her sto designets to rader: en etikettert tallblokk stablet oppå en
   full-bredde primærknapp — skrivebordets høyreskinne brettet i to og kilt ned
   i bunnen. 148,5 px høy, og med bunnmenyen under ble det et fast bånd på
   200,5 px av 812: en fjerdedel av telefonen borte før man har sett en eneste
   linje. På en ekte iPhone med home-indikator 268,5 px, fordi safe-area ble
   talt to ganger (både i `bottom` og i `padding-bottom`) på en bar som aldri
   rører skjermkanten.

   Feltet er ikke gjort lavere — det er gjort til noe annet. Et bånd med
   `border-top` over hele bredden leser som en VEGG: sida slutter der. En
   flytende pille leser som en KONTROLL som ligger PÅ sida. Innholdet synes i
   rennene på 12 px langs hver kant og skimtes gjennom materialet, og det er
   det som forteller øyet at sida fortsetter under. Derfor er også
   `backdrop-filter` tilbake — den sto her før Sonida-blokka slo den av.

   To soner på én linje: totalen til venstre (åpner summerings-arket), Lagre
   til høyre. 46 px høy, bånd 108 px, og 142 px på en iPhone i stedet for
   268,5. Ingen inn/ut-animasjon, og ingen skjul-ved-rulling: pilla er alltid
   der, og Lagre skal alltid være innen rekkevidde. */
@media (max-width: 1023.98px) {
  .qs-bar {
    /* 12 px renne på hver side. Regnestykket for høyden: 40 px innhold + 2·2 px
       pute + 2·1 px kant = 46. Og `bottom`: bunnmenyen (.app-tabbar, definert
       lenger opp i fila) måler 54 px og legger sin EGEN safe-area-pute til det;
       54 + 8 px luft opp til pilla = 62. env() står derfor kun her, aldri i
       `padding` — det var dobbelttellingen som ga 34 px ren sløsing på ekte
       maskinvare, på en bar som uansett aldri rører skjermkanten. */
    left: 12px; right: 12px;
    bottom: calc(62px + env(safe-area-inset-bottom));
    align-items: center;
    min-height: 46px;
    padding: 2px 2px 2px 15px;
    border-radius: 23px;
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    -webkit-backdrop-filter: saturate(1.8) blur(18px);
    backdrop-filter: saturate(1.8) blur(18px);
    /* Kant hele veien rundt og dybde, ikke `border-top`. Den harde kanten ER
       veggen vi fjerner. Større flate tåler — og krever — tyngre blur og
       dypere skygge enn en liten brikke ville gjort. */
    border: 1px solid color-mix(in srgb, var(--line-strong) 55%, transparent);
    box-shadow: 0 6px 20px rgb(29 31 36 / 0.10), 0 1px 3px rgb(29 31 36 / 0.06);
  }

  /* Venstre sone: rad, ikke stabel. `align-items: baseline` er hele poenget —
     tallet og etiketten står på samme grunnlinje som på en kvittering, og
     bar-ens egen `align-items: center` sentrerer gruppa i pilla. */
  .qs-total {
    flex: 1 1 auto; min-width: 0;
    flex-direction: row; align-items: baseline; gap: 6px;
    padding: 0; position: relative;
    transition: transform 120ms var(--ease-out);
  }
  /* Trykkflata er hele pillas høyde, ikke bare de ~21 px teksten fyller.
     Apple-skillen tillater hit-slop nettopp for dette; loddrett bare, så den
     ikke spiser inn i Lagre-kapselens egen flate på den andre siden av gapet. */
  .qs-total::after { content: ''; position: absolute; inset: -13px 0; }
  .qs-total:active { transform: scale(0.98); }
  /* `nowrap` på begge: pilla er trang, og uten den brakk totalen til to linjer
     fra og med 100 000 kr — målt: 99 750,00 kr ble én linje, 142 500,00 kr ble
     to, etiketten delte seg i «inkl.» / «mva», og pilla vokste. Et tilbud over
     hundre tusen er hverdagen for en elektriker, så det var ikke en ytterkant.

     Den gamle stablede baren hadde 343 px til tallet og brakk aldri; den
     trangere geometrien innførte regresjonen, og da må den bæres her.
     Etiketten er den som får forsvinne hvis noe MÅ vike (se regelen under),
     for tallet er grunnen til at sona finnes. */
  .qs-total-label {
    font: 500 11px/1.2 var(--font-mono); letter-spacing: 0.04em;
    text-transform: none; color: var(--ink-3);
    white-space: nowrap; flex: 0 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis;
  }
  .qs-total-value {
    display: block; font-size: 17px; font-weight: 600;
    line-height: 1.2; letter-spacing: -0.02em;
    white-space: nowrap; flex: none;
  }
  /* 22 px på arvet line-height 1.5 ga en glyffboks på 33 px for 22 px tekst;
     17/1.2 gir 20,4. `tabular-nums` fordi tallet ellers reflyter hver gang en
     siffer-bredde endrer seg mens man legger til linjer — det flimret. */
  .qs-total-value .font-num {
    font-size: 17px; font-family: var(--font-sans);
    font-variant-numeric: tabular-nums;
  }
  .qs-total svg { width: 12px; height: 12px; flex: none; transform: rotate(180deg); }
  .qs-total[aria-expanded="true"] svg { transform: rotate(0deg); }

  /* Høyre sone: kapselen som lever på `dirty`. Rolig grå så lenge det ikke
     finnes noe å lagre, merkefarget i det første tegnet blir skrevet. Da
     betyr fargen «du har noe utestående» — den eneste beskjeden som er verdt
     en blå flate på en skjerm i en bil. 200 ms så skiftet leses som en
     tilstandsendring og ikke et blink; `ease` og ikke `--ease-out`, fordi
     dette er en fargeendring, ikke en bevegelse inn eller ut. */
  .qs-save {
    flex: none; width: auto; min-width: 0; min-height: 40px; position: relative;
    padding: 0 18px; border-radius: 20px;
    font-size: 14.5px; font-weight: 500;
    background: var(--surface); border: 1px solid var(--line-strong); color: var(--ink-2);
    transition: background-color 200ms ease, border-color 200ms ease,
                color 200ms ease, transform 120ms var(--ease-out);
  }
  .qs-save::after { content: ''; position: absolute; inset: -3px; }
  .qs-save.is-dirty {
    background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600;
  }

  /* Rulleplassen fulgte det gamle båndet: 210 px her pluss ~92 px fra
     .qb-main/.qb-rail sine egne bunnputer ble 302 px reservert under siste
     innhold, mot et behov på 200,5 — over 100 px dødsone å rulle forbi til
     ingen nytte. Nytt behov: 108 px bånd + 16 px pusterom = 124, minus de
     ~92 som allerede finnes. */
  .quote-form { padding-bottom: calc(32px + env(safe-area-inset-bottom)); }
}

/* Materialet er en effekt, ikke bæringen: den som har bedt om mindre
   gjennomsiktighet får en tett pille i stedet, med samme geometri. */
@media (max-width: 1023.98px) and (prefers-reduced-transparency: reduce) {
  .qs-bar {
    background: var(--surface);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}

/* Den globale regelen øverst i fila nuller ut varigheten på alle overganger,
   men ikke selve trykk-sammentrekkingen — den ville bare skjedd momentant.
   Fargeskiftet på Lagre er informasjon og skal bestå; hoppet skal vekk. */
@media (max-width: 1023.98px) and (prefers-reduced-motion: reduce) {
  .qs-total:active, .qs-save:active { transform: none; }
}

/* ==========================================================================
   Tilbudsdetaljen (skjerm 04 i Sonida-portalen)
   --------------------------------------------------------------------------
   Deler skallet med byggeren: .qb (panelet), .qb-top (topplinja), .qb-btn,
   .qb-body/.qb-main, .qb-card, .qb-flabel, .qb-link, .qb-note. Alt som er
   detaljsidens eget heter .qd-*. Skinna er 340 px her, ikke 312 — designets
   egen bredde; topplinja er ett hakk høyere og knappene 40 px.
   ========================================================================== */

:root {
  /* Den grønne prikken på et fullført oppdragssteg. Ikke --ok (#065F46): den
     er tekstgrønn på lys flate, denne er en fylt flate med hvitt ikon på. */
  --ok-dot: #059669;
}

.qd .qb-top { padding: 15px 22px; gap: 14px; }
.qd .qb-btn { min-height: 40px; gap: 8px; }
.qd-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
.qd-title h1 { font-size: 17px; font-weight: 600; line-height: 1.2; letter-spacing: -0.03em; }
.qd-sub {
  margin-top: 5px;
  font: 400 12px/1.4 var(--font-mono); color: var(--ink-3);
}

.qd-rail {
  width: 340px; flex: none;
  border-left: 1px solid var(--line); background: var(--surface);
  padding: 20px;
  display: flex; flex-direction: column; gap: 14px;
}
.qd-sec + .qd-sec { padding-top: 14px; border-top: 1px solid var(--line-soft); }

/* ---- «Hva som har skjedd» ------------------------------------------------ */
.qd-tl { margin-top: 13px; display: flex; flex-direction: column; }
.qd-tl-item { display: flex; gap: 12px; }
.qd-tl-rail { display: flex; flex-direction: column; align-items: center; flex: none; }
.qd-tl-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-3); margin-top: 4px; }
.qd-tl-dot.is-now { background: var(--brand); }
.qd-tl-dot.is-bad { background: var(--bad); }
.qd-tl-line { flex: 1; width: 1px; background: var(--line); }
.qd-tl-body { padding-bottom: 14px; min-width: 0; }
.qd-tl-item:last-child .qd-tl-body { padding-bottom: 0; }
.qd-tl-title { font-size: 13px; font-weight: 500; line-height: 1.4; overflow-wrap: anywhere; }
.qd-tl-meta { margin-top: 4px; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
.qd-tl-meta.is-bad { color: var(--bad); }
.qd-tl-toggle {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--brand-ink); text-align: left;
}
.qd-tl-toggle:hover { text-decoration: underline; }
.qd-tl-days { margin-top: 8px; display: flex; flex-direction: column; gap: 7px; }

/* ---- Oppdragsstegene ----------------------------------------------------- */
.qd-stages { margin-top: 13px; display: flex; gap: 9px; flex-wrap: wrap; }
.qd-stage {
  flex: 1 1 150px; min-width: 0;
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--line); background: var(--surface);
  border-radius: 8px; padding: 12px 13px;
  font-family: inherit; text-align: left; cursor: pointer;
  transition: border-color 130ms ease, background-color 130ms ease;
}
.qd-stage:hover { border-color: var(--ink-3); }
.qd-stage-num {
  width: 21px; height: 21px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #6B7280; color: var(--ink-3);
  font: 600 10.5px/1 var(--font-mono);
}
.qd-stage-num svg { width: 12px; height: 12px; }
.qd-stage-label {
  flex: 1; min-width: 0;
  font-size: 12.5px; font-weight: 500; line-height: 1.3; color: var(--ink-3);
}
.qd-stage.is-done .qd-stage-num { border: 0; background: var(--ok-dot); color: #fff; }
.qd-stage.is-done .qd-stage-label { color: var(--ink); }
.qd-stage.is-now { border-color: var(--brand); background: var(--brand-03); }
.qd-stage.is-now .qd-stage-num { border: 0; background: var(--brand); color: #fff; }
.qd-stage.is-now .qd-stage-label { color: var(--ink); font-weight: 600; }
.qd-stage-now {
  flex: none;
  font: 500 9px/1 var(--font-mono); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--brand-ink);
}

/* ---- «Tilbudet» ---------------------------------------------------------- */
.qd-card { background: var(--surface); border: 1px solid var(--line); border-radius: 9px; overflow: hidden; }
.qd-head {
  padding: 14px 18px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.qd-pad { padding: 14px 18px; }
.qd-intro {
  padding: 14px 18px; border-bottom: 1px solid var(--line-soft);
  font-size: 13.5px; line-height: 1.62; color: var(--ink-2);
  white-space: pre-line; text-wrap: pretty;
}
.qd-room {
  padding: 10px 18px; background: var(--row-tint);
  border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 10px;
}
.qd-room-name {
  font: 600 11.5px/1 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.qd-room-sum {
  margin-left: auto;
  font: 400 12px/1 var(--font-mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.qd-lrow {
  display: grid; grid-template-columns: 1fr 78px 104px 116px; gap: 14px;
  padding: 11px 18px; align-items: center;
  border-bottom: 1px solid var(--line-soft);
}
.qd-lname { min-width: 0; font-size: 13.5px; line-height: 1.35; }
.qd-lsub { display: block; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.qd-lnum {
  font: 400 12.5px/1 var(--font-mono); color: var(--ink-3);
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.qd-lsum {
  font-size: 13.5px; font-weight: 500; line-height: 1;
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.qd-foot {
  padding: 14px 18px;
  display: flex; align-items: baseline; gap: 14px;
  justify-content: flex-end; flex-wrap: wrap;
}
.qd-foot-sum { font: 400 12.5px/1.5 var(--font-mono); color: var(--ink-3); }
.qd-foot-label { font-size: 14px; font-weight: 600; line-height: 1.2; }
.qd-foot-total {
  font-size: 22px; font-weight: 500; line-height: 1; letter-spacing: -0.04em;
  font-variant-numeric: normal; white-space: nowrap;
}

/* ---- Meldinger ----------------------------------------------------------- */
/* Tråden, boblene og svarraden er flyttet til de delte .conv-*-klassene
   (se seksjonen for skjerm 05/06 nederst): kunden og håndverkeren ser den
   samme samtalen, og skal ikke ha to sett regler som kan drifte fra hverandre.
   Panelet er ett hakk blåere hos håndverkeren enn i designet var det ikke -
   feltet er nøytralt begge steder nå. */

/* ---- Skinnas småting ----------------------------------------------------- */
.qd-url { margin-top: 10px; font: 400 12px/1.5 var(--font-mono); color: var(--ink-3); overflow-wrap: anywhere; }
.qd-actions { margin-top: 11px; display: flex; gap: 9px; flex-wrap: wrap; }
.qd-actions > * { flex: 0 1 auto; }
.qd-text { margin-top: 10px; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }
.qd-more { margin-top: 11px; display: flex; flex-direction: column; gap: 9px; align-items: flex-start; }
/* Handlingsfargen, ikke brødtekstens grå: «Åpne e-post på nytt», «Rediger
   kunde», «Dupliser» og «Trekk tilbake» sto i vanlig mørk tekst uten strek —
   rett under en blå «vis tidslinje» — og leste som overskrifter, ikke som noe
   man kan trykke på. */
.qd-more a, .qd-more button {
  display: flex; align-items: center; gap: 9px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 500; color: var(--brand-ink);
  text-decoration: none; text-align: left;
}
.qd-more a:hover, .qd-more button:hover { text-decoration: underline; }
/* De to som ikke kan angres skiller seg fra de som kan. Samme rolle som
   .qb-iconbtn.is-danger og .qb-btn.cu-danger ellers i huset. */
.qd-more .is-danger { color: var(--bad); }
.qd-more svg { width: 15px; height: 15px; color: currentColor; }
.qd-qr { margin-top: 12px; width: 176px; padding: 10px; background: #fff; border: 1px solid var(--line); border-radius: 8px; }
.qd-qr img { display: block; width: 100%; height: auto; }

/* ---- Telefonens sammendrag ----------------------------------------------- */
.qd-phone { display: none; }
/* Antall/enhet/pris faller bort som egne spor på telefon og kommer igjen som en
   mono-linje under beskrivelsen. Regelen MÅ stå før media-blokka under: samme
   spesifisitet, og da vinner den som står sist. */
.qd-lmeta-phone { display: none; }

@media (min-width: 1024px) and (max-width: 1319.98px) {
  /* Samme grunn som i byggeren: under designets egen bredde klemmer skinna
     beskrivelseskolonnen, så den legger seg under i stedet. */
  .qd .qb-body { flex-direction: column; }
  .qd-rail {
    width: auto; border-left: 0; border-top: 1px solid var(--line);
    display: grid; grid-template-columns: 1fr 1fr; gap: 20px 28px; align-items: start;
  }
  .qd-sec + .qd-sec { padding-top: 0; border-top: 0; }
}

@media (max-width: 1023.98px) {
  .qd { border: 0; border-radius: 0; background: transparent; }
  .qd .qb-top { padding: 12px 16px; gap: 11px; }
  .qd-title h1 { font-size: 14px; letter-spacing: -0.02em; }
  .qd-sub { margin-top: 3px; font-size: 10.5px; }
  /* Topplinjas knapper flytter ned i sammendraget; her er det plass til
     nummeret, kunden og statusmerket, ikke mer. */
  .qd .qb-top-act .qb-btn, .qd .qb-top-act form { display: none; }

  .qd-phone { display: flex; flex-direction: column; gap: 11px; }
  .qd-pcard { background: var(--surface); border: 1px solid var(--line); border-radius: 11px; padding: 15px 16px; }
  .qd-ptotal { display: flex; align-items: baseline; gap: 10px; }
  .qd-ptotal-label { flex: 1; min-width: 0; font: 400 12px/1 var(--font-mono); color: var(--ink-3); }
  .qd-ptotal-value {
    font-size: 20px; font-weight: 500; line-height: 1; letter-spacing: -0.04em;
    font-variant-numeric: normal;
  }
  .qd-pmeta { margin-top: 9px; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
  .qd-pq-head { display: flex; align-items: center; gap: 9px; }
  .qd-pq-head svg { width: 17px; height: 17px; color: var(--brand-ink); }
  .qd-pq-title { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500; line-height: 1.4; }
  .qd-pq-text { margin-top: 8px; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
  .qd-pbtn {
    margin-top: 11px; width: 100%;
    display: flex; align-items: center; justify-content: center; gap: 8px;
    min-height: 46px; background: var(--brand); color: #fff; border: 0;
    border-radius: 9px; font-family: inherit; font-size: 14px; font-weight: 600;
    text-decoration: none; cursor: pointer;
  }
  /* Uten dette arver ikonet ingen størrelse og fyller hele knappen. Funnet
     under gjennomgangen 20. august. */
  .qd-pbtn svg { width: 17px; height: 17px; flex: none; }
  .qd-prow { display: flex; gap: 9px; }
  .qd-prow > * {
    flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    min-height: 50px; border: 1px solid var(--line); background: var(--surface);
    border-radius: 10px; font-family: inherit; font-size: 13.5px; font-weight: 500;
    color: var(--ink-2); text-decoration: none; cursor: pointer;
  }
  /* «Send tilbud» må ligge i et <form> — den poster, den navigerer ikke. Formen
     er da et mellomledd som ikke skal tegnes: den slipper knappen inni gjennom
     til å bli selve flex-elementet, med samme utseende som naboene. Uten dette
     arvet formen knapperammen og knappen inni sto naken. */
  .qd-prow > form { flex: 1; display: flex; min-height: 0; border: 0; background: none; padding: 0; }
  .qd-prow > form > button {
    flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    min-height: 50px; border: 1px solid var(--line); background: var(--surface);
    border-radius: 10px; font-family: inherit; font-size: 13.5px; font-weight: 500;
    color: var(--ink-2); cursor: pointer;
  }
  /* Å sende er hele poenget med skjermen, så den ene knappen bærer farge. */
  .qd-prow > form > button {
    border-color: var(--brand-ink, #1D4ED8);
    background: var(--brand-ink, #1D4ED8);
    color: #FFF;
  }
  .qd-prow svg { width: 16px; height: 16px; }
  /* Fire handlinger (Rediger · Kopier · SMS · PDF) på et sendt tilbud: fire
     etiketter delt på 343 px gir 79 px hver, og «Rediger» med ikon trenger mer.
     Egen klasse i stedet for å endre regelen over — de andre radene har tre
     knapper og skal stå på en linje som før. Faller en knapp bort (kunde uten
     telefon = ingen SMS), strekker den siste seg over hele bredden. */
  .qd-prow.is-quad { flex-wrap: wrap; }
  .qd-prow.is-quad > * { flex: 1 1 calc(50% - 5px); }
  .qd-pmain {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    min-height: 52px; background: var(--brand); color: #fff; border: 0;
    border-radius: 10px; font-family: inherit; font-size: 15px; font-weight: 600;
    text-decoration: none; cursor: pointer; width: 100%;
  }
  .qd-pmain svg { width: 17px; height: 17px; }

  .qd .qb-main { padding: 16px 16px 6px; gap: 11px; }
  .qd-card, .qd-pcard { border-radius: 11px; }
  .qd-rail {
    width: auto; border-left: 0; border-top: 0; background: transparent;
    padding: 5px 16px 16px;
  }
  .qd-sec { background: var(--surface); border: 1px solid var(--line); border-radius: 11px; padding: 15px 16px; }
  .qd-sec + .qd-sec { padding-top: 15px; border-top: 1px solid var(--line); }

  /* Åpningene og lenkedelingen står allerede i sammendraget øverst. */
  .qd-sec-dup { display: none; }
  .qd-lrow { grid-template-columns: 1fr 96px; gap: 6px 12px; }
  .qd-lrow .qd-lnum { display: none; }
  .qd-lmeta-phone { display: block; }
  .qd-foot { justify-content: space-between; }
}

/* ==========================================================================
   Tilbudslista (skjerm 07 i Sonida-portalen)
   --------------------------------------------------------------------------
   Deler skallet med byggeren og detaljsiden: .qb (panelet) og .qb-top
   (topplinja). Listas egne deler heter .ql-*. Rutenettet er designets:
   104px 1fr 168px 128px 116px 40px.
   ========================================================================== */

.ql-total { font: 400 12px/1 var(--font-mono); color: var(--ink-3); }
.ql-add { display: none; }

.ql-filters {
  background: var(--surface); border-bottom: 1px solid var(--line);
  padding: 14px 22px; display: flex; flex-direction: column; gap: 11px;
}
.ql-filterrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Fast bredde: uten den startet pillene i «Oppdrag»-raden 8 px lenger inne enn
   i «Status»-raden, fordi etiketten er lengre. Drift-sidene stabler tre slike
   rader (Hendelse / Periode / Bedrift) og fikk samme trappetrinn. 64 px tar
   den lengste («Hendelse», 61,6). */
.ql-filterlabel {
  min-width: 64px;
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
}

/* Søkeraden er ikke hvit: fasiten lar panelets egen tone stå her, og båndet
   skiller pillefiltrene fra tabellen. Feltet er gjennomsiktig av samme grunn —
   i fasiten er det bare en ramme på tonen. */
.ql-searchrow {
  padding: 12px 20px; background: transparent;
  border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
}
.ql-search {
  flex: 1 1 240px; min-width: 0;
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--line); border-radius: 7px; padding: 11px 13px;
  background: transparent;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}
.ql-search:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16); }
.ql-search > svg { width: 17px; height: 17px; color: var(--ink-3); flex: none; }
.ql-search input {
  flex: 1; min-width: 0; border: 0; background: transparent; padding: 0;
  font-family: inherit; font-size: 13px; line-height: 1; color: var(--ink);
}
.ql-search input:focus { outline: none; }
.ql-search input::placeholder { color: var(--ink-3); }
.ql-sort {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 38px; padding: 0 32px 0 14px;
  border: 1px solid var(--line); border-radius: 7px; background: transparent;
  font-family: inherit; font-size: 13px; font-weight: 500; color: var(--ink-2);
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23374151' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 15px 15px;
}

/* Statuskolonnen er 184, ikke designets 168: «Akseptert» (76) + gap (6) +
   «Ikke startet» (86) er nøyaktig 168, så notisen brakk ned på egen linje og
   gjorde hver aksepterte rad 20 px høyere enn naboene. Med 184 står merket og
   notisen på samme linje i alle radene. */
.ql-grid { display: grid; grid-template-columns: 104px 1fr 184px 128px 116px 40px; gap: 14px; }
.ql-thead { padding: 10px 20px; background: var(--row-tint); border-bottom: 1px solid var(--line); }
.ql-thead span {
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.ql-thead .qb-r, .ql-r { text-align: right; }

.ql-row {
  padding: 13px 20px; align-items: center;
  border-bottom: 1px solid var(--line-soft); background: var(--surface);
  text-decoration: none; color: inherit;
  transition: background-color 120ms ease;
}
.ql-row:hover { background: var(--brand-03); }
.ql-num { font: 400 12.5px/1 var(--font-mono); color: var(--ink); white-space: nowrap; }
.ql-name { min-width: 0; font-size: 13.5px; line-height: 1.4; color: var(--ink); }
.ql-title { color: var(--ink-3); }
.ql-status { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.ql-note { font: 400 11px/1.3 var(--font-mono); color: var(--ink-3); }
.ql-note.is-bad { color: var(--bad); }
.ql-sum {
  font-size: 13.5px; font-weight: 500; line-height: 1; text-align: right;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ql-when { font: 400 11.5px/1 var(--font-mono); color: var(--ink-3); text-align: right; white-space: nowrap; }
.ql-chev { color: var(--ink-3); justify-self: end; display: flex; }
.ql-chev svg { width: 16px; height: 16px; }

.ql-foot { padding: 14px 20px; background: var(--surface); display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ql-count { font: 400 12px/1 var(--font-mono); color: var(--ink-3); }
/* «Vis mer» står ytterst til høyre i foten, telleren ytterst til venstre. Egen
   klasse i stedet for en style= i tre maler, nå som alle registrene har knappen.
   På telefon overtar .ql-foot .qb-btn { flex: 1 } og gjør den full bredde. */
.ql-more { margin-left: auto; }
.ql-empty { padding: 40px 20px; background: var(--surface); text-align: center; }
.ql-empty p { font-size: 13.5px; color: var(--ink-3); }
.ql-empty .qb-btn, .ql-empty .btn { margin-top: 14px; }

.ql-cards { display: none; }

@media (max-width: 1023.98px) {
  .ql-desk { display: none; }
  .ql-cards { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; }

  /* Designets telefontopp: tittelen til venstre, ett blått pluss-kvadrat til
     høyre. Tekstknappen ville tatt halve raden. */
  .qb-top .ql-newbtn { display: none; }
  .ql-add {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; flex: none;
    background: var(--brand); color: #fff; border-radius: 9px; text-decoration: none;
  }
  .ql-add svg { width: 19px; height: 19px; }

  .ql-filters { padding: 12px 16px; gap: 9px; }
  /* Pillene ruller vannrett i stedet for å bygge fire rader på 375 px. */
  .ql-filterrow {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; padding-bottom: 1px;
  }
  .ql-filterrow::-webkit-scrollbar { display: none; }
  .ql-filterlabel { flex: none; }
  .ql-searchrow { padding: 12px 16px; }
  .ql-search { flex: 1 1 100%; }
  .ql-sort { flex: 1 1 100%; min-height: 44px; }
  .ql-search input { font-size: 16px; }

  .ql-card {
    background: var(--surface); border: 1px solid var(--line); border-radius: 11px;
    padding: 14px 15px; text-decoration: none; color: inherit; display: block;
  }
  .ql-card-top { display: flex; align-items: baseline; gap: 10px; }
  .ql-card-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 500; line-height: 1.35; }
  .ql-card-sum { font-size: 14px; font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums; }
  .ql-card-title { margin-top: 4px; font-size: 12.5px; line-height: 1.45; color: var(--ink-3); }
  .ql-card-meta { margin-top: 10px; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
  /* Samme grunn som .rg-foot lenger nede: panelet er gjennomsiktig på telefon,
     så en hvit fot blir hengende igjen som en firkantet stripe under siste
     kort — 16 px bredere enn kortene, uten avrunding. Foten er tekst på
     papiret her. */
  .ql-foot { padding: 0 16px 16px; background: transparent; }
  .ql-foot .qb-btn { flex: 1; min-height: 46px; justify-content: center; }
  /* «Vis mer» er handlingen i foten og skal ha hele bredden på telefon, som i
     tilbudslista. I materiellfoten står den ellers og deler rad med
     «Sett kategoripåslag», og da leser to halve knapper som ett valg mellom
     dem. En klasse mer enn både .ql-foot .qb-btn over og .rg-foot .qb-btn
     lenger nede, så den vinner uansett hvilken av dem som står sist. */
  .ql-foot .qb-btn.ql-more { flex: 1 1 100%; }
}

/* ==========================================================================
   Akseptsiden og samtalen (skjerm 05 og 06 i Sonida-designet)
   --------------------------------------------------------------------------
   Alt kunden ser heter .acc-*; samtalens innmat heter .conv-* fordi den står
   BEGGE steder — på kundens akseptside og på håndverkerens tilbudsdetalj.
   Skjerm 06 er ikke en egen side: den er presentasjonen av den samme tråden,
   som panel med fast høyde på PC og som ark over siden på telefon.

   FARGENE: designet bruker bedriftens egen farge KUN i topplinja (den sier hvem
   avsenderen er). Alt annet på flaten er Sonidas eget system — handlingsblått
   på samtalen, nesten-svart på beslutningen. Den offentlige malen injiserer
   `:root { --brand: <bedriftens farge> }`, så var(--brand) ville gitt bedriftens
   farge der designet vil ha blått. Blåen står derfor som egne tokens under.
   ========================================================================== */

:root {
  /* Sonidas handlingsblå, uavhengig av bedriftens --brand. Samme verdier som
     --brand/--brand-ink/--brand-03/--brand-16 har i den interne appen. */
  --acc-blue: #1D4ED8;
  --acc-blue-ink: #1740B4;
  --acc-blue-03: #F7FAFF;
  --acc-blue-16: #C9DAFB;
  /* Designets ene farge uten token fra før: stiplet signaturkant, uutfylte
     stegsirkler og radioknapper. Samme grå som .qd-stage-num allerede bruker. */
  --acc-dash: #6B7280;
}

/* Synlig for skjermlesere, ikke for øyet. Den offentlige flaten laster ikke
   Tailwind, så .sr-only finnes ikke her. */
.acc-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Tospalta: dokumentet til venstre, beslutningen i en 392 px skinne ---- */
/* ---- Forhåndsvisningsstripa (J1) ----------------------------------------
   Bedriften ser sin egen kundeside. Rolig og lys, ikke en varselfarge: siden
   under er ikke i en feiltilstand, den er bare ikke skarpstilt. Stripa står i
   dokumentflyten (ikke fixed), så den ruller vekk og aldri dekker noe. */
.acc-previewbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 20px; padding: 11px 14px;
  background: var(--brand-06); border: 1px solid var(--brand-16); border-radius: 10px;
}
/* flex-basis, ikke auto: uten et minstemål regner flexboksen teksten som for
   bred til å dele linje med prikken, og prikken ble stående alene på linje 1. */
.acc-previewbar p {
  margin: 0; flex: 1 1 220px; min-width: 0;
  font: 400 13px/1.45 var(--font-sans); color: var(--ink-2);
}
.acc-previewdot {
  width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--brand);
}
.acc-previewback {
  margin-left: auto; font: 500 13px/1 var(--font-sans);
  color: var(--brand-ink); text-decoration: underline; white-space: nowrap;
}
@media (max-width: 767.98px) {
  /* På telefon får lenka egen linje i stedet for å presse teksten sammen. */
  .acc-previewbar { margin-bottom: 16px; }
  .acc-previewback { margin-left: 18px; }
}

.acc-grid { display: flex; gap: 32px; align-items: flex-start; }
.acc-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.acc-side { width: 392px; flex: none; display: flex; flex-direction: column; gap: 12px; }

/* Ingen position:sticky. Panelet er over 1000 px høyt med angrerettboksen og
   stegene i seg; en topp-sticky ville låst «Godta» utenfor synsfeltet på en
   vanlig laptop. Se docs/design-utelatt.md. */

/* ---- Statusstripa: tilbudet er avgjort ----------------------------------
   Erstatter det roterte .stamp-et som sto i høyrespalta til 20. august 2026.
   To grunner til å flytte den hit, øverst i DOKUMENTspalta:

   1. Høyrespalta stables UNDER dokumentet på telefon og i mellomsonen, og det
      finnes ingen order-omstokking for en avgjort tilstand. Kunden måtte rulle
      forbi hele tilbudet og hele samtalen for å se at hun hadde akseptert.
   2. Et stempel er en dekorasjon; det kunden trenger er en rolig faktalinje —
      hvem, når, og veien til kvitteringen.

   Formspråket er takkesidens (.thx-head/.thx-mark), ikke et nytt: hakesirkel,
   tittel, faktalinje. Ingen .no-print — en avgjort status skal med på papiret;
   bare lenken til kvitteringen er skjermbrukens eget. */
.acc-verdict {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--ink-3);
  border-radius: 10px; padding: 16px 20px;
}
.acc-verdict.is-ok { border-left-color: var(--ok); }
.acc-verdict.is-warn { border-left-color: var(--warn); }
.acc-verdict-mark {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--ink-3); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.acc-verdict.is-ok .acc-verdict-mark { background: var(--ok-dot); }
.acc-verdict.is-warn .acc-verdict-mark { background: var(--warn); }
.acc-verdict-mark svg { width: 19px; height: 19px; }
.acc-verdict-text { flex: 1 1 240px; min-width: 0; }
.acc-verdict-title {
  font-size: 17px; font-weight: 600; line-height: 1.2; letter-spacing: -0.025em;
  color: var(--ink); margin: 0;
}
.acc-verdict-fact {
  margin: 5px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2);
  max-width: 62ch; text-wrap: pretty;
}
.acc-verdict-link {
  flex: none; display: inline-flex; align-items: center; gap: 7px;
  min-height: 38px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--surface);
  font-size: 13px; font-weight: 500; color: var(--ink-2); text-decoration: none;
}
.acc-verdict-link:hover { border-color: var(--ink-3); color: var(--ink); }
.acc-verdict-link svg { width: 15px; height: 15px; flex: none; }

/* ---- Tittel og ingress --------------------------------------------------- */
.acc-title {
  font-size: 32px; font-weight: 700; line-height: 1.1; letter-spacing: -0.045em;
  text-wrap: pretty; max-width: 24ch; margin: 0;
}
.acc-intro {
  margin-top: 14px; font-size: 15.5px; line-height: 1.62; color: var(--ink-2);
  max-width: 60ch; text-wrap: pretty; white-space: pre-line;
}
/* Telefonens sum-blokk og gyldighetslinje: skjult på PC, der beløpet står i
   panelet ved siden av. */
.acc-phonesum, .acc-valid { display: none; }

/* ---- «Dette er med» ------------------------------------------------------ */
.acc-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; overflow: hidden;
}
.acc-chead {
  padding: 12px 20px; background: var(--row-tint);
  border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 10px;
}
.acc-clabel {
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
}
.acc-cmeta { margin-left: auto; font: 400 11.5px/1 var(--font-mono); color: var(--ink-3); }

.acc-row {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 20px; border-bottom: 1px solid var(--line-soft);
}
.acc-room > summary.acc-row { cursor: pointer; list-style: none; }
.acc-room > summary::-webkit-details-marker { display: none; }
.acc-room > summary:hover { background: var(--row-tint); }
.acc-rowmain { flex: 1; min-width: 0; }
.acc-rowname { font-size: 14.5px; font-weight: 500; line-height: 1.35; }
.acc-rowmeta {
  margin-top: 5px; font: 400 12px/1.4 var(--font-mono); color: var(--ink-3);
  display: flex; align-items: baseline;
}
/* Sammendraget kuttes med ellipse på den plassen raden faktisk har, ikke på et
   tegnantall - «· vis linjer» skal aldri bli det som forsvinner. */
.acc-rowsummary { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Telefonens hint. På PC står den samme oppfordringen i kortets hode
   («trykk for å se detaljene», 05.html:31), og raden er ren metatekst i
   samme grå som resten - ikke blå (05.html:36 og :167). */
.acc-rowhint { display: none; flex: none; color: var(--ink-3); white-space: nowrap; }
.acc-rowsum {
  font-size: 15px; font-weight: 500; line-height: 1;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Chevronen er et eget flex-element ETTER beløpet, så radene som har en
   (rommene) skjøv beløpet 31 px inn mens kjørelinja og sumraden sto helt ute
   til høyre. Fire tall i samme kolonne, to av dem innrykket. Radene uten
   chevron reserverer plassen i stedet. 17 px ikon + 14 px gap. */
.acc-row:not(:has(.acc-chev)) .acc-rowsum,
.acc-sumrow .acc-sumtotal { margin-right: 31px; }
.acc-chev { color: var(--ink-3); flex: none; display: flex; }
.acc-chev svg { width: 17px; height: 17px; display: block; transition: transform 160ms var(--ease-out); }
.acc-room[open] > summary .acc-chev svg { transform: rotate(180deg); }

/* Linjene bak «vis linjer»: antall, enhet, pris og rabatt — tallene telefonen
   ellers ville mistet når rommet slås sammen til en rad. */
.acc-sublines { background: var(--row-tint); border-bottom: 1px solid var(--line-soft); padding: 2px 20px 8px; }
.acc-subline { display: flex; gap: 14px; align-items: baseline; padding: 9px 0; }
.acc-subline + .acc-subline { border-top: 1px solid var(--line-soft); }
.acc-subname { flex: 1; min-width: 0; font-size: 13px; line-height: 1.4; color: var(--ink-2); }
.acc-submeta { display: block; margin-top: 3px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.acc-subsum {
  font: 400 12.5px/1 var(--font-mono); color: var(--ink-2);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.acc-sumrow { padding: 15px 20px; display: flex; align-items: center; gap: 14px; }
.acc-sumtext { flex: 1; min-width: 0; font-size: 13px; line-height: 1.4; color: var(--ink-3); }
.acc-sumtotal {
  font-size: 15px; font-weight: 500; line-height: 1;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.acc-estimate { padding: 0 20px 15px; }
.acc-estimate .estimate-note { margin-top: 0; padding-top: 0; border-top: 0; }

/* ---- Vilkår · Om avtalen · PDF ------------------------------------------- */
.acc-arows {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; overflow: hidden;
}
.acc-arows > * + * { border-top: 1px solid var(--line-soft); }
.acc-arow {
  display: flex; align-items: center; gap: 10px; padding: 14px 16px;
  font-size: 13.5px; font-weight: 500; line-height: 1.35; color: var(--ink);
  text-decoration: none; cursor: pointer; list-style: none;
}
.acc-arow::-webkit-details-marker { display: none; }
/* Trykk-respons. Pillene hadde ingen: fingeren traff, og ingenting bekreftet at
   trykket ble registrert. Akseptknappen ved siden av har hatt det hele tiden
   (.acc-accept lenger ned), så flaten var ujevn - noen ting svarte, andre ikke.
   0.98 og 140 ms ligger der en knapp føles «hørt» uten å bli leken; den globale
   prefers-reduced-motion-regelen slår den av for den som har bedt om det. */
.acc-arow { transition: transform 140ms var(--ease-out), background-color 140ms ease; }
.acc-arow:active { transform: scale(0.98); }
.acc-arow:hover { background: var(--row-tint); }
.acc-arow > svg { width: 17px; height: 17px; color: var(--ink-3); flex: none; }
.acc-arowtext { flex: 1; min-width: 0; }
.acc-arowsub { font-weight: 400; color: var(--ink-3); }
.acc-arow .acc-chev { margin-left: auto; }
.acc-arows details[open] > .acc-arow .acc-chev svg { transform: rotate(180deg); }
/* Skuffen ligger utenfor sin <details> (se accept/view.html), så nettleserens
   egen skjuling av lukket <details>-innhold gjelder den ikke - vi åpner og
   lukker den selv. Naboselektoren er grunnen til at skuffen MÅ bli stående
   rett etter sin egen <details> i malen. */
.acc-adrawer { display: none; padding: 0 16px 16px; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); }
.acc-arows > details[open] + .acc-adrawer { display: block; }
/* teksten hører til pilla over seg, ikke til en ny rad */
.acc-arows > .acc-adrawer { border-top: 0; }
.acc-adrawer p { margin: 0 0 10px; }
.acc-adrawer p:last-child { margin-bottom: 0; }
.acc-party + .acc-party { margin-top: 12px; }
.acc-party dt { color: var(--ink-3); }
.acc-party dd { margin: 0; overflow-wrap: anywhere; }

/* PC-formen er to piller på rad (05.html:90-92), ikke telefonens radkort
   (05.html:193-205): ingen kortflate, ingen fullbreddes rader, og PDF-en
   først. Undertekstene («standardvilkår», «parter og referanse») hører til
   radformen og faller ut - designets pille er bare ordet og en chevron.
   En åpen skuff legger seg på egen linje, ellers ville vilkårsteksten
   stått i en kolonne på under halve bredden. */
@media (min-width: 768px) {
  .acc-arows {
    background: none; border: 0; border-radius: 0; overflow: visible;
    display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start;
  }
  .acc-arows > * + * { border-top: 0; }
  .acc-arows > details { flex: none; }
  /* Pillene blir STÅENDE når en skuff åpnes. Tidligere tok hele <details>
     full bredde og pilla fulgte med ned på egen rad - den flyttet seg under
     fingeren idet du trykket (Anders, 21. august). Nå er skuffen et eget
     flex-barn som legges sist med order og bryter til neste linje alene. */
  .acc-arows > .acc-adrawer { order: 1; flex: 1 1 100%; }
  /* PDF-lenka er ikke en <details>, og står først som i designet. */
  .acc-arows > .acc-arow { order: -1; }
  .acc-arow {
    min-height: 42px; padding: 0 15px; gap: 8px;
    border: 1px solid var(--line); background: var(--surface); border-radius: 8px;
    font-size: 13px; line-height: 1; color: var(--ink-2);
  }
  .acc-arow > svg { width: 15px; height: 15px; }
  .acc-arowtext { flex: 0 1 auto; }
  .acc-arowsub { display: none; }
  .acc-arow .acc-chev { margin-left: 0; }
  .acc-arow .acc-chev svg { width: 15px; height: 15px; }
  .acc-adrawer { padding: 12px 4px 0; }
}

/* ---- Samtalen: kundens blå kort ------------------------------------------ */
/* Inngangskortet er telefonens vei inn i arket; på PC er kortet under selve
   samtalen, og inngangen er unødvendig. */
/* Designets venstrespalte: dokumentet, «Dette er med», SAMTALEN, og til slutt
   vilkår/PDF (05.html:62 og :90). På telefon bytter de to siste plass, så
   rekkefølgen settes med order begge steder - DOM-en holder dokumentet først,
   slik at en skjermleser hører hva som signeres før panelet. */
.acc-convwrap { display: flex; flex-direction: column; gap: 16px; order: 1; }
.acc-actions { order: 2; }
.acc-conventry { display: none; }
.acc-conv {
  background: var(--acc-blue-03); border: 1px solid var(--acc-blue);
  border-radius: 10px; padding: 20px 22px;
}
.conv-grip, .conv-close, .acc-conv-phonetitle { display: none; }
.acc-conv-head { display: flex; align-items: center; gap: 11px; }
.acc-conv-icon {
  width: 34px; height: 34px; border-radius: 9px; flex: none;
  background: var(--acc-blue); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.acc-conv-icon svg { width: 18px; height: 18px; }
.acc-conv-headtext { flex: 1; min-width: 0; }
.acc-conv-title { font-size: 16px; font-weight: 600; line-height: 1.25; letter-spacing: -0.025em; }
.acc-conv-sub { margin-top: 4px; font: 400 12.5px/1.4 var(--font-mono); color: var(--acc-blue-ink); }
.acc-conv-text {
  margin-top: 13px; font-size: 14px; line-height: 1.6; color: var(--ink-2);
  max-width: 58ch; text-wrap: pretty;
}
.acc-conv-panel {
  margin-top: 14px; background: var(--surface);
  border: 1px solid var(--acc-blue-16); border-radius: 9px; overflow: hidden;
}
/* Kundens panel er ett hakk tettere enn håndverkerens (designets egne tall). */
.acc-conv-panel .conv-scroll { max-height: 216px; padding: 14px; gap: 10px; }
/* ... og det gjelder boblene også. .conv-bubble bærer 04s verdier, fordi
   håndverkerens kort er den andre bruken; 05.html:74 og :78 er ett hakk
   mindre. Kun på PC: i arket gjelder 06s egne mål (se telefonblokka). */
@media (min-width: 768px) {
  .acc-conv-panel .conv-bubble { max-width: 78%; padding: 11px 13px; }
  .acc-conv-panel .conv-bubble-text { font-size: 13px; }
  .acc-conv-panel .conv-bubble-meta { margin-top: 5px; font-size: 10.5px; }
}

/* En rolig kvittering når spørsmålet er sendt. Står UTENFOR arket, så den er
   synlig på telefon også når arket er lukket. */
.acc-sent {
  padding: 12px 14px; background: var(--ok-bg); color: var(--ok);
  border: 1px solid var(--ok); border-radius: 8px;
  font-size: 13.5px; line-height: 1.5;
}

/* ---- Samtalens innmat: delt mellom akseptsiden og tilbudsdetaljen -------- */
.conv-scroll {
  max-height: 250px; overflow-y: auto;
  /* Rullingen stopper i tråden. Uten `contain` fortsetter bevegelsen i sida
     bak i det man treffer første eller siste melding — man drar for å lese
     eldre meldinger og oppdager at hele siden har flyttet seg under arket.
     `contain` og ikke `none`: den gummi-etterlikningen iOS gjør i enden er
     riktig tilbakemelding om at tråden er slutt, den skal bare ikke smitte. */
  overscroll-behavior: contain;
  padding: 16px 18px; display: flex; flex-direction: column; gap: 11px;
}
.conv-bubble {
  align-self: flex-start; max-width: 76%;
  background: var(--paper); border-radius: 10px 10px 10px 3px; padding: 12px 14px;
}
.conv-bubble-text { font-size: 13.5px; line-height: 1.5; white-space: pre-line; overflow-wrap: anywhere; }
.conv-bubble-meta { margin-top: 6px; font: 400 11px/1 var(--font-mono); color: var(--ink-3); }
.conv-bubble.is-own { align-self: flex-end; background: var(--acc-blue); border-radius: 10px 10px 3px 10px; }
.conv-bubble.is-own .conv-bubble-text { color: #fff; }
.conv-bubble.is-own .conv-bubble-meta { color: var(--acc-blue-16); }
.conv-empty { padding: 22px 16px; text-align: center; font-size: 13px; line-height: 1.55; color: var(--ink-3); }
.conv-closed { padding: 14px 16px; font-size: 13px; line-height: 1.5; color: var(--ink-3); border-top: 1px solid var(--line-soft); }
.conv-err { margin: 0; padding: 10px 14px 0; }

.conv-form {
  border-top: 1px solid var(--line-soft); background: var(--surface);
  padding: 12px 14px; display: flex; align-items: center; gap: 11px;
}
.conv-form textarea {
  flex: 1; min-width: 0; resize: none;
  border: 1px solid var(--line); border-radius: 8px; padding: 13px;
  font-family: inherit; font-size: 13.5px; line-height: 1.35; color: var(--ink);
  background: var(--surface);
}
.conv-form textarea::placeholder { color: var(--ink-3); }
.conv-form textarea:focus { outline: none; border-color: var(--acc-blue); box-shadow: 0 0 0 3px var(--acc-blue-16); }
.conv-send {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 0 18px; flex: none;
  background: var(--acc-blue); color: #fff; border: 0; border-radius: 8px;
  font-family: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  white-space: nowrap; transition: background-color 120ms ease, transform 120ms var(--ease-out);
}
.conv-send:hover { background: var(--acc-blue-ink); }
.conv-send:active { transform: scale(0.98); }
.conv-send svg { width: 16px; height: 16px; }
.conv-note { padding: 0 18px 16px; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
.conv-backdrop { display: none; }
/* Kun i arket: ikonet i hodet, lukkeknappen og håndverkerens to-linjers
   hode hører til overlegget, ikke til kortet som står i sideflyten på PC. */
.conv-sheetonly { display: none; }
.qd-sheettext { display: none; }

/* ---- Beslutningspanelet -------------------------------------------------- */
.acc-panel {
  background: var(--surface); border: 1px solid var(--ink);
  border-radius: 10px; padding: 22px 24px;
}
.acc-plabel {
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
}
/* Display-beløpene står med PROPORSJONALE siffer, ikke tabular — bevisst avvik
   fra designet, som spesifiserer tabular-nums på alle fire.

   Designets eksempelbeløp er hele kroner («20 730 kr»), så designeren så aldri
   et komma. Våre beløp har ekte øre (money.py: «Quote sums keep nok, where the
   øre are real» — takkesiden viser 30 414,06). Under tabular-nums får kommaet
   full sifferbredde: målt i Schibsted Grotesk er komma 17,8 px, nøyaktig som
   «0», og «20 730,00 kr» blir 168 px mot 150,4 px proporsjonalt. De 17,6 px
   legger seg som dødt rom rundt kommaet, og hovedbeløpet leses «20 730 , 00 kr».

   Tabular hører hjemme der siffer skal flukte loddrett — linjetabellen beholder
   den. Et enkeltstående display-tall har ingen kolonne å flukte med. */
.acc-amount {
  margin-top: 12px; font-size: 34px; font-weight: 500; line-height: 1;
  letter-spacing: -0.045em; font-variant-numeric: normal;
}
.acc-pmeta { margin-top: 10px; font: 400 12.5px/1.5 var(--font-mono); color: var(--ink-3); }
.acc-signer { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line-soft); }
.acc-lead { margin-top: 10px; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); text-wrap: pretty; }

.acc-field { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.acc-flabel {
  font: 500 11px/1 var(--font-mono); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-3);
}
.acc-input {
  width: 100%; border: 1px solid var(--line); border-radius: 8px;
  padding: 13px 14px; background: var(--surface);
  font-family: inherit; font-size: 14.5px; line-height: 1.2; color: var(--ink);
}
.acc-input::placeholder { color: var(--ink-3); }
.acc-input:focus { outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px var(--line); }

/* Egendefinert avkryssing: designets 20 px rute med rund hvit hake. Alltid AV
   som utgangspunkt — designet tegner den avhuket, men serveren krever at
   kunden faktisk krysser av (accept.py). */
.acc-consent { margin-top: 13px; display: flex; gap: 11px; align-items: flex-start; }
.acc-consent input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 20px; height: 20px; flex: none; margin: 1px 0 0; position: relative;
  border: 1.5px solid var(--acc-dash); border-radius: 5px;
  background: var(--surface); cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.acc-consent input[type="checkbox"]:checked { background: var(--acc-blue); border-color: var(--acc-blue); }
.acc-consent input[type="checkbox"]:checked::after {
  content: ""; position: absolute; left: 5.5px; top: 1.5px;
  width: 5px; height: 10px; border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.acc-consent > span { flex: 1; min-width: 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }

/* ---- Angrerett ----------------------------------------------------------- */
.acc-withdrawal {
  margin-top: 16px; background: var(--row-tint);
  border: 1px solid var(--line); border-left: 3px solid var(--ink);
  border-radius: 9px; padding: 14px 15px;
}
/* Skopet til selve avsnittet: en `p`-regel her slo .acc-plabel på etiketten
   over (0,1,1 mot 0,1,0), så «Angrerett — les før du godtar» kom ut som
   12,5 px brødtekst med 9 px marg i en boks med 14 px luft. */
.acc-withdrawal .withdrawal-lead { margin-top: 9px; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); text-wrap: pretty; }

/* ---- Stegene: signer nå, velg oppstart etterpå --------------------------- */
.acc-steps { margin-top: 14px; display: flex; align-items: center; gap: 9px; }
.acc-step { display: flex; align-items: center; gap: 9px; }
.acc-stepnum {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--acc-dash); color: var(--ink-3);
  font: 600 10.5px/1 var(--font-mono);
}
.acc-stepnum.is-done { border: 0; background: var(--ink); color: #fff; }
.acc-steplabel { font-size: 12px; font-weight: 500; line-height: 1.3; color: var(--ink); }
.acc-steplabel.is-done { font-weight: 400; color: var(--ink-3); }
.acc-stepline { flex: 1; min-width: 14px; height: 1px; background: var(--line); }
.acc-stepnote { margin-top: 9px; font-size: 12px; line-height: 1.55; color: var(--ink-3); text-wrap: pretty; }

/* ---- «Bestill med betalingsplikt» ---------------------------------------- */
/* Nesten-svart, ikke var(--brand): på DENNE siden er --brand bedriftens egen
   farge, og en gul knapp under en gul topplinje forsvinner. */
.acc-accept {
  margin-top: 16px; width: 100%;
  display: flex; align-items: center; justify-content: center;
  min-height: 56px; border: 0; border-radius: 9px;
  background: var(--ink); color: #fff;
  font-family: inherit; font-size: 16px; font-weight: 600; cursor: pointer;
  transition: opacity 120ms ease, transform 120ms var(--ease-out);
}
.acc-accept:disabled { opacity: 0.42; cursor: not-allowed; }
.acc-accept:not(:disabled):active { transform: scale(0.99); }
.acc-note { margin-top: 11px; text-align: center; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

.acc-keep {
  margin-top: 14px; background: var(--acc-blue-03);
  border: 1px solid var(--acc-blue-16); border-radius: 9px;
  padding: 13px 14px; display: flex; gap: 11px; align-items: flex-start;
}
.acc-keep svg { width: 17px; height: 17px; color: var(--acc-blue-ink); flex: none; margin-top: 1px; }
.acc-keep p { flex: 1; min-width: 0; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); text-wrap: pretty; }
.acc-keep strong { font-weight: 600; color: var(--ink); }

/* ---- Avslå: en rad nederst, begrunnelsen bak den ------------------------- */
.acc-decline { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line-soft); }
.acc-decline > summary {
  display: flex; align-items: center; justify-content: center;
  min-height: 44px; font-size: 13.5px; font-weight: 500; color: var(--ink-2);
  cursor: pointer; list-style: none; user-select: none;
}
.acc-decline > summary::-webkit-details-marker { display: none; }
.acc-decline > summary:hover { color: var(--ink); }
.acc-declineform { margin-top: 4px; }
.acc-declineform .textarea { width: 100%; font-size: 13.5px; }
.acc-declinebtn {
  margin-top: 12px; width: 100%; min-height: 44px;
  border: 1px solid var(--line); background: var(--surface); border-radius: 8px;
  font-family: inherit; font-size: 13.5px; font-weight: 500; color: var(--ink-2);
  cursor: pointer;
}
.acc-declinebtn:hover { border-color: var(--ink-3); color: var(--ink); }
.acc-decidenote { margin-top: 12px; font: 400 11px/1.5 var(--font-mono); color: var(--ink-3); }

/* Bunnlinja er telefonens; skjult på PC der panelet står ved siden av. */
.acc-bottombar { display: none; }

/* ==========================================================================
   Takkesiden (skjerm 05, høyre ramme)
   ========================================================================== */
.thx { display: flex; flex-direction: column; gap: 16px; align-items: flex-start; }
.thx-head { display: flex; align-items: center; gap: 12px; }
.thx-mark {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: var(--ok-dot); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.thx-mark svg { width: 20px; height: 20px; }
/* Avslått: samme sirkel, rolig farge. Grønt ville feiret et nei, rødt ville
   kjeftet på en kunde som gjorde nøyaktig det siden ber om. */
.thx-mark.is-quiet { background: var(--ink-3); }
.thx h1 { font-size: 28px; font-weight: 700; line-height: 1.12; letter-spacing: -0.045em; text-wrap: pretty; }
.thx-lead { font-size: 15.5px; line-height: 1.62; color: var(--ink-2); max-width: 58ch; text-wrap: pretty; }
.thx-card {
  width: 100%; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; padding: 20px 22px;
}
/* flex-start, ikke center: de to kolonnene har ulik høyde (signaturbildet kan
   bli 64 px), og sentrert falt «SIGNATUR» og «Å BETALE» fra hverandre — to
   mono-etiketter som leser som en overskriftsrad, 4–5 px i utakt. Med en ekte
   signatur ble spriket mye større. */
.thx-receipt { display: flex; flex-wrap: wrap; gap: 26px; align-items: flex-start; }
.thx-col { flex: 1 1 200px; min-width: 0; }
.thx-sig { margin-top: 10px; }
.thx-sig img { display: block; max-width: 240px; max-height: 64px; height: auto; }
.thx-signame { margin-top: 8px; font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
.thx-amount {
  margin-top: 10px; font-size: 23px; font-weight: 500; line-height: 1;
  letter-spacing: -0.04em; font-variant-numeric: normal;
}
.thx-downloads { flex: 0 1 auto; display: flex; flex-direction: column; gap: 9px; }
.thx-dl {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--surface);
  font-size: 13px; font-weight: 500; color: var(--ink-2); text-decoration: none;
}
.thx-dl:hover { border-color: var(--ink-3); color: var(--ink); }
.thx-dl svg { width: 15px; height: 15px; flex: none; }

.thx-start { border-width: 2px; border-color: var(--ink); }
.thx-badge {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--ink); color: #fff; border-radius: 4px; padding: 6px 9px;
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase;
}
.thx-badge svg { width: 13px; height: 13px; }
.thx-badgerow { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
/* Stegene ligger INNE i raden her (05.html:350), ikke som et eget avsnitt
   under - .acc-steps' egen margin dyttet dem ut av flukt med merket. */
.thx-badgerow .acc-steps { margin-top: 0; }
/* Spørsmålet «Når skal vi starte?». Det er en <legend> i skjemaet (den
   grupperer de to radioene for skjermlesere), så .thx-q deler typografien
   med den i stedet for at malen setter den på nytt. */
.thx-q, .thx-start legend { font-size: 16px; font-weight: 600; line-height: 1.25; letter-spacing: -0.025em; }
.thx-q { margin-top: 14px; }
.thx-explain { margin-top: 9px; font-size: 14px; line-height: 1.6; color: var(--ink-2); max-width: 62ch; text-wrap: pretty; }
.thx-choices { margin-top: 15px; display: flex; gap: 11px; flex-wrap: wrap; }
.thx-choice {
  flex: 1 1 250px; min-width: 0; display: flex; gap: 12px; align-items: flex-start;
  border: 1px solid var(--line); border-radius: 9px; padding: 15px 16px;
  cursor: pointer; transition: border-color 130ms ease, background-color 130ms ease;
}
.thx-choice:hover { border-color: var(--ink-3); }
.thx-choice:has(input:checked) { border-color: var(--ink); background: var(--row-tint); }
.thx-choice input[type="radio"] {
  appearance: none; -webkit-appearance: none;
  width: 20px; height: 20px; flex: none; margin: 1px 0 0; position: relative;
  border: 2px solid var(--acc-dash); border-radius: 50%; background: var(--surface);
  cursor: pointer;
}
.thx-choice input[type="radio"]:checked { border-color: var(--acc-blue); }
.thx-choice input[type="radio"]:checked::after {
  content: ""; position: absolute; left: 3px; top: 3px;
  width: 10px; height: 10px; border-radius: 50%; background: var(--acc-blue);
}
.thx-choicetext { min-width: 0; }
.thx-choicename { font-size: 14px; font-weight: 500; line-height: 1.35; }
.thx-choicesub { margin-top: 5px; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
/* Begge er <span>. Klassene ble tegnet for to linjer — margin-top over sier det
   — men ingen mal brukte underteksten før 20. august 2026, så det ble aldri
   prøvd: valgnavnet og konsekvensen fløt sammen til en løpende setning
   («… tidligst 4. september 2026 Du beholder angreretten i hele fristen.»).
   Egen regel med en klasse mer, i stedet for å endre de to over. */
.thx-choicetext > .thx-choicename,
.thx-choicetext > .thx-choicesub { display: block; }
.thx-save {
  margin-top: 15px; width: 100%;
  display: flex; align-items: center; justify-content: center;
  min-height: 52px; border: 0; border-radius: 9px;
  background: var(--ink); color: #fff;
  font-family: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
}
.thx-save:active { transform: scale(0.99); }

.thx-conv {
  width: 100%; background: var(--acc-blue-03); border: 1px solid var(--acc-blue);
  border-radius: 10px; padding: 20px 22px;
}
.thx-convbtn {
  margin-top: 13px; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 18px; border-radius: 9px;
  background: var(--acc-blue); color: #fff; text-decoration: none;
  font-size: 14.5px; font-weight: 600;
}
.thx-convbtn:hover { background: var(--acc-blue-ink); }
.thx-convbtn svg { width: 16px; height: 16px; }
.thx-back { font-size: 13.5px; }
.thx-contact { font-size: 13px; line-height: 1.6; color: var(--ink-2); }

/* ==========================================================================
   Telefon (< 768 px). Designet er tegnet for 390 px viewport med 18 px gutter.
   ========================================================================== */
@media (max-width: 767.98px) {
  /* align-items MÅ tilbake til stretch: flex-start er riktig for tospalta,
     men i en kolonne gjør den at hvert kort sizes til max-content - og da
     ruller hele siden sidelengs på en telefon. */
  .acc-grid { flex-direction: column; align-items: stretch; gap: 16px; }
  .acc-side { width: 100%; }
  /* Designet setter 14 px mellom kortene og 16 px fra dokumentet til det
     første (05.html:160, :193 og :205). */
  .acc-main { gap: 14px; }
  .acc-doc { margin-bottom: 2px; }
  /* Statusstripa: knappen legger seg under teksten i stedet for å presse
     tittelen ned i to-tre linjer på 375 px. align-items er flex-start her:
     faktalinja brytes til tre linjer på denne bredden, og en sentrert
     hakesirkel havnet da utenfor tittelen den hører til. */
  .acc-verdict { padding: 14px 16px; gap: 12px; align-items: flex-start; }
  .acc-verdict-mark { margin-top: 1px; }
  .acc-verdict-title { font-size: 16px; }
  .acc-verdict-link { flex: 1 1 100%; justify-content: center; min-height: 44px; }
  /* Designets rekkefølge på telefon: dokumentet, «Dette er med», vilkår/PDF,
     inngangen til samtalen — og deretter signeringen. På PC ligger samtalen
     over vilkårsknappene i venstrespalta; de to bytter plass her. */
  .acc-actions { order: 1; }
  .acc-convwrap { order: 2; }

  .acc-title { font-size: 23px; line-height: 1.15; letter-spacing: -0.04em; max-width: none; }
  .acc-intro { margin-top: 12px; font-size: 13.5px; line-height: 1.55; max-width: none; }
  .acc-phonesum { display: flex; margin-top: 14px; align-items: baseline; gap: 11px; }
  .acc-phonesum-value {
    font-size: 30px; font-weight: 500; line-height: 1; letter-spacing: -0.045em;
    font-variant-numeric: normal;
  }
  .acc-phonesum-meta { font: 400 12px/1.3 var(--font-mono); color: var(--ink-3); }
  .acc-valid { display: block; margin-top: 14px; font: 400 11.5px/1.3 var(--font-mono); color: var(--ink-3); }

  .acc-card, .acc-arows { border-radius: 11px; }
  .acc-chead { padding: 11px 16px; gap: 9px; }
  .acc-cmeta { font-size: 11px; }
  .acc-cmeta-long { display: none; }
  .acc-row { padding: 14px 16px; gap: 11px; }
  .acc-rowname { font-size: 14px; }
  .acc-rowmeta { margin-top: 4px; font-size: 11.5px; }
  .acc-rowhint { display: inline; }
  .acc-rowsum { font-size: 14px; }
  .acc-chev svg { width: 16px; height: 16px; }
  .acc-sublines { padding: 2px 16px 8px; }
  .acc-sumrow { padding: 13px 16px; gap: 10px; }
  .acc-sumtext { font-size: 12.5px; }
  /* Mva-prosenten faller ut for å holde fotlinja på en linje på 375 px. */
  .acc-vatpct { display: none; }
  .acc-sumtotal { font-size: 14px; }
  .acc-estimate { padding: 0 16px 13px; }

  /* Inngangen til arket. Vises kun når JavaScript faktisk har slått arket på —
     uten JS står tråden i sideflyten som før, og en knapp som ikke åpner noe
     ville vært en blindvei. */
  .conv-js .acc-conventry {
    display: flex; align-items: center; gap: 12px;
    background: var(--acc-blue-03); border: 1px solid var(--acc-blue);
    border-radius: 11px; padding: 14px 16px;
  }
  .acc-conventry-icon {
    width: 34px; height: 34px; border-radius: 9px; flex: none;
    background: var(--acc-blue); color: #fff;
    display: flex; align-items: center; justify-content: center;
  }
  .acc-conventry-icon svg { width: 17px; height: 17px; }
  .acc-conventry-text { flex: 1; min-width: 0; }
  .acc-conventry-title { display: block; font-size: 14.5px; font-weight: 600; line-height: 1.25; letter-spacing: -0.02em; }
  .acc-conventry-sub { display: block; margin-top: 3px; font: 400 11.5px/1.4 var(--font-mono); color: var(--acc-blue-ink); }
  .acc-conventry-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; padding: 0 15px; flex: none; border: 0; border-radius: 9px;
    background: var(--acc-blue); color: #fff;
    font-family: inherit; font-size: 13.5px; font-weight: 600;
    white-space: nowrap; cursor: pointer;
  }

  /* ---- Arket: tråden legger seg OVER siden, aldri i den ------------------ */
  .conv-js .conv-sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 49;
    display: flex; flex-direction: column;
    max-height: min(520px, 79dvh);
    background: var(--surface); border: 0; border-top: 1px solid var(--line);
    border-radius: 22px 22px 0 0; padding: 0; margin: 0;
    box-shadow: 0 -20px 40px -24px rgba(17, 24, 39, 0.45);
    transform: translateY(101%); visibility: hidden;
    transition: transform 260ms var(--ease-out), visibility 260ms;
  }
  .conv-js .conv-sheet.is-open { transform: translateY(0); visibility: visible; }
  .conv-js .conv-backdrop {
    display: block; position: fixed; inset: 0; z-index: 48;
    background: rgb(17 24 39 / 0.42);
    opacity: 0; visibility: hidden;
    transition: opacity 200ms ease, visibility 200ms;
  }
  .conv-js .conv-backdrop.is-open { opacity: 1; visibility: visible; }

  .conv-js .conv-sheet .conv-grip {
    display: block; width: 44px; height: 5px; border-radius: 999px;
    background: var(--line); margin: 12px auto 0; flex: none;
  }
  .conv-js .conv-sheet .conv-sheetonly { display: flex; }
  /* Håndverkerens ark: kundens navn og tilbudsreferansen i stedet for
     kortets «Meldinger · samme tråd som kunden ser» (06.html:56-58). */
  .conv-js .conv-sheet .qd-sheettext { display: block; flex: 1; min-width: 0; }
  .conv-js .conv-sheet .qd-sheettext .acc-conv-title,
  .conv-js .conv-sheet .qd-sheettext .acc-conv-sub { display: block; }
  .conv-js .conv-sheet .qb-flabel,
  .conv-js .conv-sheet .qb-suffix { display: none; }
  .conv-js .conv-sheet .qd-head { flex-wrap: nowrap; }
  .conv-js .conv-sheet .acc-conv-head,
  .conv-js .conv-sheet .qd-head {
    padding: 11px 16px 12px; margin: 0; border-bottom: 1px solid var(--line); flex: none;
  }
  .conv-js .conv-sheet .acc-conv-icon { width: 32px; height: 32px; }
  .conv-js .conv-sheet .acc-conv-icon svg { width: 17px; height: 17px; }
  .conv-js .conv-sheet .acc-conv-title { font-size: 14.5px; line-height: 1.2; letter-spacing: -0.02em; }
  .conv-js .conv-sheet .acc-conv-sub { margin-top: 3px; font-size: 11px; line-height: 1.3; color: var(--ink-3); }
  /* PC-tittelen («Spør oss om hva som helst») bytter til avsenderens navn. */
  .conv-js .conv-sheet .acc-conv-desktitle { display: none; }
  .conv-js .conv-sheet .acc-conv-phonetitle { display: block; }
  .conv-js .conv-sheet .acc-conv-text { display: none; }
  .conv-js .conv-sheet .conv-close {
    display: inline-flex; align-items: center; justify-content: center;
    margin-left: auto; width: 40px; height: 40px; flex: none;
    border: 1px solid var(--line); border-radius: 9px; background: var(--surface);
    color: var(--ink-2); cursor: pointer;
  }
  .conv-js .conv-sheet .conv-close svg { width: 17px; height: 17px; }

  .conv-js .conv-sheet .acc-conv-panel {
    margin: 0; border: 0; border-radius: 0; flex: 1; min-height: 0;
    display: flex; flex-direction: column;
  }
  .conv-js .conv-sheet .conv-scroll,
  .conv-js .conv-sheet .acc-conv-panel .conv-scroll {
    flex: 1; min-height: 0; max-height: none; padding: 14px 16px; gap: 10px;
  }
  .conv-js .conv-sheet .conv-form {
    border-top: 1px solid var(--line); flex: none; padding: 12px 16px; gap: 10px;
  }
  .conv-js .conv-sheet .conv-form:last-child { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
  .conv-js .conv-sheet .conv-note { padding: 0 16px calc(14px + env(safe-area-inset-bottom)); }
  .conv-js .conv-sheet .conv-closed { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }

  /* Boblene i arket: designets egne mål, ett hakk større enn på PC. */
  .conv-sheet .conv-bubble { max-width: 80%; border-radius: 12px 12px 12px 4px; padding: 12px 14px; }
  .conv-sheet .conv-bubble.is-own { border-radius: 12px 12px 4px 12px; }
  .conv-sheet .conv-bubble-meta { font-size: 10.5px; line-height: 1; }

  /* 16 px i skrivefeltet: iOS zoomer hele viewporten under det, og i et
     fastposisjonert ark er den zoomen ødeleggende. Paddingen ned til 12 px så
     feltet fortsatt måler 48 px, i flukt med Send-knappen. */
  .conv-form textarea { font-size: 16px; padding: 12px 13px; border-radius: 9px; }
  .conv-send { min-height: 48px; }
  /* I arket er Send designets kvadrat (06.html:36 og :66), ikke en pille:
     «Send svar» gjorde knappen 127 px bred på en 375 px rad. Ordet står
     igjen for skjermlesere. */
  .conv-js .conv-sheet .conv-send {
    width: 48px; height: 48px; min-height: 48px; padding: 0; gap: 0; border-radius: 9px;
  }
  .conv-js .conv-sheet .conv-send svg { width: 18px; height: 18px; }
  .conv-js .conv-sheet .conv-sendlabel {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  /* ---- Panelet ---------------------------------------------------------- */
  .acc-panel { border-width: 2px; border-radius: 11px; padding: 16px; }
  /* Telefonpanelet starter rett på «Signer» (05.html:214). Beløpet står
     allerede to steder på skjermen - i .acc-phonesum øverst i dokumentet og
     i den faste bunnlinja - og et tredje hode med hårstrek la ~130 px foran
     det kunden faktisk skal gjøre her. */
  .acc-panel > .acc-plabel, .acc-amount, .acc-pmeta { display: none; }
  .acc-signer { margin-top: 0; padding-top: 0; border-top: 0; }
  .acc-input { font-size: 16px; border-radius: 9px; }
  .acc-accept { margin-top: 14px; font-size: 15.5px; border-radius: 10px; }
  .acc-declineform .textarea { font-size: 16px; }
  /* Designet krymper hvert mellomrom i panelet på telefon (05.html:228-243). */
  .acc-withdrawal { margin-top: 14px; }
  .acc-steps { margin-top: 13px; }
  .acc-note { margin-top: 10px; }
  .acc-keep { margin-top: 13px; }
  .acc-keep svg { width: 16px; height: 16px; }
  .acc-decline { margin-top: 13px; padding-top: 13px; }
  .acc-decline > summary { min-height: 46px; }

  /* ---- Den faste bunnlinja ---------------------------------------------- */
  /* Opak og transform-fri: en frostet fast linje maler bare om når rullingen
     stopper på iOS, og en transform på et position:fixed-element gjør at linja
     ruller med siden. Samme erfaring som .app-tabbar. */
  .acc-bottombar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 44;
    display: flex; align-items: center; gap: 12px;
    background: var(--surface); border-top: 1px solid var(--line);
    padding: 12px 16px calc(16px + env(safe-area-inset-bottom));
  }
  .acc-bb-text { flex: 1; min-width: 0; }
  .acc-bb-label { font: 400 11px/1 var(--font-mono); color: var(--ink-3); }
  .acc-bb-value {
    margin-top: 4px; font-size: 19px; font-weight: 500; line-height: 1;
    letter-spacing: -0.04em; font-variant-numeric: normal;
  }
  .acc-bb-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 50px; padding: 0 22px; flex: none;
    background: var(--ink); color: #fff; border-radius: 10px;
    font-size: 15px; font-weight: 600; text-decoration: none;
  }
  /* Plass til å rulle personvernlinja og bunnteksten helt fri av linja.
     Foten er SØSKEN av <main>, så padding på main klarerte den aldri -
     «Levert av …» lå helt skjult bak den faste linja. */
  body.acc-deciding .site-foot { padding-bottom: calc(91px + env(safe-area-inset-bottom)); }

  /* ---- Takkesiden ------------------------------------------------------- */
  .thx { gap: 14px; }
  .thx-mark { width: 36px; height: 36px; }
  .thx-mark svg { width: 19px; height: 19px; }
  .thx h1 { font-size: 22px; line-height: 1.15; letter-spacing: -0.04em; }
  .thx-lead { font-size: 13.5px; line-height: 1.6; max-width: none; }
  .thx-card { border-radius: 11px; padding: 15px 16px; }
  /* Kvitteringen er EN kortkropp på telefon (05.html:301-307): signaturen,
     en hårstrek, og «Å betale» som en baseline-rad med beløpet til høyre -
     ikke to stablede etikett/verdi-kolonner. */
  .thx-receipt { gap: 12px; }
  .thx-col { flex: 1 1 100%; }
  .thx-receipt .thx-col + .thx-col {
    padding-top: 12px; border-top: 1px solid var(--line-soft);
    display: flex; align-items: baseline; gap: 10px;
  }
  .thx-receipt .thx-col + .thx-col .acc-plabel {
    flex: 1; min-width: 0;
    font: 400 12.5px/1.4 var(--font-sans); letter-spacing: 0;
    text-transform: none; color: var(--ink-2);
  }
  .thx-receipt .thx-col + .thx-col .thx-amount { margin-top: 0; }
  .thx-amount { font-size: 18px; }
  .thx-downloads { flex: 1 1 100%; }
  .thx-dl { min-height: 48px; justify-content: center; border-radius: 9px; }
  .thx-badge { gap: 7px; padding: 6px 8px; font-size: 9.5px; letter-spacing: 0.1em; }
  .thx-q, .thx-start legend { font-size: 15px; }
  .thx-explain { font-size: 13px; line-height: 1.55; max-width: none; }
  .thx-choices { margin-top: 12px; flex-direction: column; gap: 9px; }
  .thx-choice { flex: 1 1 auto; gap: 11px; padding: 13px 14px; }
  .thx-choicename { font-size: 13.5px; }
  .thx-choicesub { font-size: 12px; }
  /* Samtalekortet krympes som resten (05.html:289-298); telefonreglene for
     .acc-conv-* er skopet til arket, og traff aldri takkesiden. */
  .thx-conv { border-radius: 11px; padding: 14px 15px; }
  .thx-conv .acc-conv-icon { width: 32px; height: 32px; }
  .thx-conv .acc-conv-icon svg { width: 17px; height: 17px; }
  .thx-conv .acc-conv-title { font-size: 14.5px; letter-spacing: -0.02em; }
  .thx-conv .acc-conv-text { margin-top: 11px; font-size: 13px; line-height: 1.55; }
  .thx-convbtn { margin-top: 11px; width: 100%; }
}

/* Mellomsonen 768–1099 px: designet tegner ingen variant. Skinna legger seg
   under dokumentet i stedet for å klemme det. */
@media (min-width: 768px) and (max-width: 1099.98px) {
  .acc-grid { flex-direction: column; align-items: stretch; gap: 20px; }
  .acc-side { width: 100%; }
  .acc-panel { max-width: 460px; }
}

/* ==========================================================================
   Utskrift: papiret er dokumentet, ikke flaten rundt det.
   ========================================================================== */
@media print {
  .acc-grid { display: block; }
  .acc-side { width: auto; }
  .acc-card, .acc-arows { break-inside: avoid; }
  /* Pillene er skjermens form (se @media min-width: 768px). På papiret er
     vilkårene og partsopplysningene en liste med tekst, ikke to knapper. */
  .acc-arows {
    display: block; background: var(--surface);
    border: 1px solid var(--line); border-radius: 10px;
  }
  .acc-arows > * + * { border-top: 1px solid var(--line-soft); }
  .acc-arow {
    min-height: 0; padding: 14px 16px; gap: 10px;
    border: 0; border-radius: 0; font-size: 13.5px; line-height: 1.35;
  }
  .acc-arowsub { display: inline; }
  .acc-adrawer { padding: 0 16px 16px; }
  /* Vilkårene og partsopplysningene ligger bak <details> på skjermen; på
     papiret skal de stå, uansett om kunden foldet dem ut. */
  .acc-arows > .acc-adrawer { display: block !important; }
  .acc-arows .acc-chev { display: none; }
  .acc-room > .acc-sublines { display: block !important; }
  .acc-room .acc-chev { display: none; }
}

/* ---- Å flytte en linje: se at den løftes, og hvor den lander -------------- */
/* Rotårsaken til at det så ut som ingenting skjedde var at draggable satt på
   det 14 px store grepet: nettleseren dro et bilde av ikonet. Nå settes hele
   raden som dragbilde i onDragStart. Resten her er de to tilbakemeldingene
   som mangler: raden man tok tak i blir en skygge av seg selv, og en strek
   viser nøyaktig hvor den havner. Kun opacity og transform animeres. */
.qb-dragwrap { position: relative; }

.qb-dragwrap.is-dragging { opacity: 0.35; }
.qb-dragwrap.is-dragging .qb-row,
.qb-dragwrap.is-dragging .qb-room { background: var(--brand-03); }

/* Landingsstreken. 2 px i handlingsfargen, med en liten knott i venstrekanten
   så den leses som «her» og ikke som en tilfeldig radskille. */
.qb-dragwrap.is-drop-before::before,
.qb-dragwrap.is-drop-after::after {
  content: "";
  position: absolute; left: 0; right: 0; height: 2px; z-index: 3;
  background: var(--brand); border-radius: 2px;
  box-shadow: -4px 0 0 0 var(--brand);
  pointer-events: none;
}
.qb-dragwrap.is-drop-before::before { top: -1px; }
.qb-dragwrap.is-drop-after::after { bottom: -1px; }

/* Landingen: raden blinker kort i handlingsfargens lyseste fylling og setter
   seg de siste pikslene på plass. 420 ms — lenge nok til å sees, kort nok til
   at den ikke er i veien for neste flytting. */
@keyframes qb-snap {
  0%   { background: var(--brand-06); transform: translateY(-2px); }
  100% { background: transparent; transform: translateY(0); }
}
.qb-dragwrap.is-snapped .qb-row,
.qb-dragwrap.is-snapped .qb-room {
  animation: qb-snap 420ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .qb-grip { cursor: grab; }
  .qb-grip:active { cursor: grabbing; }
  /* Kjørelinja kan ikke flyttes: den hører ikke til noe rom og ligger alltid
     nederst. Grepet sier det med markøren i stedet for å late som. */
  .qb-grip.is-fixed { cursor: default; opacity: 0.45; }
  .qb-grip.is-fixed:hover { background: transparent; }
}

/* Redusert bevegelse: behold fargene som forklarer hva som skjer, fjern
   forflytningen. */
@media (prefers-reduced-motion: reduce) {
  @keyframes qb-snap {
    0%   { background: var(--brand-06); }
    100% { background: transparent; }
  }
}

/* ---- Et rom skal leses som en bolk --------------------------------------- */
/* Linjene under en romoverskrift så nøyaktig ut som de ugrupperte: samme flate,
   samme innrykk, ingenting som sa at de hørte sammen. En 3 px kant i venstre
   marg binder overskriften og linjene under den, og innrykket gjør hierarkiet
   synlig uten å legge til enda en farge. */
.qb-dragwrap.is-roomhead .qb-room {
  box-shadow: inset 3px 0 0 0 var(--brand-16);
}
.qb-dragwrap.in-room .qb-row {
  box-shadow: inset 3px 0 0 0 var(--brand-16);
  padding-left: 32px;
  background: var(--brand-03);
}
/* Bunnen av bolken: en tydeligere strek der rommet slutter, så neste rom eller
   en ugruppert linje ikke ser ut som en fortsettelse. */
.qb-dragwrap.is-roomlast .qb-row { border-bottom-color: var(--line-strong); }

/* Drop-markøren må fortsatt leses inne i en romramme. */
.qb-dragwrap.in-room.is-drop-before::before,
.qb-dragwrap.in-room.is-drop-after::after { left: 3px; }

@media (max-width: 1023.98px) {
  /* Telefonen har allerede rommene som egne kort — der ville kanten vært støy. */
  .qb-dragwrap.in-room .qb-row,
  .qb-dragwrap.is-roomhead .qb-room { box-shadow: none; padding-left: 18px; background: transparent; }
}

/* =========================================================================
   INNGANGSFLATENE — skjerm 10 «Kom i gang», 11 «Innlogging», 18 «Prøveperioden»
   -------------------------------------------------------------------------
   De tre flatene en bedrift møter FØR og RUNDT selve arbeidet: registreringen,
   innloggingen og skjermen når prøveperioden er ute. Felles for alle tre er at
   de bærer SONIDAS merke, ikke kundens — den ene unntaket er bedriftens egen
   påloggingslenke (/logg-inn/<slug>/), der en full-bredde plate på toppen
   bærer bedriftens farge og navn. Selve knappen der er nesten-svart, ikke
   bedriftsfargen: designet vil ikke ha en tredje farge i bildet.

   Prefiksene: .login-* (11), .reg-* (10), .trial-* (18), og feltrioen
   .fld / .fld-label / .fld-help som begge skjemaflatene deler. Feltrioen er
   en systemkomponent — mono-versal etikett over feltet — og rører bevisst
   IKKE .label, som skjermene som ennå ikke er bygget om lever på.
   ========================================================================= */

:root {
  /* Feilboksens tre verdier. --bad-bg (#FEE2E2) er mørkere enn flaten designet
     tegner, og hverken kanten eller teksten fantes fra før. Samme boks går
     igjen på skjerm 14 og 19. */
  --bad-soft: #FEF2F2;
  --bad-line: #FCA5A5;
  --bad-deep: #7F1D1D;
}

/* ---- Feltrioen (deles av 10 og 11) -------------------------------------- */
.fld { display: flex; flex-direction: column; gap: 6px; }
.fld-label {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
/* 12 px, ikke 11. Under 12 er kroppstekst et antimønster, og disse er ikke
   alltid korte bildetekster: den lengste .fld-help i appen er 209 tegn. Mono
   beholdes - den hører sammen med mono-versal-etiketten over feltet. */
.fld-help { font: 400 12px/1.45 var(--font-mono); color: var(--ink-3); }
/* Avkryssingsboksene fikk størrelsen sin fra Tailwinds h-4 w-4 (16 px). Samme
   mål, men husets egen klasse — Tailwind lastes etter app.css og skal ikke
   eie et skjemafelt. .em-pdf-box input er mer spesifikk og beholder sine 19. */
.fld-check { width: 16px; height: 16px; }
/* Designets telefonkort kutter hjelpelinjene ned til en, med sin egen ordlyd.
   Samme grep som .reg-lead / .reg-mobile-lead: begge står i malen, en vises. */
.fld-help.is-narrow { display: none; }
.fld-error { font: 400 12px/1.45 var(--font-sans); color: var(--bad); }
.fld-input {
  width: 100%; font-family: var(--font-sans); font-weight: 400;
  font-size: 14px; line-height: 1.25; color: var(--ink);
  /* Gjennomsiktig, ikke hvitt: designet gir feltene kun en hårstrek, og begge
     inngangsflatene ligger på papiret (--paper). Et hvitt fyll gjorde spalta
     til en rad med bokser i stedet for den tonede kolonnen fasiten tegner. */
  background: transparent;
  border: 1px solid var(--line); border-radius: 9px; padding: 14px;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}
.fld-input::placeholder { color: var(--ink-3); }
.fld-input:hover { border-color: var(--line-strong); }
.fld-input:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16);
}
/* Prikkene i et passordfelt er mono med luft mellom seg i designet. */
.fld-input[type="password"] { font-family: var(--font-mono); font-size: 15px; letter-spacing: 0.16em; }
select.fld-input {
  appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234B5563' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; background-size: 16px;
  padding-right: 38px;
}

/* ---- Feilboksen --------------------------------------------------------- */
.alert-bad {
  display: flex; gap: 11px; align-items: flex-start;
  background: var(--bad-soft); border: 1px solid var(--bad-line);
  border-radius: 9px; padding: 13px 14px;
}
.alert-bad svg { width: 17px; height: 17px; flex: none; color: var(--bad); margin-top: 1px; }
.alert-bad-text { flex: 1; min-width: 0; }
.alert-bad p { font: 400 13px/1.55 var(--font-sans); color: var(--bad-deep); }
.alert-bad p + p { margin-top: 7px; }

/* ---- Kvitteringsboksen -------------------------------------------------- */
/* Samme geometri som .alert-bad, rolig farge. Innloggingssiden er der to
   selvbetjente flyter lander med gode nyheter («E-postadressen er bekreftet»,
   «Passordet er endret»), og de sto i den røde boksen fordi det var den ene
   boksen som fantes. Egen klasse og ikke en .alert-bad-variant: markup som må
   skrive «alert-bad is-ok» for å si at noe gikk bra leser feil. */
.alert-ok {
  display: flex; gap: 11px; align-items: flex-start;
  background: var(--ok-bg); border: 1px solid var(--ok);
  border-radius: 9px; padding: 13px 14px;
}
.alert-ok svg { width: 17px; height: 17px; flex: none; color: var(--ok); margin-top: 1px; }
.alert-ok p { flex: 1; min-width: 0; font: 400 13px/1.55 var(--font-sans); color: var(--ok); }

/* =========================================================================
   Skjerm 11 · Innlogging
   Ingen kort: designet legger spalta på 400 px rett på papiret. Det gamle
   .login-card (hvitt kort, blå toppkant) er derfor ute av bruk.
   ========================================================================= */
.login-page {
  min-height: 100svh; display: flex; flex-direction: column;
  background: var(--paper); color: var(--ink);
}
.login-body {
  flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 46px max(40px, env(safe-area-inset-right)) 50px max(40px, env(safe-area-inset-left));
}
.login-col { width: 400px; max-width: 100%; }
/* Spalta med hva Sonida gjør, ved siden av skjemaet. .login-body er allerede
   en sentrert flex-rad, så den trenger bare bredde og luft. Skjemaspalta står
   urørt på 400 px: innlogginga skal fortsatt være det første tommelen treffer,
   og en salgstekst som krymper feltene har byttet om på hvem siden er for. */
.login-side { width: 280px; flex: none; margin-left: 36px; }

.login-mark {
  display: block; font: 700 20px/1 var(--font-sans);
  letter-spacing: -0.04em; color: var(--ink);
}
.login-title {
  margin-top: 22px; font: 700 27px/1.12 var(--font-sans);
  letter-spacing: -0.045em; color: var(--ink);
}
.login-sub { margin-top: 9px; font: 400 13.5px/1.55 var(--font-sans); color: var(--ink-3); }

/* Feilen står MELLOM tittelen og feltene, ikke under passordfeltet: en beskjed
   om at hele bedriften er avslått er ikke en anmerkning på ett felt. */
.login-alert { margin-top: 20px; }

.login-fields { margin-top: 20px; display: flex; flex-direction: column; gap: 13px; }
.login-col .fld-input { border-radius: 8px; padding: 12px 13px; font-size: 13.5px; }
.login-col .fld-input[type="password"] { font-size: 14px; }

.login-btn {
  display: flex; align-items: center; justify-content: center; width: 100%;
  min-height: 52px; padding: 0 16px; border: 0; border-radius: 8px;
  background: var(--brand); color: #fff;
  font: 600 15px/1 var(--font-sans); cursor: pointer;
  transition: background-color 130ms ease, transform 120ms var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
.login-btn:hover { background: var(--brand-hover); }
.login-btn:active { transform: scale(0.99); }
/* Designet gir de tre variantene hver sin knapp: Sonidas egen PC-inngang
   13,5 px / radius 7, bedriftens lenke 15 px / radius 8, telefonen 15 px /
   radius 9. Bare den første avviker fra .login-btn over, og bare på PC - derfor
   min-width-porten, ellers ville mobilvarianten arvet 13,5 px herfra. */
@media (min-width: 768px) {
  .login-page:not(.is-branded) .login-btn { border-radius: 7px; font-size: 13.5px; }
}

.login-alt { margin-top: 18px; text-align: center; font: 400 13px/1.5 var(--font-sans); color: var(--ink-3); }
.login-alt a { font-weight: 500; color: var(--brand-ink); text-decoration: none; }
.login-alt a:hover { text-decoration: underline; }
/* Ett hakk under .login-alt: «registrer bedriften» er et tilbud til mange,
   «be om en ny lenke» er en utvei for de få. Samme spalte, mindre stemme. */
.login-help { margin-top: 9px; text-align: center; font: 400 12px/1.5 var(--font-sans); color: var(--ink-3); }
.login-help a { color: var(--ink-2); text-decoration: underline; }
.login-help a:hover { color: var(--ink); }
.login-credit { margin-top: 18px; text-align: center; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

/* ---- Bedriftens egen påloggingslenke ------------------------------------ */
/* Samme geometri som .topbar i public_base.html: 64 px høy, 32 px merke. Båndet
   bar tidligere bedriftens egen farge, injisert per bedrift som --co/--co-ink.
   Etter J2 er fargen ute overalt, injeksjonen er fjernet fra login.html, og
   båndet er hvitt med en hårstrek under - identisk med akseptsidens topplinje.
   Merkevaren bæres av logoen og navnet, ikke av flaten. */
.login-brandbar {
  display: flex; align-items: center; gap: 13px; min-height: 64px;
  padding: calc(16px + env(safe-area-inset-top)) max(40px, env(safe-area-inset-right)) 16px max(40px, env(safe-area-inset-left));
  background: #FFFFFF; color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.login-brandmark {
  width: 32px; height: 32px; border-radius: 8px; flex: none; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font: 700 15px/1 var(--font-sans);
  background: var(--ink); color: #FFFFFF;
}
.login-brandmark img { max-height: 32px; max-width: 32px; width: auto; display: block; }
/* Designet tegner bare bokstavflisen, så en opplastet logo er et tilfelle
   fasiten ikke dekker. Klemt inn i 32 x 32 ble en bred logo en uleselig flekk
   (384 x 121 px ble 32 x 10) - her får den bredde, som i sidemenyen.

   Hårstreken kom med J2: bunnen er hvit, og nå er båndet det også, så uten
   kant flyter en logo med hvit bakgrunn rett ut i flaten. */
.login-brandmark.has-logo {
  width: auto; max-width: 168px; padding: 0 8px; background: #fff;
  border: 1px solid var(--line);
}
.login-brandmark.has-logo img { max-height: 24px; max-width: 152px; }
.login-brandname {
  min-width: 0; font: 600 15.5px/1.2 var(--font-sans); letter-spacing: -0.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.is-branded .login-body { padding-top: 40px; padding-bottom: 40px; align-items: flex-start; }
.is-branded .login-title { margin-top: 0; font-size: 25px; }
.is-branded .login-sub { margin-top: 11px; font-size: 13.5px; line-height: 1.6; color: var(--ink-2); }
.is-branded .login-fields { margin-top: 18px; }
/* Nesten-svart, ikke bedriftsfargen: platen over bærer alt merket siden skal ha. */
.is-branded .login-btn { background: var(--ink); }
.is-branded .login-btn:hover { background: var(--ink-2); }
.is-branded .login-credit { text-align: left; }
/* Bedriftens egen lenke har verken «Registrer bedriften din» eller
   resend-linja, så «Glemt passordet?» står alene rett under knappen: den
   trenger .login-alt sin luft, ikke de 9 pikslene som er ment å knytte den til
   linja over. Venstrestilt, som alt annet på den merkede siden. */
.is-branded .login-help { margin-top: 18px; text-align: left; }

@media (max-width: 767.98px) {
  /* padding-shorthand med faste sidetall ville nullstilt safe-area-vernet over;
     i landskap på en telefon med hakk havner spalta da under hakket. */
  .login-body {
    align-items: flex-start;
    padding: 22px max(18px, env(safe-area-inset-right)) 26px max(18px, env(safe-area-inset-left));
  }
  /* Telefonen: spalta legger seg UNDER skjemaet, ikke ved siden av og ikke
     bort. Feltene og knappen skal fortsatt være det første som møter deg -
     derfor kolonne med skjemaet først, og en flatere ramme på kortet så det
     leser som en fotnote, ikke som en andre boks å fylle ut. */
  /* Aksene bytter plass når retningen blir kolonne: `align-items: flex-start`
     over holdt innholdet i toppen fordi den var tverr-aksen i en RAD. I en
     kolonne er det justify-content som gjør den jobben, og uten linja under
     ville siden begynt å sentrere seg vertikalt. */
  .login-body { flex-direction: column; align-items: stretch; justify-content: flex-start; }
  .login-side { width: 100%; margin: 26px 0 0; }
  .login-side .reg-trust { padding: 16px; gap: 11px; background: none; }
  .login-mark { font-size: 18px; }
  .login-title { margin-top: 15px; font-size: 23px; }
  .login-sub { margin-top: 9px; }
  /* Telefonen legger ALT i en kolonne med 15 px: merke, tittel, feilboks,
     begge feltene og knappen. Feltgruppa har derfor ikke PC-ens 13 px. */
  .login-alert, .login-fields { margin-top: 15px; }
  .login-fields { gap: 15px; }
  .login-btn { border-radius: 9px; }
  /* 16 px er det som hindrer at iOS zoomer inn ved fokus — designets 13,5 px
     ville slått av vaktposten i app.css' egen mobilblokk. */
  .login-col .fld-input, .login-col .fld-input[type="password"] { font-size: 16px; }
  .is-branded .login-brandbar {
    min-height: 62px; gap: 11px;
    padding: calc(14px + env(safe-area-inset-top)) max(18px, env(safe-area-inset-right)) 14px max(18px, env(safe-area-inset-left));
  }
  .is-branded .login-brandmark { width: 30px; height: 30px; font-size: 14px; }
  .is-branded .login-brandmark img { max-height: 26px; max-width: 30px; }
  .is-branded .login-brandmark.has-logo { width: auto; max-width: 130px; padding: 0 7px; }
  .is-branded .login-brandmark.has-logo img { max-height: 22px; max-width: 116px; }
  .is-branded .login-brandname { font-size: 14.5px; }
  .is-branded .login-title { font-size: 23px; }
  .is-branded .login-body { padding-top: 22px; padding-bottom: 26px; }
}

/* =========================================================================
   Skjerm 10 · Kom i gang (registreringen)
   Steg 1 og 2 er SAMME adresse i designets egen nettleserlinje — en side i to
   tilstander, ikke to sider. Rutene byttes i DOM-en; uten JavaScript står alt
   synlig som en lang side, akkurat som før.
   ========================================================================= */
.reg-brand { font: 700 18px/1 var(--font-sans); letter-spacing: -0.04em; color: var(--ink); }
.reg-steps { margin-left: auto; display: flex; align-items: center; gap: 13px; }
.reg-dots { display: flex; align-items: center; gap: 7px; }
.reg-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--line); flex: none; }
.reg-dot.is-done { background: var(--ok-dot); }
.reg-dot.is-now { width: 22px; background: var(--brand); }
.reg-steplabel { font: 400 11.5px/1 var(--font-mono); color: var(--ink-3); }
.reg-steplabel-short { display: none; font: 400 10.5px/1 var(--font-mono); color: var(--ink-3); }

.reg-body { display: flex; gap: 36px; align-items: flex-start; }
/* [hidden] alene taper mot display:flex over — rutebyttet trenger denne. */
.reg-body[hidden], .reg-hit[hidden], .reg-cofields[hidden] { display: none; }
.reg-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.reg-side { width: 280px; flex: none; }
.reg-cofields { display: flex; flex-direction: column; gap: 13px; }

.reg-h1 {
  font: 700 32px/1.08 var(--font-sans); letter-spacing: -0.045em;
  text-wrap: pretty; max-width: 22ch; color: var(--ink);
}
.reg-lead {
  margin-top: 13px; font: 400 15.5px/1.62 var(--font-sans);
  color: var(--ink-2); max-width: 52ch; text-wrap: pretty;
}
.reg-mobile-lead { display: none; }

/* Treffkortet fra Enhetsregisteret. */
.reg-hit {
  background: var(--brand-03); border: 1px solid var(--brand-16); border-radius: 10px;
  padding: 15px 16px; display: flex; gap: 12px; align-items: flex-start;
}
.reg-hit-check {
  width: 22px; height: 22px; border-radius: 50%; background: var(--ok-dot); color: #fff;
  flex: none; display: flex; align-items: center; justify-content: center; margin-top: 1px;
}
.reg-hit-check svg { width: 14px; height: 14px; }
.reg-hit-text { flex: 1; min-width: 0; }
.reg-hit-name { font: 500 14px/1.35 var(--font-sans); color: var(--ink); }
.reg-hit-addr { margin-top: 4px; font: 400 12.5px/1.5 var(--font-sans); color: var(--ink-2); }
.reg-hit-undo {
  font: 500 12.5px/1 var(--font-sans); color: var(--brand-ink); white-space: nowrap;
  background: none; border: 0; padding: 0; cursor: pointer; flex: none;
}
.reg-hit-undo:hover { text-decoration: underline; }

/* Trefflista fra navnesøket. Samme flate og radius som .reg-hit, men nøytral
   i stedet for merkefarget: kortet over er en bekreftelse, lista er et valg
   som ennå ikke er tatt. [hidden] må stå eksplisitt fordi display på lista
   ellers overstyrer attributtet. */
.reg-results[hidden] { display: none; }
.reg-results {
  list-style: none; margin: 0; padding: 4px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  display: flex; flex-direction: column; gap: 2px;
  max-height: 292px; overflow-y: auto;
}
.reg-result {
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: 7px; padding: 9px 11px;
  display: flex; flex-direction: column; gap: 3px;
}
.reg-result:hover { background: var(--brand-03); }
.reg-result:focus-visible {
  outline: 2px solid var(--brand-ink); outline-offset: -2px; background: var(--brand-03);
}
.reg-result-name { font: 500 14px/1.35 var(--font-sans); color: var(--ink); }
.reg-result-meta { font: 400 12.5px/1.4 var(--font-sans); color: var(--ink-2); }

/* Tillitspunktene — kun ved siden av steg 1, aldri på telefon. */
.reg-trust {
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 20px; display: flex; flex-direction: column; gap: 13px;
}
.reg-trust-item { display: flex; gap: 11px; align-items: flex-start; }
.reg-trust-check {
  width: 20px; height: 20px; border-radius: 50%; background: var(--ok-dot); color: #fff;
  flex: none; display: flex; align-items: center; justify-content: center; margin-top: 1px;
}
.reg-trust-check svg { width: 13px; height: 13px; }
.reg-trust-title { font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
.reg-trust-sub { margin-top: 3px; font: 400 12px/1.45 var(--font-sans); color: var(--ink-3); }

.reg-cta {
  display: flex; align-items: center; justify-content: center; width: 100%;
  min-height: 54px; padding: 0 16px; border: 0; border-radius: 9px;
  background: var(--brand); color: #fff; font: 600 16px/1 var(--font-sans);
  cursor: pointer; text-decoration: none;
  transition: background-color 130ms ease, transform 120ms var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
.reg-cta:hover { background: var(--brand-hover); }
.reg-cta:active { transform: scale(0.99); }

.reg-haveaccount { font: 400 12.5px/1.5 var(--font-sans); color: var(--ink-3); }
.reg-haveaccount a { font-weight: 500; color: var(--brand-ink); text-decoration: none; }
.reg-haveaccount a:hover { text-decoration: underline; }
.reg-monoline { display: none; text-align: center; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

/* Bedriftskortet i sidespalta på steg 2. */
.reg-card { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 20px; }
.reg-card-label {
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
}
.reg-card-list { margin-top: 13px; display: flex; flex-direction: column; gap: 11px; }
.reg-card-key {
  font: 400 11px/1.3 var(--font-mono); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-3);
}
.reg-card-val { margin-top: 5px; font: 500 13.5px/1.4 var(--font-sans); color: var(--ink); }
.reg-card-val.is-mono { font: 400 13px/1.4 var(--font-mono); }
.reg-card-val.is-plain { font: 400 13px/1.5 var(--font-sans); }
.reg-card-foot {
  margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--line-soft);
  font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3);
}

/* ---- Steg 3 · «Sjekk e-posten din» -------------------------------------- */
.reg-done { display: flex; flex-direction: column; align-items: center; gap: 18px; text-align: center; }
.reg-tile {
  width: 56px; height: 56px; border-radius: 14px; flex: none;
  background: var(--brand-06); color: var(--brand-ink);
  display: flex; align-items: center; justify-content: center;
}
.reg-tile svg { width: 26px; height: 26px; }
.reg-done-h1 { font: 700 30px/1.1 var(--font-sans); letter-spacing: -0.045em; text-wrap: pretty; color: var(--ink); }
.reg-done-lead {
  margin-top: 13px; font: 400 15.5px/1.62 var(--font-sans);
  color: var(--ink-2); max-width: 52ch; text-wrap: pretty;
}
/* Telefonkortet har sin egen, kortere ingress i designet - samme grep som
   .reg-lead / .reg-mobile-lead på de to første stegene. */
.reg-done-lead.is-narrow { display: none; }
.reg-done-lead strong { font-weight: 500; color: var(--ink); }
.reg-note {
  width: 100%; max-width: 420px; text-align: left;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 18px 20px;
}
.reg-note p { font: 400 12.5px/1.6 var(--font-sans); color: var(--ink-2); }
.reg-note.is-warn {
  background: var(--warn-bg);
  border-color: color-mix(in srgb, var(--warn) 30%, white);
}
.reg-note.is-warn p { color: var(--warn); }
/* .reg-note p over er (0,1,1) og slår en ren klasse uansett rekkefølge - derfor
   står elementet med i velgeren her, ellers leses mono-etiketten som en vanlig
   setning i versaler og brødteksten krymper til 12,5 px. */
.reg-note p.reg-note-label {
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
}
.reg-note p.reg-note-body { margin-top: 11px; font: 400 13.5px/1.6 var(--font-sans); color: var(--ink-2); }
.reg-note-body strong { font-weight: 600; color: var(--ink); }
.reg-done-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 50px; padding: 0 22px; border: 1px solid var(--line);
  background: var(--surface); border-radius: 9px;
  font: 500 14px/1 var(--font-sans); color: var(--ink-2); text-decoration: none;
}
.reg-done-btn:hover { border-color: var(--line-strong); background: var(--paper); }
/* «Ny bekreftelseslenke»: ett felt og en knapp, i samme spalte som resten av
   steg 3-skjermen. .reg-done er sentrert og text-align: center; skjemaet
   trenger sin egen venstrestilling, ellers svever etiketten over feltet. */
.reg-resend-form {
  width: 100%; max-width: 380px; text-align: left;
  display: flex; flex-direction: column; gap: 14px;
}
/* .reg-cta er width: 100%, og .reg-done er hele 818 px-spalta. Inne i skjemaet
   over stanser den på 380 px av seg selv; står den fritt i spalta (den døde
   passordlenkens «Be om en ny lenke») ble den en blå planke tvers over siden.
   Samme mål som skjemaet ved siden av, så de to knappene flukter. */
.reg-done .reg-cta { max-width: 380px; }

@media (max-width: 767.98px) {
  .reg-body { flex-direction: column; gap: 15px; }
  .reg-main { gap: 15px; }
  /* Sidespalta har ingen mobilform i designet: telefonkortet for steg 1 slutter
     med mono-linja under knappen, og steg 2 med «Opprett konto». Begge kortene
     bor her, så spalta går ut i sin helhet - ellers ble bedriftskortet hengende
     under knappen på steg 2, og steg 1 fikk 15 px død luft etter et tomt kort. */
  .reg-side { display: none; }
  .reg-monoline { display: block; }
  .reg-haveaccount { display: none; }
  .reg-h1 { font-size: 25px; line-height: 1.1; max-width: none; }
  .reg-lead { display: none; }
  .reg-mobile-lead {
    display: block; margin-top: 11px; font: 400 14px/1.6 var(--font-sans);
    color: var(--ink-2); text-wrap: pretty;
  }
  .reg-hit { padding: 14px 15px; gap: 11px; }
  .reg-hit-name { font-size: 13.5px; }
  .reg-hit-addr { font-size: 12px; line-height: 1.45; }
  .reg-results { max-height: 240px; }
  .reg-result { padding: 10px 11px; }
  .reg-result-name { font-size: 13.5px; }
  .reg-result-meta { font-size: 12px; }
  /* 16 px er vaktposten mot at iOS zoomer inn ved fokus - designets 14 px ville
     slått den av. Regelen står FØR .reg-orgnr med vilje: lik spesifisitet, og
     den sist definerte vinner, så org.nr-feltet mistet sine 19 px her. */
  .fld-input, .fld-input[type="password"] { font-size: 16px; }
  /* Telefonen har nøyaktig ett felt på steg 1, og designet gir det sin egen
     vekt: mono, 19 px, luftig. De to blå pikslene fasiten tegner rundt det er
     fokustilstanden - kanten vokser innover, så feltet ikke hopper. */
  .reg-orgnr { font: 500 19px/1 var(--font-mono); letter-spacing: 0.04em; padding: 16px; border-radius: 10px; }
  .reg-orgnr:focus { border-width: 2px; padding: 15px; box-shadow: none; }
  .reg-brand { font-size: 16px; }
  .reg-steps { gap: 10px; }
  .reg-steplabel { display: none; }
  .reg-steplabel-short { display: inline; }
  /* Designet gir steg 2 en litt tettere rytme enn steg 1. */
  [data-route="2"] .reg-main { gap: 14px; }
  [data-route="2"] .reg-mobile-lead { margin-top: 10px; font-size: 13.5px; }
  .fld-help.is-wide { display: none; }
  .fld-help.is-narrow { display: block; }
  .reg-done { gap: 16px; }
  .reg-tile { width: 52px; height: 52px; border-radius: 13px; }
  .reg-tile svg { width: 24px; height: 24px; }
  .reg-done-h1 { font-size: 24px; line-height: 1.12; }
  .reg-done-lead { margin-top: 11px; font-size: 13.5px; line-height: 1.6; }
  .reg-done-lead.is-wide { display: none; }
  .reg-done-lead.is-narrow { display: block; }
  .reg-note { padding: 15px 16px; }
  .reg-note p.reg-note-body { margin-top: 10px; font-size: 13px; }
}

/* =========================================================================
   Skjerm 18 · Prøveperioden er over
   Ett ark på 520 px midt på papiret. Ingen KPI-fliser, ingen statuskort —
   designet erstatter dem med en setning, og setningen er bedre.
   ========================================================================= */
.trial-page { display: flex; flex-direction: column; align-items: center; }
.trial-sheet {
  width: 520px; max-width: 100%;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: 32px 34px;
}
.trial-icon {
  width: 48px; height: 48px; border-radius: 12px;
  background: var(--warn-bg); color: var(--warn);
  display: flex; align-items: center; justify-content: center;
}
.trial-icon svg { width: 24px; height: 24px; }
.trial-title {
  margin-top: 20px; font: 700 26px/1.15 var(--font-sans);
  letter-spacing: -0.045em; text-wrap: pretty; color: var(--ink);
}
.trial-lead { margin-top: 13px; font: 400 15px/1.62 var(--font-sans); color: var(--ink-2); text-wrap: pretty; }

.trial-plans { margin-top: 20px; border: 1px solid var(--line); border-radius: 9px; overflow: hidden; }
.trial-plan {
  display: flex; align-items: baseline; gap: 12px; padding: 14px 16px;
  cursor: pointer; position: relative;
}
.trial-plan + .trial-plan { border-top: 1px solid var(--line-soft); }
.trial-plan input { position: absolute; opacity: 0; width: 0; height: 0; }
.trial-plan-name { flex: 1; min-width: 0; font: 400 13px/1.4 var(--font-sans); color: var(--ink-2); }
.trial-plan.is-on { background: #F7F9FC; }
.trial-plan.is-on .trial-plan-name { font-weight: 500; color: var(--ink); }
.trial-plan:focus-within { box-shadow: inset 0 0 0 2px var(--brand-16); }
/* «2 mnd gratis» beholder markupen sin — den er låst av
   test_the_two_months_free_badge_is_visible_in_the_default_selected_state —
   men designet vil ha den som en dempet undertekst i raden, ikke en grønn
   pille ved siden av prisen. Bare presentasjonen er byttet. */
.trial-plan .badge {
  background: transparent; padding: 0; border-radius: 0;
  font: 400 13px/1.4 var(--font-sans); letter-spacing: 0; text-transform: none;
  color: var(--ink-3);
}
.trial-price { font: 500 15px/1 var(--font-sans); font-variant-numeric: tabular-nums; color: var(--ink); }

/* Fasiten satte knappen rett inntil prislista - null margin - så de to leste
   som en blokk. I praksis så det ut som en feil: knappens hjørne klistret seg
   til boksens kant. 14 px lander mellom arkets egne 13 og 20, og holder
   fortsatt knappen tydelig knyttet til prisvalget over. */
.trial-cta {
  margin-top: 14px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 54px; padding: 0 16px; border: 0; border-radius: 7px;
  background: var(--brand); color: #fff; font: 600 13.5px/1 var(--font-sans);
  text-decoration: none; cursor: pointer;
  transition: background-color 130ms ease, transform 120ms var(--ease-out);
}
.trial-cta:hover { background: var(--brand-hover); }
.trial-cta:active { transform: scale(0.99); }
.trial-cta svg { width: 16px; height: 16px; flex: none; }

.trial-keeps { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line-soft); }
.trial-keeps-label {
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
}
.trial-keeps ul { margin-top: 11px; display: flex; flex-direction: column; gap: 10px; list-style: none; padding: 0; }
.trial-keeps li { display: flex; gap: 11px; align-items: flex-start; }
.trial-check {
  width: 19px; height: 19px; border-radius: 50%; background: var(--ok-dot); color: #fff;
  flex: none; display: flex; align-items: center; justify-content: center; margin-top: 1px;
}
.trial-check svg { width: 12px; height: 12px; }
.trial-keeps-text { flex: 1; min-width: 0; font: 400 13px/1.55 var(--font-sans); color: var(--ink-2); }
.trial-fine { margin-top: 18px; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

/* «Logg ut» ligger utenfor arket, som en stille tekstknapp: skjermen kjører med
   hide_nav, så dette er den eneste veien ut for den som er logget inn i feil
   bedrift — men den skal ikke konkurrere med den ene handlingen kortet har. */
.trial-logout { margin-top: 18px; }

@media (max-width: 1023.98px) {
  .trial-sheet { padding: 24px 20px; }
}

/* Skallets innholdspadding er laget for skjermer med fanelinje. Denne kjører
   med hide_nav, så de 58 px som klarer fanelinja er dødvekt nederst, og
   designets ramme har mer luft på toppen (52 px) enn skallets 2 rem. */
.no-nav .app-content { padding: 52px 40px 56px; }
@media (max-width: 1023.98px) {
  .no-nav .app-content { padding: 22px 16px calc(24px + env(safe-area-inset-bottom)); }
}

/* =========================================================================
   Skjerm 08 · Registrene  +  skjerm 13 · Ny kunde
   -------------------------------------------------------------------------
   De fire flatene håndverkeren fyller en gang og bruker i hvert tilbud:
   materiellet, kategoriene, pakkene og kundene — pluss kundeskjemaet.

   Skallet er byggerens: .qb (panelet), .qb-top (topplinja), .qb-btn
   (knappene), og listenes .ql-* fra skjerm 07 (filtre, søkerad, tabellhode,
   rader, fot, tomtilstand, telefonkortene). Det som er nytt her er radenes
   egne deler: .mx-* materiell, .cat-* kategorier, .pk-* pakker, .ku-* kunder,
   .cu-* kundeskjemaet, og .sform-* skjemafeltene.

   To ting designet tegner finnes ikke i dataene og er derfor ikke bygget —
   «Sist oppdatert»-kolonnen med «gammel pris»-merket, og «Importer prisfil».
   Se docs/design-utelatt.md, «Fra 08 · Registrene».

   Designet legger materiellet, pakkene og kundene ved siden av hverandre på
   EN side. Appen har tre ruter med hvert sitt punkt i sidemenyen, og de tre
   sidekortene i designet har ingen vei videre til resten (3 av 86). Derfor er
   hver rute bygget som sitt eget panel i designets språk: materiellet med
   designets egen tabell, pakkene med designets egen rad, kundene med skjerm
   07s listegrammatikk fordi 08 bare tegner dem som et utsnitt.
   ========================================================================= */

/* ---- Felles for de fire registerpanelene --------------------------------- */
/* Designets topplinje her er ett hakk strammere enn byggerens (14/22, gap 16):
   14/20 og gap 14. padding-block/inline, ikke shorthand — .qb-top setter
   allerede sideluften, og en shorthand her ville nullstilt den. */
.rg-top { padding-block: 14px; padding-inline: 20px; gap: 14px; }
/* Knappeparet står 9 px fra hverandre i fasiten, ikke byggerens 10. */
.rg-top .qb-top-act, .cu-top .qb-top-act { gap: 9px; }
.rg .qb-btn { gap: 8px; }
.rg-titlerow { display: flex; align-items: center; gap: 14px; min-width: 0; }
.rg-icon { display: flex; flex: none; color: var(--ink-2); }
.rg-icon svg { width: 18px; height: 18px; display: block; }

/* En pillerad uten mono-etikett: 07 har to grupper, 08 har en. */
.rg-filters { padding-block: 12px; padding-inline: 20px; }

/* «Vis inaktive» tegner designet ikke — men filteret finnes og skal bestå. */
.rg-check {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  font: 400 12.5px/1 var(--font-sans); color: var(--ink-2);
  white-space: nowrap; cursor: pointer;
}
.rg-check input { width: 15px; height: 15px; accent-color: var(--brand); }

.rg-foot { padding: 13px 20px; }
/* Brødskrift, ikke mono. Dette er ikke en bildetekst men et avsnitt - den
   lengste er 310 tegn med forklaring av automatisk avstand - og et helt avsnitt
   norsk prosa i skrivemaskinskrift på 11,5 px er tungt å lese på en telefon i
   dagslys. Samme skille som i PDF-brevhodet: mono for identifikatorer og tall,
   brødskrift for setninger. */
.rg-foot-note { font: 400 12.5px/1.55 var(--font-sans); color: var(--ink-3); }
.rg-foot-link {
  margin-left: auto; font: 500 12.5px/1 var(--font-sans);
  color: var(--brand-ink); text-decoration: none; white-space: nowrap;
}
.rg-foot-link:hover { text-decoration: underline; }

/* ---- Materielltabellen --------------------------------------------------- */
/* Designets rutenett er 1fr 120px 96px 132px 116px. Den siste kolonnen er
   «Sist oppdatert», og Material har ingen tidsstempler — den er strøket, ikke
   fylt med noe oppdiktet. Resten står som tegnet. */
.mx-grid { display: grid; grid-template-columns: 1fr 120px 96px 132px; gap: 14px; }
.mx-cell { min-width: 0; }
.mx-name { font: 400 13.5px/1.35 var(--font-sans); color: var(--ink); }
.mx-sub { display: block; font: 400 11px/1.4 var(--font-mono); color: var(--ink-3); }
.mx-cost {
  font: 400 13px/1 var(--font-mono); color: var(--ink-3);
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mx-mark { text-align: right; }
/* Bare den overstyrte verdien er blå. Begge arvetilstandene er grå og skilles
   av ordene under — designets eget valg, og det riktige: arv er normalen. */
.mx-mark-val { font: 500 12.5px/1 var(--font-mono); color: var(--ink-3); }
.mx-mark.is-own .mx-mark-val { color: var(--brand-ink); }
.mx-mark-src { display: block; font: 400 10px/1.4 var(--font-mono); color: var(--ink-3); }
.mx-sum {
  font: 500 13.5px/1 var(--font-sans); color: var(--ink);
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Grunnlinje, ikke midtstilling: cellene i raden har ulikt antall linjer
   (varenavn + kategori mot påslag + kilde), og .ql-row sentrerer dem hver for
   seg mot hele radhøyden. Da havnet «25 %» 7 px høyere enn «38,00» i alle 60
   radene. Med baseline står tallene og navnet på samme linje, og underlinjene
   henger under der de hører hjemme. */
.mx-row { align-items: baseline; }
.mx-row.is-off { opacity: 0.55; }

/* ---- Kategoriene --------------------------------------------------------- */
/* En rad = ett skjema med sin egen Lagre-knapp, som før. Kategorier opprettes
   fra materiellskjemaet, ikke her. */
.cat-grid { display: grid; grid-template-columns: 1fr 150px 84px; gap: 12px; align-items: center; }
.cat-head { padding: 10px 20px; background: var(--row-tint); border-bottom: 1px solid var(--line); }
.cat-head span {
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.cat-row {
  padding: 11px 20px; background: var(--surface);
  border-bottom: 1px solid var(--line-soft);
}
/* stretch, ikke en fast min-høyde: knappen skal være nøyaktig så høy som
   feltene den står ved siden av (.qb-btn er 38, .input 43 på skrivebord og 44
   på telefon), og da flyter den ikke lenger midt i raden. */
.cat-row .qb-btn { width: 100%; align-self: stretch; }

/* ---- Pakkene ------------------------------------------------------------- */
.pk-list {
  padding: 14px 20px; display: flex; flex-direction: column; gap: 9px;
}
.pk-row {
  display: flex; align-items: center; gap: 11px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 13px 14px; text-decoration: none; color: inherit;
  transition: border-color 130ms ease, background-color 130ms ease;
}
.pk-row:hover { border-color: var(--line-strong); background: var(--brand-03); }
.pk-text { flex: 1; min-width: 0; }
.pk-name { display: block; font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
.pk-desc { display: block; margin-top: 3px; font: 400 12.5px/1.45 var(--font-sans); color: var(--ink-3); }
.pk-meta { display: block; margin-top: 4px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.pk-chev { display: flex; flex: none; color: var(--ink-3); }
.pk-chev svg { width: 16px; height: 16px; }
/* Bunnknappen er ikke .btn og ikke .qb-btn: designet gir den full bredde,
   44 px høyde og radius 9 — en rad til i lista, ikke en knapp ved siden av. */
.pk-new {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--surface); color: var(--ink-2);
  font: 500 13px/1 var(--font-sans); text-decoration: none; cursor: pointer;
  transition: border-color 130ms ease;
}
.pk-new:hover { border-color: var(--ink-3); }
.pk-new svg { width: 16px; height: 16px; flex: none; }

/* ---- Kundene ------------------------------------------------------------- */
/* Kunde og Kontakt deler plassen 1,5:1 i stedet for å låse e-posten til 220 px:
   ved 1024 brakk kundenavnet over tre linjer mens e-postkolonnen hadde luft til
   overs. Navnet kan ikke kuttes, e-posten kan (den har ellipse). */
.ku-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) 130px 88px 40px;
  gap: 14px;
}
.ku-cell { min-width: 0; }
.ku-name { display: block; font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
.ku-sub { display: block; margin-top: 4px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.ku-mail {
  font: 400 12.5px/1.4 var(--font-sans); color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ku-person { display: block; margin-top: 3px; font: 400 11px/1.4 var(--font-mono); color: var(--ink-3); }
.ku-phone {
  font: 400 12.5px/1 var(--font-mono); color: var(--ink-2);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ku-count {
  font: 400 12.5px/1 var(--font-mono); color: var(--ink-3);
  text-align: right; font-variant-numeric: tabular-nums;
}
/* Samme som .mx-row: telefonnummeret og tilbudstallet lå 8 px under navnet,
   og e-postkolonnen HOPPET — på en bedriftsrad (med kontaktperson under) flukta
   den med navnet, på en privatrad gled den ned. Chevronen har ingen grunnlinje
   og sentreres for seg. */
.ku-row { align-items: baseline; }
.ku-row > .ql-chev { align-self: center; }
/* Anonymisert kunde: raden står igjen så aksepterte tilbud er lesbare, men
   den er ingen lenke — det finnes ikke noe kundekort å åpne. */
.ku-row.is-off { opacity: 0.6; }

/* Telefonens kundekort er designets eget, fra Kunder-kortet i 08. */
.ku-card {
  display: block; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; padding: 13px 14px; text-decoration: none; color: inherit;
}
.ku-card-top { display: flex; align-items: baseline; gap: 10px; }
.ku-card-name { flex: 1; min-width: 0; font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
.ku-card-count { font: 400 11px/1 var(--font-mono); color: var(--ink-3); flex: none; }
.ku-card-sub { margin-top: 4px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }

/* =========================================================================
   Skjemafeltene i registrene (.sform) — skjerm 13s felt, gjenbrukt
   -------------------------------------------------------------------------
   Feltrioen .fld / .fld-label / .fld-help fra skjerm 10 og 11 er allerede
   designets, verdi for verdi. Selve kontrollen er det ikke: skjemaene her
   rendres av Django med .input/.select/.textarea, og de er fra det gamle
   systemet (radius 6, padding 8/11, 14 px). Klassene byttes IKKE i
   core/forms.py — da ville hvert eneste skjema i appen skiftet samtidig.
   Utseendet settes i stedet inne i .sform, med designets egne tall:
   radius 8, padding 12/13, 13,5 px.
   ========================================================================= */
.sform .input, .sform .select, .sform .textarea {
  width: 100%;
  font-family: var(--font-sans); font-weight: 400;
  font-size: 13.5px; line-height: 1.2; color: var(--ink);
  background-color: var(--surface);
  border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 13px;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}
.sform .input:hover, .sform .select:hover, .sform .textarea:hover { border-color: var(--line-strong); }
.sform .input:focus, .sform .select:focus, .sform .textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-16);
}
/* Designets notatboks er 64 px — knapt to linjer. Djangos Textarea kommer med
   rows="10" og ville ellers gitt en 240 px flate til en intern kommentar.
   resize: vertical, ikke both: et felt som kan dras bredere sprenger raden. */
/* Høyden er regnet i HELE linjer, ikke i runde piksler: 64 px ga 1,88 linjer,
   og andre linje ble liggende som en skive tekst uten over- eller underkant i
   bunnkanten av feltet. calc(2 linjer + polstring + ramme) gir nøyaktig to. */
.sform .textarea {
  min-height: calc(2 * 1.5em + 26px); height: calc(2 * 1.5em + 26px);
  line-height: 1.5; resize: vertical;
}
/* Standardvilkårene kommer ferdig utfylt og skal leses, ikke gjettes: seks
   hele linjer i stedet for to. */
.sform .textarea-tall { min-height: calc(6 * 1.5em + 26px); height: calc(6 * 1.5em + 26px); }
.sform .select {
  appearance: none; -webkit-appearance: none; cursor: pointer; padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234B5563' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; background-size: 16px;
}
.sform .input-num, .sform .cell-num { text-align: right; font-family: var(--font-mono); }

/* =========================================================================
   Skjerm 13 · Ny kunde  (og de to andre skjemaene i bolken)
   -------------------------------------------------------------------------
   Fire hvite gruppekort på papiret, hvert med en mono-versal kicker. Lagre og
   Avbryt står i topplinja, ikke i en actionbar under; Eksporter og Slett står
   nederst, og bare på en lagret kunde.

   Telefonen løser gruppekortene opp: rammen blir ETT hvitt ark, kickerne
   forsvinner, og kundetypen blir et todelt segment uten prikk og undertekst.
   Designet dropper i tillegg Organisasjonsnummer, Kontaktperson, Notat og hele
   Eksporter/Slett-raden på telefon. Det er ikke gjort: en bedriftskunde måtte
   da registreres fra PC, og eksporten er en personvernrettighet. Se
   docs/design-utelatt.md, «Fra 13 · Ny kunde».
   ========================================================================= */
.cu-top { padding-block: 14px; padding-inline: 20px; gap: 12px; }
.cu .qb-btn { min-height: 40px; gap: 8px; }
.cu .qb-btn-primary { font-size: 13.5px; }
.cu-body { padding: 22px 20px; display: flex; flex-direction: column; gap: 14px; }
.cu-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; padding: 18px 20px;
}
/* .12em, ikke .1em: kickeren over en gruppe står litt løsere enn etiketten
   over et felt. Begge verdiene er designets. */
.cu-kicker {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
}

.cu-types { margin-top: 11px; display: flex; gap: 10px; flex-wrap: wrap; }
.cu-type { flex: 1 1 200px; min-width: 0; display: flex; cursor: pointer; }
/* Radioen er skjult, men fortsatt der: tastaturet og skjermleseren får en
   ekte radiogruppe, og :checked + .cu-face tegner tilstanden uten :has(). */
.cu-type input { position: absolute; opacity: 0; width: 0; height: 0; }
.cu-face {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 11px;
  border: 1px solid var(--line); border-radius: 9px; padding: 14px 15px;
  transition: border-color 130ms ease, background-color 130ms ease;
}
.cu-type input:checked + .cu-face { border-color: var(--brand); background: var(--brand-03); }
.cu-type input:focus-visible + .cu-face { box-shadow: 0 0 0 3px var(--brand-16); }
/* 19 px med 2 px ring uvalgt, 6 px ring valgt: border-box gjør de 6 pikslene
   til en blå ring rundt en 7 px hvit kjerne. #6B7280 er designets egen grå
   for en uvalgt kontroll — verken --ink-3 eller --line. */
.cu-dot {
  width: 19px; height: 19px; border-radius: 50%; flex: none;
  border: 2px solid #6B7280; background: var(--surface);
  transition: border-color 130ms ease, border-width 130ms ease;
}
.cu-type input:checked + .cu-face .cu-dot { border: 6px solid var(--brand); }
.cu-type-text { min-width: 0; }
.cu-type-name { display: block; font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
.cu-type-note { display: block; margin-top: 3px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }

.cu-row { margin-top: 13px; display: flex; gap: 14px; flex-wrap: wrap; }
.cu-row > .fld { flex: 1 1 200px; min-width: 0; }
/* Org.nr og kontaktperson hører til en bedrift. Velger du Privat, forsvinner
   de - skjemaet spør ikke om noe en privatperson ikke har. .cu-biz finnes bare
   i customers/form.html, så de andre skjermene som låner .cu-skallet
   (innstillinger, jobbmaler, e-postskjemaet, drift) er urørt. Serversiden
   blanker feltene i tillegg, se CustomerForm.clean(). */
.cu-body:has(.cu-types input[value="privat"]:checked) .cu-biz { display: none; }
/* Postnummer er låst til designets 110 px og kan krympe, ikke vokse. Telefon
   får ikke ta halve raden fra e-posten. */
.cu-row > .fld.cu-post { flex: 0 1 110px; }
.cu-row > .fld.cu-narrow { flex: 0 1 200px; }
/* Samme argument for Sted: «Oslo» fikk nøyaktig like mye plass som
   «Grefsenveien 88 B» (472 px hver), og rangeringen mellom feltene forsvant.
   Gata er den lange verdien i raden. */
.cu-row > .fld.cu-city { flex: 0 1 200px; }
.cu-note { margin-top: 11px; }
.cu-help { margin-top: 12px; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
.cu-note + .cu-help { margin-top: 9px; }

/* Pakkeskjemaets linjeeditor: kickeren og de to «legg til»-knappene på samme
   rad, og feltene inne i tabellen holdt lave — .sform-kontrollen er 42 px høy
   og ville gjort hver linje til en blokk. */
.pkf-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pkf-head .qb-btn { margin-left: auto; }
.pkf-head .qb-btn + .qb-btn { margin-left: 0; }
.pkf-lines { margin-top: 13px; overflow-x: auto; }
.pkf-lines .tbl { min-width: 520px; }
.pkf-c-no { width: 34px; }
.pkf-c-type { width: 110px; }
.pkf-c-qty { width: 110px; }
.pkf-c-act { width: 46px; }
/* Linjelistas slett-knapp er alltid synlig. Den generelle regelen over
   (.tbl tbody tr .row-actions { opacity: 0 } bak (hover: hover)) er riktig for
   kunde-, materiell- og brukerlistene, der ikonene er radhandlinger på data du
   bare ser på - men her er sletting en av kontrollene i skjemaet du fyller ut.
   Spesifisiteten (0,3,2) slår media-regelens (0,2,2) uten !important og uten å
   avhenge av rekkefølgen i fila. */
.pkf-lines .tbl tbody tr .row-actions.pkf-act { opacity: 1; }
.pkf-type { color: var(--ink-2); }
.pkf-qty-error { margin-top: 4px; font-size: 12.5px; color: var(--bad); text-align: right; }

/* Telefon: linjelista fikk ikke plass, og det var Antall og slett-knappen som
   havnet utenfor skjermen - du måtte dra tabellen sidelengs inni kortet for å
   endre et antall. Type-kolonnen går ut i stedet: raden viser den selv, siden
   materiell har en nedtrekksliste og arbeid et fritekstfelt. Både <th> og <td>
   må skjules, ellers forskyves cellene en kolonne under overskriftene. */
@media (max-width: 767.98px) {
  /* `table-layout: fixed` er det som faktisk får lista inn på 375 px. Uten den
     styrer <select>-ens bredeste materiellnavn kolonnebredden, og tabellen ble
     346 px inni et 311 px kort uansett hvor mye min-width ble senket. */
  .pkf-lines .tbl { min-width: 0; width: 100%; table-layout: fixed; }
  .pkf-c-type, .pkf-type { display: none; }
  .pkf-lines .tbl thead th, .pkf-lines .tbl tbody td { padding-inline: 8px; }
  /* Overskriftene er `nowrap` i huset. Med faste kolonnebredder skøyt
     «MATERIELL / BESKRIVELSE» rett inn i «ANTALL»; her får den brekke i to. */
  .pkf-lines .tbl thead th { white-space: normal; line-height: 1.35; }
  .pkf-c-no { width: 28px; }
  .pkf-c-qty { width: 74px; }
  .pkf-c-act { width: 52px; }
  .pkf-lines td:last-child { padding-inline: 4px; }
  .sform .pkf-lines .select, .pkf-lines .cell-input { width: 100%; min-width: 0; }
  /* 44 px trykkflate. .btn-icon sin 40 px-regel gjelder bare .tbl-cards, og
     denne tabellen er ikke det. */
  .pkf-lines .qb-iconbtn { width: 44px; height: 44px; }
}
.sform .pkf-lines .select {
  font-size: 13px; padding: 8px 32px 8px 10px; border-radius: 7px;
  background-position: right 10px center; background-size: 15px;
}

.cu-foot { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }
/* Materiell- og pakkeskjemaet sletter med en POST, og et skjema kan ikke ligge
   inne i et annet — der står bunnraden utenfor .cu-body og bærer luften selv. */
.qb > .cu-foot { padding: 0 20px 22px; }
.cu-foot-note { font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

/* Ett tall som leses som et tall, ikke som en kolonne: proporsjonale siffer,
   husets sans. Tabellene beholder tabular-nums der kolonnene skal flukte. */
.cu-readout {
  padding-top: 12px;
  font: 500 16px/1 var(--font-sans); color: var(--ink);
  font-variant-numeric: proportional-nums;
}
.qb-btn.cu-danger { border-color: var(--bad-line); color: var(--bad); }
.qb-btn.cu-danger:hover { border-color: var(--bad); background: var(--bad-soft); }

/* ---- Slettebekreftelsen -------------------------------------------------- */
/* Ingen av de 19 designskjermene tegner denne flaten. Den er derfor bygget i
   samme panel- og kortspråk som resten av bolken, og ordlyden står ordrett som
   før — de juridiske avsnittene er ikke rørt, bare Tailwind-klassene rundt dem. */
.del-name { font: 600 15px/1.35 var(--font-sans); color: var(--ink); }
.del-tbl { margin-top: 14px; }
/* Tabellen står inne i et kort, ikke i et eget panel: cellenes egen sideluft
   skjøv «STATUS» og «Utkast» 12 px inn mens tabellens streker fulgte kortets
   tekstkant. Ytterkolonnene flukter med navnet og avsnittene over og under. */
.del-tbl thead th:first-child, .del-tbl tbody td:first-child { padding-left: 0; }
.del-tbl thead th:last-child, .del-tbl tbody td:last-child { padding-right: 0; }
.del-c-count { width: 80px; }
.del-block { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line-soft); }
.del-lead { font: 500 13.5px/1.55 var(--font-sans); color: var(--ink); }
.del-text { margin-top: 11px; font: 400 13.5px/1.55 var(--font-sans); color: var(--ink-2); }
.del-list {
  margin-top: 11px; padding-left: 20px; list-style: disc;
  font: 400 13.5px/1.55 var(--font-sans); color: var(--ink-2);
}
.del-list li + li { margin-top: 6px; }

/* Topplinjas to presentasjoner: PC har Avbryt + Lagre kunde som knapper,
   telefonen har et kryss til venstre og «Lagre» som ren tekst til høyre. */
.cu-close, .cu-save-phone { display: none; }
.cu-phonenote { display: none; }

/* ---- Telefonen ----------------------------------------------------------- */
@media (max-width: 1023.98px) {
  .rg-top { padding-inline: 16px; gap: 11px; }
  .rg-total-tail { display: none; }
  .rg-filters { padding-block: 12px; padding-inline: 16px; }
  /* Panelet er gjennomsiktig på telefon, så en hvit fot ble hengende igjen som
     en firkantet stripe under siste kort. Foten er tekst på papiret her —
     fasitens egne kort har ingen fot i det hele tatt. */
  .rg-foot { padding: 0 16px 16px; background: transparent; }
  /* …men ikke på kategorisiden: der er radene hvite inne i panelet, ikke kort
     på papiret, så en gjennomsiktig fot lot fotnoten falle ut av arket og bli
     stående på den grå bakgrunnen under en skarp, rett kant. */
  .cat .rg-foot { background: var(--surface); padding: 14px 16px 16px; }
  .rg-foot .qb-btn { flex: 1; min-height: 46px; justify-content: center; }
  .rg-check { font-size: 13px; }

  /* Kortlistene i registrene er fasitens 12/16 med 9 px mellom kortene — både
     pakkene og kundene. .ql-cards er 07s tall (14/16, gap 10) og blir stående
     der; her overstyres den bare inne i .rg. */
  .pk-list { padding: 12px 16px; }
  .rg .ql-cards { gap: 9px; padding: 12px 16px; }
  /* De to knappene deler raden i stedet for å klumpe seg til høyre. */
  .pkf-head .qb-btn { flex: 1; margin-left: 0; min-height: 44px; }
  /* «Linjer» blir stående: den er bolkens eneste navn, og uten den lå de to
     legg-til-knappene rett under hjelpeteksten til Beskrivelse og leste som om
     de hørte til det feltet. Samme unntak som .set-block og .dr allerede har.
     Egen linje, så den ikke stjeler bredde fra knappene på 375 px. */
  .pkf-head .cu-kicker { display: block; flex: 1 1 100%; }
  /* Navnet får linja si, påslaget og Lagre deler den neste — tre felt i
     stabel ville gitt 190 px per kategori. */
  .cat-head { display: none; }
  .cat-grid { grid-template-columns: 1fr 84px; gap: 9px; }
  .cat-name { grid-column: 1 / -1; }
  .cat-row { padding: 14px 16px; }

  .cu-cancel, .cu-save-desk { display: none; }
  .cu-close { display: inline-flex; flex: none; color: var(--ink-2); }
  .cu-close svg { width: 18px; height: 18px; display: block; }
  .cu-save-phone {
    display: inline-flex; align-items: center; margin-left: auto;
    background: none; border: 0; padding: 0; cursor: pointer;
    font: 600 13px/1 var(--font-sans); color: var(--brand-ink); text-decoration: none;
  }
  .cu-top { padding-block: 13px; padding-inline: 16px; gap: 11px; }
  .cu-top .qb-top-title { font-size: 15.5px; }

  /* Ett hvitt ark, ikke fire kort på papir. */
  .qb.cu { background: var(--surface); }
  .cu-body { padding: 16px; gap: 13px; }
  .cu-card { background: transparent; border: 0; border-radius: 0; padding: 0; }
  .cu-kicker { display: none; }
  .cu-types { margin-top: 0; gap: 9px; flex-wrap: nowrap; }
  .cu-type { flex: 1 1 0; }
  .cu-face { justify-content: center; min-height: 48px; padding: 0 10px; }
  .cu-dot, .cu-type-note { display: none; }
  .cu-type-name { font-size: 13.5px; text-align: center; }
  .cu-type input:checked + .cu-face .cu-type-name { font-weight: 600; color: var(--brand-ink); }
  /* Fasitens telefonkort har 13 px mellom hvert stablet felt, hele veien ned.
     De 11 pikslene gjelder bare VANNRETT, mellom postnummer og sted. Og første
     rad i et kort kan ikke bære margin-top når kickeren over den er skjult:
     den la seg oppå .cu-body sin gap og ga 26 px ved hvert kortskille. */
  .cu-row { row-gap: 13px; column-gap: 11px; }
  .cu-kicker + .cu-row { margin-top: 0; }
  /* Designets telefon gir hvert felt sin egen linje — bortsett fra postnummer
     og sted, som deler den siste, akkurat som på PC. 110 + 11 + 140 = 261 og
     får plass på 311 px; med 200 px basis ville de brutt fra hverandre. */
  .cu-row > .fld, .cu-row > .fld.cu-narrow { flex: 1 1 100%; }
  .cu-row > .fld.cu-post { flex: 0 1 110px; }
  .cu-row > .fld.cu-city { flex: 1 1 140px; }
  /* Notat-kickeren ER feltets etikett — den ene som må bli stående. */
  label.cu-kicker { display: block; }
  /* Designets telefonvariant kutter adresseavsnittet og SMS-hjelpelinja. */
  .cu-wide-only { display: none; }
  .cu-phonenote { display: block; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
  .qb > .cu-foot { padding: 0 16px 16px; }

  /* 16 px hindrer at iOS zoomer inn på feltet når det får fokus. */
  .sform .input, .sform .select, .sform .textarea { font-size: 16px; }
}

/* =========================================================================
   Skjerm 09 · Innstillinger  ·  17 Brukere  ·  12 Varsler
   -------------------------------------------------------------------------
   Tre administratorflater som deler skallet fra byggeren og listene: .qb,
   .qb-top/.rg-top, .qb-btn, .ql-thead/.ql-row/.ql-foot/.ql-empty og feltrioen
   .fld/.fld-label/.fld-help. Prefiksene her er .set-* (09), .ua-* (17) og
   .nf-* (12).

   Tre ting i fasiten fantes ikke fra før og er laget her: av/på-bryteren
   (42×24, ingen switch fantes — bare .check-row med avkryssing), de stiplede
   opplastingsrutene, og hex-brikka rundt fargevelgeren.

   Det fasiten tegner som appen ikke har — undermenyen som fire ruter, de seks
   fargeforslagene, «Hent fra logoen», åpningsvarselet — står i
   docs/design-utelatt.md, ikke her.
   ========================================================================= */

/* ---- 09 · Innstillinger: de to panelene --------------------------------- */
/* Fasitens 1000 + 22 + 392 er 1414 px. Innholdsflaten i appen er hardkapslet
   på 1240 px, så de to panelene får aldri fasitens bredde ved siden av
   hverandre — og satsraden med FIRE felt er det som ryker først når det brede
   panelet krymper. Basisen er derfor bredden raden faktisk trenger:
   216 (menyen) + 44 (kroppens padding) + 40 (kortets padding) + 642 (fire
   felt à 150 med 14 px mellom) = 942. Panelene står side om side først når
   942 + 22 + 392 får plass; under det brekker sidepanelet ned, og raden med
   fire — den mest gjenkjennelige delen av skjermen — står som tegnet i hele
   spennet innholdsflaten kan nå. Sidepanelet vokser aldri forbi designets 392. */
.set-cols { display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap; }
.set-main { flex: 1 1 726px; min-width: 0; display: flex; align-items: stretch; }
/* Side om side krever 942 + 22 + 392 = 1356 px. Innholdsflaten er kapslet på
   1240, så de to panelene står ALLTID under hverandre. Med `flex: 0 1 392px`
   ble sidepanelet stående på 392 px alene på raden, med nesten 800 px tomt ved
   siden av — det leses som en ødelagt side, ikke som et valg. Det vokser derfor
   til full bredde når det er alene, så kantene flukter med panelet over.
   Basisen 392 står igjen, så oppsettet faller riktig ut hvis innholdsflaten en
   dag blir bred nok. */
.set-side { flex: 1 1 392px; min-width: 0; }
.set-toperror { margin-bottom: 12px; }
#set-satser, #set-kjoring, #set-merke, #set-tekster { scroll-margin-top: 16px; }

/* Her sto to generasjoner av den samme menyen. Først .navsub: bolkene foldet
   ut i SIDEMENYEN under «Innstillinger», fjernet i J5 fordi punktene kom i
   tillegg til knappen de hang under. Så .set-nav, en pillerad øverst på siden
   under 1024 px, som skulle gjøre «den samme jobben der den faktisk trengs».
   Den er nå borte også, og av samme grunn: en side der alt ligger under ETT
   menypunkt trenger ingen meny inni seg. Tre kort er kort nok til å rulles.
   Ankrene #set-satser/#set-kjoring/#set-tekster står igjen på seksjonene, med
   scroll-margin over — de er gratis, og en lenke utenfra kan fortsatt treffe
   riktig bolk. */

.set-body {
  flex: 1; min-width: 0; padding: 22px;
  display: flex; flex-direction: column; gap: 14px;
}
/* Jevn 20 px på alle fire sider — .cu-card er 18/20 og treffer ikke her. */
.set-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-card); padding: 20px;
}
.set-card-head { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.set-card-title { font: 600 16px/1.2 var(--font-sans); letter-spacing: -0.03em; color: var(--ink); }
.set-card-lead { margin-top: 8px; font: 400 12.5px/1.5 var(--font-sans); color: var(--ink-3); }
.set-cardnote { margin-top: 14px; }
.set-row { margin-top: 16px; display: flex; gap: 14px; flex-wrap: wrap; }
.set-row > .fld { flex: 1 1 150px; min-width: 0; }

/* Enheten står INNI verdien i fasiten («795,00 kr»). Et enlinjes <input> kan
   ikke bære den, så den ligger oppå feltets høyre kant, og feltet får luft til
   den. Tallet er høyrestilt mot enheten, som i .sform .input-num.
   Luften er per enhet, ikke en marg dimensjonert for det lengste merket: med
   ett fast tall leser «895,00      kr» med 30 px hull mens «30 dager» klemmer
   på 7. Regnestykket er 13 (merkets egen høyremarg) + merkets bredde i mono
   11,5 px (≈7,5 px per tegn) + 8 px luft. */
.set-ctl { position: relative; display: block; }
.set-ctl .input {
  padding-right: 58px; text-align: right;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.set-ctl-kr .input, .set-ctl-km .input { padding-right: 36px; }
.set-ctl-pct .input { padding-right: 29px; }
.set-ctl-dager .input { padding-right: 58.5px; }
/* Chromes tallstepper legger seg nettopp i luften mellom tallet og enheten,
   og fasiten tegner ingen slik kontroll. Piltastene virker som før. */
.set-ctl .input::-webkit-outer-spin-button,
.set-ctl .input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.set-ctl .input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.set-unit {
  position: absolute; right: 13px; top: 50%; transform: translateY(-50%);
  font: 400 11.5px/1 var(--font-mono); color: var(--ink-3);
  pointer-events: none; white-space: nowrap;
}

/* Av/på-bryteren: 42×24 med en 18 px knott, som i fasiten. Avkryssingsboksen
   er den ekte kontrollen og ligger usynlig under — tastatur og skjermleser
   får en vanlig checkbox. */
.set-switch { position: relative; margin-left: auto; display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.set-switch input, .set-box input { position: absolute; opacity: 0; width: 0; height: 0; }
.set-switch-text { font: 400 12.5px/1 var(--font-sans); color: var(--ink-2); }
.set-track {
  width: 42px; height: 24px; flex: none; border-radius: 999px;
  background: var(--line-strong); padding: 3px;
  display: flex; align-items: center;
  transition: background-color 140ms ease, box-shadow 130ms ease;
}
.set-knob {
  width: 18px; height: 18px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 2px rgb(17 24 39 / 0.28);
  transition: transform 140ms var(--ease-out);
}
.set-switch input:checked ~ .set-track,
.set-box input:checked ~ .set-track { background: var(--brand); }
.set-switch input:checked ~ .set-track .set-knob,
.set-box input:checked ~ .set-track .set-knob { transform: translateX(18px); }
.set-switch input:focus-visible ~ .set-track,
.set-box input:focus-visible ~ .set-track { box-shadow: 0 0 0 3px var(--brand-16); }
/* «Tur og retur» står som et felt på linje med tallfeltene i fasiten. Boksen
   gir bryteren samme høyde som feltene ved siden av. */
.set-box {
  position: relative; display: flex; align-items: center;
  min-height: 42px; padding: 0 13px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
}

/* ---- 09 · Sidepanelet «Bedrift og merke» -------------------------------- */
.set-side-head { background: var(--surface); border-bottom: 1px solid var(--line); padding: 15px 18px; }
.set-side-title { font: 600 16px/1.2 var(--font-sans); letter-spacing: -0.03em; color: var(--ink); }
.set-side-lead { margin-top: 6px; font: 400 12px/1.5 var(--font-sans); color: var(--ink-3); }
.set-side-body { padding: 18px; display: flex; flex-direction: column; gap: 14px; }
.set-block + .set-block { border-top: 1px solid var(--line-soft); padding-top: 14px; }
/* Fasitens to fotnoter i sidepanelet står 10 px under det de hører til.
   .rg-foot-note bærer ingen marg selv — den er skrevet for en fot. */
.set-block > .rg-foot-note { margin-top: 10px; }

.set-media { margin-top: 10px; display: flex; gap: 13px; align-items: center; }
/* Appikonraden har sine egne mål i fasiten — 11/11, ikke logoradens 10/13 — og
   hjelpeteksten er der en grad større og luftigere, uten marg over: raden er
   midtstilt, så 4 px ville skjøvet teksten ned i forhold til flisene. */
.set-media-icon { margin-top: 11px; gap: 11px; }
.set-media-text { flex: 1; min-width: 0; }
.set-media-name { font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); overflow-wrap: anywhere; }
.set-media-note { margin-top: 4px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.set-media-icon .set-media-note { margin-top: 0; font-size: 12px; line-height: 1.5; }
/* Den stiplede ruta står der bedriften ennå ikke har lastet opp noe. #6B7280 er
   fasitens egen strek — samme literal .cu-dot alt bruker — og fyllet er
   radtonen, ikke --brand-03 (#F7FAFF er en annen farge enn #F7F9FC). */
.set-drop, .set-thumb {
  width: 96px; height: 56px; flex: none; border-radius: 9px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.set-drop { border: 1px dashed #6B7280; background: var(--row-tint); color: var(--ink-3); }
.set-drop svg { width: 17px; height: 17px; display: block; }
.set-drop-note { font: 400 9.5px/1 var(--font-mono); }
.set-thumb { border: 1px solid var(--line); background: var(--surface); overflow: hidden; }
.set-thumb img { max-width: 84px; max-height: 44px; width: auto; height: auto; display: block; }
/* Fasitens andre flis ved siden av appikonet: den stiplede 56×56-ruta som er
   «last opp ditt eget». Her er den en <label> for filfeltet, så flisen gjør
   det den ser ut som. */
.set-drop-sq {
  width: 56px; height: 56px; flex: none; border-radius: 14px;
  border: 1px dashed #6B7280; background: var(--row-tint); color: var(--ink-3);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
}
.set-drop-sq svg { width: 16px; height: 16px; display: block; }
/* 10 px, ikke 8,5. Søskenet .set-drop-note står på 9,5, og denne krympet
   ytterligere fordi flisen er mindre - men notisen er ikke versal, så den får
   ingen hjelp av sperring slik etikettene i huset gjør. 8,5 px gemener er
   under det noen leser komfortabelt. */
.set-drop-sq .set-drop-note { font-size: 10px; }
/* Flisene åpner filvelgeren. Feltet står likevel under — se
   docs/design-utelatt.md: uten JS er nettleserens eget felt det eneste stedet
   det valgte filnavnet vises før lagring. */
label.set-drop, label.set-drop-sq, label.set-thumb, label.set-appicon { cursor: pointer; }
label.set-drop:hover, label.set-drop-sq:hover { border-color: var(--ink-2); }
.set-appicon {
  width: 56px; height: 56px; flex: none; border-radius: 14px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font: 700 26px/1 var(--font-sans);
  /* Fasiten merker den valgte flisen, fordi den står ved siden av den andre. */
  outline: 2px solid var(--ink); outline-offset: 2px;
}
.set-appicon img { width: 100%; height: 100%; object-fit: cover; display: block; }
.set-appicon-img { background: var(--surface); border: 1px solid var(--line); }
/* Bokstavflisen. Fargen sto tidligere inline i malen, i bedriftens egen farge;
   etter J2 er den fast - og den må stå her, ellers blir flisen gjennomsiktig. */
.set-appicon-plain { background: var(--ink); color: #FFFFFF; }
.set-fileinput { margin-top: 10px; }
.set-clear {
  margin-top: 9px; display: inline-flex; align-items: center; gap: 8px;
  font: 400 12.5px/1 var(--font-sans); color: var(--ink-2); cursor: pointer;
}
.set-clear input { width: 15px; height: 15px; accent-color: var(--brand); }

/* Fasitens «Rediger» og de tre chevron-radene peker på undersider som ikke
   finnes. <details> gir samme form uten å love en side: sammendraget står som
   tegnet, og feltet folder seg ut der det står. */
.set-det > summary, .set-drow > summary { list-style: none; cursor: pointer; }
.set-det > summary::-webkit-details-marker,
.set-drow > summary::-webkit-details-marker { display: none; }
.set-det-sum { display: flex; align-items: baseline; gap: 12px; }
.set-det-main { flex: 1; min-width: 0; }
.set-idname { display: block; font: 500 14px/1.35 var(--font-sans); color: var(--ink); }
.set-idmeta { display: block; margin-top: 4px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.set-det-act { flex: none; font: 500 12.5px/1 var(--font-sans); color: var(--brand-ink); }
.set-det[open] .set-det-act { color: var(--ink-2); }
.set-det-body { margin-top: 12px; }
.set-det-body > .set-row { margin-top: 13px; }
.set-det-body > .set-row:first-child { margin-top: 0; }
.set-row > .fld.set-post { flex: 0 1 110px; }

.set-drows { margin-top: 11px; display: flex; flex-direction: column; gap: 9px; }
/* Ingen fylling: fasitens rad er en ren ramme, og panelets #F2F4F7 slår
   gjennom. En hvit pille på grått ark er en annen komponent. */
.set-drow { border: 1px solid var(--line); border-radius: 9px; }
.set-drow-sum { display: flex; align-items: center; gap: 10px; padding: 12px 13px; }
.set-drow-name { flex: 1; min-width: 0; font: 400 13px/1.4 var(--font-sans); color: var(--ink); }
.set-chev { display: flex; flex: none; color: var(--ink-3); }
.set-chev svg { width: 15px; height: 15px; transition: transform 160ms var(--ease-out); }
.set-drow[open] .set-chev svg { transform: rotate(90deg); }
.set-drow-body { padding: 0 13px 13px; display: flex; flex-direction: column; gap: 6px; }
/* .sform sin notatboks er 64 px — knapt to linjer, og skrevet for et internt
   notat. Standardtekstene er hele avsnitt, så de får registrenes egne høyder
   igjen: 132 px, og 200 px for vilkårene. */
.set-drow-body .textarea { min-height: 132px; height: 132px; }
.set-drow-body.textarea-lg .textarea { min-height: 200px; height: 200px; }

/* Hex-brikka er fasitens egen, med den ekte fargevelgeren som den 18 px ruta. */
.set-hexes { margin-top: 11px; display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }
.set-hex {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--line); border-radius: 9px; padding: 8px 11px;
  cursor: pointer;
}
.set-hex input[type="color"] {
  width: 18px; height: 18px; flex: none; padding: 0;
  border: 0; border-radius: 5px; background: none; cursor: pointer;
  appearance: none; -webkit-appearance: none;
}
.set-hex input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.set-hex input[type="color"]::-webkit-color-swatch { border: 1px solid var(--line); border-radius: 5px; }
.set-hex input[type="color"]::-moz-color-swatch { border: 1px solid var(--line); border-radius: 5px; }
.set-hex-text { display: flex; flex-direction: column; gap: 3px; }
.set-hex-val { font: 500 12.5px/1 var(--font-mono); color: var(--ink); text-transform: uppercase; }
.set-hex-role {
  font: 400 9.5px/1 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}

/* Fasiten tegner ingen lagreknapp for 09. Skjemaet må kunne lagres, og begge
   panelene er ETT skjema, så raden står under dem begge. */
.set-actions { margin-top: 16px; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.set-actions .rg-foot-note { margin-left: auto; }

/* ---- Felles for 17 og 12 ------------------------------------------------- */
/* Begge fasitene skriver topplinja med gap 12 og foten med padding 14/20.
   .rg-top og .rg-foot bærer 08s tall (14 og 13), og 08 skal beholde sine —
   derfor er de to hakkene scopet hit. Bare på PC: telefonens egne mål (11 og
   en fot uten toppluft) er 08s, og de skal gjelde her også. padding-block,
   ikke shorthand — .rg-foot setter allerede sideluften. */
@media (min-width: 1024px) {
  .ua-panel .rg-top, .nf .rg-top,
  .ua-panel .rg-titlerow, .nf .rg-titlerow { gap: 12px; }
  .ua-foot, .nf-foot { padding-block: 14px; }
}

/* ---- 17 · Brukere -------------------------------------------------------- */
/* Fasitens rutenett er 1fr 150px 140px 132px. Her står to kolonner til:
   «Sist pålogget», som fasiten stryker men dataene har, og en bredere
   Handling-kolonne — den tredje handlingen (Deaktiver/Aktiver) må finnes, ellers
   kan ingen deaktiveres, og fasitens egen fotnote forutsetter at den gjør det. */
/* Handling-kolonnen er 214 px, ikke 190: raden bærer nå fire handlinger
   (Rediger · Passord · Deaktiver · Slett), og på 190 px falt Slett ned på sin
   egen linje. Den smale PC-varianten under (1024-1199 px) beholder 190 px -
   der er hver piksel allerede lånt fra brukernavnet, og en brekk i
   handlingskolonnen koster mindre enn en brekk i e-postadressen. */
.ua-grid { display: grid; grid-template-columns: minmax(0, 1fr) 132px 116px 132px 214px; gap: 14px; }
.ua-grid.has-company { grid-template-columns: minmax(0, 1fr) 150px 132px 116px 132px 214px; }
/* På en smal PC-skjerm koster de faste kolonnene mer enn Bruker-kolonnen har:
   under 1200 px blir navnet to linjer og e-posten fire, og raden dobbelt så
   høy. «Sist pålogget» er kolonnen fasiten selv strøk — den er den som går
   først, og den står fortsatt i telefonkortet. */
@media (min-width: 1024px) and (max-width: 1199.98px) {
  .ua-grid { grid-template-columns: minmax(0, 1fr) 132px 116px 190px; }
  .ua-grid.has-company { grid-template-columns: minmax(0, 1fr) 150px 132px 116px 190px; }
  .ua-th-when, .ua-grid .ua-when { display: none; }
}
/* Raden er ingen lenke her — hver handling er sin egen. Ingen hover-tone. */
.ua-grid.ql-row:hover { background: var(--surface); }
.ua-cell { min-width: 0; }
.ua-name { display: block; font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
/* Fasiten holder «brukernavn · e-post» på en linje. Her får den brekke i
   stedet for å kuttes: en halv e-postadresse er ikke til å slå opp i, og
   overflow-wrap hindrer at en lang adresse presser kolonnen ut. */
.ua-sub {
  display: block;
  font: 400 11px/1.4 var(--font-mono); color: var(--ink-3);
  overflow-wrap: anywhere;
}
.ua-company { font: 400 12.5px/1.4 var(--font-sans); color: var(--ink-2); }
/* Rollen er ren tekst, ikke en merkelapp: den er en opplysning, ikke en status. */
.ua-role { min-width: 0; font: 400 13px/1.4 var(--font-sans); color: var(--ink-2); }
.ua-self { font: 400 10.5px/1 var(--font-mono); color: var(--ink-3); white-space: nowrap; }
.ua-when {
  font: 400 11.5px/1.35 var(--font-mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.ua-grid .badge, .ua-card .badge { padding: 5px 8px; }
/* Fasitens deaktivert-brikke er den kalde nøytralen, ikke .badge-muted (varm). */
.ua-badge-off { color: var(--ink-3); background: var(--neutral-bg); }

.ua-act { display: flex; align-items: center; gap: 12px; justify-content: flex-end; flex-wrap: wrap; }
.ua-link, .ua-link-quiet, .ua-link-bad {
  font-family: var(--font-sans); font-size: 12.5px; font-weight: 500; line-height: 1;
  background: none; border: 0; padding: 0; cursor: pointer;
  text-decoration: none; white-space: nowrap;
}
.ua-link { color: var(--brand-ink); }
.ua-link-quiet { color: var(--ink-2); }
.ua-link-bad { color: var(--bad); }
.ua-link:hover, .ua-link-quiet:hover, .ua-link-bad:hover { text-decoration: underline; }
.ua-locked { font: 400 11.5px/1.35 var(--font-mono); color: var(--ink-3); }
/* Fasitens fot er to mono-linjer under hverandre, ikke en rad. */
.ua-foot { flex-direction: column; align-items: flex-start; gap: 8px; }

.ua-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: 11px;
  padding: 14px 15px;
}
.ua-card-top { display: flex; align-items: center; gap: 10px; }
.ua-card-top .ua-name { flex: 1; min-width: 0; }
.ua-card .ua-sub { margin-top: 4px; }
.ua-card-role { margin-top: 6px; font: 400 12.5px/1.4 var(--font-sans); color: var(--ink-2); }
.ua-card-when { margin-top: 4px; }
.ua-card-act { margin-top: 12px; justify-content: flex-start; gap: 14px; }

/* ---- 12 · Varsler -------------------------------------------------------- */
.nf-list { background: var(--surface); }
.nf-row {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px 20px; border-bottom: 1px solid var(--line-soft);
  background: var(--surface); text-decoration: none; color: inherit;
  transition: background-color 120ms ease;
}
/* Prikken er ALLTID der, først i raden: blå på ulest, grå på lest. Ulest-raden
   bærer i tillegg designets svakeste blå — --brand-03, ikke en color-mix. */
.nf-dot { width: 9px; height: 9px; flex: none; margin-top: 5px; border-radius: 50%; background: var(--line); }
.nf-row.is-unread { background: var(--brand-03); }
.nf-row.is-unread .nf-dot { background: var(--brand); }
.nf-row:hover { background: var(--brand-06); }
.nf-main { flex: 1; min-width: 0; }
/* Vekten er hele forskjellen på ulest og lest — fargen er den samme. */
.nf-title { display: block; font: 400 13.5px/1.4 var(--font-sans); color: var(--ink); }
.nf-row.is-unread .nf-title { font-weight: 600; }
.nf-sub { display: block; margin-top: 4px; font: 400 12.5px/1.5 var(--font-sans); color: var(--ink-3); }
.nf-when {
  flex: none; font: 400 11.5px/1 var(--font-mono); color: var(--ink-3);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.nf-narrow { display: none; }

/* Av/på-bryteren for varsler nederst i feeden. Sto før i den globale
   `display: none` sammen med .nf-narrow og ble slått på igjen bare på telefon —
   men Chrome, Edge og Firefox på PC tar imot Web Push uten installasjon, så
   bryteren fantes ikke der brukeren faktisk sitter. .nf-narrow står urørt:
   «Merk alle lest» er avhengig av den. */
.nf-push {
  display: flex; gap: 12px; align-items: center;
  padding: 14px 20px; background: var(--row-tint); border-top: 1px solid var(--line);
}
.nf-push-icon { display: flex; flex: none; color: var(--brand-ink); }
.nf-push-icon svg { width: 17px; height: 17px; display: block; }
.nf-push-text { flex: 1; min-width: 0; }
.nf-push-title { font: 500 13px/1.4 var(--font-sans); color: var(--ink); }
.nf-push-body { margin-top: 3px; font: 400 12px/1.5 var(--font-sans); color: var(--ink-3); }
/* Bryteren i topplinja (J3). `hidden` til push.js har lest tilstanden fra
   nettleseren; visibility ville reservert plassen, men da står det et hull i
   linja for leverandøren, som aldri får knappen i det hele tatt. */
.nf-pushbtn { flex: none; white-space: nowrap; }

@media (max-width: 1023.98px) {
  /* ---- 09 på telefon: kortene under hverandre i én spalte ---------------- */
  .set-cols { gap: 14px; }
  .set-main { flex: 1 1 100%; flex-direction: column; }
  .set-side { flex: 1 1 100%; }
  .set-body { padding: 16px; gap: 12px; }
  .set-card { padding: 16px; }
  .set-card-head { gap: 9px; }
  .set-switch { margin-left: 0; flex: 1 1 100%; }
  .set-switch-text { flex: 1; }
  .set-row > .fld { flex: 1 1 100%; }
  .set-row > .fld.set-post { flex: 0 1 110px; }
  .set-side-head { padding: 14px 16px; }
  /* Hvit flate, ikke bare polstring: .qb mister ramme, radius og bunn på
     telefon, og da lå logoen, appikonet, merkefargen og standardtekstene rett
     på den grå sidebakgrunnen med hårstreker imellom — det leste som at kortet
     sluttet etter overskriften. Venstrekolonnen beholder sine hvite kort. */
  .set-side-body { padding: 16px; background: var(--surface); }
  /* Skjerm 13 skjuler .cu-kicker på telefon, fordi kortene der løses opp til
     ett ark og kickerne bare gjentar det feltene sier. Her ER kickeren blokkas
     eneste navn — uten den står logoen, ikonet og fargen uten etikett. */
  .set-block .cu-kicker { display: block; }
  .set-actions .qb-btn { flex: 1 1 40%; min-height: 46px; justify-content: center; }
  .set-actions .rg-foot-note { margin-left: 0; flex: 1 1 100%; }

  /* ---- 17 på telefon: kort, ikke rutenett -------------------------------- */
  .ua-card-act { gap: 16px; }

  /* ---- 12 på telefon ----------------------------------------------------- */
  .nf .rg-top { padding-block: 13px; padding-inline: 16px; gap: 11px; }
  .nf .qb-top-title { font-size: 15.5px; }
  .nf .ql-total { display: none; }
  .nf-row { gap: 11px; padding: 14px 16px; }
  /* .rg-foot nullstiller sin egen toppluft på telefon (08 får den fra
     .ql-cards). .nf-list har ingen bunnpolstring, så uten dette starter
     personvernlinja 0 px under siste rads hårstrek. */
  .nf-foot { padding-top: 13px; }
  .nf-sub { font-size: 12px; line-height: 1.45; }
  .nf-when { font-size: 11px; }
  .nf-wide { display: none; }
  .nf-narrow { display: inline; }
  /* «Merk alle lest» er en tekstlenke på telefon, ikke en rammeknapp.
     Byggerens telefonregel skjuler ALLE .qb-btn i .qb-top-act (den ville ellers
     presset tittelen i stykker på 375 px). Her er knappen den eneste
     handlingen i linja, og skal stå — derfor en mer spesifikk velger. */
  .nf .qb-top-act .nf-allbtn {
    display: inline-flex;
    min-height: 0; padding: 0; border: 0; background: none;
    color: var(--brand-ink); font-size: 12px;
  }
  .nf-allbtn:hover { border: 0; }
  .nf-allbtn svg { display: none; }
  /* Varselbryteren trenger NØYAKTIG samme unntak som .nf-allbtn over: regelen
     `.qb-top-act .qb-btn { display: none }` på telefon gjelder alle knapper i
     topplinja, og uten dette ville bryteren vært usynlig på mobil - der den
     betyr mest. Den beholder rammen sin: den er en av/på-bryter med to
     tilstander, ikke en engangshandling som «Merk alle lest».

     :not([hidden]) er ikke pynt: knappen står `hidden` til push.js har lest
     tilstanden, og en display-verdi her ville overstyrt nettleserens egen
     [hidden]-regel. Uten den sto det en tom, rund knapp i linja på telefon -
     også for den som har blokkert varsler og aldri skal se noen knapp. */
  .nf .qb-top-act .nf-pushbtn:not([hidden]) {
    display: inline-flex;
    min-height: 32px; padding: 0 10px; font-size: 12px;
  }
  /* Telefon: ikonet og teksten på en linje. Knappen bor i topplinja nå, så
     kortet er ren forklaringstekst og trenger ingen plass til den. */
  .nf-push {
    padding: 14px 16px; align-items: flex-start; gap: 11px; flex-wrap: wrap;
  }
  .nf-push-icon { margin-top: 1px; }
  .nf-push-icon svg { width: 16px; height: 16px; }
  .nf-push-body { margin-top: 4px; }
}

/* =========================================================================
   Skjerm 14 · Tomme tilstander og feil
   -------------------------------------------------------------------------
   Skjermen er tverrgående: den har ingen egen rute, den er de to boksene som
   dukker opp INNE i skjermene som allerede finnes. Designet tegner seks
   tilstander, men bare TO komponenter — og de er bygget som to, ikke seks:

   1. Det tomme kortet (.ql-empty) — «Ingen tilbud ennå», «Registeret er
      tomt», «Ingen treff på …». Klassen fantes fra skjerm 07 og står allerede
      i alle sju listene; her får den fasitens kort: ramme, radius 12, skygge,
      52 px ikonflis og et titteltrinn. Verdiene settes her og ikke oppe i 07,
      så den opprinnelige seksjonen står urørt.

   2. Beskjeden (.alert-bad + .alert-lg) — «E-posten kom ikke fram», «Kunden
      mangler e-postadresse», «Ingen nettforbindelse». Boksen het .alert-bad da
      den ble født på inngangsflatene (skjerm 10/11), der den bare fantes i en
      tone. Navnet står — å døpe den om ville rørt tre maler som ikke hører til
      denne bolken — men den er nå husets ene beskjedboks: .alert-lg gir
      fasitens mål, .is-warn og .is-quiet de to andre tonene, og .alert-title /
      .alert-act de to linjene designet legger til.

   Offline-siden (templates/pwa/offline.html) er det ene stedet dette ikke
   rekker: den er forhåndscachet og må rendre uten nettverk, så den kan ikke
   laste app.css. Sonida-verdiene står duplisert inline der, med vilje.
   ========================================================================= */

:root {
  /* Den varme advarselstonen. --warn-bg (#FEF3C7) er kraftigere enn flaten
     designet tegner, og hverken kanten eller den mørke teksten fantes. Samme
     trio brukes av «Advarsler og feil» på skjerm 19. */
  --warn-soft: #FFFBEB;
  --warn-line: #FDE68A;
  --warn-deep: #78350F;
}

/* ---- 1 · Det tomme kortet ------------------------------------------------ */
/* width, ikke max-width: kortet er 392 px i fasiten, men skal ha 16 px luft
   til panelkanten på 375 px. min() gjør begge deler i en verdi. */
.ql-empty {
  width: min(392px, 100% - 32px);
  margin: 26px auto;
  padding: 34px 30px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  box-shadow: 0 16px 36px -28px rgb(17 24 39 / 0.45);
  display: flex; flex-direction: column; align-items: center; gap: 15px;
  text-align: center;
}
.ql-empty-mark {
  width: 52px; height: 52px; flex: none; border-radius: 13px;
  background: var(--brand-06); color: var(--brand-ink);
  display: flex; align-items: center; justify-content: center;
}
.ql-empty-mark svg { width: 24px; height: 24px; display: block; }
.ql-empty-text { min-width: 0; }
/* Scopet med .ql-empty foran: tittelen er selv en <p>, og .ql-empty p under
   ville ellers vunnet på spesifisitet og gjort den til brødtekst. */
.ql-empty .ql-empty-title {
  font: 600 17px/1.25 var(--font-sans);
  letter-spacing: -0.025em; color: var(--ink);
}
.ql-empty p { font: 400 13.5px/1.6 var(--font-sans); color: var(--ink-2); text-wrap: pretty; }
.ql-empty .ql-empty-title + p { margin-top: 10px; }
/* Flex-gapet bærer avstanden ned til knappen; 07s egen margin-top ville lagt
   14 px oppå den. Knappen er 48 px her, ikke topplinjas 38. */
.ql-empty .qb-btn, .ql-empty .btn { margin-top: 0; min-height: 48px; }
/* Topplinjas .qb-btn har gap 7 og 13 px; fasitens kortknapp har 8 og 13,5.
   Verdiene settes her og ikke på .qb-btn, som er hele husets knapp. (Uten
   dette fikk «Legg inn vare» 8 px fra .rg .qb-btn og «Nytt tilbud» 7 px —
   samme knapp, to bredder.) */
.ql-empty .qb-btn { gap: 8px; }
.ql-empty .qb-btn-primary { font-size: 13.5px; }

/* ---- 2 · Beskjeden ------------------------------------------------------- */
/* Samme grunn som over: .alert-bad p (linje ~3613) er mer spesifikk enn en
   naken .alert-title, og ville gjort tittelen til brødtekst. */
.alert-bad .alert-title { font: 600 14.5px/1.3 var(--font-sans); color: var(--bad-deep); }
.alert-bad .alert-title + p { margin-top: 8px; }
/* Fasiten tegner handlingen som en tekstlinje i samme farge som teksten, uten
   strek. Streken kommer på hover og fokus, så den fortsatt leses som en lenke
   av noen som leter etter en. */
.alert-act {
  display: inline-block; margin-top: 11px;
  font: 600 13px/1 var(--font-sans); color: var(--bad-deep);
  text-decoration: none; background: none; border: 0; padding: 0;
  cursor: pointer;
}
.alert-act:hover, .alert-act:focus-visible { text-decoration: underline; }

/* Fasitens mål: 20/22 i stedet for 13/14, radius 12, ikon 19. */
.alert-bad.alert-lg { gap: 13px; padding: 20px 22px; border-radius: 12px; }
.alert-bad.alert-lg svg { width: 19px; height: 19px; }
/* :not(.alert-title) er bærende, ikke pynt. Tittelen ER en <p>, og en naken
   .alert-bad.alert-lg p (0-3-0) vinner over .alert-title-regelen over (0-2-0)
   — den ville da dratt tittelen fra fasitens 1,3 til 1,6 og lagt text-wrap
   oppå den. Samme felle som kommentaren tolv linjer opp advarer mot; her er
   den lukket for hele regelen i stedet for felt for felt. */
.alert-bad.alert-lg p:not(.alert-title) { line-height: 1.6; text-wrap: pretty; }

.alert-bad.is-warn { background: var(--warn-soft); border-color: var(--warn-line); }
.alert-bad.is-warn svg { color: var(--warn); }
.alert-bad.is-warn p,
.alert-bad.is-warn .alert-title,
.alert-bad.is-warn .alert-act { color: var(--warn-deep); }

/* Beskjeden på tilbudsdetaljen står øverst i venstrespalta, over dokumentet —
   ikke i skinna. På telefon kommer skinna etter hele arket, og en melding om
   at e-posten ikke kom fram kan ikke ligge nederst på siden. */
.qd-alert { margin: 0 0 14px; }

/* «Kunden har ikke svart på når vi kan starte» — inne i Oppdraget-kortet, over
   stegflisene. Samme toppavstand som .qd-stages, så boksen legger seg i kortets
   egen rytme i stedet for å stikke ut fra den. */
.qd-startnote { margin-top: 13px; }

/* Kundens begrunnelse for avslag i skinna. Feltet tar 1000 tegn, og 1000 tegn i
   en 340 px spalte er ~25 linjer som ville skjøvet Kunde og Mer ut av syne.
   Seks linjer er nok til å se hva slags svar det er; resten felles ut med «les
   hele». Utfellingen er Alpine, som tidslinjas egen «vis tidslinje» rett over. */
.qd-reason {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6;
  overflow: hidden;
}
.qd-reason.is-open { display: block; -webkit-line-clamp: none; }

@media (max-width: 1023.98px) {
  .ql-empty { margin-block: 20px; padding: 28px 22px; }
}

/* =========================================================================
   Skjerm 19 · Drift
   -------------------------------------------------------------------------
   Leverandørens eget panel over hele installasjonen. Ingen inne i en bedrift
   ser noe av dette: hele /drift/ ligger bak `vendor_required` (is_superuser),
   og en administrator har Innstillinger og Administrasjon, ikke dette.

   Skallet er husets: .qb (panelet), .qb-top + .rg-top (topplinja), .qb-btn
   (knappene), .tbl (de to diagnosetabellene). Det nye her er .dr-*: den mørke
   leverandørstripa, nøkkeltallskortene, bedriftsutdraget og de to bunnpanelene.

   Stripa ligger INNE i panelet, ikke over sidehodet. Grunnen er konkret:
   `company` blir stående i økta når leverandøren går tilbake til /drift/, så
   base.htmls .vendorbar («Du ser HRS Elektro AS som leverandør») kan allerede
   stå klistret øverst. To sticky bånd oppå hverandre er nettopp det .verifybar
   advarer mot — og de to sier ikke det samme. Inne i panelet er stripa en
   overskrift over driftsflaten, ikke en konkurrent til den.

   Designet tegner ingen telefonvariant. Bedriftsutdragets fem kolonner brytes
   derfor ned til en kortliste under 1024 px, som .ua-card på skjerm 17.
   ========================================================================= */

/* ---- Leverandørstripa ---------------------------------------------------- */
/* #93B4FA og #C3C9D4 er designets egne verdier PÅ mørk flate, og finnes ikke
   som tokens: paletten er skrevet for tekst på papir. De står som literaler her
   fordi de ikke brukes noe annet sted. */
.dr-vendor {
  background: var(--ink); padding: 12px 20px;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.dr-vendor-tag {
  font: 500 9.5px/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: #93B4FA;
}
.dr-vendor-text { font: 400 12px/1 var(--font-mono); color: #C3C9D4; }

/* Fasitens driftsknapper er 40 px med 8 px til ikonet, ikke topplinjas 38/7.
   .dr-sidene som låner skjerm 13s .cu-skall får det derfra; dashbordet,
   bedriftslista, aktiviteten og systemloggen har bare .dr. */
.dr .qb-top-act .qb-btn { min-height: 40px; gap: 8px; }
.dr .qb-top-act .qb-btn-primary { font-size: 13.5px; }

/* Byggerens telefonregel skjuler ALLE .qb-btn i .qb-top-act (den ville ellers
   presset tittelen i stykker på 375 px). På Drift ER knappene navigasjonen
   mellom driftssidene — de kan ikke forsvinne. En mer spesifikk velger, og
   regelen på linje ~2159 står urørt.

   De tre unntakene er knapper som ANDRE skjermer skjuler her med vilje, og som
   har en telefonutgave et annet sted i topplinja: .ql-newbtn (pluss-kvadratet
   .ql-add står i stedet), .cu-cancel og .cu-save-desk (× -en til venstre og
   .cu-save-phone). Uten unntaket viste bedriftslista både «Ny bedrift» og
   pluss-kvadratet, og de to skjemaene fire kontroller der huset mener to. */
@media (max-width: 1023.98px) {
  .dr .qb-top-act .qb-btn:not(.ql-newbtn):not(.cu-cancel):not(.cu-save-desk) {
    display: inline-flex;
  }
  /* Stripa er en linje i fasiten; på telefon brekker setningen, og da kan
     linjene ikke stå i 12px/1. */
  .dr-vendor-text { line-height: 1.5; }
  /* To-tre brede knapper og en tittel får ikke plass på en linje på 375 px —
     tittelen ble skjøvet ut under dem. Knapperaden tar sin egen linje i
     stedet, og knappene deler bredden likt.

     .dr-nav, ikke alle .qb-top-act: bedriftslistas pluss-kvadrat og skjemaenes
     «Opprett» er husets telefonkontroller og hører hjemme PÅ tittelens linje.
     De ville ellers fått en egen, nesten tom rad under den. */
  .dr .qb-top { flex-wrap: wrap; }
  .dr .qb-top-act.dr-nav { flex: 1 1 100%; }
  .dr .qb-top-act.dr-nav .qb-btn {
    flex: 1 1 0; min-width: 0; min-height: 44px; justify-content: center;
  }
  /* «Gå inn i bedriften» er en POST og ligger derfor i en <form>. Fleks-barnet
     er da formen, ikke knappen, og raden ble ujevn. */
  .dr .qb-top-act.dr-nav > form { flex: 1 1 0; min-width: 0; display: flex; }
  .dr .qb-top-act.dr-nav > form .qb-btn { flex: 1 1 auto; }
}

/* ---- Fargevelgerne på Ny bedrift / Rediger bedrift ---------------------- */
/* Kontrollen er husets .input — ramme, radius, bakgrunn og fokusring kommer
   derfra — og .fld-swatch bytter bare innmaten mot selve prøven. Høyden er
   .sform-feltets: 13,5px/1.2 + 12/13 luft + rammen. */
.fld-swatch { height: 42px; padding: 5px; cursor: pointer; }
.fld-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.fld-swatch::-webkit-color-swatch { border: 0; border-radius: 5px; }
.fld-swatch::-moz-color-swatch { border: 0; border-radius: 5px; }

.dr-body { padding: 20px; display: flex; flex-direction: column; gap: 13px; }

/* ---- Nøkkeltallene ------------------------------------------------------- */
/* Ett hakk mindre og løsere sporet enn dashbordets .kpi (26 px, ls .14em):
   dette er designets egne verdier, og .kpi står urørt for skjerm 01. */
.dr-kpis { display: flex; gap: 11px; flex-wrap: wrap; }
.dr-kpi {
  flex: 1 1 150px; min-width: 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; padding: 15px 17px;
}
.dr-kpi-label {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
}
.dr-kpi-value {
  margin-top: 10px;
  font: 500 24px/1 var(--font-sans); letter-spacing: -0.04em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* Sikkerhetskopi-kortet har fem tilstander designet ikke tegner («Ikke satt opp
   her», «Kan ikke leses», «Aldri» …). En setning i 24 px er ikke et nøkkeltall,
   så et tekstsvar får sin egen grad. */
.dr-kpi-value.is-text { font-size: 16px; line-height: 1.25; letter-spacing: -0.02em; }
.dr-kpi-note { margin-top: 7px; font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.dr-kpi-note.is-warn { color: var(--warn); }
.dr-kpi-note.is-bad { color: var(--bad); }

/* ---- De tre maskinsjekkene ----------------------------------------------- */
/* Database, E-post og Filer er ekte driftsvarsler designet ikke tegner. De
   beholdes, men som en stillere stripe under nøkkeltallene — ikke som seks
   like store kort ved siden av dem. */
.dr-checks {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; overflow: hidden;
}
.dr-check {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 11px 18px; border-bottom: 1px solid var(--line-soft);
}
.dr-check:last-child { border-bottom: 0; }
.dr-check .status-dot { margin-top: 0; align-self: center; }
.dr-check-label {
  /* 126, ikke 108: «E-post på profilen» er den lengste etiketten, og med 108
     dyttet den sin egen verdi 13 px lenger ut enn de fem andre radene. */
  flex: none; min-width: 126px;
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.dr-check-value { font: 500 12.5px/1.4 var(--font-sans); color: var(--ink); }
.dr-check-note { flex: 1 1 220px; min-width: 0; font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

/* ---- Kortet med hode, tabell og fot -------------------------------------- */
.dr-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; overflow: hidden;
}
.dr-card-head {
  padding: 12px 18px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
}
.dr-card-head > svg { width: 17px; height: 17px; display: block; flex: none; color: var(--ink-2); }
.dr-card-title { font: 600 14px/1.2 var(--font-sans); letter-spacing: -0.02em; color: var(--ink); }
.dr-card-link {
  margin-left: auto; white-space: nowrap;
  font: 500 12.5px/1 var(--font-sans); color: var(--brand-ink); text-decoration: none;
}
.dr-card-link:hover { text-decoration: underline; }
.dr-foot { padding: 13px 18px; }
.dr-note { font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }

/* ---- Bedriftsutdraget ---------------------------------------------------- */
.dr-grid { display: grid; grid-template-columns: 1fr 96px 116px 130px 96px; gap: 14px; }
.dr-head {
  padding: 10px 18px; background: var(--row-tint); border-bottom: 1px solid var(--line);
}
.dr-head span {
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.dr-head span + span { text-align: right; }
.dr-row {
  padding: 13px 18px; align-items: center;
  border-bottom: 1px solid var(--line-soft);
  text-decoration: none; color: inherit;
  transition: background-color 120ms ease;
}
.dr-row:hover { background: var(--brand-03); }
.dr-row > * + * { text-align: right; }
.dr-name { min-width: 0; font: 500 13.5px/1.35 var(--font-sans); color: var(--ink); }
.dr-sub { display: block; font: 400 11px/1.4 var(--font-mono); color: var(--ink-3); }
.dr-num { font: 400 13px/1 var(--font-mono); color: var(--ink); font-variant-numeric: tabular-nums; }
.dr-when { font: 400 11.5px/1 var(--font-mono); color: var(--ink-3); }
/* Enheten står bare på telefon, der kolonnehodet er borte og «4» og «47» ellers
   ville vært to tall uten navn. Samme grep som .nf-wide / .nf-narrow. */
.dr-unit { display: none; }
/* .badge er 5px 7px; utdragets piller er designets 5px 8px. Samme ett-hakks
   scoping som .ua-grid .badge på skjerm 17. */
.dr-grid .badge { padding: 5px 8px; }
/* Abonnementscella: merket på en linje, notatet som en stille andrelinje
   under — samme form som bedriftslista. */
.dr-subs .dr-quiet {
  display: block; margin-top: 3px;
  font: 400 11px/1.4 var(--font-mono); color: var(--ink-3);
}

/* ---- De to bunnpanelene -------------------------------------------------- */
.dr-panels { display: flex; gap: 11px; flex-wrap: wrap; align-items: flex-start; }
.dr-panel {
  flex: 1 1 300px; min-width: 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; padding: 16px 18px;
}
.dr-panel.is-narrow { flex: 1 1 260px; }
.dr-panel-head { display: flex; align-items: center; gap: 10px; }
.dr-panel-head svg { width: 16px; height: 16px; display: block; flex: none; color: var(--ink-2); }
.dr-panel-head.is-warn svg { color: var(--warn); }
.dr-panel-title { font: 600 13.5px/1.2 var(--font-sans); letter-spacing: -0.02em; color: var(--ink); }
.dr-list { margin-top: 12px; display: flex; flex-direction: column; gap: 10px; }
.dr-ev { display: flex; gap: 11px; align-items: baseline; }
.dr-ev-text { flex: 1; min-width: 0; font: 400 12.5px/1.45 var(--font-sans); color: var(--ink-2); }
.dr-ev-actor { font-weight: 500; color: var(--ink); }
.dr-ev-when { flex: none; font: 400 11px/1 var(--font-mono); color: var(--ink-3); }
.dr-panel-link {
  display: inline-block; margin-top: 12px;
  font: 500 12.5px/1 var(--font-sans); color: var(--brand-ink); text-decoration: none;
}
.dr-panel-link:hover { text-decoration: underline; }

/* Feil- og advarselsboksene: samme to tonene som skjerm 14s beskjed, i
   panelformat. */
.dr-msg {
  border-radius: 7px; padding: 11px 12px;
  background: var(--bad-soft); border: 1px solid var(--bad-line);
}
.dr-msg-title { font: 500 12.5px/1.4 var(--font-sans); color: var(--bad-deep); }
/* Antallet når samme feil har gjentatt seg. Mono og tabulære siffer, så «12 ×»
   og «5 ×» starter på samme sted når radene ligger under hverandre. */
.dr-msg-antall {
  font-family: var(--font-mono); font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dr-msg-sub { margin-top: 4px; font: 400 11px/1.45 var(--font-mono); color: var(--bad-deep); word-break: break-word; }
.dr-msg.is-warn { background: var(--warn-soft); border-color: var(--warn-line); }
.dr-msg.is-warn .dr-msg-title, .dr-msg.is-warn .dr-msg-sub { color: var(--warn-deep); }

/* ---- Undersidene: filtre, tabeller, skjemaer ----------------------------- */
/* Aktivitet og Systemlogg er diagnoseflater med brede mono-meldinger og
   utfellbare sporinger. De beholder .tbl — å presse dem inn i et fast rutenett
   ville kuttet nettopp det man er der for å lese — men tabellhodet får
   designets tone og sideluft. */
/* .qb-panelet er papirfarget; tabellen inne i det er arket. */
.dr .tbl { background: var(--surface); }
.dr .tbl thead th {
  background: var(--row-tint); border-bottom: 1px solid var(--line);
  font-size: 9px; letter-spacing: 0.1em; padding: 10px 18px;
}
.dr .tbl tbody td { padding: 13px 18px; border-bottom: 1px solid var(--line-soft); }
.dr .tbl tbody tr:last-child td { border-bottom: 0; }
/* De to varme gråtonene fra det gamle systemet, i Sonidas kalde. Scopet til
   .dr: .lvl-info og .badge-muted brukes også utenfor drift. */
.dr .lvl-info, .dr .badge-muted { background: var(--neutral-bg); color: var(--neutral); }
.dr-search { flex: 1 1 240px; min-width: 0; }
.dr-search .input { width: 100%; }
.dr-pager { padding: 13px 18px; }
.dr-pager .pager { margin-top: 0; }

@media (max-width: 1023.98px) {
  .dr-body { padding: 16px; gap: 11px; }
  /* 2×2-rutenettet: «Feil siste 7 dager» brekker til to etikettlinjer mens
     naboen har en, og da sto de to store tallene i samme rad på hver sin
     grunnlinje. To linjers plass til alle fire. */
  .dr-kpi-label { min-height: 2em; }
  /* «Tilbud totalt» bærer statusfordelingen og trenger bredden: i en 150 px
     halvrad ville den flytende lista blitt fire linjer og igjen strukket alle
     fire kortene. Egen rad i full bredde gir den to. De tre andre ligger
     fortsatt to og to. */
  .dr-kpi.dr-kpi-quotes { flex: 1 1 100%; }
  .dr-vendor { padding: 11px 16px; gap: 8px; }
  .dr-vendor-text { font-size: 11px; }
  /* Utdraget faller fra fem kolonner til ett kort per bedrift: navnet på egen
     linje, resten som en meta-rad under. */
  .dr-head { display: none; }
  .dr-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px 12px; padding: 13px 16px; }
  .dr-row > * + * { text-align: left; }
  .dr-name { flex: 1 1 100%; }
  .dr-unit { display: inline; }
  .dr-card-head, .dr-foot { padding-inline: 16px; }
  .dr-check { padding-inline: 16px; }
  .dr .tbl thead th, .dr .tbl tbody td { padding-inline: 16px; }
}

/* ---- Drift-undersidene: kolonnebredder og småting ------------------------ */
/* Breddene sto i Tailwind-klasser på hver <th> før (w-[150px] …). Tailwind
   lastes ETTER app.css og vinner over komponent-CSS, så de hører ikke hjemme
   på en Sonida-flate — her er de tabellens egne. */
/* Åtte kolonner tåler ikke .dr .tbl sin sideluft på 18 px — den ville alene
   tatt 288 px av bredden. Her er den 11, med de to ytterste holdt mot kanten. */
/* table-layout: fixed, ellers er de oppgitte breddene bare et ønske: en
   tabell utvider en kolonne til innholdets minstebredde, og «REGISTERENHETEN I
   BRØNNØYSUND» dyttet da hele tabellen ut av panelet. Fast layout lar
   .actor-name faktisk kutte med ellipse. */
.dr-companies { table-layout: fixed; }
/* Bare navnekolonnen brytes; et orgnr eller en dato som deles i to linjer er
   verre enn en ellipse. */
.dr-companies td:first-child { overflow-wrap: anywhere; }
/* Ellipse virker bare når flex-barnet får krympe: .actor-name har allerede
   overflow/text-overflow, men uten min-width: 0 vokser .rowlink forbi cella. */
.dr-companies .rowlink { max-width: 100%; }
.dr-companies .actor-name { min-width: 0; }
.dr-companies th, .dr-companies td { padding-inline: 11px; }
.dr-companies th:first-child, .dr-companies td:first-child { padding-left: 18px; }
.dr-companies th:last-child, .dr-companies td:last-child { padding-right: 18px; }
.dr-companies th:nth-child(2) { width: 112px; }
.dr-companies th:nth-child(3) { width: 64px; }
/* Var 122 px da fem statuslinjer sto åpent i cella. Nå rommer den et tall og
   et lite tegn; de 26 pikslene går til navnekolonnen, som er den som faktisk
   mangler plass (den har ingen egen bredde og tar det som blir til overs).
   Ikke smalere: den utfelte fordelingen skal ha plass til «Akseptert 4» på en
   linje, ellers brekker hver status i to og panelet blir ti linjer høyt. */
.dr-companies th:nth-child(4) { width: 96px; }
.dr-companies th:nth-child(5) { width: 100px; }
.dr-companies th:nth-child(6) { width: 88px; }
.dr-companies th:nth-child(7) { width: 104px; }
.dr-companies th:nth-child(8) { width: 132px; }
/* Statusfordelingen svever nå (J6). position: fixed er hele poenget: cella
   ligger inne i .qb (overflow: hidden, for de runde hjørnene) og .dr-scroll
   (overflow-x: auto), og et absolutt-posisjonert panel ble klippet av begge -
   verst på den siste raden og mot høyre kant. Fixed ser ingen av dem.

   Plasseringen regnes i JS (se x-data i drift/companies.html), for CSS anchor
   positioning er ennå ikke bredt nok støttet. Boblen lukkes på scroll: en
   fixed boble følger ikke med tabellen og ville blitt hengende i lufta. */
.dr-qpop {
  position: fixed; z-index: 60;
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 11px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 14px 34px -18px rgb(17 24 39 / 0.35);
  font: 400 12.5px/1.45 var(--font-sans); color: var(--ink-2);
  white-space: nowrap;
}

/* Statuslinjene brytes aldri - «Akseptert» og tallet hører sammen, og en
   kolonne som deler dem gjør fem statuser til ti linjer. */
.dr-companies .dr-statline { white-space: nowrap; }
.dr-qbtn {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; padding: 2px 4px; margin-left: -4px;
  border-radius: var(--radius-ctl);
  font: inherit; color: inherit; cursor: pointer;
}
.dr-qbtn:hover { background: var(--brand-03); }
.dr-qbtn svg { width: 13px; height: 13px; color: var(--ink-3); transition: transform 150ms var(--ease-out); }
.dr-qbtn.is-open svg { transform: rotate(180deg); }
/* På telefon er raden et kort, og tegnet skal treffes med tommelen. */
@media (max-width: 767.98px) {
  .dr-qbtn { min-height: 44px; padding-inline: 8px; margin-right: -8px; }
}
/* Sikkerhetsnett: på en smal skjerm ruller tabellen inne i panelet i stedet
   for å bli klippet av .qb sin overflow: hidden. */
.dr-scroll { overflow-x: auto; }

.dr-activity th:nth-child(1) { width: 148px; }
.dr-activity th:nth-child(2) { width: 168px; }
.dr-activity th:nth-child(3) { width: 136px; }
.dr-activity th:nth-child(5) { width: 136px; }
.dr-activity th:nth-child(6) { width: 196px; }

.dr-log th:nth-child(1) { width: 148px; }
.dr-log th:nth-child(2) { width: 96px; }
.dr-log th:nth-child(4) { width: 176px; }
/* Loggraden er høy: melding, knapp og en utfellbar sporing. Alt flukter mot
   toppen, ellers svever klokkeslettet midt i en åpnet traceback. */
.dr-log tbody td { vertical-align: top; }

/* Prøve-plata på bedriftsraden er tekst PÅ en tonet flate, og fasitens verdi
   er #1740B4 — nøyaktig det --brand-ink er til for (se tokenets kommentar).
   Scopet til .dr: .badge-brand brukes også på skjermer som allerede er
   godkjent, og de skal ikke skifte farge av denne rettelsen. */
.dr .badge-brand { color: var(--brand-ink); }

.dr-dim { color: var(--ink-2); }
.dr-quiet { font: 400 12.5px/1.45 var(--font-sans); color: var(--ink-3); }
/* Statusoppsummeringen sto som «Utkast 2 · Sendt 5 · …» i en kolonne så smal
   at den brakk til en status per linje uansett — og da endte hver linje på en
   løs «·». Egne linjer uten skilletegn sier det samme uten den. */
.dr-statline { display: block; }
/* Nøkkeltallskortets statusfordeling: «Utkast 2 · Sendt 5 · Akseptert 4» på
   løpende linje. Statusen og tallet henger sammen (hardt mellomrom i malen +
   nowrap), så linja aldri brekker mellom «Avslått» og «1»; det er skilletegnet
   som gir brekkpunktene. Derfor er separatoren ekte tekst og ikke ::before -
   to inline-bokser uten mellomrom mellom seg gir ingen brekkmulighet. */
.dr-stat { white-space: nowrap; }
.dr-stat-sep { color: var(--line-strong); }
.dr-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.dr-expand { margin-top: 6px; }
.dr-mt { margin-top: 12px; }

/* Bunnlinja under et driftspanel: retensjonsteksten og «Rydd nå». */
.dr-foot-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.dr-foot-row .rg-foot-note { flex: 1 1 420px; }
.dr-foot-row form { margin-left: auto; }

/* Skjemaene i Drift (Ny bedrift, Rediger bedrift) låner skjerm 13s
   gruppekort. Skjerm 13 skjuler kickeren på telefon fordi feltene der er
   selvforklarende; her er den navnet på gruppa — «Satser», «Bransjemal»,
   «Første administrator» — og fem navnløse bolker etter hverandre er ikke et
   skjema noen kommer gjennom. Samme grep som .set-block på skjerm 09. */
@media (max-width: 1023.98px) {
  .dr .cu-kicker { display: block; }
  /* Kortbakgrunnen er borte på telefon, og kickeren og .fld-label er samme
     mono-versal i samme grå — «BEDRIFT» og «FIRMANAVN» leses da som en blokk.
     Gruppenavnet får full ink og litt luft under seg (skjerm 13 nullstiller
     .cu-rows toppluft på første rad, siden kickeren der er skjult), så det er
     tydelig hva som er overskrift og hva som er etikett. .cu-kicker selv står
     urørt for skjerm 13. */
  .dr .cu-kicker { color: var(--ink); margin-bottom: 10px; }
}

/* ---- Drift → Registrering: trakten -------------------------------------- */
/* Skallet er Drifts eget (.dr-body, .dr-card, .dr-foot, .dr-note); .tr-* er
   bare stolpene, dag-radene og kildelista.

   INGEN TRANSITION, INGEN ANIMASJON, noe stolper ellers ville hatt: dette er et
   internt verktøy som åpnes for å lese av et tall, ofte flere ganger om dagen,
   og en stolpe som vokser inn er én ting å vente på hver gang.

   De tre blåtonene er én farge i tre styrker, lys til mørk etter hvor langt ned
   i trakten steget ligger. --brand-16 og --brand er tokens; mellomtonen finnes
   ikke som token og står som literal, hentet på linja mellom de to. Rekkefølgen
   i markupen er stigende styrke, så det minste tallet ligger øverst og aldri
   forsvinner under naboen sin. */
.tr-funnel, .tr-days, .tr-sources {
  padding: 14px 18px; display: flex; flex-direction: column; gap: 9px;
}
.tr-step, .tr-day, .tr-src { display: flex; align-items: center; gap: 12px; }
.tr-step-label, .tr-src-label {
  flex: none; width: 132px; min-width: 0;
  font: 500 12.5px/1.35 var(--font-sans); color: var(--ink);
  overflow-wrap: anywhere;
}
.tr-day-date {
  flex: none; width: 52px;
  font: 400 11.5px/1 var(--font-mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
/* Banen bærer alle fyllene, og de ligger oppå hverandre fra venstre kant. */
.tr-track {
  position: relative; flex: 1 1 auto; min-width: 40px; height: 10px;
  background: var(--row-tint); border: 1px solid var(--line-soft);
  border-radius: 5px; overflow: hidden;
}
.tr-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 5px 0 0 5px; }
.tr-fill.is-1 { background: var(--brand-16); }
.tr-fill.is-2 { background: #6D9AF0; }
.tr-fill.is-3 { background: var(--brand); }
/* Tallet er fasiten, stolpen er formen — derfor tabulære siffer og fast bredde,
   så fjorten rader står i kolonne og kan leses nedover. */
.tr-num {
  flex: none; min-width: 34px; text-align: right;
  font: 400 13px/1 var(--font-mono); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.tr-day-nums { flex: none; display: flex; gap: 8px; }
/* 128, ikke 116: «49 % av besøkene» er den lengste teksten kolonnen har, og med
   116 brakk den i to linjer mens naboraden under sto på én. */
.tr-share {
  flex: none; width: 128px; text-align: right;
  font: 400 11.5px/1 var(--font-mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
/* Nettsidens to totaler. Ikke .dr-kpi: de kortene er driftsoversiktens egne,
   med ramme og bakgrunn, og de ville blitt kort inne i et kort her. Dette er to
   tall på kortets egen flate, med etiketten i samme mono-versal som resten. */
.tr-totals {
  padding: 14px 18px 0; display: flex; gap: 28px; flex-wrap: wrap;
}
.tr-total-label {
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.tr-total-value {
  margin-top: 6px;
  font: 500 22px/1 var(--font-sans); letter-spacing: -0.04em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* Overskrift inne i et kort som allerede har et hode: «Mest besøkte sider» er
   en bolk under besøkstallene, ikke et eget kort. */
.tr-subhead {
  margin-bottom: 2px;
  font: 500 9px/1.3 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.tr-legend {
  padding: 12px 18px 0; display: flex; gap: 14px; flex-wrap: wrap;
}
.tr-key {
  display: inline-flex; align-items: center; gap: 6px;
  font: 400 11px/1 var(--font-mono); color: var(--ink-3);
}
.tr-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.tr-swatch.is-1 { background: var(--brand-16); }
.tr-swatch.is-2 { background: #6D9AF0; }
.tr-swatch.is-3 { background: var(--brand); }

@media (max-width: 1023.98px) {
  /* På telefon er det etiketten som må vike: navnet legger seg over stolpen, og
     raden under er bane, tall og andel som på skjerm.

     Andelen beholder sin faste bredde med vilje - med `width: auto` ble
     «— » -raden 30 px smalere enn «26 % av forrige», og da sto de tre tallene
     i trakten ikke lenger i kolonne. Det er nettopp de tre som skal leses
     nedover. */
  .tr-funnel, .tr-days, .tr-sources { padding-inline: 16px; }
  .tr-step, .tr-src { flex-wrap: wrap; }
  .tr-step-label, .tr-src-label { flex: 1 1 100%; width: auto; }
  .tr-legend, .tr-totals { padding-inline: 16px; gap: 10px; }
  .tr-totals { gap: 22px; }
}

/* =========================================================================
   Skjerm 15 · «Send som e-post» (skrivesiden)
   -------------------------------------------------------------------------
   Høyre halvdel av fasitens skjerm 15. Feltene er skjerm 13s (.fld, .cu-card,
   .sform), topplinja er husets, og .em-* er det som er nytt: nummeret ved
   siden av tittelen, den skrivebeskyttede «Fra»-ruta, notiskortet og selve
   forhåndsvisningen.

   Designet tegner en «Forhåndsvis»-KNAPP og ingen ramme rundt en visning.
   Den løpende forhåndsvisningen er beholdt likevel, og det er et valg:
   sendingen kan ikke tas tilbake, så flyten har med vilje bare en dør, og
   visningen står inne i den. Se docs/design-utelatt.md, «Fra 15 · E-posten».
   ========================================================================= */
.em-num { font: 400 12px/1 var(--font-mono); color: var(--ink-3); white-space: nowrap; }
.em-body {
  padding: 20px;
  display: grid; grid-template-columns: minmax(0, 392px) minmax(0, 1fr);
  gap: 13px; align-items: start;
}
.em-col { min-width: 0; display: flex; flex-direction: column; gap: 13px; }
/* «Fra» er avsenderen leverandøren har satt opp for bedriften — den kan ikke
   endres her, så den er en rute og ikke et felt. Grå tekst sier det uten et
   låseikon. */
.em-readonly {
  border: 1px solid var(--line); border-radius: 8px; padding: 12px 13px;
  font: 400 13.5px/1.2 var(--font-sans); color: var(--ink-3);
  /* En linje, som feltet ved siden av: «Navn <adresse>» er lengre enn en halv
     392 px-spalte og ville ellers gjort Fra tre linjer høy mens Til sto på en.
     Hele verdien ligger i title, og står uansett i forhåndsvisningen. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Til og Fra deler raden i fasiten. .cu-rows 200 px basis er skrevet for et
   fullbreddes skjema og ville brutt dem fra hverandre i en 392 px spalte. */
.em .cu-row > .fld { flex: 1 1 140px; }
/* Fasitens følgetekst er 96 px — tre linjer. .sform sin 64 px er skrevet for
   den interne notatboksen på skjerm 13. */
/* .sform .textarea setter 1.5; fasitens følgetekst er 13,5px/1.6. */
.em .textarea { min-height: 96px; height: 96px; line-height: 1.6; }
/* margin-top 13, ikke .cu-notes 11: raden er en rad i kortet, og kortets egen
   avstand mellom radene er 13. */
.em-pdf { margin-top: 13px; display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.em-pdf-box {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  font: 400 13px/1.4 var(--font-sans); color: var(--ink-2);
}
.em-pdf-box input { width: 19px; height: 19px; flex: none; accent-color: var(--brand); }
.em-pdf-note { font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3); }
.em-note {
  background: var(--row-tint); border: 1px solid var(--line);
  border-radius: 10px; padding: 16px 18px;
}
.em-note p { font: 400 12.5px/1.6 var(--font-sans); color: var(--ink-2); text-wrap: pretty; }

.em-preview {
  min-width: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; overflow: hidden;
}
.em-preview-head {
  padding: 12px 18px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.em-preview-title { font: 600 13.5px/1.2 var(--font-sans); letter-spacing: -0.02em; color: var(--ink); }
.em-preview-note { font: 400 11.5px/1.4 var(--font-mono); color: var(--ink-3); }
.em-frame { display: block; width: 100%; height: 620px; border: 0; background: var(--surface); }
.em-preview-error { padding: 12px 18px; border-top: 1px solid var(--line-soft); }

@media (max-width: 1023.98px) {
  /* Sendeknappen er den ENESTE i produktet som legger en e-post foran en
     kunde. Byggerens telefonregel skjuler alle .qb-btn i .qb-top-act; den ene
     må stå. Bare den: Avbryt er × -en til venstre på telefon (.cu-cancel), og
     å åpne hele .qb-btn her presset tittelen ned til «S.». */
  .em .qb-top-act .em-send { display: inline-flex; }
  .em-body { grid-template-columns: minmax(0, 1fr); padding: 16px; gap: 12px; }
  /* Ett felt per linje, som resten av .cu-skjemaene på telefon. */
  .em .cu-row > .fld { flex: 1 1 100%; }
  /* Nummeret vikes for tittelen på 375 px — det står uansett i emnefeltet
     rett under, og en tittel kuttet til «Send tilbu…» sier ingenting. */
  .em-num { display: none; }
  .em-frame { height: 460px; }
}

/* Prospekt-e-posten (drift/prospect_email.html) låner hele .em-skallet. Det
   ene som skiller: feltet er HELE brevet, ikke en følgetekst over en generert
   faktaboks, så .em sine 96 px ville krevd rulling inne i et felt Anders skal
   lese gjennom før han sender. 340 px er de seksten linjene rows= ber om. */
.pe .textarea { min-height: 340px; height: 340px; }
@media (max-width: 1023.98px) {
  /* På telefon ligger visningen UNDER feltet, og et felt på 340 px ville skjøvet
     den ut av rekkevidde. 240 px er fortsatt en halv side brev om gangen. */
  .pe .textarea { min-height: 240px; height: 240px; }
}

/* Første rad i et kort uten kicker skal ikke bære .cu-rows toppluft. */
.em .cu-card > .cu-row:first-child { margin-top: 0; }
/* De to skjemaene på «Rediger bedrift» er søsken, ikke ett panel. */
.dr-side { margin-top: 14px; }


/* --- Registrering: samtykket ---------------------------------------------
   Står mellom siste felt og knappen, der man faktisk bestemmer seg. Hele rada
   er klikkbar (label rundt begge), så det ikke kreves presisjon på en telefon
   for å treffe en 16 px firkant. */
.reg-godta { margin-top: 4px; }
.reg-godta-rad {
  display: flex; align-items: flex-start; gap: 10px;
  cursor: pointer; padding: 2px 0;
}
.reg-godta-boks {
  flex: none; width: 17px; height: 17px; margin: 1px 0 0;
  accent-color: var(--brand-ink, #1D4ED8); cursor: pointer;
}
.reg-godta-tekst {
  font: 400 13.5px/1.5 var(--font-sans);
  color: var(--ink-2, #4B5563); text-wrap: pretty;
}
.reg-godta-tekst a { color: var(--brand-ink, #1D4ED8); text-decoration: underline; text-underline-offset: 2px; }

/* --- Drift: abonnementskortet --------------------------------------------
   Tre felt på en rad når det er plass, under hverandre når det ikke er det.
   Knappen på egen linje: den lagrer noe som endrer hva som faktureres, og
   skal ikke ligge inntil et felt man kan treffe med tommelen ved uhell. */
.dr-abo-form { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; padding: 4px 0 2px; }
.dr-abo-felt { flex: 1 1 190px; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.dr-abo-form .qb-btn { flex: 0 0 auto; }
.dr-abo-fin { margin: 12px 0 0; font: 400 12.5px/1.5 var(--font-sans); color: var(--ink-4, #6B7280); }
/* Forespørselen fra bedriften. Ikke en advarsel — en beskjed som venter på
   svar, og som forsvinner i det den er besvart. */
.dr-forespoersel {
  margin: 0 0 14px; padding: 12px 15px;
  background: var(--surface-2, #EEF3FE); border-radius: 9px;
}
.dr-forespoersel-tittel { margin: 0; font: 600 14px/1.4 var(--font-sans); color: var(--ink, #111827); }
.dr-forespoersel-sub { margin: 4px 0 0; font: 400 13px/1.5 var(--font-sans); color: var(--ink-2, #4B5563); }
/* En oppsigelse er en annen slags beskjed enn et planbytte: den har en frist,
   og den skal ikke gå i ett med de blå. */
.dr-forespoersel--opphor { background: var(--warn-bg, #FEF3C7); }
.dr-forespoersel--opphor .dr-forespoersel-sub { color: var(--warn, #92400E); }

/* --- Bedriftens egen abonnementsside ------------------------------------- */
.ab-side { max-width: 720px; }
.ab-hode { margin-bottom: 22px; }
.ab-tittel { margin: 0; font: 700 24px/1.2 var(--font-sans); letter-spacing: -.03em; color: var(--ink, #111827); }
.ab-under { margin: 6px 0 0; font: 400 14.5px/1.5 var(--font-sans); color: var(--ink-2, #4B5563); }
.ab-naa { padding: 18px 20px; background: var(--surface, #FFF); border: 1px solid var(--line, #DDE2EA); border-radius: 12px; }
.ab-naa-rad { display: flex; flex-wrap: wrap; gap: 34px; }
.ab-etikett { margin: 0; font: 500 11px/1 var(--font-mono, var(--font-sans)); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-4, #6B7280); }
.ab-verdi { margin: 7px 0 0; font: 600 19px/1.2 var(--font-sans); color: var(--ink, #111827); }
.ab-note { margin: 3px 0 0; font: 400 13px/1.4 var(--font-sans); color: var(--ink-2, #4B5563); }
.ab-fin { margin: 16px 0 0; padding-top: 13px; border-top: 1px solid var(--line-2, #EDF0F4); font: 400 12.5px/1.5 var(--font-sans); color: var(--ink-4, #6B7280); }
.ab-venter { margin-top: 14px; padding: 13px 16px; background: var(--surface-2, #EEF3FE); border-radius: 10px; }
.ab-venter-tittel { margin: 0; font: 600 14px/1.4 var(--font-sans); color: var(--ink, #111827); }
.ab-venter-sub { margin: 4px 0 0; font: 400 13px/1.5 var(--font-sans); color: var(--ink-2, #4B5563); }
.ab-valg { margin-top: 30px; }
.ab-valg-tittel { margin: 0 0 12px; font: 600 16px/1.3 var(--font-sans); color: var(--ink, #111827); }
.ab-kort-rad { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 13px; align-items: stretch; }
.ab-kort { display: flex; flex-direction: column; padding: 18px 19px; background: var(--surface, #FFF); border: 1px solid var(--line, #DDE2EA); border-radius: 12px; }
.ab-kort.er-naa { border-color: var(--ink, #111827); }
.ab-kort-navn { margin: 0; font: 600 14px/1.3 var(--font-sans); color: var(--ink, #111827); }
.ab-merke { display: inline-block; margin-left: 5px; padding: 2px 7px; border-radius: 5px; background: var(--surface-2, #EEF3FE); font: 500 11px/1.5 var(--font-sans); color: var(--brand-ink, #1D4ED8); }
.ab-kort-pris { margin: 11px 0 0; font: 700 25px/1 var(--font-sans); letter-spacing: -.03em; color: var(--ink, #111827); }
.ab-kort-enhet { font: 400 14px/1 var(--font-sans); color: var(--ink-2, #4B5563); letter-spacing: 0; }
.ab-kort-fin { margin: 7px 0 16px; font: 400 13px/1.45 var(--font-sans); color: var(--ink-2, #4B5563); }
.ab-kort form { margin-top: auto; }
.ab-kort-naa { margin: auto 0 0; font: 500 13px/1.4 var(--font-sans); color: var(--ink-4, #6B7280); }
.ab-knapp { width: 100%; padding: 10px 14px; border: 0; border-radius: 9px; background: var(--brand-ink, #1D4ED8); color: #FFF; font: 600 14px/1.2 var(--font-sans); cursor: pointer; }
.ab-knapp:hover { background: var(--brand-ink-hover, #1740B4); }
.ab-knapp--rolig { background: var(--surface-3, #EDF0F4); color: var(--ink, #111827); }
.ab-knapp--rolig:hover { background: var(--line, #DDE2EA); }
.ab-regel { margin: 15px 0 0; font: 400 12.5px/1.55 var(--font-sans); color: var(--ink-4, #6B7280); text-wrap: pretty; }
.ab-regel a { color: var(--brand-ink, #1D4ED8); }

/* Dataeksporten på «Min bedrift». Egen seksjon under skjemaet, skilt med en
   linje: den lagrer ingenting og hører ikke til lagreknappen over. */
.eksport { margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--line, #DDE2EA); max-width: 62ch; }
.eksport-tittel { margin: 0 0 8px; font: 600 16px/1.3 var(--font-sans); color: var(--ink, #111827); }
.eksport-tekst { margin: 0 0 16px; font: 400 13.5px/1.6 var(--font-sans); color: var(--ink-2, #4B5563); text-wrap: pretty; }

/* Oppsigelsen. Sammenfelt nederst, adskilt fra planvalgene av en linje: den
   skal være å finne for den som leter, og usynlig for den som ikke gjør det.
   Dempet varselfarge, ikke rød — dette er en avslutning man har rett på, ikke
   en feil man er i ferd med å begå. */
.ab-opphor { margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--line, #DDE2EA); }
.ab-opphor-sum {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 11px; margin-left: -11px; border-radius: 8px;
  font: 500 13.5px/1.3 var(--font-sans); color: var(--ink-2, #4B5563);
  cursor: pointer; list-style: none;
  transition: background-color 140ms ease, color 140ms ease;
}
.ab-opphor-sum::-webkit-details-marker { display: none; }
/* Trekanten peker ned når den er åpen — samme retning som innholdet den
   avslører, så pila forteller hva som skjer og ikke bare at noe skjedde. */
.ab-opphor-sum::before {
  content: ""; width: 0; height: 0;
  border-left: 4.5px solid currentColor;
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform 160ms var(--ease-out, cubic-bezier(.23, 1, .32, 1));
}
.ab-opphor[open] > .ab-opphor-sum::before { transform: rotate(90deg); }
.ab-opphor-sum:hover { background: var(--surface-3, #EDF0F4); color: var(--ink, #111827); }
.ab-opphor-sum:focus-visible { outline: 2px solid var(--brand-ink, #1D4ED8); outline-offset: 2px; }
.ab-opphor-inn { padding: 4px 0 0; max-width: 62ch; }
.ab-opphor-tekst { margin: 12px 0 0; font: 400 13.5px/1.6 var(--font-sans); color: var(--ink-2, #4B5563); text-wrap: pretty; }
.ab-opphor-tekst--vekt { color: var(--ink, #111827); }
.ab-opphor-skjema { margin-top: 16px; display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
/* Avkryssingen står tett på knappen, som ved bestillingen: beslutningen og
   handlingen skal leses som én ting. */
.ab-opphor-bekreft { display: flex; gap: 9px; align-items: center; font: 400 13.5px/1.4 var(--font-sans); color: var(--ink, #111827); cursor: pointer; }
.ab-opphor-bekreft input { width: 17px; height: 17px; flex: none; accent-color: var(--brand-ink, #1D4ED8); cursor: pointer; }
.ab-opphor-skjema .ab-knapp { width: auto; padding: 9px 18px; }

/* Har de sagt opp, er det sidens viktigste opplysning — dempet gul, ikke blå,
   så den ikke leses som nok en nøytral beskjed. */
.ab-venter--opphor { background: var(--warn-bg, #FEF3C7); }
.ab-venter--opphor .ab-venter-sub { color: var(--warn, #92400E); }
.ab-venter--opphor form { margin-top: 12px; }
.ab-venter--opphor .ab-knapp { width: auto; padding: 8px 16px; background: rgba(255, 255, 255, .72); }
.ab-venter--opphor .ab-knapp:hover { background: #FFF; }

/* Trykkflater på berøring. Abonnementssiden er der bedriften bruker penger og
   sier opp — de to knappene der har minst av alt råd til å bomme. Målt på 375:
   planknappene lå på 37 px, utfellingen på 32 og «Si opp» på 35. Bare på
   (hover: none), så pekerbrukere beholder den tettere rytmen. */
@media (hover: none) {
  .ab-knapp { min-height: 44px; }
  .ab-opphor-sum { min-height: 44px; box-sizing: border-box; }
  .ab-opphor-bekreft input { width: 22px; height: 22px; }
}
/* Prikken ved «Abonnement»: bedriften venter på svar på et planbytte. Diskret
   med vilje — den er en påminnelse, ikke et varsel. */
.nav-prikk { display: inline-block; width: 6px; height: 6px; margin-left: 5px; border-radius: 50%; background: var(--brand-ink, #1D4ED8); vertical-align: middle; }
/* Bestilt, ikke fakturert: en beskjed MED en handling, i motsetning til
   planforespørselen som bare venter på at skjemaet under lagres. */
.dr-forespoersel--handling { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; }

/* Bestillingen på utestengt-skjermen. Avkryssingen står tett på knappen -
   det er én handling, ikke to. */
.trial-godta { display: flex; align-items: flex-start; gap: 10px; margin: 18px 0 14px; cursor: pointer; text-align: left; }
.trial-godta input { flex: none; width: 17px; height: 17px; margin: 2px 0 0; accent-color: var(--brand-ink, #1D4ED8); cursor: pointer; }
.trial-godta span { font: 400 13px/1.5 var(--font-sans); color: var(--ink-2, #4B5563); text-wrap: pretty; }
.trial-godta a { color: var(--brand-ink, #1D4ED8); text-decoration: underline; text-underline-offset: 2px; }
button.trial-cta { width: 100%; border: 0; cursor: pointer; font-family: inherit; }

/* --- Drift: faktureringsløpet -------------------------------------------
   Fire tilstander med hver sin ro. «Forfalt» er den eneste som skal fange
   blikket — resten er informasjon, ikke oppgaver. */
.dr-faktura {
  display: flex; flex-wrap: wrap; gap: 14px;
  align-items: flex-end; justify-content: space-between;
  margin: 0 0 14px; padding: 13px 16px; border-radius: 9px;
  background: var(--surface-3, #EDF0F4);
}
.dr-faktura--bestilt { background: var(--surface-2, #EEF3FE); }
.dr-faktura--forfalt { background: #FBF2E2; box-shadow: inset 3px 0 0 #8A5A00; }
.dr-faktura--betalt  { background: var(--surface-3, #EDF0F4); opacity: .75; }
.dr-faktura-tekst { min-width: 0; flex: 1 1 240px; }
.dr-faktura-tittel { margin: 0; font: 600 14px/1.4 var(--font-sans); color: var(--ink, #111827); }
.dr-faktura--forfalt .dr-faktura-tittel { color: #8A5A00; }
.dr-faktura-sub { margin: 4px 0 0; font: 400 13px/1.5 var(--font-sans); color: var(--ink-2, #4B5563); }
.dr-faktura-handling { display: flex; flex-wrap: wrap; gap: 9px; align-items: flex-end; }
.dr-faktura-handling .fld-label { margin-bottom: 3px; }
.dr-faktura-handling .fld-input { width: 158px; }

/* --- Drift-forsiden: faktureringskøen ------------------------------------
   Vises kun når det er noe å gjøre. En tom boks hver dag lærer øyet å hoppe
   over den, og da virker den ikke den dagen det står noe der. */
.dr-fakturako { margin-bottom: 20px; }
.dr-fakturako-tittel { margin: 0 0 9px; font: 600 13px/1 var(--font-sans); letter-spacing: .01em; color: var(--ink-2, #4B5563); }
.dr-fakturarad {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  padding: 11px 15px; margin-bottom: 6px; border-radius: 9px;
  background: var(--surface-2, #EEF3FE); text-decoration: none;
  transition: background-color 120ms ease;
}
.dr-fakturarad:hover { background: var(--brand-dempet, #C9DAFB); }
.dr-fakturarad--forfalt { background: #FBF2E2; box-shadow: inset 3px 0 0 #8A5A00; }
.dr-fakturarad--forfalt:hover { background: #F6E9CE; }
.dr-fakturarad-navn { font: 600 14px/1.4 var(--font-sans); color: var(--ink, #111827); }
.dr-fakturarad-hva { font: 400 13px/1.4 var(--font-sans); color: var(--ink-2, #4B5563); }
.dr-fakturarad--forfalt .dr-fakturarad-hva { color: #8A5A00; }

/* --- Drift → Prøveperioder ------------------------------------------------
   Samme form som «Krever handling» over, og med vilje: de to blokkene er det
   samme slaget beskjed — noen må gjøre noe, og ingenting skjer hvis lista ikke
   leses. To ulike utseender ville gjort dem til to ulike ting.

   Raden brekker som fakturaraden: navnet og fristen holder sammen på første
   linje, og aktivitetslinja faller ned under dem når bredden ikke strekker til.
   Det er derfor den samme markeringen leses både på 1280 px og på 375.

   Ingen animasjon utover fargeskiftet på hover — som resten av driftsflatene.
   Dette er et verktøy som åpnes hver morgen og leses på fem sekunder. */
.dr-prove { margin-bottom: 20px; }
.dr-prove-tittel { margin: 0 0 9px; font: 600 13px/1 var(--font-sans); letter-spacing: .01em; color: var(--ink-2, #4B5563); }
.dr-proverad {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  padding: 11px 15px; margin-bottom: 6px; border-radius: 9px;
  background: var(--surface-2, #EEF3FE); text-decoration: none;
  transition: background-color 120ms ease;
}
.dr-proverad:hover { background: var(--brand-dempet, #C9DAFB); }
/* Fem dager eller mindre, eller alt ute: den ene tilstanden som skiller «du
   bør se på dette i dag» fra «den løper». Samme gule som en forfalt faktura,
   fordi det er den samme hastegraden. */
.dr-proverad--haster { background: #FBF2E2; box-shadow: inset 3px 0 0 #8A5A00; }
.dr-proverad--haster:hover { background: #F6E9CE; }
.dr-proverad-navn { font: 600 14px/1.4 var(--font-sans); color: var(--ink, #111827); }
.dr-proverad-frist { font: 600 13px/1.4 var(--font-sans); color: var(--ink-2, #4B5563); }
.dr-proverad--haster .dr-proverad-frist { color: #8A5A00; }
/* Aktiviteten er den stille halvdelen: den leses først når fristen har fanget
   øyet, og skal aldri konkurrere med navnet. `flex-basis: 100%` under 560 px
   gir den sin egen linje i stedet for å la den brekke midt i et tall. */
.dr-proverad-akt { font: 400 13px/1.4 var(--font-sans); color: var(--ink-2, #4B5563); }
.dr-proverad-ja { font-weight: 600; color: var(--ok); }
/* Bare avstanden: typografien kommer fra .dr-note, som alle de andre
   fotnotene på flaten. To fotnoter som ser ulike ut ville vært to påstander
   om hvor viktige de er. */
.dr-prove-note { margin-top: 8px; }
@media (max-width: 560px) {
  .dr-proverad-akt { flex-basis: 100%; }
}

/* --- Drift → Prospekter --------------------------------------------------
   Radaren. Ett kort per status, én rad per firma. Ingen animasjoner, som på de
   andre driftssidene: dette er et verktøy som åpnes ofte og leses raskt.

   RADEN ER TRE SONER I FAST REKKEFØLGE: hvem det er, hvor langt brevet er
   kommet, og hva som skal gjøres. På en skjerm er det tre GRID-kolonner, og
   grunnen til at det er grid og ikke flex er hele poenget: en flex-rad legger
   statusen og knappene der det tilfeldigvis er plass etter navnet, så de
   flytter seg vannrett fra rad til rad. Med et rutenett begynner kolonne to og
   tre på samme x-verdi på hver eneste rad, og øyet kan skanne rett nedover en
   kolonne uten å lete.

   På telefonen faller de tre sonene under hverandre i samme rekkefølge — navn
   og fag, så status, så handling — fordi det er den rekkefølgen spørsmålene
   stilles i.

   Hva som ble kastet: sonen til høyre hadde vokst til fire avrundede bokser i
   samme størrelse og med samme ramme, der én av dem ikke engang var en knapp.
   Nå har raden høyst ÉN knapp med ramme, statusen er typografi, og
   vedlikeholdet er stille tekstknapper. */

/* Hentingen er sammenslått fordi den er sjelden. Utslått la de to skjemaene
   beslag på de første 430 pikslene av telefonskjermen — over filtrene og over
   den første raden — for to knapper som trykkes kanskje én gang i uka. Lukket
   er den én linje; åpen er den nøyaktig som før. */
.pr-hent {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.pr-hent-sum {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 20px; cursor: pointer;
  font: 500 12.5px/1.2 var(--font-sans); color: var(--ink-2);
  list-style: none;
  /* Uten denne står Safaris egen trekant utenpå vår egen chevron. */
  -webkit-tap-highlight-color: transparent;
}
.pr-hent-sum::-webkit-details-marker { display: none; }
.pr-hent-sum:hover,
.pr-hent-sum:active { color: var(--ink); }
.pr-hent-sum svg { width: 15px; height: 15px; color: var(--ink-3); flex: none; }
/* Trekanten vi tegner selv, så den peker rett vei i alle nettlesere. Ingen
   overgang: siden har ingen animasjoner, og et hjørne som svinger ville vært
   den første. */
.pr-hent-sum::after {
  content: ""; margin-left: auto;
  width: 7px; height: 7px; border-right: 1.5px solid var(--ink-3);
  border-bottom: 1.5px solid var(--ink-3); transform: rotate(45deg) translate(-2px, -2px);
}
.pr-hent[open] .pr-hent-sum::after { transform: rotate(-135deg) translate(-2px, -2px); }
.pr-hent[open] .pr-hent-sum { color: var(--ink); border-bottom: 1px solid var(--line-soft); }
.pr-hent-inn {
  display: flex; flex-wrap: wrap; gap: 12px 26px; align-items: flex-end;
  padding: 14px 20px;
}
.pr-hent-form { display: flex; flex-wrap: wrap; gap: 9px; align-items: flex-end; }
.pr-hent-form .fld-label { width: 100%; margin-bottom: 0; }
.pr-hent-select { width: auto; min-width: 168px; }
.pr-hent-note {
  align-self: center;
  font: 400 11.5px/1.5 var(--font-mono); color: var(--ink-3);
}

/* Utsendingen i fire tall, i sitt eget bånd mellom filtrene og lista. Mono og
   tabulære sifre (`.font-num` på tallet selv) av samme grunn som datoene ellers
   i huset: fire tall under hverandre i to nettlesere skal stå i samme kolonne.
   Ordene er sans, tallene mono — det er tallene som skal leses.

   Dempet et hakk fra det den var: dette er en fotnote til lista under, ikke et
   dashbord over den. Etikettene står i den lyseste tonen og bare tallene i
   husets tekstfarge, så linja leses som fire tall og ikke som fire påstander. */
.pr-tall {
  background: var(--surface);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px;
  padding: 9px 20px; border-bottom: 1px solid var(--line);
  font: 400 11.5px/1.6 var(--font-sans); color: var(--ink-3);
}
.pr-tall-post b { font-weight: 600; color: var(--ink-2); }

.pr-liste { display: flex; flex-direction: column; }

/* TRE KOLONNER, IKKE EN FLEX-KLYNGE. Kolonne to og tre har fast bredde nettopp
   for at de skal begynne på samme sted uansett hvor langt firmanavnet er:
   det er dét som gjør at lista kan skannes loddrett. `minmax(0, 1fr)` og ikke
   `1fr` på identiteten, ellers nekter et langt organisasjonsnummer å brekke og
   presser de to andre kolonnene ut av kortet. */
.pr-rad {
  display: grid;
  /* Breddene er MÅLT og ikke gjettet: 336 px er nøyaktig det den lengste
     tresteg-kjeden trenger for å stå på én linje, og 168 px det bredeste
     knappeparet i vedlikeholdet. Én piksel mindre og kjeden brekker på annen
     hver rad, som er akkurat den urolige kanten kolonnene skulle fjerne. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 336px) minmax(0, 168px);
  gap: 10px 16px; align-items: center;
  padding: 13px 18px; border-bottom: 1px solid var(--line-soft);
}
.pr-rad:last-child { border-bottom: 0; }
/* Bare på mus: på en telefon slår :hover inn ved berøring og blir hengende
   igjen på raden du nettopp forlot. */
@media (hover: hover) and (pointer: fine) {
  .pr-rad:hover { background: var(--row-tint); }
}
/* Hver sone får kolonnen sin OPPGITT og ikke tildelt av seg selv. En rad uten
   brev tegner ingen statussone i det hele tatt, og med automatisk plassering
   ville handlingen da glidd inn i kolonne to — altså landet et annet sted på
   akkurat de radene, som er nøyaktig det rutenettet er her for å hindre. */
.pr-hvem { grid-column: 1; }
.pr-status { grid-column: 2; }
.pr-handling { grid-column: 3; }

/* --- Sone 1: identiteten ------------------------------------------------- */
.pr-hvem { min-width: 0; }
.pr-navn { margin: 0; font: 600 14px/1.4 var(--font-sans); color: var(--ink); }
.pr-meta,
.pr-lenker {
  margin: 3px 0 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 7px;
  font: 400 12px/1.55 var(--font-sans); color: var(--ink-3);
}
/* Fag er det ene i metalinja Anders faktisk skanner etter, og det eneste som
   får husets vanlige tekstfarge. Organisasjonsform, nummer og dato er
   oppslagsverk han leser når han allerede har stoppet ved raden. */
.pr-fag { color: var(--ink-2); }
.pr-sep { color: var(--line-strong); }
.pr-lenke { color: var(--brand-ink); text-decoration: none; word-break: break-all; }
.pr-lenke:hover { text-decoration: underline; }
.pr-epost { font-family: var(--font-mono); font-size: 11.5px; word-break: break-all; }

/* Merknaden på et enkeltpersonforetak. Egen linje og ikke en badge: det er en
   setning om hva loven tillater, ikke en tilstand raden kan skifte mellom. */
.pr-enk {
  margin: 6px 0 0;
  font: 400 11.5px/1.5 var(--font-mono); color: var(--warn);
}

/* --- Sone 2: statuskjeden ------------------------------------------------
   «Sendt 20.08. → Åpnet — → Klikket 23.08.» Hele livsløpet til brevet på én
   linje, i stedet for den ene sterkeste merkelappen siden hadde før.

   Grunnen til at det er bedre: med ÉN merkelapp flyttet ordet seg fra rad til
   rad, og hver rad måtte staves før den kunne sammenlignes med naboen. Med tre
   faste steg er det STILLINGEN i kjeden som leses. Et steg som ikke har skjedd
   er en tankestrek, og en kolonne med tankestreker er et svar i seg selv.

   Mono for hele kjeden, ikke bare for tallene: her skal datoene stå rett under
   hverandre fra rad til rad, og en proporsjonal etikett foran dem ville dyttet
   dem ut av kolonne. `tabular-nums` i tillegg, fordi en mono-font som faller
   tilbake til en systemfont ellers mister nettopp det den var valgt for. */
.pr-status { min-width: 0; }
.pr-kjede {
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px;
  font: 400 11.5px/1.7 var(--font-mono); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
/* Pila og steget etter den er ett ledd, så en kjede som må brekke brekker
   FORAN en pil og aldri bak den. */
.pr-ledd { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.pr-steg { white-space: nowrap; color: var(--ink-2); }
/* Et steg som ikke har skjedd. Ett hakk lysere enn de andre og ikke tre: det
   er fortsatt en opplysning som skal kunne leses, ikke en skygge. Literal og
   ikke et tegn på paletten, som .dr-proverad-fargene over — huset har ingen
   tone mellom --ink-3 og --line-strong, og et nytt tegn på paletten for én
   tilstand på én side ville vært en ny sannhet å holde i to steder.
   4,8:1 på hvitt. */
.pr-steg.is-tom { color: #6B7280; }
.pr-pil { color: var(--line-strong); }

/* Åpnet er et livstegn: husets blå, ikke grønt — dette er ikke en suksess. */
.pr-steg.is-apnet { color: var(--brand-ink); }
/* KLIKKET ER DET STERKESTE VI VET, og det ene steget som får en flate under
   seg. Et klikk er en hånd; en åpning kan være et bildefilter i en innboks.
   Samme blå som åpnet, bare mer av den — en egen kulør ville sagt at det er
   noe ANNET som har skjedd, og det er det ikke. Flaten er liten og uten ramme,
   så den ikke kan forveksles med knappene i kolonnen ved siden av. */
.pr-steg.is-klikket {
  padding: 2px 7px; border-radius: 5px;
  background: var(--brand-06); color: var(--brand-ink); font-weight: 600;
}
/* «Fulgt opp» henger bakerst i kjeden fordi det er neste ting som skjedde i
   tid — men i den stilleste tonen: det er hva VI gjorde, ikke et livstegn fra
   firmaet, og det skal ikke ta oppmerksomhet fra «Klikket». */
.pr-steg.is-oppfolgt { color: var(--ink-3); }

/* --- Sone 3: handlingen --------------------------------------------------
   Høyst ÉN knapp med ramme, og den står alltid i samme spor. Sporet tegnes
   ikke i det hele tatt når raden ikke har et førstevalg (`har_forstevalg` i
   viewet) — et tomt spor med reservert høyde ville lagt en luftlomme i hver
   ENK-rad på telefonen, og fraværet av en knapp er allerede tydelig nok.

   Høyrestilt på en skjerm: da deler førstevalget og vedlikeholdet én loddrett
   kant helt ned gjennom lista, og det er den kanten øyet følger når det leter
   etter «hvilken rad venter på meg». */
.pr-handling {
  min-width: 0;
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
}
.pr-handling form { margin: 0; }
.pr-forst { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.pr-forst .qb-btn { min-height: 34px; font-size: 12.5px; }

/* Vedlikeholdet: samme handlinger som før, samme betingelser, men uten ramme.
   «Send på nytt» er for spesialtilfellene og de to statusknappene er
   journalføring — ingen av dem skal kunne forveksles med førstevalget når øyet
   faller nedover kolonnen. Flaten kommer først på hover, så de er stille i ro
   og likevel synlig trykkbare.

   Tonen er husets egen tredje handling, .qb-more: --ink-2 og vekt 500, ikke
   den lyse metadata-tonen. En handling skal lese seg STERKERE enn
   opplysningene over den, ellers ser den ut som nok en linje med tekst — og
   det er den ene tvetydigheten en knapp uten ramme faktisk risikerer. */
.pr-mer {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: flex-end; gap: 2px 4px;
  /* Polstringen på tekstknappen er treffflate og ikke innrykk. Uten dette
     står den siste etiketten seks piksler innenfor knappekanten over. */
  margin-right: -6px;
}
.pr-mer-btn {
  display: inline-flex; align-items: center;
  min-height: 28px; padding: 0 6px; border: 0; border-radius: 5px;
  background: none; color: var(--ink-2);
  font: 500 12px/1.2 var(--font-sans);
  text-decoration: none; cursor: pointer; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: color 130ms ease, background-color 130ms ease;
}
.pr-mer-btn:hover { background: var(--row-tint); color: var(--ink); }
/* Trykk-respons. Siden har ingen animasjoner og skal ikke ha noen, men en
   knapp som ikke svarer på fingeren kjennes ødelagt — dette er det ene stedet
   bevegelse gjør en jobb i stedet for å være pynt. Kort nok til at den er over
   før den registreres som en overgang. */
.pr-mer-btn:active { transform: scale(0.97); }
.pr-rad .qb-btn { transition: border-color 130ms ease, background-color 130ms ease, transform 130ms ease; }
.pr-rad .qb-btn:active { transform: scale(0.97); }
@media (prefers-reduced-motion: reduce) {
  .pr-mer-btn:active,
  .pr-rad .qb-btn:active { transform: none; }
}

/* «Følg opp» når brevet har ligget i fire døgn uten at noen har åpnet det eller
   trykket i det. Den skal fanges opp når øyet skanner en kolonne med like
   knapper — og ikke mer enn det.

   Derfor er den IKKE `.qb-btn-primary`: den fylte blå er sidens ene viktigste
   handling, og tjue av dem nedover en liste ville gjort alle sammen like
   uviktige. Dette er husets rolige måte i stedet — den svakeste blå flaten,
   husets egen ramme rundt, og teksten i merkefargen. Ingen animasjon, ingen
   puls: siden har ingen animasjoner, og en knapp som beveger seg for å bli sett
   ville vært den første. */
.qb-btn.is-moden {
  border-color: var(--brand-30); background: var(--brand-03);
  color: var(--brand-ink); font-weight: 600;
}
.qb-btn.is-moden:hover { border-color: var(--brand); background: var(--brand-06); }

/* Statusflokken i korthodet. Den ene tonen som manglet i badge-familien. */
.badge-warn { background: var(--warn-bg); color: var(--warn); }

/* Mellombredder: rundt 900 px har ikke identiteten plass igjen til et helt
   firmanavn ved siden av to fulle kolonner. Statusen legger seg da under
   navnet, i kolonne én, mens handlingen blir stående i sin egen kolonne til
   høyre — spørsmålet «hva gjør jeg nå» beholder altså plassen sin helt til
   telefonen, og det er det viktigste av de to å kunne treffe med øyet.
   `grid-row: 1` og ikke et spenn: handlingen skal stå på linje med navnet, og
   et spenn ned i en rad som ikke finnes på alle rader ville gitt ujevn høyde. */
@media (max-width: 1080px) and (min-width: 641px) {
  .pr-rad { grid-template-columns: minmax(0, 1fr) minmax(0, 168px); align-items: start; }
  .pr-hvem { grid-column: 1; }
  .pr-status { grid-column: 1; }
  .pr-handling { grid-column: 2; grid-row: 1; }
}

@media (max-width: 640px) {
  /* TELEFONEN ER HOVEDFLATEN, og der faller de tre sonene under hverandre i
     den rekkefølgen spørsmålene stilles: hvem er det, hvor langt er brevet
     kommet, hva gjør jeg nå. Ett rutenett med én kolonne og ikke flex, så
     rekkefølgen er den samme som i markeringen og ikke noe som må styres med
     `order`. */
  .pr-rad {
    grid-template-columns: minmax(0, 1fr);
    gap: 9px; padding: 13px 16px;
  }
  /* Kolonnetildelingen fra skjermen MÅ nullstilles her. Et element som er
     bedt om å stå i kolonne 3 lager en kolonne 3 selv om rutenettet bare har
     én — og da ble raden tre trange spalter på 375 px i stedet for én stabel.
     (Radene ble 568 px høye før dette sto her.) */
  .pr-hvem,
  .pr-status,
  .pr-handling { grid-column: 1; }
  /* Ett hakk mindre på begge de stille linjene, og det er ikke innsparing for
     innsparingens skyld: på 311 px tilgjengelig brakk «Elektriker · ENK ·
     912345604 · registrert 16.08.2026» midt i seg selv og ble to linjer på hver
     eneste rad i «Ny». Én linje som kan skummes slår to som må leses. */
  .pr-meta,
  .pr-lenker { font-size: 11.5px; }
  /* Samme regnestykke for kjeden: den lengste tresteg-kjeden er 336 px i
     skjermstørrelsen, og de siste pikslene måtte hentes her for at
     «Sendt → Åpnet → Klikket» skal stå på ÉN linje på en telefon. En kjede som
     brekker på annen hver rad er ikke en kjede, det er en stabel. */
  .pr-kjede { font-size: 11px; gap: 2px 5px; }
  .pr-ledd { gap: 5px; }
  .pr-steg.is-klikket { padding: 2px 5px; }
  /* Førstevalget beholder rammen sin, men ikke hele bredden. En kolonne med
     fem knapper i full bredde nedover skjermen gjør alle fem like viktige —
     og da er vi tilbake der vi startet. Kompakt og venstrestilt: forskjellen
     mellom førstevalget og vedlikeholdet er formen, ikke størrelsen.

     Én handlingslinje og ikke to. Med en kompakt knapp får «Følg opp | Send på
     nytt  Ikke aktuell» plass på samme linje, og det er 42 piksler spart på
     hver eneste rad i «Kontaktet» — den gruppa som er lengst. Linja brekker av
     seg selv der den ikke får plass (en «Skriv e-post» med ikon er bredere),
     og da er den akkurat som den var. */
  .pr-handling {
    flex-direction: row; flex-wrap: wrap;
    align-items: center; justify-content: flex-start; gap: 4px 8px;
  }
  .pr-forst { justify-content: flex-start; }
  .pr-forst .qb-btn { min-height: 40px; padding: 0 18px; font-size: 13px; }
  .pr-mer { justify-content: flex-start; margin-right: 0; }
  .pr-mer-btn { min-height: 36px; padding: 0 8px; }
  /* Første stille knapp på linje med teksten over, ikke et halvt tegn inn i
     rommet: polstringen er der bare for treffflaten. */
  .pr-mer { margin-left: -8px; }
  .pr-hent-sum { padding: 12px 16px; }
  .pr-hent-inn { flex-direction: column; align-items: stretch; padding: 12px 16px 14px; }
  /* Kolonne, ikke bare «stretch»: i en rad strekker align-items høyden, ikke
     bredden, så «Hent»-knappen ble stående smal ved siden av et fullbredt
     nedtrekk. Én ting per linje er dessuten lettere å treffe med tommelen. */
  .pr-hent-form { flex-direction: column; align-items: stretch; gap: 7px; }
  .pr-hent-select { width: 100%; min-width: 0; }
  .pr-hent-note { align-self: flex-start; }
  /* På en telefon rekker ikke fire tall bortover, og en linje som brekker
     tilfeldig ville etterlatt en skilleprikk alene i starten av en linje. To og
     to i stedet, i et rutenett — og da er prikkene overflødige: de skiller noe
     som allerede står hver for seg. `display: none` og ikke `visibility`,
     nettopp for at de ikke skal legge beslag på en rute. */
  .pr-tall {
    display: grid; grid-template-columns: repeat(2, auto);
    justify-content: start; gap: 3px 18px; padding: 10px 16px;
  }
  .pr-tall .pr-sep { display: none; }
}

/* «Ikke aktuell»-gruppen: primærknappen dempes til omriss — sidens
   sterkeste knapp skal ikke stå i gruppen som betyr «disse har takket
   nei». Betingelsen for NÅR knappen finnes er uendret (drift.py). */
.pr-gruppe-dempet .pr-rad .qb-btn {
  background: transparent;
  color: var(--brand);
  border: 1px solid var(--line);
}
