/* Portal — global rules that Tailwind utilities cannot express.
   Served from /banking-academy/static/portal.css. Caddy proxies only /banking-academy/*, so this
   prefix is the only one visible on the public origin. */

/* ── Focus ────────────────────────────────────────────────────────────────── */
/* One ring, everywhere. Keyboard users must always be able to see where they are. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgb(9 9 11), 0 0 0 4px rgb(251 191 36);
  border-radius: 0.375rem;
}

/* Skip link: off-screen until focused, then first thing on the page. */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -3rem;
  z-index: 60;
  padding: 0.5rem 0.875rem;
  border-radius: 0.375rem;
  background: rgb(244 244 245);
  color: rgb(9 9 11);
  font-size: 0.875rem;
  font-weight: 600;
  transition: top 120ms ease-out;
}
.skip-link:focus {
  top: 0.75rem;
}

/* ── HTMX loading + error states ──────────────────────────────────────────── */
.htmx-indicator {
  opacity: 0;
  transition: opacity 150ms linear;
  pointer-events: none;
}
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}
[aria-busy="true"] > *:not(.htmx-indicator) {
  opacity: 0.55;
  transition: opacity 150ms linear;
}

@keyframes portal-pulse {
  0%, 100% { transform: scaleX(0.15); transform-origin: left; }
  50%      { transform: scaleX(1);    transform-origin: left; }
}
.htmx-indicator-bar {
  animation: portal-pulse 1.1s ease-in-out infinite;
}

/* ── Status dot: colour is never the only carrier of meaning ─────────────── */
.dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  flex: none;
  background: currentColor;
}

