/* ==========================================================================
   suhos.css — SUHOS design-token foundation
   ==========================================================================

   Hand-authored replacement for bootstrap.min.css + style.css (INSPINIA) +
   style_001.css. No build step (no npm/webpack/vite in html/), so this file
   is hand-kept tight rather than generated/minified.

   Source of truth for this file's design decisions:
     doc/ui-analysis/03-target-architecture.md  (§2 tokens, §1 file contents)
     doc/ui-analysis/04-app-shell-and-scrolling.md (shell tokens, referenced
       but the shell rules themselves are implemented in a later phase)
     doc/ui-analysis/07-component-library.md (class-name vocabulary preview)

   Scope of THIS file at this phase: design tokens + base/reset layer only.
   Grid app shell, form controls, tables, buttons, badges, alerts, and
   utility classes are later phases (doc 04, doc 07) and are intentionally
   NOT implemented here yet — adding them prematurely would fork the token
   names this file defines away from what those phases actually need.

   Section order (kept stable so later phases can append/insert predictably):
     1. Color tokens
     2. Spacing scale
     3. Radius tokens
     4. Shadow tokens
     5. Typography tokens
     6. Z-index scale
     7. Shell dimension tokens (consumed by doc 04's shell layer)
     8. Reset / base layer
   ========================================================================== */

:root {
  /* --------------------------------------------------------------------
     1. Color
     Light scheme, one accent color (blue) — matches the existing
     `.tdmenu a { color: Blue; }` link-blue convention in style_001.css,
     so the new look reads as continuous, not a rebrand.
     -------------------------------------------------------------------- */

  /* Neutrals */
  --color-bg:            #f4f6f8;   /* page background */
  --color-surface:       #ffffff;   /* cards, table rows, panels */
  --color-surface-alt:   #f0f0f0;   /* zebra rows, header cells — matches old #F0F0F0 */
  --color-border:        #dfe3e8;
  --color-border-strong: #c7ccd1;
  --color-text:          #24292e;
  --color-text-muted:    #6b7280;
  --color-text-inverse:  #ffffff;

  /* Accent */
  --color-accent:        #2a5db0;   /* primary actions, active nav, links */
  --color-accent-hover:  #1f4a90;
  --color-accent-bg:     #eaf1fb;   /* active nav row background, subtle highlight */

  /* Semantic */
  --color-success:       #1c9d6c;
  --color-warning:       #b9861f;
  --color-danger:        #c0392b;
  --color-danger-bg:     #fbeae8;

  /* Test-mode signal — carried over from header.tpl's
     `html { background-color: darkred !important; }` (when
     [var.mode;noerr]!='production'). Token-ized so the shell and any
     future banner share one source of truth instead of a hard-coded
     `!important` global override. */
  --color-testmode-bg:   darkred;
  --color-testmode-fg:   #ffffff;

  /* --------------------------------------------------------------------
     2. Spacing scale (4px base)
     -------------------------------------------------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  /* --------------------------------------------------------------------
     3. Radius
     -------------------------------------------------------------------- */
  --radius-sm:   3px;    /* inputs, buttons */
  --radius-md:   6px;    /* cards, panels, dialog */
  --radius-lg:   10px;   /* modals */
  --radius-pill: 999px;  /* tags — matches existing .tag-button 16px pill look */

  /* --------------------------------------------------------------------
     4. Shadow levels
     -------------------------------------------------------------------- */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.06);   /* table row hover, inputs */
  --shadow-2: 0 2px 8px rgba(0, 0, 0, 0.10);   /* dropdown, card */
  --shadow-3: 0 8px 24px rgba(0, 0, 0, 0.18);  /* dialog/modal, drawer */

  /* --------------------------------------------------------------------
     5. Typography
     System font stack — no webfont download, no FOUT; matches the
     "no build pipeline" constraint.
     -------------------------------------------------------------------- */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  --font-size-base:   14px;  /* current is 12px (style_001.css) / 13px (style.css
                                 body) — both cramped; 14px is the floor for a
                                 dense-but-readable admin table UI in 2026 */
  --font-size-sm:     12px;  /* secondary text, table meta */
  --font-size-lg:     16px;  /* page headings, matches old H1 16px */
  --line-height-base: 1.45;

  /* --------------------------------------------------------------------
     6. Z-index scale
     Replaces the current ad-hoc z-index war (style.css: 1000, 1009, 2,
     2000, 2001, 2030, 2040, 2100, 2101, 9999; style_001.css:
     `.clockpicker-popover { z-index: 999999 !important; }`). Every
     z-index declaration in new/touched CSS must reference one of these
     tokens (`z-index: var(--z-dropdown)`), never a bare number.
     -------------------------------------------------------------------- */
  --z-base:     1;    /* normal content */
  --z-sticky:   10;   /* sticky table headers, sticky toolbar */
  --z-dropdown: 100;  /* select/autocomplete popovers, clockpicker */
  --z-sidebar:  200;  /* off-canvas drawer + backdrop, tablet rail */
  --z-topbar:   210;  /* top bar, above sidebar drawer when both are fixed */
  --z-modal:    300;  /* <dialog> confirm/edit modals (native dialog also gets
                          its own top-layer, but keep this for any backdrop divs) */
  --z-toast:    400;  /* toast notifications — always on top */

  /* --------------------------------------------------------------------
     7. Shell dimension tokens
     Named here (per doc 04 §2) so the app-shell phase can consume them
     without re-declaring the :root block. No .shell/.shell-* rules are
     defined in this file yet — those land with the app-shell phase.
     -------------------------------------------------------------------- */
  --sidebar-w:      220px;
  --sidebar-w-rail: 64px;
  --topbar-h:       56px;
}

/* ==========================================================================
   8. Reset / base layer
   Minimal, framework-agnostic reset — just enough to stop inherited
   browser/Bootstrap defaults from fighting the tokens above. Layout
   (grid app shell), components, and utilities are later phases.
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: var(--font-size-base);
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--space-3) 0;
  font-weight: 600;
  line-height: 1.25;
  color: var(--color-text);
}

h1 { font-size: var(--font-size-lg); }

p {
  margin: 0 0 var(--space-3) 0;
}

a {
  color: var(--color-accent);
  text-decoration: none;
}

a:hover,
a:focus {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

small,
.text-muted {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-4) 0;
}

img {
  max-width: 100%;
}

/* Baseline focus visibility — accessible default until component-level
   focus styles are added in the components phase. */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

/* ==========================================================================
   9. App shell — CSS Grid, zero JS
   ==========================================================================

   Two independent scroll containers (.shell-sidebar, .shell-main), each with
   native overflow-y: auto, sized once by grid track definitions instead of
   inspinia.js's fix_height() height-matching hack + slimScroll fake
   scrollbars + the body-class margin/position-fixed combinatorics. See
   doc/ui-analysis/04-app-shell-and-scrolling.md §1-2 for the root-cause
   analysis and target markup this implements.

   Responsive sidebar states (tablet icon rail, phone off-canvas drawer) and
   the shell.js toggle are a later phase (doc 04 §4) — not implemented here.
   ========================================================================== */

html, body {
  height: 100dvh;
  margin: 0;
  overscroll-behavior: none; /* stop the whole page from rubber-banding */
}

.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-rows: var(--topbar-h) 1fr;
  grid-template-areas:
    "sidebar topbar"
    "sidebar main";
  height: 100dvh;
  overflow: hidden; /* the shell itself never scrolls */
}

