/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

.login-ui .sso-providers {

    padding: 0.25em 0.5em;
    position: absolute;
    bottom: 0;
    left: 0;

}

.sso-providers ul {
    list-style: none;
}

.sso-providers ul, .sso-providers li {
    display: inline-block;
    margin: 0;
    padding: 0;
}

.sso-providers li::before {
    content: ' / ';
}

.sso-providers li:first-child::before {
    display: none;
}
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/* Label/tag denoting the user that shared a connection */
.jdbc-share-tag {

    background: #0095ff;
    padding: 0.25em;

    -moz-border-radius:    0.25em;
    -webkit-border-radius: 0.25em;
    -khtml-border-radius:  0.25em;
    border-radius:         0.25em;

    color: white;
    font-size: 0.75em;
    font-weight: bold;

}
.restrictionList{border:0}button.restrictionListButton{font-size:.75em}img.restrictionListHeader{width:.75em;height:.75em}img.restrictionListItem{width:1em;height:1em}/* ============================================================================
   BLUEPRINT DESIGN SYSTEM — TOKENS
   blueprint-tokens.css
   ----------------------------------------------------------------------------
   Semantic design tokens for IT-security & operations frontends.
   Works for both admin and end-user surfaces.

   Palette: white · blue · black · grey. No gradients.

   THEMING
     Default theme is dark. Switch by setting an attribute on <html> or any
     ancestor element:
        <html data-theme="dark">   (default)
        <html data-theme="light">
     If no data-theme is set, the OS preference is honoured via
     prefers-color-scheme.

   USAGE
     Components must reference SEMANTIC tokens only (e.g. var(--bp-surface)),
     never raw palette values. To re-skin, remap the tokens — not the
     components.
   ============================================================================ */

/* ------------------------------------------------------------------ *
 * 1. PRIMITIVES — raw scales. Do not use directly in components.      *
 * ------------------------------------------------------------------ */
:root {
  /* type families */
  --bp-font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
    system-ui, sans-serif;
  --bp-font-mono: "JetBrains Mono", "SFMono-Regular", "Consolas", "Menlo",
    monospace;

  /* type scale (px in rem, 16px base) */
  --bp-text-2xs: 0.656rem;  /* 10.5 — eyebrows, captions   */
  --bp-text-xs:  0.75rem;   /* 12   — micro labels         */
  --bp-text-sm:  0.781rem;  /* 12.5 — small / helper       */
  --bp-text-base:0.875rem;  /* 14   — body                 */
  --bp-text-md:  0.938rem;  /* 15   — emphasised body      */
  --bp-text-lg:  1.125rem;  /* 18   — h2                   */
  --bp-text-xl:  1.375rem;  /* 22   — h1                   */
  --bp-text-2xl: 1.5rem;    /* 24   — stat values          */
  --bp-text-3xl: 1.75rem;   /* 28   — display              */

  --bp-weight-regular: 400;
  --bp-weight-medium:  500;
  --bp-weight-semibold:600;
  --bp-weight-bold:    700;

  --bp-leading-tight: 1.25;
  --bp-leading-snug:  1.4;
  --bp-leading-normal:1.55;

  --bp-tracking-tight: -0.02em;
  --bp-tracking-normal: 0;
  --bp-tracking-wide:   0.08em;
  --bp-tracking-eyebrow:0.14em;

  /* spacing scale (4-based) */
  --bp-space-1:  4px;
  --bp-space-2:  8px;
  --bp-space-3:  12px;
  --bp-space-4:  16px;
  --bp-space-5:  20px;
  --bp-space-6:  24px;
  --bp-space-8:  32px;
  --bp-space-10: 40px;
  --bp-space-12: 48px;
  --bp-space-16: 64px;

  /* radii — near-zero, blueprint aesthetic */
  --bp-radius-sm: 2px;
  --bp-radius-md: 2px;
  --bp-radius-pill: 2px;

  /* borders */
  --bp-border-width: 1px;
  --bp-border-width-accent: 2px;

  /* blueprint grid texture */
  --bp-grid-size: 56px;

  /* motion */
  --bp-transition-fast: 0.12s ease;
  --bp-transition: 0.18s ease;

  /* z-index scale */
  --bp-z-base: 1;
  --bp-z-sticky: 10;
  --bp-z-overlay: 100;
  --bp-z-toast: 1000;

  /* layout */
  --bp-sidebar-width: 232px;
  --bp-rail-width: 72px;
  --bp-topbar-height: 52px;
  --bp-tabbar-height: 52px;
  --bp-content-max: 1320px;

  /* focus ring */
  --bp-focus-ring: 2px;
}

/* ------------------------------------------------------------------ *
 * 2. SEMANTIC TOKENS — DARK (default)                                 *
 * ------------------------------------------------------------------ */
:root,
[data-theme="dark"] {
  color-scheme: dark;

  /* surfaces */
  --bp-bg:           #0b0f14;
  --bp-surface:      #11161d;
  --bp-surface-2:    #161c25;
  --bp-surface-3:    #1b2330;

  /* lines */
  --bp-line:         #232c38;
  --bp-line-strong:  #33404f;

  /* ink
     Contrast on --bp-surface (#11161d):
       ink 15.4:1 · ink-dim 8.1:1 · ink-faint 5.2:1 (all WCAG AA). */
  --bp-ink:          #e8edf2;
  --bp-ink-dim:      #a3aebc;
  --bp-ink-faint:    #7f8b9a;
  --bp-ink-inverse:  #0b0f14;

  /* accent (action only) */
  --bp-accent:       #2f6df6;
  --bp-accent-hover: #1d4ed8;
  --bp-accent-faint: rgba(47, 109, 246, 0.12);
  --bp-on-accent:    #ffffff;

  /* status */
  --bp-ok:           #3fa66a;
  --bp-ok-faint:     rgba(63, 166, 106, 0.14);
  --bp-warn:         #c9922b;
  --bp-warn-faint:   rgba(201, 146, 43, 0.14);
  --bp-high:         #cf6a2e;
  --bp-high-faint:   rgba(207, 106, 46, 0.14);
  --bp-crit:         #d2433a;
  --bp-crit-faint:   rgba(210, 67, 58, 0.14);

  /* grid texture */
  --bp-grid-line:    #232c38;
  --bp-grid-veil:    rgba(11, 15, 20, 0.86);

  /* swatch / inset edge */
  --bp-inset-ring:   rgba(255, 255, 255, 0.08);

  /* overlay scrim */
  --bp-scrim:        rgba(0, 0, 0, 0.55);

  /* charts — flat categorical series (no gradients) */
  --bp-chart-1:      #2f6df6;
  --bp-chart-2:      #3fa66a;
  --bp-chart-3:      #c9922b;
  --bp-chart-4:      #cf6a2e;
  --bp-chart-5:      #7f8b9a;
}

/* ------------------------------------------------------------------ *
 * 3. SEMANTIC TOKENS — LIGHT                                          *
 * ------------------------------------------------------------------ */
[data-theme="light"] {
  color-scheme: light;

  --bp-bg:           #f4f6f9;
  --bp-surface:      #ffffff;
  --bp-surface-2:    #eef1f5;
  --bp-surface-3:    #e6eaf0;

  --bp-line:         #dce1e8;
  --bp-line-strong:  #c2cad4;

  --bp-ink:          #14181d;
  --bp-ink-dim:      #55606d;
  --bp-ink-faint:    #8a94a1;
  --bp-ink-inverse:  #ffffff;

  /* darker blue keeps >=4.5:1 contrast on white */
  --bp-accent:       #1d4ed8;
  --bp-accent-hover: #1639a8;
  --bp-accent-faint: rgba(29, 78, 216, 0.08);
  --bp-on-accent:    #ffffff;

  --bp-ok:           #2f8f57;
  --bp-ok-faint:     rgba(47, 143, 87, 0.10);
  --bp-warn:         #a9781d;
  --bp-warn-faint:   rgba(169, 120, 29, 0.10);
  --bp-high:         #b45416;
  --bp-high-faint:   rgba(180, 84, 22, 0.10);
  --bp-crit:         #c0352c;
  --bp-crit-faint:   rgba(192, 53, 44, 0.10);

  --bp-grid-line:    #e3e8ee;
  --bp-grid-veil:    rgba(244, 246, 249, 0.84);

  --bp-inset-ring:   rgba(0, 0, 0, 0.06);

  --bp-scrim:        rgba(20, 24, 29, 0.35);

  /* charts — flat categorical series (no gradients) */
  --bp-chart-1:      #1d4ed8;
  --bp-chart-2:      #2f8f57;
  --bp-chart-3:      #a9781d;
  --bp-chart-4:      #b45416;
  --bp-chart-5:      #55606d;
}

/* ------------------------------------------------------------------ *
 * 4. OS PREFERENCE FALLBACK                                           *
 *    Applies only when no explicit data-theme is set.                 *
 * ------------------------------------------------------------------ */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    color-scheme: light;

    --bp-bg:           #f4f6f9;
    --bp-surface:      #ffffff;
    --bp-surface-2:    #eef1f5;
    --bp-surface-3:    #e6eaf0;
    --bp-line:         #dce1e8;
    --bp-line-strong:  #c2cad4;
    --bp-ink:          #14181d;
    --bp-ink-dim:      #55606d;
    --bp-ink-faint:    #8a94a1;
    --bp-ink-inverse:  #ffffff;
    --bp-accent:       #1d4ed8;
    --bp-accent-hover: #1639a8;
    --bp-accent-faint: rgba(29, 78, 216, 0.08);
    --bp-on-accent:    #ffffff;
    --bp-ok:           #2f8f57;
    --bp-ok-faint:     rgba(47, 143, 87, 0.10);
    --bp-warn:         #a9781d;
    --bp-warn-faint:   rgba(169, 120, 29, 0.10);
    --bp-high:         #b45416;
    --bp-high-faint:   rgba(180, 84, 22, 0.10);
    --bp-crit:         #c0352c;
    --bp-crit-faint:   rgba(192, 53, 44, 0.10);
    --bp-grid-line:    #e3e8ee;
    --bp-grid-veil:    rgba(244, 246, 249, 0.84);
    --bp-inset-ring:   rgba(0, 0, 0, 0.06);
    --bp-scrim:        rgba(20, 24, 29, 0.35);
    --bp-chart-1:      #1d4ed8;
    --bp-chart-2:      #2f8f57;
    --bp-chart-3:      #a9781d;
    --bp-chart-4:      #b45416;
    --bp-chart-5:      #55606d;
  }
}
/* ============================================================================
   BLUEPRINT DESIGN SYSTEM — COMPONENTS
   blueprint-components.css
   ----------------------------------------------------------------------------
   Requires blueprint-tokens.css to be loaded first.

   All selectors are namespaced with the `bp-` prefix to avoid collisions
   with host application styles. Components reference semantic tokens only.

   Suitable for both admin consoles and end-user frontends.
   ============================================================================ */

/* ------------------------------------------------------------------ *
 * BASE / RESET (scoped, non-destructive)                              *
 * ------------------------------------------------------------------ */
.bp-root,
.bp-root *,
.bp-root *::before,
.bp-root *::after {
  box-sizing: border-box;
}

.bp-root {
  margin: 0;
  background-color: var(--bp-bg);
  color: var(--bp-ink);
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-base);
  line-height: var(--bp-leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color var(--bp-transition), color var(--bp-transition);
}

/* optional blueprint grid texture on the canvas */
.bp-root.bp-grid {
  background-image:
    linear-gradient(var(--bp-grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--bp-grid-line) 1px, transparent 1px);
  background-size: var(--bp-grid-size) var(--bp-grid-size);
  background-position: -1px -1px;
}

/* ------------------------------------------------------------------ *
 * TYPOGRAPHY HELPERS                                                  *
 * ------------------------------------------------------------------ */
.bp-mono { font-family: var(--bp-font-mono); }

.bp-display {
  font-size: var(--bp-text-3xl);
  font-weight: var(--bp-weight-semibold);
  letter-spacing: var(--bp-tracking-tight);
  line-height: var(--bp-leading-tight);
  margin: 0;
}
.bp-h1 {
  font-size: var(--bp-text-xl);
  font-weight: var(--bp-weight-semibold);
  letter-spacing: var(--bp-tracking-tight);
  margin: 0;
}
.bp-h2 {
  font-size: var(--bp-text-lg);
  font-weight: var(--bp-weight-semibold);
  margin: 0;
}
.bp-h3 {
  font-size: var(--bp-text-base);
  font-weight: var(--bp-weight-semibold);
  margin: 0;
}
.bp-text-dim   { color: var(--bp-ink-dim); }
.bp-text-faint { color: var(--bp-ink-faint); }
.bp-small      { font-size: var(--bp-text-sm); color: var(--bp-ink-dim); }

.bp-eyebrow {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: var(--bp-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--bp-ink-faint);
}

.bp-code {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: 1px 5px;
  color: var(--bp-ink);
}

.bp-pre {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-4);
  line-height: var(--bp-leading-snug);
  overflow-x: auto;
  margin: 0;
}

/* ------------------------------------------------------------------ *
 * LINKS                                                               *
 * ------------------------------------------------------------------ */
.bp-link {
  color: var(--bp-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.bp-link:hover { border-bottom-color: var(--bp-accent); }

/* ------------------------------------------------------------------ *
 * BUTTONS                                                             *
 * ------------------------------------------------------------------ */
.bp-btn {
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-base);
  font-weight: var(--bp-weight-medium);
  line-height: 1;
  color: var(--bp-ink);
  background-color: transparent;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-2) var(--bp-space-3);
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  cursor: pointer;
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.bp-btn:hover { border-color: var(--bp-ink-faint); }

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

.bp-btn--ghost {
  border-color: transparent;
  color: var(--bp-ink-dim);
}
.bp-btn--ghost:hover {
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
}

.bp-btn--danger {
  border-color: color-mix(in srgb, var(--bp-crit) 50%, transparent);
  color: var(--bp-crit);
}
.bp-btn--danger:hover {
  background-color: var(--bp-crit-faint);
}

.bp-btn--sm { padding: var(--bp-space-1) var(--bp-space-2); font-size: var(--bp-text-xs); }
.bp-btn--lg { padding: var(--bp-space-3) var(--bp-space-5); font-size: var(--bp-text-md); }
.bp-btn--block { width: 100%; justify-content: center; }

.bp-btn:disabled,
.bp-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

.bp-btn__icon { width: 14px; height: 14px; flex: none; }

.bp-btn-row {
  display: flex;
  gap: var(--bp-space-3);
  flex-wrap: wrap;
  align-items: center;
}

/* ------------------------------------------------------------------ *
 * FORMS                                                               *
 * ------------------------------------------------------------------ */
.bp-field {
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-2);
}
.bp-label {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
}
.bp-input,
.bp-select,
.bp-textarea {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-2) var(--bp-space-3);
  width: 100%;
}
.bp-textarea { font-family: var(--bp-font-sans); resize: vertical; min-height: 80px; }
.bp-input::placeholder,
.bp-textarea::placeholder { color: var(--bp-ink-faint); }
.bp-input:focus,
.bp-select:focus,
.bp-textarea:focus {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 1px;
  border-color: var(--bp-accent);
}
.bp-input:disabled,
.bp-select:disabled { opacity: 0.55; cursor: not-allowed; }

.bp-input--invalid { border-color: var(--bp-crit); }
.bp-field__hint  { font-size: var(--bp-text-xs); color: var(--bp-ink-faint); }
.bp-field__error { font-size: var(--bp-text-xs); color: var(--bp-crit); }

/* toggle / switch */
.bp-toggle {
  width: 36px;
  height: 20px;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  background-color: var(--bp-surface-2);
  border-radius: var(--bp-radius-sm);
  position: relative;
  cursor: pointer;
  flex: none;
  padding: 0;
  transition: border-color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-toggle::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background-color: var(--bp-ink-faint);
  transition: left var(--bp-transition-fast), background-color var(--bp-transition-fast);
}
.bp-toggle[aria-checked="true"] {
  border-color: var(--bp-accent);
  background-color: var(--bp-accent-faint);
}
.bp-toggle[aria-checked="true"]::after {
  left: 18px;
  background-color: var(--bp-accent);
}

/* checkbox / radio accent */
.bp-checkbox,
.bp-radio { accent-color: var(--bp-accent); width: 15px; height: 15px; }

/* ------------------------------------------------------------------ *
 * PANELS / CARDS                                                      *
 * ------------------------------------------------------------------ */
.bp-panel {
  border: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  border-radius: var(--bp-radius-md);
}
.bp-panel__head {
  padding: var(--bp-space-3) var(--bp-space-4);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
}
.bp-panel__head .bp-eyebrow { margin-left: auto; }
.bp-panel__body { padding: var(--bp-space-4); }
.bp-panel__foot {
  padding: var(--bp-space-3) var(--bp-space-4);
  border-top: var(--bp-border-width) solid var(--bp-line);
}

.bp-tag-num {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-accent);
  border: var(--bp-border-width) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  padding: 1px 6px;
}

/* ------------------------------------------------------------------ *
 * STAT STRIP                                                          *
 * ------------------------------------------------------------------ */
.bp-stat-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  border-radius: var(--bp-radius-md);
  overflow: hidden;
}
.bp-stat {
  padding: var(--bp-space-4) var(--bp-space-5);
  border-right: var(--bp-border-width) solid var(--bp-line);
}
.bp-stat:last-child { border-right: none; }
.bp-stat__label { display: block; margin-bottom: var(--bp-space-2); }
.bp-stat__value {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xl);
  font-weight: var(--bp-weight-semibold);
  line-height: 1;
  letter-spacing: var(--bp-tracking-tight);
}
.bp-stat__meta {
  margin-top: var(--bp-space-2);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
  display: flex;
  align-items: center;
  gap: var(--bp-space-1);
}
.bp-delta--up   { color: var(--bp-ok); font-family: var(--bp-font-mono); }
.bp-delta--down { color: var(--bp-crit); font-family: var(--bp-font-mono); }

/* ------------------------------------------------------------------ *
 * STATUS — PILLS, DOTS, TAGS                                          *
 * ------------------------------------------------------------------ */
.bp-pill {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: 0.04em;
  color: var(--bp-ink-dim);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-pill);
  padding: 2px var(--bp-space-2);
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-1);
}
.bp-pill--ok   { color: var(--bp-ok);   border-color: color-mix(in srgb, var(--bp-ok) 45%, transparent); }
.bp-pill--warn { color: var(--bp-warn); border-color: color-mix(in srgb, var(--bp-warn) 45%, transparent); }
.bp-pill--crit { color: var(--bp-crit); border-color: color-mix(in srgb, var(--bp-crit) 45%, transparent); }

.bp-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; display: inline-block; }
.bp-dot--ok   { background-color: var(--bp-ok); }
.bp-dot--warn { background-color: var(--bp-warn); }
.bp-dot--crit { background-color: var(--bp-crit); }

.bp-tag {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-ink-dim);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: 1px var(--bp-space-2);
  display: inline-block;
}

/* ------------------------------------------------------------------ *
 * METER / PROGRESS BAR                                                *
 * ------------------------------------------------------------------ */
.bp-bar {
  height: 6px;
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  position: relative;
  overflow: hidden;
}
.bp-bar__fill { position: absolute; top: 0; left: 0; bottom: 0; background-color: var(--bp-accent); }
.bp-bar__fill--ok   { background-color: var(--bp-ok); }
.bp-bar__fill--warn { background-color: var(--bp-warn); }
.bp-bar__fill--crit { background-color: var(--bp-crit); }

/* ------------------------------------------------------------------ *
 * TABLES                                                              *
 * ------------------------------------------------------------------ */
.bp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--bp-text-base);
}
.bp-table thead th {
  text-align: left;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  font-weight: var(--bp-weight-medium);
  padding: var(--bp-space-3) var(--bp-space-3) var(--bp-space-3);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}
.bp-table tbody td {
  padding: var(--bp-space-3);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  vertical-align: middle;
}
.bp-table tbody tr:last-child td { border-bottom: none; }
.bp-table--hover tbody tr { cursor: pointer; }
.bp-table--hover tbody tr:hover td { background-color: var(--bp-surface-2); }
.bp-table__id {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
}
.bp-table__id small {
  display: block;
  color: var(--bp-ink-faint);
  font-size: var(--bp-text-2xs);
  margin-top: 2px;
}

/* ------------------------------------------------------------------ *
 * ALERTS / BANNERS                                                    *
 * ------------------------------------------------------------------ */
.bp-alert {
  display: flex;
  gap: var(--bp-space-3);
  align-items: flex-start;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-left-width: 3px;
  background-color: var(--bp-surface);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-3) var(--bp-space-4);
  font-size: var(--bp-text-base);
}
.bp-alert--info { border-left-color: var(--bp-accent); }
.bp-alert--ok   { border-left-color: var(--bp-ok); }
.bp-alert--warn { border-left-color: var(--bp-warn); }
.bp-alert--crit { border-left-color: var(--bp-crit); }
.bp-alert__icon { width: 16px; height: 16px; flex: none; margin-top: 1px; }
.bp-alert__body b { font-weight: var(--bp-weight-semibold); }
.bp-alert__body small { display: block; color: var(--bp-ink-dim); margin-top: 2px; }

/* ------------------------------------------------------------------ *
 * EMPTY STATE                                                         *
 * ------------------------------------------------------------------ */
.bp-empty {
  border: 1px dashed var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  padding: var(--bp-space-8);
  text-align: center;
}
.bp-empty__icon { width: 28px; height: 28px; stroke: var(--bp-ink-faint); margin-bottom: var(--bp-space-3); }
.bp-empty h4 { margin: 0 0 var(--bp-space-1); font-size: var(--bp-text-base); }
.bp-empty p  { margin: 0 0 var(--bp-space-4); color: var(--bp-ink-dim); font-size: var(--bp-text-sm); }

/* ------------------------------------------------------------------ *
 * BADGES / COUNTERS                                                   *
 * ------------------------------------------------------------------ */
.bp-badge {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-on-accent);
  background-color: var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  padding: 1px 6px;
  display: inline-block;
}
.bp-badge--quiet {
  color: var(--bp-ink-faint);
  background-color: transparent;
}

/* ------------------------------------------------------------------ *
 * APP SHELL — SIDEBAR + TOPBAR (admin layout)                         *
 * ------------------------------------------------------------------ */
.bp-app {
  display: grid;
  grid-template-columns: var(--bp-sidebar-width) 1fr;
  min-height: 100vh;
}
.bp-sidebar {
  border-right: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}
.bp-sidebar__brand {
  padding: var(--bp-space-4);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
}
.bp-mark {
  width: 30px;
  height: 30px;
  flex: none;
  border: var(--bp-border-width) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  display: grid;
  place-items: center;
  font-family: var(--bp-font-mono);
  font-weight: var(--bp-weight-bold);
  font-size: var(--bp-text-xs);
  color: var(--bp-accent);
  background-color: var(--bp-accent-faint);
}
.bp-nav { padding: var(--bp-space-2) 0; flex: 1; overflow-y: auto; }
.bp-nav__group { padding: var(--bp-space-2) var(--bp-space-4) var(--bp-space-1); }
.bp-nav__link {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  padding: var(--bp-space-2) var(--bp-space-4);
  color: var(--bp-ink-dim);
  text-decoration: none;
  font-size: var(--bp-text-base);
  border-left: var(--bp-border-width-accent) solid transparent;
  cursor: pointer;
}
.bp-nav__link:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }
.bp-nav__link.is-active {
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border-left-color: var(--bp-accent);
}
.bp-nav__link .bp-nav__count {
  margin-left: auto;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-faint);
}
.bp-nav__icon { width: 15px; height: 15px; flex: none; opacity: 0.85; }

.bp-main { min-width: 0; display: flex; flex-direction: column; }
.bp-topbar {
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  padding: 0 var(--bp-space-6);
  height: var(--bp-topbar-height);
  display: flex;
  align-items: center;
  gap: var(--bp-space-4);
  position: sticky;
  top: 0;
  z-index: var(--bp-z-sticky);
}
.bp-crumb { font-family: var(--bp-font-mono); font-size: var(--bp-text-xs); color: var(--bp-ink-faint); }
.bp-crumb b { color: var(--bp-ink); font-weight: var(--bp-weight-semibold); }
.bp-crumb__sep { color: var(--bp-line-strong); margin: 0 var(--bp-space-2); }
.bp-topbar__spacer { flex: 1; }
.bp-content {
  padding: var(--bp-space-6) var(--bp-space-6) var(--bp-space-16);
  max-width: var(--bp-content-max);
  width: 100%;
}

/* environment chip */
.bp-env {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: 3px var(--bp-space-2);
  color: var(--bp-ink-dim);
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
}

/* avatar */
.bp-avatar {
  width: 28px;
  height: 28px;
  flex: none;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  display: grid;
  place-items: center;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
}

/* ------------------------------------------------------------------ *
 * USER-FRONTEND LAYOUT — centered, single column                     *
 * ------------------------------------------------------------------ */
.bp-shell {
  max-width: 960px;
  margin: 0 auto;
  padding: var(--bp-space-6) var(--bp-space-6) var(--bp-space-16);
}
.bp-shell--narrow { max-width: 560px; }

.bp-header {
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
  padding: var(--bp-space-4) 0;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  margin-bottom: var(--bp-space-6);
}
.bp-header__spacer { flex: 1; }

/* card grid for user dashboards */
.bp-grid-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--bp-space-5);
}

/* ------------------------------------------------------------------ *
 * THEME SWITCH                                                        *
 * ------------------------------------------------------------------ */
.bp-theme-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
}
.bp-switch {
  width: 46px;
  height: 24px;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  background-color: var(--bp-surface-2);
  border-radius: var(--bp-radius-sm);
  position: relative;
  cursor: pointer;
  padding: 0;
}
.bp-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background-color: var(--bp-accent);
  transition: left var(--bp-transition-fast);
}
[data-theme="light"] .bp-switch::after { left: 24px; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .bp-switch::after { left: 24px; }
}

/* ------------------------------------------------------------------ *
 * DIVIDERS / UTILITIES                                                *
 * ------------------------------------------------------------------ */
.bp-divider { height: 1px; background-color: var(--bp-line); border: 0; margin: var(--bp-space-4) 0; }
.bp-stack   { display: flex; flex-direction: column; gap: var(--bp-space-4); }
.bp-row     { display: flex; align-items: center; gap: var(--bp-space-3); }
.bp-row--between { justify-content: space-between; }
.bp-spacer  { flex: 1; }
.bp-cols-2  { display: grid; grid-template-columns: 1fr 1fr; gap: var(--bp-space-5); }
.bp-cols-3  { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--bp-space-5); }

/* ------------------------------------------------------------------ *
 * KEY-VALUE CHIP                                                      *
 *   Compact label/value pair for topbars and meta strips.             *
 * ------------------------------------------------------------------ */
.bp-chip {
  display: inline-flex;
  align-items: baseline;
  gap: var(--bp-space-2);
  padding: 3px var(--bp-space-2);
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  white-space: nowrap;
}
.bp-chip__label {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: var(--bp-tracking-wide);
  text-transform: uppercase;
  color: var(--bp-ink-faint);
}
.bp-chip__value {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  color: var(--bp-ink);
}
.bp-chip--muted .bp-chip__value { color: var(--bp-ink-dim); }

/* ------------------------------------------------------------------ *
 * DROPDOWN MENU                                                       *
 *   Anchored action menu (toolbar exports, row actions).              *
 * ------------------------------------------------------------------ */
.bp-menu { position: relative; display: inline-block; }
.bp-menu__items {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  min-width: 150px;
  z-index: var(--bp-z-overlay);
  padding: var(--bp-space-1) 0;
}
.bp-menu__items[hidden] { display: none; }
.bp-menu__item {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--bp-space-2) var(--bp-space-3);
  color: var(--bp-ink);
  background-color: transparent;
  border: none;
  text-decoration: none;
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-sm);
  cursor: pointer;
}
.bp-menu__item:hover { background-color: var(--bp-surface-2); }

/* ------------------------------------------------------------------ *
 * MODAL DIALOG                                                        *
 *   For native <dialog> elements.                                     *
 * ------------------------------------------------------------------ */
.bp-modal {
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  background-color: var(--bp-surface);
  color: var(--bp-ink);
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-base);
  line-height: var(--bp-leading-normal);
  padding: 0;
  max-width: 560px;
  width: 90vw;
}
.bp-modal--wide { max-width: 680px; }
.bp-modal::backdrop { background: var(--bp-scrim); }
.bp-modal__head {
  padding: var(--bp-space-4) var(--bp-space-5);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
}
.bp-modal__body {
  padding: var(--bp-space-4) var(--bp-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-4);
}
.bp-modal__foot {
  padding: var(--bp-space-3) var(--bp-space-5);
  border-top: var(--bp-border-width) solid var(--bp-line);
  display: flex;
  justify-content: flex-end;
  gap: var(--bp-space-2);
}

/* ------------------------------------------------------------------ *
 * PAGINATION                                                          *
 *   Compose with .bp-btn--sm buttons and .bp-select--auto.            *
 * ------------------------------------------------------------------ */
.bp-pager {
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
  padding: var(--bp-space-2) var(--bp-space-3);
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
  flex-wrap: wrap;
}
.bp-pager__total { margin-left: auto; }

/* ------------------------------------------------------------------ *
 * TABLE EXTENSIONS                                                    *
 *   Sortable headers, sticky header, group/divider rows, detail       *
 *   rows, selection cells, empty cells, action cells.                 *
 * ------------------------------------------------------------------ */
.bp-table--sortable thead th { cursor: pointer; user-select: none; white-space: nowrap; }
.bp-table--sortable thead th:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }
.bp-sort-indicator { margin-left: 4px; color: var(--bp-accent); font-family: var(--bp-font-mono); }

.bp-table--sticky thead th {
  position: sticky;
  top: 0;
  z-index: var(--bp-z-base);
  background-color: var(--bp-surface); /* opaque: rows scroll underneath */
}

.bp-table__group td {
  background-color: var(--bp-surface-2);
  cursor: pointer;
  user-select: none;
  font-weight: var(--bp-weight-medium);
  color: var(--bp-ink);
}
.bp-table__group:hover td { background-color: var(--bp-surface-3); }
.bp-table__group-toggle {
  display: inline-block;
  width: 14px;
  color: var(--bp-ink-dim);
  margin-right: var(--bp-space-1);
  font-family: var(--bp-font-mono);
}
.bp-table__group-meta {
  color: var(--bp-ink-dim);
  font-weight: var(--bp-weight-regular);
  margin-left: var(--bp-space-1);
  font-size: var(--bp-text-xs);
}

.bp-table__detail > td { background-color: var(--bp-bg); }

.bp-table__select { width: 28px; }
.bp-table__select input[type="checkbox"] { cursor: pointer; }
.bp-table__select input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.4; }

.bp-table__empty {
  text-align: center;
  padding: var(--bp-space-8);
  color: var(--bp-ink-dim);
}

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

/* ------------------------------------------------------------------ *
 * KEY-VALUE GRID                                                      *
 *   Definition-list layout for detail panes.                          *
 * ------------------------------------------------------------------ */
.bp-kv {
  display: grid;
  grid-template-columns: minmax(96px, max-content) 1fr;
  gap: var(--bp-space-2) var(--bp-space-4);
  align-items: start;
}
.bp-kv__key { color: var(--bp-ink-dim); }

/* ------------------------------------------------------------------ *
 * ACTIVITY PULSE                                                      *
 *   Live-activity indicator (compose with .bp-chip).                  *
 * ------------------------------------------------------------------ */
.bp-pulse {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--bp-accent);
  flex: none;
  animation: bp-pulse 1.2s infinite ease-in-out;
}
@keyframes bp-pulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}

/* ------------------------------------------------------------------ *
 * DISCLOSURE                                                          *
 *   For native <details>/<summary>.                                   *
 * ------------------------------------------------------------------ */
.bp-details {
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-md);
  background-color: var(--bp-surface);
}
.bp-details > summary {
  padding: var(--bp-space-2) var(--bp-space-3);
  cursor: pointer;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
  user-select: none;
}
.bp-details > summary:hover { color: var(--bp-ink); }
.bp-details[open] > summary { border-bottom: var(--bp-border-width) solid var(--bp-line); }
.bp-details__body { padding: var(--bp-space-3); }

/* ------------------------------------------------------------------ *
 * INLINE FEEDBACK                                                     *
 *   Transient status lines under forms and actions.                   *
 * ------------------------------------------------------------------ */
.bp-feedback { font-size: var(--bp-text-xs); min-height: 16px; color: var(--bp-ink-dim); }
.bp-feedback--ok   { color: var(--bp-ok); }
.bp-feedback--warn { color: var(--bp-warn); }
.bp-feedback--crit { color: var(--bp-crit); }

/* ------------------------------------------------------------------ *
 * RANGE SLIDER                                                        *
 * ------------------------------------------------------------------ */
.bp-range { accent-color: var(--bp-accent); width: 100%; max-width: 240px; }

/* ------------------------------------------------------------------ *
 * FORM LAYOUTS + WIDTH MODIFIERS                                      *
 * ------------------------------------------------------------------ */
.bp-form-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--bp-space-3) var(--bp-space-4);
  align-items: center;
}
.bp-form-row {
  display: flex;
  gap: var(--bp-space-2);
  flex-wrap: wrap;
  align-items: center;
}
.bp-choice {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  font-size: var(--bp-text-base);
  color: var(--bp-ink);
  cursor: pointer;
}
.bp-input--xs { width: 80px; }
.bp-input--sm { width: 140px; }
.bp-input--md { width: 240px; }
.bp-select--auto { width: auto; }

