@charset "UTF-8";
/* ==========================================================================
   design-system.css — GMP design system (v1, session 58)
   --------------------------------------------------------------------------
   The single source of truth for the app UI look: a token layer (:root custom
   properties) + a namespaced, reusable component vocabulary (.gmp-*).

   DESIGN RULES (see docs / memory: project_design_system):
   • Loads GLOBALLY (gmp_artist_adding_styles) alongside gmp_artist.css, so it
     must stay SAFE on the marketing landing pages too. Therefore:
       – Components are CLASS-SCOPED (.gmp-*) — they paint only opted-in nodes.
       – The only element/library overrides (DataTables) are scoped under the
         .gmp-app page wrapper, never global.
       – :root only DEFINES tokens; it paints nothing.
   • This file is the modern base. gmp_artist.css is migrated INTO it
     incrementally (legacy bespoke rules removed as each is replaced), so the
     old file shrinks over time. Do not grow gmp_artist.css.
   • Living catalogue / migration map: the v1 style-tile artifact.
   ========================================================================== */

/* ── Tokens ──────────────────────────────────────────────────────────────── */
:root {
  --ground:        #ffffff;
  --surface:       #f5f7f8;
  --surface-2:     #eaeff0;
  --border:        #dbe3e4;
  --border-strong: #c4d0d2;
  --ink:           #17262c;
  --ink-muted:     #57676c;
  --ink-faint:     #8a979b;

  --accent:        #0b7a86;
  --accent-strong: #095e67;
  --accent-tint:   #e2f1f2;
  --accent-ink:    #ffffff;

  --ok-ink:  #1f6b43; --ok-bg:  #e6f3ec; --ok-bd:  #b6dcc6;
  --warn-ink:#8a5a12; --warn-bg:#fbf0da; --warn-bd:#ecd3a3;
  --bad-ink: #a5322f; --bad-bg: #fbe7e6; --bad-bd: #eab7b5;
  --info-ink:#235d94; --info-bg:#e5eef8; --info-bd:#bad1ea;

  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  /* Absolute px, NOT rem — the app must render at a predictable size regardless of the
     theme's root font-size. Genesis uses `html{font-size:62.5%}` (10px root), which made
     rem-based tokens resolve to ~62.5% (a 16px input rendered at 10px). px decouples us
     from the host theme root. (Trade-off: the app no longer scales with the browser's
     default-font-size setting; acceptable for a dense back-office tool. Zoom still works.) */
  --fs-12: 12px; --fs-13: 13px; --fs-14: 14px; --fs-15: 15px;
  --fs-16: 16px; --fs-17: 17px; --fs-19: 19px; --fs-24: 24px; --fs-31: 31px;

  /* Semantic type tokens — components read THESE, not the raw scale, so a
     readability tweak is a one-line change here. (s58: bumped a notch.) */
  --fs-body:  var(--fs-15);
  --fs-table: var(--fs-14);   /* table body rows — "Standard" tier (user, s58) */
  --fs-th:    var(--fs-12);   /* table header (uppercase) */
  --fs-input: var(--fs-15);   /* form inputs/selects */
  --fs-label: var(--fs-13);   /* field labels */

  --r-sm: 4px; --r: 7px; --r-lg: 11px;
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 36px;
  --shadow-1: 0 1px 2px rgba(23,38,44,.06), 0 1px 1px rgba(23,38,44,.04);
  --shadow-2: 0 4px 14px rgba(23,38,44,.10), 0 1px 3px rgba(23,38,44,.06);
  --ring: 0 0 0 3px rgba(11,122,134,.28);
  /* s103 — the modal (.gmp-modal): a lifted surface and the scrim behind it. */
  --shadow-3: 0 18px 48px rgba(23,38,44,.22), 0 2px 6px rgba(23,38,44,.10);
  --scrim: rgba(23,38,44,.45);
}

/* Dark theme — token-level. OS preference by default; a future explicit
   [data-theme] toggle can override (same pattern as the style tile). */
@media (prefers-color-scheme: dark) {
  :root {
    --ground:#0e1618; --surface:#15201f; --surface-2:#1d2b2b;
    --border:#293a3a; --border-strong:#3a4e4e;
    --ink:#e7eeee; --ink-muted:#a1b1b2; --ink-faint:#6f8283;
    --accent:#37b6c1; --accent-strong:#5ecad2; --accent-tint:#11302f; --accent-ink:#06201f;
    --ok-ink:#7fd6a4; --ok-bg:#12271c; --ok-bd:#2c4d3a;
    --warn-ink:#e6bd77; --warn-bg:#2a2110; --warn-bd:#54421e;
    --bad-ink:#eda6a3; --bad-bg:#2a1615; --bad-bd:#573231;
    --info-ink:#9cc2ea; --info-bg:#131f2c; --info-bd:#2b415a;
    --shadow-1: 0 1px 2px rgba(0,0,0,.4);
    --shadow-2: 0 6px 18px rgba(0,0,0,.5);
    --ring: 0 0 0 3px rgba(55,182,193,.34);
    --scrim:rgba(0,0,0,.62);
  }
}
:root[data-theme="light"] {
  --ground:#ffffff; --surface:#f5f7f8; --surface-2:#eaeff0; --border:#dbe3e4; --border-strong:#c4d0d2;
  --ink:#17262c; --ink-muted:#57676c; --ink-faint:#8a979b;
  --accent:#0b7a86; --accent-strong:#095e67; --accent-tint:#e2f1f2; --accent-ink:#ffffff;
  --ok-ink:#1f6b43; --ok-bg:#e6f3ec; --ok-bd:#b6dcc6;
  --warn-ink:#8a5a12; --warn-bg:#fbf0da; --warn-bd:#ecd3a3;
  --bad-ink:#a5322f; --bad-bg:#fbe7e6; --bad-bd:#eab7b5;
  --info-ink:#235d94; --info-bg:#e5eef8; --info-bd:#bad1ea;
  --scrim:rgba(23,38,44,.45);
}
:root[data-theme="dark"] {
  --ground:#0e1618; --surface:#15201f; --surface-2:#1d2b2b; --border:#293a3a; --border-strong:#3a4e4e;
  --ink:#e7eeee; --ink-muted:#a1b1b2; --ink-faint:#6f8283;
  --accent:#37b6c1; --accent-strong:#5ecad2; --accent-tint:#11302f; --accent-ink:#06201f;
  --ok-ink:#7fd6a4; --ok-bg:#12271c; --ok-bd:#2c4d3a;
  --warn-ink:#e6bd77; --warn-bg:#2a2110; --warn-bd:#54421e;
  --bad-ink:#eda6a3; --bad-bg:#2a1615; --bad-bd:#573231;
  --info-ink:#9cc2ea; --info-bg:#131f2c; --info-bd:#2b415a;
  --scrim:rgba(0,0,0,.62);
}

/* ── App page wrapper ────────────────────────────────────────────────────────
   Put .gmp-app on a code-owned page's root container. It sets the app type
   baseline and is the scope under which DataTables is themed. Never applied to
   theme/landing markup. */
.gmp-app { font-family: var(--font-sans); color: var(--ink); font-size: var(--fs-body); line-height: 1.5; -webkit-font-smoothing: antialiased; }
/* font-family is NOT redundant with .gmp-app's: the theme styles headings DIRECTLY (Quicksand), and a rule on the
   element beats an inherited face (s101 walk — begar-tillgang's confirmation h3/h4; same lesson as .gmp-listsection__title). */
.gmp-app :where(h1,h2,h3,h4) { font-family: var(--font-sans); font-weight: 650; color: var(--ink); text-wrap: balance; line-height: 1.2; }
.gmp-app h3 { font-size: var(--fs-24); letter-spacing: -.015em; margin: 0 0 var(--sp-3); }
.gmp-app h4 { font-size: var(--fs-16); margin: 0 0 var(--sp-2); }
.gmp-app > p { max-width: 68ch; color: var(--ink-muted); }
.gmp-app a:not(.gmp-btn) { color: var(--accent); }   /* s138 (F-17): a link styled as a button keeps the button's colours */

/* ── App page header (Genesis theme chrome) ──────────────────────────────────
   The WP/Genesis page header (.entry-header/.entry-title, e.g. "Mina Fakturor")
   sits OUTSIDE .gmp-app — it's theme markup above our shortcode content, rendered
   on every page — so we can't reach it with a normal .gmp-app-scoped rule, and we
   must NOT restyle it on marketing/landing pages. The `:has()` gate solves both:
   `body:has(.gmp-app, .gmp-gform_wrapper)` matches ONLY pages that contain our app
   content (never a landing page), so this default parallax-pro title (Quicksand
   48px, centred, black) is re-cast as a clean CENTRED admin page header (token font/
   size/colour) on app pages alone. (Scoped-exception, like the intl-tel-input global rules.)

   s84: `body.gmp-app-page` joins the two `:has()` gates and is the better of the three. The `:has()`
   pair was a workaround for having no body class — it asks "does this page CONTAIN app markup?", which
   silently misses an app page that happens to use neither wrapper. `styrelse-och-funktionarer` is
   exactly that: its DataTable sits straight in `.entry-content` and its form wrapper is GF's own, so the
   recast never applied and the page kept the theme's 48px Quicksand. The class asks the right question
   instead — "is this a page the client's role/access matrix governs?" — which is what an application
   page IS (wpgmp_main/system-menu.php). The `:has()` gates stay as a safety net for app content on a
   page the matrix does not govern.

   🔴 O-4 (s99): AND THAT SAFETY NET BECAME A LEAK THE MOMENT CLIENT CONTENT EXISTED. "App content on a
   page the matrix does not govern" is now the DEFINITION of a client content page (D-8) — so a förening
   embedding a Gravity Form on its own page inherited the whole application chrome.
   ⚠ The obvious repair — drop the `:has()` pair and keep only `body.gmp-app-page` — is wrong, because
   `register` and `begar-tillgang` are application pages carrying GF forms with **no matrix row**
   (measured on client1, s99) and they are the two surfaces a STRANGER sees.
   ⚠ To be exact about today: those two would lose nothing *right now*, because their forms are not yet
   skinned — `register`'s wrapper carries `gform_wrapper` but not `gmp-gform_wrapper`, so the net never
   reached it. The net is kept for when they ARE skinned, which is the gf-skin rollout's own plan. The
   leak it must not reopen is the client's lane, hence `body:not(.gmp-client-page)`. */
body.gmp-app-page .entry-header,
body:not(.gmp-client-page):has(.gmp-app) .entry-header,
body:not(.gmp-client-page):has(.gmp-gform_wrapper) .entry-header {
  text-align: center; margin: 0 0 var(--sp-4); padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
}
body.gmp-app-page .entry-title,
body:not(.gmp-client-page):has(.gmp-app) .entry-title,
body:not(.gmp-client-page):has(.gmp-gform_wrapper) .entry-title {
  font-family: var(--font-sans); font-size: var(--fs-31); font-weight: 650;
  color: var(--ink); letter-spacing: -.02em; text-align: center; margin: 0;
}

/* The theme reserves 170px above the content for its own site header — which we hide on application
   pages, so the page opened with a screenful of nothing before the title. Reclaim it: the system bar is
   the top of the page now. (Left alone on any page that still shows the theme header.) */
body.gmp-app-page .site-inner { margin-top: var(--sp-5); }

/* Genesis draws a decorative rule under the title on this theme; the header's own border is the house
   separator, and two lines under one heading is one too many. */
body.gmp-app-page .entry-header::after,
body.gmp-app-page .entry-title::after { display: none; }

/* ── Panel / card ────────────────────────────────────────────────────────── */
.gmp-panel { background: var(--ground); border: 1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--shadow-1); }
.gmp-panel--sub { background: var(--surface); box-shadow: none; }
/* s126: a small form inside a panel — its fields and toolbar stacked with the house gap (generic; first use: konteringsregler's rule request) */
.gmp-stack { display: flex; flex-direction: column; gap: var(--sp-3); }
/* s126: a page's sections, one after another with the house gap (generic; first use: konteringsregler — KR-3, a panel met the next heading) */
.gmp-section + .gmp-section { margin-top: var(--sp-6); }
/* s126 (momsintyg-underlag, the walk MI-1): a voucher's edit on one wrapping line — the figure, the note, Spara — not stacked */
.gmp-mi__edit { min-width: 180px; }
.gmp-mi__line { display: flex; align-items: center; gap: 6px; }
.gmp-mi__line .mi-stated { flex: 0 0 88px; width: 88px; }
.gmp-mi__edit .mi-note { display: block; width: 100%; margin-top: 4px; font-size: var(--fs-13); padding: 4px 8px; }   /* under the figure, the cell's full width — inline it widened the table past the page */
.gmp-mi__line .mi-save { flex: 0 0 auto; }
/* s131 (BS-12): the GrullCo page `inbetalningar` — one line per payment, its state beside it */
.gmp-ip__grid .ip-ref { width: 190px; }
.gmp-ip__grid .ip-amount { width: 110px; }
.gmp-ip__grid .ip-date { width: 150px; }
.gmp-ip__grid .ip-state { font-size: var(--fs-13); line-height: 1.35; min-width: 280px; }
.gmp-ip__grid .ip-state:empty::before { content: '—'; color: var(--ink-faint); }
.gmp-ip__grid tr.is-full .ip-state, .gmp-ip__grid tr.is-found .ip-state { color: var(--ok-ink); }
.gmp-ip__grid tr.is-partial .ip-state, .gmp-ip__grid tr.is-over .ip-state, .gmp-ip__grid tr.is-double .ip-state { color: var(--warn-ink); }
.gmp-ip__grid tr.is-none .ip-state, .gmp-ip__grid tr.is-refused .ip-state, .gmp-ip__grid tr.is-failed .ip-state { color: var(--bad-ink); }
.gmp-ip__grid tr.is-done td { background: var(--ok-bg); }
.gmp-ip__grid tr.is-done input { pointer-events: none; }
.gmp-ip__grid .ip-dup { display: block; margin-top: 4px; font-weight: 600; }
.gmp-ip__actions { margin-top: var(--sp-3); gap: var(--sp-3); align-items: center; }
.gmp-mi__edit .mi-src, .gmp-mi__edit .mi-msg { display: block; margin-top: 2px; font-size: var(--fs-12); }
.gmp-mi__edit .mi-msg:empty { display: none; }
.gmp-mi__vouchers tr.is-missing .mi-shadow { color: var(--ink-faint); }
.gmp-mi__sum { font-variant-numeric: tabular-nums; }
.gmp-mi__vouchers td a { display: inline-block; white-space: nowrap; }   /* a document link never breaks mid-label ("Faktura 113 · / 1") */
.gmp-app.gmp-mi table.gmp-mi__vouchers th, .gmp-app.gmp-mi table.gmp-mi__vouchers th.dt-right { white-space: normal; }   /* nine columns: a two-word header may take two lines rather than widen the table past the page */
.gmp-panel__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.gmp-panel__head h4 { margin: 0; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
/* Buttons are UPPERCASE by house style (user, s58) — reads more robust/authoritative.
   Owned here explicitly (not left to the theme) so it holds regardless of host CSS. */
/* font-family explicit (NOT `font:inherit`) — .gmp-btn is used outside .gmp-app/.gmp-gform_wrapper
   too (e.g. the top New/Cancel buttons from initpage), where inherit would pull the THEME serif. */
.gmp-btn { font-family: var(--font-sans); font-weight: 600; font-size: var(--fs-13); line-height: 1; text-transform: uppercase; letter-spacing: .035em; cursor: pointer; border-radius: var(--r); padding: 9px 15px; border: 1px solid transparent; display: inline-flex; align-items: center; gap: 7px; text-decoration: none; transition: background .14s ease, border-color .14s ease, transform .05s ease; }
.gmp-btn:active { transform: translateY(1px); }
.gmp-btn:focus-visible { outline: none; box-shadow: var(--ring); }
/* 🔴 s119 (form 42 walk, gmpAudit) — THE THEME OUTLINES EVERY BUTTON AFTER A MOUSE CLICK. The Genesis child
   theme carries a bare `:focus { outline: #ccc solid 1px }`. `:focus-visible` above does NOT match a mouse
   click on a button, so the rule above never fires for the commonest interaction and the theme's grey
   rectangle is left sitting around the button until focus moves. App-wide, on every `.gmp-btn`.
   Same authority as s108's `.gmp-modal { outline-color }` — the theme's #ccc reaching our components —
   but answered at the interaction instead of the colour: a pointer user gets no outline at all, and the
   keyboard user still gets the ring above, which is the outcome `:focus-visible` exists to produce. */
.gmp-btn:focus:not(:focus-visible) { outline: none; }
/* s123 (entity walk, gmpAudit 1 on form 3) — THE THEME PAINTS A FOCUSED BUTTON TEAL. parallax-pro's `button:focus
   { background:#00a0af; color:#fff }` (0,1,1) beats every variant below (0,1,0) the moment a button HOLDS focus — which a
   GmpModal guarantees, returning focus to the button that opened it. Each variant restates its own face on :focus (0,2,0),
   placed BEFORE its :hover so hover still wins on equal specificity. Generic: every .gmp-btn, no id, no !important. */
.gmp-btn--primary { background: var(--accent); color: var(--accent-ink); }
.gmp-btn--primary:focus { background: var(--accent); color: var(--accent-ink); }
.gmp-btn--primary:hover { background: var(--accent-strong); color: var(--accent-ink); }
.gmp-btn--secondary { background: var(--surface); color: var(--ink); border-color: var(--border-strong); }
.gmp-btn--secondary:focus { background: var(--surface); color: var(--ink); }
.gmp-btn--secondary:hover { background: var(--surface-2); color: var(--ink); }
.gmp-btn--ghost { background: transparent; color: var(--accent); }
.gmp-btn--ghost:focus { background: transparent; color: var(--accent); }
.gmp-btn--ghost:hover { background: var(--accent-tint); color: var(--accent-strong); }
/* A button that is a TOGGLE rather than a one-shot action (s119, register row 43). The role class says
   what it WOULD do; `aria-pressed` says whether that mode is currently ON, and the accent tint is the
   design system's existing "this is the active thing" signal (.gmp-tab.is-active, .gmp-btn--ghost:hover).
   🔑 Keyed on the ARIA state, not a `.is-on` class, so the mode is announced to a screen reader as well as
   painted — a toggle whose only tell is its colour is not a control everybody can use. Out-specifies every
   role class (0,0,2,0 vs 0,0,1,0); the :hover variant is there so the footer's own :hover cannot win it back. */
.gmp-btn[aria-pressed="true"] { background: var(--accent-tint); color: var(--accent-strong); border-color: var(--accent); }
.gmp-btn[aria-pressed="true"]:hover { background: var(--accent-tint); color: var(--accent-strong); }
.gmp-btn--danger { background: transparent; color: var(--bad-ink); border-color: var(--bad-bd); }
.gmp-btn--danger:hover { background: var(--bad-bg); color: var(--bad-ink); }
.gmp-btn--sm { padding: 5px 10px; font-size: var(--fs-12); }
.gmp-btn[disabled] { opacity: .5; cursor: not-allowed; }

/* ── Inline code + file input, inside the app only (s82) ─────────────────────
   Both are ELEMENT-level, so they are scoped under `.gmp-app` per the rules at
   the top of this file — never global, because this stylesheet also loads on the
   marketing pages. The theme styles <code> as inverted dark-on-light, which reads
   as a callout rather than as "the literal text of a column heading". */
.gmp-app code { font-family: var(--font-mono); font-size: .92em; background: var(--surface-2); color: var(--ink); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 1px 5px; }
/* File picker — deliberately MATCHED to the Gravity Perks "File Upload Pro" widget further down this
   file (`.gpfup__select-files-container > button`), so the two upload affordances in the app look like one
   control (user, s82). Same font/size/weight/uppercase/padding/border/hover.

   The native `::file-selector-button` cannot be RELABELLED — the browser supplies "Choose File" in its own
   locale — so the real input is visually hidden inside a <label> and a span carries the Swedish text. The
   input stays in the DOM and keeps working: clicking the label activates it, and it is still focusable, so
   this is a relabel, not a re-implementation. */
.gmp-app .gmp-filepick, .gmp-modal .gmp-filepick { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; }
.gmp-app .gmp-filepick input[type="file"], .gmp-modal .gmp-filepick input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.gmp-app .gmp-filepick__btn, .gmp-modal .gmp-filepick__btn { font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; text-transform: uppercase; letter-spacing: .035em; line-height: 1; background: var(--surface); color: var(--ink); border: 1px solid var(--border-strong); border-radius: var(--r); padding: 9px 15px; }
.gmp-app .gmp-filepick:hover .gmp-filepick__btn, .gmp-modal .gmp-filepick:hover .gmp-filepick__btn { background: var(--surface-2); }
.gmp-app .gmp-filepick input[type="file"]:focus-visible + .gmp-filepick__btn, .gmp-modal .gmp-filepick input[type="file"]:focus-visible + .gmp-filepick__btn { outline: none; box-shadow: var(--ring); }
.gmp-app .gmp-filepick__name, .gmp-modal .gmp-filepick__name { font-size: var(--fs-13); color: var(--ink-faint); }
.gmp-app .gmp-filepick__name.has-file, .gmp-modal .gmp-filepick__name.has-file { color: var(--ink); }

/* ── Counted outcomes (s82) ──────────────────────────────────────────────────
   "Here is what will happen": a handful of counts a reviewer reads before
   approving. This was a wrapping flex row and it re-broke at a different place
   for every result — the numbers moved around the panel depending on how long
   the labels happened to be (user, s82). A table holds its shape, and the
   numerals form one column the eye can run down. */
.gmp-app table.gmp-table.gmp-countlist { width: auto; }
.gmp-app table.gmp-table.gmp-countlist td { border-top: none; padding: 3px 0; line-height: 1.35; }
.gmp-app table.gmp-table.gmp-countlist td.gmp-countlist__n { text-align: right; font-variant-numeric: tabular-nums; font-size: var(--fs-19); font-weight: 650; color: var(--accent); padding-right: var(--sp-3); width: 1%; white-space: nowrap; }
.gmp-app table.gmp-table.gmp-countlist tr.is-zero td.gmp-countlist__n { color: var(--ink-faint); }
.gmp-app table.gmp-table.gmp-countlist tr.is-zero td { color: var(--ink-faint); }

/* ── Tabs / segmented control (s82) ──────────────────────────────────────────
   Two or three mutually-exclusive views of ONE thing — the board roster's
   "a list" vs "one person", both feeding the same pipeline. Added here rather
   than as a bespoke `.brp-tab` because it is a general shape, and CLAUDE.md
   forbids growing per-page selectors when a modular one will do.

   A <button> per tab (not an <a>): it changes what is shown, it does not
   navigate, and a keyboard user should get the button semantics. The caller
   sets `aria-selected` alongside `.is-active` so the state is announced, not
   only painted. */
.gmp-tabs { display: inline-flex; gap: 2px; padding: 3px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r); }
.gmp-tab { font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; line-height: 1; cursor: pointer; border: 1px solid transparent; border-radius: var(--r-sm); padding: 8px 14px; background: transparent; color: var(--ink-muted); transition: background .14s ease, color .14s ease; }
.gmp-tab:hover { color: var(--ink); }
.gmp-tab:focus-visible { outline: none; box-shadow: var(--ring); }
.gmp-tab.is-active { background: var(--ground); color: var(--ink); border-color: var(--border); box-shadow: var(--shadow-1); }
/* s108: a tab that IS an address (the ledger's Verifikationer / Huvudbok views) is an <a> with aria-current="page";
   it must look exactly like the button form, so the anchor's own underline and colour are taken back. */
a.gmp-tab, a.gmp-tab:visited { display: inline-flex; align-items: center; text-decoration: none; color: var(--ink-muted); box-shadow: none; }
a.gmp-tab:hover { color: var(--ink); text-decoration: none; }
a.gmp-tab.is-active { color: var(--ink); box-shadow: var(--shadow-1); }


