﻿/* ─── BPG Portal — shared styles ──────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/*
  [hidden] is a UA-stylesheet rule, so ANY author rule that sets display wins over it —
  .pagination-bar { display: flex } left a hidden pager on screen, showing "Page 1 of 1"
  under a single page of results. Say it here once, with the same !important the
  .is-hidden helper already uses, so `el.hidden = true` means hidden everywhere.
*/
[hidden] { display: none !important; }

/*
  Palette bridge. Every Portal page loads Shell.Web's theme.css ahead of this
  file, and theme.css is the only place a colour is decided: it flips every
  token under [data-theme="dark"]. The --gray-* / --blue-* names below predate
  that and are read by ~200 rules here and in page <style> blocks, so rather
  than rename every call site they are ALIASED onto the shell tokens. Dark mode
  then follows for free wherever a token exists.

  Two things the aliases must get right:

  1. Every alias carries a light fallback. The customer-lane static pages under
     wwwroot/portal/ load THIS file alone — no theme.css, no theme toggle — so
     the fallback is what paints them and they stay light, exactly as before. A
     bare var(--bg-secondary) there is unresolvable, which makes the whole
     declaration invalid at computed-value time: the card paints nothing (the
     project-detail.css lesson, 2026-08-29).

  2. The accent families (blue, indigo, green, red, yellow, purple) have no
     shell equivalent, so they carry their own [data-theme="dark"] block: a
     tint that reads as a pale wash on white reads as a smear on #2d2d2d, and
     #1d4ed8 text on a dark card fails contrast outright. Same shape as
     theme.css's own .badge-* dark overrides, and the values are borrowed from
     them where one exists.

  Surfaces are never a literal. `--surface` is the one card/table/dialog
  background; `#fff` does not appear in this file, and a spec pins that
  (tests/BPG.Web.Tests/specs/shell/portal-dark-mode.spec.ts).
*/
:root {
  /* Surfaces */
  --surface:   var(--bg-secondary, #ffffff);
  --border:    var(--border-light, #e5e7eb);

  /* Neutrals → shell text / border / background tokens */
  --gray-900:  var(--text-primary, #111827);
  --gray-800:  var(--text-primary, #1f2937);
  --gray-700:  var(--text-secondary, #374151);
  --gray-600:  var(--text-secondary, #4b5563);
  --gray-500:  var(--text-tertiary, #6b7280);
  --gray-400:  var(--text-muted, #9ca3af);
  --gray-300:  var(--border-medium, #d1d5db);
  --gray-200:  var(--border-light, #e5e7eb);
  --gray-100:  var(--bg-hover, #f3f4f6);
  --gray-50:   var(--bg-tertiary, #f9fafb);

  /* Accents — light values here, dark values in the block below */
  --blue-900:  #1e3a5f;
  --blue-800:  #1d4ed8;
  --blue-700:  #1d4ed8;
  --blue-600:  #2563eb;
  --blue-200:  #bfdbfe;
  --blue-50:   #eff6ff;
  --indigo-800:#3730a3;
  --indigo-700:#4338ca;
  --green-600: #16a34a;
  --green-200: #bbf7d0;
  --green-100: #dcfce7;
  --red-600:   #dc2626;
  --red-200:   #fecaca;
  --red-100:   #fee2e2;
  --yellow-600:#d97706;
  --yellow-200:#fde68a;
  --yellow-100:#fef3c7;
  --purple-700:#7e22ce;
  --purple-100:#f3e8ff;
}

[data-theme="dark"] {
  --blue-900:  #dbeafe;
  --blue-800:  #93c5fd;
  --blue-700:  #60a5fa;
  --blue-600:  #4a9eff;
  --blue-200:  #2f4a6e;
  --blue-50:   #1f2f4a;
  --indigo-800:#c7d2fe;
  --indigo-700:#a5b4fc;
  --green-600: #74c4a4;
  --green-200: #2d5240;
  --green-100: #1f3a2a;
  --red-600:   #e08888;
  --red-200:   #5a3535;
  --red-100:   #3a2020;
  --yellow-600:#d4a574;
  --yellow-200:#5a4a2a;
  --yellow-100:#3a3020;
  --purple-700:#c4b5fd;
  --purple-100:#2e2545;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  background: var(--bg-primary, var(--gray-50));
  color: var(--gray-900);
  line-height: 1.5;
}

/* ─── Layout ─────────────────────────────────────────────────────────────── */
.portal-layout { display: flex; min-height: 100vh; }
/*
  min-width:0 prevents flex items overflowing their container (critical for wide tables).
  overflow-x:auto scrolls wide content without breaking the sticky sidebar.
*/
.portal-main   { flex: 1; padding: 2rem; min-width: 0; overflow-x: auto; }

/* ─── Sidebar nav ────────────────────────────────────────────────────────── */
/*
  Sticky sidebar: stays visible as the page body scrolls.
  height:100vh + overflow-y:auto lets the nav itself scroll if nav items exceed the screen height.
  flex-shrink:0 prevents the sidebar from collapsing when page content is wide.
*/
.portal-nav { display: flex; flex-direction: column; width: 220px; flex-shrink: 0; position: sticky; top: 0; height: 100vh; overflow-y: auto; }
.portal-nav.bg-blue   { background: var(--surface); border-right: 1px solid var(--gray-200); }

.portal-nav__brand {
  padding: 1rem 1.25rem;
  font-weight: 700;
  font-size: 0.875rem;
  border-bottom: 1px solid var(--gray-200);
}

.portal-nav__user {
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--gray-100);
}

.portal-nav__user-name { font-size: 0.8rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.portal-nav__user-email { font-size: 0.75rem; color: var(--gray-500); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.portal-nav__links { flex: 1; padding: 0.5rem 0; }

.portal-nav__link {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.625rem 1.25rem;
  font-size: 0.875rem;
  text-decoration: none;
  color: var(--gray-600);
  transition: background 0.15s, color 0.15s;
}
.portal-nav__link:hover { background: var(--gray-50); color: var(--gray-900); }
.portal-nav__link--active { background: var(--blue-50); color: var(--blue-800); font-weight: 600; border-right: 2px solid var(--blue-700); }

.portal-nav__icon { font-size: 1rem; }

.portal-nav__signout { padding: 1rem 1.25rem; border-top: 1px solid var(--gray-200); }
.portal-nav__signout-btn { background: none; border: none; cursor: pointer; font-size: 0.875rem; color: var(--gray-500); }
.portal-nav__signout-btn:hover { color: var(--red-600); }

/* ─── Page header ────────────────────────────────────────────────────────── */
.page-title   { font-size: 1.5rem; font-weight: 700; margin-bottom: 0.25rem; }
.page-subtitle { font-size: 0.875rem; color: var(--gray-500); margin-bottom: 2rem; }

/* ─── Cards / stat blocks ────────────────────────────────────────────────── */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
.stat-card { background: var(--surface); border: 1px solid var(--gray-200); border-radius: 12px; padding: 1.25rem; }
.stat-value { font-size: 2rem; font-weight: 700; }
.stat-label { font-size: 0.8rem; color: var(--gray-500); margin-top: 0.25rem; }
.stat-blue   .stat-value { color: var(--blue-800); }
.stat-green  .stat-value { color: var(--green-600); }
.stat-yellow .stat-value { color: var(--yellow-600); }

/* ─── Quick action grid ──────────────────────────────────────────────────── */
.action-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.75rem; }
.action-card { background: var(--surface); border: 1px solid var(--gray-200); border-radius: 12px; padding: 1rem; text-align: center; text-decoration: none; color: var(--gray-700); font-size: 0.875rem; font-weight: 500; transition: border-color 0.15s, box-shadow 0.15s; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
.action-card:hover { border-color: var(--blue-600); box-shadow: var(--shadow-md, 0 2px 8px rgba(0,0,0,0.08)); }
.action-card__icon { font-size: 1.75rem; }

/* ─── Tables ─────────────────────────────────────────────────────────────── */
.data-table-wrap { background: var(--surface); border: 1px solid var(--gray-200); border-radius: 12px; overflow: hidden; }
.data-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.data-table thead th { text-align: left; padding: 0.75rem 1rem; background: var(--gray-50); font-size: 0.75rem; font-weight: 600; color: var(--gray-600); text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--gray-200); }
.data-table tbody td { padding: 0.875rem 1rem; border-bottom: 1px solid var(--gray-100); }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: var(--gray-50); }

/* ─── Status badges ──────────────────────────────────────────────────────── */
.badge { display: inline-block; border-radius: 9999px; padding: 0.125rem 0.625rem; font-size: 0.75rem; font-weight: 500; }
.badge-yellow { background: var(--yellow-100); color: var(--yellow-600); }
.badge-blue   { background: var(--blue-50);    color: var(--blue-800); }
.badge-green  { background: var(--green-100);  color: var(--green-600); }
.badge-red    { background: var(--red-100);    color: var(--red-600); }
.badge-purple { background: var(--purple-100); color: var(--purple-700); }
.badge-gray   { background: var(--gray-100);   color: var(--gray-600); }

/* ─── Buttons ────────────────────────────────────────────────────────────── */
.btn { display: inline-block; border: none; cursor: pointer; font-size: 0.875rem; font-weight: 600; border-radius: 9999px; padding: 0.625rem 1.25rem; text-decoration: none; transition: background 0.15s; }
.btn-primary   { background: var(--btn-primary-bg, var(--blue-700)); color: var(--btn-primary-text, #fff); }
.btn-primary:hover { background: var(--btn-primary-hover, var(--blue-800)); }
.btn-secondary { background: var(--surface); border: 1px solid var(--gray-300); color: var(--gray-700); }
.btn-secondary:hover { background: var(--gray-100); }

/* ─── Forms ──────────────────────────────────────────────────────────────── */
.form-card { background: var(--surface); border: 1px solid var(--gray-200); border-radius: 12px; padding: 1.5rem; }
.form-group { margin-bottom: 1rem; }
.form-label { display: block; font-size: 0.8rem; font-weight: 600; color: var(--gray-700); margin-bottom: 0.375rem; }
.form-input, .form-textarea {
  width: 100%; border: 1px solid var(--gray-300); border-radius: 8px;
  padding: 0.5rem 0.75rem; font-size: 0.875rem; font-family: inherit;
  background: var(--input-bg, #ffffff); color: var(--gray-900);
  transition: border-color 0.15s;
}
.form-input:focus, .form-textarea:focus { outline: none; border-color: var(--input-focus-border, var(--blue-600)); box-shadow: 0 0 0 3px var(--input-focus-ring, rgba(37,99,235,0.12)); }
.form-textarea { resize: vertical; min-height: 120px; }

/* ─── Empty / loading / error states ────────────────────────────────────── */
.empty-state    { text-align: center; padding: 4rem 2rem; color: var(--gray-400); }
.empty-state__icon { font-size: 3rem; margin-bottom: 0.75rem; }
.empty-state__msg  { margin-bottom: 1rem; }
.loading-spinner   { text-align: center; padding: 2rem; color: var(--gray-400); font-size: 0.875rem; }
.error-banner      { background: var(--red-100); border: 1px solid var(--red-200); color: var(--red-600); border-radius: 8px; padding: 0.75rem 1rem; font-size: 0.875rem; margin-bottom: 1rem; }
.success-banner    { background: var(--green-100); border: 1px solid var(--green-200); color: var(--green-600); border-radius: 8px; padding: 1rem; text-align: center; }

/* ─── Section headers ────────────────────────────────────────────────────── */
.section-title { font-size: 0.875rem; font-weight: 600; color: var(--gray-600); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.75rem; }

/* ─── Landing / portal-chooser page ─────────────────────────────────────── */
.landing-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 2rem;
  background: var(--bg-primary, var(--gray-50));
}

.landing-header {
  text-align: center;
  margin-bottom: 3rem;
}

.landing-logo {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--blue-600);
  margin-bottom: 1.25rem;
}

.landing-title {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--gray-900);
  margin-bottom: 0.5rem;
}

.landing-subtitle {
  font-size: 0.9375rem;
  color: var(--gray-500);
}

.landing-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
  width: 100%;
  max-width: 640px;
}

.landing-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  text-decoration: none;
  background: var(--surface);
  border: 2px solid var(--gray-200);
  border-radius: 16px;
  padding: 2.5rem 2rem;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
  color: var(--gray-900);
}

.landing-card:hover {
  box-shadow: var(--shadow-xl, 0 8px 24px rgba(0, 0, 0, 0.1));
  transform: translateY(-2px);
}

.landing-card:focus-visible {
  outline: 3px solid var(--blue-600);
  outline-offset: 2px;
}

.landing-card--employee:hover { border-color: var(--indigo-700); }
.landing-card--customer:hover  { border-color: var(--blue-600); }

.landing-card__icon {
  font-size: 3rem;
  margin-bottom: 1.25rem;
  line-height: 1;
}

.landing-card__title {
  font-size: 1.125rem;
  font-weight: 700;
  margin-bottom: 0.375rem;
}

.landing-card--employee .landing-card__title { color: var(--indigo-800); }
.landing-card--customer  .landing-card__title { color: var(--blue-800); }

.landing-card__desc {
  font-size: 0.875rem;
  color: var(--gray-500);
}

.landing-card__arrow {
  margin-top: 1.25rem;
  font-size: 0.875rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.landing-card--employee .landing-card__arrow { color: var(--indigo-700); }
.landing-card--customer  .landing-card__arrow { color: var(--blue-600); }

@media (max-width: 520px) {
  .landing-cards {
    grid-template-columns: 1fr;
    max-width: 340px;
  }
}

/* ─── Internal hub / admin pages ───────────────────────────────────────────── */
.page-header {
  margin-bottom: 2rem;
}

.page-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--indigo-700);
}

.hub-section {
  margin-bottom: 2rem;
}

.hub-grid,
.admin-grid,
.app-grid,
.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}

.hub-card,
.app-card,
.detail-card,
.admin-stat-card {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  padding: 1.25rem;
}

.hub-card {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.hub-card__title,
.app-card__title,
.detail-card__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--gray-900);
}

.hub-card__meta,
.app-card__meta,
.detail-card__meta,
.table-meta,
.subtle-text {
  font-size: 0.875rem;
  color: var(--gray-500);
}

.hub-card__links,
.app-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: auto;
}

.text-link {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--blue-700);
  text-decoration: none;
}

.text-link:hover {
  text-decoration: underline;
}

/* ─── Utility ───────────────────────────────────────────────────────────────── */
.initially-hidden { display: none; }

/* ─── Button BEM variants (products page + other internal pages) ─────────── */
.btn--primary    { background: var(--btn-primary-bg, var(--blue-700)); color: var(--btn-primary-text, #fff); }
.btn--primary:hover { background: var(--btn-primary-hover, var(--blue-800)); }
.btn--secondary  { background: var(--surface); border: 1px solid var(--gray-200); color: var(--gray-700); }
.btn--secondary:hover { background: var(--gray-50); }
.btn--ghost      { background: transparent; border: 1px solid var(--gray-200); color: var(--gray-600); }
.btn--ghost:hover { background: var(--gray-50); color: var(--gray-900); }
.btn--danger     { background: var(--btn-danger-bg, #dc2626); color: var(--btn-danger-text, #fff); border: none; }
.btn--danger:hover { background: var(--btn-danger-hover, #b91c1c); }
.btn--sm         { padding: 0.3rem 0.7rem; font-size: 0.8rem; border-radius: 6px; }

/* ─── Filter bar ─────────────────────────────────────────────────────────── */
.filter-bar {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
}
.filter-bar__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}
.filter-bar__search {
  position: relative;
  flex: 1;
  min-width: 200px;
}
.filter-bar__search--wide { min-width: 220px; }
.filter-bar__search-icon {
  position: absolute;
  left: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--gray-400);
  pointer-events: none;
  font-size: 0.875rem;
}
.search-input {
  width: 100%;
  border: 1px solid var(--gray-200);
  border-radius: 8px;
  padding: 0.5rem 0.75rem 0.5rem 2.1rem;
  font-size: 0.875rem;
  font-family: inherit;
  background: var(--gray-50);
  color: var(--gray-900);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.search-input:focus {
  outline: none;
  border-color: var(--input-focus-border, var(--blue-600));
  box-shadow: 0 0 0 3px var(--input-focus-ring, rgba(37, 99, 235, 0.12));
  background: var(--input-bg, #ffffff);
}
.select-filter {
  border: 1px solid var(--gray-200);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  font-family: inherit;
  background: var(--gray-50);
  color: var(--gray-700);
  cursor: pointer;
  min-width: 140px;
  transition: border-color 0.15s;
}
.select-filter--status   { min-width: 130px; }
.select-filter--category { min-width: 160px; }
.select-filter:focus {
  outline: none;
  border-color: var(--input-focus-border, var(--blue-600));
  box-shadow: 0 0 0 3px var(--input-focus-ring, rgba(37, 99, 235, 0.12));
}
.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.875rem;
  color: var(--gray-600);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}

/* ─── Catalog header inner layout ───────────────────────────────────────── */
.catalog-header__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
}

/* ─── Table fixed-width columns ─────────────────────────────────────────── */
th.col-img     { width: 52px; }
th.col-actions { width: 130px; }

/* ─── Toast z-index ─────────────────────────────────────────────────────── */
.toast-container--portal { z-index: 9999; }

/* ─── Table thumbnail ────────────────────────────────────────────────────── */
.table-img {
  width: 40px;
  height: 40px;
  border-radius: 6px;
  object-fit: cover;
  border: 1px solid var(--gray-200);
  display: block;
}
.table-img-placeholder {
  width: 40px;
  height: 40px;
  border-radius: 6px;
  background: var(--gray-100);
  border: 1px solid var(--gray-200);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gray-400);
  font-size: 1rem;
}

/* ─── Margin indicator ───────────────────────────────────────────────────── */
.margin-positive { color: var(--green-600); font-size: 0.8rem; font-weight: 600; }
.margin-negative { color: var(--red-600); font-size: 0.8rem; font-weight: 600; }

/* ─── Pagination ─────────────────────────────────────────────────────────── */
.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1rem;
  padding: 0.5rem;
}
.pagination-info {
  font-size: 0.875rem;
  color: var(--gray-500);
  min-width: 120px;
  text-align: center;
}
.pagination-bar .btn { white-space: nowrap; }

/* ─── Mobile card layout ─────────────────────────────────────────────────── */
.mobile-cards { display: none; }

@media (max-width: 768px) {
  .data-table-wrap { display: none !important; }
  .mobile-cards { display: block; }
}

.item-card {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  padding: 1rem;
  margin-bottom: 0.75rem;
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.06));
}
.item-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 0.625rem;
  padding-bottom: 0.625rem;
  border-bottom: 1px solid var(--gray-100);
  gap: 0.75rem;
}
.item-card-title h5 {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--gray-900);
  margin: 0 0 0.2rem 0;
}
.item-card-sku {
  font-size: 0.8rem;
  color: var(--gray-500);
  font-family: 'Courier New', monospace;
}
.item-info-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.3rem 0;
  font-size: 0.875rem;
}
.item-info-label { color: var(--gray-500); font-weight: 500; }
.item-info-value { color: var(--gray-900); }
.item-card-actions {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--gray-100);
  display: flex;
  gap: 0.5rem;
}
.item-card-actions .btn { flex: 1; justify-content: center; }