/* ------------------------------------------------------------------ *
 * TAG EXTENSIONS                                                      *
 * ------------------------------------------------------------------ */
.bp-tag__count { color: var(--bp-ink-faint); margin-left: var(--bp-space-1); }
.bp-tag--info {
  color: var(--bp-accent);
  border-color: color-mix(in srgb, var(--bp-accent) 45%, transparent);
}
.bp-tag-btn {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-ink-dim);
  background-color: transparent;
  border: var(--bp-border-width) dashed var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: 1px var(--bp-space-2);
  display: inline-block;
  cursor: pointer;
  user-select: none;
}
.bp-tag-btn:hover { color: var(--bp-ink); border-color: var(--bp-ink-faint); }
.bp-tag-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-space-2);
  align-items: center;
}

/* ------------------------------------------------------------------ *
 * STATUS EXTENSIONS                                                   *
 *   Info (accent) and neutral variants for dots and pills.            *
 *   "high" is the fourth severity level (between crit and warn),     *
 *   used by vulnerability-management surfaces (CVSS High).            *
 * ------------------------------------------------------------------ */
.bp-dot--info    { background-color: var(--bp-accent); }
.bp-dot--neutral { background-color: var(--bp-ink-faint); }
.bp-dot--high    { background-color: var(--bp-high); }
.bp-pill--info {
  color: var(--bp-accent);
  border-color: color-mix(in srgb, var(--bp-accent) 45%, transparent);
}
.bp-pill--high {
  color: var(--bp-high);
  border-color: color-mix(in srgb, var(--bp-high) 45%, transparent);
}
.bp-tag--high {
  color: var(--bp-high);
  border-color: color-mix(in srgb, var(--bp-high) 45%, transparent);
}
.bp-alert--high    { border-left-color: var(--bp-high); }
.bp-bar__fill--high { background-color: var(--bp-high); }
.bp-feedback--high { color: var(--bp-high); }

/* ------------------------------------------------------------------ *
 * ICON BUTTON                                                         *
 *   Square icon-only action button (toolbars, topbars, table rows).   *
 *   Compose with .bp-btn--ghost for borderless variant.               *
 * ------------------------------------------------------------------ */
.bp-btn--icon {
  width: 32px;
  height: 32px;
  padding: 0;
  justify-content: center;
}
.bp-btn--icon.bp-btn--lg { width: 40px; height: 40px; }
.bp-btn--icon.bp-btn--sm { width: 26px; height: 26px; }

/* ------------------------------------------------------------------ *
 * ANCHORED BADGE                                                      *
 *   Counter pinned to the corner of an icon button or avatar.         *
 *   <span class="bp-badge-anchor"><button class="bp-btn bp-btn--icon">
 *     …</button><span class="bp-badge bp-badge--float">3</span></span> *
 * ------------------------------------------------------------------ */
.bp-badge-anchor { position: relative; display: inline-flex; }
.bp-badge--float {
  position: absolute;
  top: -5px;
  right: -5px;
  z-index: var(--bp-z-base);
  pointer-events: none;
}
.bp-badge--crit { background-color: var(--bp-crit); color: #ffffff; }

/* ------------------------------------------------------------------ *
 * TABS                                                                *
 *   Underline tab bar. Buttons or links; mark active with .is-active  *
 *   and aria-selected="true".                                         *
 * ------------------------------------------------------------------ */
.bp-tabs {
  display: flex;
  gap: var(--bp-space-1);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}
.bp-tab {
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-base);
  font-weight: var(--bp-weight-medium);
  color: var(--bp-ink-dim);
  background-color: transparent;
  border: none;
  border-bottom: var(--bp-border-width-accent) solid transparent;
  margin-bottom: calc(-1 * var(--bp-border-width));
  padding: var(--bp-space-2) var(--bp-space-4) var(--bp-space-3);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--bp-transition-fast),
    border-color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-tab:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }
.bp-tab.is-active {
  color: var(--bp-accent);
  border-bottom-color: var(--bp-accent);
}
.bp-tabs--scroll {
  overflow-x: auto;
  scrollbar-width: none;
}
.bp-tabs--scroll::-webkit-scrollbar { display: none; }

/* ------------------------------------------------------------------ *
 * NAV RAIL                                                            *
 *   Compact icon-first vertical navigation (alternative to            *
 *   .bp-sidebar for dense admin surfaces). Items stack icon over      *
 *   label; active item gets the accent edge.                          *
 * ------------------------------------------------------------------ */
.bp-rail {
  width: 72px;
  border-right: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: var(--bp-space-2) 0;
  overflow-y: auto;
  overflow-x: hidden;
}
.bp-rail__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--bp-space-2) var(--bp-space-1);
  color: var(--bp-ink-dim);
  background-color: transparent;
  border: none;
  border-left: var(--bp-border-width-accent) solid transparent;
  text-decoration: none;
  cursor: pointer;
  font-family: var(--bp-font-sans);
  transition: background-color var(--bp-transition-fast),
    color var(--bp-transition-fast);
}
.bp-rail__item:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }
.bp-rail__item.is-active {
  color: var(--bp-accent);
  background-color: var(--bp-accent-faint);
  border-left-color: var(--bp-accent);
}
.bp-rail__icon { width: 18px; height: 18px; flex: none; }
.bp-rail__label {
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  line-height: var(--bp-leading-tight);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
}
.bp-rail__divider {
  height: 1px;
  background-color: var(--bp-line);
  border: 0;
  margin: var(--bp-space-2) var(--bp-space-3);
}

/* ------------------------------------------------------------------ *
 * DRAWER / SLIDE-OVER                                                 *
 *   Edge-anchored panel over a scrim (contextual help, mobile nav,    *
 *   detail panes). Toggle visibility with the .is-open class.         *
 * ------------------------------------------------------------------ */
.bp-drawer-scrim {
  position: fixed;
  inset: 0;
  background-color: var(--bp-scrim);
  z-index: var(--bp-z-overlay);
  display: none;
}
.bp-drawer-scrim.is-open { display: block; }
.bp-drawer {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  width: 420px;
  max-width: 92vw;
  background-color: var(--bp-surface);
  border-left: var(--bp-border-width) solid var(--bp-line-strong);
  z-index: calc(var(--bp-z-overlay) + 1);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--bp-transition);
}
.bp-drawer--left {
  right: auto;
  left: 0;
  border-left: none;
  border-right: var(--bp-border-width) solid var(--bp-line-strong);
  transform: translateX(-100%);
}
.bp-drawer.is-open { transform: translateX(0); }
.bp-drawer__head {
  padding: var(--bp-space-4) var(--bp-space-5);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
  flex: none;
}
.bp-drawer__head .bp-spacer { flex: 1; }
.bp-drawer__body {
  padding: var(--bp-space-4) var(--bp-space-5);
  overflow-y: auto;
  flex: 1;
}
.bp-drawer__foot {
  padding: var(--bp-space-3) var(--bp-space-5);
  border-top: var(--bp-border-width) solid var(--bp-line);
  flex: none;
}

/* ------------------------------------------------------------------ *
 * COMBOBOX / AUTOCOMPLETE                                             *
 *   Suggestion list anchored under a .bp-input. Wrap the input in     *
 *   .bp-combobox; toggle the list with [hidden].                      *
 * ------------------------------------------------------------------ */
.bp-combobox { position: relative; }
.bp-combobox__list {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  max-height: 240px;
  overflow-y: auto;
  z-index: var(--bp-z-overlay);
  margin: 0;
  padding: var(--bp-space-1) 0;
  list-style: none;
}
.bp-combobox__list[hidden] { display: none; }
.bp-combobox__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-space-3);
  width: 100%;
  text-align: left;
  padding: var(--bp-space-2) var(--bp-space-3);
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
  background-color: transparent;
  border: none;
  cursor: pointer;
}
.bp-combobox__item:hover,
.bp-combobox__item.is-active { background-color: var(--bp-surface-2); }
.bp-combobox__meta {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-ink-faint);
}

/* ------------------------------------------------------------------ *
 * SPINNER                                                             *
 *   Indeterminate loading indicator. Pair with .bp-visually-hidden    *
 *   text or aria-label for screen readers.                            *
 * ------------------------------------------------------------------ */
.bp-spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--bp-line-strong);
  border-top-color: var(--bp-accent);
  border-radius: 50%;
  animation: bp-spin 0.8s linear infinite;
  flex: none;
}
.bp-spinner--lg { width: 28px; height: 28px; }
@keyframes bp-spin {
  to { transform: rotate(360deg); }
}

/* ------------------------------------------------------------------ *
 * ACCESSIBILITY                                                       *
 * ------------------------------------------------------------------ */
.bp-root :focus-visible,
.bp-btn:focus-visible,
.bp-toggle:focus-visible,
.bp-switch:focus-visible,
.bp-nav__link:focus-visible,
.bp-tab:focus-visible,
.bp-rail__item:focus-visible,
.bp-combobox__item:focus-visible,
.bp-cal__day:focus-visible,
.bp-command__item:focus-visible,
.bp-toast__close:focus-visible,
.bp-token__remove:focus-visible,
.bp-link:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

.bp-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ *
 * RESPONSIVE                                                          *
 * ------------------------------------------------------------------ */
@media (max-width: 1080px) {
  .bp-stat-strip { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: 1fr 1fr; }
  .bp-stat { border-right: none; border-bottom: var(--bp-border-width) solid var(--bp-line); }
  .bp-cols-3 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 860px) {
  .bp-app { grid-template-columns: 1fr; }
  .bp-sidebar { position: static; height: auto; }
  .bp-cols-2, .bp-cols-3 { grid-template-columns: 1fr; }
  .bp-stat-strip { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .bp-root *,
  .bp-root *::before,
  .bp-root *::after {
    transition: none !important;
    animation: none !important;
  }
}

/* ------------------------------------------------------------------ *
 * TOOLTIP                                                             *
 *   Small anchored hint. Position with your JS lib of choice or       *
 *   wrap the trigger in a relatively positioned container.            *
 * ------------------------------------------------------------------ */
.bp-tooltip {
  background-color: var(--bp-surface-3);
  color: var(--bp-ink);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-xs);
  line-height: var(--bp-leading-snug);
  padding: var(--bp-space-1) var(--bp-space-2);
  max-width: 280px;
  z-index: var(--bp-z-toast);
  pointer-events: none;
}

/* ------------------------------------------------------------------ *
 * POPOVER                                                             *
 *   Generic anchored surface (filters, pickers, rich hover cards).    *
 *   Position relative to a .bp-popover-anchor wrapper; toggle with    *
 *   [hidden].                                                         *
 * ------------------------------------------------------------------ */
.bp-popover-anchor { position: relative; display: inline-block; }
.bp-popover {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-4);
  min-width: 220px;
  z-index: var(--bp-z-overlay);
}
.bp-popover[hidden] { display: none; }
.bp-popover--right { left: auto; right: 0; }

/* ------------------------------------------------------------------ *
 * SKELETON                                                            *
 *   Loading placeholder. Flat pulse — no gradient shimmer, in line    *
 *   with the no-gradients rule.                                       *
 * ------------------------------------------------------------------ */
.bp-skeleton {
  background-color: var(--bp-surface-3);
  border-radius: var(--bp-radius-sm);
  animation: bp-skeleton-pulse 1.4s infinite ease-in-out;
}
.bp-skeleton--text   { height: 0.9em; width: 100%; }
.bp-skeleton--circle { border-radius: 50%; }
@keyframes bp-skeleton-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

/* ------------------------------------------------------------------ *
 * TOASTS                                                              *
 *   Transient notifications. Fixed stack bottom-right; severity via   *
 *   the same left-edge language as .bp-alert.                         *
 * ------------------------------------------------------------------ */
.bp-toasts {
  position: fixed;
  bottom: var(--bp-space-5);
  right: var(--bp-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-2);
  z-index: var(--bp-z-toast);
  width: 340px;
  max-width: calc(100vw - 2 * var(--bp-space-5));
}
.bp-toast {
  display: flex;
  gap: var(--bp-space-3);
  align-items: flex-start;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-left-width: 3px;
  border-left-color: var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-3) var(--bp-space-4);
  font-size: var(--bp-text-sm);
}
.bp-toast--ok   { border-left-color: var(--bp-ok); }
.bp-toast--warn { border-left-color: var(--bp-warn); }
.bp-toast--crit { border-left-color: var(--bp-crit); }
.bp-toast__body { flex: 1; min-width: 0; }
.bp-toast__body b { font-weight: var(--bp-weight-semibold); display: block; }
.bp-toast__body small { color: var(--bp-ink-dim); }
.bp-toast__close {
  background: transparent;
  border: none;
  color: var(--bp-ink-faint);
  cursor: pointer;
  padding: 0;
  font-size: var(--bp-text-base);
  line-height: 1;
  flex: none;
}
.bp-toast__close:hover { color: var(--bp-ink); }

/* ------------------------------------------------------------------ *
 * CALENDAR / DATE PICKER                                              *
 *   7-column day grid. Compose the header nav with .bp-btn--icon      *
 *   .bp-btn--sm .bp-btn--ghost. Mark states with .is-today,           *
 *   .is-selected, .is-range, .is-outside.                             *
 * ------------------------------------------------------------------ */
.bp-cal {
  display: inline-block;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-md);
  padding: var(--bp-space-3);
}
.bp-cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-space-2);
  margin-bottom: var(--bp-space-2);
}
.bp-cal__month {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  letter-spacing: var(--bp-tracking-wide);
  text-transform: uppercase;
  color: var(--bp-ink-dim);
}
.bp-cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 30px);
  gap: 2px;
}
.bp-cal__dow {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-ink-faint);
  text-align: center;
  padding: var(--bp-space-1) 0;
  text-transform: uppercase;
}
.bp-cal__day {
  width: 30px;
  height: 28px;
  display: grid;
  place-items: center;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background-color: transparent;
  border: var(--bp-border-width) solid transparent;
  border-radius: var(--bp-radius-sm);
  cursor: pointer;
  padding: 0;
}
.bp-cal__day:hover { background-color: var(--bp-surface-2); }
.bp-cal__day.is-outside { color: var(--bp-ink-faint); }
.bp-cal__day.is-today { border-color: var(--bp-accent); color: var(--bp-accent); }
.bp-cal__day.is-range { background-color: var(--bp-accent-faint); }
.bp-cal__day.is-selected {
  background-color: var(--bp-accent);
  color: var(--bp-on-accent);
}
.bp-cal__day:disabled { color: var(--bp-ink-faint); opacity: 0.45; cursor: not-allowed; }

/* ------------------------------------------------------------------ *
 * KBD                                                                 *
 *   Keyboard hint chip (shortcuts, command palettes).                 *
 * ------------------------------------------------------------------ */
.bp-kbd {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-ink-dim);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-bottom-width: 2px;
  border-radius: var(--bp-radius-sm);
  padding: 1px 5px;
  display: inline-block;
  line-height: var(--bp-leading-tight);
}

/* ------------------------------------------------------------------ *
 * COMMAND PALETTE                                                     *
 *   Searchable action list (open inside .bp-modal or a fixed          *
 *   overlay). Group headings reuse the eyebrow language; items        *
 *   mirror .bp-combobox__item.                                        *
 * ------------------------------------------------------------------ */
.bp-command {
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  width: 560px;
  max-width: 92vw;
  overflow: hidden;
}
.bp-command__input {
  width: 100%;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
  background-color: transparent;
  border: none;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  padding: var(--bp-space-3) var(--bp-space-4);
  outline: none;
}
.bp-command__input::placeholder { color: var(--bp-ink-faint); }
.bp-command__list {
  max-height: 320px;
  overflow-y: auto;
  padding: var(--bp-space-1) 0 var(--bp-space-2);
  margin: 0;
  list-style: none;
}
.bp-command__group {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: var(--bp-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  padding: var(--bp-space-3) var(--bp-space-4) var(--bp-space-1);
}
.bp-command__item {
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
  width: 100%;
  text-align: left;
  padding: var(--bp-space-2) var(--bp-space-4);
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
  background-color: transparent;
  border: none;
  cursor: pointer;
}
.bp-command__item:hover,
.bp-command__item.is-active { background-color: var(--bp-surface-2); }
.bp-command__item .bp-kbd { margin-left: auto; }
.bp-command__empty {
  padding: var(--bp-space-6);
  text-align: center;
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}

/* ------------------------------------------------------------------ *
 * TOKEN FIELD (MULTI-SELECT)                                          *
 *   Input-like wrapper holding removable value tokens plus a bare     *
 *   text input. Pair with .bp-combobox for suggestions.               *
 * ------------------------------------------------------------------ */
.bp-token-field {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-space-1);
  align-items: center;
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-1) var(--bp-space-2);
  min-height: 34px;
  cursor: text;
}
.bp-token-field:focus-within {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 1px;
  border-color: var(--bp-accent);
}
.bp-token-field__input {
  flex: 1;
  min-width: 80px;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background: transparent;
  border: none;
  outline: none;
  padding: var(--bp-space-1);
}
.bp-token {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-1);
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-ink);
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: 1px var(--bp-space-2);
}
.bp-token__remove {
  background: transparent;
  border: none;
  color: var(--bp-ink-faint);
  cursor: pointer;
  padding: 0;
  font-size: var(--bp-text-xs);
  line-height: 1;
}
.bp-token__remove:hover { color: var(--bp-crit); }

/* ------------------------------------------------------------------ *
 * SLIDER (CUSTOM)                                                     *
 *   Track/fill/thumb parts for JS-driven sliders. For native          *
 *   input[type=range] use .bp-range instead.                          *
 * ------------------------------------------------------------------ */
.bp-slider {
  position: relative;
  height: 16px;
  display: flex;
  align-items: center;
  touch-action: none;
  user-select: none;
}
.bp-slider__track {
  position: relative;
  flex: 1;
  height: 4px;
  background-color: var(--bp-surface-3);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  overflow: hidden;
}
.bp-slider__fill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  background-color: var(--bp-accent);
}
.bp-slider__thumb {
  position: absolute;
  width: 12px;
  height: 12px;
  background-color: var(--bp-surface);
  border: var(--bp-border-width-accent) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  transform: translateX(-50%);
  cursor: grab;
}
.bp-slider__thumb:active { cursor: grabbing; }
.bp-slider__thumb:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ *
 * SPLITTER                                                            *
 *   Resizable-pane divider handle. Vertical by default (between       *
 *   columns); add --h for horizontal (between rows).                  *
 * ------------------------------------------------------------------ */
.bp-splitter {
  flex: none;
  width: 5px;
  cursor: col-resize;
  background-color: transparent;
  border-left: var(--bp-border-width) solid var(--bp-line);
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast);
}
.bp-splitter--h {
  width: auto;
  height: 5px;
  cursor: row-resize;
  border-left: none;
  border-top: var(--bp-border-width) solid var(--bp-line);
}
.bp-splitter:hover,
.bp-splitter.is-dragging {
  background-color: var(--bp-accent-faint);
  border-color: var(--bp-accent);
}

/* ------------------------------------------------------------------ *
 * APP SHELL — RAIL VARIANT                                            *
 *   Use with .bp-rail as the first grid column instead of             *
 *   .bp-sidebar: <div class="bp-app bp-app--rail">.                   *
 * ------------------------------------------------------------------ */
.bp-app--rail {
  grid-template-columns: var(--bp-rail-width) 1fr;
}
.bp-app--rail .bp-rail {
  position: sticky;
  top: 0;
  height: 100vh;
}

/* ------------------------------------------------------------------ *
 * TABBAR (MOBILE BOTTOM NAV)                                          *
 *   Fixed bottom icon+label navigation for small viewports. Hidden    *
 *   on desktop; below 860px it replaces .bp-rail (pair both in the    *
 *   same shell). Mark the current item with .is-active.               *
 * ------------------------------------------------------------------ */
.bp-tabbar {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  min-height: var(--bp-tabbar-height);
  background-color: var(--bp-surface);
  border-top: var(--bp-border-width) solid var(--bp-line);
  z-index: var(--bp-z-sticky);
}
.bp-tabbar__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--bp-space-2) var(--bp-space-1);
  color: var(--bp-ink-dim);
  background-color: transparent;
  border: none;
  border-top: var(--bp-border-width-accent) solid transparent;
  text-decoration: none;
  cursor: pointer;
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  line-height: var(--bp-leading-tight);
  transition: color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-tabbar__item:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }
.bp-tabbar__item.is-active {
  color: var(--bp-accent);
  background-color: var(--bp-accent-faint);
  border-top-color: var(--bp-accent);
}
.bp-tabbar__icon { width: 18px; height: 18px; flex: none; }
@media (max-width: 860px) {
  .bp-tabbar { display: flex; }
  .bp-rail { display: none; }
  .bp-app--rail { grid-template-columns: 1fr; }
  .bp-app--rail .bp-content { padding-bottom: calc(var(--bp-tabbar-height) + var(--bp-space-8)); }
}

/* ------------------------------------------------------------------ *
 * FOOTER                                                              *
 *   Quiet page footer for user-facing surfaces.                       *
 * ------------------------------------------------------------------ */
.bp-footer {
  border-top: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  padding: var(--bp-space-4) var(--bp-space-6);
  text-align: center;
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-faint);
}

/* ------------------------------------------------------------------ *
 * AUTH CANVAS                                                         *
 *   Full-viewport centered layout for sign-in, MFA, and setup         *
 *   screens: brand header on top, a single centered card, optional    *
 *   .bp-footer at the bottom.                                         *
 * ------------------------------------------------------------------ */
.bp-auth {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.bp-auth__brand {
  padding: var(--bp-space-6);
  text-align: center;
  font-size: var(--bp-text-lg);
  font-weight: var(--bp-weight-bold);
  letter-spacing: var(--bp-tracking-tight);
  color: var(--bp-ink);
}
.bp-auth__main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--bp-space-4);
}
.bp-auth__card { width: 100%; max-width: 400px; }
.bp-auth__card--wide { max-width: 560px; }

/* ------------------------------------------------------------------ *
 * OTP INPUT                                                           *
 *   One-time-code entry (TOTP, backup codes). Compose with            *
 *   .bp-input: <input class="bp-input bp-input--otp" inputmode=       *
 *   "numeric" autocomplete="one-time-code">.                          *
 * ------------------------------------------------------------------ */
.bp-input--otp {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-lg);
  letter-spacing: 0.35em;
  text-align: center;
}

/* ------------------------------------------------------------------ *
 * CODE GRID                                                           *
 *   Grid of short one-time codes (recovery / backup codes). Items     *
 *   reuse the .bp-code language at a readable size.                   *
 * ------------------------------------------------------------------ */
.bp-code-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--bp-space-2);
}
.bp-code-grid .bp-code {
  display: block;
  text-align: center;
  font-size: var(--bp-text-sm);
  padding: var(--bp-space-2) var(--bp-space-3);
}

/* ------------------------------------------------------------------ *
 * TOPNAV                                                              *
 *   Horizontal top navigation shell (alternative to .bp-sidebar /     *
 *   .bp-rail for link-driven apps). Brand left, links center,         *
 *   .bp-topnav__user pushes to the right. Mark the current link       *
 *   with .is-active.                                                  *
 * ------------------------------------------------------------------ */
.bp-topnav {
  display: flex;
  align-items: stretch;
  gap: var(--bp-space-6);
  height: var(--bp-topbar-height);
  padding: 0 var(--bp-space-6);
  background-color: var(--bp-surface);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  position: sticky;
  top: 0;
  z-index: var(--bp-z-sticky);
}
.bp-topnav__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  font-weight: var(--bp-weight-semibold);
  color: var(--bp-ink);
  white-space: nowrap;
}
.bp-topnav__nav {
  display: flex;
  align-items: stretch;
  gap: var(--bp-space-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.bp-topnav__nav::-webkit-scrollbar { display: none; }
.bp-topnav__link {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--bp-space-3);
  color: var(--bp-ink-dim);
  text-decoration: none;
  font-size: var(--bp-text-base);
  border-bottom: var(--bp-border-width-accent) solid transparent;
  white-space: nowrap;
  transition: color var(--bp-transition-fast),
    background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast);
}
.bp-topnav__link:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }
.bp-topnav__link.is-active {
  color: var(--bp-accent);
  border-bottom-color: var(--bp-accent);
}
.bp-topnav__user {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--bp-space-3);
  font-size: var(--bp-text-sm);
  white-space: nowrap;
}

/* ------------------------------------------------------------------ *
 * STAT GRID                                                           *
 *   Responsive auto-fit grid of standalone stat cards. Children       *
 *   reuse .bp-stat; unlike .bp-stat-strip each cell is its own        *
 *   bordered card.                                                    *
 * ------------------------------------------------------------------ */
.bp-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--bp-space-3);
}
.bp-stat-grid > .bp-stat {
  border: var(--bp-border-width) solid var(--bp-line);
  background-color: var(--bp-surface);
  border-radius: var(--bp-radius-md);
}

/* ------------------------------------------------------------------ *
 * CHARTBOX                                                            *
 *   Fixed-height positioning container for canvas charts.             *
 * ------------------------------------------------------------------ */
.bp-chartbox { position: relative; height: 240px; }
.bp-chartbox--sm { height: 120px; }
.bp-chartbox--lg { height: 360px; }

/* ------------------------------------------------------------------ *
 * PAGE HEAD                                                           *
 *   Page title row: heading left, actions right.                      *
 * ------------------------------------------------------------------ */
.bp-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-space-4);
  flex-wrap: wrap;
  margin-bottom: var(--bp-space-5);
}
.bp-page-head h1 { margin: 0; }

/* ------------------------------------------------------------------ *
 * TOOLBAR                                                             *
 *   Filter/action row above tables. Fields align on their baseline    *
 *   (labels above inputs); compose with .bp-field and .bp-btn.        *
 * ------------------------------------------------------------------ */
.bp-toolbar {
  display: flex;
  gap: var(--bp-space-3);
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: var(--bp-space-4);
}
.bp-toolbar .bp-field { min-width: 150px; }

/* ------------------------------------------------------------------ *
 * FORM COLUMNS                                                        *
 *   Responsive auto-fit grid of form fields (dense record forms).     *
 * ------------------------------------------------------------------ */
.bp-form-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--bp-space-2) var(--bp-space-5);
  align-items: start;
}

/* ------------------------------------------------------------------ *
 * STACKED FORM                                                        *
 *   Plain markup form (label followed by control) without per-field   *
 *   wrappers. Direct labels take the .bp-label language.              *
 * ------------------------------------------------------------------ */
.bp-form--stacked label {
  display: block;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  margin: var(--bp-space-3) 0 var(--bp-space-1);
}

/* ------------------------------------------------------------------ *
 * PANEL — PADDED VARIANT                                              *
 *   Standalone content card without head/body/foot structure.         *
 * ------------------------------------------------------------------ */
.bp-panel--pad { padding: var(--bp-space-5); }
.bp-panel--pad + .bp-panel--pad,
.bp-panel + .bp-panel { margin-top: var(--bp-space-4); }

/* ------------------------------------------------------------------ *
 * PROSE                                                               *
 *   Long-form rendered content (markdown bodies, help pages).         *
 * ------------------------------------------------------------------ */
.bp-prose { line-height: var(--bp-leading-normal); font-size: var(--bp-text-base); }
.bp-prose h1, .bp-prose h2, .bp-prose h3 { margin: var(--bp-space-4) 0 var(--bp-space-2); }
.bp-prose h1 { font-size: var(--bp-text-lg); }
.bp-prose h2 { font-size: var(--bp-text-md); }
.bp-prose h3 { font-size: var(--bp-text-base); }
.bp-prose p { margin: var(--bp-space-2) 0; }
.bp-prose pre {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-3) var(--bp-space-4);
  overflow-x: auto;
}
.bp-prose code {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  background-color: var(--bp-surface-2);
  border-radius: var(--bp-radius-sm);
  padding: 1px 5px;
}
.bp-prose pre code { background: none; border: none; padding: 0; }
.bp-prose blockquote {
  border-left: 3px solid var(--bp-line-strong);
  margin: var(--bp-space-2) 0;
  padding: 2px var(--bp-space-3);
  color: var(--bp-ink-dim);
}
.bp-prose table { width: auto; border-collapse: collapse; margin: var(--bp-space-2) 0; }
.bp-prose table td, .bp-prose table th {
  border: var(--bp-border-width) solid var(--bp-line);
  padding: var(--bp-space-1) var(--bp-space-3);
}
.bp-prose ul, .bp-prose ol { padding-left: 22px; }

/* ------------------------------------------------------------------ *
 * DROPZONE                                                            *
 *   Drag-and-drop file target. Toggle .is-dragover from JS.           *
 * ------------------------------------------------------------------ */
.bp-dropzone {
  border: var(--bp-border-width) dashed var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  padding: var(--bp-space-6);
  text-align: center;
  color: var(--bp-ink-dim);
  background-color: var(--bp-surface);
}
.bp-dropzone.is-dragover {
  border-color: var(--bp-accent);
  background-color: var(--bp-accent-faint);
  color: var(--bp-ink);
}

/* ------------------------------------------------------------------ *
 * TEXT / CELL UTILITIES                                               *
 * ------------------------------------------------------------------ */
.bp-num { text-align: right; font-variant-numeric: tabular-nums; }
.bp-text-right  { text-align: right; }
.bp-text-accent { color: var(--bp-accent); }
.bp-text-ok     { color: var(--bp-ok); }
.bp-text-warn   { color: var(--bp-warn); }
.bp-text-crit   { color: var(--bp-crit); }
.bp-delta--flat { color: var(--bp-ink-faint); font-family: var(--bp-font-mono); }
.bp-btn-row--end { justify-content: flex-end; }

/* ==================================================================== *
 *  GUACAMOLE ADDITIONS — 2026-07-09                                     *
 *  18 components added for the Guacamole portal re-skin. Generated      *
 *  against the screen inventory of Apache Guacamole 1.6.0, per-control  *
 *  adversarially reviewed, then cross-reviewed as a set.                *
 *  Icon set is first: dependents override its mask-size and glyph.      *
 * ==================================================================== */
/* ------------------------------------------------------------------ *
 * ICON SET                                                            *
 *   Monochrome glyphs delivered as inline SVG masks. The mask only    *
 *   contributes alpha — the painted color is always currentColor —    *
 *   so icons tint from --bp-ink/-dim/-faint, --bp-accent, --bp-crit   *
 *   (via color on the icon or any ancestor) and follow theme          *
 *   switches automatically. The 'black' inside the data URIs is       *
 *   mask alpha data, never a rendered color.                          *
 *   Compose with existing slots (.bp-btn__icon, .bp-rail__icon):      *
 *   base sizing uses :where() so slot sizes always win regardless     *
 *   of source order; use --sm/--lg/--box to size explicitly.          *
 *   The element must be empty; decorative icons take aria-hidden.     *
 *   Without a glyph modifier the icon renders as a solid square —     *
 *   intentional "tofu" so missing glyphs are visible at a glance.     *
 *   To serve glyphs as extension files instead of data URIs,          *
 *   re-point --bp-icon-glyph at the hosted asset per glyph class.     *
 * ------------------------------------------------------------------ */
.bp-icon {
  display: inline-block;
  flex: none;
  vertical-align: -0.15em;
  background-color: currentColor;
  -webkit-mask-image: var(--bp-icon-glyph, none);
  mask-image: var(--bp-icon-glyph, none);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  transition: transform var(--bp-transition-fast);
}
:where(.bp-icon) { width: 16px; height: 16px; }

.bp-icon--sm { width: 14px; height: 14px; }
.bp-icon--lg { width: 24px; height: 24px; }

/* 24px box with a 16px centered glyph — maps 1:1 onto Guacamole's
   .icon geometry (ui.css: 24px box, 16px background-size). */
.bp-icon--box {
  width: 24px;
  height: 24px;
  -webkit-mask-size: 16px 16px;
  mask-size: 16px 16px;
}

/* disclosure rotation — tree carets, collapsible sections */
.bp-icon.is-turned { transform: rotate(90deg); }

