:root{--bg:#09090b;--card:#17171a;--surface:#1c1c1f;--surface-high:#27272b;--line:#313134;--text:#e4e4e7;--muted:#8e8e94;--muted2:#adadb3;--blue:#38bdf8;--on-blue:#00293b;--orange:#fb923c;--orange-strong:#fdba74;--overlay:rgba(0,0,0,.7);--input-bg:#17171a;--radius-sm:6px;--radius:10px;--radius-lg:14px;--mono:ui-monospace,'SF Mono','Cascadia Code','JetBrains Mono',Consolas,monospace;
  --notice-success-bg:#052e1c;--notice-success-text:#86efac;
  --badge-joomla3-bg:rgba(168,85,247,.14);--badge-joomla3-txt:#c084fc;
  --badge-joomla5-bg:rgba(56,189,248,.14);--badge-joomla5-txt:#38bdf8;
  --badge-joomla6-bg:rgba(52,211,153,.14);--badge-joomla6-txt:#34d399;
  --badge-js-bg:rgba(251,191,36,.14);--badge-js-txt:#fbbf24;
  --badge-custom-bg:rgba(45,212,191,.14);--badge-custom-txt:#2dd4bf;
  --badge-email-bg:rgba(148,163,184,.14);--badge-email-txt:#cbd5e1;
  --badge-domain-bg:rgba(251,146,60,.14);--badge-domain-txt:#fb923c;
  --badge-redirect-bg:rgba(129,140,248,.14);--badge-redirect-txt:#a5b4fc;
  --badge-unused-bg:rgba(148,163,184,.14);--badge-unused-txt:#94a3b8;
  --badge-netcup-bg:rgba(52,211,153,.12);--badge-netcup-txt:#34d399;
  --badge-hostcreators-bg:rgba(251,191,36,.12);--badge-hostcreators-txt:#fbbf24;
  --badge-html-bg:rgba(248,113,113,.12);--badge-html-txt:#f87171;
  --badge-php-bg:rgba(192,132,252,.12);--badge-php-txt:#c084fc;
  --badge-presta-bg:rgba(244,114,182,.12);--badge-presta-txt:#f472b6;
  --badge-default-bg:rgba(156,163,175,.12);--badge-default-txt:#9ca3af}
:root[data-theme="light"]{--bg:#f4f6fb;--card:#ffffff;--surface:#eef1f7;--surface-high:#e5e9f2;--line:#dde3ee;--text:#151b2c;--muted:#6b7686;--muted2:#4b5565;--blue:#0284c7;--on-blue:#ffffff;--orange:#c2410c;--orange-strong:#9a3412;--overlay:rgba(15,23,42,.5);--input-bg:#ffffff;
  --notice-bg:#e0f2fe;--notice-text:#0c4a6e;--notice-success-bg:#dcfce7;--notice-success-text:#166534;
  --badge-joomla3-bg:#faf5ff;--badge-joomla3-txt:#7e22ce;
  --badge-joomla5-bg:#eff6ff;--badge-joomla5-txt:#1d4ed8;
  --badge-joomla6-bg:#ecfdf5;--badge-joomla6-txt:#047857;
  --badge-js-bg:#fffbeb;--badge-js-txt:#b45309;
  --badge-custom-bg:#f0fdfa;--badge-custom-txt:#0f766e;
  --badge-email-bg:#f8fafc;--badge-email-txt:#475569;
  --badge-domain-bg:#fff7ed;--badge-domain-txt:#c2410c;
  --badge-redirect-bg:#eef2ff;--badge-redirect-txt:#4338ca;
  --badge-unused-bg:#f1f5f9;--badge-unused-txt:#64748b;
  --badge-netcup-bg:#ecfdf5;--badge-netcup-txt:#047857;
  --badge-hostcreators-bg:#fffbeb;--badge-hostcreators-txt:#b45309;
  --badge-html-bg:#fef2f2;--badge-html-txt:#b91c1c;
  --badge-php-bg:#faf5ff;--badge-php-txt:#7e22ce;
  --badge-presta-bg:#fdf2f8;--badge-presta-txt:#be185d;
  --badge-default-bg:#f1f5f9;--badge-default-txt:#475569}
:root{--sidebar-bg:#0c0c0e;--sidebar-bg-active:#242428;--sidebar-text:#e4e4e7;--sidebar-muted:#8e8e94}
*{box-sizing:border-box}
[hidden]{display:none!important}
body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Inter,Roboto,sans-serif;-webkit-font-smoothing:antialiased}
.bar,.actions{align-items:center;gap:12px}
.actions.wide{display:inline;gap:10px}
.actions.wide .button,.actions.wide .primary{flex:1;display:inline-block;align-items:center;justify-content:center;padding:10px 16px}
.actions.wide .button{background:transparent;border-color:#fb7185;color:#fb7185;margin: 4px 2px;}
.actions.wide .button:hover{background:color-mix(in srgb, #fb7185 8%, transparent)}
.actions.wide .primary{background:transparent;border-color:#34d399;color:#34d399}
.actions.wide .primary:hover{background:color-mix(in srgb, #34d399 8%, transparent)}
.row-actions{display:flex;align-items:center;gap:2px}
.bar{display:flex;justify-content:space-between;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px;margin-bottom:16px;flex-wrap:wrap}
.log-purge-form{display:inline-flex;align-items:center;gap:8px;margin-left:12px}
h1{font-size:22px;margin:0;font-weight:650;letter-spacing:-.02em}
a{color:var(--blue);text-decoration:none}
button,.button,input,select,textarea{font:inherit;font-size:13px;border-radius:var(--radius-sm);border:1px solid var(--line);padding:8px 12px;background:var(--input-bg);color:var(--text)}
button,.button{cursor:pointer;text-decoration:none;font-weight:600;transition:background .12s,border-color .12s}
.button:hover{background:var(--surface-high);border-color:var(--muted)}
.primary{background:var(--blue);color:var(--on-blue);border:1px solid var(--blue);font-weight:700}
.primary:hover{filter:brightness(1.08);background:var(--blue)}
.button svg{width:14px;height:14px;vertical-align:-2px}
.content-head-action{margin-left:auto;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
/* A "back" link paired with a primary "edit" action on a detail page —
   kept together as one right-aligned group on desktop, then on mobile
   spans the full row with back on the left and edit on the right, instead
   of each stacking as its own centered line and wasting vertical space. */
.content-head-actions-row{display:flex;align-items:center;gap:10px;margin-left:auto}
.calendar-nav-row{display:flex;gap:10px}
.danger{color:#fb7185}
.card{overflow:auto;border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--card)}
.settings-card{padding:22px;max-width:560px}
.settings-card h2{margin-top:0;font-size:15px}
table{width:100%;border-collapse:collapse;min-width:1050px}
th,td{padding:6px 14px;text-align:left;border-bottom:1px solid var(--line);vertical-align:middle}
th{color:var(--muted);background:var(--surface);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}
tbody tr{transition:background .1s}
tbody tr:hover{background:var(--surface)}
th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
th.sortable:hover{color:var(--text)}
/* Deliberately prev/next + a count, not a row of numbered page links — that
   avoids the classic mobile problem of a dozen+ number buttons overflowing
   or wrapping awkwardly; this stays exactly as usable at 360px as at 1440px. */
.pagination{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:16px;flex-wrap:wrap}
.pagination-btn[aria-disabled="true"]{opacity:.4;cursor:default;pointer-events:none}
.pagination-info{font-size:12px;text-align:center}
th.sortable::after{content:'';display:inline-block;width:10px;margin-left:4px;opacity:.35}
th.sortable.asc::after{content:'▲';opacity:1}
th.sortable.desc::after{content:'▼';opacity:1}
.dot{width:9px;height:9px;border-radius:50%;display:inline-block}
.online{background:#34d399}
.offline{background:#fb7185}
.neutral{background:#f59e0b}
.badge,.addon{display:inline-block;padding:3px 9px;border-radius:var(--radius-sm);font-weight:650;font-size:11px;font-family:var(--mono)}
.addon{border:1px solid var(--line);color:var(--muted);margin:2px;padding:3px 8px;border-radius:999px;font-weight:500}
.joomla3{background:var(--badge-joomla3-bg);color:var(--badge-joomla3-txt)}
.joomla5{background:var(--badge-joomla5-bg);color:var(--badge-joomla5-txt)}
.joomla6{background:var(--badge-joomla6-bg);color:var(--badge-joomla6-txt)}
.php{background:var(--badge-php-bg);color:var(--badge-php-txt)}
.javascript{background:var(--badge-js-bg);color:var(--badge-js-txt)}
.custom{background:var(--badge-custom-bg);color:var(--badge-custom-txt)}
.html{background:var(--badge-html-bg);color:var(--badge-html-txt)}
.prestashop{background:var(--badge-presta-bg);color:var(--badge-presta-txt)}
.email{background:var(--badge-email-bg);color:var(--badge-email-txt)}
.unused{background:var(--badge-unused-bg);color:var(--badge-unused-txt)}
.domain{background:var(--badge-domain-bg);color:var(--badge-domain-txt)}
.redirect{background:var(--badge-redirect-bg);color:var(--badge-redirect-txt)}
.hosting-netcup{background:var(--badge-netcup-bg);color:var(--badge-netcup-txt)}
.hosting-hostcreators{background:var(--badge-hostcreators-bg);color:var(--badge-hostcreators-txt)}
.hosting-default{background:var(--badge-default-bg);color:var(--badge-default-txt)}
.client-company{background:var(--badge-php-bg);color:var(--badge-php-txt)}
.client-individual{background:var(--badge-custom-bg);color:var(--badge-custom-txt)}
#domainsTable td[data-value="domain"] a{font-family:var(--mono);font-weight:600}
.icon-action{background:none;border:none;cursor:pointer;padding:6px;color:var(--muted);border-radius:var(--radius-sm);font-size:15px;line-height:1;display:inline-flex;align-items:center;justify-content:center}
.icon-action svg{width:16px;height:16px}
.icon-action:hover{color:var(--text);background:var(--surface-high)}
.icon-action.danger:hover{color:#fb7185;background:var(--surface-high)}
.note-cell{display:flex;align-items:center;gap:0;width:190px}
.note-preview{display:inline-block;flex:1;min-width:0;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;color:var(--muted);font-size:13px;margin-right:6px}
.note-cell .icon-action{flex:0 0 auto}
.modal-backdrop{position:fixed;inset:0;background:var(--overlay);display:flex;align-items:flex-start;justify-content:center;padding:40px 16px;overflow-y:auto;z-index:100;backdrop-filter:blur(3px);overscroll-behavior:contain}
/* flex column, not just block: lets a modal with an explicit min-height (set
   per-instance, e.g. so a long Tom Select dropdown has room to open without
   overflowing the card) push its own form's actions row down to the bottom
   via margin-top:auto, instead of leaving empty space below a short form. A
   modal with no min-height override behaves exactly as before — nothing
   here stretches unless a child explicitly opts in with flex/margin-top:auto. */
.modal{display:flex;flex-direction:column;max-width:720px;width:100%;background:var(--card);padding:22px;border-radius:var(--radius-lg);border:1px solid var(--line);box-shadow:0 20px 50px rgba(0,0,0,.35)}
.modal h2{margin-top:0;font-size:17px}
.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.modal-head h2{flex:1;min-width:0}
.modal-close{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:32px;height:32px;margin:-4px -4px 0 0;border:none;background:transparent;color:var(--muted);border-radius:var(--radius-sm);cursor:pointer;text-decoration:none}
.modal-close:hover{background:var(--surface-high);color:var(--text)}
.modal-close svg{width:16px;height:16px}
/* While any modal is open (present and not [hidden]), the page behind it
   can't be scrolled — on desktop a mouse wheel and on mobile a touch drag
   both used to "leak" past the modal's own scroll boundary onto the body. */
body:has(.modal-backdrop:not([hidden])),body:has(.sidebar.mobile-open){overflow:hidden}
.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.field{display:grid;gap:6px}
.field{font-size:12px;color:var(--muted);font-weight:600}
.wide{grid-column:1/-1}
.field-row-3{grid-column:1/-1;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
/* Jazyky row (contact edit modal): jazyk + úroveň side by side, equal width.
   Sized on a wrapper DIV around each <select>, not the select itself — Tom
   Select hides the original select and inserts its own ".ts-wrapper" in its
   place, which doesn't inherit inline sizing put on the (now hidden) select,
   same reason ".bar .ts-wrapper" below has its own rule instead of relying
   on the plain <select> it replaces. */
.lang-row{display:flex;gap:10px;align-items:center}
.lang-row-col{flex:1;min-width:0}
textarea{min-height:200px;max-width:100%;resize:vertical;box-sizing:border-box}
textarea[data-autoresize]{min-height:60px;max-height:200px;resize:none;line-height:1.4;overflow-y:hidden}
/* The native calendar/clock-picker glyph on <input type="date"/"time"> renders
   solid black by default — invisible against this app's dark background. Dark
   theme is the default here (see :root above), so invert it there and revert
   for light theme. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator{filter:invert(1);cursor:pointer}
:root[data-theme="light"] input[type="date"]::-webkit-calendar-picker-indicator,
:root[data-theme="light"] input[type="time"]::-webkit-calendar-picker-indicator{filter:none}
.chip-checkbox-group{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}
.chip-checkbox{position:relative;display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border-radius:999px;border:1px solid var(--line);background:var(--input-bg);cursor:pointer;font-size:13px;font-weight:600;user-select:none;transition:background .12s,border-color .12s,color .12s}
.chip-checkbox input{position:absolute;opacity:0;width:0;height:0}
.chip-checkbox:hover{border-color:var(--muted)}
.chip-checkbox:has(input:checked){background:color-mix(in srgb, var(--blue) 18%, transparent);border-color:var(--blue);color:var(--blue)}
.status-choice-group{display:flex;flex-wrap:wrap;gap:8px}
.status-choice{position:relative;display:inline-flex;align-items:center;gap:7px;padding:7px 13px;border-radius:999px;border:1px solid var(--line);background:var(--input-bg);cursor:pointer;font-size:13px;font-weight:600;user-select:none;transition:background .12s,border-color .12s,color .12s}
.status-choice input{position:absolute;opacity:0;width:0;height:0}
.status-choice:hover{border-color:var(--muted)}
.status-choice.status-online:has(input:checked){background:color-mix(in srgb, #34d399 18%, transparent);border-color:#34d399;color:#34d399}
.status-choice.status-offline:has(input:checked){background:color-mix(in srgb, #fb7185 18%, transparent);border-color:#fb7185;color:#fb7185}
.status-choice.status-neutral:has(input:checked){background:color-mix(in srgb, #f59e0b 18%, transparent);border-color:#f59e0b;color:#f59e0b}
.notice{padding:11px 13px;border-radius:var(--radius-sm);background:var(--notice-bg,#12324a);color:var(--notice-text,var(--text));margin-bottom:14px;border:1px solid color-mix(in srgb, currentColor 25%, transparent);font-size:13px;transition:opacity .4s ease, transform .4s ease}
.notice.success{background:var(--notice-success-bg);color:var(--notice-success-text)}
.notice.notice-hide{opacity:0;transform:translateY(-4px)}
.login{max-width:420px;width:calc(100% - 32px);margin:12vh auto}
.muted{color:var(--muted)}

.shell{display:flex;min-height:100vh}
.sidebar{width:258px;flex:0 0 258px;background:var(--sidebar-bg);color:var(--sidebar-text);display:flex;flex-direction:column;padding:16px 12px;gap:4px;position:sticky;top:0;align-self:flex-start;height:100vh;overflow-y:auto;border-right:1px solid rgba(255,255,255,.06)}
.sidebar-head{display:flex;align-items:center;justify-content:space-between;padding:6px 6px 14px;margin-bottom:8px;border-bottom:1px solid rgba(255,255,255,.08)}
.brand{display:flex;align-items:center;gap:10px;color:#fff;text-decoration:none;font-weight:700;font-size:15px;overflow:hidden;white-space:nowrap;letter-spacing:-.01em}
.brand-mark{width:22px;height:22px;flex:0 0 auto;display:block;object-fit:contain;border-radius:6px}
.icon-btn{background:transparent;border:1px solid rgba(255,255,255,.14);color:var(--sidebar-text);width:28px;height:28px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;cursor:pointer;flex:0 0 auto;padding:0;transition:background .12s}
.icon-btn:hover{background:rgba(255,255,255,.08)}
.icon-btn svg{width:15px;height:15px}
.sidebar-nav{display:flex;flex-direction:column;gap:2px;flex:1;margin-top:6px}
.nav-group-bottom{margin-top:auto;padding-top:10px;border-top:1px solid rgba(255,255,255,.06)}
.nav-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:var(--radius-sm);color:var(--sidebar-muted);text-decoration:none;font-weight:600;font-size:13px;border:0;border-left:2px solid transparent;background:transparent;width:100%;cursor:pointer;white-space:nowrap;overflow:hidden;text-align:left;transition:background .12s,color .12s}
.nav-item svg{flex:0 0 auto;width:16px;height:16px}
.nav-item:hover{background:rgba(255,255,255,.06);color:var(--sidebar-text)}
.nav-item.active{background:var(--sidebar-bg-active);color:var(--blue);border-left-color:var(--blue)}
.nav-count{margin-left:auto;font-family:var(--mono);font-size:10px;font-weight:700;color:var(--sidebar-muted);background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);padding:1px 6px;flex:0 0 auto}
.nav-item.active .nav-count{color:var(--blue);border-color:color-mix(in srgb, var(--blue) 40%, transparent)}
/* Inside a toggle button, the count sits right next to the label (it's info
   about that item) while the chevron — the actual expand/collapse control —
   is what gets pushed to the far right, not the count. */
.nav-group-toggle .nav-count{margin-left:4px}
.nav-group-toggle .nav-chevron{margin-left:auto;transition:transform .15s;flex:0 0 auto}
.nav-group-toggle[aria-expanded="true"] .nav-chevron{transform:rotate(90deg)}
.nav-submenu{display:flex;flex-direction:column;gap:2px;padding-left:32px;margin:2px 0 6px}
.nav-subitem{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:var(--radius-sm);color:var(--sidebar-muted);font-size:12px}
.nav-subitem em{font-style:normal;font-size:9px;background:rgba(255,255,255,.08);padding:2px 6px;border-radius:20px;margin-left:auto;font-family:var(--mono)}
a.nav-subitem{text-decoration:none;cursor:pointer}
a.nav-subitem:hover{background:rgba(255,255,255,.06);color:var(--sidebar-text)}
a.nav-subitem.active{color:var(--blue);font-weight:600}
.sidebar-foot{border-top:1px solid rgba(255,255,255,.08);padding-top:8px;margin-top:8px;display:flex;flex-direction:column;gap:2px}
.sidebar-user{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:var(--radius-sm);color:var(--sidebar-text);text-decoration:none;white-space:nowrap;overflow:hidden;cursor:pointer;transition:background .12s}
.sidebar-user:hover{background:rgba(255,255,255,.06)}
.sidebar-user:hover .logout-icon{opacity:1;color:#fb7185}
.logout-icon{margin-left:auto;flex:0 0 auto;display:flex;opacity:.45;transition:opacity .12s,color .12s}
.logout-icon svg{width:15px;height:15px}
.user-name{display:flex;flex-direction:column;gap:2px;overflow:hidden;font-size:13px}
.role-tag{font-size:10px;font-weight:700;color:var(--sidebar-muted);text-transform:uppercase;letter-spacing:.05em;font-family:var(--mono)}
.role-badge{display:inline-block;padding:3px 9px;border-radius:999px;font-size:11px;font-weight:650;background:var(--line);color:var(--muted);font-family:var(--mono)}
.role-badge.superuser{background:#4c1d95;color:#ddd6fe}
.role-badge.manager{background:#0c3d58;color:#7dd3fc}
.role-badge.reader{background:#334155;color:#cbd5e1}
.role-badge.hr{background:#134e4a;color:#5eead4}
/* Jazyky on a contact's profile: one small chip per language (name + level)
   instead of one long comma-joined string — wraps cleanly onto as many
   lines as needed instead of overflowing/squeezing at the row's edge. */
.lang-chips{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end;max-width:70%}
.lang-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;background:var(--surface);border:1px solid var(--line);font-size:12px;white-space:nowrap}
.lang-chip-level{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;padding:1px 6px;border-radius:999px}
.lang-chip-level.zakladna{background:color-mix(in srgb, #94a3b8 20%, transparent);color:#94a3b8}
.lang-chip-level.stredna{background:color-mix(in srgb, #38bdf8 20%, transparent);color:#38bdf8}
.lang-chip-level.pracovna{background:color-mix(in srgb, #818cf8 20%, transparent);color:#818cf8}
.lang-chip-level.pokrocila{background:color-mix(in srgb, #34d399 20%, transparent);color:#34d399}
.avatar{flex:0 0 auto;width:26px;height:26px;border-radius:var(--radius-sm);background:var(--blue);color:var(--on-blue);font-weight:700;display:flex;align-items:center;justify-content:center;font-size:12px}
.sidebar-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:91}
.content{flex:1;min-width:0;padding:26px 30px;overflow-x:hidden}
.content-head{display:flex;align-items:center;gap:14px;margin-bottom:20px;flex-wrap:wrap}
.content-head p{margin:2px 0 0;font-size:13px}
.mobile-only{display:none}
.mobile-topbar{align-items:center;justify-content:space-between;position:sticky;top:0;z-index:80;background:var(--sidebar-bg);border-bottom:1px solid rgba(255,255,255,.08);padding:10px 16px}
.mobile-menu-btn{display:flex;align-items:center;gap:8px;background:transparent;border:1px solid rgba(255,255,255,.14);border-radius:var(--radius-sm);padding:9px 16px;color:var(--sidebar-text);font-weight:600;font-size:14px;cursor:pointer;transition:background .12s}
.mobile-menu-btn:hover{background:rgba(255,255,255,.08)}
.mobile-menu-btn svg{width:20px;height:20px}

.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px;margin-bottom:18px}
.stat-card{position:relative;background:var(--card);border:1px solid var(--line);border-radius:var(--radius-lg);padding:16px 18px;display:flex;flex-direction:column;gap:6px;transition:border-color .15s;color:var(--text);text-decoration:none}
.stat-card:hover{border-color:var(--muted)}
.stat-card .dot{position:absolute;top:18px;right:18px}
.stat-number{font-size:26px;font-weight:750;letter-spacing:-.02em}
.stat-label{color:var(--muted);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}
.stat-sub{color:var(--muted);font-size:11px;margin-top:-2px}

/* Admin-tier dashboard: a top row of quick actions, a 4-up KPI row, a
   full-width "upcoming" row, then a 50/50 split of ranked lists (most active
   left, least active right). */
.kpi-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:18px}
.kpi-highlight{border-color:color-mix(in srgb, #f59e0b 55%, var(--line))}
.kpi-highlight:hover{border-color:#f59e0b}
.dash-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;align-items:start}
.quick-actions{display:flex;flex-direction:column;gap:8px}
.quick-actions-row{display:flex;gap:10px;flex-wrap:wrap}
.quick-actions-row .quick-action{flex:1;min-width:180px}
.quick-action{display:flex;align-items:center;gap:8px;justify-content:flex-start;width:100%;box-sizing:border-box}
.upcoming-row{display:flex;gap:12px;flex-wrap:wrap}
.upcoming-chip{display:flex;flex-direction:column;gap:4px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);padding:10px 14px;min-width:190px;flex:1}
.upcoming-chip .flat-value{align-self:flex-start}
.section-label{color:var(--blue);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}
.info-icon{display:inline-flex;position:relative;vertical-align:-3px;color:var(--orange);cursor:pointer;margin-left:4px;padding:2px}
.info-icon svg{width:14px;height:14px}
.info-icon:hover,.info-icon:focus-visible,.info-icon.is-open{color:var(--orange-strong)}
.info-icon:focus-visible{outline:2px solid var(--orange);outline-offset:2px;border-radius:4px}
.info-icon::after{
  content:attr(data-tooltip);
  position:absolute;
  left:50%;
  bottom:calc(100% + 9px);
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(3px);
  width:max-content;
  max-width:min(280px, 70vw);
  background:var(--surface-high);
  color:var(--text);
  border:1px solid var(--line);
  border-radius:var(--radius-sm);
  padding:8px 10px;
  font-size:12px;
  font-weight:400;
  line-height:1.4;
  white-space:pre-line;
  text-align:left;
  /* Reset — some headings (e.g. dashboard's .stat-section h2) are
     uppercase, and this pseudo-element would otherwise inherit that
     and shout the whole tooltip text regardless of where it sits. */
  text-transform:none;
  box-shadow:0 8px 24px rgba(0,0,0,.35);
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .08s ease, transform .08s ease;
  z-index:40;
}
.info-icon:hover::after,.info-icon:focus-visible::after,.info-icon.is-open::after{
  opacity:1;
  visibility:visible;
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(0);
}

/* Rich variant: a real child element instead of the plain data-tooltip attr,
   for tooltips that need actual markup (bold labels, spaced-out lines) rather
   than just a flat string. Same box/position/show-on-hover behaviour as the
   plain ::after version above, just targeting a real element instead. */
.info-icon-content{
  position:absolute;
  left:50%;
  bottom:calc(100% + 9px);
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(3px);
  width:max-content;
  max-width:min(280px, 70vw);
  background:var(--surface-high);
  color:var(--text);
  border:1px solid var(--line);
  border-radius:var(--radius-sm);
  padding:10px 12px;
  font-size:12px;
  font-weight:400;
  line-height:1.5;
  text-align:left;
  text-transform:none;
  box-shadow:0 8px 24px rgba(0,0,0,.35);
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .08s ease, transform .08s ease;
  z-index:40;
}
.info-icon-content p{margin:0 0 8px}
.info-icon-content p:last-child{margin-bottom:0}
.info-icon:hover .info-icon-content,.info-icon:focus-visible .info-icon-content,.info-icon.is-open .info-icon-content{
  opacity:1;
  visibility:visible;
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(0);
}

/* "Team pulse" — one-click health status on a report, and the small colored
   dot that surfaces it (per-report, or aggregated per-project) elsewhere. */
.pulse-picker{display:flex;gap:8px;margin-top:6px;flex-wrap:wrap}
.pulse-option{
  display:flex;align-items:center;gap:6px;
  padding:8px 12px;border-radius:var(--radius-sm);
  border:1px solid var(--line);background:var(--input-bg);
  font-size:13px;cursor:pointer;transition:border-color .1s ease, background .1s ease;
}
.pulse-option input{position:absolute;opacity:0;width:1px;height:1px}
.pulse-option:has(input:focus-visible){outline:2px solid var(--blue);outline-offset:2px}
.pulse-option:has(input:checked){border-color:currentColor;background:color-mix(in srgb, currentColor 14%, var(--input-bg))}
.pulse-green{color:#34d399}
.pulse-yellow{color:#f59e0b}
.pulse-red{color:#fb7185}
.pulse-dot{display:inline-block;width:10px;height:10px;border-radius:50%;vertical-align:middle}
.section-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-bottom:16px}
.section-grid-2col{grid-template-columns:repeat(2,minmax(0,1fr))}
/* Overrides .card's overflow:auto — these cards never need to scroll, and
   that clipping was cutting off info-icon tooltips that pop up above a
   heading sitting right at the card's own top edge. */
.stat-section{padding:18px;margin-bottom:0;overflow:visible}
.stat-section h2{margin:0 0 14px;font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.flat-list{display:flex;flex-direction:column}
.flat-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 2px;border-bottom:1px solid var(--line);color:inherit;text-decoration:none;font-size:13px;min-width:0}
.flat-row:last-child{border-bottom:none}
a.flat-row:hover{color:var(--blue)}
/* A long real name/label on the left must never push the value on the right
   off the edge of the card (that content would then be unreachable — the
   card itself can't scroll, by design, so it has to stay short instead). */
.flat-row>*:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex:1}
.flat-value{font-weight:700;font-family:var(--mono);color:var(--muted);font-size:12px;flex-shrink:0;white-space:nowrap}
i.flat-dot{width:8px;height:8px;border-radius:2px;display:inline-block;margin-right:9px;vertical-align:middle;background:currentColor}
.flat-row-main{display:flex;align-items:center;gap:6px;flex:1;min-width:0}
.flat-row-name{flex-shrink:0;max-width:55%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.flat-row-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-weight:400}

:root[data-sidebar-collapsed="1"] .sidebar{width:72px;flex-basis:72px}
:root[data-sidebar-collapsed="1"] .nav-label,
:root[data-sidebar-collapsed="1"] .nav-count,
:root[data-sidebar-collapsed="1"] .brand-text,
:root[data-sidebar-collapsed="1"] .user-name,
:root[data-sidebar-collapsed="1"] .logout-icon,
:root[data-sidebar-collapsed="1"] .nav-submenu,
:root[data-sidebar-collapsed="1"] .nav-group-toggle .nav-chevron{display:none}
:root[data-sidebar-collapsed="1"] .sidebar-head{justify-content:center}
:root[data-sidebar-collapsed="1"] #sidebarToggle svg{transform:rotate(180deg)}

@media(max-width:900px){
  .shell{display:block}
  /* height, not top+bottom — and dvh, not vh: a real mobile browser's
     address bar shows/hides as you scroll, and plain vh/top+bottom both
     size against the LARGE viewport (as if the bar were already hidden),
     which pushed the bottom of the drawer (the account/logout row) below
     whatever's actually visible. dvh tracks the current visible viewport
     instead. The vh line first is a fallback for a browser without dvh. */
  .sidebar{position:fixed;left:0;top:0;height:100vh;height:100dvh;z-index:95;width:258px;flex-basis:258px;transform:translateX(-100%);transition:transform .2s ease}
  .sidebar.mobile-open{transform:translateX(0)}
  .mobile-only{display:flex}
  #sidebarToggle{display:none}
  /* Grid, not flex-wrap: flex-wrap only breaks the action button onto its
     own line once the title runs out of room to share one with it — which
     depended on how long that particular page's title/subtitle happened to
     be, so it wrapped (and centered) on some pages but not others. Grid
     with a single column puts every child — the top row (burger+title),
     then action(s) — on its own full-width row unconditionally, every time. */
  .content-head{display:grid;grid-template-columns:1fr;gap:8px}
  /* A lone header action (back link, or "+ Add" button) centers itself
     within its row instead of hugging an edge. */
  .content-head-action{margin:0;justify-self:center}
  /* The back+edit pair instead spans the full row — back on the left, edit
     on the right — rather than centering as one unit. */
  .content-head-actions-row{margin-left:0;width:100%;justify-content:space-between}
  /* The calendar's prev/next pair becomes one full-width 50/50 row, each
     button bigger — easier to tap and no longer competing for space with
     the "back" link above it. */
  .calendar-nav-row{width:100%;display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .calendar-nav-row .button{padding:14px;font-size:15px;justify-content:center}
  :root[data-sidebar-collapsed="1"] .nav-label,
  :root[data-sidebar-collapsed="1"] .nav-count,
  :root[data-sidebar-collapsed="1"] .brand-text,
  :root[data-sidebar-collapsed="1"] .user-name,
  :root[data-sidebar-collapsed="1"] .logout-icon,
  :root[data-sidebar-collapsed="1"] .nav-group-toggle .nav-chevron{display:inline}
  .content{padding:18px 14px}
  .grid{grid-template-columns:minmax(0,1fr)}
  .field-row-3{grid-template-columns:minmax(0,1fr)}
  .section-grid,.section-grid-2col{grid-template-columns:minmax(0,1fr)}
  .kpi-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .dash-split{grid-template-columns:minmax(0,1fr)}
  .quick-actions-row{flex-direction:column}
  .quick-actions-row .quick-action{min-width:0}
  .lang-row{flex-wrap:wrap}
  .lang-row-col{flex-basis:100%}
  /* On a narrow screen, an info-icon near the left/right edge used to center
     its tooltip on the ICON, which routinely pushed a good chunk of the box
     off-screen. Centering on the VIEWPORT instead — both axes — guarantees
     it's always fully visible, wherever the icon itself happens to sit. */
  .info-icon::after,.info-icon-content{
    position:fixed;
    left:50%;
    top:50%;
    bottom:auto;
    transform:translate(-50%,-50%) scale(.98);
    max-width:min(340px, 86vw);
    max-height:80vh;
    overflow-y:auto;
    z-index:85;
  }
  .info-icon:hover::after,.info-icon:focus-visible::after,.info-icon.is-open::after,
  .info-icon:hover .info-icon-content,.info-icon:focus-visible .info-icon-content,.info-icon.is-open .info-icon-content{
    transform:translate(-50%,-50%) scale(1);
  }
  /* Dashboard "flat rows" (expiring documents, ending projects, …): the
     desktop layout truncates the name to 55% width and squeezes the rest
     onto one line with the date, which on a phone left almost nothing
     readable. Stack them instead — name, then detail text, then the
     date/status — each its own full-width line, indented to align under
     the name past the bullet dot (8px dot + 9px margin = 17px). */
  .flat-row{flex-direction:column;align-items:flex-start;gap:2px;padding:10px 2px}
  .flat-row-main{flex-wrap:wrap}
  .flat-row-name{max-width:100%;white-space:normal;overflow:visible;text-overflow:clip}
  .flat-row-text{flex-basis:100%;white-space:normal;overflow:visible;text-overflow:clip;padding-left:17px}
  .flat-value{white-space:normal;padding-left:17px}
  .lang-chips{max-width:100%;justify-content:flex-start}
}

/* Tom Select: retheme its hard-coded white/light styles to match dark/light mode via our tokens. */
.ts-wrapper .ts-control{background:var(--input-bg)!important;border:1px solid var(--line)!important;color:var(--text)!important;border-radius:var(--radius-sm)!important;box-shadow:none!important}
.ts-wrapper.focus .ts-control{border-color:var(--blue)!important}
.ts-control input{color:var(--text)!important}
.ts-dropdown{background:var(--card)!important;border:1px solid var(--line)!important;color:var(--text)!important;box-shadow:0 10px 30px rgba(0,0,0,.35)!important}
.ts-dropdown .ts-dropdown-content,.ts-dropdown [data-selectable],.ts-dropdown .no-results{background:var(--card)!important;color:var(--text)!important}
.ts-dropdown .active{background-color:var(--surface-high)!important;color:var(--text)!important}
/* A group label, not an option — same visual language as .section-label so it
   reads as a non-interactive category heading instead of looking exactly like
   every selectable row beneath it (which it used to, with no distinction at all). */
.ts-dropdown .optgroup-header{background:var(--card)!important;color:var(--muted)!important;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;padding:8px 10px 4px;cursor:default;pointer-events:none}
.ts-dropdown .optgroup:not(:first-child) .optgroup-header{margin-top:4px;border-top:1px solid var(--line);padding-top:10px}
.ts-dropdown [data-selectable] .highlight{background:color-mix(in srgb, var(--blue) 30%, transparent);border-radius:2px}
.bar .ts-wrapper{flex:1;min-width:200px}
