/**
 * The lead detail as a draggable three-detent bottom sheet over the
 * conversation, and its four tabs.
 *
 * Owned by track T7 of the wa-inbox-pwa run. Created empty by T1 so the <link>
 * in index.html could be written once, before any other track opened that file.
 *
 * Linked in index.html after /css/admin-wa-bulk.css and far above
 * /css/admin-person.css. The "admin" prefix is load-bearing: it is the only
 * thing scripts/bundle-css.mjs partitions on, and a differently named file
 * would ship the whole admin panel's CSS to every marketing visitor.
 *
 * ── EVERY COLOUR HERE IS A --wa-* TOKEN, AND THAT IS NOT A STYLE RULE ─────
 *
 * The inbox palette is re-pointed light and dark on `.admin-layout:has(.wai-page)`
 * (admin-whatsapp.css). A hex literal in any rule below would be the one thing
 * that does not follow the skin, and it would be invisible to whoever is testing
 * in the mode they happen to be in. That is also why the origin and channel chips
 * are redrawn here from tokens instead of borrowing `.lead-origin-chip` /
 * `.ld-ch-chip` from the leads screens: those kits are hard-coded light.
 *
 * ── RTL ───────────────────────────────────────────────────────────────────
 *
 * The island is permanently RTL, so every rule uses logical properties
 * (`inset-inline`, `padding-inline`, `border-start-start-radius`) and never
 * `left` / `right`. The one exception is `transform`, which has no logical form;
 * the sheet only ever translates on Y, so there is no sign to reason about.
 */

/* ══ The four tabs ═══════════════════════════════════════════════════════
   Rendered at EVERY width - the tabs are the pane's information architecture,
   and only the SHELL around them changes with the viewport. */

.wai-tabs {
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--wa-line);
  border-radius: 10px;
  background: var(--wa-sunken-faint);
}

.wai-tab {
  flex: 1 1 0;
  /* `min-width: 0` so a long Hebrew label can be dropped by the rule below
     rather than pushing a fifth of the strip off the pane. */
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  /* 38px painted, taken to the 44px touch minimum by the halo below - the same
     compromise `.wai-chip` makes, and for the same reason: four 44px boxes in a
     320px pane leave no room for a label beside the glyph. */
  min-block-size: 38px;
  position: relative;
  padding-inline: 6px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  color: var(--wa-ink-2);
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
}

.wai-tab::after {
  content: '';
  position: absolute;
  inset: 0;
  margin-block: -3px;
}

.wai-tab:hover {
  color: var(--wa-ink);
}

.wai-tab--on {
  background: var(--wa-panel);
  border-color: var(--wa-line);
  color: var(--wa-ink);
  font-weight: 600;
  box-shadow: var(--wa-shadow-sm);
}

.wai-tab__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The count, and only where a count means something. Never rendered at zero:
   the component drops it, so there is no "empty badge" state to style. */
.wai-tab__count {
  flex: 0 0 auto;
  min-inline-size: 16px;
  padding-inline: 4px;
  border-radius: 999px;
  background: var(--wa-sunken);
  color: var(--wa-ink-2);
  font-size: 0.62rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.wai-tab--on .wai-tab__count {
  background: var(--wa-green-wash);
  color: var(--wa-green-ink);
}

.wai-tabpanel {
  display: flex;
  flex-direction: column;
  gap: var(--space-md, 16px);
}

/* ══ The ליד tab's two new chips ═════════════════════════════════════════
   Same shape as the leads screens', drawn from this island's own tokens. */

.wai-field__value--chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.wai-origin-chip {
  display: inline-flex;
  align-items: center;
  max-inline-size: 100%;
  padding: 1px 7px;
  border: 1px solid var(--wa-line);
  border-radius: 5px;
  background: var(--wa-sunken-faint);
  color: var(--wa-ink);
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A CONFIRMED paid arrival, and only a confirmed one. `paidConfirmed` is the
   server's word for "we can evidence the click was paid"; a likely-paid verdict
   deliberately stays in the neutral chip. */
.wai-origin-chip--paid {
  background: var(--wa-green-wash);
  border-color: var(--wa-green-line);
  color: var(--wa-green-ink);
}

.wai-aff-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-inline-size: 100%;
  padding: 1px 6px;
  border: 1px solid var(--wa-line);
  border-radius: 5px;
  background: var(--wa-sunken-faint);
  color: var(--wa-ink-2);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* One of OUR OWN links. Neutral and quiet on purpose: painting it in the
   partner's colour would credit a re-engagement message of ours to a partner,
   which is the one mistake this tag exists to prevent. */
.wai-aff-chip__ours {
  flex: 0 0 auto;
  padding-inline: 4px;
  border-radius: 4px;
  background: var(--wa-sunken);
  color: var(--wa-ink-3);
  font-size: 0.6rem;
  font-weight: 600;
}

.wai-channel-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  max-inline-size: 100%;
  padding: 1px 8px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--wa-sunken-faint);
  color: var(--wa-ink);
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.4;
}

