:root {
  --lineage-dock-min-width: 1120px;
  --lineage-dock-min-height: 720px;
  /* The rail's one width. It used to be a literal in the grid template, which
     is why every control inside it was sized independently and none of them
     agreed on how much room they had. */
  --rail-width: 48px;
  --rail-pad: 8px;
  --rail-control-size: 32px;
  --surface-rail: #ececf0;
  --surface-main: #f7f7f8;
  --rail-line: #d4d5da;
  --rail-text: #4a4c55;
  --host-text: #1c1c1f;
  --host-muted: #5d5d64;
  --rail-active-bg: #315f9f;
  --rail-active-line: #6ea2ef;
  --stage-bg: #0b1323;
  --dirty-cell-bg: #ffdc5e;
  --dirty-cell-ink: #161616;
  --dirty-cell-dot: #f5b400;
  --dirty-cell-dot-ring: rgba(130, 83, 0, 0.28);
  /* The resolve bar.
   *
   * Declared HERE and not in global_module_styles.css, which is where the app's
   * palette lives, because module_manager.js installs that sheet wrapped in
   * `@scope ([data-module-runtime="<key>"])`. #host-working-indicator is a
   * direct child of <main id="app-stage">, outside every module shell, so it
   * genuinely cannot see those tokens.
   *
   * #22c55e is the value of `--success` in the module palette - defined there
   * and referenced by nothing - so the host green matches the app's green
   * without either file reaching into the other. */
  --progress-fill: #22c55e;
  --progress-fill-done: #16a34a;
  --progress-fill-failed: #ef4444;
  --progress-fill-stalled: #a16207;
  /* Its own token rather than an opacity guess against the panel's
     rgba(24, 26, 31, 0.78) ground. */
  --progress-track: rgba(255, 255, 255, 0.16);
}

/* Dark mode is hard-set off until its palettes are finished - see
   resolvedLineageTheme in module_manager.js, which pins every module to light.
   The host's own dark values are kept and gated behind the same switch: the
   manager stamps data-theme on <html>, so `[data-theme='dark']` here turns the
   whole block back on the moment that function stops pinning. Deleting these
   values would mean rewriting them later from nothing. */
@media (prefers-color-scheme: dark) {
  html[data-theme='dark'] {
    --surface-rail: #181a1e;
    --surface-main: #121316;
    --rail-line: #2f3138;
    --rail-text: #b8bfd0;
    --host-text: #f2f2f4;
    --host-muted: #a4a5ac;
    --rail-active-bg: #173767;
    --rail-active-line: #5f97e8;
    --dirty-cell-bg: #735000;
    --dirty-cell-ink: #fff6d3;
    --dirty-cell-dot: #ffc02e;
    --dirty-cell-dot-ring: rgba(255, 224, 128, 0.28);
    /* Carried here too. The block's stated invariant is that every host token
       has a dark value waiting for the day resolvedLineageTheme stops pinning
       light; omitting one would quietly break that promise. */
    --progress-fill: #4ade80;
    --progress-fill-done: #22c55e;
    --progress-fill-failed: #f87171;
    --progress-fill-stalled: #d3a02a;
    --progress-track: rgba(255, 255, 255, 0.14);
  }
}
* { box-sizing: border-box; }
html, body {
  margin: 0;
  width: 100%;
  height: 100%;
  min-width: var(--lineage-dock-min-width);
  min-height: var(--lineage-dock-min-height);
  overflow: hidden;
  font-family: "Manrope", "Avenir Next", "SF Pro Text", sans-serif;
  background: transparent;
  color: var(--host-text);
}

input,
select,
button,
textarea {
  font: inherit;
  color: inherit;
}

.file-table tbody td.db-cell-dirty,
.file-table tbody td.db-draft-dirty-cell,
td[data-col].db-cell-dirty,
td[data-col].db-draft-dirty-cell {
  position: relative;
}