.shell-sidebar {
  grid-area: sidebar;
  overflow-y: auto;         /* independent scroll track #1 */
  background: var(--color-surface-alt);
  border-right: 1px solid var(--color-border);
}

.sidebar-brand {
  padding: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.sidebar-user {
  display: block;
  color: var(--color-text);
}

.sidebar-user:hover,
.sidebar-user:focus {
  color: var(--color-accent);
  text-decoration: none;
}

.sidebar-logo {
  margin-top: var(--space-2);
  font-weight: 700;
  color: var(--color-accent);
}

.sidebar-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sidebar-nav li a {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  color: var(--color-text);
}

.sidebar-nav li a:hover,
.sidebar-nav li a:focus {
  background: var(--color-accent-bg);
  text-decoration: none;
}

.sidebar-nav li.active a {
  background: var(--color-accent-bg);
  color: var(--color-accent);
  font-weight: 600;
}

.sidebar-nav li.nav-section-label {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-4) var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  text-transform: uppercase;
}

.shell-topbar {
  grid-area: topbar;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  z-index: var(--z-topbar);
}

.sidebar-toggle {
  display: none; /* shown once the tablet/phone breakpoints (doc 04 §4) land */
  border: 0;
  background: transparent;
  font-size: var(--font-size-lg);
  cursor: pointer;
}

.topbar-title {
  font-weight: 600;
}

.topbar-tenant-switch {
  margin: 0;
}

.topbar-exten {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.topbar-testmode {
  background: var(--color-testmode-bg);
  color: var(--color-testmode-fg);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  font-weight: 600;
}

.topbar-logout {
  margin-left: auto;
  color: var(--color-text);
}

.shell-backdrop {
  display: none;
}

.shell-main {
  grid-area: main;
  overflow-y: auto;         /* independent scroll track #2 */
  padding: var(--space-5) var(--space-4);
  background: var(--color-bg);
}

/* Sticky table headers — a bonus this shell enables for free, because
   .shell-main is now a well-defined scroll container `th` can stick within. */
.shell-main table thead th {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--color-surface-alt);
}

/* --------------------------------------------------------------------
   9b. Sidebar states — desktop / tablet / phone
   Desktop (default, no media query): full-width sidebar, as defined above.
   See doc/ui-analysis/04-app-shell-and-scrolling.md §4.
   -------------------------------------------------------------------- */

/* Tablet: icon rail */
@media (max-width: 1024px) {
  .shell {
    grid-template-columns: var(--sidebar-w-rail) 1fr;
  }

  .shell-sidebar .nav-label,
  .shell-sidebar .sidebar-user,
  .shell-sidebar .sidebar-logo {
    display: none;
  }

  .sidebar-nav li a {
    justify-content: center;
    padding: var(--space-3) var(--space-2);
  }

  .sidebar-nav li.nav-section-label {
    display: none;
  }
}

/* Phone: off-canvas drawer */
@media (max-width: 640px) {
  .shell {
    grid-template-columns: 0 1fr; /* sidebar takes no track space */
  }

  .sidebar-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  .shell-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    z-index: var(--z-sidebar);
  }

  /* Off-canvas drawer always shows full labels, regardless of the tablet
     icon-rail rules above (they don't apply below 640px because this
     query's declarations come later in the cascade at equal specificity
     for the shared selectors, but be explicit for the ones that aren't shared). */
  .shell-sidebar .nav-label,
  .shell-sidebar .sidebar-user,
  .shell-sidebar .sidebar-logo {
    display: block;
  }

  .sidebar-nav li a {
    justify-content: flex-start;
  }

  .sidebar-nav li.nav-section-label {
    display: block;
  }

  .shell[data-sidebar-state="open"] .shell-sidebar {
    transform: translateX(0);
  }

  .shell-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: calc(var(--z-sidebar) - 1);
  }

  .shell[data-sidebar-state="open"] .shell-backdrop {
    display: block;
  }

  .shell-backdrop[hidden] {
    display: none;
  }

  /* Body scroll lock while the drawer is open (shell.js toggles this class
     on <body>; .shell-main already has its own overflow-y: auto, but the
     underlying page must not also scroll behind the drawer/backdrop). */
  body.sidebar-drawer-open {
    overflow: hidden;
  }
}

/* ==========================================================================
   10. Utilities
   HTML4 presentational attribute replacements (align/border/cellpadding/
   cellspacing/valign/width removed from templates) plus small single-purpose
   utility classes used to replace one-off inline `style="..."` attributes,
   per doc/ui-analysis/02-html-issue-catalog.md §2 and §4.
   ========================================================================== */
.valign-top {
  vertical-align: top;
}

.col-w-50 {
  width: 50px;
}

.col-w-70 {
  width: 70px;
}

.col-w-150 {
  width: 150px;
}

.col-w-300 {
  width: 300px;
}

.col-w-15p {
  width: 15%;
}

.col-w-25p {
  width: 25%;
}

.col-w-60p {
  width: 60%;
}

.col-w-10p {
  width: 10%;
}

.col-w-20p {
  width: 20%;
}

.col-w-30p {
  width: 30%;
}

.valign-middle {
  vertical-align: middle;
}

.text-white {
  color: var(--color-text-inverse);
}

.d-inline {
  display: inline;
}

.w-100 {
  width: 100%;
}

.list-unpadded {
  padding: 0;
}

.checkbox-label-gap {
  padding-left: 5px;
}

/* ==========================================================================
   11. Components — extracted from one-off inline `style="..."` attributes
   per doc/ui-analysis/02-html-issue-catalog.md §4. Grouped by the template
   pattern they replace rather than one class per occurrence.
   ========================================================================== */

/* Bordered fixed-width option/param inputs (editivr.tpl, editsip.tpl) */
.input-w-36-bordered {
  width: 36px;
  border: 1px solid black;
}

/* Light divider border around member/available list panes (editqueue.tpl) */
.panel-border-light {
  border: 1px solid #e6e6e6;
}

/* Tinted row/column backgrounds (editsla.tpl) */
.bg-floralwhite {
  background-color: floralwhite;
}

.bg-aliceblue {
  background-color: aliceblue;
}

/* Full-width edit-form header (editsla.tpl): title left, action buttons
   (Speichern/Löschen/Abbrechen) embedded right, in ONE bar that stays
   pinned while the form content scrolls underneath (QA feedback R3, c97).
   Sticky is relative to the nearest scrolling ancestor, so the same rule
   works inside the overlay dialog.panel (overflow-y: auto) and on the
   plain full page. */
.edit-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  position: sticky;
  top: 0;
  z-index: 10;
}

.edit-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* Button action row (Abbrechen/Löschen/Speichern) for edit-screen forms.
   Bug fix (browser QA, c72): these buttons used to sit in a `pull-right`
   (float:right) div. Since `.form-horizontal .form-group` became a flex
   container (13c), float has no effect on that div (a flex item's used
   float is always 'none'), so the buttons fell back to plain inline-block
   flow and staggered/wrapped against the following section instead of
   forming one right-aligned row. Replaces the float with a flex row;
   apply alongside the existing col-md-* sizing classes on the button
   container div (e.g. `col-md-offset-2 col-md-10 form-actions`), in place
   of `pull-right`. */
.form-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
}

