﻿/* ==========================================================================
   Konima Support — knm-theme.css
   Tema admin per Bootstrap 5.3+
   · Tutte le variabili custom usano il prefisso  --knm-theme-*
   · Tutte le classi di estensione/override usano il prefisso  .knm-t-*
   · Modalità chiaro/scuro via [data-bs-theme="light|dark"]
   · Colore accento via [data-knm-accent="…"]: i preset sono nella sezione «Preset colore accento», la sola fonte
     dei colori (knm-theme.js, i campioni delle impostazioni e i grafici li leggono da qui)
   · Densità: i livelli sono della libreria (KNM.RazorComponents #319, token --knm-density-*); questo file
     dà solo i valori di Tickets per livello e i token del template --knm-theme-gap/-card-pad/-cell-pad-*
   · Dimensione testo via --knm-theme-font-size (impostata su <html>)
   ========================================================================== */

/* --------------------------------------------------------------------------
   1 · TOKEN DI BASE (tipografia, geometrie, densità)
   -------------------------------------------------------------------------- */
/* .knm-appearance-preview__portal: the «Aspetto» preview carries an organization's colours on its own root, so the
   accent's derived values below are computed there too, not inherited from the page (appearance-templates). */
:root,
.knm-appearance-preview__portal {
  /* Tipografia */
  --knm-theme-font-size: 16px;
  --knm-theme-font-body: "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --knm-theme-font-display: "Sora", var(--knm-theme-font-body);
  --knm-theme-font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  /* Geometrie */
  --knm-theme-radius: 12px;
  --knm-theme-radius-sm: 8px;
  --knm-theme-sidebar-w: 264px;
  --knm-theme-topbar-h: 60px;

  /* KNM.RazorComponents KNMDataGrid: every grid's .WithStickyHeader() pins its <thead> at `top: 0`.
     .knm-t-topbar below is ALSO position:sticky/top:0 but at z-index 1020 vs the grid header's z-index 2,
     so without an offset the topbar paints over the grid header during scroll. Derived from
     --knm-theme-topbar-h (not a separate literal) so the two cannot drift apart. */
  --knm-grid-sticky-offset: var(--knm-theme-topbar-h);

  /* Accento: i valori (riempimento, testo sopra, testo leggibile, seconda serie) sono dei preset più sotto; il
     default arancio è il preset "orange", applicato anche a :root. Qui solo i derivati. */
  --knm-theme-accent-hover: color-mix(in oklab, var(--knm-theme-accent), #000 14%);
  --knm-theme-accent-soft: color-mix(in oklab, var(--knm-theme-accent), transparent 90%);
  --knm-theme-accent-border: color-mix(in oklab, var(--knm-theme-accent), transparent 65%);
  /* Opaque, low-chroma wash of the accent — the "off" half of a two-state control (a switch's track, an idle
     rail) where --knm-theme-accent-soft is too transparent to read as a filled shape. Defined per surface
     polarity in section 2: on a light ground it is the accent lightened, on a dark one the accent darkened.
     Declared here as a fallback so the token always resolves even before section 2 is reached. */
  --knm-theme-accent-muted: color-mix(in oklab, var(--knm-theme-accent), #fff 62%);
  /* The accent on the rules that draw it as a heading or an active label (the 404, the active tab, a hub's icon): the
     readable text of every preset and of an organization's accent, because the fill as text is 1.33:1 for yellow on
     the light page. Declared on :root, where that token already follows the theme. */
  --knm-theme-accent-label: var(--knm-theme-accent-text);

  /* Series colours of canvas-drawn charts (KNMChart / Chart.js, which cannot resolve a var()): knm-theme.js reads them
     computed and hands them to the chart. Series 1 is the accent as text (readable on the page's surface, light or
     dark); series 2 is set by every accent preset below, always a hue far from that accent (ChartPaletteCssTests pins
     at least 60 degrees), so two series never read as one; an organization's block (TenantThemeCss) sets its own under
     the same rule, because its series 1 follows the organization. Plain hex: the chart takes hex and rgb() only. */
  --knm-theme-chart-1: var(--knm-theme-accent-text);
}

/* Densità (ui-density-adoption, KNM.RazorComponents #319). The levels, the tokens and the size of every Auto control
   are the library's; these four rules only give Tickets' values per level (once, nowhere else: DensityEngineGuardTests)
   and the template's own spacing. Normal = today's Tickets look; compact and airy = Tickets' values where it had
   them, the library's otherwise. Buttons shift one step (Corrado, 16/10): normal = today's Small, airy = today's
   Medium at airy. The normal rule names [data-knm-density="normal"] too: the router's scope can be at normal inside an
   <html> painted at another level, and a value declared on :root alone would reach it inherited from <html>.
   No --knm-density-control-font-size at normal (the library's 1rem), 1rem at the other two: the text size is the
   person's own slider, density changes spacing, never type. No chip token: the library's chips take their size from
   the size map (DensityRegistration), not from --knm-density-chip-*. */
:root, [data-knm-density="normal"] {
  --knm-density-btn-padding-y: .27rem;          /* .btn-sm normal (.45 × .6) */
  --knm-density-btn-padding-x: .75rem;          /* .btn-sm normal */
  --knm-density-btn-font-size: .8125rem;        /* .btn-sm */
  --knm-density-card-spacer-y: 1.25rem;         /* today's card padding */
  --knm-density-card-spacer-x: 1.25rem;
  --knm-density-control-padding-y: .45rem;      /* today's field padding */
  --knm-density-control-padding-x: .75rem;
  --knm-theme-gap: 1.25rem;
  --knm-theme-cell-pad-y: .7rem;                /* .knm-t-table only */
  --knm-theme-cell-pad-x: .75rem;
}
[data-knm-density="compact"] {
  --knm-density-btn-padding-y: .192rem;         /* .btn-sm compact (.32 × .6) */
  --knm-density-btn-padding-x: .6rem;
  --knm-density-btn-font-size: .8125rem;
  --knm-density-card-spacer-y: .9rem;
  --knm-density-card-spacer-x: .9rem;
  --knm-density-control-padding-y: .32rem;
  --knm-density-control-padding-x: .6rem;
  --knm-density-control-font-size: 1rem;
  --knm-density-row-height: 2.125rem;           /* 34px, walk-fixes-1016 */
  --knm-density-cell-padding-y: .3rem;
  --knm-density-cell-padding-x: .6rem;
  --knm-theme-gap: .8rem;
  --knm-theme-cell-pad-y: .42rem;
  --knm-theme-cell-pad-x: .6rem;
}
[data-knm-density="airy"] {
  --knm-density-btn-padding-y: .6rem;           /* .btn airy */
  --knm-density-btn-padding-x: 1.08rem;         /* .btn airy (.9 × 1.2) */
  --knm-density-btn-font-size: .875rem;         /* .btn */
  --knm-density-card-spacer-y: 1.75rem;
  --knm-density-card-spacer-x: 1.75rem;
  --knm-density-control-padding-y: .6rem;
  --knm-density-control-padding-x: .9rem;
  --knm-density-control-font-size: 1rem;
  --knm-density-row-height: 3.25rem;            /* 52px, walk-fixes-1016 */
  --knm-density-cell-padding-y: .8rem;
  --knm-density-cell-padding-x: 1rem;
  --knm-theme-gap: 1.75rem;
  --knm-theme-cell-pad-y: 1rem;
  --knm-theme-cell-pad-x: 1rem;
}
/* One number for KNMCard and the template's .knm-t-card-pad; re-declared on every element that carries a level, because
   a var() is resolved where it is declared. */
:root, [data-knm-density] {
  --knm-theme-card-pad: var(--knm-density-card-spacer-y);
}

/* Preset colore accento (CTO 03/11: più colori, più accesi, il giallo col nero). The ONLY place the accent colours
   live: knm-theme.js lists the names, the settings swatches paint themselves with these variables, charts read them.
   Each preset gives, and ChartPaletteCssTests pins:
   · --knm-theme-accent            the fill (buttons, chips, switches, the swatch);
   · --knm-theme-accent-contrast   text on that fill, white or near-black, 4.5:1 or better (-invert: 1 when white,
                                   0 when dark, for an icon inverted with a filter);
   · --knm-accent-text-on-light    the accent as TEXT on the light surfaces (links, active values), 4.5:1 or better, also
                                   on the accent's own tint and on a tint over a tint (a mention in one's own message);
   · --knm-accent-text-on-dark     the same on the dark surfaces; section 2 maps the right one to --knm-theme-accent-text;
   · --knm-theme-chart-2           the second chart series, 60 degrees of hue or more from the fill.
   A new preset adds one line here, its name in knm-theme.js and UserPreferenceRules.Accents, and its label in RESX.
   "orange" is also :root, the default before the script runs. */
:root, [data-knm-accent="orange"] { --knm-theme-accent: #f97316; --knm-theme-accent-rgb: 249, 115, 22; --knm-theme-accent-contrast: #111827; --knm-theme-accent-contrast-invert: 0;
  --knm-accent-text-on-light: #ae3a0b; --knm-accent-text-on-light-rgb: 174, 58, 11;
  --knm-accent-text-on-dark: #fb923c; --knm-accent-text-on-dark-rgb: 251, 146, 60; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="yellow"] { --knm-theme-accent: #facc15; --knm-theme-accent-rgb: 250, 204, 21; --knm-theme-accent-contrast: #111827; --knm-theme-accent-contrast-invert: 0;
  --knm-accent-text-on-light: #854d0e; --knm-accent-text-on-light-rgb: 133, 77, 14;
  --knm-accent-text-on-dark: #facc15; --knm-accent-text-on-dark-rgb: 250, 204, 21; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="red"] { --knm-theme-accent: #dc2626; --knm-theme-accent-rgb: 220, 38, 38; --knm-theme-accent-contrast: #ffffff; --knm-theme-accent-contrast-invert: 1;
  --knm-accent-text-on-light: #b11b1b; --knm-accent-text-on-light-rgb: 177, 27, 27;
  --knm-accent-text-on-dark: #f87171; --knm-accent-text-on-dark-rgb: 248, 113, 113; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="pink"] { --knm-theme-accent: #db2777; --knm-theme-accent-rgb: 219, 39, 119; --knm-theme-accent-contrast: #ffffff; --knm-theme-accent-contrast-invert: 1;
  --knm-accent-text-on-light: #af1656; --knm-accent-text-on-light-rgb: 175, 22, 86;
  --knm-accent-text-on-dark: #f472b6; --knm-accent-text-on-dark-rgb: 244, 114, 182; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="violet"] { --knm-theme-accent: #7c3aed; --knm-theme-accent-rgb: 124, 58, 237; --knm-theme-accent-contrast: #ffffff; --knm-theme-accent-contrast-invert: 1;
  --knm-accent-text-on-light: #6d28d9; --knm-accent-text-on-light-rgb: 109, 40, 217;
  --knm-accent-text-on-dark: #a78bfa; --knm-accent-text-on-dark-rgb: 167, 139, 250; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="indigo"] { --knm-theme-accent: #4f46e5; --knm-theme-accent-rgb: 79, 70, 229; --knm-theme-accent-contrast: #ffffff; --knm-theme-accent-contrast-invert: 1;
  --knm-accent-text-on-light: #4338ca; --knm-accent-text-on-light-rgb: 67, 56, 202;
  --knm-accent-text-on-dark: #818cf8; --knm-accent-text-on-dark-rgb: 129, 140, 248; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="blue"] { --knm-theme-accent: #2563eb; --knm-theme-accent-rgb: 37, 99, 235; --knm-theme-accent-contrast: #ffffff; --knm-theme-accent-contrast-invert: 1;
  --knm-accent-text-on-light: #1d4ed8; --knm-accent-text-on-light-rgb: 29, 78, 216;
  --knm-accent-text-on-dark: #60a5fa; --knm-accent-text-on-dark-rgb: 96, 165, 250; --knm-theme-chart-2: #16a34a; }
[data-knm-accent="sky"] { --knm-theme-accent: #0ea5e9; --knm-theme-accent-rgb: 14, 165, 233; --knm-theme-accent-contrast: #111827; --knm-theme-accent-contrast-invert: 0;
  --knm-accent-text-on-light: #03669d; --knm-accent-text-on-light-rgb: 3, 102, 157;
  --knm-accent-text-on-dark: #38bdf8; --knm-accent-text-on-dark-rgb: 56, 189, 248; --knm-theme-chart-2: #ea580c; }
[data-knm-accent="teal"] { --knm-theme-accent: #14b8a6; --knm-theme-accent-rgb: 20, 184, 166; --knm-theme-accent-contrast: #111827; --knm-theme-accent-contrast-invert: 0;
  --knm-accent-text-on-light: #0e6e67; --knm-accent-text-on-light-rgb: 14, 110, 103;
  --knm-accent-text-on-dark: #2dd4bf; --knm-accent-text-on-dark-rgb: 45, 212, 191; --knm-theme-chart-2: #7c3aed; }
[data-knm-accent="green"] { --knm-theme-accent: #22c55e; --knm-theme-accent-rgb: 34, 197, 94; --knm-theme-accent-contrast: #111827; --knm-theme-accent-contrast-invert: 0;
  --knm-accent-text-on-light: #166534; --knm-accent-text-on-light-rgb: 22, 101, 52;
  --knm-accent-text-on-dark: #4ade80; --knm-accent-text-on-dark-rgb: 74, 222, 128; --knm-theme-chart-2: #2563eb; }

/* --------------------------------------------------------------------------
   2 · SUPERFICI — modalità chiara e scura
   -------------------------------------------------------------------------- */
:root,
[data-bs-theme="light"] {
  --knm-theme-accent-text: var(--knm-accent-text-on-light);
  --knm-theme-accent-text-rgb: var(--knm-accent-text-on-light-rgb);
  --knm-theme-bg: #f6f5f3;
  --knm-theme-surface: #ffffff;
  --knm-theme-surface-2: #f1efec;
  --knm-theme-border: #e7e4df;
  --knm-theme-border-strong: #d7d3cc;
  --knm-theme-text: #1d1b18;
  --knm-theme-text-muted: #74706a;
  --knm-theme-shadow: 0 1px 2px rgb(28 25 20 / .05), 0 4px 14px rgb(28 25 20 / .04);
  --knm-theme-shadow-lg: 0 24px 60px rgb(28 25 20 / .25);
  --knm-theme-sidebar-bg: #171511;
  /* The sidebar is dark in both themes, so it always takes the dark-surface text, whatever the theme's own text is. */
  --knm-theme-sidebar-accent: var(--knm-accent-text-on-dark);
  --knm-theme-sidebar-border: #2b2823;
  --knm-theme-sidebar-text: #b9b4ac;
  --knm-theme-sidebar-heading: #7c776e;
  --knm-theme-accent-muted: color-mix(in oklab, var(--knm-theme-accent), #fff 62%);
}
[data-bs-theme="dark"] {
  --knm-theme-accent-text: var(--knm-accent-text-on-dark);
  --knm-theme-accent-text-rgb: var(--knm-accent-text-on-dark-rgb);
  --knm-theme-bg: #121110;
  --knm-theme-surface: #1b1917;
  --knm-theme-surface-2: #242220;
  --knm-theme-border: #2d2a27;
  --knm-theme-border-strong: #3b3733;
  --knm-theme-text: #edeae6;
  --knm-theme-text-muted: #99948d;
  --knm-theme-shadow: 0 1px 2px rgb(0 0 0 / .35), 0 4px 14px rgb(0 0 0 / .25);
  --knm-theme-shadow-lg: 0 24px 60px rgb(0 0 0 / .5);
  --knm-theme-sidebar-bg: #0e0d0b;
  --knm-theme-sidebar-border: #262420;
  --knm-theme-sidebar-text: #aaa59d;
  --knm-theme-sidebar-heading: #6e6961;
  /* Darkened, not lightened: on the dark surfaces above, the light-mode wash would out-glare the ACTIVE state
     it is supposed to sit under. */
  --knm-theme-accent-muted: color-mix(in oklab, var(--knm-theme-accent), #000 52%);
}

/* Person colours (CTO 29/10): twelve hues that belong to people only, picked by AvatarPalette.HueClass from the
   person's id. None is the accent, the red of an error or the yellow of a warning, and each carries white initials at
   4.5:1 or better; the same values work on the dark surfaces. */
:root {
  --knm-person-hue-0: #2563eb;
  --knm-person-hue-1: #0e7490;
  --knm-person-hue-2: #0f766e;
  --knm-person-hue-3: #15803d;
  --knm-person-hue-4: #4d7c0f;
  --knm-person-hue-5: #a16207;
  --knm-person-hue-6: #9a3412;
  --knm-person-hue-7: #9f1239;
  --knm-person-hue-8: #a21caf;
  --knm-person-hue-9: #6d28d9;
  --knm-person-hue-10: #4338ca;
  --knm-person-hue-11: #475569;
}

/* --------------------------------------------------------------------------
   3 · MAPPATURA SU BOOTSTRAP
   -------------------------------------------------------------------------- */
:root,
[data-bs-theme="light"],
[data-bs-theme="dark"] {
  --bs-body-bg: var(--knm-theme-bg);
  --bs-body-color: var(--knm-theme-text);
  --bs-border-color: var(--knm-theme-border);
  --bs-secondary-color: var(--knm-theme-text-muted);
  --bs-font-monospace: var(--knm-theme-font-mono);
  --bs-secondary-bg: var(--knm-theme-surface-2);
  --bs-tertiary-bg: var(--knm-theme-surface-2);
  --bs-emphasis-color: var(--knm-theme-text);
  --bs-primary: var(--knm-theme-accent);
  --bs-primary-rgb: var(--knm-theme-accent-rgb);
  --bs-link-color: var(--knm-theme-accent-text);
  --bs-link-hover-color: var(--knm-theme-accent-text);
  --bs-link-color-rgb: var(--knm-theme-accent-text-rgb);
  --bs-link-hover-color-rgb: var(--knm-theme-accent-text-rgb);
  --bs-body-font-family: var(--knm-theme-font-body);
  --bs-border-radius: var(--knm-theme-radius-sm);
}

html { font-size: var(--knm-theme-font-size, 16px); }

body {
  font-family: var(--knm-theme-font-body);
  background-color: var(--knm-theme-bg);
  color: var(--knm-theme-text);
  font-size: .9375rem;
  letter-spacing: .005em;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6, .knm-t-display {
  font-family: var(--knm-theme-font-display);
  letter-spacing: -.015em;
}

/* Pulsanti */
/* Sizes go through Bootstrap's variables, never padding/font-size directly: .btn-sm and .btn-lg only change
   the variables, so a direct value would make them do nothing (issue #161).
   ui-density-adoption: an Auto KNMButton takes the --knm-density-btn-* tokens through the library's adapter at compact
   and airy (0,2,0, it beats these two), and at normal its size map gives it .btn-sm. .btn follows the level through the
   library's control token (plain class="btn" elements, an explicit Medium); an explicit Small stays Small at every
   level (the library's contract), so .btn-sm is fixed. */
.btn {
  --bs-btn-border-radius: var(--knm-theme-radius-sm);
  --bs-btn-font-weight: 600;
  --bs-btn-font-size: .875rem;
  --bs-btn-padding-y: var(--knm-density-control-padding-y);
  --bs-btn-padding-x: calc(var(--knm-density-control-padding-x) * 1.2);
}
.btn-sm {
  --bs-btn-font-size: .8125rem;
  --bs-btn-padding-y: .27rem;
  --bs-btn-padding-x: .75rem;
}
.btn-primary {
  --bs-btn-bg: var(--knm-theme-accent);
  --bs-btn-border-color: var(--knm-theme-accent);
  --bs-btn-color: var(--knm-theme-accent-contrast);
  --bs-btn-hover-bg: var(--knm-theme-accent-hover);
  --bs-btn-hover-border-color: var(--knm-theme-accent-hover);
  --bs-btn-hover-color: var(--knm-theme-accent-contrast);
  --bs-btn-active-bg: var(--knm-theme-accent-hover);
  --bs-btn-active-border-color: var(--knm-theme-accent-hover);
  --bs-btn-active-color: var(--knm-theme-accent-contrast);
  --bs-btn-disabled-bg: var(--knm-theme-accent);
  --bs-btn-disabled-border-color: var(--knm-theme-accent);
  --bs-btn-focus-shadow-rgb: var(--knm-theme-accent-rgb);
}
/* An outline button is text and border on the page surface, so it takes the accent as TEXT (readable on light and dark
   for every preset), never the fill: the yellow fill on white is 1.5:1 (CTO 03/11, «sui gialli c'è da lavorare»). */
.btn-outline-primary {
  --bs-btn-color: var(--knm-theme-accent-text);
  --bs-btn-border-color: color-mix(in oklab, var(--knm-theme-accent-text), transparent 55%);
  --bs-btn-hover-bg: var(--knm-theme-accent-soft);
  --bs-btn-hover-color: var(--knm-theme-accent-text);
  --bs-btn-hover-border-color: var(--knm-theme-accent-text);
  --bs-btn-active-bg: var(--knm-theme-accent);
  --bs-btn-active-color: var(--knm-theme-accent-contrast);
  --bs-btn-active-border-color: var(--knm-theme-accent);
  --bs-btn-focus-shadow-rgb: var(--knm-theme-accent-rgb);
}
/* Bootstrap's outline warning and info are #ffc107 and #0dcaf0 on the surface: 1.6:1 and 1.8:1 on white. The grid's
   edit pencil is an outline warning, so on a light theme it was barely there. They take Bootstrap's own
   *-text-emphasis colours, which it defines per light/dark theme; the filled active state keeps the bright colour with
   dark text. */
.btn-outline-warning {
  --bs-btn-color: var(--bs-warning-text-emphasis);
  --bs-btn-border-color: color-mix(in oklab, var(--bs-warning-text-emphasis), transparent 55%);
  --bs-btn-hover-bg: var(--bs-warning-bg-subtle);
  --bs-btn-hover-color: var(--bs-warning-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-warning-text-emphasis);
  --bs-btn-active-bg: var(--bs-warning);
  --bs-btn-active-color: #111827;
  --bs-btn-active-border-color: var(--bs-warning);
}
.btn-outline-info {
  --bs-btn-color: var(--bs-info-text-emphasis);
  --bs-btn-border-color: color-mix(in oklab, var(--bs-info-text-emphasis), transparent 55%);
  --bs-btn-hover-bg: var(--bs-info-bg-subtle);
  --bs-btn-hover-color: var(--bs-info-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-info-text-emphasis);
  --bs-btn-active-bg: var(--bs-info);
  --bs-btn-active-color: #111827;
  --bs-btn-active-border-color: var(--bs-info);
}
.text-primary { color: var(--knm-theme-accent-text) !important; }
.btn-outline-secondary {
  --bs-btn-color: var(--knm-theme-text);
  --bs-btn-bg: var(--knm-theme-surface);
  --bs-btn-border-color: var(--knm-theme-border-strong);
  --bs-btn-hover-bg: var(--knm-theme-surface-2);
  --bs-btn-hover-color: var(--knm-theme-text);
  --bs-btn-hover-border-color: var(--knm-theme-border-strong);
  --bs-btn-active-bg: var(--knm-theme-surface-2);
  --bs-btn-active-color: var(--knm-theme-text);
  --bs-btn-active-border-color: var(--knm-theme-border-strong);
}
/* Form. --knm-theme-control-font-size is the text size of a field; .knm-switch-beside (custom.css) derives a field's
   height from it, so the two cannot drift apart. */
:root { --knm-theme-control-font-size: .9rem; }
.form-label { font-size: .8125rem; font-weight: 700; margin-bottom: .35rem; }
.form-text { color: var(--knm-theme-text-muted); font-size: .78rem; }
.form-control, .form-select {
  background-color: var(--knm-theme-surface);
  border-color: var(--knm-theme-border-strong);
  border-radius: var(--knm-theme-radius-sm);
  color: var(--knm-theme-text);
  font-size: var(--knm-theme-control-font-size);
  padding: var(--knm-density-control-padding-y) var(--knm-density-control-padding-x);
}
.form-control::placeholder { color: var(--knm-theme-text-muted); opacity: .8; }
.form-control:focus, .form-select:focus {
  background-color: var(--knm-theme-surface);
  color: var(--knm-theme-text);
  border-color: var(--knm-theme-accent);
  box-shadow: 0 0 0 3px var(--knm-theme-accent-soft);
}
.form-check-input:checked {
  background-color: var(--knm-theme-accent);
  border-color: var(--knm-theme-accent);
}
.form-check-input:focus {
  border-color: var(--knm-theme-accent);
  box-shadow: 0 0 0 3px var(--knm-theme-accent-soft);
}
.form-range::-webkit-slider-thumb { background: var(--knm-theme-accent); }
.form-range::-moz-range-thumb { background: var(--knm-theme-accent); }

/* Dropdown — since KNM.RazorComponents 3.19 the panels of KNMSelect, KNMMenu and the grid column chooser
   carry .knm-dropdown-panel instead of Bootstrap's .dropdown-menu, so both are themed here. */
.dropdown-menu,
.knm-dropdown-panel {
  --bs-dropdown-bg: var(--knm-theme-surface);
  --bs-dropdown-border-color: var(--knm-theme-border);
  --bs-dropdown-link-color: var(--knm-theme-text);
  --bs-dropdown-link-hover-bg: var(--knm-theme-surface-2);
  --bs-dropdown-link-hover-color: var(--knm-theme-text);
  --bs-dropdown-link-active-bg: var(--knm-theme-accent);
  border-radius: 10px;
  box-shadow: var(--knm-theme-shadow);
  font-size: .875rem;
  padding: .35rem;
}
.dropdown-item { border-radius: 7px; padding: .4rem .6rem; }
/* 3.19 dropped its fade-in from Bootstrap's own menus (the user menu): kept here with the same timing. */
.dropdown-menu.show { animation: knm-t-menu-fade-in .15s ease; }
@keyframes knm-t-menu-fade-in { from { opacity: 0; transform: scale(.95); } to { opacity: 1; transform: scale(1); } }

/* Paginazione */
.pagination {
  --bs-pagination-bg: var(--knm-theme-surface);
  --bs-pagination-color: var(--knm-theme-text-muted);
  --bs-pagination-border-color: var(--knm-theme-border);
  --bs-pagination-hover-bg: var(--knm-theme-surface-2);
  --bs-pagination-hover-color: var(--knm-theme-text);
  --bs-pagination-hover-border-color: var(--knm-theme-border);
  --bs-pagination-focus-bg: var(--knm-theme-surface-2);
  --bs-pagination-focus-color: var(--knm-theme-text);
  --bs-pagination-active-bg: var(--knm-theme-accent);
  --bs-pagination-active-border-color: var(--knm-theme-accent);
  --bs-pagination-disabled-bg: var(--knm-theme-surface);
  --bs-pagination-disabled-color: var(--knm-theme-border-strong);
  --bs-pagination-disabled-border-color: var(--knm-theme-border);
  --bs-pagination-focus-box-shadow: 0 0 0 3px var(--knm-theme-accent-soft);
}
.page-link { font-size: .85rem; font-weight: 600; }

/* Offcanvas */
.offcanvas {
  --bs-offcanvas-bg: var(--knm-theme-surface);
  --bs-offcanvas-color: var(--knm-theme-text);
  --bs-offcanvas-border-color: var(--knm-theme-border);
}

/* --------------------------------------------------------------------------
   4 · LAYOUT APPLICATIVO
   -------------------------------------------------------------------------- */
.knm-t-app { display: flex; min-height: 100vh; }
.knm-t-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* The content column of the shell. TWO mechanisms live here and NEITHER replaces the other — do not delete
   one believing the other covers it:

   1. Bootstrap's .container-fluid (carried by <main> in MainLayout.razor) owns the WIDTH and the HORIZONTAL
      padding. It reads --bs-gutter-x, set here to twice the theme step so the shell keeps its own rhythm
      instead of Bootstrap's 1.5rem default (.container-fluid applies gutter-x * .5 per side).
   2. `flex: 1 0 auto` owns the HEIGHT. .knm-t-main is a flex column of header / main / footer; without a
      grow factor <main> is sized to its content, so on a short page the content box stops early and the
      remaining column height belongs to nobody. Bootstrap's container classes govern width, never height —
      adopting them does not make this line redundant.

   align-content is pinned to `start` BECAUSE of (2): this is also a grid container (.knm-t-grid) whose rows
   are implicit and auto-sized, and the initial `align-content: normal` behaves as `stretch` for grid. Once
   <main> is taller than its content, stretch would inflate a single card to the full viewport height. */
.knm-t-content {
  --bs-gutter-x: calc(var(--knm-theme-gap) * 2.6);
  flex: 1 0 auto;
  align-content: start;
  padding-top: calc(var(--knm-theme-gap) * 1.3);
  padding-bottom: calc(var(--knm-theme-gap) * 1.3);
}
/* .knm-t-content is a grid container (.knm-t-grid, below) with a single implicit auto-sized column.
   Per the CSS Grid spec, a grid item's automatic minimum size defaults to min-width: auto — i.e. its
   min-content size — which lets an unshrinkable child (e.g. a wide, non-wrapping data grid table) blow
   out the track and overflow the shell instead of shrinking with the viewport. Scoped to direct children
   of .knm-t-content only, so it does not touch .knm-t-card (or anything else) nested elsewhere — e.g.
   inside .knm-t-cols-* columns or flex rows — where the default min-content floor is not a problem. */
.knm-t-content > * { min-width: 0; }

.knm-t-grid { display: grid; gap: var(--knm-theme-gap); }
.knm-t-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.knm-t-cols-detail { grid-template-columns: minmax(0, 1fr) 340px; }
.knm-t-cols-settings { grid-template-columns: 230px minmax(0, 1fr); align-items: start; }
@media (max-width: 1199.98px) {
  .knm-t-cols-detail { grid-template-columns: 1fr; }
}
@media (max-width: 767.98px) {
  .knm-t-cols-2, .knm-t-cols-settings { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   5 · SIDEBAR (scura)
   -------------------------------------------------------------------------- */
.knm-t-sidebar {
  background-color: var(--knm-theme-sidebar-bg) !important;
  color: var(--knm-theme-sidebar-text);
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--knm-theme-sidebar-border);
}
@media (min-width: 992px) {
  .knm-t-sidebar {
    width: var(--knm-theme-sidebar-w) !important;
    flex: 0 0 var(--knm-theme-sidebar-w);
    position: sticky;
    top: 0;
    height: 100vh;
  }
}
@media (max-width: 991.98px) {
  .knm-t-sidebar { --bs-offcanvas-width: var(--knm-theme-sidebar-w); }
}
.knm-t-sidebar-brand {
  display: flex;
  align-items: center;
  gap: .7rem;
  /* No vertical padding (CTO 03/11, «questo incrocio di linee»): 1rem above and below plus the 30px mark made the brand
     63px tall against the topbar's 60, so its bottom line sat 3px under the topbar's. The min-height centres the mark
     and both lines meet. */
  padding: 0 1.15rem;
  border-bottom: 1px solid var(--knm-theme-sidebar-border);
  color: #fff;
  font-family: var(--knm-theme-font-display);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: -.01em;
  min-height: var(--knm-theme-topbar-h);
}
.knm-t-sidebar-brand em { font-style: normal; font-weight: 400; color: var(--knm-theme-sidebar-text); }
/* The brand mark (BrandLogo): always an image, the organization's logo or the product icon (CTO 27/10/2026). */
.knm-brand-logo {
  width: 30px; height: 30px;
  border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
}
.knm-t-sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: .9rem .8rem;
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Scroll stays functional, but the scrollbar is hidden (Firefox + legacy Edge). */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
/* WebKit/Blink (Chrome, Edge, Safari): hide the sidebar-nav scrollbar too. */
.knm-t-sidebar-nav::-webkit-scrollbar { width: 0; height: 0; display: none; }
.knm-t-nav-section {
  font-size: .67rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--knm-theme-sidebar-heading);
  padding: .95rem .75rem .4rem;
}
.knm-t-navlink {
  position: relative;
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .48rem .75rem;
  border-radius: 8px;
  font-size: .875rem;
  font-weight: 600;
  color: var(--knm-theme-sidebar-text);
  text-decoration: none;
  background: none;
  border: 0;
  width: 100%;
  text-align: left;
}
.knm-t-navlink i { font-size: 1rem; width: 1.15rem; text-align: center; opacity: .9; }
.knm-t-navlink:hover { color: #fff; background: rgb(255 255 255 / .05); }
.knm-t-navlink.active { color: #fff; background: rgb(255 255 255 / .07); }
.knm-t-navlink.active::before {
  content: "";
  position: absolute;
  left: -8px;
  top: 22%;
  bottom: 22%;
  width: 3px;
  border-radius: 99px;
  background: var(--knm-theme-sidebar-accent, var(--knm-theme-accent));
}
/* The sidebar is dark in both themes, so the icon takes the dark-surface text: section 2 maps the token for a preset, and
   TenantThemeCss computes it for an organization's accent. */
.knm-t-navlink.active i { color: var(--knm-theme-sidebar-accent, var(--knm-theme-accent-text)); opacity: 1; }
.knm-t-sidebar-footer {
  padding: .8rem;
  border-top: 1px solid var(--knm-theme-sidebar-border);
  display: flex;
  flex-direction: column;
  gap: .35rem;
}
.knm-t-sidebar-user {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .4rem .45rem;
  border-radius: 8px;
}
.knm-t-sidebar-user-name { color: #fff; font-size: .85rem; font-weight: 600; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.knm-t-sidebar-user-role { font-size: .72rem; color: var(--knm-theme-sidebar-heading); }
.knm-t-sidebar .knm-t-iconbtn { color: var(--knm-theme-sidebar-text); }
.knm-t-sidebar .knm-t-iconbtn:hover { color: #fff; background: rgb(255 255 255 / .07); border-color: transparent; }

/* --------------------------------------------------------------------------
   6 · TOPBAR
   -------------------------------------------------------------------------- */
.knm-t-topbar {
  min-height: var(--knm-theme-topbar-h);
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: 0 calc(var(--knm-theme-gap) * 1.3);
  background: var(--knm-theme-surface);
  border-bottom: 1px solid var(--knm-theme-border);
  position: sticky;
  top: 0;
  z-index: 1020;
}
.knm-t-pagetitle {
  font-family: var(--knm-theme-font-display);
  font-size: 1rem;
  font-weight: 600;
  margin: 0;
  letter-spacing: -.01em;
}
.knm-t-breadcrumb { font-size: .8125rem; color: var(--knm-theme-text-muted); display: flex; align-items: center; gap: .4rem; }
.knm-t-breadcrumb a { color: var(--knm-theme-text-muted); text-decoration: none; }
.knm-t-breadcrumb a:hover { color: var(--knm-theme-accent-text); }
/* RazorComponents 3.34 made its --knm-breadcrumb-* colours apply (the old selector never matched), and its link rule
   (.knm-breadcrumb-wrapper .breadcrumb-item a) outranks ours above, so every link of the path turned accent. Feed the
   library the same look through its variables: muted links, accent on hover, muted current item (Valerio, 19/10). */
.knm-breadcrumb-wrapper {
  --knm-breadcrumb-color: var(--knm-theme-text-muted);
  --knm-breadcrumb-hover-color: var(--knm-theme-accent-text);
  --knm-breadcrumb-active-color: var(--knm-theme-text-muted);
  --knm-breadcrumb-separator-color: var(--knm-theme-text-muted);
}

.knm-t-iconbtn {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--knm-theme-text-muted);
  font-size: 1.02rem;
  padding: 0;
  flex-shrink: 0;
  text-decoration: none;
}
.knm-t-iconbtn:hover { background: var(--knm-theme-surface-2); color: var(--knm-theme-text); border-color: var(--knm-theme-border); }

/* Icone visibili solo in un tema (toggle chiaro/scuro) */
[data-bs-theme="light"] .knm-only-dark { display: none; }
[data-bs-theme="dark"] .knm-only-light { display: none; }

/* --------------------------------------------------------------------------
   7 · CARD, TABELLE, COMPONENTI
   -------------------------------------------------------------------------- */
.knm-t-card {
  background: var(--knm-theme-surface);
  border: 1px solid var(--knm-theme-border);
  border-radius: var(--knm-theme-radius);
  box-shadow: var(--knm-theme-shadow);
}
.knm-t-card-pad { padding: var(--knm-theme-card-pad); }
.knm-t-card-head {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: calc(var(--knm-theme-card-pad) * .75) var(--knm-theme-card-pad);
  border-bottom: 1px solid var(--knm-theme-border);
}
.knm-t-card-title { font-family: var(--knm-theme-font-display); font-size: .95rem; font-weight: 600; margin: 0; letter-spacing: -.01em; }
.knm-t-card-foot {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: calc(var(--knm-theme-card-pad) * .7) var(--knm-theme-card-pad);
  border-top: 1px solid var(--knm-theme-border);
}

.knm-t-table { width: 100%; margin: 0; border-collapse: collapse; }
.knm-t-table th {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--knm-theme-text-muted);
  padding: calc(var(--knm-theme-cell-pad-y) * .9) var(--knm-theme-cell-pad-x);
  border-bottom: 1px solid var(--knm-theme-border);
  white-space: nowrap;
  text-align: left;
}
.knm-t-table td {
  padding: var(--knm-theme-cell-pad-y) var(--knm-theme-cell-pad-x);
  border-bottom: 1px solid var(--knm-theme-border);
  vertical-align: middle;
  font-size: .875rem;
}
.knm-t-table tbody tr:last-child td { border-bottom: 0; }
.knm-t-table tbody tr { transition: background-color .1s; }
.knm-t-table tbody tr:hover { background: rgba(var(--knm-theme-accent-rgb), .10); }
.knm-t-rowtitle { color: var(--knm-theme-text); font-weight: 600; text-decoration: none; }
.knm-t-rowtitle:hover { color: var(--knm-theme-accent-text); }
.knm-t-subtext { font-size: .76rem; color: var(--knm-theme-text-muted); }

.knm-t-id {
  font-family: var(--knm-theme-font-mono);
  font-size: .76rem;
  color: var(--knm-theme-text-muted);
  white-space: nowrap;
}

/* Chip / tag. .knm-appearance-value is the text-size readout: the theme script writes its text, so it stays a plain span
   (a KNMChip keeps its text in an inner node, and the script would overwrite the whole chip). */
.knm-t-chip,
.knm-appearance-value {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  font-size: .74rem;
  font-weight: 600;
  padding: .22em .65em;
  border-radius: 99px;
  background: var(--knm-theme-surface-2);
  border: 1px solid var(--knm-theme-border);
  color: var(--knm-theme-text-muted);
  white-space: nowrap;
}
.knm-t-chip-accent {
  background: var(--knm-theme-accent-soft);
  border-color: var(--knm-theme-accent-border);
  color: var(--knm-theme-accent-text);
}
.knm-t-chip-warn {
  background: color-mix(in oklab, #d97706, transparent 89%);
  border-color: color-mix(in oklab, #d97706, transparent 60%);
  color: color-mix(in oklab, #d97706, var(--knm-theme-text) 25%);
}

/* Punto di presenza */
.knm-t-dot { width: 8px; height: 8px; border-radius: 99px; display: inline-block; background: var(--knm-theme-border-strong); flex-shrink: 0; }
.knm-t-dot-online { background: #16a34a; }
.knm-t-dot-away { background: #d97706; }
.knm-t-dot-offline { background: #dc2626; }

/* Statistiche */
.knm-t-stat-label {
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--knm-theme-text-muted);
}
.knm-t-stat-value {
  font-family: var(--knm-theme-font-display);
  font-size: 1.7rem;
  font-weight: 600;
  letter-spacing: -.025em;
  line-height: 1.2;
}
.knm-t-stat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: var(--knm-theme-accent-soft);
  color: var(--knm-theme-accent-text);
  font-size: 1.3rem;
  flex-shrink: 0;
}

/* Grafico a barre (solo CSS) */
.knm-t-bars {
  display: grid;
  grid-template-columns: repeat(14, 1fr);
  gap: 7px;
  align-items: end;
  height: 168px;
}
.knm-t-bar {
  border-radius: 4px;
  background: color-mix(in oklab, var(--knm-theme-accent), transparent 30%);
  min-height: 6px;
  transition: background-color .12s;
}
.knm-t-bar:hover, .knm-t-bar:last-child { background: var(--knm-theme-accent); }
.knm-t-bars-labels {
  display: grid;
  grid-template-columns: repeat(14, 1fr);
  gap: 7px;
  margin-top: .55rem;
  font-family: var(--knm-theme-font-mono);
  font-size: .65rem;
  color: var(--knm-theme-text-muted);
  text-align: center;
}

/* Barre di ripartizione */
.knm-t-meter {
  height: 6px;
  border-radius: 99px;
  background: var(--knm-theme-surface-2);
  overflow: hidden;
}
.knm-t-meter > span {
  display: block;
  height: 100%;
  border-radius: 99px;
  background: var(--knm-status, var(--knm-theme-accent));
}

/* --------------------------------------------------------------------------
   8 · TAB, TOOLBAR
   -------------------------------------------------------------------------- */
.knm-tv-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }

/* --------------------------------------------------------------------------
   9 · CONVERSAZIONE TICKET
   -------------------------------------------------------------------------- */
.knm-t-thread { display: flex; flex-direction: column; gap: var(--knm-theme-gap); }
.knm-t-msg { display: flex; gap: .8rem; }
.knm-t-msg-body { flex: 1; min-width: 0; }
.knm-t-msg-head { display: flex; align-items: baseline; gap: .55rem; margin-bottom: .35rem; flex-wrap: wrap; }
.knm-t-msg-author { font-weight: 700; font-size: .865rem; }
.knm-t-msg-time { font-size: .73rem; color: var(--knm-theme-text-muted); }
.knm-t-msg-bubble {
  background: var(--knm-theme-surface);
  border: 1px solid var(--knm-theme-border);
  border-radius: var(--knm-theme-radius);
  padding: calc(var(--knm-theme-card-pad) * .75) var(--knm-theme-card-pad);
  font-size: .885rem;
  line-height: 1.65;
}
.knm-t-msg-bubble p:last-child { margin-bottom: 0; }
/* A text/plain article body — everything written before the rich-text composer, plus every mail that carried a
   text part — is rendered by ArticleBody inside a bare <p>, and a <p> collapses every run of whitespace: a reply
   typed on four lines, or a quoted email, arrived on screen as one run-on paragraph. pre-wrap keeps the author's
   line breaks and indentation while still wrapping at the bubble's edge. break-word so an unbroken URL cannot
   widen the thread column.
   Scoped with :not() so it never reaches a text/html body: that one carries its own <p> elements, where pre-wrap
   would turn the source formatting of the markup into blank lines on screen. */
.knm-t-msg-bubble > p { white-space: pre-wrap; overflow-wrap: break-word; }

/* A text/html article body (ArticleBody's sanitized branch). The allow-list admits p, div, br, span, b/strong,
   i/em, u, ul/ol/li and a — nothing that carries its own spacing — so the only rules needed here are the ones
   that keep author markup inside the bubble's typography and inside its width. */
.knm-article-html { overflow-wrap: break-word; }
.knm-article-html > :last-child { margin-bottom: 0; }
.knm-article-html p { margin-bottom: .6rem; }
.knm-article-html ul, .knm-article-html ol { margin-bottom: .6rem; padding-left: 1.35rem; }
.knm-article-html a { overflow-wrap: anywhere; }
/* An image pasted into a message (portal-gaps #18) is stored at its own size: a screenshot is wider than the
   thread column and ran under the details card. Scaled down to the bubble, never up. */
.knm-t-msg-bubble img { max-width: 100%; height: auto; }

/* The two switches under a message (ArticleBody): «Mostra messaggio completo» / «Mostra meno» and the trailing
   notice's «Mostra testo completo» / «Nascondi». A quiet secondary text button, like the page's other inline actions
   (Corrado, 05/11: not the accent-coloured link it was): muted text, the theme's text colour on hover and focus.
   A small negative margin keeps the label flush with the message's left edge while the ghost keeps its hover tint. */
.knm-article-toggle.knm-button { color: var(--knm-theme-text-muted); margin-left: -.5rem; margin-top: .25rem; }
.knm-article-toggle.knm-button:hover,
.knm-article-toggle.knm-button:focus-visible { color: var(--knm-theme-text); }
/* Trailing boilerplate (WP6): a confidentiality/GDPR notice or "received this message in error" text collapsed
   behind the toggle above, muted and left-bordered like a quote rather than more of the message. */
.knm-article-tail {
  margin-top: .5rem;
  padding: .5rem .75rem;
  border-left: 2px solid var(--knm-theme-border);
  color: var(--knm-theme-text-muted);
  font-size: .9em;
}
/* A plain-text tail (ArticleBody's escaped branch) sits two levels below .knm-t-msg-bubble —
   bubble > .knm-article-tail > p — so the bubble's own direct-child pre-wrap rule above does not
   reach it. Same rule, scoped one level deeper, for the same reason: a multi-line notice must not collapse
   into one run-on paragraph once expanded. (An HTML tail needs no equivalent: it wraps in .knm-article-html,
   which already carries its own spacing via p/ul/ol margins above.) */
.knm-article-tail > p { white-space: pre-wrap; overflow-wrap: break-word; }
/* On paper the notice comes back. The tail is hidden with the `hidden` attribute, which also takes it out of
   find-in-page, of a selection over the thread and of the printed page — acceptable on screen, where the
   toggle is one click away, and wrong on a print-out, where there is nothing to click. A printed ticket
   therefore carries the whole message, and the toggle, now a dead control, does not print. */
@media print {
  .knm-article-tail[hidden] { display: block !important; }
  .knm-article-toggle { display: none; }
}
.knm-t-msg-agent .knm-t-msg-bubble {
  border-color: var(--knm-theme-accent-border);
  background: color-mix(in oklab, var(--knm-theme-accent), var(--knm-theme-surface) 95%);
}
.knm-t-msg-note .knm-t-msg-bubble {
  border-color: color-mix(in oklab, #d97706, transparent 60%);
  background: color-mix(in oklab, #d97706, var(--knm-theme-surface) 93%);
}
/* A message already sits in a card: its text needs no second frame. */
.knm-ticket-msg .knm-t-msg-bubble,
.knm-ticket-msg.knm-t-msg-agent .knm-t-msg-bubble,
.knm-ticket-msg.knm-t-msg-note .knm-t-msg-bubble {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
}
/* «Attività» toolbar on one line: filters, search, order. KNMFilterBox renders its field first, so the box is the grid. */
.knm-ticket-activity {
  display: grid;
  grid-template-columns: auto minmax(10rem, 1fr) auto;
  gap: .75rem;
  align-items: center;
}
.knm-ticket-activity > * { grid-column: 1 / -1; min-width: 0; }
.knm-ticket-activity > .knm-field { grid-area: 1 / 2; margin: 0; }
.knm-ticket-toolbar { display: contents; }
.knm-ticket-toolbar > .btn-group { grid-area: 1 / 1; }
.knm-ticket-toolbar > .btn { grid-area: 1 / 3; }
.knm-ticket-toolbar > .btn { white-space: nowrap; }
/* Where the section is narrower than the one-line toolbar needs (a phone, and the ticket's left column next to the
   sidebar on a laptop: five filters since «Allegati» joined them, 05/11), the filters take the first row whole, each
   button sharing the width (a long label wraps inside its button); the search and the order share the second row.
   Measured on the section, not the window, because the column's width depends on the layout around it. */
.knm-ticket-activity-host { container-type: inline-size; }
@container (max-width: 47.99rem) {
  .knm-ticket-activity { grid-template-columns: 1fr auto; }
  .knm-ticket-toolbar > .btn-group { grid-area: 1 / 1 / 2 / -1; display: flex; }
  .knm-ticket-toolbar > .btn-group > .btn { flex: 1 1 0; min-width: 0; padding-left: .35rem; padding-right: .35rem; }
  .knm-ticket-activity > .knm-field { grid-area: 2 / 1; }
  .knm-ticket-toolbar > .btn { grid-area: 2 / 2; }
}
/* The ticket's values read the same whether they can be changed or not: a clickable value keeps no button padding, so
   chips, names and dates share one right edge and one row height. */
.knm-ticket-values .knm-t-proprow { min-height: 2rem; }
.knm-ticket-values .knm-t-proprow .btn,
.knm-ticket-values .form-text .btn {
  padding: 0;
  border: 0;
  background: transparent;
  font-size: inherit;
}
.knm-ticket-values .knm-t-proprow .btn:hover { opacity: .75; }
.knm-ticket-values .form-text { margin-top: -.35rem; }
::highlight(tickets-search) {
  background-color: var(--bs-warning);
  color: var(--bs-dark);
}
/* An internal note reads as yellow where it is read or written: its block and the editor body. */
.knm-ticket-note .card,
.knm-ticket-note .knm-rte__content {
  background: var(--bs-warning-bg-subtle);
}
.knm-ticket-note.knm-t-card { border-color: var(--bs-warning); }
/* Collapsed attachment picker (AttachmentComposer). A link-styled row, not a button: it opens a section of
   the same card rather than performing an action. Padding is zeroed so it lines up with the fields above it. */
.knm-attach-toggle {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: 0;
  font-weight: 600;
  text-decoration: none;
  color: var(--knm-theme-text-muted);
}
.knm-attach-toggle:hover { color: var(--knm-theme-accent-text); }
.knm-attach-toggle .badge { font-size: .68rem; }
/* Bootstrap's reboot already carries [hidden]{display:none!important}, so the collapsed panel needs no rule
   of its own — only the gap for when it is open. */
.knm-attach-toggle + div { margin-top: .6rem; }

/* Article attachment chips (message thread) */
.knm-t-atts-label {
  display: block;
  margin-top: .5rem;
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--knm-theme-text-muted);
}
.knm-t-msg-atts { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .5rem; }
.knm-t-att {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .25rem .625rem;
  border: 1px solid var(--knm-theme-border-strong);
  border-radius: var(--knm-theme-radius-sm);
  background: var(--knm-theme-surface-2);
  color: var(--knm-theme-text);
  text-decoration: none;
  font-size: .8125rem;
}
.knm-t-att:hover { border-color: var(--knm-theme-accent); }
.knm-t-att-size { color: var(--knm-theme-text-muted); }

/* Timeline attività */
.knm-t-timeline {
  margin-left: 4px;
  border-left: 1px solid var(--knm-theme-border);
  display: flex;
  flex-direction: column;
  gap: 1.05rem;
  padding-left: 1rem;
}
.knm-t-tl-item { position: relative; font-size: .8rem; line-height: 1.45; }
.knm-t-tl-item::before {
  content: "";
  position: absolute;
  left: -1.31rem;
  top: .28rem;
  width: 9px; height: 9px;
  border-radius: 99px;
  background: var(--knm-theme-surface);
  border: 2px solid var(--knm-theme-border-strong);
}
.knm-t-tl-item.knm-t-tl-accent::before { border-color: var(--knm-theme-accent); }
.knm-t-tl-time { display: block; font-size: .7rem; color: var(--knm-theme-text-muted); margin-top: .1rem; }

/* Riga proprietà (dettagli ticket) */
.knm-t-proprow,
.knm-proprow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  font-size: .835rem;
  padding: .42rem 0;
}
.knm-t-proprow > span:first-child,
.knm-proprow > span:first-child { color: var(--knm-theme-text-muted); font-weight: 600; flex-shrink: 0; }

/* --------------------------------------------------------------------------
   10 · FORM AVANZATI
   -------------------------------------------------------------------------- */
.knm-t-dropzone {
  border: 1.5px dashed var(--knm-theme-border-strong);
  border-radius: var(--knm-theme-radius);
  padding: calc(var(--knm-theme-card-pad) * 1.1);
  text-align: center;
  color: var(--knm-theme-text-muted);
  background: color-mix(in oklab, var(--knm-theme-surface-2), transparent 40%);
  font-size: .85rem;
  cursor: pointer;
  transition: border-color .12s, background-color .12s;
}
.knm-t-dropzone:hover { border-color: var(--knm-theme-accent); background: var(--knm-theme-accent-soft); }
.knm-t-dropzone i { font-size: 1.4rem; display: block; margin-bottom: .35rem; }

.knm-t-switchrow {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: .8rem 0;
  border-bottom: 1px solid var(--knm-theme-border);
}
.knm-t-switchrow:last-child { border-bottom: 0; padding-bottom: 0; }
.knm-t-switchrow:first-child { padding-top: 0; }

/* --------------------------------------------------------------------------
   11 · CUSTOMIZER (pannello aspetto)
   -------------------------------------------------------------------------- */
.knm-t-customizer { --bs-offcanvas-width: 340px; }
.knm-appearance-label {
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--knm-theme-text-muted);
  margin: 1.35rem 0 .55rem;
}
.knm-appearance-label:first-child { margin-top: 0; }
/* «Menu di navigazione» (portal only, decision of 19/10) is hidden in two cases:
   - below 992 px, where the top menu does not exist (section 20) and the menu always opens from its button, so the
     choice would change nothing on a phone;
   - while the page's menu is locked to the side (knm-theme.js marks <html>): the lock comes from the document's first
     request, so after an in-circuit move to /portal the choice would change nothing until the page is reloaded.
   The options also carry .knm-seg, whose «display: flex» is one class and comes LATER in this file: a one-class rule
   here lost to it at 390 px (the title hid, the buttons stayed). The compound .knm-seg.knm-appearance-nav has two
   classes, so these rules win wherever they sit in the file. */
@media (max-width: 991.98px) {
  .knm-appearance-nav, .knm-seg.knm-appearance-nav { display: none; }
}
[data-knm-nav-locked] .knm-appearance-nav,
[data-knm-nav-locked] .knm-seg.knm-appearance-nav { display: none; }

/* Segmented control: no KNM component draws it. KNMButtonGroup is a joined row of filled buttons, KNMTabs switches panels,
   and KNMRadioGroupStyle.ButtonGroup draws its options from data with no attribute per option, while each option here
   carries the data-knm-set-* attribute the theme script listens on. */
.knm-seg {
  display: flex;
  background: var(--knm-theme-surface-2);
  border: 1px solid var(--knm-theme-border);
  border-radius: 9px;
  padding: 3px;
  gap: 2px;
}
.knm-seg > button,
.knm-seg > a {
  flex: 1;
  border: 0;
  background: none;
  border-radius: 6px;
  padding: .38rem .5rem;
  font-size: .8rem;
  font-weight: 600;
  color: var(--knm-theme-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4em;
  white-space: nowrap;
  text-decoration: none;
}
.knm-seg > button:hover,
.knm-seg > a:hover { color: var(--knm-theme-text); }
.knm-seg > button.active,
.knm-seg > a.active {
  background: var(--knm-theme-surface);
  color: var(--knm-theme-text);
  box-shadow: 0 1px 2px rgb(0 0 0 / .1);
}

.knm-swatch {
  width: 34px; height: 34px;
  border-radius: 10px;
  border: 1px solid var(--knm-theme-border);
  background: var(--knm-theme-accent);
  padding: 0;
  cursor: pointer;
  position: relative;
}
.knm-swatch.active {
  box-shadow: 0 0 0 2px var(--knm-theme-surface), 0 0 0 4px var(--knm-theme-accent);
}
.knm-swatch.active::after {
  content: "✓";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--knm-theme-accent-contrast);
  font-size: .85rem;
  font-weight: 700;
}

.knm-field-hint { font-size: .76rem; color: var(--knm-theme-text-muted); line-height: 1.5; }

/* Messaggio di validazione sotto un campo. Non ".knm-field-hint" ma il suo contrario: un rifiuto che si legge come un
   suggerimento non viene letto affatto, ed è così che «Acme Corp» faceva sembrare rotto il pulsante (H9). */
.knm-field-error {
  display: block;
  margin-top: 4px;
  font-size: .76rem;
  line-height: 1.5;
  color: var(--bs-danger, #dc3545);
}

/* Esito positivo sotto un campo (nome utente libero): stessa misura del rifiuto, colore di successo. */
.knm-field-ok {
  display: block;
  margin-top: 4px;
  font-size: .76rem;
  line-height: 1.5;
  color: var(--bs-success, #198754);
}

/* Navigazione verticale (impostazioni) */
.knm-t-vnav { display: flex; flex-direction: column; gap: 2px; }
.knm-t-vnav a {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem .75rem;
  border-radius: 8px;
  color: var(--knm-theme-text-muted);
  font-weight: 600;
  font-size: .865rem;
  text-decoration: none;
}
.knm-t-vnav a i { width: 1.1rem; text-align: center; }
.knm-t-vnav a:hover { color: var(--knm-theme-text); background: var(--knm-theme-surface-2); }
.knm-t-vnav a.active { background: var(--knm-theme-accent-soft); color: var(--knm-theme-accent-text); }

/* Bersaglio di una voce di knm-t-vnav: lo scroll si ferma sotto la barra superiore fissa invece di
   nascondere il titolo della sezione dietro di essa. Vale sia per lo scroll da codice
   (knmPageNav.scrollToSection) sia per il salto nativo del browser su /settings#sezione. */
.knm-t-anchor-section { scroll-margin-top: calc(var(--knm-theme-topbar-h) + var(--knm-theme-gap)); }

/* --------------------------------------------------------------------------
   12 · LOGIN
   -------------------------------------------------------------------------- */
.knm-t-login {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem 1rem;
  background:
    radial-gradient(820px 420px at 50% -8%, var(--knm-theme-accent-soft), transparent 70%),
    var(--knm-theme-bg);
}
.knm-t-login-card { width: 100%; max-width: 400px; }

/* --------------------------------------------------------------------------
   13 · UTILITÀ
   -------------------------------------------------------------------------- */
.knm-t-muted { color: var(--knm-theme-text-muted); }
.knm-t-mono { font-family: var(--knm-theme-font-mono); }
.knm-t-divider { border: 0; border-top: 1px solid var(--knm-theme-border); margin: var(--knm-theme-gap) 0; opacity: 1; }
.knm-t-scroll-x { overflow-x: auto; }

/* --------------------------------------------------------------------------
   14 · SIDEBAR COMPRIMIBILE (desktop) — [data-knm-sidebar="collapsed"]
   -------------------------------------------------------------------------- */
@media (min-width: 992px) {
  .knm-t-sidebar { transition: width .18s ease, flex-basis .18s ease; }
  [data-knm-sidebar="collapsed"] .knm-t-sidebar {
    width: 78px !important;
    flex-basis: 78px;
  }
  [data-knm-sidebar="collapsed"] .knm-brand-text,
  [data-knm-sidebar="collapsed"] .knm-t-sidebar-user > div,
  [data-knm-sidebar="collapsed"] .knm-t-sidebar-user > a,
  [data-knm-sidebar="collapsed"] .knm-t-sidebar-user > form { display: none; }
  [data-knm-sidebar="collapsed"] .knm-t-sidebar-brand { justify-content: center; padding-left: 0; padding-right: 0; }
  [data-knm-sidebar="collapsed"] .knm-t-navlink {
    font-size: 0;
    gap: 0;
    justify-content: center;
    padding: .55rem 0;
  }
  [data-knm-sidebar="collapsed"] .knm-t-navlink i { font-size: 1.1rem; }
  [data-knm-sidebar="collapsed"] .knm-t-navlink.active::before { left: -5px; }
  [data-knm-sidebar="collapsed"] .knm-t-nav-section {
    font-size: 0;
    line-height: 0;
    padding: 0;
    margin: .55rem .55rem;
    border-top: 1px solid var(--knm-theme-sidebar-border);
  }
  [data-knm-sidebar="collapsed"] .knm-t-sidebar-nav .knm-t-nav-section:first-child { border-top: 0; margin: 0; }
  [data-knm-sidebar="collapsed"] .knm-t-sidebar-user { justify-content: center; padding: .3rem 0; }
}

/* --------------------------------------------------------------------------
   15 · MOBILE
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  /* Longhands, not the `padding` shorthand: horizontally the box is a .container-fluid driven by
     --bs-gutter-x (see section 4), and a shorthand here would silently take that back. */
  .knm-t-content { --bs-gutter-x: 1.8rem; padding-top: .9rem; padding-bottom: .9rem; }
  .knm-t-topbar { padding: 0 .75rem; gap: .45rem; }
  .knm-t-pagetitle { font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .knm-t-stat-value { font-size: 1.45rem; }
  /* The Kanban toolbar reflows on a phone: the search takes the full row. The selector follows the KNMInput
     conversion (item 5) — the search wrapper replaced the bespoke .knm-t-search; the board filters live in the
     filters drawer (ticket-views-toolbar), not on the toolbar. */
  .knm-tv-toolbar > .knm-tv-search { width: 100% !important; }
  .knm-tv-toolbar .ms-auto { margin-left: 0 !important; }
  .knm-tv-toolbar > .btn, .knm-tv-toolbar > a.btn { flex: 1 1 auto; text-align: center; }
  .knm-t-bars { height: 120px; }
  .knm-t-bars-labels { font-size: .55rem; }
  .knm-t-msg { gap: .55rem; }
}

/* --------------------------------------------------------------------------
   16 · BREADCRUMB
   -------------------------------------------------------------------------- */
.knm-t-breadcrumb a { display: inline-flex; align-items: center; gap: .3rem; }
.knm-t-breadcrumb i { flex-shrink: 0; }
.knm-t-breadcrumb-current {
  color: var(--knm-theme-text);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --------------------------------------------------------------------------
   17 · KANBAN  — the board is KNMKanban (KNM.RazorComponents); what is left here is the
   product skin over it. The bespoke hand-rolled grid is gone with the
   hand-rolled board it styled; what survives is the board's CssClass, the column header's class passed through
   KNMKanbanBuilder (WithColumnHeaderCssClass) and the card's own inner markup.
   -------------------------------------------------------------------------- */

/* FULL WIDTH — CTO 2026-09-04, item 8 ("pagina con troppo spazio libero ... espandila su tutte").
   The board became KNMKanban in this same branch, so the rule moved one level down with it: the
   component owns its root (position/overflow) and lays the columns out on its inner
   .knm-kanban__grid, which is what has to carry the track list. The rule that was written for the
   bespoke board — grid-auto-columns: minmax(292px, 1fr) on the board's own element — would now be
   styling the wrong element, so it is expressed here instead; the BEHAVIOUR is unchanged and so is
   the number, measured on the running host at 1680px: container 1364px, four columns, 326px each.

   292px stays the FLOOR — below it a card's number, subject and footer stop fitting — so on a narrow
   viewport the board overflows into the component's own horizontal scroll, which is what a board
   should do. auto-fit is deliberately NOT used: the four columns are fixed and always present, so
   the count is known and a track list is honest about it. */
/* Since KNM.RazorComponents 3.26.0 the track list is the component's own, driven by
   --knm-kanban-visible-columns: no override of its grid any more. */

/* The theme's surfaces, so the board reads as part of the app rather than as the component's
   own default grey, in light and dark alike. */
.knm-tv-board {
  /* Not --knm-kanban-visible-columns: its 100%/4 leaves out the gaps and the padding, so four columns always overflowed by
     a few pixels. Without it the tracks share the width and the board scrolls only below the minimum. */
  --knm-kanban-column-min-width: 280px;
  --knm-kanban-column-bg: color-mix(in oklab, var(--knm-theme-surface-2), transparent 35%);
  --knm-kanban-card-bg: var(--knm-theme-surface);
  --knm-kanban-card-radius: var(--knm-theme-radius-sm);
  /* WithCellScroll: each column scrolls on its own below the page's header and filters. */
  --knm-kanban-cell-max-height: calc(100vh - 260px);
  /* The column count (a KNMBadge) at the size of the header's small print: the density default is too small to read. */
  --knm-badge-font-size: .67rem;
}
/* Hover: the same accent halo as every other clickable card, never a coloured border (Corrado 07/11); in dark mode the
   surface lift as well. The priority stripe (--accent) keeps its own left border. */
.knm-tv-board .knm-kanban-card:hover { border-color: var(--knm-kanban-card-border-color, var(--knm-theme-border)); }
@media (prefers-reduced-motion: no-preference) {
  .knm-tv-board .knm-kanban-card { transition: box-shadow .15s ease, border-color .15s ease; }
}
.knm-tv-board .knm-kanban-card:hover {
  box-shadow: var(--knm-theme-shadow), var(--knm-theme-hover-halo);
  background-image: linear-gradient(var(--knm-theme-hover-lift), var(--knm-theme-hover-lift));
}
/* «Assegna a me» (Corrado 07/11): the library draws the action slot in the top-right corner, visible only on hover, over
   the priority chip. Here it is an icon with a tooltip at the right end of the card's last row, always visible; the row
   leaves it room only on the cards that offer it. */
.knm-tv-board .knm-kanban-card__actions {
  top: auto;
  bottom: var(--knm-kanban-card-padding-y, .5rem);
  opacity: 1;
}
.knm-tv-board .knm-kanban-card__actions .btn { width: 1.75rem; height: 1.75rem; color: var(--knm-theme-accent-text); }
.knm-tv-board .knm-kanban-card:has(.knm-kanban-card__actions button) .knm-tv-card-foot { padding-right: 2.1rem; }

/* The header is our ColumnHeaderTemplate (title + the SERVER-side total). The component's own header is a flex row
   packed at its start, so the count sits right after the title. */
.knm-tv-col-head { text-transform: none; letter-spacing: 0; font-size: .8rem; }
.knm-tv-col-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The grid's cards (KNMDataGrid cards mode: agents' list, admin, portal) lift with the theme's shadow instead of the
   library's border, in both themes: the library draws a 1px border at rest and a fixed light-only shadow on hover, so in
   the dark theme a card had no shadow at all (Valerio, 06/11). The theme's shadow token has its own dark value. On hover
   the card takes the accent halo (Corrado, 07/11: a dark shadow on a dark page cannot be seen; no ring, no border). The library's
   own tokens, set on the wrap where it resolves them, so a selected card keeps its border. */
/* The hover halo of every clickable card (grid cards, dashboard tiles, portal counters and ticket cards, hub tiles):
   a soft glow of the accent, never a coloured border (Corrado, 07/11: «il border è brutto»). Declared on every element
   so the accent of the nearest data-knm-accent is the one read. */
/* A clickable KNMList row hovers in the accent, like the rows of the tables (Corrado, 07/11); the library's grey
   tertiary background reads as nothing on the dark theme. */
.knm-list-item--clickable:hover { background: rgba(var(--knm-theme-accent-rgb), .10); }
* {
  --knm-theme-hover-halo: 0 6px 24px rgba(var(--knm-theme-accent-rgb), .30);
  --knm-theme-hover-lift: transparent;
}
/* In the dark theme a glow alone barely shows on a near-black page (Corrado, 07/11): the halo is stronger and the card's
   surface lightens a little, laid over whatever background it has. */
[data-bs-theme="dark"], [data-bs-theme="dark"] * {
  --knm-theme-hover-halo: 0 0 0 0 transparent, 0 6px 28px rgba(var(--knm-theme-accent-rgb), .45);
  --knm-theme-hover-lift: rgba(255, 255, 255, .06);
}
:is(.knm-grid-card--clickable, .knm-dash-statlink .card, .knm-portal-statlink .card, .knm-portal-ticketcard .card, .knm-hub-tile .card) {
  transition: box-shadow .15s ease, background-image .15s ease;
}
:is(.knm-grid-card--clickable:hover, .knm-dash-statlink:hover .card, .knm-portal-statlink:hover .card,
    .knm-portal-ticketcard:hover .card, .knm-hub-tile:hover .card) {
  background-image: linear-gradient(var(--knm-theme-hover-lift), var(--knm-theme-hover-lift));
}
.knm-grid-cards-wrap {
  --knm-grid-card-border: transparent;
  --knm-grid-card-hover-shadow: var(--knm-theme-shadow), var(--knm-theme-hover-halo);
  --knm-grid-card-clickable-hover-border: transparent;
  /* The card's «⋯» menu is sized for labelled items (11rem), but the grid's own edit/delete render there icon-only, so
     the panel was mostly empty (Corrado, 07/11). It shrinks to its buttons instead. */
  --knm-grid-card-menu-min-width: auto;
}
.knm-grid-card { box-shadow: var(--knm-theme-shadow); }

/* The card is a KNMCard and a real link (WithCardHref); its body keeps the theme's text colour. */
.knm-tv-card-link { display: block; color: var(--knm-theme-text); }
.knm-tv-card-title {
  font-size: .85rem;
  font-weight: 600;
  line-height: 1.35;
  margin: .3rem 0 .55rem;
  text-wrap: pretty;
}
.knm-tv-card-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; }
.knm-tv-card-who { display: inline-flex; align-items: center; gap: .5rem; white-space: nowrap; min-height: 1.75rem; }
/* The card's number and its small print (age, assignee): the look of the ticket number and of the secondary text in the
   rest of the app, written here so the board does not depend on those template classes. */
.knm-tv-card-number {
  font-family: var(--knm-theme-font-mono);
  font-size: .76rem;
  color: var(--knm-theme-text-muted);
  white-space: nowrap;
}
.knm-tv-card-meta { font-size: .76rem; color: var(--knm-theme-text-muted); }
@media (max-width: 767.98px) {
  .knm-tv-board { --knm-kanban-cell-max-height: none; }
}

/* --------------------------------------------------------------------------
   18 · RICERCA DEL PORTALE
   -------------------------------------------------------------------------- */
/* The portal's top-bar search (portal-gaps): the desk's .knm-search-host width, the field filling it, and no field
   margin, which would lift the box off the top bar's centre line (same reset as the Kanban toolbar). */
.knm-t-portal-search { width: 280px; max-width: 40vw; flex: 0 1 auto; --knm-field-spacing: 0; }
.knm-t-portal-search > * { width: 100%; }

/* --------------------------------------------------------------------------
   19 · PORTALE CLIENTI
   -------------------------------------------------------------------------- */
/* The portal's content column — sister surface of .knm-t-content above, same flex column (.knm-t-main) and
   therefore the same two lines, for the same reasons: grow to own the leftover column height, and pin
   align-content so the grid rows do not stretch to fill it. Unlike the agent desk this one is centered on a
   max-width rather than full-bleed, so it keeps its own horizontal padding instead of a Bootstrap container. */
.knm-t-customer-main {
  max-width: 1160px;
  width: 100%;
  margin: 0 auto;
  flex: 1 0 auto;
  align-content: start;
  padding: calc(var(--knm-theme-gap) * 1.3) 1.25rem;
}
.knm-t-customer-footer {
  margin-top: auto;
  border-top: 1px solid var(--knm-theme-border);
  padding: 1.1rem 1.25rem;
  text-align: center;
  font-size: .78rem;
  color: var(--knm-theme-text-muted);
}
.knm-t-customer-footer a { color: var(--knm-theme-text-muted); text-decoration: none; }
.knm-t-customer-footer a:hover { color: var(--knm-theme-accent-text); }

/* Footer area admin */
.knm-t-footer {
  margin-top: auto;
  border-top: 1px solid var(--knm-theme-border);
  padding: .9rem calc(var(--knm-theme-gap) * 1.3);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem 1.25rem;
  font-size: .78rem;
  color: var(--knm-theme-text-muted);
}
.knm-t-footer a { color: var(--knm-theme-text-muted); text-decoration: none; }
.knm-t-footer a:hover { color: var(--knm-theme-accent-text); }

.modal-content {
  background: var(--knm-theme-surface);
  color: var(--knm-theme-text);
  border: 1px solid var(--knm-theme-border);
  border-radius: var(--knm-theme-radius);
}
.modal-header, .modal-footer { border-color: var(--knm-theme-border); }

/* --------------------------------------------------------------------------
   20 · MENU ORIZZONTALE — [data-knm-nav="top"] (opzione, solo desktop)
   Stesso markup della sidebar: l'orientamento è una preferenza del tema.
   Sotto i 992px resta sempre l'offcanvas mobile.
   -------------------------------------------------------------------------- */
@media (min-width: 992px) {
  [data-knm-nav="top"] .knm-t-app { flex-direction: column; }
  [data-knm-nav="top"] .knm-t-sidebar {
    width: 100% !important;
    flex: 0 0 auto;
    height: auto;
    flex-direction: row;
    align-items: center;
    position: sticky;
    top: 0;
    z-index: 1030;
    border-right: 0;
    border-bottom: 1px solid var(--knm-theme-sidebar-border);
  }
  [data-knm-nav="top"] .knm-t-sidebar-brand {
    border-bottom: 0;
    min-height: 0;
    padding: .55rem .5rem .55rem 1.15rem;
  }
  [data-knm-nav="top"] .knm-brand-text { display: inline; }
  [data-knm-nav="top"] .knm-t-sidebar-nav {
    flex-direction: row;
    align-items: center;
    gap: .15rem;
    padding: .5rem;
    overflow-y: visible;
    overflow-x: auto;
  }
  [data-knm-nav="top"] .knm-t-nav-section { display: none; }
  [data-knm-nav="top"] .knm-t-navlink {
    width: auto;
    font-size: .875rem;
    gap: .55rem;
    justify-content: flex-start;
    padding: .45rem .8rem;
  }
  [data-knm-nav="top"] .knm-t-navlink.active::before { display: none; }
  [data-knm-nav="top"] .knm-t-sidebar-footer {
    flex-direction: row;
    align-items: center;
    gap: .4rem;
    border-top: 0;
    padding: .5rem 1rem .5rem .5rem;
    margin-left: auto;
  }
  [data-knm-nav="top"] .knm-t-sidebar-footer > .knm-t-navlink {
    width: auto;
    font-size: 0;
    gap: 0;
    padding: .5rem;
  }
  [data-knm-nav="top"] .knm-t-sidebar-footer > .knm-t-navlink i { font-size: 1.05rem; }
  [data-knm-nav="top"] .knm-t-sidebar-user { padding: .2rem; gap: .45rem; }
  [data-knm-nav="top"] .knm-t-sidebar-user > div { display: none; }
  [data-knm-nav="top"] [data-knm-toggle-sidebar] { display: none !important; }
  [data-knm-nav="top"] .knm-t-topbar { position: static; }
}

/* Global search (top-bar). The box is the Search type of KNMInput: its results panel, the cards per type, the highlight
   and the keyboard are the library's, dressed with the theme tokens in custom.css (.knm-gsearch-panel). What is left
   here is the box's width in the top bar (Corrado, 09/10). */
.knm-search-host { width: 280px; flex: 0 0 auto; }
/* The host is a d-md-flex box, so the field has to be told to fill it along the main axis. */
.knm-search-host > * { flex: 1 1 auto; min-width: 0; }

/* Notification bell */
.knm-notif { position: relative; }
/* The unread counter (a KNMBadge) laid over the top bar's icon button, in the accent the organization chose. Two classes
   to outweigh Bootstrap's .btn .badge { position: relative; top: -1px }: one class would lose to it. It sits on the
   button's top-right corner, half outside, so it never covers the icon (Corrado, 04/11: inside the button it did). */
.badge.knm-notif-badge {
  --knm-badge-bg: var(--knm-theme-accent); --knm-badge-color: var(--knm-theme-accent-contrast);
  --knm-badge-padding-x: 4px; --knm-badge-padding-y: 0; --knm-badge-font-size: .62rem; --knm-badge-radius: 9px;
  position: absolute; top: 0; right: 0; transform: translate(40%, -40%); pointer-events: none;
  min-width: 16px; height: 16px; line-height: 16px; text-align: center; }
/* No KNM component draws this panel: see the comment at the top of NotificationBell.razor. 420 px, never wider than the
   screen (notifications, U111): a line now carries who, what and which ticket. */
:root { --knm-notif-panel-w: min(420px, 100vw); }
.knm-notif-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 1200; width: var(--knm-notif-panel-w); max-height: 60vh;
  overflow-y: auto; background: var(--knm-theme-surface); color: var(--knm-theme-text);
  border: 1px solid var(--knm-theme-border); border-radius: 10px; box-shadow: var(--knm-theme-shadow); }
/* On a phone the bell sits right of the middle of the bar, so a fixed-width panel anchored to its right edge ran off the left of
   the screen: there it spans the screen under the top bar instead. */
@media (max-width: 575.98px) {
  .knm-notif-panel { position: fixed; top: calc(var(--knm-theme-topbar-h) + 4px); left: 1rem; right: 1rem; width: auto; }
}
.knm-notif-head { display: flex; align-items: center; justify-content: space-between; padding: .6rem .75rem;
  border-bottom: 1px solid var(--knm-theme-border); font-weight: 700; font-size: .8rem; }
.knm-notif-head-actions { display: flex; align-items: center; gap: .25rem; }
.knm-notif-kept { padding: .45rem .75rem; font-size: .78rem; border-bottom: 1px solid var(--knm-theme-border); }
/* The «mark all» KNMButton on the accent's soft fill. */
.btn.knm-notif-markall {
  --bs-btn-bg: var(--knm-theme-accent-soft); --bs-btn-color: var(--knm-theme-accent-text); --bs-btn-border-color: transparent;
  --bs-btn-hover-bg: color-mix(in oklab, var(--knm-theme-accent), transparent 82%); --bs-btn-hover-color: var(--knm-theme-accent-hover);
  --bs-btn-hover-border-color: transparent; }
.knm-notif-item { display: flex; gap: .6rem; width: 100%; text-align: left; padding: .55rem .75rem; border: 0;
  background: none; cursor: pointer; color: inherit; border-bottom: 1px solid var(--knm-theme-border); }
.knm-notif-item:hover { background: var(--knm-theme-surface-2); }
.knm-notif-item.is-unread { background: var(--knm-theme-accent-soft); }
.knm-notif-item i { font-size: 1rem; opacity: .75; }
.knm-notif-title { font-weight: 600; font-size: .82rem; }
.knm-notif-sub { font-size: .72rem; opacity: .6; }
.knm-notif-empty { padding: 1rem; text-align: center; font-size: .82rem; opacity: .65; }
.knm-notif-item > span { min-width: 0; overflow-wrap: anywhere; }
/* The foot: the history and the preferences, so nothing the bell leads to is hidden (T256). */
.knm-notif-foot { display: flex; justify-content: space-between; gap: .5rem; padding: .5rem .75rem; font-size: .8rem; }
.knm-notif-foot a { color: var(--knm-theme-accent-text); text-decoration: none; font-weight: 600; }
.knm-notif-foot a:hover { text-decoration: underline; }

/* Idle warning strip — the last seconds before the screen locks itself (Berruto's model).
   Fixed across the top, above everything: it interrupts, so it does not queue behind the topbar's stacking
   context. Colours from the theme tokens, so it reads the same in light and dark without a rule for each. */
.knm-idlewarn { position: fixed; top: 0; left: 0; right: 0; z-index: 1080; }
.knm-idlewarn[hidden] { display: none; }
.knm-idlewarn-body { display: flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .5rem 1rem; background: var(--bs-warning-bg-subtle);
  color: var(--bs-warning-text-emphasis);
  border-bottom: 1px solid var(--bs-warning-border-subtle); }
.knm-idlewarn-icon { font-size: 1rem; }
.knm-idlewarn-text { font-size: .85rem; font-weight: 600; font-variant-numeric: tabular-nums; }
/* 4px, like the bar this is modelled on: enough to read as a countdown, not enough to be a component. */
.knm-idlewarn-track { height: 4px; background: var(--bs-warning-border-subtle); }
/* Emptying, not filling — it is time left, not progress towards something wanted. The transition is shorter
   than the tick so a second does not read as a jump and a reset does not lag behind the mouse. */
.knm-idlewarn-bar { height: 100%; width: 100%; background: var(--bs-warning);
  transition: width .3s linear; }

/* 404 Not Found page */
.knm-notfound { display: flex; align-items: center; justify-content: center; min-height: 60vh; padding: 1.5rem; }
/* A customer sees the page inside the portal's shell, so it takes the width of the portal's content column: the same
   values as .knm-t-customer-main, the source, to keep in step with it. */
.knm-notfound-portal { max-width: 1160px; width: 100%; margin: 0 auto; flex: 1 0 auto; }
.knm-notfound-card { max-width: 460px; width: 100%; text-align: center; }
.knm-notfound-icon { font-size: 3.5rem; color: var(--knm-theme-accent-label); margin-bottom: .5rem; }
.knm-notfound-code { font-family: var(--knm-theme-font-display); font-size: 3.5rem; font-weight: 800;
  line-height: 1; color: var(--knm-theme-accent-label); margin-bottom: .5rem; }
.knm-notfound-title { font-size: 1.35rem; margin: 0 0 .5rem; }
.knm-notfound-desc { font-size: .9rem; margin: 0 0 1rem; }
.knm-notfound-path { font-size: .78rem; margin: 0 0 1.25rem; }
.knm-notfound-path code { background: var(--knm-theme-surface-2); padding: .2rem .5rem; border-radius: 6px; }
.knm-notfound-actions { display: flex; gap: .6rem; justify-content: center; flex-wrap: wrap; }