/* ─── Catalog category cards ─────────────────────────────────────────────── */
.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}
.cat-card {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  padding: 1.25rem;
  text-decoration: none;
  color: var(--gray-900);
  transition: border-color 0.15s, box-shadow 0.15s;
  display: block;
}
.cat-card:hover {
  border-color: var(--blue-600);
  box-shadow: var(--shadow-md, 0 2px 8px rgba(0, 0, 0, 0.08));
}
.cat-icon  { font-size: 2rem; margin-bottom: 0.75rem; }
.cat-title { font-weight: 600; margin-bottom: 0.25rem; }
.cat-desc  { font-size: 0.8rem; color: var(--gray-500); }
.cat-quote-link { color: var(--blue-700); text-decoration: none; font-weight: 500; }
.cat-quote-link:hover { text-decoration: underline; }

.admin-stat-card {
  border-top: 3px solid var(--indigo-700);
}

.admin-stat-card__value {
  font-size: 2rem;
  font-weight: 700;
  color: var(--indigo-800);
}

.admin-stat-card__label {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--gray-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.app-card {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.app-card__top {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
}

.app-card__icon {
  font-size: 1.6rem;
  line-height: 1;
}

.app-card__badge {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 0.2rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 700;
  background: var(--blue-50);
  color: var(--blue-700);
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.toolbar__group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.search-input {
  min-width: 240px;
  max-width: 360px;
}

.summary-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.summary-pill {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  padding: 0.85rem 1rem;
}

.summary-pill__value {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--gray-900);
}

.summary-pill__label {
  font-size: 0.8rem;
  color: var(--gray-500);
}

.table-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Link-styled button — an inline edit affordance inside a table cell
   (the GitHub username column on /admin-users). */
.btn-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--blue-600);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.btn-link.subtle-text {
  color: var(--gray-500);
}

/* One connected-account row on /settings — name + status on the left,
   Connect/Disconnect on the right. */
.connected-account {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.9rem 0 0.2rem;
}

.connected-account__name {
  font-weight: 600;
  color: var(--gray-900);
}

.connected-account__detail {
  margin: 0.15rem 0 0;
  font-size: 0.85rem;
  color: var(--gray-500);
}

/* The auto-scheduling card on /settings — work days, hours, buffer. */
.scheduling-form {
  margin-top: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.sched-field {
  border: none;
  margin: 0;
  padding: 0;
}

.sched-field legend {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--gray-900);
  padding: 0;
  margin-bottom: 0.35rem;
}

.sched-days {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
}

.sched-day {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9rem;
  color: var(--gray-900);
}

.sched-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.sched-label {
  min-width: 10.5rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--gray-900);
}