/* Scrollable summary box shown in a modal (index.tpl, slas.tpl) */
.summary-scroll-box {
  height: 300px;
  overflow-y: auto;
  overflow-x: hidden;
  text-align: left;
}

/* Wide modal used for the tenant create/edit dialogs (tenant.tpl) */
.modal-xl-custom {
  width: 90%;
  max-width: 1200px;
}

.modal-body-scrollable {
  max-height: 70vh;
  overflow: auto;
}

.modal-body-scrollable-60 {
  max-height: 60vh;
  overflow: auto;
}

.modal-dialog-80 {
  width: 80%;
}

.modal-dialog-top-20 {
  margin-top: 20vh;
}

.modal-content-centered-pad {
  text-align: center;
  padding: 30px 0;
}

/* Small helper text under a form field (tenant.tpl) */
.help-small {
  margin-top: 2px;
  display: block;
}

.form-group-mt {
  margin-top: 20px;
}

/* Right-aligned, width-capped search box above a table (rag.tpl) */
.question-search-input {
  max-width: 500px;
  margin-left: auto;
}

.icon-spinner-lg {
  font-size: 2.5em;
}

.save-msg {
  margin-top: 15px;
  font-size: 1.2em;
}

/* VIP / supervisor status icons (slas.tpl) */
.star-icon,
.sup-icon {
  color: #1ab394;
}

/* Ad-hoc "loading calls" spinner box built via JS .html() (slas.tpl) */
.spinner-box-200 {
  height: 200px;
}

/* Manual "copy link" fallback modal built via JS innerHTML (editsip.tpl) —
   plain unstyled markup outside Bootstrap's component CSS, so these classes
   carry the full presentation themselves. */
.copy-link-input {
  width: 100%;
  padding: 8px;
  margin: 10px 0;
}

.modal-actions-right {
  text-align: right;
  margin-top: 15px;
}

.btn-modal-close {
  padding: 8px 16px;
}

/* Login logo — centers the block-level image regardless of ancestor
   text-align (replaces a no-op `align-self` on a non-flex parent). */
.login-logo {
  display: block;
  margin: 0 auto;
}

/* ==========================================================================
   12. Component library — doc/ui-analysis/07-component-library.md
   Reusable, TBS-compatible components shared across screens (card c30).
   These are additive to Bootstrap 3/INSPINIA, not a replacement — see the
   doc for the exact TBS markup each class pairs with. Migrating the 13
   list pages onto `.data-list` (c31) and the unified confirm `<dialog>`
   (c32) are separate, later passes; `.data-list` and the confirm dialog
   have since landed (12b, 12h) — only wide report tables/pagination (§12
   of the doc) remain forward-looking.
   ========================================================================== */

/* --- 12a. Page header (§2) ------------------------------------------------ */
.page-header-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.page-header-title {
  margin: 0;
  font-size: var(--font-size-lg);
}

.page-header-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* --- 12b. .data-list — table/card twin (§3) ------------------------------
   `.data-list-container` is the container-query scope; `.data-list-head`
   and `.data-list-row` share the same grid column count so the two stay
   aligned. Set `--data-list-cols` inline on `.data-list` per page (column
   count = number of `[r.*]` fields), default 4. Below the container's
   640px breakpoint the grid collapses into a stacked card per row, with
   `[data-label]::before` injecting the column header text. */
.data-list-container {
  container-type: inline-size;
  container-name: data-list;
}

.data-list {
  --data-list-cols: 4;
  display: grid;
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.data-list-head,
.data-list-row {
  display: grid;
  grid-template-columns: repeat(var(--data-list-cols), minmax(0, 1fr));
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
}

.data-list-head {
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  font-weight: 600;
  border-bottom: 1px solid var(--color-border);
}

.data-list-row {
  color: var(--color-text);
  border-bottom: 1px solid var(--color-border);
  text-decoration: none;
}

.data-list-row:last-child {
  border-bottom: 0;
}

.data-list-row:hover,
.data-list-row:focus {
  background: var(--color-accent-bg);
  text-decoration: none;
}

.data-list-row [role="cell"] {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.data-list-row [data-label]::before {
  content: none; /* only injected on phone, see the container query below */
}

/* Phone twin: cards instead of grid columns */
@container data-list (max-width: 640px) {
  .data-list-head {
    display: none;
  }

  .data-list {
    display: block;
    background: transparent;
    border: 0;
    border-radius: 0;
  }

  .data-list-row {
    display: block;
    grid-template-columns: none;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-3);
    padding: var(--space-3) var(--space-4);
  }

  .data-list-row [role="cell"] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-1) 0;
    overflow: visible;
    white-space: normal;
    text-align: right;
  }

  .data-list-row [data-label]::before {
    content: attr(data-label);
    flex-shrink: 0;
    margin-right: auto;
    color: var(--color-text-muted);
    font-weight: 600;
    text-align: left;
  }
}

/* --- 12c. Form row (§4) --------------------------------------------------- */
.form-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.form-row-label {
  flex: 0 0 180px;
  padding-top: var(--space-2);
  font-weight: 600;
}

.form-row-control {
  flex: 1 1 auto;
  min-width: 0;
}

@media (max-width: 640px) {
  .form-row {
    flex-direction: column;
    gap: var(--space-1);
  }

  .form-row-label {
    flex-basis: auto;
    padding-top: 0;
  }
}

/* --- 12d. Status pill (§9) ------------------------------------------------
   Class contract only — `latency_class` is computed server-side (PHP),
   never in TBS logic. Palette mirrors the existing INSPINIA
   success/warning/danger labels so it reads as consistent. */
.status-pill {
  display: inline-block;
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--font-size-sm);
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
}

.status-pill-green {
  background: #e3f6ee;
  color: var(--color-success);
}

.status-pill-orange {
  background: #fbf1de;
  color: var(--color-warning);
}

.status-pill-red {
  background: var(--color-danger-bg);
  color: var(--color-danger);
}

/* --- 12e. Empty state (§10) ------------------------------------------------ */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-7) var(--space-4);
  text-align: center;
  color: var(--color-text-muted);
}

.empty-state-icon {
  font-size: 2.5rem;
  line-height: 1;
}

.empty-state-message {
  margin: 0 0 var(--space-2) 0;
}

/* --- 12f. Search / filter bar (§11) ---------------------------------------- */
.list-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}

.list-filter-bar .form-control {
  max-width: 320px;
}

/* multi-input server-side filter forms (e.g. supcalls) sit in the same
   bar; bootstrap's .form-group bottom margin breaks the flex row */
.list-filter-bar .form-group {
  margin: 0;
}

/* --- 12g. Toast (§8) -------------------------------------------------------
   JS-generated only (see js/suhos/toast.js) — no TBS markup, pure runtime
   feedback stacked bottom-right, above the panel/modal z-index layers. */
.toast-stack {
  position: fixed;
  right: var(--space-5);
  bottom: var(--space-5);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-width: 320px;
}

.toast {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-2);
  color: var(--color-text-inverse);
  font-size: var(--font-size-sm);
  animation: suhos-toast-in 0.15s ease-out,
             suhos-toast-out 0.3s ease-in 2.7s forwards;
}

.toast-success {
  background: var(--color-success);
}

.toast-error {
  background: var(--color-danger);
}

@keyframes suhos-toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes suhos-toast-out {
  to {
    opacity: 0;
  }
}

