/* Small custom overrides on top of the Tailwind CDN build loaded in _Layout.cshtml. */

[x-cloak] {
  display: none !important;
}

/* --- DataTables: more breathing room in the header/toolbar rows --------------------- */

table.dataTable thead th,
table.dataTable thead td {
  padding: 0.75rem 1rem !important;
}

table.dataTable tbody th,
table.dataTable tbody td {
  padding: 0.6rem 1rem;
}

.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
  padding: 0.75rem 1rem;
}

.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
  margin-left: 0.5rem;
}

/* --- Dark theme: DataTables ships white-only chrome, so override it explicitly ------ */

html.dark table.dataTable {
  color: #e2e8f0;
  border-color: #334155;
}

html.dark table.dataTable thead th,
html.dark table.dataTable thead td {
  color: #94a3b8;
  border-bottom-color: #334155;
}

html.dark table.dataTable tbody tr {
  background-color: transparent;
  border-color: #1e293b;
}

html.dark table.dataTable tbody tr:hover {
  background-color: #1e293b;
}

html.dark .dataTables_wrapper .dataTables_length,
html.dark .dataTables_wrapper .dataTables_filter,
html.dark .dataTables_wrapper .dataTables_info,
html.dark .dataTables_wrapper .dataTables_paginate {
  color: #94a3b8;
}

html.dark .dataTables_wrapper .dataTables_filter input,
html.dark .dataTables_wrapper .dataTables_length select {
  background-color: #0f172a;
  border-color: #334155;
  color: #e2e8f0;
}

html.dark .dataTables_wrapper .dataTables_paginate .paginate_button {
  color: #e2e8f0 !important;
}

html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.current {
  background: #334155 !important;
  border-color: #475569 !important;
  color: #f8fafc !important;
}

html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled {
  color: #475569 !important;
}

html.dark .dataTables_processing {
  background-color: #0f172a;
  color: #e2e8f0;
}

/* Row links (rendered client-side by DataTables' render() callbacks, so Tailwind's CDN JIT may
   not reliably pick up dark: variants baked into those JS strings) - fall back to plain CSS. */
html.dark table.dataTable tbody a,
html.dark table:not(.dataTable) tbody a {
  color: #38bdf8;
}

html.dark table.dataTable tbody a:hover,
html.dark table:not(.dataTable) tbody a:hover {
  color: #7dd3fc;
}