.sched-to {
  font-size: 0.85rem;
  color: var(--gray-500);
}

.sched-hint {
  margin: 0;
  font-size: 0.8rem;
  color: var(--gray-500);
  max-width: 46rem;
}

.sched-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.sched-status {
  font-size: 0.85rem;
  color: var(--gray-500);
}

.sched-status--error {
  color: var(--red-600);
}

.detail-card {
  margin-top: 1rem;
}

.detail-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
}

.detail-item {
  padding: 0.85rem 1rem;
  border-radius: 12px;
  background: var(--gray-50);
}

.detail-item__label {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--gray-500);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.detail-item__value {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.95rem;
  color: var(--gray-900);
}

.initially-hidden,
.is-hidden {
  display: none !important;
}

/* ─── Mobile shell: top bar + off-canvas drawer ───────────────────────────────
   The sidebar is 220px of permanently visible nav, which is right on a desktop and
   wrong on a phone: stacked above the content it pushed the actual page below the
   fold, so every visit started with a scroll past the menu. Below 900px the nav
   becomes a drawer behind a top bar instead, and the page starts at the page.

   portal-nav.ts renders .portal-topbar and .portal-scrim as siblings of .portal-nav
   inside #portal-nav, and owns the open/close state (including Escape and the
   body scroll lock). Both are display:none above the breakpoint.
   ───────────────────────────────────────────────────────────────────────────── */