.file-table tbody tr.selected > td.db-cell-dirty,
.file-table tbody tr.selected > td.db-draft-dirty-cell,
tr.selected > td[data-col].db-cell-dirty,
tr.selected > td[data-col].db-draft-dirty-cell {
  position: relative;
}

.file-table tbody td.db-cell-dirty::after,
.file-table tbody td.db-draft-dirty-cell::after,
td[data-col].db-cell-dirty::after,
td[data-col].db-draft-dirty-cell::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 5px;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--dirty-cell-dot);
  box-shadow: 0 0 0 1px var(--dirty-cell-dot-ring);
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 4;
}
#host-shell {
  position: relative;
  width: 100%;
  height: 100%;
  min-width: var(--lineage-dock-min-width);
  min-height: var(--lineage-dock-min-height);
  display: grid;
  grid-template-rows: 40px 1fr;
  grid-template-columns: var(--rail-width) 1fr;
  overflow: hidden;
  border-radius: 14px;
  background: var(--stage-bg);
}
#rail-top-cap {
  grid-column: 1;
  grid-row: 1;
  border-right: 1px solid var(--rail-line);
  border-bottom: 1px solid var(--rail-line);
  background: var(--surface-main);
}
#global-rail {
  grid-column: 1;
  grid-row: 2;
  position: relative;
  z-index: 9999;
  border-right: 1px solid var(--rail-line);
  border-bottom: 1px solid var(--rail-line);
  background: var(--surface-main);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: var(--rail-pad);
  pointer-events: auto;
  -webkit-app-region: no-drag;
}
#host-logo-wrap {
  width: var(--rail-control-size);
  height: var(--rail-control-size);
  border-radius: 8px;
  display: grid;
  place-items: center;
  margin-bottom: 4px;
}
#host-logo {
  width: 28px;
  height: 28px;
  display: block;
}
.mode-btn {
  width: var(--rail-control-size);
  height: var(--rail-control-size);
  display: grid;
  place-items: center;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--rail-text);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.03em;
  cursor: pointer;
  pointer-events: auto;
  -webkit-app-region: no-drag;
  touch-action: manipulation;
  appearance: none;
  -webkit-appearance: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  box-shadow: none;
  transition: none;
}
.mode-btn--bottom {
  margin-top: auto;
  margin-bottom: 4px;
}

.mode-icon {
  width: 18px;
  height: 18px;
  display: block;
  background-color: var(--rail-text);
  -webkit-mask-image: var(--mode-icon-url);
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-size: contain;
  mask-image: var(--mode-icon-url);
  mask-repeat: no-repeat;
  mask-position: center;
  mask-size: contain;
}
.mode-btn:hover,
.mode-btn:focus,
.mode-btn:focus-visible,
.mode-btn:active {
  border-color: transparent;
  background: transparent;
  outline: none;
  box-shadow: none;
}
.mode-btn.active {
  background: var(--rail-active-bg);
  border-color: var(--rail-active-line);
  color: #fff;
}
.mode-btn.active .mode-icon {
  background-color: #fff;
}
.mode-btn:disabled {
  opacity: 0.32;
  cursor: default;
}
.mode-btn:disabled .mode-icon {
  background-color: var(--rail-text);
}
.mode-btn[hidden],
.settings-nav-btn[hidden] {
  display: none !important;
}

/* The settings group. Stacked on the rail's own 8px rhythm so a setting sits
   exactly where a page button would, and hidden wholesale when the gear is
   collapsed - `hidden` on the group rather than on each button, so a collapsed
   rail cannot leave one of them behind. */
.settings-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.settings-group[hidden] {
  display: none !important;
}

/* Emerging from, and collapsing into, the gear.
   --rail-emerge-slot  how many rail slots this button sits below the gear
   --rail-emerge-delay when its own leg of the sequence starts
   --rail-emerge-step  how long that leg lasts
   All three are written by applyRailEmergence, which derives the delays from
   GEAR_SPIN_MS so the last button lands exactly as the gear stops turning. */