/* --- Buttons ------------------------------------------------------------------------
   Outlined by default; solid reserved for the one primary action on a page. A page of
   solid buttons gives every action the same weight, which is what made the Sync page hard
   to read.

   Every variant sets border, text AND background explicitly in both themes. The original
   bug here was a button that defined only a light-mode background and disappeared into a
   dark page; an outline style fails the same way if the border is left to inherit. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 500;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.btn:focus-visible { outline: 2px solid #0ea5e9; outline-offset: 2px; }
.btn:disabled,
.btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }

/* Primary - solid. The single affirmative action on a page. */
.btn-primary             { background-color: #0f172a; color: #fff; border-color: #0f172a; }
.btn-primary:hover       { background-color: #1e293b; border-color: #1e293b; }
.dark .btn-primary       { background-color: #38bdf8; color: #0b1220; border-color: #38bdf8; }
.dark .btn-primary:hover { background-color: #7dd3fc; border-color: #7dd3fc; }

/* Secondary - the default. Outlined, and legible on both grounds. */
.btn-secondary             { background-color: transparent; color: #334155; border-color: #cbd5e1; }
.btn-secondary:hover       { background-color: #f1f5f9; border-color: #94a3b8; }
.dark .btn-secondary       { background-color: transparent; color: #cbd5e1; border-color: #475569; }
.dark .btn-secondary:hover { background-color: #1e293b; color: #f8fafc; border-color: #64748b; }

/* Info - outlined, for a secondary action that still does something, e.g. Edit. */
.btn-info             { background-color: transparent; color: #0369a1; border-color: #7dd3fc; }
.btn-info:hover       { background-color: #f0f9ff; border-color: #0284c7; }
.dark .btn-info       { background-color: transparent; color: #7dd3fc; border-color: #0369a1; }
.dark .btn-info:hover { background-color: #082f49; color: #bae6fd; border-color: #0284c7; }

/* Danger - outlined until hovered, so a destructive action is visible but not shouting. */
.btn-danger             { background-color: transparent; color: #b91c1c; border-color: #fca5a5; }
.btn-danger:hover       { background-color: #dc2626; color: #fff; border-color: #dc2626; }
.dark .btn-danger       { background-color: transparent; color: #fca5a5; border-color: #7f1d1d; }
.dark .btn-danger:hover { background-color: #b91c1c; color: #fff; border-color: #b91c1c; }

/* Success - solid, and used once: Run Full Sync. */
.btn-success             { background-color: #059669; color: #fff; border-color: #059669; }
.btn-success:hover       { background-color: #047857; border-color: #047857; }
.dark .btn-success       { background-color: #047857; color: #ecfdf5; border-color: #047857; }
.dark .btn-success:hover { background-color: #059669; border-color: #059669; }

.btn-block { width: 100%; }

.btn-sm {
  padding: 0.25rem 0.625rem;
  font-size: 0.8125rem;
  border-radius: 0.375rem;
}

/* Validation summaries
   --------------------
   ASP.NET's asp-validation-summary ALWAYS renders its <div>; with nothing to report it merely
   swaps in the class .validation-summary-valid. Any summary given a background, border or padding
   therefore shows as an empty coloured bar on a form nobody has submitted yet.

   Hiding it here rather than wrapping each form in an @if keeps the fix with the cause: a new
   form gets the correct behaviour without its author having to know this. It is the same rule the
   buttons follow - nothing renders an empty styled box. */
.validation-summary-valid { display: none; }

/* Same problem, one field at a time: field-validation-valid is emitted for every field on a clean
   form. It carries no background today, so this is belt-and-braces against a future style making
   an empty span visible. */
.field-validation-valid { display: none; }

/* --- Page width ---------------------------------------------------------------------
   The shell - header nav and <main> - is full-bleed. Staff run this on wide monitors and
   the directory tables are the thing they spend the day looking at, so the old max-w-6xl
   (1152px) cap left most of the screen empty and forced the wide tables to scroll
   sideways inside a narrow column.

   Gutters grow with the viewport so content never sits against the edge of the glass.

   This is the ONE place page width is decided: the header and the body both use it, so
   they stay aligned with each other by construction. Individual pages still narrow their
   own content where a short measure is right - prose paragraphs, forms, the sign-in
   cards - and those caps are deliberate, not leftovers from this one. */
.page-container {
  width: 100%;
  padding-left: 1rem;
  padding-right: 1rem;
}

@media (min-width: 640px) {
  .page-container {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }
}

@media (min-width: 1024px) {
  .page-container {
    padding-left: 2rem;
    padding-right: 2rem;
  }
}

/* Small badge size for the Bar # column's wordy states ("Missing", "N/A"). A plain rule, not a
   Tailwind arbitrary value: the class is only ever produced inside a DataTables render() string,
   and the JIT has been caught missing those before. See directory-tables.js for why the size is
   passed in rather than layered over text-xs. */
.badge-sm {
  font-size: 11px;
  line-height: 1rem;
}

/* DataTables 1.13 lays its toolbar out with floats - length and info left, search and paging
   right. Below ~640px those two halves collide and the paging controls end up half off the edge
   of the card. Stack them instead; the grid itself is handled by the table's own breakpoints. */
@media (max-width: 639px) {
  .dataTables_wrapper .dataTables_length,
  .dataTables_wrapper .dataTables_filter,
  .dataTables_wrapper .dataTables_info,
  .dataTables_wrapper .dataTables_paginate {
    float: none;
    width: 100%;
    text-align: left;
  }

  .dataTables_wrapper .dataTables_filter input {
    margin-left: 0;
    width: 100%;
  }

  .dataTables_wrapper .dataTables_paginate {
    padding-top: 0;
  }

  /* Paging buttons are inline-block, so they wrap on their own once the row is full width.
     Trimming their padding fits more per line - "Previous 1 2 3 ... 1,181 Next" is a lot of
     control for a phone. */
  .dataTables_wrapper .dataTables_paginate .paginate_button {
    padding: 0.35em 0.7em;
    min-width: 0;
  }

  /* Cell padding of 1rem a side costs 2rem per column. At four columns on a 375px screen that is
     a fifth of the viewport spent on gutters, so tighten it - the !important matches the base
     rule above, which needs one to beat DataTables' own stylesheet. */
  table.dataTable thead th,
  table.dataTable thead td {
    padding: 0.6rem 0.5rem !important;
  }

  table.dataTable tbody th,
  table.dataTable tbody td {
    padding: 0.55rem 0.5rem;
  }

  .dataTables_wrapper .dataTables_length,
  .dataTables_wrapper .dataTables_filter,
  .dataTables_wrapper .dataTables_info {
    padding: 0.5rem;
  }
}

/* --- Wordmark -----------------------------------------------------------------------
   "STAFF PORTAL" beside the OBA lockup. The brief was taller but not wider, which is a
   typeface choice rather than a size one: scaling a normal face up makes it wider too, and
   scaling it vertically with a transform distorts the letterforms. Oswald is condensed, so
   it gains height at the same width.

   Set in caps to match the lockup, which is all caps. Letter-spacing is opened slightly
   because condensed caps set tight are hard to read at small sizes - the logo's own type
   does the same.

   1.375rem against the logo's 40px puts the cap height close to the artwork's second line
   without the text outgrowing the 56px bar. */
.wordmark {
  font-family: 'Oswald', 'Arial Narrow', 'Helvetica Neue Condensed', system-ui, sans-serif;
  /* 400, not 600: at this size the heavier cut read as a slab against the logo's own lighter
     lettering. Condensed faces carry their weight in narrow strokes, so they look heavier than
     the same number in a normal face. */
  font-weight: 400;
  font-size: 1.375rem;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  /* The fallbacks are narrower than Oswald at the same size; without this they would jump on
     the swap. Not exact, but it keeps the shift small enough not to catch the eye. */
  font-stretch: condensed;
}

/* Password reveal ----------------------------------------------------------

   The eye button that toggles a password field between hidden and readable.
   Requested by the Bar for the sign-in page; applied to every password field
   in the app by wwwroot/js/password-reveal.js, which finds them itself.

   Real CSS rather than Tailwind utilities, for the reason recorded against
   .badge-sm: these classes exist only inside a JS string, and the CDN's JIT
   compiler has been caught not generating rules for classes it never sees in
   markup. A missing rule here would leave the button stacked below the field
   instead of inside it. */
.pw-field {
  position: relative;
  display: block;
}

/* Room for the button, so a long password does not run underneath it. */
.pw-field > input {
  padding-right: 2.5rem;
}

.pw-toggle {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: none;
  color: #94a3b8;
  cursor: pointer;
}

.pw-toggle:hover { color: #0f172a; }
.pw-toggle:focus-visible { outline: 2px solid #0ea5e9; outline-offset: -2px; border-radius: 0.25rem; }
.pw-toggle svg { height: 1rem; width: 1rem; }

.dark .pw-toggle { color: #64748b; }
.dark .pw-toggle:hover { color: #e2e8f0; }

/* Edge and IE draw a reveal control of their own inside password inputs, which
   would sit alongside ours and toggle the same field independently. */
.pw-field > input::-ms-reveal,
.pw-field > input::-ms-clear { display: none; }

/* Member status pills ------------------------------------------------------

   Wicket's person `status`, coloured by severity rather than one hue per value.
   The Bar's ask was to spot a bad status at a glance, and a rainbow defeats
   that: with eight colours nothing stands out. Five bands, each meaning one
   thing, and only ~5% of production members land on amber or red - which is
   what keeps red meaningful.

     green   in good standing              67% of members
     slate   deceased                      18%  - not a sanction, just gone
     violet  resigned voluntarily          10%  - left by choice, not a penalty
     amber   suspended                     0.2% - temporary, they may return
     red     disbarred / stricken /        4.9% - removed for cause
             resigned by discipline
     orange  lost                          rare - contact lost, not a sanction.
                                                  Muted and browner than the amber
                                                  so the two never read alike.

   Violet rather than the orange first suggested, because orange sits beside
   amber and those two are the pair worth keeping apart: "chose to leave" and
   "suspended" must not read alike.

   Real CSS rather than Tailwind utilities because the People grid builds these
   inside a JS string, and the CDN JIT has been caught not generating rules for
   classes it never sees in markup - see the note on .badge-sm. */
.status-pill {
  display: inline-flex;
  align-items: center;
  border-radius: 0.25rem;
  padding: 0.125rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  white-space: nowrap;
}

.status-good     { background-color: #d1fae5; color: #065f46; }
.status-gone     { background-color: #e2e8f0; color: #334155; }
.status-left     { background-color: #ede9fe; color: #5b21b6; }
.status-paused   { background-color: #fef3c7; color: #92400e; }
.status-removed  { background-color: #fee2e2; color: #991b1b; }
/* Muted orange, deliberately duller and browner than the amber above: "lost" sits
   next to "suspended" in any list and the two must not be mistaken for each other.
   Lost means contact with the member has been lost, not that they were sanctioned. */
.status-lost     { background-color: #fbe3d0; color: #9a5324; }
.status-unknown  { background-color: #f1f5f9; color: #64748b; }

.dark .status-good    { background-color: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
.dark .status-gone    { background-color: rgba(100, 116, 139, 0.25); color: #cbd5e1; }
.dark .status-left    { background-color: rgba(139, 92, 246, 0.18); color: #c4b5fd; }
.dark .status-paused  { background-color: rgba(245, 158, 11, 0.15); color: #fcd34d; }
.dark .status-removed { background-color: rgba(239, 68, 68, 0.15); color: #fca5a5; }
.dark .status-lost    { background-color: rgba(194, 120, 60, 0.18); color: #e0a878; }
.dark .status-unknown { background-color: rgba(100, 116, 139, 0.18); color: #94a3b8; }

/* ---------------------------------------------------------------------------------------------
   Suspension notes.

   The "..." button that opens a cut-off note. Written here rather than as Tailwind classes for
   the same reason as the status pills: ::backdrop has no class to hang off, and the button needs
   a hover state in both themes.

   It appears only when the note is actually cut off - see suspension-notes.js - so it is a
   genuine signal that there is more to read, not decoration on every row.
   --------------------------------------------------------------------------------------------- */
.note-more {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.375rem;
  height: 1.125rem;
  margin-top: 0.0625rem;
  border: 1px solid #cbd5e1;
  /* A rounded square rather than a circle: it reads as a control next to a line of text, where a
     small circle read as punctuation - which is the one thing it must not be mistaken for here. */
  border-radius: 0.25rem;
  font-size: 0.75rem;
  line-height: 1;
  color: #475569;
  background-color: #fff;
}

.note-more:hover {
  background-color: #f1f5f9;
  border-color: #94a3b8;
  color: #0f172a;
}

.dark .note-more {
  border-color: #475569;
  color: #cbd5e1;
  background-color: transparent;
}

.dark .note-more:hover {
  background-color: #1e293b;
  border-color: #64748b;
  color: #fff;
}

.note-dialog {
  width: min(32rem, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  color: inherit;
  background-color: #fff;
}

.note-dialog::backdrop {
  background-color: rgba(15, 23, 42, 0.45);
}

.note-dialog-body {
  padding: 1.25rem 1.5rem 1.5rem;
}

/* Darker than the page, not lighter. slate-900 on a slate-950 page made the dialog the lightest
   thing on screen and it read as flat - the same trick that works in light mode (a white card on a
   grey page) inverts badly in the dark. Black with a slate-800 edge reads as a surface in front of
   the page instead, which is what the backdrop below reinforces. */
.dark .note-dialog {
  border-color: #1e293b;
  background-color: #000;
  color: #e2e8f0;
}

.dark .note-dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.72);
}

/* ---------------------------------------------------------------------------------------------
   Sortable table headings (see sortable-table.js).

   A button rather than a clickable cell, so the sort is in the tab order and Enter and Space work
   without inventing key handling. It fills the cell, which is why the <th> itself carries no
   padding: the padding lives here, or half the heading would not be clickable.

   The arrow is a pseudo-element keyed off aria-sort, so the state a screen reader announces and
   the state the eye sees can never disagree - there is only one of them.
   --------------------------------------------------------------------------------------------- */
.th-sort {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  width: 100%;
  padding: 0.5rem 1rem;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  white-space: normal;
  cursor: pointer;
}

.th-sort::after {
  content: "↕";
  opacity: 0.35;
}

.th-sort:hover {
  color: #0f172a;
}

.dark .th-sort:hover {
  color: #fff;
}

[aria-sort="ascending"] .th-sort::after {
  content: "↑";
  opacity: 1;
}

[aria-sort="descending"] .th-sort::after {
  content: "↓";
  opacity: 1;
}

/* ---------------------------------------------------------------------------------------------
   Release notes.

   The dialog is the suspension-note one widened: same native <dialog>, same backdrop, so staff
   meet one kind of modal in this app rather than two.

   .release-notes styles Markdown that Markdig rendered, which arrives as plain <h3>, <ul>, <p> and
   <strong> with no classes on it. Tailwind cannot reach those, so the rules live here - and this is
   the whole reason the notes can be written as Markdown rather than as markup.
   --------------------------------------------------------------------------------------------- */
.release-dialog {
  width: min(44rem, calc(100vw - 2rem));
  max-height: calc(100vh - 4rem);
  padding: 0;
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  color: inherit;
  background-color: #fff;
}

.release-dialog::backdrop {
  background-color: rgba(15, 23, 42, 0.45);
}

.release-dialog-body {
  padding: 1.5rem 1.75rem 1.75rem;
}

/* See the note dialog above for why this is black rather than slate-900. */
.dark .release-dialog {
  border-color: #1e293b;
  background-color: #000;
  color: #e2e8f0;
}

/* Heavier in the dark, where a 45% slate wash over an already-dark page dimmed nothing. */
.dark .release-dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.72);
}

.release-notes {
  font-size: 0.875rem;
  line-height: 1.6;
}

.release-notes h3 {
  margin-top: 1.25rem;
  margin-bottom: 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #64748b;
}

.release-notes h3:first-child {
  margin-top: 0;
}

.dark .release-notes h3 {
  color: #94a3b8;
}

.release-notes ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.release-notes li {
  position: relative;
  padding-left: 1rem;
  margin-bottom: 0.5rem;
}

/* A dash rather than a bullet: these lists sit inside a dialog with its own headings, and a column
   of round bullets reads heavier than the content deserves. */
.release-notes li::before {
  content: "–";
  position: absolute;
  left: 0;
  color: #94a3b8;
}

.release-notes p {
  margin: 0 0 0.75rem;
}

.release-notes a {
  text-decoration: underline;
}