.portal-topbar { display: none; }
.portal-scrim  { display: none; }

@media (max-width: 900px) {
  .portal-layout {
    flex-direction: column;
  }

  .portal-topbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--surface);
    border-bottom: 1px solid var(--gray-200);
    padding: 0.5rem 0.75rem;
    /* Clears the notch on iOS when the page is installed / in standalone. */
    padding-top: calc(0.5rem + env(safe-area-inset-top, 0px));
  }

  /* 44px square: the minimum comfortable tap target, and the reason the icon is
     not simply sized to the glyph. */
  .portal-topbar__toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    padding: 0;
    background: none;
    border: 1px solid var(--gray-200);
    border-radius: 10px;
    cursor: pointer;
    color: inherit;
  }

  .portal-topbar__bars,
  .portal-topbar__bars::before,
  .portal-topbar__bars::after {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    content: "";
    position: relative;
  }
  .portal-topbar__bars::before { top: -6px; position: absolute; }
  .portal-topbar__bars::after  { top:  6px; position: absolute; }

  .portal-topbar__brand {
    font-weight: 700;
    font-size: 0.9375rem;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .portal-topbar__avatar {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: 9999px;
    background: var(--blue-50);
    color: var(--blue-800);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
    text-decoration: none;
  }

  .portal-nav {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(280px, 82vw);
    height: 100%;
    /* 100dvh where supported: 100vh sits under mobile Safari's toolbar and cuts
       the sign-out button off the bottom of the drawer. */
    height: 100dvh;
    z-index: 60;
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: 2px 0 16px rgba(15, 23, 42, 0.18);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .portal-nav--open { transform: translateX(0); }

  .portal-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(15, 23, 42, 0.5);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
  }
  .portal-scrim--open {
    opacity: 1;
    pointer-events: auto;
  }

  /* Set by portal-nav.ts while the drawer is open so the page behind cannot scroll. */
  body.portal-nav-open { overflow: hidden; }

  .portal-main {
    padding: 1.25rem;
    overflow-x: auto;
  }

  /* Nav rows are the densest tap targets in the app; give them room on touch. */
  .portal-nav__link {
    min-height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .portal-nav,
  .portal-scrim {
    transition: none;
  }
}

/* Keyboard users must be able to see where they are — the drawer is operable by
   Tab and Escape, which is worth nothing without a visible ring. */
.portal-nav__link:focus-visible,
.portal-topbar__toggle:focus-visible,
.portal-topbar__avatar:focus-visible,
.btn:focus-visible,
.form-input:focus-visible,
.form-textarea:focus-visible {
  outline: 2px solid var(--blue-600);
  outline-offset: 2px;
}

/* Coarse pointers (phones, tablets) get bigger buttons everywhere, not just in nav. */
@media (pointer: coarse) {
  .btn {
    min-height: 44px;
    padding: 0.75rem 1.25rem;
  }
  .btn--sm { min-height: 38px; }
}

/* ─── Admin dialog / modal ───────────────────────────────────────────── */
.admin-dialog {
  border: none;
  border-radius: 16px;
  padding: 0;
  width: min(560px, 95vw);
  box-shadow: var(--shadow-xl, 0 8px 48px rgba(0,0,0,0.18));
  background: var(--modal-bg, var(--surface));
  color: var(--gray-900);
}

/* Custom properties reach ::backdrop only in recent engines, so the literal
   fallback is load-bearing, not decorative. */
.admin-dialog::backdrop {
  background: var(--overlay-bg, rgba(0,0,0,0.45));
}

.admin-dialog__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem 0;
}

