/* Karm stylesheet. Palette "Slate and steel" (CLAUDE.md, section 7). Use only the variables. */

@font-face {
  font-family: "IBM Plex Sans";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("../fonts/IBMPlexSans-Regular.2a953942ae89.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url("../fonts/IBMPlexSans-Medium.7339635f4f65.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("../fonts/IBMPlexMono-Regular.eaf6b13c8b24.woff2") format("woff2");
}

:root {
  --ink: #1F2933;
  --ink-2: #4A5560;
  --line: #C9CCC8;
  --paper: #F4F4F1;
  --surface: #FFFFFF;
  --action: #2B5C8A;
  --action-pressed: #1F4A72;
  --on-action: #FFFFFF;
  --header-bg: var(--ink);
  --header-ink: #F4F4F1;

  --status-idle: #8A939B;
  --status-progress: #E0A100;
  --status-done: #1A5E37;
  --status-avvik: #DC4B38;
  /* Amber outside the plan: only for unmet door type requirements (see CLAUDE.md, colour exceptions). */
  --warn: var(--status-progress);

  --font: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --touch: 48px;
  /* Density: compact by default (mouse and keyboard), 48 px on touch screens (gloves, ladders).
     Change these two to tune the whole app. */
  --control-h: 36px;
  --row-h: 36px;
  --base-font: 15px;
  --radius: 3px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #F4F4F1;
    --ink-2: #B9C0C7;
    --line: #3A4652;
    --paper: #14191F;
    --surface: #1F2933;
    --action: #7FA8D1;
    --action-pressed: #A3C2E0;
    --on-action: #14191F;
    --header-bg: var(--surface);
    --header-ink: #F4F4F1;

    --status-progress: #F2B92E;
    --status-done: #5CC08A;
    --status-avvik: #E5584C;
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }
/* The hidden attribute must always win, also over display rules on buttons etc. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--base-font);
  line-height: 1.45;
}

h1, h2, h3 { font-weight: 500; line-height: 1.2; margin: 0 0 0.6rem; }
h1 { font-size: 1.3rem; }
h2 { font-size: 1.05rem; margin-top: 1.1rem; }

a { color: var(--action); }
a:hover, a:active { color: var(--action-pressed); }

code, .mono { font-family: var(--mono); font-size: 0.95em; }

/* --- Header --------------------------------------------------------------- */

.site-header {
  background: var(--header-bg);
  color: var(--header-ink);
  border-bottom: 1px solid var(--line);
}
.site-header .inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 56px;
  flex-wrap: wrap;
}
.site-header .logo { display: block; height: 32px; width: auto; }
.site-header nav { display: flex; gap: 0.25rem; flex: 1; flex-wrap: wrap; }
.site-header nav.user { flex: 0 0 auto; }
.site-header a, .site-header button.link {
  color: var(--header-ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  padding: 0 0.75rem;
}
.site-header a:hover, .site-header button.link:hover { text-decoration: underline; }
/* Search in the header. The form fills the header's height (the menus stretch), so it centres its box;
   the selectors carry .site-header to win over the general input rule further down. */
.site-header .header-search { margin: 0; display: flex; align-items: center; }
.site-header .header-search input, .site-header .menu-search input {
  min-height: 0; height: 32px; margin: 0; padding: 0 0.5rem; border-radius: 2px;
}
.site-header .header-search input { width: clamp(8rem, 16vw, 14rem); }
.site-header .menu-search { margin: 0; padding: 0.25rem 0.5rem 0.5rem; }
.site-header .menu-search input { width: 100%; height: var(--control-h); }
/* Suggestions while typing (search.js). Below the box on desktop; in the ☰ menu they push the menu down. */
.site-header .header-search, .site-header .menu-search { position: relative; }
.search-suggest {
  position: absolute; left: 0; top: 100%; z-index: 1200; width: 26rem; max-width: calc(100vw - 2rem);
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 2px; padding: 0.25rem 0;
}
.header-search .search-suggest { left: auto; right: 0; }
.menu-search .search-suggest { position: static; width: auto; margin-top: 0.25rem; }
.search-suggest .suggest-head { padding: 0.35rem 0.75rem 0.15rem; font-size: 0.8rem; color: var(--ink-2); text-transform: uppercase; letter-spacing: 0.04em; }
.site-header .search-suggest a {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; min-height: var(--row-h);
  padding: 0.2rem 0.75rem; color: var(--ink); text-decoration: none; width: 100%;
}
.search-suggest .sub { font-size: 0.85rem; color: var(--ink-2); }
.site-header .search-suggest a:hover, .site-header .search-suggest a.active { background: var(--paper); text-decoration: none; }
.site-header .search-suggest a.active { outline: 2px solid var(--action); outline-offset: -2px; }
.site-header .search-suggest a.suggest-all { color: var(--action); border-top: 1px solid var(--line); }
.search-suggest .suggest-empty { padding: 0.4rem 0.75rem; color: var(--ink-2); }
.site-header .who { color: var(--header-ink); opacity: 0.8; padding: 0 0.75rem; align-self: center; }
/* DEV flag (dev installation only): far right in the header, top right on the login page (no header there). */
.dev-flag {
  flex: 0 0 auto; align-self: center; padding: 0.1rem 0.45rem; border-radius: 2px;
  background: var(--header-ink); color: var(--header-bg);
  font-family: var(--mono); font-size: 0.85rem; letter-spacing: 0.05em;
}
.dev-flag.corner { position: fixed; top: 0.75rem; right: 1rem; z-index: 10; background: var(--ink); color: var(--paper); }

/* Full width: use the whole screen, with a 16 px gutter. Only forms are kept narrow (readability). */
.inner { padding: 0 1rem; }
main.inner { padding-top: 0.75rem; padding-bottom: 1.5rem; }

/* --- System warning (the one allowed non-status use of red) --------------- */

.system-alert {
  background: var(--status-avvik);
  color: #FFFFFF;
  font-weight: 500;
}
.system-alert .inner { display: flex; gap: 0.75rem; align-items: flex-start; padding-top: 0.75rem; padding-bottom: 0.75rem; }
.system-alert svg { flex: 0 0 auto; margin-top: 2px; }
.system-alert p { margin: 0; }
.system-alert .detail { font-weight: 400; }

/* --- Messages and markers ------------------------------------------------- */

.messages { list-style: none; margin: 0 0 1.25rem; padding: 0; }
.messages li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--action);
  padding: 0.6rem 0.9rem;
  margin-bottom: 0.5rem;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}
.messages li.error, .messages li.warning { border-left-color: var(--ink); font-weight: 500; }
.messages .message-text { flex: 1 1 auto; }
/* × (static/js/messages.js): quiet, but a full-size target. */
.messages .message-close {
  flex: 0 0 auto; background: none; border: 0; color: var(--ink-2); font-weight: 400;
  min-height: 0; padding: 0 0.4rem; margin: -0.6rem -0.9rem -0.6rem 0; align-self: stretch; font-size: 1.25em; line-height: 1;
}
.messages .message-close:hover { background: var(--paper); color: var(--action); }
@media (pointer: coarse) { .messages .message-close { min-width: 48px; } }

.tag {
  display: inline-block;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0 0.4rem;
  font-size: 0.85rem;
  color: var(--ink-2);
  white-space: nowrap;
}
.tag.readonly { border-color: var(--ink-2); }

.muted { color: var(--ink-2); }

/* --- Page heading row ----------------------------------------------------- */

.page-head { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.page-head h1 { margin: 0; }
.page-head .actions { margin-left: auto; display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* --- Buttons and forms ---------------------------------------------------- */

.button, button, input[type="submit"] {
  font: inherit;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-h);
  padding: 0 0.9rem;
  border: 1px solid var(--action);
  border-radius: var(--radius);
  background: var(--action);
  color: var(--on-action);
  text-decoration: none;
  cursor: pointer;
}
.button:hover, button:hover, .button:active, button:active { background: var(--action-pressed); border-color: var(--action-pressed); color: var(--on-action); }

.button.secondary, button.secondary { background: var(--surface); color: var(--action); border-color: var(--line); }
.button.secondary:hover, button.secondary:hover { border-color: var(--action); color: var(--action-pressed); background: var(--surface); }
/* Service draft: an action that isn't built yet. Grey, dashed, does nothing (a span, not a button). */
.button.soon, .button.soon:hover { background: var(--surface); color: var(--ink-2); border: 1px dashed var(--line); cursor: not-allowed; }
.soon-text { cursor: not-allowed; }

button.link { background: none; border: 0; font-weight: 400; padding: 0; min-height: 0; color: var(--action); }
button.link:hover { background: none; text-decoration: underline; }

form.inline { display: inline; }

.form { max-width: 560px; }
.field { margin-bottom: 0.7rem; }
.field label { display: block; font-weight: 500; margin-bottom: 0.25rem; }
.field .help { color: var(--ink-2); font-size: 0.9rem; margin-top: 0.25rem; }
.field .errorlist, .form > .errorlist { list-style: none; padding: 0; margin: 0.25rem 0 0; font-weight: 500; }
.field .errorlist li::before, .form > .errorlist li::before { content: "! "; }

input[type="text"], input[type="password"], input[type="search"], input[type="email"], input[type="number"],
input[type="date"], input[type="file"], select, textarea {
  font: inherit;
  width: 100%;
  min-height: var(--control-h);
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
}
textarea { min-height: 6rem; }
/* A locked field (e.g. a component in use; Mads 2026-10-22): the value as plain text, no box to type into, and
   «låst» by the label (templates/_field.html). Full ink, not grey: it's a real value, just not changeable here. */
input:disabled:not([type="checkbox"]):not([type="radio"]), select:disabled, textarea:disabled {
  border-color: transparent; background: transparent; color: var(--ink); -webkit-text-fill-color: var(--ink);
  opacity: 1; padding-left: 0; padding-right: 0; appearance: none; -webkit-appearance: none; cursor: default;
}
textarea:disabled { min-height: 0; resize: none; }
.tag.locked { margin-left: 0.35rem; font-size: 0.75rem; line-height: 1.3; vertical-align: 1px; }
/* Numbers and dates don't need the full width. */
input[type="number"], input[type="date"], input.number { max-width: 14rem; font-variant-numeric: tabular-nums; }
/* Feedback while a slow form works (static/js/busy-forms.js, templates/_busy_status.html). */
.busy-status { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; margin: 0.75rem 0; grid-column: 1 / -1; }
.busy-status[hidden] { display: none; }
.busy-bar { flex: 0 0 100%; height: 4px; background: var(--line); position: relative; overflow: hidden; }
.busy-bar::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: -30%; width: 30%; background: var(--action);
  animation: busy-slide 1.2s ease-in-out infinite;
}
@keyframes busy-slide { from { left: -30%; } to { left: 100%; } }
@media (prefers-reduced-motion: reduce) { .busy-bar::after { animation: none; left: 0; width: 100%; } }
.busy-status .busy-text { font-weight: 500; }
.busy-status .busy-note { color: var(--ink-2); }
form.busy button.pressed { opacity: 0.75; cursor: progress; }
form.busy .page-pick:not(.pressed) { opacity: 0.4; }
form.busy .page-pick.pressed { outline: 3px solid var(--action); outline-offset: 2px; }

