/* =========================================================================
   views/leads-responsive.css — Leads responsive (mobile sheets, standard sheet header, address field, Leads Settings drawer)
   Split from the old monolithic styles/views.css. LOAD ORDER MATTERS:
   the <link> order in Magnet CRM.html / Client App.html reproduces the
   original file order, so the cascade is unchanged — add new rules to the
   matching feature file, not the end of the list.
   ========================================================================= */
/* ============ LEADS TABLE — responsive ============ */
/* desktop + tablet: keep the full table but scroll it horizontally once the
   columns no longer fit, so they stay readable instead of crushing/wrapping.
   --lead-min-w is set per render from the visible columns (app.js). */
@media (min-width: 641px) {
  .table-card { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .table-card .ctable { min-width: var(--lead-min-w, 820px); }
}
/* mobile: a minimal card — business name, relative time, status. */
@media (max-width: 640px) {
  .table-wrap {
    padding: var(--space-4) max(var(--space-4), var(--safe-left)) 0
             max(var(--space-4), var(--safe-right));
  }
  .table-card { border: none; background: none; box-shadow: none; overflow: visible; border-radius: 0; }
  .table-card .ctable { min-width: 0; table-layout: auto; }
  .ctable colgroup, .ctable thead { display: none; }
  .ctable, .ctable tbody { display: block; }
  .ctable tbody tr {
    display: flex; flex-wrap: wrap; align-items: center;
    column-gap: var(--space-3); row-gap: var(--space-2);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-4);
    margin-bottom: var(--space-3);
    position: relative;   /* anchor for the bottom-right star */
  }
  /* show the lead's identity (name + avatar), relative time and status — plus
     the business name as a subline when the form captures one. Works for client
     forms (name only) and admin forms (business + contact name) alike. */
  .ctable tbody td { display: none; height: auto; padding: 0; border: none; }
  .ctable tbody td::before { display: none; }
  .ctable tbody td.name-cell,
  .ctable tbody td.business-cell,
  .ctable tbody td.date-cell,
  .ctable tbody td.status-td { display: flex; align-items: center; }
  /* Gmail-style star, bottom-right of the card. Absolute-positioned so it can't
     fight the flex row order; the bottom-right corner of the card is empty
     because the status pill is short + left-aligned, so no overlap. */
  .ctable tbody td.col-star {
    display: block;
    position: absolute;
    right: var(--space-3); bottom: var(--space-3);
    padding: 0; text-align: right;
  }
  .ctable tbody td.col-star .lead-star { width: 32px; height: 32px; }
  .ctable tbody td.col-star .lead-star svg { width: 20px; height: 20px; }
  .ctable td.name-cell { order: 1; flex: 1 1 auto; min-width: 0; }
  .ctable td.name-cell .contact-cell { min-width: 0; max-width: 100%; }
  .ctable td.name-cell .name { font-size: var(--text-base); font-weight: var(--fw-bold); color: var(--text-strong); }
  .ctable td.date-cell { order: 2; margin-left: auto; flex: 0 0 auto; font-size: var(--text-sm); color: var(--text-soft); }
  .ctable td.date-cell .date-abs { display: none; }
  .ctable td.date-cell .date-rel { display: inline; }
  .ctable td.business-cell { order: 3; flex: 0 0 100%; font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-muted); }
  .ctable td.status-td { order: 4; flex: 0 0 100%; overflow: visible; }
  /* status dropdown styled like the lead-detail view (bordered pill) */
  .ctable td.status-td .stage-trigger {
    height: 30px; padding: 0 7px 0 4px;
    border: 1px solid var(--border); border-radius: var(--radius-full);
    background: var(--surface);
  }
  .ctable td.status-td .stage-trigger .stage { padding-left: 6px; }
  /* native press-IN feedback on tap (scale down) rather than a hover-like lift */
  .ctable tbody tr:active {
    background: var(--surface-hover);
    border-color: var(--border-strong);
    transform: scale(0.985);
  }
  .kcard:active {
    box-shadow: var(--shadow-sm);
    border-color: var(--border-strong);
    transform: scale(0.97);
  }
}