.admin-dialog__title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--gray-900);
  margin: 0;
}

.admin-dialog__close {
  background: none;
  border: none;
  font-size: 1.1rem;
  cursor: pointer;
  color: var(--gray-500);
  padding: 0.25rem;
  line-height: 1;
}

.admin-dialog__close:hover { color: var(--gray-900); }

.dialog-form {
  padding: 1.25rem 1.5rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.form-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--gray-700);
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  padding-top: 0.5rem;
}

.error-text {
  font-size: 0.875rem;
  color: var(--red-600);
  margin: 0;
}

@media (max-width: 560px) {
  .form-row {
    grid-template-columns: 1fr;
  }
}

/* ─── Customer account: purchases, subscriptions, profile ─────────────────────
   Everything below backs /portal/purchases.html, /portal/purchase.html,
   /portal/subscriptions.html and /portal/profile.html. It is mobile-first by
   construction: the list is a stack of cards at every width and only gains
   columns when there is room for them, because a purchase history read on a
   phone is the common case, not the fallback.
   ───────────────────────────────────────────────────────────────────────────── */

/* A currency total is the longest thing a stat tile ever holds — "$18,422.51" ran
   past the card edge at 390px with the fixed 2rem size. Fluid, with a floor that
   still reads as a headline number. */
.stat-value { font-size: clamp(1.375rem, 5.5vw, 2rem); overflow-wrap: anywhere; }

