@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap");

/* ==========================================================================
   SPARK PROFESSIONAL SERVICES — interface layer
   --------------------------------------------------------------------------
   The palette comes from the trade: graphite switchgear, copper busbar, and
   the amber of high-voltage signage. Copper carries navigation and links;
   volt amber is spent only on active state and focus, never on body text.
   Typography is IBM Plex — engineering documentation, not product marketing.

   Everything below is written against the v16 token layer (--surface-*,
   --ink-*, --outline-*) so it flows through components rather than fighting
   them selector by selector.
   ========================================================================== */

:root {
  /* --- brand ------------------------------------------------------------ */
  /* Three colours carry meaning and nothing else does. Amber is the brand and
     is spent only on primary actions, active navigation and the mark itself.
     Teal means a number moved the right way. Coral means something is wrong.
     A figure that is merely large gets none of them. */
  --spark-amber:      #FF9F1C;
  --spark-amber-lift: #FFB24D;
  --spark-amber-deep: #E8860A;
  --spark-amber-wash: #FFF4E6;
  --spark-teal:       #14B8A6;
  --spark-teal-wash:  #E6F7F5;
  --spark-coral:      #F0655B;
  --spark-coral-wash: #FDECEB;

  --spark-graphite:    #101820;   /* sidebar ground */
  --spark-graphite-2:  #16212B;   /* sidebar raised */
  --spark-graphite-3:  #1F2C38;

  /* Kept as aliases: the rules written against copper predate the amber
     system, and repointing them here retunes the whole desk in one place
     rather than in ninety selectors. */
  --spark-copper:      var(--spark-amber-deep);
  --spark-copper-lift: var(--spark-amber);
  --spark-copper-wash: var(--spark-amber-wash);
  --spark-volt:        var(--spark-amber);

  --spark-font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --spark-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* --- scale ------------------------------------------------------------ */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px;

  --r-sm: 8px; --r-md: 11px; --r-lg: 14px; --r-xl: 16px; --r-pill: 999px;

  --dur-fast: 160ms;
  --dur-base: 200ms;
  --dur-slow: 260ms;
  --ease: cubic-bezier(.2, .8, .3, 1);

  /* --- neutral ramp: cool graphite, not the stock warm-neutral grey ------ */
  --gray-50:  #F5F7F6;
  --gray-100: #EDF1F1;
  --gray-200: #E3E8EC;
  --gray-300: #D2D9DF;
  --gray-400: #A9B3BC;
  --gray-500: #869199;
  --gray-600: #536273; /* 5.9:1 on white (HIG pass, was #6B7785 at 4.56:1) */
  --gray-700: #46525F;
  --gray-800: #2A343F;
  --gray-900: #17212B;

  /* --- v16 semantic surfaces -------------------------------------------- */
  --surface-white:    #FFFFFF;
  --surface-modal:    #FFFFFF;
  --surface-menu-bar: #F5F7F6;
  --surface-gray-1:   #F5F7F6;
  --surface-gray-2:   #EDF1F1;
  --surface-gray-3:   #E3E8EC;
  --surface-gray-4:   #D2D9DF;
  --surface-gray-5:   #46525F;
  --surface-gray-6:   #2A343F;
  --surface-gray-7:   #17212B;
  --surface-orange-1: var(--spark-copper-wash);

  --outline-gray-1: #E3E8EC;
  --outline-gray-2: #D2D9DF;
  --outline-gray-3: #A9B3BC;
  --outline-gray-4: #869199;
  --outline-gray-modals: #E3E8EC;

  --ink-gray-1: #E3E8EC;
  --ink-gray-2: #D2D9DF;
  --ink-gray-3: #A9B3BC;
  --ink-gray-4: #869199;
  --ink-gray-5: #536273; /* 5.9:1 on white (HIG pass, was #6B7785 at 4.56:1) */
  --ink-gray-6: #46525F;
  --ink-gray-7: #46525F;
  --ink-gray-8: #2A343F;
  --ink-gray-9: #17212B;

  /* Links become copper by re-pointing the link tokens, so components that
     already reason about "link colour" pick it up without extra selectors. */
  --ink-blue-3:    var(--spark-copper);
  --ink-blue-link: var(--spark-copper-lift);

  /* --- legacy layout tokens (still used across the desk) ----------------- */
  --bg-color:            #FFFFFF;
  --fg-color:            #FFFFFF;
  --card-bg:             #FFFFFF;
  --control-bg:          #EDF1F1;
  --subtle-accent:       #F5F7F6;
  --border-color:        #E3E8EC;
  --dark-border-color:   #D2D9DF;
  --table-border-color:  #E8EDED;
  --sidebar-select-color: var(--spark-copper-wash);

  --text-color: #17212B;
  --text-muted: #536273; /* 5.9:1 on white (HIG pass, was #6B7785 at 4.56:1) */
  --text-light: #869199;

  --primary:        var(--spark-copper);
  --primary-color:  var(--spark-graphite);
  --brand-color:    var(--spark-copper);
  --btn-primary:    var(--spark-graphite);
  --border-primary: var(--spark-graphite);
  --checkbox-color: var(--spark-copper);

  --page-max-width: 1440px;

  --shadow-xs: 0 1px 2px rgba(23, 33, 43, .05);
  --shadow-sm: 0 1px 2px rgba(23, 33, 43, .04), 0 3px 8px -3px rgba(23, 33, 43, .07);
  --shadow-md: 0 2px 5px rgba(23, 33, 43, .05), 0 12px 28px -10px rgba(23, 33, 43, .14);
  --shadow-lift: 0 3px 8px rgba(23, 33, 43, .07), 0 18px 36px -14px rgba(23, 33, 43, .20);
  --card-shadow: var(--shadow-sm);
  --btn-shadow: none;

  --highlight-shadow: 0 0 0 3px rgba(255, 159, 28, .22);
  --scrollbar-thumb-color: #C6CED8;
  --scrollbar-track-color: transparent;
}

[data-theme="dark"] {
  /* The same three meanings, lifted for a dark ground: amber and teal both
     need more light behind them at low luminance or they read as brown and
     bottle green. The washes invert to tints of the ground, not of white. */
  --spark-amber:      #FFB24D;
  --spark-amber-lift: #FFC77A;
  --spark-amber-deep: #FF9F1C;
  --spark-amber-wash: #2C1D08;
  --spark-teal:       #2DD4BF;
  --spark-teal-wash:  #06251F;
  --spark-coral:      #FF8078;
  --spark-coral-wash: #2E1210;

  --spark-copper:      var(--spark-amber);
  --spark-copper-lift: var(--spark-amber-lift);
  --spark-copper-wash: var(--spark-amber-wash);
  --spark-volt:        var(--spark-amber);

  --spark-graphite:    #0B1218;
  --spark-graphite-2:  #101820;
  --spark-graphite-3:  #16212B;

  --surface-white:    #16212B;   /* cards sit ABOVE the ground, not on it */
  --surface-modal:    #1B2733;
  /* stock leaves these at literal white in :root, so every dialog, popover
     and toast rendered as a white slab on the dark desk */
  --modal-bg:         #16212B;
  --popover-bg:       #16212B;
  --toast-bg:         #16212B;
  --awesomebar-focus-bg: #1B2733;
  --surface-menu-bar: #101820;
  --surface-cards:    #141E27;
  --surface-gray-1:   #141E27;
  --surface-gray-2:   #1B2733;
  --surface-gray-3:   #243240;
  --surface-gray-4:   #2F3F4E;

  --outline-gray-1: #212D39;
  --outline-gray-2: #2C3A47;
  --outline-gray-3: #3D4B59;
  --outline-gray-modals: #2C3A47;

  --ink-gray-9: #EAF0F5;
  --ink-gray-8: #D3DCE4;
  --ink-gray-7: #97A5B2;
  --ink-gray-6: #97A5B2;
  --ink-gray-5: #808D9B;

  --ink-blue-3:    var(--spark-copper);
  --ink-blue-link: var(--spark-copper-lift);

  --bg-color:           #0E151C;   /* the ground */
  --fg-color:           #141E27;
  --card-bg:            #141E27;
  --control-bg:         #1B2733;
  --subtle-accent:      #16212B;
  --border-color:       #243240;
  --dark-border-color:  #2F3F4E;
  --table-border-color: #212D39;
  --sidebar-select-color: #22160C;

  --text-color: #E9EEF4;
  --text-muted: #93A0AE;
  --text-light: #6F7C8B;

  --primary-color:  #E9EEF4;
  --btn-primary:    #E9EEF4;
  --border-primary: #E9EEF4;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .45), 0 6px 16px -6px rgba(0, 0, 0, .6);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, .5), 0 24px 48px -16px rgba(0, 0, 0, .75);
  --highlight-shadow: 0 0 0 3px rgba(249, 115, 22, .22);
  --scrollbar-thumb-color: #2E3844;
}

/* ==========================================================================
   TYPOGRAPHY
   ========================================================================== */

body, .page-container, .modal, input, select, textarea, button, .btn, .form-control {
  font-family: var(--spark-font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6, .page-title, .widget-title, .section-head {
  font-family: var(--spark-font);
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.page-head .title-text, .page-title .title-text {
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* ==========================================================================
   MONOSPACE — identifiers and money only.
   Document names now read SPK-QTE-2026-0002; give them the face they earn.
   Deliberately narrow: names of people and companies stay in the sans face.
   ========================================================================== */

.spark-docname,
.list-row-col:last-of-type .level-item .ellipsis,
code, kbd, pre {
  font-family: var(--spark-mono);
  letter-spacing: -.012em;
}

[data-fieldtype="Currency"] .control-value,
[data-fieldtype="Currency"] input,
[data-fieldtype="Float"] input,
[data-fieldtype="Int"] input,
[data-fieldtype="Percent"] input,
.dt-cell__content,
.widget.number-widget-box .widget-content .number,
.widget.number-card .widget-content .number,
.list-row-col .level-item [data-filter*="Currency"],
.grid-static-col[data-fieldtype="Currency"],
.grid-static-col[data-fieldtype="Float"],
.grid-static-col[data-fieldtype="Int"],
.total-row, .grand-total {
  font-family: var(--spark-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ==========================================================================
   THE LEFT RAIL — v16's only persistent chrome, so it carries the identity.
   A graphite instrument panel against the white work surface.
   ========================================================================== */

.body-sidebar {
  background: var(--spark-graphite) !important;
  border-right: 1px solid rgba(255, 255, 255, .06);
  position: relative;
  width: 248px;
  min-width: 248px;
}

/* The rail is absolutely positioned; its container is what reserves the space
   the page is laid out around. Widening one without the other slides the rail
   over the first 28px of every page. */
.body-sidebar-container.expanded,
.body-sidebar-container.expanded .body-sidebar { width: 248px; min-width: 248px; }

/* A live copper filament down the edge of the rail. */
.body-sidebar::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0; right: 0;
  width: 2px;
  background: linear-gradient(180deg,
    var(--spark-copper) 0%,
    var(--spark-copper) 38%,
    var(--spark-volt) 50%,
    var(--spark-copper) 62%,
    var(--spark-copper) 100%);
  background-size: 100% 300%;
  opacity: .8;
  animation: spark-filament 18s linear infinite;
  pointer-events: none;
}

@keyframes spark-filament {
  from { background-position: 0 0; }
  to   { background-position: 0 300%; }
}

@media (prefers-reduced-motion: reduce) {
  .body-sidebar::after { animation: none; }
}

/* Text and icons invert onto the dark rail. */
.body-sidebar .sidebar-item-label,
.body-sidebar .item-anchor,
.body-sidebar .sidebar-item-label.header-title,
.body-sidebar .dropdown-item,
.body-sidebar .keyboard-shortcut {
  color: rgba(255, 255, 255, .78);
}

.body-sidebar .sidebar-item-icon svg use,
.body-sidebar .drop-icon svg use { stroke: rgba(255, 255, 255, .62); }
.body-sidebar .sidebar-item-icon { color: rgba(255, 255, 255, .62); }

.body-sidebar .keyboard-shortcut {
  color: rgba(255, 255, 255, .38);
  background: rgba(255, 255, 255, .07);
  border-radius: 5px;
  font-family: var(--spark-mono);
  font-size: 11px;
}

/* Brand block at the top of the rail. */
.body-sidebar .sidebar-header {
  padding-block: 12px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  margin-bottom: 6px;
}
.body-sidebar .header-logo img { filter: drop-shadow(0 0 10px rgba(255, 178, 36, .35)); }
.body-sidebar .header-title {
  font-weight: 600;
  letter-spacing: -.01em;
  color: #FFFFFF;
}
.body-sidebar .header-subtitle {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--spark-volt);
  opacity: .85;
}

/* Rows. */
.body-sidebar .standard-sidebar-item {
  border-radius: 8px;
  position: relative;
  transition: background .15s ease;
}
.body-sidebar .standard-sidebar-item:hover { background: rgba(255, 255, 255, .06); }

/* A translucent amber pill rather than the solid slab this used to be: at
   sidebar size a filled block reads as an unfinished button, and it buries the
   label it is meant to be pointing at. */
.body-sidebar .standard-sidebar-item.active-sidebar,
.body-sidebar .standard-sidebar-item.selected {
  background: linear-gradient(90deg,
              rgba(255, 159, 28, .18) 0%, rgba(255, 159, 28, .06) 100%);
  border-radius: var(--r-md);
  box-shadow: 0 0 24px -10px rgba(255, 159, 28, .55);
}
.body-sidebar .standard-sidebar-item.active-sidebar .sidebar-item-label,
.body-sidebar .standard-sidebar-item.selected .sidebar-item-label {
  color: var(--spark-amber-lift);
  font-weight: 600;
}
.body-sidebar .standard-sidebar-item.active-sidebar .sidebar-item-icon svg use,
.body-sidebar .standard-sidebar-item.selected .sidebar-item-icon svg use { stroke: var(--spark-volt); }

.body-sidebar .standard-sidebar-item.active-sidebar::before,
.body-sidebar .standard-sidebar-item.selected::before {
  content: "";
  position: absolute;
  left: -4px; top: 24%; bottom: 24%;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--spark-amber);
  box-shadow: 0 0 10px rgba(255, 159, 28, .6);
  transition: top 200ms var(--ease), bottom 200ms var(--ease);
}

/* Group captions. */
.body-sidebar .standard-sidebar-label,
.body-sidebar .sidebar-group-title {
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 10.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, .34);
}

/* Signed-in user block at the foot of the rail. */
.body-sidebar .dropdown-mobile .sidebar-item-label,
.body-sidebar .user-dropdown .sidebar-item-label { color: rgba(255, 255, 255, .8); }
.body-sidebar .avatar-frame { border: 1px solid rgba(255, 255, 255, .18); }

/* Anything inside the rail that is genuinely a popover returns to light. */
.body-sidebar .dropdown-menu,
.body-sidebar .notifications-list {
  background: var(--surface-modal);
  border: 1px solid var(--outline-gray-2);
  box-shadow: var(--shadow-md);
}
.body-sidebar .dropdown-menu .dropdown-item,
.body-sidebar .notifications-list * { color: var(--ink-gray-8); }

/* ==========================================================================
   PAGE HEAD
   ========================================================================== */

.page-head {
  border-bottom: 1px solid var(--outline-gray-1);
  backdrop-filter: saturate(1.1) blur(6px);
}

.page-head .title-area .ellipsis { letter-spacing: -.02em; }

.breadcrumb .breadcrumb-item a { color: var(--ink-gray-5); }
.breadcrumb .breadcrumb-item a:hover { color: var(--spark-copper); }

/* ==========================================================================
   LISTS
   ========================================================================== */

.list-row-head {
  background: var(--surface-gray-1);
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: .08em;
  font-weight: 600;
  position: sticky;
  top: 0;
  z-index: 3;
}

.list-row-container { transition: background .12s ease, box-shadow .12s ease; }
.list-row-container:hover { background: var(--surface-gray-1); }
.list-row-container:hover .list-subject .ellipsis { color: var(--spark-copper); }
.result .list-row-container:not(:last-child) { border-bottom: 1px solid var(--table-border-color); }

/* Status pills: shape and border carry state as well as colour. */
.indicator-pill, .indicator-pill-round {
  border-radius: 6px;
  font-weight: 550;
  letter-spacing: .015em;
  border: 1px solid transparent;
}
.indicator-pill.green  { border-color: rgba(39, 143, 94, .26); }
.indicator-pill.orange { border-color: rgba(219, 119, 6, .26); }
.indicator-pill.red    { border-color: rgba(204, 41, 41, .24); }
.indicator-pill.blue   { border-color: rgba(0, 123, 224, .24); }
.indicator-pill.gray, .indicator-pill.grey { border-color: var(--outline-gray-2); }

/* ==========================================================================
   CARDS, WIDGETS, FORMS
   ========================================================================== */

.frappe-card, .widget, .form-section, .form-tabs-sticky-down {
  border-radius: 10px;
  border-color: var(--outline-gray-1);
}

.widget {
  box-shadow: var(--card-shadow);
  transition: box-shadow .2s ease, transform .2s ease;
}
.widget:hover { box-shadow: var(--shadow-md); }
.widget.shortcut-widget-box:hover .widget-title { color: var(--spark-copper); }
.widget.number-widget-box .number,
.widget.number-card .number { letter-spacing: -.02em; }

.form-control, .input-with-feedback, textarea.form-control, .select-input {
  border-radius: 7px;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.form-control:focus, .input-with-feedback:focus, textarea.form-control:focus {
  border-color: var(--spark-copper);
  box-shadow: var(--highlight-shadow);
  outline: none;
}

.form-tabs .nav-link.active {
  color: var(--spark-copper);
  border-bottom-color: var(--spark-copper);
  font-weight: 600;
}

/* ==========================================================================
   BUTTONS AND FOCUS
   ========================================================================== */

.btn { border-radius: 7px; font-weight: 550; transition: all .16s ease; }

.btn-primary {
  background: var(--spark-graphite);
  border-color: var(--spark-graphite);
  color: #FFFFFF;
}
.btn-primary:hover, .btn-primary:focus {
  background: var(--spark-graphite-3);
  border-color: var(--spark-graphite-3);
  box-shadow: 0 4px 14px -4px rgba(14, 19, 25, .45);
}
[data-theme="dark"] .btn-primary { background: #E9EEF4; border-color: #E9EEF4; color: #0B0F14; }
[data-theme="dark"] .btn-primary:hover { background: #FFFFFF; border-color: #FFFFFF; }

:focus-visible {
  outline: 2px solid var(--spark-copper);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ==========================================================================
   REPORT / DATATABLE — the numbers view
   ========================================================================== */

.datatable .dt-header, .dt-header .dt-cell {
  background: var(--surface-gray-1);
  color: var(--ink-gray-5);
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: .08em;
  font-weight: 600;
}
.datatable .dt-cell--highlight { background: var(--spark-copper-wash); }
.datatable .dt-row:hover .dt-cell { background: var(--surface-gray-1); }

/* ==========================================================================
   SCROLLBARS
   ========================================================================== */

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--scrollbar-track-color); }
::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb-color);
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--gray-500); background-clip: content-box; }
.body-sidebar ::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, .16); background-clip: content-box; }