/* ── Form fields ─────────────────────────────────────────────────────────── */
.gmp-field { display: flex; flex-direction: column; gap: 5px; }
.gmp-field[hidden] { display: none; }   /* s107: `display:flex` above outranks the UA's [hidden] — a field the server has not asked for yet stays out */
.gmp-field > span, .gmp-field > label > span, .gmp-label { font-size: var(--fs-label); font-weight: 600; color: var(--ink-muted); }
/* s122 (F4): present for scripts and the save, absent to the eye — the supplier-invoice Status code, shown as a chip beside it */
.gmp-visually-hidden, .gmp-gform_wrapper .ginput_container input.gmp-visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* s122 (F12): a required field's * — the same colour as the skinned GF forms' .gfield_required, so the two doors read alike */
.gmp-field .gmp-field__req { color: var(--bad-ink); }
.gmp-input, .gmp-select { font: inherit; font-size: var(--fs-input); color: var(--ink); background: var(--ground); border: 1px solid var(--border-strong); border-radius: var(--r); padding: 8px 11px; width: 100%; transition: border-color .14s ease, box-shadow .14s ease; }
.gmp-input:focus, .gmp-select:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.gmp-input:disabled, .gmp-select:disabled { background: var(--surface-2); color: var(--ink-faint); }
/* s124: READ-ONLY is not disabled — the value is decided elsewhere (e.g. an invoice row's account, VAT and cost centre come
   from the article) but it is a real value the person must be able to read: muted surface, full-strength-enough ink. */
.gmp-input[readonly] { background: var(--surface-2); color: var(--ink-muted); cursor: default; }
.gmp-input--num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
.gmp-input--short { width: 96px; }   /* s125: a number of a few characters (a percent) — not a full-width field */
/* s125: a lone checkbox OUTSIDE a Gravity Form, as a bordered row (the non-GF twin of .gmp-gform-checkrow) */
.gmp-checkrow { display: flex; align-items: center; gap: 11px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface); font-weight: 600; font-size: var(--fs-14); color: var(--ink); cursor: pointer; margin: 0 0 var(--sp-3); }
.gmp-checkrow input[type="checkbox"] { accent-color: var(--accent); width: 18px; height: 18px; flex: none; margin: 0; }
.gmp-checkrow:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); }
.gmp-checkrow:has(input:disabled) { cursor: default; }
.gmp-hint { font-size: var(--fs-12); color: var(--ink-faint); }
textarea.gmp-input { resize: vertical; min-height: 96px; line-height: 1.45; }

/* Choice cards — a radio group where each option needs a sentence (s101, begar-tillgang's two paths). */
.gmp-choices { border: 0; padding: 0; margin: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.gmp-choices > legend { padding: 0; margin-bottom: var(--sp-2); }
.gmp-choice { display: flex; gap: var(--sp-3); align-items: flex-start; border: 1px solid var(--border-strong); border-radius: var(--r); padding: var(--sp-3); background: var(--ground); cursor: pointer; font-size: var(--fs-14); color: var(--ink); transition: border-color .14s ease, background .14s ease; }
.gmp-choice:hover { border-color: var(--accent); }
.gmp-choice:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); }
.gmp-choice:has(input:disabled) { cursor: not-allowed; opacity: .6; }
.gmp-choice:has(input:focus-visible) { box-shadow: var(--ring); }
.gmp-choice > input { margin: 3px 0 0; accent-color: var(--accent); flex: none; }
.gmp-choice__body { display: flex; flex-direction: column; gap: 2px; }

/* Honeypot: off-screen for people, present for bots. */
.gmp-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* begar-tillgang (s101) — an anonymous page composed from the base components; only its column lives here. */
.gmp-accessrequest { max-width: 640px; display: flex; flex-direction: column; gap: var(--sp-4); font-size: var(--fs-body); }
.gmp-accessrequest__lead { margin: 0; color: var(--ink-muted); }
/* s107 — "Koppla ditt BankID" (IdentityBindFlow::Notice): the offer and its one button, on any page needing a step-up. */
.gmp-bindoffer { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-3); max-width: 640px; margin: 0 0 var(--sp-5); font-size: var(--fs-body); }
.gmp-bindoffer__form { margin: 0; }
.gmp-bindoffer__note { margin: 0; color: var(--ink-muted); font-size: var(--fs-13); }
.gmp-affsign__dialog { display: flex; flex-direction: column; gap: var(--sp-3); }
/* s107 — the outcome of a BankID round trip above a list (AffidavitSignFlow::Notice): spaced from what follows. */
.gmp-flownotice { display: flex; flex-direction: column; gap: var(--sp-3); max-width: 640px; margin: 0 0 var(--sp-5); }
.gmp-flownotice .gmp-bindoffer { margin: 0; }
/* s107 — "Signera med BankID" on an egen försäkran (AffidavitSignFlow::Button): a bare form around one button. */
.gmp-affsign { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0; }
.gmp-accessrequest__form { display: flex; flex-direction: column; gap: var(--sp-4); }
.gmp-accessrequest__form h3, .gmp-accessrequest__form h4, .gmp-accessrequest__form p { margin-top: 0; margin-bottom: 0; }
.gmp-accessrequest__disclosure { display: flex; flex-direction: column; gap: var(--sp-2); }
.gmp-accessrequest__actions { display: flex; gap: var(--sp-3); margin: 0; }

/* logga-in (s102) — the code-owned login form (LoginPage), composed from the base components; only its column and
   the one control the base set has no class for (a single inline checkbox) live here. */
.gmp-login { max-width: 420px; display: flex; flex-direction: column; gap: var(--sp-4); font-size: var(--fs-body); }
.gmp-login__form { display: flex; flex-direction: column; gap: var(--sp-4); }
.gmp-login__remember { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-14); color: var(--ink); cursor: pointer; }
.gmp-login__remember > input { width: 16px; height: 16px; margin: 0; flex: none; accent-color: var(--accent); }
.gmp-login__actions { display: flex; gap: var(--sp-3); margin: 0; }
.gmp-login__links { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); margin: 0; font-size: var(--fs-14); }

/* byt-foretag (s103) — "Byt förening" (ForeningSwitchPage), which replaced GF form 1: the person's föreningar as one panel
   list, the current one marked, each other one a small secondary button that navigates to that subsite. `.gmp-app` and
   `.gmp-switch` sit on the SAME element, hence the chained `.gmp-app.gmp-switch`. */
.gmp-switch { max-width: 560px; display: flex; flex-direction: column; gap: var(--sp-4); font-size: var(--fs-body); }
.gmp-app.gmp-switch .gmp-switch__intro { margin: 0; }
/* parallax-pro bullets and indents `.entry-content ul` (0,1,1) and `.entry-content ul > li` (0,1,2); the panel's own padding
   moves onto the rows so their hairlines run edge to edge. */
.gmp-app.gmp-switch ul.gmp-switch__list { list-style: none; margin: 0; padding: 0; }
.gmp-app.gmp-switch .gmp-switch__list > li.gmp-switch__item { list-style: none; margin: 0; display: flex; align-items: center; justify-content: space-between;
	gap: var(--sp-3); padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--border); }
.gmp-app.gmp-switch .gmp-switch__list > li.gmp-switch__item:first-child { border-top: 0; }
.gmp-switch__name { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
/* ⚠ The app-page link rule scores (0,3,2) and would paint this button teal — the Startsidan finding (s102). (0,4,1) wins. */
.gmp-app.gmp-switch .gmp-switch__item a.gmp-btn { flex: none; color: var(--ink); text-decoration: none; }
.gmp-app.gmp-switch .gmp-switch__item a.gmp-btn:hover { color: var(--ink); }

/* Startsidan (s102, client-content-design.md §9 L-4/L-7) — the photo edge to edge, a band over its lower left. Works on
   both parallax-pro (client1) and gmp-client (client900): the break-out is relative to the viewport, not the theme's column. */
body.gmp-start-page { overflow-x: hidden; }                     /* 100vw includes the scrollbar; never a sideways scroll */
body.gmp-start-page .entry-header { display: none; }            /* "Startsidan" as a heading says nothing */
/* The photo meets the system menu and the footer (user, s102 walk). Measured on parallax-pro: `.site-inner` carried a 24px
   top margin and `article.entry` a 100px bottom margin. Zeroed on this page only — both themes, margin AND padding. */
/* …and on gmp-client (client900) the gap was not a margin at all: its sticky-footer shell makes `.site-container` a 100vh
   flex column and `.site-inner` `flex: 1 0 auto`, so on a page as short as this one the stretch rendered as 73px of white
   between the photo and the footer. Not growing here keeps the footer under the photo; parallax-pro is not a flex shell,
   so `flex-grow` is inert there. */
body.gmp-start-page .site-inner { margin-top: 0; padding-top: 0; padding-bottom: 0; flex-grow: 0; }
body.gmp-start-page .content-sidebar-wrap,
body.gmp-start-page .content,
body.gmp-start-page .entry,
body.gmp-start-page .entry-content { margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; }
.gmp-start { position: relative; width: 100vw; margin-left: calc(50% - 50vw); font-family: var(--font-sans); }
.gmp-start__photo { position: relative; line-height: 0; }
.gmp-start__photo picture, .gmp-start__photo img { display: block; width: 100%; }
.gmp-start__photo img { height: auto; max-height: calc(100vh - 140px); object-fit: cover; }
/* The band sits top-left, the same distance in from the left and the top (user, s102 walk). */
.gmp-start__band { position: absolute; left: clamp(16px, 4vw, 48px); top: clamp(16px, 4vw, 48px); max-width: min(560px, calc(100% - 32px));
	padding: var(--sp-4) var(--sp-5); border-radius: var(--r-lg); color: var(--accent-ink);
	background: color-mix(in srgb, var(--ink) 74%, transparent); }
.gmp-start__band p { margin: 0; }
.gmp-start__name { font-size: 24px; font-weight: 650; line-height: 1.25; }
.gmp-start__who { margin-top: var(--sp-2) !important; font-size: var(--fs-14); }
.gmp-start__switch { margin-top: var(--sp-3) !important; }
/* "Byt förening" as a small outlined button — an underlined link was too quiet on the dark band (user, s102 walk). */
/* ⚠ Specificity, MEASURED in the browser (s102 walk): the app-page link rule
   `body:not(.gmp-client-page):has(.gmp-app, .gmp-gform_wrapper) .entry-content a { color: var(--accent) }` scores (0,3,2) —
   the :not() and the :has() each add a class — and painted both of these teal. A first fix at (0,3,1) still lost.
   Prefixing the page's own body class lifts both to (0,4,x): no !important, and no dependency on theme markup. */
body.gmp-start-page .gmp-start .gmp-start__band .gmp-start__switch a { display: inline-block; padding: 5px 12px; border: 1px solid var(--accent-ink); border-radius: var(--r);
	color: var(--accent-ink); font-size: 13px; font-weight: 600; text-decoration: none; }
body.gmp-start-page .gmp-start .gmp-start__band .gmp-start__switch a:hover,
body.gmp-start-page .gmp-start .gmp-start__band .gmp-start__switch a:focus-visible { background: var(--accent-ink); color: var(--ink); }
.gmp-start__actions { margin-top: var(--sp-3) !important; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* The credit: a light chip with dark text, a notch smaller — white on a mid-tone scrim collided with the photo (user, s102 walk). */
body.gmp-start-page .gmp-start .gmp-start__photo .gmp-credit-mark { position: absolute; right: 8px; bottom: 8px; padding: 2px 7px; border-radius: 4px; font-size: 10px; line-height: 1.4;
	color: var(--ink); background: color-mix(in srgb, var(--ground) 86%, transparent); text-decoration: none; }
body.gmp-start-page .gmp-start .gmp-start__photo .gmp-credit-mark:hover,
body.gmp-start-page .gmp-start .gmp-start__photo .gmp-credit-mark:focus-visible { text-decoration: underline; }
@media (max-width: 640px) {
	.gmp-start__band { position: static; max-width: none; border-radius: 0; background: var(--ink); }
	.gmp-start__photo img { max-height: none; }
}

/* Bildkällor och licenser (s102, §9 L-6b) — generated from assets/credits.php. */
.gmp-credits { max-width: 760px; display: flex; flex-direction: column; gap: var(--sp-4); font-size: var(--fs-body); }
.gmp-credits__lead { margin: 0; color: var(--ink-muted); }
.gmp-credits__item { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: flex-start; }
.gmp-credits__thumb { display: block; width: 320px; max-width: 100%; height: auto; border-radius: var(--r); }
.gmp-credits__body { flex: 1 1 260px; min-width: 0; }
.gmp-credits__title { margin: 0 0 var(--sp-2) 0; font-size: 18px; font-weight: 650; color: var(--ink); }
.gmp-credits__what { margin: 0 0 var(--sp-3) 0; font-size: var(--fs-14); color: var(--ink-muted); }
.gmp-credits__facts { display: grid; grid-template-columns: max-content 1fr; gap: var(--sp-2) var(--sp-4); margin: 0; font-size: var(--fs-14); }
.gmp-credits__facts dt { font-weight: 600; color: var(--ink-muted); }
.gmp-credits__facts dd { margin: 0; color: var(--ink); }
.gmp-credits-link { margin: var(--sp-2) 0 0; font-size: 12px; text-align: center; font-family: var(--font-sans); }
.gmp-credits-link a { color: var(--ink-muted); }
/* Grid of fields (auto-fitting) */
.gmp-fieldgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-3); }
.gmp-fieldgrid--2 { grid-template-columns: 2fr 1fr; }
@media (max-width: 640px) { .gmp-fieldgrid--2 { grid-template-columns: 1fr; } }
/* s124: a field whose VALUE is long (an article's "nr – description", a property's name) takes two cells of the grid. */
.gmp-fieldgrid > .gmp-field--wide { grid-column: span 2; }
@media (max-width: 640px) { .gmp-fieldgrid > .gmp-field--wide { grid-column: auto; } }

/* ── Inline status text (replaces color:#b00 / #127a2e spans) ────────────── */
.gmp-msg { font-size: var(--fs-13); font-weight: 600; }
.gmp-msg--error { color: var(--bad-ink); }
.gmp-msg--ok    { color: var(--ok-ink); }
.gmp-msg--warn  { color: var(--warn-ink); }   /* s132: done, but something the operator should know (a member not told of a partial payment) */

/* ── Notices (replaces #tyvarr, #mandatory, #noinvoice, .lightwarning …) ──── */
.gmp-notice { display: flex; gap: var(--sp-3); align-items: flex-start; border: 1px solid; border-radius: var(--r); padding: 11px 14px; font-family: var(--font-sans); font-size: var(--fs-14); }   /* s108: the family too — a notice injected outside a skinned form inherited the theme's Cormorant (walk) */
.gmp-notice__ic { font-weight: 700; flex: none; line-height: 1.45; }
.gmp-notice--info  { color: var(--info-ink); background: var(--info-bg); border-color: var(--info-bd); }
.gmp-notice--ok    { color: var(--ok-ink);   background: var(--ok-bg);   border-color: var(--ok-bd); }
.gmp-notice--warn  { color: var(--warn-ink); background: var(--warn-bg); border-color: var(--warn-bd); }
.gmp-notice--error { color: var(--bad-ink);  background: var(--bad-bg);  border-color: var(--bad-bd); }

/* ── Flash notices (FlashNotice, s74) ─────────────────────────────────────
   A one-shot message carried across a GF confirm() redirect. It slides in so the
   eye catches that something NEW appeared — a notice that is simply present on
   page load reads as page furniture and gets skipped.

   Only --auto fades out (info/ok, set in FlashNotice::Render): "the agreement went
   by post", "the request is queued" — nothing to act on. warn/error deliberately
   persist; an error that vanishes mid-read is worse than no error at all.

   The fade collapses max-height/padding/margin/border as well as opacity, so the
   space closes up instead of leaving a hole where the box was. overflow:hidden is
   what makes the max-height collapse actually clip. */
.gmp-flash { display: flex; flex-direction: column; gap: var(--sp-2, 8px); margin-bottom: 12px; }
.gmp-notice--flash { animation: gmp-flash-in .28s ease-out both; }
.gmp-notice--flash.gmp-notice--auto {
  overflow: hidden;
  animation: gmp-flash-in .28s ease-out both, gmp-flash-out .5s ease-in 6s both;
}
@keyframes gmp-flash-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes gmp-flash-out {
  from { opacity: 1; max-height: 200px; }
  to   { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0;
         margin-bottom: 0; border-top-width: 0; border-bottom-width: 0; }
}
/* Motion is decoration here, never the message: with reduced motion the notice is
   simply there, and an auto-dismiss one still leaves rather than trapping the
   layout mid-animation. */
@media (prefers-reduced-motion: reduce) {
  .gmp-notice--flash { animation: none; }
  .gmp-notice--flash.gmp-notice--auto { animation: gmp-flash-out .01s linear 6s both; }
}

/* ── Status chips (DL lifecycle etc.) ────────────────────────────────────── */
.gmp-chip { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 650; line-height: 1.4; padding: 3px 9px; border-radius: 100px; border: 1px solid; white-space: nowrap; }   /* s109 walk: the family and line-height too — a chip placed outside a table or skinned form (the year status on Bokföring) inherited the theme's serif; same fix as .gmp-notice s108 */
.gmp-chip::before { content: ""; width: 6px; height: 6px; border-radius: 100px; background: currentColor; }
.gmp-chip--draft  { color: var(--ink-muted); background: var(--surface-2); border-color: var(--border-strong); }
.gmp-chip--final  { color: var(--info-ink);  background: var(--info-bg);  border-color: var(--info-bd); }
.gmp-chip--sealed { color: var(--accent-strong); background: var(--accent-tint); border-color: var(--accent); }
.gmp-chip--sent   { color: var(--ok-ink);    background: var(--ok-bg);    border-color: var(--ok-bd); }
.gmp-chip--danger { color: var(--bad-ink);   background: var(--bad-bg);   border-color: var(--bad-bd); }
/* Something to check, not an error (s103: a register status the classifier did not recognise). */
.gmp-chip--warn   { color: var(--warn-ink);  background: var(--warn-bg);  border-color: var(--warn-bd); }
/* System/machine-owned marker (e.g. the CUSTADVANCE settlement row in the rows repeater).
   Mono + uppercase so it reads as a system tag, accent-tinted to stay in-family. */
.gmp-chip--system { color: var(--accent-strong); background: var(--accent-tint); border-color: var(--accent); font-family: var(--font-mono); font-size: 11px; letter-spacing: .03em; text-transform: uppercase; }
/* VOID — a document that was cancelled. Deliberately the heaviest of the quiet chips (s104, user): a
   muted row alone reads "inactive/secondary", but a makulerad invoice is not secondary, it is VOID, and
   the reader must not mistake it for a live one. So: strong ink on a solid border, uppercase, no dot —
   weight without colour, because void is a fact about the document, not an error. */
.gmp-chip--void { color: var(--ink); background: var(--ground); border-color: var(--ink-muted); border-width: 1.5px; font-size: 11px; letter-spacing: .04em; text-transform: uppercase; font-weight: 700; padding: 2px 8px; }
.gmp-chip--void::before { display: none; }
.gmp-chip--system::before { background: var(--accent); }

/* ── Modal (s103, supplier-quickadd-design.md §4.4) ──────────────────────────
   The app's ONE modal — js/gmp-modal.js (GmpModal). A native <dialog> opened with showModal(): the browser supplies
   the focus trap, Esc, the ::backdrop and the TOP LAYER, so it sits above every theme stacking context with no
   z-index. Class-scoped like everything here; nothing paints a <dialog> that did not opt in.

   🔑 It is mounted on <body>, OUTSIDE .gmp-app, so it inherits the THEME's typeface, size and line-height unless it
   says otherwise (the intl-tel-input lesson, s62) — hence font, size, colour and line-height are set on the dialog
   itself, and the title and the close button restate theirs against the theme's h2/button rules.

   🔴 A widget that mounts its dropdown on <body> (jQuery UI datepicker, tom-select, intl-tel-input) renders BENEATH
   the top layer, invisible behind the dialog. Inside a modal: plain controls, or a dropdown mounted in the dialog.

   Width min(640px, 100vw − 32px) keeps the 16px gutter at phone width; the body scrolls, the head and the foot stay.
   A backdrop click does not close (typed data is never lost to a stray click) — that is behaviour, in the JS. */
.gmp-modal { box-sizing: border-box; width: min(640px, calc(100vw - 32px)); max-width: calc(100vw - 32px); max-height: calc(100vh - 32px); margin: auto; padding: 0; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--ground); color: var(--ink); box-shadow: var(--shadow-3); font-family: var(--font-sans); font-size: var(--fs-body); line-height: 1.5; -webkit-font-smoothing: antialiased; overflow: hidden; }
.gmp-modal[open] { display: flex; flex-direction: column; }
/* ::backdrop inherits custom properties only in recent engines, so the fallback carries the colour everywhere else. */
.gmp-modal::backdrop { background: rgba(23,38,44,.45); background: var(--scrim, rgba(23,38,44,.45)); }
.gmp-modal *, .gmp-modal *::before, .gmp-modal *::after { box-sizing: border-box; }
.gmp-modal .gmp-modal__panel { display: flex; flex-direction: column; min-height: 0; max-height: calc(100vh - 34px); margin: 0; padding: 0; border: 0; background: transparent; }
.gmp-modal .gmp-modal__head { flex: none; display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border); }
.gmp-modal .gmp-modal__title { flex: 1; margin: 0; padding: 0; font-family: var(--font-sans); font-size: var(--fs-19); font-weight: 650; line-height: 1.3; letter-spacing: 0; text-transform: none; color: var(--ink); }
.gmp-modal .gmp-modal__close { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin: 0; padding: 0; border: 1px solid transparent; border-radius: var(--r); background: transparent; box-shadow: none; color: var(--ink-muted); font-family: var(--font-sans); font-size: var(--fs-24); font-weight: 400; line-height: 1; text-transform: none; cursor: pointer; }
.gmp-modal .gmp-modal__close:hover { background: var(--surface-2); color: var(--ink); }
.gmp-modal .gmp-modal__close:focus-visible { outline: none; box-shadow: var(--ring); }
.gmp-modal .gmp-modal__close:disabled { opacity: .5; cursor: not-allowed; }
.gmp-modal .gmp-modal__errors { flex: none; margin: var(--sp-4) var(--sp-5) 0; }
/* 🔴 .gmp-notice sets display:flex, which beats the browser's own [hidden] rule — so an EMPTY error bar showed on open
   (found on the first walk, s103; gmpAudit read 0 because its colours are tokens). */