/* This deliberately overrides `.mode-btn { transition: none }` above, and is
   the only place that policy is lifted. The policy exists so a rail button
   never animates its own hover or pressed state - a rail that fades under the
   pointer reads as laggy. Travelling in and out of the gear is not that: it is
   a transition the group makes as a whole, on one event, and it stops. Nothing
   here touches colour or the pressed state, which still change instantly. */
.settings-group .settings-nav-btn {
  transition:
    transform var(--rail-emerge-step, 200ms) cubic-bezier(0.2, 0.8, 0.3, 1) var(--rail-emerge-delay, 0ms),
    opacity var(--rail-emerge-step, 200ms) ease var(--rail-emerge-delay, 0ms);
}

/* The collapsed pose, held at both ends of the journey. Stacked back up under
   the gear by its own slot distance, shrunk into it and transparent - so the
   button is literally inside the gear's box at rest, and the reveal is it
   coming out. The rail slot is the control size plus the group's 8px gap. */
.settings-group.is-emerging .settings-nav-btn,
.settings-group.is-collapsing .settings-nav-btn {
  transform: translateY(calc(var(--rail-emerge-slot, 1) * (var(--rail-control-size) + 8px) * -1)) scale(0.35);
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  /* Someone who has asked the system to stop animating has asked for exactly
     this: the group appears and disappears, and nothing travels. The JS also
     skips the staggering, so these two agree rather than one undoing the
     other. */
  .settings-group .settings-nav-btn {
    transition: none;
  }
  .settings-group.is-emerging .settings-nav-btn,
  .settings-group.is-collapsing .settings-nav-btn {
    transform: none;
    opacity: 1;
  }
}

/* The host's hover tip. Same shape as the module's .resolution-class-tip, on
   this side of the boundary - see bindHostTips for why it cannot be shared. */
.host-tip {
  position: fixed;
  z-index: 400;
  width: max-content;
  max-width: 260px;
  padding: 6px 9px;
  border: 1px solid var(--rail-line);
  border-radius: 6px;
  /* The rail's own surface and the host's text colour, not --rail-text: that
     token is the dim grey an INACTIVE rail glyph is painted in, and a tip
     wearing it was near-invisible against its own background. Both halves
     follow the theme, so this reads in light and dark without a second rule. */
  background: var(--surface-rail);
  color: var(--host-text);
  font-size: 12px;
  line-height: 1.35;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.28);
  pointer-events: none;
}
.host-tip[hidden] {
  display: none !important;
}

/* The gear turns the way the group is going: clockwise as it opens,
   anticlockwise as it closes. The class is added on click and removed on
   animationend, so a rapid double click restarts the turn rather than
   stacking two of them.

   Applied to .mode-icon and not to the button: .mode-btn is `transition: none`
   by policy and carries the hit target, and rotating the box would rotate the
   8px-radius square along with the glyph. */
@keyframes lineage-gear-spin-cw {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes lineage-gear-spin-ccw {
  from { transform: rotate(0deg); }
  to { transform: rotate(-360deg); }
}
.settings-gear .mode-icon.is-spinning-cw {
  animation: lineage-gear-spin-cw 380ms ease-in-out;
}
.settings-gear .mode-icon.is-spinning-ccw {
  animation: lineage-gear-spin-ccw 380ms ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
  .settings-gear .mode-icon.is-spinning-cw,
  .settings-gear .mode-icon.is-spinning-ccw {
    animation: none;
  }
  /* Someone who has asked the system to stop animating has asked for exactly
     this. The controller already drops interpolation, the floor and the pauses
     under reduced motion and steps only on real events; these rules are the
     other half - no easing on the step, and a spinner that does not spin.
     Together they leave a bar that still reports the truth and never moves
     except when something has actually happened. */
  .host-working-fill {
    transition: none;
  }
  .host-working-spinner {
    animation: none;
  }
}
.mode-btn.active:hover,
.mode-btn.active:focus,
.mode-btn.active:focus-visible,
.mode-btn.active:active {
  background: var(--rail-active-bg);
  border-color: var(--rail-active-line);
  color: #fff;
}

/* The account avatar and its menu. mode-btn--bottom already pushes it to the
   foot of the rail; this wrapper exists so the popup can be positioned against
   the button rather than against the rail. */
.rail-account {
  position: relative;
  margin-top: auto;
  display: grid;
  place-items: center;
}
/* An explicit display beats the UA's [hidden] rule, so the wrapper needs its
   own. Without this a hidden avatar still reserved the foot of the rail. */
.rail-account[hidden] {
  display: none !important;
}
.rail-account .mode-btn--bottom {
  margin-top: 0;
}
.rail-avatar {
  overflow: hidden;
  background: var(--surface-rail);
  border-color: var(--rail-line);
}
.rail-avatar-initials {
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--rail-text);
  text-transform: uppercase;
}
/* Before the profile loads there are no initials to show, so the old account
   glyph stays in place rather than leaving an empty circle. */