/* --- 12h. Confirm dialog (§7) -----------------------------------------
   Native <dialog> — replaces the SweetAlert-based delete_button.js and
   the never-wired Bootstrap .modal in delete_modal.tpl (c32). Markup:
   delete_modal.tpl; JS: js/suhos/confirm-dialog.js. */
.confirm-dialog {
  box-sizing: border-box;
  width: 100%;
  max-width: 400px;
  padding: var(--space-5);
  border: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  color: var(--color-text);
}

.confirm-dialog::backdrop {
  background: rgba(0, 0, 0, 0.45);
}

.confirm-dialog-icon {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-lg);
  color: var(--color-warning);
  text-align: center;
}

.confirm-dialog-title {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-lg);
  text-align: center;
}

.confirm-dialog-body {
  margin: 0 0 var(--space-4);
  color: var(--color-text-muted);
  text-align: center;
}

.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

/* --- 12i. Opening-hours grid / day-accordion (settings.php, c50) ----------
   doc/ui-analysis/06-mobile-responsive-spec.md — "settings.php opening-hours
   grid → day-accordion". Single markup, single MergeBlock('open', …), no
   duplicate <input> elements (that would double-submit the array-style
   open_day[]/open_from[]/... names the settings.php POST handler indexes
   positionally — a correctness risk the spec's own duplicate-markup snippet
   doesn't account for). Instead: one native <details class="oh-day"> per
   day, `block=details` attached to open.day_name. `>=640px` forces the
   details body open via CSS (overriding the native [open] gate) and
   flattens the details/summary/body wrappers with `display:contents` so
   the day name + 4 field labels become plain CSS Grid cells aligned under
   .oh-header — visually the same grid the old <table> gave. `<640px` lets
   native <details>/<summary> behave as a real accordion, one day open at a
   time is not enforced (each is independent, like the old table rows),
   summary shows the day name + a read-only "from–to" preview of the AM
   hours so the collapsed row is still informative. */
.oh-table {
  width: 100%;
}

.oh-header {
  display: none;
}

.oh-day {
  border-bottom: 1px solid var(--color-border);
}

.oh-day:last-child {
  border-bottom: 0;
}

.oh-day-summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  cursor: pointer;
  list-style: none;
}

.oh-day-summary::-webkit-details-marker {
  display: none;
}

.oh-day-summary::after {
  content: "\25BE"; /* ▾ */
  margin-left: auto;
  color: var(--color-text-muted);
  transition: transform 0.15s ease;
}

.oh-day[open] > .oh-day-summary::after {
  transform: rotate(-180deg);
}

.oh-day-name {
  font-weight: 600;
}

.oh-day-hours {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.oh-day-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 0 0 var(--space-3);
}

.oh-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-weight: 400;
}

.oh-field-label {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.oh-field input {
  width: 100%;
}

/* Desktop/tablet: force every day open and lay the flattened day-name + 4
   field cells out as a grid aligned under .oh-header, i.e. the old table. */
@media (min-width: 640px) {
  .oh-table {
    display: grid;
    grid-template-columns: minmax(120px, 160px) repeat(4, minmax(80px, 1fr));
    column-gap: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-4);
  }

  .oh-header {
    display: contents;
  }

  .oh-col-day,
  .oh-col {
    padding: var(--space-2) 0;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: 600;
    border-bottom: 1px solid var(--color-border);
  }

  /* Unwrap <details>/<summary>/<div> so their children become direct grid
     cells; !important is required to beat the UA rule that hides a closed
     details' body (`details:not([open]) > *:not(summary){display:none}`). */
  .oh-day,
  .oh-day-summary,
  .oh-day-body {
    display: contents !important;
  }

  .oh-day-summary::after {
    content: none;
  }

  .oh-day-hours {
    display: none;
  }

  .oh-day-name,
  .oh-field {
    align-self: center;
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border);
  }

  .oh-day-name {
    font-weight: 400;
  }

  .oh-field {
    flex-direction: row;
    align-items: center;
  }

  .oh-field-label {
    display: none;
  }
}

/* --- 12j. Wide report tables — column priority + row expansion (c53) -----
   doc/ui-analysis/06-mobile-responsive-spec.md "Wide report tables
   (index/calls/supcalls/recordings)". Applies to calls.tpl and
   recordings.tpl (`table.report-table`): each `<th>`/`<td>` pair carries a
   `data-priority` attribute (1 = always visible, 2 = tablet+, 3 =
   desktop-only) and every row's `tr.row-main` is immediately followed, in
   the same `MergeBlock(...,'tbody')` repeat unit, by a hidden `tr.row-detail`
   listing the columns that priority hiding removes at the current
   breakpoint — toggled by js/suhos/row-expand.js via the `[data-row-toggle]`
   button in the row's first cell. index.tpl uses DataTables' own Responsive
   extension instead (columns.responsivePriority) — see index.tpl's inline
   script — so it needs no rules here beyond the vendored
   dataTables.responsive css already linked on that page. supcalls.tpl
   already satisfies this requirement via the `.data-list` twin (12b): its
   phone card shows every field with no hiding, so no expansion mechanism is
   needed there. */
[data-priority] {
  transition: none;
}

@media (max-width: 639px) {
  .report-table [data-priority="2"],
  .report-table [data-priority="3"] {
    display: none;
  }
}

@media (min-width: 640px) and (max-width: 1023px) {
  .report-table [data-priority="3"] {
    display: none;
  }
}

.row-toggle {
  display: none; /* only meaningful once priority hiding removes a column */
  min-width: 28px;
  min-height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--font-size-base);
  line-height: 1;
  cursor: pointer;
}

.row-toggle span {
  display: inline-block;
  transition: transform 0.15s ease;
}

.row-main.row-expanded .row-toggle span {
  transform: rotate(90deg);
}

@media (max-width: 1023px) {
  .row-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

.row-detail td {
  background: var(--color-surface-alt);
  padding: var(--space-3) var(--space-4);
}

.row-detail-item {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--color-border);
}

.row-detail-item:last-child {
  border-bottom: 0;
}

.row-detail-label {
  color: var(--color-text-muted);
  font-weight: 600;
}

.row-detail-value {
  text-align: right;
}

/* Phone-only touch target bump for the row toggle, consistent with the
   spec's "Touch & viewport hygiene" 44px minimum for interactive controls. */
@media (max-width: 639px) {
  .row-toggle {
    min-width: 44px;
    min-height: 44px;
  }
}

/* --- 12k. Queue member tap-to-move + reorder (editqueue.php, c51) ---------
   doc/ui-analysis/06-mobile-responsive-spec.md "editqueue drag-drop member
   lists → touch alternative". Replaces jQuery-UI .sortable() with a
   `.touch-controls` button row appended to every `#members li` /
   `#available li` by editqueue.js: one "move to other list" button and
   up/down reorder buttons, all real <button>s with aria-label so they stay
   keyboard-operable — a strict a11y improvement over the pointer-drag-only
   original, not just a phone accommodation. */
.touch-controls {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2, 8px);
  margin-top: var(--space-2, 8px);
}