/* glyphs — navigation */
.bp-icon--chevron-up      { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 15l7-7 7 7'/%3E%3C/svg%3E"); }
.bp-icon--chevron-down    { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E"); }
.bp-icon--chevron-left    { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E"); }
.bp-icon--chevron-right   { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E"); }
.bp-icon--chevrons-left   { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M18 5l-7 7 7 7M11 5l-7 7 7 7'/%3E%3C/svg%3E"); }
.bp-icon--chevrons-right  { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 5l7 7-7 7M13 5l7 7-7 7'/%3E%3C/svg%3E"); }
.bp-icon--arrow-up        { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 20.5V4.5M5.5 11L12 4.5 18.5 11'/%3E%3C/svg%3E"); }
.bp-icon--arrow-down      { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5v16M5.5 13L12 19.5 18.5 13'/%3E%3C/svg%3E"); }
.bp-icon--home            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E"); }
.bp-icon--logout          { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M10 4.5H4.5v15H10M20 12H9.5M16 8l4 4-4 4'/%3E%3C/svg%3E"); }
.bp-icon--fullscreen      { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 9.5V4h5.5M14.5 4H20v5.5M20 14.5V20h-5.5M9.5 20H4v-5.5'/%3E%3C/svg%3E"); }

/* glyphs — actions */
.bp-icon--search          { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5L21 21'/%3E%3C/svg%3E"); }
.bp-icon--eye             { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M2 12c2.6-4.7 6-7 10-7s7.4 2.3 10 7c-2.6 4.7-6 7-10 7s-7.4-2.3-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E"); }
.bp-icon--eye-off         { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M2 12c2.6-4.7 6-7 10-7s7.4 2.3 10 7c-2.6 4.7-6 7-10 7s-7.4-2.3-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M4 3.5l16 17'/%3E%3C/svg%3E"); }
.bp-icon--x               { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E"); }
.bp-icon--plus            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E"); }
.bp-icon--check           { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 12.5l5.5 5.5L20 7'/%3E%3C/svg%3E"); }
.bp-icon--lock            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='4.5' y='11' width='15' height='9.5'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E"); }
.bp-icon--question        { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.3 9.2a2.8 2.8 0 1 1 4.5 2.2c-1 .8-1.8 1.4-1.8 2.6'/%3E%3Ccircle cx='12' cy='17.6' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E"); }
.bp-icon--import          { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5V14M7.5 9.5l4.5 4.5 4.5-4.5M3.5 16.5v4h17v-4'/%3E%3C/svg%3E"); }
.bp-icon--upload          { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 14V3.5M7.5 8L12 3.5 16.5 8M3.5 16.5v4h17v-4'/%3E%3C/svg%3E"); }

/* glyphs — objects (list items, protocols, user menu) */
.bp-icon--user            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E"); }
.bp-icon--users           { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E"); }
.bp-icon--user-plus       { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='9.5' cy='7.5' r='4'/%3E%3Cpath d='M2.5 20.5c.7-4 3.4-6.5 7-6.5s6.3 2.5 7 6.5M18.5 4v6M15.5 7h6'/%3E%3C/svg%3E"); }
.bp-icon--users-plus      { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15.5 15c2.3.7 3.7 2.4 4 5M18.5 3.5v6M15.5 6.5h6'/%3E%3C/svg%3E"); }
.bp-icon--folder          { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E"); }
.bp-icon--folder-open     { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 19V5.5h6.5l2 3H19v2M3 19l2.7-8.5H22L19.2 19z'/%3E%3C/svg%3E"); }
.bp-icon--folder-plus     { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3zM12 10.5v5M9.5 13h5'/%3E%3C/svg%3E"); }
.bp-icon--display         { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E"); }
.bp-icon--display-plus    { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M12 7.5v6.5M8.75 10.75h6.5M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E"); }
.bp-icon--terminal        { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E"); }
.bp-icon--kubernetes      { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E"); }
.bp-icon--balancer        { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E"); }
.bp-icon--plug            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E"); }
.bp-icon--keyboard        { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2' y='6' width='20' height='12'/%3E%3Cpath d='M5 9.5h1M8 9.5h1M11 9.5h1M14 9.5h1M17 9.5h1M5 12.5h1M8 12.5h1M11 12.5h1M14 12.5h1M17 12.5h1M8 15.5h8'/%3E%3C/svg%3E"); }
.bp-icon--gear            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='3.5'/%3E%3Cpath d='M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.3 5.3l2.1 2.1M16.6 16.6l2.1 2.1M18.7 5.3l-2.1 2.1M7.4 16.6l-2.1 2.1'/%3E%3C/svg%3E"); }

/* glyphs — media (recording player, history play link) */
.bp-icon--play            { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.5 4.5l12 7.5-12 7.5z' fill='black'/%3E%3C/svg%3E"); }
.bp-icon--pause           { --bp-icon-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 4.5h4v15h-4zM13.5 4.5h4v15h-4z' fill='black'/%3E%3C/svg%3E"); }

/* ------------------------------------------------------------------ *
 * TREE VIEW                                                           *
 *   Recursive nested list — connection group trees, permission        *
 *   trees, location choosers. Pure presentation: the host app owns    *
 *   expand/collapse behavior (Guacamole's .expandable/.expanded/      *
 *   .empty/.children map directly onto these classes). Slots:         *
 *   leading .bp-checkbox or .bp-tree__icon, trailing .bp-badge or     *
 *   .bp-tree__count. Paged children compose .bp-pager.                *
 * ------------------------------------------------------------------ */
.bp-tree {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--bp-text-base);
}
.bp-tree__node { margin: 0; }

/* caption — the interactive row for a node */
.bp-tree__caption {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  padding: var(--bp-space-1) var(--bp-space-2);
  color: var(--bp-ink-dim);
  text-decoration: none;
  border-left: var(--bp-border-width-accent) solid transparent;
  cursor: pointer;
  transition: background-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.bp-tree__caption:hover { background-color: var(--bp-surface-2); color: var(--bp-ink); }
.bp-tree__caption:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* active node — accent left edge, mirrors .bp-nav__link.is-active */
.bp-tree__caption.is-active,
.bp-tree__node.is-active > .bp-tree__caption {
  color: var(--bp-ink);
  background-color: var(--bp-accent-faint);
  border-left-color: var(--bp-accent);
}

/* caret — composes the shared icon set:
   markup: <span class="bp-icon bp-icon--chevron-right bp-tree__caret"> */
.bp-tree__caret {
  width: 14px;
  height: 14px;
  flex: none;
  cursor: pointer;
  -webkit-mask-size: 10px 10px;
  mask-size: 10px 10px;
  transition: transform var(--bp-transition-fast);
}
.bp-tree__caret:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
.bp-tree__node.is-expanded > .bp-tree__caption .bp-tree__caret { transform: rotate(90deg); }
.bp-tree__node.is-empty > .bp-tree__caption .bp-tree__caret { visibility: hidden; }

/* leading icon slot (protocol / folder glyph supplied by host app) */
.bp-tree__icon {
  width: 16px;
  height: 16px;
  flex: none;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
.bp-tree__caption .bp-checkbox { flex: none; }

/* label — ellipsize long names; works on <a> or <span> */
.bp-tree__label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: inherit;
  text-decoration: none;
}

/* trailing count — quiet mono counter; or drop in a .bp-badge */
.bp-tree__count {
  margin-left: auto;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-faint);
}
.bp-tree__caption > .bp-badge { margin-left: auto; }

/* children — indented under a 1px guide line */
.bp-tree__children {
  list-style: none;
  margin: 0 0 0 var(--bp-space-3);
  padding: 0 0 0 var(--bp-space-3);
  border-left: var(--bp-border-width) solid var(--bp-line);
}
/* static-markup helper; hosts that remove collapsed children from the
   DOM (Guacamole ng-if) never hit this rule */
.bp-tree__node:not(.is-expanded) > .bp-tree__children { display: none; }

/* ghost / create row — "New Connection…" affordances */
.bp-tree__caption--ghost {
  margin: var(--bp-space-1) 0;
  border: var(--bp-border-width) dashed var(--bp-line);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink-dim);
  cursor: pointer;
}
.bp-tree__caption--ghost:hover {
  border-color: var(--bp-line-strong);
  background-color: var(--bp-surface-2);
  color: var(--bp-ink);
}

/* ------------------------------------------------------------------ *
 * THUMBNAIL CARD                                                      *
 *   Screenshot / live-preview card (recent connections, home grid,    *
 *   docked client panel). The media well letterboxes any aspect       *
 *   ratio; media content itself is data — never tint or theme it.    *
 *   Corner action (compose with .bp-btn--ghost .bp-btn--icon          *
 *   .bp-btn--sm) reveals on :hover AND :focus-within — keyboard       *
 *   parity; a hover-only reveal excludes keyboard users.              *
 *   Lay out grids with the existing .bp-grid-cards.                   *
 * ------------------------------------------------------------------ */
.bp-thumb-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  overflow: hidden;
  transition: border-color var(--bp-transition-fast);
}
.bp-thumb-card:hover { border-color: var(--bp-line-strong); }

.bp-thumb-card__link {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
/* ring sits inside: the card clips overflow */
.bp-thumb-card__link:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: calc(-1 * var(--bp-focus-ring));
}

/* media well — letterbox hosting an <img> screenshot or a live
   display element; children are inert so the link gets the click */
.bp-thumb-card__media {
  aspect-ratio: 16 / 10;
  background-color: var(--bp-surface-2);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.bp-thumb-card__media > * {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  pointer-events: none;
}

/* caption bar — compose text with .bp-small; name ellipsizes */
.bp-thumb-card__caption {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  padding: var(--bp-space-2) var(--bp-space-3);
  min-width: 0;
}
.bp-thumb-card__name {
  flex: 1;
  min-width: 0;
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* corner action — hidden until hover OR keyboard focus enters card */
.bp-thumb-card__action {
  position: absolute;
  top: var(--bp-space-2);
  right: var(--bp-space-2);
  z-index: var(--bp-z-base);
  background-color: var(--bp-surface); /* opaque: floats over media */
  opacity: 0;
  transition: opacity var(--bp-transition-fast),
    color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-thumb-card:hover .bp-thumb-card__action,
.bp-thumb-card:focus-within .bp-thumb-card__action { opacity: 1; }

/* states */
.bp-thumb-card.is-active { border-color: var(--bp-accent); }
.bp-thumb-card.is-attention {
  border-left-width: 3px; /* same edge language as .bp-alert */
  border-left-color: var(--bp-warn);
}

/* dock strip — vertical scroll list of thumb cards for the docked
   client panel (.client-panel). Grab handle shares .bp-splitter's
   token language: line edge at rest, accent + accent-faint when
   engaged. Toggle .is-dragging while resizing/collapsing.            */
.bp-thumb-strip {
  display: flex;
  flex-direction: column;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  min-width: 0;
}
.bp-thumb-strip__handle {
  flex: none;
  height: 10px;
  padding: 0;
  background-color: transparent;
  border: none;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  cursor: grab;
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast);
}
.bp-thumb-strip__handle:hover,
.bp-thumb-strip__handle.is-dragging {
  background-color: var(--bp-accent-faint);
  border-color: var(--bp-accent);
}
.bp-thumb-strip__handle.is-dragging { cursor: grabbing; }
.bp-thumb-strip__handle:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: calc(-1 * var(--bp-focus-ring));
}
.bp-thumb-strip__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-2);
  padding: var(--bp-space-2);
}
.bp-thumb-strip__list .bp-thumb-card { flex: none; }

/* ------------------------------------------------------------------ *
 * VEIL                                                                *
 *   Loading overlay for views, panels, and wizard steps. Reuses       *
 *   .bp-spinner. Default form is an inset overlay: give the host      *
 *   position:relative, or wrap it in .bp-veil-host and toggle         *
 *   .is-loading on the host to swap content for the veil (mirrors     *
 *   Guacamole's .loading hook). --view covers the viewport; --section *
 *   renders inline as a panel placeholder. Set role="status" on the   *
 *   veil and aria-busy="true" on the host while loading. Spinner      *
 *   motion is disabled by the prefers-reduced-motion kill switch      *
 *   above; the static ring + label remain legible.                    *
 * ------------------------------------------------------------------ */
.bp-veil {
  position: absolute;
  inset: 0;
  z-index: var(--bp-z-overlay);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--bp-space-3);
  background-color: color-mix(in srgb, var(--bp-bg) 60%, transparent);
  border-radius: inherit; /* follow rounded hosts (.bp-panel) so the backdrop doesn't spill past corners */
  cursor: progress;
}
.bp-veil[hidden] { display: none; }

.bp-veil__label {
  font-size: var(--bp-text-sm);
  color: var(--bp-ink-faint);
}

/* whole-view loading (fixed, covers the viewport) */
.bp-veil--view {
  position: fixed;
  border-radius: 0;
}

/* inline placeholder — occupies space instead of covering it */
.bp-veil--section {
  position: static;
  z-index: auto;
  min-height: 120px;
  background-color: transparent;
}

/* host convenience: positions the veil and swaps content while loading */
.bp-veil-host { position: relative; }
.bp-veil-host.is-loading { min-height: 120px; }
.bp-veil-host:not(.is-loading) > .bp-veil { display: none; }
.bp-veil-host.is-loading > :not(.bp-veil) { visibility: hidden; }

/* ------------------------------------------------------------------ *
 * PROGRESS BAR — INDETERMINATE                                        *
 *   Modifier on .bp-bar for unknown-duration work. The sliding        *
 *   segment is a ::after pseudo-element, so no child markup is        *
 *   needed; any leftover .bp-bar__fill is suppressed so JS can flip   *
 *   modes by toggling the class alone. ARIA: role="progressbar"       *
 *   without aria-valuenow signals indeterminate to assistive tech.    *
 * ------------------------------------------------------------------ */
.bp-bar--indeterminate::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 30%;
  background-color: var(--bp-accent);
  animation: bp-bar-slide 1.4s infinite ease-in-out;
}
.bp-bar--indeterminate > .bp-bar__fill { display: none; }
@keyframes bp-bar-slide {
  /* Percentages are relative to the 30%-wide segment:
     -101% clears the left edge; 100% / 0.30 ≈ 334% clears the right. */
  from { transform: translateX(-101%); }
  to   { transform: translateX(334%); }
}
@media (prefers-reduced-motion: reduce) {
  /* The global .bp-root kill switch (see ACCESSIBILITY) stops the
     slide; render a static full-width faint fill so the bar never
     reads as an empty track. Also applies outside .bp-root. */
  .bp-bar--indeterminate::after {
    width: 100%;
    background-color: var(--bp-accent-faint);
    animation: none;
  }
}

/* ------------------------------------------------------------------ *
 * PROGRESS RING                                                       *
 *   Circular determinate progress (session recording player load /    *
 *   seek overlay). Drive with a custom property on the root:          *
 *     <span class="bp-progress-ring" style="--bp-ring-value: 62">     *
 *   The value circle must carry pathLength="100" so dashoffset maps   *
 *   1:1 to percent. Indeterminate variant reuses the SPINNER          *
 *   bp-spin keyframes (defined in the SPINNER section — do not        *
 *   redefine). Non-interactive: no focus treatment required.          *
 * ------------------------------------------------------------------ */
.bp-progress-ring {
  --bp-ring-value: 0; /* 0–100 */
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--bp-space-10);
  height: var(--bp-space-10);
  flex: none;
}
.bp-progress-ring__svg {
  display: block;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg); /* arc starts at 12 o'clock */
}
.bp-progress-ring__track,
.bp-progress-ring__value {
  fill: none;
  stroke-width: 3; /* SVG user units — scales with the ring size */
}
.bp-progress-ring__track { stroke: var(--bp-line); }
.bp-progress-ring__value {
  stroke: var(--bp-accent);
  stroke-linecap: butt; /* square ends, blueprint aesthetic */
  stroke-dasharray: 100;
  stroke-dashoffset: calc(100 - var(--bp-ring-value));
  transition: stroke-dashoffset var(--bp-transition), stroke var(--bp-transition);
}
.bp-progress-ring__label {
  position: absolute;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  line-height: var(--bp-leading-tight);
  color: var(--bp-ink-dim);
  user-select: none;
}

/* status variants (match .bp-bar__fill semantics: ok/warn/high/crit) */
.bp-progress-ring--ok   .bp-progress-ring__value { stroke: var(--bp-ok); }
.bp-progress-ring--warn .bp-progress-ring__value { stroke: var(--bp-warn); }
.bp-progress-ring--high .bp-progress-ring__value { stroke: var(--bp-high); }
.bp-progress-ring--crit .bp-progress-ring__value { stroke: var(--bp-crit); }
/* warn/high labels stay --bp-ink-dim: those hues fall below AA at 12px */
.bp-progress-ring--ok   .bp-progress-ring__label { color: var(--bp-ok); }
.bp-progress-ring--crit .bp-progress-ring__label { color: var(--bp-crit); }

/* large — recording-player overlay scale */
.bp-progress-ring--lg { width: var(--bp-space-16); height: var(--bp-space-16); }
.bp-progress-ring--lg .bp-progress-ring__label { font-size: var(--bp-text-sm); }

/* indeterminate — fixed quarter arc spun via the shared bp-spin keyframes */
.bp-progress-ring--indeterminate .bp-progress-ring__svg {
  /* bp-spin only declares `to: 360deg`; drop the -90deg base so the
     implicit from is 0deg and the loop is seamless (no 90deg snap). */
  transform: none;
  animation: bp-spin 0.8s linear infinite;
}
.bp-progress-ring--indeterminate .bp-progress-ring__value {
  stroke-dashoffset: 75;
  transition: none;
}
.bp-progress-ring--indeterminate .bp-progress-ring__label { display: none; }

/* ------------------------------------------------------------------ *
 * PLAYER BAR (SESSION RECORDING)                                      *
 *   Overlay transport bar for the session recording player.           *
 *   Composition over existing primitives: .bp-btn--icon (play/pause/  *
 *   fullscreen), .bp-mono (time readout), .bp-btn[aria-disabled]      *
 *   (key-log toggle), and the .bp-slider token spec re-applied to a   *
 *   native input[type=range]. (.bp-range, the designated native-range *
 *   primitive, is accent-color only — too bare for a transport seek,  *
 *   so the .bp-slider track/thumb spec is applied here instead.)      *
 *   The player stage is committed dark regardless of app theme (the   *
 *   recording canvas is black): set data-theme="dark" on              *
 *   .bp-player-stage — tokens re-map to the dark layer, so this       *
 *   component needs no theme-specific rules.                          *
 *   Auto-hide: toggle .is-idle (inverse of guac-player's              *
 *   recent-mouse-movement class); hover or focus-within re-reveals.   *
 * ------------------------------------------------------------------ */
.bp-player-stage {
  position: relative;
  overflow: hidden;
  background-color: var(--bp-bg);
}

.bp-player-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--bp-z-overlay);
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-1);
  padding: var(--bp-space-1) var(--bp-space-2) var(--bp-space-2);
  background-color: var(--bp-surface-3);
  border-top: var(--bp-border-width) solid var(--bp-line);
  transition: opacity var(--bp-transition);
}
.bp-player-bar.is-idle { opacity: 0; }
.bp-player-bar.is-idle:hover,
.bp-player-bar.is-idle:focus-within { opacity: 1; }

.bp-player-bar__controls {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
}
.bp-player-bar__end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
}

.bp-player-bar__time {
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* seek — native range styled to the .bp-slider token spec. WebKit and
   Gecko pseudo-elements cannot share a rule; both sets are specced
   (matches the selector list required by guac's seek.css). Track is
   flat with no progress fill: the usual filled-range trick is a
   linear-gradient background (system rule: no gradients) — use the
   JS-driven .bp-slider where a fill is required. */
.bp-player-bar__seek {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 16px;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}
.bp-player-bar__seek:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
.bp-player-bar__seek:disabled { opacity: 0.45; cursor: not-allowed; }

/* WebKit / Blink */
.bp-player-bar__seek::-webkit-slider-runnable-track {
  box-sizing: border-box;
  height: 4px;
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
}
.bp-player-bar__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  box-sizing: border-box;
  width: 12px;
  height: 12px;
  margin-top: -4px; /* (track 4px − thumb 12px) / 2 */
  background-color: var(--bp-surface);
  border: var(--bp-border-width-accent) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  cursor: grab;
}
.bp-player-bar__seek::-webkit-slider-thumb:active { cursor: grabbing; }

/* Firefox */
.bp-player-bar__seek::-moz-range-track {
  box-sizing: border-box;
  height: 4px;
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
}
.bp-player-bar__seek::-moz-range-thumb {
  box-sizing: border-box;
  width: 12px;
  height: 12px;
  background-color: var(--bp-surface);
  border: var(--bp-border-width-accent) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  cursor: grab;
}
.bp-player-bar__seek::-moz-range-thumb:active { cursor: grabbing; }

/* ------------------------------------------------------------------ *
 * TIMELINE ACTIVITY HEATMAP                                           *
 *   Overlaid SVG area series rendered behind a seek slider (session   *
 *   recording player). Path "d" geometry is data-driven (host         *
 *   service); CSS owns only fill/stroke. Flat translucent fills —     *
 *   no gradients. Non-interactive: clicks fall through to the         *
 *   composed .bp-range/.bp-slider, which carry the focus states.      *
 *   Legend composes .bp-chip + .bp-dot--chart-*.                      *
 *   Markup: one <svg viewBox preserveAspectRatio="none"> per series.  *
 * ------------------------------------------------------------------ */
.bp-heatmap {
  position: relative;
  width: 100%;
  height: var(--bp-space-12);
  pointer-events: none;
}
.bp-heatmap--sm { height: var(--bp-space-8); }

/* anchor over the bottom edge of a positioned ancestor (controls bar) */
.bp-heatmap--overlay {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
}

/* hidden until the host reveals it (e.g. controls-bar hover); the
   container is pointer-events:none, so the host toggles .is-revealed */
.bp-heatmap--peek {
  opacity: 0;
  transition: opacity var(--bp-transition);
}
.bp-heatmap--peek.is-revealed { opacity: 1; }

/* series — one svg per event class, stacked in DOM order */
.bp-heatmap__series {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.bp-heatmap__series path {
  fill: var(--bp-heatmap-series, var(--bp-chart-1));
  /* flat 35% area; no --bp-chart-*-faint alpha tokens exist yet */
  fill-opacity: 0.35;
  stroke: var(--bp-heatmap-series, var(--bp-chart-1));
  stroke-width: 1;
  /* keep the 1px stroke under preserveAspectRatio="none" scaling */
  vector-effect: non-scaling-stroke;
}
.bp-heatmap__series--1 { --bp-heatmap-series: var(--bp-chart-1); }
.bp-heatmap__series--2 { --bp-heatmap-series: var(--bp-chart-2); }
.bp-heatmap__series--3 { --bp-heatmap-series: var(--bp-chart-3); }
.bp-heatmap__series--4 { --bp-heatmap-series: var(--bp-chart-4); }
.bp-heatmap__series--5 { --bp-heatmap-series: var(--bp-chart-5); }

/* legend — column of .bp-chip entries pinned above the right edge */
.bp-heatmap__legend {
  position: absolute;
  right: var(--bp-space-2);
  bottom: calc(100% + var(--bp-space-2));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--bp-space-1);
}

/* chart-series swatches for .bp-dot (heatmap/chart legend keys) */
.bp-dot--chart-1 { background-color: var(--bp-chart-1); }
.bp-dot--chart-2 { background-color: var(--bp-chart-2); }
.bp-dot--chart-3 { background-color: var(--bp-chart-3); }
.bp-dot--chart-4 { background-color: var(--bp-chart-4); }
.bp-dot--chart-5 { background-color: var(--bp-chart-5); }

/* ------------------------------------------------------------------ *
 * VIRTUAL KEYBOARD                                                   *
 *   Interactive keycaps for the on-screen keyboard (OSK) and the     *
 *   text-input method bar (Ctrl/Alt/Esc/Tab). Unlike .bp-kbd — a     *
 *   static hint chip — .bp-key is a pressable control.               *
 *   Inside .bp-keyboard every metric is em-based: the host scales    *
 *   the whole keyboard by setting font-size on the tray root         *
 *   (Guacamole.OnScreenKeyboard.resize via guacOsk.js), so rem/px    *
 *   metrics there would break the fit.                               *
 * ------------------------------------------------------------------ */
.bp-key {
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  line-height: 1;
  white-space: nowrap;
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: 0.5em 0.75em;
  min-width: 2.75em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.bp-key:hover { background-color: var(--bp-surface-3); }

/* momentary press — maps to .guac-keyboard-pressed and
   button.key:active in the text-input widget */
.bp-key:active,
.bp-key.is-pressed {
  background-color: var(--bp-accent);
  border-color: var(--bp-accent);
  color: var(--bp-on-accent);
}

/* latched sticky modifier (Ctrl/Alt/Shift/Caps held on) — maps to
   .guac-keyboard-modifier-* root classes and .key.sticky.pressed */
.bp-key.is-latched {
  background-color: var(--bp-accent-faint);
  border-color: var(--bp-accent);
  color: var(--bp-accent);
}

.bp-key:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

.bp-key:disabled,
.bp-key[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* left-aligned cap for named keys (Tab, Caps, Enter, Shift, Ctrl…) —
   mirrors Guacamole's .guac-keyboard-key-caps/-enter/-tab/… */
.bp-key--named {
  justify-content: flex-start;
  padding-left: 0.75em;
}

/* keyboard tray — host JS sets font-size here on resize; everything
   below cascades from it in em */
.bp-keyboard {
  display: inline-flex;
  flex-direction: column;
  gap: 0.3em;
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: 0.5em;
  cursor: default;
  user-select: none;
  -webkit-user-select: none;
}

.bp-keyboard__row {
  display: flex;
  gap: 0.3em;
}

/* keys inside the scaled tray: em-only metrics, evenly flexed */
.bp-keyboard .bp-key {
  font-size: 0.85em;
  flex: 1 1 0;
  min-width: 2.2em;
  height: 2.6em;
  padding: 0 0.5em;
  margin: 0;
}

/* width modifiers — flex-grow ratios keep rows justified */
.bp-keyboard .bp-key--w2    { flex-grow: 1.6; }
.bp-keyboard .bp-key--w3    { flex-grow: 2.4; }
.bp-keyboard .bp-key--space { flex-grow: 6; }

/* empty spacer — maps to .guac-keyboard-gap */
.bp-keyboard__gap {
  flex: 1 1 0;
  min-width: 2.2em;
}

/* ------------------------------------------------------------------ *
 * COLOR SWATCH & PICKER                                               *
 *   24px color tile for color fields (terminal color scheme field,    *
 *   guac-input-color). The tile's color is user data — the host sets  *
 *   it inline (style="background-color: …"); there is no default and  *
 *   no token for it. Caption (palette index / field name) is the      *
 *   element's text content.                                           *
 *     .is-dark       host-computed: swatch color is dark (guac uses   *
 *                    W3C relative luminance <= 0.6), flip caption.    *
 *     .is-read-only  picker unavailable; display only.                *
 * ------------------------------------------------------------------ */
.bp-swatch {
  width: 24px;
  height: 24px;
  min-width: 24px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  line-height: 1;
  /* Caption sits on the swatch color (user data, theme-independent),
     so it must NOT follow the theme. No theme-invariant on-color pair
     (--bp-ink-on-light / --bp-ink-on-dark) exists in
     blueprint-tokens.css yet (recommended add). Interim mapping:
       default  -> --bp-ink-inverse : exact in the default dark theme;
                   in light theme light swatches degrade (rarest case)
       .is-dark -> --bp-on-accent   : #ffffff in BOTH themes — exact on
                   dark swatches everywhere
     Mitigations: inset keyline keeps tile edges legible, and .is-quiet
     hides palette captions by default (matches Guacamole). */
  color: var(--bp-ink-inverse);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  /* inner keyline so light swatch colors read on light surfaces */
  box-shadow: inset 0 0 0 1px var(--bp-inset-ring);
  padding: 0;
  cursor: pointer;
  transition: border-color var(--bp-transition-fast);
}
.bp-swatch:hover { border-color: var(--bp-ink-faint); }
.bp-swatch:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* Caption flip for dark swatch colors (maps to guac-input-color's
   luminance-computed .dark class). --bp-on-accent is white in both
   themes, so this is theme-invariant — see mapping note above. */
.bp-swatch.is-dark { color: var(--bp-on-accent); }

.bp-swatch.is-read-only { cursor: not-allowed; opacity: 0.6; }
.bp-swatch.is-read-only:hover { border-color: var(--bp-line-strong); }

/* full-width tile for the default foreground/background rows */
.bp-swatch--grow { width: auto; flex: 1; }

/* palette row (8 tiles per ANSI intensity row) */
.bp-swatch-row { display: flex; gap: var(--bp-space-1); }

/* hide palette indices until scheme details are shown */
.bp-swatch-row.is-quiet .bp-swatch { color: transparent; }

/* Pickr popup re-chrome (guac-input-color)
   The picker dialog is created by colorPickerService.js:93-109 with
   appClass 'guac-input-color-picker', theme 'monolith', and is
   appended to <body> — outside any .bp-root — so these selectors must
   target Pickr's own classes globally (documented exemption to the
   .bp-* namespacing rule; there is no element of ours to hook).
   Requires [data-theme] on <html> (or unset, for OS preference) so
   the body-appended popup resolves the same tokens as the app.

   BRITTLE: '.pcr-*' classes are @simonwep/pickr 1.x internals,
   version-coupled to the monolith theme DOM — re-verify after any
   Pickr upgrade. Load this file AFTER pickr's monolith theme CSS so
   equal-specificity frame rules win.

   NO-GRADIENT EXEMPTION (blueprint-tokens.css:8): the saturation
   square and hue strip inside the popup are functional color-space
   representations — data surfaces rendered inline by Pickr itself,
   not decoration. They are exempt and left untouched; all chrome
   around them (frame, input, buttons) stays flat. */
.guac-input-color-picker[data-theme="monolith"] {
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  box-shadow: none;
  font-family: var(--bp-font-sans);
}

/* saturation square / hue strip: gradients untouched (see exemption
   above) — only squared to the blueprint radius, plus inset keyline */
.guac-input-color-picker[data-theme="monolith"] .pcr-palette,
.guac-input-color-picker[data-theme="monolith"] .pcr-slider {
  border-radius: var(--bp-radius-sm);
  box-shadow: inset 0 0 0 1px var(--bp-inset-ring);
}

/* current/last color preview chips */
.guac-input-color-picker[data-theme="monolith"] .pcr-color-preview .pcr-last-color,
.guac-input-color-picker[data-theme="monolith"] .pcr-color-preview .pcr-current-color {
  border-radius: var(--bp-radius-sm);
}

/* palette swatch buttons inside the popup */
.guac-input-color-picker[data-theme="monolith"] .pcr-swatches > button {
  border-radius: var(--bp-radius-sm);
  box-shadow: inset 0 0 0 1px var(--bp-inset-ring);
}

/* hex input — mirrors .bp-input */
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-result {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  box-shadow: none;
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-result:focus {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 1px;
  border-color: var(--bp-accent);
  box-shadow: none;
}

/* save / cancel — mirror .bp-btn--primary / .bp-btn */
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save,
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel {
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  line-height: 1;
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-1) var(--bp-space-2);
  cursor: pointer;
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save {
  color: var(--bp-on-accent);
  background-color: var(--bp-accent);
  border: var(--bp-border-width) solid var(--bp-accent);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save:hover {
  background-color: var(--bp-accent-hover);
  border-color: var(--bp-accent-hover);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel {
  color: var(--bp-ink);
  background-color: transparent;
  border: var(--bp-border-width) solid var(--bp-line-strong);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel:hover {
  border-color: var(--bp-ink-faint);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save:focus-visible,
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ *
 * DROPDOWN MENU — ITEM VARIANTS                                       *
 *   Additive spec on .bp-menu__item. __icon = leading glyph slot      *
 *   (inline SVG, currentColor). --danger = destructive action         *
 *   (logout, disconnect). .is-current = entry for the page the user   *
 *   is already on.                                                    *
 * ------------------------------------------------------------------ */
/* scoped under __items so it outranks the shared `.bp-root :focus-visible`
   (+2px offset) in the ACCESSIBILITY section regardless of block placement */
.bp-menu__items .bp-menu__item:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: -2px; /* inset — items span the full popover width */
}

/* leading icon slot — follows item ink via currentColor */
.bp-menu__icon {
  display: inline-block;
  width: var(--bp-text-base);   /* 14px */
  height: var(--bp-text-base);
  margin-right: var(--bp-space-2);
  vertical-align: -2px;
  color: inherit;
}
.bp-menu__icon svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: currentColor;
}

/* destructive action */
.bp-menu__item--danger { color: var(--bp-crit); }
.bp-menu__item--danger:hover { background-color: var(--bp-crit-faint); }

/* current page — non-actionable, keep last so it wins over --danger */
.bp-menu__item.is-current,
.bp-menu__item.is-current:hover {
  background-color: transparent;
  cursor: default;
  opacity: 0.45;
}

/* ------------------------------------------------------------------ *
 * DATE/TIME PICKER (bp-datetime)                                      *
 *   Themed wiring for input[type=date] / input[type=time] (Guacamole  *
 *   DATE/TIME fields: .date-field / .time-field). The closed state    *
 *   is a standard .bp-input. The native popup is OS-rendered and      *
 *   unthemable — two supported modes:                                 *
 *     native   : bare .bp-datetime wrapper; indicator inherits the    *
 *                theme via color-scheme and is dimmed, not recolored. *
 *     enhanced : extension JS adds .is-enhanced, hides the native     *
 *                indicator, and opens a panel composed of             *
 *                .bp-popover + .bp-datetime__panel hosting .bp-cal    *
 *                (dates) or .bp-datetime__times (times). The native   *
 *                input stays functional as fallback and keeps         *
 *                guac-lenient-date/time parsing.                      *
 *   Compose the trigger with .bp-btn .bp-btn--icon .bp-btn--sm        *
 *   .bp-btn--ghost, footer actions with .bp-btn--sm. Toggle the       *
 *   panel with [hidden]; mark open state with .is-open. Invalid /     *
 *   disabled reuse .bp-input--invalid / :disabled.                    *
 * ------------------------------------------------------------------ */
.bp-datetime { position: relative; }

/* closed input — normalize the WebKit segment editor to token ink */
.bp-datetime .bp-input::-webkit-datetime-edit { padding: 0; }
.bp-datetime .bp-input::-webkit-datetime-edit-text { color: var(--bp-ink-faint); }
.bp-datetime .bp-input::-webkit-datetime-edit-month-field:focus,
.bp-datetime .bp-input::-webkit-datetime-edit-day-field:focus,
.bp-datetime .bp-input::-webkit-datetime-edit-year-field:focus,
.bp-datetime .bp-input::-webkit-datetime-edit-hour-field:focus,
.bp-datetime .bp-input::-webkit-datetime-edit-minute-field:focus,
.bp-datetime .bp-input::-webkit-datetime-edit-ampm-field:focus {
  background-color: var(--bp-accent);
  color: var(--bp-on-accent);
  border-radius: var(--bp-radius-sm);
}

/* native mode — indicator already follows the theme via color-scheme;
   dim it rather than recoloring (no alpha-ink token exists; opacity
   keeps it token-honest) */
.bp-datetime .bp-input::-webkit-calendar-picker-indicator {
  opacity: 0.6;
  cursor: pointer;
  transition: opacity var(--bp-transition-fast);
}
.bp-datetime .bp-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* enhanced mode — our trigger replaces the native indicator */
.bp-datetime.is-enhanced .bp-input { padding-right: var(--bp-space-8); }
.bp-datetime.is-enhanced .bp-input::-webkit-calendar-picker-indicator { display: none; }

.bp-datetime__trigger {
  position: absolute;
  top: 50%;
  right: var(--bp-space-1);
  transform: translateY(-50%);
}
.bp-datetime.is-open .bp-input { border-color: var(--bp-accent); }
.bp-datetime.is-open .bp-datetime__trigger { color: var(--bp-accent); }

/* panel — compose: class="bp-popover bp-datetime__panel" */
.bp-datetime__panel {
  min-width: 0;
  padding: var(--bp-space-2);
  width: max-content;
}
.bp-datetime__panel .bp-cal { border: none; padding: var(--bp-space-1); }

/* time list — mirrors .bp-cal__day states */
.bp-datetime__times {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 128px;
  max-height: 216px;
  overflow-y: auto;
  margin: 0;
  padding: var(--bp-space-1);
  list-style: none;
}
.bp-datetime__time {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  text-align: left;
  background-color: transparent;
  border: var(--bp-border-width) solid transparent;
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-1) var(--bp-space-3);
  cursor: pointer;
}
.bp-datetime__time:hover { background-color: var(--bp-surface-2); }
.bp-datetime__time.is-now { border-color: var(--bp-accent); color: var(--bp-accent); }
.bp-datetime__time.is-selected {
  background-color: var(--bp-accent);
  color: var(--bp-on-accent);
}
.bp-datetime__time:disabled { color: var(--bp-ink-faint); opacity: 0.45; cursor: not-allowed; }

/* footer — Today/Now + Clear, composed from .bp-btn--sm */
.bp-datetime__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-space-2);
  border-top: var(--bp-border-width) solid var(--bp-line);
  margin-top: var(--bp-space-2);
  padding-top: var(--bp-space-2);
}

/* focus — matches central ACCESSIBILITY rule for standalone use */
.bp-datetime__time:focus-visible,
.bp-datetime__trigger:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ *
 * OPTION CARD                                                         *
 *   Figure-labelled radio choice (input methods, mouse modes).        *
 *   A <label class="bp-option-card"> wraps a .bp-visually-hidden      *
 *   radio (direct child); selection renders on the card itself,       *
 *   mirroring .bp-rail__item.is-active. The __media well is optional  *
 *   — text-only choices omit it. Group with .bp-option-group, or      *
 *   compose .bp-cols-2 / .bp-grid-cards. Checked state is driven by   *
 *   :has(:checked); .is-selected is the no-:has fallback class.       *
 * ------------------------------------------------------------------ */
.bp-option-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--bp-space-3);
}
.bp-option-card {
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-2);
  padding: var(--bp-space-3);
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-md);
  cursor: pointer;
  user-select: none;
  transition: border-color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-option-card:hover { border-color: var(--bp-ink-faint); }
.bp-option-card__media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 96px;
  padding: var(--bp-space-3);
  background-color: var(--bp-surface-2);
  border-radius: var(--bp-radius-sm);
}
.bp-option-card__media img,
.bp-option-card__media svg {
  display: block;
  max-width: 100%;
  max-height: 120px;
}
.bp-option-card__title {
  font-size: var(--bp-text-base);
  font-weight: var(--bp-weight-medium);
  line-height: var(--bp-leading-tight);
  color: var(--bp-ink);
}
.bp-option-card__caption {
  font-size: var(--bp-text-sm);
  line-height: var(--bp-leading-snug);
  color: var(--bp-ink-dim);
}

/* selected — mirrors .bp-rail__item.is-active */
.bp-option-card:has(> input:checked),
.bp-option-card.is-selected {
  border-color: var(--bp-accent);
  background-color: var(--bp-accent-faint);
}
.bp-option-card:has(> input:checked) .bp-option-card__title,
.bp-option-card.is-selected .bp-option-card__title { color: var(--bp-accent); }

/* keyboard focus on the hidden radio lights the card */
.bp-option-card:has(> input:focus-visible) {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
/* no-:has() engines: :focus-within fallback (also rings on pointer focus) */
@supports not selector(:has(*)) {
  .bp-option-card:focus-within {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    outline-offset: 2px;
  }
}

/* disabled */
.bp-option-card:has(> input:disabled),
.bp-option-card.is-disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.bp-option-card:has(> input:disabled):hover,
.bp-option-card.is-disabled:hover { border-color: var(--bp-line); }

/* ------------------------------------------------------------------ *
 * INPUT ADORNMENTS                                                    *
 *   Input-skinned wrapper embedding content inside a text control:    *
 *   a leading glyph (filter magnifier), a trailing action (password   *
 *   reveal — compose .bp-btn--icon .bp-btn--sm .bp-btn--ghost as a    *
 *   direct child), or a static unit suffix ('%'). The wrapper carries *
 *   the .bp-input chrome; focus lifts to it via :focus-within like    *
 *   .bp-token-field. Glyph slots size inline SVGs, tint via           *
 *   currentColor. Mark states with .is-invalid / .is-disabled.        *
 * ------------------------------------------------------------------ */
.bp-input-affix {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  width: 100%;
  min-height: 34px;
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: 0 var(--bp-space-2) 0 var(--bp-space-3);
  cursor: text;
  transition: border-color var(--bp-transition-fast);
}
.bp-input-affix:focus-within {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 1px;
  border-color: var(--bp-accent);
}
/* trailing action carries its own ring (see ACCESSIBILITY) — don't double up */
.bp-input-affix:has(> .bp-btn:focus-visible) { outline: none; }

.bp-input-affix__input {
  flex: 1;
  min-width: 0;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background: transparent;
  border: none;
  outline: none;
  padding: var(--bp-space-2) 0;
}
/* the global .bp-root :focus-visible ring outranks the plain outline:none
   above — re-assert it so only the wrapper's :focus-within ring shows */
.bp-input-affix__input:focus-visible { outline: none; }
.bp-input-affix__input::placeholder { color: var(--bp-ink-faint); }

/* spinners collide with a unit suffix — steppers compose outside the
   wrapper as freestanding .bp-btn--icon buttons instead */
.bp-input-affix__input[type="number"] { appearance: textfield; }
.bp-input-affix__input[type="number"]::-webkit-inner-spin-button,
.bp-input-affix__input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.bp-input-affix__icon {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--bp-ink-faint);
  transition: color var(--bp-transition-fast);
}
.bp-input-affix__icon svg { width: 100%; height: 100%; display: block; }
.bp-input-affix:focus-within .bp-input-affix__icon { color: var(--bp-ink-dim); }

.bp-input-affix__suffix {
  flex: none;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-faint);
  user-select: none;
}

.bp-input-affix > .bp-btn { flex: none; }

.bp-input-affix--invalid { border-color: var(--bp-crit); }
.bp-input-affix.is-disabled,
.bp-input-affix:has(> .bp-input-affix__input:disabled) {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ------------------------------------------------------------------ *
 * QR CODE MATTE                                                       *
 *   Presentation tile for QR codes (TOTP enrollment). The matte fill  *
 *   is deliberately un-tokenized #fff: a scannable QR code requires   *
 *   a light quiet zone, and any token-driven surface would go dark    *
 *   under the dark theme and break scanning. Functional, not          *
 *   decorative — exempt from the semantic-token rule for that reason  *
 *   alone. The matte padding forms the quiet zone.                    *
 *   Render .bp-qr__matte as <button> or <a> when the code is a click  *
 *   target (Guacamole opens the otpauth:// key URI on click);         *
 *   otherwise use a <span>. Pair .bp-qr__caption with .bp-small.      *
 * ------------------------------------------------------------------ */
.bp-qr {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--bp-space-2);
  margin: 0; /* neutralize <figure> default */
}
.bp-qr__matte {
  display: block;
  padding: var(--bp-space-4); /* quiet zone */
  background-color: #fff;     /* always-white — see banner note */
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  line-height: 0;
  transition: border-color var(--bp-transition-fast);
}
button.bp-qr__matte,
a.bp-qr__matte {
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  text-decoration: none;
}
button.bp-qr__matte:hover,
a.bp-qr__matte:hover { border-color: var(--bp-accent); }
.bp-qr__matte:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
.bp-qr__img {
  display: block;
  max-width: 100%;
  height: auto;
  image-rendering: pixelated; /* keep modules crisp when scaled */
}
.bp-qr__caption {
  margin: 0;
  max-width: 260px;
  text-align: center;
}

/* ------------------------------------------------------------------ *
 * PRIVACY CONCEAL                                                     *
 *   Opt-in cover that hides sensitive content (e.g. the clipboard     *
 *   textarea) until the user clicks to reveal. Opaque flat fill —     *
 *   no blur, no gradient, per the system rules; privacy requires      *
 *   full opacity anyway. Wrap the content in .bp-conceal, place       *
 *   .bp-conceal__cover last, remove the cover with .is-revealed.      *
 *   Keep the underlying field disabled while concealed (the app       *
 *   toggles it, as Guacamole does via ng-disabled).                   *
 * ------------------------------------------------------------------ */
.bp-conceal {
  position: relative;
}
.bp-conceal > :not(.bp-conceal__cover) {
  transition: opacity var(--bp-transition);
}
.bp-conceal:not(.is-revealed) > :not(.bp-conceal__cover) {
  opacity: 0.55; /* mirrors .bp-input:disabled */
  user-select: none;
}
.bp-conceal__cover {
  position: absolute;
  inset: 0;
  z-index: var(--bp-z-base);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--bp-space-3);
  background-color: var(--bp-surface-2); /* opaque: content stays private */
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  cursor: pointer;
  transition: border-color var(--bp-transition-fast);
}
.bp-conceal__cover:hover { border-color: var(--bp-accent); }
.bp-conceal__cover:hover .bp-conceal__hint { color: var(--bp-ink); }
.bp-conceal__cover:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
.bp-conceal__hint {
  font-size: var(--bp-text-sm);
  color: var(--bp-ink-dim);
  text-align: center;
  transition: color var(--bp-transition-fast);
}
.bp-conceal.is-revealed .bp-conceal__cover { display: none; }

/* ------------------------------------------------------------------ *
 * TABLE ROW STATES                                                    *
 *   Row-level state classes for .bp-table. Disabled records render    *
 *   faint italic (Users / User Groups tabs); selected rows pair with  *
 *   the .bp-table__select checkbox cell to visibly arm bulk actions   *
 *   (Active Sessions kill). Purely additive to TABLE EXTENSIONS.      *
 * ------------------------------------------------------------------ */
.bp-table tr.is-disabled > td,
.bp-table tr.is-disabled > td a {
  color: var(--bp-ink-faint);
  font-style: italic;
}

.bp-table tr.is-selected > td { background-color: var(--bp-accent-faint); }
.bp-table tr.is-selected > td:first-child {
  box-shadow: inset var(--bp-border-width-accent) 0 0 var(--bp-accent);
}

/* selection must survive hover feedback on hoverable tables */
.bp-table--hover tbody tr.is-selected:hover > td {
  background-color: var(--bp-accent-faint);
}

/* ------------------------------------------------------------------ *
 * BREADCRUMB — INTERACTIVE                                            *
 *   Additive on the static .bp-crumb topbar treatment. .bp-crumb--nav *
 *   turns the trail into navigation: anchor segments with hover       *
 *   pills, an icon-only root crumb (masked glyph tinted from          *
 *   currentColor — pair with the .bp-icon set), and ellipsis          *
 *   truncation for deep paths inside fixed-width drawers. Mark the    *
 *   current segment with aria-current="page" (or .is-current).        *
 *   Segments also work as <div role="link"> for ng-click hosts.       *
 * ------------------------------------------------------------------ */
.bp-crumb--nav {
  display: flex;
  align-items: center;
  min-width: 0;           /* permit truncation in fixed-width drawers */
  white-space: nowrap;
}
.bp-crumb--nav .bp-crumb__sep { flex: none; margin: 0 var(--bp-space-1); }

.bp-crumb__link {
  color: var(--bp-ink-dim);
  text-decoration: none;
  padding: 2px var(--bp-space-1);
  border-radius: var(--bp-radius-sm);
  cursor: pointer;
  min-width: 0;
  max-width: 18ch;        /* deep paths: middle segments ellipsize */
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-crumb__link:hover {
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
}
.bp-crumb__link[aria-current="page"],
.bp-crumb__link.is-current {
  color: var(--bp-ink);
  font-weight: var(--bp-weight-semibold);
  max-width: none;
  flex-shrink: 0.2;       /* current segment keeps priority when tight */
}

/* icon-only root crumb (e.g. filesystem drive) */
.bp-crumb__root {
  flex: none;
  width: 24px;
  height: 24px;
  display: inline-grid;
  place-items: center;
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink-dim);
  cursor: pointer;
  transition: color var(--bp-transition-fast),
    background-color var(--bp-transition-fast);
}
.bp-crumb__root:hover { color: var(--bp-ink); background-color: var(--bp-surface-2); }

/* root glyph: place a .bp-icon inside .bp-crumb__root (14px sizing below);
   supply the image via a glyph class or an inline --bp-icon-glyph. */
.bp-crumb__root .bp-icon { width: 14px; height: 14px; }

.bp-crumb__link:focus-visible,
.bp-crumb__root:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
/* ============================================================================
   PEPPER26 — Guacamole -> Blueprint adapter (assembled 2026-07-09)
   Load order (guac-manifest.json): blueprint-tokens, blueprint-components,
   THIS FILE. Concatenated after Guacamole's own CSS in /app.css.
   Group order matters: shared is the foundation; later groups may override.
   8 cross-review ownership conflicts were resolved before assembly.
   ============================================================================ */
/* ======================= GROUP: shared ======================= */
/* ============================================================================
   PEPPER26 BRANDING EXTENSION — ADAPTER CSS, GROUP "SHARED" (FOUNDATION)
   ----------------------------------------------------------------------------
   Re-skins Apache Guacamole 1.6.0's existing DOM to the Blueprint design
   system. Selectors match Guacamole's own markup/CSS verbatim (no bp-*
   classes in the DOM). This bundle is concatenated AFTER Guacamole's CSS in
   /app.css, so equal-specificity rules here win by source order.

   Tokens: blueprint-tokens.css (var(--bp-*)). pepper26.js sets data-theme on
   <html>; both themes resolve automatically through the tokens — no
   [data-theme] rules appear in this file.

   Icon strategy: original background-image icons are replaced with
   mask-image data-URI glyphs copied from the .bp-icon set
   (blueprint-components.css, GUACAMOLE ADDITIONS). The 'black' in the URIs
   is mask alpha, never a rendered color; the painted color is a token via
   background-color. Three glyphs absent from the set (warning, refresh,
   share) are drawn here in the identical 24x24/stroke-2/linecap-square
   language — flagged for upstreaming.

   No !important is used anywhere: Guacamole's own rules for these surfaces
   use none, so source order + matched specificity suffice.

   Screens covered (adapter-group-shared.json):
     1. Base application shell (index.html + index/styles)
     2. Modal overlay (guac-modal) + shell modal contexts
     3. Notification / status dialog (guac-notification)
     4. Generic dropdown menu (guacMenu)
     5. Section / page tabs (guacSectionTabs, guacPageList — shared rules)
     6. Form group + labeled field wrappers (guac-form / guac-form-field)
     7. Simple input field types (text/username/email/number/checkbox/
        textarea/date/time)
     8. Password field with mask/unmask toggle
     9. Select field types (ENUM / LANGUAGE / TIMEZONE)
    10. Terminal color scheme field
    11. Color swatch + Pickr popup (guac-input-color)
    12. Redirect interstitial field
    13. Filter/search box (guac-filter)
    14. Pagination bar (guac-pager)
    15. User item chip (guac-user-item)
    16. Tree / list items + object icons (ui.css — permission editor trees,
        connection group trees)
    17. Connection stability warning overlay
   ============================================================================ */


/* ==========================================================================
 * 1. BASE APPLICATION SHELL — global chrome (index/styles/ui.css,
 *    headers.css, buttons.css, input.css)
 * ========================================================================== */

/* --- body / typography (overrides ui.css body: white bg, Carlito) --- */
body {
    background: var(--bp-bg);
    color: var(--bp-ink);
    font-family: var(--bp-font-sans);
    font-size: var(--bp-text-base);
    line-height: var(--bp-leading-normal);
}

/* neutralize the green tap highlight (input.css:20-22, same selector list) */
input[type=checkbox], input[type=number], input[type=text], input[type=email], input[type=radio], label, textarea {
    -webkit-tap-highlight-color: transparent;
}

/* --- links: token accent instead of browser default blue --- */
a {
    color: var(--bp-accent);
}
a:focus-visible {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
}

/* --- headings (headers.css h1/h2) --- */
h1 {
    font-size: var(--bp-text-3xl);
    font-weight: var(--bp-weight-semibold);
    letter-spacing: var(--bp-tracking-tight);
}
h2 {
    font-size: var(--bp-text-lg);
    font-weight: var(--bp-weight-semibold);
    text-transform: none;
    letter-spacing: var(--bp-tracking-normal);
}

/* --- header bar (headers.css .header: rgba black wash + shadow) --- */
.header {
    background: var(--bp-surface);
    border-bottom: var(--bp-border-width) solid var(--bp-line);
    box-shadow: none;
}
/* stacked headers separator (headers.css:81-84, selector verbatim) */
.header:not(.ng-hide) ~ * .header,
.header:not(.ng-hide) ~ .header {
    border-top: var(--bp-border-width) solid var(--bp-line);
}

/* --- buttons (buttons.css: #3C3C3C/#5A5A5A/#2C2C2C ramp, text-shadow,
       box-shadow). Base = Blueprint outlined neutral (.bp-btn);
       input[type=submit] = primary; .danger = crit outline. --- */
input[type="submit"], button, a.button {
    -webkit-appearance: none;
    appearance: none;
    text-decoration: none;
    background-color: transparent;
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    color: var(--bp-ink);
    text-shadow: none;
    box-shadow: none;
    font-family: var(--bp-font-sans);
    font-size: var(--bp-text-base);
    font-weight: var(--bp-weight-medium);
    cursor: pointer;
    transition: background-color var(--bp-transition-fast),
        border-color var(--bp-transition-fast),
        color var(--bp-transition-fast);
}
input[type="submit"]:hover, button:hover, a.button:hover {
    background-color: var(--bp-surface-2);
    border-color: var(--bp-ink-faint);
}
input[type="submit"]:active, button:active, a.button:active {
    background-color: var(--bp-surface-3);
    box-shadow: none;
}
input[type="submit"]:focus-visible, button:focus-visible, a.button:focus-visible {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
}

/* primary action — form submits (login, save, continue) */
input[type="submit"] {
    background-color: var(--bp-accent);
    border-color: var(--bp-accent);
    color: var(--bp-on-accent);
}
input[type="submit"]:hover {
    background-color: var(--bp-accent-hover);
    border-color: var(--bp-accent-hover);
}
input[type="submit"]:active {
    background-color: var(--bp-accent-hover);
}

/* danger (buttons.css: #A43/#C54/#932) — mirrors .bp-btn--danger */
button.danger, a.button.danger {
    background: transparent;
    border-color: color-mix(in srgb, var(--bp-crit) 50%, transparent);
    color: var(--bp-crit);
}
button.danger:hover, a.button.danger:hover {
    background: var(--bp-crit-faint);
    border-color: var(--bp-crit);
}
button.danger:active, a.button.danger:active {
    background: var(--bp-crit-faint);
}

/* disabled — last so it beats the hover/primary rules above
   (buttons.css:73-77 selector verbatim) */
input[type="submit"]:disabled, button:disabled, button.danger:disabled {
    background-color: transparent;
    border-color: var(--bp-line);
    color: var(--bp-ink-faint);
    opacity: 0.45;
    cursor: not-allowed;
}

/* icon-prefixed buttons (buttons.css:89-134): swap the ::before SVG
   background-images for mask glyphs tinted from currentColor, so the icon
   follows the button ink in every state and theme. */
.button.logout::before,          button.logout::before,
.button.reconnect::before,       button.reconnect::before,
.button.manage::before,          button.manage::before,
.button.back::before,            button.back::before,
.button.home::before,            button.home::before,
.button.change-password::before, button.change-password::before {
    background-image: none;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 1em;
    mask-size: 1em;
    -webkit-mask-position: 0.5em center;
    mask-position: 0.5em center;
}
.button.logout::before,
button.logout::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M10 4.5H4.5v15H10M20 12H9.5M16 8l4 4-4 4'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M10 4.5H4.5v15H10M20 12H9.5M16 8l4 4-4 4'/%3E%3C/svg%3E");
}
/* refresh glyph: NOT in the bp-icon set — drawn in the identical style */
.button.reconnect::before,
button.reconnect::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M20 12a8 8 0 1 1-2.3-5.7'/%3E%3Cpath d='M20 3.5V8h-4.5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M20 12a8 8 0 1 1-2.3-5.7'/%3E%3Cpath d='M20 3.5V8h-4.5'/%3E%3C/svg%3E");
}
.button.manage::before,
button.manage::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='3.5'/%3E%3Cpath d='M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.3 5.3l2.1 2.1M16.6 16.6l2.1 2.1M18.7 5.3l-2.1 2.1M7.4 16.6l-2.1 2.1'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='3.5'/%3E%3Cpath d='M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.3 5.3l2.1 2.1M16.6 16.6l2.1 2.1M18.7 5.3l-2.1 2.1M7.4 16.6l-2.1 2.1'/%3E%3C/svg%3E");
}
.button.back::before,
button.back::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E");
}
.button.home::before,
button.home::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E");
}
.button.change-password::before,
button.change-password::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='4.5' y='11' width='15' height='9.5'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='4.5' y='11' width='15' height='9.5'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
}

/* --- text inputs (input.css:24-36 selector verbatim: 1px #777 border,
       white bg). Geometry (padding/max-width/font-size) is intentionally
       untouched so every screen keeps its layout. --- */
div.location, input[type=text], input[type=email], input[type=number], input[type=password], textarea {
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface-2);
    color: var(--bp-ink);
    font-family: var(--bp-font-mono);
    transition: border-color var(--bp-transition-fast);
}
input[type=text]:focus, input[type=email]:focus, input[type=number]:focus,
input[type=password]:focus, textarea:focus {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    border-color: var(--bp-accent);
}
input[type=text]::placeholder, input[type=email]::placeholder,
input[type=number]::placeholder, input[type=password]::placeholder,
textarea::placeholder {
    color: var(--bp-ink-faint);
}
input[type=text]:disabled, input[type=email]:disabled, input[type=number]:disabled,
input[type=password]:disabled, textarea:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* checkboxes / radios — token accent (no core chrome to beat) */
input[type=checkbox], input[type=radio] {
    accent-color: var(--bp-accent);
}


/* ==========================================================================
 * 2. MODAL OVERLAY (guac-modal) + SHELL MODAL CONTEXTS
 *    (notification/styles/modal.css, index/styles/status.css,
 *     logged-out.css, automatic-login-rejected.css, fatal-page-error.css)
 * ========================================================================== */

/* retime the fade-in to the motion token (modal.css:47-51) */
guac-modal {
    -webkit-animation: fadein var(--bp-transition);
    -moz-animation: fadein var(--bp-transition);
    animation: fadein var(--bp-transition);
}

/* global status dialog scrim (status.css:20-22). index.html places the
   class ON the guac-modal element itself, so both forms are covered. */
.global-status-modal guac-modal,
guac-modal.global-status-modal {
    background: var(--bp-scrim);
}

/* full-page shell modals: hardcoded white backgrounds → page bg token
   (logged-out.css:20-23, automatic-login-rejected.css:20-23) */
.logged-out-modal guac-modal {
    background: var(--bp-bg);
}
.automatic-login-rejected-modal guac-modal {
    background: var(--bp-bg);
}

/* fatal page error — recolor the warning glyph (fatal-page-error.css:38-48;
   original uses background shorthand with url(images/warning.svg)) */
.fatal-page-error h1::before {
    background: var(--bp-crit);
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5L21.5 20h-19z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Ccircle cx='12' cy='17.5' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5L21.5 20h-19z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Ccircle cx='12' cy='17.5' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: center;
    mask-position: center;
}
.fatal-page-error h1 {
    color: var(--bp-crit);
    font-size: var(--bp-text-xl);
}


/* ==========================================================================
 * 3. NOTIFICATION / STATUS DIALOG (guac-notification)
 *    (notification/styles/notification.css) — restyles every dialog in the
 *    app: errors, confirmations, progress, countdowns, credential prompts.
 * ========================================================================== */

/* card (notification.css:20-25: white bg, black text, shadow) */
.notification {
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-md);
    box-shadow: none;
    background: var(--bp-surface);
    color: var(--bp-ink);
    overflow: hidden; /* children respect the rounded corners */
}

/* error variant (notification.css:27-29: #FDD) → surface + crit edge,
   .bp-alert--crit language; the card must stay opaque over the scrim */
.notification.error {
    background: var(--bp-surface);
    border-left-width: 3px;
    border-left-color: var(--bp-crit);
}

/* title bar (notification.css:49-60: black wash + shadow) → mono eyebrow */
.notification .title-bar {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-xs);
    font-weight: var(--bp-weight-medium);
    letter-spacing: var(--bp-tracking-eyebrow);
    color: var(--bp-ink-dim);
    border-bottom: var(--bp-border-width) solid var(--bp-line);
    box-shadow: none;
    background: var(--bp-surface-2);
}

/* progress track (notification.css:74-99: #C2C2C2 + animated diagonal
   stripes — stripes violate the flat/no-gradient rule). The background
   shorthand drops url(images/progress.svg); animation:none beats the
   notification-progress keyframes. */
.notification .progress {
    background: var(--bp-surface-2);
    -webkit-animation: none;
    animation: none;
    border: var(--bp-border-width) solid var(--bp-line);
    border-radius: var(--bp-radius-sm);
    overflow: hidden;
}

/* determinate fill (notification.css:62-72: hardcoded #A3D655 green) */
.notification .progress .bar {
    background: var(--bp-accent);
    box-shadow: none;
}

/* keep the progress caption above the fill and the indeterminate slide */
.notification .progress > div:not(.bar) {
    position: relative;
}

/* indeterminate — the .bar is ng-show'd on progressPercent, so an unknown
   ratio leaves it .ng-hide; render a sliding accent segment instead
   (mirrors .bp-bar--indeterminate). Non-:has() engines degrade to a calm
   flat track. */
.notification .progress:has(> .bar.ng-hide)::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 30%;
    background-color: var(--bp-accent);
    animation: pepper26-bar-slide 1.4s infinite ease-in-out;
}
@keyframes pepper26-bar-slide {
    /* relative to the 30%-wide segment: -101% clears left, 334% clears right */
    from { transform: translateX(-101%); }
    to   { transform: translateX(334%); }
}
@media (prefers-reduced-motion: reduce) {
    .notification .progress:has(> .bar.ng-hide)::after {
        width: 100%;
        background-color: var(--bp-accent-faint);
        animation: none;
    }
}

/* countdown ("reconnecting in N seconds…") */
.notification .countdown-text {
    color: var(--bp-ink-faint);
    font-size: var(--bp-text-sm);
}


/* ==========================================================================
 * 4. GENERIC DROPDOWN MENU (guacMenu — navigation/styles/menu.css)
 * ========================================================================== */

/* trigger bar (menu.css:49-62: rgba black washes) → ghost-button language */
.menu-dropdown {
    border-left: var(--bp-border-width) solid var(--bp-line);
    background: transparent;
    transition: background-color var(--bp-transition-fast);
}
.menu-dropdown:hover {
    background: var(--bp-surface-2);
}
.menu-dropdown.open,
.menu-dropdown.open:hover {
    background: var(--bp-surface-3);
}

.menu-dropdown .menu-title {
    color: var(--bp-ink-dim);
}

/* chevron indicator (menu.css:84-97: images/arrows/down.svg) → masked
   bp chevron-down, tinted from its own color token via currentColor */
.menu-dropdown .menu-indicator {
    background-image: none;
    background-color: currentColor;
    color: var(--bp-ink-faint);
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 1em;
    mask-size: 1em;
    -webkit-mask-position: center;
    mask-position: center;
}

/* popover panel (menu.css:99-116: #EEE + shadow) → .bp-menu__items tokens */
.menu-dropdown .menu-contents {
    background: var(--bp-surface);
    box-shadow: none;
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-top: none;
    border-radius: 0 0 var(--bp-radius-sm) var(--bp-radius-sm);
}

/* items — kill the signature #CDA green hover (menu.css:132-144) */
.menu-dropdown .menu-contents li a {
    color: var(--bp-ink);
    font-size: var(--bp-text-sm);
    transition: background-color var(--bp-transition-fast);
}
.menu-dropdown .menu-contents li a:hover {
    background-color: var(--bp-surface-2);
}

/* current page (menu.css:146-151) — bp .is-current convention (0.45) */
.menu-dropdown .menu-contents li a.current,
.menu-dropdown .menu-contents li a.current:hover {
    background-color: transparent;
    cursor: default;
    opacity: 0.45;
}

/* danger item (menu.css:153-161: white on #A43/#C54) →
   .bp-menu__item--danger: crit ink, crit-faint hover */
.menu-dropdown .menu-contents li a.danger {
    color: var(--bp-crit);
    font-weight: var(--bp-weight-medium);
    background-color: transparent;
}
.menu-dropdown .menu-contents li a.danger:hover {
    background-color: var(--bp-crit-faint);
}


/* ==========================================================================
 * 5. SECTION TABS + PAGE TABS (navigation/styles/tabs.css — combined
 *    selectors cover guacSectionTabs AND guacPageList, incl. data-source
 *    tabs on the manage screens). Underline-tab language (.bp-tab).
 * ========================================================================== */

.page-tabs .page-list ul,
.section-tabs ul {
    background: transparent;
    border-bottom: var(--bp-border-width) solid var(--bp-line);
}

.page-tabs .page-list li a[href],
.section-tabs li a {
    color: var(--bp-ink-dim);
    font-weight: var(--bp-weight-medium);
    transition: background-color var(--bp-transition-fast),
        color var(--bp-transition-fast);
}
.page-tabs .page-list li a[href]:visited {
    color: var(--bp-ink-dim);
}
.page-tabs .page-list li a[href]:hover,
.section-tabs li a:hover {
    background-color: var(--bp-surface-2);
    color: var(--bp-ink);
}

/* selected tab (tabs.css:57-63: rgba(0,0,0,0.3) fill) → accent underline;
   inset box-shadow avoids shifting the tab-bar box model */
.page-tabs .page-list li a[href].current,
.page-tabs .page-list li a[href].current:hover,
.section-tabs li a.current,
.section-tabs li a.current:hover {
    background: transparent;
    color: var(--bp-accent);
    box-shadow: inset 0 calc(-1 * var(--bp-border-width-accent)) 0 var(--bp-accent);
}


/* ==========================================================================
 * 6. FORM GROUP + LABELED FIELD (guac-form / guac-form-field)
 *    form.html / formField.html — no core chrome to beat; additive rhythm.
 * ========================================================================== */

.form-group .form {
    margin: 0 0 var(--bp-space-5);
}

/* section header (h3.form-header) — Blueprint eyebrow treatment */
.form .form-header {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-2xs);
    font-weight: var(--bp-weight-medium);
    text-transform: uppercase;
    letter-spacing: var(--bp-tracking-eyebrow);
    color: var(--bp-ink-faint);
    border-bottom: var(--bp-border-width) solid var(--bp-line);
    margin: var(--bp-space-4) 0 var(--bp-space-3);
    padding: 0 0 var(--bp-space-1);
}

/* vertical field rhythm — margin only: the notification dialog re-lays
   .labeled-field as table-row (notification.css:114-116) where margins are
   inert, so this cannot break that layout */
.form .fields .labeled-field {
    margin-bottom: var(--bp-space-3);
}

/* field label — .bp-label treatment (applies inside dialogs too) */
.field-header label {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-2xs);
    letter-spacing: var(--bp-tracking-wide);
    text-transform: uppercase;
    color: var(--bp-ink-faint);
}

/* legacy table-layout form labels (form/styles/form.css:20-24) */
.form table.fields th {
    color: var(--bp-ink-faint);
}


/* ==========================================================================
 * 7. SIMPLE INPUT FIELD TYPES — text/username/email/number/checkbox/
 *    textarea/date/time. Closed-state chrome; native popups are OS chrome
 *    (see unresolved).
 * ========================================================================== */

/* date/time inputs are NOT covered by input.css's selector list — give them
   the same chrome + geometry as their text siblings */
.date-field input[type=date],
.time-field input[type=time] {
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface-2);
    color: var(--bp-ink);
    font-family: var(--bp-font-mono);
    width: 100%;
    max-width: 16em;   /* match input.css geometry */
    padding: 0.25em;   /* match input.css geometry */
    font-size: 0.8em;  /* match input.css geometry */
    transition: border-color var(--bp-transition-fast);
}
.date-field input[type=date]:focus,
.time-field input[type=time]:focus {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    border-color: var(--bp-accent);
}

/* native picker indicator follows the theme via color-scheme; dim it
   rather than recoloring (mirrors .bp-datetime) */
.date-field input[type=date]::-webkit-calendar-picker-indicator,
.time-field input[type=time]::-webkit-calendar-picker-indicator {
    opacity: 0.6;
    cursor: pointer;
    transition: opacity var(--bp-transition-fast);
}
.date-field input[type=date]::-webkit-calendar-picker-indicator:hover,
.time-field input[type=time]::-webkit-calendar-picker-indicator:hover {
    opacity: 1;
}

/* read-only email presentation (emailField.html:11 mailto anchor) */
.email-field a[href^="mailto:"] {
    color: var(--bp-accent);
    text-decoration: none;
    border-bottom: var(--bp-border-width) solid transparent;
}
.email-field a[href^="mailto:"]:hover {
    border-bottom-color: var(--bp-accent);
}


/* ==========================================================================
 * 8. PASSWORD FIELD — mask/unmask toggle (form/styles/form-field.css)
 *    The type-driven sibling-selector swap mechanism is preserved; only the
 *    assets (guac-show-pass.svg / guac-hide-pass.svg) and inks change.
 * ========================================================================== */

.form-field .password-field .icon.toggle-password {
    opacity: 1; /* raise form-field.css's 0.5 — ink handled by tokens */
    cursor: pointer;
    background-image: none;
    background-color: var(--bp-ink-dim);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 1em;
    mask-size: 1em;
    -webkit-mask-position: center;
    mask-position: center;
    transition: background-color var(--bp-transition-fast);
}
.form-field .password-field .icon.toggle-password:hover {
    background-color: var(--bp-ink);
}

/* masked → offer "show" (eye) — overrides form-field.css:40-42 */
.form-field .password-field input[type=password] ~ .icon.toggle-password {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M2 12c2.6-4.7 6-7 10-7s7.4 2.3 10 7c-2.6 4.7-6 7-10 7s-7.4-2.3-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M2 12c2.6-4.7 6-7 10-7s7.4 2.3 10 7c-2.6 4.7-6 7-10 7s-7.4-2.3-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
}

/* unmasked → offer "hide" (eye-off) — overrides form-field.css:45-47 */
.form-field .password-field input[type=text] ~ .icon.toggle-password {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M2 12c2.6-4.7 6-7 10-7s7.4 2.3 10 7c-2.6 4.7-6 7-10 7s-7.4-2.3-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M4 3.5l16 17'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M2 12c2.6-4.7 6-7 10-7s7.4 2.3 10 7c-2.6 4.7-6 7-10 7s-7.4-2.3-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M4 3.5l16 17'/%3E%3C/svg%3E");
}


/* ==========================================================================
 * 9. SELECT FIELD TYPES (ENUM / LANGUAGE / TIMEZONE) — the form module
 *    ships NO select CSS, so these are the sole rules. Native appearance is
 *    kept: the OS option list follows color-scheme from the tokens.
 * ========================================================================== */

.select-field select,
.language-field select,
.time-zone-field select.time-zone-region,
.time-zone-field select.time-zone,
.terminal-color-scheme-field select {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-sm);
    color: var(--bp-ink);
    background-color: var(--bp-surface-2);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    padding: var(--bp-space-1) var(--bp-space-2);
    max-width: 16em; /* align with the text-input column (input.css) */
    width: 100%;
    cursor: pointer;
    transition: border-color var(--bp-transition-fast);
}
.select-field select:focus,
.language-field select:focus,
.time-zone-field select.time-zone-region:focus,
.time-zone-field select.time-zone:focus,
.terminal-color-scheme-field select:focus {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    border-color: var(--bp-accent);
}
.select-field select:disabled,
.language-field select:disabled,
.time-zone-field select.time-zone-region:disabled,
.time-zone-field select.time-zone:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
/* the scheme select spans its 320px field (terminal-color-scheme-field.css:24) */
.terminal-color-scheme-field select {
    max-width: none;
}


/* ==========================================================================
 * 10. TERMINAL COLOR SCHEME FIELD (form/styles/terminal-color-scheme-field.css)
 *     Swatch colors themselves are user data (ng-style inline) — untouched.
 * ========================================================================== */

/* editor box (css:28-35: hardcoded #EEE + silver border) */
.terminal-color-scheme-field .custom-color-scheme {
    background: var(--bp-surface-2);
    border: var(--bp-border-width) solid var(--bp-line);
    border-radius: var(--bp-radius-sm);
}

/* swatch tiles — .bp-swatch language: keyline + inset ring; caption ink is
   theme-invariant-ish per the bp-swatch interim mapping (ink-inverse /
   on-accent), since the tile color is user data */
.terminal-color-scheme-field .guac-input-color {
    color: var(--bp-ink-inverse);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    box-shadow: inset 0 0 0 1px var(--bp-inset-ring);
    transition: border-color var(--bp-transition-fast);
}
.terminal-color-scheme-field .guac-input-color:hover {
    border-color: var(--bp-ink-faint);
}
.terminal-color-scheme-field .guac-input-color.dark {
    color: var(--bp-on-accent);
}
.terminal-color-scheme-field .guac-input-color.read-only:hover {
    border-color: var(--bp-line-strong);
}

/* details header + ▸/▾ arrows (css:88-100) — text carets kept, re-inked */
.terminal-color-scheme-field .custom-color-scheme-details-header {
    color: var(--bp-ink-dim);
}

/* show/hide links (css:107-114: hardcoded 'color: blue') */
.terminal-color-scheme-field .custom-color-scheme-hide-details,
.terminal-color-scheme-field .custom-color-scheme-show-details {
    color: var(--bp-accent);
}


/* ==========================================================================
 * 11. PICKR COLOR-PICKER POPUP (guac-input-color)
 *     The popup is appended to <body> with appClass 'guac-input-color-picker'
 *     (colorPickerService.js:93-109) — global selectors are the only hook.
 *     BRITTLE: .pcr-* classes are @simonwep/pickr 1.x internals.
 *     NO-GRADIENT EXEMPTION: the saturation square and hue strip are
 *     functional color-space surfaces rendered by Pickr — left untouched;
 *     only the chrome around them is themed (per the documented exemption
 *     in blueprint-components.css GUACAMOLE ADDITIONS).
 * ========================================================================== */

.guac-input-color-picker[data-theme="monolith"] {
    background-color: var(--bp-surface);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-md);
    box-shadow: none;
    font-family: var(--bp-font-sans);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-palette,
.guac-input-color-picker[data-theme="monolith"] .pcr-slider {
    border-radius: var(--bp-radius-sm);
    box-shadow: inset 0 0 0 1px var(--bp-inset-ring);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-color-preview .pcr-last-color,
.guac-input-color-picker[data-theme="monolith"] .pcr-color-preview .pcr-current-color {
    border-radius: var(--bp-radius-sm);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-swatches > button {
    border-radius: var(--bp-radius-sm);
    box-shadow: inset 0 0 0 1px var(--bp-inset-ring);
}

/* hex input — mirrors .bp-input */
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-result {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-xs);
    color: var(--bp-ink);
    background-color: var(--bp-surface-2);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    box-shadow: none;
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-result:focus {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    border-color: var(--bp-accent);
    box-shadow: none;
}

/* save / cancel — mirror .bp-btn--primary / .bp-btn (core already strips
   the app button chrome inside the picker, terminal-color-scheme-field.css:153) */
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save,
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel {
    font-family: var(--bp-font-sans);
    font-size: var(--bp-text-xs);
    font-weight: var(--bp-weight-medium);
    border-radius: var(--bp-radius-sm);
    padding: var(--bp-space-1) var(--bp-space-2);
    cursor: pointer;
    transition: background-color var(--bp-transition-fast),
        border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save {
    color: var(--bp-on-accent);
    background-color: var(--bp-accent);
    border: var(--bp-border-width) solid var(--bp-accent);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-save:hover {
    background-color: var(--bp-accent-hover);
    border-color: var(--bp-accent-hover);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel {
    color: var(--bp-ink);
    background-color: transparent;
    border: var(--bp-border-width) solid var(--bp-line-strong);
}
.guac-input-color-picker[data-theme="monolith"] .pcr-interaction .pcr-cancel:hover {
    border-color: var(--bp-ink-faint);
}


/* ==========================================================================
 * 12. REDIRECT INTERSTITIAL FIELD (form/styles/redirect-field.css)
 * ========================================================================== */

/* overlay (css:20-28: hardcoded 'background: white' — dark-theme hazard) */
.redirect-field-container {
    background: var(--bp-bg);
}
.redirect-field {
    color: var(--bp-ink-dim);
    font-size: var(--bp-text-md);
}


/* ==========================================================================
 * 13. FILTER / SEARCH BOX (list/styles/filter.css)
 *     The magnifier.svg background-image inside the input cannot be
 *     token-tinted; move the glyph to a masked ::before on the .filter
 *     wrapper (guacFilter.html: div.filter > input.search-string).
 * ========================================================================== */

.filter {
    position: relative;
}
.filter .search-string {
    background-image: none; /* drop images/magnifier.svg; keep 2.25em inset */
}
.filter::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0.75em;
    width: 1em;
    pointer-events: none;
    background-color: var(--bp-ink-faint);
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5L21 21'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5L21 21'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 1em;
    mask-size: 1em;
    -webkit-mask-position: center;
    mask-position: center;
}


/* ==========================================================================
 * 14. PAGINATION BAR (list/styles/pager.css)
 * ========================================================================== */

/* nav arrow buttons — mask plumbing + per-glyph bp chevrons */
.pager .icon.first-page,
.pager .icon.prev-page,
.pager .icon.next-page,
.pager .icon.last-page {
    background-color: var(--bp-ink-dim);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 16px 16px; /* matches ui.css .icon glyph size */
    mask-size: 16px 16px;
    -webkit-mask-position: center;
    mask-position: center;
    transition: background-color var(--bp-transition-fast);
}
.pager .icon.first-page:hover,
.pager .icon.prev-page:hover,
.pager .icon.next-page:hover,
.pager .icon.last-page:hover {
    background-color: var(--bp-ink);
}
/* per-glyph overrides beat pager.css:73-87 (same selectors, later order) */
.pager .icon.first-page {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M18 5l-7 7 7 7M11 5l-7 7 7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M18 5l-7 7 7 7M11 5l-7 7 7 7'/%3E%3C/svg%3E");
}
.pager .icon.prev-page {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E");
}
.pager .icon.next-page {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
}
.pager .icon.last-page {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 5l7 7-7 7M13 5l7 7-7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 5l7 7-7 7M13 5l7 7-7 7'/%3E%3C/svg%3E");
}

/* numbered page links (pager.css:57-59: underlined) → quiet accent links */
.pager .set-page {
    text-decoration: none;
    color: var(--bp-accent);
    border-radius: var(--bp-radius-sm);
    transition: background-color var(--bp-transition-fast);
}
.pager .set-page:hover {
    background: var(--bp-accent-faint);
}

/* current-page pill (pager.css:61-71: rgba black pill) → accent fill.
   Placed after :hover (equal specificity) so the fill wins on hover. */
.pager .set-page.current {
    background: var(--bp-accent);
    border: var(--bp-border-width) solid var(--bp-accent);
    border-radius: var(--bp-radius-sm);
    color: var(--bp-on-accent);
    font-weight: var(--bp-weight-semibold);
}

/* ellipsis indicators */
.pager .more-pages {
    color: var(--bp-ink-faint);
}

/* disabled arrows (pager.css:40-47: 0.25) → bp disabled convention */
.pager .first-page.disabled,
.pager .prev-page.disabled,
.pager .set-page.disabled,
.pager .next-page.disabled,
.pager .last-page.disabled {
    opacity: 0.45;
}


/* ==========================================================================
 * 15. USER ITEM CHIP (list/styles/user-item.css)
 * ========================================================================== */

/* anonymous variant (user-item.css:20-23: italic + 50% opacity) →
   faint ink, no italic (Blueprint tone conventions) */
.user-item.anonymous {
    font-style: normal;
    opacity: 1;
    color: var(--bp-ink-faint);
}


/* ==========================================================================
 * 16. TREE / LIST ITEMS + OBJECT ICONS (index/styles/ui.css) — connection
 *     group trees, permission-editor trees, user/group lists.
 * ========================================================================== */

.list-item .name {
    color: var(--bp-ink);
}
.list-item .usage {
    font-style: normal;
    color: var(--bp-ink-faint);
}

/* selection + hover (ui.css:110-126: #DEB / #CDA greens) */
.list-item.selected {
    background: var(--bp-accent-faint);
}
.list-item:not(.selected) .caption:hover {
    background: var(--bp-surface-2);
}

/* tree guide elbows (ui.css:241-259: #BBB) */
.expandable.expanded > .children > .list-item:before {
    border-left: var(--bp-border-width) solid var(--bp-line);
}
.expandable.expanded > .children > .list-item:after {
    border-bottom: var(--bp-border-width) solid var(--bp-line);
}

/* --- object icons: mask plumbing (shared), then per-glyph rules whose
       selectors match ui.css verbatim so each original background-image is
       beaten at equal specificity. Icons tint from --bp-ink-dim. --- */
.icon.user, .icon.user.add,
.icon.user-group, .icon.user-group.add,
.icon.connection, .icon.connection.add,
.connection .icon,
.connection .icon.kubernetes, .connection .icon.ssh, .connection .icon.telnet,
.connection .icon.vnc, .connection .icon.rdp,
.connection-group > .caption .icon,
.connection-group.expanded > .caption .icon,
.connection-group.empty.balancer .icon,
.sharing-profile .icon,
.expandable > .caption .icon.expand,
.expandable.expanded > .caption .icon.expand,
.expandable.empty > .caption .icon.expand {
    background-color: var(--bp-ink-dim);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: 16px 16px; /* matches ui.css .icon background-size */
    mask-size: 16px 16px;
}

/* users (ui.css:151-165) */
.icon.user {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
}
.icon.user.add {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='9.5' cy='7.5' r='4'/%3E%3Cpath d='M2.5 20.5c.7-4 3.4-6.5 7-6.5s6.3 2.5 7 6.5M18.5 4v6M15.5 7h6'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='9.5' cy='7.5' r='4'/%3E%3Cpath d='M2.5 20.5c.7-4 3.4-6.5 7-6.5s6.3 2.5 7 6.5M18.5 4v6M15.5 7h6'/%3E%3C/svg%3E");
}
.icon.user-group {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E");
}
.icon.user-group.add {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15.5 15c2.3.7 3.7 2.4 4 5M18.5 3.5v6M15.5 6.5h6'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15.5 15c2.3.7 3.7 2.4 4 5M18.5 3.5v6M15.5 6.5h6'/%3E%3C/svg%3E");
}

/* connections (ui.css:167-213) */
.icon.connection {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
}
.icon.connection.add {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M12 7.5v6.5M8.75 10.75h6.5M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M12 7.5v6.5M8.75 10.75h6.5M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
}
.connection .icon {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
}
.connection .icon.kubernetes,
.connection .icon.ssh,
.connection .icon.telnet {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E");
}
/* kubernetes gets its dedicated glyph — more specific than the shared
   terminal rule above only by source order (equal specificity, later wins) */
.connection .icon.kubernetes {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E");
}
.connection .icon.vnc,
.connection .icon.rdp {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
}

/* connection groups / balancer / sharing profile (ui.css:189-227) */
.connection-group > .caption .icon {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
}
.connection-group.expanded > .caption .icon {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 19V5.5h6.5l2 3H19v2M3 19l2.7-8.5H22L19.2 19z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 19V5.5h6.5l2 3H19v2M3 19l2.7-8.5H22L19.2 19z'/%3E%3C/svg%3E");
}
.connection-group.empty.balancer .icon {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E");
}
/* share glyph: NOT in the bp-icon set — drawn in the identical style */
.sharing-profile .icon {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='6' cy='12' r='2.5'/%3E%3Ccircle cx='17' cy='5.5' r='2.5'/%3E%3Ccircle cx='17' cy='18.5' r='2.5'/%3E%3Cpath d='M8.2 10.7l6.6-3.9M8.2 13.3l6.6 3.9'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='6' cy='12' r='2.5'/%3E%3Ccircle cx='17' cy='5.5' r='2.5'/%3E%3Ccircle cx='17' cy='18.5' r='2.5'/%3E%3Cpath d='M8.2 10.7l6.6-3.9M8.2 13.3l6.6 3.9'/%3E%3C/svg%3E");
}

/* expand carets (ui.css:261-272: guac-closed/guac-open) → bp chevrons */
.expandable > .caption .icon.expand {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
    -webkit-mask-size: 10px 10px; /* mirrors .bp-tree__caret glyph size */
    mask-size: 10px 10px;
}
.expandable.expanded > .caption .icon.expand {
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    -webkit-mask-size: 10px 10px;
    mask-size: 10px 10px;
}
.expandable.empty > .caption .icon.expand {
    opacity: 0.45; /* bp disabled convention (was 0.25, ui.css:269-272) */
    background-image: none;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    -webkit-mask-size: 10px 10px;
    mask-size: 10px 10px;
}


/* ==========================================================================
 * 17. CONNECTION STABILITY WARNING (client/styles/connection-warning.css)
 *     Chrome-only overlay — never touches the remote display itself.
 * ========================================================================== */

/* toast (css:20-37: #FFE card, #FA0 edge, shadow) → .bp-toast--warn tokens;
   original geometry (2em icon gutter) kept */
#connection-warning {
    border-left: 2em solid var(--bp-warn);
    box-shadow: none;
    background: var(--bp-surface);
    color: var(--bp-ink);
    border-radius: 0 var(--bp-radius-sm) var(--bp-radius-sm) 0;
}

/* warning glyph on the warn-colored gutter (css:39-56; original uses the
   background shorthand with url(images/warning.svg)). --bp-on-accent is
   white in BOTH themes — correct on the warn fill either way. */
#connection-warning::before {
    background: var(--bp-on-accent);
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5L21.5 20h-19z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Ccircle cx='12' cy='17.5' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5L21.5 20h-19z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Ccircle cx='12' cy='17.5' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: center;
    mask-position: center;
}

/* ======================= GROUP: login ======================= */
/* ======================================================================
 *  PEPPER26 ADAPTER — GROUP: LOGIN
 *  Blueprint re-skin for Guacamole 1.6.0 login surfaces.
 *  Screens covered:
 *    1. Login — initial credentials prompt
 *    2. Login — error state (invalid credentials)
 *    3. Login — continuation / CONTINUE flow (insufficient credentials)
 *    4. TOTP — authentication code entry
 *    5. TOTP — enrollment (QR code + secret key details)
 *  Rules target Guacamole's own selectors (no bp- classes in the DOM);
 *  this file is concatenated after Guacamole CSS in /app.css, so equal
 *  specificity wins by order. No !important is needed anywhere in this
 *  group (Guacamole's login/dialog/input/totp CSS uses none).
 *  Visual patterns are copied from blueprint-components.css (.bp-auth,
 *  .bp-input, .bp-btn--primary, .bp-pill, .bp-alert, .bp-qr, .bp-code,
 *  .bp-icon); all colors/sizes/fonts come from --bp-* tokens except the
 *  literals copied verbatim from those components (flagged inline).
 * ====================================================================== */

/* ------------------------------------------------------------------ *
 * 1. LOGIN — SHELL & CARD                                             *
 *    (overrides app/login/styles/login.css + dialog.css; the card     *
 *    also carries .notification, whose white bg / raster shadow from  *
 *    app/notification/styles/notification.css:20-25 is beaten here    *
 *    by the higher-specificity .login-ui .login-dialog rule)          *
 * ------------------------------------------------------------------ */

/* full-viewport canvas — matches login.css:20-29 verbatim */
div.login-ui {
    background: var(--bp-bg);
    color: var(--bp-ink);
    font-family: var(--bp-font-sans);
}

/* centered card — .bp-auth__card + .bp-panel language.
   Resets Guacamole's 1.25em dialog scaling (dialog.css:33-42) to the
   Blueprint base size so all inner em/rem sizing is deterministic. */
.login-ui .login-dialog {
    max-width: 400px; /* copied from .bp-auth__card (blueprint-components.css) */
    padding: var(--bp-space-8) var(--bp-space-6) var(--bp-space-6);
    font-size: var(--bp-text-base);
    line-height: var(--bp-leading-normal);
    color: var(--bp-ink);
    background-color: var(--bp-surface);
    border: var(--bp-border-width) solid var(--bp-line);
    border-radius: var(--bp-radius-md);
    box-shadow: none; /* removes .notification raster shadow (notification.css:21-22) */
}

/* legacy engraving on table headers (dialog.css:60-62) — illegible on
   dark surfaces; also affects the TOTP details table */
.login-ui .login-dialog th {
    text-shadow: none;
}

/* help / instruction paragraph (login.html:21-22, direct child of the form) */
.login-ui .login-dialog .login-form > p {
    font-size: var(--bp-text-sm);
    line-height: var(--bp-leading-snug);
    color: var(--bp-ink-dim);
    margin: var(--bp-space-3) 0;
}

/* ------------------------------------------------------------------ *
 * 2. LOGIN — BRAND (logo, app name, version pill)                     *
 * ------------------------------------------------------------------ */

/* logo swap — replaces images/guac-tricolor.svg (dialog.css:97-107) */
.login-ui .login-dialog .logo {
    width: var(--bp-space-12);
    height: var(--bp-space-12);
    margin: 0 auto var(--bp-space-4);
    background-image: url("app/ext/pepper26/images/logo.png");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

.login-ui .login-dialog .version {
    padding: var(--bp-space-2) 0 var(--bp-space-5);
}

/* wordmark — .bp-auth__brand language (dialog.css:68-73 made it
   uppercase 1.25em; Blueprint brand is bold, tight-tracked, no caps) */
.login-ui .login-dialog .version .app-name {
    font-size: var(--bp-text-lg);
    font-weight: var(--bp-weight-bold);
    letter-spacing: var(--bp-tracking-tight);
    text-transform: none;
    color: var(--bp-ink);
}

/* version badge — green italic pill (dialog.css:75-95) → .bp-pill.
   Keeps Guacamole's absolute bottom-right viewport pinning. */
.login-ui .login-dialog .version .version-number {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-2xs);
    font-style: normal;
    letter-spacing: 0.04em; /* copied from .bp-pill */
    color: var(--bp-ink-faint);
    background: var(--bp-surface);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-pill);
    padding: var(--bp-space-1) var(--bp-space-2);
    margin: var(--bp-space-2);
    opacity: 1;
}

/* ------------------------------------------------------------------ *
 * 3. LOGIN — FIELDS                                                   *
 *    Converts the floating fake-placeholder labels (login.css:59-87)  *
 *    into stacked Blueprint mono labels and applies the .bp-input     *
 *    language to the login-scoped inputs (input.css:20-33).           *
 * ------------------------------------------------------------------ */

/* field wrapper spacing (spacing moves here from the input's old
   margin-bottom; matches login.css:59-63 selector) */
.login-ui .login-fields .labeled-field {
    margin: 0 0 var(--bp-space-4);
}

/* floating label → static stacked label (was absolute, z-index -1,
   opacity .5 behind the input; login.css:65-78) */
.login-ui .login-fields .labeled-field .field-header {
    position: static;
    z-index: auto;
    overflow: visible;
    opacity: 1;
    margin: 0 0 var(--bp-space-1);
    font-size: var(--bp-text-2xs);
}

/* .bp-label language on the actual <label> (formField.html:5-7) */
.login-ui .login-fields .labeled-field .field-header label {
    font-family: var(--bp-font-mono);
    letter-spacing: var(--bp-tracking-wide);
    text-transform: uppercase;
    color: var(--bp-ink-faint);
}

/* .bp-input language — matches input.css:20-33 selector */
.login-ui .login-dialog .login-fields input {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-xs);
    color: var(--bp-ink);
    background-color: var(--bp-surface-2);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-radius: var(--bp-radius-sm);
    padding: var(--bp-space-2) var(--bp-space-3);
    width: 100%;
    max-width: none;
    margin: 0;
    display: block;
    caret-color: var(--bp-ink);
}

.login-ui .login-dialog .login-fields input::placeholder {
    color: var(--bp-ink-faint);
}

/* kill the empty-field transparency trick — beats login.css:80-82
   (same selector, later in bundle) */
.login-ui .login-fields .labeled-field.empty input {
    background: var(--bp-surface-2);
}

/* kill the focus-goes-white trick — beats login.css:84-86
   (same selector, later in bundle) */
.login-ui .login-fields .labeled-field input:focus {
    background: var(--bp-surface-2);
}

/* .bp-input:focus ring */
.login-ui .login-dialog .login-fields input:focus {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    outline-offset: var(--bp-border-width);
    border-color: var(--bp-accent);
}

/* pending state: Guacamole disables all fields while submitted
   (login.js:219-222) — .bp-input:disabled language */
.login-ui .login-dialog .login-fields input:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* browser autofill paints an opaque light box that breaks the dark
   theme; standard inset-shadow repaint (spread is structural, colors
   are tokens) */
.login-ui .login-dialog .login-fields input:-webkit-autofill,
.login-ui .login-dialog .login-fields input:-webkit-autofill:hover,
.login-ui .login-dialog .login-fields input:-webkit-autofill:focus {
    -webkit-box-shadow: inset 0 0 0 1000px var(--bp-surface-2);
    box-shadow: inset 0 0 0 1000px var(--bp-surface-2);
    -webkit-text-fill-color: var(--bp-ink);
}

/* ------------------------------------------------------------------ *
 * 4. LOGIN — ACTIONS                                                  *
 *    The LOGIN / CONTINUE submits are the primary CTA →               *
 *    .bp-btn--primary. Selector matches input.css:35-38; also beats   *
 *    the generic dark-grey button chrome, text-shadow and raster      *
 *    box-shadows from app/index/styles/buttons.css:25-58 on           *
 *    specificity.                                                     *
 * ------------------------------------------------------------------ */
.login-ui .login-dialog .buttons {
    margin-top: var(--bp-space-5);
}

.login-ui .login-dialog .buttons input[type="submit"] {
    width: 100%;
    margin: 0;
    -webkit-appearance: none;
    appearance: none;
    font-family: var(--bp-font-sans);
    font-size: var(--bp-text-base);
    font-weight: var(--bp-weight-medium);
    line-height: var(--bp-leading-tight);
    color: var(--bp-on-accent);
    background-color: var(--bp-accent);
    border: var(--bp-border-width) solid var(--bp-accent);
    border-radius: var(--bp-radius-sm);
    padding: var(--bp-space-2) var(--bp-space-3);
    min-width: 0;
    text-shadow: none;   /* buttons.css:33 engraving */
    box-shadow: none;    /* buttons.css:42 raster shadow */
    cursor: pointer;
    transition: background-color var(--bp-transition-fast),
        border-color var(--bp-transition-fast);
}

.login-ui .login-dialog .buttons input[type="submit"]:hover {
    background-color: var(--bp-accent-hover);
    border-color: var(--bp-accent-hover);
}

/* buttons.css:51-58 adds inset/outset shadows on :active */
.login-ui .login-dialog .buttons input[type="submit"]:active {
    background-color: var(--bp-accent-hover);
    border-color: var(--bp-accent-hover);
    box-shadow: none;
}

.login-ui .login-dialog .buttons input[type="submit"]:focus-visible {
    outline: var(--bp-focus-ring) solid var(--bp-accent);
    outline-offset: var(--bp-border-width-accent);
}

/* pending state (buttons.css:73-77 dims to grey; keep accent, fade) */
.login-ui .login-dialog .buttons input[type="submit"]:disabled {
    background-color: var(--bp-accent);
    color: var(--bp-on-accent);
    opacity: 0.45;
    cursor: not-allowed;
}

/* ------------------------------------------------------------------ *
 * 5. LOGIN — ERROR STATE                                              *
 *    Fixed top strip (login.css:35-53, #FDD / #964040) → Blueprint    *
 *    critical alert language (.bp-alert--crit left-edge).             *
 * ------------------------------------------------------------------ */
.login-ui.error p.login-error {
    padding: var(--bp-space-3) var(--bp-space-4);
    margin: var(--bp-space-2);
    background: var(--bp-surface);
    border: var(--bp-border-width) solid var(--bp-line-strong);
    border-left-width: 3px; /* copied from .bp-alert edge language */
    border-left-color: var(--bp-crit);
    border-radius: var(--bp-radius-sm);
    color: var(--bp-ink);
    font-size: var(--bp-text-base);
    line-height: var(--bp-leading-snug);
}

/* restrained motion: retune the head-shake (animation.css:20-34 moved
   the card ±0.25em via margins) to a subtle 4px transform nudge. The
   element hook (.login-ui.error .login-dialog, dialog.css:121-128) is
   left untouched; redefining the keyframes later in the bundle wins. */
@keyframes shake-head {
    0%, 50%  { transform: translateX(var(--bp-space-1)); }
    25%, 75% { transform: translateX(calc(-1 * var(--bp-space-1))); }
    100%     { transform: translateX(0); }
}

@-webkit-keyframes shake-head {
    0%, 50%  { transform: translateX(var(--bp-space-1)); }
    25%, 75% { transform: translateX(calc(-1 * var(--bp-space-1))); }
    100%     { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
    /* fadein (dialog.css:20-24) and shake-head (dialog.css:121-128) */
    .login-ui,
    .login-ui.error .login-dialog {
        animation: none;
        -webkit-animation: none;
    }
}

/* ------------------------------------------------------------------ *
 * 6. LOGIN — CONTINUATION (expired password / MFA prompt)             *
 *    Guacamole widens to 6in and strips the card edges                *
 *    (dialog.css:109-114); Blueprint keeps the panel look at the      *
 *    wide-card width instead.                                         *
 * ------------------------------------------------------------------ */
.login-ui.continuation .login-dialog {
    max-width: 560px; /* copied from .bp-auth__card--wide (blueprint-components.css) */
    border: var(--bp-border-width) solid var(--bp-line); /* restores edges dropped by dialog.css:110-111 */
    box-shadow: none;
}

/* CONTINUE is auto-width, right-aligned (input.css:40-42) — restate
   with the natural button minimum so it doesn't collapse */
.login-ui.continuation .login-dialog .buttons input[type="submit"] {
    width: auto;
    padding: var(--bp-space-2) var(--bp-space-5);
}

/* ------------------------------------------------------------------ *
 * 7. TOTP — AUTHENTICATION CODE ENTRY                                 *
 *    (extensions/guacamole-auth-totp templates/authenticationCode-    *
 *    Field.html:41-46) — .bp-input--otp language on the code input.   *
 *    Specificity (0,4,1) beats both the base input restyle above and  *
 *    Guacamole's labeled-field.empty rule (login.css:80-82).          *
 * ------------------------------------------------------------------ */
.login-ui .login-dialog .login-fields .totp-code input {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-lg);
    letter-spacing: 0.35em; /* copied from .bp-input--otp */
    text-align: center;
}

/* the placeholder is prose ("Authentication code") — undo OTP spread */
.login-ui .login-dialog .login-fields .totp-code input::placeholder {
    letter-spacing: var(--bp-tracking-normal);
    font-size: var(--bp-text-sm);
    font-family: var(--bp-font-sans);
}

/* ------------------------------------------------------------------ *
 * 8. TOTP — ENROLLMENT (QR + secret details)                          *
 *    (extensions/guacamole-auth-totp styles/totp.css)                 *
 * ------------------------------------------------------------------ */

/* instructional copy + details table sizing — matches totp.css:20-22 */
.totp-enroll p,
.totp-details {
    font-size: var(--bp-text-sm);
}

.totp-enroll p {
    color: var(--bp-ink-dim);
    line-height: var(--bp-leading-snug);
}

/* QR image → .bp-qr__matte treatment (totp.css:28-33). The matte fill
   is deliberately un-tokenized #fff, copied from .bp-qr__matte's
   documented exemption: a scannable QR needs a light quiet zone in
   both themes. */
.totp-qr-code img {
    margin: var(--bp-space-4);
    padding: var(--bp-space-4); /* quiet zone */
    background-color: #fff;     /* functional, per .bp-qr__matte exemption */
    border: var(--bp-border-width) solid var(--bp-line);
    border-radius: var(--bp-radius-sm);
    box-shadow: none;           /* totp.css:31 raster shadow */
    image-rendering: pixelated; /* .bp-qr__img: crisp modules when scaled */
    transition: border-color var(--bp-transition-fast);
}

.totp-qr-code img:hover {
    border-color: var(--bp-accent);
}

/* details disclosure header — .bp-details summary language */
h3.totp-details-header {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-2xs);
    font-weight: var(--bp-weight-medium);
    letter-spacing: var(--bp-tracking-wide);
    text-transform: uppercase;
    color: var(--bp-ink-faint);
}

/* '▸ ' text arrow (totp.css:39-41) → .bp-icon chevron-right mask glyph
   (currentColor tint, theme-safe; 'black' in the data URI is mask
   alpha, never a rendered color) */
h3.totp-details-header::before {
    content: "";
    display: inline-block;
    width: 14px;  /* copied from .bp-icon--sm */
    height: 14px;
    margin-right: var(--bp-space-1);
    vertical-align: -0.15em; /* copied from .bp-icon */
    background-color: currentColor;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}

/* '▾ ' open arrow (totp.css:43-45) → chevron-down glyph */
.totp-details-visible h3.totp-details-header::before {
    content: "";
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
}

/* show/hide toggle links — hardcoded 'color: blue; text-decoration:
   underline' (totp.css:64-70) → .bp-link language. display switching
   (totp.css:47-62) is left untouched. */
.totp-hide-details,
.totp-show-details {
    color: var(--bp-accent);
    text-decoration: none;
    border-bottom: var(--bp-border-width) solid transparent;
    cursor: pointer;
}

.totp-hide-details:hover,
.totp-show-details:hover {
    border-bottom-color: var(--bp-accent);
}

/* key/value details table — .bp-kv language (totp.css:72-83) */
.totp-details th {
    font-family: var(--bp-font-sans);
    font-weight: var(--bp-weight-regular);
    color: var(--bp-ink-dim);
    padding: var(--bp-space-1) var(--bp-space-3) var(--bp-space-1) 0;
    vertical-align: top;
}

.totp-details td {
    font-family: var(--bp-font-mono);
    color: var(--bp-ink);
    padding: var(--bp-space-1) 0;
}

/* grouped secret / digits / algorithm / interval chips — .bp-code
   language (totp.css:85-88) */
.totp-detail {
    font-family: var(--bp-font-mono);
    font-size: var(--bp-text-xs);
    color: var(--bp-ink);
    background-color: var(--bp-surface-2);
    border: var(--bp-border-width) solid var(--bp-line);
    border-radius: var(--bp-radius-sm);
    padding: 1px 5px; /* copied from .bp-code */
    margin: 0 var(--bp-space-1) var(--bp-space-1) 0;
}

/* ======================= GROUP: home-nav ======================= */
/* ======================================================================
   PEPPER26 ADAPTER — GROUP "home-nav"
   ----------------------------------------------------------------------
   Maps Apache Guacamole 1.6.0 DOM (unchanged markup) onto the Blueprint
   design system using --bp-* tokens only. Concatenated AFTER Guacamole's
   own CSS in /app.css: equal-specificity selectors are written verbatim
   so source order wins. No !important is used (Guacamole uses none in
   the overridden rules). Icon swaps use mask-image data-URI glyphs
   copied from the .bp-icon set (blueprint-components.css, GUACAMOLE
   ADDITIONS) painted with currentColor so they tint per theme.

   Screens covered:
     1. Home screen (home.html) — layout, section headers, loading veil
     2. Recent Connections panel (guacRecentConnections.html)
     3. Connection group tree (guacGroupList.html + item templates)
     4. Group list filter (guacGroupListFilter.html) — header-scoped only
     5. User menu (guacUserMenu.html / guacMenu.html)
     6. Page list / tab bar (guacPageList.html + tabs.css .section-tabs)
     7. Settings > Connections (settingsConnections.html)
     8. Settings > User Groups (settingsUserGroups.html)
     9. Connection Permission Editor (connectionPermissionEditor.html)
    10. Location Chooser (locationChooser.html)

   NOT restyled here (owned by the parallel "shared" group at generic
   selectors): a.button base, .filter .search-string, .pager, generic
   .menu-dropdown chrome (.menu-title colors, .menu-contents panel,
   .menu-indicator), form inputs, body typography/background.
   ====================================================================== */


/* ------------------------------------------------------------------ *
 * 0. SHARED ICON PLUMBING (tree + list glyph boxes)
 *    Guacamole draws list/tree icons as background-images on empty
 *    24px .icon divs (index/styles/ui.css .icon: 24px box, 16px
 *    background-size). Convert those boxes to currentColor masks:
 *    background-image is cancelled per original selector (verbatim,
 *    same specificity, later in bundle) and the glyph becomes mask
 *    alpha. mask-size 16px mirrors the original background-size.
 * ------------------------------------------------------------------ */
.connection .icon,
.connection-group > .caption .icon,
.sharing-profile .icon,
.connection-group.empty.balancer .icon,
.expandable > .caption .icon.expand,
.settings.user-groups table.user-group-list .icon.user-group {
  background-image: none;
  background-color: currentColor;
  color: var(--bp-ink-dim);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
}

/* protocol glyphs — beats ui.css `.connection .icon` (guac-plug.svg) */
.connection .icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
}

/* text protocols — beats ui.css `.connection .icon.kubernetes/.ssh/.telnet`
   (guac-text.svg): equal specificity, later in bundle */
.connection .icon.kubernetes,
.connection .icon.ssh,
.connection .icon.telnet {
  background-image: none;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E");
}

/* kubernetes gets its own glyph (must follow the grouped text rule) */
.connection .icon.kubernetes {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E");
}

/* desktop protocols — beats ui.css `.connection .icon.vnc/.rdp` */
.connection .icon.vnc,
.connection .icon.rdp {
  background-image: none;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
}

/* group folders — beats ui.css `.connection-group > .caption .icon`
   (folder-closed.svg) */
.connection-group > .caption .icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
}

/* beats ui.css `.connection-group.expanded > .caption .icon`
   (folder-open.svg) */
.connection-group.expanded > .caption .icon {
  background-image: none;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 19V5.5h6.5l2 3H19v2M3 19l2.7-8.5H22L19.2 19z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 19V5.5h6.5l2 3H19v2M3 19l2.7-8.5H22L19.2 19z'/%3E%3C/svg%3E");
}

/* empty balancing groups render as launchable endpoints — beats
   ui.css `.connection-group.empty.balancer .icon` (guac-monitor.svg) */
.connection-group.empty.balancer .icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E");
}