/* Day-first date fields (core/forms.py DateField, static/js/date-fields.js): text field + calendar button.
   The real <input type="date"> sits invisibly under the button, so the browser's picker opens there. */
.date-field { display: inline-flex; align-items: stretch; gap: 0.35rem; position: relative; }
.date-field input.date-text { width: 9.5rem; max-width: 9.5rem; font-variant-numeric: tabular-nums; }
.date-field .date-pick { padding: 0 0.5rem; min-width: var(--control-h); display: inline-flex; align-items: center; justify-content: center; }
.date-field .date-pick[hidden] { display: none; }
.date-field .date-pick .icon { width: 20px; height: 20px; }
.date-field .date-pick-native {
  position: absolute; right: 0; bottom: 0; width: var(--control-h); height: 1px; min-height: 0;
  padding: 0; border: 0; opacity: 0; pointer-events: none;
}
input[type="file"] { padding: 0.35rem 0.6rem; }

/* Touch screens: everything back to full size. */
@media (pointer: coarse) {
  :root { --control-h: var(--touch); --row-h: var(--touch); --base-font: 16px; }
  .rail a, .rail .soon { min-height: 64px; }
  form.qty input, form.qty button { min-height: 44px; height: 44px; }
}
input:focus, select:focus, textarea:focus, button:focus-visible, a:focus-visible {
  outline: 2px solid var(--action);
  outline-offset: 1px;
}
/* 16 px on PC, flush with the text (Mads 2026-10-19); 22 px on touch, where the label around it is the 48 px target. */
input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--action); vertical-align: middle; }
@media (pointer: coarse) { input[type="checkbox"] { width: 22px; height: 22px; } }
.check { display: inline-flex; align-items: center; gap: 0.5rem; min-height: var(--control-h); cursor: pointer; }

.filter-bar { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.6rem; }
/* Dørliste: an action for the ticked doors («Sett dørtype»). */
.bulk-bar { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.6rem; }
.filter-bar input[type="search"] { width: auto; flex: 1 1 16rem; max-width: 28rem; }

/* --- Tables --------------------------------------------------------------- */

.table-wrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--line); }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 0.3rem 0.65rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
th { font-weight: 500; color: var(--ink-2); font-size: 0.9rem; white-space: nowrap; }
/* Sortable column headers (dørliste): they look like the others; the active one gets ▴/▾, a hover underlines. */
th a.sort { color: inherit; text-decoration: none; }
th a.sort:hover, th a.sort:focus-visible { text-decoration: underline; }
th[aria-sort] { color: var(--ink); }
tr:last-child td { border-bottom: 0; }
td.num { font-family: var(--mono); white-space: nowrap; }
tbody tr { height: var(--row-h); }
td a.row-link { display: block; text-decoration: none; }
td a.row-link:hover { text-decoration: underline; }
td .sub { font-size: 0.8rem; }

/* New bid/project: the job number field only applies to "Prosjekt". Pure CSS, no JS. */
.create-project:has(input[name="kind"][value="tilbud"]:checked) .field-job_number { display: none; }
.field ul.radio, .field div[id$="kind"] { list-style: none; padding: 0; margin: 0; }
.field-kind label { font-weight: 400; }
.field-kind > label { font-weight: 500; }
.field-kind div > div label, .field-kind li label { display: flex; align-items: center; gap: 0.5rem; min-height: var(--control-h); cursor: pointer; }
input[type="radio"] { width: 22px; height: 22px; accent-color: var(--action); margin: 0; }

dl.facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.15rem 1.5rem; margin: 0; background: var(--surface); border: 1px solid var(--line); padding: 0.6rem 0.9rem; }
dl.facts dt { color: var(--ink-2); }
dl.facts dd { margin: 0; }

/* --- Login ---------------------------------------------------------------- */

.auth-page { max-width: 420px; margin: 3rem auto; padding: 0 1rem; }
/* The SVG has ~6 px empty on each side at this size (10 of 100 units' height), pulled in so «for»
   has the same space on both sides and the centred row centres what you see. */
.auth-page .logo { height: 56px; width: auto; display: block; margin-inline: -6px; }
/* «Karm for <company>»: the company logo matches the height of Karm's door frame (~74% of 56 px). */
.auth-brand { display: flex; align-items: center; justify-content: center; gap: 0.6rem; margin-bottom: 1.5rem; min-height: 56px; }
.auth-brand .for { color: var(--ink-2); font-size: 1.1rem; }
/* Light paper: the normal logo straight on the page, no plate (Mads, 2026-10-13), as tall as the
   negative one. Dark paper without a negative logo: the normal logo needs its white plate. */
.auth-brand .company-mark { display: inline-flex; }
.auth-brand .company-mark img { display: block; height: 42px; width: auto; max-width: 220px; object-fit: contain; }
.auth-brand .company-mark.dark-plate { background: #1F2933; border: 1px solid #1F2933; border-radius: 2px; padding: 4px 8px; }
.auth-brand .company-mark.dark-plate img { height: 32px; max-width: 200px; }
@media (prefers-color-scheme: dark) {
  .auth-brand .company-mark:not(.dark-plate) { background: #FFFFFF; border: 1px solid var(--line); border-radius: 2px; padding: 4px 8px; }
  .auth-brand .company-mark:not(.dark-plate) img { height: 32px; max-width: 200px; }
}
.auth-brand .company-mark-negative { display: block; height: 42px; width: auto; max-width: 220px; object-fit: contain; }
.auth-brand .company-name { font-size: 1.25rem; font-weight: 500; }
/* A wide company logo shrinks (object-fit keeps its shape) rather than push the row past a narrow screen. */
.auth-brand .company-mark, .auth-brand .company-mark-negative { min-width: 0; }
.auth-brand .company-mark img { max-width: min(220px, 100%); }
/* With a background photo (Firmainnstillinger) the photo fills the page and «Karm for <company>» moves
   into the login box (Mads 2026-10-20): logos on a photo are unreadable on some photos. Smaller, to fit. */
.login-photo { position: fixed; inset: 0; background: var(--paper) center / cover no-repeat; }
.login-photo + .auth-page { position: relative; }
.auth-brand.in-panel { zoom: 0.8; padding-bottom: 1.5rem; border-bottom: 1px solid var(--line); }
@media (max-width: 400px) { .auth-brand.in-panel { zoom: 0.72; } }
.auth-page .panel { background: var(--surface); border: 1px solid var(--line); padding: 1.5rem; }
.auth-page button { width: 100%; }
/* Error pages (templates/_error_page.html): the login page's look. */
.error-page h1 { margin-top: 0; }
.error-page p:last-child { margin-bottom: 0; }

.auth-page .logo-on-paper-dark { display: none !important; }
@media (prefers-color-scheme: dark) {
  .auth-page .logo-on-paper-light { display: none !important; }
  .auth-page .logo-on-paper-dark { display: block !important; }
}

footer.site-footer { color: var(--ink-2); font-size: 0.85rem; padding-block: 2rem; }

/* --- Project shell: crumbs in the top bar, icon rail on the left, content fills the rest --- */

:root { --header-h: 48px; --rail-w: 76px; }
.site-header .inner { min-height: var(--header-h); gap: 1rem; }
/* The SVG's door frame fills ~74% of its height, so 32 px gives a ~24 px frame: the same height as
   the company logo plate next to it (18 px + 2 × 3 px padding). */
.site-header .logo { height: 32px; }
.site-header a, .site-header button.link { min-height: var(--header-h); }

.crumbs { display: flex; align-items: center; gap: 0.25rem; flex: 1; min-width: 0; flex-wrap: nowrap; }
.crumbs > span[aria-hidden] { opacity: 0.6; }
.crumbs .project-title { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; line-height: var(--header-h); }
.tag.on-dark { color: var(--header-ink); border-color: currentColor; opacity: 0.85; }

.project-app { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); min-height: calc(100vh - var(--header-h)); }
.project-main { padding: 0.75rem 1rem 2rem; min-width: 0; }

.rail { background: var(--surface); border-right: 1px solid var(--line); }
.rail ul { list-style: none; margin: 0; padding: 0; position: sticky; top: 0; }
.rail a, .rail .soon {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: 56px; padding: 5px 2px; text-decoration: none; text-align: center;
  font-size: 0.7rem; line-height: 1.1; border-left: 3px solid transparent; color: var(--ink-2);
}
.rail a:hover { color: var(--action); background: var(--paper); }
.rail a.active { color: var(--action); border-left-color: var(--action); background: var(--paper); font-weight: 500; }
.rail .soon { opacity: 0.4; cursor: default; }
.rail .icon { flex: 0 0 auto; }

/* Phones: the rail becomes a tab bar at the bottom of the screen (thumb reach). */
@media (max-width: 760px) {
  .crumbs > a:first-child, .crumbs > span[aria-hidden] { display: none; }
  .site-header .who { display: none; }
  .project-app { grid-template-columns: minmax(0, 1fr); }
  .project-main { padding: 0.75rem 0.75rem calc(80px + env(safe-area-inset-bottom)); }
  .rail {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000;
    border-right: 0; border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .rail ul { display: flex; overflow-x: auto; position: static; }
  .rail li { flex: 1 0 64px; }
  .rail li:has(.soon) { display: none; }
  .rail a { border-left: 0; border-top: 3px solid transparent; }
  .rail a.active { border-top-color: var(--action); }
}

/* --- Plans ------------------------------------------------------------------ */

.row-actions { white-space: nowrap; text-align: right; }
.row-actions > * { margin-left: 0.75rem; }
.row-actions button.link[disabled] { color: var(--line); cursor: default; text-decoration: none; }
.inline-form { display: flex; gap: 0.75rem; align-items: flex-end; flex-wrap: wrap; }
.inline-form .field { margin-bottom: 0; flex: 1 1 16rem; }
.inline-form .field .help { display: none; }

.notice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--ink);
  padding: 0.6rem 0.9rem;
  margin-bottom: 0.75rem;
  font-weight: 500;
}

