/* PAYVISIA — the NEUTRAL platform's palette.
   This is what an unrecognised host and a company that signed itself up see. A partner's
   colours never live here: BrandContext overrides --navy and --accent per host from the
   partner's own record, so every rule below that reads those variables is re-themed for free.
   ERHR's navy-and-gold was this file's palette until 2026-09-05, which made the platform look
   like one partner; it now sits on ERHR's agent row, where the demo seeds it. Allegro IT's blue
   stood in from then until 2026-09-09 — the builder's colours, not the product's.

   PAYVISIA now has its own. Four of the values below are the designmanual's (v1.0, August 2026,
   section 05 FARVER) at the exact hex it names, and are marked as such. The manual gives five
   colours and this stylesheet needs a ladder, so the remaining navy steps are the SAME HUE at
   other lightnesses — hsl(210, …), the hue of #003366 — rather than four more inventions. What
   the manual does not name at all (muted text, hairlines, the ok/warn/bad triples) is left as it
   was: unmandated changes there would be taste wearing a brand's clothes. */

:root {
  --navy-900: #002142;      /* hsl(210 100% 13%) — the dark ground: sidebar, .bare */
  --navy-800: #002b57;      /* hsl(210 100% 17%) — one step down from --navy, for hovers */
  --navy: #003366;          /* designmanual: PAYVISIA Navy */
  --navy-600: #0052a3;      /* hsl(210 100% 32%) — links; 7.7:1 on white */
  --navy-400: #7ea6ce;      /* hsl(210 45% 65%) */

  --accent: #007acc;        /* designmanual: Accent Blue */
  --accent-soft: #e6f0fa;   /* designmanual: Light Blue */
  --teal: #1f7a7a;

  --ink: #333333;           /* designmanual: Dark Grey */
  --muted: #5c6b78;
  --faint: #8b98a3;
  --line: #dde3e8;
  --bg: #f4f6f8;            /* designmanual: Light Grey — already this value */
  --paper: #ffffff;

  --ok: #2e7d5b;
  --ok-bg: #e7f3ed;
  --warn: #9a6b16;
  --warn-bg: #fbf1dc;
  /* The same caution, light enough to read on a navy ground. Deliberately outside the
     designmanual: its five colours have no warning role, and the one place this is used says
     "lovforslaget er endnu ikke vedtaget" — which has to be able to interrupt. */
  --warn-light: #e0c98d;
  --bad: #b3352e;
  --bad-bg: #fbe9e6;

  --radius: 10px;
  --shadow: 0 1px 2px rgba(16, 34, 48, 0.06), 0 4px 14px rgba(16, 34, 48, 0.05);
}

/* ---------------------------------------------------------- brand typography

   The designmanual's section 06: League Spartan for display type, Montserrat for subheadings
   and body. Self-hosted because SecurityHeaders.cs sets `font-src 'self'` — a CDN link would be
   blocked, and widening that header to allow one would be the wrong trade for an application
   about salary data. Provenance, licence and hashes: wwwroot/fonts/README.md.

   `font-weight: 100 900` is the whole variable axis, not a copy of the manual's three named
   weights. A request outside a variable font's declared range is clamped SILENTLY, and this
   stylesheet asks for 650 and 700 in a dozen places — declaring 300 600 would render every bold
   heading light with nothing to notice.

   The `unicode-range` on each face is load-bearing, not decoration: it is what stops a Danish
   page fetching the latin-ext file for glyphs it never draws. */