/* ------------------------------------------------------------------ *
 * 1. HOME SCREEN (home.html — .home-view, section headers, loading)
 * ------------------------------------------------------------------ */

/* section header bars — restyle index/styles/headers.css .header
   (rgba backgrounds + box-shadow) as flat Blueprint page heads.
   Scoped to this group's screens to avoid clobbering other groups. */
.home-view .header,
.connection-permissions .header {
  background-color: var(--bp-surface);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  box-shadow: none;
}

/* second header's separator — beats headers.css
   `.header:not(.ng-hide) ~ .header` rgba border-top */
.home-view .header:not(.ng-hide) ~ .header,
.home-view .header:not(.ng-hide) ~ * .header,
.connection-permissions .header:not(.ng-hide) ~ .header {
  border-top: var(--bp-border-width) solid var(--bp-line);
}

/* section titles — eyebrow treatment (headers.css h2 is 1.25em bold
   uppercase; keep uppercase, adopt Blueprint eyebrow voice) */
.home-view .header h2,
.connection-permissions .header h2 {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: var(--bp-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--bp-ink-dim);
  align-self: center;
  padding: var(--bp-space-3) var(--bp-space-4);
}

/* filter input embedded in a header — beats headers.css
   `.header .filter input` (transparent bg, rgba left divider) */