.gmp-modal .gmp-modal__errors[hidden] { display: none; }
.gmp-modal .gmp-modal__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--sp-4); padding: var(--sp-5); }
.gmp-modal .gmp-modal__text { margin: 0; color: var(--ink); font-size: var(--fs-body); }
/* A form section inside a modal — the gf-skin's section eyebrow (.gsection_title), so a code-owned form reads like a skinned one. */
.gmp-modal .gmp-modal__section { margin: 0; padding: 0; font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 650; line-height: 1.4; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.gmp-modal .gmp-quickadd { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-quickadd .gmp-modal__section:not(:first-child) { margin-top: var(--sp-2); }
/* s123 K-N1: the Kivra-number modal (gmp-kivra.js) — same column rhythm as the quick-add; the confirm is a staff-only checkbox line. */
.gmp-modal .gmp-kivra { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-kivra__confirm { display: flex; gap: var(--sp-2); align-items: center; font-size: var(--fs-14); color: var(--ink); }
.gmp-modal .gmp-kivra__confirm[hidden] { display: none; }   /* the flex rule above beats [hidden] — the walk showed the staff confirm to everyone */
.gmp-modal .gmp-modal__foot { flex: none; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2); padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--border); background: var(--surface); }
.gmp-modal .gmp-modal__fielderror { margin-top: 2px; }
/* 🔴 The message lands INSIDE the field's <label class="gmp-field">, where `.gmp-field > label > span` / `.gmp-field > span`
   (0,1,1) paint it as a muted label and beat .gmp-msg--error (0,1,0) — the first walk read it grey, and gmpAudit could not
   see it because grey is a valid token (s103). Restated at (0,3,0). */
.gmp-modal .gmp-field .gmp-modal__fielderror { color: var(--bad-ink); font-size: var(--fs-13); font-weight: 600; }
.gmp-modal [aria-invalid="true"] { border-color: var(--bad-ink); }
.gmp-modal[aria-busy="true"] .gmp-modal__body { opacity: .72; }

/* A link inside any dialog (s111): the theme paints `a` in the legacy teal #00a0af, which reaches a GmpModal body
   wherever the page is not .gmp-app (the kvitton page's Kontera dialog). A button-styled link keeps its own colours. */
.gmp-modal .gmp-modal__body a:not(.gmp-btn) { color: var(--accent); }
.gmp-modal .gmp-modal__body a:not(.gmp-btn):hover { color: var(--accent-strong); }

/* ── A dialog's facts: a label/value list at the top of a GmpModal body (s110) ─────────────────────────────────
   One pattern for every modal that states what the operator is acting on — the card reconciliation's invoice, a
   reimbursement's member and amount. Was `.gmp-cardrec__facts`, one component's copy; a second dialog needing the
   same list made it shared rather than a third copy. Values in tabular numerals so amounts line up. */
.gmp-modal .gmp-facts { display: grid; grid-template-columns: max-content 1fr; gap: 2px var(--sp-4); margin: 0; font-size: var(--fs-13); }
.gmp-modal .gmp-facts dt { color: var(--ink-muted); font-weight: 600; }
.gmp-modal .gmp-facts dd { margin: 0; color: var(--ink); font-variant-numeric: tabular-nums; }

/* The reimbursement approval (s110, receipt-affidavit-design.md §6.1 d): facts, then at most one notice — D-I7's
   "bank details changed" (warn) or D-I2's "no bank details" (error, and the primary action becomes the request). */
.gmp-modal .gmp-rcptpay { display: flex; flex-direction: column; gap: var(--sp-3); }

/* ── A dialog's list: a compact table inside a GmpModal body (s111) ──────────────────────────────────────────
   One pattern for every modal that lists rows — the card reconciliation's open claims, a payment file's payments.
   Was `.gmp-cardrec__table`, one component's copy; the "Utförd" dialog needing the same list made it shared (the
   `.gmp-facts` precedent). Figures right-aligned in tabular numerals so öre line up. */
.gmp-modal table.gmp-modal__table { width: 100%; margin: 0; border-collapse: collapse; border: 0; font-size: var(--fs-13); }
.gmp-modal .gmp-modal__table th { padding: 4px 6px; border: 0; border-bottom: 1px solid var(--border-strong); background: transparent; color: var(--ink-muted); font-weight: 650; text-align: left; }
.gmp-modal .gmp-modal__table td { padding: 6px; border: 0; border-bottom: 1px solid var(--border); background: transparent; color: var(--ink); vertical-align: top; }
.gmp-modal .gmp-modal__table .gmp-modal__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.gmp-modal .gmp-modal__table .gmp-modal__date { white-space: nowrap; font-variant-numeric: tabular-nums; }
.gmp-modal .gmp-modal__table tfoot td { border-bottom: 0; border-top: 1px solid var(--border-strong); font-weight: 650; }

/* ── Card reconciliation panel (s105, accounting-suite-scope.md §0.6) — a GmpModal body ──────────────────────
   Open card claims with a tick each (a .gmp-modal__table), and a running tally against the card invoice's total. The
   tally is the decision the operator is making (C-4: exact match), so it carries the status — ok when it matches,
   warn until then — and SAVE is only enabled at a match. */
.gmp-modal .gmp-cardrec { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-cardrec tr.is-ticked td { background: var(--accent-tint); }
.gmp-modal .gmp-cardrec input[type="checkbox"] { width: 16px; height: 16px; margin: 2px 0 0; accent-color: var(--accent); }
.gmp-modal .gmp-cardrec__tally { display: flex; justify-content: space-between; gap: var(--sp-3); margin: 0; padding: var(--sp-2) var(--sp-3); border: 1px solid var(--warn-bd); border-radius: var(--r); background: var(--warn-bg); color: var(--warn-ink); font-weight: 650; font-variant-numeric: tabular-nums; }
.gmp-modal .gmp-cardrec__tally.is-match { border-color: var(--ok-bd); background: var(--ok-bg); color: var(--ok-ink); }
.gmp-modal .gmp-cardrec__empty { margin: 0; color: var(--ink-muted); }

/* The receipt KONTERING (s111, §6.3): the receipt beside its facts and fields, the rows underneath — GrullCo reads the
   underlag while typing. A PDF is an iframe through ClientDocServe, a photo an <img>; the two columns stack on a phone. */
.gmp-modal .gmp-kontera { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-kontera__top { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--sp-4); }   /* the receipt is what is read — it gets the room */
@media (max-width: 720px) { .gmp-modal .gmp-kontera__top { grid-template-columns: minmax(0, 1fr); } }
.gmp-modal .gmp-kontera__side { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-kontera__fields { grid-template-columns: minmax(0, 1fr); }
.gmp-modal .gmp-kontera__pdf { width: 100%; height: 460px; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
.gmp-modal .gmp-kontera__img { display: block; max-width: 100%; max-height: 460px; border: 1px solid var(--border); border-radius: var(--r); }
.gmp-modal .gmp-kontera__links { margin: var(--sp-1) 0 0; font-size: var(--fs-13); }
.gmp-modal .gmp-kontera__nodoc { margin: 0; color: var(--ink-muted); }

/* The "Utförd" confirmation (s111, D-I5): the file's facts, the statement date, its payments (a .gmp-modal__table)
   and — on a resumed file — which are already booked. */
.gmp-modal .gmp-fileexec { display: flex; flex-direction: column; gap: var(--sp-3); }
/* The date field sits alone under the table: sized to its content, and its label on one line (the walk found
   "Datum på kontoutdraget" wrapped over two, squeezed to the date input's width). */
.gmp-modal .gmp-fileexec .gmp-field { align-self: flex-start; }
.gmp-modal .gmp-fileexec .gmp-field > span { white-space: nowrap; }
.gmp-modal .gmp-fileexec tr.is-booked td { color: var(--ink-muted); }

/* ── The ledger drill-down (s108, T3 — accounting-suite-scope.md §2 T3.1) ────
   js/ledger-view.js: a voucher, or one account's ledger, inside a WIDE GmpModal. Like the card reconciliation the
   dialog is body-mounted, outside .gmp-app, so the theme's table/button/heading rules reach it — every element here
   sets what it needs rather than inheriting. */
.gmp-modal.gmp-modal--wide { width: min(1080px, calc(100vw - 32px)); }
.gmp-modal { outline-color: var(--border-strong); }   /* walk s108: the theme's #ccc outline colour reaches every dialog */
.gmp-modal table.gmp-ledgerview__table tbody { border: 0; }                /* walk s108: the theme's #ddd tbody border */
.gmp-modal .gmp-ledgerview { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-ledgerview__back { align-self: flex-start; }
.gmp-modal .gmp-ledgerview__facts { display: grid; grid-template-columns: max-content 1fr; gap: 2px var(--sp-4); margin: 0; font-size: var(--fs-13); }
.gmp-modal .gmp-ledgerview__facts dt { color: var(--ink-muted); font-weight: 600; }
.gmp-modal .gmp-ledgerview__facts dd { margin: 0; color: var(--ink); }
.gmp-modal .gmp-ledgerview__scroll { overflow-x: auto; }
.gmp-modal table.gmp-ledgerview__table { width: 100%; margin: 0; border-collapse: collapse; border: 0; font-size: var(--fs-13); }
.gmp-modal .gmp-ledgerview__table th { padding: 4px 8px; border: 0; border-bottom: 1px solid var(--border-strong); background: transparent; color: var(--ink-muted); font-size: var(--fs-12); font-weight: 650; letter-spacing: .04em; text-transform: uppercase; text-align: left; white-space: nowrap; }
.gmp-modal .gmp-ledgerview__table td { padding: 6px 8px; border: 0; border-bottom: 1px solid var(--border); background: transparent; color: var(--ink); vertical-align: top; }
.gmp-modal .gmp-ledgerview__table tfoot td { border-top: 1px solid var(--border-strong); border-bottom: 0; font-weight: 650; }
.gmp-modal .gmp-ledgerview__table .gmp-ledgerview__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.gmp-modal .gmp-ledgerview__table .gmp-ledgerview__code,
.gmp-modal .gmp-ledgerview__table .gmp-ledgerview__date { white-space: nowrap; font-variant-numeric: tabular-nums; }
.gmp-modal .gmp-ledgerview__table tr.gmp-ledgerview__ib td { background: var(--surface); color: var(--ink-muted); }
.gmp-modal .gmp-ledgerview__sub { display: block; margin-top: 1px; color: var(--ink-muted); font-size: var(--fs-12); }
.gmp-modal .gmp-ledgerview__link { display: inline; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; color: var(--accent); font: inherit; font-weight: 600; letter-spacing: 0; text-transform: none; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; white-space: nowrap; }
.gmp-modal .gmp-ledgerview__link:hover { background: none; color: var(--accent-strong); }
.gmp-modal .gmp-ledgerview__link:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }
.gmp-modal .gmp-ledgerview__docs { margin: 0; padding: 0 0 0 1.2em; font-size: var(--fs-13); }
.gmp-modal .gmp-ledgerview__docs a { color: var(--accent); }
.gmp-modal .gmp-ledgerview__empty { margin: 0; color: var(--ink-muted); font-size: var(--fs-13); }

@media (prefers-reduced-motion: no-preference) {
  .gmp-modal[open] { animation: gmp-modal-in .16s ease-out; }
}
@keyframes gmp-modal-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ── Toolbar row (button + total) ────────────────────────────────────────── */
.gmp-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.gmp-total { margin-left: auto; font-weight: 650; font-variant-numeric: tabular-nums; }
.gmp-divider { border: none; border-top: 1px solid var(--border); margin: var(--sp-4) 0; }

/* ── The ledger page (s108, T3) — the view switch and the year picker on `verifikationer`, and the numeric columns of
   its two tables. The drill-down dialog itself is styled in the modal section above. */
.gmp-ledger, .gmp-ledger__bar { color: var(--ink); }   /* walk s108: both inherited the theme's black */
.gmp-ledger__bar { justify-content: space-between; margin: var(--sp-3) 0 var(--sp-4); }
.gmp-ledger__year { display: inline-flex; align-items: center; gap: var(--sp-2); margin: 0; font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; color: var(--ink-muted); }
.gmp-ledger__year .gmp-select { width: auto; min-width: 18ch; }
.gmp-ledger__yeargroup { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }   /* s109: picker · status chip · the year's one action */
.gmp-fyaction { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-ledger__flash { margin-bottom: var(--sp-4); }
.gmp-ledger__new { margin-left: var(--sp-2); }   /* s109 walk: Ny verifikation closes the year group's row instead of floating above it */
.gmp-ledger table.dataTable td.dt-right { font-variant-numeric: tabular-nums; white-space: nowrap; }
.gmp-ledger table.dataTable td .gmp-btn + .gmp-btn { margin-left: var(--sp-1); }

/* ── The reports (s127, financial-reports-design.md) — Resultatrapport / Balansrapport on the same page. A report is a
   tree with subtotal rows, not a DataTable: level-indented groups whose accounts fold, sums and results as ruled lines.
   The account button opens the ledger dialog above; the 📄 per row is .gmp-ledgerview__doc. */
.gmp-ledger__period { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0; }
.gmp-ledger__period .gmp-select { min-width: 11ch; }
.gmp-ledger.gmp-report-wrap { font-family: var(--font-sans); }   /* walk s127: the table inherited the theme's serif */
.gmp-report__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-4); margin: 0 0 var(--sp-3); }
.gmp-report__title { margin: 0; font-size: var(--fs-19); font-weight: 650; color: var(--ink); }
.gmp-report__period { margin: 0; font-size: var(--fs-14); color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.gmp-report__printed { display: none; margin: 0; font-size: var(--fs-12); color: var(--ink-faint); }
.gmp-report__check { margin: 0 0 var(--sp-3); font-size: var(--fs-13); color: var(--ink-muted); }
.gmp-report__scroll { overflow-x: auto; }
.gmp-ledger table.gmp-report { width: 100%; margin: 0; border-collapse: collapse; border: 0; font-size: var(--fs-table); color: var(--ink); }
.gmp-ledger table.gmp-report tbody { border: 0; }
.gmp-ledger .gmp-report th, .gmp-ledger .gmp-report td { font-family: inherit; padding: 5px 8px; border: 0; background: transparent; text-align: left; vertical-align: baseline; }
.gmp-ledger .gmp-report thead th { border-bottom: 1px solid var(--border-strong); color: var(--ink-muted); font-size: var(--fs-th); font-weight: 650; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.gmp-ledger .gmp-report .gmp-report__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; width: 1%; }
.gmp-ledger .gmp-report__sub { display: block; margin-top: 2px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--ink-faint); }
.gmp-ledger .gmp-report__heading th { padding-top: var(--sp-4); font-size: var(--fs-13); font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-muted); }
.gmp-ledger .gmp-report__heading.gmp-report--l2 th { padding-top: var(--sp-3); padding-left: 20px; text-transform: none; letter-spacing: 0; color: var(--ink); }
.gmp-ledger .gmp-report__group td { font-weight: 600; border-top: 1px solid var(--border); }
.gmp-ledger .gmp-report__group.gmp-report--l2 td:first-child { padding-left: 20px; }
.gmp-ledger .gmp-report__group.gmp-report--l3 td:first-child { padding-left: 36px; }
.gmp-ledger .gmp-report__account td { color: var(--ink-muted); font-size: var(--fs-13); }
.gmp-ledger .gmp-report__account td:first-child { padding-left: 52px; }
.gmp-ledger .gmp-report__sum th, .gmp-ledger .gmp-report__sum td { font-weight: 650; border-top: 1px solid var(--border-strong); }
.gmp-ledger .gmp-report__sum.gmp-report--l2 th { padding-left: 20px; }
.gmp-ledger .gmp-report__result th, .gmp-ledger .gmp-report__result td { font-weight: 700; border-top: 2px solid var(--ink); background: var(--surface); }
.gmp-ledger .gmp-report__computed a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.gmp-ledger .gmp-report__toggle,
.gmp-ledger .gmp-report__acct { display: inline; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; font: inherit; letter-spacing: 0; text-transform: none; text-align: left; cursor: pointer; }
.gmp-ledger .gmp-report__toggle { color: var(--ink); font-weight: 600; }
.gmp-ledger .gmp-report__toggle::before { content: "▾"; display: inline-block; width: 1.1em; color: var(--ink-faint); }
.gmp-ledger .gmp-report__toggle[aria-expanded="false"]::before { content: "▸"; }
.gmp-ledger .gmp-report__acct { color: var(--accent); }
.gmp-ledger .gmp-report__acct:hover, .gmp-ledger .gmp-report__toggle:hover { background: none; color: var(--accent-strong); text-decoration: underline; }
.gmp-ledger .gmp-report__toggle:focus-visible, .gmp-ledger .gmp-report__acct:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }
.gmp-ledger .gmp-report__konto { font-variant-numeric: tabular-nums; }
.gmp-modal .gmp-ledgerview__doc { color: var(--accent); font-weight: 600; white-space: nowrap; }

/* s127 (Documents walk D-2): an entity form the page's JS reveals ("Nytt …") flashed visible while the page loaded. A form that opts
   in with `gmp-gform--deferred` (GF adds `…_wrapper` to the wrapper) stays hidden while <html> carries `gmp-deferred-pending` — set
   by the page's initpage before the form renders, removed by the entity JS once it has hidden the form itself. A refused submit's
   ajax redisplay comes after, so the guard can never hide it. */
html.gmp-deferred-pending .gmp-gform--deferred_wrapper,
html.gmp-deferred-pending #cancelbuttondivtop { display: none; }   /* the entity's Avbryt — every entity uses this container id (tags.cancelb) */
.gmp-notice.gmp-newdocs__receipts { clear: both; margin: var(--sp-3) 0; }   /* under the floated Nytt / Avbryt, full width */
.gmp-notice.gmp-newdocs__receipts a { color: var(--info-ink); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
#buttondivtop, #cancelbuttondivtop, #norowshtml { color: var(--ink); }   /* walk s127: the entity button containers inherited the theme's black (gmpAudit) */

/* R-15 (s127): "Kopplingar" — the dimension filters, behind a disclosure so the bar stays clean. On the report (a part of the
   period's GET form) and in the account dialog (client-side over its rows). */
.gmp-modal .gmp-ledgerview__links { display: inline-block; }
/* Walk s127: on the report, Kopplingar is its own row under the bar, and its fields an even grid — label above, every select the
   same width — so opening it neither re-wraps the bar nor leaves three ragged widths. */
.gmp-report__links { display: block; margin: calc(-1 * var(--sp-2)) 0 var(--sp-4); }
.gmp-report__linksbody { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-3); margin-top: var(--sp-2);
  padding: var(--sp-3); border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
.gmp-report__dim { display: flex; flex-direction: column; gap: 4px; margin: 0; font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; color: var(--ink-muted); }
.gmp-report__dim .gmp-select { width: 100%; min-width: 0; }
.gmp-modal .gmp-ledgerview__linksbody { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin-top: var(--sp-2); }
.gmp-report__links > summary, .gmp-modal .gmp-ledgerview__links > summary { list-style: none; }
.gmp-report__links > summary::-webkit-details-marker, .gmp-modal .gmp-ledgerview__links > summary::-webkit-details-marker { display: none; }
.gmp-report__links > summary::after, .gmp-modal .gmp-ledgerview__links > summary::after { content: "▾"; margin-left: 2px; }
.gmp-report__links[open] > summary::after, .gmp-modal .gmp-ledgerview__links[open] > summary::after { content: "▴"; }
.gmp-report__urval { width: 100%; margin: 0; font-size: var(--fs-13); color: var(--ink); }
.gmp-report__urval a { color: var(--accent); }
.gmp-modal .gmp-ledgerview__dim { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-13); font-weight: 600; color: var(--ink-muted); }
.gmp-modal .gmp-ledgerview__dim .gmp-select { width: auto; min-width: 14ch; max-width: 34ch; }
.gmp-modal .gmp-ledgerview__note { margin: 0; font-size: var(--fs-13); color: var(--ink); }
.gmp-modal .gmp-ledgerview__note[hidden] { display: none; }

/* Print (R-11): the report alone — the board takes it to its meeting. The browser's own "Save as PDF" is the PDF until T2. */
@media print {
  .gmp-toolbar.gmp-ledger__bar, .gmp-ledger__new, .gmp-ledger .gmp-report__toggle::before, .gmp-ledger .gmp-report__excel, .gmp-report__urval a, .gmp-report__links { display: none; }
  .gmp-report__printed { display: block; }
  .gmp-ledger .gmp-report__accounts[hidden] { display: none; }
  .gmp-ledger .gmp-report__acct { color: inherit; text-decoration: none; }
  .gmp-ledger .gmp-report__result th, .gmp-ledger .gmp-report__result td { background: none; }
  .gmp-ledger .gmp-report tr { break-inside: avoid; }
}

/* ── The account plan page (s108, the Accounts lap — register-migration-status §6n) ───────────────────────────
   The kassör's toolbar (the request to GrullCo + what she may change herself), and the note under the Active box that
   says why an account cannot be deactivated before she tries. */
/* ── The fiscal-year picker (s112, FiscalYearView::Picker) — one look for every page that picks a year; Bokföring's shape. */
.gmp-fypicker { display: inline-flex; align-items: center; gap: var(--sp-2); margin: 0; font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; color: var(--ink-muted); }
.gmp-fypicker .gmp-select { width: auto; min-width: 12ch; }

/* ── Exportera SIE (s112, T3.2) — the year, its facts, the preliminary notice, one button. Layout only. */
.gmp-sie, .gmp-sie__bar { color: var(--ink); }
.gmp-sie__lead { margin: var(--sp-3) 0; font-family: var(--font-sans); font-size: var(--fs-14); color: var(--ink); max-width: 70ch; }
.gmp-sie__bar { margin: 0 0 var(--sp-2); }
.gmp-sie__facts { margin: 0 0 var(--sp-4); }
.gmp-sie__actions { margin-top: var(--sp-4); }
.gmp-sie__msg:empty { display: none; }
.gmp-sie__msg { margin-top: var(--sp-3); }

/* ── Ingående balans (s112, OB-1/OB-2) — `ingaende-saldon`: the year picker (Bokföring's shape), where the numbers come
   from, a read table on .gmp-table, and GrullCo's editor on GmpVoucherRows. Layout only; every look is a component's. */
.gmp-ob, .gmp-ob__bar { color: var(--ink); }
.gmp-ob__bar { margin: var(--sp-3) 0 var(--sp-2); }
.gmp-ob__edit { margin-left: auto; }
.gmp-ob [hidden] { display: none; }   /* s112 walk: .gmp-btn sets display, which beat the hidden attribute — Ändra stayed up while editing */
.gmp-ob__source { margin: 0 0 var(--sp-4); }
.gmp-ob__scroll { overflow-x: auto; }
.gmp-app table.gmp-table.gmp-ob__table .gmp-ob__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.gmp-app table.gmp-table.gmp-ob__table .gmp-ob__code { font-variant-numeric: tabular-nums; white-space: nowrap; }
.gmp-app table.gmp-table.gmp-ob__table tfoot td { padding: 9px 12px; border-top: 1px solid var(--border-strong); font-weight: 650; }
.gmp-ob__editor { margin-top: var(--sp-3); }
.gmp-ob__editor .gmp-hint { margin: 0 0 var(--sp-3); }
.gmp-ob__msg:empty { display: none; }
.gmp-ob__msg { margin-top: var(--sp-3); }
.gmp-ob__actions { margin-top: var(--sp-3); }
/* s129 (R-16e.1): the IB per cost centre — the sum row is the control, a KST that does not balance is marked */
.gmp-ob__legend { margin: 0 0 var(--sp-2); }
.gmp-app table.gmp-table.gmp-ob__table--kst tfoot td.is-off { color: var(--bad-ink); }
.gmp-app table.gmp-table.gmp-ob__table--kst .gmp-ob__unsplit { color: var(--warn-ink); }
.gmp-ob__kstsum { margin: var(--sp-2) 0 0; text-align: right; font-size: var(--fs-13); font-weight: 600; font-variant-numeric: tabular-nums; }
.gmp-ob__kstsum:empty { display: none; }
.gmp-ob__kstsum.is-ok  { color: var(--ok-ink); }
.gmp-ob__kstsum.is-off { color: var(--bad-ink); }
/* s130: the per-account check of a GL-imported year — the head line reuses .gmp-ob__kstsum, the accounts listed under it */
.gmp-ob__acctsum:empty { display: none; }
.gmp-ob__acctlist { margin: var(--sp-1) 0 0; padding: 0; list-style: none; text-align: right; font-size: var(--fs-13); color: var(--bad-ink); font-variant-numeric: tabular-nums; }
.gmp-ob__acctlist li + li { margin-top: 2px; }
.gmp-ob ul.gmp-ob__acctlist > li { list-style: none; margin-left: 0; padding-left: 0; }   /* walk: the theme's list marker leaked in as a stray dot */
.gmp-ob ul.gmp-ob__acctlist > li::before { content: none; }

/* s130: a READINESS LIST — "what happens if I do this", one line per check: ✕ blocks the save, ! saves but names what will
   be refused, ✓ holds, → what comes next. Generic (first use: the KST switch on `installningar`, KstSettings). */
.gmp-readiness { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans); font-size: var(--fs-14); }
.gmp-readiness__item { display: flex; gap: var(--sp-2); align-items: flex-start; line-height: 1.45; color: var(--ink); }
.gmp-readiness__ic { flex: none; width: 18px; height: 18px; margin-top: 1px; border-radius: 100px; border: 1px solid; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; line-height: 1; }
.gmp-readiness__item.is-block .gmp-readiness__ic { color: var(--bad-ink);  background: var(--bad-bg);  border-color: var(--bad-bd); }
.gmp-readiness__item.is-block { color: var(--bad-ink); }
.gmp-readiness__item.is-warn  .gmp-readiness__ic { color: var(--warn-ink); background: var(--warn-bg); border-color: var(--warn-bd); }
.gmp-readiness__item.is-ok    .gmp-readiness__ic { color: var(--ok-ink);   background: var(--ok-bg);   border-color: var(--ok-bd); }
.gmp-readiness__item.is-info  .gmp-readiness__ic { color: var(--info-ink); background: var(--info-bg); border-color: var(--info-bd); }

/* s130: avtalsfakturering — the warnings before Fastställ (D-9 unsigned agreements, D-11 identical usage rows) */
.gmp-as-warn { margin: var(--sp-3) 0; }
/* walk (user): the theme's list marker sat out of line with the text — no markers; each item an indented line of its own */
.gmp-as-warn ul { margin: 6px 0 0; padding: 0 0 0 12px; list-style: none; }
.gmp-as-warn ul > li { margin: 2px 0; padding: 0; list-style: none; }
.gmp-as-warn ul > li::before { content: none; }

/* s130: installningar — the code-owned sections above form 17 (InstallningarPage). Class-scoped, tokens only. */
.gmp-inst { color: var(--ink); margin-bottom: var(--sp-6); }
.gmp-inst [hidden] { display: none; }
.gmp-inst__kstform { max-width: 720px; }
.gmp-inst__catch { max-width: 320px; }
.gmp-inst__msg:empty { display: none; }
.gmp-inst__remform { max-width: 720px; }
.gmp-inst__remmsg:empty { display: none; }
.gmp-inst__facts { display: grid; grid-template-columns: max-content 1fr; gap: 6px var(--sp-4); margin: 0 0 var(--sp-2); font-size: var(--fs-14); }
.gmp-inst__facts dt { color: var(--ink-muted); font-weight: 600; }
.gmp-inst__facts dd { margin: 0; }