/* ==========================================================================
   LOGIN / PORTAL
   ========================================================================== */

.page-card, .login-content {
  border-radius: 12px;
  box-shadow: var(--shadow-md);
  border: 1px solid var(--outline-gray-1);
}
.for-login .page-card-head::after {
  content: "HIGH VOLTAGE TESTING & COMMISSIONING";
  display: block;
  margin-top: 6px;
  font-family: var(--spark-mono);
  font-size: 11px;
  letter-spacing: .16em;
  color: var(--ink-gray-4);
}

/* --------------------------------------------------------------------------
   Rail footer — the signed-in user block. Everything here inherits light
   text explicitly; the stock colours assume a white surface.
   -------------------------------------------------------------------------- */

.body-sidebar-bottom,
.body-sidebar-bottom a,
.body-sidebar-bottom span,
.body-sidebar-bottom p,
.body-sidebar-bottom .sidebar-item-label,
.body-sidebar-cards,
.body-sidebar-cards *,
.body-sidebar .collapse-sidebar-link {
  color: rgba(255, 255, 255, .74);
}

.body-sidebar-bottom .dropdown-navbar-user .sidebar-item-label { color: #FFFFFF; }
.body-sidebar-bottom svg use,
.body-sidebar .collapse-sidebar-link svg use { stroke: rgba(255, 255, 255, .6); }

.body-sidebar-bottom { border-top: 1px solid rgba(255, 255, 255, .07); }
.body-sidebar-bottom .dropdown-navbar-user:hover { background: rgba(255, 255, 255, .06); border-radius: 8px; }

/* The rail's own dropdowns are popovers on a light surface — reset them. */
.body-sidebar-bottom .dropdown-menu,
.body-sidebar-bottom .dropdown-menu a,
.body-sidebar-bottom .dropdown-menu span {
  color: var(--ink-gray-8);
  background-color: transparent;
}
.body-sidebar-bottom .dropdown-menu {
  background: var(--surface-modal);
  border: 1px solid var(--outline-gray-2);
  box-shadow: var(--shadow-md);
}

/* Header block: brand over context. */
.body-sidebar .sidebar-header .header-title {
  font-size: .95rem;
  line-height: 1.15;
}
.body-sidebar .sidebar-header .header-subtitle {
  font-size: 11px;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Grid headers stay in the sans face — only the values below them are data. */
.grid-heading-row .col,
.grid-heading-row .static-area,
.form-grid .grid-heading-row,
.grid-heading-row [data-fieldtype] {
  font-family: var(--spark-font);
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: .07em;
  font-weight: 600;
  color: var(--ink-gray-5);
}

.body-sidebar .header-logo img.spark-mark {
  display: block;
  border-radius: 0;
  background: none;
}

/* ==========================================================================
   DASHBOARD — number cards and charts
   ========================================================================== */

.widget.number-widget-box,
.widget.number-card {
  border-radius: 10px;
  border: 1px solid var(--outline-gray-1);
  position: relative;
  overflow: hidden;
}

/* A copper hairline along the top edge marks these as Spark's own figures. */
.widget.number-widget-box::before,
.widget.number-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--spark-copper), var(--spark-volt));
  opacity: .85;
}

.widget.number-widget-box .widget-head .widget-title,
.widget.number-card .widget-head .widget-title {
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--ink-gray-5);
}

.widget.number-widget-box .widget-content .number,
.widget.number-card .widget-content .number {
  font-family: var(--spark-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: -.03em;
  color: var(--ink-gray-9);
}

/* Charts: axis furniture recedes, the data does not. */
.chart-container .chart-legend, .frappe-chart .chart-label { font-family: var(--spark-font); }
.frappe-chart .axis text, .frappe-chart .chart-label {
  font-family: var(--spark-mono);
  font-size: 11px;
  fill: var(--ink-gray-5);
}
.frappe-chart .axis line, .frappe-chart line.y-line, .frappe-chart .y-axis-guide {
  stroke: var(--outline-gray-1);
}
.widget.chart .widget-head .chart-title { letter-spacing: -.015em; font-weight: 600; }

/* Shortcut tiles read as buttons, and their count badge as data. */
.widget.shortcut-widget-box { border-radius: 10px; }
.widget.shortcut-widget-box .indicator-pill {
  font-family: var(--spark-mono);
  font-variant-numeric: tabular-nums;
}

/* The onboarding link is retired along with the tours. */
.body-sidebar-bottom .onboarding-sidebar,
.body-sidebar-bottom p:has(> .onboarding-sidebar) { display: none !important; }

/* The About dialog, rebuilt by spark.js. */
.spark-about { text-align: center; padding: 8px 4px 18px; }
.spark-about img { display: block; margin: 0 auto 14px; }
.spark-about-name {
  font-size: 1.28rem; font-weight: 600; letter-spacing: -.02em; color: var(--ink-gray-9);
  text-wrap: balance;
}
.spark-about-tag { color: var(--ink-gray-5); font-size: .85rem; margin-top: 2px; }
.spark-about-ver {
  font-family: var(--spark-mono); font-size: 11px; letter-spacing: .04em;
  color: var(--spark-copper); margin-top: 10px;
}
.spark-about-rule {
  width: 40px; height: 3px; border-radius: 3px; margin: 22px auto;
  background: linear-gradient(90deg, var(--spark-copper), var(--spark-volt));
}
.spark-about-label {
  font-family: var(--spark-mono); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-gray-5);
}
.spark-about-components {
  font-family: var(--spark-mono); font-size: 11px; color: var(--ink-gray-6);
  margin-top: 6px; word-spacing: .1em;
}

/* Bootstrap paints .modal-content with a literal white, so the token never got
   a look in and every dialog was a white slab on the dark desk. Routed through
   --modal-bg, which both themes define. */
.modal-content,
.modal-header,
.modal-body,
.modal-footer {
  background-color: var(--modal-bg);
  color: var(--ink-gray-9);
}
.modal-header, .modal-footer { border-color: var(--outline-gray-1); }
.dropdown-menu, .popover, .frappe-popover { background-color: var(--popover-bg); }

/* The document log dialog. */
.spark-doclog { width: 100%; border-collapse: collapse; font-size: .82rem; }
.spark-doclog th {
  text-align: left; font-size: 10.5px; font-weight: 650;
  letter-spacing: .06em; text-transform: uppercase; color: var(--s-ink-3, var(--ink-gray-5));
  border-bottom: 1px solid var(--s-rule-2, var(--outline-gray-2)); padding: 0 10px 7px 0;
}
.spark-doclog td { padding: 8px 10px 8px 0; border-bottom: 1px solid var(--outline-gray-1);
                vertical-align: top; }
.spark-doclog-msg { color: var(--ink-gray-9); }
.spark-doclog-when, .spark-doclog-who {
  font-family: var(--spark-mono); color: var(--ink-gray-5); white-space: nowrap;
}
.spark-doclog-event {
  font-family: var(--spark-mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; border: 1px solid var(--outline-gray-2);
  border-radius: 5px; padding: 2px 7px; color: var(--ink-gray-5);
}
.spark-doclog-event.created { border-color: #2F9E63; color: #248150; }
.spark-doclog-event.updated { border-color: var(--spark-copper); color: var(--spark-copper); }
.spark-doclog-event.viewed  { border-color: #0B72D9; color: #0B72D9; }

/* ==========================================================================
   THE INSTRUMENT LAYER — motion, depth, and the live state
   --------------------------------------------------------------------------
   Spark reads meters all day: test sets, relays, insulation testers. That
   world has a visual language of its own — monospace readouts, threshold
   colours, hairline scales, and the moment a circuit goes live. Every
   animation below is drawn from it rather than added as decoration:

     a value SETTLES like a needle coming to rest
     a request ENERGISES a conductor across the top of the screen
     a row under the cursor picks up a COPPER EDGE, the way a busbar does
     anything genuinely in progress carries the VOLT PULSE

   Rules the whole layer obeys: nothing blocks input, nothing runs longer
   than 320ms, nothing loops except a real live state, and everything stops
   dead under prefers-reduced-motion. This is a tool people use for eight
   hours, not a landing page.
   ========================================================================== */

:root {
  --sp-quick: 130ms;
  --sp-base:  200ms;
  --sp-slow:  320ms;
  /* settle: fast out of the gate, easing into place like a needle */
  --sp-ease:     cubic-bezier(.22, .68, .28, 1);
  --sp-ease-out: cubic-bezier(.16, 1, .3, 1);

  --sp-lift:    0 1px 2px rgba(14, 19, 25, .05), 0 6px 18px -8px rgba(14, 19, 25, .18);
  --sp-lift-hi: 0 2px 4px rgba(14, 19, 25, .07), 0 16px 36px -12px rgba(194, 65, 12, .30);
  --sp-ring:    0 0 0 1px var(--spark-copper);

  --sp-good: #2F9E63;
  --sp-warn: #E08A1E;
  --sp-crit: #C0392B;
}

/* --------------------------------------------------------------------------
   The conductor. A copper-to-volt sweep across the top whenever the desk is
   waiting on the server — the same read as a test set energising, and far
   less nagging than a spinner over the content you are trying to read.
   -------------------------------------------------------------------------- */
#spark-current {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 2000;
  pointer-events: none; opacity: 0; overflow: hidden;
  transition: opacity var(--sp-base) ease;
}
#spark-current::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg,
    transparent 0%, var(--spark-copper) 30%, var(--spark-volt) 50%,
    var(--spark-copper) 70%, transparent 100%);
  transform: translateX(-100%);
}
body.spark-live #spark-current { opacity: 1; }
body.spark-live #spark-current::before {
  animation: spark-current 1s linear infinite;
}
@keyframes spark-current { to { transform: translateX(100%); } }

/* --------------------------------------------------------------------------
   Lists. Rows arrive in sequence rather than all at once, which reads as the
   view filling rather than flashing. Capped at twenty and finished inside
   380ms — the stagger is a texture, never a wait. It only runs on a route
   change, so an in-place refresh does not replay it.
   -------------------------------------------------------------------------- */
@keyframes spark-rise {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}
.spark-enter .list-row-container,
.spark-enter .dt-row {
  animation: spark-rise var(--sp-base) var(--sp-ease) backwards;
}
.spark-enter .list-row-container:nth-child(n+21),
.spark-enter .dt-row:nth-child(n+21) { animation: none; }
.spark-enter .list-row-container:nth-child(1)  { animation-delay:   0ms; }
.spark-enter .list-row-container:nth-child(2)  { animation-delay:  16ms; }
.spark-enter .list-row-container:nth-child(3)  { animation-delay:  32ms; }
.spark-enter .list-row-container:nth-child(4)  { animation-delay:  48ms; }
.spark-enter .list-row-container:nth-child(5)  { animation-delay:  64ms; }
.spark-enter .list-row-container:nth-child(6)  { animation-delay:  80ms; }
.spark-enter .list-row-container:nth-child(7)  { animation-delay:  96ms; }
.spark-enter .list-row-container:nth-child(8)  { animation-delay: 112ms; }
.spark-enter .list-row-container:nth-child(9)  { animation-delay: 128ms; }
.spark-enter .list-row-container:nth-child(10) { animation-delay: 144ms; }
.spark-enter .list-row-container:nth-child(11) { animation-delay: 156ms; }
.spark-enter .list-row-container:nth-child(12) { animation-delay: 166ms; }
.spark-enter .list-row-container:nth-child(13) { animation-delay: 174ms; }
.spark-enter .list-row-container:nth-child(14) { animation-delay: 180ms; }
.spark-enter .list-row-container:nth-child(15) { animation-delay: 186ms; }
.spark-enter .list-row-container:nth-child(n+16) { animation-delay: 192ms; }

/* The copper edge. Grows from the centre out, so it reads as a contact
   closing rather than a border being switched on. */
.list-row-container {
  position: relative;
  transition: background-color var(--sp-quick) ease;
}
.list-row-container::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, var(--spark-volt), var(--spark-copper));
  transform: scaleY(0); transform-origin: 50% 50%;
  transition: transform var(--sp-base) var(--sp-ease-out);
}
.list-row-container:hover::before,
.list-row-container:focus-within::before { transform: scaleY(1); }
.list-row-container:hover { background-color: rgba(194, 65, 12, .035); }

/* Money and identifiers line up in a column or they are not worth reading. */
.list-row-col,
.dt-cell__content,
.number-widget-box .number,
.indicator-pill { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   The rail. The active item carries the copper bar; hovering slides a
   dimmer one into place first, so the pointer feels connected to the target.
   -------------------------------------------------------------------------- */
.standard-sidebar-item { position: relative; }
.standard-sidebar-item::after {
  content: ""; position: absolute; left: 0; top: 6px; bottom: 6px; width: 2px;
  border-radius: 0 2px 2px 0;
  background: var(--spark-copper);
  transform: scaleY(0); transform-origin: 50% 50%; opacity: .55;
  transition: transform var(--sp-base) var(--sp-ease-out), opacity var(--sp-base);
}
.standard-sidebar-item:hover::after { transform: scaleY(.6); }
.standard-sidebar-item.selected::after { transform: scaleY(1); opacity: 1; }

/* --------------------------------------------------------------------------
   Buttons. A press has to feel like a press; a primary action gets a copper
   halo on hover rather than a colour change, so the label stays legible.
   -------------------------------------------------------------------------- */
.btn, .btn-default, .btn-primary, .btn-secondary {
  transition: transform var(--sp-quick) var(--sp-ease),
              box-shadow var(--sp-base) var(--sp-ease),
              background-color var(--sp-quick) ease,
              border-color var(--sp-quick) ease;
}
.btn:active { transform: translateY(1px) scale(.994); }
.btn-primary:hover {
  box-shadow: var(--sp-ring), 0 8px 22px -8px rgba(194, 65, 12, .55);
}
.btn-default:hover, .btn-secondary:hover { border-color: var(--spark-copper); }

/* --------------------------------------------------------------------------
   Cards lift toward the cursor. Two pixels — enough to read as responsive,
   not enough to make a dashboard feel like it is breathing at you.
   -------------------------------------------------------------------------- */
.number-widget-box, .widget.links-widget-box, .widget.shortcut-widget-box,
.widget.chart-widget-box {
  transition: transform var(--sp-base) var(--sp-ease),
              box-shadow var(--sp-base) var(--sp-ease),
              border-color var(--sp-base) ease;
}
.number-widget-box:hover, .widget.links-widget-box:hover,
.widget.shortcut-widget-box:hover, .widget.chart-widget-box:hover {
  transform: translateY(-2px);
  box-shadow: var(--sp-lift-hi);
  border-color: var(--spark-copper);
}
.number-widget-box .number {
  letter-spacing: -.02em;
  transition: color var(--sp-base) ease;
}

/* --------------------------------------------------------------------------
   Live state. The only thing in here allowed to loop, and only for something
   that is genuinely happening right now.
   -------------------------------------------------------------------------- */
@keyframes spark-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(255, 178, 36, .5); }
  70%  { box-shadow: 0 0 0 6px rgba(255, 178, 36, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 178, 36, 0); }
}
.spark-live-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--spark-volt); margin-right: 7px; vertical-align: 1px;
  animation: spark-pulse 2.4s var(--sp-ease-out) infinite;
}

/* --------------------------------------------------------------------------
   Page and form arrival. One short fade-up on the content, so moving between
   screens has a direction rather than a cut.
   -------------------------------------------------------------------------- */