.home-view .header .filter input,
.connection-permissions .header .filter input {
  background-color: transparent;
  background-image: none;
  border: none;
  border-left: var(--bp-border-width) solid var(--bp-line);
  border-radius: 0;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
  padding: var(--bp-space-2) var(--bp-space-3);
}
.home-view .header .filter input::placeholder,
.connection-permissions .header .filter input::placeholder {
  color: var(--bp-ink-faint);
}
.home-view .header .filter input:focus,
.connection-permissions .header .filter input:focus {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: calc(-1 * var(--bp-focus-ring));
}

/* whole-view loading veil — keep Guacamole's .loading mechanics
   (loading.css: content hidden, ::before spinner, spinning-cog
   animation) but swap the 96px cog image for a token ring spinner.
   The animation property is inherited from the original rule. */
.home-view.loading {
  background-color: var(--bp-bg);
  cursor: progress;
}
.home-view.loading::before,
.settings.connections.loading::before,
.settings.user-groups.loading::before,
.settings.user-groups tbody.loading::before {
  background-image: none;
  width: var(--bp-space-10);
  height: var(--bp-space-10);
  margin-left: calc(-1 * var(--bp-space-5));
  margin-top: calc(-1 * var(--bp-space-5));
  border: var(--bp-border-width-accent) solid var(--bp-line);
  border-top-color: var(--bp-accent);
  border-radius: 50%;
}