.rail-avatar-initials:empty {
  display: none;
}
.rail-avatar-initials:not(:empty) + .rail-avatar-fallback {
  display: none;
}
.rail-avatar.active .rail-avatar-initials {
  color: #fff;
}

.rail-menu {
  position: absolute;
  bottom: 0;
  left: calc(100% + 8px);
  z-index: 10000;
  width: 248px;
  padding: 8px;
  border: 1px solid var(--rail-line);
  border-radius: 10px;
  background: var(--surface-main);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.24);
  color: var(--host-text);
  font-size: 13px;
  text-align: left;
}
.rail-menu[hidden] {
  display: none !important;
}
.rail-menu-identity {
  padding: 4px 8px 8px;
}
.rail-menu-email {
  overflow: hidden;
  color: var(--host-text);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-menu-company {
  overflow: hidden;
  color: var(--host-muted);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-menu-row {
  display: grid;
  gap: 4px;
  padding: 4px 8px 8px;
}
.rail-menu-row[hidden] {
  display: none !important;
}
.rail-menu-label {
  color: var(--host-muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.rail-menu-select {
  width: 100%;
  min-width: 0;
  padding: 5px 7px;
  border: 1px solid var(--rail-line);
  border-radius: 6px;
  background: var(--surface-rail);
  color: var(--host-text);
  font: inherit;
}
.rail-menu-sep {
  height: 1px;
  margin: 4px 0;
  background: var(--rail-line);
}
.rail-menu-item {
  display: block;
  width: 100%;
  padding: 7px 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--host-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
/* `display: block` above beats the UA stylesheet's [hidden] rule, so hiding
   Sign out for a signed-out user needs saying explicitly. */
.rail-menu-item[hidden] {
  display: none !important;
}
.rail-menu-item:hover,
.rail-menu-item:focus-visible {
  background: var(--surface-rail);
  outline: none;
}
.rail-menu-item:disabled {
  opacity: 0.45;
  cursor: default;
}
.rail-menu-status {
  padding: 0 8px;
  color: var(--host-muted);
  font-size: 12px;
}
.rail-menu-status:empty {
  display: none;
}

/* The agent orb. Inert: no pointer events, so it cannot swallow a click meant
   for the module underneath it, and nothing is listening for one anyway. */
.agent-orb {
  position: absolute;
  right: 20px;
  bottom: 20px;
  z-index: 6;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rail-line);
  border-radius: 50%;
  background: var(--surface-main);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.22);
  opacity: 0.55;
  pointer-events: none;
}
.agent-orb-core {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 30%, var(--rail-active-line), var(--rail-active-bg));
}

#app-stage {
  grid-column: 2;
  grid-row: 1 / 3;
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--stage-bg);
}

#host-shell.module-overlay-covering-rail #app-stage {
  grid-column: 1 / 3;
  overflow: visible;
  z-index: 10001;
}

#host-shell.module-overlay-covering-rail #window-controls-bar {
  z-index: 20002;
}