@keyframes spark-page {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
.spark-enter .layout-main-section > .form-layout,
.spark-enter .widget-group,
.spark-enter .custom-block-container {
  animation: spark-page var(--sp-slow) var(--sp-ease) backwards;
}

/* Dialogs come up from slightly below rather than appearing on the spot. */
.modal.fade .modal-dialog {
  transform: translateY(14px) scale(.985);
  transition: transform var(--sp-slow) var(--sp-ease-out),
              opacity var(--sp-base) ease;
}
.modal.show .modal-dialog { transform: none; }

/* --------------------------------------------------------------------------
   Loading. A copper shimmer rather than a grey pulse, so a half-drawn screen
   still looks like Spark.
   -------------------------------------------------------------------------- */
@keyframes spark-shimmer { to { background-position-x: -200%; } }
.list-skeleton, .skeleton-card, .widget.skeleton {
  background: linear-gradient(100deg,
    var(--surface-gray-1) 38%, rgba(194, 65, 12, .07) 50%,
    var(--surface-gray-1) 62%) 0 0 / 200% 100%;
  animation: spark-shimmer 1.4s linear infinite;
}

/* --------------------------------------------------------------------------
   Nothing above is worth a headache, a stutter on an old machine, or a
   vestibular problem.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  #spark-current::before,
  .spark-enter .list-row-container,
  .spark-enter .dt-row,
  .spark-enter .layout-main-section > .form-layout,
  .spark-enter .widget-group,
  .spark-enter .custom-block-container,
  .spark-live-dot,
  .list-skeleton, .skeleton-card, .widget.skeleton {
    animation: none !important;
  }
  .number-widget-box, .widget, .btn, .modal.fade .modal-dialog,
  .list-row-container::before, .standard-sidebar-item::after {
    transition: none !important;
  }
  .number-widget-box:hover, .widget:hover, .btn:active {
    transform: none !important;
  }
}

/* ==========================================================================
   THE DOCUMENT LAYER — forms, and the colour the desk was missing
   --------------------------------------------------------------------------
   Stock forms are grey labels and flat fields on white: correct, and utterly
   without hierarchy. Nothing tells you where one part of a record ends and
   the next begins, and nothing is coloured, so nothing is emphasised.

   The model here is a test sheet on a clipboard. Each section is a sheet of
   paper on the desk. Every field carries a small monospaced label the way a
   readout is labelled on an instrument. Copper marks what is active, and
   values are set in the face that lets a column of figures line up.
   ========================================================================== */

/* --- the ground the sheets sit on ------------------------------------- */
.layout-main-section-wrapper .layout-main-section,
.page-body .layout-main-section { background: transparent; }
.page-container, .main-section { background: var(--surface-gray-1); }

/* --- the title bar ----------------------------------------------------- */
.page-head .page-title .title-text,
.page-head .title-area .title-text {
  font-weight: 600;
  letter-spacing: -.025em;
}
.page-head .page-title .indicator-pill {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* --- form tabs: an instrument tray, not loose links ------------------- */
.form-tabs-list {
  border: 1px solid var(--outline-gray-1);
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .86), rgba(255, 255, 255, .58)),
    var(--surface-gray-1);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8),
              0 10px 28px -22px rgba(14, 19, 25, .5);
  padding: 6px;
  margin-bottom: 16px;
  overflow-x: auto;
}
.form-tabs {
  border-bottom: 0;
  display: flex;
  gap: 6px;
  min-height: 36px;
}
.form-tabs .nav-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  border: 1px solid transparent !important;
  border-radius: 8px;
  color: var(--ink-gray-6);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: 0;
  margin: 0;
  padding: 7px 13px !important;
  white-space: nowrap;
  transition: color var(--sp-quick) ease, background-color var(--sp-quick) ease,
              border-color var(--sp-quick) ease, box-shadow var(--sp-quick) ease;
}
.form-tabs .nav-link::after {
  content: "";
  position: absolute;
  left: 13px;
  right: 13px;
  bottom: 5px;
  height: 2px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--spark-copper), var(--spark-volt));
  opacity: 0;
  transform: scaleX(.35);
  transform-origin: 0 50%;
  transition: opacity var(--sp-quick) ease, transform var(--sp-base) var(--sp-ease-out);
}
.form-tabs .nav-link:hover {
  color: var(--ink-gray-9);
  background: rgba(255, 255, 255, .7);
  border-color: var(--outline-gray-1) !important;
}
.form-tabs .nav-link.active {
  color: var(--spark-copper);
  background: var(--surface-white);
  border-color: rgba(194, 65, 12, .22) !important;
  box-shadow: 0 1px 2px rgba(14, 19, 25, .05),
              0 8px 18px -12px rgba(194, 65, 12, .65);
}
.form-tabs .nav-link.active::after { opacity: 1; transform: scaleX(1); }

/* --- every section is a sheet ----------------------------------------- */
.form-layout .form-section.card-section {
  position: relative;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .98), rgba(255, 255, 255, .92)),
    var(--surface-white);
  border: 1px solid rgba(212, 219, 227, .86);
  border-radius: 12px;
  padding: 7px 20px 18px;
  margin: 0 0 14px;
  /* Visible, so a dropdown opened near the card's bottom edge can spill
     past it instead of being cut off mid-list. The rail keeps to the
     corner radius on its own. */
  overflow: visible;
  box-shadow: 0 1px 2px rgba(14, 19, 25, .04),
              0 18px 38px -28px rgba(14, 19, 25, .36);
  transition: border-color var(--sp-base) ease, box-shadow var(--sp-base) ease,
              transform var(--sp-base) var(--sp-ease-out);
}
.form-layout .form-section.card-section::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  border-radius: 12px 0 0 12px;
  background: linear-gradient(180deg, var(--spark-copper), var(--spark-volt));
  opacity: .22;
}
/* No transform here. A transformed ancestor becomes the containing block
   for anything fixed inside it — and the platform's grid row editor is
   fixed, over a backdrop that is not. The one-pixel lift put the editor
   under its own grey and left it unclickable. The shadow carries the focus. */
.form-layout .form-section.card-section:focus-within {
  border-color: rgba(194, 65, 12, .38);
  box-shadow: 0 1px 2px rgba(14, 19, 25, .06),
              0 22px 48px -28px rgba(14, 19, 25, .45);
}
.form-layout .form-section.card-section:focus-within::before { opacity: 1; }
.form-layout .form-section.card-section > * { position: relative; }

/* --- section headings read as labels, not headings -------------------- */
.form-section .section-head {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--spark-copper);
  font-weight: 600;
  padding: 15px 0 9px;
}
.form-section .section-head::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--spark-volt);
  box-shadow: 0 0 0 4px rgba(255, 178, 36, .18);
  flex: 0 0 auto;
}
.form-section .section-head.collapsible:hover { color: var(--spark-copper-lift); }

/* --- the fields -------------------------------------------------------- */
.frappe-control .control-label,
.form-column .control-label {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
  font-weight: 500;
  margin-bottom: 5px;
}
.frappe-control { margin-bottom: 14px; }
.frappe-control .control-value,
.frappe-control .like-disabled-input {
  font-size: .86rem;
  color: var(--ink-gray-9);
  min-height: 34px;
  border-radius: 8px;
  padding: 7px 10px;
  background: var(--surface-gray-1);
  border: 1px solid transparent;
}

.form-control, .input-with-feedback,
.frappe-control select, .frappe-control textarea {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(250, 252, 254, .95));
  border: 1px solid rgba(174, 184, 196, .76);
  border-radius: 8px;
  font-size: .86rem;
  color: var(--ink-gray-9);
  min-height: 34px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .82),
              0 1px 2px rgba(14, 19, 25, .025);
  transition: border-color var(--sp-quick) ease, box-shadow var(--sp-quick) ease,
              background-color var(--sp-quick) ease;
}
.form-control:hover:not(:focus) { border-color: var(--outline-gray-3); }
.form-control:focus, .frappe-control select:focus, .frappe-control textarea:focus {
  border-color: var(--spark-copper);
  background: var(--surface-white);
  box-shadow: 0 0 0 3px rgba(194, 65, 12, .12),
              0 10px 22px -18px rgba(194, 65, 12, .85);
  outline: none;
}
.form-control[disabled], .form-control[readonly] {
  background: repeating-linear-gradient(135deg,
              var(--surface-gray-1) 0, var(--surface-gray-1) 9px,
              var(--surface-gray-2) 9px, var(--surface-gray-2) 10px);
  color: var(--ink-gray-7);
  border-color: var(--outline-gray-1);
}

/* money and quantities line up or they are not worth reading */
.frappe-control[data-fieldtype="Currency"] .form-control,
.frappe-control[data-fieldtype="Float"] .form-control,
.frappe-control[data-fieldtype="Int"] .form-control,
.frappe-control[data-fieldtype="Percent"] .form-control,
.frappe-control[data-fieldtype="Date"] .form-control,
.frappe-control[data-fieldtype="Currency"] .control-value,
.frappe-control[data-fieldtype="Float"] .control-value {
  font-family: var(--spark-mono);
  font-size: .82rem;
  font-variant-numeric: tabular-nums;
}

/* a checkbox that is on should look on */
.frappe-control[data-fieldtype="Check"] input:checked {
  accent-color: var(--spark-copper);
}

/* --- the side panel --------------------------------------------------- */
.layout-side-section .sidebar-label,
.layout-side-section .form-sidebar .sidebar-label {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}
.layout-side-section > .form-sidebar,
.layout-side-section .sidebar-menu {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .98), rgba(255, 255, 255, .9)),
    var(--surface-white);
  border: 1px solid rgba(212, 219, 227, .86);
  border-radius: 12px;
  padding: 14px 15px;
  box-shadow: 0 1px 2px rgba(14, 19, 25, .035),
              0 18px 38px -30px rgba(14, 19, 25, .44);
}

/* --- the timeline gets a rail ----------------------------------------- */
.new-timeline { position: relative; }
.new-timeline .timeline-item { position: relative; }
.new-timeline .timeline-dot,
.new-timeline .timeline-badge {
  background: var(--spark-copper) !important;
  border-color: var(--spark-copper) !important;
  box-shadow: 0 0 0 3px var(--spark-copper-wash);
}
.new-timeline .timeline-content {
  border: 1px solid var(--outline-gray-1);
  border-radius: 10px;
  background: var(--surface-white);
  padding: 10px 13px;
}
.new-timeline .timeline-message-box { border-radius: 10px; }

/* the footer headings match the section labels rather than shouting */
.form-footer .comment-box .h6,
.form-footer h6, .form-footer .form-footer-title,
.new-timeline .timeline-actions .h6 {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--spark-copper);
  font-weight: 500;
}

/* --- comment box ------------------------------------------------------- */
.comment-input-container .ql-editor,
.form-footer .comment-input-wrapper {
  border-radius: 10px;
  background: var(--surface-white);
}

/* --- the grid inside a form (child tables) ----------------------------
   Drawn in spark-ui.css, CHILD TABLES: one heading for every Spark table,
   themed for both desks. */

/* --------------------------------------------------------------------------
   Dashboard headings and cards. "Operations" was set as body text in bold;
   it reads as a section label now, matching the form sections and the rail.
   -------------------------------------------------------------------------- */
.widget-group .widget-group-head .widget-group-title,
.layout-main-section .widget-group-title,
.workspace-body .widget-group-title {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--spark-copper);
  font-weight: 500;
}

.number-widget-box {
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(14, 19, 25, .035);
}
.number-widget-box .widget-label,
.number-widget-box .widget-title {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}
.number-widget-box .number {
  font-family: var(--spark-mono);
  font-size: 1.3rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.03em;
}

/* ==========================================================================
   TABLES, PANELS AND THE ROOM AROUND THEM
   --------------------------------------------------------------------------
   A report is a column of figures. It wants smaller type than prose, a header
   that reads as labels rather than headings, and rows that are easy to track
   across — which means a hairline, a faint alternating ground, and a copper
   edge under the cursor. Everything else here is padding that was missing.
   ========================================================================== */

/* --- the report sheet --------------------------------------------------- */
.report-wrapper .datatable,
.widget .datatable, .datatable {
  border: 1px solid var(--outline-gray-1);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface-white);
  box-shadow: 0 1px 2px rgba(14, 19, 25, .035);
}

.datatable .dt-row-header {
  background: var(--surface-gray-1);
  border-bottom: 1px solid var(--outline-gray-2);
}
.datatable .dt-cell--header .dt-cell__content {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-gray-6);
  font-weight: 500;
}

/* smaller than body text: a table is scanned, not read */
.datatable .dt-cell__content {
  font-size: 11px;
  line-height: 1.45;
  padding: 7px 9px;
}
.datatable .dt-cell { border-right: 1px solid var(--line-soft, #EEF1F4); }
.datatable .dt-row { border-bottom: 1px solid var(--outline-gray-1); }

/* the faint ground makes a wide row trackable across the page */
.datatable .dt-scrollable .dt-row:nth-child(even) .dt-cell {
  background-color: var(--surface-gray-1);
}
.datatable .dt-scrollable .dt-row:hover .dt-cell {
  background-color: rgba(194, 65, 12, .045);
}
.datatable .dt-cell--focus {
  outline: 2px solid var(--spark-copper);
  outline-offset: -2px;
  border-radius: 3px;
}
.datatable .dt-row-filter .dt-filter {
  font-size: 11px;
  border-radius: 6px;
}

/* figures line up; identifiers get the face they earn */
.datatable .dt-cell--col-0 .dt-cell__content,
.datatable .dt-cell__content .indicator-pill {
  font-family: var(--spark-mono);
  font-size: 11px;
}

/* the filter bar above the report is a panel, not loose controls */
.page-form.report-filter-area, .report-wrapper > .page-form {
  background: var(--surface-white);
  border: 1px solid var(--outline-gray-1);
  border-radius: 12px;
  padding: 11px 14px;
  margin-bottom: 12px;
}

/* --- list views get the same treatment -------------------------------- */
.frappe-list .result {
  border: 1px solid var(--outline-gray-1);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface-white);
}
.frappe-list .list-row-head {
  background: var(--surface-gray-1);
  border-bottom: 1px solid var(--outline-gray-2);
}
.frappe-list .list-row-head .list-row-col span {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-gray-6);
}
.frappe-list .list-row { font-size: .8rem; }

/* --- the form footer had no room at all -------------------------------- */
.form-footer { padding-top: 6px; }
.form-footer .comment-box,
.form-footer .form-tabs-list ~ div,
.form-footer .new-timeline {
  background: var(--surface-white);
  border: 1px solid var(--outline-gray-1);
  border-radius: 12px;
  padding: 15px 18px;
  margin-bottom: 12px;
}
.form-footer .comment-title,
.form-footer .timeline-item.activity-title h4 {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--spark-copper);
  font-weight: 500;
}

/* --- the activity trail ------------------------------------------------ */
.new-timeline .timeline-item { padding-bottom: 4px; }
.new-timeline .timeline-content {
  padding: 10px 14px;
  font-size: .8rem;
  line-height: 1.55;
}
.new-timeline .timeline-item .timeline-content .text-muted { font-size: 11px; }

/* --- link and shortcut cards ------------------------------------------ */
.widget.links-widget-box, .widget.shortcut-widget-box, .widget.onboarding-widget-box {
  border: 1px solid var(--outline-gray-1);
  border-radius: 12px;
  background: var(--surface-white);
  padding: 15px 17px;
  box-shadow: 0 1px 2px rgba(14, 19, 25, .035);
}
.widget.links-widget-box .widget-title,
.widget.shortcut-widget-box .widget-title {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--spark-copper);
  font-weight: 500;
  margin-bottom: 9px;
}
.widget.links-widget-box .link-item {
  font-size: .8rem;
  padding: 5px 0;
  border-radius: 6px;
  transition: color var(--sp-quick) ease, padding-left var(--sp-base) var(--sp-ease);
}
.widget.links-widget-box .link-item:hover {
  color: var(--spark-copper);
  padding-left: 4px;
}

/* --- anything that was flush to its edge ------------------------------ */
.widget-group { margin-bottom: 22px; }
.workspace-body .widget-group + .widget-group { margin-top: 4px; }
.layout-main-section > .row, .layout-main-section > .form-page { padding-bottom: 4px; }

[data-theme="dark"] .form-tabs-list {
  background:
    linear-gradient(180deg, rgba(26, 34, 43, .92), rgba(19, 25, 32, .78)),
    var(--surface-gray-1);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04),
              0 14px 32px -24px rgba(0, 0, 0, .9);
}
[data-theme="dark"] .form-tabs .nav-link:hover {
  background: rgba(255, 255, 255, .035);
}
[data-theme="dark"] .form-tabs .nav-link.active {
  background: var(--surface-gray-2);
  border-color: rgba(249, 115, 22, .34) !important;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .45),
              0 10px 22px -14px rgba(249, 115, 22, .36);
}
[data-theme="dark"] .form-layout .form-section.card-section,
[data-theme="dark"] .layout-side-section > .form-sidebar,
[data-theme="dark"] .layout-side-section .sidebar-menu {
  background:
    linear-gradient(180deg, rgba(22, 29, 37, .98), rgba(19, 25, 32, .92)),
    var(--surface-cards);
  border-color: var(--outline-gray-2);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .45),
              0 20px 44px -30px rgba(0, 0, 0, .9);
}
[data-theme="dark"] .frappe-control .control-value,
[data-theme="dark"] .frappe-control .like-disabled-input {
  background: rgba(255, 255, 255, .025);
}
[data-theme="dark"] .form-control,
[data-theme="dark"] .input-with-feedback,
[data-theme="dark"] .frappe-control select,
[data-theme="dark"] .frappe-control textarea {
  background:
    linear-gradient(180deg, rgba(26, 34, 43, .96), rgba(19, 25, 32, .96));
  border-color: var(--outline-gray-3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035),
              0 1px 2px rgba(0, 0, 0, .28);
}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .frappe-control select:focus,
[data-theme="dark"] .frappe-control textarea:focus {
  background: var(--surface-gray-2);
  box-shadow: 0 0 0 3px rgba(249, 115, 22, .18),
              0 12px 24px -18px rgba(249, 115, 22, .5);
}
[data-theme="dark"] .form-control[disabled],
[data-theme="dark"] .form-control[readonly] {
  background: repeating-linear-gradient(135deg,
              var(--surface-gray-1) 0, var(--surface-gray-1) 9px,
              var(--surface-gray-2) 9px, var(--surface-gray-2) 10px);
}