/* ------------------------------------------------------------------ *
 * 2. RECENT CONNECTIONS PANEL (guacRecentConnections.html, home.css)
 * ------------------------------------------------------------------ */

/* card — beats home.css `div.recent-connections div.connection`
   (0.5em radius, bare padding): bordered surface card, 2px radius */
div.recent-connections div.connection {
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-3);
  margin: var(--bp-space-3);
  transition: border-color var(--bp-transition-fast);
}
div.recent-connections div.connection:hover {
  border-color: var(--bp-line-strong);
}
div.recent-connections div.connection a {
  text-decoration: none;
  color: inherit;
}

/* media well — chrome around the screenshot only; the <img> itself is
   session data and stays untouched (never tint or theme it) */
.recent-connections .connection .thumbnail {
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  overflow: hidden;
}
.recent-connections .connection .thumbnail img {
  max-width: 100%;
}

.recent-connections .connection .caption {
  margin-top: var(--bp-space-2);
}
.recent-connections .connection .caption .name {
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
}

/* empty state */
.recent-connections .placeholder {
  font-size: var(--bp-text-sm);
  color: var(--bp-ink-faint);
}

/* remove (X) — beats home.css `.remove-recent::after`
   (x-black.svg background): masked glyph tinting from currentColor */
.recent-connections .connection .remove-recent {
  color: var(--bp-ink-dim);
  opacity: 0.6;
  cursor: pointer;
}
.recent-connections .connection .remove-recent::after {
  background-image: none;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.recent-connections .connection .remove-recent:hover {
  opacity: 1;
  color: var(--bp-crit);
}
/* keyboard parity with the hover reveal (see jsNeeds: tabindex) */
.recent-connections .connection:focus-within .remove-recent {
  visibility: visible;
}
.recent-connections .connection .remove-recent:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
  opacity: 1;
}


/* ------------------------------------------------------------------ *
 * 3. CONNECTION GROUP TREE (guacGroupList.html + ui.css list rules)
 *    Shared by Home, Settings > Connections, permission editors and
 *    the location chooser.
 * ------------------------------------------------------------------ */

/* row hover — beats ui.css `.list-item:not(.selected) .caption:hover`
   (#CDA) */
.list-item:not(.selected) .caption:hover {
  background: var(--bp-surface-2);
}

/* selected row — beats ui.css `.list-item.selected` (#DEB) */
.list-item.selected {
  background: var(--bp-accent-faint);
}

/* item names — beats ui.css `.list-item .name` (color: black) */
.list-item .name {
  color: var(--bp-ink);
}

/* roomier rows inside trees only (does not touch other list modules) */
.group-list .list-item .caption {
  padding: var(--bp-space-1) var(--bp-space-2);
  border-radius: var(--bp-radius-sm);
}

/* active-user badge — restyle ui.css `.caption .activeUserCount`
   (italic float) as a Blueprint badge */
.caption .activeUserCount {
  font-style: normal;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  color: var(--bp-on-accent);
  background-color: var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  padding: 1px 6px;
  margin-right: var(--bp-space-3);
}

/* expand caret — beats ui.css `.expandable > .caption .icon.expand`
   (guac-closed.svg). Chevron rotates 90° when expanded instead of
   swapping images. Plumbing (mask props) set in section 0. */
.expandable > .caption .icon.expand {
  color: var(--bp-ink-faint);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  -webkit-mask-size: 10px 10px;
  mask-size: 10px 10px;
  transition: transform var(--bp-transition-fast);
}
/* beats ui.css `.expandable.empty > .caption .icon.expand`
   (guac-open.svg at 0.25 opacity) — keep the dimming */
.expandable.empty > .caption .icon.expand {
  background-image: none;
  transform: none;
}

/* indent guide connectors — beats ui.css
   `.expandable.expanded > .children > .list-item:before/:after`
   (#BBB lines) */
.expandable.expanded > .children > .list-item:before {
  border-left: var(--bp-border-width) solid var(--bp-line);
}
.expandable.expanded > .children > .list-item:after {
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}


/* ------------------------------------------------------------------ *
 * 4. GROUP LIST FILTER (guacGroupListFilter.html)
 *    The generic `.filter .search-string` input (list/styles/
 *    filter.css) is themed by the "shared" group; header-embedded
 *    variants are handled in section 1. Nothing further needed here.
 * ------------------------------------------------------------------ */


/* ------------------------------------------------------------------ *
 * 5. USER MENU (guacUserMenu.html; navigation/styles/user-menu.css)
 *    Generic .menu-dropdown chrome is the shared group's. Here:
 *    the avatar glyph, href-keyed item icons, logout danger styling
 *    and the profile block.
 * ------------------------------------------------------------------ */

/* trigger avatar — beats user-menu.css `.user-menu .menu-dropdown
   .menu-title` (guac-user.svg background). The element carries text,
   so the glyph moves to a masked ::before instead of an element mask. */
.user-menu .menu-dropdown .menu-title {
  background-image: none;
  position: relative;
}
.user-menu .menu-dropdown .menu-title::before {
  content: '';
  position: absolute;
  left: 0.5em;
  top: 50%;
  width: 1em;
  height: 1em;
  margin-top: -0.5em;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* menu items — beats user-menu.css `.user-menu .menu-dropdown
   .menu-contents li a` (guac-monitor.svg default icon) */
.user-menu .menu-dropdown .menu-contents li a {
  background-image: none;
  position: relative;
}
.user-menu .menu-dropdown .menu-contents li a::before {
  content: '';
  position: absolute;
  left: 0.75em;
  top: 50%;
  width: 1em;
  height: 1em;
  margin-top: -0.5em;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  /* default glyph: display (mirrors guac's monitor default) */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
}

/* home link — beats user-menu.css `... li a[href="#/"]`
   (guac-home-dark.svg) */
.user-menu .menu-dropdown .menu-contents li a[href="#/"] {
  background-image: none;
}
.user-menu .menu-dropdown .menu-contents li a[href="#/"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E");
}

/* settings links — beats user-menu.css guac-config-dark.svg rules;
   userGroups/history hrefs added so they match the other settings
   pages instead of falling back to the default glyph */
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/users"],
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/userGroups"],
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/connections"],
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/history"],
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/sessions"],
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/preferences"] {
  background-image: none;
}
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/users"]::before,
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/userGroups"]::before,
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/connections"]::before,
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/history"]::before,
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/sessions"]::before,
.user-menu .menu-dropdown .menu-contents li a[href="#/settings/preferences"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='3.5'/%3E%3Cpath d='M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.3 5.3l2.1 2.1M16.6 16.6l2.1 2.1M18.7 5.3l-2.1 2.1M7.4 16.6l-2.1 2.1'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='3.5'/%3E%3Cpath d='M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.3 5.3l2.1 2.1M16.6 16.6l2.1 2.1M18.7 5.3l-2.1 2.1M7.4 16.6l-2.1 2.1'/%3E%3C/svg%3E");
}

/* logout — beats user-menu.css `... li a.logout` (guac-logout-dark.svg);
   styled as a destructive action (.bp-menu__item--danger pattern) */
.user-menu .menu-dropdown .menu-contents li a.logout {
  background-image: none;
  color: var(--bp-crit);
}
.user-menu .menu-dropdown .menu-contents li a.logout:hover {
  background-color: var(--bp-crit-faint);
}
.user-menu .menu-dropdown .menu-contents li a.logout::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M10 4.5H4.5v15H10M20 12H9.5M16 8l4 4-4 4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M10 4.5H4.5v15H10M20 12H9.5M16 8l4 4-4 4'/%3E%3C/svg%3E");
}

/* profile block — beats user-menu.css `.profile` rgba divider; text
   maps to ink scale. Width (2in) left as-is. */
.user-menu .menu-dropdown .menu-contents .profile {
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}
.user-menu .menu-dropdown .menu-contents .profile .full-name {
  color: var(--bp-ink);
}
.user-menu .menu-dropdown .menu-contents .profile .full-name a {
  color: var(--bp-ink);
  text-decoration: none;
}
.user-menu .menu-dropdown .menu-contents .profile .full-name a:hover {
  color: var(--bp-accent);
}
.user-menu .menu-dropdown .menu-contents .profile .organization,
.user-menu .menu-dropdown .menu-contents .profile .organizational-role {
  color: var(--bp-ink-dim);
}


/* ------------------------------------------------------------------ *
 * 6. PAGE LIST / TAB BAR (guacPageList.html; navigation/styles/
 *    tabs.css) + SECTION TABS (guacSectionTabs.html)
 *    .bp-tab spec applied to the anchor-based tabs. The accent
 *    underline is an inset box-shadow (structure is ul > li > a, so
 *    the .bp-tab negative-margin trick cannot reach the ul border).
 * ------------------------------------------------------------------ */

/* tab strip — beats tabs.css `.page-tabs .page-list ul, .section-tabs ul`
   (rgba wash + rgba border) */
.page-tabs .page-list ul,
.section-tabs ul {
  background: transparent;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}

/* tab links — beats tabs.css `... li a[href], .section-tabs li a`
   (color: black) */
.page-tabs .page-list li a[href],
.section-tabs li a {
  color: var(--bp-ink-dim);
  font-weight: var(--bp-weight-medium);
  transition: color var(--bp-transition-fast),
    background-color var(--bp-transition-fast),
    box-shadow var(--bp-transition-fast);
}

/* beats tabs.css `... a[href]:visited { color: black }` */
.page-tabs .page-list li a[href]:visited {
  color: var(--bp-ink-dim);
}

/* hover — beats tabs.css #CDA hover */
.page-tabs .page-list li a[href]:hover,
.section-tabs li a:hover {
  background-color: var(--bp-surface-2);
  color: var(--bp-ink);
}

/* current tab — beats tabs.css rgba(0,0,0,0.3) block; accent underline
   drawn as an inset shadow sitting on the strip's border */
.page-tabs .page-list li a[href].current,
.page-tabs .page-list li a[href].current:hover,
.section-tabs li a.current,
.section-tabs li a.current:hover {
  background: transparent;
  color: var(--bp-accent);
  box-shadow: inset 0 calc(-1 * var(--bp-border-width-accent)) 0 var(--bp-accent);
}

.page-tabs .page-list li a[href]:focus-visible,
.section-tabs li a:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: calc(-1 * var(--bp-focus-ring));
}


/* ------------------------------------------------------------------ *
 * 7. SETTINGS > CONNECTIONS (settingsConnections.html;
 *    settings/styles/settings.css, buttons.css, connection-list.css)
 * ------------------------------------------------------------------ */

/* help text */
.settings.connections > p,
.settings.user-groups > p {
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}

/* toolbar spacing (base a.button chrome is the shared group's) */
.settings.connections .toolbar,
.settings.user-groups .toolbar {
  gap: var(--bp-space-3);
}
.settings.connections .toolbar .action-buttons,
.settings.user-groups .toolbar .action-buttons {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
}

/* action-button leading icons — beats settings/styles/buttons.css
   `a.button.add-*::before` background-image rules (masked glyphs,
   tint from the button's own ink) */
a.button.add-user::before,
a.button.add-user-group::before,
a.button.add-connection::before,
a.button.add-connection-group::before,
a.button.import-connections::before {
  background-image: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: 0.5em center;
  mask-position: 0.5em center;
  -webkit-mask-size: 1em 1em;
  mask-size: 1em 1em;
}
/* beats buttons.css `a.button.add-user::before` (guac-user-add.svg) */
a.button.add-user::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='9.5' cy='7.5' r='4'/%3E%3Cpath d='M2.5 20.5c.7-4 3.4-6.5 7-6.5s6.3 2.5 7 6.5M18.5 4v6M15.5 7h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='9.5' cy='7.5' r='4'/%3E%3Cpath d='M2.5 20.5c.7-4 3.4-6.5 7-6.5s6.3 2.5 7 6.5M18.5 4v6M15.5 7h6'/%3E%3C/svg%3E");
}
/* beats buttons.css `a.button.add-user-group::before`
   (guac-user-group-add.svg) */
a.button.add-user-group::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15.5 15c2.3.7 3.7 2.4 4 5M18.5 3.5v6M15.5 6.5h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15.5 15c2.3.7 3.7 2.4 4 5M18.5 3.5v6M15.5 6.5h6'/%3E%3C/svg%3E");
}
/* beats buttons.css `a.button.add-connection::before`
   (guac-monitor-add.svg) */
a.button.add-connection::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M12 7.5v6.5M8.75 10.75h6.5M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M12 7.5v6.5M8.75 10.75h6.5M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
}
/* beats buttons.css `a.button.add-connection-group::before`
   (guac-group-add.svg) */
a.button.add-connection-group::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3zM12 10.5v5M9.5 13h5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3zM12 10.5v5M9.5 13h5'/%3E%3C/svg%3E");
}
/* beats buttons.css `a.button.import-connections::before`
   (guac-file-import.svg) */
a.button.import-connections::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5V14M7.5 9.5l4.5 4.5 4.5-4.5M3.5 16.5v4h17v-4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 3.5V14M7.5 9.5l4.5 4.5 4.5-4.5M3.5 16.5v4h17v-4'/%3E%3C/svg%3E");
}

/* ghost create rows — beats connection-list.css opacity/italic rule;
   .bp-tree__caption--ghost treatment (dashed line box, dim ink) */
.settings.connections .connection-list .new-connection,
.settings.connections .connection-list .new-connection-group,
.settings.connections .connection-list .new-sharing-profile {
  opacity: 1;
  font-style: italic;
  border: var(--bp-border-width) dashed var(--bp-line);
  border-radius: var(--bp-radius-sm);
  margin: var(--bp-space-1) 0;
  transition: border-color var(--bp-transition-fast);
}
.settings.connections .connection-list .new-connection:hover,
.settings.connections .connection-list .new-connection-group:hover,
.settings.connections .connection-list .new-sharing-profile:hover {
  border-color: var(--bp-line-strong);
}

/* beats connection-list.css hardcoded `color: black` on ghost anchors
   (verbatim selector list, later in bundle) */
.settings.connections .connection-list .new-connection a,
.settings.connections .connection-list .new-connection a:hover,
.settings.connections .connection-list .new-connection a:visited,
.settings.connections .connection-list .new-connection-group a,
.settings.connections .connection-list .new-connection-group a:hover,
.settings.connections .connection-list .new-connection-group a:visited,
.settings.connections .connection-list .new-sharing-profile a,
.settings.connections .connection-list .new-sharing-profile a:hover,
.settings.connections .connection-list .new-sharing-profile a:visited {
  text-decoration: none;
  color: var(--bp-ink-dim);
}
.settings.connections .connection-list .new-connection a:hover,
.settings.connections .connection-list .new-connection-group a:hover,
.settings.connections .connection-list .new-sharing-profile a:hover {
  color: var(--bp-ink);
}
.settings.user-groups table.user-group-list th {
  background: transparent;
  text-align: left;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: var(--bp-tracking-wide);
  text-transform: uppercase;
  color: var(--bp-ink-faint);
}
.settings.user-groups table.user-group-list th.sortable:hover {
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
}
/* beats sorted-tables.css `...sort-primary.sort-descending:after`
   (arrows/up.svg) */
.settings.user-groups table.user-group-list th.sort-primary.sort-descending:after {
  background-image: none;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 20.5V4.5M5.5 11L12 4.5 18.5 11'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 20.5V4.5M5.5 11L12 4.5 18.5 11'/%3E%3C/svg%3E");
}

/* row links */
.settings.user-groups table.user-group-list tr.user-group td.user-group-name a[href] {
  color: var(--bp-ink);
  text-decoration: none;
  transition: background-color var(--bp-transition-fast);
}
.settings.user-groups table.user-group-list tr.user-group td.user-group-name a[href]:hover {
  background-color: var(--bp-surface-2);
}

/* disabled groups — beats user-group-list.css `tr.user-group.disabled`
   (color: gray) */
.settings.user-groups table.user-group-list tr.user-group.disabled,
.settings.user-groups table.user-group-list tr.user-group.disabled td.user-group-name a[href] {
  color: var(--bp-ink-faint);
  font-style: italic;
}

/* group glyph — beats ui.css `.icon.user-group`
   (guac-user-group.svg); plumbing in section 0 */
.settings.user-groups table.user-group-list .icon.user-group {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E");
}


/* ------------------------------------------------------------------ *
 * 9. CONNECTION PERMISSION EDITOR (connectionPermissionEditor.html)
 *    Header + filter via section 1; section tabs via section 6; tree
 *    and protocol glyphs via sections 0/3. Only the per-node choice
 *    rows need attention here.
 * ------------------------------------------------------------------ */
.connection-permissions .choice input[type='checkbox'] {
  accent-color: var(--bp-accent);
}
.connection-permission.choice .name,
.connection-group-permission.choice .name,
.sharing-profile-permission.choice .name {
  color: var(--bp-ink);
}

/* ======================= GROUP: settings ======================= */
/* ======================================================================
   PEPPER26 BLUEPRINT ADAPTER — GROUP: SETTINGS
   ----------------------------------------------------------------------
   Screens: Settings shell (settings.html) · Users tab
   (settingsUsers.html) · Active Sessions tab (settingsSessions.html) ·
   Connection History tab (settingsConnectionHistory.html) · Preferences
   tab (settingsPreferences.html) · Guacamole in-session side menu
   (#guac-menu, client.html / connection.html / connectionGroup.html /
   guacClientZoom.html).

   Loaded AFTER all Guacamole CSS in the /app.css bundle, so equal
   specificity wins by source order. Every selector below mirrors real
   Guacamole 1.6.0 markup/CSS (files cited inline). Generic controls —
   buttons (incl. button.danger), guac-filter, guac-pager, .menu-dropdown
   generics, guac-user-menu links, notification dialogs, guac-form field
   rows, checkboxes/radios/inputs — are themed by the "shared" group and
   are deliberately NOT restyled here.

   No !important anywhere: none of the Guacamole rules being overridden
   use !important or inline styles.
   ====================================================================== */

/* ------------------------------------------------------------------ *
 * SCREEN: SETTINGS SHELL (settings.html)                              *
 * ------------------------------------------------------------------ */

.settings-view { color: var(--bp-ink); }

/* page header bar — overrides .header (index/styles/headers.css:39-73) */
.settings-view .header {
  background: var(--bp-surface);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  box-shadow: none;
}
.settings-view .header h2 {
  font-family: var(--bp-font-sans);
  font-size: var(--bp-text-lg);
  font-weight: var(--bp-weight-semibold);
  letter-spacing: var(--bp-tracking-tight);
  text-transform: none;
  color: var(--bp-ink);
  padding: var(--bp-space-3) var(--bp-space-4);
}

/* shared tab-content scaffolding (settings/styles/settings.css:20-70),
   inherited by every settings tab */
.settings.section > p { color: var(--bp-ink-dim); }
.settings table.properties th {
  color: var(--bp-ink-dim);
  padding-right: var(--bp-space-4);
}
.settings .toolbar { gap: var(--bp-space-3); }

/* loading state — overrides the spinning cog image
   (.loading::before, index/styles/loading.css:37-60) with a Blueprint
   ring spinner; reuses Guacamole's own spinning-cog keyframes
   (loading.css:63). Scoped to this group's roots + table bodies. */
.settings.loading::before,
.preferences.loading::before,
.settings tbody.loading::before {
  width: var(--bp-space-10);
  height: var(--bp-space-10);
  margin-left: calc(-1 * var(--bp-space-5));
  margin-top: calc(-1 * var(--bp-space-5));
  background-image: none;
  border: var(--bp-border-width-accent) solid var(--bp-line-strong);
  border-top-color: var(--bp-accent);
  border-radius: var(--bp-space-5);
  animation: spinning-cog 0.8s linear infinite;
}

/* empty-state placeholder — overrides .placeholder
   (index/styles/lists.css:80-89: white text-shadow, 2em bolder) */
.settings .placeholder {
  color: var(--bp-ink-faint);
  text-shadow: none;
  opacity: 1;
  font-size: var(--bp-text-md);
  font-weight: var(--bp-weight-medium);
  padding: var(--bp-space-8) 0;
}

/* ------------------------------------------------------------------ *
 * SCREEN: USERS TAB (settingsUsers.html)                              *
 * ------------------------------------------------------------------ */

.settings.users table.user-list tr.user:hover {
  background-color: var(--bp-surface-2);
}
/* row link ink — beats .user a { color: black } (index/styles/lists.css) */
.settings.users table.user-list tr.user td.username a[href] {
  color: var(--bp-ink);
}
/* disabled accounts — replaces gray italic (user-list.css:39-43) with
   the Blueprint faint-ink tone (td-level too: td carries explicit ink) */
.settings.users table.user-list tr.user.disabled,
.settings.users table.user-list tr.user.disabled td,
.settings.users table.user-list tr.user.disabled td.username a[href] {
  color: var(--bp-ink-faint);
  font-style: normal;
}

/* row user glyph — replaces .icon.user guac-user.svg
   (index/styles/ui.css:151-153); .icon 24px box kept, 16px mask */
.settings.users table.user-list .icon.user {
  background-image: none;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
}

/* ------------------------------------------------------------------ *
 * SCREEN: ACTIVE SESSIONS TAB (settingsSessions.html)                 *
 * ------------------------------------------------------------------ */

/* row hover — replaces hardcoded #CDA (settings/styles/sessions.css:24-26) */
.settings table.session-list tr.session:hover {
  background: var(--bp-surface-2);
}
/* in-row link to the live client */
.settings table.session-list td a {
  color: var(--bp-accent);
  text-decoration: none;
}
.settings table.session-list td a:hover {
  color: var(--bp-accent-hover);
  text-decoration: underline;
}

/* ------------------------------------------------------------------ *
 * SCREEN: CONNECTION HISTORY TAB (settingsConnectionHistory.html)     *
 * ------------------------------------------------------------------ */

/* search row — flex layout kept (history.css:20-47); just breathing room */
.settings.connectionHistory .filter { gap: var(--bp-space-2); }

/* recording link — replaces hardcoded #0000ee (history.css:75-77) */
.settings.connectionHistory a.history-session-recording {
  color: var(--bp-accent);
}
.settings.connectionHistory a.history-session-recording:hover {
  color: var(--bp-accent-hover);
}
/* trailing play glyph — replaces guac-play-link.svg ::after
   (history.css:79-89); 1em box geometry inherited from original rule */
.settings.connectionHistory a.history-session-recording::after {
  background-image: none;
  background-color: currentColor;
  margin-left: var(--bp-space-1);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.5 4.5l12 7.5-12 7.5z' fill='black'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.5 4.5l12 7.5-12 7.5z' fill='black'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* ------------------------------------------------------------------ *
 * SCREEN: PREFERENCES TAB (settingsPreferences.html)                  *
 * ------------------------------------------------------------------ */

.preferences { color: var(--bp-ink); }

/* section dividers — h2.header picks up the global .header bar chrome
   (headers.css:39-73) + uppercase h2 base; recast as Blueprint eyebrow
   section headings on a hairline */
.preferences h2.header {
  background: transparent;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  box-shadow: none;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: var(--bp-tracking-eyebrow);
  color: var(--bp-ink-faint);
  margin-top: var(--bp-space-6);
  padding: var(--bp-space-2) var(--bp-space-4);
}

/* field tables — replaces 3px rgba(0,0,0,.125) left rail
   (settings/styles/preferences.css:20-24) */
.preferences .form .fields {
  padding-left: var(--bp-space-3);
  border-left: var(--bp-border-width-accent) solid var(--bp-line);
}
.preferences .form .fields .field-header,
.preferences .form .fields .form-field {
  padding: var(--bp-space-1);
}
.preferences .form .fields .field-header {
  padding-right: var(--bp-space-4);
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}
/* hand-built appearance/password tables (settingsPreferences.html
   table.fields th) — th is otherwise browser-default bold centered */
.preferences .form table.fields th {
  text-align: left;
  font-weight: var(--bp-weight-regular);
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
  padding-right: var(--bp-space-4);
}

/* radio-choice captions (input-method.css:20-23, mouse-mode.css:40-43) */
.preferences .input-method .caption,
.preferences .mouse-mode .caption {
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}

/* schema-driven attributes block (no .section class of its own) */
.preferences .attributes { margin: var(--bp-space-4); }

/* ------------------------------------------------------------------ *
 * SCREEN: GUACAMOLE SIDE MENU (#guac-menu, client.html:49-198)        *
 * ------------------------------------------------------------------ */

/* drawer chrome — overrides .menu (client/styles/menu.css:20-36):
   #EEE fill + white/black inset shadows -> Blueprint drawer surface;
   slide transition and open/closed positioning left untouched */
.menu {
  background: var(--bp-surface);
  box-shadow: none;
  border-right: var(--bp-border-width) solid var(--bp-line-strong);
  color: var(--bp-ink);
}
/* drawer header — overrides the global .header wash inside the menu */
.menu-content .header {
  background: var(--bp-surface);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  box-shadow: none;
}
.menu-content .header h2 {
  color: var(--bp-ink);
  font-size: var(--bp-text-md);
  font-weight: var(--bp-weight-semibold);
}
/* section headings (menu.css .menu-section h3) — eyebrow treatment */
.menu-section h3 {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: var(--bp-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--bp-ink-faint);
}
#guac-menu .menu-body .description {
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}

/* share links panel — overrides #guac-menu #share-links washes
   (client/styles/guac-menu.css) */