@font-face {
  font-family: "League Spartan";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/league-spartan-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "League Spartan";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/league-spartan-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/montserrat-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/montserrat-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Each stack keeps the old system stack behind the brand face, so a font request that fails
     degrades to exactly what this product looked like before 2026-09-09 rather than to Times. */
  --font-body: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;
  --font-display: "League Spartan", "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  /* 14.5px, not the 15px the system stack used. Montserrat runs optically larger and wider at
     the same nominal size, and the app shell is full of fixed-width furniture — a 252 px
     sidebar, a company switcher, table headers — that a straight swap pushed into wrapping. */
  font: 14.5px/1.55 var(--font-body);
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
p { margin: 0 0 0.75rem; }
p:last-child { margin-bottom: 0; }
a { color: var(--navy-600); }

/* ---------------------------------------------------------------- app shell */

.app {
  display: grid;
  grid-template-columns: 252px minmax(0, 1fr);
  min-height: 100vh;
}

.sidebar {
  background: var(--navy-900);
  color: #dce5ec;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand {
  display: block;
  padding: 1.4rem 1.25rem 1.1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  text-decoration: none;
}

/* Bounded by a BOX, not by one edge, because this slot draws two shapes of mark: PAYVISIA's own
   lockup is 5.15:1 (wordmark over tagline), a typical partner wordmark nearer 2:1. A fixed width
   shrank the wide one until "Making Pay Visible" was four pixels tall and the mark sat under the
   designmanual's 120 px digital minimum; a fixed height would blow the tall one out of a 212 px
   column.

   `max-width` + `max-height`, never `width` + `max-height`. A *specified* width is not recomputed
   when max-height clamps the height — measured, 2026-09-09: a 2.27:1 partner mark came out
   180 x 48 instead of 180 x 79, squashed, which is the one thing the manual names outright
   ("Må ikke forvrænges"). With both maxima and no fixed side, the ratio decides. Same idiom as
   .logo-preview on the partner form. */
.brand-logo {
  display: block;
  max-width: 180px;
  max-height: 48px;
  /* The wordmark is a single navy fill; inverting it keeps one asset for both surfaces, and it
     is the manual's own "negativ logo på mørk baggrund" rather than a liberty taken here. */
  filter: brightness(0) invert(1);
}

/* A partner's mark is not a silhouette. `brightness(0) invert(1)` flattens everything it
   touches to white, which is exactly right for one flat navy fill and destructive for anything
   else — measured 2026-09-09, a partner logo with a coloured ground rendered as a solid white
   rectangle in the sidebar. It applied to every mark from the first commit until then, so no
   white-label customer could have had a usable logo.

   Both dark grounds, not just the sidebar: a registered partner host shows the landing page too,
   and .landing-head inverts there for the same reason.

   Uninverted, an upload is drawn in its own colours, which then need somewhere to stand: most
   brand marks are dark on transparent and would vanish into the navy ground. The chip is the one
   .logo-preview already uses on the partner form, so the operator picking the logo and the
   customer living with it see the same thing. */
.brand-logo.is-partner,
.landing-head .signin-logo.is-partner {
  filter: none;
  box-sizing: content-box;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  background: #fafbfc;
}

/* Display type, not body: this label echoes the wordmark on a host whose logo is a partner's,
   so it should be set in the face the wordmark is drawn from. */
.brand-sub {
  display: block;
  margin-top: 0.55rem;
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav { padding: 0.9rem 0.65rem 1.5rem; flex: 1; }

.nav-group {
  margin: 1.1rem 0 0.35rem;
  padding: 0 0.6rem;
  color: var(--navy-400);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.nav-group:first-child { margin-top: 0.2rem; }

.nav a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.6rem;
  border-radius: 7px;
  color: #cad6e0;
  font-size: 0.9rem;
  text-decoration: none;
}
.nav a:hover { background: rgba(255, 255, 255, 0.07); color: #fff; }
.nav a:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.nav a.is-active {
  background: var(--navy-600);
  color: #fff;
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--accent);
}

.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
}
.dot-bad { background: #e0665c; }
.dot-warn { background: #e0b45c; }

.sidebar-foot {
  padding: 0.9rem 1.25rem 1.2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  font-size: 0.8rem;
}
/* Stacked, not side by side: "Behandling af personoplysninger" is longer than the sidebar is
   wide, and a policy link is found when looked for rather than advertised — so it sits quieter
   than the role beneath it, and brightens on hover to show it is a link at all. */
.sidebar-legal { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.9rem; }
.sidebar-legal a { color: var(--navy-400); text-decoration: none; line-height: 1.3; }
.sidebar-legal a:hover { color: #fff; text-decoration: underline; }
.sidebar-foot .who { margin: 0; color: var(--navy-400); }
.sidebar-foot .who-name { margin: 0.1rem 0 0; color: #fff; font-weight: 600; }

.main { display: flex; flex-direction: column; min-width: 0; }

/* ---------------------------------------------------------------- topbar */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.75rem;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 5;
}

.crumb { margin: 0 0 0.15rem; color: var(--muted); font-size: 0.8rem; }
/* The company name carries the tenant context for every figure on the page, so it reads at
   heading weight rather than breadcrumb weight (requested 2026-08-24). */
.crumb-company { font-size: 1.05rem; font-weight: 700; color: var(--navy); }

/* Shown only while the reader is inside a customer's data on a support permission. Warm rather
   than red: this is a legitimate, customer-issued state, and an alarm colour would train people
   to dismiss it. It has to be readable at a glance, because it is the only thing on the screen
   distinguishing this session from the customer's own administrator. */
.support-notice {
  margin: .45rem 0 0;
  padding: .4rem .65rem;
  max-width: 90ch;
  background: var(--warn-bg);
  border: 1px solid #ecd9b0;
  border-radius: var(--radius);
  color: #7a5b18;
  font-size: .82rem;
  line-height: 1.45;
}
.topbar h1 { font-size: 1.25rem; }
.topbar-right { display: flex; align-items: center; gap: 0.75rem; }

.switcher { position: relative; }
.switcher summary {
  list-style: none;
  cursor: pointer;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
}
.switcher summary::-webkit-details-marker { display: none; }
.switcher summary::after { content: " ▾"; color: var(--muted); }
.switcher[open] summary { border-color: var(--navy-600); }

.switcher-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  width: 260px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.4rem;
  z-index: 10;
}
.switcher-menu a {
  display: block;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
  color: var(--ink);
  font-size: 0.85rem;
  text-decoration: none;
}
.switcher-menu a:hover { background: var(--bg); }
.switcher-menu .sub { display: block; color: var(--muted); font-size: 0.75rem; }
.switcher-menu .is-current { background: var(--accent-soft); }

.avatar {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--navy);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 700;
}

/* ---------------------------------------------------------------- content */

.content { padding: 1.5rem 1.75rem 2rem; flex: 1; }

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 1.25rem;
  overflow: hidden;
}

.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--line);
}
.card-head h2 { font-size: 1rem; }
.card-head .hint { color: var(--muted); font-size: 0.82rem; }