@media (max-width: 640px) {
  .drawer { width: 100%; }
  /* lead detail → bottom sheet */
  .drawer.sheet {
    position: fixed; inset: auto 0 0 0; top: auto;
    /* Stop short of the top so the iPhone notch / status bar always has
       breathing room above the sheet: at most 90dvh, and never closer than
       safe-top + 14px to the screen edge. */
    width: 100%;
    height: min(90dvh, calc(100dvh - var(--safe-top) - 14px));
    max-height: min(90dvh, calc(100dvh - var(--safe-top) - 14px));
    border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
    /* translate3d (not translateY) keeps the sheet on ONE GPU layer from the
       off-screen start through the slide — WebKit otherwise re-rasterizes when it
       promotes the layer mid-animation, which reads as a stutter / wrong start. */
    transform: translate3d(0, 100%, 0);
    /* The drawer sheets (esp. Lead Detail) are the tallest/heaviest. On WebKit a
       very front-loaded curve (--ease-enter) put almost all the travel in the
       first ~50ms — exactly the frames WebKit drops while rasterizing the big
       layer — so the rise looked invisible and only the tail showed. A slightly
       longer iOS decelerate spreads the travel across frames that actually render.

       ONLY transform is transitioned — NOT height. On iOS the sheet's computed
       height (dvh / safe-area) settles a frame or two after open; if `height` were
       in the transition that settle would ANIMATE, so the sheet looked like it
       "grew up to height" instead of sliding in at full size (localhost's dvh is
       stable, so it never showed there). The peek → full-screen expansion gets its
       own height/radius transition inline (drawerShell.expand). Close + drag also
       set their own inline transitions.

       Curve: a GENTLE-START ease (cubic-bezier(.4,0,.2,1)), not the front-loaded
       --ease-ios. On a 60Hz phone the very first frame of the open is expensive to
       rasterize (~40-63ms — measured), and the animation clock keeps running during
       it. With a front-loaded curve that one slow frame lands the sheet ~45% up, so
       it "doesn't start at the bottom." A gentle start covers far less ground in
       that first frame, so even when it's dropped the sheet still begins near the
       bottom and rises — matching localhost. (Localhost never showed this: at
       160fps the first frame is ~7ms and advances almost nothing.) */
    transition: transform 360ms cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: var(--shadow-lg);
  }
  .drawer.sheet.show { transform: translate3d(0, 0, 0); }
  /* peek preview (TickTick style) — a bit over half the viewport; any tap
     or upward swipe removes .peek and the sheet slides up to full height */
  .drawer.sheet.peek { height: 62dvh; }
  /* the task sheet peeks a bit higher so the title + first lines are visible */
  .task-drawer.sheet.peek { height: 74dvh; }
  /* expanded task sheet goes truly FULL SCREEN: edge-to-edge, square corners,
     content clearing the notch — one animation with the back-button slide-in */
  .task-drawer.sheet:not(.peek) {
    height: 100dvh; max-height: 100dvh;
    border-radius: 0;
    padding-top: var(--safe-top);
  }
  /* back (close) button — 0-width while peeking; expansion slides it in from
     the left, pushing the Inbox chip right as part of the same animation */
  .task-drawer .td-back {
    width: 0; opacity: 0; transform: translateX(-12px);
    margin-right: 0; padding: 0; overflow: hidden; flex-shrink: 0;
    height: 40px; border-radius: var(--radius-full);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-field); color: var(--text-strong);
    pointer-events: none;
    transition: width var(--dur-slow) var(--ease), opacity var(--dur-slow) var(--ease),
                transform var(--dur-slow) var(--ease), margin-right var(--dur-slow) var(--ease);
  }
  .task-drawer .td-back svg { width: 19px; height: 19px; flex-shrink: 0; }
  .task-drawer.sheet:not(.peek) .td-back {
    width: 40px; opacity: 1; transform: none;
    margin-right: var(--space-2); pointer-events: auto;
  }
  .drawer.sheet.peek .td-scroll { overflow: hidden; }
  /* the whole preview is one gesture surface — no inner scrolling until expanded */
  .drawer.sheet.peek .drawer-body, .drawer.sheet.peek .drawer-sched,
  .drawer.sheet.peek .td-scroll { touch-action: none; }
  /* (grab-handle pill removed — drag-to-dismiss still works from the top
     chrome; a small inset keeps the header off the rounded edge) */
  .drawer.sheet { padding-top: 8px; }
  /* ===== Standard sheet header (see .sheet-head standard below) =========
     X (left) · centered title · tick (right). Replaces the old grab-handle +
     floating translucent X for every drawer-based bottom sheet. */
  .drawer.sheet .drawer-head {
    position: relative; justify-content: flex-start;
    /* the sheet's 8px top inset + 4px here = 12px above the buttons, equal to
       the 12px below and the 12px sides — header reads perfectly centred */
    height: auto; min-height: 56px; padding: 4px 12px 12px;
    gap: 8px; touch-action: none;
  }
  /* the whole sheet's top chrome (grab handle + header + summary subhead) is a
     drag-to-dismiss surface — the grab handle's touch belongs to the sheet box,
     so the sheet itself must opt out of scroll-hijack; only the body + schedule
     panel pan. (Interactive controls opt out of the drag in JS.) */
  .drawer.sheet { touch-action: none; }
  /* the scrollers declare pan-y so a vertical drag SCROLLS (incl. over a focused
     contenteditable, which on iOS otherwise grabs the drag for caret/selection and
     blocks scrolling) while horizontal stays available for the JS back-swipe.
     .td-scroll was missing this — it's why the task notes wouldn't scroll with the
     keyboard up. (peek mode overrides to none above: the whole sheet drags.) */
  .drawer.sheet .drawer-body, .drawer.sheet .drawer-sched, .drawer.sheet .td-scroll { touch-action: pan-y; }
  .drawer.sheet .drawer-head .drawer-title {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    max-width: 58%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    pointer-events: none;
  }
  .drawer.sheet .drawer-close {
    width: 44px; height: 44px; border-radius: var(--radius-full);
    background: var(--surface-field); border: none; color: var(--text-strong);
  }
  @media (hover: hover) and (pointer: fine) {
    .drawer.sheet .drawer-close:hover { background: var(--border); }
  }
  .drawer.sheet .drawer-close svg { width: 18px; height: 18px; }
  /* primary confirm tick (right) — only meaningful inside a sheet */
  .drawer-done { display: none; }
  .drawer.sheet .drawer-done {
    display: inline-flex; align-items: center; justify-content: center;
    margin-left: auto; flex-shrink: 0;
    width: 44px; height: 44px; border-radius: var(--radius-full);
    background: var(--primary-600); color: var(--on-primary);
  }
  @media (hover: hover) and (pointer: fine) {
    .drawer.sheet .drawer-done:hover { background: var(--primary-600); }
  }
  .drawer.sheet .drawer-done svg { width: 19px; height: 19px; }
  /* Drawer V2's pinned footer (Call / Text / Schedule) now carries the primary
     actions — in the native iOS WebView it must clear the home indicator, or the
     Schedule CTA sits under it. The portal footer (Dead Lead) benefits too. */
  .drawer.sheet .drawer-foot { padding-bottom: max(var(--space-4), env(safe-area-inset-bottom)); }
  /* the slide-up schedule panel keeps the sheet's rounded top */
  .drawer.sheet .drawer-sched { border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; overflow: hidden; }
  .drawer-scrim { position: fixed; background: var(--sheet-scrim); }

  /* (Page zoom-back behind the sheet removed — the page stays full-size under the
     dim scrim while the sheet is up. .zoom-out is intentionally a no-op now.) */
  /* The scaled page reveals .app-frame at the edges. Paint that frame in the
     SAME colour as the page (--surface, not the gray --canvas) so the receding
     page reads as one continuous surface moving back in space — not a card
     shrinking on top of a separate background. The translucent dim scrim sits
     above both, so a colour mismatch here would otherwise show straight through. */
  .app-frame:has(.drawer.sheet) { background: var(--surface); }
}