.touch-controls button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 1px solid var(--color-border, #e6e6e6);
  border-radius: 6px;
  background: var(--color-surface, #fff);
  color: var(--color-text, #333);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.touch-controls button:hover,
.touch-controls button:focus-visible {
  background: var(--color-surface-alt, #f5f5f5);
  outline: 2px solid var(--color-primary, #1ab394);
  outline-offset: 1px;
}

.touch-controls .btn-move {
  margin-right: auto;
}

/* --- 12i. edittech routing table → route cards on phone (c52) -------------
   Honest exception per doc/ui-analysis/06-mobile-responsive-spec.md
   (edittech section): the row holds <select> elements populated/kept in
   sync entirely by edittech.js (rtypes/rcond/etc. inline data-island,
   id-keyed by [routing.$]) and is a single TBS `block=tr` repeat with no
   dynamic add/remove of rows. Per the c50 precedent (settings opening-hours
   accordion), duplicate markup was rejected here too: it would double the
   r_no[]/r_typestr[]/r_deststr[]/r_wait[]/r_condstr[] POST arrays (hidden
   inputs still submit) and corrupt saves. Instead this reshapes the SAME
   <tr>/<td> elements via a container query (per the spec's own intro
   rationale: edittech renders both full-page and inside the c41 overlay
   panel, where available width — not viewport width — decides table vs.
   card), with `data-label` driving `::before` row labels exactly like the
   `.data-list` twin (12b). No template duplication, so JS-toggled select/
   text visibility (edittech.js's updateRoutingRow) keeps working unchanged,
   and any row layout the JS ever added at runtime would inherit the same
   CSS automatically since it targets the row/cell structure, not a class
   the JS would need to add. */
.route-table-container {
  container-type: inline-size;
  container-name: route-table;
}

/* Explicit column widths for the table-form layout (>640px container width).
   Bug fix (browser QA, c72): with no `table-layout: fixed` and the header
   row's <th> carrying no width, the browser's auto table layout sized
   columns from content, not from the col-w-* classes previously stuck on
   the data row's <td> (which are ignored on rows after the first without
   fixed layout) — the "Nr." text input's default intrinsic size dominated
   while the Art/Anschluss/Sek/Bedingung selects and inputs were squeezed
   and truncated. Fixed layout + a <colgroup> (which sizes columns
   regardless of which row carries width) makes this deterministic:
   Nr. very narrow (1 digit), Art/Anschluss wide, Sek narrow (2 digits),
   Bedingung wide enough for its longest option text (e.g. "Nur intern").
   Below 640px the container query overrides table-layout with
   display:block on table/tr/td, so these widths don't apply to the card
   layout. */
.route-table {
  table-layout: fixed;
  width: 100%;
}

.route-col-no   { width: 6%; }
.route-col-type { width: 33%; }
.route-col-dest { width: 33%; }
.route-col-wait { width: 8%; }
.route-col-cond { width: 20%; }

@container route-table (max-width: 640px) {
  .route-table > tr:first-child {
    display: none;
  }

  .route-table,
  .route-table tr,
  .route-table td {
    display: block;
    width: 100%;
  }

  .route-table tr {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-3);
    padding: var(--space-3) var(--space-4);
  }

  .route-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-1) 0;
    border: 0;
  }

  .route-table td[data-label]::before {
    content: attr(data-label);
    flex-shrink: 0;
    margin-right: auto;
    color: var(--color-text-muted);
    font-weight: 600;
    text-align: left;
  }

  .route-table td .form-control,
  .route-table td select {
    max-width: 65%;
  }

  .route-table td input,
  .route-table td select {
    min-height: 44px;
  }
}

/* --- 12l. Native checkbox / radio (§7) + date-range inputs (c70) -----------
   Replaces iCheck (icheckbox_square-green/iradio_square-green): the plugin's
   markup/JS is gone (footer.tpl no longer inits `.i-checks`, and templates
   no longer wrap inputs in an icheckbox/iradio div), so this is just a
   light accent-color touch on the plain BS3 .checkbox/.radio inputs — no
   custom-drawn boxes. Also styles the two native <input type="date"> pairs
   that replaced daterangepicker (index.tpl, calendar.tpl). */
.checkbox input[type="checkbox"],
.radio input[type="radio"] {
  width: 16px;
  height: 16px;
  margin-right: var(--space-2);
  accent-color: var(--color-accent);
  vertical-align: middle;
}

.daterange-inputs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.daterange-inputs input[type="date"] {
  width: auto;
}

/* ==========================================================================
   13. Bootstrap 3 / INSPINIA compatibility layer (card c70)
   ==========================================================================

   suhos.css is now the ONLY stylesheet: css/bootstrap.min.css, css/style.css
   (INSPINIA theme), style_001.css and css/animate.css are removed (doc
   03-target-architecture.md §1/§4). This section re-implements, against the
   design tokens above, the subset of Bootstrap 3 + INSPINIA + legacy
   style_001.css class names that templates in html/*.tpl still use verbatim.
   Per doc 03: this is a reskin, not a rename — class NAMES are unchanged so
   no template markup needs editing. Coverage was driven by a grep inventory
   of every class attribute across all .tpl files under html/ (recursively) and the page .js files; anything
   below exists because at least one real screen depends on it. Visual
   fidelity to the old Bootstrap 3 / INSPINIA look is approximate by design
   (hand-authored, not a port), acceptable per doc 09 Phase 7.
   ========================================================================== */

/* --- 13a. Grid (row, col-xs-N, col-md-N, col-lg-N, offset) -------------- */

.row {
  display: flex;
  flex-wrap: wrap;
  margin-left: -15px;
  margin-right: -15px;
}

[class^="col-"],
[class*=" col-"] {
  position: relative;
  width: 100%;
  padding-left: 15px;
  padding-right: 15px;
  box-sizing: border-box;
}

/* xs: always active (mobile-first stacking) */
.col-xs-1  { flex: 0 0 8.3333%;  max-width: 8.3333%; }
.col-xs-2  { flex: 0 0 16.6667%; max-width: 16.6667%; }
.col-xs-3  { flex: 0 0 25%;      max-width: 25%; }
.col-xs-4  { flex: 0 0 33.3333%; max-width: 33.3333%; }
.col-xs-5  { flex: 0 0 41.6667%; max-width: 41.6667%; }
.col-xs-6  { flex: 0 0 50%;      max-width: 50%; }
.col-xs-7  { flex: 0 0 58.3333%; max-width: 58.3333%; }
.col-xs-8  { flex: 0 0 66.6667%; max-width: 66.6667%; }
.col-xs-9  { flex: 0 0 75%;      max-width: 75%; }
.col-xs-10 { flex: 0 0 83.3333%; max-width: 83.3333%; }
.col-xs-11 { flex: 0 0 91.6667%; max-width: 91.6667%; }
.col-xs-12 { flex: 0 0 100%;     max-width: 100%; }

/* md/lg: below their breakpoint every col-md-N and col-lg-N stacks full width
   (mirrors Bootstrap 3's mobile-first behavior — the same markup that reads
   as a 2-column form row on desktop stacks on phone without extra classes). */
@media (min-width: 768px) {
  .col-md-1  { flex: 0 0 8.3333%;  max-width: 8.3333%; }
  .col-md-2  { flex: 0 0 16.6667%; max-width: 16.6667%; }
  .col-md-3  { flex: 0 0 25%;      max-width: 25%; }
  .col-md-4  { flex: 0 0 33.3333%; max-width: 33.3333%; }
  .col-md-5  { flex: 0 0 41.6667%; max-width: 41.6667%; }
  .col-md-6  { flex: 0 0 50%;      max-width: 50%; }
  .col-md-7  { flex: 0 0 58.3333%; max-width: 58.3333%; }
  .col-md-8  { flex: 0 0 66.6667%; max-width: 66.6667%; }
  .col-md-9  { flex: 0 0 75%;      max-width: 75%; }
  .col-md-10 { flex: 0 0 83.3333%; max-width: 83.3333%; }
  .col-md-11 { flex: 0 0 91.6667%; max-width: 91.6667%; }
  .col-md-12 { flex: 0 0 100%;     max-width: 100%; }
  .col-md-offset-2 { margin-left: 16.6667%; }
}

@media (min-width: 992px) {
  .col-lg-3  { flex: 0 0 25%;      max-width: 25%; }
  .col-lg-9  { flex: 0 0 75%;      max-width: 75%; }
  .col-lg-12 { flex: 0 0 100%;     max-width: 100%; }
}

/* --- 13b. Buttons -------------------------------------------------------- */

.btn {
  display: inline-block;
  font: inherit;
  font-weight: 600;
  font-size: var(--font-size-base);
  line-height: 1.4;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  user-select: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-4);
  color: var(--color-text);
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  transition: background-color .12s ease, border-color .12s ease;
}

.btn:hover  { text-decoration: none; filter: brightness(0.97); }
.btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.btn:disabled, .btn.disabled { opacity: .55; cursor: not-allowed; }

.btn-primary {
  color: var(--color-text-inverse);
  background: var(--color-accent);
  border-color: var(--color-accent);
}
.btn-primary:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); }

