/* =============================================================================
   Reusable Deployer — Postman deployment console (light theme, 0 dependency)
   Direction: faithful to the ALL — Accor Live Limitless site (https://all.accor.com).
   White background, deep navy "Stratos" #050033, electric-blue accents, gold touch.
   Pill-shaped buttons (navy -> indigo gradient CTA), clear semantic states.
   Monospace identifiers. System fonts only (no network resource).
   ========================================================================== */

:root {
  /* Backgrounds & surfaces (all light) */
  --bg:        #ffffff;   /* page background */
  --panel:     #ffffff;   /* panels / cards */
  --surface:   #f7f9fb;   /* contained surface (mid) */
  --surface-2: #f2f4f6;   /* surface hover */
  --surface-3: #eceef0;   /* recessed surface */

  /* Rules / borders */
  --line:      #e6e8ea;   /* thin rule */
  --line-2:    #d9dadc;   /* bottom outline */
  --line-3:    #c4c7c9;   /* strong outline */

  /* Text */
  --fg:        #232136;   /* headings / strong (on-surface-hi) */
  --body:      #3e3d48;   /* default body */
  --muted:     #5e5b73;   /* subdued (on-surface-low) */
  --faint:     #767676;   /* very subdued — min AA 4.5:1 on white */

  /* Brand — deep navy "Stratos", Accor's signature color */
  --primary:   #050033;   /* THE Accor color */
  --stratos-1: #1f1b4b;
  --stratos-2: #38326c;
  --stratos-3: #524f81;
  --stratos-4: #8e8bc1;
  --stratos-5: #b7b3ec;
  --stratos-6: #d1ccff;
  --stratos-7: #e3dfff;
  --stratos-8: #ede8ff;
  --stratos-9: #f6f2ff;

  /* Accent & links */
  --accent:        #2d4cd5;   /* electric blue: focus, selection, active tab */
  --accent-hover:  #183cc7;
  --link:          #0051ae;
  --link-hover:    #2a71db;

  /* Gold — premium accent, use sparingly */
  --gold:    #af913a;
  --gold-2:  #c4a963;
  --gold-3:  #d7bf7a;

  /* Semantic states (light theme) */
  --ok:        #006a53;   --ok-bg:   #e6f3eb;   --ok-line:   #4ecda8;
  --err:       #be003c;   --err-bg:  #ffecec;   --err-line:  #ffb2b8;
  --err-hover: #9e0031;   --err-pressed: #890029;
  --warn:      #564500;   --warn-bg: #fff6e4;   --warn-line: #f2d166;
  --info:      #2d4cd5;   --info-bg: #e8edff;   --info-line: #b7b3ec;

  --font: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Code", "Segoe UI Mono", Consolas, monospace;

  --radius: 14px;
  --radius-sm: 10px;
  --pill: 60px;
  --shadow:      0 1px 2px rgba(7,5,24,.06);
  --shadow-lg:   0 10px 30px -18px rgba(7,5,24,.22);
  --ring: 0 0 0 3px rgba(45,76,213,.30);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font: 14px/1.55 var(--font);
  color: var(--body);
  background:
    radial-gradient(1100px 480px at 12% -10%, rgba(82,79,129,.06), transparent 60%),
    radial-gradient(900px 520px at 100% 0%, rgba(45,76,213,.04), transparent 55%),
    var(--bg);
  background-attachment: fixed;
  min-height: 100%;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ----- Header ---------------------------------------------------------------- */
header {
  position: sticky; top: 0; z-index: 20;
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px;
  padding: 14px 22px;
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(7,5,24,.02), var(--shadow-lg);
}
/* Top accent rule: thin, subtle navy -> indigo gradient */
header::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, var(--primary), var(--stratos-3) 60%, transparent);
  opacity: .9;
}

.brand { display: flex; align-items: center; gap: 12px; margin-right: auto; }

/* WCC logo (pixel-art orca) */
.brand .brand-logo { height: 38px; width: auto; flex: 0 0 auto; display: block; }
.brand h1 { font-size: 15px; font-weight: 700; letter-spacing: .2px; margin: 0; color: var(--fg); }
.brand-sub {
  margin: 1px 0 0; font-size: 11px; color: var(--muted);
  letter-spacing: .2px;
}

