/* Albach User Management — styling adapted from the spareparts theme. */
:root {
    --primary: #198754;
    --primary-dark: #0f5132;
    --danger: #dc3545;
    --white: #ffffff;
    --gray-100: #f8f9fa;
    --gray-200: #e9ecef;
    --gray-300: #dee2e6;
    --gray-700: #495057;
    --gray-800: #343a40;
    --font-family: 'Nunito', Arial, sans-serif;
    /* Mirrors sparepartsWT so the shared header controls size by the same
       formula. UM has no A-/A+ control, so it stays at 1. */
    --font-scale: 1;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: var(--font-family);
    font-size: 14px;
    background-color: #f5f5f5;
    color: var(--gray-800);
    line-height: 1.5;
}

/* ---- White nav row ---- */
.nav-container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--white);
    box-shadow: 0 2px 10px rgba(0,0,0,0.15);
}
.nav-logo-link { display: inline-flex; align-items: center; }
.nav-logo-img  { height: 40px; width: auto; display: block; }
.nav-title {
    font-size: 18px;
    font-weight: 700;
    color: var(--primary-dark);
    margin-left: 6px;
}
.nav-right-host { display: flex; align-items: center; margin-left: auto; gap: 8px; }

.btn-logout {
    background: var(--primary);
    border: none;
    color: var(--white);
    padding: 0 14px !important;
    border-radius: 6px !important;
    font-size: 13px !important;
    font-weight: 600;
    height: 32px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
}
.btn-logout:hover { background: var(--primary-dark); }

/* ---- Green action bar ---- */
.action-bar {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px;
    min-height: 52px;
    flex-wrap: wrap;
    box-shadow: 0 2px 8px rgba(0,0,0,0.10);
}
.action-bar-label { color: var(--white); font-weight: 600; }
.company-switch {
    min-width: 240px;
    padding: 5px 10px;
    border: none;
    border-radius: 6px;
    font-size: 13px;
    height: 32px;
    background: rgba(255,255,255,0.95);
    color: var(--gray-800);
}

/* ---- Content ---- */
.um-content { padding: 20px; max-width: 1000px; margin: 0 auto; }
.um-h2 {
    font-size: 18px;
    font-weight: 700;
    color: var(--primary-dark);
    margin: 22px 0 10px;
    border-left: 4px solid var(--primary);
    padding-left: 10px;
}
.um-card {
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: 8px;
    padding: 14px 18px;
}
.tree-node { line-height: 1.9; color: var(--gray-700); }

/* Company hierarchy tree: expand/collapse toggle in the name cell. */
.tree-toggle { cursor: pointer; color: var(--gray-500); font-size: 10px; width: 14px;
    display: inline-block; text-align: center; user-select: none; flex: 0 0 auto; }
.tree-toggle:hover { color: var(--primary); }
.tree-toggle-spacer { display: inline-block; width: 14px; flex: 0 0 auto; }

/* Scrollable checkbox list (e.g. extra-parent picker in the company editor). */
.um-check-scroll { max-height: 240px; overflow-y: auto; overflow-x: hidden;
    padding: 6px 10px; margin-bottom: 8px; }
.um-check-scroll .form-row { margin-bottom: 4px; }
/* Service-client grantable scopes: wrapping checkbox grid. */
.scope-check-list { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 2px 0 10px 0; }
.scope-check { flex: 0 0 auto; min-width: 160px; }
/* Service-client list item: name/id header row + read-only scope chips. */
.service-client-item { padding: 10px 0; border-bottom: 1px solid var(--gray-200); }
.service-client-item:last-of-type { border-bottom: none; }
.service-client-info { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.service-client-name { font-weight: 700; color: var(--gray-800); font-size: 14px; }
.service-client-id { font-size: 12px; color: var(--gray-500); font-family: monospace; }
.scope-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.scope-chip { font-size: 11px; padding: 2px 9px; border-radius: 999px;
    background: var(--gray-100); color: var(--gray-700); border: 1px solid var(--gray-200); }
.scope-chip.muted { font-style: italic; background: transparent; border: none; color: var(--gray-500); }
/* Small hint line under a form field. */
.form-hint { font-size: 12px; color: var(--gray-500); margin: 2px 0 8px 0; }

/* Live password-rules box (admin set-password field in the user editor).
   In-flow (not absolute) so it always renders and never hides behind the
   browser's native password-autofill dropdown. */
.pw-field-wrap { position: relative; }
.pw-popup { margin: 4px 0 8px 0; background: #fff; border: 1px solid var(--gray-300);
    border-radius: 8px; box-shadow: 0 4px 14px rgba(0,0,0,.10); padding: 10px 14px;
    max-width: 340px; font-size: 12px; line-height: 1.7; }

/* Searchable dropdowns (WSuggestionPopup): company parent, machine company
   assignment. Wt renders each item inside an anchor, so the browser's default
   link colour and underline have to be cleared explicitly. */
.Wt-suggest {
    background: var(--white); border: 1px solid var(--gray-300); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,.14); max-height: 260px; overflow-y: auto;
    z-index: 1100; padding: 4px 0; font-size: 13px;
}
.Wt-suggest ul { list-style: none; margin: 0; padding: 0; }
.Wt-suggest li {
    padding: 0; cursor: pointer; white-space: nowrap; color: var(--gray-800);
}
.Wt-suggest li > * { display: block; padding: 8px 14px; }
.Wt-suggest a, .Wt-suggest a:link, .Wt-suggest a:visited {
    color: var(--gray-800); text-decoration: none;
}
/* The typed part is highlighted with <b>; tint it instead of shouting. */
.Wt-suggest b { color: var(--primary-dark); font-weight: 700; }
.Wt-suggest li:hover, .Wt-suggest .active, .Wt-suggest .sel {
    background: var(--gray-100);
}
.Wt-suggest li:hover a, .Wt-suggest .active a, .Wt-suggest .sel a { color: var(--primary-dark); }