.btn-default, .btn-white, .btn-secondary, .btn-outline-secondary {
  color: var(--color-text);
  background: var(--color-surface);
  border-color: var(--color-border-strong);
}
.btn-default:hover, .btn-white:hover, .btn-secondary:hover, .btn-outline-secondary:hover {
  background: var(--color-surface-alt);
}

.btn-danger {
  color: var(--color-text-inverse);
  background: var(--color-danger);
  border-color: var(--color-danger);
}
.btn-success {
  color: var(--color-text-inverse);
  background: var(--color-success);
  border-color: var(--color-success);
}
.btn-info {
  color: var(--color-text-inverse);
  background: #2f8fd1;
  border-color: #2f8fd1;
}
.btn-warning {
  color: var(--color-text-inverse);
  background: var(--color-warning);
  border-color: var(--color-warning);
}

.btn-sm { padding: var(--space-1) var(--space-3); font-size: var(--font-size-sm); }
.btn-xs { padding: 2px var(--space-2); font-size: var(--font-size-sm); }
.btn-block, .btn.block { display: block; width: 100%; }

.btn-group { display: inline-flex; }
.btn-group > .btn { border-radius: 0; margin-left: -1px; }
.btn-group > .btn:first-child { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); margin-left: 0; }
.btn-group > .btn:last-child { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }

/* Bootstrap's modal/alert "x" dismiss glyph button */
.close {
  float: right;
  border: 0;
  background: transparent;
  font-size: 21px;
  line-height: 1;
  color: var(--color-text);
  opacity: .5;
  cursor: pointer;
  padding: 0;
}
.close:hover { opacity: .8; }

/* --- 13c. Forms ---------------------------------------------------------- */

.form-control {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-2) var(--space-3);
  font-size: var(--font-size-base);
  line-height: 1.4;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}
.form-control:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-accent-bg);
}
.form-control[readonly], .form-control:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); }

.form-group {
  margin-bottom: var(--space-4);
}
.form-group::after { content: ""; display: table; clear: both; }

/* Horizontal forms (settings.tpl, tenant.tpl): Bootstrap-3 markup is
   `.form-group > label.col-md-2.control-label + div.col-md-10`. The col-md-*
   rules above only give flex sizing to children of a flex container — plain
   .form-group is a block, so historically the columns just stacked. Turn
   .form-horizontal .form-group into a row (mirrors .row) so label + field
   sit on one line on desktop, vertically centered; labels stay LEFT-aligned
   (not the old Bootstrap right-justified look). Below 640px the columns
   fall back to their default width:100% (from the [class*="col-"] rule) and
   wrap, i.e. stack on narrow screens. */
.form-horizontal .form-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin-left: -15px;
  margin-right: -15px;
}
.form-horizontal .form-group:has(.oh-table) {
  align-items: flex-start;
}
@media (min-width: 640px) {
  .form-horizontal .form-group > .col-md-2  { flex: 0 0 16.6667%; max-width: 16.6667%; }
  .form-horizontal .form-group > .col-md-10 { flex: 0 0 83.3333%; max-width: 83.3333%; }
  .form-horizontal .form-group > .col-md-offset-2 { margin-left: 16.6667%; flex: 0 0 83.3333%; max-width: 83.3333%; }
}
.form-horizontal .control-label {
  padding-top: 0;
  margin-bottom: 0;
  font-weight: 600;
  text-align: left;
}
.form-horizontal .form-group:has(.oh-table) .control-label {
  padding-top: 7px;
}
.control-label { display: inline-block; max-width: 100%; margin-bottom: var(--space-1); font-weight: 600; }

.form-inline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; }
.form-inline .form-group { margin-bottom: 0; }

.help-block { display: block; margin-top: var(--space-1); color: var(--color-text-muted); font-size: var(--font-size-sm); }

.checkbox, .radio { position: relative; display: block; margin: var(--space-2) 0; }
.checkbox label, .radio label { font-weight: normal; cursor: pointer; }

.input-group { position: relative; display: flex; width: 100%; }
.input-group .form-control { flex: 1 1 auto; width: 1%; }
.input-group-addon,
.input-group-btn {
  display: flex;
  align-items: center;
  white-space: nowrap;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-alt);
}
.input-group > .form-control:not(:first-child),
.input-group > .input-group-addon:not(:first-child),
.input-group > .input-group-btn:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-group > .form-control:not(:last-child),
.input-group > .input-group-addon:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; border-right: 0; }
.input-group-btn .btn { border-radius: 0; }
.input-group-btn:first-child .btn { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); }
.input-group-btn:last-child .btn { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }

/* --- 13d. Tables ----------------------------------------------------------
   Base look for plain `.table` markup (list pages not yet on `.data-list`,
   the components.tpl demo, DataTables-holdout screens' own <table>). */

.table {
  width: 100%;
  border-collapse: collapse;
  background: var(--color-surface);
}
.table th, .table td {
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--color-border);
  text-align: left;
  vertical-align: middle;
}
.table thead th {
  border-bottom: 2px solid var(--color-border-strong);
  background: var(--color-surface-alt);
  font-weight: 600;
}
.table-hover tbody tr:hover { background: var(--color-accent-bg); }
.table-responsive { width: 100%; overflow-x: auto; }

/* --- 13e. Alerts / error banner ------------------------------------------ */