/* s129 (R-16e.2): kst-omforingar — the KST transfer queue (KstCorrectionPage). Class-scoped, tokens only. */
.gmp-kc { color: var(--ink); }
.gmp-kc [hidden] { display: none; }
.gmp-kc__bar { margin: var(--sp-3) 0 var(--sp-2); gap: var(--sp-2); flex-wrap: wrap; }
.gmp-kc__refresh { margin-left: auto; }
.gmp-kc__howto { margin: 0 0 var(--sp-3); border: 1px solid var(--border); border-radius: var(--r); padding: var(--sp-2) var(--sp-3); background: var(--surface); }
.gmp-kc__howto summary { cursor: pointer; font-weight: 600; }
.gmp-kc__howto ol { margin: var(--sp-2) 0 0; padding-left: 1.3em; font-size: var(--fs-14); }
.gmp-kc__howto li { margin: 0 0 var(--sp-1); }
.gmp-kc__tabs { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: var(--sp-4) 0 var(--sp-3); }
.gmp-kc__tab { border: 1px solid var(--border); background: var(--surface); color: var(--ink); border-radius: var(--r); padding: 6px 12px; font: inherit; font-size: var(--fs-13); cursor: pointer; }
.gmp-kc__tab b { font-variant-numeric: tabular-nums; }
.gmp-kc__tab.is-on { border-color: var(--accent); background: var(--accent-tint); }
.gmp-kc__card { border: 1px solid var(--border); border-radius: var(--r-lg); margin: 0 0 var(--sp-3); overflow: hidden; background: var(--ground); }
.gmp-kc__head { display: flex; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-2) var(--sp-4); background: var(--surface); border-bottom: 1px solid var(--border); }
.gmp-kc__meta { white-space: nowrap; }
.gmp-kc__badge { font-size: var(--fs-12); font-weight: 700; padding: 2px 8px; border-radius: 99px; background: var(--ok-bg); color: var(--ok-ink); }
.gmp-kc__badge--review { background: var(--bad-bg); color: var(--bad-ink); }
.gmp-kc__badge--decided { background: var(--info-bg); color: var(--info-ink); }
.gmp-kc__badge--skipped { background: var(--warn-bg); color: var(--warn-ink); }
.gmp-kc__badge--booked { background: var(--surface-2); color: var(--ink-muted); }
.gmp-kc__rule { font-size: var(--fs-12); color: var(--ink-muted); font-family: var(--font-mono); }
.gmp-kc__note { margin: var(--sp-2) var(--sp-4) 0; color: var(--ink-muted); font-size: var(--fs-13); }
.gmp-kc__note--decided { color: var(--info-ink); }
.gmp-kc__cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.gmp-kc__col { padding: var(--sp-2) var(--sp-4); min-width: 0; }
.gmp-kc__col + .gmp-kc__col { border-left: 1px solid var(--border); }
.gmp-kc__col h4 { margin: 0 0 var(--sp-1); font-size: var(--fs-12); text-transform: uppercase; letter-spacing: .05em; color: var(--ink-muted); }
.gmp-app table.gmp-table.gmp-kc__rows td { padding: 3px 6px 3px 0; font-size: var(--fs-13); font-variant-numeric: tabular-nums; }
.gmp-app table.gmp-table.gmp-kc__rows .gmp-kc__num { text-align: right; white-space: nowrap; }
.gmp-app table.gmp-table.gmp-kc__rows .gmp-kc__acct { font-weight: 600; white-space: nowrap; }
.gmp-app table.gmp-table.gmp-kc__rows .gmp-kc__name { color: var(--ink-muted); max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gmp-kc__chip { display: inline-block; font-size: var(--fs-12); font-weight: 700; padding: 0 6px; border-radius: var(--r-sm); background: var(--accent-tint); color: var(--accent-strong); }
.gmp-kc__chip--none { background: var(--bad-bg); color: var(--bad-ink); }
.gmp-kc__sums { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-1); font-size: var(--fs-12); font-variant-numeric: tabular-nums; }
.gmp-kc__sum.is-ok { color: var(--ok-ink); }
.gmp-kc__sum.is-off { color: var(--bad-ink); font-weight: 650; }
.gmp-kc__actions { padding: 0 var(--sp-4) var(--sp-3); gap: var(--sp-2); }
.gmp-kc__msg:empty { display: none; }
.gmp-kc__msg { margin-top: var(--sp-3); }
.gmp-kc__dialog .gmp-field { margin-top: var(--sp-3); display: block; }
.gmp-kc__kstsum { margin: var(--sp-2) 0 0; text-align: right; font-size: var(--fs-13); font-weight: 600; font-variant-numeric: tabular-nums; }
.gmp-kc__kstsum:empty { display: none; }
.gmp-kc__kstsum.is-ok  { color: var(--ok-ink); }
.gmp-kc__kstsum.is-off { color: var(--bad-ink); }

/* s129 (R-16 step 5): the KST status + the kassör's approval on Bokföring och rapporter (KstBalancePanel) */
.gmp-kstbs { margin: var(--sp-3) 0; }
.gmp-kstbs__body { display: block; min-width: 0; flex: 1 1 auto; }
.gmp-kstbs__text { margin: 0; max-width: none; }
.gmp-kstbs__actions { margin-top: var(--sp-2); gap: var(--sp-2); }
.gmp-kstbs__dialog .gmp-kstbs__confirm { margin: var(--sp-3) 0 var(--sp-2); display: flex; gap: var(--sp-2); align-items: flex-start; }
.gmp-kstbs__dialog > .gmp-btn { margin-top: var(--sp-2); }
@media (max-width: 640px) {
  .gmp-kc__col + .gmp-kc__col { border-left: 0; border-top: 1px solid var(--border); }
  .gmp-app table.gmp-table.gmp-kc__rows .gmp-kc__name { display: none; }
}

.gmp-kontoplan__bar { margin: var(--sp-3) 0 var(--sp-4); color: var(--ink); }
.gmp-kontoplan__hint { font-family: var(--font-sans); font-size: var(--fs-13); color: var(--ink-muted); }
.gmp-kontoplan__usage { margin-top: var(--sp-2); }
.gmp-kontoplan__flash { margin-bottom: var(--sp-4); }   /* s109 walk: the flash sat flush on the DataTable filter buttons */
.gmp-modal .gmp-kontoplan__request { display: flex; flex-direction: column; gap: var(--sp-3); }

/* ── Org-number lookup (s103, supplier-quickadd-design.md §4.5) ──────────────
   js/gmp-orgnr-lookup.js: one row under an org number — "Hämta uppgifter", the warning chips (D-4), the outcome line. It lives both
   inside the modal and inside a skinned GF field, so it carries its own layout and depends on neither host. An empty chip list or
   outcome line takes no space. Chips may wrap here: a status in the register's own words can be longer than a chip usually is. */
.gmp-lookup { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-1); }
/* s123 (entity walk K-N2): the private customer's lookup — its own un-posted personnummer input under the Företag/Privatperson choice. */
.gmp-lookup-person { display: flex; flex-direction: column; gap: var(--sp-1); margin-top: var(--sp-3); max-width: 420px; }
.gmp-lookup .gmp-lookup__flags { display: inline-flex; flex-wrap: wrap; gap: var(--sp-1); }
.gmp-lookup .gmp-lookup__flags:empty,
.gmp-lookup .gmp-lookup__msg:empty,
.gmp-lookup .gmp-lookup__hint:empty { display: none; }
/* The registered name (user, s103): on its own line, in ink — it is the answer the user compares the form against. */
.gmp-lookup .gmp-lookup__hint { flex-basis: 100%; font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; color: var(--ink); }
.gmp-lookup .gmp-chip { white-space: normal; }
.gmp-lookup .gmp-lookup__msg { font-family: var(--font-sans); font-size: var(--fs-13); color: var(--ink-muted); }
/* s122 N8: the org number is already a supplier — a warning in the warn palette on its own line, never a block ("Hämta ändå"). */
.gmp-lookup .gmp-lookup__exists { flex-basis: 100%; font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600;
  color: var(--warn-ink); background: var(--warn-bg); border: 1px solid var(--warn-bd); border-radius: var(--r-sm); padding: var(--sp-1) var(--sp-2); }
.gmp-lookup .gmp-lookup__exists:empty { display: none; }
.gmp-lookup .gmp-lookup__again[hidden] { display: none; }

/* ══ DataTables theming — GLOBAL on the DataTables-injected classes ═════════
   Evolved (s62) from the original .gmp-app-only scope: DataTables is the FIRST
   thing on every entity page (invoice list, etc.) and recurs in Document-
   Management (e.g. the docconn/docnotconn tables in the gpfup context) — and
   most of those tables are NOT inside a .gmp-app wrapper. `.dataTables_wrapper table.dataTable` /
   `.dataTables_wrapper` are classes DataTables injects only where it runs (never
   on a marketing/landing page), and there are ZERO legacy `.dataTables_wrapper table.dataTable`
   rules to conflict — so scoping on them directly is safe (same widget-class
   reasoning as .iti / .ts-control) and harmonises every table app-wide at once. */
.dataTables_wrapper table.dataTable { border-collapse: collapse !important; width: 100% !important; font-size: var(--fs-table); }
.dataTables_wrapper table.dataTable thead th { text-align: left; font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .05em; color: var(--ink-muted); font-weight: 650; padding: 10px 12px; background: var(--surface); border-bottom: 1px solid var(--border-strong); }
.dataTables_wrapper table.dataTable tbody td { padding: 10px 12px; border-top: 1px solid var(--border); color: var(--ink); }
/* s74: DataTables ships its own #ddd borders and wins on load order for the element-level `tbody`
   border-bottom, which the rule above never covered (it targets `tbody td`). Visible on the tables
   EMBEDDED IN A FORM — the customer's property / invoice / letter history — which is where the token
   audit caught it. Element-scoped, so it stays generic rather than per-form. */
.dataTables_wrapper table.dataTable tbody { border-bottom: 1px solid var(--border); }
/* ...and the EMPTY state. A table with no rows never gets DataTables initialised, so it carries neither
   `.dataTable` nor a `.dataTables_wrapper` — it is a plain table with the app's own markup classes, and
   every wrapper-scoped rule above misses it. That is why an empty "Kundens registrerade fastigheter"
   rendered with browser/DataTables #ddd borders next to a fully skinned table. */
/* s106 (register row 34): the EMPTY-state table also inherits the theme's TYPE — Cormorant 22px, black — because
   nothing but these two border rules ever reached it. Found on the kvitton page, whose list starts empty. */
table.responsive.nowrap.hover { font-family: var(--font-sans); font-size: var(--fs-table); color: var(--ink); }
table.responsive.nowrap.hover tbody { border-bottom: 1px solid var(--border); }
table.responsive.nowrap.hover tbody td { border-top: 1px solid var(--border); color: var(--ink); }
.dataTables_wrapper table.dataTable tbody td { border-top-color: var(--border); }
.dataTables_wrapper table.dataTable tbody tr { background: var(--ground); transition: background .1s ease; }
.dataTables_wrapper table.dataTable tbody tr:hover { background: var(--accent-tint); }
.dataTables_wrapper table.dataTable td.dt-right, .dataTables_wrapper table.dataTable th.dt-right { text-align: right; font-variant-numeric: tabular-nums; }
/* s132 (Kostnadsställen walk, the user: "Aktiv is asymmetric"): a centred column's HEADER stayed left (the thead rule above), and a
   sortable header carries 26px on the right for the arrow — so the label is centred over its cells only with the same 26px on the left. */
.dataTables_wrapper table.dataTable td.dt-center, .dataTables_wrapper table.dataTable th.dt-center { text-align: center; }
.dataTables_wrapper table.dataTable thead th.dt-center[class*="sorting"] { padding-left: 26px; }

/* ── DataTables master-detail expander (td.dt-control) ────────────────────────
   The manual expand column a table-def opts into via `dt-control` in its `align`
   (e.g. the docnotconn "where is this doc also connected" child table, documents.js).
   It is a real feature, NOT the Responsive collapse control — kept always-visible via
   the `all` class (helpers.js). Core DataTables paints its +/− circle in an off-palette
   green (#31b131)/red (#d33333); re-own it on tokens. `tr.shown` = documents.js open-state
   (DT's own `tr.dt-hasChild` covered too). Specificity (0,0,3,x) beats core's bare
   `td.dt-control:before` (0,0,1,x) with no !important. (s64) */
.dataTables_wrapper table.dataTable td.dt-control { text-align: center; cursor: pointer; }
.dataTables_wrapper table.dataTable td.dt-control:before {
  content: "+"; box-sizing: content-box; display: inline-block;
  height: 1em; width: 1em; line-height: 1em; margin-top: -1px;
  border: .14em solid var(--ground); border-radius: 1em;
  font-family: var(--font-mono); text-indent: 0 !important; text-align: center;
  color: var(--accent-ink); background: var(--accent); box-shadow: var(--shadow-1);
}
.dataTables_wrapper table.dataTable tr.shown td.dt-control:before,
.dataTables_wrapper table.dataTable tr.dt-hasChild td.dt-control:before {
  content: "−"; background: var(--ink-muted);
}

/* font-family here (not just on .gmp-app) — the table now lives outside .gmp-app on most entity
   pages, so without this the cells inherit the THEME font (Gotham/Helvetica). Covers cells +
   buttons + filter + info + pagination in one place. */
.dataTables_wrapper { color: var(--ink-muted); font-family: var(--font-sans); font-size: var(--fs-13); }
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select { font: inherit; font-size: var(--fs-13); color: var(--ink); background: var(--ground); border: 1px solid var(--border-strong); border-radius: var(--r); padding: 5px 9px; margin-left: 6px; }
.dataTables_wrapper .dataTables_filter input:focus,
.dataTables_wrapper .dataTables_length select:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.dataTables_wrapper .dataTables_info { font-size: var(--fs-13); padding-top: var(--sp-3); }
.dataTables_wrapper .dataTables_paginate { padding-top: var(--sp-2); }
.dataTables_wrapper .dataTables_paginate .paginate_button { padding: 5px 11px !important; margin: 0 2px; border-radius: var(--r-sm) !important; border: 1px solid var(--border) !important; color: var(--ink) !important; background: var(--ground) !important; }
.dataTables_wrapper .dataTables_paginate .paginate_button.current { background: var(--accent) !important; border-color: var(--accent) !important; color: var(--accent-ink) !important; }
.dataTables_wrapper .dataTables_paginate .paginate_button:hover:not(.current) { background: var(--surface-2) !important; border-color: var(--border-strong) !important; color: var(--ink) !important; }
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled { opacity: .45; }
/* — DataTables core-CSS completion (s64). The injected-DT strip (removing the legacy #xxxtable_*
   ID chrome from gmp_artist.css) exposed DataTables' OWN core CSS underneath, which paints a few
   bits off-token: the filter search box border #aaa, and info/paginate/label text #333. Core uses
   the SAME `.dataTables_wrapper …` selectors as our theme and loads AFTER us, so it wins ties on
   source order — a one-step specificity bump (type attr / element-qualified class) beats it cleanly,
   no !important. Compact chrome size now lives on `.dataTables_wrapper{font-size}` above (was a
   `font-size:12px` in the stripped legacy block). */
.dataTables_wrapper .dataTables_filter input[type="search"],
.dataTables_wrapper div.dataTables_length select { border-color: var(--border-strong); }
/* s107 (register row 38): the theme's full-width select turned DataTables' floated "Visar [25] kvitton" into three stacked
   lines — the float shrinks to the select, the text wraps around it. One line, the select as wide as its value. */
.dataTables_wrapper div.dataTables_length label { white-space: nowrap; }
.dataTables_wrapper div.dataTables_length select { width: auto; margin: 0 6px; }
.dataTables_wrapper div.dataTables_info,
.dataTables_wrapper div.dataTables_paginate,
.dataTables_wrapper div.dataTables_length,
.dataTables_wrapper div.dataTables_length label,
.dataTables_wrapper div.dataTables_filter,
.dataTables_wrapper div.dataTables_filter label { color: var(--ink-muted); }
/* prev/next disabled + current text: core pins these with !important on TIED selectors and wins on
   load order — add an `a` element qualifier (one-step specificity bump) so ours wins. Disabled →
   faint tier; current → accent-ink (readable on the accent bg set by the .current rule above). */
.dataTables_wrapper .dataTables_paginate a.paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate a.paginate_button.disabled:hover { color: var(--ink-faint) !important; }
.dataTables_wrapper .dataTables_paginate a.paginate_button.current { color: var(--accent-ink) !important; }
/* …and the ENABLED page links, which the s64 pass missed because nothing it audited had a second
   page (s104, the 45-row supplier-invoice list). Core's #333 ties the `.paginate_button` colour set
   above and wins on load order, exactly like the two states beside it; same `a` qualifier, same fix.
   Lower specificity than .disabled/.current, so those keep their own colour. */
.dataTables_wrapper .dataTables_paginate a.paginate_button { color: var(--ink) !important; }
/* core table/tbody bottom borders (rgba(0,0,0,.3) / #ddd) → token border. Core pins the table
   line via `table.dataTable.no-footer` → include `.no-footer` to out-specify it. */
.dataTables_wrapper table.dataTable,
.dataTables_wrapper table.dataTable.no-footer,
.dataTables_wrapper table.dataTable > tbody { border-bottom-color: var(--border); }
/* App-content links → design-system accent. The theme paints links in the OLD brand teal
   (#00a0af); entity-list actionable links (View/Edit/customer/pdf/…) live in `.entry-content`.
   Scope to app pages via the :has() gate (same pattern as the .entry-title recast) so
   marketing/landing links stay theme-owned. Our `!important` pagination rules keep their colours
   (this rule has no !important). (s64) */
/* s138 (F-17, the Oderland walk): `:not(.gmp-btn)` — at (0,3,2) this rule out-ranked `.gmp-btn--primary` and painted the
   Startsidan's "Logga in" button's TEXT teal on its own teal background: an invisible primary action on the first page a
   member sees. A link styled as a button owns its colours; this rule is for text links only. */
body:not(.gmp-client-page):has(.gmp-app, .gmp-gform_wrapper) .entry-content a:not(.gmp-btn) { color: var(--accent); }
body:not(.gmp-client-page):has(.gmp-app, .gmp-gform_wrapper) .entry-content a:not(.gmp-btn):hover { color: var(--accent-strong); }

/* ── DataTables filter-button base (typography + shape) ───────────────────────
   The status-filter buttons DataTables renders above a table. This gives them the app
   button look (font/size/shape) generically; the STATUS COLOUR comes from the semantic
   class the row/button carries (below). */
.dataTables_wrapper .dt-buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--sp-3); }
.dataTables_wrapper .dt-buttons button.dt-button {
  font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; line-height: 1;
  border-radius: var(--r); padding: 8px 12px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--ink); margin: 0; cursor: pointer;
  transition: background .14s ease, border-color .14s ease;
}
.dataTables_wrapper .dt-buttons button.dt-button:hover { border-color: var(--border-strong); filter: brightness(.97); }

/* ── DataTables STATUS colours — SEMANTIC redesign (B), landing entity-by-entity ──
   The legacy presentational vocabulary (`tr.cXXX`/`button.cXXX`, colour-named, painted by
   scattered `#table tr.cXXX` rules in gmp_artist.css) is being replaced by SEMANTIC status
   classes emitted from each entity's dd `rowcolor`/`buttclasses` maps (`gmp-status--ok/warn/
   bad/info/muted/accent`). As each table-def migrates we agree its `prepfunc`/`shstatus`
   semantics, rewrite its maps to the semantic names, and they get styled by ONE block here
   (row tint + filter chip, contextually). The legacy `cXXX` CSS stays until no dd references
   it, then it's deleted wholesale.
   Migrated (s62): the invoices table-def (PrepInvRow) — Draft/2→muted, Skickade→info,
   Förfallna→bad, Påminda→warn, Betalda/credited→ok; "Alla"=neutral base; Kred/Ränta=accent
   type-chips; statuses 8/9 (dead legacy) → no colour. A migrated row/button carries the NEW
   class so the legacy `#table tr.cXXX` rules no longer match it — no specificity fight. The
   row tints keep `!important` only to sit above DataTables' zebra striping. */
.dataTables_wrapper table.dataTable tbody tr.gmp-status--muted  { background: var(--surface-2) !important; }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--info   { background: var(--info-bg)   !important; }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--warn   { background: var(--warn-bg)   !important; }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--bad    { background: var(--bad-bg)    !important; }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--ok     { background: var(--ok-bg)     !important; }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--accent { background: var(--accent-tint) !important; }
/* VOID rows (s104, user: muted alone was "too gentle"). Three signals, none of them colour, because a
   cancelled document is inert rather than wrong — colour is reserved for states that need an action:
     1. the muted surface it already had                (it is not live)
     2. a solid left bar in --ink-muted                 (structural weight; a border on <tr> does not
                                                         paint, so it goes on the leading cell)
     3. struck-through figures in the right-aligned cells (the money is void, and that is the one thing
                                                         a reader must not misread)
   The badge itself is a real element rendered by the entity, never CSS `content` — the Swedish label
   lives in Helper with every other string. Generic on .gmp-status--void, so any entity gets it. */
.dataTables_wrapper table.dataTable tbody tr.gmp-status--void    { background: var(--surface-2) !important; color: var(--ink-faint); }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--void > td:first-child { box-shadow: inset 3px 0 0 var(--ink-muted); }
.dataTables_wrapper table.dataTable tbody tr.gmp-status--void > td.dt-right { text-decoration: line-through; text-decoration-thickness: 1px; }
/* CELL-level status (s120, §A row 49) — the same vocabulary as the row rules above, for a table where ONE cell
   carries the state and the rest of the row is plain data (first user: the property change feed's Åtgärd column,
   stamped by fast_class::CreateHistoricRecs through the dd's `drow => 'field,tdclass'`). Same !important as the row
   rules, for the same reason: DataTables paints its sorted-column cells at 0,4,3. The ink is set with the ground so
   a cell reads on its own, not only against its row. Void is the one that differs: a single cell cannot carry the
   row's left bar or struck figures, so it is muted italic — history, not an error. */
.dataTables_wrapper table.dataTable tbody td.gmp-status--muted  { background: var(--surface-2)   !important; color: var(--ink-muted); }
.dataTables_wrapper table.dataTable tbody td.gmp-status--info   { background: var(--info-bg)     !important; color: var(--info-ink); }
.dataTables_wrapper table.dataTable tbody td.gmp-status--warn   { background: var(--warn-bg)     !important; color: var(--warn-ink); }
.dataTables_wrapper table.dataTable tbody td.gmp-status--bad    { background: var(--bad-bg)      !important; color: var(--bad-ink); }
.dataTables_wrapper table.dataTable tbody td.gmp-status--ok     { background: var(--ok-bg)       !important; color: var(--ok-ink); }
.dataTables_wrapper table.dataTable tbody td.gmp-status--accent { background: var(--accent-tint) !important; color: var(--accent-strong); }
.dataTables_wrapper table.dataTable tbody td.gmp-status--void   { color: var(--ink-muted); font-style: italic; }   /* not --ink-faint: ~3:1 on white is too faint for text that is read */
.dataTables_wrapper .dt-buttons button.gmp-status--muted  { background: var(--surface-2);   color: var(--ink-muted);     border-color: var(--border-strong); }
.dataTables_wrapper .dt-buttons button.gmp-status--info   { background: var(--info-bg);      color: var(--info-ink);      border-color: var(--info-bd); }
.dataTables_wrapper .dt-buttons button.gmp-status--warn   { background: var(--warn-bg);      color: var(--warn-ink);      border-color: var(--warn-bd); }
.dataTables_wrapper .dt-buttons button.gmp-status--bad    { background: var(--bad-bg);       color: var(--bad-ink);       border-color: var(--bad-bd); }
.dataTables_wrapper .dt-buttons button.gmp-status--ok     { background: var(--ok-bg);        color: var(--ok-ink);        border-color: var(--ok-bd); }
.dataTables_wrapper .dt-buttons button.gmp-status--accent { background: var(--accent-tint);  color: var(--accent-strong); border-color: var(--accent); }

/* the ClientInvoice rows-repeater table (#cinvRows, a real <table> not a DataTable) picks up the
   Genesis `tbody{border-bottom:#ddd}` leak — tokenise it so app tables stay on-palette. */
