/* ============================================================
   Winnrs house style — one shared look for every app, every page.
   Home: backbone /static, served at team.winnrs.co/static
   Grown in pieces (see UI_KIT_PLAN.md). Phase A: header + boxes + page basics.

   How to use on a page:
     <link rel="stylesheet" href="https://team.winnrs.co/static/winnrs-ui.css">
   Then use the wui- classes below, or let winnrs-header.js draw the header.

   Everything is prefixed "wui-" so it never clashes with a page's own styles.
   Change a colour or size once here → every app updates.
   ============================================================ */

:root {
  --header-bg: #1a1a2e;   /* the dark top bar */
  --page-bg:   #f4f5f8;   /* the light page behind everything */
  --surface:   #ffffff;   /* white boxes */
  --border:    #e4e6ef;   /* thin box outline */
  --radius:    14px;      /* rounded corners */
  --text:      #1a1a2e;   /* normal words */
  --text-muted:#6b7280;   /* quieter words */
  --accent:    #6d4aff;   /* the one highlight colour (links, focus) */
  --accent-dark:#5538e0;

  /* ── THE COLOUR A NEGATIVE NUMBER SHOWS IN. THE ONE HOME FOR IT. ──────────
     Randy, 2026-09-02: a negative shows as red (120), and becomes -120 again
     the moment you click into the box.

     Before this it was hand-written SEVEN times in six files across four apps
     — counted that day over every .html/.js/.css in Documents\Winnrs outside
     node_modules and worktrees, never a typed folder list — and had already
     drifted into TWO different reds (#c0392b and #dc2626). Picking one here
     ends that; #c0392b is the one winnrs-ui.css already uses for an error
     message (.wui-state-error below), so a negative amount and a refusal now
     speak in the same red instead of two.

     The BRACKETS are not here, and that is deliberate: CSS can paint a colour
     but it cannot read -120 out of a box. That half lives in the one file that
     can — winnrs-numbers.js, on this same shelf — and it names this class
     without ever naming a colour. Mottos a, b, c, n. */
  --negative:  #c0392b;

  /* --danger: SOMETHING WENT WRONG. Added 2026-09-07, §11 JOB 188's sitting.
     🔴 IT IS NOT A SECOND NAME FOR --negative, AND KEEPING THEM APART IS THE
     WHOLE POINT. --negative means "this NUMBER is below zero". --danger means
     "this MESSAGE is an error". They happen to be the same red today. The day
     Randy wants a different red for a minus figure, every error message in the
     fleet would have followed it — which is matching by the VALUE instead of
     by what the thing MEANS (mottos a, d).
     ⚠️ THIS DOES NOT UNDO THE DECISION WRITTEN 20 LINES ABOVE, and it is worth
     saying so rather than letting a later reader think it was overruled. That
     note chose #c0392b so "a negative amount and a refusal speak in the same
     red instead of two". They still do — same value, on purpose. What it never
     said is that they must share a NAME, and two names holding one value is
     what keeps that choice REVERSIBLE instead of welded shut.
     🔴 AND THE NAME IS NOT INVENTED HERE. It was already hand-typed in four
     places before this line existed, and it had ALREADY drifted into four
     different reds — counted over every .css and .html in Documents\Winnrs
     outside worktrees and node_modules, never a typed folder list:
         client database/static/db/relabel.html:13        #c0392b
         photo selection/styles.css:12                    #a53b3b
         report drill through (old)/chatbot/static/admin.html:17   #ef4444
         report drill through (old)/drill-through-wizard/styles.html:10  #dc2626
     This gives that existing name ONE home (mottos b, c, n). The value is the
     one the live client database already uses.
     ✅ --good and --warn WERE in exactly the same state and now have their own
     home too — see the two lines below. §11 JOB 196, 2026-09-09. */
  --danger:    #c0392b;

  /* --warn: SOMETHING NEEDS A SECOND LOOK, and nothing has gone wrong yet.
     Added 2026-09-09, §11 JOB 196, the sitting that gave --danger its home
     having named these two as the next pair.
     🔴 THE NAME WAS NOT INVENTED HERE EITHER. It was already hand-typed in FOUR
     files before this line existed, in THREE different shades — counted over
     every .css, .html and .js in Documents\Winnrs outside .git and
     node_modules, never a typed folder list:
         client database/static/db/relabel.html:13                       #b45309
         photo selection/styles.css:11                                   #9b6b16
         report drill through (old)/drill-through-wizard/styles.html     #d97706
         report drill through (old)/report-webapp/styles.html            #d97706
     ⚠️ THE ROADMAP ROW SAID TWO FILES. A sweep of the whole fleet says four, in
     three shades.
     🔴 THE VALUE IS CHOSEN BY THE SAME RULE --danger USED, not by taste: the one
     the live client database already uses. So relabel.html keeps exactly the
     amber it has today and simply stops typing it out.
     🔴 AND NOTHING ELSE WAS TOUCHED, ON PURPOSE, NOT BY OVERSIGHT (motto o).
     `photo selection` is RETIRING — Randy, 2026-09-01: "no, i change my mind,
     the photo selection project will be retired" — and its page does not load
     this file at all, so pointing it here would leave it with no colour at all.
     `report drill through (old)` is covered by
     `..\master map\DEAD_FOLDERS_DO_NOT_TOUCH.md`. Both are left alone by the
     rules, not missed by a sweep. */
  --warn:      #b45309;

  /* --good: IT WORKED. Added 2026-09-09, §11 JOB 196.
     🔴 THIS ONE HAD NOT DRIFTED YET, WHICH IS THE POINT OF DOING IT NOW. The
     sweep above found the name written in exactly ONE file,
     `client database/static/db/relabel.html:13` at #1f9d55, so giving it a home
     today changes nothing anybody can see and stops the second copy ever being
     typed. Every other success message in the fleet types its own green with no
     shared name to point at — that is the drift this line exists to prevent
     rather than to repair (mottos b, c, n; and motto f — cheaper now than after
     the fourth copy). */
  --good:      #1f9d55;

  --wui-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --btn-radius: 8px;      /* rounded corners for buttons/fields (smaller than card radius) */

  /* ── WHICH POP-UP SITS ON TOP OF WHICH. THE ONE HOME FOR THAT ORDER. ──────
     Every page that draws one of these also loads this file (checked over all
     11 of them, 2026-09-02). Before this, the order lived as a COMMENT in
     error-report.js and six numbers typed into five other files — and a comment
     cannot stop the next number being typed. AUDIT_FINDINGS.md
     CD9_static_js_css/SLICE-08. Mottos a, b, h.

     Read the list downwards: each line is drawn on top of the one above it.
     To add a pop-up, add a line here. NEVER type a stacking number into a file.

     ⚠️ THE ONE ORDER THAT CHANGED, AND IT IS THE BUG THE FINDING NAMES.
     The Lock dialog used to be drawn ON TOP of the "are you sure?" box. So
     opening Lock on a journal page and then pressing the browser's Back button
     drew the "Are you sure you want to go back?" question UNDERNEATH the Lock
     dialog's grey backdrop — invisible, and clicking it shut the Lock dialog
     instead of answering the question. A box you MUST answer is now the top of
     the ladder, always. Every other order below is exactly what it already was. */
  --wz-refusal-pill:  9989;   /* the red "your save was refused" tab            */
  --wz-refusal:       9990;   /* the panel that says WHY it was refused         */
                              /*   (deliberately below the table's own pop-ups  */
                              /*    at 9999 — that was decided in S4.8 and is   */
                              /*    NOT changed here)                           */
  --wz-banner:       99997;   /* the orange "you are previewing" strip on top   */
  --wz-card:         99998;   /* the "unsaved work found" card, bottom right    */
  --wz-dialog:       99999;   /* the Lock dialog and its grey backdrop          */
  --wz-ask:         100000;   /* a box you MUST answer. ALWAYS THE TOP.         */
}