/* ═══════════════════════════════════════════════════════════════════════════
   NOTICES — the toast and the message dialog

   Two things interrupt the operator: a toast confirming something happened,
   and a dialog stopping them because something can't. Stock paints both as
   plain white slabs with a coloured dot, which reads as a browser artefact
   rather than part of the product. Both are treated here as system chrome:
   graphite in either theme, a semantic rail carrying the severity, and the
   figures set in the same mono the rest of the desk uses.
   ═══════════════════════════════════════════════════════════════════════ */

#alert-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 2100;
}

.desk-alert {
  position: relative;
  overflow: hidden;
  min-width: 296px;
  max-width: 400px;
  padding: 12px 40px 12px 18px;
  border-radius: 11px;
  border: 1px solid rgba(255, 255, 255, .09);
  background: linear-gradient(180deg, #1A222B 0%, var(--spark-graphite-2) 100%);
  box-shadow: 0 20px 44px -14px rgba(8, 12, 17, .62),
              0 2px 6px -2px rgba(8, 12, 17, .5);
  animation: spark-toast-in .34s cubic-bezier(.2, .9, .28, 1) backwards;
}

/* The severity rail. Stock leans on the icon alone, which is 16px of colour
   in a 300px box — too small to read without looking straight at it. */
.desk-alert::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--spark-copper);
}
.desk-alert.green::before  { background: #34D399; }
.desk-alert.red::before    { background: #F87171; }
.desk-alert.orange::before { background: var(--spark-volt); }
.desk-alert.blue::before   { background: #60A5FA; }

.desk-alert .alert-title-container { align-items: flex-start; gap: 9px; }
.desk-alert .alert-title-container > div:first-child { line-height: 0; margin-top: 1px; }
.desk-alert .icon               { --icon-stroke: currentColor; color: var(--spark-copper-lift); }
.desk-alert.green  .icon        { color: #34D399; }
.desk-alert.red    .icon        { color: #F87171; }
.desk-alert.orange .icon        { color: var(--spark-volt); }
.desk-alert.blue   .icon        { color: #60A5FA; }

/* !important, because the platform's own rule for this text outranks the
   toast's and painted it in the page's ink — dark on graphite, which is
   the "empty toast" that was reported four times. */
.desk-alert .alert-message {
  font-size: .8rem;
  font-weight: 500;
  line-height: 1.45;
  color: #EDF0F3 !important;
  letter-spacing: -.002em;
  font-variant-numeric: tabular-nums;
}
#alert-container .desk-alert .alert-message-container .alert-subtitle,
#alert-container .desk-alert .alert-body {
  font-size: 11px;
  line-height: 1.5;
  color: #93A0AD;
  margin-top: 3px;
  padding-left: 25px;   /* line up under the message, clear of the icon column */
}
.desk-alert .alert-subtitle:empty { display: none; }
/* Whatever a message carries inside it — a bold name, a link, a muted span
   the platform styled for a white toast — stays readable on graphite. */
.desk-alert .alert-message *, .desk-alert .alert-subtitle * { color: inherit !important; }
.desk-alert .alert-message a, .desk-alert .alert-subtitle a { color: #FFD08A !important; text-decoration: underline; }
.desk-alert .alert-subtitle { color: #93A0AD; }

.desk-alert a.close {
  position: absolute;
  top: 9px;
  right: 10px;
  padding: 3px;
  border-radius: 5px;
  color: #7C8894;
  opacity: .8;
  transition: opacity .14s ease, background-color .14s ease, color .14s ease;
}
.desk-alert a.close:hover {
  opacity: 1;
  color: #EDF0F3;
  background: rgba(255, 255, 255, .08);
}

@keyframes spark-toast-in {
  from { opacity: 0; transform: translate3d(18px, -6px, 0) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* ── the message dialog ─────────────────────────────────────────────────── */

.modal-dialog .modal-content { border-radius: 13px; }

.msgprint-dialog .modal-content {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--outline-gray-1);
  box-shadow: 0 28px 64px -18px rgba(8, 12, 17, .38);
}

/* A closing rule in the product's own colour, so the dialog is unmistakably
   part of Spark rather than something the browser threw up. */
.msgprint-dialog .modal-content::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 4;   /* the header is sticky at z-index 3 and would paint over it */
  background: linear-gradient(90deg, var(--spark-copper) 0%, var(--spark-volt) 100%);
}

.msgprint-dialog .modal-header {
  padding: 17px 18px 13px;
  align-items: center;
}
.msgprint-dialog .modal-title {
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: -.012em;
  color: var(--ink-gray-9);
}

/* The severity dot is 6px of flat colour. Given a ring it reads at a glance
   without growing large enough to compete with the title. */
.msgprint-dialog .title-section { align-items: center; gap: 10px; }
.msgprint-dialog .title-section .indicator {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin: 0;
  border: none;
  border-radius: 50%;
}
.msgprint-dialog .title-section .indicator::before { display: none; }
.msgprint-dialog .title-section .indicator.green {
  background-color: #10B981; box-shadow: 0 0 0 3.5px rgba(52, 211, 153, .20);
}
.msgprint-dialog .title-section .indicator.red {
  background-color: #EF4444; box-shadow: 0 0 0 3.5px rgba(248, 113, 113, .20);
}
.msgprint-dialog .title-section .indicator.orange {
  background-color: #F59E0B; box-shadow: 0 0 0 3.5px rgba(255, 178, 36, .22);
}
.msgprint-dialog .title-section .indicator.blue {
  background-color: #3B82F6; box-shadow: 0 0 0 3.5px rgba(96, 165, 250, .20);
}

.msgprint-dialog .modal-body { padding: 16px 18px 20px; }
.msgprint-dialog .msgprint {
  font-size: .825rem;
  line-height: 1.62;
  color: var(--ink-gray-7);
  max-width: 62ch;
  font-variant-numeric: tabular-nums;
}
.msgprint-dialog .msgprint strong,
.msgprint-dialog .msgprint b { color: var(--ink-gray-9); font-weight: 600; }
.msgprint-dialog .msgprint a { color: var(--spark-copper); text-decoration: underline; }

/* Figures and document names inside a notice are identifiers — set them in
   the mono face so a job number is scannable rather than prose. */
.msgprint-dialog .msgprint code,
.desk-alert .alert-message code {
  font-family: var(--spark-mono);
  font-size: .95em;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface-gray-2);
  color: var(--ink-gray-8);
}

.msgprint-dialog .modal-footer { padding: 12px 18px 16px; }

@media (prefers-reduced-motion: reduce) {
  .desk-alert { animation: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   ASK SPARK — the docked assistant

   Graphite, like the launcher band and the toasts: this is system chrome, not
   a document, and the distinction should be visible without reading a word.
   It sits over the desk rather than displacing it, because the question is
   usually about whatever is already on screen.
   ═══════════════════════════════════════════════════════════════════════ */

.spark-chat-fab {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 1035;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px 10px 13px;
  border: 1px solid rgba(255, 255, 255, .10);
  border-radius: 999px;
  background: linear-gradient(180deg, #1E2732 0%, var(--spark-graphite) 100%);
  color: #EDF0F3;
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  box-shadow: 0 14px 32px -10px rgba(8, 12, 17, .55);
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease, opacity .16s ease;
}
.spark-chat-fab svg { color: var(--spark-copper-lift); }
.spark-chat-fab:hover {
  transform: translateY(-1px);
  box-shadow: 0 18px 40px -12px rgba(8, 12, 17, .62);
}
.spark-chat-fab.is-open { opacity: 0; pointer-events: none; }

.spark-chat {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 1040;
  display: flex;
  flex-direction: column;
  width: 408px;
  max-width: calc(100vw - 32px);
  height: 620px;
  max-height: calc(100vh - 96px);
  border: 1px solid rgba(255, 255, 255, .09);
  border-radius: 15px;
  overflow: hidden;
  background: var(--spark-graphite-2);
  box-shadow: 0 34px 70px -20px rgba(8, 12, 17, .62);
  opacity: 0;
  transform: translateY(12px) scale(.985);
  transition: opacity .18s ease, transform .18s cubic-bezier(.2, .9, .28, 1);
}
.spark-chat.is-in { opacity: 1; transform: none; }

.spark-chat-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 15px 15px 13px 17px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  background: linear-gradient(180deg, #1D2530 0%, var(--spark-graphite-2) 100%);
}
.spark-chat-eyebrow {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--spark-copper-lift);
}
.spark-chat-sub { font-size: 11px; color: #8D99A6; margin-top: 3px; }
.spark-chat-x {
  border: 0;
  background: transparent;
  color: #7C8894;
  padding: 4px;
  border-radius: 6px;
  cursor: pointer;
  transition: color .14s ease, background-color .14s ease;
}
.spark-chat-x:hover { color: #EDF0F3; background: rgba(255, 255, 255, .08); }

.spark-chat-thread {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px 15px 6px;
  display: flex;
  flex-direction: column;
  gap: 11px;
  scrollbar-width: thin;
  scrollbar-color: #37424E transparent;
}
.spark-chat-thread::-webkit-scrollbar { width: 8px; }
.spark-chat-thread::-webkit-scrollbar-thumb {
  background: #37424E; border-radius: 4px; border: 2px solid var(--spark-graphite-2);
}

.spark-msg { display: flex; }
.spark-msg-you { justify-content: flex-end; }
.spark-bubble {
  max-width: 86%;
  padding: 10px 13px;
  border-radius: 12px;
  font-size: .795rem;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
}
.spark-msg-spark .spark-bubble {
  background: var(--spark-graphite-3);
  color: #DCE3EA;
  border: 1px solid rgba(255, 255, 255, .05);
  border-top-left-radius: 4px;
}
.spark-msg-you .spark-bubble {
  background: linear-gradient(180deg, var(--spark-copper-lift) 0%, var(--spark-copper) 100%);
  color: #fff;
  border-top-right-radius: 4px;
}

.spark-wait { display: flex; align-items: center; gap: 4px; }
.spark-wait span {
  font-family: var(--spark-mono);
  font-size: 11px;
  letter-spacing: .09em;
  color: #7C8894;
  margin-left: 6px;
}
.spark-wait i {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--spark-copper-lift);
  animation: spark-wait 1.1s ease-in-out infinite;
}
.spark-wait i:nth-child(2) { animation-delay: .16s; }
.spark-wait i:nth-child(3) { animation-delay: .32s; }
@keyframes spark-wait {
  0%, 60%, 100% { opacity: .25; transform: translateY(0); }
  30%           { opacity: 1;   transform: translateY(-3px); }
}

/* ── a proposal ─────────────────────────────────────────────────────────── */
.spark-propose {
  margin-top: 11px;
  padding: 11px 12px;
  border-radius: 9px;
  border: 1px solid rgba(255, 178, 36, .26);
  background: rgba(255, 178, 36, .07);
}
.spark-propose-label {
  font-size: .765rem; font-weight: 600; color: #F3F5F7; line-height: 1.4;
}
.spark-propose-why { font-size: 11px; color: #9AA6B2; margin-top: 3px; line-height: 1.5; }
.spark-propose-act { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.spark-do {
  border: 0;
  border-radius: 7px;
  padding: 6px 13px;
  background: var(--spark-volt);
  color: #241703;
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  font-weight: 600;
  cursor: pointer;
  transition: filter .14s ease, transform .1s ease;
}
.spark-do:hover:not(:disabled) { filter: brightness(1.08); }
.spark-do:active:not(:disabled) { transform: translateY(1px); }
.spark-do:disabled { opacity: .55; cursor: default; }
.spark-propose-note { font-size: 11px; color: #8D99A6; }
.spark-propose.is-done { border-color: rgba(52, 211, 153, .3); background: rgba(52, 211, 153, .07); }
.spark-made {
  font-family: var(--spark-mono); font-size: 11px; color: #34D399;
  text-decoration: underline; text-underline-offset: 2px;
}

/* ── openers ────────────────────────────────────────────────────────────── */
.spark-chat-chips {
  flex: 0 0 auto;
  padding: 10px 15px 4px;
  max-height: 188px;
  overflow-y: auto;
  border-top: 1px solid rgba(255, 255, 255, .06);
}
.spark-chat-chips[hidden] { display: none; }
.spark-chip-head {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: #8A96A3;
  margin: 0 0 8px;
}
.spark-chip-group { margin-bottom: 9px; }
.spark-chip-label {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #6E7A87;
  margin-bottom: 5px;
}
.spark-chip-row { display: flex; flex-wrap: wrap; gap: 5px; }
.spark-chip {
  border: 1px solid rgba(255, 255, 255, .10);
  background: rgba(255, 255, 255, .035);
  color: #B9C4CF;
  border-radius: 999px;
  padding: 5px 11px;
  font-size: 11px;
  line-height: 1.3;
  cursor: pointer;
  text-align: left;
  transition: background-color .14s ease, color .14s ease, border-color .14s ease;
}
.spark-chip:hover {
  background: rgba(226, 89, 15, .16);
  border-color: rgba(226, 89, 15, .42);
  color: #F3F5F7;
}

/* ── composer ───────────────────────────────────────────────────────────── */
.spark-chat-composer {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 11px 13px 13px;
  border-top: 1px solid rgba(255, 255, 255, .07);
  background: var(--spark-graphite);
}
.spark-chat-composer textarea {
  flex: 1 1 auto;
  resize: none;
  border: 1px solid rgba(255, 255, 255, .11);
  border-radius: 9px;
  background: rgba(255, 255, 255, .04);
  color: #EDF0F3;
  font-family: var(--spark-font);
  font-size: .79rem;
  line-height: 1.5;
  padding: 8px 11px;
  max-height: 132px;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.spark-chat-composer textarea::placeholder { color: #6E7A87; }
.spark-chat-composer textarea:focus {
  outline: none;
  border-color: rgba(226, 89, 15, .6);
  box-shadow: 0 0 0 3px rgba(226, 89, 15, .14);
}
.spark-chat-composer button {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border: 0; border-radius: 9px;
  background: var(--spark-copper);
  color: #fff;
  cursor: pointer;
  transition: filter .14s ease, transform .1s ease;
}
.spark-chat-composer button:hover { filter: brightness(1.1); }
.spark-chat-composer button:active { transform: translateY(1px); }

@media (max-width: 560px) {
  .spark-chat { right: 8px; left: 8px; bottom: 8px; width: auto; height: calc(100vh - 74px); }
  .spark-chat-fab { right: 12px; bottom: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .spark-chat { transition: none; }
  .spark-wait i { animation: none; opacity: .6; }
}

.spark-bubble strong { color: #FFF; font-weight: 600; }
.spark-msg-you .spark-bubble strong { color: #FFF; }
.spark-bubble code {
  font-family: var(--spark-mono); font-size: .93em;
  padding: 1px 5px; border-radius: 4px;
  background: rgba(255, 255, 255, .09); color: #F3F5F7;
}


/* ═══════════════════════════════════════════════════════════════════════════
   WORKSPACE BLOCKS — rows that close their own gaps

   Every widget on a workspace sits in a block carrying Bootstrap column
   classes: cards at col-lg-3, shortcuts at col-lg-2, link panels at col-md-4.
   Floated columns of unequal height do not clear each other, so a row of cards
   staggers, and the next row starts against the tallest thing above it rather
   than against the top of the row.

   It shows worst on a restricted account. A field technician cannot see half
   the widgets, so half the blocks are simply absent — and the ones that remain
   are laid out around holes where the others used to be.

   Laying the container out as a twelve-column grid fixes both at once: rows
   are rows, and a widget the viewer is not allowed to see simply shifts the
   rest up rather than leaving a hole. Nothing here knows or cares which
   widgets were filtered out; the layout just closes up.
   ═══════════════════════════════════════════════════════════════════════ */

[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 13px;
  align-items: start;
  grid-auto-flow: row;
  margin: 0;
}

/* The column classes set an explicit width and float. Both have to go, or the
   grid item is sized by the old rules instead of by its track. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block {
  width: auto;
  max-width: none;
  float: none;
  padding: 0;
  margin: 0;
  grid-column: span 12;
}

/* Widths, restated as spans. Widest breakpoint first, then narrowed. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-lg-3 { grid-column: span 3; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-lg-2 { grid-column: span 3; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-md-4:not(.col-lg-3):not(.col-lg-2) {
  grid-column: span 4;
}

/* Cards carry one figure each and read as a set, so they share a height.
   Link panels hold wildly different numbers of links — stretching those to
   match the tallest is what left a panel of two links with a hand's depth of
   empty card under it. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:has(.number-widget-box),
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:has(.shortcut-widget-box) {
  align-self: stretch;
}
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor .ce-block .widget.number-widget-box,
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor .ce-block .widget.shortcut-widget-box { height: 100%; }
/* Equal heights. Left to their natural size these cards ended at seven
   different depths across two rows, and because a grid row is as tall as its
   tallest card the space under the short ones was dead either way — ragged
   AND empty. Stretching them at least makes the row read as a row, and the
   count pinned to the bottom gives the freed space something to say. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:has(.links-widget-box) {
  align-self: stretch;
}

/* A heading introduces the run of widgets under it, so it wants air above and
   none below — the stock margin put it midway between the two groups and it
   read as belonging to neither. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:has(.ce-header) {
  grid-column: span 12;
  margin-top: 12px;
}
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:first-child:has(.ce-header) { margin-top: 0; }

@media (max-width: 1199px) {
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-lg-3 { grid-column: span 4; }
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-lg-2 { grid-column: span 3; }
}
@media (max-width: 991px) {
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-lg-3,
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-md-4:not(.col-lg-3):not(.col-lg-2) {
    grid-column: span 6;
  }
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block.col-lg-2 { grid-column: span 4; }
}
@media (max-width: 767px) {
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor { gap: 10px; }
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block { grid-column: span 12 !important; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE 2026 SYSTEM — shell, cards, motion

   Everything below reads from the tokens above. Amber appears in exactly three
   places: the active navigation item, a primary action, and the mark. Teal is
   reserved for a figure that moved the right way, coral for one that did not.
   A number that is merely large gets neither.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── the rail ───────────────────────────────────────────────────────────── */
/* rail width lives with .body-sidebar above, where the rail actually is. */

/* The stock active item is a solid slab in the brand colour, which at this
   size reads as a button someone forgot to finish. A translucent wash with a
   slim indicator says "you are here" without shouting it. */
.desk-sidebar .sidebar-item-container.selected > .desk-sidebar-item,
.standard-sidebar-item.selected,
.sidebar-item-container .desk-sidebar-item.selected {
  position: relative;
  background: linear-gradient(90deg,
              rgba(255, 159, 28, .17) 0%, rgba(255, 159, 28, .07) 100%);
  border-radius: var(--r-md);
  box-shadow: 0 0 22px -8px rgba(255, 159, 28, .45);
  color: var(--spark-amber-lift);
}
.desk-sidebar .sidebar-item-container.selected > .desk-sidebar-item::before,
.standard-sidebar-item.selected::before,
.sidebar-item-container .desk-sidebar-item.selected::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 50%;
  width: 3px;
  height: 17px;
  border-radius: 0 2px 2px 0;
  background: var(--spark-amber);
  transform: translateY(-50%);
  transition: height var(--dur-base) var(--ease), opacity var(--dur-base) var(--ease);
}
.desk-sidebar .sidebar-item-container.selected > .desk-sidebar-item .sidebar-item-label,
.standard-sidebar-item.selected .sidebar-item-label {
  color: var(--spark-amber-lift);
  font-weight: 550;
}
.desk-sidebar-item,
.standard-sidebar-item {
  border-radius: var(--r-md);
  padding: 5px 10px;
  transition: background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.desk-sidebar-item:hover:not(.selected),
.standard-sidebar-item:hover:not(.selected) { background: rgba(255, 255, 255, .05); }

/* A collapsible group animates its own height. grid-template-rows is the only
   way to do that to `auto` without measuring in script. */
.sidebar-child-item,
.desk-sidebar .drop-icon + .sidebar-child-item {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 220ms var(--ease);
}
.sidebar-child-item.hidden,
.sidebar-child-item[style*="display: none"] { grid-template-rows: 0fr; }
.desk-sidebar .drop-icon { transition: transform var(--dur-base) var(--ease); }
.desk-sidebar .sidebar-item-container.opened > .desk-sidebar-item .drop-icon {
  transform: rotate(90deg);
}

/* ── cards ──────────────────────────────────────────────────────────────── */
.widget.number-widget-box,
.widget.links-widget-box,
.widget.shortcut-widget-box,
.widget.chart-widget,
.widget.dashboard-widget-box {
  background: var(--surface-white);
  border: 1px solid var(--outline-gray-1);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.widget.number-widget-box:hover,
.widget.links-widget-box:hover,
.widget.shortcut-widget-box:hover,
.widget.chart-widget:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lift);
  border-color: var(--outline-gray-2);
}

/* Money is a column of digits people compare down the page. */
.widget.number-widget-box .widget-content .number,
.number-card .number,
.stat-value,
td[data-fieldtype="Currency"],
td[data-fieldtype="Float"],
td[data-fieldtype="Int"] {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.015em;
}

/* ── hierarchy: four ahead of the rest ──────────────────────────────────── */
/* The dashboard opened with fourteen identical cards, which is a list, not a
   hierarchy — nothing on it was more important than anything else. The first
   four are the ones a director asks about, so they are given the size. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
  > .ce-block.col-lg-3:nth-of-type(-n+6) .widget.number-widget-box {
  padding: 17px 18px 16px;
}
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
  > .ce-block.col-lg-3:nth-of-type(-n+6) .number-widget-box .widget-content .number {
  font-size: 1.62rem;
  font-weight: 600;
}
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
  > .ce-block.col-lg-3 .number-widget-box .widget-content .number {
  font-size: 1.24rem;
  font-weight: 600;
  color: var(--ink-gray-9);
}
.widget.number-widget-box .widget-head .widget-label,
.widget.number-widget-box .number-label {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}

/* The percentage the card already computes. Teal up, coral down — the arrow
   carries the direction too, so colour is never the only signal. */
.widget.number-widget-box .card-stats .percentage-stat-area,
.number-card .percentage-stat-area { font-size: 11px; font-weight: 500; }
.widget.number-widget-box .green-stat,
.number-card .green-stat  { color: #0F9384; }
.widget.number-widget-box .red-stat,
.number-card .red-stat    { color: #D2483E; }
.widget.number-widget-box .grey-stat { color: var(--ink-gray-5); }

/* ── buttons and chips ──────────────────────────────────────────────────── */
.btn-primary,
.btn.btn-primary {
  background: var(--spark-amber);
  border-color: var(--spark-amber);
  color: #241703;
  font-weight: 550;
  border-radius: var(--r-sm);
  transition: filter var(--dur-fast) var(--ease), transform 90ms var(--ease);
}
.btn-primary:hover, .btn.btn-primary:hover {
  background: var(--spark-amber-deep); border-color: var(--spark-amber-deep); color: #fff;
}
.btn:active, .btn-primary:active { transform: scale(.98); }

/* ── focus, for people who do not use a mouse ───────────────────────────── */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--spark-amber);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
.desk-sidebar a:focus-visible,
.desk-sidebar button:focus-visible { outline-color: var(--spark-amber-lift); }

/* ── entrances ──────────────────────────────────────────────────────────── */
@keyframes spark-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block {
  animation: spark-rise var(--dur-slow) var(--ease) backwards;
}
/* Staggered, but only across the first two rows — past that the reader has
   scrolled and a delayed card just looks broken. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(1)  { animation-delay: 0ms; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(2)  { animation-delay: 40ms; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(3)  { animation-delay: 80ms; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(4)  { animation-delay: 120ms; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(5)  { animation-delay: 160ms; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(6)  { animation-delay: 200ms; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block:nth-of-type(n+7) { animation-delay: 220ms; }

/* ── Ask Spark: amber, restrained ───────────────────────────────────────── */
.spark-chat-fab {
  border-color: rgba(255, 159, 28, .34);
  background: linear-gradient(180deg, #1E2B36 0%, var(--spark-graphite) 100%);
}
.spark-chat-fab svg { color: var(--spark-amber); }
.spark-chat-fab:hover {
  border-color: rgba(255, 159, 28, .6);
  box-shadow: 0 14px 34px -12px rgba(23, 33, 43, .5),
              0 0 0 4px rgba(255, 159, 28, .12);
}

/* ── responsive ─────────────────────────────────────────────────────────── */
/* Tablet only. Below 769px the rail is a drawer with its own width, and this
   rule was still reaching it — the drawer opened at 216px instead of 286. */
@media (min-width: 769px) and (max-width: 1024px) {
  .body-sidebar-container.expanded,
  .body-sidebar-container.expanded .body-sidebar,
  .body-sidebar { width: 216px; min-width: 216px; }
}
@media (max-width: 768px) {
  .widget.number-widget-box { padding: 13px 14px; }
  .btn, .desk-sidebar-item, .standard-sidebar-item { min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block {
    animation: none;
  }
  .widget.number-widget-box:hover,
  .widget.links-widget-box:hover,
  .widget.shortcut-widget-box:hover,
  .widget.chart-widget:hover { transform: none; }
  .btn:active, .btn-primary:active { transform: none; }
  .sidebar-child-item { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE ALERT LIST — counts above, a denser table below

   The list view already filters, sorts, pages and exports. None of that is
   rebuilt. What it cannot do is tell you the shape of the problem before you
   start reading rows, so the strip goes above it — and the rows themselves are
   tightened, because thirty alerts at desk-default row height is four screens.
   ═══════════════════════════════════════════════════════════════════════ */

.spark-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(186px, 1fr));
  gap: 12px;
  margin: 0 0 16px;
}
.spark-strip .sc {
  position: relative;
  display: block;
  text-align: left;
  padding: 14px 15px 13px 17px;
  border: 1px solid var(--outline-gray-1);
  border-left-width: 3px;
  border-radius: var(--r-lg);
  background: var(--surface-white);
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.spark-strip .sc:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lift);
}
.spark-strip .sc:active { transform: scale(.99); }
.spark-strip .sc.open     { border-left-color: var(--ink-gray-4); }
.spark-strip .sc.critical { border-left-color: var(--spark-coral); }
.spark-strip .sc.warning  { border-left-color: var(--spark-amber); }
.spark-strip .sc.done     { border-left-color: var(--spark-teal); }

.spark-strip .k {
  display: block;
  font-size: 11px;
  color: var(--ink-gray-5);
}
.spark-strip .v {
  display: block;
  font-size: 1.5rem;
  font-weight: 650;
  letter-spacing: -.022em;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  margin-top: 2px;
}
.spark-strip .sc.critical .v { color: #C2382E; }
.spark-strip .sc.warning  .v { color: #B06A05; }
.spark-strip .sc.done     .v { color: #0B7C70; }
.spark-strip .s {
  display: block;
  font-size: 11px;
  color: var(--ink-gray-5);
  margin-top: 3px;
}

/* Row density. The default is built for documents you read one at a time. */
.list-row-container .list-row {
  padding-top: 9px;
  padding-bottom: 9px;
  font-size: .8rem;
  transition: background-color var(--dur-fast) var(--ease);
}
.list-row-container:hover { background: var(--spark-amber-wash); }
[data-theme="dark"] .list-row-container:hover { background: rgba(255, 255, 255, .045); }
.list-row .list-subject { font-weight: 500; }
.list-row-col .like-disabled-input,
.list-row .list-row-col span { font-variant-numeric: tabular-nums; }

/* The severity pill the list settings hand back. */
.list-row .indicator-pill {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  font-weight: 600;
  border-radius: var(--r-pill);
  padding: 2px 9px;
}

@media (max-width: 768px) {
  .spark-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spark-strip .v { font-size: 1.28rem; }
}
@media (prefers-reduced-motion: reduce) {
  .spark-strip .sc:hover, .spark-strip .sc:active { transform: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   ROOM BETWEEN THINGS

   Every panel on a workspace was sitting 13px from its neighbour, which reads
   as one undifferentiated field of cards rather than a page with sections in
   it. Cards inside a group stay close; the gap between groups, and around the
   page itself, opens up so the eye can find the seams.
   ═══════════════════════════════════════════════════════════════════════ */

[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor {
  gap: 16px;
  padding-bottom: 40px !important;
}

/* A heading is the start of a section, so the air belongs above it. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
  > .ce-block:has(.ce-header) { margin-top: 26px; }
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
  > .ce-block:first-child:has(.ce-header) { margin-top: 0; }

/* A full-width block — a chart, the attention panel — is its own section and
   wants clearance from the row of cards above it. */
[data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
  > .ce-block.col-xs-12:not(:has(.ce-header)):not(:first-child) { margin-top: 8px; }

.layout-main-section-wrapper,
.page-body .container { padding-bottom: 32px; }
.list-row-container:first-child { border-top: 0; }

/* ── link panels, as a shelf of tools ───────────────────────────────────── */
/* Reference: a titled card per area, its links stacked with a chevron each
   and the count of what is inside it. The stock widget is a bare list of
   anchors, which gives no sense of how big an area is before you open it. */
.widget.links-widget-box { padding: 16px 17px 14px; }
.widget.links-widget-box .widget-head { margin-bottom: 12px; padding-bottom: 12px;
  border-bottom: 1px solid var(--outline-gray-1); }
.widget.links-widget-box .widget-title,
.widget.links-widget-box .widget-head .widget-label > .widget-title {
  font-family: var(--spark-font);
  font-size: .84rem;
  font-weight: 600;
  letter-spacing: -.008em;
  text-transform: none;
  color: var(--ink-gray-9);
}
.widget.links-widget-box .link-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 8px 8px 9px;
  margin: 0 -8px;
  border-radius: var(--r-sm);
  font-size: .8rem;
  color: var(--ink-gray-7);
  transition: background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              padding-left var(--dur-fast) var(--ease);
}
.widget.links-widget-box .link-item::after {
  content: "\203A";
  margin-left: auto;
  color: var(--ink-gray-3);
  font-size: 1rem;
  line-height: 1;
  transition: color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.widget.links-widget-box .link-item:hover {
  background: var(--spark-amber-wash);
  color: var(--ink-gray-9);
  padding-left: 13px;
}
.widget.links-widget-box .link-item:hover::after {
  color: var(--spark-amber-deep);
  transform: translateX(2px);
}
.widget.links-widget-box .link-item:focus-visible {
  outline: 2px solid var(--spark-amber);
  outline-offset: -2px;
}

/* ── shortcut tiles ─────────────────────────────────────────────────────── */
.widget.shortcut-widget-box { padding: 14px 15px; }
.widget.shortcut-widget-box .widget-head .widget-label {
  font-size: .8rem;
  font-weight: 550;
  letter-spacing: -.005em;
  text-transform: none;
  color: var(--ink-gray-8);
}
.widget.shortcut-widget-box .indicator-pill {
  font-family: var(--spark-mono);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  border-radius: var(--r-pill);
}

@media (max-width: 768px) {
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor { gap: 12px; }
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
    > .ce-block:has(.ce-header) { margin-top: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .widget.links-widget-box .link-item,
  .widget.links-widget-box .link-item::after { transition: none; }
}


/* ── the link card, filled out ──────────────────────────────────────────── */
.widget.links-widget-box {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.widget.links-widget-box .widget-body { flex: 1 1 auto; }

/* Stock prints a launch arrow beside the label and this stylesheet adds a
   chevron at the row end. One row, two arrows, both saying "this goes
   somewhere". The chevron is the one aligned with the others, so it stays. */
.widget.links-widget-box .link-item .indicator-pill + svg,
.widget.links-widget-box .link-item > svg.es-line,
.widget.links-widget-box .link-item .link-arrow,
.widget.links-widget-box .link-item svg.icon-xs { display: none; }

.widget.links-widget-box .link-foot {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  padding-top: 11px;
  border-top: 1px solid var(--outline-gray-1);
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}
.widget.links-widget-box .link-foot b {
  font-weight: 600;
  color: var(--ink-gray-7);
  font-variant-numeric: tabular-nums;
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE LIST, GIVEN ROOM

   The subject column was truncating job titles at about half their length and
   then leaving a hand's width of nothing before the next column — the title,
   which is the only part anyone reads to decide, was the one thing squeezed.
   The row now spends its width on the subject and lets the fixed-width
   columns take what they need.
   ═══════════════════════════════════════════════════════════════════════ */

.list-row-container { padding: 0 4px; }

.frappe-list .list-row-head,
.frappe-list .list-row {
  padding-left: 15px;
  padding-right: 15px;
  gap: 14px;
}

/* Column headings should read as headings, not as another row of data. */
.frappe-list .list-row-head {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
  background: var(--surface-gray-1);
  border-bottom: 1px solid var(--outline-gray-2);
}

/* Dates and counts line up down the column. */
.frappe-list .list-row-col .text-muted,
.frappe-list .list-row .level-item {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* Breathing room around the whole result set, and under the filter bar. */
.frappe-list .result,
.frappe-list .list-paging-area { border-radius: var(--r-lg); }
.frappe-list .list-paging-area { padding: 12px 15px; }
.page-form.flex { margin-bottom: 14px; padding: 4px 0; row-gap: 8px; }

/* The status and severity pills, at a size that does not shout. */
.list-row .indicator-pill,
.list-row-col .indicator-pill {
  font-size: 11px;
  padding: 3px 9px;
  letter-spacing: .11em;
}


/* A flex child defaults to min-width:auto, meaning it refuses to shrink below
   its content. One long job title therefore widened its whole row past the
   others instead of ellipsising, and took the column axis with it. Zeroing the
   floor down the chain lets the text truncate, which is what it is for. */
.list-row-container .list-row .list-subject .level-item,
.list-row-container .list-row .list-subject a,
.list-row-container .list-row .list-subject span.ellipsis { min-width: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   GUTTERS AND A SMALLER SET

   Content ran edge to edge on a wide monitor — a 2560px line of table is not
   a line anyone reads, and the page had nothing holding it in. A max width
   plus real side padding gives it a margin to sit inside. The list type comes
   down a notch with it: these pages hold thirty rows, and the scale was set
   for reading one document at a time.
   ═══════════════════════════════════════════════════════════════════════ */

/* One gutter, on the outer box. The section wrapper sits inside
   .layout-main and used to take the same 26px again, so every page began
   52px in from the rail and a wide list scrolled sideways for the want of
   the room its own margins took. */
.layout-main-section-wrapper,
.page-body .layout-main,
[data-page-route="Workspaces"] .layout-main-section-wrapper {
  max-width: 1560px;
  margin-left: auto;
  margin-right: auto;
}
.page-body .layout-main { padding-left: 20px; padding-right: 20px; }
.layout-main-section-wrapper,
[data-page-route="Workspaces"] .layout-main-section-wrapper { padding-left: 0; padding-right: 0; }
.page-head .container,
.page-body .container { padding-left: 20px; padding-right: 20px; }

/* ── the list, one notch down ───────────────────────────────────────────── */
.list-row-container .list-row .level-left .list-row-col.list-subject a,
.frappe-list .list-subject .level-item.bold,
.frappe-list .list-subject a.ellipsis { font-size: .775rem; }

.frappe-list .list-row-col .text-muted,
.frappe-list .list-row .level-item { font-size: 11px; }

.frappe-list .list-row-head { font-size: 11px; letter-spacing: .08em; }

.list-row .indicator-pill,
.list-row-col .indicator-pill { font-size: 11px; padding: 2px 8px; }

.list-row-container .list-row { padding-top: 8px; padding-bottom: 8px; }

@media (max-width: 1200px) {
  .page-body .layout-main,
  .page-head .container,
  .page-body .container { padding-left: 16px; padding-right: 16px; }
}
@media (max-width: 768px) {
  .page-body .layout-main,
  .page-head .container,
  .page-body .container { padding-left: 12px; padding-right: 12px; }
}

/* Below tablet the rail must stop reserving width. Forcing 216px on a 390px
   screen left 140px for the page — the sidebar was the page. Stock already
   knows how to collapse it; these overrides just have to get out of the way. */
/* ── the rail, as a drawer ──────────────────────────────────────────────── */
/* The hamburger already toggles `.expanded`; there was simply nothing behind
   it — the container collapsed to zero width and the panel never appeared.
   Off-canvas by default, slid in over the page, with a scrim behind it. */
@media (max-width: 768px) {
  .body-sidebar-container {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: 286px;
    max-width: 84vw;
    min-width: 0;
    z-index: 1045;
    transform: translateX(-100%);
    transition: transform 260ms var(--ease);
    will-change: transform;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  /* The desktop rule sets .expanded to 248px with two classes of specificity,
     so the drawer's single-class width lost to it and opened narrow. */
  .body-sidebar-container.expanded {
    transform: none;
    width: 286px;
    min-width: 286px;
    max-width: 84vw;
    box-shadow: 0 0 48px rgba(8, 12, 17, .5);
  }
  .body-sidebar-container.expanded .body-sidebar {
    width: 286px;
    min-width: 286px;
    max-width: 84vw;
  }
  .body-sidebar-container .body-sidebar {
    width: 286px;
    min-width: 286px;
    max-width: 84vw;
    min-height: 100%;
  }
  /* Room for a thumb on every row of the drawer. */
  .body-sidebar .standard-sidebar-item,
  .body-sidebar .desk-sidebar-item { min-height: 46px; }
}

/* The scrim. Present at all widths but only ever lit by the drawer. */
.spark-scrim {
  position: fixed;
  inset: 0;
  z-index: 1040;
  background: rgba(8, 12, 17, .52);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.spark-scrim.on { opacity: 1; pointer-events: auto; }
body.spark-drawer-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .body-sidebar-container { transition: none; }
  .spark-scrim { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE FILTER BAR, AND THE FORM

   The filter row wrapped onto a second line with one lonely field on it and no
   air around either — it read as a mistake rather than a row of controls. The
   fields are given a common width so they wrap into columns instead of a
   ragged line, and the bar gets a surface of its own so it separates from the
   table under it.
   ═══════════════════════════════════════════════════════════════════════ */

.page-form.flex {
  gap: 9px;
  align-items: center;
  padding: 12px 14px;
  background: var(--surface-white);
  border: 1px solid var(--outline-gray-1);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
}
.page-form .standard-filter-section { gap: 9px; flex-wrap: wrap; }
.page-form .standard-filter-section .form-group,
.page-form .standard-filter-section .frappe-control {
  flex: 0 1 186px;
  min-width: 0;
  margin-bottom: 0;
}
.page-form .form-control,
.page-form .input-with-feedback {
  height: 34px;
  font-size: .765rem;
  border-radius: var(--r-sm);
}
.page-form .filter-selector .btn,
.page-form .sort-selector .btn { height: 34px; border-radius: var(--r-sm); font-size: .765rem; }

/* ── form view ──────────────────────────────────────────────────────────── */
/* A column heading that ellipsises to "COMP…" has stopped being a heading.
   Tighter tracking, and permission to wrap onto a second line rather than
   truncate — the header row can afford the height; the reader cannot afford
   to guess which column they are looking at. */
.frappe-list .list-row-head .list-row-col,
.list-row-head > .level-left > .list-row-col {
  white-space: normal;
  line-height: 1.25;
  letter-spacing: .05em;
}
.frappe-list .list-row-head { font-size: 11px; align-items: center; }
.frappe-list .list-row-head .list-row-col > span,
.list-row-head .list-row-col .level-item { white-space: normal; }


/* The column strip takes the row; the bulk-action bar only appears when rows
   are ticked and must not reserve width before then. */
.list-row-head > .level-left.list-header-subject { flex: 1 1 auto; min-width: 0; }
.list-row-head > .level-left.checkbox-actions { flex: 0 0 auto; }
.list-row-head > .level-left.checkbox-actions:empty { display: none; }


/* ═══════════════════════════════════════════════════════════════════════════
   THE PHONE

   A desk list is a table: columns that only mean anything when you can see
   several at once. At 390px you cannot, so the table stops pretending — each
   row becomes a card with the subject on its own line and the rest of the
   columns beneath it as a wrapped strip of values.

   The rest is the difference between a website that shrinks and something
   that feels like an app: targets you can actually hit, a bar that clears the
   home indicator, no accidental sideways scroll, and no 16px-input zoom jump.
   ═══════════════════════════════════════════════════════════════════════ */

@media (max-width: 768px) {
  /* ── the shell ────────────────────────────────────────────────────────── */
  html, body { overscroll-behavior-x: none; }
  .page-head .container,
  .page-body .container,
  .layout-main-section-wrapper { padding-left: 12px; padding-right: 12px; }

  /* Nothing may exceed the viewport. The stock page-head row is 395px wide on
     a 390px screen, which is enough to make the whole page rubber-band. */
  .page-head-content,
  .page-head .row,
  .layout-main,
  .layout-main-section { max-width: 100%; min-width: 0; overflow-x: hidden; }

  /* ── touch ────────────────────────────────────────────────────────────── */
  .btn, .list-row-col a, .sidebar-item-container a,
  .page-form .form-control, .filter-selector .btn, .sort-selector .btn,
  .list-paging-area .btn { min-height: 44px; }
  .list-row-checkbox, .list-header-subject .list-check-all {
    width: 20px; height: 20px;
  }

  /* iOS zooms the page in when a focused input is under 16px. */
  input, select, textarea, .form-control { font-size: 16px !important; }

  /* ── the assistant, out of the way of the thumb ───────────────────────── */
  .spark-chat-fab {
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    padding: 11px 15px 11px 13px;
    font-size: 11px;
  }
  .spark-chat {
    right: 8px; left: 8px;
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    width: auto;
    height: calc(100dvh - 88px);
    max-height: none;
    border-radius: 16px;
  }
  .spark-chat-chips { max-height: 132px; }

  /* ── workspace blocks ─────────────────────────────────────────────────── */
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor {
    gap: 10px;
    padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)) !important;
  }
  .widget.number-widget-box { padding: 12px 13px; }
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor
    > .ce-block.col-lg-3 .number-widget-box .widget-content .number { font-size: 1.16rem; }
  .widget.links-widget-box .link-item { padding: 11px 8px; min-height: 44px; }

  /* ── notices ──────────────────────────────────────────────────────────── */
  #alert-container { left: 8px; right: 8px; }
  .desk-alert { min-width: 0; max-width: none; }
  .modal-dialog { margin: 8px; }
  .msgprint-dialog .modal-body { padding: 14px 15px 18px; }
}

/* Very small phones: the two-up card grid becomes one. */
@media (max-width: 400px) {
  .md-kpis { grid-template-columns: minmax(0, 1fr) !important; }
  .spark-strip { grid-template-columns: minmax(0, 1fr); }
}

/* Six containers nest between the viewport and a card, and on desktop each
   one's padding is a sensible 12–14px. Stacked on a 390px screen they took
   108px — 28% of the display — and squeezed the content into 283px. Padding
   belongs at the outer edge only; everything inside it runs full width. */
@media (max-width: 768px) {
  .layout-main-section-wrapper { padding-left: 10px; padding-right: 10px; }
  .layout-main-section,
  .layout-main-section > .page-body,
  [data-page-route="Workspaces"] .layout-main-section {
    padding-left: 0; padding-right: 0;
  }
  [data-page-route="Workspaces"] .codex-editor,
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor,
  [data-page-route="Workspaces"] .codex-editor .codex-editor__redactor > .ce-block,
  [data-page-route="Workspaces"] .codex-editor .ce-block__content {
    padding-left: 0; padding-right: 0; margin-left: 0; margin-right: 0;
  }
  .widget.custom-block-widget-box,
  .widget.custom-block-widget-box > .widget-body {
    padding-left: 0; padding-right: 0;
  }
  .widget.custom-block-widget-box > .widget-head { display: none; }
}

/* The header row carries TWO .level-left blocks — the column strip and a
   bulk-action bar that only fills when rows are ticked. The grid was landing
   on both, so the real strip got half the width and its columns came out 37px
   against the data rows' 139px. That is why the headings sat nowhere near the
   data they name. */
.list-row-head > .level-left.list-header-subject { flex: 1 1 auto; min-width: 0; }
.list-row-head > .level-left.checkbox-actions { flex: 0 0 auto; }
.list-row-head > .level-left.checkbox-actions:empty { display: none; }


/* ═══════════════════════════════════════════════════════════════════════════
   SECTION TABS

   A sidebar tells you where everything in the business is. A tab strip tells
   you what else is *here* — the other lists that belong to the thing you are
   already looking at. The incumbent system has both, and the adjacency is
   most of why moving around it feels quick: Customers to Sites to Contacts
   without a trip back to a menu.
   ═══════════════════════════════════════════════════════════════════════ */

.spark-tabs {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 14px;
  padding: 0 2px 0 0;
  border-bottom: 1px solid var(--outline-gray-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.spark-tabs::-webkit-scrollbar { display: none; }

.spark-tabs-eyebrow {
  flex: 0 0 auto;
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
  padding-bottom: 10px;
}

.spark-tabs-list { display: flex; align-items: center; gap: 2px; flex: 1 1 auto; }

.spark-tab {
  position: relative;
  flex: 0 0 auto;
  padding: 9px 12px 11px;
  font-size: .805rem;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink-gray-6);
  white-space: nowrap;
  cursor: pointer;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  transition: color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.spark-tab:hover { color: var(--ink-gray-9); background: var(--surface-gray-1); }
.spark-tab:focus-visible { outline: 2px solid var(--spark-amber); outline-offset: -2px; }

/* The live tab gets the rule, in the product's colour. */
.spark-tab.on { color: var(--ink-gray-9); font-weight: 600; }
.spark-tab.on::after {
  content: "";
  position: absolute;
  left: 8px; right: 8px; bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--spark-amber);
}

@media (max-width: 768px) {
  .spark-tabs { gap: 10px; margin-bottom: 10px; }
  .spark-tabs-eyebrow { display: none; }
  .spark-tab { padding: 10px 10px 12px; font-size: .78rem; min-height: 44px; }
}


/* ── A–Z strip and the row Options menu ─────────────────────────────────── */
/* A list of 75 customers is browsed by initial far more often than it is
   searched, and acting on a record should not require opening it first. */

.spark-alpha {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  margin: 0 0 12px;
  padding-bottom: 2px;
}
.spark-alpha .al {
  min-width: 26px;
  height: 26px;
  padding: 0 5px;
  border: 0;
  background: none;
  border-radius: var(--r-sm);
  font-size: 11px;
  font-weight: 500;
  color: var(--ink-gray-6);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.spark-alpha .al:first-child { min-width: 38px; font-weight: 600; }
.spark-alpha .al:hover { background: var(--surface-gray-2); color: var(--ink-gray-9); }
.spark-alpha .al.on {
  background: var(--spark-amber-wash);
  color: var(--spark-amber-deep);
  font-weight: 650;
}
.spark-alpha .al:focus-visible { outline: 2px solid var(--spark-amber); outline-offset: 1px; }

.spark-opt {
  /* The row is a link with its own overlay; without a stacking context of its
     own the button sits underneath it and the click opens the record. */
  position: relative;
  z-index: 3;
  border: 1px solid var(--outline-gray-1);
  background: var(--surface-white);
  color: var(--ink-gray-7);
  border-radius: var(--r-sm);
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 500;
  margin-right: 8px;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.spark-opt::after { content: " \25BE"; font-size: .62em; opacity: .7; }
.spark-opt:hover { border-color: var(--spark-amber); color: var(--spark-amber-deep); }

.spark-opt-menu {
  position: fixed;
  z-index: 1060;
  min-width: 194px;
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  padding: 5px;
  border: 1px solid var(--outline-gray-1);
  border-radius: var(--r-md);
  background: var(--surface-white);
  box-shadow: var(--shadow-md);
  animation: spark-rise .16s var(--ease) backwards;
}
.spark-opt-menu button {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  border-radius: var(--r-sm);
  padding: 8px 11px;
  font-size: .78rem;
  color: var(--ink-gray-8);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.spark-opt-menu button:hover {
  background: var(--spark-amber-wash);
  color: var(--spark-amber-deep);
}
.spark-opt-menu button:focus-visible { outline: 2px solid var(--spark-amber); outline-offset: -2px; }

@media (max-width: 768px) {
  .spark-alpha { display: none; }      /* a thumb does not want 27 targets */
  .spark-opt { margin-right: 4px; min-height: 32px; }
}

/* The right-hand block is pinned at 152px so every row's columns line up, and
   it clips. Adding an Options button into it put the button outside its own
   parent's box, where the row overlay swallowed the click. A row that carries
   one gets the extra width it needs — the alignment still holds because every
   row in a list either has the button or none of them do. */
.list-row-container .list-row > .level-right:has(.spark-opt),
.list-row-head > .level-right:has(.spark-opt) {
  flex: 0 0 190px !important;
  width: 190px !important;
  overflow: visible;
}
/* The header has no button, so it needs the same width to stay in step.
   190 is what the button, the age and the comment count take; the 238 it
   was pinned at before was a quarter of a laptop's table given to nothing. */
.frappe-list .list-row-head > .level-right { flex: 0 0 190px !important; width: 190px !important; }

/* The tag column used to be hidden on every list. The incumbent shows Tags on
   some lists (Quotes, Leads) and not others, so spark.apply_columns decides
   per list from the manifest — this must not force it either way. */

/* "Create Customer" set the way the office reads it. */
.page-head .btn-primary.primary-action {
  text-transform: uppercase;
  letter-spacing: .04em;
  font-weight: 600;
}


/* ── the Attachments and Logs panels ────────────────────────────────────── */
.spark-panel { padding: 2px 0 4px; }
.spark-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--outline-gray-1);
  font-size: .78rem;
  color: var(--ink-gray-6);
}
.spark-panel-empty {
  padding: 26px 2px;
  font-size: .82rem;
  color: var(--ink-gray-5);
}

.spark-file, .spark-log {
  display: grid;
  align-items: center;
  gap: 14px;
  padding: 10px 2px;
  border-bottom: 1px solid var(--outline-gray-1);
  font-size: .8rem;
}
.spark-file { grid-template-columns: minmax(0, 1fr) 84px 130px 150px; }
.spark-log  { grid-template-columns: 150px 130px minmax(0, 1fr); }
.spark-file:last-child, .spark-log:last-child { border-bottom: 0; }

.spark-file-head, .spark-log-head {
  font-family: var(--spark-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
  border-bottom-color: var(--outline-gray-2);
}
.spark-file-name a { color: var(--ink-gray-9); font-weight: 500; }
.spark-file-name a:hover { color: var(--spark-amber-deep); }
.spark-file-meta, .spark-log-when, .spark-log-who {
  color: var(--ink-gray-5);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.spark-log-what { color: var(--ink-gray-7); font-size: .765rem; }

@media (max-width: 768px) {
  .spark-file { grid-template-columns: minmax(0, 1fr) 78px; }
  .spark-file > :nth-child(n+3) { display: none; }
  .spark-log { grid-template-columns: minmax(0, 1fr); row-gap: 3px; }
}

/* ---------------------------------------------------------------- record tables
   The lists inside a record's tabs. Same columns, same order as the incumbent. */
/* The heading row is the one every other table in the system wears — the
   lists, the child tables, the Parts & Labour tables and the order's own
   lines: small muted capitals on the head ground over one hairline. The
   graphite band it used to be read as a black bar in the light desk and
   vanished in the dark one. */
.spark-tbl-head, .spark-tbl-row {
	display: grid;
	gap: var(--margin-sm);
	align-items: center;
	padding: 8px 12px;
	border-bottom: 1px solid var(--s-rule, var(--border-color));
}
.spark-tbl-head {
	padding-top: 7px;
	padding-bottom: 7px;
	font-size: 10.5px;
	font-weight: 650;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--s-ink-3, var(--ink-gray-5));
	background: var(--s-head, var(--surface-gray-1));
	border-bottom: 1px solid var(--s-rule-2, var(--border-color));
	border-radius: 8px 8px 0 0;
}
.spark-tbl-row { font-size: var(--text-sm); cursor: pointer; }
.spark-tbl-row:nth-of-type(even) { background: var(--s-sunk, var(--surface-gray-1)); }
.spark-tbl-row:hover { background: var(--s-hover, var(--spark-amber-wash)); }
.spark-tbl-row:last-child { border-bottom: 0; }
.spark-tbl-row > div, .spark-tbl-head > div {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.spark-tbl-row > .num, .spark-tbl-head > .num {
	text-align: right;
	font-variant-numeric: tabular-nums;
}
@media (max-width: 768px) {
	.spark-tbl-head { display: none; }
	.spark-tbl-row {
		grid-template-columns: 1fr 1fr !important;
		row-gap: 2px;
	}
}

/* --------------------------------------------------------------- status strip
   The third level under a history tab: narrows what is already on screen. */
.spark-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	padding: 6px var(--padding-sm);
	border-bottom: 1px solid var(--border-color);
	background: var(--control-bg);
}
.spark-chip {
	padding: 3px 10px;
	font-size: var(--text-xs);
	font-weight: 500;
	color: var(--text-muted);
	background: transparent;
	border: 1px solid transparent;
	border-radius: 10px;
	cursor: pointer;
}
.spark-chip:hover { color: var(--text-color); }
.spark-chip.on {
	color: var(--text-color);
	background: var(--fg-color);
	border-color: var(--border-color);
	font-weight: 600;
}

/* ------------------------------------------------------- status sub-lists
   The second strip under a work section: All | Open | Progress | ... */
.spark-status {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
	padding: 4px var(--padding-sm) 0;
	border-bottom: 1px solid var(--border-color);
	margin-bottom: var(--margin-sm);
}
.spark-status-tab {
	padding: 5px 12px;
	font-size: var(--text-sm);
	color: var(--text-muted);
	cursor: pointer;
	white-space: nowrap;
	border-bottom: 2px solid transparent;
}
.spark-status-tab:hover { color: var(--text-color); }
.spark-status-tab.on {
	color: var(--text-color);
	font-weight: 600;
	border-bottom-color: var(--spark-amber, #d9822b);
}

/* A section left with nothing visible in it — every field hidden — still draws
   its heading. Section Breaks cannot be hidden, so take the empty one out. */
.form-section.spark-empty-section { display: none !important; }

/* Attachment rows carry three flags, saved as they are ticked. */
.spark-panel-actions { display: flex; gap: 6px; }
.spark-file-flag { margin: 0; cursor: pointer; }
.spark-tbl-row .spark-file-flag { transform: translateY(1px); }

/* =======================================================================
   READING A LIST AT A GLANCE
   Tones use the platform's own semantic pairs — --bg-green on
   --text-on-green and so on — because those are the ones it redraws for the
   dark theme; the raw ramp (--green-100) stays pale in both, which put
   light pastel pills on a dark page. Blue borrows Spark's --info, since the
   platform's dark "text on blue" is an amber. Restraint is the point: if
   everything is coloured, nothing is.
   ======================================================================= */
.spark-pill {
	display: inline-flex;
	align-items: center;
	padding: 2px 9px 3px;
	border-radius: 11px;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.5;
	letter-spacing: .01em;
	white-space: nowrap;
	background: var(--control-bg);
	color: var(--text-muted);
}
.spark-pill.is-good { background: var(--bg-green, #e6f4ec);  color: var(--text-on-green, #17663a); }
.spark-pill.is-warn { background: var(--bg-orange, #fdf0e0); color: var(--text-on-orange, #9a5b0d); }
.spark-pill.is-bad  { background: var(--bg-red, #fbe6e6);    color: var(--text-on-red, #9b2c2c); }
.spark-pill.is-live { background: var(--info-wash, #e7eefc); color: var(--info, #1d4ed8); }

/* Figures line up and stay comparable down the column. */
.list-row-col.num, .spark-tbl-row .num, .spark-tbl-head .num {
	text-align: right;
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
}
/* A zero is the common case; it should not compete with what needs chasing. */
.list-row-col.num.is-zero { color: var(--text-muted); font-weight: 400; }
.list-row-col.num:not(.is-zero) { font-weight: 500; color: var(--text-color); }
.list-row-col.num.is-owed:not(.is-zero) { color: var(--orange-700, #9a5b0d); font-weight: 600; }

/* A blank cell reads as a fault; a dash reads as "nothing here". */
.list-row-col.is-empty { color: var(--text-lightest, #c0c4c9); }
.list-row-col.is-date  { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* Rows: a steady rhythm, and a hover that says "this one". */
.frappe-list .list-row-container .list-row { transition: background 90ms ease; }
.frappe-list .list-row-container:hover .list-row { background: var(--control-bg); }
.frappe-list .list-row-container .list-row:focus-within {
	outline: 2px solid var(--spark-amber, #d9822b);
	outline-offset: -2px;
}
.frappe-list .list-row-head .list-row-col {
	font-size: 11px;
	letter-spacing: .06em;
	color: var(--text-muted);
}

/* =======================================================================
   LONG RECORDS
   The Details pane runs past a screen now, and losing the tabs on the way
   down means scrolling back up to change pane. Keep both rows in view.
   ======================================================================= */
.spark-hier {
	position: sticky;
	top: 0;
	z-index: 6;
	background: var(--fg-color);
	box-shadow: 0 1px 0 var(--border-color);
}

/* Headings stay on one line — a wrapped two-line heading costs more vertical
   space than the column saves. */
.frappe-list .list-row-head .list-row-col {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* ==========================================================================
   THE SEARCH ROW AND THE LIST FOOTER
   --------------------------------------------------------------------------
   The incumbent puts a search box under the alphabet, and under the table a
   total followed by a band of bulk actions. Both are shapes people already
   know; the point of matching them is that nobody has to re-learn where to
   look on their first day.
   ========================================================================== */

.spark-search {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 2px 0 14px;
}

.spark-search-box { position: relative; display: flex; }
.spark-search-box .spark-q {
  width: min(420px, 46vw);
  padding: 6px 26px 6px 10px;
  font-size: var(--text-sm);
  color: var(--ink-gray-9);
  background: var(--control-bg);
  border: 1px solid var(--outline-gray-2);
  border-radius: var(--radius-sm, 6px);
}
.spark-search-box .spark-q:focus {
  outline: none;
  border-color: var(--spark-amber-deep, #B45309);
  box-shadow: 0 0 0 2px var(--outline-gray-1);
}
.spark-search-box .spark-q::-webkit-search-cancel-button { display: none; }
.spark-q-clear {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 0 4px;
  color: var(--ink-gray-4);
}
.spark-q-clear:hover { color: var(--ink-gray-7); }

.spark-q-go {
  padding: 6px 16px;
  font-size: var(--text-sm);
  color: var(--ink-gray-9);
  background: var(--fg-color);
  border: 1px solid var(--outline-gray-2);
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
}
.spark-q-go:hover { background: var(--control-bg); }

.spark-q-link {
  font-size: var(--text-sm);
  color: var(--spark-amber-deep, #B45309);
  text-decoration: none;
}
.spark-q-link:hover { text-decoration: underline; color: var(--spark-amber-deep, #B45309); }
.spark-q-note { font-size: 11px; color: var(--ink-gray-5); }

/* ---- the total under the table --------------------------------------- */
/* It is a list row in every respect but its content, so it inherits the
   column widths of whichever layout the list is in. */
.list-row-container.spark-total {
  border-top: 1.5px solid var(--ink-gray-9);
  border-bottom: 0;
  background: var(--fg-color);
  cursor: default;
}
.list-row-container.spark-total .list-row { cursor: default; }
.list-row-container.spark-total:hover { background: var(--fg-color); }
.spark-total .list-row-col { padding-top: 9px; padding-bottom: 9px; }
.spark-total-l {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--ink-gray-9);
}
.spark-total .list-row-col.num {
  font-weight: 600;
  color: var(--ink-gray-9);
  font-variant-numeric: tabular-nums;
}

/* ---- the bulk action band -------------------------------------------- */
.spark-bulk {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 13px 15px;
  margin-top: 14px;
  background: var(--control-bg);
  border-radius: var(--radius-sm, 6px);
  font-size: var(--text-sm);
}
.spark-bulk-all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 6px 0 0;
  cursor: pointer;
  color: var(--ink-gray-8);
}
.spark-bulk-all input { margin: 0; cursor: pointer; }
.spark-bulk-a { color: var(--spark-amber-deep, #B45309); text-decoration: none; }
.spark-bulk-a:hover { text-decoration: underline; color: var(--spark-amber-deep, #B45309); }
.spark-bulk-sep { color: var(--ink-gray-3); }

@media (max-width: 720px) {
  .spark-search { gap: 8px; }
  .spark-search-box .spark-q { width: 100%; }
  .spark-q-note { flex-basis: 100%; }
}

/* ---- "With selected": the bulk-edit panel under the action bar -------- */
.spark-with { margin-top: 2px; }
.spark-with-tab {
  border: 1px solid var(--outline-gray-2);
  border-bottom: 0;
  background: var(--control-bg);
  border-radius: var(--radius-sm, 6px) var(--radius-sm, 6px) 0 0;
  padding: 6px 15px;
  font-size: var(--text-sm);
  color: var(--ink-gray-8);
  cursor: pointer;
}
.spark-with-tab[aria-expanded="true"] {
  background: var(--fg-color);
  color: var(--ink-gray-9);
  font-weight: 600;
}
.spark-with-body {
  border: 1px solid var(--outline-gray-2);
  border-radius: 0 var(--radius-sm, 6px) var(--radius-sm, 6px) var(--radius-sm, 6px);
  background: var(--control-bg);
  padding: 16px 15px;
}
.spark-with-loading { color: var(--ink-gray-5); font-size: var(--text-sm); }
.spark-with-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px 18px;
}
.spark-with-f { display: flex; flex-direction: column; gap: 5px; margin: 0; }
.spark-with-f > span {
  font-size: 10.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-gray-6);
}
.spark-with-f select,
.spark-with-f input {
  width: 100%;
  padding: 6px 8px;
  font-size: var(--text-sm);
  color: var(--ink-gray-9);
  background: var(--fg-color);
  border: 1px solid var(--outline-gray-2);
  border-radius: var(--radius-sm, 6px);
}
.spark-with-f select[multiple] { padding: 4px; }
.spark-with-pct { display: flex; align-items: center; gap: 6px; }
.spark-with-pct span { color: var(--ink-gray-5); font-size: var(--text-sm); }
.spark-with-foot {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
}
.spark-with-go {
  padding: 7px 20px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--fg-color);
  background: var(--spark-amber-deep, #B45309);
  border: 0;
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
}
.spark-with-go:hover { filter: brightness(1.08); }
.spark-with-note { font-size: var(--text-sm); color: var(--ink-gray-6); }

/* ---- the Project panes ----------------------------------------------- */
.spark-tbl-row.spark-tbl-total {
  border-top: 1.5px solid var(--ink-gray-9);
  font-weight: 600;
  cursor: default;
}
.spark-tbl-row.spark-tbl-total:hover { background: transparent; }
/* the cost centre's whole name and number, as simPRO writes it */
.spark-cc-panel .spark-tbl-row > div:first-child { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.3; }
/* a section of the Cost Centre List, as simPRO groups them */
.spark-cc-section { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-top: 10px; padding: 8px 12px; border-radius: 8px; background: var(--spark-graphite, #13202C); color: #fff;
  font: 700 .78rem var(--spark-display, inherit); letter-spacing: .02em; }
.spark-cc-section b { font-weight: 600; opacity: .8; font-variant-numeric: tabular-nums; }

.spark-ov-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px;
  padding: 4px 0 2px;
}
.spark-ov {
  border: 1px solid var(--outline-gray-1);
  border-radius: var(--radius-sm, 6px);
  padding: 13px 14px;
  background: var(--fg-color);
}
.spark-ov h4 {
  margin: 0 0 9px;
  font-size: 10.5px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}
.spark-ov-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
  font-size: .82rem;
}
.spark-ov-row span { color: var(--ink-gray-6); }
.spark-ov-row b { font-variant-numeric: tabular-nums; color: var(--ink-gray-9); }

/* ---- the map --------------------------------------------------------- */
.spark-map {
  height: 62vh;
  min-height: 380px;
  border: 1px solid var(--outline-gray-2);
  border-radius: var(--radius-sm, 6px);
  overflow: hidden;
}
.spark-map-head {
  font-size: var(--text-sm);
  color: var(--ink-gray-6);
  margin-bottom: 9px;
}
.spark-map-empty { padding: 28px 4px; max-width: 560px; }
.spark-map-empty p { font-size: var(--text-sm); color: var(--ink-gray-7); }
.spark-map-note {
  color: var(--ink-gray-5) !important;
  font-size: 11px !important;
  margin-top: 12px;
}
/* Leaflet paints its own controls; keep them off the desk's dark surfaces. */
.leaflet-container { background: var(--control-bg); font: inherit; }

/* ---- the Gantt pane -------------------------------------------------- */
.spark-gantt { padding: 4px 0 2px; }
.spark-gantt-row {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 3fr) 150px;
  gap: 12px;
  align-items: center;
  padding: 7px 2px;
  border-bottom: 1px solid var(--outline-gray-1);
  font-size: .8rem;
}
.spark-gantt-row:last-child { border-bottom: 0; }
.spark-gantt-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink-gray-8);
}
.spark-gantt-track {
  position: relative;
  height: 17px;
  border-radius: 4px;
  background: var(--control-bg);
}
.spark-gantt-bar {
  position: absolute;
  top: 0;
  height: 100%;
  border-radius: 4px;
  background: var(--outline-gray-2);
  overflow: hidden;
}
.spark-gantt-fill {
  display: block;
  height: 100%;
  background: var(--spark-amber-deep, #B45309);
  opacity: .85;
}
.spark-gantt-when {
  color: var(--ink-gray-5);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.spark-gantt-rest {
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--outline-gray-1);
  color: var(--ink-gray-5);
  font-size: 11px;
}

/* ---- the job's overview ledgers -------------------------------------- */
.spark-ov-ledger { margin-top: 20px; }
.spark-ov-ledger h4 {
  margin: 0 0 8px;
  font-size: 10.5px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}
.spark-ov-ledger h4 span {
  margin-left: 6px;
  color: var(--ink-gray-4);
  letter-spacing: 0;
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE DATA TABLE

   One layout for every list. Each column is the width its kind needs, every
   row is identical by construction, and a table wider than the screen scrolls
   sideways inside its own box while the header and the subject column hold
   still. The box stops at the bottom of the window, so the page itself hardly
   scrolls — the rows move under a header that never leaves.

   Below 769px none of this applies: the row is a card.
   ═══════════════════════════════════════════════════════════════════════ */

.frappe-list .result.spark-table {
  --row-bg: var(--fg-color);
  position: relative;
  border: 1px solid var(--outline-gray-1);
  border-radius: var(--r-lg);
  background: var(--fg-color);
}

@media (min-width: 769px) {
  .frappe-list .result-container:has(> .result.spark-table) {
    overscroll-behavior-x: contain;
    border: 1px solid var(--outline-gray-1);
    border-radius: var(--r-lg);
  }
  /* A table that scrolls sideways has to look like one. An overlay scrollbar
     appears only once the wheel moves, so the columns under the pinned block
     seem simply to be missing. A drawn scrollbar is always there. Setting
     scrollbar-width would switch the drawn one off in Chromium, so it is
     only offered where the drawn one is not understood. */
  .frappe-list .result-container:has(> .result.spark-table)::-webkit-scrollbar { height: 10px; width: 10px; }
  .frappe-list .result-container:has(> .result.spark-table)::-webkit-scrollbar-track { background: var(--surface-gray-1); }
  .frappe-list .result-container:has(> .result.spark-table)::-webkit-scrollbar-thumb {
    background: var(--outline-gray-3);
    border: 2px solid var(--surface-gray-1);
    border-radius: 6px;
  }
  .frappe-list .result-container:has(> .result.spark-table)::-webkit-scrollbar-thumb:hover { background: var(--ink-gray-5); }
  @supports not selector(::-webkit-scrollbar) {
    .frappe-list .result-container:has(> .result.spark-table) { scrollbar-width: thin; scrollbar-color: var(--outline-gray-3) transparent; }
  }
  .frappe-list .result.spark-table { border: 0; border-radius: 0; }
  /* The desk clips .result. With the rows wider than the box, that clipping
     is what made the last columns disappear under the pinned block with no
     scrollbar to say so: the box can only scroll what it is allowed to see. */
  .frappe-list .result.spark-table { overflow: visible !important; }
  .frappe-list .result.spark-table > .list-row-container { min-width: max-content; }

  /* The header stays put. */
  .spark-table > .list-row-container:first-child {
    position: sticky;
    top: 0;
    z-index: 6;
    background: var(--surface-gray-1);
  }
  .spark-table .list-row-head {
    background: var(--surface-gray-1);
    border-bottom: 1px solid var(--outline-gray-2);
  }

  /* The checkbox has a column of its own at the edge… */
  .spark-table .level-left > .spark-cb,
  .spark-table .list-row-head > .level-left.checkbox-actions {
    position: sticky;
    left: 0;
    z-index: 2;
    flex: 0 0 var(--spark-cb, 40px);
    width: var(--spark-cb, 40px);
    margin: 0;
    background: var(--row-bg);
  }
  .spark-table .list-row-head > .level-left.checkbox-actions {
    order: -1;
    display: flex !important;
    flex: 0 0 var(--spark-cb, 40px) !important;
    width: var(--spark-cb, 40px) !important;
    max-width: var(--spark-cb, 40px);
    min-width: 0 !important;      /* stock gives the block min-width: 80% */
    overflow: hidden;
    background: var(--surface-gray-1);
    z-index: 3;
  }
  .spark-table .list-row-head > .level-left.checkbox-actions .list-subject { margin: 0; }
  .spark-table .list-row-head > .level-left.checkbox-actions .list-header-meta { display: none; }
  .spark-table .list-subject .level-item.select-like:not(.spark-cb) { display: none; }

  /* …and the subject holds still beside it, but only when it is first. */
  .spark-table.is-wide .list-row > .level-left > .list-row-col.list-subject.is-first,
  .spark-table.is-wide .list-row-head > .level-left > .list-row-col.list-subject.is-first {
    position: sticky;
    left: var(--spark-cb, 40px);
    z-index: 2;
    background: var(--row-bg);
    padding-right: 8px;
  }
  .spark-table.is-wide .list-row-head > .level-left > .list-row-col.list-subject.is-first {
    z-index: 3;
    background: var(--surface-gray-1);
  }
  .spark-table:not(.is-wide) .list-row > .level-right,
  .spark-table:not(.is-wide) .level-left > .spark-cb { background: transparent; }
  .spark-table.is-wide.is-scrolled .list-row > .level-left > .list-row-col.list-subject.is-first,
  .spark-table.is-wide.is-scrolled .list-row-head > .level-left > .list-row-col.list-subject.is-first {
    box-shadow: 6px 0 12px -8px rgba(16, 24, 32, .28), 1px 0 0 var(--outline-gray-1);
  }
  .spark-table .list-row-head .list-row-col.list-subject { justify-content: flex-start; }
  /* The heart is a social gesture on a work list; the row keeps its menu,
     its age and its comment count. */
  .spark-table .level-right .list-liked-by-me,
  .spark-table .level-right .like-action,
  .spark-table .level-right .list-row-like { display: none !important; }

  /* And the row's own controls, at the right edge. */
  .spark-table .list-row > .level-right,
  .spark-table .list-row-head > .level-right {
    position: sticky;
    right: 0;
    z-index: 2;
    flex: 0 0 auto;
    width: auto;
    min-width: 152px;
    justify-content: flex-end;
    gap: 6px;
    padding-left: 10px;
    background: var(--row-bg);
  }
  .spark-table .list-row-head > .level-right { background: var(--surface-gray-1); z-index: 3; }
  .spark-table.is-wide .list-row > .level-right,
  .spark-table.is-wide .list-row-head > .level-right {
    box-shadow: -6px 0 12px -8px rgba(16, 24, 32, .28);
  }

  /* Rows: a grid of declared tracks. The widths are written once onto the
     table as --spark-cols (see spark.grid), and the heading and every row
     are laid out from that one declaration, so they line up by construction
     — there is nothing left for them to disagree about. The engine this
     replaced wrote a pixel width onto every cell of every row on every
     render, having measured them all first. */
  .spark-table .list-row,
  .spark-table .list-row-head {
    width: auto;
    max-width: none;
    min-width: 100%;
    overflow: visible;
    padding-left: 14px;
    padding-right: 12px;
    gap: 0;
  }
  .spark-table .list-row > .level-left,
  .spark-table .list-row-head > .level-left.list-header-subject {
    display: grid;
    grid-template-columns: var(--spark-cols, 1fr);
    align-items: center;
    flex: 1 1 auto;
    gap: 0;
    min-width: 0;
    overflow: visible;
  }
  /* A row carries the checkbox inside the same grid; the heading keeps its
     own block for it, beside this one and the same width, so the two still
     start at the same place. */
  .spark-table .list-row > .level-left,
  .spark-table .list-row-head > .level-left:has(> .spark-cb) {
    grid-template-columns: var(--spark-cb, 40px) var(--spark-cols, 1fr);
  }
  /* A cell is exactly its track. Without this a cell whose padding sits
     outside its width — the checkbox gutter, the subject — measures wider
     than the track it was given and laps over the next one. */
  .spark-table .list-row-col,
  .spark-table .level-left > .spark-cb {
    box-sizing: border-box;
    max-width: 100%;
  }
  .spark-table .list-row-col {
    min-width: 0;
    margin-right: 0;
    padding-right: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .spark-table .list-row-col.hide { display: none !important; }
  .spark-table .list-row-head .list-row-col { white-space: nowrap; line-height: 1.3; }

  /* The total stays at the foot of the box. */
  .spark-table > .list-row-container.spark-total {
    position: sticky;
    bottom: 0;
    z-index: 5;
    background: var(--fg-color);
  }
  .spark-table > .list-row-container.spark-total .list-subject,
  .spark-table > .list-row-container.spark-total .level-right { background: var(--fg-color); }
}

/* Hover paints the row and, through the token, the two pinned cells too. */
.spark-table > .list-row-container { transition: background .1s ease; }
.spark-table > .list-row-container:hover,
.spark-table > .list-row-container:focus,
.spark-table > .list-row-container:focus-within { --row-bg: var(--surface-gray-1); background: var(--surface-gray-1); }
.spark-table > .list-row-container:not(:last-child) { border-bottom: 1px solid var(--table-border-color); }

/* A row that has just been changed from the list says so, briefly. */
.spark-table > .list-row-container.is-saved { --row-bg: var(--spark-teal-wash); background: var(--spark-teal-wash); }

/* Cell type. */
.spark-table .list-row-col.num { text-align: right; font-family: var(--spark-mono); font-variant-numeric: tabular-nums; justify-content: flex-end; }
.spark-table .list-row-col.num .filterable { font-weight: 500; color: var(--ink-gray-9); }
.spark-table .list-row-col.num.is-zero .filterable { color: var(--ink-gray-4); font-weight: 400; }
.spark-table .list-row-col.num.is-owed .filterable { color: var(--spark-coral); font-weight: 600; }
.spark-table .list-row-col.is-date { font-family: var(--spark-mono); font-size: 11px; color: var(--ink-gray-6); font-variant-numeric: tabular-nums; }
.spark-table .list-row-col.is-empty .filterable,
.spark-table .list-row-col.is-empty a,
.spark-table .list-row-col.is-empty span { color: var(--ink-gray-3); }
.spark-table .list-row-col.is-status { overflow: hidden; }
/* The incumbent's Status column, beside a Status Name column, is a coloured
   dot. It is a dot at every specificity, because the rule that shapes the
   pills in a table cell is the more specific of the two. */
.spark-table .list-row-col.is-status .spark-pill.is-dot {
  width: 12px; min-width: 12px; max-width: 12px; height: 12px;
  padding: 0; border-radius: 50%; overflow: hidden;
}
.spark-table .list-row-col.is-status .spark-pill {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}
.spark-table .list-row-head .list-row-col.num { justify-content: flex-end; }

/* Column headings read as headings. */
.spark-table .list-row-head .list-row-col,
.spark-table .list-row-head .list-row-col > span {
  font-family: var(--spark-font);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: none;
  color: var(--ink-gray-6);
  white-space: nowrap;
}
.spark-table .list-row-head .list-row-col > span[data-sort-by] { cursor: pointer; }
.spark-table .list-row-head .list-row-col > span[data-sort-by]:hover { color: var(--ink-gray-9); }

/* Row type. */
.spark-table .list-row-container .list-row .list-subject a,
.spark-table .list-subject .level-item.bold { font-size: .8rem; font-weight: 600; color: var(--ink-gray-9); }
.spark-table .list-row-container:hover .list-subject a { color: var(--spark-copper); text-decoration: none; }
.spark-table .list-row-container .list-row a:hover { text-decoration: none; }
.spark-table .list-row-container:hover .list-row { background: var(--surface-gray-1); }
.spark-table .list-row-col .filterable { font-size: .775rem; color: var(--ink-gray-8); }
.spark-table .list-row-container .list-row { padding-top: 9px; padding-bottom: 9px; }
.frappe-list.spark-dense .spark-table .list-row-container .list-row { padding-top: 4px; padding-bottom: 4px; }
.frappe-list.spark-dense .spark-table .list-row-col .filterable { font-size: 11px; }

/* A cell that can be changed says so on hover — a pencil after the value,
   nothing drawn round the whole cell. The ring round the cell read as an
   input box that had lost its value. */
.spark-table .list-row-col.is-editable { cursor: pointer; border-radius: 6px; position: relative; }
.spark-table .list-row-col.is-editable::after {
  content: "";
  flex: 0 0 auto;
  width: 13px; height: 13px;
  margin-left: 6px;
  opacity: 0;
  background: currentColor;
  color: var(--spark-amber-deep);
  -webkit-mask: 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='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: 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='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: opacity var(--dur-fast) var(--ease);
}
.spark-table .list-row-col.is-editable:hover::after { opacity: .9; }
.spark-table .list-row-col.is-editable:hover .spark-pill,
.spark-table .list-row-col.is-editable:hover .filterable { text-decoration: none; }
.spark-table .list-row-col.is-editable.is-empty:hover .filterable::before {
  content: "+ ";
  color: var(--spark-amber-deep);
}
.spark-table .list-row-col.is-editable.is-empty:hover .filterable { color: var(--spark-amber-deep); }

/* The row's own menu, only when the row is under the pointer. */
.spark-table .spark-opt { opacity: .55; transition: opacity .1s ease; }
.spark-table > .list-row-container:hover .spark-opt,
.spark-table .spark-opt:focus-visible { opacity: 1; }

/* The count above the rows, and the pager under them. */
.frappe-list .list-paging-area {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 6px 0;
  border: 0;
  background: transparent;
}


/* ─── the popover ───────────────────────────────────────────────────────── */
.spark-pop {
  position: fixed;
  z-index: 1060;
  min-width: 220px;
  max-width: min(360px, calc(100vw - 16px));
  padding: 8px;
  background: var(--fg-color);
  border: 1px solid var(--outline-gray-2);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px -8px rgba(16, 24, 32, .28), 0 2px 6px rgba(16, 24, 32, .08);
  animation: spark-pop-in .14s var(--ease);
}
@keyframes spark-pop-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .spark-pop { animation: none; } }
.spark-pop-title {
  padding: 2px 6px 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-gray-5);
}
.spark-pop-q, .spark-pop-in {
  width: 100%;
  height: 34px;
  padding: 0 10px;
  font-size: .8rem;
  color: var(--ink-gray-9);
  background: var(--surface-gray-1);
  border: 1px solid var(--outline-gray-2);
  border-radius: 8px;
  margin-bottom: 6px;
}
.spark-pop-q:focus, .spark-pop-in:focus { outline: none; border-color: var(--spark-amber); box-shadow: 0 0 0 3px var(--spark-amber-wash); background: var(--fg-color); }
.spark-pop-row { display: flex; gap: 6px; align-items: center; }
.spark-pop-row .spark-pop-in { margin-bottom: 0; flex: 1 1 auto; }
.spark-pop-list { max-height: 300px; overflow: auto; display: flex; flex-direction: column; gap: 1px; }
.spark-pop-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 8px;
  text-align: left;
  font-size: .8rem;
  color: var(--ink-gray-8);
  background: transparent;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}
.spark-pop-opt:hover, .spark-pop-opt:focus-visible { background: var(--surface-gray-1); outline: none; }
.spark-pop-opt.on { background: var(--spark-amber-wash); }
.spark-pop-opt.on::after { content: "✓"; margin-left: auto; color: var(--spark-amber-deep); font-weight: 700; }
.spark-pop-opt.is-clear { color: var(--ink-gray-5); border-top: 1px solid var(--outline-gray-1); border-radius: 0; margin-top: 4px; }
.spark-pop-v { font-weight: 500; color: var(--ink-gray-9); }
.spark-pop-d { font-size: 11px; color: var(--ink-gray-5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spark-pop-none { padding: 10px 8px; font-size: .78rem; color: var(--ink-gray-5); }


/* ─── the list's tools ──────────────────────────────────────────────────── */
.spark-tool {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 10px;
  font-size: var(--text-sm);
  color: var(--ink-gray-7);
  background: var(--fg-color);
  border: 1px solid var(--outline-gray-2);
  border-radius: 8px;
  cursor: pointer;
}
.spark-tool:hover { background: var(--surface-gray-1); color: var(--ink-gray-9); }
.spark-density { margin-left: auto; padding: 0 8px; }
.spark-filters-btn { display: none; }
.spark-filters-btn.has-n { color: var(--spark-amber-deep); border-color: var(--spark-amber-lift); }

/* The standard filter strip: real widths on a desk… */
.page-form .standard-filter-section { gap: 8px 10px; }
.page-form .standard-filter-section .form-group { min-width: 150px; flex: 0 1 190px; margin: 0; }
.page-form .standard-filter-section .form-control { height: 32px; font-size: .78rem; border-radius: 8px; }

/* …and a sheet below a laptop, where ten boxes at three characters each read
   as noise. The button in the search row opens it. */
@media (max-width: 1280px) {
  .spark-filters-btn { display: inline-flex; }
  .layout-main-section:not(.spark-filters-open) .page-form .standard-filter-section { display: none; }
  .layout-main-section.spark-filters-open .page-form .standard-filter-section {
    display: flex;
    flex-wrap: wrap;
    padding: 12px;
    margin-bottom: 10px;
    background: var(--surface-gray-1);
    border: 1px solid var(--outline-gray-1);
    border-radius: var(--r-md);
  }
  .page-form .standard-filter-section .form-group { flex: 1 1 200px; }
}


/* ─── the phone card ────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .frappe-list .result-container:has(> .result.spark-table) { border: 0; overflow: visible; height: auto !important; }
  .frappe-list .result.spark-table {
    border: 0;
    background: transparent;
    border-radius: 0;
    width: 100% !important;
    min-width: 0 !important;
    height: auto !important;
    overflow: visible !important;
  }
  .spark-table > .list-row-container { width: 100% !important; min-width: 0 !important; margin-right: 0 !important; padding-left: 0 !important; }
  .spark-table > .list-row-container:first-child { display: none; }        /* no header on a card */
  .spark-table > .list-row-container {
    margin-bottom: 8px;
    background: var(--fg-color);
    border: 1px solid var(--outline-gray-1) !important;
    border-radius: var(--r-md);
  }
  .spark-table .list-row {
    position: relative;
    display: block;
    padding: 12px 13px;
    width: auto;
    max-width: none;
    overflow: visible;
  }
  .spark-table .list-row > .level-left {
    display: flex !important;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 12px;
    min-width: 0;
    overflow: visible;
  }
  .spark-table .list-row > .level-left > * { display: none !important; }
  .spark-table .list-row > .level-left > .xs-on {
    display: flex !important;
    flex: 0 0 auto;
    width: auto !important;
    min-width: 0 !important;
    max-width: 100%;
  }
  .spark-table .list-row > .level-left > .xs-on .list-row-col { width: auto; min-width: 0; flex: 0 0 auto; }
  .spark-table .list-row > .level-left > .list-subject.xs-on,
  .spark-table .list-row > .level-left > .list-subject.xs-on .level-item,
  .spark-table .list-row > .level-left > .list-subject.xs-on a { min-width: 0; overflow-wrap: anywhere; }
  .spark-table .list-row > .level-left > .list-subject.xs-on {
    flex: 1 1 calc(100% - 46px);
    order: -2;
    font-size: .88rem;
    margin-bottom: 2px;
    padding-right: 88px;
    overflow: visible;
    white-space: normal;
  }
  .spark-table .list-row > .level-left > .list-row-col.is-status { order: -1; }
  .spark-table .list-row > .level-left > .list-row-col.num { margin-left: auto; font-size: .82rem; }
  .spark-table .list-row > .level-left > .list-row-col .filterable { font-size: 11px; color: var(--ink-gray-7); }
  .spark-table .list-row > .level-left > .mobile-layout { padding-left: 0 !important; }
  .spark-table .list-row > .level-right {
    position: absolute;
    top: 9px;
    right: 9px;
    display: flex;
    width: auto;
    flex: none;
    background: transparent;
    box-shadow: none;
  }
  .spark-table .list-row > .level-right > :not(.spark-opt) { display: none !important; }  /* the card shows its own pill */
  .spark-table .list-row > .level-right:empty { display: none; }
  .spark-table .level-left > .spark-cb { display: flex !important; flex: 0 0 30px; order: -3; margin: 0; }
  .spark-table .spark-opt { opacity: 1; }
  .spark-table > .list-row-container.spark-total .list-row { grid-template-columns: 1fr; }
  .spark-table > .list-row-container.spark-total .level-left > * { display: flex !important; }
  .spark-search .spark-density { display: none; }
}

/* ── the subject: the record's number, then what the work is ─────────────── */
/* The incumbent's Job column reads "335 - Protection Relay REF615…". The
   number is the record's own and is set apart from the description so a row
   can be found by either. */
/* The number always shows; the description gives way and ends in an ellipsis
   rather than being cut off mid-word at the column's edge. */
/* The desk wraps the link in a span of its own, and that span is the flex
   item the cell sizes — so it, not the link, is what has to give. */
.spark-table .list-row-col.list-subject > span {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.spark-table .list-subject a:has(.spark-subj-no) {
  display: flex;
  align-items: baseline;
  min-width: 0;
}
.spark-table .list-subject a .spark-subj-no { flex: 0 0 auto; }
.spark-table .list-subject a .spark-subj-said {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spark-table .list-subject a .spark-subj-no {
  font-family: var(--spark-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-gray-7);
  font-variant-numeric: tabular-nums;
}
.spark-table .list-subject a .spark-subj-said {
  margin-left: 8px;
  color: var(--ink-gray-9);
}
.spark-table .list-subject a .spark-subj-said::before {
  content: "·";
  margin-right: 8px;
  color: var(--ink-gray-4);
}

/* ------------------------------------------------------------ rail bands
   Three headings over the ten groups — the work, the money, and the things
   you look up. They are drawn by spark.rail_bands rather than stored on the
   sidebar record, and they are taken out entirely when the rail collapses to
   its icons, where a word with nothing under it is just noise. */
.body-sidebar .spark-rail-band {
	padding: 16px 16px 5px;
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .34);
	user-select: none;
	pointer-events: none;
}
.body-sidebar .spark-rail-band:first-child { padding-top: 6px; }
/* And gone when the rail is narrow, as a fact rather than as the outcome of
   a redraw landing at the right moment.
   spark.rail_bands takes them out of the DOM, but it can only do that when
   it runs, and collapsing is an animation: a pass that lands mid-transition
   measures a rail that is still wide and puts them back. This says it in the
   one place that cannot be mistimed — the container carries `expanded` while
   the rail is open, so its absence is the whole condition. A stale band left
   in the DOM by any future pass still does not show. */
.body-sidebar-container:not(.expanded) .spark-rail-band { display: none !important; }