.gmp-app tbody { border-bottom-color: var(--border); }

/* ── Static tables (NOT DataTables-initialised) — e.g. längd detail, signing status.
   Tagged with .gmp-table so they get the same token look without fighting the
   DataTables stylesheet's specificity (so no !important needed here). ── */
.gmp-app .gmp-panel > table.gmp-table:last-child { margin-bottom: 0; }
.gmp-app .gmp-notice ul { margin: 6px 0 0; }
.gmp-app table.gmp-table { border-collapse: collapse; width: 100%; font-size: var(--fs-table); background: var(--ground); }
/* s103 — a year-by-category money grid (the supplier spending panel): figures right-aligned in tabular digits, the total
   column strong; the total ROW takes the existing .gmp-row-strong. Replaced the legacy #suppspend_table ID rules. */
.gmp-app table.gmp-table.gmp-spend th:not(:first-child),
.gmp-app table.gmp-table.gmp-spend td:not(:first-child) { text-align: right; font-variant-numeric: tabular-nums; }
.gmp-app table.gmp-table.gmp-spend td:last-child { font-weight: 650; }
.gmp-app table.gmp-table thead th { text-align: left; font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .05em; color: var(--ink-muted); font-weight: 650; padding: 10px 12px; background: var(--surface); border-bottom: 1px solid var(--border-strong); }
.gmp-app table.gmp-table td { padding: 9px 12px; border-top: 1px solid var(--border); color: var(--ink); vertical-align: top; }
/* A `th` used as a ROW LABEL — `tbody th` — rather than as a column header (s91, user).
   The component styled `thead th` and `td` and never this, so every two-column label/value table drew a
   rule under the VALUES and nothing under the LABELS, and gave the label 1px of padding against the value's
   9px 12px. Found by eye on the board-change review block, but it was never a GravityFlow quirk: it is our
   own component missing a case, so every label/value table in the app had it. */
.gmp-app table.gmp-table tbody th {
  text-align: left; padding: 9px 12px; border-top: 1px solid var(--border);
  color: var(--ink-muted); font-weight: 600; vertical-align: top;
}
.gmp-app table.gmp-table.borderless td { border-top: none; padding: 4px 8px; }
.gmp-app table.gmp-table.borderless tbody th { border-top: none; padding: 4px 8px; }
/* s106: a column that should take only the width of its content (codes, dates, amounts), so the one free-text
   column gets the rest instead of wrapping. Opt in per cell; amounts keep their own right alignment. */
.gmp-app table.gmp-table .gmp-col-fit { width: 1%; white-space: nowrap; }
.gmp-app table.gmp-table td.dt-right, .gmp-app table.gmp-table th.dt-right { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Reusable row emphasis helpers (längd detail: DI header / sub-line / annotation) */
.gmp-app tr.gmp-row-strong > td { font-weight: 600; background: var(--surface); }
.gmp-app tr.gmp-row-sub > td { color: var(--ink-muted); }
.gmp-app tr.gmp-row-note > td { color: var(--ink-faint); font-style: italic; }
/* System/settlement row (read-only, machine-owned — e.g. the CUSTADVANCE credit regulator on a ClientInvoice):
   muted + tinted so it reads clearly as a non-editable system line, not a business row. An accent
   hairline on the leading cell marks it as machine-owned (final look, s61 — paired with .gmp-chip--system). */
.gmp-app tr.gmp-row-system > td { color: var(--ink-muted); background: var(--surface-2); }
.gmp-app tr.gmp-row-system > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* Small text utility */
.gmp-muted { color: var(--ink-muted); }

@media (prefers-reduced-motion: reduce) {
  .gmp-btn, .gmp-input, .gmp-select, .dataTables_wrapper table.dataTable tbody tr { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   GRAVITY FORMS SKIN  —  scope root: .gmp-gform_wrapper   (s61)
   --------------------------------------------------------------------------
   ONE class replaces the enumerated #gform_wrapper_N (76 forms) + #gform_submit_button_N
   lists in gmp_artist.css. GF applies a form's cssClass verbatim to <form> ("gmp-gform")
   and appends _wrapper on the wrapper div → the whole form sits under .gmp-gform_wrapper.
   Opt in per form via cssClass:"gmp-gform" in forms/*.json (code-before-content); ZERO
   GF-field-id coupling — every selector targets GF's own class vocabulary.

   CASCADE NOTE: GF's base input rule below uses input[type="…"] (attribute selector,
   specificity 0,0,3,1). Every state/variant modifier (.gmpreadonly, number, error, grandtotal)
   therefore ALSO carries .ginput_container / a type attr so it ties that specificity and wins
   on source order — a bare `.x input` (0,0,2,1) is silently defeated by the base rule.
   ═══════════════════════════════════════════════════════════════════════ */
.gmp-gform_wrapper { font-family: var(--font-sans); color: var(--ink); font-size: var(--fs-body); max-width: 900px; }
.gmp-gform_wrapper .gform_heading { margin-bottom: var(--sp-4); }
.gmp-gform_wrapper .gform_title { font-family: var(--font-sans); font-size: var(--fs-24); font-weight: 650; letter-spacing: -.015em; margin: 0; }
.gmp-gform_wrapper .gform_description { display: block; color: var(--ink-muted); font-size: var(--fs-14); margin-top: 4px; }

/* field grid — GF's 12-col grid, re-spaced on tokens */
/* row-gap tightened — dense back-office forms read better a touch tighter. GF's framework sets a
   big row-gap (~40px) via an unguarded rule, so use the doubled wrapper + longhands to win. */
.gmp-gform_wrapper.gform_wrapper .gform_fields { display: grid; grid-template-columns: repeat(12, 1fr); row-gap: var(--sp-3); column-gap: var(--sp-4); margin: 0; padding: 0; list-style: none; }
.gmp-gform_wrapper .gfield { grid-column: span 12; display: flex; flex-direction: column; gap: 5px; min-width: 0; margin: 0; }
/* choice fields (radio/checkbox) render as <fieldset><legend>…: the flex `gap` does NOT reach the
   <legend> (browsers lay legends out specially — it sat flush, 0px, above the options no matter the
   gap). So space the OPTIONS CONTAINER explicitly instead — that's a normal flex child and obeys margin. */
.gmp-gform_wrapper .gfield--type-choice > .ginput_container { margin-top: 8px; }
.gmp-gform_wrapper .gfield--width-half          { grid-column: span 6; }
.gmp-gform_wrapper .gfield--width-third         { grid-column: span 4; }
.gmp-gform_wrapper .gfield--width-quarter       { grid-column: span 3; }
.gmp-gform_wrapper .gfield--width-three-quarter { grid-column: span 9; }
@media (max-width: 680px) { .gmp-gform_wrapper .gfield[class*="gfield--width-"] { grid-column: span 12; } }

/* labels + required + description */
.gmp-gform_wrapper .gfield_label { font-size: var(--fs-label); font-weight: 600; color: var(--ink-muted); margin: 0; }
.gmp-gform_wrapper .gfield_required { color: var(--bad-ink); margin-left: 3px; text-decoration: none; }
.gmp-gform_wrapper .gfield_description { font-size: var(--fs-12); color: var(--ink-faint); padding-top: 2px; }

/* inputs / selects / textarea — the workhorse (attribute selectors ⇒ specificity 0,0,3,1) */
.gmp-gform_wrapper .ginput_container input[type="text"],
.gmp-gform_wrapper .ginput_container input[type="email"],
.gmp-gform_wrapper .ginput_container input[type="tel"],
.gmp-gform_wrapper .ginput_container input[type="number"],
.gmp-gform_wrapper .ginput_container input[type="date"],
.gmp-gform_wrapper .ginput_container input[type="password"],
.gmp-gform_wrapper .ginput_container select,
.gmp-gform_wrapper .ginput_container textarea {
  font: inherit; font-size: var(--fs-input); color: var(--ink); background: var(--ground);
  border: 1px solid var(--border-strong); border-radius: var(--r); padding: 9px 11px; width: 100%;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.gmp-gform_wrapper .ginput_container input:focus,
.gmp-gform_wrapper .ginput_container select:focus,
.gmp-gform_wrapper .ginput_container textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.gmp-gform_wrapper .ginput_container input:disabled,
.gmp-gform_wrapper .ginput_container select:disabled { background: var(--surface-2); color: var(--ink-faint); }
/* Complex fields — name, password (register rows 27–28, s102, form 38). The PARTS of a complex field carry sub-labels
   ("Förnamn", "Bekräfta lösenord") that inherited the input's 15px ink and outweighed the 13px field label above them.
   They are hints, so they take the hint voice. Keyed on GF's sub-label class — covers every complex field at once. */
.gmp-gform_wrapper .ginput_complex .gform-field-label--type-sub { font-size: var(--fs-12); font-weight: 400; color: var(--ink-faint); margin: 4px 0 0; }
.gmp-gform_wrapper .ginput_container textarea { min-height: 82px; resize: vertical; line-height: 1.5; }

/* number fields → right-aligned tabular mono, keyed on GF's own container class (not field id).
   [type] attrs ⇒ ties the base rule's specificity so `font: inherit` doesn't reset the mono face. */
.gmp-gform_wrapper .ginput_container_number input[type="text"],
.gmp-gform_wrapper .ginput_container_number input[type="number"] { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }

/* A button placed INSIDE a skinned field (s103: the supplier picker's "+ Ny leverantör"). The skin makes .gfield a flex column,
   which would stretch the button across the field; generic, so any field-level button sits at its own width. */
.gmp-gform_wrapper .gfield > .gmp-btn { align-self: flex-start; margin-top: var(--sp-1); }

/* GF List field (enableColumns) — e.g. form 25 field 26 "Konteringsrader" (the accounting-rows
   grid: Konto / KST / Beskrivning / Belopp … with add/remove-row buttons). Its cell <input>s already
   inherit the base input skin (the container carries .ginput_container). What's left is the TABLE
   chrome: header row, cell borders, and the +/- row icons. Generic — keyed on GF's own list classes
   (.gfield_list*, never a field id), covers every List field app-wide. Class names cover GF 2.5+
   (.gfield_header_item / .gfield_list_cell) and the older (.gfield_list_group_item) markup. */
.gmp-gform_wrapper .gfield_list { border-collapse: collapse; width: 100%; margin: 0; }
.gmp-gform_wrapper .gfield_list thead .gfield_header_item {
  text-align: left; font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-muted); font-weight: 650; padding: 8px 10px; background: var(--surface);
  border-bottom: 1px solid var(--border-strong);
}
.gmp-gform_wrapper .gfield_list td.gfield_list_cell,
.gmp-gform_wrapper .gfield_list td.gfield_list_group_item { padding: 6px 8px; border-top: 1px solid var(--border); vertical-align: top; }
.gmp-gform_wrapper .gfield_list td.gfield_list_icons { white-space: nowrap; width: 1%; }
/* s130 (walk A-E3): a select in a List field kept its narrow intrinsic width — "*Elmätare Bertil" was cut on Förbrukningsavtal */
.gmp-gform_wrapper .ginput_container_list select { width: 100%; min-width: 220px; }
/* opt-in (cssClass gmp-list--wide-first on the field): the first column of a List field gets three times the room — form 67's
   device picker, whose option reads "Elmätare Bertil B - Elmätare (ELM002)" (walk A-E3). Header and rows alike. */
.gmp-gform_wrapper .gmp-list--wide-first .gfield_list_header > .gform-grid-col:first-child,
.gmp-gform_wrapper .gmp-list--wide-first .gfield_list_group > .gform-grid-col:first-child { flex: 3 1 0; }
/* the add (+) / delete (−) row buttons — GF renders <button>/<img>; give them the app icon-button look */
.gmp-gform_wrapper .gfield_list .add_list_item,
.gmp-gform_wrapper .gfield_list .delete_list_item {
  font-family: var(--font-sans);   /* else inherits the theme's Quicksand on the +/− glyphs */
  color: var(--ink-muted); background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--r-sm); width: 26px; height: 26px; line-height: 1; cursor: pointer; padding: 0; margin: 0 2px;
}
.gmp-gform_wrapper .gfield_list .add_list_item:hover { color: var(--accent-strong); border-color: var(--accent); background: var(--accent-tint); }
.gmp-gform_wrapper .gfield_list .delete_list_item:hover { color: var(--bad-ink); border-color: var(--bad-bd); background: var(--bad-bg); }

/* GF List field — the COLUMNS/GRID markup (s73). GF renders list fields two ways and the rules above only
   cover the older TABLE variant (thead / td.gfield_list_cell). A list field with enableColumns on GF 2.5+
   renders DIVs instead — .ginput_container_list--columns > .gfield_list_container > .gfield_list_header
   (.gform-grid-row) > .gfield_header_item (.gform-grid-col) — so form 67's "Avtalet gäller följande resurser"
   inherited none of it and rendered raw. Keyed on GF's own classes, so this covers every grid list app-wide. */
.gmp-gform_wrapper .ginput_container_list--columns { margin-top: 12px; }   /* legend was sitting on the headers */
.gmp-gform_wrapper .gfield_list_header {
  padding-bottom: 6px; margin-bottom: 8px; border-bottom: 1px solid var(--border-strong);
}
.gmp-gform_wrapper .gfield_list_header .gfield_header_item {
  font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-muted); font-weight: 650;
}
.gmp-gform_wrapper .gfield_list_group + .gfield_list_group { margin-top: 6px; }
/* Centre the row's cells, and centre the button INSIDE the icons cell. Both are needed and it is easy to stop
   at the first: the icons cell is itself display:flex and stretches to the full row height, so with only the row
   rule the 26px button still pinned to the top of a 60px cell. align-self on the cell does nothing here — the
   cell is the flex CONTAINER for the button, so it is align-items that decides. */
.gmp-gform_wrapper .gfield_list_group { align-items: center; }
/* The icons cell holds BOTH buttons (add + delete). They were wrapping onto two lines, making the cell 60px
   tall against a 38px input — which is what made the circles look unaligned with the row rather than merely
   off-centre. nowrap puts them side by side, the cell collapses to button height, and the row centring then
   lines them up with the inputs. */
.gmp-gform_wrapper .gfield_list_group .gfield_list_icons {
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: center;
  gap: 4px; flex: 0 0 auto; width: auto; min-width: 60px;
}
.gmp-gform_wrapper .gfield_header_item--icons { text-align: center; }

/* The row +/- controls. GF 2.5+ renders them as <button> carrying the TEXT "Lägg till" / "Ta bort", not a
   glyph — so the 26px icon-button box clipped the label into an unreadable stack. font-size:0 collapses the
   label (it stays in the accessibility tree as the button's name) and the icon is DRAWN, not typed.
   Why drawn: a "+" character centres on the font's math axis, not on its em box, so flex-centring the glyph
   leaves it visibly high inside the circle no matter how the box is aligned — which is exactly what it did.
   Two absolutely-positioned bars are centred by geometry and are identical in every font. */
.gmp-gform_wrapper .gfield_list .add_list_item,
.gmp-gform_wrapper .gfield_list .delete_list_item,
.gmp-gform_wrapper .gfield_list_container .add_list_item,
.gmp-gform_wrapper .gfield_list_container .delete_list_item {
  position: relative; box-sizing: border-box; display: inline-block;
  border-radius: 50%; font-size: 0; line-height: 0;
  width: 26px; height: 26px; padding: 0; flex: 0 0 auto;
}
.gmp-gform_wrapper .add_list_item::before,
.gmp-gform_wrapper .add_list_item::after,
.gmp-gform_wrapper .delete_list_item::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  background: currentColor; transform: translate(-50%, -50%); border-radius: 1px;
}
.gmp-gform_wrapper .add_list_item::before,
.gmp-gform_wrapper .delete_list_item::before { width: 11px; height: 1.5px; }   /* horizontal bar */
.gmp-gform_wrapper .add_list_item::after     { width: 1.5px; height: 11px; }   /* vertical bar -> "+" */

/* Chosen (the enhanced select behind GF's dropdowns) — vendor CSS sizes its visible control at 25px/13px while
   every real input in the form is 38px/15px, which is what made the customer picker look cramped next to the
   address fields directly below it. Match the input skin so a Chosen select is indistinguishable from a plain
   one. The native <select> is display:none behind it, so this is the only control the user ever sees. */
.gmp-gform_wrapper .chosen-container { width: 100% !important; font-size: 15px; }
/* Specificity note: Chosen ships its own `.chosen-container-single .chosen-single { height: 25px }` from a
   stylesheet this page loads cross-origin (unreadable via cssRules), and a 3-class selector was not beating it.
   Qualifying the anchor and adding the .ginput_container ancestor takes this to 0,0,4,1 — enough to win on
   merit rather than with !important, which the register keeps for genuine last resorts. */
.gmp-gform_wrapper .ginput_container .chosen-container-single a.chosen-single {
  height: 38px; line-height: 36px; padding: 0 10px; box-sizing: border-box;
  background: #fff; border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  color: var(--ink); box-shadow: none; font-size: 15px;
}
.gmp-gform_wrapper .ginput_container .chosen-container-single a.chosen-single div b { margin-top: 6px; }
.gmp-gform_wrapper .chosen-container-active.chosen-with-drop .chosen-single { box-shadow: var(--ring); }
.gmp-gform_wrapper .chosen-container .chosen-drop { border-color: var(--border-strong); border-radius: 0 0 var(--r-sm) var(--r-sm); }
.gmp-gform_wrapper .chosen-container .chosen-results li.highlighted { background: var(--accent); color: #fff; }
/* s103 (form 24, Motkonto): the rest of Chosen. gmp_artist.css paints `a.chosen-single > span` light cyan for every
   Chosen select (0,0,1,2) — left in place for the forms not yet skinned, answered here; and the vendor draws the search
   box and the results in its own greys. */
.gmp-gform_wrapper .ginput_container .chosen-container-single a.chosen-single > span { background: transparent; }
/* ⚠ measured: a single-wrapper selector TIED GF's foundation Chosen rules (not guarded by gform-theme__disable) and lost on
   load order — the doubled wrapper, the house pattern of register rows 8, 11 and 12. */
.gmp-gform_wrapper.gform_wrapper .chosen-container .chosen-search input.chosen-search-input[type="text"] { border-color: var(--border-strong); border-radius: var(--r-sm); }
.gmp-gform_wrapper .chosen-container ul.chosen-results { color: var(--ink); }

/* Agreement T&C block (form 67 html field, #ovrigavillkor) — the terms the customer is about to sign, so it
   must read as prose, not as form chrome. The legacy rules bolded the entire block and styled the label blue +
   underlined; both are gone (s73). Headings stay bold via their own <strong>. */
#ovrigavillkor { font-size: var(--fs-body, 15px); font-weight: 400; color: var(--ink); line-height: 1.55; }
#ovrigavillkor > p.paraovrigavillkor {
  margin: 0 0 10px; color: var(--ink-muted); text-decoration: none;
  font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .05em; font-weight: 650;
}
#ovrigavillkor p { margin: 0 0 8px; }
#ovrigavillkor p strong { font-weight: 650; color: var(--ink); }

/* read-only / computed fields — GF cssClass "gmpreadonly" (its JS sets [readonly]).
   The invoice totals (Net, Moms 6/12/25, Total moms, Öresavrundning, Total) are these:
   calm, non-editable, no focus affordance. */
.gmp-gform_wrapper .gmpreadonly .ginput_container input,
.gmp-gform_wrapper .ginput_container input[readonly] { background: var(--surface-2); color: var(--ink-muted); border-color: var(--border); cursor: default; }
.gmp-gform_wrapper .gmpreadonly .ginput_container input:focus,
.gmp-gform_wrapper .ginput_container input[readonly]:focus { border-color: var(--border); box-shadow: none; }
/* grand total (Total inkl. moms) reads as the answer — accent tint, heavier (add class in forms/*.json) */
.gmp-gform_wrapper .gmp-gform-grandtotal .gfield_label { color: var(--accent); }
.gmp-gform_wrapper .gmp-gform-grandtotal .ginput_container input { color: var(--ink); font-weight: 680; font-size: var(--fs-16); background: var(--accent-tint); border-color: var(--accent); }

/* A READ-ONLY FIELD WHOSE VALUE CARRIES A STATE (register row 40, s117).
   -----------------------------------------------------------------------------
   The invoice's View mode painted six fields from JS with hardcoded `.css('background-color', …)` off
   `Helper::$globals['idcl']` — #A3F395 green, #F3A5A5 red, #E371EC purple, lightyellow. Inline styles beat
   every stylesheet, so the design system could not reach them, and the same invoice showed one palette on
   the form and the s62 semantic one on the list beside it.
   Generic, keyed on a class the JS adds — never a field id — so any entity's read-only status field can use
   it. The type attribute takes it to 0,0,4,1, one step above the base input rule (0,0,3,1): a clean win on
   specificity rather than on load order, and no !important.
   🔑 The vocabulary is the s62 one (ok/warn/bad/info/muted) so a state cannot mean two things in two places,
   and the s104 rule holds: COLOUR IS FOR A STATE THAT NEEDS AN ACTION. "Skickas" is the ordinary answer and
   gets none; "Bromsad" and an exhausted reminder régime are deviations a board should see. */
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--muted { background: var(--surface-2);   color: var(--ink-muted);     border-color: var(--border-strong); }
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--info  { background: var(--info-bg);     color: var(--info-ink);      border-color: var(--info-bd); }
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--warn  { background: var(--warn-bg);     color: var(--warn-ink);      border-color: var(--warn-bd); }
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--bad   { background: var(--bad-bg);      color: var(--bad-ink);       border-color: var(--bad-bd); }
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--ok    { background: var(--ok-bg);       color: var(--ok-ink);        border-color: var(--ok-bd); }
/* A field the person may CLICK to change (the reminder brake). The affordance is the cursor and the hover,
   not a colour — the value's own state already owns the colour above. */
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--action { cursor: pointer; }
.gmp-gform_wrapper .ginput_container input[type="text"].gmp-field--action:hover { border-color: var(--accent); }
/* The form's own title when the record is a CREDIT NOTE (s117). It was `.css("color","red")` from JS —
   inline, unreachable, and the wrong signal: a kreditfaktura is a kind of invoice, not an error, so it
   takes the accent rather than --bad-ink. */
.gmp-gform_wrapper .gform_heading > h2.gform_title.gmp-gform-title--credit { color: var(--accent-strong); }

/* Enhanced select widget — Gravity Perks "Advanced Select" (bundles tom-select with a
   -----------------------------------------------------------------------------
   bootstrap5 theme). Its own frontend.css tries to inherit --gform-theme-control-*
   vars, but we run gform-theme__disable → those vars are unset, so the widget falls
   back to cramped bootstrap5 defaults (14px, 3.75px padding, harsh #686e77 border,
   3px radius, #343a40 ink). Re-skin the control to sit FLUSH with our .ginput_container
   inputs (same 9/11 padding, --border-strong, 7px radius, 15px, --ink) and theme the
   dropdown on tokens. Generic: every entity picker across the app uses this widget.
   Specificity: Perks frontend.css is .ts-control (0,0,1,0); bootstrap5 theme reaches
   ~0,0,3,0 (.ts-wrapper.single.… .ts-control) — scope under .ts-wrapper to clear it. */