.token { display: flex; align-items: center; gap: 10px; }
#token {
  width: 280px; max-width: 44vw;
  font-family: var(--mono); font-size: 12.5px; letter-spacing: .3px;
}

/* Signed-in account: Postman profile (avatar + full name) + badge + button */
.account { display: flex; align-items: center; gap: 12px; }
.user { display: inline-flex; align-items: center; gap: 9px; }
.user[hidden] { display: none; }
.avatar {
  width: 30px; height: 30px; flex: 0 0 auto; border-radius: 50%; overflow: hidden;
  display: inline-grid; place-items: center;
  background: linear-gradient(150deg, var(--stratos-2), var(--primary));
  color: #f9f9ff; font-size: 11px; font-weight: 700; letter-spacing: .3px;
  box-shadow: 0 0 0 1px var(--line-2), inset 0 1px 0 rgba(255,255,255,.15);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.user-name { font-weight: 600; font-size: 13px; color: var(--fg); white-space: nowrap; }

nav { display: flex; gap: 6px; }
.tab {
  position: relative; background: transparent; border: 1px solid transparent;
  color: var(--muted); border-radius: var(--radius-sm);
  padding: 7px 16px; cursor: pointer; font-weight: 600;
  letter-spacing: .1px; font-size: 13px;
  transition: color .15s, background .15s, border-color .15s;
}
.tab:hover { color: var(--fg); background: var(--surface-2); }
.tab.active { color: var(--accent); background: var(--info-bg); }
.tab.active::after {
  content: ""; position: absolute; left: 14px; right: 14px; bottom: -1px; height: 2px;
  background: var(--accent); border-radius: 2px;
}

/* ----- Layout ---------------------------------------------------------------- */
main { padding: 30px 22px 56px; max-width: 1040px; margin: 0 auto; }

h2 {
  font-size: 22px; font-weight: 700; letter-spacing: -.2px; margin: 0 0 4px; color: var(--fg);
}
h2 + .muted { margin-top: 0; margin-bottom: 22px; }
h3 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 1.4px;
  color: var(--muted); font-weight: 700; margin: 0 0 12px;
}
h4 { font-size: 14px; margin: 0 0 8px; font-weight: 700; color: var(--fg); }
.muted { color: var(--muted); }

/* staggered entrance */
#view > * { animation: rise .42s cubic-bezier(.2,.7,.2,1) both; }
#view > *:nth-child(1){ animation-delay: .02s; }
#view > *:nth-child(2){ animation-delay: .07s; }
#view > *:nth-child(3){ animation-delay: .12s; }
#view > *:nth-child(4){ animation-delay: .17s; }
#view > *:nth-child(n+5){ animation-delay: .2s; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ----- Inputs ---------------------------------------------------------------- */
input, button { font: inherit; }
input[type="text"], input[type="password"], input:not([type]) {
  background: #ffffff; border: 1px solid var(--line-2); color: var(--fg);
  border-radius: var(--radius-sm); padding: 9px 12px; transition: border-color .15s, box-shadow .15s;
}
input::placeholder { color: var(--faint); }
input:focus-visible { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
input:disabled { opacity: .55; cursor: not-allowed; background: var(--surface); }

input[type="checkbox"] {
  width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex: 0 0 auto;
}

/* ----- Table (Targets screen) ------------------------------------------------- */
table {
  width: 100%; border-collapse: separate; border-spacing: 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow-lg);
}
thead th {
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--muted); font-weight: 700; padding: 12px 14px;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
tbody td { padding: 12px 14px; border-bottom: 1px solid var(--line); vertical-align: middle; color: var(--body); }
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background .12s; }
tbody tr:hover { background: var(--surface); }
td:nth-child(2) { font-weight: 600; color: var(--fg); }
td.muted, td:last-child { font-family: var(--mono); font-size: 12px; color: var(--faint); }
input.tname { width: 100%; max-width: 260px; }