#guac-menu #share-links {
  background: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
}
#guac-menu #share-links th {
  color: var(--bp-ink-dim);
  font-weight: var(--bp-weight-medium);
  text-align: left;
}
#guac-menu #share-links a[href] {
  font-family: var(--bp-font-mono);
  font-weight: var(--bp-weight-medium);
  color: var(--bp-accent);
}
#guac-menu #share-links a[href]:hover { color: var(--bp-accent-hover); }

/* device rows — overrides #guac-menu #devices .device washes and the
   hover border-color: black (guac-menu.css) */
#guac-menu #devices .device {
  background: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  position: relative;
  transition: border-color var(--bp-transition-fast);
}
#guac-menu #devices .device:hover { border-color: var(--bp-accent); }
/* filesystem glyph — replaces images/drive.svg background
   (guac-menu.css #devices .device.filesystem) with a folder mask glyph */
#guac-menu #devices .device.filesystem { background-image: none; }
#guac-menu #devices .device.filesystem::before {
  content: '';
  position: absolute;
  left: var(--bp-space-4);
  top: 0;
  bottom: 0;
  width: var(--bp-space-6);
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-5) var(--bp-space-5);
  mask-size: var(--bp-space-5) var(--bp-space-5);
}

/* input-method / mouse-mode captions inside the drawer (guac-menu.css) */
#guac-menu #keyboard-settings .caption,
#guac-menu #mouse-settings .figure .caption {
  color: var(--bp-ink-dim);
}

/* connection-select dropdown — filter divider (connection-select-menu.css
   .filter input rgba border-bottom) */
.connection-select-menu .menu-dropdown .menu-contents .filter input {
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}
/* row link ink — beats .connection a / .connection-group a { color:black }
   (index/styles/lists.css) */
.connection-select-menu-connection a,
.connection-select-menu-connection-group a {
  color: var(--bp-ink);
}
.connection-select-menu .menu-contents .connection-select-menu-connection:hover,
.connection-select-menu .menu-contents .connection-select-menu-connection-group:hover {
  background-color: var(--bp-surface-2);
}

/* protocol glyphs in the connection tree (connection.html
   div.icon.type[ng-class=item.protocol]) — replace ui.css protocol
   background images (ui.css:197-214) with currentColor mask glyphs */
.connection-select-menu-connection .icon.type,
.connection-select-menu-connection-group .icon.type {
  background-image: none;
  background-color: currentColor;
  color: var(--bp-ink-dim);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 3v4.5M15 3v4.5M6 7.5h12V11a6 6 0 0 1-12 0zM12 17v4'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
}
.connection-select-menu-connection .icon.type.ssh,
.connection-select-menu-connection .icon.type.telnet {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4' width='19' height='16'/%3E%3Cpath d='M6.5 9l4 3.5-4 3.5M13 16h4.5'/%3E%3C/svg%3E");
}
.connection-select-menu-connection .icon.type.kubernetes {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M12 3.5v6M12 14.5v6M3.5 12h6M14.5 12h6M6 6l4.2 4.2M13.8 13.8L18 18M18 6l-4.2 4.2M10.2 13.8L6 18'/%3E%3C/svg%3E");
}
.connection-select-menu-connection .icon.type.vnc,
.connection-select-menu-connection .icon.type.rdp {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='2.5' y='4.5' width='19' height='12.5'/%3E%3Cpath d='M8.5 20.5h7M12 17v3.5'/%3E%3C/svg%3E");
}
.connection-select-menu-connection-group .icon.type.balancer {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='4' r='2'/%3E%3Cpath d='M12 6v5M5 13.5V11h14v2.5M12 11v2.5'/%3E%3Crect x='2.5' y='13.5' width='5' height='5'/%3E%3Crect x='9.5' y='13.5' width='5' height='5'/%3E%3Crect x='16.5' y='13.5' width='5' height='5'/%3E%3C/svg%3E");
}

/* group expand carets — replace guac-closed.svg / guac-open.svg
   (index/styles/ui.css:261-272), scoped to the connection-select tree;
   the .empty opacity 0.25 from ui.css is preserved */
.connection-select-menu .expandable > .caption .icon.expand {
  background-image: none;
  background-color: currentColor;
  color: var(--bp-ink-faint);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-3) var(--bp-space-3);
  mask-size: var(--bp-space-3) var(--bp-space-3);
}
.connection-select-menu .expandable.expanded > .caption .icon.expand {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
}

/* share dropdown glyph — replaces images/share.svg on the menu title
   (client/styles/share-menu.css); the 2em left padding is original */
.share-menu .menu-dropdown .menu-title {
  background-image: none;
  position: relative;
}
.share-menu .menu-dropdown .menu-title::before {
  content: '';
  position: absolute;
  left: var(--bp-space-2);
  top: 0;
  bottom: 0;
  width: var(--bp-space-4);
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='6.5' cy='12' r='2.5'/%3E%3Ccircle cx='17.5' cy='5.5' r='2.5'/%3E%3Ccircle cx='17.5' cy='18.5' r='2.5'/%3E%3Cpath d='M8.8 10.9l6.4-4M8.8 13.1l6.4 4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='6.5' cy='12' r='2.5'/%3E%3Ccircle cx='17.5' cy='5.5' r='2.5'/%3E%3Ccircle cx='17.5' cy='18.5' r='2.5'/%3E%3Cpath d='M8.8 10.9l6.4-4M8.8 13.1l6.4 4'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
}

/* zoom stepper — overrides client/styles/zoom.css (rgba pill buttons,
   #CDA hover); the <img> glyphs are hidden and replaced with mask
   glyphs so they tint from currentColor */
.client-zoom .client-zoom-out,
.client-zoom .client-zoom-in {
  max-width: none;
  width: var(--bp-space-8);
  height: var(--bp-space-8);
  margin: var(--bp-space-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  background: var(--bp-surface-2);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink-dim);
  position: relative;
  transition: border-color var(--bp-transition-fast),
    background-color var(--bp-transition-fast),
    color var(--bp-transition-fast);
}
/* hover redeclares the full border like the original rule it beats
   (zoom.css :hover border 1px solid rgba(0,0,0,1)) */
.client-zoom .client-zoom-out:hover,
.client-zoom .client-zoom-in:hover {
  border: var(--bp-border-width) solid var(--bp-accent);
  background: var(--bp-accent-faint);
  color: var(--bp-accent);
}
.client-zoom .client-zoom-out img,
.client-zoom .client-zoom-in img { display: none; }
.client-zoom .client-zoom-out::before,
.client-zoom .client-zoom-in::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
}
.client-zoom .client-zoom-out::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
}
.client-zoom .client-zoom-in::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
}

/* zoom readout — overrides .client-zoom-state input border rgba
   (zoom.css) */
.client-zoom .client-zoom-state {
  font-family: var(--bp-font-mono);
  color: var(--bp-ink);
}
.client-zoom .client-zoom-state input {
  font-family: inherit;
  color: var(--bp-ink);
  background: transparent;
  border-color: var(--bp-line-strong);
}
.client-zoom .client-zoom-autofit { color: var(--bp-ink); }

/* ======================= GROUP: manage ======================= */
/* ======================================================================
 * PEPPER26 ADAPTER — GROUP "MANAGE"
 * Blueprint re-skin for Apache Guacamole 1.6.0 management screens:
 *   1. Manage-screen shared scaffolding (properties table, action row,
 *      attribute forms, connection parameters)
 *   2. Manage User / Manage User Group (read-only notice, data-source
 *      tab state icons)
 *   3. Manage Connection (history table, location chooser)
 *   4. Manage Connection Group  (covered by 1 + 3, see note)
 *   5. Manage Sharing Profile
 *   6. Connection Import wizard (upload card, drop target, config help,
 *      error table)
 *   7. Connection Import file-format help page
 *   8. Identifier Set Editor (membership chips + disclosure — pairs
 *      with the three pepper26 HTML patches)
 *   9. Sortable table headers (table.sorted / guac-sort-order)
 *  10. File transfer manager dialog
 *  11. Clipboard editor
 *  12. Do-not-touch inventory
 *
 * Rules are concatenated AFTER Guacamole's own CSS in /app.css, so
 * equal-specificity selectors here win by order. Selectors are copied
 * verbatim from the cited Guacamole source files. No !important is used
 * anywhere: none of the beaten Guacamole rules use !important or inline
 * styles (the only inline style in scope — the transfer bar width —
 * is data we preserve, not chrome we fight).
 *
 * Generic controls (buttons .save/.cancel/.danger/.clone, inputs,
 * selects, checkboxes, .header bars, guac-user-menu, .page-tabs base
 * chrome, .filter/.search-string boxes, guac-pager, notification
 * modals, the global .loading veil) are themed by the shared/base
 * adapter groups and are deliberately NOT restyled here.
 * ==================================================================== */

/* ------------------------------------------------------------------ *
 * 1. MANAGE-SCREEN SHARED SCAFFOLDING
 *    Sources: manage/styles/forms.css, manage/styles/attributes.css,
 *    manage/styles/connection-parameter.css
 * ------------------------------------------------------------------ */

/* properties table label column — .bp-label mono treatment
   (beats manage/styles/forms.css `.manage table.properties th`) */
.manage table.properties th {
  text-align: left;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  padding: var(--bp-space-2) var(--bp-space-4) var(--bp-space-2) 0;
  white-space: nowrap;
  vertical-align: middle;
}

/* control column rhythm (new rule — no Guacamole counterpart) */
.manage table.properties td {
  padding: var(--bp-space-1) 0;
  color: var(--bp-ink);
}

.manage table.properties {
  border-spacing: 0 var(--bp-space-1);
}

/* Save / Clone / Cancel / Delete action row
   (beats manage/styles/forms.css `.manage .action-buttons`;
   button variants themselves come from the shared group) */
.manage .action-buttons {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--bp-space-3);
  text-align: center;
  margin: var(--bp-space-6) 0;
}

/* guac-form section headings inside attribute forms — quiet eyebrow
   instead of the boxed banner
   (beats manage/styles/attributes.css `.attributes .form h3`) */
.attributes .form h3 {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: var(--bp-tracking-wide);
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  padding: var(--bp-space-2) 0;
  margin: var(--bp-space-5) 0 var(--bp-space-2);
  border-top: none;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  box-shadow: none;
  background: transparent;
}

/* guac-form label cells — same .bp-label language as table.properties
   (beats attributes.css / connection-parameter.css `.field-header`) */
.attributes .form .fields .field-header,
.connection-parameters .form .fields .field-header {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  padding: var(--bp-space-2) var(--bp-space-4) var(--bp-space-2) 0;
}

.attributes .form .fields .form-field,
.connection-parameters .form .fields .form-field {
  padding: var(--bp-space-1) 0;
}

/* protocol-parameter form guide edge
   (beats manage/styles/connection-parameter.css
   `.connection-parameters .form .fields` — 3px rgba(0,0,0,0.125)) */
.connection-parameters .form .fields {
  border-left: var(--bp-border-width-accent) solid var(--bp-line);
  padding-left: var(--bp-space-3);
}

/* ------------------------------------------------------------------ *
 * 2. MANAGE USER & MANAGE USER GROUP
 *    Sources: manage/styles/manage-user.css,
 *    manage/styles/manage-user-group.css
 * ------------------------------------------------------------------ */

/* read-only notice — warn alert language
   (beats manage-user.css:62 / manage-user-group.css:62 `#FDA` banner) */
.manage-user .notice.read-only,
.manage-user-group .notice.read-only {
  background: var(--bp-warn-faint);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-left: var(--bp-border-width-accent) solid var(--bp-warn);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  text-align: left;
  font-size: var(--bp-text-base);
  padding: var(--bp-space-3) var(--bp-space-4);
}

/* data-source tab state icons — replace lock.svg / plus.svg /
   checkmark.svg background images with mask glyphs from the bp-icon
   set so they follow theme tokens.
   (beats manage-user(-group).css:41/45/58 background-image rules;
   the shared :before geometry from lines 27-38 is inherited as-is) */
.manage-user .page-tabs .page-list li.read-only a[href]:before,
.manage-user .page-tabs .page-list li.unlinked  a[href]:before,
.manage-user .page-tabs .page-list li.linked    a[href]:before,
.manage-user-group .page-tabs .page-list li.read-only a[href]:before,
.manage-user-group .page-tabs .page-list li.unlinked  a[href]:before,
.manage-user-group .page-tabs .page-list li.linked    a[href]:before {
  background-image: none;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
}

/* read-only: lock, quiet ink */
.manage-user .page-tabs .page-list li.read-only a[href]:before,
.manage-user-group .page-tabs .page-list li.read-only a[href]:before {
  background-color: var(--bp-ink-faint);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='4.5' y='11' width='15' height='9.5'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Crect x='4.5' y='11' width='15' height='9.5'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
}

/* unlinked: plus, accent (create affordance);
   the 0.5 opacity dimming from manage-user.css:49 is kept as-is —
   it matches Blueprint's dimming convention */
.manage-user .page-tabs .page-list li.unlinked a[href]:before,
.manage-user-group .page-tabs .page-list li.unlinked a[href]:before {
  background-color: var(--bp-accent);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
}

/* linked: checkmark, ok */
.manage-user .page-tabs .page-list li.linked a[href]:before,
.manage-user-group .page-tabs .page-list li.linked a[href]:before {
  background-color: var(--bp-ok);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 12.5l5.5 5.5L20 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 12.5l5.5 5.5L20 7'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------ *
 * 3. MANAGE CONNECTION
 *    Sources: manageConnection.html, index/styles/ui.css (.history),
 *    manage/styles/locationChooser.css
 * ------------------------------------------------------------------ */

/* usage-history table — .bp-table language (new rules; only generic
   `.history th, .history td` padding exists in ui.css and is
   out-specified here) */
.manage-connection .history table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--bp-text-base);
}
.manage-connection .history table th {
  text-align: left;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
  padding: var(--bp-space-3);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}
.manage-connection .history table td {
  padding: var(--bp-space-3);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  vertical-align: middle;
}
.manage-connection .history table td.start,
.manage-connection .history table td.duration,
.manage-connection .history table td.remoteHost {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
}

/* "never used" empty state */
.manage-connection .history > p {
  font-style: italic;
  color: var(--bp-ink-faint);
}

/* location chooser — trigger styled as a select-alike (the .location
   div has no stock styling; new rules) */
.location-chooser .location {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-space-2);
  width: 100%;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-2) var(--bp-space-3);
  cursor: pointer;
  transition: border-color var(--bp-transition-fast);
}
.location-chooser .location:hover { border-color: var(--bp-ink-faint); }

/* trailing chevron (bp-icon--chevron-down as mask) */
.location-chooser .location::after {
  content: "";
  flex: none;
  width: var(--bp-space-3);
  height: var(--bp-space-3);
  background-color: var(--bp-ink-faint);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* dropdown shell — popover surface tokens; geometry (absolute,
   z-index 2, 3in/2in) inherited from the stock rule
   (beats manage/styles/locationChooser.css `.location-chooser
   .dropdown` — white bg, rgba(0,0,0,0.5) border) */
.location-chooser .dropdown {
  background: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
}

/* ------------------------------------------------------------------ *
 * 4. MANAGE CONNECTION GROUP
 *    No unique surfaces: fully covered by section 1 (properties
 *    table, attribute form, action row) and section 3 (location
 *    chooser). Intentionally no additional rules.
 * ------------------------------------------------------------------ */

/* ------------------------------------------------------------------ *
 * 5. MANAGE SHARING PROFILE
 *    Read-only primary-connection value cell (manageSharingProfile
 *    .html:16-17 — a bare td holding text). Quiet mono value.
 * ------------------------------------------------------------------ */
.manage-sharing-profile table.properties td {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
}

/* ------------------------------------------------------------------ *
 * 6. CONNECTION IMPORT WIZARD
 *    Source: import/styles/import.css
 * ------------------------------------------------------------------ */

/* upload card — flat bordered panel
   (beats import.css `.file-upload-container` — rgba border + drop
   shadow) */
.file-upload-container {
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-md);
  box-shadow: none;
}

/* selected-file variant
   (beats import.css `.file-upload-container.file-selected` gap) */
.file-upload-container.file-selected {
  align-items: center;
  gap: var(--bp-space-8);
}
.file-upload-container.file-selected .file-name {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-md);
  color: var(--bp-ink);
}

/* upload header row */
.file-upload-container .file-options {
  font-weight: var(--bp-weight-semibold);
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
}
.file-upload-container .file-help-link {
  color: var(--bp-accent);
  text-decoration: none;
  border-bottom: var(--bp-border-width) solid transparent;
}
.file-upload-container .file-help-link:hover {
  border-bottom-color: var(--bp-accent);
}

/* drop target — .bp-dropzone language
   (beats import.css `.drop-target` — black border on rgba(0,0,0,.04)) */
.file-upload-container .drop-target {
  background: var(--bp-surface);
  border: var(--bp-border-width) dashed var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  color: var(--bp-ink-dim);
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast);
}

/* file chosen (beats import.css `.drop-target.file-present`) */
.file-upload-container .drop-target.file-present {
  background: var(--bp-surface-2);
}

/* drag hover — .bp-dropzone.is-dragover semantics
   (beats import.css `.drop-target.drop-pending` — #3161a9) */
.file-upload-container .drop-target.drop-pending {
  background: var(--bp-accent-faint);
  border-color: var(--bp-accent);
  color: var(--bp-ink);
}
/* content stays legible on the faint accent wash
   (beats import.css `.drop-target.drop-pending > *` — opacity 0.5) */
.file-upload-container .drop-target.drop-pending > * {
  opacity: 1;
}

.file-upload-container .drop-target .title { color: var(--bp-ink); }
.file-upload-container .drop-target .file-name {
  font-family: var(--bp-font-mono);
  color: var(--bp-ink);
}
.file-upload-container .drop-target .browse-link { color: var(--bp-accent); }

/* parse errors (beats import.css `.file-upload-container .file-error`) */
.file-upload-container .file-error { color: var(--bp-crit); }

/* import-config checkbox rows — align checkbox, label, help glyph */
.file-upload-container .import-config li {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  padding: var(--bp-space-1) 0;
}

/* hover-tooltip help icon — bp-icon--question mask replaces
   question.svg (beats import.css `.import-config .help::after`) */
.file-upload-container .import-config .help::after {
  background-image: none;
  background-color: var(--bp-ink-faint);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.3 9.2a2.8 2.8 0 1 1 4.5 2.2c-1 .8-1.8 1.4-1.8 2.6'/%3E%3Ccircle cx='12' cy='17.6' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.3 9.2a2.8 2.8 0 1 1 4.5 2.2c-1 .8-1.8 1.4-1.8 2.6'/%3E%3Ccircle cx='12' cy='17.6' r='1.3' fill='black' stroke='none'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-4) var(--bp-space-4);
  mask-size: var(--bp-space-4) var(--bp-space-4);
  top: 0;
}
.file-upload-container .import-config .help:hover::after {
  background-color: var(--bp-ink-dim);
}

/* action row spacing (beats import.css `.import .import-buttons`) */
.import .import-buttons {
  margin-top: var(--bp-space-4);
  gap: var(--bp-space-3);
}

/* per-row error results */
.import .errors { margin-top: var(--bp-space-6); }
/* (beats import.css `.import .errors .error-message` — red) */
.import .errors .error-message { color: var(--bp-crit); }
.import .errors .error-message ul { padding-left: var(--bp-space-5); }

/* ------------------------------------------------------------------ *
 * 7. CONNECTION IMPORT FILE-FORMAT HELP
 *    Source: import/styles/help.css — .bp-prose treatment
 * ------------------------------------------------------------------ */
.import.help p {
  line-height: var(--bp-leading-normal);
  color: var(--bp-ink-dim);
}

/* code examples (beats help.css `.import.help pre` — rgba(0,0,0,0.15)) */
.import.help pre {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-3) var(--bp-space-4);
  overflow-x: auto;
}

/* footnotes (beats help.css `.import.help .footnotes` — gray border) */
.import.help .footnotes {
  border-top: var(--bp-border-width) solid var(--bp-line);
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}

/* ------------------------------------------------------------------ *
 * 8. IDENTIFIER SET EDITOR (membership chips)
 *    Source: manage/styles/related-objects.css. The expand/collapse
 *    arrows and chip-remove X are <img src> elements in the stock
 *    template; the three pepper26 HTML patches replace them with
 *    empty <span> carriers (same class + ng-* attributes) which are
 *    drawn here as mask glyphs. Span rules below are element-
 *    qualified so the stock <img> fallback keeps working (functional,
 *    unthemed) if the patches are not installed.
 * ------------------------------------------------------------------ */

/* selected-identifier chips — .bp-token language
   (beats related-objects.css `.abbreviated-related-objects ul li` —
   silver border on #F5F5F5) */
.related-objects .abbreviated-related-objects ul li {
  border: var(--bp-border-width) solid var(--bp-line-strong);
  background: var(--bp-surface-2);
  border-radius: var(--bp-radius-sm);
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink);
  padding: var(--bp-space-1) var(--bp-space-2);
}

/* chip remove X — patched span (bp-icon--x) */
.related-objects .abbreviated-related-objects ul li span.remove {
  display: inline-block;
  width: var(--bp-space-3);
  height: var(--bp-space-3);
  margin-right: var(--bp-space-1);
  vertical-align: middle;
  background-color: var(--bp-ink-faint);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  cursor: pointer;
  transition: background-color var(--bp-transition-fast);
}
.related-objects .abbreviated-related-objects ul li span.remove:hover {
  background-color: var(--bp-crit);
}

/* expand / collapse disclosure — patched spans (bp-icon chevrons);
   table-cell keeps the stock display:table layout of
   .abbreviated-related-objects intact */
.related-objects .abbreviated-related-objects span.expand,
.related-objects .abbreviated-related-objects span.collapse {
  display: table-cell;
  width: var(--bp-space-6);
  height: var(--bp-space-6);
  background-color: var(--bp-ink-dim);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: left center;
  mask-position: left center;
  -webkit-mask-size: var(--bp-space-3) var(--bp-space-3);
  mask-size: var(--bp-space-3) var(--bp-space-3);
  cursor: pointer;
  transition: background-color var(--bp-transition-fast);
}
.related-objects .abbreviated-related-objects span.expand:hover,
.related-objects .abbreviated-related-objects span.collapse:hover {
  background-color: var(--bp-ink);
}
.related-objects .abbreviated-related-objects span.expand {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
}
.related-objects .abbreviated-related-objects span.collapse {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
}

/* expanded checkbox list divider
   (beats related-objects.css `.all-related-objects` — silver border) */
.related-objects .all-related-objects {
  border-top: var(--bp-border-width) solid var(--bp-line);
}

/* checkbox rows in the expanded list (new rules) */
.related-objects .all-related-objects ul li {
  padding: var(--bp-space-1) 0;
}
.related-objects .all-related-objects ul li label {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  cursor: pointer;
}

/* empty states — token ink instead of opacity dimming
   (beats related-objects.css `p.no-related-objects` /
   `p.no-objects-available` — opacity 0.5) */
.related-objects .abbreviated-related-objects p.no-related-objects,
.related-objects .all-related-objects p.no-objects-available {
  color: var(--bp-ink-faint);
  opacity: 1;
}

/* ------------------------------------------------------------------ *
 * 9. SORTABLE TABLE HEADERS (table.sorted / guac-sort-order)
 *    Source: index/styles/sorted-tables.css — used by the import
 *    error table (and any table.sorted app-wide, keeping one look).
 * ------------------------------------------------------------------ */

/* (beats sorted-tables.css `table.sorted th` — rgba(0,0,0,0.125)) */
table.sorted th {
  background: transparent;
  text-align: left;
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-2xs);
  font-weight: var(--bp-weight-medium);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-faint);
}

/* (beats sorted-tables.css `table.sorted th, table.sorted td` —
   #AAA borders) */
table.sorted th,
table.sorted td {
  border: none;
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  padding: var(--bp-space-2) var(--bp-space-3);
}

table.sorted th.sortable {
  transition: background-color var(--bp-transition-fast),
    color var(--bp-transition-fast);
}
table.sorted th.sortable:hover {
  background-color: var(--bp-surface-2);
  color: var(--bp-ink-dim);
}

/* primary sort column
   (beats sorted-tables.css `th.sort-primary` — bold) */
table.sorted th.sort-primary {
  font-weight: var(--bp-weight-semibold);
  color: var(--bp-accent);
}

/* ascending indicator — bp-icon--chevron-down mask via currentColor
   (beats sorted-tables.css `th.sort-primary:after` —
   arrows/down.svg) */
table.sorted th.sort-primary:after {
  background-image: none;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--bp-space-3) var(--bp-space-3);
  mask-size: var(--bp-space-3) var(--bp-space-3);
}

/* descending indicator — chevron-up
   (beats sorted-tables.css `th.sort-primary.sort-descending:after` —
   arrows/up.svg; background-image:none must be repeated at this
   specificity or the stock up.svg rule wins the cascade) */
table.sorted th.sort-primary.sort-descending:after {
  background-image: none;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 15l7-7 7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 15l7-7 7 7'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------ *
 * 10. FILE TRANSFER MANAGER (client view, corner dialog)
 *     Sources: client/styles/file-transfer-dialog.css,
 *     client/styles/transfer-manager.css, client/styles/transfer.css
 * ------------------------------------------------------------------ */

/* breathing room from the viewport corner
   (beats file-transfer-dialog.css `#file-transfer-dialog` right/bottom 0) */
#file-transfer-dialog {
  right: var(--bp-space-3);
  bottom: var(--bp-space-3);
}

/* panel surface (beats transfer-manager.css `.transfer-manager` —
   white) */
.transfer-manager {
  background: var(--bp-surface);
  color: var(--bp-ink);
}

/* panel frame (beats file-transfer-dialog.css
   `#file-transfer-dialog .transfer-manager` — rgba border + shadow) */
#file-transfer-dialog .transfer-manager {
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-md);
  box-shadow: none;
}

/* per-client section heading (beats transfer-manager.css
   `.transfer-manager h3` — opacity 0.5) */
.transfer-manager h3 {
  color: var(--bp-ink-faint);
  opacity: 1;
}

/* progress layer — flat faint fills replace the 25%-opacity overlay
   (beats transfer.css `.transfer .progress` — opacity 0.25) */
.transfer .progress { opacity: 1; }

/* track while transferring — kill the animated stripe image
   (beats transfer.css `.transfer.in-progress .progress` — #EEE +
   progress.svg animation) */
.transfer.in-progress .progress {
  background-color: var(--bp-surface-2);
  background-image: none;
  animation: none;
  -webkit-animation: none;
}

/* fill — width stays inline-driven by getPercentDone(); only the
   paint changes (beats transfer.css `.transfer .progress .bar` —
   #A3D655) */
.transfer .progress .bar { background: var(--bp-accent-faint); }

/* completed download, click to save
   (beats transfer.css `.transfer.savable .filename` — blue) */
.transfer.savable .filename { color: var(--bp-accent); }

/* failed transfer (beats transfer.css `.transfer.error` — #FDD) */
.transfer.error { background: var(--bp-crit-faint); }
.transfer.error .error-text { color: var(--bp-crit); }

/* progress caption (new rule) */
.transfer .text {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
}

/* ------------------------------------------------------------------ *
 * 11. CLIPBOARD EDITOR (in-menu clipboard widget)
 *     Source: clipboard/styles/clipboard.css
 * ------------------------------------------------------------------ */

/* textarea — .bp-textarea tokens
   (beats clipboard.css `.clipboard` white bg / #AAA border via the
   more-specific stock `.clipboard-editor .clipboard` slot) */
.clipboard-editor .clipboard {
  background-color: var(--bp-surface-2);
  color: var(--bp-ink);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
}
.clipboard-editor .clipboard:focus {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 1px;
  border-color: var(--bp-accent);
}
/* concealed state keeps text invisible (stock rule retained);
   re-assert transparency over the ink set above */
.clipboard-editor .clipboard.clipboard-contents-hidden { color: transparent; }

/* click-to-reveal privacy hint — .bp-conceal language
   (beats clipboard.css `.clipboard-contents-hidden-hint-text` —
   rgba(0,0,0,0.125) on #888) */
.clipboard-editor .clipboard-contents-hidden-hint .clipboard-contents-hidden-hint-text {
  background: var(--bp-surface-3);
  color: var(--bp-ink-dim);
  border-radius: var(--bp-radius-sm);
  transition: color var(--bp-transition-fast);
}
.clipboard-editor .clipboard-contents-hidden-hint:hover .clipboard-contents-hidden-hint-text {
  color: var(--bp-accent);
}

/* ------------------------------------------------------------------ *
 * 12. DO NOT TOUCH — functional plumbing, never brand these:
 *     .resize-sensor            (guacResize detection layer — must
 *                                keep opacity:0 / z-index:-1)
 *     .clipboard-service-target (offscreen copy/paste target)
 *     remote session pixel content (canvas / .display internals)
 *     No rules in this file target any of the above.
 * ------------------------------------------------------------------ */
/* bp-table canon parity: no rule under the final row */
table.sorted tbody tr:last-child td { border-bottom: none; }

/* ======================= GROUP: client ======================= */
/* =========================================================================
 * PEPPER26 BLUEPRINT ADAPTER — GROUP: CLIENT
 * -------------------------------------------------------------------------
 * Re-skins Apache Guacamole 1.6.0 in-session chrome to the Blueprint design
 * system using ONLY existing Guacamole selectors (no bp- classes in DOM).
 * Concatenated AFTER Guacamole's CSS in /app.css: equal-specificity rules
 * win by order, so original selectors are matched verbatim.
 *
 * Screens covered:
 *   1. Session recording player — settings wrapper (.settings.connectionHistoryPlayer)
 *   2. Session recording player — guac-player module (controls/seek/heatmap/
 *      progress/text view)
 *   3. Client viewport / tiled remote-display grid
 *   4. Filesystem menu / file browser drawer (#filesystem-menu)
 *   5. Client status / error notification modal (.client-status-modal)
 *   6. Docked client panel (#other-connections .client-panel)
 *   7. On-screen keyboard (.guac-keyboard)
 *   8. Text input method widget (.text-input)
 *
 * Icon strategy: Guacamole's background-image / <img> raster+SVG icons are
 * replaced with mask-image data-URI glyphs painted from currentColor
 * (glyphs copied from the .bp-icon set in blueprint-components.css; three
 * glyphs missing from that set — file, folder-up, warning — are drawn here
 * in the identical 24x24 / stroke-2 / square-linecap style and flagged for
 * upstream adoption).  For <img> elements the intrinsic bitmap is shifted
 * out of the paint box via object-fit:none + far-negative object-position
 * so only the masked background-color (currentColor) renders — no DOM
 * changes needed. The 'black' in mask data URIs is alpha data, never a
 * rendered color.
 *
 * No !important is used: none of the Guacamole rules beaten here use
 * !important or inline styles for the overridden properties.
 *
 * Remote session pixel content (div.display canvas, live thumbnails,
 * recording framebuffer) is intentionally untouched (chrome-only rule).
 * ========================================================================= */

/* ======================================================================= *
 * 1. SESSION RECORDING PLAYER — SETTINGS WRAPPER                          *
 *    beats app/settings/styles/history-player.css                        *
 *    pepper26.js sets data-theme="dark" on this element (see jsNeeds) so *
 *    tokens resolve to the dark layer over the black recording canvas    *
 *    regardless of app theme; without it, tokens follow the app theme.   *
 * ======================================================================= */

/* stage — beats history-player.css `.settings.connectionHistoryPlayer`
   (background: black; color: white) */
.settings.connectionHistoryPlayer {
  background: var(--bp-bg);
  color: var(--bp-ink);
  font-family: var(--bp-font-sans);
}

/* help / error blocks — inherit token ink; give them panel framing */
.settings.connectionHistoryPlayer .guac-player-help-no-recording,
.settings.connectionHistoryPlayer .guac-player-help-recording-error {
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-left: var(--bp-border-width-accent) solid var(--bp-crit);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-3) var(--bp-space-4);
  color: var(--bp-ink-dim);
}

/* transport buttons (Cancel on the loading overlay) — beats
   history-player.css `.settings.connectionHistoryPlayer .guac-player-button`
   (2px solid white border, black bg, white bold text) */
.settings.connectionHistoryPlayer .guac-player-button {
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  background: var(--bp-surface);
  color: var(--bp-ink);
  font-weight: var(--bp-weight-medium);
  font-size: var(--bp-text-base);
  cursor: pointer;
  transition: border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.settings.connectionHistoryPlayer .guac-player-button:hover {
  border-color: var(--bp-accent);
  color: var(--bp-accent);
}
.settings.connectionHistoryPlayer .guac-player-button:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* control bar — beats history-player.css
   `.settings.connectionHistoryPlayer .guac-player-controls`
   (background: rgba(0,0,0,0.5)); auto-hide opacity rules are kept */
.settings.connectionHistoryPlayer .guac-player-controls {
  background: var(--bp-surface-3);
  border-top: var(--bp-border-width) solid var(--bp-line);
}

/* heat-map legend panel — beats history-player.css
   `... .heat-map .legend` (background rgba(0,0,0,.85), radius 5px) */
.settings.connectionHistoryPlayer .guac-player-controls .heat-map .legend {
  background-color: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-xs);
}

/* legend swatches — beats history-player.css hardcoded #5BA300 / #888888.
   Mapping: key events (the interesting series) -> chart-1; frame events
   (neutral density, grey in stock Guacamole) -> chart-5. */