.gmp-gform_wrapper .ts-wrapper { width: 100%; min-width: 0; }
.gmp-gform_wrapper .ts-wrapper .ts-control {
  /* padding-right is set by bootstrap5's `.ts-wrapper.single .ts-control` rule with
     !important via these vars (max(--ts-pr-min, --ts-pr-clear-button + --ts-pr-caret)),
     so we can't win it with a plain padding declaration — we drive it through the vars.
     bootstrap ALSO paints its own down-caret at 0,0,5,0 (we don't out-specify it, and it's
     a fine neutral chevron — no point in an arms race for our own), so we just reserve a
     clean ~30px on the right to clear it and zero the (unused) caret/clear-button reserves.
     NB: the zeros MUST carry a unit (0px) — a unitless 0 makes bootstrap's max() mix a length
     with a number → invalid at computed-value time → padding-right silently falls back to 0.
     Use background-COLOR (never the `background` shorthand — that resets background-image and
     would wipe bootstrap's caret). */
  --ts-pr-min: 30px; --ts-pr-caret: 0px; --ts-pr-clear-button: 0px;
  min-height: 38px; padding: 8px 11px; gap: 5px;
  font-size: var(--fs-input); color: var(--ink); background-color: var(--ground);
  border: 1px solid var(--border-strong); border-radius: var(--r); box-shadow: none;
}
.gmp-gform_wrapper .ts-wrapper.focus .ts-control,
.gmp-gform_wrapper .ts-wrapper .ts-control.focus { border-color: var(--accent); box-shadow: var(--ring); }
.gmp-gform_wrapper .ts-wrapper.disabled .ts-control { background: var(--surface-2); color: var(--ink-faint); }
.gmp-gform_wrapper .ts-control > input { font-size: var(--fs-input); color: var(--ink); }
.gmp-gform_wrapper .ts-control > input::placeholder { color: var(--ink-faint); }
/* selected token(s): plain text for single, chips for multi */
.gmp-gform_wrapper .ts-control .item { color: var(--ink); }
.gmp-gform_wrapper .ts-wrapper.multi .ts-control .item {
  background: var(--accent-tint); color: var(--accent-strong);
  border: 1px solid var(--accent); border-radius: var(--r-sm); padding: 1px 7px;
}
/* dropdown panel + options */
.gmp-gform_wrapper .ts-dropdown {
  font-size: var(--fs-input); color: var(--ink); background: var(--ground);
  border: 1px solid var(--border-strong); border-radius: var(--r); box-shadow: var(--shadow-2);
  margin-top: 4px; overflow: hidden;
}
.gmp-gform_wrapper .ts-dropdown .option { padding: 8px 11px; color: var(--ink); }
.gmp-gform_wrapper .ts-dropdown .option.active { background: var(--accent-tint); color: var(--accent-strong); }
.gmp-gform_wrapper .ts-dropdown .option.selected { background: var(--surface); font-weight: 600; }
.gmp-gform_wrapper .ts-dropdown .optgroup-header { font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-muted); background: var(--surface); padding: 6px 11px; }
.gmp-gform_wrapper .ts-dropdown .no-results,
.gmp-gform_wrapper .ts-dropdown .create { color: var(--ink-muted); padding: 8px 11px; }

/* Phone widget — Gravity Perks "Advanced Phone Field" (bundles intl-tel-input v24).
   -----------------------------------------------------------------------------
   The nice case (contrast tom-select): intl-tel-input v24 exposes a clean CSS-variable
   API and consumes it for every painted surface (arrow, borders, dial code, dropdown bg,
   hover). Its frontend.css tries to inherit --gform-theme-* into these, but we run
   gform-theme__disable → they're unset, so it falls back to off-palette defaults (arrow
   #555, border #ccc, dial #999, hover rgba(0,0,0,.05)). We theme it via the widget's own
   var API — the same upgrade-proof "work with the widget" approach as tom-select. The tel
   <input> already gets our .ginput_container skin; intl-tel-input keeps the left padding
   that clears the flag (verified: padL 52px, our 9/11 elsewhere).

   SCOPE EXCEPTION (documented, like DataTables): these rules are NOT under .gmp-gform_wrapper.
   When the country dropdown opens, intl-tel-input builds a SECOND `.iti.iti--container` and
   appends it to <body> (outside every form wrapper), so a wrapper-scoped rule can't reach it.
   The .iti* classes are widget-specific — they never appear on a marketing/landing page — so
   scoping on them directly keeps the same "only paints opted-in nodes" safety as .gmp-*. */
.iti {
  --iti-arrow-color:    var(--ink-muted);
  --iti-border-color:   var(--border-strong);
  --iti-dialcode-color: var(--ink-faint);
  --iti-dropdown-bg:    var(--ground);
  --iti-hover-color:    var(--accent-tint);   /* row hover + keyboard highlight */
  /* the dropdown is appended to <body>, so its rows inherit the THEME's font (Genesis
     Cormorant Garamond 22px serif) — jarring in a sans form. Set our font on the widget
     container; it cascades to the body-mounted .iti--container + every country row. */
  font-family: var(--font-sans);
}
/* the caret triangle: pin the colour explicitly — the border-top shorthand's var() lost to a
   currentColor fallback in the live cascade, so set both orientations' visible edge directly. */
.iti__arrow { border-top-color: var(--ink-muted); }
.iti__arrow--up { border-bottom-color: var(--ink-muted); }
/* country dropdown: match the tom-select panel (radius + elevation + token border).
   Prefixed with `.iti ` (0,0,2,0): iti's own single-class rules (.iti__country padding,
   .iti__dropdown-content radius) tie ours and win on load order (its frontend.css loads
   after design-system.css), so we out-specify with the container class. */
.iti .iti__dropdown-content { color: var(--ink); font-size: var(--fs-input); line-height: 1.45; border: 1px solid var(--border-strong); border-radius: var(--r); box-shadow: var(--shadow-2); overflow: hidden; }
.iti .iti__search-input { font-size: var(--fs-input); color: var(--ink); border: none; border-bottom: 1px solid var(--border); padding: 9px 11px; }
.iti .iti__search-input:focus { outline: none; border-bottom-color: var(--accent); }
.iti .iti__country { padding: 7px 11px; font-size: var(--fs-input); color: var(--ink); }
.iti .iti__country.iti__highlight { color: var(--accent-strong); background: var(--accent-tint); }

/* GravityFlow front-end chrome — typography only (s90, §C.1)
   -----------------------------------------------------------------------------
   `attgora` puts GravityFlow's OWN markup on a client-facing page: the inbox table, the entry-detail
   wrapper, the status box and the approve/reject buttons. None of it is ours, so it inherits the Genesis
   theme — which is how *"Ärendet har fått avslag"* (GravityFlow's own Swedish string) came to render in a
   serif in the middle of a sans application.

   SCOPE EXCEPTION, same bar as DataTables / .iti / #ui-datepicker-div: these `gravityflow*` classes are
   injected by the plugin and never appear on a marketing or landing page, so scoping on them directly keeps
   the "only paints opted-in nodes" safety without needing a wrapper.

   ⚠ TYPOGRAPHY ONLY, deliberately. The rest of §C.1 — suppress-vs-restyle per element for the inbox table,
   sidebar, timeline and workflow_info — is a design decision per element AND partly a CONFIGURATION one
   (the shortcode takes `id_column`, `sidebar`, `timeline`… so some of it should be turned off rather than
   painted). Deciding that inside a font fix is how a font fix becomes a migration. This closes the reported
   symptom and nothing more. */
.gravityflow_wrap,
.gravityflow_workflow_wrap,
.gravityflow_workflow_detail,
.gravityflow-status-box-field,
.gravityflow-action-buttons {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  color: var(--ink);
}
.gravityflow-status-box-field-label { color: var(--ink-muted); font-weight: 600; }
.gravityflow-status-box-field-value { color: var(--ink); }

/* Date picker — jQuery UI `#ui-datepicker-div` (s87)
   -----------------------------------------------------------------------------
   THE app-wide date affordance: every GF `dateType:datepicker` field (24 of them,
   all `ymd_dash`) and — since s87 — the three code-rendered surfaces (DL, AINV,
   board roster) that used to ship a native `<input type=date>`.

   SCOPE EXCEPTION (documented, like DataTables and .iti): jQuery UI appends ONE
   `#ui-datepicker-div` to <body>, outside every form wrapper, so a `.gmp-gform_wrapper`
   rule can never reach it. That is also why `gmpAudit('#gform_wrapper_N')` cannot see
   it — forms 5, 25 and 67 audited 0 for two sessions while their picker was off-palette.
   Audit it by selector directly: `gmpAudit('#ui-datepicker-div')` with the picker open.

   Why an ID and not a class: the widget has exactly one instance, the id is set by
   jQuery UI itself, and GF's vendor sheet paints at 0,0,2,0 (`.gform-legacy-datepicker
   .ui-datepicker`) — an ID is the honest way to win without `!important`. GF's only
   ID-level rule sets `z-index:9999!important`, which we want.

   This is a COMPLETE skin, not a patch on GF's: on the three code-rendered pages there is
   no GF form, so `gforms_datepicker_css` is not enqueued and these rules are the only paint.

   Replaces the legacy `gmp_artist.css` block (Gotham 15/20px, `font-weight:bolder` days,
   `color:red` Sundays, `#F58486` weekend headers, and a `transform:scale(.60)` mobile hack
   that shrank the whole widget instead of sizing it). Two deliberate changes: weekends are
   MUTED, not red — `--bad-ink` means error in this system and a Saturday is not an error —
   and small screens get smaller CELLS rather than a blurry 60% transform. */
#ui-datepicker-div {
  /* jQuery UI writes `display:block` inline when it opens, so this stays the load-flash
     guard the legacy sheet carried (its comment: "a quirk … showing up at page load"). */
  display: none;
  padding: var(--sp-2);
  background: var(--ground);
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  box-shadow: var(--shadow-2);
  font-family: var(--font-sans);
  font-size: var(--fs-14);
  color: var(--ink);
}
/* header: month/year selects centred, arrows pinned to the edges */
#ui-datepicker-div .ui-datepicker-header { position: relative; padding: 0 0 var(--sp-2); background: transparent; border: 0; }
#ui-datepicker-div .ui-datepicker-title { display: flex; gap: var(--sp-2); align-items: center; justify-content: center; margin: 0 30px; line-height: 28px; color: var(--ink); }
#ui-datepicker-div .ui-datepicker-title select { font: inherit; font-size: var(--fs-13); color: var(--ink); background: var(--ground); border: 1px solid var(--border-strong); border-radius: var(--r-sm); padding: 3px 6px; }
#ui-datepicker-div .ui-datepicker-title select:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
/* prev/next: jQuery UI renders TEXT inside `.ui-icon` and relies on a sprite we do not load.
   Same answer as the list +/− button (register row 19): `font-size:0` hides the label from
   sight but not from the a11y tree, and the chevron is DRAWN from two borders — font- and
   sprite-independent, and it inherits a token colour. */
#ui-datepicker-div .ui-datepicker-prev,
#ui-datepicker-div .ui-datepicker-next { position: absolute; top: 0; width: 28px; height: 28px; border-radius: var(--r-sm); cursor: pointer; font-size: 0; color: var(--ink-muted); text-decoration: none; }
#ui-datepicker-div .ui-datepicker-prev { left: 0; }
#ui-datepicker-div .ui-datepicker-next { right: 0; }
#ui-datepicker-div .ui-datepicker-prev:hover,
#ui-datepicker-div .ui-datepicker-next:hover { background: var(--accent-tint); }
#ui-datepicker-div .ui-datepicker-prev.ui-state-disabled,
#ui-datepicker-div .ui-datepicker-next.ui-state-disabled { opacity: .4; cursor: default; background: transparent; }
#ui-datepicker-div .ui-datepicker-prev .ui-icon,
#ui-datepicker-div .ui-datepicker-next .ui-icon { position: absolute; top: 50%; left: 50%; width: 7px; height: 7px; background: none; text-indent: 0; overflow: hidden; border: solid var(--ink-muted); border-width: 0 0 2px 2px; }
#ui-datepicker-div .ui-datepicker-prev .ui-icon { margin: -4px 0 0 -2px; transform: rotate(45deg); }
#ui-datepicker-div .ui-datepicker-next .ui-icon { margin: -4px 0 0 -6px; transform: rotate(-135deg); }
/* the grid */
#ui-datepicker-div table.ui-datepicker-calendar { width: 100%; margin: 0; border-collapse: collapse; font-size: var(--fs-14); }
#ui-datepicker-div .ui-datepicker-calendar th { padding: 5px 0; background: transparent; border: 0; font-size: var(--fs-12); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-faint); }
/* The theme paints `tbody{border-bottom:1px solid #ddd}` (register row 21) and `a{color:#00a0af}`
   globally. Inside a GF form the vendor datepicker sheet happens to mask both; on the three
   code-rendered pages there is no vendor sheet, so they came through — the picker audited 0 on
   form 73 and 5 on skapa-styrelse (s87). This is what "a COMPLETE skin, not a patch" has to mean. */
#ui-datepicker-div .ui-datepicker-calendar tbody { border-bottom: 0; }
#ui-datepicker-div .ui-datepicker-calendar td { padding: 1px; border: 0; color: var(--ink); }
#ui-datepicker-div .ui-datepicker-calendar td a,
#ui-datepicker-div .ui-datepicker-calendar td span { display: block; width: 32px; line-height: 30px; text-align: center; border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--ink); font-weight: 400; text-decoration: none; }
#ui-datepicker-div .ui-datepicker-calendar td a:hover { background: var(--accent-tint); color: var(--accent-strong); }
#ui-datepicker-div .ui-datepicker-calendar td a.ui-state-active { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
#ui-datepicker-div .ui-datepicker-calendar td a.ui-state-highlight { border-color: var(--accent); color: var(--accent-strong); }
#ui-datepicker-div .ui-datepicker-calendar td.ui-datepicker-week-end a { color: var(--ink-muted); }
#ui-datepicker-div .ui-datepicker-calendar td.ui-datepicker-unselectable span,
#ui-datepicker-div .ui-datepicker-calendar td.ui-state-disabled span,
#ui-datepicker-div .ui-datepicker-calendar td.ui-datepicker-other-month span { color: var(--ink-faint); }
/* small screens: smaller cells, not a scaled-down widget */
@media (max-width: 760px) {
  #ui-datepicker-div .ui-datepicker-calendar td a,
  #ui-datepicker-div .ui-datepicker-calendar td span { width: 28px; line-height: 26px; }
}

/* File-upload widget — Gravity Perks "File Upload Pro" (.gpfup__*).
   -----------------------------------------------------------------------------
   The hard case (like tom-select): NO CSS-var API — the plugin hardcodes its colours
   (droparea rgba(0,0,0,.02)/dashed .15/#666, #999 filesize, #790000 error, #3498db
   progress), and the "Välj filer" button's LEGACY BRAND TEAL #00a0af comes from OUR OWN
   gmp_artist.css (span.gpfup__select-files-container > button, 0,0,2,1) + it inherits the
   theme's Quicksand. Re-skin onto tokens. Scoped under .gmp-gform_wrapper (widget is inline
   in the field, not body-mounted): form-5-only, so other forms keep the legacy teal until
   they migrate (shed the gmp_artist.css rule then). The token rules out-specify: droparea
   0,0,2,0 > gpfup 0,0,1,0; button 0,0,3,1 > legacy 0,0,2,1. */
.gmp-gform_wrapper .gpfup__droparea { background: var(--surface); border: 1px dashed var(--border-strong); border-radius: var(--r); color: var(--ink-muted); }
.gmp-gform_wrapper .gpfup__droparea--over { background: var(--accent-tint); border-color: var(--accent); color: var(--ink); }
.gmp-gform_wrapper .gpfup__select-files-container { color: var(--ink-muted); }
/* the select-files button → our secondary-button look (kills #00a0af + Quicksand) */
.gmp-gform_wrapper span.gpfup__select-files-container > button {
  font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; text-transform: uppercase; letter-spacing: .035em;
  background-color: var(--surface); color: var(--ink); border: 1px solid var(--border-strong); border-radius: var(--r); padding: 9px 15px;
}
.gmp-gform_wrapper span.gpfup__select-files-container > button:hover { background-color: var(--surface-2); }
/* uploaded-file list: dividers, meta, error, progress, delete icon.
   .gpfup__file sets no font-size → the filename/size inherit the form's ~15px (reads a touch
   large). Give the row a 14px base + a smaller 12px size line so the meta has a clear hierarchy. */
.gmp-gform_wrapper .gpfup__file { font-size: var(--fs-14); color: var(--ink); }
.gmp-gform_wrapper .gpfup__file:not(:last-of-type) { border-bottom-color: var(--border); }
/* s111: the list's own frame — GPFUP paints it rgba(0,0,0,.1). Seen only when a refused form redisplays its files
   (the kvitton duplicate question), a state the s106/s107 audits never reached. */
.gmp-gform_wrapper .gpfup__files { border-color: var(--border); }
.gmp-gform_wrapper .gpfup__filesize { color: var(--ink-faint); font-size: var(--fs-12); }
.gmp-gform_wrapper .gpfup__file-error { color: var(--bad-ink); }
.gmp-gform_wrapper .gpfup_progress { background: var(--accent); }
.gmp-gform_wrapper .gpfup__delete svg { fill: var(--ink-muted); }

/* sections → quiet divider + accent eyebrow.
   GF's foundation theme paints an unguarded 1px rgba(104,110,119,.35) border-BOTTOM on
   .gfield--type-section (a hairline under every section), which out-specifies our plain
   .gsection `border:none`. We want ONLY our top divider, so kill the bottom with the doubled
   wrapper + the type class (0,0,4,0, beats it) across all 7 form-5 sections. */
.gmp-gform_wrapper .gsection { grid-column: span 12; border: none; border-top: 1px solid var(--border); margin: var(--sp-3) 0 0; padding: var(--sp-4) 0 0; }
.gmp-gform_wrapper.gform_wrapper .gfield--type-section.gsection { border-bottom: 0 none; }
/* 🔑 `.gmp-paneltitle` shares this rule ON PURPOSE (s119, register row 44). A heading the SERVER injects
   above a panel inside a skinned form — the owners/GA/invoice/letter/update tables on forms 8 and 42 — is
   the same thing as a section heading, so it gets the same eyebrow rather than a lookalike of its own.
   One rule, one look; a second set of declarations is how two headings drift apart. */
.gmp-gform_wrapper .gsection_title, .gmp-gform_wrapper .gmp-paneltitle { font-family: var(--font-sans); font-size: var(--fs-th); text-transform: uppercase; letter-spacing: .08em; color: var(--accent); font-weight: 650; margin: 0; }
.gmp-gform_wrapper .gmp-paneltitle { margin: var(--sp-3) 0 var(--sp-2); }
/* The one panel title that is also a control (Visa/Göm fastighetsinfo). It must read as clickable without
   becoming the theme's teal link, and it keeps the eyebrow's colour — so: the affordance is the underline
   on hover and the pointer, not a second colour. */
.gmp-gform_wrapper .gmp-paneltitle__toggle { color: inherit; text-decoration: none; cursor: pointer; border-bottom: 1px dashed currentColor; }
.gmp-gform_wrapper .gmp-paneltitle__toggle:hover, .gmp-gform_wrapper .gmp-paneltitle__toggle:focus-visible { color: var(--accent-strong); border-bottom-style: solid; }
.gmp-gform_wrapper .gsection .gsection_description { font-size: var(--fs-label); color: var(--ink-muted); margin-top: 3px; }

/* GF renders choice fields (checkbox/radio) as <fieldset> — strip the browser/theme frame AND the
   legacy teal `.readybox` 3px frame (on Klarmarkera) so they read as the clean rows the skin defines,
   not a boxed fieldset. fieldset.gfield (0,0,2,1) out-specifies .readybox / .gform-theme--foundation
   fieldset / the theme's bare fieldset. Scoped: un-migrated forms keep their frame until they adopt gmp-gform. */
.gmp-gform_wrapper fieldset.gfield { border: none; padding: 0; margin: 0; min-width: 0; }
/* radio + checkbox lists */
/* GF framework forces the choice list to flex-direction:column (3-class rule, no gform-theme__disable guard)
   → options stack vertically. Beat it at 0,0,4,0 (.gfield--type-choice is on both radio & checkbox fieldsets)
   and force a horizontal wrapping row. */
.gmp-gform_wrapper.gform_wrapper .gfield--type-choice .gfield_radio, .gmp-gform_wrapper.gform_wrapper .gfield--type-choice .gfield_checkbox { display: flex; flex-direction: row; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); margin: 0; padding: 0; list-style: none; }
/* GF's framework rule `.gform-theme--framework .gfield--type-choice .gchoice{display:inline-grid}` forces each
   choice to the field's full width → 5 options stack in 5 rows. That rule LACKS the gform-theme__disable guard,
   so we out-specify it by doubling the wrapper class (.gmp-gform_wrapper.gform_wrapper = 0,0,4,0 > its 0,0,3,0):
   make each choice a content-width flex pill so the group flows inline + wraps. (Reusable trick for stray
   framework rules that slip past gform-theme__disable.) */
.gmp-gform_wrapper.gform_wrapper .gfield_radio .gchoice, .gmp-gform_wrapper.gform_wrapper .gfield_checkbox .gchoice { display: flex; align-items: center; gap: 7px; width: auto; }
.gmp-gform_wrapper .gchoice label { font-size: var(--fs-14); color: var(--ink); font-weight: 500; margin: 0; }
.gmp-gform_wrapper input[type="checkbox"], .gmp-gform_wrapper input[type="radio"] { accent-color: var(--accent); width: 16px; height: 16px; flex: none; }
/* a lone-checkbox field styled as a switch-row (opt in with cssClass "gmp-gform-switchrow") */
.gmp-gform_wrapper .gmp-gform-switchrow .gfield_label { display: none; }

/* Confirm-before-submit CHECK ROW — a clean box per action, opt in with cssClass "gmp-gform-checkrow".
   Used for the invoice finalize/credit/copy boxes grouped just above the footer. Hides the per-box
   legend header; the choice becomes a bordered row (checkbox + short bold label), with an optional
   one-line muted hint (the field description). The `.gmp-checkgroup` label above the first box (a tiny
   section eyebrow) is optional. */
.gmp-gform_wrapper .gmp-gform-checkrow > .gfield_label { display: none; }
.gmp-gform_wrapper .gmp-gform-checkrow > .ginput_container { margin-top: 0; }
.gmp-gform_wrapper .gmp-gform-checkrow .gfield_checkbox { margin: 0; padding: 0; display: block; }
/* QUESTION FIELD — a field the SERVER asks for on a refused submit (s106, the kvitton duplicate explanation), opt in
   with cssClass "gmp-gform-askfirst". The question must be read before the box is filled, so the validation message
   moves up under the label (the field is a flex column); the box is sized for a sentence, not an essay. */
.gmp-gform_wrapper .gmp-gform-askfirst > .gfield_label { order: -2; }
.gmp-gform_wrapper .gmp-gform-askfirst > .validation_message { order: -1; padding-top: 0; }
/* ⚠ measured: GF foundation's `textarea.large` sets a 180px MIN block size (not guarded by gform-theme__disable), so a
   plain `height` loses — the doubled wrapper (rows 8, 11, 12) sets both. */
.gmp-gform_wrapper.gform_wrapper .gmp-gform-askfirst .ginput_container textarea { min-height: 82px; min-block-size: 82px; height: 82px; }
.gmp-gform_wrapper.gform_wrapper .gmp-gform-checkrow .gfield_checkbox .gchoice {
  display: flex; align-items: center; gap: 11px; width: 100%; margin: 0;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface); transition: border-color .14s ease, background .14s ease;
}
.gmp-gform_wrapper .gmp-gform-checkrow .gchoice:hover { border-color: var(--border-strong); background: var(--surface-2); }
.gmp-gform_wrapper .gmp-gform-checkrow .gchoice label { font-weight: 600; font-size: var(--fs-14); color: var(--ink); margin: 0; cursor: pointer; }
.gmp-gform_wrapper .gmp-gform-checkrow input[type="checkbox"] { width: 18px; height: 18px; flex: none; }
/* checked box gets an accent frame so a ticked confirmation reads at a glance */
.gmp-gform_wrapper .gmp-gform-checkrow .gchoice:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); }
/* optional one-line hint under a box (field description), aligned under the label */
.gmp-gform_wrapper .gmp-gform-checkrow .gfield_description { color: var(--ink-muted); font-size: var(--fs-12); margin: 5px 0 0 43px; padding: 0; }

/* GF "ready-class" alert blocks — interaction-matrix pass #2 (s61).
   -----------------------------------------------------------------------------
   .gf_alert_green / .gf_alert_red / .gf_alert_yellow are Gravity Forms legacy
   "ready classes" (defined in GF's basic.min.css). They paint an off-palette
   slab (green #cbeca0, bright red, yellow) with a text-shadow — and their base
   selector is UNGUARDED by gform-theme__disable, so they leak into every skinned
   form (same failure mode as the choice-group flex rules). They're JS-toggled
   info blocks: form 5's field 13 reveals inject email/SMS/KIVRA feedback here
   (Helper.ShowInvoiceTypeSupportingFields); also used on forms 3/16/41 and the
   users.js reg-code messages. One generic rule maps all three onto the token
   notice look.
   SPECIFICITY: the winning legacy rule is GF's FOUNDATION theme (NOT basic.css):
   `.gform-theme--foundation .gfield.gfield_html.gf_alert_green` = 0,0,4,0, and
   it is UNGUARDED by gform-theme__disable (same escape-hatch story as the choice
   groups). We beat it by mirroring GF's own class chain (.gfield.gfield_html.
   gf_alert_*) under the DOUBLED wrapper (.gmp-gform_wrapper.gform_wrapper) →
   0,0,5,0, no !important needed for colour/border/bg. GF's basic.css layout rule
   sets margin/padding with !important, so those two answer with tokenized
   !important — the only place it's required. */