/* A card whose body folds away. Native <details>, like .switcher above: it needs no script —
   the CSP forbids inline script — and it is keyboard-operable and screen-reader-announced for
   free.

   The affordance is a BUTTON-SHAPED chevron, not a glyph appended to text. The first attempt
   put " ▸" on the ::after of the hint, which read as punctuation belonging to the sentence
   beside it and was nearly invisible. Jack, 2026-09-11. */
.card-disclosure > summary { cursor: pointer; list-style: none; align-items: center; }
.card-disclosure > summary::-webkit-details-marker { display: none; }

.disclosure-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.9rem;
  height: 1.9rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--muted);
  transition: transform 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.card-disclosure[open] .disclosure-chevron { transform: rotate(180deg); }
.card-disclosure > summary:hover .disclosure-chevron {
  border-color: var(--navy-600);
  color: var(--navy-600);
}
.card-disclosure > summary:focus-visible .disclosure-chevron { border-color: var(--navy-600); }

/* The tally carries the verdict, so it is coloured rather than muted: red while something is
   missing, green when nothing is. Jack, 2026-09-11. Colour is not the only cue — the text says
   "N krav mangler" or "alle krav opfyldt" — so it still reads without it. */
.card-head .tally { font-weight: 400; }
.card-head .tally-ok { color: var(--ok); }
.card-head .tally-bad { color: var(--bad); }
.card-body { padding: 1.25rem; }
.card-foot {
  padding: 0.85rem 1.25rem;
  background: #fafbfc;
  border-top: 1px solid var(--line);
  font-size: 0.85rem;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.grid { display: grid; gap: 1.25rem; }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }

/* A cell that spans every column of whichever grid it is in — for help text that explains the
   fields above it rather than one field beside it. Works in grid-2, -3 and -4 alike, and needs
   no change in the single-column mobile rules below, where "all columns" is already one. */
.field-wide { grid-column: 1 / -1; }

/* ---------------------------------------------------------------- kpi */

.kpi { padding: 1rem 1.1rem; }
.kpi .label { color: var(--muted); font-size: 0.8rem; margin: 0 0 0.35rem; }
.kpi .value { font-size: 1.55rem; font-weight: 700; letter-spacing: -0.02em; }
.kpi .value small { font-size: 0.85rem; font-weight: 500; color: var(--muted); }
.kpi .meta { margin: 0.3rem 0 0; font-size: 0.8rem; color: var(--muted); }