#window-controls-bar {
  grid-column: 1 / 3;
  grid-row: 1;
  position: relative;
  height: 40px;
  z-index: 20;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  min-width: max-content;
  gap: 10px;
  padding: 0 12px;
  border-bottom: 1px solid var(--rail-line);
  background: var(--surface-main);
  -webkit-app-region: drag;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: auto;
  cursor: default;
}

html[data-lineage-web-runtime="runtime2"],
html[data-lineage-web-runtime="runtime2"] body {
  min-width: 0;
  min-height: 0;
  background: var(--surface-main);
}

html[data-lineage-web-runtime="runtime2"] #host-shell {
  grid-template-rows: 1fr;
  min-width: 0;
  min-height: 0;
  border-radius: 0;
}

html[data-lineage-web-runtime="runtime2"] #window-controls-bar,
html[data-lineage-web-runtime="runtime2"] #rail-top-cap,
html[data-lineage-web-runtime="runtime2"] .window-resize-hit {
  display: none !important;
}

html[data-lineage-web-runtime="runtime2"] #global-rail,
html[data-lineage-web-runtime="runtime2"] #app-stage {
  grid-row: 1;
}

html[data-lineage-web-runtime="runtime2"] .app-frame,
html[data-lineage-web-runtime="runtime2"] .host-settings {
  top: 0;
  height: 100%;
}

html[data-lineage-web-runtime="runtime2"] #route-mask {
  top: 0;
}

.win-btn,
.mode-btn,
.window-resize-hit {
  -webkit-app-region: no-drag;
}

.window-resize-hit {
  position: absolute;
  z-index: 10000;
  pointer-events: auto;
  user-select: none;
  -webkit-user-select: none;
  background: transparent;
  touch-action: none;
}

.window-resize-hit--north,
.window-resize-hit--south {
  left: 10px;
  right: 10px;
  height: 6px;
}

.window-resize-hit--east,
.window-resize-hit--west {
  top: 10px;
  bottom: 10px;
  width: 6px;
}

.window-resize-hit--north {
  top: 0;
  cursor: ns-resize;
}

.window-resize-hit--east {
  right: 0;
  cursor: ew-resize;
}

.window-resize-hit--south {
  bottom: 0;
  cursor: ns-resize;
}

.window-resize-hit--west {
  left: 0;
  cursor: ew-resize;
}

.window-resize-hit--north-east,
.window-resize-hit--north-west,
.window-resize-hit--south-east,
.window-resize-hit--south-west {
  width: 10px;
  height: 10px;
}

.window-resize-hit--north-east {
  top: 0;
  right: 0;
  cursor: nesw-resize;
}

.window-resize-hit--north-west {
  top: 0;
  left: 0;
  cursor: nwse-resize;
}

.window-resize-hit--south-east {
  right: 0;
  bottom: 0;
  cursor: nwse-resize;
}

.window-resize-hit--south-west {
  left: 0;
  bottom: 0;
  cursor: nesw-resize;
}

.win-btn {
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.22);
  padding: 0;
  cursor: default;
  appearance: none;
  -webkit-appearance: none;
  -webkit-app-region: no-drag;
}
.win-btn::before {
  content: '';
  display: block;
  width: 100%;
  height: 100%;
  text-align: center;
  line-height: 14px;
  font-size: 10px;
  font-weight: 700;
  color: rgba(60, 30, 30, 0.88);
  opacity: 0;
  transition: opacity 90ms linear;
}

