/* Supplai shell + shared components.
 *
 * Every number is a Flutter logical px, and the whole page is drawn at 90%
 * like the Flutter app (kDesktopZoom in lib/core/theme/app_zoom.dart), so the
 * two read the same side by side. Tokens mirror AppPalette light/dark.
 */

/* The exact file Flutter web draws with: Roboto 2.137 (2017), Regular only,
 * fetched by the engine from Google Fonts. Not today's Roboto 3, a redrawn
 * family with other shapes and spacing, which is what made the prototype's
 * text read differently next to the app. One face on purpose: w500 renders
 * regular and w600/w700 as a synthetic bold, the way Flutter renders them. */
@font-face { font-family: Roboto; font-weight: 400; font-style: normal; font-display: swap; src: url(../fonts/roboto-2.137-regular.woff2) format("woff2"); }

:root {
  --zoom: .9;
  --bg: #F4F2EE;
  --surface: #FFFFFF;
  --surface-light: #EFEDE7;
  --card: #FFFFFF;
  --primary: #1976D2;
  --primary-light: #42A5F5;
  --secondary: #2E7D32;
  --text: #1A1A1A;
  --text-2: #4A4A4A;
  --muted: #6A6A6A;
  --border: #D9D6D0;
  --error: #D32F2F;
  --warning: #E65100;
  --success: #2E7D32;
  --selected: rgba(0, 0, 0, .10);
  --hover: rgba(0, 0, 0, .04);
  --pressed: rgba(0, 0, 0, .08);
  --shadow: rgba(0, 0, 0, .08);
  --shimmer-base: #E8E5DF;
  --shimmer-hi: #F4F2EE;
  --seg-bg: #EFEDE7;
  --tint-rgb: 0, 0, 0;
  --sel-bar: rgba(26, 26, 26, .6);
  --tooltip-bg: #333333;
  --top-shade: rgba(0, 0, 0, .035);
  --fab-shadow: 0 4px 14px rgba(0, 0, 0, .08);
  --menu-shadow: 0 1px 3px rgba(0, 0, 0, .2), 0 1px 8px rgba(0, 0, 0, .12);

  --ease-out-cubic: cubic-bezier(.215, .61, .355, 1);
  --ease-in-cubic: cubic-bezier(.55, .055, .675, .19);
  --ease-in-out-cubic: cubic-bezier(.645, .045, .355, 1);
  --ease-out: cubic-bezier(0, 0, .58, 1);
  --ease-in-out: cubic-bezier(.42, 0, .58, 1);

  --sidebar-w: 212px;
  --topbar-h: 76px;
  /* The page's side padding. 20px, the top bar's own: 28 plus the old 14px
     inset read as a gap between the sidebar and every screen (Lucas, 2026-10-03). */
  --gutter: 20px;
  /* Extra room between the sidebar and every screen; kept as a knob, off. */
  --main-inset: 0px;
  /* The page's layers, bottom to top. Every overlay takes one of these (or
     the token plus a step inside its own band), so the order is written
     down once: a tooltip is above everything, the tour included. */
  --z-sticky: 3;
  --z-sidebar: 10;
  --z-fab: 20;
  --z-nav: 40;
  --z-menu: 60;
  --z-drawer: 70;
  --z-modal: 80;
  --z-toast: 90;
  --z-popover: 95;
  --z-tour: 1000;
  --z-tooltip: 1100;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #1E1E1E;
  --surface: #2D2D2D;
  --surface-light: #3D3D3D;
  --card: #2D2D2D;
  --primary: #2196F3;
  --primary-light: #64B5F6;
  --secondary: #4CAF50;
  --text: #FFFFFF;
  --text-2: #B0B0B0;
  --muted: #808080;
  --border: #404040;
  --error: #EF5350;
  --warning: #FFA726;
  --success: #66BB6A;
  --selected: rgba(255, 255, 255, .08);
  --hover: rgba(255, 255, 255, .04);
  --pressed: rgba(255, 255, 255, .08);
  --shadow: rgba(0, 0, 0, .40);
  --shimmer-base: #2A2A2A;
  --shimmer-hi: #3A3A3A;
  --seg-bg: #4A4A4A;
  --tint-rgb: 255, 255, 255;
  --sel-bar: rgba(255, 255, 255, .6);
  --tooltip-bg: #1A1A1A;
  --top-shade: rgba(0, 0, 0, .14);
  --fab-shadow: 0 4px 14px rgba(0, 0, 0, .35);
  color-scheme: dark;
}

@media (max-width: 767.98px), (pointer: coarse) { :root { --zoom: 1; --gutter: 16px; --main-inset: 0px; } }

* { box-sizing: border-box; }
html { zoom: var(--zoom); -webkit-text-size-adjust: 100%; }
/* Plotly sizes hover labels and legends by measuring text in a hidden SVG it
   appends to <body>. Under the zoom those measurements come back 10% short
   and the text spills out of its box; at zoom 1 they are the plot's own px.
   (The pointer side of the same problem is in chart.js.) */