.settings.connectionHistoryPlayer .guac-player-controls .heat-map .legend .key-events::after {
  background-color: var(--bp-chart-1);
  border-radius: var(--bp-radius-sm);
}
.settings.connectionHistoryPlayer .guac-player-controls .heat-map .legend .frame-events::after {
  background-color: var(--bp-chart-5);
  border-radius: var(--bp-radius-sm);
}

/* heat-map SVG area fills — beats history-player.css hardcoded
   rgba(91,163,0,.5) / rgba(135,135,135,.75); follows the .bp-heatmap
   spec (flat 35% fill + 1px non-scaling stroke) */
.settings.connectionHistoryPlayer .heat-map svg.key-events path {
  fill: var(--bp-chart-1);
  fill-opacity: 0.35;
  stroke: var(--bp-chart-1);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.settings.connectionHistoryPlayer .heat-map svg.frame-events path {
  fill: var(--bp-chart-5);
  fill-opacity: 0.35;
  stroke: var(--bp-chart-5);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* ======================================================================= *
 * 2. SESSION RECORDING PLAYER — GUAC-PLAYER MODULE                        *
 *    beats app/player/styles/{player,seek,progressIndicator,textView}.css *
 * ======================================================================= */

/* --- play / pause buttons (player.css: color white, hover
       rgba(255,255,255,.5)) ------------------------------------------- */
.guac-player-controls .guac-player-play,
.guac-player-controls .guac-player-pause {
  color: var(--bp-ink);
  border-radius: var(--bp-radius-sm);
  transition: background-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.guac-player-controls .guac-player-play:hover,
.guac-player-controls .guac-player-pause:hover {
  background: var(--bp-accent-faint);
  color: var(--bp-accent);
}
.guac-player-controls .guac-player-play:focus-visible,
.guac-player-controls .guac-player-pause:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* icon glyph swap — beats player.css .play-icon/.pause-icon
   background-image url(guac-play.svg / guac-pause.svg).
   Glyphs: .bp-icon--play / .bp-icon--pause (blueprint-components.css). */
.guac-player-controls .play-icon,
.guac-player-controls .pause-icon {
  background-image: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 16px 16px;
  mask-size: 16px 16px;
}
.guac-player-controls .play-icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.5 4.5l12 7.5-12 7.5z' fill='black'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.5 4.5l12 7.5-12 7.5z' fill='black'/%3E%3C/svg%3E");
}
.guac-player-controls .pause-icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 4.5h4v15h-4zM13.5 4.5h4v15h-4z' fill='black'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 4.5h4v15h-4zM13.5 4.5h4v15h-4z' fill='black'/%3E%3C/svg%3E");
}

/* time readout — mirrors .bp-player-bar__time */
.guac-player-controls .guac-player-position {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
  color: var(--bp-ink-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* key-log toggle — actionable link ink; .disabled reads as inert */
.guac-player-controls .guac-player-keys {
  color: var(--bp-accent);
  font-size: var(--bp-text-sm);
}
.guac-player-controls .guac-player-keys:hover {
  text-decoration: underline;
}
.guac-player-controls .guac-player-keys.disabled,
.guac-player-controls .guac-player-keys.disabled:hover {
  color: var(--bp-ink-faint);
  cursor: default;
  text-decoration: none;
}

/* --- seek slider — mirrors .bp-player-bar__seek token spec.
       Scoped selectors outrank seek.css's bare input[type="range"]
       pseudo-element rules (track/fill #5AF, 3px white thumb). ---------- */
.guac-player-controls .guac-player-seek {
  -webkit-appearance: none;
  appearance: none;
  height: 16px;
  background: transparent;
  cursor: pointer;
}
/* beats seek.css `input[type="range"]:focus { outline: none }` */
.guac-player-controls .guac-player-seek:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* WebKit / Blink — beats seek.css ::-webkit-slider-runnable-track /
   ::-webkit-slider-thumb / :focus::-webkit-slider-runnable-track */
.guac-player-controls .guac-player-seek::-webkit-slider-runnable-track {
  box-sizing: border-box;
  height: 4px;
  background: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
}
.guac-player-controls .guac-player-seek:focus::-webkit-slider-runnable-track {
  background: var(--bp-surface-2);
}
.guac-player-controls .guac-player-seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  box-sizing: border-box;
  width: 12px;
  height: 12px;
  margin-top: -4px; /* (track 4px - thumb 12px) / 2 */
  background: var(--bp-surface);
  border: var(--bp-border-width-accent) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  cursor: grab;
}
.guac-player-controls .guac-player-seek::-webkit-slider-thumb:active {
  cursor: grabbing;
}

/* Firefox — beats seek.css ::-moz-range-track / ::-moz-range-thumb */
.guac-player-controls .guac-player-seek::-moz-range-track {
  box-sizing: border-box;
  height: 4px;
  background: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
}
.guac-player-controls .guac-player-seek::-moz-range-thumb {
  box-sizing: border-box;
  width: 12px;
  height: 12px;
  background: var(--bp-surface);
  border: var(--bp-border-width-accent) solid var(--bp-accent);
  border-radius: var(--bp-radius-sm);
  cursor: grab;
}
.guac-player-controls .guac-player-seek::-moz-range-thumb:active {
  cursor: grabbing;
}

/* --- loading / seek status overlay (player.css .guac-player-status:
       rgba(0,0,0,.5)) -------------------------------------------------- */
guac-player .guac-player-status {
  background: var(--bp-scrim);
}
guac-player .guac-player-status p {
  color: var(--bp-ink);
  font-size: var(--bp-text-md);
}

/* --- circular percent progress (progressIndicator.css) ---------------- */
guac-player-progress-indicator .guac-player-progress-text {
  font-family: var(--bp-font-mono);
  font-weight: var(--bp-weight-medium);
  color: var(--bp-ink);
}
/* beats progressIndicator.css hardcoded `border: 12px solid #5AF` on the
   rotation-pie ring; geometry (inline JS transform) is untouched */
guac-player-progress-indicator .guac-player-progress-bar-container.past-halfway::before,
guac-player-progress-indicator .guac-player-progress-bar {
  border-color: var(--bp-accent) transparent transparent var(--bp-accent);
}

/* --- key-log text view (textView.css) --------------------------------- */
/* beats textView.css `.guac-player-text-container`
   (background-color: white; color: black) */
.guac-player-text-container {
  background-color: var(--bp-surface);
  color: var(--bp-ink);
  border-left: var(--bp-border-width) solid var(--bp-line);
}

/* fullscreen toggle — beats textView.css .fullscreen-button
   background-image url(fullscreen.svg). Glyph: .bp-icon--fullscreen. */
.guac-player-text-container .text-controls .fullscreen-button {
  background-image: none;
  background-color: currentColor;
  color: var(--bp-ink-dim);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 9.5V4h5.5M14.5 4H20v5.5M20 14.5V20h-5.5M9.5 20H4v-5.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 9.5V4h5.5M14.5 4H20v5.5M20 14.5V20h-5.5M9.5 20H4v-5.5'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 16px 16px;
  mask-size: 16px 16px;
  transition: color var(--bp-transition-fast);
}
.guac-player-text-container .text-controls .fullscreen-button:hover {
  color: var(--bp-ink);
}

.guac-player-text-container .result-count {
  color: var(--bp-ink-dim);
  font-size: var(--bp-text-sm);
}

/* transcript batches — clickable seek targets */
.text-batches .text-batch {
  border-radius: var(--bp-radius-sm);
  transition: background-color var(--bp-transition-fast);
}
.text-batches .text-batch:hover {
  background-color: var(--bp-surface-2);
}
/* beats textView.css `.text-batches .text-batch .timestamp { color: blue }` */
.text-batches .text-batch .timestamp {
  color: var(--bp-accent);
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-xs);
}
.text-batches .text {
  font-family: var(--bp-font-mono);
}
/* beats textView.css `.not-typed { font-weight: bold }` (color added) */
.text-batches .text .not-typed {
  font-weight: var(--bp-weight-semibold);
  color: var(--bp-ink);
}
/* beats textView.css `.future { color: dimgray }` */
.text-batches .text .future {
  color: var(--bp-ink-faint);
}

/* ======================================================================= *
 * 3. CLIENT VIEWPORT / TILED REMOTE-DISPLAY GRID                          *
 *    beats app/client/styles/{client,tiled-client-grid,keyboard}.css     *
 *    div.display canvas content is session data — never themed.         *
 * ======================================================================= */

/* letterbox around the remote framebuffer — beats client.css
   `body.client { background: black }` */
body.client {
  background: var(--bp-bg);
}

/* drag-over upload highlight — beats client.css
   `.client .drop-pending .display { background: #3161a9 }` */
.client .drop-pending .display {
  background: var(--bp-accent);
}

/* user-menu disconnect entry — beats client.css
   `.client .user-menu .menu-contents li a.disconnect` background-image
   url(x.svg). The anchor also holds text, so the glyph moves to ::before
   (masking the element itself would erase the label). */
.client .user-menu .menu-contents li a.disconnect {
  background-image: none;
  position: relative;
  color: var(--bp-crit);
}
.client .user-menu .menu-contents li a.disconnect:hover {
  background: var(--bp-crit-faint);
}
.client .user-menu .menu-contents li a.disconnect::before {
  content: "";
  position: absolute;
  left: 0.75em;
  top: 50%;
  transform: translateY(-50%);
  width: 1em;
  height: 1em;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* tile header — beats tiled-client-grid.css
   `.tiled-client-grid .client-tile .client-tile-header`
   (background: #444; color: white) */
.tiled-client-grid .client-tile .client-tile-header {
  background: var(--bp-surface-3);
  color: var(--bp-ink);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  font-family: var(--bp-font-sans);
  font-weight: var(--bp-weight-medium);
}
/* beats `.tiled-client-grid .client-tile.focused .client-tile-header`
   (background-color: #3161a9) — accent inversion for the focused tile */
.tiled-client-grid .client-tile.focused .client-tile-header {
  background-color: var(--bp-accent);
  color: var(--bp-on-accent);
  border-bottom-color: var(--bp-accent);
}

/* header <img> icons -> currentColor mask glyphs (x.svg / share-white.svg).
   object-fit:none + far-negative object-position parks the intrinsic
   bitmap outside the paint box so only the masked background renders. */
.tiled-client-grid .client-tile-disconnect,
.tiled-client-grid .client-tile-shared-indicator {
  width: 1em;
  object-fit: none;
  object-position: -9999px -9999px; /* hide original bitmap, keep box */
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
/* glyph: .bp-icon--x */
.tiled-client-grid .client-tile-disconnect {
  cursor: pointer;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
}
/* glyph: .bp-icon--users */
.tiled-client-grid .client-tile-shared-indicator {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='8.5' cy='8' r='3.5'/%3E%3Cpath d='M2 20c.5-3.5 3-5.5 6.5-5.5s6 2 6.5 5.5M15 4.9a3.5 3.5 0 0 1 0 6.2M17.5 14.8c2.4.7 4 2.6 4.5 5.2'/%3E%3C/svg%3E");
}

/* joined-user count badge — beats tiled-client-grid.css
   `.tiled-client-grid .client-user-count` (background: #055) */
.tiled-client-grid .client-user-count {
  border-radius: var(--bp-radius-sm);
  background: var(--bp-accent);
  color: var(--bp-on-accent);
  font-weight: var(--bp-weight-semibold);
  font-family: var(--bp-font-sans);
}
/* header-embedded variant — beats
   `.tiled-client-grid .client-tile-header .client-user-count`
   (background: black); surface chip reads on both header states */
.tiled-client-grid .client-tile-header .client-user-count {
  background: var(--bp-surface);
  color: var(--bp-ink);
}

/* badge glyph — beats `.client-user-count::before` background
   url(guac-user-white.svg). Glyph: .bp-icon--user. */
.tiled-client-grid .client-user-count::before {
  background: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='7.5' r='4'/%3E%3Cpath d='M4.5 20.5c.7-4 3.6-6.5 7.5-6.5s6.8 2.5 7.5 6.5'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* hover popup (user list) + transient join/leave toasts — beats
   `.client-user-count-users, .client-user-count-message`
   (background: black; color: white) */
.tiled-client-grid .client-user-count .client-user-count-users,
.tiled-client-grid .client-user-count .client-user-count-message {
  border-radius: var(--bp-radius-sm);
  background: var(--bp-surface);
  color: var(--bp-ink);
  font-weight: var(--bp-weight-regular);
  font-size: var(--bp-text-sm);
}
/* beats `.client-user-count .client-user-count-users { border: 1px solid #333 }` */
.tiled-client-grid .client-user-count .client-user-count-users {
  border: var(--bp-border-width) solid var(--bp-line-strong);
}
/* popup caret — beats `.client-user-count-users::before`
   (background: black; border: 1px solid #333) */
.tiled-client-grid .client-user-count .client-user-count-users::before {
  background: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-right: none;
  border-bottom: none;
}

/* OSK / text-input tray container — beats keyboard.css
   `.keyboard-container` (background: #222; border-top: 1px solid black;
   opacity: .85) — Blueprint surfaces are flat and opaque */
.keyboard-container {
  border-top: var(--bp-border-width) solid var(--bp-line);
  background: var(--bp-surface);
  opacity: 1;
}

/* ======================================================================= *
 * 4. FILESYSTEM MENU / FILE BROWSER DRAWER                                *
 *    beats app/client/styles/{filesystem-menu,file-browser}.css          *
 *    (generic .menu drawer chrome + .button are themed by the shared     *
 *    group; only #filesystem-menu-specific surfaces are handled here)    *
 * ======================================================================= */

/* breadcrumb bar — beats filesystem-menu.css
   `#filesystem-menu .header.breadcrumbs`
   (background rgba(0,0,0,.0125), border rgba(0,0,0,.05)) */
#filesystem-menu .header.breadcrumbs {
  background: var(--bp-surface-2);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
}

/* crumb segments — mirrors .bp-crumb__link */
#filesystem-menu .header.breadcrumbs .breadcrumb {
  color: var(--bp-ink-dim);
  font-weight: var(--bp-weight-medium);
  border-radius: var(--bp-radius-sm);
  transition: background-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
/* beats `#filesystem-menu .header.breadcrumbs .breadcrumb:hover`
   (background-color: #CDA) */
#filesystem-menu .header.breadcrumbs .breadcrumb:hover {
  background-color: var(--bp-surface-3);
  color: var(--bp-ink);
}

/* root crumb — beats `.breadcrumb.root` background-image url(drive.svg).
   Empty div: whole-element mask is safe. Glyph: .bp-icon--home
   (no drive glyph exists in the bp-icon set; home = filesystem root). */
#filesystem-menu .header.breadcrumbs .breadcrumb.root {
  background-image: none;
  background-color: currentColor;
  color: var(--bp-ink-dim);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M4 11.5l8-7.5 8 7.5V20h-5.5v-5.5h-5V20H4z'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 1.25em 1.25em;
  mask-size: 1.25em 1.25em;
}
/* keep the glyph painted on hover (the generic .breadcrumb:hover
   background repaint above would recolor the mask fill) */
#filesystem-menu .header.breadcrumbs .breadcrumb.root:hover {
  background-color: currentColor;
  color: var(--bp-accent);
}

/* file rows — beats file-browser.css `.file-browser .list-item .caption`
   (border: 1px solid transparent) — kept, adds token ink + radius */
.file-browser .list-item .caption {
  border: var(--bp-border-width) solid transparent;
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  transition: background-color var(--bp-transition-fast), border-color var(--bp-transition-fast);
}
/* focused row — beats `.file-browser .list-item.focused .caption`
   (1px dotted rgba(0,0,0,.5) border, rgba(204,221,170,.5) bg) */
.file-browser .list-item.focused .caption {
  border: var(--bp-border-width) solid var(--bp-accent);
  background: var(--bp-accent-faint);
}

/* file-type icons — beat file-browser.css background-image rules
   (file.svg / folder-closed.svg / folder-up.svg). `background:
   currentColor` shorthand clears the original background-image.
   .icon geometry (24px box / 16px glyph, ui.css:58) maps to mask-size. */
.file-browser .normal-file > .caption .icon,
.file-browser .directory > .caption .icon,
.file-browser .directory.previous > .caption .icon {
  background: currentColor;
  color: var(--bp-ink-dim);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 16px 16px;
  mask-size: 16px 16px;
}
/* derived glyph "file" — drawn in bp-icon style (missing from the set) */
.file-browser .normal-file > .caption .icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6.5 3.5H14l4 4v13H6.5zM14 3.5v4h4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6.5 3.5H14l4 4v13H6.5zM14 3.5v4h4'/%3E%3C/svg%3E");
}
/* glyph: .bp-icon--folder */
.file-browser .directory > .caption .icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3C/svg%3E");
}
/* derived glyph "folder-up" — folder + up arrow, bp-icon style */
.file-browser .directory.previous > .caption .icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3Cpath d='M12 16.5V11M9.5 13.5L12 11l2.5 2.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M3 5.5h6.5l2 3H21V19H3z'/%3E%3Cpath d='M12 16.5V11M9.5 13.5L12 11l2.5 2.5'/%3E%3C/svg%3E");
}

/* ======================================================================= *
 * 5. CLIENT STATUS / ERROR NOTIFICATION MODAL                             *
 *    beats app/client/styles/notification.css                            *
 *    (the inner guac-notification generics ride the shared group; these  *
 *    higher-specificity .client-status-modal rules replace Guacamole's   *
 *    own scoped overrides, which would otherwise beat the shared theme)  *
 * ======================================================================= */

/* backdrop — beats `.client-status-modal { background: rgba(0,0,0,.5) }` */
.client-status-modal {
  background: var(--bp-scrim);
}

/* dialog strip — beats `.client-status-modal .notification`
   (background rgba(40,40,40,.75), color white, border none) */
.client-status-modal .notification {
  background: var(--bp-surface);
  color: var(--bp-ink);
  border-top: var(--bp-border-width) solid var(--bp-line);
  border-bottom: var(--bp-border-width) solid var(--bp-line);
  font-family: var(--bp-font-sans);
}
/* error variant — beats `.notification.error { background: rgba(112,9,8,.75) }`
   Blueprint alert language: surface + crit accent edge */
.client-status-modal .notification.error {
  background: var(--bp-surface);
  border-top-color: var(--bp-crit);
  border-top-width: var(--bp-border-width-accent);
}

/* action buttons — beats `.client-status-modal .notification .button`
   (2px solid white border) and its :hover/:active white-alpha fills */
.client-status-modal .notification .button {
  background: transparent;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  font-weight: var(--bp-weight-medium);
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.client-status-modal .notification .button:hover {
  text-decoration: none;
  background: var(--bp-accent-faint);
  border-color: var(--bp-accent);
  color: var(--bp-accent);
}
.client-status-modal .notification .button:active {
  background: var(--bp-accent);
  border-color: var(--bp-accent);
  color: var(--bp-on-accent);
}
.client-status-modal .notification .button:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* connection-parameter prompt fields — beats notification.css
   `... .parameters input[...]/textarea` (transparent bg, 2px white border);
   selector list copied verbatim so order decides */
.client-status-modal .notification .parameters input[type=email],
.client-status-modal .notification .parameters input[type=number],
.client-status-modal .notification .parameters input[type=password],
.client-status-modal .notification .parameters input[type=text],
.client-status-modal .notification .parameters textarea {
  background: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  font-family: var(--bp-font-mono);
}
.client-status-modal .notification .parameters input[type=email]:focus,
.client-status-modal .notification .parameters input[type=number]:focus,
.client-status-modal .notification .parameters input[type=password]:focus,
.client-status-modal .notification .parameters input[type=text]:focus,
.client-status-modal .notification .parameters textarea:focus {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 1px;
  border-color: var(--bp-accent);
}

/* ======================================================================= *
 * 6. DOCKED CLIENT PANEL (other active connections)                       *
 *    beats app/index/styles/other-connections.css                        *
 *    Live thumbnail canvases are session data — framing only.           *
 * ======================================================================= */

/* panel shell — beats `#other-connections .client-panel`
   (rgba(0,0,0,.25) bg, rgba(255,255,255,.25) border) */
#other-connections .client-panel {
  border: var(--bp-border-width) solid var(--bp-line-strong);
  background: var(--bp-surface);
}

/* grab handle — beats `#other-connections .client-panel-handle`
   (white bg + arrows/right.svg image, opacity .5) — strip stays a strip;
   the chevron moves to ::after so the mask doesn't erase the strip */
#other-connections .client-panel-handle {
  background-color: var(--bp-surface-2);
  background-image: none;
  border-right: var(--bp-border-width) solid var(--bp-line);
  opacity: 1;
  transition: background-color var(--bp-transition-fast);
}
/* beats `#other-connections .client-panel-handle:hover { opacity: .75 }` */
#other-connections .client-panel-handle:hover {
  opacity: 1;
  background-color: var(--bp-accent-faint);
}
/* glyph: .bp-icon--chevrons-right (panel open -> collapse direction) */
#other-connections .client-panel-handle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  transform: translate(-50%, -50%);
  background-color: var(--bp-ink-dim);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 5l7 7-7 7M13 5l7 7-7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 5l7 7-7 7M13 5l7 7-7 7'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
/* beats `.client-panel.hidden .client-panel-handle` background-image
   url(arrows/left.svg) — glyph flips to .bp-icon--chevrons-left */
#other-connections .client-panel.hidden .client-panel-handle {
  background-image: none;
}
#other-connections .client-panel.hidden .client-panel-handle::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M18 5l-7 7 7 7M11 5l-7 7 7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M18 5l-7 7 7 7M11 5l-7 7 7 7'/%3E%3C/svg%3E");
}

/* thumbnail card — beats `#other-connections .client-panel-connection`
   (1px white border, black bg, drop shadow, opacity .5) — mirrors
   .bp-thumb-card: flat, opaque, border feedback instead of opacity */
#other-connections .client-panel-connection {
  border: var(--bp-border-width) solid var(--bp-line-strong);
  background: var(--bp-surface);
  box-shadow: none;
  opacity: 1;
  border-radius: var(--bp-radius-sm);
  transition: border-color var(--bp-transition-fast);
}
#other-connections .client-panel-connection:hover {
  opacity: 1;
  border-color: var(--bp-accent);
}

/* attention overlay — beats `.client-panel-connection a[href]::before`
   (warning-white.svg on black); scrim only — the glyph moves to ::after */
#other-connections .client-panel-connection a[href]::before {
  background: var(--bp-scrim);
}
/* derived glyph "warning" — triangle-alert drawn in bp-icon style
   (missing from the set); mirrors .bp-thumb-card.is-attention language */
#other-connections .client-panel-connection a[href]::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  transform: translate(-50%, -50%);
  z-index: 1;
  pointer-events: none;
  background-color: var(--bp-warn);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 4L21.5 20H2.5z'/%3E%3Cpath d='M12 10v4'/%3E%3Ccircle cx='12' cy='17' r='1.2' fill='black' stroke='none'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 4L21.5 20H2.5z'/%3E%3Cpath d='M12 10v4'/%3E%3Ccircle cx='12' cy='17' r='1.2' fill='black' stroke='none'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  opacity: 0;
  transition: opacity 0.25s;
}
#other-connections .client-panel-connection.needs-attention a[href]::after {
  opacity: 1;
}
#other-connections .client-panel-connection.needs-attention {
  border-color: var(--bp-warn);
}

/* close button — beats `#other-connections button.close-other-connection`
   (transparent, opacity .5) and its img rule (#A43 circle around x.svg) */
#other-connections button.close-other-connection {
  background: var(--bp-surface);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink-dim);
  opacity: 1;
  transition: color var(--bp-transition-fast), border-color var(--bp-transition-fast);
}
#other-connections button.close-other-connection:hover {
  opacity: 1;
  color: var(--bp-crit);
  border-color: var(--bp-crit);
}
#other-connections button.close-other-connection:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}
/* glyph: .bp-icon--x tinted from the button ink */
#other-connections button.close-other-connection img {
  background: currentColor;
  border-radius: 0;
  padding: 0;
  object-fit: none;
  object-position: -9999px -9999px; /* hide original bitmap, keep box */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5.5 5.5l13 13M18.5 5.5l-13 13'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
/* beats `#other-connections button.close-other-connection:hover img
   { background: #C54 }` */
#other-connections button.close-other-connection:hover img {
  background: currentColor;
}

/* name caption — beats `#other-connections .client-panel-connection .name`
   (rgba(0,0,0,.5) bg, white text) */
#other-connections .client-panel-connection .name {
  color: var(--bp-ink);
  background: var(--bp-surface);
  border-top: var(--bp-border-width) solid var(--bp-line);
  font-weight: var(--bp-weight-medium);
  font-family: var(--bp-font-sans);
}

/* ======================================================================= *
 * 7. ON-SCREEN KEYBOARD                                                   *
 *    beats app/osk/styles/osk.css — keycaps follow the .bp-key spec.     *
 *    Structural metrics stay em-based: Guacamole.OnScreenKeyboard        *
 *    scales the tray via font-size (guacOsk.js), so only paint changes. *
 * ======================================================================= */

/* keycap — beats `.guac-keyboard .guac-keyboard-key`
   (bg #444, border .125em #666, radius .25em, white text, text-shadow) */
.guac-keyboard .guac-keyboard-key {
  background: var(--bp-surface-2);
  border: 0.125em solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  font-family: var(--bp-font-mono);
  font-weight: var(--bp-weight-medium);
  text-shadow: none;
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.guac-keyboard .guac-keyboard-key:hover {
  background: var(--bp-surface-3);
}

/* touch/hover highlight — beats `.guac-keyboard-key.highlight`
   (bg/border #666) */
.guac-keyboard .guac-keyboard-key.highlight {
  background: var(--bp-surface-3);
  border-color: var(--bp-line-strong);
}

/* latched modifiers — beats osk.css modifier block (bg #882, border #DD4);
   selector list copied verbatim; .bp-key.is-latched language */
.guac-keyboard.guac-keyboard-modifier-shift .guac-keyboard-key-rshift,
.guac-keyboard.guac-keyboard-modifier-shift .guac-keyboard-key-lshift,
.guac-keyboard.guac-keyboard-modifier-control .guac-keyboard-key-rctrl,
.guac-keyboard.guac-keyboard-modifier-control .guac-keyboard-key-lctrl,
.guac-keyboard.guac-keyboard-modifier-alt .guac-keyboard-key-ralt,
.guac-keyboard.guac-keyboard-modifier-alt .guac-keyboard-key-lalt,
.guac-keyboard.guac-keyboard-modifier-alt-gr .guac-keyboard-key-alt-gr,
.guac-keyboard.guac-keyboard-modifier-caps .guac-keyboard-key-caps,
.guac-keyboard.guac-keyboard-modifier-super .guac-keyboard-key-super,
.guac-keyboard.guac-keyboard-modifier-lat .guac-keyboard-key-latin {
  background: var(--bp-accent-faint);
  border-color: var(--bp-accent);
  color: var(--bp-accent);
}

/* momentary press — beats `.guac-keyboard-key.guac-keyboard-pressed`
   (bg #822, border #D44); .bp-key.is-pressed accent inversion */
.guac-keyboard .guac-keyboard-key.guac-keyboard-pressed {
  background: var(--bp-accent);
  border-color: var(--bp-accent);
  color: var(--bp-on-accent);
}

/* ======================================================================= *
 * 8. TEXT INPUT METHOD WIDGET (IME bar)                                   *
 *    beats app/textInput/styles/textInput.css                            *
 * ======================================================================= */

/* bar — beats `.text-input { background: #222; color: white }` */
.text-input {
  background: var(--bp-surface);
  color: var(--bp-ink);
}

/* composing textarea — beats `.text-input .target { color: white }`;
   sizes/padding untouched (guacTextInput.js geometry) */
.text-input .target {
  color: var(--bp-ink);
  font-family: var(--bp-font-mono);
  caret-color: var(--bp-accent);
}

/* sent-text echo — animated fade kept; quiet mono per matrix */
.text-input .sent-history .sent-text {
  color: var(--bp-ink-faint);
  font-family: var(--bp-font-mono);
}

/* Ctrl/Alt/Esc/Tab keys — beats `.text-input .text-input-buttons button`
   (bg #444, border .125em #666, radius .25em, text-shadow); .bp-key spec */
.text-input .text-input-buttons button {
  background: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line);
  border-radius: var(--bp-radius-sm);
  color: var(--bp-ink);
  font-family: var(--bp-font-mono);
  font-weight: var(--bp-weight-medium);
  text-shadow: none;
  transition: background-color var(--bp-transition-fast),
    border-color var(--bp-transition-fast), color var(--bp-transition-fast);
}
.text-input .text-input-buttons button:hover {
  background: var(--bp-surface-3);
}
/* momentary press — beats `button:active { background:#822; border #D44 }` */
.text-input .text-input-buttons button:active {
  background: var(--bp-accent);
  border-color: var(--bp-accent);
  color: var(--bp-on-accent);
}
/* latched sticky modifier — beats `button.pressed { background:#882;
   border #DD4 }`; .bp-key.is-latched language */
.text-input .text-input-buttons button.pressed {
  background: var(--bp-accent-faint);
  border-color: var(--bp-accent);
  color: var(--bp-accent);
}
.text-input .text-input-buttons button:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* ======================= PEPPER26 THEME TOGGLE ======================= */
.pepper26-theme-toggle {
  position: fixed;
  right: var(--bp-space-4);
  bottom: var(--bp-space-8);
  z-index: 30;
  width: 36px;
  min-width: 36px; /* generic button min-width would stretch it to 70px */
  height: 36px;
  padding: 0;
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: 50%;
  background-color: var(--bp-surface);
  cursor: pointer;
  transition: background-color var(--bp-transition-fast), border-color var(--bp-transition-fast);
}
.pepper26-theme-toggle:hover { background-color: var(--bp-surface-2); border-color: var(--bp-ink-faint); }
.pepper26-theme-toggle:focus-visible { outline: var(--bp-focus-ring) solid var(--bp-accent); }
.pepper26-theme-toggle::before {
  content: "";
  display: block;
  margin: auto;
  width: 18px;
  height: 18px;
  background-color: var(--bp-ink-dim);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
  /* moon = "switch to dark" (shown in light theme) */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z'/%3E%3C/svg%3E");
}
[data-theme="dark"] .pepper26-theme-toggle::before {
  /* sun = "switch to light" */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9L17 7M7 17l-2.1 2.1'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9L17 7M7 17l-2.1 2.1'/%3E%3C/svg%3E");
}

/* ======================= QA SWEEP FIXES (2026-07-10) ======================= */

/* Bare selects inside manage-editor properties tables (manageConnection.html
   `table.properties td > select` — protocol picker) have no field-type wrapper,
   so the shared .select-field rules never reach them. Same look as shared. */
table.properties select {
  font-family: var(--bp-font-mono);
  font-size: var(--bp-text-sm);
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
  border: var(--bp-border-width) solid var(--bp-line-strong);
  border-radius: var(--bp-radius-sm);
  padding: var(--bp-space-1) var(--bp-space-2);
  cursor: pointer;
  transition: border-color var(--bp-transition-fast);
}
table.properties select:focus {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  border-color: var(--bp-accent);
}

/* Header-embedded filters (home, connection permissions): the home-nav group's
   padding reset removed stock's 2.25em left inset, so shared's ::before
   magnifier overlapped the placeholder. Restore the inset. */
.home-view .header .filter input,
.connection-permissions .header .filter input {
  padding-left: 2.25em;
}

/* Hide the Guacamole version number pill (login screen, bottom-right) —
   user request 2026-07-10; matches the original SPSA branding behavior. */
.login-ui .login-dialog .version .version-number,
.version-number {
  display: none;
}

/* ================= ADVANCED-SETTINGS COLLAPSING (manage editors) =================
   pepper26.js tags rarely-needed fields with .pepper26-advanced; a section
   containing any becomes .pepper26-has-adv and its .form-header IS the toggle
   (chevron + "Erweitert" marker, role=button). ONE collapsing level; collapsed
   blocks stay visible as their headers. Fields are never moved in the DOM. */
.manage .form .labeled-field.pepper26-advanced {
  display: none;
}
.manage .form.pepper26-adv-open .labeled-field.pepper26-advanced {
  display: block;
}

.manage .form.pepper26-has-adv .form-header {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  transition: color var(--bp-transition-fast), background-color var(--bp-transition-fast);
}
.manage .form.pepper26-has-adv .form-header:hover {
  color: var(--bp-ink);
  background-color: var(--bp-surface-2);
}
.manage .form.pepper26-has-adv .form-header:focus-visible {
  outline: var(--bp-focus-ring) solid var(--bp-accent);
  outline-offset: 2px;
}

/* chevron — rotates open */
.manage .form.pepper26-has-adv .form-header::before {
  content: "";
  width: 12px;
  height: 12px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: 10px 10px; mask-size: 10px 10px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  transition: transform var(--bp-transition-fast);
}
.manage .form.pepper26-adv-open .form-header::before {
  transform: rotate(90deg);
}

/* "Erweitert" marker — right-aligned dashed tag; label text set by pepper26.js */
.manage .form.pepper26-has-adv .form-header::after {
  content: attr(data-pepper26-label);
  margin-left: auto;
  padding: 1px var(--bp-space-2);
  border: var(--bp-border-width) dashed var(--bp-line);
  border-radius: var(--bp-radius-sm);
  font-size: var(--bp-text-2xs);
  letter-spacing: var(--bp-tracking-wide);
  color: var(--bp-ink-faint);
}
.manage .form.pepper26-has-adv .form-header:hover::after {
  border-color: var(--bp-line-strong);
  color: var(--bp-ink-dim);
}