.page-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; }
.page-pick {
  display: flex; flex-direction: column; gap: 0.5rem; height: auto; padding: 0.5rem;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line);
}
.page-pick:hover, .page-pick:focus-visible { background: var(--surface); color: var(--action); border-color: var(--action); }
.page-pick img { width: 100%; height: auto; border: 1px solid var(--line); background: #FFFFFF; }

.plan-bar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.floor-tabs { display: flex; flex-wrap: wrap; border: 1px solid var(--line); background: var(--surface); }
.floor-tabs a {
  display: inline-flex; align-items: center; min-height: var(--control-h); padding: 0 1rem;
  color: var(--ink); text-decoration: none; border-bottom: 4px solid transparent;
}
.floor-tabs a + a { border-left: 1px solid var(--line); }
.floor-tabs a.active { border-bottom-color: var(--action); color: var(--action); font-weight: 500; }
.plan-bar .floor-tabs { margin-right: auto; }
.rev-pick { display: flex; align-items: center; gap: 0.5rem; }
.rev-pick select { width: auto; }

/* Fixed height, so nothing shifts while tiles load. On plan pages the drawing fills
   everything below the top bar and the one-line plan bar. */
.plan-wrap { position: relative; }
.plan { height: 70vh; min-height: 360px; background: var(--surface); border: 1px solid var(--line); }
.plan-page .project-main { padding: 0; display: flex; flex-direction: column; height: calc(100vh - var(--header-h)); height: calc(100dvh - var(--header-h)); }
.plan-page .plan-wrap { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.plan-page .plan { flex: 1 1 auto; height: auto; min-height: 300px; border: 0; }
.plan-page .notice, .plan-page .messages { flex: 0 0 auto; margin: 0; border-left-width: 4px; border-top: 0; border-right: 0; }
.plan-page .messages li { margin: 0; border-top: 0; border-right: 0; }

/* The plan bar: one thin strip flush under the top bar. Compact controls for mouse users;
   touch screens keep 48 px targets (gloves). */
.plan-page .plan-bar {
  flex: 0 0 auto; margin: 0; gap: 0.5rem; padding: 0 0.5rem 0 0;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
.plan-page .floor-tabs { border: 0; background: none; }
.plan-page .floor-tabs a + a { border-left: 0; }
.plan-page .plan-bar { min-height: 40px; }
.plan-page .floor-tabs a { min-height: 40px; padding: 0 0.85rem; border-bottom-width: 3px; }
.plan-page .plan-bar .button, .plan-page .plan-bar select { min-height: 32px; height: 32px; padding-top: 0; padding-bottom: 0; }
.plan-page .plan-bar .button { padding: 0 0.75rem; font-size: 0.95rem; }
.plan-page .rev-pick label { font-size: 0.9rem; color: var(--ink-2); }
/* Touch screens: back to 48 px targets. */
@media (pointer: coarse) {
  .plan-page .plan-bar { padding: 0 0.5rem 0.5rem; }
  .plan-page .floor-tabs a { min-height: var(--touch); }
  .plan-page .plan-bar .button, .plan-page .plan-bar select { min-height: var(--touch); height: var(--touch); }
}
@media (max-width: 760px) {
  .plan-page .project-main { height: auto; padding-bottom: calc(76px + env(safe-area-inset-bottom)); }
  .plan-page .plan { height: calc(100dvh - var(--header-h) - 200px); }
}
.plan-label {
  position: absolute; top: 0.5rem; left: 4rem; z-index: 500;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line);
  padding: 0.25rem 0.6rem; font-weight: 500; pointer-events: none;
}

/* Leaflet controls in Karm's style: flat, thin borders, 48 px touch targets. */
/* .plan.leaflet-container: more specific than leaflet.css, which loads after this file. */
.plan.leaflet-container { font: inherit; background: var(--paper); }
.leaflet-bar { border: 1px solid var(--line) !important; border-radius: var(--radius) !important; box-shadow: none !important; }
.leaflet-bar a, .leaflet-touch .leaflet-bar a {
  width: var(--control-h); height: var(--control-h); line-height: var(--control-h);
  background: var(--surface); color: var(--ink); border-bottom-color: var(--line);
  font-size: 1.4rem;
}
.leaflet-bar a:hover { background: var(--paper); color: var(--action); }
.leaflet-bar a:first-child, .leaflet-bar a:last-child { border-radius: 0; }

/* --- Library ----------------------------------------------------------------- */

.subtabs { display: flex; flex-wrap: wrap; border-bottom: 1px solid var(--line); margin-bottom: 0.6rem; }
.subtabs a {
  display: inline-flex; align-items: center; min-height: var(--control-h); padding: 0 0.9rem;
  color: var(--ink-2); text-decoration: none; border-bottom: 3px solid transparent; margin-bottom: -1px;
}
.subtabs a:hover { color: var(--action); }
.subtabs a.active { color: var(--action); border-bottom-color: var(--action); font-weight: 500; }

table.dense td, table.dense th { padding-top: 0.35rem; padding-bottom: 0.35rem; }
table.dense tbody tr { height: var(--row-h); }
th.r, td.r { text-align: right; }
.section-head { margin-top: 1.5rem; margin-bottom: 0.5rem; }
.section-head h2 { margin: 0; }

/* Front page «Oversikt» (projects/home.html) */
.home-block { margin-bottom: 1.25rem; }
.home-block > h2 { margin: 0 0 0.5rem; }
.home-block .section-head { margin-top: 0; }
a.home-resume { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; min-height: var(--row-h); padding: 0 0.75rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: 4px; color: var(--ink); text-decoration: none; }
a.home-resume:hover { border-color: var(--action); }
a.home-resume .go { margin-left: auto; color: var(--action); }
ul.plain { list-style: none; padding: 0; margin: 0; }
ul.plain li { padding: 0.2rem 0; }
.filter-bar select { width: auto; }
form.qty { display: inline-flex; gap: 0.35rem; align-items: center; }
form.qty input { width: 4.5rem; min-height: 30px; height: 30px; padding: 0 0.4rem; text-align: right; }
form.qty button { min-height: 30px; height: 30px; padding: 0 0.6rem; }
/* Invisible but still taking its space, so the table doesn't re-flow when it appears. */
form.qty button.unchanged { visibility: hidden; }
details.history { margin-top: 0.5rem; color: var(--ink-2); }
details.history summary { cursor: pointer; min-height: 36px; display: flex; align-items: center; }

/* Suggestions ("Motorlås foreslår styreenhet: [Legg til …]") */
.suggestions { background: var(--surface); border: 1px solid var(--line); border-left: 4px solid var(--action); padding: 0.5rem 0.75rem; margin: 0.75rem 0; }
.suggestions h2 { margin: 0 0 0.35rem; font-size: 1rem; }
.suggestion { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; padding: 0.25rem 0; }
.suggestion .what { margin-right: 0.35rem; }
input.address-input { width: 7rem; min-height: 30px; height: 30px; padding: 0 0.4rem; }
@media (pointer: coarse) { input.address-input { min-height: 44px; height: 44px; } }
/* A part under its Utstyr item in the Utstyr list (Mads 2026-10-25). */
tr.part-row td { color: var(--ink-2); }
tr.part-row .part-mark { padding-left: 0.4rem; color: var(--line); }
input.qty-input { width: 4.5rem; min-height: 30px; height: 30px; padding: 0 0.4rem; text-align: right; }
@media (pointer: coarse) { input.qty-input { min-height: 44px; height: 44px; } }

/* Unmet requirements on a door type (amber accent, dark text; never a status marker). */
.requirements { background: var(--surface); border: 1px solid var(--line); border-left: 6px solid var(--warn); padding: 0.5rem 0.75rem; margin: 0 0 0.75rem; }
.requirements h2 { margin: 0 0 0.35rem; font-size: 1rem; display: flex; align-items: center; gap: 0.4rem; }
.requirements h2 svg { color: var(--warn); }
.requirement { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.2rem 0; }
.requirements p { margin: 0.3rem 0 0; font-size: 0.9rem; }
.tag.warn { border-color: var(--warn); color: var(--ink); background: color-mix(in srgb, var(--warn) 18%, transparent); }

/* Forms in sections (door types) */
.form-sections { max-width: 900px; }
/* A door type's two halves side by side (Mads 2026-10-16): Dør | Beslagspakke; one column on narrow screens. */
.halves { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 0 1.5rem; align-items: start; }
@media (max-width: 1000px) { .halves { grid-template-columns: minmax(0, 1fr); } }
.halves .half { min-width: 0; }
.halves .half-name { font-weight: 400; font-size: 0.9em; }
.halves h3 { font-size: 1rem; margin: 0; }
.door-type-create .half > div[hidden] { display: none; }
.door-type-create .field-row.narrow { max-width: 720px; }
.pack-summary { margin: 0 0 0.35rem; color: var(--ink-2); }
.scope-choice { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0; }
/* Component form (Mads 2026-10-16): two columns on a wide screen, one on a narrow one. */
.component-form .form-columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1.25rem; max-width: 1200px; align-items: start; }
@media (max-width: 900px) { .component-form .form-columns { grid-template-columns: minmax(0, 1fr); } }
.component-form .form-group { border: 1px solid var(--line); background: var(--surface); margin: 0 0 0.6rem; padding: 0.4rem 0.75rem 0.1rem; min-width: 0; }
.component-form .form-group[hidden], .component-form .field-wrap[hidden] { display: none; }
.component-form .form-group legend { font-weight: 500; padding: 0 0.3rem; }
.component-form .form-actions { display: flex; gap: 0.5rem; margin-top: 0.25rem; }
/* Categories as one row: the main one filled, the extras outlined (colour plus the words Hoved/Også). */
.category-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }
.category-row .cat-label { color: var(--ink-2); font-size: 0.9rem; }
.category-row select.main-chip { width: auto; background: var(--action); color: var(--on-action); border-color: var(--action); font-weight: 500; }
.category-row select.main-chip:disabled { opacity: 0.7; }
.category-row .cat-chips { display: contents; }
.cat-chip { display: inline-flex; align-items: stretch; border: 1px solid var(--line); border-radius: 2px; background: var(--surface); min-height: var(--control-h); }
.cat-chip button { background: none; border: 0; color: var(--ink); min-height: 0; padding: 0 0.5rem; }
.cat-chip button:hover { background: var(--paper); color: var(--action); }
.cat-chip button:disabled { cursor: default; background: none; color: var(--ink); }
.cat-chip .cat-remove { border-left: 1px solid var(--line); color: var(--ink-2); }
.category-row select.cat-add { width: auto; }
.form-sections fieldset { border: 1px solid var(--line); background: var(--surface); margin: 0 0 0.6rem; padding: 0.4rem 0.75rem 0.1rem; }
.form-sections legend { font-weight: 500; padding: 0 0.3rem; }
.field-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 0 0.75rem; }
.field-row .field-description, .field-row .field-code { grid-column: span 2; }