.gmp-gform_wrapper.gform_wrapper .gfield.gfield_html.gf_alert_green,
.gmp-gform_wrapper.gform_wrapper .gfield.gfield_html.gf_alert_red,
.gmp-gform_wrapper.gform_wrapper .gfield.gfield_html.gf_alert_yellow {
  border: 1px solid; border-radius: var(--r); text-shadow: none;
  font-size: var(--fs-14); line-height: 1.45;
  margin: var(--sp-3) 0 !important; padding: 11px 14px !important;
}
.gmp-gform_wrapper.gform_wrapper .gfield.gfield_html.gf_alert_green  { color: var(--ok-ink);   background: var(--ok-bg);   border-color: var(--ok-bd); }
.gmp-gform_wrapper.gform_wrapper .gfield.gfield_html.gf_alert_red    { color: var(--bad-ink);  background: var(--bad-bg);  border-color: var(--bad-bd); }
.gmp-gform_wrapper.gform_wrapper .gfield.gfield_html.gf_alert_yellow { color: var(--warn-ink); background: var(--warn-bg); border-color: var(--warn-bd); }

/* GF foundation theme paints a couple of small text bits off-palette; our base
   rules tie on specificity and lose on load order (foundation loads after us), so
   answer with the doubled wrapper. Surfaced by js/dev/audit-tokens.js on form 5:
   the char counter (Perks textarea limit) and the required-field legend/asterisk. */
.gmp-gform_wrapper.gform_wrapper .ginput_counter { color: var(--ink-faint); }
/* s124 (entity walk I-V2, register row 43): a form in VIEW mode (`.gmp-view`, set by the entity's view setter) has nothing to type, so no
   "0 av 50 maximalt antal tecken" under each read-only field. Generic — any entity that marks its view gets it. */
.gmp-gform_wrapper.gform_wrapper.gmp-view .ginput_counter { display: none; }
.gmp-gform_wrapper.gform_wrapper .gform_required_legend .gfield_required,
.gmp-gform_wrapper.gform_wrapper .gfield_required { color: var(--bad-ink); }

/* validation — reuse the notice look, no default red slab */
/* 🔴 The validation SUMMARY sits OUTSIDE the <form> — a direct child of the wrapper — so `gform-theme__disable` (which
   excludes only descendants of the form) does not reach it, and GF's framework rules `.gform-theme--framework
   .gform_validation_errors` (0,0,2,0) and `… .gform-icon` (0,0,3,0) tied with these and won on load order: every refused
   submit painted GF's red rgb(192,43,10) (found s102 auditing form 38's refused state; register row 29). The doubled
   wrapper is one class stronger — the house answer for unguarded GF rules (rows 8, 11, 12). No !important. */
.gmp-gform_wrapper.gform_wrapper .gform_validation_errors { border: 1px solid var(--bad-bd); background: var(--bad-bg); border-radius: var(--r); padding: 12px 14px; margin-bottom: var(--sp-4); box-shadow: none; }
.gmp-gform_wrapper.gform_wrapper .gform_validation_errors:focus { border-color: var(--bad-bd); outline: 2px solid var(--bad-bd); outline-offset: 2px; }
.gmp-gform_wrapper.gform_wrapper .gform_validation_errors .gform_submission_error { color: var(--bad-ink); font-family: var(--font-sans); font-size: var(--fs-body); font-weight: 680; display: flex; flex-direction: row; align-items: center; gap: 8px; margin: 0; }
.gmp-gform_wrapper.gform_wrapper .gform_validation_errors .gform-icon { color: var(--bad-ink); background-color: transparent; border-color: var(--bad-bd); }
.gmp-gform_wrapper.gform_wrapper .gform_validation_errors ol, .gmp-gform_wrapper.gform_wrapper .gform_validation_errors ul { margin: 8px 0 0; padding-left: 20px; color: var(--bad-ink); font-size: var(--fs-label); }
.gmp-gform_wrapper .gfield_error .gfield_label { color: var(--bad-ink); }
.gmp-gform_wrapper .gfield_error .ginput_container input, .gmp-gform_wrapper .gfield_error .ginput_container select, .gmp-gform_wrapper .gfield_error .ginput_container textarea { border-color: var(--bad-bd); background: var(--bad-bg); }
.gmp-gform_wrapper .validation_message { color: var(--bad-ink); font-size: var(--fs-12); font-weight: 600; padding-top: 4px; }

/* footer — GF submit + the custom action buttons, mapped to the button system.
   Default = primary (accent); semantic variants keyed off GF/custom button classes. */
.gmp-gform_wrapper .gform_footer, .gmp-gform_wrapper .gform_page_footer { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--border); }
.gmp-gform_wrapper .gform_footer input[type="submit"],
.gmp-gform_wrapper .gform_footer button,
.gmp-gform_wrapper .gform_page_footer input[type="submit"],
.gmp-gform_wrapper .gform_page_footer button {
  font: inherit; font-weight: 600; font-size: var(--fs-13); line-height: 1; text-transform: uppercase; letter-spacing: .035em;
  cursor: pointer; border-radius: var(--r); padding: 11px 17px; border: 1px solid transparent;
  background: var(--accent); color: var(--accent-ink); white-space: nowrap;
  /* neutralize the shared legacy button class rule (.cancel_button/.credinv_button/… — no _5 suffix,
     can't be deleted while other forms use it): kill its float:right + margin-left:8px leak. flex gap spaces us. */
  float: none; margin: 0;
  /* the Genesis child theme sets a bare `input{width:100%}` — that stretches the submit <input> full-width
     (the custom <button> actions aren't affected). Force content width so all footer actions sit on one row. */
  width: auto;
  transition: background .14s ease, border-color .14s ease, transform .05s ease;
}
.gmp-gform_wrapper .gform_footer input[type="submit"]:hover,
.gmp-gform_wrapper .gform_footer button:hover { background: var(--accent-strong); }
.gmp-gform_wrapper .gform_footer input[type="submit"]:active,
.gmp-gform_wrapper .gform_footer button:active { transform: translateY(1px); }
.gmp-gform_wrapper .gform_footer input[type="submit"]:focus-visible,
.gmp-gform_wrapper .gform_footer button:focus-visible { outline: none; box-shadow: var(--ring); }
/* button ROLE is carried in GF's button id (gform_<role>_button_<formId>) — the buttons often
   have only class "gform_button button" (no .credinv_button/.delete_button class), so key off the
   id substring. Scoped under .gform_footer so these out-specify the default (primary) rule above. */
/* secondary actions (copy, credit-note, cancel, change-contact, pdf, view-uploads) */
.gmp-gform_wrapper .gform_footer [id*="copyinv_button"], .gmp-gform_wrapper .gform_footer [id*="credinv_button"],
.gmp-gform_wrapper .gform_footer [id*="cancel_button"], .gmp-gform_wrapper .gform_footer [id*="changecontact_button"],
.gmp-gform_wrapper .gform_footer [id*="pdflink_button"], .gmp-gform_wrapper .gform_footer [id*="viewuploads_button"],
.gmp-gform_wrapper .gform_footer [id*="sendletter_button"] {   /* s135: "Skicka ett brev" opens a modal — a secondary action beside Spara */
  background: var(--surface); color: var(--ink); border-color: var(--border-strong);
}
.gmp-gform_wrapper .gform_footer [id*="copyinv_button"]:hover, .gmp-gform_wrapper .gform_footer [id*="credinv_button"]:hover,
.gmp-gform_wrapper .gform_footer [id*="cancel_button"]:hover, .gmp-gform_wrapper .gform_footer [id*="changecontact_button"]:hover,
.gmp-gform_wrapper .gform_footer [id*="pdflink_button"]:hover, .gmp-gform_wrapper .gform_footer [id*="viewuploads_button"]:hover,
.gmp-gform_wrapper .gform_footer [id*="sendletter_button"]:hover { background: var(--surface-2); }
/* destructive (delete) — s135: the "stop letter" button left with the letter section of forms 3/24 */
.gmp-gform_wrapper .gform_footer [id*="delete_button"] {
  background: transparent; color: var(--bad-ink); border-color: var(--bad-bd);
}
.gmp-gform_wrapper .gform_footer [id*="delete_button"]:hover { background: var(--bad-bg); }

/* HTML-block fields are structural wrappers (the repeater in field 4; legacy layout wrappers like
   form 5's field 29 that opens a <div> floating the totals+checkboxes into a 40% right column). The
   base .gfield rule makes every field a flex column — that would collapse those float-based layouts to
   the left, so HTML blocks stay display:block and let their own content flow (floats included). */
.gmp-gform_wrapper .gfield--type-html { margin: 0; display: block; }
/* s124 (entity walk, register row 42): the SUMMARY COLUMN — an HTML-block wrapper whose child fields (the totals) sit in a
   40% column on the right. Replaces form 5's `#field_5_29 > .gfield` legacy rule; opt in with cssClass `gmp-gform-sumcol`
   on the wrapper field. The other forms still on the legacy list (9/16/41/43/70) move here when they are skinned. */
.gmp-gform_wrapper .gmp-gform-sumcol > .gfield { width: 40%; float: right; clear: right; }

/* ── acting-household banner (§6.1b.4) ────────────────────────────────────────────────────────────
   Class-scoped like everything else here. The REPRESENTING state is deliberately the loudest thing on
   the page: it is the one piece of chrome whose whole job is to stop someone acting on the wrong
   household, and chrome that blends in has already failed at that. The self/choose states are quiet by
   design — a switch you can find, not a warning you learn to ignore. */
.gmp-acting { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center;
  padding: 9px 14px; font-size: var(--fs-14); border: 1px solid; border-radius: var(--r); margin: 0 0 var(--sp-3); }
.gmp-acting__ic { font-weight: 700; flex: none; }
.gmp-acting__who { flex: 1 1 auto; min-width: 0; }
.gmp-acting__form { display: flex; gap: var(--sp-2, 6px); align-items: center; margin: 0; }
.gmp-acting__form select { max-width: 100%; }
.gmp-acting--representing { color: var(--warn-ink); background: var(--warn-bg); border-color: var(--warn-bd); font-weight: 600; }
.gmp-acting--choose { color: var(--info-ink); background: var(--info-bg); border-color: var(--info-bd); }
.gmp-acting--self { color: var(--ink); background: var(--surface-2); border-color: var(--border); }

/* ── locked fields (s84) ─────────────────────────────────────────────────────────────────────────
   A control the acting user may not change: still readable, visibly not theirs to edit. The list is
   decided SERVER-side (AjaxGuard::WritableFields → RetrieveStaffData_AJAX → LockUneditableFields);
   this is only how it looks. Enforcement never depends on this rule existing. */
.gmp-locked,
input.gmp-locked,
select.gmp-locked {
	background: var(--surface-2, #f4f6f7);
	color: var(--text-muted, #6b7780);
	border-style: dashed;
	cursor: not-allowed;
}
.gmp-locked:focus {
	outline: none;
	box-shadow: none;
}

/* ── the theme header on application pages (s84, user) ────────────────────────────────────────────
   Genesis renders its site header on every page. It used to carry WordPress's stock "Arkiv /
   Kategorier" block widgets — demo content that bled onto every application screen — and with those
   cleared it is an empty 66px black band.

   The system menu IS this application's navigation, so on an app page the theme header has nothing to
   say. `gmp-app-page` is set from the CLIENT'S OWN role/access matrix (wpgmp_main/system-menu.php), so
   anonymous pages — logga-in, register, begär-tillgång, where no system menu is drawn — keep theirs. */
body.gmp-app-page .site-header { display: none; }

/* ── Attest step block (s92) ──────────────────────────────────────────────
   The evidence an attestant reads beside Gravity Flow's approve/reject buttons
   (AttestStepBlock, docs/attest-surface-design.md §4). Almost all of its paint
   comes from .gmp-panel / .gmp-table / .gmp-notice / .gmp-chip already — the
   block opts in by wrapping itself in .gmp-app — so only the embedded PDF
   viewer needs rules of its own: an <object> has no intrinsic height and
   collapses to nothing without one. */
.gmp-attestblock__doc { margin-top: var(--sp-3); }
.gmp-attestblock__doc:first-of-type { margin-top: 0; }
.gmp-attestblock__pdf {
  display: block; width: 100%; height: 62vh; min-height: 320px; max-height: 780px;
  margin-top: var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface);
}
/* On a phone the embedded viewer is worse than useless — it eats the screen and
   scroll-traps the page. Shrink it to a preview; "Öppna i ny flik" is the real
   affordance there, and it is always rendered beside it. */
/* s106: a photographed receipt — the image at its own proportions, capped so a tall one does not fill the page. */
.gmp-attestblock__img {
  display: block; max-width: 100%; height: auto; max-height: 780px;
  margin-top: var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface);
}
@media (max-width: 700px) {
  .gmp-attestblock__pdf { height: 34vh; min-height: 200px; }
  .gmp-attestblock__img { max-height: 50vh; }
}

/* Conversation on an attest task (s92) — questions to board colleagues and their answers.
   Components do the work (.gmp-panel / .gmp-input / .gmp-btn / .gmp-chip); these rules only
   give the thread its indentation and rhythm. */
.gmp-attestblock__qa { border-left: 3px solid var(--border-strong); padding-left: var(--sp-3); margin: var(--sp-3) 0; }
.gmp-attestblock__qa blockquote { margin: 0 0 var(--sp-2); padding: 0; border: none; font-style: normal; color: var(--ink); }
.gmp-attestblock__qa blockquote.gmp-attestblock__answer { color: var(--ink); background: var(--surface); border-radius: var(--r); padding: 9px 12px; }
.gmp-attestblock__qa p { margin: 0 0 var(--sp-1); }
.gmp-attestblock__ask, .gmp-attestblock__answerform { margin-top: var(--sp-3); display: grid; gap: var(--sp-2); }
.gmp-attestblock__ask select.gmp-input, .gmp-attestblock__ask textarea.gmp-input,
.gmp-attestblock__answerform textarea.gmp-input, .gmp-attestblock__answerform input.gmp-input { width: 100%; }
.gmp-attestblock__ask button, .gmp-attestblock__answerform button { justify-self: start; }
.gmp-attestblock__src { border: 1px solid var(--border); border-radius: var(--r); padding: var(--sp-2) var(--sp-3); display: grid; gap: 6px; }
.gmp-attestblock__src legend { font-size: var(--fs-label); color: var(--ink-muted); padding: 0 4px; }
.gmp-attestblock__src label { display: flex; align-items: center; gap: 7px; font-size: var(--fs-14); }
.gmp-attestblock__msg:empty { display: none; }

/* ── Two named lists under one page (s93) ─────────────────────────────────────────────────────────
   `attgora` carries two things addressed to you that are NOT the same kind of thing: Gravity Flow tasks
   you must decide, and questions you must answer. They cannot share a table (a question is not a GF task
   — §3.1), so the page must make "two sections, one heading each" legible at a glance. Generic, because
   the next surface that stacks two lists should not invent a third heading style. */
.gmp-listsection { margin-bottom: var(--sp-5); }
.gmp-listsection__title { font-family: var(--font-sans); font-size: var(--fs-19); font-weight: 650; color: var(--ink); margin: 0 0 var(--sp-1); display: flex; align-items: center; gap: var(--sp-2); }
.gmp-listsection__lead { font-size: var(--fs-14); color: var(--ink-muted); margin: 0 0 var(--sp-3); }

/* ── "Frågor till mig" — the questions list on `attgora` (s93) ─────────────────────────────────────
   A question is not a GravityFlow task and cannot appear in the inbox table above this, so it gets a
   list of its own. Its reader is often someone with an EMPTY inbox — they are not in the approval chain
   — so this panel has to read as a destination in its own right, not as an afterthought below a table.
   Everything here is token-only; the panel opts in via `.gmp-app` like every other code-owned surface. */
/* 🔑 `font-family` on .gmp-listsection__title is NOT redundant. `.gmp-app` sets the sans stack, but the
   theme styles `h2` DIRECTLY, and a rule on the element beats a font INHERITED from an ancestor — so the
   heading came back Quicksand while everything around it was on the system stack. Caught by gmpAudit's
   type check in the s93 walk, not by looking; same cause and same fix as `.gform_title` in s62. */
.gmp-questions__item {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--r);
  background: var(--ground);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-3);
}
/* The `?fraga=<id>` deep-link target. A mail says "someone asked you something"; landing on a list of
   four and hunting for which one is a small failure the link is supposed to prevent. */
.gmp-questions__item.is-focused { border-left-color: var(--accent-strong); box-shadow: var(--ring); }
.gmp-questions__meta { font-size: var(--fs-13); color: var(--ink-muted); margin: 0 0 var(--sp-2); }
.gmp-questions__q {
  margin: 0; padding: 0 0 0 var(--sp-3);
  border: none; border-left: 3px solid var(--border-strong);
  font-style: normal; color: var(--ink); font-size: var(--fs-body);
}

/* 🔑 The theme hangs a decorative “ on EVERY blockquote (parallax-pro style.css:237 — `content:"\201C"`,
   30px, pulled out to the left). On a marketing page that is editorial styling and stays. Inside an app
   component a quoted question is DATA, and a 30px curly quote reads as decoration on something nobody
   decorated. Found in the s93 browser walk — and it was already doing this to the s92 step block's
   question and answer, which is why both are neutralised here rather than one.
   Class-scoped, so the theme keeps its decoration everywhere it belongs. */
.gmp-questions__q::before,
.gmp-attestblock__qa blockquote::before { content: none; }

/* The count beside the heading. Same shape as the menu badge, different palette: that one sits on the
   dark platform bar and owns its own colours, this one lives in app content and takes the tokens. */
.gmp-badge {
  display: inline-block; min-width: 20px; padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
  font-family: var(--font-sans);   /* it can sit inside any heading — do not inherit that heading's face */
  font-size: var(--fs-12); font-weight: 700; line-height: 18px; text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ── GmpVoucherRows — the kontering grid (s109, T1(a); js/voucher-rows.js) ─────────────────────────────────
   Rows of compact inputs, typed inline; the house input/select look at a denser size so a voucher's rows sit
   close together. Class-scoped: nothing here reaches an element that has not opted in. */
.gmp-vrows { font-family: var(--font-sans); color: var(--ink); }
.gmp-vrows__scroll { overflow-x: auto; }
.gmp-vrows__table { width: 100%; border-collapse: collapse; font-size: var(--fs-table); }
.gmp-vrows__th { text-align: left; font-size: var(--fs-th); font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-muted); padding: 0 6px 6px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.gmp-vrows__th--money { text-align: right; }
.gmp-vrows__th--x { width: 28px; }
.gmp-vrows__cell { padding: 4px 6px 2px; vertical-align: top; }
/* s111 (the kvitton Kontera walk): outside the verifikationer page the THEME's table rules reach the grid — #ddd borders
   on tbody and every cell. The grid's rows are separated by space, not lines; only its foot keeps a rule. */
.gmp-vrows__table > tbody, .gmp-vrows__table > tbody > tr > td { border: 0; }
/* s111 (roadmap "minimum column widths", user s109): widths alone let GrullCo's extra columns squeeze konto/debet/kredit
   to nothing — a table cell's width is a suggestion. The minimums hold them; the scroll wrapper takes the overflow. */
.gmp-vrows__cell--account { width: 150px; min-width: 120px; }
.gmp-vrows__cell--money { width: 130px; min-width: 110px; }
.gmp-vrows__cell--select { width: 140px; min-width: 120px; }
.gmp-vrows__cell--text { min-width: 180px; }   /* the free text must stay typeable when the grid is narrow — the table scrolls instead */
.gmp-vrows__cell--x { width: 28px; padding-top: 8px; }
.gmp-vrows .gmp-vrows__in { font-size: var(--fs-14); padding: 6px 8px; }
.gmp-vrows .gmp-vrows__in[aria-invalid="true"] { border-color: var(--bad-ink); }
.gmp-vrows .gmp-vrows__in[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--bad-bg); }
.gmp-vrows__hint { display: block; min-height: 16px; font-size: var(--fs-12); color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.gmp-vrows__msg { display: block; font-size: var(--fs-12); color: var(--bad-ink); }
.gmp-vrows__msg:empty { display: none; }
.gmp-vrows__rm { font-family: var(--font-sans); border: 0; background: transparent; color: var(--ink-faint); font-size: 18px; line-height: 1; cursor: pointer; padding: 2px 4px; border-radius: var(--r-sm); }
.gmp-vrows__rm:hover { color: var(--bad-ink); background: var(--bad-bg); }
/* s125 (T1(c)): a row the SYSTEM owns (the supplier debt on form 25) and a read-only grid (View) — shown, not typed in */
.gmp-vrows .gmp-vrows__row.is-locked .gmp-vrows__in,
.gmp-vrows.is-readonly .gmp-vrows__in { background: var(--surface-2); color: var(--ink-muted); border-color: transparent; cursor: default; }
.gmp-sinv-kontering .gmp-toolbar { margin-top: var(--sp-2); }
.gmp-vrows__foot td { padding: 8px 6px 0; border-top: 1px solid var(--border); font-weight: 650; }
.gmp-vrows__sumlabel { color: var(--ink-muted); font-size: var(--fs-13); }
.gmp-vrows__sum { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; padding-right: 15px; }
.gmp-vrows__diff { margin-top: var(--sp-2); text-align: right; font-size: var(--fs-13); font-weight: 650; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.gmp-vrows__diff.is-off { color: var(--bad-ink); }
.gmp-vrows__diff.is-ok { color: var(--ok-ink); }
/* s126 — the row's links on a line of their own (the user: the grid got too wide). A small toggle in the row; the line spans the
   table under it, its fields in a wrapping grid. `has-links` accents a closed toggle that is not empty. */
.gmp-vrows__th--more, .gmp-vrows__cell--more { width: 1%; white-space: nowrap; }
.gmp-vrows__cell--more { padding-top: 7px; }
.gmp-vrows__more { font: inherit; font-size: var(--fs-12); font-weight: 600; color: var(--ink-muted); background: transparent; border: 1px solid var(--border); border-radius: var(--r-sm); padding: 3px 8px; cursor: pointer; white-space: nowrap; }
.gmp-vrows__more::after { content: " ▸"; }
.gmp-vrows__more[aria-expanded="true"]::after { content: " ▾"; }
.gmp-vrows__more:hover { color: var(--accent); border-color: var(--accent); }
.gmp-vrows__more.has-links { color: var(--accent); border-color: var(--accent); background: var(--accent-tint); }
.gmp-vrows__detail[hidden] { display: none; }
.gmp-vrows__detailcell { padding: 2px 6px 10px; }
.gmp-vrows__links { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--sp-2) var(--sp-3); padding: var(--sp-2) var(--sp-3); background: var(--surface-2); border-radius: var(--r); }
.gmp-vrows__link > span:first-child { font-size: var(--fs-12); }
.gmp-vrows__link .gmp-vrows__hint { max-width: none; white-space: normal; }   /* the walk: "fakt 188268 · 4 500,00 kr" was cut off */
.gmp-vrows__cell--lookup { width: 150px; min-width: 120px; }
/* s126 — the lookup combobox: a search glyph in the field, one list per grid fixed under the field it serves (inside the
   dialog's top layer, so nothing clips it). ↑/↓ mark `is-active`. */
.gmp-vrows .gmp-vrows__lookup { padding-right: 26px; background-repeat: no-repeat; background-position: right 8px center; background-size: 12px 12px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23748088' stroke-width='2'%3E%3Ccircle cx='7' cy='7' r='5'/%3E%3Cpath d='M11 11l4 4'/%3E%3C/svg%3E"); }
.gmp-vrows__menu { position: fixed; z-index: 10; margin: 0; padding: 4px 0; list-style: none; max-height: 260px; overflow-y: auto; background: var(--ground); border: 1px solid var(--border-strong); border-radius: var(--r); box-shadow: var(--shadow-2); font-size: var(--fs-13); }
.gmp-vrows__menu[hidden] { display: none; }
.gmp-vrows__opt { display: flex; gap: var(--sp-2); padding: 6px 10px; cursor: pointer; }
.gmp-vrows__opt:hover, .gmp-vrows__opt.is-active { background: var(--accent-tint); }
.gmp-vrows__optval { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); min-width: 48px; }
.gmp-vrows__optlabel { color: var(--ink-muted); }
.gmp-vrows__menunote { padding: 6px 10px; color: var(--ink-faint); font-style: italic; }
/* The manual voucher modal (s109, T1(a); js/manual-voucher.js). */
.gmp-mv { display: flex; flex-direction: column; gap: var(--sp-4); }
.gmp-mv__head { display: grid; grid-template-columns: 170px 1fr 190px; gap: var(--sp-3); }   /* s126: + the stated VAT */
@media (max-width: 560px) { .gmp-mv__head { grid-template-columns: 1fr; } }
/* The drill-down's reversal (s109, T1(a) step 5): the link to the other voucher, and the "Vänd" action. */
.gmp-modal .gmp-ledgerview__verlink { padding: 0 6px; font-family: var(--font-mono); text-transform: none; letter-spacing: 0; }
.gmp-modal .gmp-ledgerview__actions { display: flex; justify-content: flex-end; margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--border); }