.score-ring {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.score-number { font-size: 2.6rem; font-weight: 700; letter-spacing: -0.03em; }
.score-number small { font-size: 1rem; font-weight: 500; color: var(--muted); }

.meter {
  height: 8px;
  border-radius: 99px;
  background: #e9edf1;
  overflow: hidden;
}
.meter span { display: block; height: 100%; border-radius: 99px; background: var(--teal); }
.meter.is-bad span { background: var(--bad); }
.meter.is-warn span { background: var(--accent); }

/* ---------------------------------------------------------------- pills */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 650;
  white-space: nowrap;
}
.pill-ok { background: var(--ok-bg); color: var(--ok); }
.pill-warn { background: var(--warn-bg); color: var(--warn); }
.pill-bad { background: var(--bad-bg); color: var(--bad); }
.pill-neutral { background: #eef1f4; color: var(--muted); }
.pill-info { background: #e8eff5; color: var(--navy-600); }

.tag {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 0.75rem;
  color: var(--muted);
  background: #fafbfc;
}

/* ---------------------------------------------------------------- banner */

.banner {
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  padding: 0.95rem 1.15rem;
  border-radius: var(--radius);
  margin-bottom: 1.25rem;
  border: 1px solid;
}
.banner-bad { background: var(--bad-bg); border-color: #f0c4bf; color: #7d211c; }
.banner-info { background: #eaf1f7; border-color: #cdddea; color: var(--navy); }
.banner-warn { background: var(--warn-bg); border-color: #ecd9b0; color: #7a5b18; }
.banner strong { display: block; margin-bottom: 0.15rem; }
/* …but a <strong> inside the body text is emphasis, not a heading. */
.banner p strong { display: inline; margin-bottom: 0; }
.banner p { margin: 0; font-size: 0.88rem; }
.banner .banner-mark { font-size: 1.2rem; line-height: 1.2; }

/* ---------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}
table.data th, table.data td {
  padding: 0.6rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
table.data thead th {
  background: #f8fafb;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
table.data thead th a { color: inherit; text-decoration: none; }
table.data thead th a:hover { color: var(--navy); }
table.data thead th .sort { color: var(--accent); }
table.data tbody tr:hover { background: #fbfcfd; }
table.data tbody tr.is-flagged { background: var(--bad-bg); }
table.data tbody tr.is-flagged:hover { background: #f8ddd9; }

/* A row that opens its own editor — Medarbejderevaluering, where clicking a person to argue for
   them is the whole point of the screen. The pointer is the only affordance the row itself gets;
   the actual control is the button inside it, so keyboard and screen-reader users reach the same
   editor without depending on a click handler bolted to a <tr>. */
table.data tbody tr.row-clickable { cursor: pointer; }

/* A button that reads as text, for a control living inside a table cell where a real button would
   dominate the row. Keeps the focus ring — this is the row's keyboard entry point. */
.btn-link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
}
.btn-link:disabled { cursor: default; }
table.data tfoot td {
  padding: 0.6rem 0.75rem;
  background: #f8fafb;
  font-weight: 650;
  border-top: 1px solid var(--line);
}
.num { text-align: right; font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }
.strong { font-weight: 650; }
.muted { color: var(--muted); }
.small { font-size: 0.82rem; }
.tiny { font-size: 0.75rem; }

.filter-row td { padding: 0.4rem 0.5rem; background: #fff; }
/* Also any control sitting directly in a data cell — the ownership picker on the platform
   screen, the weight input on Lønkriterier. Without this they render as raw browser controls
   beside styled ones, which reads as an unfinished page rather than as a different kind of
   control. */
.filter-row input, .filter-row select,
table.data td > select, table.data td > input {
  width: 100%;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  font-size: 0.8rem;
  color: var(--ink);
  background: #fff;
}
.filter-row input::placeholder { color: var(--faint); }

.gapbar {
  display: inline-block;
  vertical-align: middle;
  width: 90px;
  height: 7px;
  border-radius: 99px;
  background: #eaeef1;
  overflow: hidden;
  margin-right: 0.5rem;
}
.gapbar span { display: block; height: 100%; background: var(--teal); }
.gapbar.is-warn span { background: var(--accent); }
.gapbar.is-bad span { background: var(--bad); }

/* ---------------------------------------------------------------- pagination */

.pager {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.83rem;
}
.pager a, .pager span.page {
  display: inline-block;
  min-width: 30px;
  text-align: center;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--navy-600);
  text-decoration: none;
  background: #fff;
}
.pager .is-current { background: var(--navy); color: #fff; border-color: var(--navy); font-weight: 650; }
.pager .is-disabled { color: var(--faint); background: #f7f9fa; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #fff;
  color: var(--ink);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { border-color: var(--navy-400); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.btn-primary { background: var(--navy); border-color: var(--navy); color: #fff; }
.btn-primary:hover { background: var(--navy-800); border-color: var(--navy-800); }
/* .btn-accent removed 2026-09-09: no markup in the repository ever used it, and its hover was
   #b9821f — ERHR's gold, in the stylesheet whose own header says ERHR's brand ships only in the
   demo seed. Dead rules are where a retired palette survives a rebrand unnoticed. */
.btn-row { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }

/* ---------------------------------------------------------------- forms */

.field { margin-bottom: 1rem; }
.field label {
  display: block;
  margin-bottom: 0.25rem;
  font-size: 0.82rem;
  font-weight: 650;
  color: var(--ink);
}
.field .help { margin: 0.25rem 0 0; font-size: 0.78rem; color: var(--muted); }

/* A checkbox and its wording are one sentence, so the box sits inline before the text rather
   than above it. Both declarations are load-bearing: `.field label` sets `display: block` and
   `.field input` sets `width: 100%`, so a checkbox left to inherit them stretches the full row
   and strands itself at the right-hand edge, on the line above the label it belongs to. That is
   what the criterion editor did from the day it was written — it asked for a `.scale-label`
   class that was never defined anywhere, so nothing overrode either rule. Jack, 2026-09-07.
   The `label.` in the selector is not decoration: it is needed to outrank `.field label`. */
.field label.check-label {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-weight: 650;
}
.field label.check-label input[type="checkbox"] {
  width: auto;
  flex: none;
  margin: 0.15rem 0 0;
}

/* A row's name, opening that row's own editor. Deliberately a <button> and not an <a>: it acts
   on this page instead of navigating, and an anchor that does not navigate quietly breaks
   middle-click, open-in-new-tab and the status-bar preview — it promises a destination it does
   not have. Styled as a link because in a table the name is where people click. When the reader
   cannot edit, it renders as plain text rather than as a link that does nothing. */
.cell-link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--navy-600);
  text-align: left;
  text-decoration: underline;
  cursor: pointer;
}
.cell-link:hover { text-decoration: none; }
.cell-link:disabled { color: inherit; text-decoration: none; cursor: default; }

/* One figure inside an already-flagged row that is itself the contradiction — the pay on a
   løntrin whose points say it should be higher. The row carries is-flagged; this says which
   number caused it, so the reader is not left comparing rows by eye. Colour is not the only
   signal: the cell carries a title, and the card foot explains it in words. */
.is-warn-text { color: var(--accent); font-weight: 700; }
/* Marks a field the form refuses to save without — currently only køn, which the whole
   gender-split analysis rests on. */
.field label .req {
  margin-left: 0.4rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bad);
}
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: 7px;
  font: inherit;
  font-size: 0.9rem;
  color: var(--ink);
  background: #fff;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--navy-600);
  box-shadow: 0 0 0 3px rgba(42, 78, 104, 0.12);
}
.field textarea { min-height: 76px; resize: vertical; }
.field-row { display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field-row-3 { display: grid; gap: 1rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }

fieldset { border: 0; margin: 0 0 1.25rem; padding: 0; }
legend {
  padding: 0;
  margin-bottom: 0.6rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Score 1–5 as radio chips — HTML state, no script. */
.scale { display: flex; gap: 0.3rem; }
.scale input { position: absolute; opacity: 0; width: 0; height: 0; }
.scale label {
  display: grid;
  place-items: center;
  width: 34px;
  height: 32px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #fff;
  font-size: 0.85rem;
  font-weight: 650;
  color: var(--muted);
  cursor: pointer;
  margin: 0;
}
.scale label:hover { border-color: var(--navy-400); }
.scale input:checked + label { background: var(--navy); border-color: var(--navy); color: #fff; }
.scale input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 1px; }

.check { display: flex; align-items: flex-start; gap: 0.5rem; margin-bottom: 0.45rem; font-size: 0.88rem; }
.check input { margin-top: 0.2rem; }

/* ---------------------------------------------------------------- law note */

.lawnote {
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  padding: 0.75rem 1rem;
  border-radius: 0 8px 8px 0;
  font-size: 0.85rem;
}
.lawnote strong { display: block; margin-bottom: 0.15rem; }

.spec {
  border-left: 3px solid var(--navy-400);
  background: #eef2f6;
  padding: 0.7rem 1rem;
  border-radius: 0 8px 8px 0;
  font-size: 0.82rem;
  color: var(--navy);
}

/* ---------------------------------------------------------------- misc blocks */

.stack > * + * { margin-top: 0.85rem; }

.deflist { margin: 0; font-size: 0.88rem; }
.deflist div { display: flex; justify-content: space-between; gap: 1rem; padding: 0.4rem 0; border-bottom: 1px solid var(--line); }
.deflist div:last-child { border-bottom: 0; }
.deflist dt { color: var(--muted); margin: 0; }
.deflist dd { margin: 0; font-weight: 600; text-align: right; }

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  position: relative;
  padding: 0 0 1rem 1.5rem;
  border-left: 2px solid var(--line);
  font-size: 0.86rem;
}
.timeline li:last-child { padding-bottom: 0; }
.timeline li::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 3px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--navy-400);
}
.timeline li.is-next::before { background: var(--accent); border-color: var(--accent); }
.timeline .when { display: block; font-weight: 700; }

.wheel { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.75rem; }
.month {
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 0.7rem 0.8rem;
  background: #fff;
  min-height: 104px;
}
.month h3 { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-bottom: 0.35rem; }
.month p { font-size: 0.84rem; margin: 0 0 0.25rem; }
.month.is-active { border-color: var(--accent); background: var(--accent-soft); }
.month.is-empty { background: #fafbfc; }

.steps { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1.25rem; }
.steps a, .steps span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  font-size: 0.82rem;
  color: var(--muted);
  text-decoration: none;
}
.steps .is-done { color: var(--ok); border-color: #bfe0d0; background: var(--ok-bg); }
.steps .is-current { background: var(--navy); border-color: var(--navy); color: #fff; font-weight: 650; }

/* ---------------------------------------------------------------- document preview */

.doc {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: var(--shadow);
  padding: 2.5rem 2.75rem;
  max-width: 46rem;
  margin: 0 auto;
  font-size: 0.9rem;
}
/* --doc-accent is set inline per document, from the same validated hex the PDF's rule and
   headings use. Falling back to --navy keeps any older markup that sets no accent looking as it
   did. Before this, the preview drew the rule in PAYVISIA navy while the PDF drew it in the
   partner's colour — one of five ways the two disagreed. */
.doc-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 2rem; border-bottom: 2px solid var(--doc-accent, var(--navy)); padding-bottom: 1rem; margin-bottom: 1.5rem; }
/* Two caps, for the reason given at .brand-logo. This one ends up in front of the customer's
   own recipients, so it is the slot where an unreadable tagline costs the most. */
.doc-head img { max-width: 160px; max-height: 44px; }
.doc-meta { text-align: right; line-height: 1.5; white-space: nowrap; }
.doc h2 { font-size: 1.3rem; margin-bottom: 0.35rem; }
.doc h3 { font-size: 0.95rem; margin: 1.5rem 0 0.5rem; color: var(--doc-accent, var(--navy)); }
.doc table.data { font-size: 0.83rem; }
.doc .sig { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; margin-top: 2.5rem; }
.doc .sig div { border-top: 1px solid var(--ink); padding-top: 0.35rem; font-size: 0.8rem; color: var(--muted); }

/* The blocks a composed document is made of. Each mirrors what PdfDocumentPresenter draws for
   the same block, so the two presentations stay recognisably one document. */
.doc-cite { font-size: 0.78rem; font-style: italic; color: var(--muted); margin-bottom: 0.5rem; }
.doc-italic { font-style: italic; }
.doc-accented { color: var(--doc-accent, var(--navy)); }
.doc-platform { color: var(--navy); }
.doc-indent { padding-left: 0.9rem; }
.doc-caveat { margin-top: 0.6rem; line-height: 1.5; }
.doc-total { margin-top: 0.4rem; }
.doc-standalone { margin-top: 0.6rem; }
/* The model flags per cell, not per row — a suppressed category in the ligelønsanalyse shows
   unflagged head counts beside a flagged name, which a row-level rule cannot express. */
.doc table.data td.is-flagged { background: var(--bad-bg); }
.doc-score { display: flex; gap: 1.4rem; align-items: flex-start; margin-bottom: 0.4rem; }
.doc-score .figure { font-size: 1.7rem; font-weight: 700; color: var(--navy); line-height: 1.1; }
.doc-score .caption { font-size: 0.78rem; color: var(--muted); }
.doc-score ul { list-style: none; margin: 0; padding: 0; }
.doc-score li { font-size: 0.83rem; margin-bottom: 0.15rem; }
.doc-foot { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 2rem; padding-top: 0.6rem; border-top: 1px solid var(--line); }

/* ---------------------------------------------------------------- draft footer */

.draft {
  padding: 1rem 1.75rem 1.5rem;
  color: var(--faint);
  font-size: 0.78rem;
  border-top: 1px solid var(--line);
  background: var(--paper);
}
.draft strong { color: var(--muted); font-weight: 650; }

/* ---------------------------------------------------------------- responsive */

@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-2-1, .grid-3 { grid-template-columns: minmax(0, 1fr); }
  .wheel { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar { position: static; height: auto; }
  .nav { display: flex; flex-wrap: wrap; gap: 0.25rem; padding: 0.75rem; }
  .nav-group { width: 100%; margin: 0.5rem 0 0.1rem; }
  .grid-4, .grid-2, .field-row, .field-row-3 { grid-template-columns: minmax(0, 1fr); }
  .content, .topbar { padding-left: 1rem; padding-right: 1rem; }
  .doc { padding: 1.5rem 1.25rem; }

  /* The sidebar collapsed here from the start; the topbar did not, and it was the one thing
     still forcing the page sideways on a phone. Its two halves total ~405px of nowrap content
     against a 360px viewport, so every page scrolled horizontally — a data table scrolling
     inside .table-wrap is fine, the page itself doing it is not. */
  .topbar { flex-wrap: wrap; row-gap: 0.6rem; }
  .topbar > * { min-width: 0; }
  .topbar-right { flex-wrap: wrap; justify-content: flex-end; }
  .switcher summary { max-width: 100%; }
}

/* ---------------------------------------------------------------- toast
   Added for the product (not from the prototype): the little popup that answers a click on a
   control whose feature is not built in this etape. */

.toast {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 1000;
  max-width: 22rem;
  background: var(--navy);
  color: #fff;
  padding: 0.7rem 1rem;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  font-size: 0.86rem;
  line-height: 1.4;
  animation: toast-in 0.18s ease-out;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(0.5rem); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------------- print */

@media print {
  .sidebar, .topbar, .btn-row, .draft-hide, .toast { display: none !important; }
  body { background: #fff; }
  .app { display: block; }
  .content { padding: 0; }
  .doc { border: 0; box-shadow: none; max-width: none; padding: 0; }
}

/* ---------------------------------------------------------------- sign-in
   Added for the product (not from the prototype): the screen that exists before there is a
   tenant, and the top bar's replacement for the old dev user switcher. */

.bare { min-height: 100vh; display: grid; place-items: center; background: var(--navy-900); padding: 2rem 1rem; }
.signin { width: 100%; max-width: 24rem; }

/* The "next step" link at the foot of every flow page. Deliberately NOT a button: the control it
   replaces was a link wearing a submit button's clothes, in a card footer under an editable
   table, and it was read as "save" by everyone who met it. A link that looks like a link cannot
   make that promise. */
.next-step { margin: 1.5rem 0 0; text-align: right; font-size: 0.9rem; }
.next-step a { color: var(--navy-600); font-weight: 600; text-decoration: none; }
.next-step a:hover { text-decoration: underline; }

/* The stored logo on the partner form. A checked ground rather than white, because most brand
   marks are dark on transparent and would otherwise be invisible against the card. */
.logo-preview {
  display: inline-block;
  margin-bottom: 0.6rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fafbfc;
}
.logo-preview img { display: block; max-width: 180px; max-height: 64px; }

/* The neutral platform's landing page. It shares .bare with the sign-in screen deliberately —
   same ground, same logo block — and only widens the column, so the two read as one product
   rather than as a marketing site bolted onto an app. */
/* `align-self` on the item rather than a `:has()` rule on the container, so this needs no
   selector support to work: .bare centres its child vertically, which is right for a short
   sign-in card and wrong for a page taller than the viewport — centred overflow pushes the top
   ABOVE the scroll origin, where scrolling cannot reach it and the heading is simply gone. */
.landing { width: 100%; max-width: 60rem; color: #dce5ec; align-self: start; }
.landing-head { max-width: 42rem; }
.landing-head h1 { margin: 0 0 0.75rem; font-size: 1.9rem; line-height: 1.2; color: var(--paper); }
.landing-lead { margin: 0; font-size: 1rem; line-height: 1.6; color: #b9c8d4; }
.landing-cards { display: grid; gap: 1rem; margin: 2rem 0; grid-template-columns: 1fr; }
@media (min-width: 780px) { .landing-cards { grid-template-columns: repeat(3, 1fr); } }
.landing-card { background: var(--paper); border-radius: var(--radius); padding: 1.25rem 1.35rem; }
.landing-card h2 { margin: 0 0 0.5rem; font-size: 0.95rem; color: var(--navy); }
.landing-card p { margin: 0; font-size: 0.86rem; line-height: 1.55; color: var(--muted); }
.landing-panel { background: rgba(255, 255, 255, 0.06); border-radius: var(--radius); padding: 1.25rem 1.35rem; }
.landing-panel h2 { margin: 0 0 0.6rem; font-size: 0.95rem; color: var(--paper); }
.landing-panel p { margin: 0 0 0.6rem; font-size: 0.88rem; line-height: 1.6; }
.landing-panel p:last-child { margin-bottom: 0; }
.landing-caveat { color: var(--warn-light); }
.landing-actions { margin-top: 2rem; }
.landing-note { margin: 1rem 0 0; font-size: 0.88rem; line-height: 1.6; color: #b9c8d4; max-width: 42rem; }
.landing a { color: var(--paper); }
.landing .btn-primary { color: var(--paper); }
.signin-card { background: var(--paper); border-radius: var(--radius); box-shadow: var(--shadow); padding: 2rem 1.75rem; }
/* Two caps, for the reason given at .brand-logo. Wider here than in the sidebar: the card is
   328 px inside its padding, and sign-in is where the mark is doing the introducing. */
/* The gap under the mark used to come from .signin-product's margin. That label is now rendered
   only on a partner's host, so the spacing has to belong to the mark instead — and it differs by
   case: alone, the mark needs the full gap before the form; with the label under it, the two are
   one block and want to sit close. Margins between adjacent siblings collapse to the larger of
   the two, so this cannot be expressed by giving the label a smaller top margin — the modifier
   is what carries it. Same class and same condition as .brand-logo.is-partner. */
.signin-logo { max-width: 200px; max-height: 52px; display: block; margin-bottom: 1.5rem; }
.signin-logo.is-partner { margin-bottom: 0.35rem; }

/* One class, two grounds: .signin-card is white, .landing-head is --navy-900. The mark is navy
   #003366 either way, so the landing page needs the same inversion the sidebar does. This was
   survivable while the mark was Allegro IT's lighter blue and merely low-contrast on that
   ground; against the delivered navy it is the same colour as the page, and the logo simply
   disappeared. Keyed on the container rather than adding a modifier class, so no page has to
   remember which ground it is standing on. */
.landing-head .signin-logo { filter: brightness(0) invert(1); }
/* Display type, for the reason given at .brand-sub. The top margin is gone: .signin-logo now
   owns the space above, because it is the element that is always there. */
.signin-product {
  margin: 0 0 1.5rem;
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.signin-error {
  background: var(--bad-bg);
  color: var(--bad);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
  margin-bottom: 1rem;
}
.signin-submit { width: 100%; justify-content: center; margin-top: 0.5rem; }
.signin-note { margin: 1.25rem 0 0; font-size: 0.76rem; color: var(--muted); line-height: 1.5; }

.signout { display: flex; align-items: center; gap: 0.75rem; margin: 0; }
.signout-who { display: none; text-align: right; line-height: 1.25; font-size: 0.82rem; }
.signout-who .sub { display: block; color: var(--muted); font-size: 0.75rem; }
@media (min-width: 860px) { .signout-who { display: block; } }
.btn-quiet { background: transparent; border-color: var(--line); color: var(--muted); }
.btn-quiet:hover { color: var(--ink); border-color: var(--navy-400); }

/* --- Platform administration ------------------------------------------------------------
   The operator's own area. Deliberately plain: it sits outside the customer-facing shell
   (BareLayout, no sidebar, no tenant switcher) because it belongs to nobody's tenant, and
   looking different from the product is the point rather than an omission. */
.platform-shell { min-height: 100vh; background: var(--bg); }
/* The sign-out for the two shells that have no TopBar (PlatformLayout, PartnerLayout).
   Aligned to .platform's own 1100px column so it sits over the page it belongs to rather than
   floating against the viewport edge. */
.signout-bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .75rem;
  max-width: 1100px;
  margin: 0 auto;
  padding: .9rem 1.25rem 0;
}
.signout-bar-who { font-size: .85rem; color: var(--muted); }
.platform { max-width: 1100px; margin: 0 auto; padding: 2rem 1.25rem 4rem; }
.platform-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; }
.platform-head h1 { margin: 0 0 .25rem; }
.platform-head .muted { max-width: 60ch; }
.platform .card { margin-bottom: 1.25rem; }
.platform ul.plain { list-style: none; margin: 0 0 1rem; padding: 0; }
.platform ul.plain li { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .4rem 0; border-bottom: 1px solid var(--line); }
.platform ul.plain li:last-child { border-bottom: 0; }

/* The grants panel in the platform shell. It renders only for an account a customer has let
   in, so it is styled as the exception it is — a warm border against the shell's plain grey,
   rather than another quiet card. Aligned to .platform's own column, like .signout-bar. */
.platform-grants {
  max-width: 1100px;
  margin: 1rem auto 0;
  padding: .9rem 1.1rem;
  background: var(--warn-bg);
  border: 1px solid #ecd9b0;
  border-radius: var(--radius);
  color: #7a5b18;
}
.platform-grants-head { display: flex; align-items: flex-start; gap: .75rem; }
.platform-grants-head strong { display: block; margin-bottom: .15rem; }
.platform-grants-head p { margin: 0; font-size: .88rem; }
.platform-grants-list { list-style: none; margin: .75rem 0 0; padding: 0; }
.platform-grants-list li {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
  padding: .45rem 0;
  border-top: 1px solid #ecd9b0;
}
/* The lapse sentence is long on purpose — a sliding date has to say that it slides — so it
   takes the remaining width rather than pushing the button off the row. */
.platform-grants-list li .small { flex: 1 1 20rem; }

/* ------------------------------------------------------- visually hidden */

/* Off-screen rather than display:none, so a file input stays reachable by keyboard and by a
   screen reader while its own <label> is what gets styled as a button. display:none would
   remove it from the accessibility tree and from the tab order along with the pixels. */
.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;
}

/* Bot defence: the honeypot field, hidden from people but not from a naive bot.
   Positioned off-screen rather than `display: none` alone — some bots skip anything
   display:none, which would defeat the whole point of the field. See
   .claude/rules/bot-defence.md and src/Payvisia.Web/Services/FormGuard.cs. */
.hp-field {
    position: absolute;
    left: -9999px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* The edit form opens inside the table, where the row is.

   It used to be a card under the list. On a table of any length that puts the form below the
   fold, so clicking "Rediger" appeared to do nothing at all — met on 2026-09-05. Opening in
   place also keeps the row's own context on screen while it is being edited. */
tr.row-editor > td {
  padding: 0;
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
}
.row-editor-body { padding: 1.15rem 1.25rem; }
.row-editor-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 0 0 0.9rem;
}
.row-editor-head h2 { font-size: 0.95rem; }
.row-editor-head .hint { color: var(--muted); font-size: 0.82rem; }
.row-editor-body .field:last-of-type { margin-bottom: 0.9rem; }

/* The form's own buttons sit right, under the row's own Rediger/Slet. Left-aligned they read
   as a third pair of controls belonging to the table; right-aligned they close the form where
   the eye already is. Jack, 2026-09-05. */
.row-editor-body .btn-row { justify-content: flex-end; }

/* The template link, under the button row it is subordinate to. It needs real space above it:
   sitting tight under the buttons it read as their caption rather than as its own small act. */
.template-hint {
  margin: 1rem 0 0;
  font-size: 0.82rem;
  color: var(--muted);
}

/* ------------------------------------------------- suggestion field (combobox)

   The native <datalist> these replaced (2026-09-10) drew its popup outside this stylesheet
   entirely — the browser's own panel, in the OS theme, 564 rows tall on the DISCO field. Every
   rule below exists because none of it could be written before. */
.suggest { position: relative; }

.suggest-list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  max-height: 17rem;
  overflow-y: auto;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 43, 87, 0.13);
}

.suggest-option {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem 0.55rem;
  border-radius: 4px;
  cursor: pointer;
}

/* Hover and keyboard highlight are one state deliberately: two different-looking "current"
   options on screen at once is the classic combobox confusion. */
.suggest-option:hover,
.suggest-option.is-active { background: var(--accent-soft); }

.suggest-value {
  font-size: 0.86rem;
  font-weight: 650;
  color: var(--ink);
}

.suggest-description {
  font-size: 0.78rem;
  color: var(--muted);
}

/* ---------------------------------------------------------------- notice

   A fact that belongs ON the thing it is about, rather than in a card beside it. Same shape as
   .lawnote — which states what the law says — but this one states what is wrong with the data
   in front of you, so it carries the warning colours and appears only when there is something
   to say. Introduced 2026-09-10 when the Datakvalitet panel was removed from /medarbejdere:
   five of its six rows were counts nobody acted on, and the sixth stopped the analysis. */
.notice {
  margin: 0 1.1rem 1rem;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 8px 8px 0;
  font-size: 0.85rem;
}
.notice strong { display: block; margin-bottom: 0.15rem; }
.notice-bad { border-left-color: var(--bad); background: var(--bad-bg); }

/* -------------------------------------------------------- sub-processors
   A legal table on a document page: readable at a glance, and horizontally scrollable rather
   than squeezed on a narrow screen — a truncated processor name is a wrong legal statement. */
.subprocessors { width: 100%; border-collapse: collapse; margin: 0.75rem 0 1.25rem; font-size: 0.94rem; }
.subprocessors th { text-align: left; font-weight: 600; padding: 0.4rem 0.6rem; border-bottom: 2px solid var(--navy); }
.subprocessors td { padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--line); vertical-align: top; }

/* ------------------------------------------------------------- policy page
   A document inside the anonymous shell. `.bare` centres its child on both axes and is sized
   for a 24rem sign-in card, so a long document needs `align-self: start` and its own width —
   otherwise it renders vertically centred and cramped on the navy ground. */
.policy {
  width: 100%;
  max-width: 48rem;
  align-self: start;
  background: var(--paper);
  border-radius: var(--radius);
  padding: 2rem 2.25rem;
}
.policy h1 { margin: 0 0 0.25rem; }
.policy h2 { margin: 1.75rem 0 0.5rem; font-size: 1.05rem; }
.policy p, .policy li { line-height: 1.55; }
.policy .lede { color: var(--muted); margin: 0 0 1.5rem; }
.policy-foot { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--line); font-size: 0.9rem; }
@media (max-width: 40rem) { .policy { padding: 1.25rem; } }

/* ------------------------------------------------------- legal footer links
   On the anonymous shell they sit under the card on the navy ground; inside the app they join
   the pilot caveat. Both are quiet: a policy link is found when looked for, not advertised. */
.bare-foot { margin-top: 1.25rem; display: flex; gap: 1.25rem; justify-content: center; flex-wrap: wrap; font-size: 0.85rem; }
.bare-foot a { color: rgba(255, 255, 255, 0.75); }
.bare-foot a:hover { color: #fff; }