/* --- Doors on the plan -------------------------------------------------------- */

/* Door status markers (CLAUDE.md, section 4): shape + colour, never colour alone. Shapes are drawn
   in static/js/checkoff.js. Unconfirmed position: dashed outline. */
.door-marker svg { display: block; overflow: visible; width: 100%; height: 100%; }
/* A white edge so drawing lines stop at the symbol (Mads 2026-10-20). */
.door-marker .halo { fill: #FFFFFF; }
.m-idle .ring { fill: rgba(255, 255, 255, 0.85); stroke: var(--status-idle); stroke-width: 3; }
.m-progress .disc { fill: var(--status-progress); stroke: var(--status-progress); stroke-width: 2; }
.m-waiting .ring { fill: rgba(255, 255, 255, 0.9); stroke: var(--status-progress); stroke-width: 3; }
.m-waiting .bar { fill: var(--status-progress); }
.m-late .donut { fill: rgba(255, 255, 255, 0.9); stroke: var(--status-done); stroke-width: 4; }
.m-done .disc { fill: var(--status-done); stroke: var(--status-done); stroke-width: 1; }
.m-done .tick { fill: none; stroke: #FFFFFF; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.door-marker.unconfirmed .ring, .door-marker.unconfirmed .disc, .door-marker.unconfirmed .donut { stroke-dasharray: 3 2.5; }
.door-marker.unconfirmed .disc { stroke: #1F2933; }
.leaflet-marker-draggable { cursor: move; }
.door-label.leaflet-tooltip {
  background: rgba(255, 255, 255, 0.92); color: #1F2933; border: 1px solid #C9CCC8; border-radius: 2px;
  box-shadow: none; padding: 0 4px; font-family: var(--mono); font-size: 11px; line-height: 16px;
}
.door-label.leaflet-tooltip::before { display: none; }
.hide-door-labels .door-label { display: none; }
/* «Vis ▾» → «Adresser» (Mads 2026-10-25): the address after the ID, in grey. */
.door-label .label-address { display: none; margin-left: 0.5em; color: #4A5560; }
.show-addresses .door-label .label-address { display: inline; }
/* «Demp tegning» (Mads 2026-10-20): the drawing lighter on its white sheet, so doors and merknader stand out. */
.dim-drawing .leaflet-tile-pane { opacity: 0.65; }
.plan.placing { cursor: crosshair; }
.door-popup { font: 14px/1.4 var(--font); min-width: 10rem; }
.door-popup a { display: inline-block; margin-top: 0.3rem; }

.place-panel {
  position: absolute; top: 0.5rem; right: 0.5rem; z-index: 600; width: 18rem;
  background: var(--surface); border: 1px solid var(--line); border-left: 4px solid var(--action); padding: 0.6rem 0.75rem;
}
.place-row { margin-bottom: 0.45rem; }
.place-row label { display: block; font-weight: 500; font-size: 0.9rem; margin-bottom: 0.15rem; }
.place-row input { font-family: var(--mono); }
.place-row input[type="search"] { font-family: inherit; }
/* How the door type search read each word: understood words as tags, plain text in quotes. */
.search-terms { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem; margin: 0.3rem 0 0.4rem; font-size: 0.85rem; }
.search-terms[hidden] { display: none; }
.search-terms .tag.text-term { background: none; border-style: dashed; }
.place-hint { font-size: 0.85rem; color: var(--ink-2); margin: 0.2rem 0 0.4rem; }
.place-error { font-weight: 500; margin: 0 0 0.4rem; }
#place-toggle.active, #equip-toggle.active, #note-toggle.active, #plan-lock.active { background: var(--action); color: var(--on-action); border-color: var(--action); }
/* «Lås» on the plan (Mads 2026-10-25, plan-lock.js): padlock and word; locked hides the placing tools. */
.plan-lock { display: inline-flex; align-items: center; }
.plan-lock > span { display: inline-flex; align-items: center; gap: 0.35rem; }
.plan-lock .icon { width: 18px; height: 18px; }
.plan-lock[aria-pressed="true"] .lock-off, .plan-lock[aria-pressed="false"] .lock-on { display: none; }
.plan-locked #place-toggle, .plan-locked #equip-toggle, .plan-locked #place-panel, .plan-locked #equip-panel { display: none; }

/* Merknader on the plan (static/js/notes-layer.js): the action colour only, never a status colour.
   Dashed = place carried from the previous revision, not checked yet; faded = utført. */
.note-marker svg { display: block; overflow: visible; width: 100%; height: 100%; }
.note-marker .halo { fill: #FFFFFF; stroke: #FFFFFF; stroke-width: 5; stroke-linejoin: round; }
.note-marker .bubble { fill: var(--surface); stroke: var(--action); stroke-width: 2; stroke-linejoin: round; }
.note-marker .lines { stroke: var(--action); stroke-width: 2; stroke-linecap: round; fill: none; }
.note-marker.unconfirmed .bubble { stroke-dasharray: 3 2; }
.note-marker.done { opacity: 0.45; }
.plan .note-area { stroke: var(--action); fill: var(--action); fill-opacity: 0.08; stroke-dasharray: 6 4; }
.plan .note-area.unconfirmed { stroke-dasharray: 2 4; }
.plan .note-area.done { opacity: 0.45; }
.plan .note-sketch { stroke: var(--action); fill: none; stroke-dasharray: 4 4; }
.plan .note-corner { stroke: var(--action); fill: var(--surface); stroke-width: 2; }
.plan .note-corner.first { fill: var(--action); }
.note-panel .segmented { display: flex; gap: 0.25rem; }
.note-panel .segmented [aria-pressed="true"] { background: var(--action); color: var(--on-action); border-color: var(--action); }
.note-panel .label { display: block; font-weight: 500; font-size: 0.9rem; margin-bottom: 0.15rem; }
.note-popup .note-text { white-space: normal; overflow-wrap: anywhere; margin-bottom: 0.35rem; }
.note-popup .note-tags { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 0.25rem; }
.note-popup .popup-actions { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.5rem; }
.note-popup .note-error { font-weight: 500; margin: 0.35rem 0 0; }
.note-form label { display: block; font-weight: 500; font-size: 0.9rem; margin-bottom: 0.4rem; }
.note-form label.check { display: flex; font-weight: inherit; }
.note-form textarea, .note-form input[type="text"] { display: block; width: 100%; margin-top: 0.15rem; min-height: 0; }
.note-form textarea { min-height: 4.5rem; }

/* Door comments: internal first, clearly marked as not for the customer. */
.comments { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: 0.6rem; margin-bottom: 0.6rem; }
.comment { background: var(--surface); border: 1px solid var(--line); padding: 0.45rem 0.75rem; }
.comment.internal { border-left: 4px solid var(--ink-2); }
.comment-label { font-weight: 500; font-size: 0.9rem; margin-bottom: 0.15rem; }
.comment-text { white-space: normal; }
.cl-access { margin: 0.25rem 0 0.4rem; }
.cl-access .cl-address { width: 8rem; margin-left: 0.35rem; }
.door-marker .comment-badge { fill: #1F2933; stroke: #FFFFFF; stroke-width: 1; stroke-linejoin: round; }
.door-marker .comment-dot { fill: #FFFFFF; }

/* --- Låsplan ------------------------------------------------------------------ */

/* Key columns: name written upwards with the key stempel under it, like the company's sheet. */
table.lockplan th.key-col { vertical-align: bottom; text-align: center; padding: 0.3rem 0.25rem; width: 2rem; }
table.lockplan th.key-col span { display: block; margin: 0 auto; }
table.lockplan th.key-col span:first-child { writing-mode: vertical-rl; transform: rotate(180deg); white-space: nowrap; max-height: 10rem; overflow: hidden; text-overflow: ellipsis; font-weight: 400; }
table.lockplan td.x { text-align: center; border-left: 1px solid var(--line); }
/* "This key opens this cylinder": a solid dot in ink (drawn, so it looks the same on every device). */
.key-dot { display: inline-block; width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--ink); vertical-align: middle; }
table.lockplan th.key-col { border-left: 1px solid var(--line); }
details.doors { display: inline-block; margin-right: 0.5rem; }
details.doors summary { cursor: pointer; color: var(--action); }
details.doors ul { margin-top: 0.25rem; }
.inline-form .field-prefix, .inline-form .field-quantity { flex: 0 0 6rem; }
.inline-form .field-opens_all { flex: 0 0 auto; align-self: center; }

/* Keys in the door popup on the plan */
.door-keys { margin: 0.4rem 0 0.2rem; padding-top: 0.4rem; border-top: 1px solid var(--line); }
.door-keys .keys-head { margin-bottom: 0.25rem; }
.door-keys label.check { display: flex; gap: 0.4rem; align-items: center; padding: 0.15rem 0; }
.door-keys fieldset { border: 1px solid var(--line); margin: 0.3rem 0; padding: 0.1rem 0.5rem 0.2rem; }
.door-keys legend { padding: 0 0.25rem; font-weight: 500; }
.door-keys .per-lock { margin-top: 0.3rem; color: var(--ink-2); }
.door-keys .key-error { color: var(--ink); border-left: 4px solid var(--ink); padding-left: 0.4rem; margin-top: 0.3rem; }
.door-keys .key-list { max-height: 14rem; overflow-y: auto; }
.key-form fieldset { border: 1px solid var(--line); background: var(--surface); margin: 0 0 0.6rem; padding: 0.3rem 0.75rem; max-width: 560px; }
.key-form legend { font-weight: 500; padding: 0 0.3rem; }
.key-form label.check { display: flex; gap: 0.5rem; align-items: center; min-height: var(--row-h); }
.login-photo-preview { display: block; width: 320px; max-width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border: 1px solid var(--line); }
.company-logo { display: block; max-width: 100%; height: 60px; width: auto; background: #FFFFFF; border: 1px solid var(--line); padding: 4px; }

/* «Karm for <company>» in the header. The logo sits on a small white plate, since most company
   logos are made for white paper and the header is dark. */
/* The same space either side of «for»: the logo SVG has ~3 px empty on its right (216 of 226 units). */
.site-header a.brand { padding: 0; gap: calc(0.5rem - 3px); flex: 0 0 auto; }
.site-header a.brand:hover { text-decoration: none; }
.site-header .brand-for { display: inline-flex; align-items: center; gap: 0.5rem; flex: 0 0 auto; }
.site-header .brand-for .for { opacity: 0.7; }
.site-header .company-mark { display: inline-flex; background: #FFFFFF; border-radius: 2px; padding: 3px 6px; }
.site-header .company-mark img { display: block; height: 18px; width: auto; max-width: 140px; object-fit: contain; }
.site-header .company-name { font-weight: 500; white-space: nowrap; }
/* Phones: the project name needs the room. */
@media (max-width: 760px) { .site-header .brand-for { display: none; } }
/* Negative logo: straight on the dark header, no plate. Same 24 px as the plate it replaces. */
.site-header .company-mark-negative { display: block; height: 24px; width: auto; max-width: 160px; object-fit: contain; }
/* Preview of the negative logo on Firmainnstillinger, on the header's own dark colour. */
.logo-on-dark { display: inline-block; background: var(--header-bg); padding: 8px 12px; border-radius: 2px; }
.logo-on-dark img { display: block; height: 40px; width: auto; }

/* --- Header dropdowns: Innstillinger (administrators) and the user menu ------------ */
.site-header .header-menus { display: flex; align-items: stretch; flex: 0 0 auto; }
details.menu { position: relative; }
details.menu > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.4rem;
  min-height: var(--header-h); padding: 0 0.6rem; color: var(--header-ink);
}
details.menu > summary::-webkit-details-marker { display: none; }
details.menu > summary::after { content: ""; border: 4px solid transparent; border-top-color: currentColor; margin-top: 4px; opacity: 0.7; }
details.menu > summary:hover .menu-label { text-decoration: underline; }
details.menu[open] > summary { background: rgba(255, 255, 255, 0.08); }
details.menu .icon { width: 20px; height: 20px; }
.site-header .menu-label.who { opacity: 1; padding: 0; }
.menu-panel {
  position: absolute; right: 0; top: 100%; z-index: 1100; min-width: 13rem;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 2px;
  display: flex; flex-direction: column; padding: 0.25rem 0;
}
.site-header .menu-panel a, .site-header .menu-panel button.link {
  color: var(--ink); min-height: var(--row-h); padding: 0 0.9rem; width: 100%; text-align: left; justify-content: flex-start;
}
.site-header .menu-panel a:hover, .site-header .menu-panel button.link:hover { background: var(--paper); text-decoration: none; }
.menu-panel form { margin: 0; }
.menu-panel .menu-note { color: var(--ink-2); font-size: 0.85rem; padding: 0.35rem 0.9rem 0.45rem; border-bottom: 1px solid var(--line); margin-bottom: 0.25rem; }
/* Phones: icons only in the bar; names are in the open menu. */
@media (max-width: 760px) { .site-header .menu-label { display: none; } }

/* --- Notifications (the bell) ------------------------------------------------- */
.notifications-menu > summary::after { display: none; }
.notifications-menu .bell { position: relative; display: inline-flex; }
/* Unread count: the action colour (the one accent), never a status colour. */
.notifications-menu .badge {
  position: absolute; top: -6px; right: -9px; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 9px;
  background: var(--action); color: #FFFFFF; font-size: 11px; font-weight: 500; line-height: 18px; text-align: center;
}
.notifications-panel { width: 22rem; max-width: calc(100vw - 1rem); }
.site-header .notifications-panel a.notification {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem; min-height: auto;
  padding: 0.45rem 0.9rem; border-bottom: 1px solid var(--line); white-space: normal; line-height: 1.35;
}
.notifications-panel .notification.unread .text { font-weight: 500; }
.notifications-panel .notification:not(.unread) .text { color: var(--ink-2); }
.notifications-panel .when { font-size: 0.8rem; color: var(--ink-2); }
.notifications-panel .menu-empty { padding: 0.6rem 0.9rem; color: var(--ink-2); }
.notifications-panel .menu-foot { display: flex; justify-content: space-between; align-items: center; }
.notifications-panel .menu-foot a, .notifications-panel .menu-foot button.link { width: auto; }
tr.unread td { font-weight: 500; }
@media (max-width: 760px) { .notifications-panel { position: fixed; top: var(--header-h); right: 0.5rem; left: 0.5rem; width: auto; } }

/* Two revisions side by side (older-revision choice). */
.compare { display: flex; gap: 1rem; flex-wrap: wrap; margin: 0 0 1rem; }
.compare figure { margin: 0; flex: 1 1 20rem; max-width: 40rem; }
.compare img { display: block; width: 100%; height: auto; background: #FFFFFF; border: 1px solid var(--line); }
.compare figcaption { font-size: 0.9rem; color: var(--ink-2); margin-top: 0.3rem; }

/* --- Check-off list (plan popup and door page) --------------------------------- */
.door-checklist { margin-top: 0.4rem; padding-top: 0.4rem; border-top: 1px solid var(--line); }
.cl-head { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.3rem; }
.cl-head svg { flex: 0 0 auto; }
.cl-items { list-style: none; margin: 0; padding: 0; }
.cl-item { display: flex; flex-wrap: wrap; align-items: center; gap: 0 0.5rem; border-bottom: 1px solid var(--line); min-height: var(--row-h); }
/* Only the box ticks (Mads 2026-10-19); the name opens the part's documents. */
.cl-item label.cl-tick { flex: 0 0 auto; justify-content: center; min-width: var(--control-h); min-height: var(--control-h); margin-left: -0.5rem; }
.cl-what { flex: 1 1 0; min-width: 0; padding: 0.2rem 0; }
.cl-what button.cl-name { text-align: left; font: inherit; }
.cl-item.st-fitted .cl-what span.cl-name, .cl-item.st-fitted .cl-what .mono { color: var(--ink-2); }
.cl-item.st-missing .cl-name { font-weight: 500; }
.cl-docs { flex: 1 0 100%; list-style: none; margin: 0 0 0.4rem calc(var(--control-h) - 0.5rem); padding: 0.2rem 0 0.2rem 0.6rem; border-left: 2px solid var(--action); }
.cl-docs li { padding: 0.15rem 0; }
@media (pointer: coarse) { .cl-docs a { display: inline-flex; align-items: center; min-height: var(--control-h); } }
.cl-missing[aria-pressed="true"] { font-weight: 500; text-decoration: underline; }
.cl-actions { margin-top: 0.5rem; display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; }
.cl-undo { margin-top: 0.4rem; padding: 0.3rem 0.5rem; border-left: 4px solid var(--action); background: var(--paper); }
.cl-error, .cl-orphans { margin-top: 0.4rem; padding: 0.3rem 0.5rem; border-left: 4px solid var(--ink); font-weight: 500; }
.door-checklist .cl-items, .equip-checklist .cl-items { max-height: 16rem; overflow-y: auto; }
.cl-marking { font-weight: 500; white-space: nowrap; }
/* «K»: from a kit. A small mark beside the name; on the door page it links to the kit (a bigger target on touch). */
.kit-mark { display: inline-block; min-width: 1.1rem; padding: 0 0.15rem; border: 1px solid var(--line); border-radius: 2px; font-family: var(--mono); font-size: 0.75rem; line-height: 1.3; text-align: center; color: var(--ink-2); text-decoration: none; vertical-align: 0.05em; }
a.kit-mark { color: var(--action); }
@media (pointer: coarse) { a.kit-mark { min-width: var(--control-h); line-height: calc(var(--control-h) - 2px); font-size: 0.85rem; } }
.page-checklist { max-width: 760px; }

/* --- CE marking ---------------------------------------------------------------- */
.ce-steps { padding-left: 1.4rem; max-width: 760px; }
.ce-steps li { padding: 0.35rem 0; border-bottom: 1px solid var(--line); }
.ce-steps li.done a { font-weight: 500; }
.ce-steps li.locked a { color: var(--ink-2); }
.ce-problems { border-left: 4px solid var(--ink); padding: 0.3rem 0.5rem 0.3rem 1.6rem; max-width: 760px; }
.ce-form .field ul, .ce-form .field div[id] { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.2rem 1rem; }
.ce-form .field ul label, .ce-form .field div[id] label { font-weight: 400; display: inline-flex; gap: 0.35rem; align-items: center; }
/* Bottom of the door popup (Mads 2026-10-25): «Alt montert» as quiet links, then a line, then the door's
   links in one row with «Ta av tegningen» pushed right. */
.door-popup .cl-actions, .equip-popup .cl-actions { gap: 0.25rem 0.5rem; }
.door-popup .popup-actions { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; align-items: center;
  margin-top: 0.6rem; padding-top: 0.4rem; border-top: 1px solid var(--line); }
.door-popup .popup-actions a { text-decoration: none; }
.door-popup .popup-actions a:hover { text-decoration: underline; }
.door-popup .popup-actions .unplace { margin-left: auto; }
@media (pointer: coarse) {
  .door-popup .popup-actions a, .door-popup .popup-actions button.link, .door-popup .cl-actions button.link,
  .equip-popup .cl-actions button.link {
    min-height: var(--touch); display: inline-flex; align-items: center; }
}
.ce-photos { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.3rem 0; }
.ce-photos figure { margin: 0; display: flex; flex-direction: column; align-items: flex-start; }
.ce-photos img { display: block; width: 120px; height: 90px; object-fit: cover; border: 1px solid var(--line); }
/* Dør-ID (and Utstyr ID) in the popup: «Endre» beside it, a text field in its place while editing. */
.door-popup .door-id-edit, .equip-popup .equip-id-edit { margin-left: 0.35rem; font-family: var(--font); }
.equip-popup .equip-id-input { width: 8rem; margin: 0; display: inline-block; }
@media (pointer: coarse) { .equip-popup .equip-id-edit { min-height: var(--touch); } }
.door-popup .door-id-field { display: flex; align-items: center; margin: 0; font-weight: inherit; }
.door-popup .door-id-input { flex: 1; min-width: 0; width: 8rem; margin: 0; }
@media (pointer: coarse) { .door-popup .door-id-edit { min-height: var(--touch); } }
.door-popup .door-type label { display: flex; align-items: center; gap: 0.35rem; margin: 0.2rem 0 0; font-weight: inherit; }
.door-popup .door-type select { flex: 1; min-width: 0; width: auto; margin: 0; }
.door-popup .door-hand { margin-top: 0.2rem; display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
.door-popup .hand-btn { min-height: 28px; height: 28px; padding: 0 0.55rem; background: var(--surface); color: var(--action); border: 1px solid var(--line); font-family: var(--mono); }
.door-popup .hand-btn[aria-pressed="true"] { background: var(--action); color: #FFFFFF; border-color: var(--action); }
@media (pointer: coarse) { .door-popup .hand-btn { min-height: 44px; height: 44px; padding: 0 0.9rem; } }
/* Door bottom sheet on phones (doors-layer.js): the popup's content in a full-width panel above the
   tab bar, one scroll area. Flat, a thin top border, no shadow. `bottom` is set from the tab bar. */
.door-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1100;
  max-height: 60vh; max-height: 60dvh; overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); color: var(--ink); border-top: 1px solid var(--line);
  padding: 0 0.75rem 0.75rem;
}
.door-sheet[hidden] { display: none; }
.door-sheet .sheet-bar {
  position: sticky; top: 0; z-index: 1; display: flex; justify-content: center; align-items: center;
  height: var(--touch); margin: 0 -0.75rem; background: var(--surface);
}
.door-sheet .sheet-grip { width: 36px; height: 4px; border-radius: 2px; background: var(--line); }
.door-sheet .sheet-close {
  position: absolute; right: 0; top: 0; width: var(--touch); height: var(--touch); min-height: 0;
  margin: 0; padding: 0; background: none; border: 0; color: var(--ink); font-size: 1.6rem; line-height: 1;
}
.door-sheet .door-popup { font-size: var(--base-font); min-width: 0; margin-top: -0.5rem; }
/* Utstyr in the sheet (Mads 2026-10-25): the same room as a door. */
.door-sheet .equip-popup { font-size: var(--base-font); margin-top: -0.5rem; }
.door-sheet .equip-popup .equip-head { padding-right: var(--touch); font-size: 1.1em; }
.door-sheet .door-popup > .mono:first-child { padding-right: var(--touch); font-size: 1.1em; }
.door-sheet .cl-items, .door-sheet .key-list, .door-sheet .equip-checklist .cl-items { max-height: none; overflow: visible; }
.door-sheet .popup-actions a { min-height: var(--touch); display: inline-flex; align-items: center; margin-top: 0; }
.door-marker.selected svg { outline: 3px solid var(--action); outline-offset: 2px; border-radius: 50%; }

/* --- Utstyr on the plan (Mads 2026-10-22) --------------------------------------------- */
/* A small square (doors are round) with the fag's letters; an arrow out of its edge where it points. Fixed colours
   like the door markers: they sit on the white drawing in dark mode too. Status fill comes with check-off. */
.equip-marker svg { display: block; overflow: visible; width: 100%; height: 100%; }
.equip-marker .equip-box { fill: #FFFFFF; stroke: var(--status-idle); stroke-width: 2; }
.equip-marker .equip-letters { fill: #1F2933; font-family: var(--mono); font-weight: 500; text-anchor: middle; }
.equip-marker .equip-arrow { fill: none; stroke: #1F2933; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* Status like the doors (Mads 2026-10-25): the whole square, dark letters on amber, white on green. */
.equip-marker.st-progress .equip-box { fill: var(--status-progress); stroke: var(--status-progress); }
.equip-marker.st-waiting .equip-box { stroke: var(--status-progress); stroke-width: 3.5; }
.equip-marker.st-late .equip-box { stroke: var(--status-done); stroke-width: 3.5; }
.equip-marker.st-done .equip-box { fill: var(--status-done); stroke: var(--status-done); }
.equip-marker.st-done .equip-letters { fill: #FFFFFF; }
.equip-marker.unconfirmed .equip-box { stroke-dasharray: 3 2.5; }
.equip-marker .equip-select { fill: none; stroke: var(--action); stroke-width: 3; }
.hide-door-labels .equip-label { display: none; }
.equip-popup { font: 14px/1.4 var(--font); }
.equip-popup .equip-head { margin-bottom: 0.2rem; }
.equip-popup .equip-parts { list-style: none; margin: 0.2rem 0 0; padding: 0; }
.equip-popup .equip-checklist { margin-top: 0.3rem; }
.equip-popup .comment { margin-top: 0.4rem; }
/* Like the door popup's bottom (Mads 2026-10-25): links under a line, «Slett» pushed right. */
.equip-actions { display: flex; gap: 0.25rem 1rem; flex-wrap: wrap; align-items: center;
  margin-top: 0.6rem; padding-top: 0.4rem; border-top: 1px solid var(--line); }
.equip-actions a { text-decoration: none; }
.equip-actions a:hover { text-decoration: underline; }
.equip-actions .remove { margin-left: auto; }
@media (pointer: coarse) {
  .equip-actions a, .equip-actions button.link { min-height: var(--touch); display: inline-flex; align-items: center; }
}
.fag-letters { display: inline-block; min-width: 1.6em; padding: 0 0.2em; border: 1px solid var(--ink); border-radius: 2px;
               font-family: var(--mono); font-size: 0.75rem; line-height: 1.35; text-align: center; }
.fag-head { display: flex; align-items: center; gap: 0.5rem; margin-top: 1.25rem; }
.aim-hint { position: absolute; left: 50%; top: 0.5rem; transform: translateX(-50%); z-index: 700; margin: 0;
            background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-left: 4px solid var(--action);
            padding: 0.3rem 0.6rem; font-size: 0.9rem; }
/* «Vis ▾»: the header's dropdown, as a button in the plan bar. */
.plan-bar details.layer-menu > summary { min-height: 32px; height: 32px; color: var(--ink); }
.plan-bar details.layer-menu > summary::after { opacity: 0.6; }
.layer-menu .menu-panel { left: 0; right: auto; min-width: 15rem; padding: 0.35rem 0; }
.layer-menu .menu-panel label.check { min-height: var(--row-h); padding: 0 0.9rem; display: flex; align-items: center; gap: 0.45rem; }
.layer-menu .menu-panel label.check.sub { padding-left: 2.2rem; }
.layer-menu .menu-panel label.check .muted { margin-left: auto; font-variant-numeric: tabular-nums; }
@media (pointer: coarse) { .plan-bar details.layer-menu > summary { min-height: var(--touch); height: var(--touch); } }
.dense tr.removed td { color: var(--ink-2); }
/* Beslagsliste, "quantity first" (chosen by Mads 2026-10-13): the quantity leads each row like a pick
   list; categories are slim small-caps labels with a line under them, all in one table body so every
   product row keeps its divider. No background bands. */
table.bom td.qty { font-weight: 500; font-size: 1.05em; width: 1%; padding-right: 1rem; }
table.bom tr.group { height: auto; }
table.bom tr.group th {
  font-size: 0.75rem; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2);
  padding-top: 0.9rem; padding-bottom: 0.2rem;
}
table.bom tbody tr.group:first-child th { padding-top: 0.4rem; }

/* --- Phones: compact chrome (decided by Mads 2026-10-13) --------------------------------------
   .wide-only / .phone-only switch between the desktop and phone versions of a control. */
@media (min-width: 761px) { .phone-only { display: none !important; } }
/* Desktop: the plan tools sit in the plan bar's row as before. */
.plan-tools { display: contents; }
.plan-more { display: none; }
.menu-panel .menu-sep { border-bottom: 1px solid var(--line); }
.phone-menu > summary::after { display: none; }
@media (max-width: 760px) {
  .wide-only { display: none !important; }
  /* Fixed header: Safari 26 takes the colour of the bars around the page (status bar) from an opaque
     fixed element at the top, no longer from <meta name="theme-color"> (kept for Android). */
  :root { --tabbar-h: 57px; }
  .site-header { position: fixed; top: 0; left: 0; right: 0; z-index: 1200; }
  body { padding-top: calc(var(--header-h) + 1px); }
  .site-header .inner { flex-wrap: nowrap; gap: 0.5rem; }
  .site-header nav { flex-wrap: nowrap; overflow-x: auto; min-width: 0; gap: 0; }
  .site-header nav a { padding: 0 0.5rem; white-space: nowrap; }
  details.menu > summary { padding: 0 0.55rem; }

  /* Plan view: floor tabs and ⋯ on one row; the plan fills the rest down to the tab bar. */
  .plan-page .project-main {
    height: calc(100vh - var(--header-h) - 1px); height: calc(100dvh - var(--header-h) - 1px);
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  }
  .plan-page .plan { height: auto; min-height: 200px; }
  .plan-page .plan-bar { flex-wrap: nowrap; padding: 0; gap: 0; position: relative; }
  .plan-page .floor-tabs { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; overflow-x: auto; margin-right: 0; }
  .plan-page .floor-tabs a { white-space: nowrap; }
  .plan-page .plan-more {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    width: var(--touch); height: var(--touch); min-height: var(--touch); margin: 0; padding: 0;
    background: none; color: var(--ink); border: 0; border-left: 1px solid var(--line); border-radius: 0;
  }
  .plan-page .plan-more[aria-expanded="true"] { background: var(--paper); }
  .plan-page .plan-tools { display: none; }
  .plan-page .plan-tools.open {
    display: flex; flex-direction: column; align-items: stretch; gap: 0.5rem;
    position: absolute; top: 100%; right: 0; z-index: 1050; width: min(20rem, calc(100vw - 1rem));
    background: var(--surface); border: 1px solid var(--line); padding: 0.75rem;
  }
  .plan-page .plan-tools form, .plan-page .plan-tools button, .plan-page .plan-tools .button { width: 100%; margin: 0; }
  .plan-page .plan-tools .button { justify-content: center; }
  .plan-page .plan-tools .rev-pick { flex-direction: column; align-items: stretch; gap: 0.25rem; }
  .plan-page .plan-tools .rev-pick select { width: 100%; }
}
@media (max-width: 760px) and (pointer: coarse) { :root { --tabbar-h: 65px; } }
/* Icon buttons on touch screens: no sticky hover colour from the generic button:hover. */
.plan-page .plan-more:hover, .plan-page .plan-more:active, .door-sheet .sheet-close:hover, .door-sheet .sheet-close:active { background: none; color: var(--ink); }
.plan-page .plan-more[aria-expanded="true"]:hover { background: var(--paper); }

/* --- Kalkyle ---------------------------------------------------------------------------------- */
/* Boxes as wide as their content, flowing side by side (chosen by Mads 2026-10-13: tighter
   layout, rows stay 36 px). Explanations sit behind a «?» (_hint.html), not under the tables. */
.calc-grid { display: flex; flex-wrap: wrap; gap: 0.25rem 1.75rem; align-items: flex-start; }
.calc-grid section { flex: 0 1 auto; max-width: 100%; }
.calc-grid h2 { margin: 0.5rem 0 0.35rem; }
/* Key figures on both kalkyle tabs (Mads 2026-10-28). The colour on Tilleggsfortjeneste / tap per time is a decided
   exception to «status colours are for doors» (CLAUDE.md): the same three, tinted. */
.calc-keys { display: flex; flex-wrap: wrap; width: fit-content; max-width: 100%; background: var(--surface); border: 1px solid var(--line); margin: 0.5rem 0 0.75rem; }
.calc-keys .key { display: grid; grid-template-columns: auto auto; align-items: baseline; column-gap: 0.75rem;
  padding: 0.4rem 1rem; border-right: 1px solid var(--line); min-width: 10rem; }
.calc-keys .key:last-child { border-right: 0; }
.calc-keys .label { grid-column: 1 / -1; color: var(--ink-2); font-size: 0.85em; }
.calc-keys .value { font-size: 1.5rem; font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.calc-keys .note { grid-column: 1 / -1; color: var(--ink-2); font-size: 0.85em; }
.calc-keys .level-ok { background: color-mix(in srgb, var(--status-done) 16%, var(--surface)); border-left: 6px solid var(--status-done); }
.calc-keys .level-near { background: color-mix(in srgb, var(--status-progress) 24%, var(--surface)); border-left: 6px solid var(--status-progress); }
.calc-keys .level-loss { background: color-mix(in srgb, var(--status-avvik) 18%, var(--surface)); border-left: 6px solid var(--status-avvik); }

/* «Justering» on Oversikt: a panel like the summary boxes, a field per row. */
.calc-grid .calc-extras table.calc-sum th[scope="row"] { min-width: 0; }
.calc-extras table.calc-sum td { padding-top: 2px; padding-bottom: 2px; }
.calc-extras input { width: 6.5rem; text-align: right; }
.calc-extras table.dense tr.gap { height: 0.75rem; }
.calc-extras tr.gap td { padding: 0; background: var(--paper); border-left: 0; border-right: 0; }
.calc-extras .errorlist { list-style: none; padding: 0; margin: 0.15rem 0 0; font-weight: 500; }
.calc-extras .errorlist li::before { content: "! "; }
.calc-extras-save { display: flex; justify-content: flex-end; margin-top: 0.5rem; }
.calc-grid .table-wrap { width: fit-content; max-width: 100%; }
.calc-grid table { width: auto; }
.calc-grid table.calc-sum th[scope="row"] { min-width: 11rem; }
details.hint { display: inline-block; position: relative; vertical-align: middle; font-size: 0.8rem; font-weight: 400; }
details.hint > summary {
  list-style: none; cursor: pointer; width: 1.15rem; height: 1.15rem; line-height: 1.05rem; text-align: center;
  border: 1px solid var(--line); border-radius: 50%; color: var(--ink-2);
}
details.hint > summary::-webkit-details-marker { display: none; }
details.hint[open] > summary { color: var(--action); border-color: var(--action); }
details.hint .hint-text {
  position: absolute; left: 0; top: 1.5rem; z-index: 20; width: max-content; max-width: min(24rem, 80vw);
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); padding: 0.4rem 0.6rem; line-height: 1.4;
}
@media (pointer: coarse) { details.hint > summary { width: 1.6rem; height: 1.6rem; line-height: 1.5rem; } }
/* Kalkyle settings: three slim groups side by side, help as a tooltip (title), no frames. */
.calc-settings { display: flex; flex-wrap: wrap; gap: 0 2rem; align-items: flex-start; }
.calc-settings fieldset { border: 0; padding: 0; margin: 0; flex: 0 1 auto; }
.calc-settings legend { font-size: 0.75rem; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); padding: 0; margin-bottom: 0.2rem; }
.calc-settings .field-row { display: flex; flex-wrap: wrap; gap: 0 0.75rem; }
.calc-settings .field { margin-bottom: 0.45rem; }
.calc-settings .field label { font-weight: 400; font-size: 0.85rem; color: var(--ink-2); margin-bottom: 0.1rem; }
.calc-settings .field .help { display: none; }
.calc-settings input { width: 7rem; }
.calc-settings select { width: auto; max-width: 22rem; }
.calc-settings-save { flex-basis: 100%; }
table.calc-sum th[scope="row"] { font-weight: 400; text-align: left; white-space: normal; }
table.calc-sum td { white-space: nowrap; }
table.calc-sum tr.subtotal th, table.calc-sum tr.subtotal td { font-weight: 500; }
table.calc-sum tr.total th, table.calc-sum tr.total td { font-weight: 500; font-size: 1.1em; border-top: 2px solid var(--ink); }
table.calc-sum th.indent { padding-left: 1.5rem; color: var(--ink-2); }
table.calc-lines td.own { font-weight: 500; }
table.calc-lines tr.extra td { color: var(--ink-2); }
table.calc-lines tr.section-head th, table.calc-lines tr.section-head td { font-weight: 500; border-top: 2px solid var(--ink-2); padding-top: 0.6rem; }
table.calc-lines tr.delsum td { font-weight: 500; border-top: 1px solid var(--ink-2); }
.actions-row { margin: 0.5rem 0; }

/* Comments in the door popup / bottom sheet: as on the door page, compact, at most 6 lines each. */
.door-popup .door-comments:not(:empty) { display: grid; gap: 0.3rem; margin-top: 0.4rem; }
.door-popup .comment { padding: 0.25rem 0.5rem; }
.door-popup .comment-label { font-size: 0.8rem; margin-bottom: 0; }
.door-popup .comment-text { display: -webkit-box; -webkit-line-clamp: 6; line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }

/* Leaflet's popup in Karm's colours (it was Leaflet's own: white, #333 text, 12 px radius, big
   shadow), so it follows dark mode. leaflet.css loads after this file: hence the .plan prefix. */
.plan .leaflet-popup-content-wrapper, .plan .leaflet-popup-tip {
  background: var(--surface); color: var(--ink); border: 1px solid var(--line);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.plan .leaflet-popup-content-wrapper { border-radius: var(--radius); }
.plan .leaflet-popup-content { margin: 0.6rem 0.75rem; }
.plan .leaflet-popup a:not(.leaflet-popup-close-button) { color: var(--action); }
.plan.leaflet-container a.leaflet-popup-close-button { color: var(--ink-2); }
.plan.leaflet-container a.leaflet-popup-close-button:hover { color: var(--ink); }

/* Linjer: more compact rows on PC (Mads 2026-10-13: ~28 px, slightly smaller text); touch keeps 48 px. */
table.calc-lines { font-size: 0.93rem; }
table.calc-lines tbody tr { height: 28px; }
table.calc-lines td, table.calc-lines th { padding-top: 0.15rem; padding-bottom: 0.15rem; }
table.calc-lines .tag { padding-top: 0; padding-bottom: 0; line-height: 1.3; }
@media (pointer: coarse) {
  table.calc-lines { font-size: inherit; }
  table.calc-lines tbody tr { height: var(--row-h); }
  table.calc-lines td, table.calc-lines th { padding-top: 0.35rem; padding-bottom: 0.35rem; }
}

/* Linjer: main columns first, then a divider and the details (Mads 2026-10-13). Cells never wrap,
   so every row stays one line; the table scrolls sideways in its box instead. */
table.calc-lines { width: max-content; min-width: 100%; }
table.calc-lines td, table.calc-lines th { white-space: nowrap; }
table.calc-lines td.note { white-space: normal; min-width: 20rem; }
table.calc-lines .split { border-left: 3px solid var(--line); }
/* Linjer: numbers you can click and type into (Timer/stk, påslag). They look like the other numbers
   until hovered or focused; a value of the line's own is bold. */
form.line-value { display: inline; margin: 0; }
/* «Dine verdier» (decided by Mads 2026-10-13: grouped and boxed): the editable numbers look like
   input fields all the time, in their own group of columns before the calculated ones. */
form.line-value input {
  width: 4.2rem; height: 1.45rem; min-height: 0; padding: 0 0.3rem; margin: 0; text-align: right;
  font: inherit; color: var(--ink); background: var(--paper); border: 1px solid var(--line); border-radius: 2px;
}
form.line-value input.wide { width: 6rem; }
/* The line's supplier (Mads 2026-10-22): the same small box; boxed in bold when the kalkyle chose its own. */
form.line-value select {
  width: auto; height: 1.45rem; min-height: 0; padding: 0 0.3rem; margin: 0;
  font: inherit; color: var(--ink); background: var(--paper); border: 1px solid var(--line); border-radius: 2px;
}
td.own form.line-value select { font-weight: 500; border: 2px solid var(--ink-2); }
@media (pointer: coarse) { form.line-value select { height: 2.25rem; } }  /* innpris: kroner need more room than hours and % */
form.line-value input.own { font-weight: 500; border: 2px solid var(--ink-2); padding: 0 calc(0.3rem - 1px); }  /* own value: 2 px border (Mads 2026-10-13) */
form.line-value input:hover { border-color: var(--ink-2); }
form.line-value input:focus { border-color: var(--action); background: var(--surface); outline: none; }
@media (pointer: coarse) { form.line-value input { height: 2.25rem; } }
table.calc-lines tr.group-head th { font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; padding-bottom: 0; border-bottom: 0; height: auto; }
table.calc-lines tr.group-head th.own-group { color: var(--action); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Linjer: tick lines in the Nr cell, then «Flytt til» (decided by Mads 2026-10-13). */
.move-bar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin: 0 0 0.4rem; }
.move-bar .move-count { color: var(--ink-2); }
.move-bar.has-picks .move-count { color: var(--ink); font-weight: 500; }
.move-bar select { width: auto; }
table.calc-lines button.remove { font-size: 1.1rem; line-height: 1; color: var(--ink-2); padding: 0 0.3rem; }
table.calc-lines button.remove:hover { color: var(--ink); }

/* Linjer: every column as narrow as its content; the spare width of a wide screen goes to
   Beskrivelse, never to an empty column (Mads 2026-10-14). Section links sit in the section heading. */
table.calc-lines th, table.calc-lines td { width: 1%; }
table.calc-lines .desc { width: auto; }
table.calc-lines .section-actions { float: right; margin-left: 1.5rem; font-weight: 400; }
table.calc-lines .section-actions a, table.calc-lines .section-actions .inline { margin-left: 0.75rem; }

/* Kalkyle settings: «Denne jobben» up front, the rest under «Flere innstillinger» (Mads 2026-10-14). */
.calc-settings details.more-settings { flex-basis: 100%; margin: 0.1rem 0 0.5rem; }
.calc-settings details.more-settings > summary { cursor: pointer; color: var(--action); margin-bottom: 0.4rem; }
.calc-settings details.more-settings[open] { display: flex; flex-wrap: wrap; gap: 0 2rem; align-items: flex-start; }
.calc-settings details.more-settings[open] > summary { flex-basis: 100%; }

/* Linjer: the tick boxes in their own narrow first column, so 1, 1.1, 1.2 line up (Mads 2026-10-14). */
/* A narrow tick column (kalkyle Linjer, «Hent dørtype»). */
table .pick-col { width: 1%; padding-right: 0; }
table .pick-col input { margin: 0; }

/* Desktop popup beside the door, not above it (doors-layer.js placeBeside): no pointer. */
.plan .door-popup-side .leaflet-popup-tip-container { display: none; }
.plan .door-popup-side { margin-bottom: 0; }

/* Administrasjon → Brukere: the temporary password, shown once (Mads 2026-10-21). */
.temp-password code { font-size: 1.5rem; }
/* Administrasjon → Logg (2026-10-21): «Fra»/«Til» beside their date fields, details under an entry, pager. */
.filter-bar .inline-field { display: inline-flex; align-items: center; gap: 0.35rem; }
.audit-details summary { color: var(--action); cursor: pointer; font-size: 0.9em; }
.audit-details .facts { margin: 0.25rem 0 0; }
.pager { display: flex; gap: 1rem; align-items: center; }
