/**
 * The application chrome, one definition, every screen.
 *
 * WHY THIS FILE EXISTS. The title bar was defined separately in seventeen pages
 * and had drifted into three heights (62px, 46px, and "whatever 12px of padding
 * comes to") and two different backgrounds (a navy gradient on the reviewer
 * screens, flat #16233b on the admin ones). It was corrected once before and drifted
 * again, because correcting seventeen copies leaves seventeen places for the next
 * one to diverge.
 *
 * Loaded LAST in each page's <head>, after that page's own <style>, so these rules
 * win on equal specificity. A screen that genuinely needs to differ should say so
 * with a class on the bar, not by redefining .topbar.
 *
 * Anything here is shared chrome: the bar, the brand, the nav tabs, the account
 * chip. Page-specific layout stays in the page.
 */

:root {
  /* Named so the bar cannot drift by a pixel again without changing this line. */
  --chrome-height: 62px;
  --chrome-pad-x: 22px;
  --chrome-navy-800: #1c2c4c;
  --chrome-navy-900: #16233b;
}

.topbar {
  background: linear-gradient(180deg, var(--chrome-navy-800), var(--chrome-navy-900));
  color: #fff;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 var(--chrome-pad-x);
  height: var(--chrome-height);
  /* Both, deliberately: the height is fixed and the padding must not re-inflate it,
     and the bar must not be squeezed by a flex parent on the scrolling screens. */
  box-sizing: border-box;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  z-index: 40;
}

/* The brand sits at a fixed size so a logo on one screen and a wordmark on another
   do not change the bar's optical weight, which is what "the bar looks different"
   usually turns out to mean once the heights already match. */
.topbar .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 800;
  font-size: 18px;
  letter-spacing: .02em;
  white-space: nowrap;
}
.topbar .brand .logo {
  width: 34px;
  height: 34px;
  display: block;
  flex-shrink: 0;
}