/* The tiers, in the island's own vocabulary. `unknown` stays neutral: the
   absence of evidence is not a channel claim, and colouring it would make it
   read as one. */
.wai-channel-chip--paid {
  background: var(--wa-green-wash);
  border-color: var(--wa-green-line);
  color: var(--wa-green-ink);
}

.wai-channel-chip--likely-paid {
  background: var(--wa-warn-wash);
  border-color: var(--wa-warn-line);
  color: var(--wa-warn);
}

.wai-channel-chip--referral {
  background: var(--wa-sunken-soft);
  border-color: var(--wa-line);
  color: var(--wa-ink);
}

.wai-channel-chip--unpaid,
.wai-channel-chip--unknown {
  background: var(--wa-sunken-faint);
  border-color: var(--wa-line);
  color: var(--wa-ink-2);
}

/* The confidence word rides the chip only when the verdict is not confirmed,
   the same rule the person page's pill follows. */
.wai-channel-chip__conf {
  font-weight: 500;
  opacity: 0.75;
}

/* ══ The יום פתוח tab's new facts ════════════════════════════════════════ */

.wai-seat-facts {
  margin: 8px 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-block-start: 8px;
  border-block-start: 1px dashed var(--wa-line);
}

.wai-seat__zoom {
  color: var(--wa-link);
  font-weight: 600;
  text-decoration: underline;
}

/* A Zoom seat on a date with NO link. This is the state that makes an email or
   a WhatsApp confirmation useless, so it is stated rather than left blank. */
.wai-seat__fact--warn {
  color: var(--wa-warn);
  font-weight: 600;
}

/* Attendance is TRI-STATE and printed, never editable from a conversation.
   `unset` must not look like "no": it is "nobody has looked yet". */
.wai-attend {
  display: inline-flex;
  align-items: center;
  padding: 0 6px;
  border: 1px solid var(--wa-line);
  border-radius: 5px;
  font-size: 0.68rem;
  font-weight: 600;
}

.wai-attend--yes {
  background: var(--wa-green-wash);
  border-color: var(--wa-green-line);
  color: var(--wa-green-ink);
}

.wai-attend--no {
  background: var(--wa-danger-wash);
  border-color: var(--wa-danger-line);
  color: var(--wa-danger-ink);
}

.wai-attend--unset {
  background: var(--wa-sunken-faint);
  color: var(--wa-ink-3);
}

.wai-answers {
  margin: 6px 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--wa-sunken-faint);
}

.wai-answers__q {
  margin: 0;
  color: var(--wa-ink-2);
  font-size: 0.7rem;
  font-weight: 600;
}

