
  :root{
    --ink: oklch(0.16 0.012 255);
    --ink-2: oklch(0.28 0.01 255);
    --ink-3: oklch(0.45 0.008 255);
    --ink-4: oklch(0.62 0.006 255);
    --line: oklch(0.88 0.006 255);
    --line-2: oklch(0.93 0.005 255);
    --bone: oklch(0.985 0.003 85);
    --bone-2: oklch(0.965 0.004 85);
    --bone-3: oklch(0.945 0.005 85);
    --indigo: oklch(0.52 0.19 275);
    --indigo-soft: oklch(0.94 0.03 275);
    --amber: oklch(0.76 0.13 70);
    --amber-soft: oklch(0.96 0.04 80);
    --green: oklch(0.62 0.14 150);
    --green-soft: oklch(0.95 0.04 150);
    --red: oklch(0.58 0.18 25);
    --red-soft: oklch(0.96 0.03 25);
    --sans:"Inter Tight",ui-sans-serif,system-ui,sans-serif;
    --serif:"Instrument Serif",Times,serif;
    --mono:"JetBrains Mono",ui-monospace,monospace;
  }

  /* ── Dark palette override (JS-toggled via data-theme="dark" on <html>) ── */
  :root[data-theme="dark"] {
    --ink: oklch(0.96 0.005 255);
    --ink-2: oklch(0.86 0.008 255);
    --ink-3: oklch(0.68 0.01 255);
    --ink-4: oklch(0.52 0.012 255);
    --line: oklch(0.28 0.01 255);
    --line-2: oklch(0.22 0.008 255);
    --bone: oklch(0.16 0.008 255);
    --bone-2: oklch(0.19 0.009 255);
    --bone-3: oklch(0.23 0.01 255);
    --indigo: oklch(0.72 0.16 275);
    --indigo-soft: oklch(0.26 0.06 275);
    --amber: oklch(0.78 0.13 70);
    --amber-soft: oklch(0.28 0.06 70);
    --green: oklch(0.72 0.15 150);
    --green-soft: oklch(0.26 0.06 150);
    --red: oklch(0.7 0.17 25);
    --red-soft: oklch(0.28 0.07 25);
  }

  /* ── OS dark mode fallback (no data-theme set, respects prefers-color-scheme) ── */
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
      --ink: oklch(0.96 0.005 255);
      --ink-2: oklch(0.86 0.008 255);
      --ink-3: oklch(0.68 0.01 255);
      --ink-4: oklch(0.52 0.012 255);
      --line: oklch(0.28 0.01 255);
      --line-2: oklch(0.22 0.008 255);
      --bone: oklch(0.16 0.008 255);
      --bone-2: oklch(0.19 0.009 255);
      --bone-3: oklch(0.23 0.01 255);
      --indigo: oklch(0.72 0.16 275);
      --indigo-soft: oklch(0.26 0.06 275);
      --amber: oklch(0.78 0.13 70);
      --amber-soft: oklch(0.28 0.06 70);
      --green: oklch(0.72 0.15 150);
      --green-soft: oklch(0.26 0.06 150);
      --red: oklch(0.7 0.17 25);
      --red-soft: oklch(0.28 0.07 25);
    }
  }
  html,body{margin:0;background:var(--bone);font-family:var(--sans);color:var(--ink);-webkit-font-smoothing:antialiased}
  *{box-sizing:border-box}
  .mono{font-family:var(--mono);font-feature-settings:"ss01","cv11"}
  .serif{font-family:var(--serif);font-weight:400}
  .st *::-webkit-scrollbar{width:6px;height:6px}
  .st *::-webkit-scrollbar-thumb{background:rgba(0,0,0,.12);border-radius:999px}

  /* Layout */
  .layout {
    display: grid;
    grid-template-columns: 240px 1fr 320px;
    height: 100vh;
    gap: 0;
  }

  /* Mobile brand bar (hidden by default; shown only on mobile via the
     @media block below). Sits inside .center, above .center-topbar. */
  .mobile-brand-bar { display: none; }

  /* Left sidebar */
  .sidebar-left {
    border-right: 1px solid var(--line);
    background: var(--bone-2);
    display: flex;
    flex-direction: column;
    overflow: auto;
    transition: width 0.18s ease;
  }

  /* Collapsed state — icons only */
  .layout.left-collapsed {
    grid-template-columns: 60px 1fr 320px;
  }

  .layout.right-collapsed {
    grid-template-columns: 240px 1fr 40px;
  }

  .layout.left-collapsed.right-collapsed {
    grid-template-columns: 60px 1fr 40px;
  }

  @media (max-width: 1400px) {
    .layout.left-collapsed {
      grid-template-columns: 60px 1fr 320px;
    }
    .layout.left-collapsed.right-collapsed {
      grid-template-columns: 60px 1fr 40px;
    }
  }

  .sidebar-left.collapsed .nav-item-label,
  .sidebar-left.collapsed .nav-section-label,
  .sidebar-left.collapsed .role-badge,
  .sidebar-left.collapsed .sidebar-left-header > div:first-child span {
    display: none;
  }

  .sidebar-left.collapsed .nav-item {
    justify-content: center;
    padding: 9px 0;
  }

  .sidebar-left.collapsed .sidebar-left-header {
    padding: 14px 0 12px;
    justify-content: center;
    flex-direction: column;
    gap: 8px;
  }

  .sidebar-left.collapsed .sidebar-left-header > div:first-child {
    justify-content: center;
  }

  .sidebar-left.collapsed .collapse-btn {
    transform: rotate(180deg);
  }

  .sidebar-left.collapsed .nav-section {
    padding-top: 8px !important;
    border-top: 1px solid var(--line-2);
    margin-top: 6px;
  }

  .sidebar-left.collapsed .nav-section:first-child {
    border-top: none;
    margin-top: 0;
  }

  .sidebar-left-header {
    padding: 14px 18px 12px;
    border-bottom: 1px solid var(--line-2);
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .role-badge {
    margin-left: auto;
    font-size: 9.5px;
    padding: 3px 7px;
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--ink-3);
    letter-spacing: .08em;
  }

  .collapse-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ink-4);
    font-size: 10px;
    padding: 2px 4px;
    transition: color 0.12s;
  }

  .collapse-btn:hover {
    color: var(--ink);
  }

  .sidebar-left-content {
    flex: 1;
    overflow: auto;
    padding: 12px 0;
  }

  .sidebar-left-footer {
    border-top: 1px solid var(--line-2);
    padding: 12px 0;
    display: flex;
    flex-direction: column;
  }

  .nav-section {
    padding: 0;
  }

  .nav-section-label {
    font-size: 10px;
    letter-spacing: 0.1em;
    color: var(--ink-4);
    text-transform: uppercase;
    padding: 6px 18px;
    margin-bottom: 0;
    font-weight: 600;
  }

  .nav-item {
    padding: 7px 18px;
    font-size: 12.5px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--ink-2);
    transition: background 0.12s;
    margin-bottom: 0;
  }

  /* Button-as-nav-item (e.g. Logout): reset native button styles so it
     matches the <a> nav-items above it. Inline styles are not needed. */
  button.nav-item {
    border: none;
    background: none;
    font-family: inherit;
    font-size: 12.5px;
    width: 100%;
    text-align: left;
  }

  .nav-item:hover {
    background: var(--bone-3);
  }

  .nav-item.active {
    background: var(--bone-3);
    color: var(--indigo);
    font-weight: 500;
  }

  /* Center content */
  .center {
    background: var(--bone);
    overflow: auto;
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .center-topbar {
    padding: 18px 32px 14px;
    border-bottom: 1px solid var(--line-2);
    background: var(--bone-2);
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .center-topbar-left {
    flex: 1;
  }

  .center-topbar h2 {
    font-size: 20px;
    font-weight: 600;
    letter-spacing: -0.015em;
    margin: 0;
  }

  .center-topbar-label {
    font-size: 10px;
    color: var(--ink-4);
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .search-box {
    padding: 8px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--bone);
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink);
    width: 280px;
  }

  .search-box::placeholder {
    color: var(--ink-4);
  }

  .topbar-controls {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .icon-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ink-3);
    font-size: 12px;
    padding: 5px 8px;
    transition: all 0.12s;
    border-radius: 5px;
  }

  .icon-btn:hover {
    background: var(--bone-3);
    color: var(--ink);
  }

  .icon-btn.small {
    font-size: 10px;
    padding: 4px 6px;
  }

  .center-scroll {
    flex: 1;
    overflow: auto;
    padding: 22px 32px 48px;
    min-width: 0;
  }

  /* Vendor list */
  .vendor-list {
    display: flex;
    flex-direction: column;
    gap: 0;
  }

  .vendor-list-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(120px, 200px) 40px;
    gap: 16px;
    padding: 12px 18px;
    background: var(--bone-3);
    border: 1px solid var(--line);
    border-bottom: none;
    border-radius: 10px 10px 0 0;
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-4);
    font-weight: 600;
  }

  .vendor-list-header-cell {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
    user-select: none;
  }

  .vendor-list-header-cell:hover {
    color: var(--ink-2);
  }

  .sort-indicator {
    font-size: 9px;
    opacity: 0.5;
  }

  .vendor-card {
    border: 1px solid var(--line);
    border-radius: 0;
    background: var(--bone-2);
    background-clip: padding-box;
    overflow: hidden;
    border-bottom: none;
  }

  .vendor-card:last-child {
    border-bottom: 1px solid var(--line);
    border-radius: 0 0 10px 10px;
  }

  .vendor-header {
    padding: 14px 18px;
    background: var(--bone-2);
    border-bottom: 1px solid var(--line-2);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(120px, 200px) 40px;
    gap: 16px;
    align-items: center;
    cursor: pointer;
    transition: background 0.12s;
  }

  .vendor-header:hover {
    background: var(--bone-3);
  }

  .vendor-header-sortable {
    font-size: 10px;
    color: var(--ink-4);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0;
  }

  .vendor-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .vendor-expand-icon {
    font-size: 18px;
    color: var(--ink-3);
    text-align: center;
    transition: transform 0.12s;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .vendor-expand-icon.collapsed {
    transform: rotate(-90deg);
  }

  .vendor-products {
    display: flex;
    flex-direction: column;
  }

  .product-row {
    padding: 10px 32px;
    border-bottom: 1px solid var(--line-2);
    display: grid;
    grid-template-columns: 140px 1fr 100px 80px;
    gap: 12px;
    align-items: center;
    font-size: 12px;
    color: var(--ink-2);
  }

  .product-row:last-child {
    border-bottom: none;
  }

  .product-name {
    font-weight: 500;
    color: var(--ink);
  }

  .product-status {
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 500;
    text-align: center;
  }

  .product-status.active {
    background: var(--green-soft);
    color: var(--green);
  }

  .product-status.review {
    background: var(--amber-soft);
    color: var(--amber);
  }

  /* Right sidebar - KPIs */
  .sidebar-right {
    border-left: 1px solid var(--line);
    background: var(--bone-2);
    display: flex;
    flex-direction: column;
    overflow: auto;
  }

  .sidebar-right-header {
    padding: 18px 20px;
    border-bottom: 1px solid var(--line-2);
    background: var(--bone);
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .sidebar-right-header-left {
    flex: 1;
  }

  .sidebar-right-label {
    font-size: 10px;
    letter-spacing: 0.1em;
    color: var(--ink-4);
    text-transform: uppercase;
    margin-bottom: 6px;
  }

  .sidebar-right-title {
    font-size: 14px;
    font-weight: 500;
  }

  .sidebar-right-content {
    flex: 1;
    overflow: auto;
    padding: 18px 20px;
  }

  .kpi-block {
    margin-bottom: 20px;
  }

  /* ============================================================
     INFO BLOCK — bordered container with compact label/value rows.
     Use for record metadata (audit fields, account snapshots, etc.)
     in the right rail. Differs from .kpi-block: small text, no big
     numbers — purely textual key/value info.
     Reference design: public/admin-dashboard.html "Account" card.
     ============================================================ */
  .info-block {
    padding: 12px 14px;
    background: var(--bone);
    border: 1px solid var(--line);
    border-radius: 8px;
    margin-bottom: 14px;
  }
  .info-block-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-weight: 600;
    margin-bottom: 10px;
  }
  .info-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    font-size: 12px;
    padding: 4px 0;
  }
  .info-row-label {
    color: var(--ink-3);
  }
  .info-row-value {
    color: var(--ink);
    font-weight: 500;
    text-align: right;
  }

  .kpi-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--ink-4);
    text-transform: uppercase;
    margin-bottom: 8px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
  }

  .kpi-icon {
    font-size: 12px;
    opacity: 0.7;
  }

  .kpi-value {
    font-size: 32px;
    font-weight: 700;
    color: var(--ink);
    line-height: 1.2;
    display: flex;
    align-items: baseline;
    gap: 6px;
  }

  .kpi-value-accent {
    font-size: 24px;
    font-weight: 600;
  }

  .kpi-subtext {
    font-size: 12px;
    color: var(--ink-2);
    margin-top: 6px;
    line-height: 1.5;
  }

  .kpi-trend {
    font-size: 12px;
    font-weight: 500;
  }

  .kpi-trend.up {
    color: var(--green);
  }

  .kpi-trend.down {
    color: var(--red);
  }

  .kpi-trend.neutral {
    color: var(--ink-4);
  }

  .kpi-divider {
    height: 1px;
    background: var(--line-2);
    margin: 16px 0;
  }

  /* Expand button (hidden by default) */
  .expand-btn {
    position: absolute;
    top: 14px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ink-3);
    font-size: 10px;
    padding: 2px 4px;
    z-index: 50;
    transition: color 0.12s;
    display: none;
  }

  .expand-btn:hover {
    color: var(--ink);
  }

  .expand-btn.left {
    left: 8px;
  }

  .expand-btn.right {
    right: 8px;
  }

  .expand-btn.visible {
    display: block;
  }

  /* Responsive */
  @media (max-width: 1200px) {
    .layout {
      grid-template-columns: 60px 1fr 320px;
    }
    .layout.right-collapsed {
      grid-template-columns: 60px 1fr 40px;
    }
    .sidebar-left {
      /* Force icon-only collapsed rail at narrow viewports */
    }
    .sidebar-left .nav-item-label,
    .sidebar-left .nav-section-label,
    .sidebar-left .role-badge,
    .sidebar-left .sidebar-left-header > div:first-child span {
      display: none;
    }
    .sidebar-left .nav-item {
      justify-content: center;
      padding: 9px 0;
    }
    .sidebar-left .sidebar-left-header {
      padding: 14px 0 12px;
      justify-content: center;
    }
    .sidebar-left .sidebar-left-header > div:first-child {
      justify-content: center;
    }
    .expand-btn.left.visible {
      display: block;
    }
  }

  @media (max-width: 1400px) {
    .layout {
      grid-template-columns: 240px 1fr 320px;
    }
    .layout.right-collapsed {
      grid-template-columns: 240px 1fr 40px;
    }
    .layout.left-collapsed.right-collapsed {
      grid-template-columns: 60px 1fr 40px;
    }
    .expand-btn.right.visible {
      display: block;
    }
  }

  /* ============================================================
     ADDED: nav items are <a href> anchors (not <div>) so navigation works.
     Reset anchor defaults on .nav-item to match the original <div> styling.
     ============================================================ */
  .nav-item, .nav-item:link, .nav-item:visited, .nav-item:hover, .nav-item:active {
    text-decoration: none;
    color: inherit;
  }

  /* ============================================================
     RESPONSIVE — auto-collapse and mobile overlay
     Breakpoints:
       - Desktop (>=1200px): both sidebars expanded by default
       - Tablet (900-1199px): right sidebar auto-collapsed to rail (via JS),
         left becomes icon-only rail (existing rule at line ~562)
       - Mobile (<900px): sidebars become slide-in overlays controlled by
         hamburger (left) and context button (right) in the topbar.
     ============================================================ */

  /* Mobile-only buttons — hidden on desktop, shown when body.has-mobile-shell */
  .mobile-hamburger,
  .mobile-context-btn {
    display: none;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 6px 9px;
    height: 32px;
    cursor: pointer;
    color: var(--ink);
    font-family: var(--sans);
  }
  .mobile-hamburger:hover,
  .mobile-context-btn:hover {
    background: var(--bone-3);
  }

  /* Backdrop element added by JS when overlay is open */
  .mobile-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 150;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
  }
  .mobile-backdrop.active {
    opacity: 1;
    pointer-events: auto;
  }

  /* ============= Mobile (<900px) — overlay sidebars ============= */
  @media (max-width: 899px) {

    /* Layout collapses to single column when in mobile mode */
    body.has-mobile-shell .layout {
      grid-template-columns: 1fr !important;
      grid-template-rows: auto;
    }

    /* Sidebars leave the grid flow and become fixed overlays */
    body.has-mobile-shell .sidebar-left,
    body.has-mobile-shell .sidebar-right {
      position: fixed;
      top: 0;
      height: 100vh;
      z-index: 200;
      transition: transform 0.22s ease;
      box-shadow: 0 0 24px rgba(0, 0, 0, 0.08);
    }

    body.has-mobile-shell .sidebar-left {
      left: 0;
      width: 280px;
      max-width: 85vw;
      transform: translateX(-100%);
      border-right: 1px solid var(--line);
    }

    body.has-mobile-shell .sidebar-right {
      right: 0;
      width: 320px;
      max-width: 90vw;
      transform: translateX(100%);
      border-left: 1px solid var(--line);
    }

    body.has-mobile-shell .sidebar-left.mobile-open,
    body.has-mobile-shell .sidebar-right.mobile-open {
      transform: translateX(0);
    }

    /* Force full nav (labels visible) inside the mobile overlay,
       overriding the 1200px icon-rail rule that would otherwise hide them */
    body.has-mobile-shell .sidebar-left .nav-item-label,
    body.has-mobile-shell .sidebar-left .nav-section-label,
    body.has-mobile-shell .sidebar-left .role-badge,
    body.has-mobile-shell .sidebar-left .sidebar-left-header > div:first-child span {
      display: inline !important;
    }
    body.has-mobile-shell .sidebar-left .nav-item {
      justify-content: flex-start !important;
      padding: 9px 14px !important;
    }
    body.has-mobile-shell .sidebar-left .sidebar-left-header {
      padding: 18px 16px 12px !important;
      justify-content: flex-start !important;
      flex-direction: row !important;
    }

    /* Show mobile-only topbar buttons */
    body.has-mobile-shell .mobile-hamburger,
    body.has-mobile-shell .mobile-context-btn {
      display: inline-flex;
    }
    body.has-mobile-shell .mobile-context-btn {
      margin-left: auto;
    }

    /* Hide desktop "toggle sidebars" control on mobile — drawers replace it.
       (Other items in .topbar-controls, like the download button, stay visible.) */
    body.has-mobile-shell .desktop-only-toggle {
      display: none;
    }

    /* Topbar wraps on small screens; search drops to its own row */
    body.has-mobile-shell .center-topbar {
      flex-wrap: wrap;
      padding: 10px 14px 12px;
      gap: 10px;
    }
    body.has-mobile-shell .center-topbar h2 {
      font-size: 17px;
    }
    body.has-mobile-shell .center-topbar-left {
      min-width: 0;
    }
    body.has-mobile-shell .search-box {
      flex: 1 0 100%;
      width: auto;
      order: 10;
    }

    /* Tighter content padding */
    body.has-mobile-shell .center-scroll {
      padding: 12px;
    }

    /* Lock body scroll while an overlay is open */
    body.has-mobile-shell.scroll-locked {
      overflow: hidden;
    }

    /* ============================================================
       MOBILE BRAND BAR — visible only on mobile.
       Shows ProofOfThings logo + name + role badge as a horizontal
       band at the top of .center (above .center-topbar). On scroll
       JS adds .scrolled — shrinks the bar and applies a translucent
       blur backdrop, matching iOS-style condensed headers.
       ============================================================ */
    body.has-mobile-shell .mobile-brand-bar {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 12px 16px;
      background: var(--bone-2);
      border-bottom: 1px solid var(--line-2);
      color: var(--ink);
      flex-shrink: 0;
      z-index: 50;
      /* Smooth transitions for the scroll-shrink effect */
      transition: padding 0.18s ease, background 0.18s ease;
    }
    body.has-mobile-shell .mobile-brand-bar svg {
      transition: width 0.18s ease, height 0.18s ease;
      flex-shrink: 0;
    }
    body.has-mobile-shell .mobile-brand-name {
      font-family: var(--sans);
      font-weight: 600;
      font-size: 15px;
      letter-spacing: -0.02em;
      flex: 1;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      transition: font-size 0.18s ease;
    }
    body.has-mobile-shell .mobile-brand-bar .role-badge {
      /* Reset margin-left:auto from the sidebar context — here we want
         the badge sitting tight against the brand name, not pushed right. */
      margin: 0;
      flex-shrink: 0;
    }

    /* Scrolled state — applied by JS when .center-scroll has scrolled. */
    body.has-mobile-shell .mobile-brand-bar.scrolled {
      padding: 8px 16px;
      background: color-mix(in oklch, var(--bone-2) 80%, transparent);
      backdrop-filter: blur(12px) saturate(140%);
      -webkit-backdrop-filter: blur(12px) saturate(140%);
      border-bottom-color: color-mix(in oklch, var(--line-2) 60%, transparent);
    }
    body.has-mobile-shell .mobile-brand-bar.scrolled svg {
      width: 16px;
      height: 16px;
    }
    body.has-mobile-shell .mobile-brand-bar.scrolled .mobile-brand-name {
      font-size: 13px;
    }
  }

  /* ============= Tablet (900-1199px) — right sidebar collapses to rail =============
     The existing rule at the top of this stylesheet (~line 562) already handles
     the left-side icon-rail behavior for <=1200px. We add JS-driven default-collapse
     for the right side on first load (see admin-shell.js applyTabletDefaults).

     Below: column overrides so tablet width has a coherent layout regardless of
     whether the user has manually toggled state. */
  @media (max-width: 1199px) and (min-width: 900px) {
    .layout {
      grid-template-columns: 60px 1fr 320px;
    }
    .layout.right-collapsed {
      grid-template-columns: 60px 1fr 40px;
    }
    .layout.left-collapsed {
      grid-template-columns: 60px 1fr 320px;
    }
    .layout.left-collapsed.right-collapsed {
      grid-template-columns: 60px 1fr 40px;
    }
  }

  /* ============= Mobile list-view layout (<600px) =============
     The default 3-column grid for vendor/parent rows doesn't fit on phones.
     Stack vertically: name on row 1, secondary metadata on row 2,
     status/score align right.

     This applies to any page using the list-view template (.vendor-list,
     .vendor-card, .vendor-header, .product-row), regardless of the
     domain entity (vendors, clients, users, etc.). */
  @media (max-width: 599px) {
    body.has-mobile-shell .vendor-list-header {
      grid-template-columns: 1fr 32px;
      padding: 10px 12px;
      gap: 8px;
    }
    body.has-mobile-shell .vendor-list-header-cell:nth-child(2) {
      /* Secondary column header is implied by the stacked subrow below */
      display: none;
    }

    body.has-mobile-shell .vendor-header {
      grid-template-columns: 1fr auto;
      grid-template-rows: auto auto;
      padding: 12px 14px;
      gap: 2px 12px;
    }
    body.has-mobile-shell .vendor-header > .vendor-name {
      grid-column: 1;
      grid-row: 1;
    }
    body.has-mobile-shell .vendor-header > div:nth-child(2) {
      grid-column: 1;
      grid-row: 2;
      font-size: 11px;
    }
    body.has-mobile-shell .vendor-header > div:nth-child(3) {
      grid-column: 2;
      grid-row: 1 / span 2;
      align-self: center;
    }

    body.has-mobile-shell .product-row {
      grid-template-columns: 1fr auto;
      grid-template-rows: auto auto;
      padding: 10px 14px 10px 24px;
      gap: 2px 10px;
    }
    body.has-mobile-shell .product-row > .product-name {
      grid-column: 1;
      grid-row: 1;
    }
    body.has-mobile-shell .product-row > span:nth-child(2) {
      grid-column: 1;
      grid-row: 2;
      font-size: 11px;
      color: var(--ink-3);
    }
    body.has-mobile-shell .product-row > .product-status {
      grid-column: 2;
      grid-row: 1;
      justify-self: end;
    }
    body.has-mobile-shell .product-row > span:nth-child(4) {
      grid-column: 2;
      grid-row: 2;
      text-align: right;
      font-size: 11px;
      color: var(--ink-3);
    }
  }

  /* ============================================================
     RIGHT SIDEBAR COLLAPSED RAIL
     The right sidebar has two visual states controlled by a single
     class on the element: .collapsed.

     Default (no .collapsed class):
       - Header, content, and any footer render normally.
       - The collapsed rail is hidden.

     When .sidebar-right.collapsed is set:
       - Header and content are hidden.
       - The collapsed rail is shown — a thin column with an expand button.

     This class is toggled by:
       - User clicking the collapse/expand button on the sidebar.
       - JS auto-applying it at tablet widths (900–1199px) on first load
         and on resize, unless the user has explicitly overridden via click.
     ============================================================ */

  /* Default: rail hidden, regular content shown. */
  .sidebar-right-collapsed-rail {
    display: none;
  }

  /* Collapsed state: hide content, show rail. */
  .sidebar-right.collapsed > .sidebar-right-header,
  .sidebar-right.collapsed > .sidebar-right-content {
    display: none;
  }
  .sidebar-right.collapsed > .sidebar-right-collapsed-rail {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 14px 6px;
    flex: 1;
  }
  .sidebar-right.collapsed {
    overflow: hidden;
    padding: 0;
  }

  /* The expand button inside the rail — match the existing collapse-btn
     styling so toggling collapse/expand looks consistent. */
  .sidebar-right-collapsed-rail .collapse-btn {
    margin: 0;
  }

  /* ============================================================
     DETAIL PAGE COMPONENTS (cross-page, cross-role)
     Patterns used by detail pages (client detail, vendor detail,
     questionnaire detail, etc). Designed once, reused everywhere.
     ============================================================ */

  /* --- Editable form (page-level edit mode) ---
     Wrapper class .edit-form holds field definitions. Adding .editing
     swaps read-only field values for inputs and Edit-button for Save/Cancel.
     This is the canonical editable-record pattern — use it on any detail
     page where an admin can edit the record's metadata. */
  .edit-form .field-input,
  .edit-form .field-textarea,
  .edit-form .field-select { display: none; }
  .edit-form.editing .field-value { display: none; }
  .edit-form.editing .field-input,
  .edit-form.editing .field-textarea,
  .edit-form.editing .field-select { display: block; }

  .edit-form .edit-cancel,
  .edit-form .edit-save { display: none; }
  .edit-form.editing .edit-toggle { display: none; }
  .edit-form.editing .edit-cancel,
  .edit-form.editing .edit-save { display: inline-flex; }

  .edit-form-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
    padding: 18px;
  }
  .edit-form-grid .field.span-2 { grid-column: span 2; }
  .edit-form-grid .field.span-3 { grid-column: span 3; }

  .field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  .field-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-weight: 600;
  }
  .field-value {
    font-size: 13px;
    color: var(--ink);
    min-height: 32px;
    padding: 6px 0;
    line-height: 1.4;
    word-break: break-word;
  }
  .field-value.muted { color: var(--ink-4); font-style: italic; }
  .field-value.mono { font-family: var(--mono); font-size: 12px; }
  .field-input,
  .field-select {
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink);
    padding: 7px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--bone);
    width: 100%;
  }
  .field-input:focus,
  .field-select:focus {
    outline: none;
    border-color: var(--indigo);
    box-shadow: 0 0 0 3px var(--indigo-soft);
  }
  .field-textarea {
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink);
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--bone);
    width: 100%;
    min-height: 70px;
    resize: vertical;
  }

  /* --- Client summary bar (6-cell stats strip) ---
     Generic per-record stats display. Use for client detail, vendor detail, etc. */
  .client-summary {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 0;
    background: var(--bone-2);
    border: 1px solid var(--line);
    border-radius: 10px;
    margin-bottom: 18px;
    overflow: hidden;
  }
  .summary-item {
    padding: 14px 16px;
    border-right: 1px solid var(--line-2);
  }
  .summary-item:last-child { border-right: none; }
  .summary-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-weight: 600;
    margin-bottom: 6px;
  }
  .summary-value {
    font-size: 18px;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.015em;
  }
  .summary-unit {
    font-size: 12px;
    color: var(--ink-4);
    font-weight: 500;
    margin-left: 2px;
  }

  /* --- Advisory banner (generic — admin notice, warning, etc.) --- */
  .advisory-banner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    border: 1px solid color-mix(in oklch, var(--amber) 35%, transparent);
    background: var(--amber-soft);
    border-radius: 10px;
    margin-bottom: 18px;
    flex-wrap: wrap;
  }
  .advisory-banner.info {
    border-color: color-mix(in oklch, var(--indigo) 35%, transparent);
    background: var(--indigo-soft);
  }
  .advisory-icon {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: var(--amber-soft);
    display: flex;
    align-items: center;
    justify-content: center;
    color: color-mix(in oklch, var(--amber) 60%, var(--ink));
    flex-shrink: 0;
  }
  .advisory-banner.info .advisory-icon {
    background: var(--indigo-soft);
    color: var(--indigo);
  }
  .advisory-title {
    font-size: 13.5px;
    font-weight: 500;
    color: color-mix(in oklch, var(--amber) 80%, var(--ink));
  }
  .advisory-banner.info .advisory-title { color: var(--indigo); }
  .advisory-subtitle {
    font-size: 12px;
    color: color-mix(in oklch, var(--amber) 45%, var(--ink-3));
    margin-top: 2px;
  }
  .advisory-banner.info .advisory-subtitle { color: var(--ink-3); }

  /* --- Flash messages --- */
  .flash-msg {
    margin: 1rem; padding: 10px 14px; border-radius: 8px;
    font-size: 13px; line-height: 1.5;
    border: 1px solid transparent;
  }
  .flash-msg.success {
    background: var(--green-soft);
    color: color-mix(in oklch, var(--green) 80%, var(--ink));
    border-color: color-mix(in oklch, var(--green) 35%, transparent);
  }
  .flash-msg.error {
    background: var(--red-soft);
    color: color-mix(in oklch, var(--red) 80%, var(--ink));
    border-color: color-mix(in oklch, var(--red) 35%, transparent);
  }

  /* --- Detail section card --- */
  .detail-section {
    border: 1px solid var(--line);
    background: var(--bone-2);
    /* Paint background only inside the border. Default `border-box` lets
       background bleed under the 1px border, which on some renderers shows
       a faint sharp corner just past the rounded curve. */
    background-clip: padding-box;
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 18px;
  }
  .section-header {
    display: flex;
    align-items: center;
    padding: 14px 18px;
    border-bottom: 1px solid var(--line-2);
    gap: 14px;
  }
  .section-title {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.005em;
    margin: 0;
  }
  .section-subtitle {
    font-size: 11.5px;
    color: var(--ink-4);
    margin-top: 3px;
  }
  .section-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .section-link {
    margin-left: auto;
    font-size: 12px;
    color: var(--indigo);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-weight: 500;
  }
  .section-link:hover { color: color-mix(in oklch, var(--indigo) 80%, var(--ink)); }

  /* --- Two-column layout (used inside detail pages) ---
     margin-bottom matches .detail-section so vertical rhythm stays
     consistent whether sections are alone or paired in a two-col. */
  .two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
    margin-bottom: 18px;
  }
  .two-col .detail-section { margin-bottom: 0; }

  /* --- Table (lightweight, in-section table) ---
     NEVER use horizontal scrolling. Cells shrink with the container via
     min-width: 0 on grid items; long text truncates with ellipsis. At mobile
     widths, .table-row stacks vertically (see responsive overrides below). */
  .table {
    /* Column template — every header cell and every row
       inherits from this variable, so adding/removing a column is a
       one-line change on the parent element. Override per-table:
         <div class="table" style="--table-cols: 24px 1fr 70px 100px;">  */
    --table-cols: minmax(0, 1fr); display: flex; flex-direction: column; }
  .table-header,
  .table-row { /* width: container — no min-width forcing overflow */ }
  .table-header {
    display: grid;
    padding: 10px 18px;
    font-size: 10px;
    letter-spacing: 0.06em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-family: var(--mono);
    border-bottom: 1px solid var(--line-2);
    font-weight: 600;
  }
  .table-row {
    display: grid;
    padding: 12px 18px;
    align-items: center;
    gap: 10px;
    border-bottom: 1px solid var(--line-2);
    transition: background 0.12s;
    font-size: 13px;
  }
  .table-row.clickable { cursor: pointer; }
  .table-row.clickable:hover { background: var(--bone-3); }
  .table-row:last-child { border-bottom: none; }
  .table-row.compact { padding: 10px 18px; }
  /* Allow grid items to shrink below their content width — required so cells
     don't force the row wider than the container. Pair with text truncation
     on long-text cells (.app-name, .rec-name, etc). */
  .table-row > *,
  .table-header > * { min-width: 0; }

  /* Cell variants */
  .cell-app { display: flex; align-items: center; gap: 10px; min-width: 0; }
  .app-swatch {
    width: 24px; height: 24px; border-radius: 5px;
    opacity: 0.55; flex-shrink: 0;
  }
  .cell-app > div { min-width: 0; flex: 1; }
  .app-name {
    font-size: 13px; color: var(--ink); font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .app-meta {
    font-size: 10.5px; color: var(--ink-4); font-family: var(--mono);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .cell-mono { font-size: 12px; color: var(--ink-2); font-family: var(--mono); text-align: right; }
  .cell-ink3 { color: var(--ink-3); }
  .cell-amber { color: color-mix(in oklch, var(--amber) 60%, var(--ink)); }
  .cell-red { color: var(--red); }
  .cell-util { display: flex; align-items: center; gap: 6px; justify-content: flex-end; }
  .util-bar {
    width: 46px; height: 4px;
    background: var(--line-2);
    border-radius: 2px; overflow: hidden; flex-shrink: 0;
  }
  .util-fill { height: 100%; border-radius: 2px; }
  .util-green { background: var(--green); }
  .util-amber { background: var(--amber); }
  .util-red { background: var(--red); }
  .util-indigo { background: var(--indigo); }

  /* --- Badge (re-usable status pill, separate from .product-status) --- */
  .badge {
    display: inline-block;
    font-size: 10px;
    font-weight: 500;
    padding: 2px 8px;
    border-radius: 4px;
    letter-spacing: 0.02em;
  }
  .badge-green { background: var(--green-soft); color: var(--green); }
  .badge-red { background: var(--red-soft); color: var(--red); }
  .badge-amber { background: var(--amber-soft); color: color-mix(in oklch, var(--amber) 60%, var(--ink)); }
  .badge-indigo { background: var(--indigo-soft); color: var(--indigo); }
  .badge-neutral { background: var(--bone-3); color: var(--ink-3); }
  .chev { font-size: 16px; color: var(--ink-4); line-height: 1; }

  /* --- Recommendations / surveys / generic ranked list --- */
  .rec-list { display: flex; flex-direction: column; }
  .rec-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px;
    border-bottom: 1px solid var(--line-2);
    transition: background 0.12s;
  }
  .rec-row.clickable { cursor: pointer; }
  .rec-row.clickable:hover { background: var(--bone-3); }
  .rec-row:last-child { border-bottom: none; }
  .rec-rank {
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-4);
    width: 20px;
    text-align: center;
  }
  .rec-main { flex: 1; min-width: 0; }
  .rec-name {
    font-size: 13px; font-weight: 500; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .rec-meta {
    font-size: 11px; color: var(--ink-4); margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .rec-score { font-family: var(--mono); font-size: 13px; color: var(--ink); font-weight: 600; }
  .score-num { color: var(--indigo); }
  .score-max { color: var(--ink-4); font-weight: 400; font-size: 11px; }

  /* --- Activity log --- */
  .activity-list { display: flex; flex-direction: column; }
  .activity-item {
    display: grid;
    grid-template-columns: 28px 1fr auto;
    gap: 10px;
    padding: 12px 18px;
    border-bottom: 1px solid var(--line-2);
    align-items: flex-start;
  }
  .activity-item:last-child { border-bottom: none; }
  .activity-icon {
    width: 26px; height: 26px;
    border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .activity-indigo { background: var(--indigo-soft); color: var(--indigo); }
  .activity-amber { background: var(--amber-soft); color: color-mix(in oklch, var(--amber) 60%, var(--ink)); }
  .activity-green { background: var(--green-soft); color: var(--green); }
  .activity-neutral { background: var(--bone-3); color: var(--ink-3); }
  .activity-body {
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--ink-2);
  }
  .activity-actor { font-weight: 500; color: var(--ink); }

  /* --- Buttons --- */
  .btn {
    font-family: var(--sans);
    font-size: 12.5px;
    font-weight: 500;
    padding: 6px 12px;
    border-radius: 6px;
    cursor: pointer;
    border: 1px solid transparent;
    transition: all 0.12s;
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .btn-primary { background: var(--ink); color: var(--bone); }
  .btn-primary:hover { background: var(--ink-2); }
  .btn-ghost { background: transparent; color: var(--ink-2); border-color: var(--line); }
  .btn-ghost:hover { background: var(--bone-3); }
  .btn-danger { background: var(--red-soft); color: var(--red); border-color: color-mix(in oklch, var(--red) 30%, transparent); }
  .btn-danger:hover { background: color-mix(in oklch, var(--red) 12%, var(--red-soft)); }

  /* --- Toggle switch (for anonymization rows etc.) --- */
  .toggle {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 18px;
    flex-shrink: 0;
  }
  .toggle input {
    opacity: 0;
    width: 0;
    height: 0;
  }
  .toggle .slider {
    position: absolute;
    cursor: pointer;
    inset: 0;
    background: var(--line);
    border-radius: 999px;
    transition: 0.18s;
  }
  .toggle .slider::before {
    content: '';
    position: absolute;
    height: 14px;
    width: 14px;
    left: 2px;
    bottom: 2px;
    background: white;
    border-radius: 50%;
    transition: 0.18s;
    box-shadow: 0 1px 2px rgba(0,0,0,0.2);
  }
  .toggle input:checked + .slider { background: var(--indigo); }
  .toggle input:checked + .slider::before { transform: translateX(14px); }

  /* --- Detail-page responsive overrides --- */
  @media (max-width: 1100px) {
    .two-col { grid-template-columns: 1fr; }
    .client-summary { grid-template-columns: repeat(3, 1fr); }
    .summary-item:nth-child(3n) { border-right: none; }
    .summary-item:nth-child(-n+3) { border-bottom: 1px solid var(--line-2); }
    .edit-form-grid { grid-template-columns: repeat(2, 1fr); }
  }
  @media (max-width: 899px) {
    body.has-mobile-shell .client-summary { grid-template-columns: repeat(2, 1fr); }
    body.has-mobile-shell .summary-item { border-right: 1px solid var(--line-2) !important; border-bottom: 1px solid var(--line-2); }
    body.has-mobile-shell .summary-item:nth-child(2n) { border-right: none !important; }
    body.has-mobile-shell .summary-item:nth-last-child(-n+2) { border-bottom: none; }
    body.has-mobile-shell .edit-form-grid { grid-template-columns: 1fr; padding: 14px; }
    body.has-mobile-shell .advisory-banner { flex-direction: column; align-items: flex-start; }
    body.has-mobile-shell .section-header { padding: 12px 14px; }
    body.has-mobile-shell .detail-section { border-radius: 8px; }

    /* --- Tables on mobile: STACK rows vertically (NEVER scroll horizontally).
       The header is hidden; each cell becomes its own row inside the .table-row.
       The primary cell (.cell-app, vendor name) takes full width; secondary cells
       (badges, scores, toggles) wrap below in a tight row. */
    body.has-mobile-shell .table-header { display: none; }
    body.has-mobile-shell .table-row {
      display: flex !important;
      flex-wrap: wrap;
      align-items: center;
      gap: 8px 14px;
      padding: 14px 16px !important;
      grid-template-columns: none !important;
    }
    body.has-mobile-shell .table-row.compact {
      padding: 12px 14px !important;
    }
    body.has-mobile-shell .table-row > .cell-app {
      flex: 1 1 100%;
    }
    /* All secondary cells become inline auto-width pieces */
    body.has-mobile-shell .table-row > div:not(.cell-app) {
      flex: 0 0 auto;
      text-align: left !important;
    }
    /* Hide the trailing chevron on mobile — saves space, tap-target is the row */
    body.has-mobile-shell .table-row > div > .chev {
      display: none;
    }
  }

  /* ============================================================
     EDITABLE SUMMARY STRIP (top row of an .edit-form)
     Inputs styled to match .summary-value's big-bold display so
     the visual stays clean when toggling between view and edit.
     ============================================================ */
  .summary-input,
  .summary-select {
    display: none;
    font-family: var(--sans);
    font-size: 18px;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.015em;
    border: none;
    border-bottom: 1.5px solid transparent;
    background: transparent;
    padding: 0;
    margin: 0;
    width: 100%;
    outline: none;
    appearance: none;
    line-height: 1.3;
  }
  .summary-input:focus,
  .summary-select:focus {
    border-bottom-color: var(--indigo);
  }
  .summary-select {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M2 4l3 3 3-3' fill='none' stroke='%2399999c' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-position: right 0 center;
    background-repeat: no-repeat;
    background-size: 10px 10px;
    padding-right: 14px;
    cursor: pointer;
  }
  .edit-form.editing .summary-item.editable .summary-value { display: none; }
  .edit-form.editing .summary-item.editable .summary-input,
  .edit-form.editing .summary-item.editable .summary-select { display: block; }
  /* Read-only cells get muted in edit mode to make editable cells stand out */
  .edit-form.editing .summary-item:not(.editable) .summary-value { opacity: 0.55; }

  /* Nested .client-summary inside an .edit-form — strip its own border/radius
     so it sits flush against the section-header above. Use descendant
     combinator (not direct child) because new forms wrap the summary inside
     a .detail-section card. */
  .edit-form .client-summary {
    border: none;
    border-radius: 0;
    margin-bottom: 0;
  }

  /* ============================================================
     EXPAND LINK (text-link variant of "Show more details")
     Lives in the section-actions row alongside the icon buttons.
     Matches .section-link styling but with a rotating chevron.
     ============================================================ */
  .expand-link {
    cursor: pointer;
    margin-left: 0;  /* not auto — we share the actions row with icon buttons */
  }
  .expand-link svg {
    transition: transform 0.18s;
  }
  .expand-link.expanded svg {
    transform: rotate(180deg);
  }
  /* Hide the expand link in edit mode — panel is auto-open. */
  .edit-form.editing .expand-link { display: none; }

  /* ============================================================
     EXPANDED PANEL — wrapper around the per-section cards. Used to be
     an inner panel inside the main form card (with its own background
     + top border), now it's just a vertical-stack wrapper that lives
     OUTSIDE the main card. No background — each .form-section-card
     paints its own — and no border. Display rules (flex stack, gap)
     are set further down in the section-cards block.
     ============================================================ */
  .form-expanded[hidden] { display: none; }
  .edit-form.editing .form-expanded { display: flex; }

  /* ============================================================
     ICON BUTTONS in section-actions (Edit / Save / Cancel)
     Same display behaviour as the previous text buttons:
     Edit visible in view mode, Save+Cancel visible in edit mode.
     ============================================================ */
  .icon-btn { display: inline-flex; align-items: center; justify-content: center; }
  .edit-form .edit-cancel,
  .edit-form .edit-save { display: none; }
  .edit-form.editing .edit-toggle { display: none; }
  .edit-form.editing .edit-cancel,
  .edit-form.editing .edit-save { display: inline-flex; }
  /* Save icon gets a subtle indigo tint to read as "primary action" */
  .icon-btn.edit-save { color: var(--indigo); }
  .icon-btn.edit-save:hover { background: var(--indigo-soft); color: var(--indigo); }
  .icon-btn.edit-cancel:hover { background: var(--bone-3); color: var(--ink); }

  /* ============================================================
     FILTER POPOVER + ACTIVE-FILTER CHIPS (cross-page, cross-role)
     A generic, anchored popover that the page can attach to any
     "Filter" button. Markup contract:

       <div class="filter-popover-anchor">
         <button class="btn btn-ghost" data-popover="<id>" onclick="toggleFilterPopover(this)">
           Filter <span class="filter-count">0</span>
         </button>
         <div class="filter-popover" id="<id>" data-target="<rowSelector>" data-chips="<chipsId>">
           <div class="filter-popover-header">
             <span class="filter-popover-title">Filter</span>
             <button class="filter-popover-clear" onclick="clearFilters(this)">Clear</button>
           </div>
           <div class="filter-group">
             <div class="filter-group-label">Industry</div>
             <div class="filter-options">
               <label class="filter-option"><input type="checkbox" data-group="industry" data-label="Banking" value="banking" onchange="applyFilters(this)"><span>Banking</span></label>
               ...
             </div>
           </div>
         </div>
       </div>

     Chips container:  <div class="filter-chips" id="<chipsId>"></div>
     Each row to filter: <div ... data-industry="banking" data-anonymization="hidden-name">
     Multi-value: separate values with spaces, e.g. data-industry="banking treasury".
     ============================================================ */
  .filter-popover-anchor {
    position: relative;
    display: inline-flex;
  }
  .filter-popover {
    /* position: fixed (not absolute) so the popover escapes the parent
       .detail-section's overflow:hidden — popovers must float above all
       page content regardless of where the trigger lives in the DOM.
       JS sets the inline top/left/bottom when opening on desktop; on mobile,
       the @media rule below pins it to the bottom edge with !important. */
    position: fixed;
    min-width: 280px;
    max-width: 360px;
    /* If popover content is taller than the viewport, scroll inside the
       popover instead of overflowing off-screen. */
    max-height: calc(100vh - 20px);
    overflow-y: auto;
    background: var(--bone);
    border: 1px solid var(--line);
    border-radius: 10px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.12);
    padding: 14px 16px;
    z-index: 200;
    display: none;
  }
  .filter-popover.open { display: block; }

  /* --- Filter search input (a recognized filter type alongside checkboxes) --- */
  .filter-search { margin-bottom: 14px; }
  .filter-search input {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: 13px;
    font-family: var(--sans);
    background: var(--bone-2);
    color: var(--ink);
    box-sizing: border-box;
  }
  .filter-search input::placeholder { color: var(--ink-4); }
  .filter-search input:focus {
    outline: none;
    border-color: var(--indigo);
    box-shadow: 0 0 0 3px var(--indigo-soft);
    background: var(--bone);
  }

  .filter-popover-header {
    display: flex;
    align-items: center;
    margin-bottom: 12px;
    gap: 12px;
  }
  .filter-popover-title {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-3);
  }
  .filter-popover-clear {
    margin-left: auto;
    font-size: 11px;
    color: var(--indigo);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    font-family: var(--sans);
    font-weight: 500;
  }
  .filter-popover-clear:hover { text-decoration: underline; }

  .filter-group { margin-bottom: 14px; }
  .filter-group:last-child { margin-bottom: 0; }
  .filter-group-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-weight: 600;
    margin-bottom: 8px;
  }
  .filter-options {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .filter-option {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13px;
    color: var(--ink);
    cursor: pointer;
    padding: 4px 0;
  }
  .filter-option input { margin: 0; cursor: pointer; }

  /* Filter-count badge in the trigger button (hidden until JS sets a value) */
  .filter-count {
    display: none;
    background: var(--indigo);
    color: var(--bone);
    font-size: 10px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 999px;
    margin-left: 4px;
    line-height: 1.5;
  }
  .filter-count.active { display: inline-block; }

  /* --- Filter trigger (icon-only button on lists) ---
     Required on every list/table that supports filtering. Two icons sit inside;
     CSS swaps them based on .has-active (toggled by JS in applyFilters when any
     filter is active). The "active" icon is the same funnel filled in indigo,
     making it instantly clear that a filter is applied without needing text or
     a count badge (active filters are also shown as chips below the header). */
  .filter-trigger {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border-radius: 6px;
  }
  .filter-trigger .icon-active { display: none; }
  .filter-trigger.has-active .icon-empty { display: none; }
  .filter-trigger.has-active .icon-active { display: inline-block; }
  .filter-trigger.has-active {
    color: var(--indigo);
    background: var(--indigo-soft);
  }
  .filter-trigger.has-active:hover {
    background: color-mix(in oklch, var(--indigo-soft) 80%, var(--indigo) 15%);
    color: var(--indigo);
  }


  /* ============================================================
     ACTIVE FILTER CHIPS (sits between section-header and the list)
     Auto-hides when empty via .filter-chips:empty.
     ============================================================ */
  .filter-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    padding: 10px 18px;
    border-bottom: 1px solid var(--line-2);
    background: var(--bone);
  }
  .filter-chips:empty { display: none; }
  .filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11.5px;
    background: var(--indigo-soft);
    color: var(--indigo);
    padding: 3px 4px 3px 9px;
    border-radius: 4px;
    font-weight: 500;
  }
  .filter-chip-remove {
    background: none;
    border: none;
    cursor: pointer;
    color: inherit;
    font-size: 14px;
    padding: 0 5px;
    line-height: 1;
    border-radius: 3px;
    font-family: var(--sans);
  }
  .filter-chip-remove:hover {
    background: rgba(255, 255, 255, 0.6);
  }
  .filter-chip-clear-all {
    font-size: 11px;
    color: var(--ink-3);
    background: none;
    border: none;
    cursor: pointer;
    padding: 3px 6px;
    margin-left: auto;
    font-family: var(--sans);
  }
  .filter-chip-clear-all:hover { color: var(--ink); }

  /* ============================================================
     Mobile: filter popover becomes a bottom sheet
     ============================================================ */
  @media (max-width: 899px) {
    body.has-mobile-shell .filter-popover.open {
      /* Override any inline top/left/right that desktop JS may have set —
         mobile is always anchored to the bottom edge as a sheet. */
      position: fixed !important;
      inset: auto 0 0 0 !important;
      top: auto !important;
      left: 0 !important;
      right: 0 !important;
      bottom: 0 !important;
      width: 100% !important;
      max-width: 100% !important;
      min-width: 0 !important;
      border-radius: 14px 14px 0 0;
      padding: 18px 18px 24px;
      z-index: 220;
      box-shadow: 0 -4px 28px rgba(0, 0, 0, 0.18);
      border-bottom: none;
    }
    /* Larger tap targets on the bottom sheet */
    body.has-mobile-shell .filter-popover.open .filter-option {
      padding: 8px 0;
      font-size: 14px;
    }
    body.has-mobile-shell .filter-chips {
      padding: 10px 14px;
    }
  }


  /* ============================================================
     RIGHT-RAIL LIST PATTERN
     ============================================================
     Unified pattern for any list-like content in the right rail (Team
     members, recent activity, watchlists, related items, etc).

     Two right-rail-only behaviors that don't apply to main-content lists:
       1. Lists with > 4 items collapse everything past the first 4 into
          a hidden .rail-overflow region, exposed via an in-place expand
          toggle. The list never drills to a separate page.
       2. The filter icon and chip strip live in the same compact rail
          context. CSS overrides shrink the chip-strip padding for the
          narrower rail width.

     Markup contract:
       <section class="rail-section">
         <div class="rail-section-header">
           <span class="rail-section-label">Team</span>
           <div class="rail-section-actions">
             <button class="icon-btn filter-trigger" ...>...</button>
             <div class="filter-popover" id="teamFilter"
                  data-target="#teamList .rail-list-item"
                  data-chips="teamChips">...</div>
           </div>
         </div>
         <div class="filter-chips" id="teamChips"></div>
         <div class="rail-list" id="teamList">
           <div class="rail-list-item" data-role="owner" data-search="...">...</div>
           ... (first 4 items always visible)
           <div class="rail-list-item rail-overflow" data-role="..." data-search="...">...</div>
           ... (items 5+ hidden until expand or filter)
         </div>
         <button class="rail-expand-toggle"
                 data-list="teamList"
                 data-collapsed-label="View all 12 members"
                 data-expanded-label="Show less"
                 onclick="toggleRailListExpand(this)">View all 12 members</button>
       </section>
     ============================================================ */

  .rail-section {
    padding: 12px 14px;
    background: var(--bone);
    border: 1px solid var(--line);
    border-radius: 8px;
  }
  .rail-section + .rail-section { margin-top: 14px; }

  .rail-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
  }
  .rail-section-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-weight: 600;
    flex: 1;
    min-width: 0;
  }
  .rail-section-actions {
    display: flex;
    gap: 2px;
    align-items: center;
    flex-shrink: 0;
  }

  /* The actual list — column flex container of items. */
  .rail-list {
    display: flex;
    flex-direction: column;
  }
  .rail-list-item {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 6px 0;
    min-width: 0;
  }
  /* Items past the first 4 carry .rail-overflow and stay hidden by default. */
  .rail-list-item.rail-overflow { display: none; }
  /* Two ways an overflow item becomes visible:
       (a) user clicked the expand toggle → .rail-list.expanded
       (b) a filter is active → .rail-list.filtering (set by applyFiltersToRows)
     The "filtering" override exists so search/checkbox filters can match
     against overflow items even when the list is in its collapsed state. */
  .rail-list.expanded .rail-list-item.rail-overflow { display: flex; }
  .rail-list.filtering .rail-list-item.rail-overflow { display: flex; }

  .rail-avatar {
    width: 24px;
    height: 24px;
    border-radius: 999px;
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 600;
    flex: 0 0 auto;
  }
  .rail-list-item-text { flex: 1; min-width: 0; }
  .rail-list-item-name {
    font-size: 12px;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .rail-list-item-meta {
    font-size: 10.5px;
    color: var(--ink-4);
    font-family: var(--mono);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* In-place expand toggle. Replaces any "View all X →" link on rail-lists. */
  .rail-expand-toggle {
    font-size: 11px;
    color: var(--indigo);
    background: none;
    border: none;
    padding: 8px 0 0 0;
    margin: 0;
    cursor: pointer;
    font-family: var(--sans);
    font-weight: 500;
    text-align: left;
    display: inline-flex;
    align-items: center;
    gap: 4px;
  }
  .rail-expand-toggle:hover { text-decoration: underline; }

  /* Filter chips inside a rail section need slimmer padding and no border
     since the rail-section already provides its own visual boundary. */
  .rail-section .filter-chips {
    padding: 0 0 8px 0;
    background: transparent;
    border-bottom: none;
  }


  /* === Column-aligned table: header + rows share the same grid template ===
     Headers and rows use `var(--table-cols)`. The variable is set ONCE on the
     .table parent. Any inline grid-template-columns on individual rows is
     redundant and should be removed during refactor. */
  .table-header,
  .table-row {
    grid-template-columns: var(--table-cols);
  }

  /* Row progress bar — full-width visual under questionnaire rows. Sits
     inside the .table-row as a grid-column: 1 / -1 child so it sorts with
     its parent row when the user picks a sort order. */
  .row-progress {
    grid-column: 1 / -1;
    height: 4px;
    background: var(--bone-3);
    border-radius: 2px;
    margin-top: 8px;
    overflow: hidden;
  }
  .row-progress-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 0.2s;
  }
  .row-progress-fill.success { background: var(--green); }
  .row-progress-fill.indigo  { background: var(--indigo); }
  .row-progress-fill.warning { background: var(--amber); }
  .row-progress-fill.empty   { background: transparent; }

  /* Rank cell — small grey number for Top-matches-style ranked lists */
  .cell-rank {
    font-size: 11.5px;
    color: var(--ink-3);
    font-family: var(--mono);
    text-align: center;
  }

  /* Activity cell — avatar/dot + body text combined. Sits in a .table-row
     where the avatar is its own column (28px) and the body wraps freely. */
  .cell-activity-icon {
    width: 22px;
    height: 22px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }
  .cell-activity-body {
    font-size: 12.5px;
    color: var(--ink);
    line-height: 1.45;
  }
  .cell-activity-body .actor { font-weight: 500; }
  .cell-activity-body .meta  { color: var(--ink-3); }
  .cell-activity-time {
    font-size: 11px;
    color: var(--ink-4);
    font-family: var(--mono);
    text-align: right;
    white-space: nowrap;
  }

  /* === Sort trigger button (icon-only, mirrors .filter-trigger) ===
     Same styling pattern — outlined icon by default, filled when sort is
     applied (anything other than the default sort). Toggled via .has-active
     by applySort() in app-shell.js. */
  .sort-trigger {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border-radius: 6px;
  }
  .sort-trigger .icon-active { display: none; }
  .sort-trigger.has-active .icon-empty { display: none; }
  .sort-trigger.has-active .icon-active { display: inline-block; }
  .sort-trigger.has-active {
    color: var(--indigo);
    background: var(--indigo-soft);
  }
  .sort-trigger.has-active:hover {
    background: color-mix(in oklch, var(--indigo-soft) 80%, var(--indigo) 15%);
    color: var(--indigo);
  }

  /* --- Inline progress cell ---------------------------------------------
     Compact horizontal bar + percent label, sized to fit inside a single
     table cell (NOT a full-width row-progress). Used for columns like
     "Seats used" or "Coverage %" where each row shows its own value.

     Color modifiers — pick by VALUE THRESHOLD, never by row status:
       .cell-progress-fill.success  >=70%   (green)
       .cell-progress-fill.warning   40-69% (amber)
       .cell-progress-fill.danger   <40%    (red)
     The bar's color expresses how the value reads on its own. A row may
     have a separate status badge (keep/review/cut) that depends on multiple
     factors — never use the row's status to drive the bar color, since a
     row can be "review" overall while still having healthy utilization.
     ---------------------------------------------------------------------- */
  .cell-progress {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    width: 100%;
  }
  .cell-progress-bar {
    display: block;
    flex: 1;
    min-width: 0;
    height: 4px;
    background: var(--bone-3);
    border-radius: 2px;
    overflow: hidden;
  }
  .cell-progress-fill {
    display: block;
    height: 100%;
    border-radius: 2px;
  }
  .cell-progress-fill.success { background: var(--green); }
  .cell-progress-fill.warning { background: var(--amber); }
  .cell-progress-fill.danger  { background: var(--red); }
  .cell-progress-label {
    font-size: 12px;
    color: var(--ink);
    font-family: var(--mono);
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* === AI Results grid (3-column card grid for KPI/insight tiles) === */
  .ai-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
  }
  .ai-card {
    padding: 16px 18px;
    border-right: 1px solid var(--line-2);
    border-bottom: 1px solid var(--line-2);
    cursor: pointer;
    transition: background 0.12s;
  }
  .ai-card:hover { background: var(--bone-3); }
  .ai-card:nth-child(3n) { border-right: none; }
  .ai-card:nth-last-child(-n+3) { border-bottom: none; }
  .ai-card-label {
    font-size: 10px;
    letter-spacing: 0.06em;
    color: var(--ink-4);
    text-transform: uppercase;
    font-weight: 600;
    font-family: var(--mono);
  }
  .ai-card-value {
    font-size: 28px;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -0.02em;
    margin-top: 8px;
  }
  .ai-card-sub {
    font-size: 11.5px;
    color: var(--ink-3);
    margin-top: 4px;
    line-height: 1.45;
  }
  .ai-card-action {
    font-size: 11.5px;
    color: var(--indigo);
    margin-top: 10px;
    font-weight: 500;
  }
  /* Below 700px: stack to 2 columns to keep cards readable */
  @media (max-width: 700px) {
    .ai-grid { grid-template-columns: repeat(2, 1fr); }
    .ai-card:nth-child(3n) { border-right: 1px solid var(--line-2); }
    .ai-card:nth-child(2n) { border-right: none; }
    .ai-card:nth-last-child(-n+3) { border-bottom: 1px solid var(--line-2); }
    .ai-card:nth-last-child(-n+2) { border-bottom: none; }
  }

  /* === Live-indicator pill with pulsing dot (used in section-actions) === */
  .pill-indicator {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    color: var(--green);
    padding: 2px 8px;
    background: var(--green-soft);
    border-radius: 999px;
    font-weight: 500;
  }
  .pulse-dot {
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: var(--green);
    animation: pulse 1.8s ease-in-out infinite;
  }
  @keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
  }

  /* === Infographic variant: full-width edge-to-edge container ===
     Used for sections that contain SVG charts, narrative typography, and
     large display elements. Removes the inner padding of .detail-section
     so the infographic can manage its own layout. */
  .detail-section.infographic {
    padding: 0;
    overflow: hidden;
  }

  /* ============================================================
     AUTH SHELL — for logged-out pages (login, forgot-password,
     reset-password, accept-invite, magic-link-sent, logout)
     Two-column layout: left brand panel (bone-2) with serif tagline,
     right form panel (bone) with the form card.
     Collapses to single column (right only) under 768px.
     ============================================================ */
  body.auth-shell {
    margin: 0;
    background: var(--bone);
    min-height: 100vh;
    font-family: var(--sans);
  }

  /* Two-column container */
  .auth-container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-height: 100vh;
    gap: 0;
  }

  /* ----- LEFT PANEL ---------------------------------------------- */
  /* Brand panel: logo top, serif tagline middle, footer bottom.
     Keeps a consistent "you're entering ProofOfThings" feeling
     across all auth flows. The headline copy varies per page. */
  .auth-left {
    background: var(--bone-2);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 48px;
    color: var(--ink);
    border-right: 1px solid var(--line);
  }
  .auth-left-header {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .auth-logo-icon {
    /* Holds the ProofOfThings brand-mark SVG. SVG uses currentColor so we just
       set the color here. Transparent background — the bars themselves are the mark. */
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ink);
  }
  .auth-logo-text {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
  }
  .auth-left-content {
    flex: 1;
    display: flex;
    align-items: center;
    margin: 32px 0;
  }
  .auth-left-message {
    max-width: 360px;
  }
  .auth-left-message h1 {
    /* Serif headline, larger and tighter. Variable per page. */
    font-family: var(--serif);
    font-size: 42px;
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0 0 18px 0;
  }
  .auth-left-message p {
    font-size: 15.5px;
    line-height: 1.6;
    color: var(--ink-2);
    margin: 0;
  }
  .auth-left-footer {
    font-size: 12.5px;
    color: var(--ink-3);
    line-height: 1.5;
  }
  .auth-left-footer a {
    color: var(--indigo);
    text-decoration: none;
    font-weight: 500;
  }
  .auth-left-footer a:hover { text-decoration: underline; }

  /* ----- RIGHT PANEL --------------------------------------------- */
  /* Form panel. Card lives centered vertically; same width across all
     auth pages so visual rhythm doesn't shift between flows. */
  .auth-right {
    background: var(--bone);
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 48px;
  }
  .auth-form-wrapper {
    max-width: 380px;
    margin: 0 auto;
    width: 100%;
  }
  .auth-form-header {
    margin-bottom: 28px;
  }
  .auth-eyebrow {
    /* Optional small uppercase label above the title (e.g., "You've been invited") */
    font-family: var(--mono);
    font-size: 10px;
    color: var(--ink-4);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    margin-bottom: 12px;
  }
  .auth-form-header h2 {
    font-size: 28px;
    font-weight: 600;
    letter-spacing: -0.015em;
    margin: 0 0 8px 0;
    line-height: 1.2;
  }
  .auth-form-header p {
    font-size: 13.5px;
    color: var(--ink-3);
    margin: 0;
    line-height: 1.55;
  }
  .auth-form-header p strong { color: var(--ink); font-weight: 500; }

  /* Form fields */
  .auth-field {
    margin-bottom: 18px;
  }
  .auth-field-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
  }
  .auth-label {
    display: block;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    margin-bottom: 8px;
  }
  /* When label is in a flex row with a side-link, kill the bottom margin */
  .auth-field-row .auth-label { margin-bottom: 0; }
  .auth-field-link {
    font-size: 12.5px;
    color: var(--indigo);
    text-decoration: none;
    font-weight: 500;
  }
  .auth-field-link:hover { text-decoration: underline; }
  .auth-input {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--line);
    border-radius: 8px;
    font-family: var(--sans);
    font-size: 14px;
    background: var(--bone);
    color: var(--ink);
    transition: border-color 0.12s, box-shadow 0.12s;
    box-sizing: border-box;
  }
  .auth-input:focus {
    outline: none;
    border-color: var(--indigo);
    box-shadow: 0 0 0 3px var(--indigo-soft);
  }
  .auth-input::placeholder { color: var(--ink-4); }
  .auth-input.has-error {
    border-color: var(--red);
    background: var(--red-soft);
  }
  .auth-input.has-error:focus {
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--red) 18%, transparent);
  }
  .auth-help {
    font-size: 12px;
    color: var(--ink-3);
    margin-top: 6px;
    line-height: 1.45;
  }
  .auth-error {
    font-size: 12px;
    color: var(--red);
    margin-top: 6px;
    line-height: 1.45;
    display: none;
  }
  .auth-input.has-error + .auth-error,
  .auth-error.show {
    display: block;
  }

  /* Password input + reveal eye button */
  .auth-password-wrap { position: relative; }
  .auth-password-wrap .auth-input { padding-right: 42px; }
  .auth-password-toggle {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ink-4);
    padding: 4px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .auth-password-toggle:hover { color: var(--ink); }
  .auth-password-toggle:focus {
    outline: none;
    box-shadow: 0 0 0 2px var(--indigo-soft);
  }

  /* Remember me + Forgot password row (login only) */
  .auth-form-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 22px;
    font-size: 13px;
  }
  .auth-checkbox {
    display: flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
    color: var(--ink-2);
  }
  .auth-checkbox input[type="checkbox"] { cursor: pointer; }

  /* Primary submit (full-width indigo) */
  .auth-submit {
    width: 100%;
    padding: 12px 16px;
    background: var(--indigo);
    color: var(--bone);
    border: none;
    border-radius: 8px;
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    letter-spacing: -0.01em;
    transition: background 0.12s, box-shadow 0.12s, transform 0.04s;
  }
  .auth-submit:hover {
    background: color-mix(in oklch, var(--indigo) 80%, var(--ink));
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  }
  .auth-submit:active { transform: scale(0.99); }
  .auth-submit:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
  .auth-submit.loading {
    color: transparent;
    position: relative;
  }
  .auth-submit.loading::after {
    content: '';
    position: absolute;
    width: 16px; height: 16px;
    top: 50%; left: 50%;
    margin: -8px 0 0 -8px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: var(--bone);
    border-radius: 50%;
    animation: auth-spin 0.6s linear infinite;
  }
  @keyframes auth-spin { to { transform: rotate(360deg); } }

  /* Secondary button (outlined). Use as <a> for "Back to sign in" links. */
  .auth-secondary {
    display: block;
    width: 100%;
    padding: 11px 16px;
    background: var(--bone);
    color: var(--ink-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    box-sizing: border-box;
    margin-top: 10px;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
  }
  .auth-secondary:hover {
    background: var(--bone-3);
    border-color: var(--ink-4);
    color: var(--ink);
  }

  /* SSO row + divider (kept commented in markup until SSO decided) */
  .auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 26px 0;
    font-size: 12px;
    color: var(--ink-4);
  }
  .auth-divider::before,
  .auth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--line);
  }
  .auth-sso-row {
    display: flex;
    gap: 12px;
    margin-bottom: 26px;
  }
  .auth-sso-button {
    flex: 1;
    padding: 10px 12px;
    background: var(--bone-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-2);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: background 0.12s, border-color 0.12s;
  }
  .auth-sso-button:hover {
    background: var(--bone-3);
    border-color: var(--ink-4);
  }

  /* Card-bottom footer line (e.g., "Don't have an account? Contact admin") */
  .auth-card-footer {
    margin-top: 26px;
    text-align: center;
    font-size: 13px;
    color: var(--ink-3);
  }
  .auth-card-footer a {
    color: var(--indigo);
    text-decoration: none;
    font-weight: 500;
  }
  .auth-card-footer a:hover { text-decoration: underline; }

  /* Big confirmation icon (magic-link-sent, logout) */
  .auth-icon-tile {
    width: 56px;
    height: 56px;
    border-radius: 12px;
    background: var(--indigo-soft);
    color: var(--indigo);
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 22px;
  }
  .auth-icon-tile.green { background: var(--green-soft); color: var(--green); }
  .auth-icon-tile.amber { background: var(--amber-soft); color: color-mix(in oklch, var(--amber) 60%, var(--ink)); }

  /* Password strength meter (reset-password, accept-invite) */
  .auth-strength { margin-top: 10px; }
  .auth-strength-bar {
    height: 4px;
    background: var(--bone-3);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 6px;
  }
  .auth-strength-fill {
    display: block;
    height: 100%;
    width: 0;
    background: var(--ink-4);
    transition: width 0.18s ease, background 0.18s ease;
    border-radius: 2px;
  }
  .auth-strength-fill.weak    { width: 25%; background: var(--red); }
  .auth-strength-fill.fair    { width: 55%; background: var(--amber); }
  .auth-strength-fill.good    { width: 80%; background: var(--green); }
  .auth-strength-fill.strong  { width: 100%; background: var(--green); }
  .auth-strength-label {
    font-size: 11.5px;
    color: var(--ink-3);
    margin: 0;
  }

  /* Banner (for expired tokens or locked accounts) */
  .auth-banner {
    border-radius: 8px;
    padding: 11px 14px;
    margin-bottom: 22px;
    font-size: 12.5px;
    line-height: 1.5;
    display: flex;
    gap: 10px;
    align-items: flex-start;
  }
  .auth-banner.amber {
    background: var(--amber-soft);
    color: color-mix(in oklch, var(--amber) 80%, var(--ink));
    border: 1px solid color-mix(in oklch, var(--amber) 35%, transparent);
  }
  .auth-banner.red {
    background: var(--red-soft);
    color: var(--red);
    border: 1px solid color-mix(in oklch, var(--red) 35%, transparent);
  }
  .auth-banner svg { flex-shrink: 0; margin-top: 1px; }

  /* Mobile: collapse to right panel only.
     Below 768px the left brand panel is hidden so the form gets full width;
     this matches the source template's responsive behavior. */
  @media (max-width: 768px) {
    .auth-container { grid-template-columns: 1fr; }
    .auth-left { display: none; }
    .auth-right { padding: 32px 24px; }
    .auth-form-wrapper { max-width: 100%; }
    .auth-form-header h2 { font-size: 24px; }
  }

  /* ============================================================
     CUSTOMIZE NAV EDITOR (/admin/customize)
     Tree of sections + items with drag handles, inline edit fields,
     visibility toggles, and add/delete buttons. Built on top of the
     existing .detail-section + .icon-btn vocabulary.
     ============================================================ */

  .role-tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 24px;
    padding: 0 4px;
  }
  .role-tab {
    background: none;
    border: none;
    padding: 10px 14px;
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-3);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    text-transform: capitalize;
  }
  .role-tab:hover { color: var(--ink); }
  .role-tab.active {
    color: var(--ink);
    border-bottom-color: var(--indigo);
  }

  .editor-section {
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--bone);
    margin-bottom: 16px;
    overflow: hidden;
  }
  .editor-section.is-hidden { opacity: 0.55; }
  .editor-section.is-footer-pseudo { border-style: dashed; background: transparent; }

  .editor-section-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--line-2);
    background: var(--bone-2);
  }
  .editor-drag {
    color: var(--ink-4);
    cursor: grab;
    user-select: none;
    font-size: 14px;
    line-height: 1;
    padding: 0 2px;
  }
  .editor-drag:active { cursor: grabbing; }
  .editor-section-label {
    flex: 1;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-3);
  }
  .editor-section-label-input {
    flex: 1;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink);
    border: none;
    background: transparent;
    border-bottom: 1px solid var(--indigo);
    padding: 2px 0;
    outline: none;
    font-family: var(--sans);
  }
  .editor-section-actions { display: flex; gap: 4px; align-items: center; }

  .editor-items {
    list-style: none;
    margin: 0;
    padding: 6px 6px 8px;
    min-height: 36px;
  }
  .editor-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 6px;
    font-size: 13px;
  }
  .editor-item:hover { background: var(--bone-3); }
  .editor-item.is-hidden { opacity: 0.55; }
  .editor-item.is-system .editor-system-tag {
    font-size: 9px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-4);
    font-weight: 600;
    padding: 1px 5px;
    border: 1px solid var(--line);
    border-radius: 3px;
    background: var(--bone-2);
  }
  .editor-item-icon {
    display: inline-flex;
    width: 18px;
    height: 18px;
    align-items: center;
    justify-content: center;
    color: var(--ink-3);
    flex-shrink: 0;
  }
  .editor-item-label {
    flex: 1;
    color: var(--ink);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .editor-item-label-input {
    flex: 1;
    border: none;
    background: transparent;
    border-bottom: 1px solid var(--indigo);
    padding: 2px 0;
    outline: none;
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink);
    font-weight: 500;
  }
  .editor-item-meta {
    font-size: 11px;
    color: var(--ink-4);
    font-family: var(--mono);
    margin-right: 4px;
  }
  .editor-item-actions { display: flex; gap: 2px; align-items: center; }

  .editor-toggle {
    width: 30px;
    height: 16px;
    border-radius: 9999px;
    background: var(--line);
    position: relative;
    cursor: pointer;
    border: none;
    padding: 0;
    flex-shrink: 0;
    transition: background 0.15s;
  }
  .editor-toggle::after {
    content: '';
    position: absolute;
    width: 12px;
    height: 12px;
    background: white;
    border-radius: 9999px;
    top: 2px;
    left: 2px;
    transition: left 0.15s;
    box-shadow: 0 1px 2px rgba(0,0,0,0.15);
  }
  .editor-toggle.on { background: var(--green); }
  .editor-toggle.on::after { left: 16px; }

  .editor-add-row {
    display: flex;
    justify-content: flex-start;
    padding: 4px 12px 8px;
  }
  .editor-add-btn {
    background: none;
    border: 1px dashed var(--line);
    color: var(--ink-3);
    padding: 6px 12px;
    border-radius: 6px;
    font-family: var(--sans);
    font-size: 12px;
    cursor: pointer;
    transition: border-color 0.12s, color 0.12s;
  }
  .editor-add-btn:hover {
    border-color: var(--ink-3);
    color: var(--ink);
  }

  .editor-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
  }
  .editor-toolbar-actions { display: flex; gap: 8px; }
  .editor-btn {
    background: var(--ink);
    color: var(--bone);
    border: 1px solid var(--ink);
    border-radius: 6px;
    padding: 7px 14px;
    font-family: var(--sans);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
  }
  .editor-btn.ghost {
    background: transparent;
    color: var(--ink-2);
    border-color: var(--line);
  }
  .editor-btn.danger {
    background: transparent;
    color: var(--red);
    border-color: color-mix(in oklch, var(--red) 30%, transparent);
  }
  .editor-btn:hover { opacity: 0.9; }

  /* Sortable.js drop placeholder */
  .editor-ghost {
    opacity: 0.4;
    background: var(--indigo-soft);
  }
  .editor-chosen { cursor: grabbing; }

  /* ========================================================
     Form-friendly multi-select field (chip + flyout, real
     checkboxes — usable inside a <form>). Same UX as the
     filter-block partial but inputs have a name= so submission
     picks up selections. Used on /admin/surveys/new and the
     builder right rail.
     ======================================================== */
  .ms-field { display: flex; flex-direction: column; }
  /* Chip row sits below the trigger with reserved 1-row height so the
     field doesn't reflow when chips appear/disappear. Single line, no
     wrapping; we cap to 3 chips + a "+N more" pill in JS. */
  .ms-chips {
    display: flex; flex-wrap: nowrap; gap: 4px;
    margin-top: 6px;
    height: 22px;
    overflow: hidden;
  }
  .ms-chip {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 4px 3px 10px;
    background: var(--indigo-soft); color: var(--indigo);
    border-radius: 12px; font-size: 11.5px; font-weight: 500;
    white-space: nowrap; max-width: 220px;
  }
  .ms-chip-label { overflow: hidden; text-overflow: ellipsis; }
  .ms-chip-x {
    background: transparent; border: none; color: var(--indigo);
    font-size: 14px; line-height: 1; width: 18px; height: 18px;
    border-radius: 999px; cursor: pointer; padding: 0;
    display: flex; align-items: center; justify-content: center;
  }
  .ms-chip-x:hover { background: color-mix(in oklch, var(--indigo) 25%, transparent); color: var(--bone); }
  /* "+N more" pill styled lighter than a real chip so it reads as a count. */
  .ms-chip-more {
    background: var(--bone-3);
    color: var(--ink-3);
    padding: 3px 10px;
    cursor: default;
  }

  .ms-trigger-wrap { position: relative; }
  .ms-trigger {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 7px 10px;
    background: var(--bone); border: 1px solid var(--line); border-radius: 6px;
    font-family: var(--sans); font-size: 12.5px; color: var(--ink);
    cursor: pointer; text-align: left;
  }
  .ms-trigger:hover { border-color: var(--ink-3); }
  .ms-trigger-wrap.is-open .ms-trigger {
    border-color: var(--indigo);
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--indigo) 15%, transparent);
  }
  .ms-trigger-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ms-trigger-chev { color: var(--ink-4); font-size: 10px; transition: transform 0.12s; }
  .ms-trigger-wrap.is-open .ms-trigger-chev { transform: rotate(180deg); }

  .ms-flyout {
    position: absolute; top: calc(100% + 4px); left: 0; right: 0;
    z-index: 50;
    background: var(--bone); border: 1px solid var(--line);
    border-radius: 7px;
    padding: 6px;
    box-shadow: 0 6px 16px color-mix(in oklch, var(--ink) 12%, transparent);
    max-height: 280px; overflow: auto;
  }
  .ms-flyout[hidden] { display: none; }
  .ms-search {
    width: 100%; margin-bottom: 6px;
    padding: 6px 8px; border: 1px solid var(--line); border-radius: 5px;
    font-family: var(--sans); font-size: 12px;
  }
  .ms-search:focus { border-color: var(--indigo); outline: none; }
  /* Select all / Select none bulk-select bar — sits above the option
     list inside ms-flyout and filter-flyout. */
  .ms-bulk {
    display: flex; gap: 6px;
    margin: 0 0 6px;
    padding: 0 2px;
  }
  .ms-bulk-btn {
    flex: 1;
    padding: 4px 8px;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 5px;
    font-family: var(--sans);
    font-size: 11px;
    color: var(--ink-3);
    cursor: pointer;
  }
  .ms-bulk-btn:hover { color: var(--indigo); border-color: var(--indigo); background: var(--bone-2); }

  .ms-options-list { display: flex; flex-direction: column; gap: 1px; }
  .ms-option {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px; border-radius: 5px; cursor: pointer;
    font-size: 12.5px; color: var(--ink);
  }
  .ms-option:hover { background: var(--bone-3); }
  .ms-option.is-hidden { display: none; }
  .ms-option input[type="checkbox"] { accent-color: var(--indigo); cursor: pointer; }
  .ms-option-sub { color: var(--ink-4); font-size: 11px; margin-left: 4px; }
  .ms-option-empty {
    padding: 8px 10px; font-size: 11.5px; color: var(--ink-4); font-style: italic;
  }

  /* ========================================================
     Read-only survey view (partials/survey-view.ejs). Used to
     expand attached surveys inline on the product detail page.
     ======================================================== */
  .sv-body { padding: 4px 0 8px; }
  .sv-section { padding: 16px 18px; border: 1px solid var(--line); border-radius: 8px; background: var(--bone); margin-top: 12px; }
  .sv-section:first-child { margin-top: 4px; }
  .sv-section-num { font-family: var(--mono); font-size: 10px; color: var(--ink-4); letter-spacing: 0.1em; text-transform: uppercase; }
  .sv-section-title { font-size: 16px; font-weight: 600; color: var(--ink); margin-top: 4px; }
  .sv-section-intro { font-size: 12.5px; color: var(--ink-3); margin-top: 4px; line-height: 1.5; }
  .sv-q { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line-2); }
  .sv-q:first-of-type { margin-top: 12px; padding-top: 0; border-top: 0; }
  .sv-q-meta { display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--ink-4); }
  .sv-q-code { font-family: var(--mono); }
  .sv-q-kind { font-family: var(--mono); padding: 1px 6px; border: 1px solid var(--line); border-radius: 3px; background: var(--bone-2); color: var(--ink-3); }
  .sv-q-weight { margin-left: auto; font-family: var(--mono); }
  .sv-q-prompt { font-size: 14px; color: var(--ink); margin-top: 4px; line-height: 1.4; font-weight: 500; }
  .sv-q-help { font-size: 12px; color: var(--ink-3); margin-top: 3px; line-height: 1.5; }
  .sv-q-placeholder { margin-top: 6px; padding: 8px 12px; background: var(--bone-2); border: 1px solid var(--line-2); border-radius: 5px; font-size: 12px; color: var(--ink-4); font-style: italic; }
  .sv-choices { list-style: none; padding: 0; margin: 6px 0 0; display: flex; flex-direction: column; gap: 4px; }
  .sv-choices li { padding: 5px 10px 5px 28px; border: 1px solid var(--line-2); border-radius: 5px; background: var(--bone-2); font-size: 12.5px; color: var(--ink-2); position: relative; }
  .sv-choices li::before { content: ''; position: absolute; left: 9px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; border: 1.5px solid var(--ink-4); }
  .sv-choices.is-radio li::before { border-radius: 999px; }
  .sv-choices.is-check li::before { border-radius: 3px; }
  .sv-matrix { width: 100%; border: 1px solid var(--line); border-radius: 6px; background: var(--bone-2); border-collapse: collapse; margin-top: 6px; overflow: hidden; }
  .sv-matrix th, .sv-matrix td { padding: 6px 10px; border: 1px solid var(--line-2); font-size: 11.5px; }
  .sv-matrix th { background: var(--bone); color: var(--ink-4); font-family: var(--mono); font-weight: 500; text-align: center; font-size: 10.5px; letter-spacing: 0.06em; }
  .sv-matrix td { text-align: center; color: var(--ink-3); }
  .sv-matrix td:first-child { text-align: left; color: var(--ink); font-weight: 500; }

  /* Expandable attached-survey row on the product detail page. */
  .product-survey-row { border: 1px solid var(--line); border-radius: 8px; margin-top: 10px; overflow: hidden; background: var(--bone-2); }
  .product-survey-head { display: grid; grid-template-columns: 26px minmax(0, 2.4fr) 70px 100px 70px 70px 90px; gap: 12px; align-items: center; padding: 10px 14px; background: var(--bone); border-bottom: 1px solid transparent; cursor: pointer; user-select: none; }
  .product-survey-row.is-open .product-survey-head { border-bottom-color: var(--line-2); }
  .product-survey-row .ps-chev { color: var(--ink-4); font-size: 11px; transition: transform 0.12s; }
  .product-survey-row.is-open .ps-chev { transform: rotate(90deg); color: var(--ink-2); }
  .product-survey-body { display: none; padding: 12px 16px 16px; }
  .product-survey-row.is-open .product-survey-body { display: block; }

  /* ========================================================
     Form section cards — visible container per section in the
     expanded form (Show more details). Each catalog section
     (Identity / Company / Headquarters / etc.) sits in its own
     bordered card with a header label so the form reads as a
     stack of grouped sections rather than one continuous grid.
     ======================================================== */
  /* Section cards live OUTSIDE the main form container (rendered as
     siblings of the .detail-section "Create X" card). Generous gap
     between cards for clear visual separation, with margin-top to
     space them away from the main card. */
  .form-expanded { display: flex; flex-direction: column; gap: 24px; margin-top: 24px; padding: 0; }
  .form-section-card {
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--bone-2);
    /* Same fix as .detail-section — keep background inside the border so
       a sharp corner doesn't poke through the rounded clip. */
    background-clip: padding-box;
    overflow: hidden;
  }
  .form-section-card-header {
    padding: 10px 16px;
    background: var(--bone);
    border-bottom: 1px solid var(--line-2);
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--ink-3);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
  }
  .form-section-card .edit-form-grid {
    padding: 14px 16px;
  }

  /* ========================================================
     Row-action icons — small buttons in the rightmost column of
     a top-level list row (vendors, clients, products, users).
     Replace the previous "View details →" sub-row link with
     direct-navigation icons on the row itself.
     ======================================================== */
  .row-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 4px;
  }
  .row-action-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    color: var(--ink-3);
    border: 1px solid transparent;
    background: transparent;
    text-decoration: none;
    transition: all 0.1s;
  }
  .row-action-btn:hover {
    color: var(--ink);
    background: var(--bone-3);
    border-color: var(--line);
  }
  .row-action-btn:active { transform: translateY(1px); }

  /* Drag handle for reorderable table rows (reference-data lists). */
  .reorder-handle {
    cursor: grab;
    color: var(--ink-4);
    font-size: 14px;
    line-height: 1;
    letter-spacing: -2px;
    user-select: none;
    text-align: center;
    padding-top: 2px;
  }
  .reorder-handle:hover { color: var(--ink-2); }
  .reorder-handle:active { cursor: grabbing; }

  /* Inline edit row — used for both creating new items and editing
     existing ones. Replaces a display row temporarily. Cancel removes
     it (or restores the display row); Save POSTs / PATCHes. */
  .editor-item-edit {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px;
    background: var(--bone-2);
    border: 1px solid color-mix(in oklch, var(--indigo) 35%, var(--line));
    border-radius: 6px;
    margin: 6px 4px;
  }
  .editor-edit-fields {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
  }
  .editor-edit-field { flex: 1; min-width: 140px; }
  .editor-edit-field.wide { flex: 2; min-width: 200px; }
  .editor-edit-field.is-hidden { display: none; }
  .editor-edit-field-label {
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-4);
    font-weight: 600;
    margin-bottom: 4px;
  }
  .editor-edit-input,
  .editor-edit-select {
    width: 100%;
    box-sizing: border-box;
    font-family: var(--sans);
    font-size: 13px;
    padding: 6px 8px;
    border: 1px solid var(--line);
    border-radius: 4px;
    background: var(--bone);
    color: var(--ink);
    outline: none;
  }
  .editor-edit-input:focus,
  .editor-edit-select:focus {
    border-color: var(--indigo);
  }
  .editor-edit-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
  }
  .editor-edit-actions .visible-toggle-wrap {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-right: auto;
    font-size: 11px;
    color: var(--ink-3);
  }

  /* ============================================================
     FIELD SUBHEADER — groups fields inside an .edit-form-grid into
     labelled sections. Each subheader spans the full grid width
     and visually separates the previous group from the next.
     Non-interactive: just a label.
     ============================================================ */
  .field-subheader {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 18px;
    margin-top: 6px;
    border-top: 1px solid var(--line);
  }
  .field-subheader:first-child {
    padding-top: 0;
    margin-top: 0;
    border-top: none;
  }
  .field-subheader-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 600;
    flex: 0 0 auto;
  }

  /* ============================================================
     FLYOUT FILTER — reusable filter block for any list page.
     Each block: label + per-block 'Clear' link + chips of selected
     values + a trigger button that opens a flyout with an in-flyout
     search + scrollable checkbox list.
     ============================================================ */
  .filter-block {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .filter-block-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
  }
  .filter-clear-link {
    background: none;
    border: none;
    cursor: pointer;
    font-family: var(--sans);
    font-size: 11px;
    color: var(--ink-4);
    padding: 0;
    text-decoration: underline;
    text-underline-offset: 2px;
  }
  .filter-clear-link:hover:not(:disabled) { color: var(--indigo); }
  .filter-clear-link:disabled {
    color: var(--line);
    cursor: default;
    text-decoration: none;
  }

  /* Selected chips, shown below the trigger. Reserved fixed 1-row
     height so the field doesn't reflow when chips appear/disappear.
     Capped to 3 chips + "+N more" pill in the JS that builds them. */
  .filter-chips {
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    margin-top: 6px;
    height: 22px;
    overflow: hidden;
  }
  .filter-chips:empty { height: 0; margin-top: 0; }
  /* "+N more" pill — distinct from a real chip so it reads as a count. */
  .filter-chip-more {
    background: var(--bone-3) !important;
    color: var(--ink-3) !important;
    cursor: default;
  }
  .filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px 4px 2px 8px;
    font-size: 11px;
    font-weight: 500;
    background: var(--indigo-soft);
    color: var(--indigo);
    border-radius: 12px;
    line-height: 1.4;
    max-width: 100%;
  }
  .filter-chip-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .filter-chip-x {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    color: var(--indigo);
    padding: 0 4px;
    flex-shrink: 0;
  }
  .filter-chip-x:hover { color: var(--ink); }

  /* Trigger: looks like a select. Click to open the flyout. Label
     reads "All vendors" when empty, "N selected" when filtered. */
  .filter-trigger-wrap { position: relative; }
  .filter-trigger {
    width: 100%;
    box-sizing: border-box;
    padding: 6px 10px;
    border: 1px solid var(--line);
    border-radius: 4px;
    background: var(--bone);
    font-family: var(--sans);
    font-size: 12px;
    color: var(--ink-2);
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    text-align: left;
  }
  .filter-trigger:hover { border-color: var(--ink-3); }
  .filter-trigger-wrap.is-open .filter-trigger {
    border-color: var(--indigo);
    box-shadow: 0 0 0 2px color-mix(in oklch, var(--indigo) 20%, transparent);
  }
  .filter-trigger-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .filter-trigger-chev {
    font-size: 9px;
    color: var(--ink-3);
    flex-shrink: 0;
    transition: transform 0.15s;
  }
  .filter-trigger-wrap.is-open .filter-trigger-chev {
    transform: rotate(180deg);
  }

  /* Flyout: anchored below the trigger. Hidden by default; toggled
     by toggleFilterFlyout() in app-shell.js. Min-width keeps long
     option labels (e.g. "Comcast Business") on one line even when
     the trigger lives in a narrow grid column (compare picker
     modal). max-width caps it so very long labels still wrap. */
  .filter-flyout {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: auto;
    min-width: 220px;
    max-width: 320px;
    z-index: 100;
    background: var(--bone);
    border: 1px solid var(--line);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .filter-flyout[hidden] { display: none; }
  .filter-flyout .filter-search {
    padding: 5px 8px;
    border: 1px solid var(--line);
    border-radius: 4px;
    font-family: var(--sans);
    font-size: 12px;
    color: var(--ink);
    outline: none;
    background: var(--bone);
    width: 100%;
    box-sizing: border-box;
  }
  .filter-flyout .filter-search:focus { border-color: var(--indigo); }
  .filter-options-list {
    max-height: 220px;
    overflow-y: auto;
    padding: 2px;
  }
  .filter-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 6px;
    font-size: 12px;
    cursor: pointer;
    border-radius: 3px;
    color: var(--ink-2);
    line-height: 1.3;
  }
  .filter-option:hover { background: var(--bone-3); }
  .filter-option.is-hidden { display: none; }
  .filter-option input[type="checkbox"] {
    cursor: pointer;
    flex-shrink: 0;
    margin: 0;
  }
  .filter-option-empty {
    padding: 6px 8px;
    font-size: 11px;
    color: var(--ink-4);
    font-style: italic;
  }

  /* ============================================================
     COMPARE PAGE
     Side-by-side product comparison grid. Sticky feature column
     on the left, N product columns on the right. Density modes
     (compact/regular/roomy), winner highlighting per numeric row,
     row-different markers, mobile pager (≤720px).
     ============================================================ */

  /* Topbar Export PDF / Request demos buttons (already styled by .btn) */
  .btn[disabled] { opacity: 0.45; cursor: not-allowed; }

  /* Summary strip above the grid */
  .summary {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    background: var(--bone-2);
    border: 1px solid var(--line);
    background-clip: padding-box;
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 18px;
  }
  .summary > div { padding: 12px 16px; border-right: 1px solid var(--line-2); }
  .summary > div:last-child { border-right: none; }
  .summary .lbl { font-size: 10px; letter-spacing: .08em; color: var(--ink-4); text-transform: uppercase; font-weight: 600; margin-bottom: 4px; }
  .summary .val { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }

  /* Toolbar above grid — closed container with its own bottom edge,
     separated from the grid below by 14px of page-bone background. */
  .grid-toolbar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 10px 14px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--bone-3);
    margin-bottom: 14px;
  }
  .grid-toolbar .toolbar-grp { display: flex; align-items: center; gap: 6px; }
  .grid-toolbar .lbl { font-size: 10px; color: var(--ink-4); text-transform: uppercase; letter-spacing: .08em; font-weight: 600; }
  /* Compare-page pill toggle. Distinct from the slider .toggle class
     defined earlier in this file — that one is `display: inline-block;
     width: 32px; height: 18px;` and would squeeze this pill into a tiny
     box if we shared the name. */
  .cmp-toggle {
    display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    padding: 4px 9px; border: 1px solid var(--line); border-radius: 999px;
    font-size: 11.5px; color: var(--ink-2); background: var(--bone-2);
    font-family: var(--sans);
    white-space: nowrap;
    flex-shrink: 0;
    line-height: 1;
  }
  .cmp-toggle.on { background: var(--indigo); color: white; border-color: var(--indigo); }
  .cmp-toggle .dot { width: 6px; height: 6px; border-radius: 999px; background: var(--ink-4); flex-shrink: 0; }
  .cmp-toggle.on .dot { background: white; }
  .seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: var(--bone-2); }
  .seg button {
    appearance: none; border: 0; background: transparent;
    font: 500 11.5px/1 var(--sans); color: var(--ink-2);
    padding: 6px 10px; cursor: pointer; border-right: 1px solid var(--line-2);
  }
  .seg button:last-child { border-right: none; }
  .seg button.on { background: var(--ink); color: var(--bone); }

  /* Compare grid wrapper. The wrapper paints in the page-light bone
     so the margin-top gaps between groups visually separate one
     "table" from the next. Each section's cells supply their own
     bone-2 background. No wrapper border — we don't want vertical
     side-lines running through the inter-section gaps; section
     boundaries are drawn per-section via group-cell's border-top. */
  .compare-wrap {
    background: var(--bone);
    background-clip: padding-box;
  }
  /* No horizontal scroll — columns shrink to fit the available
     center width. Cells use min-width: 0 (set elsewhere) so their
     content can truncate or wrap rather than expand the grid. */
  .compare-scroll { overflow-x: hidden; }
  .compare {
    display: grid;
    width: 100%;
    min-width: 0;
    /* Cols set inline by JS; default to feature col + 4 product cols */
    grid-template-columns: minmax(0, 260px) repeat(4, minmax(0, 1fr));
  }
  .compare-wrap[data-cols="2"] .compare { grid-template-columns: minmax(0, 260px) repeat(2, minmax(0, 1fr)); }
  .compare-wrap[data-cols="3"] .compare { grid-template-columns: minmax(0, 260px) repeat(3, minmax(0, 1fr)); }
  /* Hide slots beyond the visible count. !important is required so
     these rules also win against the .show-mismatched reveal rule
     below — otherwise clicking "Show anyway" un-hides slot-3 in
     a 3-col view, throwing off row alignment. */
  .compare-wrap[data-cols="2"] .slot-cell[data-slot="2"],
  .compare-wrap[data-cols="2"] .slot-cell[data-slot="3"],
  .compare-wrap[data-cols="3"] .slot-cell[data-slot="3"] { display: none !important; }

  /* sticky feature column */
  .compare .feat,
  .compare .group-cell.feat,
  .compare .head-cell.feat {
    position: sticky; left: 0; z-index: 5;
    background: var(--bone-2);
  }
  .compare .head-cell.feat { z-index: 8; }

  /* Header row (product cards) — boxed with top, left, right borders
     so it reads as its own table just like the data sections below. */
  .head-cell {
    padding: 18px 18px 16px;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    background: var(--bone-2);
    position: sticky; top: 0; z-index: 6;
    border-right: 1px solid var(--line);
  }
  .head-cell.feat { border-left: 1px solid var(--line); }
  /* Right edge of the top row depends on the View segmented control —
     same pattern as the section side-borders below. */
  .head-cell:last-child { border-right: none; }
  .compare-wrap[data-cols="4"] .head-cell.slot-cell[data-slot="3"],
  .compare-wrap[data-cols="3"] .head-cell.slot-cell[data-slot="2"],
  .compare-wrap[data-cols="2"] .head-cell.slot-cell[data-slot="1"] {
    border-right: 1px solid var(--line);
  }

  .product-card { display: flex; flex-direction: column; gap: 10px; height: 100%; }
  .product-card-top { display: flex; align-items: flex-start; gap: 10px; }
  .product-swatch {
    width: 36px; height: 36px; border-radius: 8px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    color: white; font-family: var(--serif); font-size: 18px;
  }
  .product-name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.2; }
  .product-vendor { font-size: 11px; color: var(--ink-4); font-family: var(--mono); }
  .remove-x {
    margin-left: auto; background: none; border: 0; color: var(--ink-4);
    cursor: pointer; padding: 2px 4px; font-size: 14px; line-height: 1; border-radius: 4px;
  }
  .remove-x:hover { background: var(--bone-3); color: var(--ink); }
  .product-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 11px; }
  .product-meta .m-lbl { color: var(--ink-4); text-transform: uppercase; letter-spacing: .06em; font-size: 9.5px; font-weight: 600; }
  .product-meta .m-val { font-weight: 500; color: var(--ink); font-family: var(--mono); }

  /* margin-top: auto pushes the fit-bar (and the .product-actions
     below it) to the bottom of the card, so all sibling cards in
     the grid row align their fit-bar baselines regardless of how
     tall the name/vendor block above happens to be. */
  .fit-bar { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 6px; background: var(--bone); margin-top: auto; }
  .fit-num { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--indigo); }
  .fit-track { flex: 1; height: 4px; background: var(--line-2); border-radius: 2px; overflow: hidden; }
  .fit-fill { display: block; height: 100%; background: var(--indigo); border-radius: 2px; }
  .fit-label { font-size: 10px; color: var(--ink-4); font-family: var(--mono); letter-spacing: .04em; }

  /* Auto-margin lives on .fit-bar above; keeping one here too would
     split the available space between them and break vertical
     alignment of fit-bars across sibling cards. */
  .product-actions { display: flex; gap: 6px; }
  .product-actions .btn { flex: 1; justify-content: center; font-size: 11.5px; padding: 6px 8px; text-decoration: none; }

  /* group header rows */
  .group-cell {
    padding: 14px 18px 8px;
    background: var(--bone-3);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line-2);
    font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
    color: var(--ink-3); font-weight: 600;
    /* Margin shows the wrapper's lighter --bone background through,
       creating an inter-section gap that reads as separate tables. */
    margin-top: 14px;
  }
  .group-toggle {
    appearance: none; background: none; border: 0; color: var(--ink-3);
    cursor: pointer; font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
    font-weight: 600; display: flex; align-items: center; gap: 6px; padding: 0;
    font-family: var(--sans);
  }
  .group-toggle .chev { display: inline-block; transition: transform .15s; font-size: 9px; }
  .group-toggle.collapsed .chev { transform: rotate(-90deg); }
  /* When a group is collapsed, hide all of its data rows */
  .compare [data-row-group].is-collapsed { display: none; }

  /* feature data rows */
  .compare .cell {
    padding: 11px 18px;
    border-bottom: 1px solid var(--line-2);
    font-size: 13px;
    color: var(--ink-2);
    line-height: 1.4;
    display: flex; align-items: center;
    min-width: 0;
  }
  .compare-wrap[data-density="compact"] .cell { padding: 7px 18px; font-size: 12.5px; }
  .compare-wrap[data-density="roomy"]   .cell { padding: 15px 18px; font-size: 13.5px; }
  .compare .cell.feat {
    color: var(--ink); font-weight: 500; font-size: 13px;
    background: var(--bone-2); border-right: 1px solid var(--line);
  }
  .cell.value-cell { position: relative; background: var(--bone-2); }
  /* Per-section side borders. Each section's table has a vertical
     line on the left edge of the leftmost cell and on the right
     edge of the rightmost visible cell, running from the top of
     the section header down through every data row. The gap
     between sections has no cells, so the lines stop and resume
     at the next section — exactly what we want. */
  .compare .group-cell.feat,
  .compare .cell.feat {
    border-left: 1px solid var(--line);
  }
  /* Right edge — the rightmost visible product column. The data-cols
     attr on .compare-wrap is set by the View segmented control. */
  .compare-wrap[data-cols="4"] .group-cell.slot-cell[data-slot="3"],
  .compare-wrap[data-cols="4"] .cell.slot-cell[data-slot="3"],
  .compare-wrap[data-cols="3"] .group-cell.slot-cell[data-slot="2"],
  .compare-wrap[data-cols="3"] .cell.slot-cell[data-slot="2"],
  .compare-wrap[data-cols="2"] .group-cell.slot-cell[data-slot="1"],
  .compare-wrap[data-cols="2"] .cell.slot-cell[data-slot="1"] {
    border-right: 1px solid var(--line);
  }
  /* Close each section at the bottom: the last data row (the cell
     immediately followed by a group-cell, OR the very last cell in
     the grid) gets a darker border-bottom matching the section's
     other edges, so the table reads as fully boxed. */
  .compare .cell:has(+ .group-cell) {
    border-bottom: 1px solid var(--line);
  }
  .compare > .cell:last-child,
  .compare > .cell.feat:nth-last-child(2) ~ .cell {
    border-bottom: 1px solid var(--line);
  }
  .cell.row-different::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
    background: var(--amber); opacity: .6;
  }
  .cell.winner {
    background: color-mix(in oklch, var(--green) 11%, var(--bone-2));
    box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--green) 22%, transparent);
  }
  .cell.winner .winner-mark {
    margin-left: auto; display: inline-flex; align-items: center; gap: 4px; font-size: 9.5px;
    color: color-mix(in oklch, var(--green) 70%, var(--ink)); font-family: var(--mono); letter-spacing: .06em; text-transform: uppercase;
    padding: 3px 7px; border: 1px solid color-mix(in oklch, var(--green) 40%, transparent); border-radius: 999px;
    background: color-mix(in oklch, var(--green) 18%, var(--bone)); font-weight: 600; flex-shrink: 0;
  }
  .compare-wrap.no-winners .cell.winner { background: var(--bone-2); box-shadow: none; }
  .compare-wrap.no-winners .winner-mark { display: none; }
  /* Differences-only mode: hide rows where every filled value matches */
  .compare-wrap.diff-only [data-row-equal="true"] { display: none; }
  /* Tiered groups (category- or industry-scoped) whose scope doesn't
     intersect every selected product are hidden by default; the
     banner's "Show anyway" toggle removes this class on the wrapper.
     `!important` because group-cell.feat has its own display:flex
     rule (specificity 0,2,1) that would otherwise win. */
  .compare-wrap [data-scope-mismatch="true"] { display: none !important; }
  .compare-wrap.show-mismatched [data-scope-mismatch="true"] { display: flex !important; }
  /* Per-session × hide on group headers (and the cells under the
     hidden group). Driven by a sessionStorage list applied as a
     data-session-hidden attr on each affected element. */
  .compare-wrap [data-session-hidden="true"] { display: none !important; }
  /* Make room on the group header for the × button */
  .compare-wrap .group-cell.feat { display: flex; align-items: baseline; gap: 6px; }
  .compare-wrap .group-cell.feat .group-toggle { flex: 1; min-width: 0; text-align: left; }
  .compare-wrap .group-cell.feat .group-hide-x:hover { background: var(--bone-3); color: var(--ink); }

  /* tick / cross / partial pills inside cells */
  .tick { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 999px; background: var(--green-soft); color: var(--green); font-size: 11px; font-weight: 600; }
  .cross { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 999px; background: var(--bone-3); color: var(--ink-4); font-size: 13px; }
  .partial { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 999px; background: var(--amber-soft); color: color-mix(in oklch, var(--amber) 60%, var(--ink)); font-size: 11px; font-weight: 600; }
  .cell-with-icon { display: flex; align-items: center; gap: 10px; }
  .cell-with-icon .label { color: var(--ink-3); font-size: 11.5px; }

  /* compare badges */
  .compare .badge { display: inline-block; font-size: 10px; font-weight: 500; padding: 2px 8px; border-radius: 4px; letter-spacing: .02em; }
  .compare .badge-amber { background: var(--amber-soft); color: color-mix(in oklch, var(--amber) 60%, var(--ink)); }
  .compare .badge-indigo { background: var(--indigo-soft); color: var(--indigo); }

  /* empty product slot */
  .add-slot {
    padding: 18px 18px 16px;
    border-radius: 8px;
    background: repeating-linear-gradient(135deg, var(--bone-2), var(--bone-2) 6px, var(--bone-3) 6px, var(--bone-3) 7px);
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
    min-height: 148px;
    color: var(--ink-4);
  }
  .add-slot button {
    font-family: var(--sans); font-size: 12px; font-weight: 500; color: var(--indigo);
    background: var(--bone-2); border: 1px dashed var(--indigo);
    padding: 6px 12px; border-radius: 6px; cursor: pointer;
  }
  .add-slot button:hover { background: var(--indigo-soft); }
  .add-slot .add-hint { font-size: 10.5px; color: var(--ink-4); font-family: var(--mono); letter-spacing: .04em; }

  /* picker modal */
  .modal-bg {
    position: fixed; inset: 0; background: rgba(20,18,14,.45);
    z-index: 100; display: flex; align-items: center; justify-content: center; padding: 20px;
  }
  .modal-bg[hidden] { display: none; }
  .modal {
    background: var(--bone); border: 1px solid var(--line); border-radius: 12px;
    width: 560px; max-width: 100%; max-height: 80vh;
    display: flex; flex-direction: column;
    box-shadow: 0 20px 60px rgba(0,0,0,.2);
  }
  .modal-header { padding: 16px 18px; border-bottom: 1px solid var(--line-2); display: flex; align-items: center; gap: 10px; }
  .modal-header h3 { margin: 0; font-size: 15px; font-weight: 600; }
  .modal-search {
    flex: 1; padding: 6px 10px; border: 1px solid var(--line); border-radius: 6px;
    background: var(--bone-2); font-family: var(--sans); font-size: 13px; outline: none;
  }
  .modal-search:focus { border-color: var(--indigo); }
  .modal-list { flex: 1; overflow: auto; padding: 6px; }
  .modal-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 7px; cursor: pointer; }
  .modal-row:hover { background: var(--bone-3); }
  .modal-row.disabled { opacity: .45; cursor: not-allowed; }
  .modal-row .swatch {
    width: 28px; height: 28px; border-radius: 6px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    color: white; font-family: var(--serif); font-size: 14px;
  }
  .modal-row .info { flex: 1; min-width: 0; }
  .modal-row .nm { font-size: 13px; font-weight: 500; color: var(--ink); }
  .modal-row .meta { font-size: 11px; color: var(--ink-4); font-family: var(--mono); }
  .modal-row .selected-mark {
    font-size: 10px; color: var(--green); font-family: var(--mono);
    letter-spacing: .04em; text-transform: uppercase;
  }
  .modal-foot { padding: 10px 18px; border-top: 1px solid var(--line-2); display: flex; align-items: center; gap: 10px; justify-content: space-between; color: var(--ink-4); font-size: 11.5px; }

  /* footer summary */
  .footer-callout {
    margin-top: 24px;
    display: grid; grid-template-columns: 1fr auto auto; gap: 14px; align-items: center;
    padding: 18px 22px; border: 1px solid var(--line);
    border-radius: 10px; background: var(--bone-2);
    background-clip: padding-box;
  }
  .footer-callout .ai-icon {
    width: 34px; height: 34px; border-radius: 8px;
    background: color-mix(in oklch, var(--indigo) 18%, white);
    display: flex; align-items: center; justify-content: center;
    color: var(--indigo); flex-shrink: 0;
  }
  .footer-callout .title { font-size: 13.5px; font-weight: 500; }
  .footer-callout .sub { font-size: 12px; color: var(--ink-3); margin-top: 2px; }

  /* mobile pager — only shown ≤720px */
  .mobile-pager { display: none; }

  @media (max-width: 1024px) {
    .summary { grid-template-columns: repeat(2, 1fr); }
    .summary > div { border-right: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2); }
    .summary > div:nth-child(2) { border-right: none; }
    .summary > div:nth-child(3), .summary > div:nth-child(4) { border-bottom: none; }
    .footer-callout { grid-template-columns: 1fr; gap: 12px; }
    .footer-callout .btn { justify-self: start; }
  }

  @media (max-width: 720px) {
    .summary { grid-template-columns: repeat(2, 1fr); }
    .grid-toolbar { gap: 8px; padding: 10px 12px; }
    .grid-toolbar .density-grp { width: 100%; justify-content: flex-end; margin-left: 0 !important; }
    .seg button { padding: 5px 8px; font-size: 10.5px; }
    .toggle { font-size: 10.5px; padding: 4px 8px; }

    .mobile-pager {
      display: flex; align-items: center; gap: 10px;
      padding: 10px 12px;
      border-left: 1px solid var(--line); border-right: 1px solid var(--line);
      background: var(--bone-2);
    }
    .mobile-pager .pager-btn {
      width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--line);
      background: var(--bone); color: var(--ink-2);
      display: flex; align-items: center; justify-content: center; cursor: pointer;
      font-size: 16px; line-height: 1; flex-shrink: 0;
    }
    .mobile-pager .pager-btn:disabled { opacity: .4; cursor: not-allowed; }
    .mobile-pager .pager-info { flex: 1; text-align: center; font-size: 11px; color: var(--ink-3); font-family: var(--mono); letter-spacing: .04em; }
    .mobile-pager .pager-info strong { color: var(--ink); font-weight: 600; font-family: var(--mono); }
    .mobile-pager .dots { display: flex; gap: 5px; justify-content: center; margin-top: 4px; }
    .mobile-pager .dot { width: 5px; height: 5px; border-radius: 999px; background: var(--line); }
    .mobile-pager .dot.on { background: var(--indigo); width: 14px; }
    .mobile-pager-stack { display: flex; flex-direction: column; flex: 1; gap: 0; }

    /* Mobile: 1 product col at a time, driven by data-mobile-idx */
    .compare-wrap .compare { grid-template-columns: minmax(130px, 150px) minmax(0, 1fr) !important; }
    .compare-wrap .slot-cell { display: none; }
    .compare-wrap[data-mobile-idx="0"] .slot-cell[data-slot="0"],
    .compare-wrap[data-mobile-idx="1"] .slot-cell[data-slot="1"],
    .compare-wrap[data-mobile-idx="2"] .slot-cell[data-slot="2"],
    .compare-wrap[data-mobile-idx="3"] .slot-cell[data-slot="3"] { display: flex; }

    .head-cell { padding: 14px 14px 12px; }
    .product-card { gap: 8px; }
    .product-name { font-size: 14px; }
    .compare .cell { padding: 10px 12px; font-size: 12.5px; }
    .compare .cell.feat { font-size: 12px; }
    .winner-mark { display: none; }
    .footer-callout { padding: 14px 16px; }
  }

  /* ============================================================
     PRINT — Export PDF flow uses window.print(). Strip the page
     chrome (sidebars, topbar, toolbar, banners, modals, etc.) and
     show the #printHeader. Force background printing so the
     compare grid keeps its on-screen colors and borders.
     ============================================================ */
  /* Zero @page margin so Chrome has nowhere to draw its
     "Headers and footers" content (URL, page number, date).
     Content gets its own breathing room from body padding inside
     @media print below. The @top-/bottom- boxes also force
     content: "" in browsers (Firefox, some Safari) that honor
     CSS Paged Media spec margin boxes. */
  @page {
    size: landscape;
    margin: 0;
    @top-left      { content: ""; }
    @top-center    { content: ""; }
    @top-right     { content: ""; }
    @bottom-left   { content: ""; }
    @bottom-center { content: ""; }
    @bottom-right  { content: ""; }
  }
  @media print {
    /* Keep cell backgrounds + borders in the printout. By default
       Chrome strips them to save ink. */
    *, *::before, *::after {
      -webkit-print-color-adjust: exact !important;
      print-color-adjust: exact !important;
    }

    /* Replace @page margin with body padding so the content sits
       in a clear printable area. */
    body { padding: 0.4in !important; box-sizing: border-box; }

    /* Hide page chrome (.print-hide is on screen-only links like
       "Back to products" that shouldn't appear in the PDF). */
    .sidebar-left, .sidebar-right, .center-topbar, .mobile-brand-bar,
    .mobile-pager, .grid-toolbar, #categoryBanner, #sessionHiddenBar,
    .modal-bg, #compareBar, .footer-callout .btn, .group-hide-x,
    .remove-x, .product-actions, .print-hide {
      display: none !important;
    }

    /* Reveal the print-only header */
    .print-only { display: flex !important; }
    #printHeader {
      align-items: center;
      gap: 14px;
      padding: 0 0 14px;
      margin-bottom: 16px;
      border-bottom: 2px solid var(--ink);
      color: var(--ink);
      font-family: var(--sans);
    }
    #printHeader svg { color: var(--ink); flex-shrink: 0; }
    #printHeader .print-brand {
      font-size: 16px; font-weight: 700; letter-spacing: -0.005em;
    }
    #printHeader .print-title {
      font-size: 13px; color: var(--ink-3); font-weight: 500;
      padding-left: 12px; border-left: 1px solid var(--line);
    }
    #printHeader .print-products {
      flex: 1; font-size: 12px; color: var(--ink-2);
      padding-left: 12px; border-left: 1px solid var(--line);
    }
    #printHeader .print-date {
      font-size: 11px; color: var(--ink-4); font-family: var(--mono);
    }

    /* Reset the layout so the center stretches to page width */
    body { background: white !important; }
    .layout { display: block !important; }
    .center { padding: 0 !important; max-width: none !important; min-width: 0 !important; }
    .center-scroll { padding: 0 !important; overflow: visible !important; height: auto !important; }

    /* Compare grid: render at full page width, no scroll constraints,
       sticky positioning off so rows flow normally across pages. */
    .compare-wrap { overflow: visible !important; }
    .compare-scroll { overflow: visible !important; }
    .compare .head-cell, .compare .group-cell, .compare .cell.feat {
      position: static !important;
    }

    /* Avoid splitting a section's header off from its first row */
    .compare .group-cell, .compare .cell {
      page-break-inside: avoid;
    }

    /* Ask & footer-callout AI box look noisy in PDFs — drop them */
    .info-block:has(#askBox), #askBox, #askBtn, #askAnswer, #askStatus {
      display: none !important;
    }
  }