.topbar .nav-tabs { display: flex; gap: 6px; margin-left: 4px; min-width: 0; }
.topbar .nav-tabs a {
  color: #dbe6f6;
  text-decoration: none;
  padding: 7px 14px;
  border-radius: 8px;
  background: rgba(255, 255, 255, .08);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.topbar .nav-tabs a:hover { background: rgba(255, 255, 255, .14); }
.topbar .nav-tabs a.active {
  background: rgba(255, 255, 255, .16);
  box-shadow: inset 0 -2px 0 #f7b733;
}

.topbar .spacer { flex: 1; }

/* Administrative destinations, grouped on the RIGHT of the bar (after the spacer)
 * and tinted amber, so they are the same set in the same place on every admin
 * screen instead of a different hand-kept list on each, and so a link that
 * writes across the whole tenant never sits camouflaged among the reviewer's own
 * tabs. Same amber language as the administration zone on Home. */
.topbar .admin-tabs { display: flex; gap: 6px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
/* When the bar is too narrow for every tab, the admin group scrolls inside itself
   rather than shoving the account name off the right edge. Scrollbar hidden: on a
   normal-width screen it never scrolls, and a bar in the chrome would read as an
   error. Overflow lives on this group, never on .topbar. That would clip the
   account dropdown that hangs below the bar on the reviewer screens. */
.topbar .admin-tabs::-webkit-scrollbar { display: none; }
.topbar .admin-tabs a {
  color: #ffd98a;
  text-decoration: none;
  padding: 7px 14px;
  border-radius: 8px;
  background: rgba(247, 183, 51, .14);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.topbar .admin-tabs a:hover { background: rgba(247, 183, 51, .26); color: #fff; }
.topbar .admin-tabs a.active {
  background: rgba(247, 183, 51, .30);
  color: #fff;
  box-shadow: inset 0 -2px 0 #f7b733;
}

.topbar .who {
  font-size: 13px;
  line-height: 1.2;
  text-align: right;
  white-space: nowrap;
}
.topbar .who small { display: block; color: #9fb2d0; font-size: 11px; }

/* The account chip is a <button>, and `font: inherit` does NOT carry colour, so
   its name text fell back to the user-agent button colour (near-black) on the dark
   bar. Force a light colour here, once, for every screen and every theme (the bar
   is dark in all of them). */
.topbar .user-chip { color: #eaf1fb; }
.topbar .user-chip .who { color: #eaf1fb; }
.topbar .user-chip .caret { color: #9fb2d0; }

/* Theme switcher, sitting beside the account chip. The bar is dark in every
   theme, so the control is styled for the dark bar and needs no theme rules. */
.topbar .theme-switch { position: relative; flex-shrink: 0; }
.topbar .theme-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 8px; cursor: pointer;
  color: #dbe6f6; background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .14);
}
.topbar .theme-trigger:hover { background: rgba(255, 255, 255, .16); color: #fff; }
.topbar .theme-trigger svg { width: 18px; height: 18px; display: block; }
.topbar .theme-menu {
  /* Above the mobile nav overlay (z-index 60), so an open theme menu is never
     hidden behind the expanded navigation on a narrow screen. */
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 70;
  min-width: 148px; padding: 6px;
  background: #1e293b; border: 1px solid #334155; border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .5);
}
.topbar .theme-menu[hidden] { display: none; }
.topbar .theme-menu button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 7px; cursor: pointer;
  background: transparent; color: #e5e9f0; font: inherit; font-size: 13px; text-align: left;
}
.topbar .theme-menu button:hover { background: rgba(255, 255, 255, .08); }
.topbar .theme-menu button.active { color: #f7b733; }
.topbar .theme-menu svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Account menu, the chip and its Logout / Password / Support dropdown.
 *
 * These visual rules lived only inside each reviewer screen's own <style>, so the
 * menu could not be shown on the admin screens (Users, Upload, Duplicates, Overlays,
 * Custom Fields, Processing) or Sub-users, which had no menu at all, and therefore
 * no logo, no mobile nav and no way to log out. Owned here now, once, scoped to
 * .topbar, for every screen and every theme (the bar is dark in all of them).
 * account-menu.js injects the markup wherever a screen lacks it; these rules render
 * it. Reviewer screens keep their own inline copy and are left untouched. */
.topbar .user-menu { position: relative; flex-shrink: 0; }
.topbar .user-chip {
  display: flex; align-items: center; gap: 10px;
  background: rgba(255, 255, 255, .08);
  padding: 6px 12px 6px 6px;
  border-radius: 999px;
  border: none; cursor: pointer;
  font: inherit; font-size: 13px;
}
.topbar .user-chip .avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; color: #fff; flex-shrink: 0;
}
.topbar .user-chip .who { line-height: 1.2; }
.topbar .user-chip .who small { display: block; font-size: 11px; }
.topbar .user-chip .caret { margin-left: 2px; transition: transform .15s; }
.topbar .user-menu.open .caret { transform: rotate(180deg); }
.topbar .user-dropdown {
  position: absolute; right: 0; top: calc(100% + 8px);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 14px 34px rgba(15, 32, 56, .20);
  min-width: 208px; padding: 6px; z-index: 60;
  display: none;
}
.topbar .user-menu.open .user-dropdown { display: block; }
.topbar .menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  border: none; background: transparent; padding: 9px 12px; border-radius: 8px;
  font: inherit; font-size: 13.5px; font-weight: 500; color: var(--text);
  cursor: pointer; text-align: left;
}
.topbar .menu-item svg { color: var(--muted); flex-shrink: 0; }
.topbar .menu-item:hover { background: var(--brand-soft); color: var(--brand); }
.topbar .menu-item:hover svg { color: var(--brand); }
.topbar .menu-item.danger:hover { background: #fee2e2; color: #b91c1c; }
.topbar .menu-item.danger:hover svg { color: #b91c1c; }
.topbar .menu-sep { height: 1px; background: var(--border); margin: 5px 4px; }

/* Mobile nav toggle, hidden on desktop, revealed by the mobile block below. */
.topbar .nav-toggle {
  display: none;
  background: rgba(255, 255, 255, .10); border: none; color: #fff;
  width: 40px; height: 40px; border-radius: 10px; cursor: pointer;
  align-items: center; justify-content: center; flex-shrink: 0;
}
.topbar .nav-toggle:hover { background: rgba(255, 255, 255, .18); }

/* -----------------------------------------------------------------------------
 * Dossier Dark, the "ink" variant, the dark counterpart to the paper Dossier.
 * Same CSS-variable remap as the light Dossier, in warm dark archival values, not
 * corporate navy. The Dossier STRUCTURE rules further down apply to BOTH variants,
 * matched with [data-theme^="dossier"], so the docket table and exhibit sheet read
 * the same on ink as on paper.
 * -------------------------------------------------------------------------- */
:root[data-theme="dossier-dark"] {
  --bg: #17140f;
  --surface: #211d16;   --card: #211d16;
  --frame-bg: #100e0a;
  --panel-head: #2a251c;
  --row-hover: #2b261d;
  --row-stripe: #1e1a13;
  --grid: #39332a;      --grid-line: #39332a;

  --text: #ece7db;      --ink: #ece7db;
  --muted: #a89f8b;

  --border: #39332a;    --line: #39332a;

  /* Exhibit-red, brightened just enough to read on ink while staying a brick,
     not a signal red. */
  --brand: #d16a5d;
  --brand-soft: rgba(209, 106, 93, .20);

  --green-soft: rgba(122, 160, 96, .20);
  --red-soft:   rgba(209, 106, 93, .20);
  --amber-soft: rgba(201, 160, 88, .20);
  --slate-soft: rgba(168, 159, 139, .16);
  --violet-soft:rgba(150, 130, 180, .20);

  /* Semantic status INK colours, the solid text/icon/fill counterparts to the
     -soft tints above. The screens define --danger / --warn / --ok / … once in a
     bare :root with LIGHT values, which chrome.css never re-themed, so on ink they
     stayed dark and low-contrast, e.g. button.danger's red label on the dark
     surface, which the element-by-element dark pass never caught. Brightened here
     to the same hue family as the -soft tints, so every `var(--danger)` reads on
     ink without hunting each element down. Light keeps the screens' own values,
     this block only applies under data-theme="dossier-dark". Left out on purpose:
     --gold (already a bright gold that reads on ink) and --grape (a dark fill sat
     behind white text, which brightening would wreck). */
  --danger: #e79a90;  --red: #e79a90;
  --warn:   #d8b46a;  --amber: #d8b46a;
  --ok:     #9ec98a;  --green: #9ec98a;
  --violet: #bda9dd;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, .55);
  --shadow:    0 1px 3px rgba(0, 0, 0, .55);
  --shadow-hover: 0 10px 28px rgba(0, 0, 0, .6);
}

/* -----------------------------------------------------------------------------
 * Dossier theme, warm archival paper, ink, and a reserved exhibit-red.
 *
 * A SKIN, nothing more: it remaps the same CSS variables the light/grey/dark
 * themes use, plus a small set of Dossier-specific rules (serif headings,
 * monospaced counts, docket-style header rules, an ink bar). No page markup
 * changes, so switching away in the theme dropdown reverts it completely, and
 * deleting this block removes the theme without touching any screen.
 *
 * The palette is lifted from web/mockups/1-dossier.html, the direction Eddy chose.
 * Exhibit-red (--brand) is a muted brick, kept distinct from the brighter
 * semantic danger red the app still uses for destructive actions.
 * -------------------------------------------------------------------------- */
:root[data-theme="dossier"] {
  --bg: #f2f1ea;
  --surface: #fbfaf5;   --card: #fbfaf5;
  --frame-bg: #eae8de;
  --panel-head: #eae8de;
  --row-hover: #eae8de;
  --row-stripe: #f3f0e6;
  --grid: #d8d4c6;      --grid-line: #d8d4c6;

  --text: #1d1b16;      --ink: #1d1b16;
  --muted: #5b574c;

  --border: #c8c3b2;    --line: #c8c3b2;

  /* Exhibit-red is the accent, links, active states, primary emphasis. */
  --brand: #9a2f28;
  --brand-soft: #f0dcd8;

  /* Status tints warmed to sit on paper rather than on white. */
  --green-soft: #dfe7d4;
  --red-soft:   #f0dcd8;
  --amber-soft: #efe2c6;
  --slate-soft: #e6e2d6;
  --violet-soft:#e4dced;

  /* A case file is flat, not floating, shadows are barely there. */
  --shadow-sm: 0 1px 0 rgba(29, 27, 22, .06);
  --shadow-md: 0 1px 2px rgba(29, 27, 22, .10);
  --shadow:    0 1px 2px rgba(29, 27, 22, .08);
  --shadow-hover: 0 6px 18px rgba(29, 27, 22, .14);
}

/* -----------------------------------------------------------------------------
 * A third theme, for readers who find the archival paper too warm or too dim.
 *
 * Named "dossier-white" so it starts with "dossier": all 34 of the structural
 * rules below are keyed on [data-theme^="dossier"] (ink bar, serif headings,
 * monospaced identifiers, docket tables, the exhibit sticker), and the prefix is
 * what buys them. Only ONE rule in this file uses the exact value "dossier", the
 * palette above, so a palette is all this theme needs to define. The 79
 * dossier-dark overrides do not reach it, which is right: it is a light theme.
 *
 * White surfaces on a cool grey page, so a card still reads as a card. Warmth
 * comes out of the greys but the exhibit red stays: it is the product's accent,
 * not a property of the paper.
 * -------------------------------------------------------------------------- */
:root[data-theme="dossier-white"] {
  --bg: #edf0f4;
  --surface: #ffffff;   --card: #ffffff;
  --frame-bg: #f4f6f9;
  --panel-head: #f4f6f9;
  --row-hover: #f1f4f8;
  --row-stripe: #fafbfd;
  --grid: #e2e7ee;      --grid-line: #e2e7ee;

  --text: #16191f;      --ink: #16191f;
  --muted: #5c6472;

  --border: #d8dee6;    --line: #d8dee6;

  --brand: #9a2f28;
  --brand-soft: #f7e4e1;

  /* Status tints cooled to sit on white rather than on paper. */
  --green-soft: #ddefd9;
  --red-soft:   #f7e4e1;
  --amber-soft: #f8ecd2;
  --slate-soft: #e8edf3;
  --violet-soft:#e8e2f5;

  /* A shade more lift than the paper theme: on white, a flat card and a flat page
     are the same colour and the edges disappear. */
  --shadow-sm: 0 1px 0 rgba(22, 25, 31, .05);
  --shadow-md: 0 1px 3px rgba(22, 25, 31, .09);
  --shadow:    0 1px 2px rgba(22, 25, 31, .07);
  --shadow-hover: 0 6px 18px rgba(22, 25, 31, .12);
}

/* The bar goes warm ink instead of corporate navy, with the exhibit-red active
   accent replacing the amber underline. Structure is unchanged, still the same
   light-on-dark chrome, only recoloured. */
:root[data-theme^="dossier"] .topbar { background: #1d1b16; }
:root[data-theme^="dossier"] .topbar .nav-tabs a.active { box-shadow: inset 0 -2px 0 var(--brand); }

/* Type signature, serif for the editorial voice, the brand wordmark included. */
:root[data-theme^="dossier"] .topbar .brand,
:root[data-theme^="dossier"] h1,
:root[data-theme^="dossier"] h2,
:root[data-theme^="dossier"] .page-head h1,
:root[data-theme^="dossier"] .kpi .value {
  font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  letter-spacing: .01em;
}
/* Counts and identifiers set as data, the mockup's monospaced bates/IDs/hashes. */
:root[data-theme^="dossier"] .total-pill,
:root[data-theme^="dossier"] code,
:root[data-theme^="dossier"] kbd,
:root[data-theme^="dossier"] samp,
:root[data-theme^="dossier"] .mono {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}

/* Docket-style tables: a firm ink underline beneath the header row, and every
   cell rule pulled back to the paper's own line colour so the grid reads quiet. */
:root[data-theme^="dossier"] thead th,
:root[data-theme^="dossier"] table th {
  background-color: var(--panel-head);
  color: var(--muted);
  border-bottom: 1px solid var(--ink);
}
:root[data-theme^="dossier"] table,
:root[data-theme^="dossier"] table td,
:root[data-theme^="dossier"] table tr,
:root[data-theme^="dossier"] table thead,
:root[data-theme^="dossier"] table tbody { border-color: var(--line); }

/* The Files totals row is painted with a page-local navy that no variable reaches;
   repaint it in the palette's ink so the frozen footer belongs on paper. */
:root[data-theme^="dossier"] tfoot td { background: #1d1b16; color: #fbfaf5; }
:root[data-theme^="dossier"] tfoot td.text-left { color: #c9c3b4; }

/* =============================================================================
 * Dossier STRUCTURE (UI 1b), the docket-table treatment. Markup is untouched;
 * these are theme-scoped, so Light / Grey / Dark keep the plain layout and only
 * the case-file theme reads as a docket. Matches web/mockups/1-dossier.html.
 * ========================================================================== */

/* Files KPIs become "tally plates": flat, squared, with an ink spine down the
   left. The last plate, Not Categorized, is the one that wants marking, so it
   takes the exhibit-red spine and figure. */
:root[data-theme^="dossier"] .kpi {
  border-radius: 2px;
  border-left: 3px solid var(--ink);
  box-shadow: none;
}
:root[data-theme^="dossier"] .kpi .label { letter-spacing: .14em; }
:root[data-theme^="dossier"] .kpi:last-child { border-left-color: var(--brand); }
:root[data-theme^="dossier"] .kpi:last-child .value { color: var(--brand); }

/* Docket rows. The subset, the custodian, is the exhibit line, set in
   exhibit-red monospace; every count is tabular data, monospaced so the figures
   line up the way a docket's do, and kept centred under their column headers. The
   ink header rule and ink footer already ship above. */
:root[data-theme^="dossier"] .subset .name {
  color: var(--brand);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px;
}
:root[data-theme^="dossier"] tbody td:not(.text-left),
:root[data-theme^="dossier"] tfoot td:not(.text-left) {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}

/* View as an exhibit sheet. The viewer header names the document like a sheet
   head, a serif title with the exhibit marker beside it, and the Information
   panel reads as the custody record. Sticker element lives in view.html but is
   inert (display:none) on every theme but this one. */
.viewer-title .doc-name .exhibit-sticker { display: none; }
:root[data-theme^="dossier"] .viewer-title .doc-name #viewerTitle {
  font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  font-weight: 600;
}
:root[data-theme^="dossier"] .viewer-title .doc-name .exhibit-sticker {
  display: inline-block;
  flex-shrink: 0;
  overflow: visible;
  font: 700 10.5px/1 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .05em;
  color: #fbfaf5;
  background: var(--brand);
  padding: 5px 8px;
  border-radius: 2px;
  transform: rotate(-1.5deg);
  box-shadow: 0 1px 0 rgba(29, 27, 22, .18);
}
/* Custody record: the metadata rules go from a pale dashed grid to quiet solid
   hairlines, so the panel reads as a filled-in sheet rather than a form. */
:root[data-theme^="dossier"] .info-row { border-bottom: 1px solid var(--line); }
:root[data-theme^="dossier"] .info-row .k { letter-spacing: .04em; }

/* A few surfaces are painted with a hardcoded pale fill rather than through a
   variable, table header rows and the account-menu popup. They would glare on a
   dark surface, so they are repainted here in one place, using each theme's own
   --panel-head/--surface so grey and dark each get their matching shade. Scoped
   to the two dark-ish themes, so light is untouched. */
:root[data-theme="dossier-dark"] thead th,
:root[data-theme="dossier-dark"] table th {
  background-color: var(--panel-head);
  color: var(--muted, #94a3b8);
}
:root[data-theme="dossier-dark"] .user-dropdown {
  background: var(--surface);
  color: var(--text, var(--ink));
  border-color: var(--border, var(--line));
}
:root[data-theme="dossier-dark"] .user-dropdown .menu-item { color: var(--text, var(--ink)); }
:root[data-theme="dossier-dark"] .user-dropdown .menu-item:hover { background: rgba(255, 255, 255, .06); }

/* GRID LINES. Several screens draw table and cell borders with a hardcoded pale
   colour (#eef2f7, #e2e8f0, …). On a dark surface those become harsh bright lines
   that fight the content. Pull every table border back to the theme's own line
   colour so the grid reads as a quiet divider, the way it does in the light theme.
   Column rules too (the vertical grid on the results tables). */
:root[data-theme="dossier-dark"] table,
:root[data-theme="dossier-dark"] table td,
:root[data-theme="dossier-dark"] table tr,
:root[data-theme="dossier-dark"] table thead,
:root[data-theme="dossier-dark"] table tbody { border-color: var(--line); }

/* Row hover on the dark themes: a faint light wash rather than whatever pale fill
   the light theme used, which would flash bright. */
:root[data-theme="dossier-dark"] tbody tr:hover { background: var(--row-hover); }

@media (max-width: 880px) {
  :root { --chrome-pad-x: 14px; }
  .topbar { gap: 10px; }
  .topbar .brand { font-size: 16px; }
  .topbar .admin-tabs { gap: 4px; }
  .topbar .admin-tabs a { padding: 6px 10px; font-size: 13px; }

  /* Collapse the reviewer tabs behind the hamburger. Owned here so the admin
     screens (whose toggle account-menu.js injects) get the same behaviour as the
     reviewer screens, instead of overflowing their tabs off the edge. */
  .topbar .nav-toggle { display: inline-flex; margin-left: auto; }
  .topbar .nav-tabs {
    position: fixed; top: var(--chrome-height); left: 0; right: 0;
    flex-direction: column; gap: 4px; margin-left: 0;
    background: var(--chrome-navy-900);
    padding: 10px 12px 14px;
    border-top: 1px solid rgba(255, 255, 255, .10);
    box-shadow: 0 16px 28px rgba(0, 0, 0, .38);
    display: none; z-index: 60;
  }
  .topbar.nav-open .nav-tabs { display: flex; }
  .topbar .nav-tabs a { width: 100%; padding: 8px 12px; font-size: 13px; }
  .topbar .spacer { display: none; }
  .topbar .user-chip .who, .topbar .user-chip .caret { display: none; }
  .topbar .user-chip { padding: 5px; gap: 0; }
}

/* -----------------------------------------------------------------------------
 * Session-expired panel (web/shell.js showSessionExpired).
 *
 * Shown when a 401 reaches the running application: the whole UI is greyed out
 * behind a scrim so nothing underneath can be clicked, and the only control is
 * "sign in again". Themed through the same tokens as the rest of the chrome, so
 * it reads as part of the application in light, dark and grey alike. The z-index
 * sits above the media dock's floating panel (which has no explicit stacking of
 * its own but can float over content).
 * -------------------------------------------------------------------------- */
.session-expired-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2147483000;           /* above every screen, menu and the media dock */
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(8, 12, 22, .55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  animation: session-expired-fade .16s ease-out;
}
.session-expired-card {
  width: min(420px, 100%);
  box-sizing: border-box;
  background: var(--card, #fbfaf5);
  color: var(--text, #1d1b16);
  border: 1px solid var(--border, #c8c3b2);
  border-radius: 12px;
  box-shadow: var(--shadow-hover, 0 10px 28px rgba(0, 0, 0, .2));
  padding: 26px 26px 22px;
  text-align: left;
}
.session-expired-card h2 {
  margin: 0 0 8px;
  font-size: 19px;
  font-weight: 650;
  color: var(--text, #1d1b16);
}
.session-expired-card p {
  margin: 0 0 20px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted, #5b574c);
}
.session-expired-signin {
  appearance: none;
  border: none;
  cursor: pointer;
  background: var(--brand, #9a2f28);
  color: #fff;
  font: inherit;
  font-weight: 600;
  padding: 10px 18px;
  border-radius: 8px;
}
.session-expired-signin:hover { filter: brightness(1.06); }
.session-expired-signin:focus-visible { outline: 2px solid var(--brand, #9a2f28); outline-offset: 2px; }

@keyframes session-expired-fade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .session-expired-backdrop { animation: none; }
}

/* -----------------------------------------------------------------------------
 * App version tag in the site footer. A quiet monospace build stamp after the
 * copyright line; theme-neutral (uses --muted), so it reads on every theme. Bump
 * the number in the footers (one string, like the copyright year). See the
 * footer <span class="app-version"> in each web/*.html page.
 * -------------------------------------------------------------------------- */
.app-version {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: .92em;
  color: var(--muted);
  white-space: nowrap;
}
/* Separator only once the span is filled (version.js stamps it), so a footer
   shown before the stamp, or if the script fails to load, has no dangling dot. */
.app-version:not(:empty)::before { content: "·"; margin: 0 .5em; opacity: .55; }

/* -----------------------------------------------------------------------------
 * Dossier Dark chrome tweaks. The structure rules above (shared with the paper
 * Dossier via [data-theme^="dossier"]) paint an ink bar and an ink totals footer
 * that need adjusting for a page that is itself dark: the bar takes a hairline to
 * lift off the page, and the footer a darker band so the totals row still reads as
 * a distinct row rather than blending into the dark table.
 * -------------------------------------------------------------------------- */
:root[data-theme="dossier-dark"] .topbar { border-bottom: 1px solid #39332a; }
:root[data-theme="dossier-dark"] tfoot td { background: #0f0d09; color: #ece7db; }
:root[data-theme="dossier-dark"] tfoot td.text-left { color: #a89f8b; }

/* -----------------------------------------------------------------------------
 * Dossier Dark, app-wide fixes for elements the pages hard-coded light. The
 * screens theme through tokens, but a few common patterns set literal light
 * values that would glare on ink. These catch the frequent ones globally
 * (chrome.css loads last, so equal-specificity page rules yield to these).
 * -------------------------------------------------------------------------- */
/* Form controls: no white boxes on ink. */
:root[data-theme="dossier-dark"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
:root[data-theme="dossier-dark"] textarea,
:root[data-theme="dossier-dark"] select {
  background-color: var(--surface);
  color: var(--text);
  border-color: var(--border);
}
:root[data-theme="dossier-dark"] input::placeholder,
:root[data-theme="dossier-dark"] textarea::placeholder { color: var(--muted); }

/* The destructive-action hover, repeated across many screens as a pale red block. */
:root[data-theme="dossier-dark"] .menu-item.danger:hover,
:root[data-theme="dossier-dark"] .icon-act.del:hover { background: var(--red-soft); }

/* -----------------------------------------------------------------------------
 * Dossier Dark, recurring light chips, icons, hovers and pale sub-panels that
 * the pages hard-coded. Class names recur across screens, so these catch them in
 * one place (chrome.css loads last, so equal-specificity page rules yield).
 * -------------------------------------------------------------------------- */
/* Circular delete-confirm disc, and file-type badges (MSG / EML / PDF). */
:root[data-theme="dossier-dark"] .confirm-icon,
:root[data-theme="dossier-dark"] .doc-row .type,
:root[data-theme="dossier-dark"] .rel-child .type { background: var(--red-soft); color: #e79a90; }
/* The "not categorized" status disc. */
:root[data-theme="dossier-dark"] .status.none { background: var(--slate-soft); }
/* Pale cancel / secondary hovers, and the pale close/delete hovers. */
:root[data-theme="dossier-dark"] .btn-cancel:hover,
:root[data-theme="dossier-dark"] .cancel-btn:hover,
:root[data-theme="dossier-dark"] .btn-ghost:hover,
:root[data-theme="dossier-dark"] .btn-secondary:hover { background: var(--row-hover); }
:root[data-theme="dossier-dark"] .modal-close:hover,
:root[data-theme="dossier-dark"] .notes-close:hover,
:root[data-theme="dossier-dark"] .save-close:hover,
:root[data-theme="dossier-dark"] .adv-close:hover,
:root[data-theme="dossier-dark"] .note-icon-btn.del:hover { background: var(--red-soft); }
/* Pale near-white sub-panels and headers used across screens. */
:root[data-theme="dossier-dark"] .snippet-row td,
:root[data-theme="dossier-dark"] .coll-head { background: var(--panel-head); }
/* Status tiles (Overlays) become washes of their own hue rather than near-white. */
:root[data-theme="dossier-dark"] .tile.ok { background: var(--green-soft); border-color: var(--border); }
:root[data-theme="dossier-dark"] .tile.bad { background: var(--amber-soft); border-color: var(--border); }

/* Amber note/warning banners (view.html .dl-warning, .tx-note): dark-amber text
   is unreadable over the translucent amber wash on ink, so lift it on dark. */
:root[data-theme="dossier-dark"] .dl-warning,
:root[data-theme="dossier-dark"] .tx-note { color: #d8b46a; }

/* -----------------------------------------------------------------------------
 * Dossier Dark, semantic chips, tags, badges and banners. The pages colour these
 * with light tints + dark text: correct on paper, unreadable on ink. On the dark
 * theme give each a translucent wash of its own hue and a lightened label. Grouped
 * by meaning; the class names recur across screens, so these catch them all.
 * -------------------------------------------------------------------------- */
/* GREEN, active / applied / editor / clean / ok */
:root[data-theme="dossier-dark"] .pill.active,
:root[data-theme="dossier-dark"] .pill.applied,
:root[data-theme="dossier-dark"] .role-pill.editor,
:root[data-theme="dossier-dark"] .coverage.clean,
:root[data-theme="dossier-dark"] .msg.ok { background: var(--green-soft); color: #9ec98a; border-color: var(--border); }
/* AMBER, pending / owner / limited / frozen / coverage */
:root[data-theme="dossier-dark"] .pill.pending,
:root[data-theme="dossier-dark"] .pill.owner,
:root[data-theme="dossier-dark"] .pill.limited,
:root[data-theme="dossier-dark"] .tag.frozen,
:root[data-theme="dossier-dark"] .coverage { background: var(--amber-soft); color: #d8b46a; border-color: var(--border); }
/* RED, failed / pdf / off-tag / type badges / restore-warning / warn disc */
:root[data-theme="dossier-dark"] .pill.failed,
:root[data-theme="dossier-dark"] .ext-pdf,
:root[data-theme="dossier-dark"] .tag.off,
:root[data-theme="dossier-dark"] .doc-leaf .d-type,
:root[data-theme="dossier-dark"] .restore-warning,
:root[data-theme="dossier-dark"] .modal .warn-ico { background: var(--red-soft); color: #e79a90; border-color: var(--border); }
/* VIOLET, sub / via / owner-role / mp3 / tag / same / field-hit key */
:root[data-theme="dossier-dark"] .pill.sub,
:root[data-theme="dossier-dark"] .via,
:root[data-theme="dossier-dark"] .role-pill.owner,
:root[data-theme="dossier-dark"] .ext-mp3,
:root[data-theme="dossier-dark"] .tag,
:root[data-theme="dossier-dark"] .pill.same,
:root[data-theme="dossier-dark"] .field-hit .fk { background: var(--violet-soft); color: #bda9dd; }
/* NEUTRAL / cool, off / canceled / analysed / viewer role / shared / code */
:root[data-theme="dossier-dark"] .pill.off,
:root[data-theme="dossier-dark"] .pill.canceled,
:root[data-theme="dossier-dark"] .pill.analysed,
:root[data-theme="dossier-dark"] .role-pill.viewer,
:root[data-theme="dossier-dark"] .folder-row .shared-tag,
:root[data-theme="dossier-dark"] code { background: var(--slate-soft); color: var(--muted); }
/* ERROR banners */
:root[data-theme="dossier-dark"] .error,
:root[data-theme="dossier-dark"] .msg.err,
:root[data-theme="dossier-dark"] .notice.err { background: var(--red-soft); color: #e79a90; border-color: var(--border); }
:root[data-theme="dossier-dark"] .field-hit { color: var(--muted); }

/* Dossier Dark, the remaining status banners/badges (notice.*, pill.none, ext-other). */
:root[data-theme="dossier-dark"] .notice.ok { background: var(--green-soft); color: #9ec98a; border-color: var(--border); }
:root[data-theme="dossier-dark"] .notice.warn { background: var(--amber-soft); color: #d8b46a; border-color: var(--border); }
:root[data-theme="dossier-dark"] .pill.none { background: var(--red-soft); color: #e79a90; }
:root[data-theme="dossier-dark"] .ext-other { background: var(--slate-soft); color: var(--muted); }

/* Dark overrides for admin sub-page classes, .flag/.dec (Duplicates), .drop
   (Overlays, Upload), and .grant-head plus the access/grant text (Sub-users), used
   to live here, keyed on generic class names in this GLOBAL sheet. That is the same
   latent trap as the old .bar collision: one rule here reaches any screen that
   reuses the name. They now live in each screen's own <style>, which the shell keeps
   mounted only while that screen is up (shell.js), so a generic name can no longer
   leak across screens. Genuinely-shared components (.notice, .pill, .ext-other)
   stay above; they are meant to be global. */

/* -----------------------------------------------------------------------------
 * The help control, one definition for every screen that offers one.
 *
 * Each screen brought its own modal idiom, Workspace has .modal-overlay, view.html
 * has .confirm-overlay, Files had none at all. Four hand-rolled help dialogs would
 * have been four places for the next wording change to be missed, so the button,
 * the dialog and their behavior are shared here and in help.js; a screen supplies
 * only its content. This is a genuinely global component, like .notice and .pill.
 *
 * Deliberately NOT a bare circled "i". On the Search toolbar an unlabeled disc sat
 * beside three labeled buttons and read as a status badge rather than a control,
 * and filled in the exhibit red it read as a warning. The word carries it.
 * -------------------------------------------------------------------------- */
.help-btn { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; background: var(--brand-soft); border: 1px solid var(--brand); border-radius: 999px; padding: 6px 13px 6px 10px; font-family: inherit; font-weight: 700; font-size: 13px; line-height: 1.2; color: var(--brand); cursor: pointer; transition: background 0.15s, box-shadow 0.15s; }
/* Hover lightens rather than filling with the accent: a solid --brand fill carries
   white text at only 3.5:1 on the dark theme, so one inverted state cannot pass
   contrast on both themes. */
.help-btn:hover { background: var(--surface); box-shadow: 0 0 0 3px var(--brand-soft); }
.help-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--brand-soft), 0 0 0 4px var(--brand); }
.help-btn svg { flex-shrink: 0; }
/* Help sits at the right edge of its header on every screen. Most headers have a
   spacer that gets it there; this is for the ones whose row is only a heading. */
.help-btn.push-right { margin-left: auto; }

/* Above the page modals (view.html's .confirm-overlay is 120) but below the media
   dock, so opening help over an open dialog still lands on top. */
.help-overlay { position: fixed; inset: 0; background: rgba(15, 32, 56, 0.45); display: none; align-items: center; justify-content: center; padding: 20px; z-index: 200; }
.help-overlay.open { display: flex; }
.help-modal { background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 18px 50px rgba(0, 0, 0, .28); width: min(680px, 100%); max-height: min(80vh, 720px); display: flex; flex-direction: column; overflow: hidden; }
.help-head { display: flex; align-items: center; gap: 12px; padding: 15px 20px; border-bottom: 1px solid var(--border); background: var(--panel-head); }
.help-head h2 { margin: 0; font-size: 17px; font-weight: 700; flex: 1; }
.help-close { border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: 8px; padding: 5px; display: flex; line-height: 0; }
.help-close:hover { background: var(--row-hover); color: var(--text); }
.help-body { padding: 18px 20px 22px; overflow-y: auto; font-size: 14px; line-height: 1.6; }
.help-body h3 { margin: 20px 0 7px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.help-body h3:first-child { margin-top: 0; }
.help-body p { margin: 0 0 10px; }
.help-body p:last-child, .help-body ul:last-child { margin-bottom: 0; }
.help-body ul { margin: 0 0 10px; padding-left: 20px; }
.help-body li { margin: 0 0 6px; }
.help-body ul ul { margin: 6px 0 0; }
/* Search's help names keys and query syntax, so these have to carry over from the
   rules that used to live in Search.html. */
.help-body kbd { font-family: inherit; font-size: 11.5px; font-weight: 600; background: var(--panel-head); border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px; color: var(--text); }
.help-body code { font-size: 12.5px; background: var(--panel-head); border-radius: 5px; padding: 1px 5px; }