.wai-answers__a {
  margin: 0;
  color: var(--wa-ink);
  font-size: 0.74rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

/* ══ The tombstone chip ══════════════════════════════════════════════════
   A plain span and never `WaLeadStatusSelect`: on this branch there is no
   `status` object to hand that component. `.wai-status-chip` already carries the
   padding, radius and size in admin-whatsapp.css; this only adds the ink. */

.wai-status-chip--dead {
  background: var(--wa-danger-wash);
  border-color: var(--wa-danger-line);
  color: var(--wa-danger-ink);
}

/* ══ The bottom sheet (D18) ══════════════════════════════════════════════
   Phones only. Above 767px this whole block matches nothing and the pane is the
   `.wai-lead` column / slide-over it has always been. The breakpoint is spelled
   `767px` byte for byte because `useAdminBreakpoints` spells its query the same
   way: a `768px` in one place and a `767px` in the other gives a one-pixel band
   with two shells and no pane. */

@media (max-width: 767px) {
  .wai-page {
    /* Duplicated in JS as `WA_SHEET_PEEK_PX` in WaLeadPanel.vue and the two MUST
       agree: the component computes the peek offset from it and this file
       reserves the strip's height off the grid so the composer is never covered.
       tests/waLeadSheetDetents.spec.ts pins the pair. */
    --wai-sheet-peek: 96px;
  }

  /* The thread ends where the peek strip starts, for as long as the sheet is
     open at ANY detent - held at every detent rather than only at peek, so the
     transcript does not relayout underneath a sheet that is animating over it. */
  .wai-page--lead-open .wai-grid {
    padding-block-end: calc(var(--wai-sheet-peek) + env(safe-area-inset-bottom));
  }

  /* The drawer's scrim would dim the conversation that the peek strip exists to
     keep readable. The sheet brings its own, and only from the half detent up. */
  .wai-scrim {
    display: none;
  }

  /* The positioning box is the VISIBLE viewport, not the layout viewport.
     `position: fixed` resolves against the layout viewport, which iOS does NOT
     shrink for the on-screen keyboard - and the notes tab holds a textarea, so a
     sheet pinned with `inset-block-end: 0` would put its own composer under the
     keyboard. `--app-vvh` is published by useVisualViewport() while an editable
     element has focus; anchoring to the TOP with an explicit visible height is
     what makes the sheet's bottom edge track the top of the keyboard. This is
     exactly where AdminSheet's `inset: 0` must NOT be copied. */
  .wai-leadsheet-layer {
    position: fixed;
    inset-inline: 0;
    inset-block-start: 0;
    block-size: var(--app-vvh, 100dvh);
    /* A NEW RUNG, between the drawer (1030) and the sheet scrim (1040). Above
       1030 so it covers the shell's phone bars and the nav drawer's scrim;
       BELOW 1040/1050 so every AdminSheet raised from the thread behind it - the
       templates hub, the canned replies, the thread actions - correctly paints
       OVER it. Give it 1040+ and a template picker opened while the sheet is at
       peek renders underneath it, unreachable, with no error. */
    z-index: 1035;
    display: flex;
    align-items: flex-end;
    /* The layer itself is inert: the conversation behind the peek strip stays
       tappable, which is the whole point of a non-modal sheet. */
    pointer-events: none;
  }

  .wai-leadsheet-scrim {
    position: absolute;
    inset: 0;
    background: var(--wa-scrim);
    opacity: 0;
    transition: opacity 0.18s ease;
    pointer-events: none;
  }

  .wai-leadsheet-layer--covered .wai-leadsheet-scrim {
    opacity: 1;
    pointer-events: auto;
  }

  .wai-leadsheet {
    position: relative;
    z-index: 1036;
    pointer-events: auto;
    inline-size: 100%;
    /* The FULL detent, and the only height this element ever has: it is always
       laid out at full height and only translated, so a detent change is a
       compositor transform and never a relayout of the transcript behind it.
       56px is the compact thread header, left uncovered on purpose so an agent
       at the full detent can still see whose conversation this is. */
    block-size: min(88dvh, calc(var(--app-vvh, 100dvh) - 56px));
    display: flex;
    flex-direction: column;
    min-block-size: 0;
    background: var(--wa-panel);
    border-block-start: 1px solid var(--wa-line);
    /* NO backdrop-filter, and no filter, perspective, contain or will-change
       either. See the docblock in WaLeadPanel.vue: any of them makes this box
       the containing block for every position:fixed DESCENDANT, and an
       AdminSheet raised from inside would then be trapped in the sheet's own box
       instead of covering the viewport. A near-opaque fill does the same visual
       job without creating the trap - the same decision, for the same reason, as
       `.adm-sheet` in admin.css. */
    border-start-start-radius: 20px;
    border-start-end-radius: 20px;
    box-shadow: var(--wa-shadow-lg);
    /* SHUT. The component writes only the offset, into --wai-sheet-y, so the
       closed state stays pure CSS and cannot be beaten by an inline style. */
    transform: translateY(100%);
    /* Transform only while settling. During a drag the component adds
       `--dragging`, or every frame of the gesture is animated 220ms late. */
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0.22, 1);
  }

  .wai-page--lead-open .wai-leadsheet {
    transform: translateY(var(--wai-sheet-y, 0px));
  }

  .wai-leadsheet--dragging {
    transition: none;
  }

  /* The drag surface: the grab bar plus the whole peek strip. `touch-action:
     none` is what stops the browser claiming the vertical gesture for a scroll
     before the handler sees it. It is deliberately NOT on the body. */
  .wai-leadsheet__grip {
    flex: 0 0 auto;
    touch-action: none;
    cursor: grab;
  }

  .wai-leadsheet__grab {
    display: block;
    inline-size: 40px;
    block-size: 4px;
    margin: 7px auto 0;
    border-radius: 999px;
    background: var(--wa-line-strong);
  }

  /* The peek strip: the three questions an agent has mid-sentence, answered
     without covering anything. Sized to --wai-sheet-peek minus the grab bar's
     row, so what the grid reserves and what the strip occupies are one number. */
  .wai-leadsheet__peek {
    display: flex;
    align-items: center;
    gap: 8px;
    min-block-size: calc(var(--wai-sheet-peek) - 11px);
    padding: 8px var(--space-md, 16px);
  }

  .wai-leadsheet__name {
    flex: 1 1 auto;
    min-inline-size: 0;
    color: var(--wa-ink);
    font-size: 0.92rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .wai-leadsheet__fact {
    flex: 0 0 auto;
    color: var(--wa-ink-2);
    font-size: 0.72rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  /* NN/g is explicit that a grab handle alone is not a dismissal affordance and
     that a downward swipe near the top of a phone screen is ambiguous with the
     notification shade. The X is not decoration. */
  .wai-leadsheet__close {
    flex: 0 0 auto;
    inline-size: 44px;
    block-size: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-inline-end: -10px;
    border: none;
    border-radius: var(--radius-full, 980px);
    background: none;
    color: var(--wa-ink-2);
    font-size: 1rem;
    cursor: pointer;
  }

  .wai-leadsheet__body {
    flex: 1 1 auto;
    min-block-size: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* `pan-y`, so the body scrolls normally at every detent. The handoff into a
       sheet drag is decided in JS and only from scrollTop 0, downward, on a real
       touch - see WaLeadPanel.vue. */
    touch-action: pan-y;
    display: flex;
    flex-direction: column;
    gap: var(--space-md, 16px);
    padding: 0 var(--space-md, 16px);
    padding-block-end: calc(16px + env(safe-area-inset-bottom));
  }

  /* The tab strip sticks to the top of the scroller: at the half detent the
     body is the only thing that scrolls, and a strip that scrolled away would
     leave an agent inside a tab with no way back to the other three.

     It is also the strip's SCROLLPORT, and that is the fix for a permanent
     clip rather than an edge case. Measured on 2026-09-05 in Chromium at the
     live 0.76rem Noto Sans Hebrew: with four `flex: 1 1 0` tabs every tab is an
     equal quarter - 85.5px at 390, 81.75 at 375, 78 at 360, 68 at 320 - and
     `הערות צוות` needs 59px of label and is handed 54 / 51 / 47 / 37. It
     ellipsised at all four widths and `יום פתוח` joined it from 360 down. With
     `overflow-x: visible` there was no scrollport, so the ellipsis was
     permanent: nothing an agent could do would ever reveal the word.

     Four tabs is D19 and the labels are the owner's, so the LAYOUT gives: each
     tab takes the width its own label needs (below), and when the four together
     exceed the strip it scrolls. Above 767px `.wai-tab__label` is
     `display: none` (the rule at the foot of this file), so none of this
     reaches the 320px desktop pane. */
  .wai-tabs {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    background: var(--wa-panel);
    flex-wrap: nowrap;
    overflow-x: auto;
    /* A fling that runs off the end of the strip must not chain out into the
       sheet's own scroller, which at scrollTop 0 hands a downward drag to the
       detent gesture. Same rule, same reason, as `.wai-list__chips`. */
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .wai-tabs::-webkit-scrollbar {
    display: none;
  }

  /* `flex-shrink: 0` IS the fix. `flex: 1 1 0` made every tab an equal quarter
     and left the label to ellipsise inside it; `1 0 auto` starts each tab at
     its own content width and lets it grow into whatever the four leave over,
     so the strip still fills edge to edge whenever everything fits.

     `overflow-x: auto` makes `overflow-y` compute to `auto` as well, so the
     3px `.wai-tab::after` halo would be clipped - and clipped content is not
     hit-testable. The strip's own 4px `padding` already contains the overhang
     with a pixel to spare (measured scrollHeight === clientHeight === 46), so
     do not trim that padding to buy width. */
  .wai-tab {
    flex: 1 0 auto;
    font-size: 0.76rem;
  }
}

/* The pane is 320px wide above 767px, which is not enough for four labels
   beside four glyphs. The glyph plus the button's `title` and `aria-label`
   carry the name there - which is why both attributes are on every tab. */
@media (min-width: 768px) {
  .wai-tab__label {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .wai-leadsheet,
  .wai-leadsheet-scrim {
    transition: none;
  }
}