/* ── Page basics ──────────────────────────────────────────── */
/* Add class "wui" to <body> to opt a page into the house look. */
body.wui {
  margin: 0;
  background: var(--page-bg);
  color: var(--text);
  font-family: var(--wui-font);
  -webkit-font-smoothing: antialiased;
}

/* Full-width content area under the header (UI_KIT_PLAN.md §4a — no side
   gutters, Randy 2026-07-24; the gap ITSELF zeroed 2026-07-29, General rule 5).
   Fills the screen edge to edge, no side padding at all. Changed here ONCE so
   every page is full-width by default — no page needs its own opt-out.
   The one written exception (a centred sign-in card, static/db/index.html)
   restores its own side padding locally — see that page's own <style>. */
.wui-page {
  max-width: none;
  padding: 28px 0 48px;
}

/* ── The dark header (drawn by winnrs-header.js) ──────────── */
.wui-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 52px;
  flex-shrink: 0;
  padding: 0 20px;
  background: var(--header-bg);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 1000;
}
.wui-header-left  { display: flex; align-items: center; gap: 12px; min-width: 0; }
.wui-header-right { display: flex; align-items: center; gap: 10px; }

.wui-header-back {
  color: #c8c8e8; text-decoration: none; font-size: 0.9rem; font-weight: 600;
  white-space: nowrap;
}
.wui-header-back:hover { color: #fff; }

/* The Winnrs mark. It used to be painted solid white here
   (`filter: brightness(0) invert(1)`), which assumed a see-through picture. The
   picture is actually a black mark on a WHITE square, so that line turned the
   whole square white — a blank white circle in every header (Randy, 2026-08-01).
   It now sits in its own white circle with the real mark showing. That is also
   exactly what db.winnrs.co's branding.js already forces onto this image, so the
   mark finally looks the same on every app, branding.js loaded or not. */
.wui-header-logo {
  width: 26px; height: 26px; object-fit: contain;
  background: #fff; border-radius: 50%;
}
.wui-header-title {
  font-weight: 700; font-size: 1.02rem; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── The nav trail (winnrs-header.js, UI_KIT_PLAN.md §5a) ─── */
/* Sits after the page name: `Settings › Reports-to ▾`. Deliberately quieter than
   the page name — it's the route you took, not the thing you're looking at. */
.wui-trail { display: flex; align-items: center; gap: 4px; min-width: 0; }
.wui-trail-sep { color: rgba(255,255,255,0.35); font-size: 0.9rem; }
.wui-trail-step { position: relative; display: flex; align-items: center; }
.wui-trail-link {
  color: #c8c8e8; text-decoration: none; font-size: 0.88rem; font-weight: 600;
  white-space: nowrap; padding: 4px 2px;
}
.wui-trail-link:hover { color: #fff; }
.wui-trail-current .wui-trail-link { color: #fff; }
.wui-trail-link-btn {
  background: none; border: none; font-family: inherit; cursor: pointer;
}
.wui-trail-caret {
  background: none; border: none; color: rgba(255,255,255,0.55);
  cursor: pointer; font-size: 0.7rem; padding: 4px 3px; line-height: 1;
  font-family: inherit;
}
.wui-trail-caret:hover { color: #fff; }
.wui-trail-menu {
  position: absolute; top: 28px; left: 0; z-index: 200;
  min-width: 190px; max-height: 60vh; overflow-y: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(16,24,40,0.18);
  padding: 4px 0;
}
.wui-trail-item {
  display: block; padding: 8px 14px; font-size: 0.86rem;
  color: var(--text); text-decoration: none; white-space: nowrap;
}
.wui-trail-item:hover { background: var(--page-bg); }
.wui-trail-item-on { font-weight: 700; }
/* "Loading…" / "Couldn't load that list." while a live list is being fetched. */
.wui-trail-empty {
  padding: 10px 14px; font-size: 0.84rem;
  color: var(--text-muted); white-space: nowrap;
}
/* Heading above a group in the dropdown (e.g. "Go to another app") — keeps this
   app's own pages visually apart from jumps to other apps, which otherwise read
   as one confusing list when two of them share a name. */
.wui-trail-group {
  margin-top: 4px; padding: 8px 14px 4px;
  border-top: 1px solid var(--border);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted); white-space: nowrap;
}

/* Small screens: the page name matters more than the route — hide all but the
   step you're on, so the header never squashes the name out of view. */
@media (max-width: 720px) {
  .wui-trail-sep, .wui-trail-step:not(.wui-trail-current) { display: none; }
}

/* Optional client-name badge (db.winnrs.co's per-client tool pages). */
.wui-header-client { font-size: 0.85rem; color: #ccc; white-space: nowrap; }
.wui-header-client strong { color: #fff; }

/* Signed-in person chip on the right. Clicking it opens the account menu
   (winnrs-header.js) — switch to another Google account, or sign out. */
.wui-header-user {
  display: flex; align-items: center; gap: 10px; font-size: 0.9rem;
  background: none; border: none; color: inherit; font-family: inherit;
  padding: 4px 8px; border-radius: 8px; cursor: pointer;
}
.wui-header-user:hover { background: rgba(255,255,255,0.12); }
.wui-username { color: #fff; white-space: nowrap; }
.wui-user-caret { color: rgba(255,255,255,0.6); font-size: 0.7rem; }

/* The account menu itself. */
.wui-usermenu-wrap { position: relative; display: flex; align-items: center; }
.wui-usermenu {
  position: absolute; top: 44px; right: 0; z-index: 1200;
  min-width: 240px; max-width: 320px;
  background: #fff; color: #1c1c2b;
  border: 1px solid rgba(0,0,0,0.1); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.25);
  padding: 6px; overflow: hidden;
}
.wui-usermenu-head {
  padding: 8px 10px 10px; border-bottom: 1px solid rgba(0,0,0,0.08); margin-bottom: 6px;
}
.wui-usermenu-label {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: #6b6b80; margin-bottom: 3px;
}
.wui-usermenu-who {
  font-size: 0.85rem; color: #1c1c2b; font-weight: 600;
  word-break: break-all; line-height: 1.35;
}
.wui-usermenu-item {
  display: block; width: 100%; text-align: left;
  background: none; border: none; font-family: inherit;
  padding: 9px 10px; border-radius: 7px;
  font-size: 0.88rem; color: #1c1c2b; text-decoration: none; cursor: pointer;
}
.wui-usermenu-item:hover { background: #f0f0f6; }
.wui-usermenu-note {
  padding: 6px 10px 4px; font-size: 0.74rem; color: #6b6b80; line-height: 1.4;
}
.wui-avatar     { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }
.wui-avatar-ph  {
  width: 32px; height: 32px; border-radius: 50%; background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; color: #fff; font-size: 0.85rem;
}

/* Extra buttons / links on the right of the header. */
.wui-header-link, .wui-header-btn {
  background: rgba(255,255,255,0.12); color: #fff; border: none;
  padding: 8px 14px; border-radius: 8px; font-size: 0.85rem; font-weight: 600;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  font-family: inherit;
}
.wui-header-link:hover, .wui-header-btn:hover { background: rgba(255,255,255,0.22); }

/* ── The flag bell (winnrs-header.js, UI_KIT_PLAN.md §5b) ─── */
.wui-bell-wrap { position: relative; }
.wui-bell-btn {
  position: relative;
  background: rgba(255,255,255,0.12); border: none; color: #fff;
  width: 34px; height: 34px; border-radius: 8px; font-size: 1rem;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.wui-bell-btn:hover { background: rgba(255,255,255,0.22); }
.wui-bell-badge {
  position: absolute; top: -4px; right: -4px;
  background: #e0413f; color: #fff; font-size: 0.68rem; font-weight: 700;
  min-width: 16px; height: 16px; padding: 0 3px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  line-height: 1; box-shadow: 0 0 0 2px var(--header-bg);
}
.wui-bell-panel {
  position: absolute; top: 42px; right: 0; z-index: 200;
  width: 340px; max-height: 420px; overflow-y: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(16,24,40,0.18);
}
.wui-bell-empty { padding: 18px; color: var(--text-muted); font-size: 0.88rem; text-align: center; }
.wui-bell-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border);
}
.wui-bell-row:last-child { border-bottom: none; }
.wui-bell-row-main { flex: 1; min-width: 0; text-decoration: none; color: inherit; cursor: pointer; }
.wui-bell-row-title { font-weight: 600; font-size: 0.88rem; color: var(--text); }
.wui-bell-row-meta { font-size: 0.76rem; color: var(--text-muted); margin-top: 2px; }
.wui-bell-row-detail { font-size: 0.8rem; color: var(--text-muted); margin-top: 4px; }
.wui-bell-fix {
  flex-shrink: 0; background: var(--page-bg); border: 1px solid var(--border);
  border-radius: 6px; padding: 4px 8px; font-size: 0.72rem; font-weight: 600;
  color: var(--text-muted); cursor: pointer; white-space: nowrap;
}
.wui-bell-fix:hover { background: var(--border); color: var(--text); }

@media (max-width: 560px) {
  .wui-bell-panel { position: fixed; top: 60px; left: 12px; right: 12px; width: auto; }
}

/* ── Section boxes (the framed, padded content boxes) ─────── */
.wui-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: 0 1px 3px rgba(16,24,40,0.06);
}

/* ── Buttons ──────────────────────────────────────────────── */
/* Opt-in class — put it on a <button>, or an app's own button class can just
   copy these values (kept as one recipe so every app's buttons match). */
.wui-btn {
  padding: 8px 16px;
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  background: var(--surface);
  color: var(--text);
}
.wui-btn:hover:not(:disabled) { background: var(--page-bg); }
.wui-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* The one highlighted action on a page/panel (Save, Create, Submit). */
.wui-btn-primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.wui-btn-primary:hover:not(:disabled) { background: var(--accent-dark); border-color: var(--accent-dark); }

/* Smaller button (compact rows, in-table actions). */
.wui-btn-sm { padding: 6px 11px; font-size: 0.78rem; }

/* A destructive action (Delete selected, confirm-remove).
   🔴 THIRD RED, POINTED AT --danger — 2026-09-07, Randy's own "way A". Found
   while giving --danger its one home (§11 JOB 188's sitting): this class
   painted #ef4444/#dc2626, a THIRD shade beside --negative/--danger's
   #c0392b, inside the very file meant to end three copies of one red. Every
   danger button across the 8 screens that use it (client database's access,
   admin-hide-column, am, close, dc and sts screens, email service's index,
   backbone's own secrets.html) now shows the shared red instead of its own.
   No behaviour changes — a delete button still deletes exactly what it did.
   Randy's own words, asked plainly what the risk was: "only look change?" —
   yes, only look, and he chose to take it. */
.wui-btn-danger {
  background: var(--danger); color: #fff; border-color: var(--danger);
}
.wui-btn-danger:hover:not(:disabled) { background: #a52f22; border-color: #a52f22; }
.wui-btn-danger:disabled { background: var(--border); color: var(--text-muted); border-color: var(--border); }

/* Quiet delete — red words on a white pill, fills in on hover. */
.wui-btn-danger-outline { color: var(--danger); border-color: #e0b0ac; }
.wui-btn-danger-outline:hover:not(:disabled) { border-color: var(--danger); background: var(--surface); }

/* ── Fields (text/select/textarea) ───────────────────────── */
.wui-input {
  padding: 6px 10px;
  font-size: 0.85rem;
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  background: var(--surface);
  color: var(--text);
}
.wui-input:focus {
  outline: none;
  border-color: var(--accent);
}
/* A field that fills its table cell / filter column. */
.wui-input-full { width: 100%; }

/* ── The furniture around a full-height list page ─────────── */
/* 🔴 WHY THIS BLOCK IS HERE, AND IT WAS MEASURED, NEVER GUESSED. Every list
   page in the fleet hand-wrote the same heading, the same one-line message bar,
   the same "loading…" / "something went wrong" box and the same turning circle.
   Counted 2026-08-17 over all 71 pages that carry their own <style> — never a
   typed folder list: the turning circle appeared in 25 pages, the state box in
   23, the heading's h1 in 15, and inside Task Management's own 11 screens FIVE
   of these rules were byte-for-byte identical in all 11.

   `check_shared_files.py` reported 34 of those pairs at once and refused every
   save until they were judged. They were a copy. This is the merge (mottos b,
   c, g, n).

   ⚠️ NAMES ARE `wui-` PREFIXED ON PURPOSE — this file's own rule, at the top:
   "Everything is prefixed wui- so it never clashes with a page's own styles."
   Adding a bare `.state` here would land on every page in the fleet that
   happens to use that word, including ones nobody checked. Each page was
   renamed instead. */

/* The page's own heading strip: title on the left, badges/actions on the right.
   The padding below is the commonest of the three the pages used (6 of 11); a
   page that genuinely wants a different one still sets it in its own <style>,
   which is loaded after this file and so wins. */
.wui-panel-header {
  padding: 18px 24px 10px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
/* The same heading with nothing on its right: a title and a paragraph under it,
   stacked, no side padding. The client list and the staff list both wanted
   exactly this and both wrote it out for themselves, word for word. */
.wui-panel-header-plain {
  display: block;
  padding: 0;
  margin-bottom: 18px;
}
.wui-panel-header-plain .wui-sub { max-width: none; }

.wui-panel-header h1 { font-size: 1.25rem; margin-bottom: 3px; }
.wui-panel-header .wui-sub {
  color: var(--text-muted);
  font-size: .85rem;
  max-width: 720px;
}

/* One-line message bar under the heading — save results and errors. Starts
   hidden; `wui-msg-show` reveals it. */
.wui-msg { margin: 0 24px 8px; font-size: .85rem; display: none; white-space: pre-line; }
.wui-msg-show { display: block; }
.wui-msg-err  { color: var(--danger); }
.wui-msg-ok   { color: #15803d; }

/* The "loading…" / "nothing here" / "something went wrong" box that sits where
   the list will be. */
.wui-state { padding: 30px; text-align: center; color: var(--text-muted); font-size: .92rem; }
.wui-state-error { color: var(--danger); }

/* A negative number, anywhere in the fleet — a grid cell, a report line, an
   ordinary typing box. It shows as red (120); clicking into the box turns it
   back into -120. The BRACKETS are put on by winnrs-numbers.js on this same
   shelf; this rule only paints. Nothing else may colour a negative — a new
   hand-written `.neg { color: … }` is refused by backbone/check_ui_kit.py.
   Randy, 2026-09-02. */
.wui-neg { color: var(--negative); }

/* The turning circle shown while a page is fetching. */
.wui-spinner {
  width: 24px; height: 24px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  margin: 0 auto 10px;
  animation: wui-spin .8s linear infinite;
}
@keyframes wui-spin { to { transform: rotate(360deg); } }

/* A small pill beside a page title saying which build of a screen this is.
   Red = it writes to real records; amber = it only reads. Both colours were
   already in use, 4 pages each, so both are kept rather than one chosen. */
.wui-tag {
  display: inline-flex; align-items: center; gap: 6px;
  background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5;
  padding: 5px 12px; border-radius: 999px;
  font-size: .78rem; font-weight: 600; white-space: nowrap;
}
.wui-tag-quiet { background: #fef3c7; color: #92400e; border-color: #fcd34d; }

/* The vertical stack a full-height page puts its parts in. This class name was
   already `wui-` prefixed in two pages and had never actually been added to
   this file - so the shared name existed while the rule stayed copied. */
.wui-page-stack { width: 100%; display: flex; flex-direction: column; gap: 20px; }

/* The little dark bar that slides up at the bottom to say something was saved.
   Identical in 3 of backbone's own 4 pages before this. */
.wui-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: #1a1a2e; color: #fff; padding: 10px 18px;
  border-radius: 10px; font-size: .85rem; z-index: 200;
  animation: wui-fadein .25s;
}
@keyframes wui-fadein {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
}

/* ── A page that fills the screen and scrolls inside itself ─ */
/* Put `class="wui-full"` on the page's own <html> tag. Eleven screens in Task
   Management wrote these same five rules out for themselves; they are the
   difference between a page that scrolls as one long sheet and a page whose
   list scrolls under a heading that stays put.

   ⚠️ `:where(...)` IS NOT DECORATION. It makes these rules count for NOTHING in
   the "which rule wins" contest, exactly as the bare `*` and `#view-main` they
   replace did. Written the obvious way — `html.wui-full *` — the reset would
   suddenly outrank a page's own `h1 { margin-bottom: 3px; }` and flatten it.
   The whole point is that this changes no page's look at all. */
:where(html.wui-full), :where(html.wui-full) body { height: 100%; }
:where(html.wui-full) *,
:where(html.wui-full) *::before,
:where(html.wui-full) *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* The part under the heading that gets whatever height is left over... */
:where(html.wui-full) #view-main { flex: 1; display: flex; flex-direction: column; min-height: 0; }
/* ...and the box the table itself scrolls in, drawn by the shared toolbar. */
:where(html.wui-full) .tb-tablewrap { flex: 1; min-height: 0; overflow: auto; }

/* ── A page that is at least as tall as the screen ────────── */
/* Put `class="wui-tall"` on the page's own <html> tag. The front door's own
   three screens - the client list, the staff list and the Control Room - each
   wrote this same block out for themselves. Same `:where(...)` reason as
   `wui-full` above: these must not outrank anything a page says for itself. */
:where(html.wui-tall), :where(html.wui-tall) body { min-height: 100%; }
:where(html.wui-tall) *,
:where(html.wui-tall) *::before,
:where(html.wui-tall) *::after { box-sizing: border-box; margin: 0; padding: 0; }
:where(html.wui-tall) body { min-height: 100vh; display: flex; flex-direction: column; }

/* The strip that takes whatever height is left, and the column inside it that
   the list sits in. The client list and the staff list both wrote these two
   lines out for themselves, word for word. `min-height: 0` is the part that
   matters: without it the list's own scroll box grows past the bottom of the
   screen and cannot scroll down at all (measured on those pages, 2026-07-30 —
   3616px tall on a 900px screen). */
.wui-grow-row   { flex: 1; display: flex; width: 100%; min-height: 0; }
.wui-grow-stack { flex: 1; display: flex; flex-direction: column; gap: 20px; min-height: 0; }

/* ── A menu of clickable tiles ────────────────────────────── */
/* Two screens in the Database system wrote this out twice: the Admin settings
   menu and the Client menu. Every hover colour, every "not built yet" rule and
   the whole tile shape were the same; only three sizes differed, and those two
   pages still set those three for themselves below this file. */
.wui-menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
}
.wui-menu-card {
  display: flex; flex-direction: column; gap: 5px;
  background: #fafbfd;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 18px 16px;
  text-decoration: none;
  color: var(--text);
  cursor: pointer;
  transition: .12s;
}
.wui-menu-card:hover {
  background: #f1edff;
  border-color: var(--accent);
  transform: translateY(-1px);
}
.wui-menu-card .wui-menu-name { font-weight: 700; font-size: 1.02rem; }
.wui-menu-card .wui-menu-tag  { font-size: .72rem; color: var(--accent); font-weight: 700; margin-top: 4px; }

/* A tile for something not built yet: greyed out, and it does not react. */
.wui-menu-card.wui-menu-soon { opacity: .55; cursor: default; }
.wui-menu-card.wui-menu-soon:hover {
  background: #fafbfd; border-color: var(--border); transform: none;
}
.wui-menu-card.wui-menu-soon .wui-menu-tag { color: var(--text-muted); }

/* Small screens: let the header wrap instead of squashing. */
@media (max-width: 560px) {
  .wui-header { height: auto; padding: 10px 14px; flex-wrap: wrap; }
  .wui-page { padding: 20px 0 40px; }
}