#js-plotly-tester { zoom: calc(1 / var(--zoom)); }
html, body { margin: 0; height: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: Roboto, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  line-height: 1.43;
  letter-spacing: .25px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Fractional glyph metrics and no hinting: closer to how Flutter's Skia
     draws text (the app renders to a canvas, not with the browser's text). */
  text-rendering: geometricPrecision;
  overflow: hidden;
}
button, input, select, textarea { font: inherit; letter-spacing: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: inherit; text-decoration: none; }
[x-cloak] { display: none !important; }
.ic { flex: none; display: block; }
.num { font-variant-numeric: tabular-nums; }

/* ── Shell ───────────────────────────────────────────────────────────── */

.app-shell {
  display: flex;
  width: 100%;
  height: calc(100dvh / var(--zoom));
}

.sidebar {
  flex: none;
  width: var(--sidebar-w);
  height: 100%;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  overflow: hidden;
  white-space: nowrap;
  transition: width 200ms linear;
}
.app-shell.is-collapsed .sidebar { width: 64px; }
.app-shell.is-collapsed .sb-label,
.app-shell.is-collapsed .sb-section-title,
.app-shell.is-collapsed .sb-wordmark,
.app-shell.is-collapsed .sb-pill,
.app-shell.is-collapsed .acct-text,
.app-shell.is-collapsed .acct-unfold,
.app-shell.is-collapsed .sb-dash-toggle { display: none; }

.sb-head { padding: 20px 19px 16px 20px; display: flex; align-items: center; gap: 12px; height: 65px; }
.sb-logo { width: 24px; height: 24px; border: 2px solid var(--text); border-radius: 4px; flex: none; }
.sb-wordmark { font-size: 20px; font-weight: 700; letter-spacing: .25px; flex: 1; }
.sb-activity {
  position: relative; display: grid; place-items: center; width: 27px; height: 27px;
  border-radius: 8px; color: var(--text-2); flex: none;
}
.sb-activity:hover { background: var(--hover); }
.app-shell.is-collapsed .sb-head { flex-direction: column; align-items: flex-start; height: auto; gap: 8px; padding-bottom: 0; }

.sb-scroll { flex: 1; overflow-y: auto; overflow-x: hidden; padding-top: 8px; scrollbar-width: thin; scrollbar-color: transparent transparent; }
.sb-scroll:hover { scrollbar-color: var(--border) transparent; }
.sb-section { margin-bottom: 12px; }
.sb-section-title { padding: 8px 16px; font-size: 11px; font-weight: 500; color: var(--muted); line-height: 1.43; }

.sb-item { display: block; padding: 2px 8px; }
.sb-row {
  position: relative;
  display: flex; align-items: center;
  border-radius: 8px;
  height: 40px;
  transition: background-color 60ms linear;
}
.sb-row:hover { background: var(--hover); }
.sb-row:active { background: var(--pressed); }
.sb-item.is-active .sb-row { background: var(--selected); }
.sb-bar { margin-left: 4px; width: 3px; height: 24px; border-radius: 2px; background: transparent; flex: none; }
.sb-item.is-active .sb-bar { background: var(--sel-bar); }
.sb-icon { margin-left: 8px; color: var(--text-2); transition: transform 160ms var(--ease-out-cubic); }
.sb-row:hover .sb-icon { transform: scale(1.1); }
.sb-item.is-active .sb-icon { color: var(--text); }
.sb-label { margin-left: 12px; font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; flex: 1; padding-right: 8px; }
.sb-item.is-active .sb-label { font-weight: 500; }
.sb-pill { font-size: 9px; font-weight: 500; color: var(--text-2); background: rgba(106, 106, 106, .18); padding: 2px 5px; border-radius: 4px; margin-right: 8px; }
.sb-dash-toggle { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 6px; color: var(--muted); margin-right: 4px; }
.sb-dash-toggle:hover { background: var(--hover); }
.sb-dash-toggle .ic { transition: transform 160ms var(--ease-out-cubic); }
.sb-dash-toggle[aria-expanded="true"] .ic { transform: rotate(180deg); }
.sb-sub-head { padding: 8px 8px 3px 36px; font-size: 9.5px; font-weight: 700; letter-spacing: .6px; color: var(--muted); }
.sb-sub { display: block; padding: 1px 8px 1px 24px; }
.sb-sub-row { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 8px; font-size: 11.5px; color: var(--text-2); overflow: hidden; }
.sb-sub-row:hover { background: var(--hover); }
.sb-sub-dot { width: 7px; overflow: hidden; display: flex; justify-content: flex-end; transition: width 140ms var(--ease-out); flex: none; }
.sb-sub-dot .ic { opacity: 0; transition: opacity 120ms linear; }
.sb-sub-row:hover .sb-sub-dot { width: 14px; }
.sb-sub-row:hover .sb-sub-dot .ic { opacity: 1; }
.sb-sub-label { overflow: hidden; text-overflow: ellipsis; }

.sb-foot { border-top: 1px solid var(--border); padding: 6px 4px 8px 8px; display: flex; align-items: center; }
.app-shell.is-collapsed .sb-foot { flex-direction: column; padding: 6px 4px 8px; gap: 2px; }
.acct { flex: 1; display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 0; min-width: 0; text-align: left; }
.acct:hover { background: var(--hover); }
.app-shell.is-collapsed .acct { padding: 6px 0; flex: none; }
.acct-avatars { position: relative; width: 46px; height: 30px; flex: none; }
.acct-org { position: absolute; left: 0; top: 2px; width: 26px; height: 26px; border-radius: 50%; background: var(--surface-light); display: grid; place-items: center; font-size: 11px; font-weight: 700; color: var(--text); overflow: hidden; }
.acct-org img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: var(--surface-light); }
.acct-user { position: absolute; right: 0; top: 0; width: 30px; height: 30px; border-radius: 50%; background: var(--surface); padding: 2px; }
.acct-user span { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--primary); color: #fff; font-size: 12px; font-weight: 700; letter-spacing: 0; }
.acct-text { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.acct-name { font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.acct-org-name { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.acct-unfold { color: var(--muted); }
.icon-btn { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; color: var(--text-2); flex: none; transition: background-color 80ms linear; }
.icon-btn:hover { background: var(--hover); }
.icon-btn:active { background: var(--pressed); }

/* The menu that opens from the account row, and any other popup menu */
.menu {
  position: fixed; z-index: var(--z-menu); min-width: 240px;
  background: var(--card); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: var(--menu-shadow); padding: 8px 0;
  transform-origin: bottom left;
}
.menu-enter { transition: opacity 120ms linear, transform 160ms var(--ease-out-cubic); }
.menu-enter-start { opacity: 0; transform: scale(.96); }
.menu-enter-end { opacity: 1; transform: scale(1); }
.menu-item { display: flex; align-items: center; gap: 12px; width: 100%; height: 40px; padding: 0 12px; font-size: 13px; font-weight: 500; text-align: left; color: var(--text); }
.menu-item .ic { color: var(--text-2); }
.menu-item:hover { background: var(--hover); }
.menu-sep { height: 1px; background: var(--border); margin: 7px 0 8px; }
.menu-head { display: flex; align-items: center; gap: 10px; height: 52px; padding: 0 12px; }
.menu-head b { display: block; font-size: 13px; font-weight: 600; }
.menu-head small { display: block; font-size: 11px; color: var(--muted); }

/* ── Main column: top bar + content ───────────────────────────────────── */

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; height: 100%; position: relative; }
.topbar {
  flex: none; height: var(--topbar-h); padding: 10px 20px 0 calc(20px + var(--main-inset)); background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 12px;
}
.tb-title-col { flex: 1; min-width: 0; padding-left: 12px; }
.tb-title { font-size: 19px; font-weight: 700; line-height: 1.2; letter-spacing: -.2px; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tb-sub { margin-top: 4px; font-size: 12.5px; line-height: 1.3; color: var(--muted); letter-spacing: .25px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tb-actions { display: flex; align-items: center; gap: 8px; margin-left: 8px; flex: none; }
.bell { position: relative; }
/* The activity tab (shell/bell.html): folded to a handle at the top bar's
   right edge; out while something runs or is unread, and on hover. */
.act-tab { position: relative; flex: none; display: flex; align-items: center; justify-content: flex-end; height: 48px; max-width: 14px; margin-right: -20px; padding-right: 0; overflow: hidden; transition: max-width 220ms var(--ease-out-cubic), padding 220ms var(--ease-out-cubic); }
.act-tab:hover, .act-tab:focus-within, .act-tab.is-out { max-width: 64px; padding-right: 14px; }
.act-handle { position: absolute; right: 4px; top: 50%; width: 5px; height: 26px; margin-top: -13px; border-radius: 3px; background: var(--border); transition: opacity 160ms linear; }
.act-tab:hover .act-handle, .act-tab:focus-within .act-handle, .act-tab.is-out .act-handle { opacity: 0; }
.act-tab .bell { opacity: 0; transition: opacity 160ms linear; }
.act-tab:hover .bell, .act-tab:focus-within .bell, .act-tab.is-out .bell { opacity: 1; }
.act-ring { position: absolute; inset: 3px; border-radius: 50%; border: 2px solid transparent; pointer-events: none; }
.bell.has-jobs .act-ring { border-color: color-mix(in srgb, var(--primary) 25%, transparent); border-top-color: var(--primary); animation: act-spin 1s linear infinite; }
@keyframes act-spin { to { transform: rotate(360deg); } }
.act-jobs { display: flex; flex-direction: column; padding: 4px 0 8px; }
.act-job { display: flex; align-items: center; gap: 10px; padding: 8px 16px; }
.act-job-spin { flex: none; width: 14px; height: 14px; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--primary) 25%, transparent); border-top-color: var(--primary); animation: act-spin 1s linear infinite; }
.act-job-bar { display: block; height: 4px; margin-top: 6px; border-radius: 2px; background: var(--surface-light); overflow: hidden; }
.act-job-bar i { display: block; height: 100%; background: var(--primary); border-radius: 2px; }
.act-job-pct { flex: none; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .bell.has-jobs .act-ring, .act-job-spin { animation: none; } }
.bell-badge { position: absolute; right: 8px; top: 8px; min-width: 16px; padding: 0 5px; height: 16px; border-radius: 10px; background: var(--error); color: #fff; font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; letter-spacing: 0; }

.content { flex: 1; min-height: 0; position: relative; background: var(--bg); }
.page { position: absolute; inset: 0 0 0 var(--main-inset); overflow: auto; padding: 16px var(--gutter) 20px; scrollbar-width: none; }
/* Flutter overlays its scrollbar on the content; a native one took 15px of
   width and pushed every right edge in. */

/* Loading bar for htmx navigations: a hairline under the top bar */
.nav-progress { position: absolute; left: 0; right: 0; top: var(--topbar-h); height: 2px; z-index: 30; pointer-events: none; overflow: hidden; opacity: 0; transition: opacity 200ms linear; }
.htmx-request .nav-progress, .nav-progress.htmx-request { opacity: 1; }
.nav-progress::after { content: ""; position: absolute; inset: 0; width: 40%; background: var(--primary); animation: navprog 900ms var(--ease-in-out) infinite; }
@keyframes navprog { from { transform: translateX(-100%); } to { transform: translateX(260%); } }
/* Any request a person started (shell.js, "every press answers at once"):
   the bar past 150 ms, the pressed control busy, a write's button disabled
   with a spinner until its answer. */
.nav-progress.is-busy { opacity: 1; }
[aria-busy="true"]:is(a, button, [role="tab"], select) { cursor: progress; }
a[aria-busy="true"]:not(.sb-item) { opacity: .72; }
.busy-spin { display: inline-block; flex: none; width: 12px; height: 12px; margin-right: 6px; vertical-align: -2px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: saspin 700ms linear infinite; }
@media (prefers-reduced-motion: reduce) { .busy-spin { animation-duration: 2s; } }

/* ── Agent FAB ────────────────────────────────────────────────────────── */

.content > .fab-wrap { position: absolute; right: 20px; bottom: 20px; z-index: var(--z-fab); }
.fab-wrap > .fab {
  position: relative;
  height: 44px; min-width: 44px; padding: 0 12px; border-radius: 22px;
  display: flex; align-items: center; background: var(--card); border: 1px solid var(--border);
  box-shadow: var(--fab-shadow); color: var(--text); overflow: hidden;
}
.fab:hover { background-image: linear-gradient(var(--hover), var(--hover)); }
.fab-label { font-size: 13px; font-weight: 600; max-width: 0; opacity: 0; padding-left: 0; white-space: nowrap; transition: max-width 180ms var(--ease-out-cubic), padding 180ms var(--ease-out-cubic), opacity 120ms linear; }
.fab:hover .fab-label { max-width: 120px; padding-left: 8px; opacity: 1; }

/* ── Cards, buttons, segmented controls, badges ──────────────────────── */

.card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; }
/* --field-under: the surface an outlined field's floating label sits on,
   so its cut-out matches it (warm paper in light, dark in dark). Each
   container that paints a surface sets it; the label reads it. */
body { --field-under: var(--bg); }
.card, .sop-card, .sop-spc { --field-under: var(--card); }
.psp { --field-under: var(--bg); }
.sp, .ui-confirm-dlg { --field-under: var(--surface); }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 36px; padding: 0 16px; border-radius: 8px; font-size: 13px; font-weight: 500; white-space: nowrap;
  transition: background-color 100ms linear, border-color 100ms linear, box-shadow 100ms linear;
}
.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover { background: color-mix(in srgb, var(--primary) 92%, #000); }
.btn-primary:active { background: color-mix(in srgb, var(--primary) 84%, #000); }
.btn-outline { border: 1px solid var(--border); color: var(--text); background: transparent; }
.btn-outline:hover { background: var(--hover); }
.btn-text { color: var(--primary); padding: 0 8px; }
.btn-text:hover { background: color-mix(in srgb, var(--primary) 8%, transparent); }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn-danger { background: var(--error); color: #fff; }
.btn-danger:hover { background: color-mix(in srgb, var(--error) 90%, #000); }

/* ── The confirmation dialog (layers.js uiConfirm; every hx-confirm) ─── */
.ui-confirm { position: fixed; inset: 0; z-index: calc(var(--z-modal) + 9); display: grid; place-items: center; padding: 16px; background: rgba(0, 0, 0, .44); animation: swapin 120ms var(--ease-out) both; }
.ui-confirm-dlg { width: min(420px, 100%); padding: 22px 22px 18px; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 11px 15px rgba(0, 0, 0, .2), 0 24px 38px rgba(0, 0, 0, .14); }
.ui-confirm-title { margin: 0; font-size: 15.5px; font-weight: 600; line-height: 1.4; letter-spacing: 0; }
.ui-confirm-body { margin: 8px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--text-2); }
.ui-confirm-acts { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
.ui-confirm-acts .btn { height: 34px; }
.btn-icon { width: 36px; padding: 0; }
.ibtn { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 8px; color: var(--text-2); transition: background-color 80ms linear; }
.ibtn:hover { background: var(--hover); color: var(--text); }
.ibtn.is-on { background: var(--selected); color: var(--text); }

.seg { display: inline-flex; padding: 3px; gap: 2px; border-radius: 8px; background: var(--seg-bg); position: relative; }
.seg button, .seg a { position: relative; z-index: 1; height: 26px; padding: 0 10px; border-radius: 6px; font-size: 11.5px; color: var(--text-2); display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; transition: color 120ms linear; }
.seg button:hover, .seg a:hover { color: var(--text); }
.seg .is-on { color: var(--text); font-weight: 500; }
.seg-thumb { position: absolute; z-index: 0; top: 3px; bottom: 3px; border-radius: 6px; background: var(--card); box-shadow: 0 1px 2px rgba(0, 0, 0, .10); transition: left 200ms var(--ease-out-cubic), width 200ms var(--ease-out-cubic); }

.chip { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--card); font-size: 12px; color: var(--text); }
.chip:hover { background-image: linear-gradient(var(--hover), var(--hover)); }

.badge { display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 8px; border-radius: 10px; font-size: 10.5px; font-weight: 500; white-space: nowrap; letter-spacing: .1px; }
.badge-dot::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

.input {
  height: 36px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface-light);
  padding: 0 12px; font-size: 13px; outline: none; transition: border-color 100ms linear, background-color 100ms linear;
}
.input:focus { border-color: var(--primary); }
.input::placeholder { color: var(--muted); opacity: .75; font-style: italic; font-weight: 300; }
.search { position: relative; display: flex; align-items: center; }
.search .ic { position: absolute; left: 12px; color: var(--muted); pointer-events: none; }
.search .input { padding-left: 36px; width: 100%; }

/* Tooltip: data-tip on any element. The bubble is one element on <body>
   (static/js/tooltip.js), position fixed on the top layer, placed from the
   trigger's rect and clamped to the viewport, so no sidebar, side panel or
   overflow container can clip it or draw over it. Never a ::after inside
   the trigger again: that one was clipped by every scrolling ancestor
   (tests/ui/test_tooltip_layer.py). */
[data-tip] { position: relative; }
.ui-tip {
  position: fixed; z-index: var(--z-tooltip); left: 0; top: 0;
  width: max-content; max-width: min(360px, calc(100vw / var(--zoom) - 16px));
  background: var(--tooltip-bg); color: #fff; font-size: 12px; letter-spacing: 0; line-height: 1.35; padding: 4px 8px; border-radius: 6px;
  white-space: pre-line; overflow-wrap: anywhere; text-align: left; pointer-events: none;
  opacity: 0; transition: opacity 150ms linear;
}
.ui-tip[hidden] { display: none; }
.ui-tip.is-on { opacity: 1; }
/* InfoTooltip (info_tooltip.dart): inverted, roomier, wraps at 300 px. */
.ui-tip.is-info { max-width: min(300px, calc(100vw / var(--zoom) - 16px)); padding: 9px 12px; border-radius: 8px; background: var(--text); color: var(--bg); line-height: 1.45; }

/* ── Shimmer skeleton (shimmer 3.0: 1.5s, left→right, one sweep over all bars) */

.sk { background: linear-gradient(100deg, var(--shimmer-base) 0%, var(--shimmer-base) 35%, var(--shimmer-hi) 50%, var(--shimmer-base) 65%, var(--shimmer-base) 100%); background-size: 300vw 100%; background-attachment: fixed; animation: shimmer 1.5s linear infinite; border-radius: 6px; }
@keyframes shimmer { from { background-position: 100vw 0; } to { background-position: -200vw 0; } }

/* ── Side panel (showSidePanel): full height, over everything ─────────── */

.sp-scrim { position: fixed; inset: 0; z-index: var(--z-drawer); background: rgba(0, 0, 0, .32); }
.sp {
  position: fixed; z-index: calc(var(--z-drawer) + 1); top: 0; right: 0; bottom: 0; width: min(560px, 100vw);
  height: calc(100dvh / var(--zoom));
  background: var(--surface); border-left: 1px solid var(--border); display: flex; flex-direction: column;
  box-shadow: -8px 0 24px rgba(0, 0, 0, .08);
}
.sp-enter { transition: transform 280ms var(--ease-out-cubic); }
.sp-leave { transition: transform 220ms var(--ease-in-cubic); }
.sp-from { transform: translateX(100%); }
.sp-to { transform: translateX(0); }
.fade-enter { transition: opacity 220ms linear; }
.fade-leave { transition: opacity 180ms linear; }
.fade-from { opacity: 0; }
.fade-to { opacity: 1; }
.sp-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 16px 14px 24px; border-bottom: 1px solid var(--border); }
.sp-title { font-size: 16px; font-weight: 600; line-height: 1.33; letter-spacing: 0; }
.sp-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.sp-body { flex: 1; overflow: auto; padding: 20px 24px 28px; }

/* ── The changes list (app/ui/changes.py): a side panel on .sp ─────────── */
.chg-sp { width: min(520px, 100vw); }
.chg-sp.is-docked { box-shadow: -8px 0 24px rgba(0, 0, 0, .14); }
.chg-hcol { flex: 1; min-width: 0; }
.chg-x { width: 34px; height: 34px; flex: none; display: grid; place-items: center; border-radius: 50%; color: var(--text-2); }
.chg-x:hover { background: var(--hover); }
.chg-filters { display: flex; flex-direction: column; gap: 10px; padding: 12px 24px 14px; border-bottom: 1px solid var(--border); }
.chg-tabs { display: inline-flex; align-self: flex-start; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.chg-tab input { position: absolute; opacity: 0; pointer-events: none; }
.chg-tab span { display: block; font-size: 12px; padding: 5px 10px; color: var(--text-2); cursor: pointer; }
.chg-tab input:checked + span { background: color-mix(in srgb, var(--primary) 12%, transparent); color: var(--primary); font-weight: 600; }
.chg-tab input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: -2px; }
.chg-q { display: flex; align-items: center; gap: 8px; padding: 0 10px; height: 34px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-light); color: var(--muted); }
.chg-q:focus-within { border-color: var(--primary); }
.chg-q input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--text); font-size: 13px; }
/* Filters one at a time: chips plus "+ Filtro" (shell/_changes_bar.html). */
.chg-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.chg-bar:not(:has(.chg-chip, .chg-add)) { display: none; }
.chg-chip { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; height: 26px; padding: 0 2px 0 10px; border-radius: 999px; font-size: 12px; color: var(--text); background: color-mix(in srgb, var(--primary) 9%, transparent); border: 1px solid color-mix(in srgb, var(--primary) 22%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chg-chip-k { color: var(--text-2); }
.chg-chip-x { width: 20px; height: 20px; flex: none; display: grid; place-items: center; border-radius: 50%; color: var(--text-2); }
.chg-chip-x:hover { background: var(--hover); color: var(--text); }
.chg-add, .chg-sort { position: relative; }
.chg-add > summary, .chg-sort > summary { list-style: none; cursor: pointer; user-select: none; }
.chg-add > summary::-webkit-details-marker, .chg-sort > summary::-webkit-details-marker { display: none; }
.chg-add-btn { display: inline-flex; align-items: center; height: 26px; padding: 0 10px; border-radius: 999px; font-size: 12px; font-weight: 500; color: var(--text-2); }
.chg-add-btn:hover, .chg-add[open] > .chg-add-btn { color: var(--text); background: var(--hover); }
.chg-pop { position: absolute; top: calc(100% + 4px); left: 0; z-index: var(--z-popover); min-width: 200px; max-width: min(320px, 80vw); padding: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 20px rgba(0, 0, 0, .14); }
.chg-pop-r { left: auto; right: 0; min-width: 150px; }
.chg-pop-h { display: flex; align-items: center; gap: 4px; padding: 2px 6px 4px 0; font-size: 11.5px; font-weight: 600; color: var(--muted); }
.chg-pop-back { width: 24px; height: 24px; display: grid; place-items: center; border-radius: 6px; color: var(--text-2); }
.chg-pop-back:hover { background: var(--hover); }
.chg-pop-q { width: 100%; height: 28px; margin: 0 0 4px; padding: 0 8px; font-size: 12.5px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-light); color: var(--text); outline: 0; }
.chg-pop-q:focus { border-color: var(--primary); }
.chg-pop-list { max-height: 260px; overflow: auto; }
.chg-pop-i { display: block; width: 100%; text-align: left; padding: 6px 8px; border-radius: 6px; font-size: 12.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chg-pop-i:hover, .chg-pop-i:focus-visible { background: var(--hover); }
.chg-pop-i.is-on { color: var(--primary); font-weight: 600; }
.chg-countrow { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0 0 10px; }
.chg-countrow > p { margin: 0; flex: 1; min-width: 0; }
.chg-sort > summary { display: inline-flex; align-items: center; font-size: 12px; color: var(--muted); white-space: nowrap; }
.chg-sort > summary:hover, .chg-sort[open] > summary { color: var(--text); }
.chg-body { padding: 14px 24px 28px; }
.chg-list.htmx-request { opacity: .55; transition: opacity 120ms linear; }
.chg-lead { font-size: 12.5px; color: var(--text-2); }
.chg-count { font-size: 13px; }
.chg-count span { color: var(--muted); }
.chg-items { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.chg-card { display: flex; flex-direction: column; gap: 3px; width: 100%; text-align: left; padding: 9px 12px; border: 1px solid var(--border); border-radius: 8px; color: var(--text); background: transparent; font: inherit; overflow-wrap: anywhere; }
button.chg-card, a.chg-card { cursor: pointer; }
button.chg-card:hover, a.chg-card:hover, .chg-card:focus-visible { background: var(--hover); }
.chg-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.chg-what { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; min-width: 0; }
.chg-label { font-size: 13px; font-weight: 600; }
.chg-lvl, .chg-kind { font-size: 11px; color: var(--muted); padding: 1px 6px; border-radius: 999px; background: rgba(var(--tint-rgb), .06); white-space: nowrap; }
.chg-delta { flex: none; font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.chg-delta.t-up { color: var(--success); }
.chg-delta.t-down { color: var(--error); }
.chg-delta.t-flat { color: var(--muted); }
.chg-text { font-size: 12.5px; line-height: 1.4; }
.chg-text b { font-weight: 600; }
.chg-nums { font-size: 12px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.chg-meta { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 11.5px; color: var(--muted); }
.chg-reason { font-size: 11px; color: var(--text-2); padding: 1px 6px; border-radius: 999px; border: 1px solid var(--border); white-space: nowrap; }
.chg-note { font-size: 12px; color: var(--text-2); font-style: italic; line-height: 1.4; }
.chg-more { margin-top: 12px; width: 100%; padding: 8px; border: 1px solid var(--border); border-radius: 999px; font-size: 12px; color: var(--text); }
.chg-more:hover { background: var(--hover); }
.chg-empty { margin: 8px 0 0; font-size: 12.5px; color: var(--muted); }
@media (max-width: 600px) { .chg-filters, .chg-body { padding-left: 16px; padding-right: 16px; } }

/* Content appearing after a swap: a short fade, like AnimatedSwitcher */
.swap-in { animation: swapin 220ms var(--ease-out) both; }
@keyframes swapin { from { opacity: 0; } to { opacity: 1; } }
.htmx-swapping { opacity: .5; transition: opacity 120ms linear; }

/* Placeholder for the routes this prototype does not cover */
.empty-route { height: 100%; display: grid; place-items: center; text-align: center; color: var(--muted); font-size: 13px; }
.empty-route b { display: block; color: var(--text); font-size: 15px; font-weight: 600; margin-bottom: 6px; letter-spacing: 0; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

/* ── Navigation skeleton (shell.js showNavSkeleton) ─────────────────────── */
.nav-skel { position: fixed; top: 0; right: 0; bottom: 0; z-index: var(--z-nav); display: flex; flex-direction: column; background: var(--bg); animation: swapin 120ms var(--ease-out) both; }
.nav-skel .content { flex: 1; }
/* A whole page drawn ahead (shell.js showPageSkeleton): entering a tenant
   (the shell with Inicio) or leaving one (the org picker). */
.nav-skel.psk { left: 0; flex-direction: row; }
.psk-side { width: var(--sidebar-w); flex: none; padding: 16px; background: var(--surface); border-right: 1px solid var(--border); }
.psk-main { flex: 1; min-width: 0; display: flex; flex-direction: column; position: relative; }
.psk-head { display: flex; align-items: center; gap: 12px; padding: 24px 32px; border-bottom: 1px solid var(--border); }
.psk-picker { width: 100%; max-width: 960px; margin: 0 auto; padding: 32px; box-sizing: border-box; }
/* The button that started it (hx-disabled-elt), with a spinner. */
[data-sa-go].htmx-request, .sa-busy.htmx-request { position: relative; color: transparent !important; }
[data-sa-go].htmx-request::after, .sa-busy.htmx-request::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 14px; height: 14px; margin: -9px 0 0 -9px;
  border: 2px solid rgba(255, 255, 255, .9); border-right-color: transparent; border-radius: 50%; animation: saspin 700ms linear infinite;
}
.menu-item[data-sa-go].htmx-request::after { left: 24px; border-color: var(--error); border-right-color: transparent; }
.sa-ink.htmx-request::after { border-color: var(--bg); border-right-color: transparent; }
@keyframes saspin { to { transform: rotate(360deg); } }
.nav-progress.is-on { opacity: 1; }
/* The live screens' loading page: the bar sits on the page's top edge,
   inside the main column. It was fixed to the viewport, and ran under the
   sidebar too. */
.nav-progress.is-page { top: 0; }
.nsk-page { display: flex; flex-direction: column; gap: 14px; overflow: hidden; }
.nsk-row { display: flex; gap: 10px; }
.nsk-card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 0; }
.nsk-fill { flex: 1; min-height: 0; overflow: hidden; }
.nsk-line { display: flex; gap: 6%; align-items: center; height: 44px; border-bottom: 1px solid var(--border); padding: 0 8px; }
.nsk-line .sk:first-child { margin-right: auto; }
.nsk-cols { flex: 1; display: flex; gap: 20px; min-height: 0; }
.nsk-col { flex: 1; display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.nsk-side { width: 360px; flex: none; display: flex; flex-direction: column; gap: 14px; }
.nsk-grid { flex: 1; display: grid; grid-template-columns: repeat(7, 1fr); margin-top: 18px; border-top: 1px solid var(--border); }
.nsk-cell { border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); min-height: 84px; }

/* A live read that failed, drawn in place of #main (shell/_live_error.html). */
.live-error { height: 100%; display: flex; align-items: center; justify-content: center; padding: 24px 16px; box-sizing: border-box; }
.live-error-card { max-width: 420px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.live-error-card h2 { margin: 0; font-size: 20px; font-weight: 700; }
.live-error-card p { margin: 0; color: var(--text-2); line-height: 1.5; }
.live-error-icon { color: var(--error); }
.live-error-retry { margin-top: 8px; padding: 10px 18px; border-radius: 8px; background: var(--text); color: var(--bg); font-weight: 600; }

/* ── "Cargando tus datos" (shell/_loader.html): the app's first load only,
   on the boot page (a typed or opened URL). Screens keep their shimmer. */
.ld { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; z-index: 5;
  animation: ld-in 260ms var(--ease-out-cubic, ease-out) both; }
.ld-card { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 18px 28px 16px;
  background: color-mix(in srgb, var(--surface) 90%, transparent); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 6px 24px rgba(0, 0, 0, .08); }
.ld-fig { width: 96px; height: 40px; overflow: visible; }
.ld-today { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 3; }
.ld-hist, .ld-fcst { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ld-hist { stroke: var(--text-2); }
.ld-fcst { stroke: var(--primary); stroke-dasharray: 42; stroke-dashoffset: 42; animation: ld-draw 2.4s var(--ease-in-out, ease-in-out) infinite; }
.ld-band { fill: var(--primary); opacity: 0; animation: ld-band 2.4s ease-in-out infinite; }
.ld-dot { fill: var(--primary); transform-box: fill-box; transform-origin: center; animation: ld-dot 2.4s ease-in-out infinite; }
.ld-title { font-size: 14px; font-weight: 500; color: var(--text); }
.ld-msgs { display: grid; font-size: 12px; color: var(--muted); min-height: 16px; }
.ld-msgs > span { grid-area: 1 / 1; text-align: center; opacity: 0; animation: ld-msg 9.6s linear infinite; }
.ld-msgs > span:nth-child(2) { animation-delay: 2.4s; }
.ld-msgs > span:nth-child(3) { animation-delay: 4.8s; }
.ld-msgs > span:nth-child(4) { animation-delay: 7.2s; }
@keyframes ld-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes ld-draw { 0% { stroke-dashoffset: 42; } 55%, 85% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: -42; } }
@keyframes ld-band { 0%, 20% { opacity: 0; } 55%, 85% { opacity: .16; } 100% { opacity: 0; } }
@keyframes ld-dot { 0%, 100% { transform: scale(1); } 15% { transform: scale(1.45); } 30% { transform: scale(1); } }
@keyframes ld-msg { 0% { opacity: 0; transform: translateY(3px); } 3%, 22% { opacity: 1; transform: none; } 25%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ld, .ld-fcst, .ld-band, .ld-dot, .ld-msgs > span { animation: none; }
  .ld-fcst { stroke-dashoffset: 0; }
  .ld-band { opacity: .16; }
  .ld-msgs > span:first-child { opacity: 1; }
}

/* The boot page (shell/boot.html): the sidebar's head and a shimmer, the loader in the middle. */
body.boot { margin: 0; height: calc(100dvh / var(--zoom)); display: grid; grid-template-columns: var(--sidebar-w) 1fr; background: var(--bg); }
.boot-side { border-right: 1px solid var(--border); background: var(--surface); }
.boot-rows { display: flex; flex-direction: column; gap: 22px; padding: 18px 20px; }
.boot-rows i { display: block; height: 12px; }
.boot-rows i:nth-child(odd) { width: 70%; }
.boot-main { position: relative; }
@media (max-width: 767.98px) { body.boot { grid-template-columns: 1fr; } .boot-side { display: none; } }