.um-table {
    width: 100%;
    background: var(--white);
    border-collapse: collapse;
    table-layout: auto;
    border-radius: 8px;
    /* No overflow:hidden here: it would box in the sticky header below, which
       can only stick within its nearest scrolling/clipping ancestor. The header
       cells carry the top corners instead. */
    box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
.um-table th, .um-table td {
    padding: 8px 12px;
    text-align: left;
    border-bottom: 1px solid var(--gray-200);
    font-size: 13px;
}
.um-table thead th {
    background: var(--primary);
    color: var(--white);
    font-weight: 600;
    /* Sticks to the top of .um-content-area, the scrolling ancestor, so the
       column names stay readable down a long list. */
    position: sticky;
    top: 0;
    z-index: 3;
}
.um-table thead th:first-child { border-top-left-radius: 8px; }
.um-table thead th:last-child  { border-top-right-radius: 8px; }

/* Wt writes an inline `display: block` on the table element, and an inline
   style beats a stylesheet rule without !important. As a block box the table
   loses table layout: the anonymous table inside it sizes to its content, so
   the columns stop short and leave the right side of every row empty --
   measured at 737px of dead space in a 1600px viewport. Scoped to the desktop
   breakpoint because the mobile card layout below deliberately makes the table
   a block. */
@media (min-width: 769px) {
    .um-table { display: table !important; }
}
.um-table tbody tr:nth-child(even) { background: #fafbfa; }
.um-table tbody tr:hover { background: #eef6f1; }
.um-empty { color: var(--gray-500); font-style: italic; padding: 6px 0; }
.um-type-tree-cell {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--gray-800);
}
.um-type-tree-branch {
    color: var(--gray-400);
    letter-spacing: 1px;
}
.um-preset-app {
    border-top: 1px solid var(--gray-200);
    padding-top: 10px;
    margin-top: 12px;
}

/* ---- Login page ---- */
.login-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 16px;
    background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 50%, var(--primary-dark) 100%);
}
.login-center-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    max-width: 400px;
}
.login-box {
    background: var(--white);
    width: 100%;
    padding: 40px 20px;
    border-radius: 8px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-align: center;
}
.login-card { width: 100%; }
.login-logo {
    max-width: 200px;
    height: auto;
    margin-bottom: 30px;
    filter: brightness(0) invert(1);
}
.login-title {
    color: var(--primary);
    margin-bottom: 20px;
    font-size: 24px;
    font-weight: 700;
}
.login-title h2 {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
}
.login-input {
    width: 100%;
    padding: 12px 16px;
    margin: 8px 0;
    border: 2px solid var(--gray-300);
    border-radius: 5px;
    font-size: 14px;
    transition: border-color .3s ease;
}
.login-input:focus { outline: none; border-color: var(--primary); }
.login-remember {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0 0;
    color: var(--gray-700);
    font-size: 13px;
    font-weight: 600;
    text-align: left;
}
.login-remember input { margin: 0; }
.login-button {
    width: 100%;
    padding: 12px;
    margin-top: 20px;
    background: var(--primary);
    color: var(--white);
    border: none;
    border-radius: 5px;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
    transition: background .3s ease;
}
.login-button:hover { background: var(--primary-dark); }
.login-btn {
    background: var(--primary);
    color: var(--white);
    border: none;
    padding: 11px;
    border-radius: 6px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    margin-top: 6px;
}
.login-btn:hover { background: var(--primary-dark); }
.login-error {
    color: var(--danger, #dc3545);
    font-size: 14px;
    text-align: center;
    min-height: 16px;
    margin-top: 8px;
}
.login-forgot { text-align: center; font-size: 12px; color: var(--primary); cursor: pointer; margin-top: 12px; }
.login-forgot:hover { text-decoration: underline; }
.login-privacy-notice { text-align: center; font-size: 12px; color: var(--gray-600, #6c757d); margin-top: 14px; }
.login-privacy-link { color: var(--primary); text-decoration: none; }
.login-privacy-link:hover { text-decoration: underline; }
/* Cookie consent banner (fixed bottom bar, dismissed via the consent cookie). */
.cookie-banner {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 9999;
    background: #212529;
    color: #f8f9fa;
    padding: 12px 20px;
    font-size: 0.92em;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.2);
}
.cookie-banner-text { flex: 1 1 auto; }
.cookie-banner-link {
    color: #6cc28a;
    text-decoration: underline;
}
.cookie-banner-link:hover { color: #8edaa6; }
.cookie-banner-btn {
    background: #198754;
    color: #fff;
    border: none;
    padding: 8px 18px;
    border-radius: 4px;
    cursor: pointer;
    font-weight: 600;
}
.cookie-banner-btn:hover { background: #157347; }

/* Live password-rules checklist (reset / setup page) */
.pw-rules { margin: 2px 0 10px; font-size: 12px; line-height: 1.5; }
.pw-rules-title { display: block; color: var(--gray-700); font-weight: 600; margin-bottom: 2px; }
.pw-rule-ok   { color: var(--primary); }
.pw-rule-bad  { color: var(--danger, #dc3545); }
.pw-rule-note { color: var(--gray-700); }
.login-footer {
    position: fixed;
    bottom: 20px;
    color: rgba(255,255,255,0.7);
    font-size: 12px;
}
.login-footer-link {
    color: rgba(255,255,255,0.7);
    text-decoration: none;
    margin-left: 12px;
}
.login-footer-link:hover { text-decoration: underline; }

/* ============ App shell: header + sidebar + content ============ */
html, body { height: 100%; margin: 0; overflow-x: hidden; max-width: 100%; }
/* Only the app shell fills the viewport. A blanket ".Wt-domRoot > div" also hit
   everything else Wt parents at the root — popups, dialogs, the Ajax badge —
   stretching each to full height. The login/reset pages carry their own
   min-height. */
.Wt-domRoot { height: 100%; }
.Wt-domRoot > .um-shell { height: 100%; }
.um-shell { display: flex; flex-direction: column; height: 100%; max-width: 100vw; overflow-x: hidden; }

/* Outer wrapper: stacks the two rows vertically. */
.um-header {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
}

/* Row 1: white bar — logo + app title. Matches sparepartsWT nav-container. */
.um-header-top {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 15px;
    background: var(--white);
    box-shadow: 0 2px 10px rgba(0,0,0,0.2);
    min-height: 60px;
}
.um-header-logo { height: 40px; width: auto; }
/* Pinned to the logo's baseline edge rather than centred, so the app name sits
   in the same place here and in sparepartsWT instead of drifting with the
   line box. */
.um-header-title { font-weight: 700; font-size: 16px; color: var(--primary-dark); align-self: flex-end; line-height: 1.4; }
/* No vertical padding: it would make the row taller than the 60px
   sparepartsWT nav-container it has to line up with. */
/* !important is required: Wt writes an inline "display: block" on this
   container, which would otherwise win over the stylesheet and drop the logo
   back to inline flow — adding a baseline gap that made the row 66px instead
   of 60px and left the title unable to align to the logo. */
.um-brand { display: inline-flex !important; align-items: center; gap: 8px; cursor: pointer; border-radius: 8px; padding: 0 6px 0 0; }
.um-brand:hover .um-header-title { color: var(--primary); }

/* Row 2: green bar, kept empty; a fixed-height strip so the header lines up
   with sparepartsWT's assembly-bar (catalog viewer). */
.um-header-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 16px;
    /* 48px clears the 32px controls sparepartsWT puts in its own green bar
       without the dead space a 60px strip left. Keep both apps in step. */
    min-height: 48px;
    box-sizing: border-box;
    flex-wrap: wrap;
    row-gap: 6px;
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    color: var(--white);
    box-shadow: 0 2px 8px rgba(0,0,0,0.10);
}
.um-spacer { flex: 1 1 auto; }
.um-burger { display: inline-flex; cursor: pointer; padding: 6px; border-radius: 6px; }
.um-burger:hover { background: rgba(0,0,0,0.07); }
.um-burger svg { stroke: var(--primary-dark); }
.um-lang { display: flex; gap: 3px; margin-right: 4px; }
.um-lang-opt { cursor: pointer; padding: 4px 8px; border-radius: 5px; font-size: 12px; font-weight: 700; color: var(--white); opacity: 0.7; }
.um-lang-opt:hover { background: rgba(255,255,255,0.22); opacity: 1; }

/* User-name dropdown trigger in the white header bar: a green pill (app's
   signature 135deg gradient) matching sparepartsWT's .user-dropdown-btn. */
.um-user-menu-trigger {
    /* !important for the same reason as .um-brand: Wt writes an inline
       "display: block" here, which killed the 6px gap before the caret and
       left the label sitting on the baseline instead of centred. */
    display: inline-flex !important; align-items: center; gap: 6px; cursor: pointer;
    height: 32px; padding: 0 12px; margin-left: 8px; border-radius: 7px;
    box-sizing: border-box;
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    transition: filter .3s ease;
}
.um-user-menu-trigger:hover { filter: brightness(1.08); }
.um-user-menu-name {
    color: var(--white); font-size: calc(13px * var(--font-scale)); font-weight: 600; line-height: 1.2;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 220px;
}
.um-user-menu-chevron {
    flex: 0 0 auto;
    color: var(--white); font-size: calc(10px * var(--font-scale)); line-height: 1;
}

/* Wt popup menu (user dropdown + language submenu): no Wt theme CSS ships,
   so style the default markup ourselves. */
.Wt-popupmenu {
    background: var(--white) !important; border: 1px solid var(--gray-300) !important;
    border-radius: 8px !important; box-shadow: 0 6px 20px rgba(0,0,0,0.15) !important;
    min-width: 180px !important; padding: 6px 0 !important; list-style: none !important;
    z-index: 1200 !important;
}
.Wt-popupmenu li { list-style: none !important; }
.Wt-popupmenu .Wt-item, .Wt-popupmenu a {
    display: flex !important; align-items: center !important; gap: 10px !important;
    padding: 8px 16px !important; font-size: 13.5px !important; font-weight: 600 !important;
    color: var(--gray-800) !important; text-decoration: none !important; cursor: pointer !important;
    background: var(--white) !important; transition: background .12s ease !important; white-space: nowrap !important;
}
.Wt-popupmenu .Wt-item:hover, .Wt-popupmenu a:hover {
    background: var(--primary-light) !important; color: var(--primary-dark) !important;
}
/* Highlighted row: Wt's default theme sets `.active { background: blue }`.
   Override to on-brand green (this is the actual class, not .Wt-selected). */
.Wt-popupmenu .active, .Wt-popupmenu .active a {
    background: var(--primary-light) !important; color: var(--primary-dark) !important;
    outline: none !important;
}
.Wt-popupmenu .Wt-chkbox { accent-color: var(--primary) !important; }
.Wt-popupmenu .Wt-separator {
    border: none !important; border-top: 1px solid var(--gray-200) !important;
    margin: 6px 0 !important; padding: 0 !important;
}
.Wt-popupmenu .Wt-submenu-marker, .Wt-popupmenu .submenu { margin-left: auto !important; }

.um-body { display: flex; flex: 1 1 auto; min-height: 0; }
.um-sidebar {
    flex: 0 0 224px; width: 224px; background: var(--white);
    border-right: 1px solid var(--gray-200); padding: 12px 0; overflow-y: auto;
    transition: flex-basis .2s ease, width .2s ease, transform .24s cubic-bezier(.22,.61,.36,1);
}
/* Desktop: nav-open collapses sidebar to icon-only strip. */
.um-shell.nav-open .um-sidebar { flex-basis: 62px; width: 62px; }
.um-shell.nav-open .um-nav-label { display: none; }
.um-nav-item {
    display: flex; align-items: center; gap: 13px; padding: 12px 20px;
    cursor: pointer; color: var(--gray-700); font-weight: 600; font-size: 14px; white-space: nowrap;
    border-left: 3px solid transparent;
}
.um-nav-item:hover { background: var(--gray-100); }
.um-nav-item.active { background: var(--primary-light); color: var(--primary-dark); border-left-color: var(--primary); }
.um-nav-icon { display: inline-flex; }
.um-nav-icon svg { width: 20px; height: 20px; }
.um-content-area { flex: 1 1 auto; min-height: 0; min-width: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; background: #f5f5f5; }
/* The page inset lives on the panels, not on the scroll box. With padding
   here the sticky table header anchored below it and rows stayed visible in
   the band above the header. */
.um-content-area > * { padding: 24px 28px; }
.um-body { min-height: 0; }
.um-sidebar { min-height: 0; }

/* ---- Dashboard ---- */
.um-dashboard { max-width: 1120px; }
.dashboard-head { margin: 10px 0 18px; }
.dashboard-subtitle { color: var(--gray-700); font-size: 14px; margin-top: 6px; max-width: 760px; }
.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 16px;
}
.dashboard-card {
    display: grid;
    grid-template-columns: 42px 1fr auto;
    align-items: center;
    gap: 14px;
    min-height: 112px;
    padding: 18px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: 8px;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.dashboard-card:hover {
    border-color: var(--primary);
    box-shadow: 0 8px 22px rgba(0,0,0,0.08);
    transform: translateY(-1px);
}
.dashboard-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 8px;
    color: var(--primary-dark);
    background: var(--primary-light);
}
.dashboard-card-icon svg { width: 22px; height: 22px; }
.dashboard-card-title { display: block; font-weight: 800; color: var(--gray-800); font-size: 15px; margin-bottom: 5px; }
.dashboard-card-detail { color: var(--gray-700); font-size: 13px; line-height: 1.35; }
.dashboard-card-metric {
    align-self: start;
    min-width: 34px;
    padding: 5px 9px;
    border-radius: 999px;
    background: var(--gray-100);
    color: var(--primary-dark);
    font-weight: 800;
    font-size: 13px;
    text-align: center;
}

/* ---- CRUD panels ---- */
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 10px 0; flex-wrap: wrap; }
.um-search {
    flex: 1 1 200px; max-width: 320px; padding: 8px 12px;
    border: 1px solid var(--gray-300); border-radius: 7px; font-size: 13px;
}
.um-search:focus { outline: none; border-color: var(--primary); }
.panel-add-btn {
    background: var(--primary); color: var(--white); border: none;
    padding: 7px 14px; border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer;
}
.panel-add-btn:hover { background: var(--primary-dark); }
.action-btn {
    background: var(--gray-200); color: var(--gray-800); border: none;
    padding: 4px 10px; border-radius: 5px; font-size: 12px; cursor: pointer; margin-right: 4px;
}
.action-btn:hover { background: var(--gray-300); }
/* Sortable column headers: clickable, active column shows an arrow (▲/▼).
   Normal = brand green; hover darkens. */
.action-btn.sortable { background: var(--primary); color: #fff; font-weight: 600; }
.action-btn.sortable:hover { background: var(--primary-dark); color: #fff; }
/* Row Edit button: brand green. */
.action-btn.edit { background: var(--primary); color: #fff; }
.action-btn.edit:hover { background: var(--primary-dark); color: #fff; }
.action-btn.danger { background: #f8d7da; color: #842029; }
.action-btn.danger:hover { background: #f1aeb5; }
/* Destructive action in a dialog title bar: kept far from Save/Cancel so a
   mis-click on the primary actions cannot delete the record. */
.dlg-title-delete {
    float: right; margin: 1px 30px 0 0;
    background: #f8d7da; color: #842029;   /* readable on the dark title bar */
    border: none; border-radius: 5px;
    padding: 4px 10px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.dlg-title-delete:hover { background: #f1aeb5; }
/* PDF viewer dialog: dark title bar, content fills the dialog. */
.pdf-file-viewer .titlebar, .pdf-viewer-bar {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    color: #fff;
}
/* The PDF viewer sizes itself from its content box (see pdfviewer.cpp): Wt's own
   show-time positioning script overrides any size set on the dialog element. */
.pdf-file-viewer .body { padding: 0 !important; }

/* Imported-data rows: label | value | action, aligned like a table. */
/* Action column holds "Request"/"Beantragen", so it is wider than a plain Edit
   button needs; the value column gives the width back since most values are a
   single tick. */
.opt-row {
    display: grid; grid-template-columns: 1fr 88px 100px;
    gap: 10px; align-items: center;
    padding: 5px 0; border-bottom: 1px solid var(--gray-100);
}
.opt-row:last-child { border-bottom: none; }
.opt-label { color: var(--gray-700); font-size: 13px; line-height: 1.35; }
.opt-value { text-align: center; font-weight: 600; color: var(--gray-800); font-size: 13px;
             overflow-wrap: anywhere; }
.opt-action { text-align: right; }
/* Options the machine does not have: dimmed so present ones stand out. */
.opt-row-missing .opt-label, .opt-row-missing .opt-value { color: var(--gray-500); }
.opt-row-missing { background: repeating-linear-gradient(
    -45deg, transparent, transparent 6px, rgba(0,0,0,0.015) 6px, rgba(0,0,0,0.015) 12px); }
/* Search box + "show not fitted" toggle above the imported-data list. Sticky so
   they stay reachable while scrolling a long option list. */
.opt-controls {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 8px 0; margin-bottom: 4px;
}
/* The option list scrolls inside its own box, so the search field and the
   "not fitted" toggle above it stay put without sticky positioning. */
.opt-scroll {
    max-height: 55vh; overflow-y: auto; overflow-x: hidden;
    border: 1px solid var(--gray-200); border-radius: 8px;
    background: var(--white); padding: 4px 12px;
}
.opt-missing-toggle { font-size: 12px; color: var(--gray-700); }
.opt-action .action-btn { margin-right: 0; white-space: nowrap; padding: 4px 8px; }

/* Group title inside an imported-data card. */
.opt-group {
    display: block; margin: 10px 0 4px; padding: 4px 0 3px;
    position: sticky; top: 0; z-index: 2; background: var(--white);
    font-weight: 600; font-size: 12px; color: var(--primary);
    border-bottom: 1px solid var(--gray-200);
}
/* Machine rows are clickable as a whole, so the number needs no link styling. */
.machine-num { font-weight: 700; color: var(--gray-800); }
.um-table-clickable tbody tr { cursor: pointer; }
.um-table-clickable tbody tr:hover .machine-num { color: var(--primary-dark); }

/* Machine filter row: a slim chip per filter, each opening a checkbox popup. */
.machine-filters {
    display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 10px;
}
.filter-chip {
    height: 28px; padding: 0 10px;
    font-size: 12.5px; font-weight: 600; line-height: 26px;
    color: var(--gray-700, #495057); background: var(--white);
    border: 1px solid var(--gray-300, #ced4da); border-radius: 14px;
    cursor: pointer; white-space: nowrap;
    transition: border-color .12s ease, background .12s ease, color .12s ease;
}
.filter-chip:hover { border-color: var(--primary); color: var(--primary-dark); }
.filter-chip-active {
    background: var(--primary); border-color: var(--primary); color: var(--white);
}
.filter-chip-active:hover { color: var(--white); }
.filter-chip-clear { border-style: dashed; }
.filter-count { margin-left: auto; font-size: 12px; color: var(--gray-500, #adb5bd); }

/* Anchored dropdown panel: search on top, scrollable checkbox list below. */
/* Fixed width with a viewport cap: a long company name must wrap inside the
   popup, never stretch it across the screen. */
.filter-pop {
    width: 250px; max-width: calc(100vw - 24px); box-sizing: border-box;
    padding: 8px; z-index: 1200;
    background: var(--white); border: 1px solid var(--gray-200); border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0,0,0,.14);
}
.filter-pop-search {
    width: 100%; box-sizing: border-box; height: 28px; padding: 0 8px;
    font-size: 13px; color: var(--gray-800);
    border: 1px solid var(--gray-300, #ced4da); border-radius: 6px; background: var(--white);
}
.filter-pop-search:focus { outline: none; border-color: var(--primary); }
.filter-pop-list { max-height: 230px; overflow-y: auto; margin: 6px 0 0; }
.filter-pop-item {
    display: flex; align-items: flex-start; gap: 8px;
    padding: 4px 2px; font-size: 13px; color: var(--gray-800); cursor: pointer;
    /* min-width:0 lets the flex item shrink; without it a long unbroken label
       pushes the popup wider than its declared width. */
    min-width: 0; overflow-wrap: anywhere;
}
.filter-pop-item input { flex: 0 0 auto; margin-top: 2px; }
.filter-pop-item:hover { background: var(--gray-100, #f1f3f5); border-radius: 4px; }
.filter-pop-empty { display: block; padding: 8px 2px; font-size: 12.5px; color: var(--gray-500, #adb5bd); }
.filter-pop-foot { margin-top: 6px; border-top: 1px solid var(--gray-100, #f1f3f5); padding-top: 6px; }
.filter-pop-clear {
    height: 24px; padding: 0 8px; font-size: 12px; cursor: pointer;
    color: var(--gray-600, #6c757d); background: transparent;
    border: 1px solid var(--gray-300, #ced4da); border-radius: 12px;
}
.filter-pop-clear:hover { border-color: var(--primary); color: var(--primary-dark); }
@media (max-width: 700px) {
    .filter-count { margin-left: 0; }
    .filter-pop { width: 220px; }
}

/* Paging row below the machine table; hidden when everything fits on one page. */
.machine-pager {
    display: flex; gap: 8px; align-items: center; justify-content: flex-end;
    margin-top: 10px;
}
.machine-pager .filter-chip:disabled {
    opacity: .45; cursor: default; border-color: var(--gray-200); color: var(--gray-500, #adb5bd);
}
.pager-info { font-size: 12px; color: var(--gray-500, #adb5bd); }

/* Machine change history rows inside the info drawer. */
.opt-manual-badge {
    margin-left: 8px; padding: 1px 7px; border-radius: 999px;
    font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    color: var(--primary-dark); background: var(--gray-100, #f1f3f5);
    border: 1px solid var(--gray-200);
}

.hist-row {
    display: grid; grid-template-columns: 140px 1fr 1fr 150px;
    gap: 8px; align-items: baseline;
    padding: 5px 2px; border-bottom: 1px solid var(--gray-100, #f1f3f5); font-size: 13px;
}
.hist-when   { color: var(--gray-600, #6c757d); font-variant-numeric: tabular-nums; }
.hist-field  { font-weight: 600; color: var(--gray-800); }
.hist-old    { color: var(--gray-600, #6c757d); text-decoration: line-through; }
.hist-new    { color: var(--primary-dark); font-weight: 600; }
.hist-source { color: var(--gray-500, #adb5bd); font-size: 12px; text-align: right; }
@media (max-width: 700px) {
    .hist-row { grid-template-columns: 1fr; gap: 2px; }
    .hist-source { text-align: left; }
}

/* SVG icons on action buttons (data-URI = identical on every platform) */
.panel-add-btn::before {
    content: ''; display: inline-block; width: 14px; height: 14px; margin-right: 7px; vertical-align: -2px;
    background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
}
.action-btn.danger::before {
    content: ''; display: inline-block; width: 13px; height: 13px; margin-right: 5px; vertical-align: -2px;
    background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23842029' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 6 5 6 21 6'/%3E%3Cpath d='M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6'/%3E%3C/svg%3E");
}
/* Primary/save dialog buttons get a checkmark (same data-URI SVG on every platform). */
.login-btn::before {
    content: ''; display: inline-block; width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px;
    background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
}
.action-btn, .panel-add-btn, .login-btn { transition: background .15s ease; }

/* secondary (flat) button — Back / Next / Cancel / Close */
.btn-light {
    background: var(--white); color: var(--gray-700);
    border: 1px solid var(--gray-300); padding: 9px 18px; border-radius: 7px;
    font-size: 13px; font-weight: 600; cursor: pointer; margin-left: 8px;
}
.btn-light:hover { background: var(--gray-100); }
.btn-light:disabled { opacity: .45; cursor: default; }

/* dialog footer: consistent spacing + primary button look */
.Wt-dialog .login-btn { padding: 9px 20px; border-radius: 7px; margin-left: 8px; border: 1px solid var(--primary); }

/* dialog forms */
.form-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.form-label { min-width: 130px; font-size: 13px; color: var(--gray-700); }
.form-input { flex: 1; padding: 7px 10px; border: 1.5px solid var(--gray-300); border-radius: 6px; font-size: 13px; }
.form-input:focus { outline: none; border-color: var(--primary); }

/* repeatable customer-number rows (form.customer_nr) */
.cust-nr-list { display: flex; flex-direction: column; gap: 6px; margin: 0 0 8px 140px; }
.cust-nr-row { display: flex; align-items: center; gap: 8px; }
.cust-nr-row .form-input { flex: 1; }
.cust-nr-rm { flex: 0 0 auto; width: 30px; padding: 6px 0; text-align: center; margin-left: 0; }
.form-section { display: block; font-weight: 700; color: var(--primary-dark); margin: 12px 0 6px; }

/* Collapsible drawer section. Styled like .form-section but focusable, since the
   header is the control that loads and reveals the section. */
.lazy-head {
    display: block; width: 100%; text-align: left;
    margin: 12px 0 6px; padding: 6px 0;
    font: inherit; font-weight: 700; color: var(--primary-dark);
    background: none; border: 0; border-bottom: 1px solid var(--gray-200);
    cursor: pointer;
}
.lazy-head::before {
    content: "\25B8"; display: inline-block; width: 14px;
    color: var(--gray-500); transition: transform .12s ease;
}
.lazy-head.open::before { transform: rotate(90deg); }
.lazy-head:hover { color: var(--primary); }
.lazy-head:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.lazy-body { display: block; }
/* Nested option sections sit inside the scrolling list, so they need no margin. */
.opt-scroll .lazy-head { margin-top: 6px; }
.hist-more { margin: 10px 0 4px; }

/* Simple lazy-section list row (company drawer: sub-companies / machines / users). */
.drawer-list-row {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    padding: 7px 2px; border-bottom: 1px solid var(--gray-100, #f1f3f5); font-size: 13px;
}
.drawer-list-row .primary { font-weight: 600; color: var(--gray-800); }
.drawer-list-row .meta { color: var(--gray-500, #adb5bd); font-size: 12px; }
.drawer-list-row.clickable { cursor: pointer; }
.drawer-list-row.clickable:hover { background: var(--gray-50, #f8f9fa); }
.form-hint { display: block; color: var(--gray-500); font-size: 12px; margin: -2px 0 10px 140px; }

/* Modern form controls: custom checkboxes + switch-style "Enable" toggles. */
.um-card input[type="checkbox"], .um-preset-app input[type="checkbox"] {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px; margin: 0; flex: 0 0 auto; vertical-align: middle;
    border: 2px solid #888; border-radius: 5px; background: #fff;
    position: relative; cursor: pointer; transition: background .15s, border-color .15s;
}
.um-card input[type="checkbox"]:checked, .um-preset-app input[type="checkbox"]:checked {
    background: var(--primary); border-color: var(--primary);
}
.um-card input[type="checkbox"]:checked::after, .um-preset-app input[type="checkbox"]:checked::after {
    content: ""; position: absolute; left: 5px; top: 1px; width: 4px; height: 9px;
    border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.um-card input[type="checkbox"]:disabled, .um-preset-app input[type="checkbox"]:disabled { opacity: .5; cursor: not-allowed; }

/* "Enable <app>" rendered as a sliding switch (overrides the checkbox look). */
.app-toggle { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; color: var(--gray-800); }
.app-toggle input[type="checkbox"], input.app-toggle[type="checkbox"] {
    width: 42px !important; height: 24px !important; border-radius: 12px !important; border: none !important;
    background: var(--gray-300); cursor: pointer; transition: background .2s;
}
.app-toggle input[type="checkbox"]::after, input.app-toggle[type="checkbox"]::after {
    content: "" !important; position: absolute !important; top: 3px !important; left: 3px !important;
    width: 18px !important; height: 18px !important; border: none !important; border-radius: 50% !important;
    background: #fff !important; box-shadow: 0 1px 3px rgba(0,0,0,.3); transform: none !important; transition: left .2s;
}
.app-toggle input[type="checkbox"]:checked, input.app-toggle[type="checkbox"]:checked { background: var(--primary) !important; }
.app-toggle input[type="checkbox"]:checked::after, input.app-toggle[type="checkbox"]:checked::after { left: 21px !important; }

/* validation */
.form-label.req { color: var(--gray-800); }
.form-input.Wt-invalid, input.Wt-invalid { border-color: var(--danger) !important; background: #fff6f6; }
.field-error { display: block; color: var(--danger); font-size: 11px; margin: -4px 0 8px 140px; }
.wizard-step { display: block; font-weight: 700; font-size: 15px; color: var(--primary); margin-bottom: 12px; padding-bottom: 8px; border-bottom: 2px solid var(--gray-200); }
.login-ok { color: var(--primary); font-size: 13px; min-height: 16px; }
.um-card { margin-bottom: 16px; }

/* ---- Profile picture ----
   Wt writes an inline display:block on containers, so every flex container here
   needs !important or the layout silently falls back to block. */
.avatar-row {
    display: flex !important; align-items: center; gap: 18px; flex-wrap: wrap;
}
.avatar-frame {
    flex: 0 0 auto; width: 96px; height: 96px; border-radius: 50%;
    overflow: hidden; background: var(--gray-100, #f1f3f5);
    border: 1px solid var(--gray-200);
    display: flex !important; align-items: center; justify-content: center;
}
.avatar-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-placeholder {
    font-size: 30px; font-weight: 700; color: var(--gray-500);
    letter-spacing: 1px; user-select: none;
}
.avatar-actions {
    display: flex !important; flex-direction: column; align-items: flex-start;
    gap: 6px; min-width: 0;
}
.avatar-actions .form-hint { margin: 0; }
.avatar-upload { font-size: 13px; max-width: 100%; }
.avatar-upload input[type="file"] { max-width: 100%; font-size: 13px; }

/* Permission-group editor: list pane + entry-editor pane side by side (stacks on mobile). */
.um-group-split { display: flex; gap: 16px; align-items: flex-start; }
.um-group-split > * { min-width: 0; }

/* Secondary filter row (e.g. "show deleted", view selector) — flex + wraps on mobile. */
.panel-filter-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }

/* ---- Custom form controls — identical on every platform (no native rendering) ---- */
/* Checkbox: draw our own box + checkmark instead of the OS-native one. */
input[type="checkbox"] {
    appearance: none; -webkit-appearance: none; -moz-appearance: none;
    width: 18px; height: 18px; margin: 0; flex: 0 0 auto;
    border: 1.5px solid var(--gray-400, #ced4da); border-radius: 4px;
    background: var(--white); cursor: pointer; position: relative; vertical-align: middle;
    transition: background .12s ease, border-color .12s ease;
}
input[type="checkbox"]:hover { border-color: var(--primary); }
input[type="checkbox"]:checked { background: var(--primary); border-color: var(--primary); }
input[type="checkbox"]:checked::after {
    content: ""; position: absolute; left: 5px; top: 1px;
    width: 4px; height: 9px; border: solid var(--white); border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
input[type="checkbox"]:focus-visible { outline: 2px solid var(--primary-light, #a3cfbb); outline-offset: 1px; }

/* Dropdown: same SVG chevron everywhere instead of the native arrow. */
select {
    appearance: none; -webkit-appearance: none; -moz-appearance: none;
    padding: 7px 30px 7px 10px; border: 1.5px solid var(--gray-300); border-radius: 6px;
    font-size: 13px; color: var(--gray-800, #343a40); background-color: var(--white); cursor: pointer;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23495057' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat; background-position: right 9px center; background-size: 12px;
}
select:focus { outline: none; border-color: var(--primary); }
select.form-input { flex: 1; }

/* ---- Tabs (WTabWidget) ---- */
.Wt-tabs { border-bottom: 2px solid var(--primary); margin-bottom: 18px; }
.Wt-tabs ul { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0; }
.Wt-tabs li { display: inline-block; }
.Wt-tabs a, .Wt-tabs span {
    display: inline-block; padding: 9px 20px; text-decoration: none;
    color: var(--gray-700); font-weight: 600; font-size: 14px;
    background: var(--gray-200); border-radius: 8px 8px 0 0; border: none;
}
.Wt-tabs a:hover { background: var(--gray-300); }
.Wt-tabs .itemselected a, .Wt-tabs .itemselected span,
.Wt-tabs li.selected a, .Wt-tabs li.selected span {
    background: var(--primary); color: var(--white);
}

/* ---- System page tab bar: WMenu styled as horizontal tabs (setStyleClass "um-tabbar") ---- */
/* Tab bar (WMenu). Wt ships its own menu styling, so the selected state is set
   with !important: without it Wt's rules win and the active tab renders as an
   outlined box instead of a filled one. The hairline underneath is a separator,
   not a decoration — a thick full-width rule read as a stray line. */
.um-tabbar {
    display: flex; flex-wrap: wrap; gap: 4px; list-style: none;
    margin: 0 0 16px; padding: 0;
    border-bottom: 1px solid var(--gray-200);
}
.um-tabbar li { display: inline-block; list-style: none; margin: 0; border: none; }
.um-tabbar a, .um-tabbar span {
    display: inline-block; padding: 8px 16px; text-decoration: none; cursor: pointer;
    color: var(--gray-600); font-weight: 600; font-size: 13px; white-space: nowrap;
    background: var(--gray-200); border-radius: 8px 8px 0 0;
    border: none !important; outline: none !important; box-shadow: none !important;
}
.um-tabbar a:hover { background: var(--gray-300); color: var(--gray-800); }
.um-tabbar li.active > a, .um-tabbar a.active,
.um-tabbar .Wt-selected a, .um-tabbar .itemselected a, .um-tabbar li.selected a,
.um-tabbar li.Wt-selected > a, .um-tabbar li.Wt-selected > span {
    background: var(--primary) !important; color: var(--white) !important;
}
@media (max-width: 768px) {
    /* Tabs wrap to multiple rows with larger tap targets. */
    .um-tabbar { flex-wrap: wrap; }
    .um-tabbar a, .um-tabbar span { padding: 10px 14px; font-size: 14px; min-height: 40px; box-sizing: border-box; }
    /* Wide tables scroll inside their card instead of widening the page. */
    .um-card table { display: block; overflow-x: auto; max-width: 100%; }
}

/* Read-only application/permission summary: one card per app, its values as
   pills. */
.perm-apps { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 6px; }
.perm-app {
    background: var(--gray-100, #f1f3f5); border: 1px solid var(--gray-200);
    border-radius: 8px; padding: 8px 10px;
}
.perm-app-name {
    display: block; margin-bottom: 6px;
    font-weight: 700; font-size: 11.5px; letter-spacing: .03em; text-transform: uppercase;
    color: var(--primary);
}
.perm-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.perm-chip {
    display: inline-block; padding: 3px 10px; border-radius: 12px;
    background: var(--white); border: 1px solid var(--gray-300, #ced4da);
    font-size: 12px; line-height: 18px; color: var(--gray-800);
    overflow-wrap: anywhere;
}

/* ---- Dialogs (WDialog) ---- */
.Wt-dialogcover { background: rgba(0,0,0,0.45); cursor: pointer; }
.Wt-dialog {
    border: none !important;
    border-radius: 12px !important;
    box-shadow: 0 14px 50px rgba(0,0,0,0.35) !important;
    overflow: hidden;
}
/* WMessageBox renders as a fit-content flex column of rows (title / body /
   footer). A short title otherwise leaves the title row shrink-wrapped with a
   gap on the right. Stretch every row to the full dialog width; the title bar
   (flex:1 1 auto) then fills its row. */
.Wt-dialog .dialog-layout { align-items: stretch !important; }
/* The layout is inline `width: fit-content`, so a short dialog stays narrower
   than the dialog's min-width (280px) and leaves a gap on the right. Force the
   layout to fill the dialog; rows (align-items: stretch) then span full width. */
.Wt-dialog:not(.um-drawer) .dialog-layout { width: 100% !important; }
.Wt-dialog .dialog-layout > .Wt-fill-width { width: 100% !important; box-sizing: border-box; }
.Wt-dialog .titlebar {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    color: var(--white); font-weight: 700; font-size: 16px; padding: 12px 18px;
}
.Wt-dialog .body { padding: 18px; }
.Wt-dialog .footer { padding: 12px 18px; border-top: 1px solid var(--gray-200); text-align: right; }

/* Standard message-box buttons (Yes/No/Ok) — Wt gives them no project class,
   so style them here. Known styled buttons are excluded so they keep their look. */
.Wt-dialog .footer button:not(.login-btn):not(.btn-light) {
    padding: 8px 18px; margin-left: 8px;
    border: 1px solid var(--gray-300); border-radius: 7px;
    background: var(--white); color: var(--gray-700);
    font-size: 14px; font-weight: 600; cursor: pointer;
}
.Wt-dialog .footer button:not(.login-btn):not(.btn-light):hover { background: var(--gray-100); }
/* primary / default (first) button → green */
.Wt-dialog .footer button:not(.login-btn):not(.btn-light):first-of-type {
    background: var(--primary); color: var(--white); border-color: var(--primary);
}
.Wt-dialog .footer button:not(.login-btn):not(.btn-light):first-of-type:hover { background: var(--primary-dark); }

/* Small confirm / message-box dialogs (everything that is NOT the side drawer) */
.Wt-dialog:not(.um-drawer) {
    width: auto !important;
    min-width: 280px;
    max-width: 440px !important;
    height: auto !important;
    max-height: 88vh !important;
}
.Wt-dialog:not(.um-drawer) .body { padding: 18px 20px !important; }
.Wt-dialog:not(.um-drawer) .footer { text-align: right; }

/* Message-box (WMessageBox) icon + text: lay out as two columns so long text
   wraps in its own column instead of flowing under the floated icon. */
.Wt-dialog .Wt-msgbox-body {
    display: flex;
    align-items: center;
    gap: 14px;
}
.Wt-dialog .Wt-msgbox-icon {
    float: none !important;
    flex: 0 0 auto;
    margin: 0 !important;
}
.Wt-dialog .Wt-msgbox-text {
    flex: 1 1 auto;
    margin: 0 !important;
    line-height: 1.45;
}

/* Agreement dialog: wider than the default, with a scrollable + wrapping body. */
.Wt-dialog.um-agreement { width: 92vw !important; max-width: 680px !important; }
/* The 440px cap above is meant for form dialogs; the PDF viewer sizes itself
   from its content box and needs the cap lifted. */
.Wt-dialog.pdf-file-viewer { width: auto !important; max-width: 64vw !important; }
.Wt-dialog.um-agreement .body { padding: 18px 20px !important; }
.agreement-scroll {
    max-height: 60vh;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 8px;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: anywhere;
    line-height: 1.45;
}

/* ===== Right-side drawer (form panels slide in from the right) ===== */
.Wt-dialog.um-drawer {
    position: fixed !important;
    top: 0 !important; right: 0 !important; left: auto !important; bottom: 0 !important;
    /* 40% of the viewport: the machine drawer carries a lot (config, options,
       history), and 480px was cramped on a wide screen. Floors at 480px so it
       does not get narrow on small laptops. */
    width: 40vw !important; min-width: 480px !important; max-width: 94vw !important;
    height: 100vh !important; height: 100dvh !important;
    margin: 0 !important; border-radius: 0 !important;
    box-shadow: -14px 0 40px rgba(0,0,0,0.25) !important;
    animation: drawerIn .24s cubic-bezier(.22,.61,.36,1);
}
@keyframes drawerIn { from { transform: translateX(100%); } to { transform: translateX(0); } }
.Wt-dialog.um-drawer .dialog-layout { display: flex !important; flex-direction: column; width: 100% !important; height: 100% !important; }
.Wt-dialog.um-drawer .titlebar { flex: 0 0 auto; font-size: 17px; padding: 16px 22px; }
.Wt-dialog.um-drawer .body { flex: 1 1 auto !important; min-height: 0; overflow-y: auto; padding: 22px 22px 28px !important; }
.Wt-dialog.um-drawer .footer { flex: 0 0 auto; padding: 14px 22px; background: var(--white); }

/* ---- Desktop: hide hamburger (sidebar is always visible) ---- */
.um-burger { display: none; }
/* ---- Desktop: hide the drawer titlebar's back/close control; the desktop
   header geometry is tuned and must not shift, and the bottom Close button
   already covers desktop. ---- */
.um-drawer-back { display: none; }

/* ===== RESPONSIVE — tablet & mobile ===== */

/* --- 768px: tablet breakpoint --- */
@media (max-width: 768px) {
    /* Show hamburger in the white top row. */
    .um-burger { display: inline-flex; }

    /* Sidebar hidden off-screen; slides in as overlay. Header is 108px tall (60 white + 48 green). */
    .um-sidebar {
        position: fixed !important;
        top: 108px; left: 0; bottom: 0;
        width: 240px !important; flex: none !important;
        transform: translateX(-100%);
        z-index: 200;
        box-shadow: none;
    }
    .um-shell.nav-open .um-sidebar {
        transform: translateX(0);
        box-shadow: 4px 0 20px rgba(0,0,0,0.22);
        flex-basis: 240px !important;
    }
    /* Keep nav labels visible in mobile overlay. */
    .um-shell.nav-open .um-nav-label { display: inline !important; }

    /* Backdrop behind sidebar overlay. */
    .um-shell.nav-open::after {
        content: '';
        position: fixed;
        inset: 108px 0 0 0;
        background: rgba(0,0,0,0.35);
        z-index: 199;
    }

    .um-content-area > * { padding: 16px 14px; }
    .dashboard-grid { grid-template-columns: 1fr; }

    /* Form drawer full width on mobile. min-width must be reset too: it is
       applied after max-width, so the base 480px floor would override both
       values below it and push the drawer's left edge off a narrower screen,
       where overflow-x:hidden makes it unreachable. */
    .Wt-dialog.um-drawer {
        min-width: 0 !important;
        width: 100vw !important;
        max-width: 100vw !important;
    }

    /* Tables not yet converted to cards: contained horizontal scroll. */
    .um-table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        white-space: nowrap;
        min-width: 0;
        max-width: 100%;
    }

    /* Card layout. Each row becomes a card and each cell a label/value line;
       the label text comes from the data-label attribute the panel sets on the
       body cells, so it stays translated and new columns are picked up. */
    .um-table.um-table-cards {
        display: block;
        overflow-x: visible;
        white-space: normal;
        background: transparent;
        box-shadow: none;
        border-radius: 0;
    }
    .um-table-cards thead { display: none; }
    .um-table-cards tbody { display: block; }
    .um-table-cards tbody tr {
        display: block;
        background: var(--white);
        border: 1px solid var(--gray-200);
        border-radius: 8px;
        margin-bottom: 10px;
        box-shadow: 0 1px 3px rgba(0,0,0,0.06);
    }
    /* Zebra striping and the desktop hover tint would flood a whole card, so
       both are reset to the card background here. */
    .um-table-cards tbody tr:nth-child(even),
    .um-table-cards tbody tr:hover { background: var(--white); }
    .um-table-cards tbody tr:active { background: #eef6f1; }

    .um-table-cards tbody td {
        display: flex;
        align-items: baseline;
        gap: 10px;
        width: auto;
        padding: 8px 12px;
        border-bottom: 1px solid var(--gray-200);
        white-space: normal;
        overflow-wrap: anywhere;
    }
    .um-table-cards tbody td::before {
        content: attr(data-label);
        flex: 0 0 38%;
        max-width: 38%;
        color: var(--gray-500, #6c757d);
        font-size: 12px;
        font-weight: 600;
    }
    .um-table-cards tbody tr td:last-child { border-bottom: none; }

    /* Action cells carry an empty label and take the full card width. */
    .um-table-cards tbody td[data-label=""] { display: block; }
    .um-table-cards tbody td[data-label=""]::before { content: none; }
    .um-table-cards tbody td[data-label=""]:empty { display: none; }

    .panel-head { flex-wrap: wrap; gap: 8px; }
    .um-search { flex: 1 1 100%; max-width: none; }
    .panel-add-btn { flex: 0 0 auto; min-height: 40px; padding: 9px 16px; }

    /* Tablet-range (481-768) touch targets. */
    .action-btn { min-height: 40px; padding: 7px 10px; }
    .um-lang-opt { min-height: 40px; display: inline-flex; align-items: center; }

    /* Permission-group editor: stack the two panes on narrow screens. */
    .um-group-split { flex-direction: column; }

    /* The logo is 891x102, so at its 40px height it is ~349px wide — on a phone
       that fills the row on its own and pushes the user menu (and with it
       logout) off screen. Cap it by viewport share so the menu always fits. */
    .um-header-logo { height: auto; max-height: 40px; max-width: 42vw; }

    /* Hide app title in white row when space is tight. */
    .um-header-title { display: none; }

    /* Touch-size the user pill exactly as sparepartsWT does below 768px. */
    .um-user-menu-trigger {
        font-size: calc(14px * var(--font-scale));
        padding: 6px 12px;
        height: 40px;
    }

    .form-label { min-width: 100px; }
    .form-hint { margin-left: 110px; }
    .field-error { margin-left: 110px; }
    .cust-nr-list { margin-left: 110px; }

    .login-box {
        width: 95%;
        padding: 20px 16px;
    }
    .login-logo { max-width: 150px; }

    /* Machine filter chips + the Prev/Next pager buttons (same class): fixed
       28px height is below the 40px touch minimum. Let the box grow instead
       of staying pinned to 28px. */
    .filter-chip {
        height: auto;
        min-height: 40px;
        padding: 8px 12px;
        line-height: 1.3;
    }

    /* Destructive dialog-footer button: pad it up to a touch-safe height. */
    .dlg-title-delete {
        min-height: 40px;
        display: flex;
        align-items: center;
    }

    /* Checkbox tap area: 18px is under the 24px minimum. Growing the visible
       box itself (rather than an invisible hit-only overlay) keeps the check
       glyph centred with no extra markup. Checked against the two grids that
       hold checkboxes: .um-check-scroll rows are single flex rows with their
       own gap, and .scope-check-list items have a 160px min-width — a 6px
       box growth does not push either into wrapping or clipping. */
    input[type="checkbox"] {
        width: 24px;
        height: 24px;
    }
    input[type="checkbox"]:checked::after {
        left: 7px; top: 3px; width: 6px; height: 11px;
    }
    .um-card input[type="checkbox"], .um-preset-app input[type="checkbox"] {
        width: 24px;
        height: 24px;
    }
    .um-card input[type="checkbox"]:checked::after, .um-preset-app input[type="checkbox"]:checked::after {
        left: 7px; top: 3px; width: 6px; height: 11px;
    }

    /* Company-tree expand/collapse toggle: enlarge the tap area to 40x40 via
       an absolutely-positioned pseudo-element instead of growing the toggle's
       own box. This keeps the glyph's visual size and the row's flex layout
       (gap-based, name label position) completely untouched — an absolutely
       positioned box is taken out of flow, so it cannot push the label or
       change indentation, and it still paints above the row's static content
       so taps in the overlap area land on the toggle, not the row. */
    .tree-toggle { position: relative; }
    .tree-toggle::before {
        content: '';
        position: absolute;
        top: 50%; left: 50%;
        width: 40px; height: 40px;
        transform: translate(-50%, -50%);
    }

    /* Autosuggest dropdown (company/parent search): cap it to the viewport
       and let long names wrap instead of forcing a nowrap width that an
       ancestor's overflow-x:hidden then clips unreachably. */
    .Wt-suggest {
        max-width: calc(100vw - 24px);
        overflow-x: hidden;
    }
    .Wt-suggest li {
        white-space: normal;
        overflow-wrap: anywhere;
    }

    /* Imported-data option row: the fixed 88px/100px columns squeeze the
       label unreadably narrow inside a full-width drawer. Stack the label on
       its own row, value + action share the row below. */
    .opt-row {
        grid-template-columns: 1fr auto;
        grid-template-areas: "label label" "value action";
        row-gap: 2px;
    }
    .opt-label { grid-area: label; }
    .opt-value { grid-area: value; text-align: left; }
    .opt-action { grid-area: action; }

    /* PDF viewer dialog: the 64vw cap (sized for desktop) leaves a lot of a
       phone screen unused. */
    .Wt-dialog.pdf-file-viewer {
        width: 94vw !important;
        max-width: 94vw !important;
    }

    /* Drawer body: 22px side padding costs 44px of a 375px screen. */
    .Wt-dialog.um-drawer .body { padding: 22px 14px 28px !important; }

    /* Back/close control at the left of the drawer titlebar (mobile only —
       desktop keeps its tuned geometry and relies on the bottom Close button).
       The bottom Close/Cancel button stays; this is only a second way in from
       the top, so a touch user does not lose track of how to leave the panel. */
    .Wt-dialog.um-drawer .titlebar { display: flex; align-items: center; gap: 8px; }
    .Wt-dialog.um-drawer .titlebar h4 { margin: 0; min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; }
    .um-drawer-back {
        display: inline-flex;
        position: relative;
        align-items: center;
        justify-content: center;
        flex: 0 0 auto;
        color: inherit; /* same foreground as the rest of the titlebar */
        cursor: pointer;
    }
    .um-drawer-back svg { width: 20px; height: 20px; display: block; }
    /* 44x44 tappable area via an absolutely-positioned overlay, the same
       technique .tree-toggle uses above — grows the hit target without
       affecting the visible icon size or the titlebar layout. */
    .um-drawer-back::before {
        content: '';
        position: absolute;
        top: 50%; left: 50%;
        width: 44px; height: 44px;
        transform: translate(-50%, -50%);
    }
}

/* --- 480px: phone breakpoint --- */
@media (max-width: 480px) {
    body { font-size: 13px; }

    .um-header-top { gap: 8px; padding: 6px 10px; min-height: 44px; }
    /* Tighter still on phones: burger + logo + user menu must share ~355px. */
    .um-header-logo { max-height: 34px; max-width: 40vw; }
    .um-user-menu-name { max-width: 110px; }
    /* Only the horizontal padding tightens, as in sparepartsWT: the green bar
       keeps its 60px height so it stays flush with the catalog viewer's. */
    .um-header-bar { padding: 6px 10px; gap: 8px; }

    /* Header is 100px tall on phones (52 white + 48 green); align the overlay
       sidebar + backdrop to it. The white row is 52px, not its 44px min-height:
       the 40px logo plus 6px padding above and below already exceeds it. */
    .um-sidebar { top: 100px; }
    .um-shell.nav-open::after { top: 100px; }

    .um-lang-opt { padding: 4px 6px; }

    /* Ensure tappable targets are at least 40px. */
    .um-lang-opt { min-height: 40px; display: inline-flex; align-items: center; }

    .um-content-area > * { padding: 12px 10px; }

    .login-logo {
        max-width: 120px;
        margin-bottom: 20px;
    }
    .login-box { padding: 20px 12px; }
    .login-title,
    .login-title h2 { font-size: 18px; }

    .action-btn { padding: 8px 10px; min-height: 40px; }
    .um-nav-item { padding: 14px 16px; min-height: 44px; }

    .form-row { flex-wrap: wrap; }
    .form-label { min-width: 100%; margin-bottom: 2px; }
    .form-input { flex: 1 1 100%; }
    .form-hint { margin-left: 0; }

    /* Profile picture: smaller circle, controls take the full row underneath. */
    .avatar-row { gap: 12px; }
    .avatar-frame { width: 72px; height: 72px; }
    .avatar-placeholder { font-size: 24px; }
    .avatar-actions { flex: 1 1 100%; }
    .field-error { margin-left: 0; }
    .cust-nr-list { margin-left: 0; }

    .Wt-dialog.um-drawer .footer { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }

    /* Centered (non-drawer) dialogs: keep inside the viewport on tiny screens. */
    .Wt-dialog:not(.um-drawer) {
        min-width: 0 !important; width: 92vw !important; max-width: 92vw !important;
        left: 4vw !important; right: auto !important; margin-left: 0 !important; transform: none !important;
    }
    .login-btn { min-height: 40px; }
}

/* Ajax loading indicator. Matches sparepartsWT's badge. Wt attaches inline
   styles to its own default red box, so these need !important. The delayed
   fade-in keeps short requests from flashing the badge. */
div.Wt-loading {
    position: fixed !important;
    top: 14px !important;
    right: 14px !important;
    left: auto !important;
    /* Kept after the root height rule was narrowed to .um-shell: the badge must
       size to its content whatever a host page or a future rule does. */
    height: auto !important;
    width: auto !important;
    bottom: auto !important;
    z-index: 10000;
    /* No !important on display: Wt hides the badge by setting an inline
       "display: none", and an !important here would keep it spinning forever. */
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px 7px 11px;
    border-radius: 999px;
    background: var(--primary, #198754) !important;
    color: #fff !important;
    font-family: var(--font-family, 'Nunito', Arial, sans-serif) !important;
    font-size: var(--font-size-sm, 12px) !important;
    font-weight: 700;
    letter-spacing: .2px;
    box-shadow: 0 4px 14px rgba(15, 81, 50, .35);
    pointer-events: none;
    opacity: 0;
    animation: sp-loading-in .18s ease-out .25s forwards;
}
div.Wt-loading::before {
    content: ""; flex: 0 0 13px; width: 13px; height: 13px;
    border: 2px solid rgba(255, 255, 255, .35); border-top-color: #fff;
    border-radius: 50%; animation: btn-spin .6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
@keyframes sp-loading-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    div.Wt-loading { animation: none; opacity: 1; }
    div.Wt-loading::before { animation-duration: 1.8s; }
}
@media (max-width: 768px) {
    div.Wt-loading { top: 10px !important; right: 10px !important; }
}

/* ============ Embed mode (?embed=1) ============
   The host app (Flutter WebView) draws its own chrome, so UM hides its header
   and sidebar and gives the whole viewport to the content area. Not inside a
   media query: embed mode applies at every width. Kept last in the file so it
   also beats the equal-specificity mobile overlay rules above. */
.um-embed .um-header { display: none; }
.um-embed .um-sidebar { display: none !important; }
.um-embed .um-body { flex: 1 1 auto; min-height: 0; height: 100%; }
.um-embed .um-content-area {
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    min-width: 0;
    margin: 0;
}
/* Sticky headers are off inside a host WebView. They work in a browser, where
   .um-content-area is the scrolling box, but a WebView sizes its document
   differently and the header then anchors to the wrong box and lets rows show
   above it. Needs measuring from inside the WebView before re-enabling. */
.um-embed .um-table thead th { position: static; }
/* Sidebar backdrop: kill it outright so a stray nav-open class can never put an
   overlay over the embedded content. */
.um-shell.um-embed.nav-open::after { content: none !important; display: none !important; }