/* ── Reminder history on an invoice (s113, LR-1) ─────────────────────────────
   The reminders sent for the invoice on screen, above the form footer. Class-scoped
   and token-only, like every component here; it carries `.gmp-app` so the table and
   link rules that live under that wrapper reach it. */
.gmp-invreminders {
  margin: var(--sp-4) 0 var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  font-family: var(--font-sans);
  font-size: var(--fs-13);
}
.gmp-invreminders__label {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--ink-muted);
  font-size: var(--fs-12);
  letter-spacing: .04em;
  text-transform: uppercase;
}
.gmp-invreminders__list { margin: 0; padding: 0; list-style: none; }
.gmp-invreminders__list li + li { margin-top: var(--sp-1); }
.gmp-invreminders__list a { color: var(--accent); }
.gmp-invreminders__list a:hover { color: var(--accent-strong); }

/* Lightbox — magnificPopup's close button (s120, §A row 48)
   SCOPE EXCEPTION #5, same bar as DataTables / .iti / #ui-datepicker-div / .gravityflow*: body-mounted vendor
   chrome, and `.mfp-*` never matches on a marketing page. Deliberately the CLOSE BUTTON ONLY — the near-black
   backdrop (#0b0b0b on .mfp-bg, #000 on the iframe holder) is correct BY INTENT: a lightbox dims the page to put
   the document forward, and retokenising it to the palette would defeat its purpose.
   magnific-popup.css loads AFTER this file, so these win on specificity (0,1,1 / 0,2,1), never on order. */
button.mfp-close {
  font-family: var(--font-sans);
}
/* The vendor sets `outline: none` and `box-shadow: none` on the button and offers nothing in their place, so a
   keyboard user had no idea where focus was. currentColor, not --ring: the button sits on the dark backdrop, where
   the teal ring at .28 alpha is close to invisible. */
button.mfp-close:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -4px;
  opacity: 1;
}

/* ── Board documents (s128, board-documents-design.md §4) ──────────────────────────────────────────────────────────────
   dokument-styrelsen / dokument-foreningen — master-detail (the user's ruling): the list left, the chosen document right,
   stacked under 720px. Replaces form 53's DataTable + magnific popups; no rule for it lives in gmp_artist.css. */
.gmp-docs__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.gmp-docs__bar .gmp-docs__filter { width: auto; min-width: 150px; }
.gmp-docs__bar .gmp-docs__new { margin-left: auto; }
.gmp-docs__bar .gmp-docs__flash { flex: 1 0 100%; margin: 0; }
.gmp-docs__split { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--ground); overflow: hidden; min-height: 420px; }
.gmp-docs--empty .gmp-docs__split { grid-template-columns: minmax(0, 1fr); min-height: 0; }
.gmp-docs__list { border-right: 1px solid var(--border); overflow-y: auto; max-height: 72vh; }
.gmp-docs--empty .gmp-docs__list { border-right: 0; }
.gmp-docs__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); cursor: pointer; outline: none; }
.gmp-docs__row:hover { background: var(--surface); }
.gmp-docs__row[aria-selected="true"] { background: var(--accent-tint); box-shadow: inset 3px 0 0 var(--accent); }
.gmp-docs__row:focus-visible { box-shadow: inset 3px 0 0 var(--accent), var(--ring); }
.gmp-docs__rowtitle { font-size: var(--fs-14); font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.gmp-docs__rowmeta { font-size: var(--fs-12); color: var(--ink-muted); margin-top: 2px; }
.gmp-docs__none { margin: 0; padding: var(--sp-4); font-size: var(--fs-13); color: var(--ink-muted); }
.gmp-docs__empty { padding: var(--sp-6) var(--sp-5); text-align: center; color: var(--ink-muted); font-size: var(--fs-14); }
.gmp-docs__empty p { margin: 0 auto; max-width: 460px; }
.gmp-docs__empty .gmp-docs__emptytitle { font-size: var(--fs-17); font-weight: 600; color: var(--ink); margin-bottom: var(--sp-2); }
.gmp-docs__view { padding: var(--sp-4); min-width: 0; }
.gmp-docs__viewhead { display: flex; align-items: flex-start; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.gmp-docs__viewhead .gmp-docs__viewtitle { margin: 0; font-family: var(--font-sans); font-size: var(--fs-17); font-weight: 600; color: var(--ink); line-height: 1.35; flex: 1 1 auto; overflow-wrap: anywhere; }
.gmp-docs__viewgrid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--sp-4); }
.gmp-docs__preview { border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); overflow: hidden; }
.gmp-docs__pdf { display: block; width: 100%; height: 540px; border: 0; }
.gmp-docs__img { display: block; width: 100%; height: auto; max-height: 540px; object-fit: contain; }
.gmp-docs .gmp-facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px var(--sp-3); margin: 0 0 var(--sp-4); font-size: var(--fs-13); }
.gmp-docs .gmp-facts dt { color: var(--ink-muted); font-weight: 600; }
.gmp-docs .gmp-facts dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }
.gmp-docs__actions { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-2); }
.gmp-docs__actions .gmp-btn { justify-content: center; text-align: center; }
@media (max-width: 720px) {
  .gmp-docs__split, .gmp-docs__viewgrid { grid-template-columns: minmax(0, 1fr); }
  .gmp-docs__list { border-right: 0; border-bottom: 1px solid var(--border); max-height: 40vh; }
  .gmp-docs__pdf { height: 420px; }
}

/* The editor (GmpModal, wide): the facts left, the document right — and before a file is chosen, the right side IS the
   drop zone while the fields wait read-only (the user's ruling: a quiet waiting state, never greyed-out controls). */
.gmp-modal .gmp-docform { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: var(--sp-5); }
.gmp-modal .gmp-docform__fields { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-docform__hint { margin: 0; padding: var(--sp-2) var(--sp-3); border-radius: var(--r); background: var(--accent-tint); color: var(--accent-strong); font-size: var(--fs-13); font-weight: 600; }
.gmp-modal .gmp-docform__hint[hidden] { display: none; }
.gmp-modal .gmp-docform--waiting .gmp-docform__fields .gmp-field { pointer-events: none; }
.gmp-modal .gmp-docform--waiting .gmp-docform__fields .gmp-input,
.gmp-modal .gmp-docform--waiting .gmp-docform__fields .gmp-select { background: var(--surface); border-style: dashed; }
.gmp-modal .gmp-docform__doc { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; border-radius: var(--r-lg); }
.gmp-modal .gmp-docform__doc.is-over { box-shadow: var(--ring); }
.gmp-modal .gmp-docform__doc .gmp-docs__preview { border-radius: var(--r); background: var(--surface); }
.gmp-modal .gmp-docform__doc .gmp-docs__pdf { display: block; width: 100%; height: 460px; border: 0; }
.gmp-modal .gmp-docform__doc .gmp-docs__img { display: block; width: 100%; max-height: 460px; object-fit: contain; }
.gmp-modal .gmp-docdrop { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; min-height: 380px; width: 100%; padding: var(--sp-5); border: 2px dashed var(--border-strong); border-radius: var(--r-lg); background: var(--surface); color: var(--ink-muted); font-family: var(--font-sans); font-weight: 400; text-transform: none; letter-spacing: normal; line-height: 1.4; box-shadow: none; cursor: pointer; transition: border-color .14s ease, background .14s ease; }   /* a real <button>: the theme's button casing and weight reset */
.gmp-modal .gmp-docdrop:hover, .gmp-modal .gmp-docform__doc.is-over .gmp-docdrop { border-color: var(--accent); background: var(--accent-tint); color: var(--accent-strong); }
.gmp-modal .gmp-docdrop:focus-visible { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.gmp-modal .gmp-docdrop__ic { width: 36px; height: 36px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; margin-bottom: var(--sp-1); }
.gmp-modal .gmp-docdrop__main { font-size: var(--fs-16); font-weight: 600; color: var(--ink); }
.gmp-modal .gmp-docdrop__alt { font-size: var(--fs-14); color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.gmp-modal .gmp-docdrop__rule { font-size: var(--fs-12); color: var(--ink-faint); margin-top: var(--sp-2); }
.gmp-modal .gmp-docform__meta { margin: 0; font-size: var(--fs-12); color: var(--ink-muted); overflow-wrap: anywhere; }
.gmp-modal .gmp-docform__swap { border: 0; background: none; padding: 0; font: inherit; text-transform: none; letter-spacing: normal; box-shadow: none; color: var(--accent); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.gmp-modal .gmp-docform__fileerr[hidden] { display: none; }
@media (max-width: 720px) {
  .gmp-modal .gmp-docform { grid-template-columns: minmax(0, 1fr); }
  .gmp-modal .gmp-docform__doc { order: -1; }          /* the file first on a phone — it is what unlocks the rest */
  .gmp-modal .gmp-docdrop { min-height: 180px; }
  .gmp-modal .gmp-docform__doc .gmp-docs__pdf { height: 320px; }
}

/* ── Utskick (s132, utskick-design.md step 1) — the page's list and the plan inside its modal. The modal's layout is the
   board documents' own (.gmp-docform / .gmp-docdrop, above) — one document dialog shape across the app. ── */
.gmp-app.gmp-ut .gmp-ut__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.gmp-app.gmp-ut .gmp-ut__flash { flex: 1 1 100%; }
.gmp-app.gmp-ut .gmp-ut__row { cursor: pointer; }
.gmp-app.gmp-ut .gmp-ut__row:hover td, .gmp-app.gmp-ut .gmp-ut__row:focus-visible td { background: var(--accent-tint); }
.gmp-app.gmp-ut .gmp-ut__row:focus-visible { outline: none; box-shadow: var(--ring); }
.gmp-app.gmp-ut .gmp-ut__title { font-weight: 600; color: var(--ink); }
.gmp-modal .gmp-utform .gmp-ut__hits { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.gmp-modal .gmp-utform .gmp-ut__hit { width: 100%; text-align: left; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); padding: 6px 10px; font: inherit; font-size: var(--fs-14); color: var(--ink); cursor: pointer; }
.gmp-modal .gmp-utform .gmp-ut__hit:hover, .gmp-modal .gmp-utform .gmp-ut__hit:focus-visible { border-color: var(--accent); background: var(--accent-tint); outline: none; }
.gmp-modal .gmp-utform .gmp-ut__picked { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.gmp-modal .gmp-utform .gmp-ut__unpick { border: 0; background: none; padding: 0 0 0 4px; font: inherit; line-height: 1; color: inherit; cursor: pointer; }
.gmp-modal .gmp-utform .gmp-ut__files { margin: 0; padding-left: 1.2em; font-size: var(--fs-13); color: var(--ink-muted); }
.gmp-modal .gmp-utform .gmp-ut__plan { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-utform .gmp-ut__sum { margin: 0; font-size: var(--fs-16); color: var(--ink); }
.gmp-modal .gmp-utform .gmp-ut__blocked { flex-direction: column; gap: var(--sp-1); }
.gmp-modal .gmp-utform .gmp-ut__blocked ul { margin: 0; padding-left: 1.2em; }
.gmp-modal .gmp-utform .gmp-ut__all summary { cursor: pointer; font-size: var(--fs-14); font-weight: 600; color: var(--accent-strong); }
.gmp-modal .gmp-utform .gmp-ut__recips { margin-top: var(--sp-2); font-size: var(--fs-13); }
.gmp-modal .gmp-utform .gmp-ut__recips tr.is-blocked td { color: var(--warn-ink); }
.gmp-modal .gmp-utform .gmp-ut__send { align-self: flex-start; }
.gmp-modal .gmp-ut__confirm { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-ut__confirm p { margin: 0; }
.gmp-modal .gmp-ut__confirm .gmp-ut__carriers { margin: 0; padding-left: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-1); }   /* s133: what each channel really does */

/* ── "Skicka ett brev" (s135, utskick-design.md §18 6b) — the single letter's modal (js/single-letter.js). The board documents' layout
   (.gmp-docform): the letter left, the page right. The page is a 210 mm sheet in a sandboxed iframe, SCALED to the column by the script
   (the box's height follows) — so the preview has the printed page's proportions at any width. The editor: a fixed toolbar over a
   plain editable area; its blocks drawn in the page's own steps (Normal · Större = h3 · Rubrik = h2). */
.gmp-modal .gmp-letterform { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.gmp-modal .gmp-letter__to { display: flex; flex-direction: column; gap: 2px; }
.gmp-modal .gmp-letter__kind { font-size: var(--fs-12); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-muted); }
.gmp-modal .gmp-letter__name { font-size: var(--fs-17); font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.gmp-modal .gmp-letter__how { margin: 0; }
.gmp-modal .gmp-letter__mode { margin: 0; font-size: var(--fs-13); color: var(--warn-ink); }
.gmp-modal .gmp-letter__edit { border: 1px solid var(--border-strong); border-radius: var(--r); background: var(--ground); overflow: hidden; }
.gmp-modal .gmp-letter__edit:focus-within { border-color: var(--accent); box-shadow: var(--ring); }
.gmp-modal .gmp-letter__tools { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 4px; border-bottom: 1px solid var(--border); background: var(--surface); }
.gmp-modal .gmp-letter__tool { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 30px; margin: 0; padding: 0 8px; border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; box-shadow: none; color: var(--ink); font-family: var(--font-sans); font-size: var(--fs-14); font-weight: 600; line-height: 1; text-transform: none; letter-spacing: normal; cursor: pointer; }   /* a real <button>: the theme's casing reset */
.gmp-modal .gmp-letter__tool:hover { background: var(--surface-2); }
.gmp-modal .gmp-letter__tool:focus-visible { outline: none; box-shadow: var(--ring); }
.gmp-modal .gmp-letter__tool[aria-pressed="true"] { background: var(--accent-tint); border-color: var(--accent); color: var(--accent-strong); }
.gmp-modal .gmp-letter__tool.is-b { font-weight: 800; }
.gmp-modal .gmp-letter__tool.is-i { font-style: italic; font-weight: 500; }   /* the house sans, in italic — a serif here was an off-token font (gmpAudit, walk s135) */
.gmp-modal .gmp-letter__tool.is-u { text-decoration: underline; text-underline-offset: 2px; }
.gmp-modal .gmp-letter__sep { width: 1px; height: 20px; margin: 0 4px; background: var(--border-strong); }
.gmp-modal .gmp-letter__block { width: auto; padding: 4px 8px; font-size: var(--fs-13); }
.gmp-modal .gmp-letter__area { min-height: 220px; max-height: 360px; overflow-y: auto; padding: var(--sp-3); font-size: var(--fs-15); line-height: 1.5; color: var(--ink); outline: none; }
.gmp-modal .gmp-letter__area { position: relative; }
.gmp-modal .gmp-letter__area.is-empty::before { content: attr(data-placeholder); position: absolute; top: var(--sp-3); left: var(--sp-3); color: var(--ink-faint); pointer-events: none; }   /* the area starts as one empty <p>, never :empty */
.gmp-modal .gmp-letter__area p, .gmp-modal .gmp-letter__area ul, .gmp-modal .gmp-letter__area ol { margin: 0 0 8px; }
.gmp-modal .gmp-letter__area ul, .gmp-modal .gmp-letter__area ol { padding-left: 24px; }
.gmp-modal .gmp-letter__area ul > li { list-style: disc; }   /* the theme resets list-style on every li (walk s135): the bullet was gone */
.gmp-modal .gmp-letter__area ol > li { list-style: decimal; }
.gmp-modal .gmp-letter__area h2 { margin: 8px 0 4px; font-family: var(--font-sans); font-size: var(--fs-19); font-weight: 650; text-transform: none; letter-spacing: 0; color: var(--ink); }
.gmp-modal .gmp-letter__area h3 { margin: 8px 0 4px; font-family: var(--font-sans); font-size: var(--fs-17); font-weight: 650; text-transform: none; letter-spacing: 0; color: var(--ink); }
.gmp-modal .gmp-letter__files { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.gmp-modal .gmp-letter__file { display: flex; justify-content: space-between; gap: var(--sp-3); font-size: var(--fs-13); color: var(--ink); overflow-wrap: anywhere; }
.gmp-modal .gmp-letter__sheet { position: relative; overflow: hidden; height: 560px; background: var(--surface-2); }
.gmp-modal .gmp-letter__sheet .gmp-letter__frame { position: absolute; top: 0; left: 0; width: 794px; max-width: none; height: 1123px; border: 0; background: #ffffff; transform-origin: 0 0; }   /* the sheet is paper in both themes; max-width: the theme caps every iframe at 100% — which shrank the sheet before it was scaled (walk s135) */
@media (max-width: 720px) {
  .gmp-modal .gmp-letterform { grid-template-columns: minmax(0, 1fr); }
  .gmp-modal .gmp-letterform .gmp-docform__doc { order: 0; }   /* the letter first on a phone; the page after it (unlike a document, it is what you write) */
}

/* Pills — a radio group drawn as toggles (visibility; signing in step 4). Real radios underneath: keyboard + a11y for free. */
.gmp-pills { display: flex; flex-wrap: wrap; gap: var(--sp-2); border: 0; margin: 0; padding: 0; min-width: 0; }
.gmp-pill { position: relative; display: inline-flex; cursor: pointer; }
.gmp-pill input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.gmp-pill span { display: inline-block; padding: 6px 14px; border: 1px solid var(--border-strong); border-radius: 100px; background: var(--ground); color: var(--ink); font-family: var(--font-sans); font-size: var(--fs-13); font-weight: 600; transition: border-color .14s ease, background .14s ease; }
.gmp-pill:hover span { border-color: var(--accent); }
.gmp-pill input:checked + span { background: var(--accent-tint); border-color: var(--accent); color: var(--accent-strong); }
.gmp-pill input:focus-visible + span { box-shadow: var(--ring); }

/* Board documents — signing (s128, board-documents-design.md §5): the signer picker in the modal, the per-signer list and the
   note in the document view. */
.gmp-modal .gmp-docform__signing { display: flex; flex-direction: column; gap: var(--sp-2); }
.gmp-modal .gmp-signers { display: flex; flex-direction: column; gap: var(--sp-1); padding: var(--sp-3); border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
.gmp-modal .gmp-signers__label { font-size: var(--fs-12); font-weight: 600; color: var(--ink-muted); text-transform: uppercase; letter-spacing: .03em; margin-top: var(--sp-2); }
.gmp-modal .gmp-signers__label:first-child { margin-top: 0; }
.gmp-modal .gmp-signers__row { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-14); color: var(--ink); cursor: pointer; padding: 3px 0; }
.gmp-modal .gmp-signers__row input { accent-color: var(--accent); width: 16px; height: 16px; margin: 0; }
.gmp-modal .gmp-signers__role { color: var(--ink-muted); font-size: var(--fs-12); }
.gmp-modal .gmp-signers__ext { display: flex; flex-direction: column; gap: var(--sp-2); }
.gmp-modal .gmp-signers__extrow { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: var(--sp-2); }
.gmp-modal .gmp-signers__extrow .gmp-modal__fielderror { grid-column: 1 / -1; }
.gmp-modal .gmp-signers .gmp-docform__swap { align-self: flex-start; margin-top: var(--sp-1); }
.gmp-modal .gmp-signers .gmp-modal__fielderror[hidden] { display: none; }
@media (max-width: 720px) { .gmp-modal .gmp-signers__extrow { grid-template-columns: minmax(0, 1fr); } }
.gmp-docs .gmp-signerlist { list-style: none; margin: 0 0 var(--sp-3); padding: 0; border-top: 1px solid var(--border); }
.gmp-docs .gmp-signerlist__row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 6px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-13); }
.gmp-docs .gmp-signerlist__name { color: var(--ink); overflow-wrap: anywhere; }
.gmp-docs .gmp-docs__signnote { margin: 0 0 var(--sp-3); font-size: var(--fs-12); color: var(--ink-muted); line-height: 1.45; }

/* ── Our own document link (s134, utskick-design.md §14.4) — the landing page of `<subsite>/d/<token>`. A whole document of its own:
   no theme, no menu; one card, the förening, the title, one button. Phone-first — most links arrive by SMS. */
body.gmp-doclink { margin: 0; min-height: 100vh; display: flex; align-items: flex-start; justify-content: center; padding: var(--sp-6) var(--sp-4); box-sizing: border-box; background: var(--surface); color: var(--ink); font-family: var(--font-sans); font-size: var(--fs-body); line-height: 1.5; }
.gmp-doclink__card { width: 100%; max-width: 440px; box-sizing: border-box; background: var(--ground); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-1); padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-2); }
.gmp-doclink__kicker { margin: 0; font-size: var(--fs-12); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-muted); }
.gmp-doclink__from { margin: 0; font-size: var(--fs-24); line-height: 1.25; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.gmp-doclink__title { margin: var(--sp-2) 0 0; font-size: var(--fs-17); color: var(--ink); overflow-wrap: anywhere; }
.gmp-doclink__meta { margin: 0; font-size: var(--fs-13); color: var(--ink-muted); }
.gmp-doclink__open { margin: var(--sp-4) 0 var(--sp-2); }
.gmp-doclink__open .gmp-btn { width: 100%; justify-content: center; padding: 13px 15px; font-size: var(--fs-14); }
.gmp-doclink__note { margin: 0; font-size: var(--fs-13); color: var(--ink-muted); }
/* s134 (utskick step 5): the opened mailing's letter table — the name may wrap, channel and status never break mid-word; an imported
   mailing says where it came from ONCE, as a quiet pill under its summary (not a note on every letter). */
.gmp-modal .gmp-ut__recips td:nth-child(2), .gmp-modal .gmp-ut__recips td:nth-child(3),
.gmp-modal .gmp-ut__recips th:nth-child(2), .gmp-modal .gmp-ut__recips th:nth-child(3) { white-space: nowrap; }
.gmp-modal .gmp-ut__legacy { align-self: flex-start; margin: 0; padding: 2px 10px; border: 1px solid var(--border); border-radius: 100px; background: var(--surface); color: var(--ink-muted); font-size: var(--fs-12); }
/* s134: the list's filter — the board's own mailings by default, "Alla brev" for every door's (the imported history). */
.gmp-app.gmp-ut .gmp-ut__filter { margin-bottom: var(--sp-3); }

/* ── Brevutskick från fastighetsregistret (s136, utskick-design.md U-15 (2)) — `lm-brevutskick`, re-done in the house design.
   Panels, a .gmp-countlist summary and static .gmp-tables carry the look; these rules are layout only. */
.gmp-app.gmp-lmrel .gmp-lmrel__flash { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.gmp-app.gmp-lmrel .gmp-lmrel__flash:empty { display: none; }
.gmp-app.gmp-lmrel .gmp-lmrel__summary { display: flex; flex-direction: column; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.gmp-app.gmp-lmrel .gmp-lmrel__summary p, .gmp-app.gmp-lmrel .gmp-panel > p { margin: 0 0 var(--sp-3); }
.gmp-modal .gmp-lmrel__confirm { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-lmrel__confirm p { margin: 0; }

/* ── Påminnelser (s138) — `paminnelser`, the officers' release of reminders on a manual-release förening. The lm-brevutskick
   shape: panels, a notice for the mode, a static .gmp-table with a tick per row; these rules are layout only. */
.gmp-app.gmp-remrel .gmp-remrel__mode, .gmp-app.gmp-remrel .gmp-remrel__flash { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.gmp-app.gmp-remrel .gmp-remrel__mode:empty, .gmp-app.gmp-remrel .gmp-remrel__flash:empty { display: none; }
.gmp-app.gmp-remrel .gmp-remrel__list > p { margin: 0 0 var(--sp-3); }
.gmp-app.gmp-remrel .gmp-remrel__num { text-align: right; font-variant-numeric: tabular-nums; }
.gmp-app.gmp-remrel [hidden] { display: none; }   /* walk s138: .gmp-btn's display beat the attribute — the release showed in auto mode */
.gmp-app.gmp-remrel tr.is-blocked td { color: var(--warn-ink); }
.gmp-modal .gmp-remrel__confirm { display: flex; flex-direction: column; gap: var(--sp-3); }
.gmp-modal .gmp-remrel__confirm p { margin: 0; }