/* ----- Buttons --------------------------------------------------------------- */
/* Main Accor CTA: pill shape, navy -> indigo gradient, sentence case */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  background: linear-gradient(75deg, var(--primary) 0%, var(--stratos-3) 100%);
  color: #f9f9ff; border: 1px solid var(--stratos-5); border-radius: var(--pill);
  padding: 10px 22px; font-weight: 600; letter-spacing: .1px;
  font-size: 13.5px; cursor: pointer;
  box-shadow: var(--shadow); transition: background .18s, color .18s, transform .12s, box-shadow .18s;
}
/* Accor signature hover: powder pink -> lavender, indigo text */
.btn:hover {
  background: linear-gradient(75deg, #ffd4ea 0%, #d6d3ff 100%);
  color: var(--stratos-1); border-color: var(--stratos-5);
  box-shadow: 0 10px 24px -12px rgba(7,5,24,.35);
}
.btn:active { background: var(--primary); color: #f9f9ff; transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: var(--ring); }
.btn:disabled {
  background: linear-gradient(75deg, var(--primary) 0%, var(--stratos-3) 100%);
  color: #f9f9ff; opacity: .5; filter: saturate(.6); cursor: progress; box-shadow: none;
}
/* Secondary button: very light blue, outlined, pill */
.btn.secondary {
  background: var(--info-bg); color: var(--stratos-1); border: 1px solid var(--stratos-5); box-shadow: none;
}
.btn.secondary:hover {
  background: linear-gradient(75deg, #fff0f4, #e9e5ff); color: var(--stratos-1); border-color: var(--stratos-5);
}

/* ----- Badges (mono + dot) ----------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 11.5px; font-weight: 600; letter-spacing: .2px;
  color: var(--muted); background: var(--surface);
  border: 1px solid var(--line-2); border-radius: 999px; padding: 3px 11px; white-space: nowrap;
}
.badge::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--faint);
}
.badge.ok  { color: var(--ok);  border-color: var(--ok-line);  background: var(--ok-bg); }
.badge.ok::before  { background: var(--ok); }
.badge.err { color: var(--err); border-color: var(--err-line); background: var(--err-bg); }
.badge.err::before { background: var(--err); }

/* Multi-line error message (e.g. duplicate folders with their URLs):
   overrides the badge's nowrap/flex to allow line wrapping. */
.badge:has(.badge-msg) { align-items: flex-start; }
.badge-msg { white-space: normal; overflow-wrap: anywhere; line-height: 1.7; }
.badge-msg a { color: inherit; text-decoration: underline; }

/* "source" tag in the table: premium gold touch */
td .badge { color: var(--warn); border-color: var(--gold-3); background: #faf4e6; }
td .badge::before { background: var(--gold); }

/* ----- Deploy screen: columns + selections ------------------------------------ */
.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 8px; }
.cols section {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow-lg);
}
.row {
  display: flex; gap: 10px; align-items: center; padding: 8px 10px; margin: 2px -10px;
  border-radius: var(--radius-sm); transition: background .12s;
}
.cols .row:hover { background: var(--surface); }
.row b { font-weight: 600; color: var(--fg); }
.row .muted { font-family: var(--mono); font-size: 12px; }

/* Scan / Deploy actions */
.actions { display: flex; gap: 12px; align-items: center; margin: 16px 0; }

/* Deploy button: real action (apply), solid danger red, pill shape kept */
.btn.danger {
  background: var(--err); color: #ffffff; border-color: var(--err-line);
  box-shadow: 0 8px 22px -12px rgba(190,0,60,.5);
}
.btn.danger:hover { background: var(--err-hover); color: #ffffff; border-color: var(--err-line); }
.btn.danger:active { background: var(--err-pressed); color: #ffffff; }
/* Deploy disabled until a scan has run */
.btn.danger:disabled {
  background: var(--surface-3); color: var(--faint); border-color: var(--line-2);
  opacity: 1; filter: none; cursor: not-allowed; box-shadow: none;
}

/* ----- Deployment report ------------------------------------------------------- */
#report { margin-top: 20px; }
#report:empty { display: none; }

/* banner (first .badge in the report) */
#report > .badge {
  display: flex; width: 100%; justify-content: flex-start;
  font-size: 12.5px; padding: 11px 16px; border-radius: var(--radius); margin: 0 0 14px;
}
#report > .badge:not(.ok):not(.err) {
  color: var(--info); border-color: var(--info-line); background: var(--info-bg);
}
#report > .badge:not(.ok):not(.err)::before { background: var(--info); }
#report > .muted { margin-top: 14px; font-family: var(--mono); font-size: 12px; }

.tcard, .ccard {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 16px; margin: 12px 0; background: var(--panel);
}
.tcard { box-shadow: var(--shadow-lg); border-left: 3px solid var(--stratos-5); }
.tcard > h4 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tcard > h4 .muted { font-family: var(--mono); font-size: 12px; font-weight: 400; }
.tcard:has(.badge.err) { border-left-color: var(--err); }

.ccard {
  background: var(--surface); margin: 10px 0; border-left: 3px solid var(--line-3);
  display: flex; flex-direction: column; gap: 2px;
}
.ccard > b { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; color: var(--fg); }
.ccard:has(.badge.ok)  { border-left-color: var(--ok); }
.ccard:has(.badge.err) { border-left-color: var(--err); }
.ccard ul { margin: 8px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.ccard li { color: var(--body); }
.ccard li.muted { color: var(--muted); }
.ccard li b { font-weight: 600; color: var(--fg); }
/* Merge notes attached to their marked folder (nested under the match). */
.ccard ul.subnotes { margin: 3px 0 2px; padding-left: 14px; border-left: 2px solid var(--line-3); gap: 2px; }

/* Clickable folder path (to Postman) in the report */
.folder-link { color: var(--link); text-decoration: none; font-weight: 600; word-break: break-word; }
.folder-link:hover { color: var(--link-hover); text-decoration: underline; }
/* Warning: target has more requests than the source (deleted on deploy) */
.warn-note { color: var(--err); font-weight: 600; margin-left: 4px; }

/* ----- Live deployment log ----------------------------------------------------- */
.runlabel { position: relative; padding-left: 18px; margin: 0 0 12px; }
.runlabel::before {
  content: ""; position: absolute; left: 0; top: 6px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 3px rgba(45,76,213,.18); animation: pulse 1.1s ease-in-out infinite;
}
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

/* Container: scrolling block. NB: no flex-column here on purpose — with many
   children, flex would shrink each row (flex-shrink:1) to fit the max height
   instead of scrolling, which crushes and overlaps the text. */
.livelog {
  font-family: var(--mono); font-size: 12.5px; line-height: 1.65;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 14px; max-height: 340px; overflow-y: auto; overflow-x: hidden;
  display: block;
  /* Tree rhythm: no per-level indent here (handled further below) */
  --ll-indent: 18px;
}
/* One line = natural height, never squeezed by the container. */
.ll {
  display: flex; align-items: baseline; gap: 8px;
  min-width: 0;                 /* allows ellipsis in a flex context */
  color: var(--muted);
  padding-block: 1px;           /* slight leading, reads like a console */
}
/* The label may truncate; the counter (.dim) always stays visible. */
.ll > .ll-text {
  flex: 1 1 auto; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ll .dim { flex: 0 0 auto; opacity: .65; }   /* counter (k/N) pinned to the right */

/* Target rows: strong titles, breathing room above. */
.ll.head { color: var(--fg); font-weight: 600; margin-top: 8px; }
.ll.head:first-child { margin-top: 0; }

/* Hierarchical indent = tree structure (leading glyphs aligned). */
.ll.sub  { padding-left: var(--ll-indent); }
.ll.sub2 { padding-left: calc(var(--ll-indent) * 2); }

/* Semantic states (readable on light background). */
.ll.ok  { color: var(--ok); }
.ll.err { color: var(--err); }

/* Thin, discreet scrollbar. */
.livelog { scrollbar-width: thin; scrollbar-color: var(--line-3) transparent; }
.livelog::-webkit-scrollbar { width: 9px; }
.livelog::-webkit-scrollbar-track { background: transparent; }
.livelog::-webkit-scrollbar-thumb {
  background: var(--line-3); border-radius: 999px;
  border: 2px solid var(--surface);   /* visual margin around the thumb */
}
.livelog::-webkit-scrollbar-thumb:hover { background: var(--stratos-4); }

/* ----- Toast ------------------------------------------------------------------- */
.toast {
  position: fixed; bottom: 22px; right: 22px; z-index: 50;
  display: flex; align-items: center; gap: 10px;
  background: #ffffff; border: 1px solid var(--line-2); color: var(--fg);
  padding: 12px 16px; border-radius: var(--radius); box-shadow: var(--shadow-lg);
  border-left: 3px solid var(--accent);
  animation: toast-in .26s cubic-bezier(.2,.8,.2,1) both;
}
.toast[hidden] { display: none; }
.toast.ok  { border-left-color: var(--ok); }
.toast.err { border-left-color: var(--err); }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }

/* ----- Footer -------------------------------------------------------------------- */
.appfoot {
  max-width: 1040px; margin: 0 auto; padding: 0 22px 30px;
  display: flex; gap: 10px; align-items: center;
  font-family: var(--mono); font-size: 11.5px; color: var(--faint);
}
.appfoot .dot { opacity: .7; color: var(--stratos-4); }

/* ----- Sign-in gate (centered token entry) --------------------------------------- */
/* Locked state: until the token is verified, only the gate is visible. */
body.locked header,
body.locked main,
body.locked .appfoot { display: none; }
body.unlocked #gate { display: none; }

.gate {
  position: fixed; inset: 0; z-index: 40;
  display: grid; place-items: center; padding: 24px;
  background:
    radial-gradient(1100px 480px at 12% -10%, rgba(82,79,129,.10), transparent 60%),
    radial-gradient(900px 520px at 100% 0%, rgba(45,76,213,.06), transparent 55%),
    var(--bg);
}
.gate-card {
  width: 100%; max-width: 420px;
  display: flex; flex-direction: column; gap: 12px; text-align: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 34px 30px;
  animation: rise .5s cubic-bezier(.2,.7,.2,1) both;
}
/* Enlarged WCC logo on the sign-in screen */
.gate-card .gate-logo { height: 84px; width: auto; margin: 0 auto 8px; display: block; }
.gate-title { font-size: 21px; font-weight: 700; letter-spacing: -.2px; margin: 0; color: var(--fg); }
.gate-sub { margin: 0 0 8px; color: var(--muted); font-size: 13px; }
.gate-label {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--muted); font-weight: 700; margin-top: 6px;
}
.gate-card #token {
  width: 100%; max-width: none; text-align: left;
  font-family: var(--mono); font-size: 13px; letter-spacing: .3px; padding: 11px 13px;
}
.gate-card #gate-submit { width: 100%; justify-content: center; margin-top: 4px; padding: 11px 22px; }
.gate-msg { margin: 2px 0 0; font-size: 12.5px; }
.gate-msg.err  { color: var(--err); }
.gate-msg.info { color: var(--muted); }
.gate-msg[hidden] { display: none; }
.gate-hint { margin: 8px 0 0; font-size: 11.5px; color: var(--faint); }

/* ----- Responsive ---------------------------------------------------------------- */
@media (max-width: 760px) {
  .cols { grid-template-columns: 1fr; }
  header { gap: 10px 14px; }
  .brand { margin-right: 0; width: 100%; }
  .account { width: 100%; flex-wrap: wrap; }
  .user { margin-right: auto; }
  nav { width: 100%; }
  .tab { flex: 1; text-align: center; }
  main { padding: 22px 16px 44px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  /* Exceptions: these two convey functional timing (how long you've held the
     button, whether a scan is still running), not decoration. Silently
     collapsing them to 0ms would make the hold-to-confirm gesture impossible
     to gauge and the scan look frozen, even though nothing is broken. */
  .progress.indeterminate .progress-fill { animation-duration: 1.3s !important; }
  .progress-fill.active { animation-duration: .7s !important; }
  .long-press.holding .lp-fill { transition-duration: 3000ms !important; }
}

/* ----- Backup gate (serverless apply) --------------------------------------------- */
.backup-gate {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 20px; display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px;
}
.backup-gate .row { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.backup-gate .actions { display: flex; gap: 10px; margin-top: 4px; }

/* ----- "Select all / deselect all" toggles ---------------------------------------- */
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.sel-toggle {
  background: none; border: none; padding: 0; font: inherit; font-size: 12px; font-weight: 600;
  color: var(--link); cursor: pointer; text-decoration: none;
}
.sel-toggle:hover { color: var(--link-hover); text-decoration: underline; }
.sel-toggle-group { display: flex; gap: 8px; align-items: baseline; }
.sel-toggle-group .dot { color: var(--faint); }

/* ----- Spinner (button busy state) ------------------------------------------------ */
.spinner {
  width: 14px; height: 14px; flex: 0 0 auto; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.4); border-top-color: #fff;
  animation: spin .7s linear infinite;
}
.btn.secondary .spinner, .sel-toggle .spinner { border-color: rgba(45,76,213,.25); border-top-color: var(--accent); }
@keyframes spin { to { transform: rotate(360deg); } }

/* Live status pill: a soft pulse on the connected dot signals "alive", not stale. */
#conn.ok::before { animation: pulse-soft 2.2s ease-in-out infinite; }
@keyframes pulse-soft { 0%, 100% { box-shadow: 0 0 0 0 rgba(0,106,83,.35); } 50% { box-shadow: 0 0 0 4px rgba(0,106,83,0); } }

/* ----- Skeleton loader (tab switches) ---------------------------------------------- */
.skeleton { display: flex; flex-direction: column; gap: 10px; padding: 2px 0; }
.skeleton-row { display: flex; gap: 14px; align-items: center; }
.skeleton-bar {
  height: 14px; border-radius: 7px;
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ----- Progress bar (scan/deploy live status) -------------------------------------- */
.progress-wrap { margin: 10px 0 14px; }
.progress-label {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--mono); font-size: 11.5px; color: var(--muted); margin-bottom: 6px;
}
.progress {
  position: relative; height: 10px; border-radius: 999px; overflow: hidden;
  background: var(--surface-3); box-shadow: inset 0 1px 2px rgba(7,5,24,.06);
}
.progress-fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--primary), var(--accent));
  transition: width .3s ease;
}
.progress.indeterminate .progress-fill {
  width: 40% !important; position: absolute; top: 0; bottom: 0;
  animation: indeterminate 1.3s ease-in-out infinite;
}
@keyframes indeterminate {
  0%   { left: -40%; }
  100% { left: 100%; }
}
/* Marching-stripe overlay on the currently-writing item: the fill's exact
   width can sit still for a few seconds while a single PUT is in flight —
   this keeps the bar visibly "alive" instead of looking frozen. */