/* schedule-consultation inner panel — slides up over the whole drawer */
.drawer-sched {
  position: absolute; left: 0; right: 0; bottom: 0; top: 0;
  z-index: 2; background: var(--surface);
  display: flex; flex-direction: column;
  /* Gentle-start curve (same fix as .drawer.sheet): the consult panel is heavy
     (calendar grid + form), so on a 60Hz phone its first frame is slow; with a
     front-loaded curve that one slow frame lands it ~mid-screen ("doesn't start at
     the bottom"). A gentle start keeps it rising from the bottom. */
  transform: translate3d(0, 100%, 0); transition: transform 360ms cubic-bezier(0.4, 0, 0.2, 1);
}
.drawer.sched-open .drawer-sched { transform: translate3d(0, 0, 0); }
.sched-body { flex: 1; overflow-y: auto; overflow-x: hidden; min-height: 0; padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-5); }
.sched-section { display: flex; flex-direction: column; gap: var(--space-3); }
/* Client portal: "Google Calendar isn't connected yet" banner atop the schedule panel. */
.sched-gcal-warn { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0; padding: var(--space-3) var(--space-4); border: 1px solid color-mix(in srgb, var(--warning-600) 32%, transparent); background: var(--warning-bg); border-radius: var(--radius-lg); font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--text); }
.sched-gcal-warn svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; color: var(--warning-600); }
.sched-gcal-warn a { color: var(--warning-600); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
/* Calendar event detail sheet (Quote details + reschedule + delete). */
.ed-summary { display: flex; flex-direction: column; gap: var(--space-2); }
.ed-badges { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.ed-badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: var(--radius-full); background: var(--gray-50); border: 1px solid var(--border); color: var(--text-soft); font-size: var(--text-xs); font-weight: var(--fw-medium); }
.ed-badge svg { width: 13px; height: 13px; flex-shrink: 0; }
.ed-badge--src { color: var(--text-strong); }
.ed-badge--sync { color: var(--info-600); background: var(--info-bg); border-color: transparent; }
.ed-sub { font-size: var(--text-sm); color: var(--text-soft); }
.ed-join { align-self: flex-start; margin-top: var(--space-1); }
.attendee-chip--ro { padding: 0 12px; }
.ed-none { color: var(--text-soft); font-size: var(--text-sm); }
.sched-foot .btn-ghost-danger.btn-wide { justify-content: center; }
.ed-title-lg { font-size: var(--text-lg); font-weight: var(--fw-bold); color: var(--text-strong); letter-spacing: -0.01em; overflow-wrap: anywhere; }
.ed-when { display: flex; flex-direction: column; gap: var(--space-2); }
.ed-when-row { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-md); color: var(--text-strong); font-weight: var(--fw-medium); }
.ed-when-row svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--text-soft); }
.ed-desc { font-size: var(--text-md); color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; margin: 0; }
.ed-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4) var(--space-5); }
.ed-grid .dw-cell:nth-child(3) { grid-column: 1 / -1; }
/* the Duration/type/address grid sits under the date/time rows in the merged
   "Meeting details" section — a touch more space sets it apart from the times. */