.alert {
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
}
.alert-danger  { color: var(--color-danger); background: var(--color-danger-bg); border-color: var(--color-danger); }
.alert-warning { color: #7a5a10; background: #fdf3e0; border-color: var(--color-warning); }
.alert-info    { color: #1c5580; background: #e8f2fb; border-color: #2f8fd1; }
.alert-success { color: var(--color-success); background: #e6f7f0; border-color: var(--color-success); }

/* Legacy style_001.css .errormsg banner — used on login.tpl + all 8 edit
   forms + settings.tpl + transcribe.tpl (POST-redirect-GET error display). */
.errormsg {
  font-size: var(--font-size-lg);
  font-weight: bold;
  color: var(--color-danger);
}

/* --- 13f. Modals (Bootstrap 3 markup, native JS behind it — see
   js/suhos/modal-compat.js). Two usage patterns both land here:
     1. `$('#x').modal('show'|'hide')` (rag.tpl, tenant.tpl, slas.tpl) — driven
        by modal-compat.js's $.fn.modal shim, which toggles inline
        `display:block` exactly like plain jQuery .show()/.hide() would.
     2. Plain `$('#x').show()/.hide()` (index.tpl, moh.tpl, calendar.tpl,
        supcalendar.tpl, editsla.tpl, editsound.tpl, supcalls.tpl,
        transcribe.tpl) — these already only ever depended on jQuery core,
        never on bootstrap.js, so they need no JS change at all; they just
        need this CSS to exist. ---------------------------------------- */

.modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.5);
}
.modal.show { display: block; }
body.modal-open { overflow: hidden; }

.modal-dialog {
  position: relative;
  width: auto;
  max-width: 600px;
  margin: 30px auto;
}
.modal-dialog-centered { display: flex; align-items: center; min-height: calc(100% - 60px); margin: 30px auto; }
.modal-sm { max-width: 320px; }
.modal-lg { max-width: 800px; }
.modal-xl, .modal-xl-custom { max-width: 1100px; }
.modal-dialog-80 { max-width: 80vw; }
.modal-dialog-top-20 { margin-top: 20px; }

.modal-content {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  outline: 0;
}
.modal-content-centered-pad { padding: var(--space-5); text-align: center; }

.modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
}
.inmodal .modal-header { flex-direction: column; align-items: center; text-align: center; }
.modal-title { margin: 0; font-size: var(--font-size-lg); font-weight: 600; }
.modal-body { padding: var(--space-5); overflow-y: auto; }
.modal-body-scrollable { max-height: 60vh; overflow-y: auto; }
.modal-body-scrollable-60 { max-height: 60vh; overflow-y: auto; }
.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--color-border);
}
.modal-actions-right { display: flex; justify-content: flex-end; gap: var(--space-2); }
.btn-modal-close { margin-left: auto; }

/* Bootstrap's fade/`in` transition classes: no-op now that animate.css is
   gone — the modal simply appears/disappears via display toggling above. */
.fade, .in { opacity: 1; }

/* --- 13g. INSPINIA page/card chrome (.wrapper/.ibox family) --------------
   Still the structural wrapper around every edit-form page (all 8
   `edit*.tpl`) and the components.tpl living style guide (card c30). */

.wrapper { box-sizing: border-box; }
.wrapper-content { padding: var(--space-5) 0; }
.float-e-margins { margin-bottom: var(--space-5); }
.full-width { width: 100%; }
.content-box { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); }

.ibox {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-1);
  margin-bottom: var(--space-5);
}
.ibox-title {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface-alt);
  border-top-left-radius: var(--radius-md);
  border-top-right-radius: var(--radius-md);
}
.ibox-title h5 { margin: 0; font-size: var(--font-size-base); font-weight: 700; }
.ibox-content { padding: var(--space-4); }