/* ── Tables ───────────────────────────────────────────────────────────────── */
.portal-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: rgb(24 24 27);
}
.portal-table tbody tr {
  min-height: 40px;
}
.truncate-cell {
  display: block;
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Touch targets ────────────────────────────────────────────────────────── */
@media (max-width: 639px) {
  .tap,
  .portal-table tbody td {
    min-height: 44px;
  }
  .tap {
    min-width: 44px;
  }
  /* Pagination and other ghost buttons are 36px by default. */
  .btn-ghost {
    min-height: 44px;
  }
}

/* ── Scrollbars ───────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: rgb(24 24 27); }
::-webkit-scrollbar-thumb { background: rgb(63 63 70); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: rgb(82 82 91); }

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

/* ── Lead table cell primitives ───────────────────────────────────────────────
   The 50-row detail page renders ~2,500 cells. Naming the repeated styles here
   instead of repeating utility strings is what keeps that page under 300 KB. */
.hcell { padding: .5rem .75rem; font-size: .75rem; line-height: 1rem; font-weight: 500; color: rgb(161 161 170); white-space: nowrap; }
.hcell-r { text-align: right; }
.cell { padding: .5rem .75rem; }
.cell-r { padding: .5rem .75rem; text-align: right; font-variant-numeric: tabular-nums; color: rgb(244 244 245); }
.tv { display: block; max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: rgb(244 244 245); }
.mut { color: rgb(161 161 170); white-space: nowrap; }
.lnk { display: inline-flex; align-items: center; min-height: 26px; max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .75rem; color: rgb(251 191 36); }
.lnk:hover { color: rgb(252 211 77); }
.lnk-m { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.cb { height: 1.5rem; width: 1.5rem; accent-color: rgb(245 158 11); }
.dt { font-size: .75rem; line-height: 1rem; color: rgb(161 161 170); }
.dd { margin: 0 0 .25rem; font-size: .875rem; color: rgb(244 244 245); overflow-wrap: anywhere; }
.btn-ghost { display: inline-flex; align-items: center; gap: .25rem; height: 2.25rem; padding: 0 .75rem; border-radius: .375rem; border: 1px solid rgb(63 63 70); font-size: .875rem; font-weight: 500; color: rgb(244 244 245); }
.btn-ghost:hover { background: rgb(39 39 42); }
.field-grid { display: grid; grid-template-columns: 1fr; gap: 0 1.5rem; }
@media (min-width: 640px) { .field-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .field-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ── Badge ───────────────────────────────────────────────────────────────── */
.bdg { display: inline-flex; align-items: center; gap: .375rem; border-radius: .375rem; border: 1px solid; padding: .125rem .5rem; font-size: .75rem; line-height: 1rem; font-weight: 500; white-space: nowrap; }
.bdg-emerald { color: rgb(52 211 153); border-color: rgb(52 211 153 / .3); background: rgb(52 211 153 / .1); }
.bdg-amber   { color: rgb(252 211 77); border-color: rgb(252 211 77 / .3); background: rgb(252 211 77 / .1); }
.bdg-blue    { color: rgb(96 165 250); border-color: rgb(96 165 250 / .3); background: rgb(96 165 250 / .1); }
.bdg-red     { color: rgb(248 113 113); border-color: rgb(248 113 113 / .3); background: rgb(248 113 113 / .1); }
.bdg-zinc    { color: rgb(212 212 216); border-color: rgb(82 82 91); background: rgb(39 39 42); }

/* ── hidden must actually hide ────────────────────────────────────────────────
   A Tailwind display utility (inline-flex, flex) outranks the UA sheet's
   [hidden] { display: none }, so a `hidden` attribute on such an element does
   nothing. Confirm strips and the bulk bar were rendering permanently. */
[hidden] { display: none !important; }

/* The primary nav list is the one element that must ignore that rule on
   desktop, so it toggles a class instead of the attribute. */
.nav-sheet { display: block; }
.nav-sheet.closed { display: none; }
@media (min-width: 640px) {
  .nav-sheet, .nav-sheet.closed { display: flex; }
}

/* Row-level disclosure button: small enough to keep the row under 48px, but
   still a 28px focus target. */
.btn-row { display: inline-flex; align-items: center; height: 1.75rem; padding: 0 .5rem; border-radius: .375rem; border: 1px solid rgb(63 63 70); font-size: .75rem; line-height: 1rem; font-weight: 500; color: rgb(244 244 245); }
.btn-row:hover { background: rgb(39 39 42); }

/* Inline-flex children sit on the text baseline, which adds descender space to
   the line box and pushed data rows to 57px. Middle alignment removes it. */
.cell, .cell-r { vertical-align: middle; line-height: 1.25; }
/* Block-level children keep the row height deterministic: an inline-flex child
   sits on the baseline and silently adds descender space to the line box. */
.cell > .lnk { display: block; line-height: 24px; min-height: 24px; }
.cell > .bdg, .cell > .btn-row { display: flex; width: max-content; }
.cbwrap { display: flex; align-items: center; }

/* ── Stacked card mode for data tables below sm ───────────────────────────────
   A wide table in a horizontal scroller breaks two things on a phone: the
   `<td colspan>` detail row starts at the table's left edge, so tapping "Open"
   in the last column scrolls the panel off-screen; and every in-cell control
   (24px links, 24px checkboxes, 28px disclosure buttons) stays well under the
   44px touch floor. Stacking the rows removes the scroller entirely and lets
   the controls grow, without rendering the rows a second time as cards. */
@media (max-width: 639px) {
  .portal-table.stack,
  .portal-table.stack tbody,
  .portal-table.stack tfoot { display: block; }
  .portal-table.stack thead { display: none; }

  .portal-table.stack tbody tr,
  .portal-table.stack tfoot tr { display: block; padding: .375rem 0 .625rem; }

  .portal-table.stack tbody td,
  .portal-table.stack tbody th,
  .portal-table.stack tfoot td,
  .portal-table.stack tfoot th {
    display: flex;
    align-items: center;
    gap: .75rem;
    width: auto;
    min-height: 44px;
    padding: .25rem .75rem;
    text-align: left;
  }

  /* The column name travels with the cell instead of the (hidden) header. */
  .portal-table.stack td[data-label]::before,
  .portal-table.stack th[data-label]::before {
    content: attr(data-label);
    flex: 0 0 7.5rem;
    font-size: .75rem;
    line-height: 1rem;
    color: rgb(161 161 170);
  }

  /* A numeric cell with no value would render as a labelled blank strip. */
  .portal-table.stack tbody td.cell-r:empty { display: none; }

  /* Only the cells the template marked data-card stay in the phone card. Every
     column as its own 44px row turned one lead into a 584px form and the page
     into 36 screens; the rest are already in the Open panel, one tap away. */
  .portal-table.stack tbody td[data-label]:not([data-card]) { display: none; }

  /* The expanded detail row spans the card, so it takes no label and no flex. */
  .portal-table.stack tbody td[colspan] { display: block; }

  /* Touch floor applies to the controls, not the cells: min-height does
     nothing on display:table-cell, and a measuring tool walks the anchors. */
  .portal-table.stack .cell > .lnk,
  .portal-table.stack .cell > .btn-row,
  .portal-table.stack .cbwrap {
    display: flex;
    align-items: center;
    min-height: 44px;
    line-height: 1.25;
  }
  /* A card is taller than it is wide, so values wrap instead of ellipsing at
     16rem. Notes are clamped to two lines; the full value is in the panel. */
  .portal-table.stack .cell > .lnk {
    max-width: none;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .portal-table.stack .tv {
    max-width: none;
    white-space: normal;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow-wrap: anywhere;
  }
  /* The row checkbox IS the focusable target, so a 44px label wrapper around a
     28px input does not satisfy the touch floor any audit will measure. Grow
     the input itself; bulk selection is a primary action on a phone. */
  .portal-table.stack .cb { height: 44px; width: 44px; }
  .portal-table.stack .cell-r { justify-content: flex-start; }
}

/* ── Lead Desk (client view) ──────────────────────────────────────────────── */
/* The two mark buttons. 36px on desktop -- `.btn-row` is 28px, which is below
   the interactive floor -- and 44px below the sm breakpoint via `.tap`. */
.mark-btn {
  display: inline-flex;
  align-items: center;
  height: 2.25rem;
  padding: 0 .75rem;
  border-radius: .375rem;
  border: 1px solid rgb(63 63 70);
  font-size: .875rem;
  line-height: 1.25rem;
  font-weight: 500;
  color: rgb(244 244 245);
}
.mark-btn:hover { background: rgb(39 39 42); }

/* Visually hidden, still announced. Used for the selected filter, so the page
   keeps exactly one aria-current (the nav) without losing the state in a
   screen reader. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── Lead Desk: the lead table at real widths ─────────────────────────────── */
/* Twenty real rows made this table 1,606px wide inside a 1,390px scroller at
   1440, so Interested / Not relevant sat off-screen with nothing to say they
   existed. Capping the text columns fits THIS list; sticking the action column
   to the right edge keeps it reachable whatever the next list does. Both, not
   either: trimming alone would break again on the next client. */
.lead-table { table-layout: auto; }
.lead-table .lead-company { min-width: 13rem; max-width: 19rem; }
.lead-table .lead-type    { min-width: 9rem;  max-width: 12rem; }
.lead-table .lead-why     { min-width: 15rem; max-width: 26rem; }
.lead-table .lead-contact { max-width: 11rem; }
.lead-table .lead-reach   { max-width: 13rem; }

/* Company and Type WRAP rather than ellipsising. The first caps put every one
   of twenty Type cells behind a tooltip ("Architecture pr...") and truncated a
   quarter of the company names. A firm's name and what it does are the two
   things the client reads to decide; neither may need a hover to be legible.
   Wrapping also degrades honestly -- a longer name takes a second line instead
   of silently disappearing. */
.lead-table .lead-name {
  display: block;
  max-width: none;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: anywhere;
  min-height: 24px;
  font-size: .875rem;
  line-height: 1.25rem;
  color: rgb(251 191 36);
}
.lead-table .lead-name:hover { color: rgb(252 211 77); }

.lead-table .wrap-cell {
  display: block;
  max-width: none;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.25rem;
}

/* Three lines. At two, the practices' sentence was cut at "...with 9..." and
   the part that makes the argument -- the kind of work the firm takes on --
   sat behind a tooltip. 35px of 105 shown is not a summary, it is a teaser. */
.clamp3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: rgb(244 244 245);
  line-height: 1.25rem;
}

/* The action column is pinned to the right edge of the scroller. The z-index
   sits above the sticky <thead> so the header corner does not paint over it. */
.lead-table .lead-actions {
  position: sticky;
  right: 0;
  z-index: 2;
  background: rgb(24 24 27);
  box-shadow: -8px 0 8px -8px rgb(0 0 0 / .6);
}
.lead-table .lead-actions-h { z-index: 3; }

/* Company links on the phone card list were 20px tall. */
.card-link { display: inline-flex; align-items: center; min-height: 28px; }
@media (max-width: 639px) {
  .card-link { min-height: 44px; }
}

/* An operator preview session is labelled on every page. */
.preview-bar {
  background: rgb(252 211 77 / .12);
  border-bottom: 1px solid rgb(252 211 77 / .35);
}
