/* ============================================================================
   TENDER MANAGER — module stylesheet
   ============================================================================
   Ported from the departmental app's styles.css (Tender_Manager_Handover_
   2026-08-05). The brief was "the pages to be exact exact that in the proposed
   project", so the layout, density, colours and table grammar are reproduced
   rather than reinterpreted.

   WHAT CHANGED, AND WHY
   ---------------------
   * Every rule is scoped under .tm-page. The source owned the whole document;
     here it is one page inside MainLayoutMS, so unscoped element selectors
     (body, table, h1) would leak across the portal.
   * The source's #sidebar / #main / .toast / .banner rules are gone. The portal
     shell already provides navigation and chrome, and this module raises no
     toasts (BECAspire.Web/CLAUDE.md) — results are reported inline instead.
   * The palette is declared once on .tm-page and hangs off the portal's --BEC-*
     semantic tokens where an honest match exists, keeping the source hex as the
     fallback so the page still renders correctly if a token is renamed.

   NOT loaded globally: each Tender Manager page pulls it in through
   <HeadContent>, the same way css/modules/it-support-grid.css is used.
   ============================================================================ */

.tm-page {
    /* ── Palette ──────────────────────────────────────────────────────────
       Every colour now resolves through a --BEC-* token, with the original
       source hex kept only as the fallback so a renamed token degrades to
       something that still reads rather than to `unset`.

       The one deliberate non-mapping is --tm-highlight. It marks the sort
       indicator and the benchmark group band, both of which sit ON the navy
       header — and the brand blue on navy is illegible. The brand's own
       warning gold is used there instead of inventing a colour. */
    --tm-navy: var(--BEC-themePrimary, #1e3c72);
    --tm-navy-dark: var(--BEC-themeDark, #172c56);
    --tm-navy-soft: var(--BEC-themeSecondary, #2b4d81);
    --tm-accent: var(--BEC-colorBrandBackground, #0078d4);
    --tm-accent-hover: var(--BEC-colorBrandBackgroundHover, #106ebe);
    --tm-highlight: var(--BEC-Warning-Main, #ffb900);
    --tm-bg: var(--BEC-colorNeutralBackground3, #f5f5f5);
    --tm-card: var(--BEC-colorNeutralBackground1, #ffffff);
    --tm-border: var(--BEC-colorNeutralStroke1, #d1d1d1);
    --tm-text: var(--BEC-colorNeutralForeground1, #242424);
    --tm-muted: var(--BEC-colorNeutralForeground3, #616161);
    --tm-green: var(--BEC-colorPaletteGreenForeground1, #107c10);
    --tm-red: var(--BEC-colorPaletteRedForeground1, #bc2f32);
    --tm-amber: var(--BEC-colorPaletteYellowForeground1, #8a6c00);
    --tm-blue: var(--BEC-colorBrandForeground1, #0078d4);
    --tm-hover: var(--BEC-colorNeutralBackground3, #f5f5f5);

    /* Height of one data row, used to draw the empty rows below the last
       record. Kept as a variable so the two places that need to agree — the
       cell padding and the filler stripe — cannot drift apart. */
    --tm-row-h: 31px;

    color: var(--tm-text);
    font-size: 14px;

    /* ── Fill the viewport ───────────────────────────────────────────────
       The page is a flex column so the grid can take every pixel left below
       the header, and the scrollbar therefore sits at the bottom of the
       viewport instead of halfway up it when there are only a few rows.
       100dvh, not 100vh: on mobile Safari the toolbar collapse changes vh
       mid-scroll and the grid would resize under the user's finger. */
    display: flex;
    flex-direction: column;
    /* The portal header height is a token; what sits between it and this page
       (the layout's own padding) is not, so it is a single named number rather
       than a figure buried in a calc. If the grid ends up a little short or a
       little tall, --tm-chrome-gap is the one value to change. */
    min-height: calc(100dvh
                     - var(--BEC-layoutHeaderHeight, 60px)
                     - var(--tm-chrome-gap, 56px));
    padding-block: 10px 14px;
    padding-inline: 20px;
}

/* ---------- Page heading ----------
   Title, subtitle, filters and buttons share one band. Previously the filters
   sat on their own row below the title, which cost ~60px of vertical space on
   every page before a single record was visible. */
.tm-page .tm-head {
    display: flex;
    /* nowrap on purpose: the title must sit ON the filter line, not above it.
       The toolbar is the flexible half and wraps INSIDE itself when the filters
       run out of room, which keeps the title where it belongs. Below 1200px
       there is no honest way to fit both, so the whole band wraps instead. */
    flex-wrap: nowrap;
    align-items: flex-end;
    gap: 10px 18px;
    margin-block-end: 10px;
}
.tm-page .tm-head-title { flex: 0 0 auto; min-width: 0; }
.tm-page .tm-head .tm-toolbar { flex: 1 1 auto; min-width: 0; margin-block-end: 0; justify-content: flex-end; }

@media (max-width: 1200px) {
    .tm-page .tm-head { flex-wrap: wrap; }
    .tm-page .tm-head .tm-toolbar { justify-content: flex-start; }
}

.tm-page h1.tm-title {
    font-size: 20px; margin-block: 0; color: var(--tm-navy);
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
}
.tm-page .tm-sub { color: var(--tm-muted); font-size: 12.5px; margin-block-end: 0; }

/* ---------- The "what is this page" hover ----------
   Replaces the sentence that used to sit under every title. See TmInfo.razor
   for why it is a button and why the bubble is driven from a data attribute. */
.tm-page .tm-info {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; padding: 0; flex: 0 0 auto;
    border: none; border-radius: 50%; background: none; cursor: help;
    color: var(--tm-muted); font-family: inherit;
}
.tm-page .tm-info:hover, .tm-page .tm-info:focus-visible { color: var(--tm-accent); }
.tm-page .tm-info:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: 1px; }
.tm-page .tm-info .material-symbols-outlined { font-size: 18px; }

.tm-page .tm-info::after {
    content: attr(data-tip);
    position: absolute;
    top: calc(100% + 8px);
    inset-inline-start: -8px;
    z-index: 40;

    /* The sentences run to about 200 characters, so the bubble is a paragraph,
       not a one-liner: fixed width and normal wrapping rather than nowrap. */
    width: max-content; max-width: 340px;
    white-space: normal; text-align: start; text-transform: none;
    font-size: 12px; font-weight: 400; line-height: 1.45; letter-spacing: 0;

    background: var(--tm-navy-dark); color: #fff;
    padding: 8px 11px; border-radius: 6px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .22);

    opacity: 0; visibility: hidden;
    transition: opacity .12s ease;
    pointer-events: none;
}
.tm-page .tm-info:hover::after,
.tm-page .tm-info:focus-visible::after { opacity: 1; visibility: visible; }

@media (prefers-reduced-motion: reduce) {
    .tm-page .tm-info::after { transition: none; }
}

/* ---------- State blocks (loading / error / empty) ----------
   The source used a toast for failures. Per the portal design standard a page
   failure is shown inline with a retry, so these replace it. */
.tm-page .tm-state {
    display: flex; align-items: center; gap: 12px;
    background: var(--tm-card); border: 1px solid var(--tm-border);
    border-radius: 8px; padding: 18px 20px; margin-block-end: 18px; font-size: 13.5px;
}
.tm-page .tm-state.tm-error { border-color: #e6bcb6; background: #fdf1ef; color: #922b21; }
.tm-page .tm-state .material-symbols-outlined { font-size: 22px; }
.tm-page .tm-state .tm-spinner {
    width: 18px; height: 18px; border-radius: 50%;
    border: 2px solid var(--tm-border); border-top-color: var(--tm-navy);
    animation: tm-spin .8s linear infinite; flex-shrink: 0;
}
@keyframes tm-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .tm-page .tm-state .tm-spinner { animation-duration: 3s; }
}

/* An action's result, reported beside the action instead of in a toast. */
.tm-page .tm-notice {
    display: flex; align-items: center; gap: 8px;
    border-radius: 6px; padding: 8px 12px; margin-block-end: 12px; font-size: 12.5px;
}
.tm-page .tm-notice-ok { background: #eaf6ef; border: 1px solid #bfe0cd; color: #1e6b3a; }
.tm-page .tm-notice-err { background: #fdf1ef; border: 1px solid #e6bcb6; color: #922b21; }
.tm-page .tm-notice .material-symbols-outlined { font-size: 18px; }

/* ---------- KPI cards ---------- */
.tm-page .tm-kpi-row {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 14px; margin-block-end: 20px;
}
.tm-page .tm-kpi {
    background: var(--tm-card); border: 1px solid var(--tm-border);
    border-radius: 8px; padding: 14px 16px;
}
.tm-page .tm-kpi .tm-kpi-value { font-size: 26px; font-weight: 700; color: var(--tm-navy); }
.tm-page .tm-kpi .tm-kpi-label {
    font-size: 12px; color: var(--tm-muted); text-transform: uppercase;
    letter-spacing: .5px; margin-block-start: 2px;
}
.tm-page .tm-kpi.k-green .tm-kpi-value { color: var(--tm-green); }
.tm-page .tm-kpi.k-red   .tm-kpi-value { color: var(--tm-red); }
.tm-page .tm-kpi.k-amber .tm-kpi-value { color: var(--tm-amber); }
.tm-page .tm-kpi.k-blue  .tm-kpi-value { color: var(--tm-blue); }

/* ---------- Cards ---------- */
.tm-page .tm-card {
    background: var(--tm-card); border: 1px solid var(--tm-border);
    border-radius: 8px; padding: 16px; margin-block-end: 18px;
}
.tm-page .tm-card h3 {
    font-size: 14px; color: var(--tm-navy); margin-block-end: 12px;
    text-transform: uppercase; letter-spacing: .5px;
}
.tm-page .tm-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 1100px) { .tm-page .tm-grid-2 { grid-template-columns: 1fr; } }

/* ---------- Horizontal bars ----------
   Marked up as a <dl> so each bar is a label/value pair to a screen reader;
   the default dl/dt/dd margins are cleared so the row still lays out as the
   source's flex row. */
.tm-page .tm-bars { margin: 0; }
.tm-page .tm-bar-row dt, .tm-page .tm-bar-row dd { margin: 0; }
.tm-page .tm-bar-row { display: flex; align-items: center; gap: 8px; margin-block-end: 7px; font-size: 12.5px; }
.tm-page .tm-bar-label {
    width: 150px; text-align: end; color: var(--tm-muted); flex-shrink: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tm-page .tm-bar-track { flex: 1; background: var(--tm-bg); border-radius: 4px; height: 18px; position: relative; }
.tm-page .tm-bar-fill { height: 100%; border-radius: 4px; background: var(--tm-navy); min-width: 2px; }
.tm-page .tm-bar-fill.alt { background: var(--tm-navy-soft); }
.tm-page .tm-bar-val { width: 46px; font-weight: 600; }

/* ---------- Toolbar ---------- */
.tm-page .tm-toolbar { display: flex; flex-wrap: wrap; gap: 8px 10px; margin-block-end: 14px; align-items: flex-end; }
.tm-page .tm-toolbar input[type="text"],
.tm-page .tm-toolbar input[type="search"],
.tm-page .tm-toolbar select {
    padding: 6px 10px; border: 1px solid var(--tm-border); border-radius: 6px;
    font-size: 13px; background: var(--tm-card); color: inherit; min-height: 32px;
}
.tm-page .tm-toolbar input[type="text"],
.tm-page .tm-toolbar input[type="search"] { width: 240px; }
.tm-page .tm-toolbar .tm-spacer { flex: 1 1 12px; }
.tm-page .tm-toolbar select:focus-visible,
.tm-page .tm-toolbar input:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: 1px; border-color: var(--tm-accent); }

/* ---------- Filter field ----------
   Every control in the toolbar is named. A bare row of dropdowns reads as
   "All / All / All" and the only way to learn what any of them does is to open
   it, which is exactly the state this replaces. The <label> wraps the control,
   so the visible caption IS the accessible name — no aria-label to drift out
   of sync with what is on screen. */
.tm-page .tm-filter { display: flex; flex-direction: column; gap: 3px; }
.tm-page .tm-filter > .tm-filter-label {
    font-size: 10.5px; font-weight: 700; letter-spacing: .5px;
    text-transform: uppercase; color: var(--tm-muted); white-space: nowrap;
}
.tm-page .tm-filter select { min-width: 132px; }

/* ---------- Buttons ---------- */
.tm-page .tm-btn {
    padding: 8px 14px; border: 1px solid var(--tm-border); border-radius: 6px; cursor: pointer;
    background: #fff; font-size: 13px; color: var(--tm-text); min-height: 34px;
    display: inline-flex; align-items: center; gap: 6px; font-family: inherit;
}
.tm-page .tm-btn:hover:not(:disabled) { background: var(--tm-hover); }
.tm-page .tm-btn:disabled { opacity: .5; cursor: not-allowed; }
.tm-page .tm-btn:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: 1px; }
.tm-page .tm-btn-primary { background: var(--tm-navy); color: #fff; border-color: var(--tm-navy); }
.tm-page .tm-btn-primary:hover:not(:disabled) { background: var(--tm-navy-dark); }
.tm-page .tm-btn-accent { background: var(--tm-accent); color: #fff; border-color: var(--tm-accent); }
.tm-page .tm-btn-accent:hover:not(:disabled) { background: var(--tm-accent-hover); border-color: var(--tm-accent-hover); }
.tm-page .tm-btn-danger { background: var(--tm-red); color: #fff; border-color: var(--tm-red); }
.tm-page .tm-btn-sm { padding: 5px 10px; font-size: 12px; min-height: 28px; }
.tm-page .tm-btn .material-symbols-outlined { font-size: 17px; }

/* ---------- Tables ----------
   The wrap is the flex child that grows, so the grid always reaches the bottom
   of the viewport and scrolls there — with three rows or with three hundred.
   It is itself a column flexbox so the ruled filler below can claim whatever
   the table does not use. */
.tm-page .tm-table-wrap {
    flex: 1 1 auto;
    min-height: 220px;
    display: flex;
    flex-direction: column;
    overflow: auto;
    background: var(--tm-card);
    border: 1px solid var(--tm-border); border-radius: 8px;
}
.tm-page table.tm-data { width: 100%; border-collapse: collapse; font-size: 12.5px; flex: 0 0 auto; }
.tm-page table.tm-data th {
    background: var(--tm-navy); color: #fff; padding: 8px 10px; text-align: start;
    white-space: nowrap; user-select: none; position: sticky; top: 0; z-index: 1;
}
.tm-page table.tm-data th.tm-sortable { cursor: pointer; }
.tm-page table.tm-data th .tm-sort-ind { color: var(--tm-highlight); }
.tm-page table.tm-data td { padding: 7px 10px; border-bottom: 1px solid var(--tm-border); white-space: nowrap; }
.tm-page table.tm-data tbody tr.tm-clickable:hover { background: var(--tm-hover); cursor: pointer; }

/* ---------- Empty rows below the last record ----------
   Ruled blank rows filling the rest of the frame, so a short result set does
   not leave the grid floating in a white void with its border halfway up the
   screen. Drawn as a repeating gradient rather than rendered as empty <tr>s:
   fake rows would be read out by a screen reader, counted by the browser's
   find-in-page, and would have to be recomputed on every resize. This is one
   element that costs nothing and is invisible to assistive tech. */
.tm-page .tm-rowfill {
    flex: 1 1 auto;
    min-height: 0;
    pointer-events: none;
    background-image: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent calc(var(--tm-row-h) - 1px),
        var(--tm-border) calc(var(--tm-row-h) - 1px),
        var(--tm-border) var(--tm-row-h));
}
.tm-page table.tm-data td.num { text-align: end; font-variant-numeric: tabular-nums; }
.tm-page table.tm-data td.tm-wrap { white-space: normal; min-width: 240px; }
.tm-page table.tm-data td.tm-wrap-wide { white-space: normal; min-width: 260px; }

/* An empty result set gets the same frame as a full one — the message where the
   first row would be, ruled blanks beneath it — so the page does not change
   shape depending on whether the filter matched anything. */
.tm-page .tm-empty {
    flex: 1 1 auto;
    min-height: 220px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--tm-card);
    border: 1px solid var(--tm-border);
    border-radius: 8px;
}
.tm-page .tm-empty-msg {
    padding: 14px 16px; font-size: 13px; color: var(--tm-muted);
    border-bottom: 1px solid var(--tm-border); flex: 0 0 auto;
}

/* ---------- Status / priority indicators ----------
   Kept as the source's pills so the log reads identically. Each carries its own
   glyph as well as its colour, so status is never colour-only. */
.tm-page .tm-pill {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 9px; border-radius: 10px; font-size: 11px; font-weight: 600; white-space: nowrap;
}
.tm-page .tm-pill .material-symbols-outlined { font-size: 13px; }
.tm-page .pill-SUBMITTED   { background: #d5e8d4; color: #1e6b3a; }
.tm-page .pill-ON-PROGRESS { background: #fdebd0; color: #9c640c; }
.tm-page .pill-APOLOGIZED  { background: #f2d7d5; color: #922b21; }
.tm-page .pill-NOT-YET     { background: #d6dbdf; color: #4d5656; }
.tm-page .pill-AWARDED     { background: #2e8b57; color: #fff; }
.tm-page .pill-LOST        { background: #f2d7d5; color: #922b21; }
.tm-page .pill-SHORTLISTED { background: #d4e6f1; color: #1a5276; }
.tm-page .pill-CANCELLED   { background: #d6dbdf; color: #4d5656; }
.tm-page .pill-RE-TENDER   { background: #fdebd0; color: #9c640c; }
.tm-page .pill-PENDING     { background: #fdebd0; color: #9c640c; }
.tm-page .pill-CONVERTED   { background: #d5e8d4; color: #1e6b3a; }
.tm-page .pill-CLOSED      { background: #d6dbdf; color: #4d5656; }
.tm-page .pill-STRATEGIC   { background: #e8a33d; color: #fff; letter-spacing: .3px; }
.tm-page .pill-APOLOGY     { background: #fadbd8; color: #922b21; }
.tm-page .pill-default     { background: #eaecee; color: #566573; }

/* Text for assistive tech only — the attachment column's header is an icon,
   which reads as nothing without it. */
.tm-page .tm-visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
}

/* ---------- Attachment cell ---------- */
.tm-page td.tm-att-cell { cursor: pointer; text-align: center; font-size: 14px; }
.tm-page td.tm-att-cell:hover { background: var(--tm-hover); }
.tm-page .tm-att-count {
    background: var(--tm-navy); color: #fff; border-radius: 9px; font-size: 10px;
    padding: 1px 6px; margin-inline-start: 3px; font-weight: 700; vertical-align: top;
}
.tm-page .tm-att-cat {
    font-weight: 700; font-size: 12.5px; color: var(--tm-navy); text-transform: uppercase;
    letter-spacing: .5px; margin: 14px 0 4px; padding-block-end: 4px; border-bottom: 2px solid var(--tm-navy);
}
.tm-page .tm-att-cat:first-child { margin-block-start: 0; }
.tm-page .tm-att-row {
    display: flex; align-items: center; gap: 10px;
    padding: 6px 10px 6px 26px; border-bottom: 1px solid var(--tm-border); font-size: 13px;
}
.tm-page .tm-att-row .tm-att-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-page .tm-att-row .tm-att-meta { color: var(--tm-muted); font-size: 11.5px; white-space: nowrap; }
.tm-page .tm-att-path {
    background: #eaf2fa; border: 1px solid #c7dbee; border-radius: 6px;
    padding: 8px 12px; margin-block-end: 14px; font-size: 12.5px; color: var(--tm-navy);
}

/* ---------- Benchmark grid ---------- */
.tm-page tr.tm-bm-groups th {
    background: var(--tm-navy-dark); color: var(--tm-highlight); text-align: center;
    border-right: 2px solid rgba(255,255,255,.25); font-size: 11px; letter-spacing: 1px;
}
.tm-page tr.tm-bm-project td {
    background: var(--tm-bg); color: var(--tm-navy); font-weight: 700;
    border-top: 2px solid var(--tm-navy); font-size: 12.5px;
}
.tm-page tbody tr.tm-bm-project:hover { background: var(--tm-bg); cursor: default; }
.tm-page .tm-bm-project-count { font-weight: 400; color: var(--tm-muted); font-size: 11px; }
.tm-page .tm-bm-lock { color: #b0bcc9; font-size: 12px; }

/* ---------- In-place dropdown cell editing ---------- */
.tm-page td.tm-ec { cursor: pointer; }
.tm-page td.tm-ec .tm-ec-caret { color: #a8b6c4; font-size: 9px; margin-inline-start: 4px; opacity: 0; transition: opacity .12s; }
.tm-page tbody tr:hover td.tm-ec .tm-ec-caret { opacity: 1; }
.tm-page tbody tr:hover td.tm-ec:hover { background: var(--tm-hover); box-shadow: inset 0 0 0 1px var(--tm-accent); }
.tm-page .tm-ec-select {
    font-size: 12px; padding: 2px 4px; border: 1px solid var(--tm-blue); border-radius: 4px;
    max-width: 160px; background: #fff; font-family: inherit;
}
@media (prefers-reduced-motion: reduce) {
    .tm-page td.tm-ec .tm-ec-caret { transition: none; }
}

/* ---------- Pager ---------- */
.tm-page .tm-pager {
    display: flex; gap: 8px; align-items: center; justify-content: flex-end;
    padding: 10px 4px; font-size: 12.5px; color: var(--tm-muted);
}

/* ---------- Dashboard extras ---------- */
.tm-page .tm-slices { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; }
.tm-page .tm-slice {
    background: var(--tm-bg); border: 1px solid var(--tm-border); border-radius: 8px;
    padding: 10px 12px; text-align: center;
}
.tm-page .tm-slice-val { font-size: 18px; font-weight: 700; color: var(--tm-navy); }
.tm-page .tm-slice-label {
    font-size: 10.5px; color: var(--tm-muted); text-transform: uppercase;
    letter-spacing: .4px; margin-block-start: 3px;
}
.tm-page .tm-yoy { font-size: 15px; font-weight: 700; color: var(--tm-muted); }
.tm-page .tm-yoy-up { color: var(--tm-green); }
.tm-page .tm-yoy-down { color: var(--tm-red); }

.tm-page .tm-mini-scroll { max-height: 320px; overflow-y: auto; }
.tm-page table.tm-data.tm-mini { font-size: 12px; }
.tm-page table.tm-data.tm-mini th { padding: 6px 8px; position: static; }
.tm-page table.tm-data.tm-mini td { padding: 5px 8px; }
.tm-page table.tm-data.tm-mini td.tm-mini-name { white-space: normal; min-width: 140px; max-width: 260px; }
.tm-page .tm-card-more {
    float: inline-end; font-size: 11px; font-weight: 400; color: var(--tm-accent);
    text-decoration: none; text-transform: none; letter-spacing: 0;
}
.tm-page .tm-card-more:hover { text-decoration: underline; }
.tm-page .tm-due {
    display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 11px;
    font-weight: 600; background: #eaecee; color: #566573; white-space: nowrap;
}
.tm-page .tm-due-soon { background: #fdebd0; color: #9c640c; }
.tm-page .tm-due-over { background: #f2d7d5; color: #922b21; }

/* ---------- Record window ----------
   The source opens records in a centred modal. Reproduced here because the
   brief was an exact port; the portal standard prefers a side panel, which is
   noted in docs/modules/tender-manager.md as the one open design question. */
.tm-modal-overlay {
    position: fixed; inset: 0; background: rgba(15,25,40,.55); z-index: 1200;
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.tm-modal {
    background: #fff; border-radius: 10px; width: 900px; max-width: 100%;
    max-height: 92vh; display: flex; flex-direction: column;
    box-shadow: 0 12px 40px rgba(0,0,0,.25); color: #22303e; font-size: 14px;
    --tm-navy: var(--BEC-themePrimary, #1e3c72);
    --tm-navy-dark: var(--BEC-themeDark, #172c56);
    --tm-accent: var(--BEC-colorBrandBackground, #0078d4);
    --tm-border: var(--BEC-colorNeutralStroke1, #d1d1d1);
    --tm-muted: var(--BEC-colorNeutralForeground3, #616161);
    --tm-blue: var(--BEC-colorBrandForeground1, #0078d4);
    --tm-red: var(--BEC-colorPaletteRedForeground1, #bc2f32);
    --tm-green: var(--BEC-colorPaletteGreenForeground1, #107c10);
    --tm-amber: var(--BEC-colorPaletteYellowForeground1, #8a6c00);
    --tm-bg: var(--BEC-colorNeutralBackground3, #f5f5f5);
    --tm-text: var(--BEC-colorNeutralForeground1, #242424);
    --tm-card: var(--BEC-colorNeutralBackground1, #ffffff);
}
.tm-modal.tm-modal-narrow { width: 620px; }
.tm-modal-header {
    padding: 14px 20px; border-bottom: 1px solid var(--tm-border);
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
}
.tm-modal-header h2 { font-size: 16px; color: var(--tm-navy); margin: 0; }
.tm-modal-close {
    border: none; background: none; font-size: 24px; cursor: pointer;
    color: var(--tm-muted); line-height: 1; padding: 0 4px;
}
.tm-modal-close:focus-visible { outline: 2px solid var(--tm-blue); }
.tm-modal-body { padding: 18px 20px; overflow-y: auto; }
.tm-modal-footer {
    padding: 12px 20px; border-top: 1px solid var(--tm-border);
    display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap;
}

/* The modal renders outside .tm-page, so the shared primitives it uses are
   repeated for its subtree rather than duplicated by hand in the markup. */
.tm-modal .tm-btn {
    padding: 8px 14px; border: 1px solid var(--tm-border); border-radius: 6px; cursor: pointer;
    background: #fff; font-size: 13px; color: var(--tm-text); min-height: 34px;
    display: inline-flex; align-items: center; gap: 6px; font-family: inherit;
}
.tm-modal .tm-btn:hover:not(:disabled) { background: var(--BEC-colorNeutralBackground3, #f5f5f5); }
.tm-modal .tm-btn:disabled { opacity: .5; cursor: not-allowed; }
.tm-modal .tm-btn:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: 1px; }
.tm-modal .tm-btn-primary { background: var(--tm-navy); color: #fff; border-color: var(--tm-navy); }
.tm-modal .tm-btn-accent { background: var(--tm-accent); color: #fff; border-color: var(--tm-accent); }
.tm-modal .tm-btn-danger { background: var(--tm-red); color: #fff; border-color: var(--tm-red); }
.tm-modal .tm-btn-sm { padding: 5px 10px; font-size: 12px; min-height: 28px; }
.tm-modal .tm-btn .material-symbols-outlined { font-size: 17px; }
.tm-modal .tm-notice { display: flex; align-items: center; gap: 8px; border-radius: 6px; padding: 8px 12px; margin-block-end: 12px; font-size: 12.5px; }
.tm-modal .tm-notice-ok { background: #eaf6ef; border: 1px solid #bfe0cd; color: #1e6b3a; }
.tm-modal .tm-notice-err { background: #fdf1ef; border: 1px solid #e6bcb6; color: #922b21; }
.tm-modal .tm-att-cat {
    font-weight: 700; font-size: 12.5px; color: var(--tm-navy); text-transform: uppercase;
    letter-spacing: .5px; margin: 14px 0 4px; padding-block-end: 4px; border-bottom: 2px solid var(--tm-navy);
}
.tm-modal .tm-att-row {
    display: flex; align-items: center; gap: 10px;
    padding: 6px 10px; border-bottom: 1px solid var(--tm-border); font-size: 13px;
}
.tm-modal .tm-att-row .tm-att-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-modal .tm-att-row .tm-att-meta { color: var(--tm-muted); font-size: 11.5px; white-space: nowrap; }
.tm-modal .tm-pill {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 9px; border-radius: 10px; font-size: 11px; font-weight: 600; white-space: nowrap;
}

/* ---------- Forms ---------- */
.tm-form-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 16px; }
.tm-form-grid .tm-full { grid-column: 1 / -1; }
.tm-form-grid .tm-two { grid-column: span 2; }
@media (max-width: 760px) { .tm-form-grid { grid-template-columns: 1fr; } .tm-form-grid .tm-two, .tm-form-grid .tm-full { grid-column: 1 / -1; } }
.tm-field label {
    display: block; font-size: 11px; font-weight: 600; color: var(--tm-muted);
    text-transform: uppercase; margin-block-end: 4px; letter-spacing: .4px;
}
.tm-field input, .tm-field select {
    width: 100%; padding: 7px 9px; border: 1px solid var(--tm-border);
    border-radius: 6px; font-size: 13px; font-family: inherit; color: inherit; min-height: 34px;
}
.tm-field input[readonly] { background: var(--BEC-colorNeutralBackground3, #f5f5f5); color: var(--tm-muted); }
.tm-field input:focus-visible, .tm-field select:focus-visible {
    outline: 2px solid rgba(36,113,163,.55); border-color: var(--tm-blue);
}
.tm-field .tm-field-error { color: #922b21; font-size: 11.5px; margin-block-start: 3px; display: block; }
.tm-field input.tm-invalid, .tm-field select.tm-invalid { border-color: #c0392b; }
.tm-derived-note { font-size: 12px; color: var(--tm-muted); margin-block-start: 10px; }
.tm-page .tm-derived-note { color: var(--tm-muted); }

.tm-parent-link {
    background: #eaf2fa; border: 1px solid #c7dbee; border-radius: 6px;
    padding: 8px 12px; margin-block-end: 14px; font-size: 13px; color: var(--tm-navy);
}

/* ---------- Type-ahead ---------- */
.tm-ac-wrap { position: relative; }
.tm-ac-list {
    position: absolute; top: 100%; inset-inline: 0; z-index: 1300;
    background: #fff; border: 1px solid var(--tm-blue); border-top: none;
    border-radius: 0 0 6px 6px; max-height: 230px; overflow-y: auto;
    box-shadow: 0 10px 24px rgba(0,0,0,.18);
}
.tm-ac-item { padding: 7px 10px; font-size: 12.5px; cursor: pointer; }
.tm-ac-item:hover, .tm-ac-item.tm-active { background: var(--BEC-colorNeutralBackground3, #f5f5f5); }
.tm-ac-new { padding: 6px 10px; font-size: 11px; color: var(--tm-amber); border-top: 1px dashed var(--tm-border); }

/* ---------- New-task project picker ---------- */
.tm-task-results {
    margin-block-start: 12px; max-height: 46vh; overflow-y: auto;
    border: 1px solid var(--tm-border); border-radius: 6px;
}
.tm-task-item {
    display: grid; grid-template-columns: 90px 1fr 220px; gap: 10px; align-items: center;
    padding: 8px 12px; border-bottom: 1px solid var(--tm-border); cursor: pointer;
    font-size: 13px; width: 100%; text-align: start; background: none; border-inline: none; border-top: none; font-family: inherit;
}
.tm-task-item:hover, .tm-task-item:focus-visible { background: var(--BEC-colorNeutralBackground3, #f5f5f5); }
.tm-task-item .tm-task-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-task-item .tm-task-client { color: var(--tm-muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-task-item .tm-task-parent { font-size: 10.5px; color: var(--tm-amber); }

/* ---------- List Manager ---------- */
.tm-page .tm-lists-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 16px; }
.tm-page .tm-list-card ul { list-style: none; margin: 8px 0; padding: 0; max-height: 260px; overflow-y: auto; }
.tm-page .tm-list-card li {
    display: flex; justify-content: space-between; align-items: center;
    padding: 5px 8px; border-bottom: 1px solid var(--tm-border); font-size: 13px;
}
.tm-page .tm-list-card li button {
    border: none; background: none; color: var(--tm-red); cursor: pointer;
    font-size: 15px; line-height: 1; padding: 2px 6px; font-family: inherit;
}
.tm-page .tm-list-card li button:focus-visible { outline: 2px solid var(--tm-blue); }
.tm-page .tm-list-add { display: flex; gap: 6px; }
.tm-page .tm-list-add input {
    flex: 1; padding: 6px 8px; border: 1px solid var(--tm-border);
    border-radius: 6px; font-size: 13px; font-family: inherit; min-height: 32px;
}

/* ---------- Data & Export ---------- */
.tm-page .tm-setting-row {
    display: flex; align-items: center; gap: 14px; padding: 12px 0;
    border-bottom: 1px solid var(--tm-border); flex-wrap: wrap;
}
.tm-page .tm-setting-row:last-child { border-bottom: none; }
.tm-page .tm-setting-desc { flex: 1; min-width: 260px; }
.tm-page .tm-setting-desc b { display: block; margin-block-end: 2px; }
.tm-page .tm-setting-desc span { color: var(--tm-muted); font-size: 12.5px; }

/* ---------- Print ----------
   The three reports are printed and circulated; the source tuned this to fit
   an A4 landscape page, so the same tuning is kept. The portal chrome is
   suppressed the way the source suppressed its own sidebar. */
@media print {
    @page { size: A4 landscape; margin: 8mm; }
    .tm-page .tm-toolbar, .tm-page .tm-pager, .tm-modal-overlay { display: none !important; }
    .tm-page .tm-title { font-size: 15px; margin-block-end: 2px; }
    .tm-page .tm-sub { font-size: 10px; }
    .tm-page .tm-kpi-row { break-inside: avoid; gap: 8px; }
    .tm-page .tm-kpi { padding: 6px 8px; }
    .tm-page .tm-kpi .tm-kpi-value { font-size: 16px; }
    .tm-page .tm-table-wrap { overflow: visible !important; border: none !important; }
    .tm-page table.tm-data { width: 100% !important; font-size: 8px; }
    .tm-page table.tm-data th {
        position: static !important; padding: 3px 4px; font-size: 8px;
        background: #1b3a5c !important; color: #fff !important;
        -webkit-print-color-adjust: exact; print-color-adjust: exact;
    }
    .tm-page table.tm-data td {
        white-space: normal !important; min-width: 0 !important; max-width: none !important;
        padding: 2px 4px; word-break: break-word; overflow-wrap: anywhere;
    }
    .tm-page table.tm-data tbody tr { page-break-inside: avoid; }
    .tm-page .tm-pill, .tm-page .tm-att-count, .tm-page .tm-due {
        -webkit-print-color-adjust: exact; print-color-adjust: exact;
    }
    .tm-page td.tm-att-cell, .tm-page .tm-ec-caret, .tm-page .tm-card-more { display: none !important; }
}