/* ── Notice: a state that is neither an error nor a success ─────────────────── */
.notice-banner {
  background: var(--blue-50);
  border: 1px solid var(--blue-200);
  color: var(--blue-800);
  border-radius: 10px;
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  margin-bottom: 1rem;
}
.notice-banner p { margin: 0; }
.notice-banner p + p { margin-top: 0.5rem; }
/* Inherit rather than the UA link blue: --blue-800/--blue-50 is the pair the
   banner's own text already uses in both themes, so a link reads exactly as
   legible as the sentence around it instead of a second, unverified colour. */
.notice-banner a { color: inherit; font-weight: 600; text-decoration: underline; }
.notice-banner--warn {
  background: var(--yellow-100);
  border-color: var(--yellow-200);
  color: var(--yellow-600);
}

/* ── Purchase list ──────────────────────────────────────────────────────────── */
.purchase-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* The whole row is the tap target — not a "view" link inside it. */
.purchase-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.35rem 1rem;
  align-items: start;
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  padding: 1rem;
  text-decoration: none;
  color: inherit;
  min-height: 44px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.purchase-row:hover { border-color: var(--blue-600); box-shadow: var(--shadow-md, 0 2px 8px rgba(0, 0, 0, 0.07)); }

.purchase-row__ref {
  font-weight: 700;
  font-size: 0.9375rem;
  font-family: 'Courier New', monospace;
  word-break: break-all;
}
.purchase-row__summary {
  grid-column: 1 / -1;
  font-size: 0.875rem;
  color: var(--gray-600);
  /* Two lines, then ellipsis — a long item description must not push the price
     and status out of view on a narrow screen. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.purchase-row__meta {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  font-size: 0.8125rem;
  color: var(--gray-500);
  margin-top: 0.25rem;
}
.purchase-row__total {
  font-weight: 700;
  font-size: 1rem;
  white-space: nowrap;
  text-align: right;
}

@media (min-width: 720px) {
  .purchase-row {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) auto;
    align-items: center;
  }
  .purchase-row__summary { grid-column: 2; margin: 0; }
  .purchase-row__meta    { grid-column: 1 / 3; margin-top: 0.15rem; }
  .purchase-row__total   { grid-row: 1 / 3; grid-column: 3; align-self: center; }
}

/* ── Purchase detail ────────────────────────────────────────────────────────── */
.detail-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  align-items: start;
}
@media (min-width: 900px) {
  .detail-columns { grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); }
}