.win-btn-close { background: #ff5f57; }
.win-btn-min { background: #ffbd2e; }
.win-btn-zoom { background: #28c840; }
.win-btn-close::before { content: '×'; }
.win-btn-min::before { content: '−'; }
.win-btn-zoom::before { content: '＋'; }

.win-btn:hover { filter: brightness(0.96); }
.win-btn:hover::before { opacity: 1; }
.win-btn:active { filter: brightness(0.9); }
.win-btn:focus,
.win-btn:focus-visible {
  outline: none;
  box-shadow: none;
}

#route-mask {
  position: absolute;
  top: 40px;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  display: none;
  pointer-events: none;
}

#route-mask.visible {
  display: block;
}

.host-visual-alert {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 11000;
  transform: translate(-50%, -50%);
  min-width: 220px;
  max-width: min(520px, calc(100% - 48px));
  padding: 14px 22px;
  border-radius: 14px;
  background: rgba(24, 26, 31, 0.76);
  color: #ffffff;
  font-size: 18px;
  font-weight: 700;
  text-align: center;
  line-height: 1.25;
  box-shadow: 0 18px 52px rgba(0, 0, 0, 0.22);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
  white-space: normal;
}

.host-visual-alert.visible {
  opacity: 1;
}

.host-visual-alert.verbose {
  min-width: min(560px, calc(100% - 48px));
  max-width: min(760px, calc(100% - 48px));
  max-height: min(72vh, 640px);
  overflow: auto;
  padding: 18px 22px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.38;
  text-align: left;
  white-space: pre-line;
}

/* The panel grows to hold a two-line label and a segmented bar.
 *
 * Two lines rather than one because the real sentence does not fit on one:
 * "Searching Audio Network's public website (us.audionetwork.com/track/
 * searchkeyword) for ANW works" is over a hundred characters. Splitting the
 * action from the location keeps all of it, and puts the volatile half - a URL,
 * a count, an estimate - on the line that is allowed to truncate.
 *
 * Column, not row, so the spinner form and the bar form share one box. Kept to
 * flexbox, custom properties, transform and text-overflow: everything here
 * behaves identically on Chrome, Firefox and Safari, and nothing reaches for
 * :has(), @container or scroll-driven animation, none of which this stylesheet
 * uses anywhere. */
.host-working-indicator {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 11020;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-width: 146px;
  max-width: min(560px, calc(100% - 48px));
  min-height: 48px;
  padding: 12px 18px;
  border-radius: 12px;
  background: rgba(24, 26, 31, 0.78);
  color: #ffffff;
  font-size: 16px;
  font-weight: 800;
  line-height: 1.2;
  box-shadow: 0 18px 52px rgba(0, 0, 0, 0.22);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
}

.host-working-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.host-working-primary {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The line that carries the location, the payload and the forecast. Lighter and
 * smaller because it is context, not the headline - and the one allowed to be
 * cut, since a truncated URL still tells you which host you are hitting. */
.host-working-secondary {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  color: rgba(255, 255, 255, 0.66);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.host-working-secondary[hidden],
.host-working-track[hidden] {
  display: none !important;
}

/* Five rows, stacked. Each is `label | bar | status`, on a three-column grid so
 * every label starts at the same x and every status word ends at the same one -
 * a ragged column of statuses is the thing that makes a list like this hard to
 * scan.
 *
 * The bar column is 1fr; the label and status columns size to content, with the
 * status column given a min so "Queued"/"Running"/"Done"/"Skipped" do not shift
 * the bar's right edge as the words change under it. */
.host-working-track {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
}

.host-working-step {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(60px, 1fr) 62px;
  align-items: center;
  gap: 10px;
}

.host-working-step-label {
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: rgba(255, 255, 255, 0.9);
}

/* A step that has not started, or had nothing to do, recedes. The run's shape
 * stays legible without every row shouting equally. */
.host-working-step[data-state="pending"] .host-working-step-label,
.host-working-step[data-state="skipped"] .host-working-step-label {
  color: rgba(255, 255, 255, 0.45);
  font-weight: 600;
}

.host-working-bar {
  position: relative;
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--progress-track);
}

/* scaleX rather than width: it runs on the compositor, so the fill stays smooth
 * on all three engines while the main thread is busy - which, during a resolve,
 * it continuously is. transform-origin left so it grows from the left edge. */
.host-working-fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--progress-fill);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 140ms linear;
}

.host-working-step[data-state="done"] .host-working-fill {
  background: var(--progress-fill-done);
}