.ed-grid--merged { margin-top: var(--space-2); }
.ed-address-val { display: flex; align-items: flex-start; gap: 6px; }
.ed-address-val svg { width: 15px; height: 15px; flex-shrink: 0; margin-top: 2px; color: var(--text-soft); }
.ed-contact { display: flex; flex-direction: column; gap: var(--space-4); }
.ed-link { color: var(--primary-600); text-decoration: none; overflow-wrap: anywhere; }
.ed-link:hover { text-decoration: underline; }
/* Category tag (Quote / Consultation) — the dot uses the Quote/Consult stage
   colour (--stage-demo), the amber the pipeline uses for this stage everywhere. */
.ed-badge--type .ed-cat-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--stage-demo); flex-shrink: 0; }
.ed-badge--type { color: var(--text-strong); }
.ed-foot { display: flex; flex-direction: column; gap: var(--space-2); }
/* Both footer buttons go full width + match the booking-CTA height (46px). The
   base .btn-ghost-danger is a square icon button, so width/padding are restored here. */
.ed-foot .btn.btn-wide { width: 100%; height: 46px; font-size: var(--text-base); justify-content: center; }
.ed-foot .btn.btn-wide svg { width: 19px; height: 19px; }
.ed-foot .btn-ghost-danger.btn-wide { padding: 0 var(--btn-pad-x); }
.sched-cal-head { justify-content: space-between; margin-bottom: var(--space-1); }
.cal-grid .day.empty { pointer-events: none; }
/* date picker — soft square tiles (scoped to the scheduling calendar) */
.sched-cal { gap: var(--space-2); }
.sched-cal .day {
  width: 100%; height: auto; margin: 0; aspect-ratio: 1 / 1;
  border-radius: var(--radius-md);
  background: var(--gray-100); color: var(--text-strong); font-weight: var(--fw-semibold);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .sched-cal .day:hover { background: var(--gray-200); }
}
.sched-cal .day.other { background: var(--gray-50); color: var(--text-soft); opacity: 0.5; pointer-events: none; }
.sched-cal .day.active { background: var(--primary-600); color: var(--on-primary); box-shadow: 0 3px 9px color-mix(in srgb, var(--primary-600) 26%, transparent); }
@media (hover: hover) and (pointer: fine) {
  .sched-cal .day.active:hover { background: var(--primary-600); }
}
/* two-step date → time picker (time step slides over the calendar) */
.cal-area { position: relative; overflow: hidden; min-height: 326px; }
.cal-step { height: 100%; }
.time-step {
  position: absolute; inset: 0; background: var(--surface);
  display: flex; flex-direction: column; gap: var(--space-3);
  transform: translateX(100%); transition: transform var(--dur-slow) var(--ease);
  pointer-events: none;
}
.cal-area.time-open .time-step { transform: translateX(0); pointer-events: auto; }
.time-step-top { display: flex; align-items: center; justify-content: space-between; }
.sched-back { display: inline-flex; align-items: center; gap: 4px; height: 30px; padding: 0 10px 0 6px; border-radius: var(--radius-sm); color: var(--text-muted); font-size: var(--text-md); font-weight: var(--fw-medium); transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .sched-back:hover { background: var(--nav-hover-bg); color: var(--text-strong); }
}
.sched-back svg { width: 18px; height: 18px; }
.time-step .time-date { font-size: var(--text-base); font-weight: var(--fw-semibold); color: var(--text-strong); }
.time-fmt button { height: 26px; padding: 0 10px; }
.time-list { flex: 1; min-height: 0; overflow-y: auto; display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-2); align-content: start; padding-right: 4px; }
.time-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-2); }
.time-slot {
  height: 40px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text); font-size: var(--text-md); font-weight: var(--fw-medium);
  box-shadow: var(--btn-shadow);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .time-slot:hover { border-color: var(--primary-300); background: var(--primary-50); }
}
.time-slot.active { border-color: var(--primary-600); background: var(--primary-50); color: var(--primary-700); box-shadow: inset 0 0 0 1px var(--primary-600); }
@media (hover: hover) and (pointer: fine) {
  html[data-theme="dark"] .time-slot:hover { border-color: var(--primary-500); background: color-mix(in srgb, var(--primary-500) 18%, var(--surface)); color: var(--text-strong); }
}
html[data-theme="dark"] .time-slot.active { border-color: var(--primary-500); background: color-mix(in srgb, var(--primary-500) 22%, var(--surface)); color: var(--gray-900); box-shadow: inset 0 0 0 1px var(--primary-500); }
.field { display: flex; flex-direction: column; gap: 6px; }
/* .field's flex display beats the UA [hidden] rule — restore it so a
   `hidden` field (e.g. the in-person address) actually collapses. */