.progress-fill.active {
  background-image:
    linear-gradient(90deg, var(--primary), var(--accent)),
    repeating-linear-gradient(45deg, rgba(255,255,255,.45) 0 6px, transparent 6px 12px);
  animation: stripes .7s linear infinite;
}
@keyframes stripes { from { background-position: 0 0, 0 0; } to { background-position: 0 0, 17px 0; } }

/* ----- Long-press confirmation (replaces native confirm() for critical actions) ---- */
/* A single deliberate 3-second hold instead of a click-through browser dialog:
   harder to trigger by accident, and the fill animation itself is the feedback. */
.long-press { position: relative; overflow: hidden; isolation: isolate; }
.long-press .lp-fill {
  position: absolute; inset: 0; width: 0%;
  background: rgba(255,255,255,.32); z-index: 0;
  pointer-events: none;
}
.long-press .lp-label { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 8px; }
.long-press.holding { cursor: progress; }
.long-press .lp-label::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; opacity: .55;
}
.long-press.holding .lp-label::before { animation: pulse-soft-fg .6s ease-in-out infinite; }
@keyframes pulse-soft-fg { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }

/* ----- Quick "saved" acknowledgment (Targets tab) ----------------------------------- */
.saved-flash { animation: saved-pulse .9s ease both; }
@keyframes saved-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(0,106,83,.45); }
  40%  { box-shadow: 0 0 0 6px rgba(0,106,83,0); }
  100% { box-shadow: 0 0 0 0 rgba(0,106,83,0); }
}

/* ----- Status transitions on report cards ------------------------------------------ */
.tcard, .ccard { animation: rise .32s cubic-bezier(.2,.7,.2,1) both; }
.badge.ok, .badge.err { animation: pop .22s cubic-bezier(.3,1.4,.4,1) both; }
@keyframes pop { from { transform: scale(.85); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ----- Modal (hold-to-confirm dialogs, e.g. rollback) ------------------------------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(5,0,51,.35); backdrop-filter: blur(2px);
  display: grid; place-items: center; padding: 20px;
  animation: fade-in .18s ease both;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
.modal-card {
  width: 100%; max-width: 420px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 22px 24px;
  animation: rise .28s cubic-bezier(.2,.7,.2,1) both;
}
.modal-card h3 { margin: 0 0 10px; font-size: 16px; color: var(--fg); }
.modal-msg { font-size: 13.5px; color: var(--body); line-height: 1.6; }
.modal-card .actions { margin-top: 18px; }