/* A run that died. The row freezes at its real position and turns red - it must
 * never run on to full, because the thing it would be claiming to have finished
 * is the thing that broke. */
.host-working-step[data-state="failed"] .host-working-fill {
  background: var(--progress-fill-failed);
}

/* Nothing heard for long enough that the forecast has stopped describing
 * anything, so the fill stops rather than creeping toward the cap. */
.host-working-step[data-state="stalled"] .host-working-fill {
  background: var(--progress-fill-stalled);
}

/* The word that makes the row readable without measuring the bar. tabular-nums
 * so a count that appears here does not jitter, matching the CSV import bar's
 * label. */
.host-working-status {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.55);
}

.host-working-step[data-state="active"] .host-working-status {
  color: var(--progress-fill);
}

.host-working-step[data-state="done"] .host-working-status {
  color: rgba(255, 255, 255, 0.8);
}

.host-working-step[data-state="failed"] .host-working-status {
  color: var(--progress-fill-failed);
}

.host-working-step[data-state="stalled"] .host-working-status {
  color: var(--progress-fill-stalled);
}

/* Off-screen, not display:none - a live region that is not rendered is not
 * announced by every screen reader. */
.host-working-announce {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.host-working-indicator[hidden] {
  display: none !important;
}

.host-working-indicator.visible {
  opacity: 1;
}

.host-working-spinner {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  border-radius: 999px;
  border: 2px solid rgba(255, 255, 255, 0.18);
  border-top-color: #ffffff;
  animation: host-working-spin 0.8s linear infinite;
}

@keyframes host-working-spin {
  to { transform: rotate(360deg); }
}

.app-frame {
  position: absolute;
  top: 40px;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: calc(100% - 40px);
  border: 0;
  background: transparent;
  display: block;
  pointer-events: auto;
}

.merged-runtime-stage {
  overflow: hidden;
}

.merged-module-shell {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

.merged-module-shell[data-host-overlay-active='1'] {
  overflow: visible;
  z-index: 2147482000;
}

.merged-module-shell > * {
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  max-width: 100%;
}

.hidden {
  display: none !important;
}

.host-settings {
  position: absolute;
  top: 40px;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: auto;
  background: var(--surface-main);
  z-index: 10;
  margin-top: 2px;
}

.host-settings.settings-inactive {
  visibility: hidden;
  pointer-events: none;
}

.host-settings-shell {
  padding: 12px;
  display: grid;
  gap: 12px;
  min-height: 100%;
  align-content: start;
  position: relative;
  z-index: 0;
  -webkit-app-region: no-drag;
}

.host-settings-header,
.host-settings-section {
  border: 1px solid var(--rail-line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--surface-main) 86%, #ffffff 14%);
}

.host-settings-header {
  padding: 10px 12px;
}

.host-settings-header h1 {
  margin: 0;
  font-size: 22px;
  color: var(--host-text);
}

.host-settings-section {
  padding: 10px;
  position: relative;
  z-index: 0;
  -webkit-app-region: no-drag;
}

#app_visibility_section {
  position: relative;
  z-index: 50;
  pointer-events: auto;
  -webkit-app-region: no-drag;
}

.host-settings-section h2 {
  margin: 0 0 8px;
  font-size: 15px;
  color: var(--host-text);
}

.app-visibility-mode {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
  cursor: default;
}

.app-mode-btn {
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface-main) 85%, #dfe5f3 15%);
  color: var(--rail-text);
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  pointer-events: auto;
  position: relative;
  z-index: 51;
  -webkit-app-region: no-drag;
}

.app-mode-btn:hover {
  filter: brightness(0.95);
}

.app-mode-btn:active {
  filter: brightness(0.9);
}

.app-mode-btn.active {
  background: var(--rail-active-bg);
  border-color: var(--rail-active-line);
  color: #fff;
}

.app-mode-btn.active:hover {
  filter: brightness(1.05);
}

