/* ==========================================================================
   OpenClaw Tender Portal — PORTAL UI POLISH — 2026-08-12
   --------------------------------------------------------------------------
   Purely additive presentation layer. Loaded LAST on every portal page.
   Contains no layout restructuring, no new markup requirements and no
   behavioural hooks — every selector targets a class that already exists.

   Purpose: the portal grew one phase at a time, so each page arrived with its
   own container width, control height, button colour and table treatment.
   This file reconciles them into a single system without touching the
   per-phase stylesheets, so it can be removed in one step.

   Rules enforced here:
     1. Two container widths only — wide (data) and narrow (forms/reading).
     2. One control height, one radius scale, one focus ring.
     3. Ink is the primary action colour. Orange is reserved for urgency and
        destructive intent, per the base design note.
     4. No stray blue.
     5. Tables share one header, one row rhythm, tabular figures.
   ========================================================================== */

:root {
  --pol-wide: 1440px;
  --pol-narrow: 1080px;
  --pol-gutter: 48px;

  --pol-control-h: 40px;
  --pol-radius-sm: 6px;
  --pol-radius: 10px;
  --pol-radius-lg: 14px;

  --pol-ink: #1a1712;
  --pol-ink-hover: #322b22;
  --pol-surface: #fbfaf6;
  --pol-surface-2: #f3efe6;
  --pol-border: #ded8ca;
  --pol-border-strong: #cabfa8;
  --pol-muted: #6f675a;
  --pol-accent: #d1471f;
  --pol-accent-soft: #fbe7de;
  --pol-danger: #a8321f;
  --pol-danger-soft: #f8e5e1;
  --pol-success: #2f7a52;

  --pol-ring: 0 0 0 3px rgba(209, 71, 31, 0.18);
  --pol-shadow-sm: 0 1px 2px rgba(26, 23, 18, 0.05);
  --pol-shadow: 0 10px 30px -20px rgba(26, 23, 18, 0.34);
}

/* --------------------------------------------------------------------------
   1. Container widths
   -------------------------------------------------------------------------- */

.ops-shell,
.supplier-shell,
.tender-detail-main {
  width: min(var(--pol-wide), calc(100% - var(--pol-gutter)));
  margin: 0 auto;
}

.account-shell,
.analysis-page {
  width: min(var(--pol-narrow), calc(100% - var(--pol-gutter)));
  margin: 0 auto;
}

.ops-shell {
  padding: 34px 0 72px;
}

.supplier-shell {
  padding: 34px 0 72px;
}

.account-shell {
  padding: 48px 0 72px;
}

.analysis-page {
  padding: 34px 0 72px;
}

/* The admin accounts screen carries a two-column workspace, so it earns the
   wide container rather than the narrow reading width. */
.account-shell:has(.admin-grid) {
  width: min(1240px, calc(100% - var(--pol-gutter)));
}

/* --------------------------------------------------------------------------
   2. Form controls — one height, one radius, one focus ring
   -------------------------------------------------------------------------- */

.auth-page input[type="text"],
.auth-page input[type="password"],
.auth-page input[type="email"],
.auth-page input[type="search"],
.auth-page select,
.supplier-page input[type="text"],
.supplier-page input[type="email"],
.supplier-page input[type="search"],
.supplier-page select,
.supplier-page textarea,
.analysis-page input[type="text"],
.ops-shell input[type="text"],
.ops-shell input[type="search"],
.ops-shell select {
  min-height: var(--pol-control-h);
  padding: 8px 12px;
  border: 1px solid var(--pol-border);
  border-radius: var(--pol-radius-sm);
  background: #fff;
  color: var(--pol-ink);
  font-size: 14px;
  line-height: 1.4;
  transition: border-color var(--mo-fast) var(--mo-ease), box-shadow var(--mo-fast) var(--mo-ease);
}

.auth-page input:hover:not(:disabled),
.supplier-page input:hover:not(:disabled),
.ops-shell input:hover:not(:disabled),
.auth-page select:hover:not(:disabled),
.supplier-page select:hover:not(:disabled),
.ops-shell select:hover:not(:disabled) {
  border-color: var(--pol-border-strong);
}

.auth-page input:focus,
.auth-page select:focus,
.auth-page textarea:focus,
.supplier-page input:focus,
.supplier-page select:focus,
.supplier-page textarea:focus,
.analysis-page input:focus,
.ops-shell input:focus,
.ops-shell select:focus {
  outline: none;
  border-color: var(--pol-accent);
  box-shadow: var(--pol-ring);
}

/* Native selects render inconsistently next to text inputs. Give them the
   same box and one shared chevron. */
.auth-page select,
.supplier-page select,
.ops-shell select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236f675a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  cursor: pointer;
}

/* Field labels: one voice across every page. */
.auth-form label,
.supplier-form-grid label,
.ops-filter-grid label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pol-muted);
}

/* Checkboxes pick up the brand ink rather than the browser blue. */
.auth-page input[type="checkbox"],
.supplier-page input[type="checkbox"] {
  accent-color: var(--pol-ink);
  width: 16px;
  height: 16px;
  cursor: pointer;
}

.auth-checkbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--pol-border);
  border-radius: var(--pol-radius-sm);
  background: var(--pol-surface-2);
}

.auth-checkbox-row label,
.auth-checkbox-row span {
  letter-spacing: 0.06em;
}

/* --------------------------------------------------------------------------
   3. Buttons — ink is primary, orange means urgency, red means destructive
   -------------------------------------------------------------------------- */

.auth-form button[type="submit"],
.supplier-primary-button,
.analysis-primary,
.admin-delete-form.role-change-form .promote-master-button,
.admin-delete-form.role-change-form .demote-master-button,
.ops-filter-actions button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--pol-control-h);
  padding: 0 18px;
  border: 1px solid var(--pol-ink);
  border-radius: var(--pol-radius-sm);
  background: var(--pol-ink);
  color: #fff;
  font-size: 14px;
  font-weight: 650;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--mo-fast) var(--mo-ease), border-color var(--mo-fast) var(--mo-ease), transform var(--mo-fast) var(--mo-ease);
}

.auth-form button[type="submit"]:hover:not(:disabled),
.supplier-primary-button:hover:not(:disabled),
.analysis-primary:hover:not(:disabled),
.admin-delete-form.role-change-form .promote-master-button:hover:not(:disabled),
.admin-delete-form.role-change-form .demote-master-button:hover:not(:disabled),
.ops-filter-actions button[type="submit"]:hover:not(:disabled) {
  background: var(--pol-ink-hover);
  border-color: var(--pol-ink-hover);
}