/* Status trail. Horizontal on a wide screen, vertical on a phone — a four-step
   trail squeezed onto 360px is unreadable in either direction otherwise. */
.order-trail {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.order-trail__step {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: 0.875rem;
  color: var(--gray-500);
}
.order-trail__dot {
  width: 1.1rem;
  height: 1.1rem;
  flex-shrink: 0;
  margin-top: 0.15rem;
  border-radius: 9999px;
  border: 2px solid var(--gray-200);
  background: var(--surface);
}
.order-trail__step--done { color: var(--gray-900); }
.order-trail__step--done .order-trail__dot { background: var(--green-600); border-color: var(--green-600); }
.order-trail__step--current { color: var(--blue-800); font-weight: 600; }
.order-trail__step--current .order-trail__dot { border-color: var(--blue-700); background: var(--blue-50); }
.order-trail__when { display: block; font-size: 0.8125rem; font-weight: 400; color: var(--gray-500); }

@media (min-width: 720px) {
  .order-trail { flex-direction: row; }
  .order-trail__step { flex: 1; flex-direction: column; align-items: flex-start; gap: 0.4rem; }
}

/* Line items. A table on a phone means horizontal scrolling to read a price,
   so each line is its own block until there is width for columns. */
.line-items { display: flex; flex-direction: column; }
.line-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.2rem 1rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--gray-100);
}
.line-item:last-child { border-bottom: none; }
.line-item__name { font-weight: 600; font-size: 0.9375rem; }
.line-item__sku {
  grid-column: 1 / -1;
  font-family: 'Courier New', monospace;
  font-size: 0.8125rem;
  color: var(--gray-500);
}
.line-item__qty { grid-column: 1; font-size: 0.875rem; color: var(--gray-600); }
.line-item__total { grid-column: 2; font-weight: 600; white-space: nowrap; text-align: right; }