.gray-bg   { background: var(--color-bg); }
.navy-bg   { background: #1a2942; color: var(--color-text-inverse); }
.blue-bg   { background: var(--color-accent); color: var(--color-text-inverse); }
.yellow-bg { background: var(--color-warning); color: var(--color-text-inverse); }

.hr-line-dashed { border-top: 1px dashed var(--color-border-strong); margin: var(--space-4) 0; }

/* Login page (login.tpl is a standalone page, not routed through header.tpl) */
.middle-box { max-width: 400px; margin: 0 auto; padding-top: 40px; }
.loginscreen { padding: var(--space-5); background: var(--color-surface); border-radius: var(--radius-md); box-shadow: var(--shadow-2); }
.login-logo { max-width: 220px; margin-bottom: var(--space-4); }

/* --- 13h. INSPINIA demo-page components still in real use ----------------
   file-manager/folder-list (moh.tpl's upload/class browser),
   agile-list/agile-detail/sortable-list (editqueue.tpl's queue-member
   reorder list — jQuery-UI Sortable still drives the interaction, out of
   scope for this card; only the visual skin is retokenized here),
   issue-tracker (compact DataTables row treatment on index.tpl/slas.tpl and
   other list screens). Retokenized from css/style.css, not deleted outright,
   per doc 03 §1 "functional, not theme" carve-out. */

.file-manager { list-style: none; margin: 0; padding: 0; }
.folder-list li { border-bottom: 1px solid var(--color-border); display: block; }
.folder-list li a { display: block; padding: var(--space-2) 0; color: var(--color-text); text-decoration: none; }
.folder-list li i { margin-right: var(--space-2); color: var(--color-text-muted); }

.sortable-list { padding: var(--space-2) 0; }
.agile-list { list-style: none; margin: 0; padding: 0; }
.agile-list li {
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  margin: 0 0 var(--space-2) 0;
  padding: var(--space-3);
}
.agile-detail { margin-top: var(--space-1); font-size: var(--font-size-sm); color: var(--color-text-muted); }

table.issue-tracker tbody tr td { vertical-align: middle; height: 50px; }

/* --- 13i. Utilities (text align, float/pull, visibility, flex, spacing) -- */

.text-center { text-align: center; }
.text-left   { text-align: left; }
.text-right  { text-align: right; }
.pull-left  { float: left; }
.pull-right { float: right; }
.clear, .clearfix::after { content: ""; display: table; clear: both; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.block { display: block; }
.d-block { display: block; }
.d-flex { display: flex; }
.justify-content-center { justify-content: center; }
.justify-content-end { justify-content: flex-end; }
.align-items-center { align-items: center; }
.font-bold { font-weight: 700; }
.img-fluid { max-width: 100%; height: auto; }
.qr-code { display: block; width: 100%; max-width: 320px; margin-inline: auto; }

@media (min-width: 1025px) {
  .hidden-desktop { display: none; }
}

/* INSPINIA spacing shorthands still referenced (m-b/m-t) alongside a few
   Bootstrap 4/5-style rem-scale utilities added more recently (mb-2/mb-3/
   my-3) — both families kept since both have live call sites. */
.m-b { margin-bottom: var(--space-5); }
.m-t { margin-top: var(--space-5); }
.m-2  { margin: 0.5rem; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-3 { margin-bottom: 1rem; }
.my-3 { margin-top: 1rem; margin-bottom: 1rem; }

/* --- 13j. Legacy style_001.css functional carryovers ---------------------
   Simple pre-data-list tables still used by calls.tpl/sip.tpl/
   recordings.tpl/slas.tpl (Phase 3 list-migration hasn't reached these
   yet) and recordings.tpl's file-link cells. */

.tablediv { position: relative; top: var(--space-3); margin-left: auto; margin-right: auto; }
.tdline { border-bottom: 1px solid var(--color-border); padding-right: var(--space-4); }
.tdnumber { border-bottom: 1px solid var(--color-border); text-align: right; padding-right: var(--space-4); }
.afile, .afile a, .afile a:visited { text-decoration: none; color: var(--color-accent); }
.afile a:hover { color: var(--color-danger); }

/* Address-import tag editor (kept verbatim from style_001.css per doc 03 §1,
   re-tokenized where it overlaps existing tokens; layout rules unchanged). */
.tag-div { width: 100%; overflow: auto; padding-right: 5px; }
.tag-title { display: flex; flex-direction: row; flex-wrap: inherit; }
.tag-title h1 { color: var(--color-text); width: 100%; align-items: center; display: flex; }
.tag-title input { width: 100%; display: flex; margin: 0; }
.tag-button {
  padding: 7px 8px 7px 12px;
  background-color: var(--color-surface-alt);
  display: inline-flex;
  border-radius: var(--radius-pill);
  align-items: center;
  cursor: pointer;
  min-height: 20px;
  border: none;
  font-size: var(--font-size-sm);
  font-weight: 500;
  text-align: left;
  line-height: 1.125;
}
.tag-button:hover { background-color: var(--color-border-strong); }
.tag-button-disabled { cursor: not-allowed; }
.tag-icon {
  width: 18px !important;
  height: 18px !important;
  font-size: 18px;
  display: inline-block;
  opacity: 0.4;
  cursor: pointer;
  margin-left: var(--space-2);
}
.tag-button i { float: right; margin-right: 6px; }
.tag-button i:hover { cursor: pointer; }
.tag-updownload { color: var(--color-text-muted); }
.tag-input-new { width: 100%; padding: 0; margin: var(--space-3) 0 0; }

/* address-import contact list (contact-name/phone-number) */
.contact-name { cursor: pointer; text-decoration: none; }
.phone-number { color: var(--color-text-inverse); font-weight: bold; cursor: pointer; }

/* Phone hover tooltip (index.tpl/supcalls.tpl click-to-call) */
.phonetip {
  position: fixed;
  color: #fff;
  background-color: #676a6c;
  border: 1px solid #000;
  padding: var(--space-3);
  border-radius: 7px;
  font-size: 14px;
  z-index: var(--z-dropdown);
  width: 400px;
  height: 90px;
}

/* Loading spinner (rag.tpl document processing) */
.spinner {
  border: 4px solid var(--color-surface-alt);
  border-top: 4px solid var(--color-accent);
  border-radius: 50%;
  width: 20px;
  height: 20px;
  animation: suhos-spin 1s linear infinite;
  margin: 10px auto;
}
.spinner-border {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--color-border-strong);
  border-right-color: var(--color-accent);
  border-radius: 50%;
  animation: suhos-spin .75s linear infinite;
}
@keyframes suhos-spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* FullCalendar 3 month-view row height override (calendar.tpl/supcalendar.tpl) */
.fc-dayGridMonth-view .fc-daygrid-body tr { height: 30px !important; }

/* clockpicker popover — was `z-index: 999999 !important` in style_001.css;
   re-skinned against the shared z-index scale per doc 03 §2. */
.clockpicker-popover { z-index: var(--z-dropdown); }

/* --- 13k. Simple CSS-only animation replacements for animate.css --------- */

.animated { animation-duration: .3s; animation-fill-mode: both; }
@keyframes suhos-fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes suhos-fadeInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }
@keyframes suhos-fadeInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
.fadeIn { animation-name: suhos-fadeIn; }
.fadeInDown { animation-name: suhos-fadeInDown; }
.fadeInRight { animation-name: suhos-fadeInRight; }

/* --- 14. KI Gesprächsprotokoll overlay (index.tpl #summary_modal) --------
   Three-card overlay (Call Details / Summary / Transcript) with a sticky
   header (title + hovering nav pills on a rule) and a single scrolling
   content panel below it. See doc/ui-analysis for the card spec (Anrufdetails
   tpl block etc — glob patterns for other template dirs are intentionally
   not referenced in this comment). */

/* Right-side overlay panel — STRUCTURALLY IDENTICAL to the proven-working
   edit-form overlay `dialog.panel` in suhos-panel.css (used by editsla.php /
   slas.php). A native <dialog> opened with .showModal(): renders in the browser
   top layer, full height, with a ::backdrop for dimming and native ESC +
   backdrop-click close. The whole dialog scrolls (overflow-y: auto) and the
   header is `position: sticky` so it stays visible — same model as dialog.panel.
   Deliberately does NOT set `display` on the dialog (that would beat the UA
   `dialog:not([open])` rule and render on page load). */
.protocol-panel {
  box-sizing: border-box;
  position: fixed;
  inset: 0 0 0 auto;        /* right-aligned, full height */
  margin: 0;
  width: 66vw;              /* 2/3 of viewport — matches dialog.panel (editsla) */
  max-width: 66vw;
  height: 100vh;
  max-height: 100vh;
  border: none;
  padding: 0;
  overflow-y: auto;         /* whole panel scrolls; header sticks (see below) */
  background: var(--color-bg);   /* cards float on page-grey; bare area below
                                    short content is the dialog itself, so a
                                    click there closes too (e.target === dlg) */
  color: var(--color-text);
  box-shadow: var(--shadow-3);
  z-index: var(--z-modal);
  animation: protocol-slide-in 0.22s ease-out;
}

.protocol-panel::backdrop {
  background: rgba(0, 0, 0, 0.35);
}

@keyframes protocol-slide-in {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}

.protocol-header {
  position: sticky;         /* stays visible while the dialog body scrolls */
  top: 0;
  z-index: 1;
  background: var(--color-surface);
  padding: var(--space-4) var(--space-5) 0;
  border-bottom: none;
  text-align: left;
}

.protocol-header .modal-title {
  margin: 0;
  padding-right: var(--space-6);
  font-size: var(--font-size-lg);
  color: var(--color-text);
}

.protocol-close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-4);
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
  line-height: 1;
  cursor: pointer;
  padding: var(--space-1);
}

.protocol-close:hover {
  color: var(--color-accent);
}

.protocol-navbar {
  position: relative;
  margin-top: var(--space-3);
  height: var(--space-5);
}

.protocol-navline {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  border-top: 1px solid var(--color-border);
}

.protocol-nav {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  gap: var(--space-2);
  background: transparent;
}

.protocol-nav-btn {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  cursor: pointer;
  white-space: nowrap;
}

.protocol-nav-btn:hover {
  color: var(--color-accent);
  border-color: var(--color-border-strong);
}

.protocol-nav-btn.is-active {
  color: var(--color-accent);
  border-color: var(--color-accent);
  background: var(--color-accent-bg);
}

.protocol-body {
  padding: var(--space-5);
  /* transparent so any bare dialog area below short content reads as one
     surface; the dialog element (not this div) is the scroll container. */
}

.protocol-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-1);
  margin-bottom: var(--space-5);
}

.protocol-card:last-child {
  margin-bottom: 0;
}

.protocol-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.protocol-card-head h5 {
  margin: 0;
  font-size: var(--font-size-base);
  color: var(--color-text);
}

.protocol-copy {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: var(--space-1);
  font-size: var(--font-size-base);
}

.protocol-copy:hover {
  color: var(--color-accent);
}

.protocol-card-body {
  padding: var(--space-4);
}

.protocol-detail {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-1) 0;
  font-size: var(--font-size-base);
}

.protocol-detail-label {
  min-width: 140px;
  flex: 0 0 auto;
  color: var(--color-text-muted);
}

.protocol-detail-value {
  color: var(--color-text);
}

.protocol-transcript {
  white-space: pre-wrap;
  font-family: var(--font-sans);
  margin: 0;
  color: var(--color-text);
}

@media (max-width: 640px) {
  .protocol-panel { width: 100vw; max-width: 100vw; }
  .protocol-nav { flex-wrap: wrap; }
  .protocol-nav-btn { font-size: var(--font-size-sm); }
}