.field[hidden] { display: none; }
.field > label { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-muted); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.attendee-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.attendee-chips:empty { display: none; }
.attendee-chip { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 6px 0 10px; border-radius: var(--radius-full); background: var(--primary-50); color: var(--primary-700); font-size: var(--text-sm); font-weight: var(--fw-medium); }
.attendee-chip button { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; color: var(--primary-600); transition: background var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .attendee-chip button:hover { background: var(--primary-100); }
}
.attendee-chip button svg { width: 12px; height: 12px; }
/* ---- In-person address field + Places autocomplete menu ----------- */
.addr-field { position: relative; }
/* trailing location-pin icon inside the address input */
.addr-field .input { padding-right: 38px; }
.addr-field-ico {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  display: inline-flex; width: 16px; height: 16px; color: var(--text-soft); pointer-events: none;
}
.addr-field-ico svg { width: 16px; height: 16px; }
.addr-ac {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); padding: 4px; max-height: 264px; overflow-y: auto;
}
.addr-opt {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 8px 10px; border-radius: var(--radius-sm); color: var(--text);
  transition: background var(--dur) var(--ease);
}
.addr-opt.active { background: var(--nav-hover-bg); }
@media (hover: hover) and (pointer: fine) { .addr-opt:hover { background: var(--nav-hover-bg); } }
.addr-opt-ico { display: inline-flex; flex-shrink: 0; color: var(--text-soft); }
.addr-opt-ico svg { width: 16px; height: 16px; }
.addr-opt-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.addr-opt-main { font-size: var(--text-md); font-weight: var(--fw-medium); color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.addr-opt-sub { font-size: var(--text-sm); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sched-foot { flex-shrink: 0; border-top: 1px solid var(--border); padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }

/* ---- Leads Settings drawer (reuses the Lead Detail shell) ---------- */
.ls-section { display: flex; flex-direction: column; gap: var(--space-2); }
.ls-formsel { display: flex; gap: var(--space-2); }
.ls-formsel .input { flex: 1; }
.ls-formsel .btn { flex-shrink: 0; white-space: nowrap; }
.ls-tabs { gap: var(--space-5); border-bottom: 1px solid var(--border); }
.ls-panel { display: flex; flex-direction: column; gap: var(--space-3); }
.ls-panel[hidden] { display: none; }
.ls-help { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-snug); margin: 0; }
.ls-empty-note { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-4); border: 1px dashed var(--border); border-radius: var(--radius-lg); color: var(--text-soft); font-size: var(--text-sm); line-height: var(--leading-snug); }
.ls-empty-note svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }
.ls-checklist { display: flex; flex-direction: column; gap: 2px; }
.sortable-checklist { gap: 6px; }
/* reusable sortable checklist (drag-to-reorder by handle) */
.sortable-row { display: flex; align-items: center; gap: var(--space-2); border-radius: var(--radius-md); background: var(--gray-50); border: 1px solid var(--border-faint); transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease), opacity var(--dur) var(--ease); }
.sortable-row .ls-check { flex: 1; min-width: 0; }
@media (hover: hover) and (pointer: fine) {
  .sortable-row .ls-check:hover { background: transparent; }
  .sortable-row:hover { background: var(--gray-100); border-color: var(--border); }
}
.sortable-row .drag-handle {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin-right: 4px; border: none; background: transparent;
  color: var(--text-soft); border-radius: var(--radius-sm); cursor: grab; touch-action: none;
  opacity: 0.4; transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .sortable-row:hover .drag-handle { opacity: 1; }
  .sortable-row .drag-handle:hover { color: var(--text); background: var(--gray-100); }
}
.sortable-row .drag-handle:active { cursor: grabbing; }
.sortable-row .drag-handle svg { width: 16px; height: 16px; }
.sortable-row.dragging { background: var(--gray-50); border: 1px dashed var(--border-strong); box-shadow: none; }
.sortable-row.dragging > * { opacity: 0.3; }
.sortable-checklist .drag-overlay {
  pointer-events: none; z-index: 5; margin: 0; cursor: grabbing;
  background: var(--surface); border-color: var(--border-strong);
  box-shadow: var(--shadow-lg); opacity: 1;
}
.sortable-checklist .drag-overlay > * { opacity: 1; }
.sortable-checklist .drag-overlay .drag-handle { opacity: 1; }
.sortable-checklist .drop-line {
  position: absolute; left: 4px; right: 4px; height: 2px; border-radius: 2px;
  background: color-mix(in srgb, var(--primary-600) 55%, transparent);
  pointer-events: none; z-index: 2;
}
.sortable-checklist .drop-line[hidden] { display: none; }
.ls-check { display: flex; align-items: center; gap: var(--space-3); height: 42px; padding: 0 var(--space-2); border-radius: var(--radius-sm); cursor: pointer; transition: background var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .ls-check:hover { background: var(--nav-hover-bg); }
}
.ls-check span { font-size: var(--text-md); color: var(--text); font-weight: var(--fw-medium); }
.ls-endpoint { display: flex; gap: var(--space-2); }
.ls-endpoint .input { flex: 1; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: var(--text-sm); color: var(--text-muted); }
.ls-copy.copied { border-color: var(--success-600); }
.ls-copy.copied svg { color: var(--success-600); }
.ls-collapse { border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.ls-collapse-head { display: flex; align-items: center; gap: var(--space-2); width: 100%; height: 44px; padding: 0 var(--space-3); font-size: var(--text-md); font-weight: var(--fw-medium); color: var(--text); background: var(--surface); transition: background var(--dur) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .ls-collapse-head:hover { background: var(--gray-50); }
}
.ls-collapse-head svg { width: 16px; height: 16px; color: var(--text-soft); transition: transform var(--dur) var(--ease); }
.ls-collapse-head.open svg { transform: rotate(90deg); }
.ls-collapse-body { border-top: 1px solid var(--border); }
.ls-code { margin: 0; padding: var(--space-3) var(--space-4); font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: var(--text-xs); line-height: 1.6; color: var(--text); background: var(--surface-sunk); white-space: pre; overflow-x: auto; }
.ls-danger { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); border: 1px solid #f1cccc; background: #fef6f6; border-radius: var(--radius-lg); }
.ls-danger-title { font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--danger-600); }
.ls-delete { align-self: flex-start; margin-top: var(--space-1); color: var(--danger-600); border-color: #f1cccc; background: var(--surface); }
.ls-delete svg { color: var(--danger-600); }
html[data-theme="dark"] .ls-danger { border-color: color-mix(in srgb, var(--danger-600) 38%, var(--border)); background: var(--danger-bg); }
html[data-theme="dark"] .ls-delete { border-color: color-mix(in srgb, var(--danger-600) 38%, var(--border)); background: var(--surface); }
@media (hover: hover) and (pointer: fine) {
  .ls-delete:hover { background: var(--danger-bg); border-color: var(--danger-600); }
}
.ls-save { margin-top: var(--space-1); }