.auth-form button[type="submit"]:active:not(:disabled),
.supplier-primary-button:active:not(:disabled),
.analysis-primary:active:not(:disabled) {
  transform: translateY(1px);
}

/* Secondary / navigation buttons: quiet, bordered, same metrics. */
.secondary-button,
.supplier-secondary-button,
.supplier-header-actions a,
.account-header-actions a,
.account-header-actions button,
.ops-header-actions a,
.ops-refresh-link,
.ops-filter-actions a,
.detail-secondary-button,
.analysis-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--pol-control-h);
  padding: 0 15px;
  border: 1px solid var(--pol-border);
  border-radius: var(--pol-radius-sm);
  background: #fff;
  color: var(--pol-ink);
  font-size: 13.5px;
  font-weight: 650;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--mo-fast) var(--mo-ease), border-color var(--mo-fast) var(--mo-ease);
}

.secondary-button:hover,
.supplier-secondary-button:hover,
.supplier-header-actions a:hover,
.account-header-actions a:hover,
.account-header-actions button:hover,
.ops-header-actions a:hover,
.ops-refresh-link:hover,
.detail-secondary-button:hover,
.analysis-back:hover {
  background: var(--pol-surface-2);
  border-color: var(--pol-border-strong);
}

/* Destructive actions read as destructive, not as the primary action. */
.danger-button,
.admin-delete-form:not(.role-change-form) .danger-button,
.admin-delete-form button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--pol-control-h);
  padding: 0 16px;
  border: 1px solid var(--pol-danger);
  border-radius: var(--pol-radius-sm);
  background: #fff;
  color: var(--pol-danger);
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
  transition: background-color var(--mo-fast) var(--mo-ease), color var(--mo-fast) var(--mo-ease);
}

.danger-button:hover,
.admin-delete-form:not(.role-change-form) .danger-button:hover,
.admin-delete-form button[type="submit"]:hover {
  background: var(--pol-danger);
  color: #fff;
}

/* Disabled state is legible rather than washed out. */
button:disabled,
.analysis-primary:disabled {
  background: #e7e1d4;
  border-color: var(--pol-border-strong);
  color: #7a7264;
  cursor: not-allowed;
  transform: none;
  opacity: 1;
}

/* One visible keyboard focus treatment for every interactive element. */
.auth-page a:focus-visible,
.auth-page button:focus-visible,
.supplier-page a:focus-visible,
.supplier-page button:focus-visible,
.ops-shell a:focus-visible,
.ops-shell button:focus-visible,
.analysis-page a:focus-visible,
.analysis-page button:focus-visible,
.tender-detail-body a:focus-visible,
.tender-detail-body button:focus-visible {
  outline: 2px solid var(--pol-accent);
  outline-offset: 2px;
  border-radius: var(--pol-radius-sm);
}

/* --------------------------------------------------------------------------
   4. No stray blue
   -------------------------------------------------------------------------- */

.supplier-header-actions a,
.supplier-page a:not(.supplier-primary-button) {
  color: var(--pol-ink);
}

.ops-refresh-link,
.ops-section a:not(.ops-status-pill) {
  color: var(--pol-ink);
}

/* --------------------------------------------------------------------------
   5. Cards and panels — one radius, one border, one shadow
   -------------------------------------------------------------------------- */

.auth-card,
.account-card,
.account-panel,
.admin-user-list-card,
.ops-section,
.ops-metric,
.ops-check-card,
.supplier-header,
.supplier-summary,
.supplier-toolbar,
.analysis-upload-card,
.analysis-result {
  border-radius: var(--pol-radius);
  border: 1px solid var(--pol-border);
  background: var(--pol-surface);
  box-shadow: var(--pol-shadow-sm);
}

.ops-section,
.supplier-header {
  box-shadow: var(--pol-shadow);
}

/* .supplier-search is a <label> wrapping the search input, not a container.
   It must never take card treatment — a border/background here renders as a
   stray box nested inside the toolbar card. */
.supplier-search {
  border: none;
  background: none;
  box-shadow: none;
  padding: 0;
}

/* Section eyebrows: same size, weight and tracking everywhere. */
.auth-card-kicker,
.auth-eyebrow,
.ops-section-heading > .auth-card-kicker,
.supplier-eyebrow,
.analysis-section-heading,
.eyebrow {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--pol-accent);
}

/* Page titles share one scale. */
.account-header h1,
.ops-header h1,
.supplier-header h1,
.analysis-hero h1 {
  font-size: 32px;
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin: 6px 0 8px;
}

/* --------------------------------------------------------------------------
   6. Metric tiles
   -------------------------------------------------------------------------- */

.ops-metric,
.supplier-summary > * {
  padding: 16px 18px;
}

.ops-metric strong,
.supplier-summary strong {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.ops-overview {
  gap: 14px;
}

/* --------------------------------------------------------------------------
   7. Tables — one header, one rhythm, tabular figures
   -------------------------------------------------------------------------- */

.ops-table,
.audit-table,
.supplier-list table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.ops-table thead th,
.audit-table thead th,
.supplier-list table thead th {
  padding: 10px 14px;
  border-bottom: 1px solid var(--pol-border-strong);
  background: var(--pol-surface-2);
  color: var(--pol-muted);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}

.ops-table tbody td,
.audit-table tbody td,
.supplier-list table tbody td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--pol-border);
  vertical-align: top;
  font-size: 13.5px;
}

.ops-table tbody tr:last-child td,
.audit-table tbody tr:last-child td,
.supplier-list table tbody tr:last-child td {
  border-bottom: none;
}

.ops-table tbody tr:hover td,
.audit-table tbody tr:hover td {
  background: rgba(209, 71, 31, 0.035);
}

.ops-table-wrap {
  border-radius: var(--pol-radius-sm);
  border: 1px solid var(--pol-border);
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   8. Status pills and badges
   -------------------------------------------------------------------------- */

.ops-status-pill,
.role-badge,
.master-badge,
.status-badge,
.supplier-check {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.6;
  white-space: nowrap;
}

.ops-status-pill.ok,
.status-badge.active {
  background: #e4f1e9;
  border-color: #bfdccc;
  color: #24603f;
}

.ops-status-pill.warning {
  background: #f7ead8;
  border-color: #e2c9a4;
  color: #8a4a10;
}

.ops-status-pill.error,
.status-badge.disabled {
  background: var(--pol-danger-soft);
  border-color: #e6bfb7;
  color: var(--pol-danger);
}

.role-badge {
  background: var(--pol-surface-2);
  border-color: var(--pol-border);
  color: var(--pol-muted);
}

.master-badge {
  background: #efe9db;
  border-color: var(--pol-border-strong);
  color: var(--pol-ink);
}

/* Monospaced identifiers stay legible and do not wrap mid-token. */
.ops-table code,
.audit-table code,
.ops-detail-list dd code {
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--pol-surface-2);
  border: 1px solid var(--pol-border);
  font-size: 11.5px;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   9. Admin accounts — separate the destructive zone from routine actions
   -------------------------------------------------------------------------- */

.admin-user-row {
  border: 1px solid var(--pol-border);
  border-radius: var(--pol-radius);
  background: #fff;
  padding: 18px 20px;
  transition: border-color var(--mo-fast) var(--mo-ease), box-shadow var(--mo-fast) var(--mo-ease);
}

.admin-user-row:hover {
  border-color: var(--pol-border-strong);
  box-shadow: var(--pol-shadow-sm);
}

.admin-user-summary strong {
  font-size: 16px;
  letter-spacing: -0.01em;
}

.admin-user-meta {
  color: var(--pol-muted);
  font-size: 12.5px;
}

.admin-delete-form {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--pol-border-strong);
}