.totals { margin-top: 1rem; border-top: 1px solid var(--gray-200); padding-top: 0.75rem; }
.totals__row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.875rem;
  padding: 0.25rem 0;
  color: var(--gray-600);
}
.totals__row--grand {
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--gray-900);
  border-top: 1px solid var(--gray-200);
  margin-top: 0.5rem;
  padding-top: 0.75rem;
}

.address-block {
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--gray-700);
  font-style: normal;
}

/* ── Subscriptions ──────────────────────────────────────────────────────────── */
.sub-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
}
.sub-card__price { font-size: 1.75rem; font-weight: 700; }
.sub-card__price small { font-size: 0.875rem; font-weight: 500; color: var(--gray-500); }

.seat-meter {
  height: 8px;
  border-radius: 9999px;
  background: var(--gray-100);
  overflow: hidden;
  margin: 0.5rem 0 0.35rem;
}
.seat-meter__fill { height: 100%; background: var(--blue-600); border-radius: 9999px; }
.seat-meter__fill--full { background: var(--yellow-600); }

/* ── Page actions ───────────────────────────────────────────────────────────── */
.page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}
.page-actions .btn { flex: 1 1 auto; text-align: center; }

@media (min-width: 720px) {
  .page-actions .btn { flex: 0 0 auto; }
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 44px;
  font-size: 0.875rem;
  color: var(--blue-700);
  text-decoration: none;
}
.back-link:hover { text-decoration: underline; }

/* Filter controls stack on a phone; a search box sharing a row with a select at
   360px leaves both too small to use. */
.filter-bar__row .form-input,
.filter-bar__row .select-filter { min-height: 44px; }

@media (max-width: 560px) {
  .filter-bar__row { flex-direction: column; align-items: stretch; }
  .filter-bar__row > * { width: 100%; }
}

/* Skeletons: a purchase list that pops in from nothing reads as broken on a slow
   mobile connection. */
.skeleton-row {
  height: 84px;
  border-radius: 12px;
  background: linear-gradient(90deg, var(--gray-100) 25%, var(--gray-50) 37%, var(--gray-100) 63%);
  background-size: 400% 100%;
  animation: skeleton-sheen 1.4s ease infinite;
}
@keyframes skeleton-sheen {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-row { animation: none; }
}