.app-mode-status {
  margin: 0;
  font-size: 12px;
  color: var(--rail-text);
  opacity: 0.9;
}

.host-settings-frame {
  position: relative;
  z-index: 1;
  width: 100%;
  min-height: 460px;
  height: min(78vh, 900px);
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  background: transparent;
  overflow: auto;
}

.settings-runtime-stage {
  isolation: isolate;
  min-height: 100%;
}

.tracker-subtabs {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
  position: relative;
  z-index: 5;
  isolation: isolate;
  pointer-events: auto;
  -webkit-app-region: no-drag;
}

.tracker-tab {
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  background: transparent;
  color: var(--rail-text);
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 700;
  position: relative;
  z-index: 6;
  cursor: pointer;
  pointer-events: auto;
  -webkit-app-region: no-drag;
}

.tracker-tab.active {
  background: var(--rail-active-bg);
  border-color: var(--rail-active-line);
  color: #fff;
}

.res-settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}

.res-settings-grid label {
  display: grid;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--rail-text);
}

.res-settings-grid select {
  height: 32px;
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface-main) 92%, transparent);
  color: var(--host-text);
  padding: 0 8px;
}

.check-row {
  display: flex !important;
  align-items: center;
  gap: 8px;
}

.settings-paths {
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  padding: 8px;
  font-family: "IBM Plex Mono", "SF Mono", monospace;
  font-size: 11px;
  white-space: pre-wrap;
  margin-bottom: 10px;
  color: var(--host-muted);
}

.res-settings-actions {
  display: flex;
  gap: 8px;
  margin: 6px 0 10px;
}

.res-settings-actions button {
  height: 32px;
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  background: transparent;
  color: var(--host-text);
  padding: 0 10px;
  font-size: 12px;
  font-weight: 700;
}

.settings-json,
.settings-pre {
  width: 100%;
  min-height: 180px;
  border: 1px solid var(--rail-line);
  border-radius: 8px;
  background: transparent;
  color: var(--host-text);
  font-family: "IBM Plex Mono", "SF Mono", monospace;
  font-size: 11px;
  padding: 8px;
}

@media (prefers-color-scheme: dark) {
  html[data-theme='dark'] input,
  html[data-theme='dark'] select,
  html[data-theme='dark'] textarea {
    -webkit-text-fill-color: var(--host-text);
    caret-color: var(--host-text);
  }

  html[data-theme='dark'] input::placeholder,
  html[data-theme='dark'] textarea::placeholder {
    color: var(--host-muted);
    -webkit-text-fill-color: var(--host-muted);
  }
}

/* The rail's settings, while a macro owns the app. Greyed and unclickable
 * rather than hidden: a control that vanishes mid-run makes the user hunt for
 * it afterwards, where one that is visibly unavailable says the app is busy and
 * will give it back. The gear itself stays live - opening the disclosure
 * changes nothing about the run, and locking it would trap someone who had just
 * opened the group. */
.settings-group.is-macro-locked {
  pointer-events: none;
}
/* Greyed the way every other disabled button in the app is: the same button,
 * drawn exactly as it always is, at 0.42. The generic `.mode-btn:disabled`
 * rules repaint the glyph in the rail's text colour and dim again, which on a
 * setting that is ON put a dark glyph on the blue "on" fill - a grey box with
 * no icon in it. Not while the group is travelling in or out of the gear:
 * that animation owns opacity then. */
.settings-group.is-macro-locked:not(.is-emerging):not(.is-collapsing) .settings-nav-btn:disabled {
  opacity: 0.42;
}
.settings-group.is-macro-locked .settings-nav-btn.active:disabled .mode-icon {
  background-color: #fff;
}

/* A macro whose plan has not landed yet. The panel is present but says nothing
   for the moment between its work item being minted and its first phase being
   published - which is better than flashing the generic spinner the panel
   exists to replace. Invisible rather than hidden, so the box does not pop into
   place a frame later. */
.host-working-indicator.is-awaiting-macro {
  opacity: 0;
}