.admin-delete-form label,
.admin-delete-form > span {
  display: block;
  margin-bottom: 6px;
  color: var(--pol-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.master-protection-note {
  padding: 10px 12px;
  border-radius: var(--pol-radius-sm);
  background: var(--pol-surface-2);
  border: 1px solid var(--pol-border);
  color: var(--pol-muted);
  font-size: 12.5px;
}

/* --------------------------------------------------------------------------
   10. Analysis upload — a real drop target instead of a bare file input
   -------------------------------------------------------------------------- */

.analysis-file-field {
  display: block;
  padding: 20px;
  border: 1.5px dashed var(--pol-border-strong);
  border-radius: var(--pol-radius);
  background: var(--pol-surface-2);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--mo-fast) var(--mo-ease), background-color var(--mo-fast) var(--mo-ease);
}

.analysis-file-field:hover,
.analysis-file-field:focus-within {
  border-color: var(--pol-accent);
  background: var(--pol-accent-soft);
}

.analysis-file-field > span {
  display: block;
  margin-bottom: 10px;
  color: var(--pol-muted);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* The inner input already carries a dashed box in analysis-page.css; the
   drop target owns that treatment now, so the input goes flat. */
.analysis-file-field input[type="file"] {
  width: 100%;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  font-size: 13.5px;
  cursor: pointer;
}

.analysis-file-field input[type="file"]::file-selector-button {
  min-height: 34px;
  margin-right: 12px;
  padding: 0 14px;
  border: 1px solid var(--pol-ink);
  border-radius: var(--pol-radius-sm);
  background: var(--pol-ink);
  color: #fff;
  font-size: 13px;
  font-weight: 650;
  cursor: pointer;
}

.analysis-file-field input[type="file"]::file-selector-button:hover {
  background: var(--pol-ink-hover);
}

.analysis-selected-file {
  margin-top: 10px;
  color: var(--pol-muted);
  font-size: 13px;
}

.analysis-privacy-note {
  padding: 12px 14px;
  border-radius: var(--pol-radius-sm);
  border: 1px solid var(--pol-border);
  background: var(--pol-surface-2);
  color: var(--pol-muted);
  font-size: 12.5px;
  line-height: 1.55;
}

/* --------------------------------------------------------------------------
   11. Empty states read as intentional, not as a failure
   -------------------------------------------------------------------------- */

.ops-helper,
.supplier-help,
.analysis-missing-list:empty::after {
  color: var(--pol-muted);
  font-size: 13px;
}

.ops-table-wrap td[colspan],
.ops-event-list:empty::after {
  padding: 26px 14px;
  color: var(--pol-muted);
  text-align: center;
}

/* --------------------------------------------------------------------------
   12. Messages / flash banners
   -------------------------------------------------------------------------- */

.auth-message,
.supplier-message,
.analysis-error,
.ops-warning-box {
  display: block;
  padding: 12px 14px;
  border-radius: var(--pol-radius-sm);
  border: 1px solid var(--pol-border);
  background: var(--pol-surface-2);
  color: var(--pol-ink);
  font-size: 13.5px;
  line-height: 1.5;
}

.auth-message.error,
.auth-message.danger,
.supplier-message.error,
.analysis-error {
  border-color: #e6bfb7;
  background: var(--pol-danger-soft);
  color: var(--pol-danger);
}

.auth-message.warning,
.ops-warning-box {
  border-color: #e2c9a4;
  background: #f7ead8;
  color: #8a4a10;
}

.auth-message.success {
  border-color: #bfdccc;
  background: #e4f1e9;
  color: #24603f;
}

/* --------------------------------------------------------------------------
   13. Workspace tabs
   -------------------------------------------------------------------------- */

.workspace-tab {
  border-radius: var(--pol-radius-sm) var(--pol-radius-sm) 0 0;
  font-size: 13.5px;
  font-weight: 650;
  transition: background-color var(--mo-fast) var(--mo-ease), color var(--mo-fast) var(--mo-ease);
}

.workspace-tab:hover:not(.active) {
  background: var(--pol-surface-2);
}

.workspace-tab-count {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   14. Print — operational pages are occasionally printed for audit packs
   -------------------------------------------------------------------------- */

@media print {
  .ops-header-actions,
  .account-header-actions,
  .supplier-header-actions,
  .ops-filter-actions,
  .ops-refresh-link {
    display: none !important;
  }

  .ops-shell,
  .account-shell,
  .supplier-shell {
    width: 100%;
  }

  .ops-section,
  .ops-metric,
  .account-card {
    box-shadow: none;
    break-inside: avoid;
  }
}

/* --------------------------------------------------------------------------
   15. Responsive — the polish layer must not fight the existing breakpoints
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  :root {
    --pol-gutter: 28px;
  }

  .account-header h1,
  .ops-header h1,
  .supplier-header h1,
  .analysis-hero h1 {
    font-size: 26px;
  }

  .ops-header,
  .supplier-header,
  .account-header {
    gap: 16px;
  }

  .ops-header-actions,
  .supplier-header-actions,
  .account-header-actions {
    flex-wrap: wrap;
  }

  .ops-table thead th,
  .ops-table tbody td {
    padding: 10px;
  }
}

@media (max-width: 620px) {
  .secondary-button,
  .supplier-secondary-button,
  .supplier-header-actions a,
  .account-header-actions a,
  .account-header-actions button,
  .ops-header-actions a {
    flex: 1 1 auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .auth-form button[type="submit"],
  .supplier-primary-button,
  .analysis-primary,
  .admin-user-row,
  .workspace-tab {
    transition: none;
  }
}
/* ==========================================================================
   16. SIDEBAR REDESIGN — 2026-08-12
   --------------------------------------------------------------------------
   The control rail carried three stacked bordered boxes (markets, service
   status, identity panel), a blue avatar that appeared nowhere else in the
   product, a heavy red fill on the selected market, and an admin button grid
   whose first label wrapped to two lines while its neighbour did not.

   This section resolves those without touching markup or JavaScript.
   ========================================================================== */

@media (min-width: 961px) {
  :root {
    --sidebar-width: 300px;
  }
}

.sidebar {
  padding: 22px 16px 18px;
  background:
    radial-gradient(85% 38% at 12% -6%, rgba(209, 71, 31, 0.10), transparent 60%),
    linear-gradient(180deg, #1e1a15 0%, #141109 100%);
}

/* ---- Brand ---- */

.brand {
  gap: 13px;
  margin: 0;
  padding: 0 4px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.brand-icon {
  width: 44px;
  height: 44px;
  border-radius: 11px;
  font-size: 20px;
  background: linear-gradient(150deg, #e2562b, #bc3a14);
  box-shadow:
    0 8px 20px -12px rgba(226, 86, 43, 0.85),
    inset 0 1px rgba(255, 255, 255, 0.2);
}

.brand strong {
  font-size: 18.5px;
  letter-spacing: -0.015em;
}

.brand span {
  margin-top: 4px;
  color: #9d9080;
  font-size: 9px;
  letter-spacing: 0.22em;
}

/* ---- Market navigation ---- */

.market-nav {
  margin: 14px -4px 0;
  padding: 0 4px;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.14) transparent;
}

.market-nav::-webkit-scrollbar {
  width: 6px;
}

.market-nav::-webkit-scrollbar-thumb {
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.12);
}

.market-nav::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.2);
}

.market-nav::-webkit-scrollbar-track {
  background: transparent;
}

.nav-label {
  padding: 4px 6px 9px;
  color: #8b7f6e;
  font-size: 9px;
  letter-spacing: 0.2em;
}

.country-list {
  gap: 3px;
}

/* A market and its sources read as one unit, so the group carries the
   grouping rather than the button carrying a heavy fill. */
.country-group {
  border-radius: 10px;
  transition: background-color var(--mo-fast) var(--mo-ease);
}

.country-group.expanded {
  background: rgba(255, 255, 255, 0.026);
  padding-bottom: 2px;
}

.country-button {
  position: relative;
  min-height: 38px;
  padding: 8px 12px 8px 14px;
  border-radius: 8px;
  color: #cfc5b6;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
}

.country-button:hover {
  background: rgba(255, 255, 255, 0.04);
  color: #f0e9dd;
}

/* Quieter selection: a warm tint and a short accent rule, not a red slab. */
.country-button.active {
  background: rgba(226, 86, 43, 0.075);
  box-shadow: none;
  color: #fdf1e7;
}

.country-button.active::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 4px;
  width: 3px;
  height: 16px;
  border-radius: 2px;
  background: #e2562b;
  transform: translateY(-50%);
}

/* ---- Source rows ---- */

.source-list {
  gap: 0;
  margin-left: 15px;
  padding-left: 11px;
  border-left: 1px solid rgba(255, 255, 255, 0.07);
}

.country-group.expanded .source-list {
  padding-top: 2px;
  padding-bottom: 6px;
}

.source-button {
  position: relative;
  min-height: 30px;
  padding: 5px 9px 5px 14px;
  border-radius: 6px;
  color: #b6aa99;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

/* Replaces the ring bullet with a tick off the rail — less visual noise at
   small sizes, and it reads as a branch rather than a list marker. */
.source-button::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -11px;
  width: 7px;
  height: 1px;
  border: none;
  border-radius: 0;
  background: rgba(255, 255, 255, 0.14);
  transform: translateY(-50%);
  transition:
    background-color var(--mo-fast) var(--mo-ease),
    width var(--mo-fast) var(--mo-ease);
}

.source-button:hover {
  background: rgba(255, 255, 255, 0.04);
  color: #ede5d9;
}

.source-button:hover::before {
  width: 9px;
  background: rgba(226, 86, 43, 0.6);
}

.source-button.active {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  font-weight: 600;
}

.source-button.active::before {
  width: 9px;
  background: #e2562b;
}

/* ---- Bottom block: one card, not three ---- */

.service-status {
  gap: 9px;
  margin: 12px 0 0;
  padding: 11px 12px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-bottom: none;
  border-radius: 12px 12px 0 0;
  background: rgba(255, 255, 255, 0.028);
}

.service-status strong {
  color: #efe8dd;
  font-size: 12px;
  font-weight: 600;
}

.service-status span {
  color: #8b8070;
  font-size: 10px;
}

.status-dot {
  width: 8px;
  height: 8px;
  box-shadow: 0 0 0 4px rgba(47, 122, 82, 0.16);
}

.portal-auth-user-panel {
  gap: 12px;
  margin: 0;
  padding: 13px 12px 12px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 0 0 12px 12px;
  background: rgba(255, 255, 255, 0.028);
  box-shadow: none;
}

/* The seam between the two joined cards. */
.portal-auth-user-panel::before {
  content: "";
  display: block;
  height: 1px;
  margin: -13px -12px 1px;
  background: rgba(255, 255, 255, 0.07);
}

/* ---- Identity ---- */

.portal-auth-user-copy {
  min-height: 38px;
  padding-left: 48px;
}

/* Was the only blue element in the entire product. */
.portal-auth-user-copy::before {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: linear-gradient(150deg, #4a3f33, #2e2620);
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: #f0d9c8;
  font-size: 15px;
  font-weight: 650;
  box-shadow: none;
}

.portal-auth-user-copy > span {
  color: #857a6a;
  font-size: 8.5px;
  letter-spacing: 0.17em;
}

.portal-auth-user-copy > strong {
  color: #fff8ef;
  font-size: 14.5px;
  font-weight: 650;
}

.portal-auth-user-copy > small {
  margin-top: 5px;
  padding: 2px 7px;
  border-radius: 4px;
  border: 1px solid rgba(226, 86, 43, 0.26);
  background: rgba(226, 86, 43, 0.13);
  color: #ee8563;
  font-size: 8.5px;
  letter-spacing: 0.09em;
}

/* ---- Action groups ---- */

.portal-auth-user-actions {
  gap: 7px;
}

.portal-auth-action-label {
  margin: 3px 1px 0;
  color: #7d7263;
  font-size: 8.5px;
  letter-spacing: 0.16em;
}

/* Administration labels are long enough to wrap in a two-column grid, which
   left one button two lines tall beside a one-line neighbour. One column per
   row keeps the rhythm even and the labels intact. */
.portal-auth-admin-grid {
  grid-template-columns: 1fr;
  gap: 5px;
}

.portal-auth-admin-grid > a {
  grid-column: 1 / -1 !important;
}

.portal-auth-primary-grid {
  gap: 6px;
}

.portal-auth-user-actions a,
.portal-auth-user-actions button {
  min-height: 36px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.portal-auth-user-actions a {
  border-color: rgba(255, 255, 255, 0.09);
  background: rgba(255, 255, 255, 0.038);
  color: #d3c9b9;
  transition: background-color var(--mo-fast) var(--mo-ease), border-color var(--mo-fast) var(--mo-ease), color var(--mo-fast) var(--mo-ease);
}

.portal-auth-user-actions a:hover {
  border-color: rgba(226, 86, 43, 0.4);
  background: rgba(226, 86, 43, 0.1);
  color: #fff;
}

.portal-auth-logout-form {
  margin-top: 4px !important;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

.portal-auth-user-actions .portal-auth-logout-form button {
  min-height: 36px;
  border-color: rgba(255, 255, 255, 0.09);
  background: transparent;
  color: #b3a897;
  transition: background-color var(--mo-fast) var(--mo-ease), border-color var(--mo-fast) var(--mo-ease), color var(--mo-fast) var(--mo-ease);
}

.portal-auth-user-actions .portal-auth-logout-form button:hover {
  border-color: rgba(224, 72, 61, 0.45);
  background: rgba(224, 72, 61, 0.1);
  color: #ffb9af;
}

/* ---- Narrow desktop / tablet ---- */

@media (max-width: 960px) and (min-width: 761px) {
  :root {
    --sidebar-width: 262px;
  }

  .portal-auth-action-grid {
    grid-template-columns: 1fr;
  }

  .portal-auth-action-grid > a {
    grid-column: 1 / -1 !important;
  }
}

@media (max-width: 760px) {
  .sidebar {
    padding: 16px 14px;
  }

  .brand {
    margin: 0;
  }

  /* On mobile the status card is hidden, so the identity panel becomes a
     standalone card again and needs all four corners back. */
  .portal-auth-user-panel {
    margin: 10px 0 0;
    border-radius: 12px;
  }

  .portal-auth-user-panel::before {
    display: none;
  }

  .service-status {
    margin-right: 0;
    margin-left: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .country-group,
  .source-button::before,
  .portal-auth-user-actions a,
  .portal-auth-user-actions button {
    transition: none;
  }
}

/* ==========================================================================
   17. COLLAPSIBLE SIGNED-IN PANEL — 2026-08-12
   --------------------------------------------------------------------------
   The identity row becomes a toggle. The panel starts compact on every load
   and expands on press.

   Progressive enhancement: everything below is scoped to .is-collapsible,
   which user-panel.js adds at runtime. Without JavaScript the panel renders
   exactly as before, fully expanded, and nothing is hidden behind a toggle
   that cannot be operated.
   ========================================================================== */

.portal-auth-user-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: default;
}

.portal-auth-user-toggle .portal-auth-user-copy {
  flex: 1 1 auto;
  min-width: 0;
}

/* The chevron only means something once the panel can actually collapse. */
.portal-auth-user-chevron {
  display: none;
}

.portal-auth-user-panel.is-collapsible .portal-auth-user-toggle {
  cursor: pointer;
  border-radius: 9px;
  padding: 4px;
  margin: -4px;
  transition: background-color var(--mo-fast) var(--mo-ease);
}

.portal-auth-user-panel.is-collapsible .portal-auth-user-toggle:hover {
  background: rgba(255, 255, 255, 0.04);
}

.portal-auth-user-panel.is-collapsible .portal-auth-user-toggle:focus-visible {
  outline: 2px solid rgba(226, 86, 43, 0.7);
  outline-offset: 1px;
}

.portal-auth-user-panel.is-collapsible .portal-auth-user-chevron {
  display: block;
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  margin-right: 5px;
  border-right: 1.6px solid #9d9182;
  border-bottom: 1.6px solid #9d9182;
  transform: rotate(-45deg) translate(-1px, -1px);
  transition: transform var(--mo-base) var(--mo-ease), border-color var(--mo-fast) var(--mo-ease);
}

.portal-auth-user-panel.is-collapsible .portal-auth-user-toggle:hover
  .portal-auth-user-chevron {
  border-color: #e8dccb;
}

.portal-auth-user-panel.is-collapsible.is-open .portal-auth-user-chevron {
  transform: rotate(-135deg) translate(-2px, -2px);
}

/* Compact: the actions collapse away entirely.

   Note: grid-template-rows: 0fr does NOT work here — the actions element has
   six children, so only the first row would collapse and the rest would form
   auto-sized implicit rows. max-height collapses all of them. */
.portal-auth-user-panel.is-collapsible .portal-auth-user-actions {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transition:
    max-height var(--mo-slow) var(--mo-ease),
    opacity var(--mo-fast) var(--mo-ease),
    visibility 0s linear var(--mo-slow);
}

.portal-auth-user-panel.is-collapsible.is-open .portal-auth-user-actions {
  max-height: 600px;
  opacity: 1;
  visibility: visible;
  transition:
    max-height var(--mo-slow) var(--mo-ease),
    opacity var(--mo-base) var(--mo-ease) 50ms,
    visibility 0s;
}

/* Collapsed, the panel is a single row, so it does not need the taller
   stacked padding. */
.portal-auth-user-panel.is-collapsible {
  gap: 0;
  padding-bottom: 13px;
  transition: padding-bottom var(--mo-slow) var(--mo-ease);
}

.portal-auth-user-panel.is-collapsible.is-open {
  gap: 12px;
  padding-bottom: 12px;
}

@media (prefers-reduced-motion: reduce) {
  .portal-auth-user-panel.is-collapsible .portal-auth-user-actions,
  .portal-auth-user-panel.is-collapsible.is-open .portal-auth-user-actions,
  .portal-auth-user-panel.is-collapsible,
  .portal-auth-user-chevron {
    transition: none;
  }
}

/* ==========================================================================
   18. MOTION — 2026-08-12
   --------------------------------------------------------------------------
   The portal had 21 ad-hoc transition declarations across its stylesheets, at
   six different durations and four easings, and most interactive elements had
   none at all — hover and focus snapped. This section gives the whole product
   one motion vocabulary.

   Rules followed here:
     - only compositor-friendly properties are animated (transform, opacity,
       colour, shadow, border). Nothing animates width, height, top or left,
       because those force layout on every frame;
     - motion is short. 120ms for state feedback, 200ms for movement;
     - one easing. A gentle ease-out, so things arrive rather than stop dead;
     - anything that repeats hundreds of times on a page (table rows, list
       items) gets colour-only transitions, never transforms;
     - every rule is switched off under prefers-reduced-motion, including the
       ones inherited from the older stylesheets.
   ========================================================================== */

:root {
  --mo-ease: cubic-bezier(0.32, 0.72, 0.24, 1);
  --mo-fast: 200ms;
  --mo-base: 320ms;
  --mo-slow: 440ms;
}

/* ---- Buttons, links and controls ---- */

.auth-page a,
.auth-page button,
.supplier-page a,
.supplier-page button,
.ops-shell a,
.ops-shell button,
.analysis-page a,
.analysis-page button,
.tender-detail-body a,
.tender-detail-body button,
.text-button,
.clear-filters-button,
.empty-clear-button,
.previous-page-button,
.next-page-button,
.tender-ai-button,
.supplier-mini-button,
.supplier-add-button,
.detail-primary-button,
.detail-secondary-button,
.detail-soft-button,
.detail-danger-button {
  transition:
    background-color var(--mo-fast) var(--mo-ease),
    border-color var(--mo-fast) var(--mo-ease),
    color var(--mo-fast) var(--mo-ease),
    box-shadow var(--mo-fast) var(--mo-ease),
    transform var(--mo-fast) var(--mo-ease);
}

/* A press should register. 1px is enough to feel, small enough not to jump. */
.auth-form button[type="submit"]:active:not(:disabled),
.supplier-primary-button:active:not(:disabled),
.analysis-primary:active:not(:disabled),
.secondary-button:active,
.supplier-secondary-button:active,
.detail-primary-button:active,
.detail-secondary-button:active,
.tender-ai-button:active {
  transform: translateY(1px);
}

input,
select,
textarea {
  transition:
    border-color var(--mo-fast) var(--mo-ease),
    box-shadow var(--mo-fast) var(--mo-ease),
    background-color var(--mo-fast) var(--mo-ease);
}

/* ---- Cards ---- */

.tender-card {
  transition:
    transform var(--mo-base) var(--mo-ease),
    box-shadow var(--mo-base) var(--mo-ease),
    border-color var(--mo-base) var(--mo-ease);
  will-change: auto;
}

.tender-card:hover {
  transform: translateY(-2px);
}

.stat-card,
.work-summary-card,
.workspace-card,
.supplier-card-head,
.tender-supplier-card,
.ops-check-card,
.admin-user-row {
  transition:
    border-color var(--mo-base) var(--mo-ease),
    box-shadow var(--mo-base) var(--mo-ease),
    background-color var(--mo-base) var(--mo-ease);
}

/* ---- Tabs ---- */

.view-tab,
.workspace-tab {
  transition:
    background-color var(--mo-fast) var(--mo-ease),
    color var(--mo-fast) var(--mo-ease),
    border-color var(--mo-fast) var(--mo-ease),
    box-shadow var(--mo-fast) var(--mo-ease);
}

.view-tab-count,
.workspace-tab-count {
  transition:
    background-color var(--mo-fast) var(--mo-ease),
    color var(--mo-fast) var(--mo-ease);
}

/* ---- Rows and chips: colour only ----
   These repeat many times per page, so they must never animate transforms. */

.ops-table tbody tr td,
.audit-table tbody tr td,
.supplier-list table tbody tr td,
.tender-source-row,
.supplier-chip,
.workspace-assignee-chip,
.ops-event-row {
  transition: background-color var(--mo-fast) var(--mo-ease);
}

/* ---- Sidebar rail ---- */

.country-button,
.source-button,
.brand-icon {
  transition:
    background-color var(--mo-fast) var(--mo-ease),
    color var(--mo-fast) var(--mo-ease),
    box-shadow var(--mo-fast) var(--mo-ease);
}

/* ---- Panels that appear ---- */

.supplier-dialog {
  animation: mo-panel-in var(--mo-slow) var(--mo-ease);
}

@keyframes mo-panel-in {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.995);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Content that arrives after a fetch fades in rather than popping. */
.analysis-result,
.workspace-panel:not(.hidden) {
  animation: mo-fade-in var(--mo-base) var(--mo-ease);
}

@keyframes mo-fade-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* ---- Loading states ---- */

.analysis-spinner,
.detail-loader {
  animation-timing-function: linear;
}

.analysis-progress {
  transition: width var(--mo-slow) var(--mo-ease);
}

/* ---- Scrollbars ----
   The main column scrolls constantly during triage; the default bar is a
   heavy light-on-light slab against the warm page. */

.main-content,
.ops-table-wrap,
.supplier-list {
  scrollbar-width: thin;
  scrollbar-color: rgba(26, 23, 18, 0.22) transparent;
}

.main-content::-webkit-scrollbar,
.ops-table-wrap::-webkit-scrollbar,
.supplier-list::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.main-content::-webkit-scrollbar-thumb,
.ops-table-wrap::-webkit-scrollbar-thumb,
.supplier-list::-webkit-scrollbar-thumb {
  border: 3px solid transparent;
  border-radius: 6px;
  background: rgba(26, 23, 18, 0.2);
  background-clip: content-box;
  transition: background-color var(--mo-fast) var(--mo-ease);
}

.main-content::-webkit-scrollbar-thumb:hover,
.ops-table-wrap::-webkit-scrollbar-thumb:hover,
.supplier-list::-webkit-scrollbar-thumb:hover {
  background: rgba(26, 23, 18, 0.34);
  background-clip: content-box;
}

.main-content::-webkit-scrollbar-track,
.ops-table-wrap::-webkit-scrollbar-track,
.supplier-list::-webkit-scrollbar-track {
  background: transparent;
}

/* ---- Reduced motion ----
   Authoritative switch-off. This is the last stylesheet on every page, so it
   also neutralises the motion declared in the older stylesheets. */

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

  .tender-card:hover {
    transform: none;
  }
}

/* ==========================================================================
   19. OPEN, CLOSE AND PRESS — 2026-08-12
   --------------------------------------------------------------------------
   Section 18 gave hover and focus a shared vocabulary. This section covers the
   two interactions that still snapped:

     1. PRESS — every control now gives the same physical feedback.
     2. OPEN / CLOSE — panels, tabs, dialogs and the sidebar market groups.

   Open/close is the harder half. The portal hides things with
   `.hidden { display: none !important }`, and display is a discrete property,
   so historically it could not be transitioned at all. This uses
   `transition-behavior: allow-discrete` together with `@starting-style`, which
   lets the browser hold the element in the layout for the length of the
   transition and animate opacity and transform across it.

   Where a browser does not support those, every rule below is simply ignored
   and the element appears exactly as it does today. Nothing depends on it.
   ========================================================================== */

/* ---- 1. Press ----------------------------------------------------------
   One displacement for everything clickable, including the controls the
   earlier sections missed: sidebar rows, tabs, chips and icon buttons. */

.country-button:active,
.source-button:active,
.view-tab:active,
.workspace-tab:active,
.supplier-chip:active,
.supplier-icon-button:active,
.supplier-mini-button:active,
.text-button:active,
.clear-filters-button:active,
.empty-clear-button:active,
.previous-page-button:active,
.next-page-button:active,
.tender-ai-button:active,
.ops-header-actions a:active,
.ops-refresh-link:active,
.account-header-actions a:active,
.account-header-actions button:active,
.supplier-header-actions a:active,
.portal-auth-user-actions a:active,
.portal-auth-user-actions button:active,
.portal-auth-user-toggle:active,
.danger-button:active,
.admin-delete-form button:active,
.analysis-back:active {
  transform: translateY(1px);
}

/* The press must snap in and ease out, otherwise a quick click never shows
   the displacement at all. */
.country-button,
.source-button,
.view-tab,
.workspace-tab,
.supplier-chip,
.supplier-icon-button,
.supplier-mini-button,
.text-button,
.portal-auth-user-toggle,
.danger-button {
  transition-property: background-color, border-color, color, box-shadow, transform;
  transition-duration: var(--mo-fast);
  transition-timing-function: var(--mo-ease);
}

:where(button, a, [role="button"]):active {
  transition-duration: 40ms;
}

/* Disabled controls must not appear pressable. */
button:disabled:active,
.analysis-primary:disabled:active {
  transform: none;
}

/* ---- 2. Open and close: .hidden ---------------------------------------- */

.workspace-panel,
.analysis-result,
.analysis-progress,
.analysis-error,
.detail-error-card,
.detail-loading-card,
.supplier-message,
.auth-message,
.tender-card-links,
.attention-panel,
.work-summary-card {
  transition:
    opacity var(--mo-base) var(--mo-ease),
    transform var(--mo-base) var(--mo-ease),
    display var(--mo-base) var(--mo-ease) allow-discrete;
}

/* The state each of these animates FROM when it is first shown. */
@starting-style {
  .workspace-panel:not(.hidden),
  .analysis-result:not(.hidden),
  .analysis-progress:not(.hidden),
  .analysis-error:not(.hidden),
  .detail-error-card:not(.hidden),
  .detail-loading-card:not(.hidden),
  .supplier-message:not(.hidden),
  .auth-message:not(.hidden),
  .tender-card-links:not(.hidden),
  .attention-panel:not(.hidden),
  .work-summary-card:not(.hidden) {
    opacity: 0;
    transform: translateY(4px);
  }
}

.workspace-panel.hidden,
.analysis-result.hidden,
.analysis-progress.hidden,
.analysis-error.hidden,
.detail-error-card.hidden,
.detail-loading-card.hidden,
.supplier-message.hidden,
.auth-message.hidden,
.tender-card-links.hidden,
.attention-panel.hidden,
.work-summary-card.hidden {
  opacity: 0;
  transform: translateY(4px);
}

/* ---- 3. Open and close: the supplier dialog ---------------------------- */

.supplier-dialog {
  opacity: 0;
  transform: translateY(10px) scale(0.98);
  transition:
    opacity var(--mo-base) var(--mo-ease),
    transform var(--mo-base) var(--mo-ease),
    overlay var(--mo-base) var(--mo-ease) allow-discrete,
    display var(--mo-base) var(--mo-ease) allow-discrete;
}

.supplier-dialog[open] {
  opacity: 1;
  transform: none;
}

@starting-style {
  .supplier-dialog[open] {
    opacity: 0;
    transform: translateY(10px) scale(0.98);
  }
}

.supplier-dialog::backdrop {
  opacity: 0;
  transition:
    opacity var(--mo-base) var(--mo-ease),
    overlay var(--mo-base) var(--mo-ease) allow-discrete,
    display var(--mo-base) var(--mo-ease) allow-discrete;
}

.supplier-dialog[open]::backdrop {
  opacity: 1;
}

@starting-style {
  .supplier-dialog[open]::backdrop {
    opacity: 0;
  }
}

/* ---- 4. Open and close: sidebar market groups --------------------------
   base.css animates this with max-height: 0 -> 720px. Because a market's
   source list is only ~70px tall, the reveal finishes in the first tenth of
   the transition and the collapse appears to do nothing until the very end,
   then snaps shut. Measured: 66px of the 68px final height was reached in the
   first frame.

   interpolate-size lets height: 0 -> auto animate properly, so the motion
   matches the content. Browsers without it keep the max-height behaviour
   below, which is what ships today. */

:root {
  interpolate-size: allow-keywords;
}

.source-list {
  transition:
    height var(--mo-slow) var(--mo-ease),
    max-height var(--mo-slow) var(--mo-ease),
    padding var(--mo-slow) var(--mo-ease),
    opacity var(--mo-base) var(--mo-ease);
  opacity: 0;
}

@supports (interpolate-size: allow-keywords) {
  .source-list {
    height: 0;
    max-height: none;
  }

  .country-group.expanded .source-list {
    height: auto;
  }
}

.country-group.expanded .source-list {
  opacity: 1;
}

/* ---- 5. Open and close: workspace tab panels --------------------------- */

.workspace-panel:not(.hidden) {
  animation: mo-panel-swap var(--mo-base) var(--mo-ease);
}

@keyframes mo-panel-swap {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* ---- Reduced motion ---------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .country-button:active,
  .source-button:active,
  .view-tab:active,
  .workspace-tab:active,
  .portal-auth-user-toggle:active,
  :where(button, a, [role="button"]):active {
    transform: none;
  }

  .workspace-panel,
  .analysis-result,
  .supplier-dialog,
  .supplier-dialog::backdrop,
  .source-list {
    transition-duration: 0.01ms !important;
  }

  .source-list {
    opacity: 1;
  }
}

/* ==========================================================================
   20. SMOOTHER — 2026-08-12
   --------------------------------------------------------------------------
   Sections 18 and 19 were tuned for restraint: 140ms feedback, 200ms movement.
   That reads as crisp rather than smooth — the motion is over before the eye
   registers it as motion at all.

   This section slows the whole vocabulary to a perceptible range and adds the
   thing that was still missing: content that ARRIVES. Panels, cards and rows
   now rise into place instead of appearing already positioned.

   Durations are now 200ms for feedback, 320ms for movement, 440ms for panels,
   on a softer curve that decelerates longer into the finish.
   ========================================================================== */

/* ---- Press: scale rather than shift ----
   A 1px displacement is invisible on a large button. A slight scale is felt on
   every control regardless of size, and reads as the surface yielding. */

.auth-form button[type="submit"]:active:not(:disabled),
.supplier-primary-button:active:not(:disabled),
.analysis-primary:active:not(:disabled),
.secondary-button:active,
.supplier-secondary-button:active,
.detail-primary-button:active,
.detail-secondary-button:active,
.tender-ai-button:active,
.danger-button:active,
.country-button:active,
.source-button:active,
.view-tab:active,
.workspace-tab:active,
.portal-auth-user-actions a:active,
.portal-auth-user-actions button:active,
.portal-auth-user-toggle:active,
.ops-header-actions a:active,
.account-header-actions a:active,
.supplier-header-actions a:active {
  transform: scale(0.975);
}

/* Release is slow and eased; the press itself stays quick so it feels
   immediate rather than laggy. */
:where(button, a, [role="button"]) {
  transition-duration: var(--mo-fast);
}

:where(button, a, [role="button"]):active {
  transition-duration: 60ms;
}

button:disabled:active {
  transform: none;
}

/* ---- Content arrives ---- */

@keyframes mo-rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.hero,
.stat-grid,
.work-summary-card,
.search-panel,
.view-tabs,
.ops-section,
.ops-overview,
.supplier-header,
.supplier-summary,
.supplier-toolbar,
.account-card,
.account-panel,
.admin-user-list-card,
.analysis-upload-card {
  animation: mo-rise var(--mo-slow) var(--mo-ease) backwards;
}

/* A short cascade so the page assembles rather than snapping in as one block.
   Capped deliberately: past a handful of steps the last element feels late. */
.stat-grid { animation-delay: 40ms; }
.work-summary-card { animation-delay: 80ms; }
.search-panel { animation-delay: 120ms; }
.view-tabs { animation-delay: 160ms; }

.ops-section:nth-of-type(2) { animation-delay: 60ms; }
.ops-section:nth-of-type(3) { animation-delay: 120ms; }
.ops-section:nth-of-type(4) { animation-delay: 180ms; }

/* Tender cards rise as the board fills. The stagger is capped at eight so a
   long result set does not take a visible second to finish arriving, and the
   board re-renders on every filter change. */
.tender-card {
  animation: mo-rise var(--mo-base) var(--mo-ease) backwards;
}

.tender-card:nth-child(1) { animation-delay: 0ms; }
.tender-card:nth-child(2) { animation-delay: 30ms; }
.tender-card:nth-child(3) { animation-delay: 60ms; }
.tender-card:nth-child(4) { animation-delay: 90ms; }
.tender-card:nth-child(5) { animation-delay: 120ms; }
.tender-card:nth-child(6) { animation-delay: 150ms; }
.tender-card:nth-child(7) { animation-delay: 180ms; }
.tender-card:nth-child(n + 8) { animation-delay: 200ms; }

/* Table rows arrive together rather than individually — hundreds of staggered
   rows would be both slow and distracting. */
.ops-table tbody,
.audit-table tbody,
.supplier-list table tbody {
  animation: mo-fade-in var(--mo-slow) var(--mo-ease) backwards;
  animation-delay: 100ms;
}

/* ---- Hover gets room to breathe ---- */

.tender-card:hover {
  transform: translateY(-3px);
}

.stat-card:hover,
.work-summary-card:hover {
  transform: translateY(-1px);
}

.stat-card,
.work-summary-card {
  transition:
    transform var(--mo-base) var(--mo-ease),
    border-color var(--mo-base) var(--mo-ease),
    box-shadow var(--mo-base) var(--mo-ease);
}

/* ---- Open and close, slowed to match ---- */

.portal-auth-user-panel.is-collapsible .portal-auth-user-actions {
  transition:
    max-height var(--mo-slow) var(--mo-ease),
    opacity var(--mo-base) var(--mo-ease),
    visibility 0s linear var(--mo-slow);
}

.portal-auth-user-panel.is-collapsible.is-open .portal-auth-user-actions {
  transition:
    max-height var(--mo-slow) var(--mo-ease),
    opacity var(--mo-base) var(--mo-ease) 60ms,
    visibility 0s;
}

/* ---- Reduced motion: nothing above survives ---- */

@media (prefers-reduced-motion: reduce) {
  .hero,
  .stat-grid,
  .work-summary-card,
  .search-panel,
  .view-tabs,
  .ops-section,
  .ops-overview,
  .supplier-header,
  .supplier-summary,
  .supplier-toolbar,
  .account-card,
  .account-panel,
  .admin-user-list-card,
  .analysis-upload-card,
  .tender-card,
  .ops-table tbody,
  .audit-table tbody,
  .supplier-list table tbody {
    animation: none !important;
  }

  .tender-card:hover,
  .stat-card:hover,
  .work-summary-card:hover,
  :where(button, a, [role="button"]):active {
    transform: none;
  }
}

/* Animations do not run when printing, and fill-mode would leave every
   animated block at its start state — invisible. Audit packs must print. */
@media print {
  .hero,
  .stat-grid,
  .work-summary-card,
  .search-panel,
  .view-tabs,
  .ops-section,
  .ops-overview,
  .supplier-header,
  .supplier-summary,
  .supplier-toolbar,
  .account-card,
  .account-panel,
  .admin-user-list-card,
  .analysis-upload-card,
  .tender-card,
  .ops-table tbody,
  .audit-table tbody,
  .supplier-list table tbody {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}


/* Phase 15 — compact Pursuing readiness indicator */
.tender-readiness-note {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 0 9px;
  border: 1px solid #e1c9a2;
  border-radius: 999px;
  background: #fff8e9;
  color: #745a2b;
  font-size: 11px;
  font-weight: 700;
}

.tender-readiness-note.ready {
  border-color: #b9d0ad;
  background: #eef6e8;
  color: #44633a;
}

/* Phase 19 — portal-wide knowledge search entry */
.portal-global-search { margin-top:18px; display:flex; gap:8px; width:min(760px,100%); }
.portal-global-search input { flex:1 1 auto; min-width:0; min-height:43px; padding:0 13px; border:1px solid #d7dde5; border-radius:10px; background:#fff; color:#26313d; font:500 13px Inter,sans-serif; }
.portal-global-search button { min-width:88px; min-height:43px; padding:0 15px; border:0; border-radius:10px; background:#202832; color:#fff; font-weight:700; cursor:pointer; }
@media (max-width:560px) { .portal-global-search { flex-direction:column; } }

/* Phase 22 — tender amendment intelligence */
.amendment-badge {
  border-color: #c9a94b;
  background: #fff8df;
  color: #6c5200;
}
.amendment-badge.severity-high,
.amendment-badge.severity-critical {
  border-color: #d77455;
  background: #fff0ea;
  color: #8c2f16;
}
