/* Vantage Wholesale -- design system foundation.
 *
 * Ported from the prototype's <style> block (docs/vantage-portal.html
 * lines 17-449, foundation only). Page-specific patterns (cards,
 * tables, modals, marketplace, kanban, etc.) land in the commits that
 * port the views that use them, so we don't ship CSS we don't use yet.
 *
 * Brand palette: navy #112A36, mint #6FC6A0, light wash #DBEEE0,
 * deep accent #1F534B. Gold is reserved for Priority-tier value-adds
 * only -- never general CTAs.
 */

/* ---------- Variables ---------- */

:root {
  --navy: #112a36;
  --navy-2: #17384a;
  --navy-3: #1f4759;
  --mint: #6fc6a0;
  --mint-2: #5ab58f;
  --mint-3: #9ad8ba;
  --light: #dbeee0;
  --light-2: #edf6ef;
  --deep: #1f534b;
  --deep-2: #174039;
  --white: #f8fafa;
  --ink: #0c1f29;
  --ink-2: #3a4a53;
  --muted: #6a7a82;
  --line: #e2ebee;
  --line-2: #cfdde1;
  --danger: #d85858;
  --warn: #e2a73b;
  --ok: #2f9e6c;

  /* Priority tier accent -- reserved exclusively for Priority-tier
     value-adds (chips, badges, exclusive-deal markers, upgrade CTAs).
     Never use for general CTAs; the colour earns its meaning by scarcity. */
  --gold:        #d4af5a;
  --gold-bright: #e8c87a;
  --gold-deep:   #8a6520;
  --gold-soft:   rgba(212, 175, 90, 0.10);
  --gold-ink:    #1a1408;

  --radius:    12px;
  --radius-sm: 8px;
  --shadow-sm: 0 1px 2px rgba(17, 42, 54, 0.06);
  --shadow-md: 0 6px 18px rgba(17, 42, 54, 0.08);
  --shadow-lg: 0 18px 40px rgba(17, 42, 54, 0.14);
  --font: "Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI",
          Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}

* { box-sizing: border-box; }
html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  font-size: 14px;
  line-height: 1.45;
}

a { color: var(--deep); }
a:hover { color: var(--navy); }
h1, h2, h3, h4 { color: var(--ink); }

/* ---------- Layout: signed-in shell ---------- */

#app {
  display: grid;
  grid-template-columns: 248px 1fr;
  min-height: 100vh;
}

.sidebar {
  background: var(--navy);
  color: #cfdde1;
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  border-right: 1px solid var(--navy-3);
  position: sticky; top: 0; height: 100vh;
}

.brand {
  display: flex; align-items: center; gap: 12px;
  padding: 4px 6px 20px;
  border-bottom: 1px solid var(--navy-3);
  margin-bottom: 16px;
  text-decoration: none;
}
.brand-mark {
  width: 36px; height: 36px; border-radius: 8px;
  background: var(--white); color: var(--navy);
  font-weight: 800; display: grid; place-items: center;
  font-size: 20px; letter-spacing: -0.5px;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.05; }

/* Brand text colours default to the LIGHT surface treatment (anon
   card, future marketing pages). The sidebar inverts these for its
   navy background. Choosing "light surface" as the default rather
   than the historical "dark surface" because the first page every
   new user sees -- sign-in -- is on a light surface. */
.brand-name-1 { color: var(--navy); font-weight: 700; font-size: 15px; }
.brand-name-2 { color: var(--deep); font-weight: 700; font-size: 15px; }

.sidebar .brand-name-1 { color: #fff; }
.sidebar .brand-name-2 { color: var(--mint); }

.nav {
  display: flex; flex-direction: column; gap: 2px;
  /* The sidebar is height:100vh; the footer must stay visible no
     matter how many nav items render. Letting the nav scroll
     internally pins the footer at the bottom. min-height:0 lets
     the flex shrink-to-fit work inside the column-flex sidebar. */
  overflow-y: auto;
  min-height: 0;
  flex: 1 1 auto;
  scrollbar-width: thin;
  scrollbar-color: var(--navy-3) transparent;
}
.nav::-webkit-scrollbar { width: 6px; }
.nav::-webkit-scrollbar-track { background: transparent; }
.nav::-webkit-scrollbar-thumb { background: var(--navy-3); border-radius: 3px; }

.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 8px;
  color: #b8c9ce;
  font-size: 13.5px; font-weight: 500;
  text-decoration: none;
  user-select: none;
}
.nav-item:hover  { background: var(--navy-2); color: #fff; }
.nav-item.active { background: var(--deep); color: #fff; }
.nav-ico {
  width: 16px;
  display: inline-grid; place-items: center;
  color: var(--mint);
}

.sidebar-footer {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--navy-3);
  display: flex; flex-direction: column; gap: 10px;
}
.sidebar-footer .who {
  font-size: 12px;
  color: #8ea3ab;
  line-height: 1.35;
}
.sidebar-footer .who strong { color: #fff; font-weight: 600; }
.sidebar-footer .sign-out {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--navy-2);
  border: 1px solid var(--navy-3);
  color: #cfdde1;
  font-size: 12.5px; font-weight: 500;
  padding: 7px 10px; border-radius: 8px;
  cursor: pointer;
  font-family: inherit;
}
.sidebar-footer .sign-out:hover { background: var(--navy-3); color: #fff; }

/* Plain block flow rather than flex column. Flex on the grid item was
   creating an implicit formatting context that prevented .topbar's
   position: sticky from anchoring to the viewport on scroll. With block
   flow, .topbar + .view-root stack naturally and sticky behaves. */
.main { min-width: 0; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 28px 14px;
  background: var(--white);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 {
  margin: 0;
  font-size: 22px;
  letter-spacing: -0.2px;
  color: var(--ink);
}
.topbar .subtitle { margin: 2px 0 0; color: var(--muted); font-size: 13px; }
.topbar-right { display: flex; gap: 10px; position: relative; align-items: center; }

.view-root { padding: 24px 28px 48px; }

/* ---------- Layout: anonymous / Devise pages ---------- */

/* Centred-card layout used by sign-in, OTP step, password reset,
   invitation accept. Replaces the sidebar+topbar shell when there's
   no signed-in user. */
.anon-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px 16px;
  background: var(--light-2);
}
.anon-card {
  width: 100%;
  max-width: 420px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px 28px 24px;
  box-shadow: var(--shadow-md);
}
.anon-card h1 {
  margin: 0 0 6px;
  font-size: 22px;
  letter-spacing: -0.3px;
}
.anon-card p {
  color: var(--ink-2);
  font-size: 13.5px;
  margin: 0 0 16px;
}
.anon-card .brand {
  border-bottom: 0;
  padding: 0 0 20px;
  margin-bottom: 0;
}
.anon-card .brand-mark { background: var(--navy); color: #fff; }

/* Action row beneath an .anon-card form -- single button right now,
   the .actions class lets us add a Cancel beside it later without
   re-templating. */
.anon-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}
.anon-actions .btn { flex: 1 0 auto; }

/* Inline checkbox row used for "remember me" type options inside an
   .anon-card. Smaller than a full .field; sits between the last
   field and the submit row. */
.anon-inline-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--ink-2);
  margin: 4px 0 0;
  cursor: pointer;
}

/* Cross-page links beneath the anon-card form (Forgot password / Sign in).
   Sits below the form; muted by default, deep on hover. */
.anon-links {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 12.5px;
}
.anon-links a {
  color: var(--muted);
  text-decoration: none;
  font-weight: 500;
}
.anon-links a:hover { color: var(--deep); text-decoration: underline; }

/* Small muted line beneath a .field input, e.g. "We've pre-filled
   this from your email; please change it." Distinct from per-field
   error text (.field-error) which is danger-coloured. */
.field-help {
  font-size: 11.5px;
  margin-top: 4px;
  line-height: 1.45;
}

/* ---------- 2FA enrolment + backup codes (staff onboarding) -------
 *
 * The 2FA enrolment page shows a QR code beside a "can't scan?"
 * fallback with the secret text. Two-column layout on wide
 * viewports; stacks below 600px. Backup-codes page renders the ten
 * one-time codes in a 2-col monospace grid for legibility / paste-
 * friendliness. */

.otp-enrol-grid {
  display: grid;
  grid-template-columns: minmax(180px, 220px) 1fr;
  gap: 24px;
  align-items: start;
  margin: 8px 0 16px;
}
.otp-enrol-qr svg { width: 100%; height: auto; max-width: 220px; }
.otp-enrol-secret-code {
  display: inline-block;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--light-2);
  font-size: 12.5px;
  color: var(--ink);
  letter-spacing: 0.04em;
  word-break: break-all;
  margin-top: 4px;
}
@media (max-width: 600px) {
  .otp-enrol-grid { grid-template-columns: 1fr; }
}

.backup-codes-list {
  list-style: none;
  padding: 0;
  margin: 16px 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 16px;
}
.backup-codes-list li code {
  display: block;
  padding: 8px 12px;
  background: var(--light-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-align: center;
}
@media (max-width: 480px) {
  .backup-codes-list { grid-template-columns: 1fr; }
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 8px;
  font-size: 13px; font-weight: 600;
  cursor: pointer; border: 1px solid transparent;
  transition: all 120ms ease;
  font-family: inherit;
  text-decoration: none;
}
.btn-primary { background: var(--navy); color: #fff; }
.btn-primary:hover { background: var(--deep); color: #fff; }
.btn-accent  { background: var(--mint); color: var(--navy); }
.btn-accent:hover { background: var(--mint-2); color: var(--navy); }
.btn-ghost   { background: transparent; color: var(--ink-2); border-color: var(--line-2); }
.btn-ghost:hover { background: var(--light-2); }
.btn-danger  { background: #fff; color: var(--danger); border-color: #f1c9c9; }
.btn-danger:hover { background: #fdecec; }
.btn-sm      { padding: 5px 9px; font-size: 12px; }
.btn-xs      { padding: 3px 8px; font-size: 11.5px; }

/* button_to wraps the actual <button> in a <form>; the form should
   not introduce extra layout space. */
form.button_to { display: inline; margin: 0; }

/* ---------- Form fields ---------- */

.input, .select, .textarea {
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--line-2); border-radius: 8px;
  background: #fff; color: var(--ink);
  font-family: inherit; font-size: 13px;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--mint);
  box-shadow: 0 0 0 3px rgba(111, 198, 160, 0.2);
}
.textarea { min-height: 80px; resize: vertical; }

.field { display: flex; flex-direction: column; gap: 4px; }
.field label {
  font-size: 11.5px;
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.field-row   { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.field-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }

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

/* Generic surface container, used for any "panel of related content"
   (deal list rows, supplier-portal form sections, marketplace cards in
   Phase 3.3, etc). Ported from the prototype's .card. */
.card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow-sm);
}
.card-title {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.card-title small {
  color: var(--muted);
  font-weight: 500;
  font-size: 12px;
}

/* Form section header inside a card. Tiny uppercase label that
   visually groups several .field rows. */
.form-section {
  margin-top: 18px;
  margin-bottom: 8px;
  font-size: 11.5px;
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.form-section:first-child { margin-top: 0; }

.form-actions {
  display: flex; gap: 10px;
  margin-top: 22px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

/* ---------- Stats grid (dashboard) ----------
 *
 * Four-up tile row used on the supplier dashboard. Each card has a
 * coloured 3px accent stripe on the left edge to differentiate the
 * metric meaning at a glance (default mint = neutral, navy / deep =
 * informational, warn = needs attention). Ported from the prototype's
 * .stat-grid / .stat-card. */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.stat-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  position: relative;
  overflow: hidden;
}
.stat-card::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--mint);
}
.stat-card.navy::before { background: var(--navy); }
.stat-card.deep::before { background: var(--deep); }
.stat-card.warn::before { background: var(--warn); }

.stat-label {
  font-size: 11.5px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.stat-value {
  font-size: 26px;
  font-weight: 700;
  margin-top: 4px;
  letter-spacing: -0.4px;
  color: var(--ink);
}
.stat-delta {
  font-size: 11.5px;
  margin-top: 4px;
  color: var(--muted);
}

/* A stat card rendered as a link (e.g. "Live on marketplace" clicks
   through to the Live Deals page). Keeps the card visuals, removes
   default link styling, and adds a subtle hover lift to make the
   affordance discoverable. */
.stat-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform 120ms ease, box-shadow 120ms ease;
}
.stat-card-link:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  color: inherit;
}

/* ---------- Choice cards (form-top mode chooser) --------------------
 *
 * Two big segmented buttons used to pick between two mutually-
 * exclusive form modes (e.g. supplier submit: "Yes, include the
 * ASIN" / "No, just the product details"). The active card uses the
 * deep accent colour so the choice is obvious at a glance; inactive
 * cards stay neutral white. Ported from the prototype's inline
 * data-submit-mode buttons (docs/vantage-portal.html ~20718). */

.choice-cards {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.choice-card {
  flex: 1 1 240px;
  min-width: 240px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
  border-radius: 8px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  text-align: left;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.choice-card:hover { border-color: var(--mint-3); }
.choice-card.active {
  background: var(--deep);
  color: #fff;
  border-color: var(--deep);
}
.choice-card-title { font-weight: 600; }
.choice-card-sub {
  font-weight: 400;
  font-size: 11px;
  opacity: 0.85;
  margin-top: 2px;
}

/* ---------- Sub-tabs (single | bulk selector under chooser) --------- */

.sub-tabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.sub-tab {
  padding: 7px 16px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
  border-radius: 7px;
  cursor: pointer;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
}
.sub-tab.active {
  background: var(--deep);
  color: #fff;
  border-color: var(--deep);
}
/* Coming-soon variant: rendered as disabled so the user can see the
   eventual two-path UI without it pretending to work. */
.sub-tab:disabled,
.sub-tab[disabled] {
  cursor: not-allowed;
  opacity: 0.55;
}

/* ---------- Form-mode banner (above form sections) -----------------
 *
 * Wide horizontal info strip at the top of a form, used to explain
 * the implication of the chosen mode. Two variants: mint for
 * "neutral / supportive" mode (no-ASIN: we handle the heavy lifting),
 * gold for "elevated / scored" mode (with-ASIN: deal goes through
 * auto-scoring). Ported from the prototype's renderSingleDealForm
 * inline-styled blocks (docs/vantage-portal.html ~20244-20253). */

.form-mode-banner {
  padding: 10px 14px;
  border-radius: 6px;
  margin-bottom: 18px;
  border-left: 3px solid transparent;
}
.form-mode-banner.mint {
  background: var(--light);
  border-left-color: var(--mint);
}
.form-mode-banner.gold {
  background: var(--gold-soft);
  border-left-color: var(--gold);
}
.form-mode-banner-title {
  font-weight: 600;
  font-size: 12.5px;
  margin-bottom: 4px;
}
.form-mode-banner.mint .form-mode-banner-title { color: var(--deep); }
.form-mode-banner.gold .form-mode-banner-title { color: var(--gold-deep); }
.form-mode-banner-body {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}

/* ---------- Info card (small inline explainer block) ---------------
 *
 * Tiny help block used inside a .field slot in place of an input
 * (e.g. "No ASIN needed: our team matches the product..." in
 * no-ASIN mode). Less heavy than form-mode-banner. */

.info-card {
  font-size: 11.5px;
  line-height: 1.5;
  padding: 8px 12px;
  border-radius: 6px;
  color: var(--muted);
}
.info-card.mint { background: var(--light); }

/* ---------- Form label adornments ---------------------------------- */

/* The asterisk shown beside required labels. Keeps the required
   indicator separate from the label text so the visual weight is
   tunable in one place. */
.required-marker {
  color: var(--danger);
  font-weight: 700;
}
/* Muted parenthetical hint inside a label, e.g. "Case size (units/case) *".
   Smaller, non-uppercase, regular weight -- visually subordinate to
   the label's primary text. */
.label-sub {
  font-weight: 400;
  font-size: 11px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
}

/* ---------- Welcome banner + welcome card (supplier dashboard) ------
 *
 * lock-banner: full-width navy-to-deep gradient strip used at the top
 * of role dashboards. Ported from the prototype's .lock-banner; the
 * prototype also has a .priority variant for gold-trim Priority client
 * surfaces -- not ported yet because we don't render Priority client
 * pages in 3.1. */

.lock-banner {
  background: linear-gradient(135deg, var(--navy) 0%, var(--deep) 100%);
  color: #fff;
  padding: 10px 14px;
  border-radius: 8px;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 1.4;
}
.lock-banner strong { font-weight: 700; }

/* Chip variant for use on dark surfaces (lock-banner, hero strips).
   Default .chip is designed for light backgrounds; this one inverts.
   Chained selector (.chip.chip-on-dark) so it beats .chip on specificity
   regardless of stylesheet rule order. */
.chip.chip-on-dark {
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  border: none;
}

/* Greeting card sitting under the welcome banner. The padding +
   spacing values are tuned to feel like a single conversational unit
   (heading + paragraph + CTAs + footnote), not a generic content card. */
.welcome-card {
  padding: 18px 20px;
}
.welcome-greeting {
  margin: 0 0 6px;
  font-size: 20px;
  letter-spacing: -0.2px;
}
.welcome-copy {
  font-size: 13.5px;
  margin: 0;
  line-height: 1.55;
}
.welcome-actions {
  margin-top: 18px;
  flex-wrap: wrap;
}
.welcome-subnote {
  font-size: 11.5px;
  margin-top: 8px;
  line-height: 1.5;
}

/* "How submissions work" 4-step explainer (supplier dashboard). Each
   step is a heading + a muted body paragraph; this rule styles the
   step heading consistently across the four cells. */
.how-step-title {
  font-weight: 600;
  color: var(--deep);
  font-size: 13.5px;
  margin-bottom: 4px;
}
.how-step-body {
  font-size: 12.5px;
  line-height: 1.55;
}

/* ---------- Status chips ----------
 *
 * Small inline pill for Deal#status, Order#status, etc. The base .chip
 * is muted gray; the variants apply meaning. Each label still includes
 * the text status -- the colour is a visual reinforcement, not the
 * primary signal (accessibility). */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  background: var(--light-2);
  color: var(--ink-2);
  border: 1px solid var(--line);
  white-space: nowrap;
}
.chip-ok      { background: rgba(47, 158, 108, 0.10); color: #196b46; border-color: rgba(47, 158, 108, 0.25); }
.chip-warn    { background: rgba(226, 167, 59, 0.12); color: #8a5a14; border-color: rgba(226, 167, 59, 0.3); }
.chip-danger  { background: rgba(216, 88, 88, 0.10);  color: #8a2a2a; border-color: rgba(216, 88, 88, 0.3); }
.chip-info    { background: rgba(17, 42, 54, 0.06);   color: var(--navy); border-color: rgba(17, 42, 54, 0.18); }
.chip-navy    { background: #e3ebef;                       color: var(--navy); border-color: rgba(17, 42, 54, 0.18); }
.chip-priority {
  background: var(--gold-soft);
  color: var(--gold-deep);
  border-color: rgba(212, 175, 90, 0.45);
}

/* ---------- Deal-list rows (supplier dashboard) ---------- */

.deal-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 18px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  align-items: start;
  box-shadow: var(--shadow-sm);
}
.deal-row + .deal-row { margin-top: 10px; }
.deal-row .title    { font-weight: 600; color: var(--ink); }
.deal-row .meta     { color: var(--muted); font-size: 12.5px; margin-top: 3px; }
.deal-row .meta strong { color: var(--ink-2); font-weight: 600; }
.deal-row .right    { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }

/* Empty-state card for the supplier dashboard when no deals exist. */
.empty-state {
  border: 1px dashed var(--line-2);
  border-radius: var(--radius);
  padding: 32px 24px;
  text-align: center;
  background: var(--light-2);
}
.empty-state h2 {
  margin: 0 0 6px;
  font-size: 17px;
  color: var(--ink);
}
.empty-state p {
  margin: 0 0 16px;
  color: var(--ink-2);
  font-size: 13.5px;
}

/* ---------- Two-column panel grid (Live Deals cards) ---------------
 *
 * 2-col grid used by the supplier's Live Deals page; ported from the
 * prototype's .panel-grid-2 (~vantage-portal.html:268). Collapses to
 * one column at narrow widths so cards don't squish below readable
 * width. Width-based collapse is fine here even though we don't ship
 * a mobile layout overall: this is an intra-page reflow, not a shell-
 * level layout decision. */

.panel-grid-2 {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 16px;
}
.panel-grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
}
@media (max-width: 900px) {
  .panel-grid-2 { grid-template-columns: 1fr; }
  .panel-grid-3 { grid-template-columns: 1fr; }
}

/* ---------- Progress bars (stock commitment, etc.) -----------------
 *
 * Thin pill bar used on the Live Deals cards to show the paid + held
 * stock split against total units. Two layered .progress-bar children
 * inside one .progress track: the committed bar (paid + held) sits
 * underneath at lighter opacity; the paid bar sits on top at full
 * opacity. Width is set inline per deal. Colour variant changes with
 * commitment rate (mint < 50%, deep 50-79%, warn >= 80%). */

.progress {
  height: 8px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
  position: relative;
}
.progress-bar {
  height: 100%;
  background: var(--mint);
  transition: width 200ms ease;
  position: absolute;
  top: 0;
  left: 0;
}
.progress-bar-mint { background: var(--mint); }
.progress-bar-deep { background: var(--deep); }
.progress-bar-warn { background: var(--warn); }

/* The "committed" layer sits under the "paid" layer at reduced
   opacity so the supplier sees the paid-vs-reserved split as a
   single bar with two intensities rather than two separate bars. */
.progress-bar-committed { opacity: 0.45; z-index: 0; }
.progress-bar-paid      { opacity: 1;    z-index: 1; }

/* ---------- Attention banner (above list views) --------------------
 *
 * Compact "N need your attention" strip rendered above the supplier
 * Live Deals / My Submissions lists when something changed since
 * the supplier last visited. Mirrors the prototype's
 * renderAttentionBanner (~vantage-portal.html:5587). */

.attention-banner {
  background: var(--light);
  border: 1px solid var(--mint);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.attention-banner-dot {
  font-size: 18px;
  line-height: 1;
  color: var(--deep);
  font-weight: 300;
  flex-shrink: 0;
  margin-top: 1px;
}
.attention-banner-body { flex: 1; min-width: 0; }
.attention-banner-title {
  font-weight: 600;
  font-size: 13px;
  color: var(--ink);
}
.attention-banner-sub {
  font-size: 12px;
  margin-top: 2px;
  line-height: 1.45;
}
.attention-banner-hint {
  font-size: 11px;
  margin-left: 6px;
  color: var(--muted);
}

/* ---------- Tables -------------------------------------------------
 *
 * Base .table styling: uppercase muted headers on a light-wash
 * background, generous cell padding, single-pixel row separators,
 * hover-tint on body rows. Used by the supplier My Submissions
 * table (and any future list view). Ported verbatim from the
 * prototype (~vantage-portal.html:273-278) -- this got missed when
 * the table view shipped in 3.1.a.3 and only the attention-row
 * extension rules below were added; the headers were rendering
 * with browser defaults. */

.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th, .table td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  /* Centre vertically. Default HTML <td> alignment is `baseline`,
     which top-aligns single-line cells (chips, dates, money) against
     multi-line cells (title + muted subtitle). Looks like the chips
     are hovering at the top of the row. `middle` keeps each column's
     content visually centred against the tallest cell in the row. */
  vertical-align: middle;
}
.table th {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
  background: var(--light-2);
}
.table tbody tr:hover { background: var(--light-2); }
.table tbody tr.clickable { cursor: pointer; }
.table td .muted { color: var(--muted); font-size: 12px; }
/* Right-align utility for table cells (e.g. numeric columns).
   More specific than the generic .right utility so it beats the
   .table td text-align: left default. */
.table th.right, .table td.right { text-align: right; }

/* ---------- Attention-row highlighting -----------------------------
 *
 * Subtle mint-tinted background + 3px left border on rows / cards
 * that have updated since the user last viewed the list. Two flavors:
 * .table tr.attention-row for table rows, and .attention-row on a
 * .card / stock-card for the Live Deals grid. Ported from the
 * prototype (~vantage-portal.html:2659-2671). */

.table tr.attention-row > td {
  background: rgba(111, 198, 160, 0.07);
  box-shadow: inset 3px 0 0 0 var(--mint);
}
.table tr.attention-row:hover > td {
  background: rgba(111, 198, 160, 0.12);
}
.card.attention-row,
.stock-card.attention-row {
  border-left: 3px solid var(--mint);
  background: rgba(111, 198, 160, 0.05);
}

/* ---------- Table-in-card wrapper ----------------------------------
 *
 * A .table laid inside a .card needs the card's padding to be 0 (so
 * the table edges align with the card's outline) and overflow:hidden
 * so the table's first / last row corners are clipped by the card's
 * border-radius. */

.card.table-card {
  padding: 0;
  overflow: hidden;
}

/* ---------- Live Deals page (supplier_live_deals#index) ------------ */

.live-deals-header        { gap: 16px; align-items: flex-start; }
.live-deals-title         { margin: 0; font-size: 18px; }
.live-deals-count         { font-weight: 500; font-size: 13px; }
.live-deals-subtitle      { font-size: 12.5px; }
.live-deals-scoreboard    { text-align: right; }
.live-deals-committed-value {
  font-size: 18px;
  font-weight: 700;
  color: var(--deep);
}
.live-deals-scoreboard-sub { font-size: 11.5px; }
.live-deals-footnote {
  font-size: 11.5px;
  line-height: 1.55;
  max-width: 780px;
}

/* ---------- Stock card (one deal on Live Deals grid) --------------- */

.stock-card                   { padding: 16px 18px; }
.stock-card-head              { margin-bottom: 8px; }
.stock-card-ref               { font-size: 11px; font-weight: 600; }
.stock-card-title {
  font-weight: 600;
  font-size: 14px;
  line-height: 1.35;
  color: var(--ink);
  margin-bottom: 4px;
}
.stock-card-ids               { font-size: 11.5px; margin-bottom: 14px; }
.stock-card-movement          { margin-bottom: 14px; }
.stock-card-movement-head     { margin-bottom: 6px; }
.stock-card-committed-label   { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.stock-card-committed-pct     { font-size: 12.5px; font-weight: 700; }
.stock-card-committed-pct.stock-card-bar-mint  { color: var(--mint-2); }
.stock-card-committed-pct.stock-card-bar-deep  { color: var(--deep); }
.stock-card-committed-pct.stock-card-bar-warn  { color: var(--warn); }
.stock-card-progress          { margin: 0; }
.stock-card-breakdown {
  font-size: 11px;
  margin-top: 6px;
}
.stock-card-terms {
  font-size: 11.5px;
  line-height: 1.6;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.stock-card-terms-strong { color: var(--ink); }
.stock-card-posted       { margin-top: 3px; }

/* ---------- My Submissions page (supplier_my_submissions#index) ---- */

.submissions-header        { gap: 16px; align-items: flex-start; }
.submissions-title         { margin: 0; font-size: 18px; }
.submissions-count         { font-weight: 500; font-size: 13px; }
.submissions-subtitle      { font-size: 12.5px; }
.submissions-product-title { font-weight: 600; }
.submissions-product-sub   { font-size: 11.5px; }
.submissions-footnote {
  font-size: 11.5px;
  line-height: 1.55;
}

/* ---------- Error summary ----------
 *
 * Rendered at the top of forms when the model fails validation. Lists
 * the offending fields so the user doesn't have to scan the form for
 * the inline error message. */
.error-summary {
  background: #fdecec;
  border: 1px solid #f1c9c9;
  border-left: 4px solid var(--danger);
  border-radius: 10px;
  padding: 12px 16px;
  margin-bottom: 16px;
}
.error-summary h3 {
  margin: 0 0 6px;
  font-size: 13.5px;
  color: #8a2a2a;
}
.error-summary ul { margin: 0; padding-left: 20px; color: #8a2a2a; font-size: 13px; }
.error-summary li { margin: 2px 0; }

/* Per-field error message (under the input). */
.field-error {
  font-size: 11.5px;
  color: var(--danger);
  margin-top: 2px;
}

/* ---------- Flash messages ---------- */

/* Replaces the prototype's toast system. Devise renders notice + alert
   via the layout; toasts go via Stimulus once we have a real broadcast
   channel (Phase 4). For Phase 3, plain inline banners. */
.flash {
  margin-bottom: 16px;
  padding: 11px 14px 11px 16px;
  border-radius: 10px;
  font-size: 13.5px;
  font-weight: 500;
  border: 1px solid transparent;
  border-left-width: 4px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.flash::before {
  font-weight: 700;
  font-size: 14px;
  line-height: 1;
}
.flash-notice {
  background: var(--light-2);
  color: var(--deep-2);
  border-color: var(--mint-3);
  border-left-color: var(--mint);
}
.flash-notice::before { content: "\2713"; color: var(--deep); }
.flash-alert {
  background: #fdecec;
  color: #8a2a2a;
  border-color: #f1c9c9;
  border-left-color: var(--danger);
}
.flash-alert::before  { content: "\26A0"; color: var(--danger); }

/* ---------- Staff orders workflow --------------------------------- *
 *
 * Index page: KPI cards (reuses .stat-grid), status-pill filter row,
 * search form. Show page: allocation card + shared order-timeline +
 * transition buttons + inline transition forms.
 */

/* Status-pill filter row (above the orders table). Same visual
 * primitive as the marketplace category pills but with a count
 * badge attached to each pill. */
.status-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px 4px 12px;
  border-radius: 14px;
  font-size: 12.5px;
  background: var(--light-2);
  color: var(--ink-2);
  text-decoration: none;
  border: 1px solid var(--line);
  transition: background-color 0.12s, border-color 0.12s, color 0.12s;
}

.status-pill:hover {
  background: #fff;
  border-color: var(--navy);
  color: var(--navy);
}

.status-pill.active {
  background: var(--navy);
  color: #fff;
  border-color: var(--navy);
}

.status-pill .pill-count {
  font-size: 10.5px;
  font-weight: 700;
  background: rgba(17, 42, 54, 0.10);
  color: var(--ink);
  padding: 1px 6px;
  border-radius: 8px;
  min-width: 16px;
  text-align: center;
}

.status-pill.active .pill-count {
  background: rgba(255, 255, 255, 0.20);
  color: #fff;
}

.status-pill.muted-pill {
  color: var(--muted);
}

/* Search form sits in its own card just above the table. */
.orders-search-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Shared order-timeline partial (used by staff_orders/show and
 * client_orders/show in 3.4.c). Two-column row layout: label
 * left, value right. Tight vertical rhythm. */
.order-timeline .timeline-row {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 12px;
  padding: 6px 0;
  align-items: baseline;
}

.order-timeline .timeline-row + .timeline-row {
  border-top: 1px solid var(--line);
}

.order-timeline .timeline-label {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.order-timeline .timeline-value {
  font-size: 13px;
  color: var(--ink);
}

/* Inline transition form (the <details> collapsible on the staff
 * order workflow card). Open state shows the form below the
 * trigger button. */
.transition-form {
  display: inline-block;
  margin-right: 8px;
}

.transition-form > summary {
  list-style: none;
  cursor: pointer;
  display: inline-block;
}

.transition-form > summary::-webkit-details-marker {
  display: none;
}

.transition-form[open] {
  display: block;
  margin-top: 0;
  padding-top: 12px;
}

.transition-form[open] > summary {
  margin-bottom: 12px;
}

.transition-form[open] form {
  max-width: 520px;
  padding: 12px;
  background: var(--light-2);
  border-radius: 6px;
}

/* ---------- Client orders (My Orders) ------------------------------ *
 *
 * Index list + show detail + cancel button. Mostly leans on existing
 * stat-grid + table-card + card primitives; just a couple of
 * affordances unique to the orders surface.
 */

/* Deal-name link in the order table row -- standard table cell uses
 * the default link blue, which feels heavy alongside the muted
 * supporting text. Inherit colour + carry a subtle hover underline. */
.deal-link {
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
}

.deal-link:hover {
  color: var(--navy);
  text-decoration: underline;
}

/* The stats bar above the table reuses .stat-grid; .order-stats-bar
 * exists as a hook for any future overrides specific to the client
 * view (no per-card tweaks today). */

/* ---------- Client marketplace (Deal Flow) ------------------------- *
 *
 * Card grid + per-card layout for the client-facing deal browse
 * (ClientMarketplaceController#index). Ports the prototype's
 * VIEWS.marketplace + renderMarketplaceCard (~vantage-portal.html:
 * 8348 / 8956). Card width tuned for 3-up on a typical staff/
 * client laptop, dropping to 2-up below ~1200px and 1-up below
 * ~800px (which is a degraded-but-usable target, not a designed
 * mobile experience -- v1 is desktop-first per the migration plan).
 */

.marketplace-filters {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.marketplace-search-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.category-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.category-pill {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 14px;
  font-size: 12px;
  background: var(--light-2);
  color: var(--ink-2);
  text-decoration: none;
  border: 1px solid var(--line);
  transition: background-color 0.12s, border-color 0.12s;
}

.category-pill:hover {
  background: #fff;
  border-color: var(--navy);
  color: var(--navy);
}

.category-pill.active {
  background: var(--navy);
  color: #fff;
  border-color: var(--navy);
}

.marketplace-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-top: 10px;
}

@media (max-width: 1200px) {
  .marketplace-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 800px) {
  .marketplace-grid { grid-template-columns: 1fr; }
}

.market-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px 16px;
  gap: 12px;
  box-shadow: 0 1px 0 rgba(17, 42, 54, 0.04);
}

.market-card.is-sold-out {
  opacity: 0.65;
}

.market-card-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.market-card-meta {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 2px;
}

.market-card-title {
  font-size: 14.5px;
  font-weight: 700;
  margin: 0;
  line-height: 1.35;
  color: var(--ink);
}

.market-card-supplier {
  font-size: 12px;
}

.market-card-econ {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px 14px;
  padding: 10px 12px;
  background: var(--light-2);
  border-radius: 6px;
}

.econ-cell {
  display: flex;
  flex-direction: column;
}

.econ-label {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.econ-value {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}

.market-card-stock {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.stock-line {
  font-size: 13px;
}

.stock-bar {
  position: relative;
  height: 6px;
  background: var(--light-2);
  border-radius: 3px;
  overflow: hidden;
}

.stock-bar-paid,
.stock-bar-held {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
}

.stock-bar-paid {
  background: var(--navy);
  z-index: 2;
}

.stock-bar-held {
  background: rgba(17, 42, 54, 0.25);
  z-index: 1;
}

.stock-meta {
  font-size: 11.5px;
}

.market-card-cta {
  /* Flex column so the disabled-reserve button can sit above an
   * explainer note (visible-text instead of a flaky native
   * tooltip). align-items: stretch (the flex column default)
   * makes the button take full width. */
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 4px;
}

.market-card-cta .btn {
  text-align: center;
}

.market-card-cta-note {
  font-size: 11px;
  text-align: center;
}

.btn.disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

/* ---------- Priority banner (Access viewers only) ----------------- */

.priority-banner {
  border-left: 3px solid var(--gold);
  background: #fdf7e7;
  padding: 14px 16px;
}

.priority-banner-body {
  display: flex;
  align-items: center;
  gap: 12px;
}

.priority-banner-icon {
  font-size: 22px;
  color: var(--gold);
  flex: 0 0 auto;
}

.priority-banner-text {
  flex: 1;
  font-size: 13px;
  color: var(--ink);
}

.priority-banner-cta {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* ---------- Kanban (staff Deals Pipeline) -------------------------- *
 *
 * Six-column horizontal flow used by the staff deal-review workflow.
 * Mirrors the prototype's kanban (~docs/vantage-portal.html:12527,
 * .kanban / .kanban-col / .kanban-card). Cards are link_to wrappers
 * (whole-card click into review). Column width tuned for desktop
 * staff use -- narrower than the marketplace cards because we want
 * all six visible at typical staff laptop widths without horizontal
 * scroll.
 */

.kanban {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
  margin-top: 8px;
}

.kanban-col {
  background: var(--light-2);
  border-radius: 8px;
  padding: 10px;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.kanban-col-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  color: var(--ink-2);
  padding: 4px 6px 8px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 2px;
}

.kanban-col-count {
  background: var(--navy);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 10px;
  min-width: 18px;
  text-align: center;
}

.kanban-col-empty {
  font-size: 12px;
  color: var(--muted);
  font-style: italic;
  padding: 14px 6px;
  text-align: center;
}

.kanban-card {
  display: block;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px 12px;
  text-decoration: none;
  color: inherit;
  box-shadow: 0 1px 0 rgba(17, 42, 54, 0.04);
  transition: border-color 0.12s ease, box-shadow 0.12s ease,
              transform 0.06s ease;
}

.kanban-card:hover {
  border-color: var(--navy);
  box-shadow: 0 2px 6px rgba(17, 42, 54, 0.08);
}

.kanban-card:active {
  transform: translateY(1px);
}

.kanban-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 6px;
  /* Long category chips (e.g. "Stationery & Office Supplies") can
   * exceed the card width; allow the chip to wrap to its own row
   * rather than overflow the card boundary. */
  flex-wrap: wrap;
  row-gap: 4px;
}

/* Cap the chip width so even a single wrapped chip can't exceed
 * the card's content box; allow internal text to wrap if the
 * category name is very long. */
.kanban-card-top .chip {
  max-width: 100%;
  white-space: normal;
  line-height: 1.3;
}

.kanban-card-ref {
  font-size: 10.5px;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.03em;
}

.kanban-card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.35;
  margin-bottom: 6px;
  /* Two-line clamp so taller titles don't push cards out of alignment */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.kanban-card-meta {
  font-size: 11.5px;
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}

/* Narrower kanban inside the staff content column -- below ~1280px
 * the six columns crowd; let them scroll horizontally rather than
 * stacking vertically (stacking would defeat the visual "pipeline"). */
@media (max-width: 1280px) {
  .kanban {
    grid-template-columns: repeat(6, minmax(180px, 1fr));
    overflow-x: auto;
    padding-bottom: 6px;
  }
}

/* ---------- Reject affordance (staff deal review) ----------------- *
 *
 * <details>/<summary> based collapsible. The summary doubles as the
 * trigger button (Reject this deal…); opening exposes a textarea +
 * submit form. Styled to look attached to the card it sits inside.
 */

.reject-affordance {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.reject-affordance > summary {
  list-style: none;
  cursor: pointer;
}

.reject-affordance > summary::-webkit-details-marker {
  display: none;
}

/* ---------- Utility ---------- */

.row         { display: flex; align-items: center; gap: 8px; }
.row-between { display: flex; align-items: center; justify-content: space-between; }
.gap-sm { gap: 8px; }   .gap-md { gap: 14px; }   .gap-lg { gap: 20px; }
.mt-sm { margin-top: 10px; }   .mt-md { margin-top: 18px; }   .mt-lg { margin-top: 28px; }
.mb-sm { margin-bottom: 10px; } .mb-md { margin-bottom: 18px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.muted  { color: var(--muted); }
.mono   { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.right  { text-align: right; }
.center { text-align: center; }
.divider { height: 1px; background: var(--line); margin: 14px 0; }
.scroll  { overflow: auto; }
.hidden  { display: none !important; }

/* ---------- Responsive ----------
 *
 * v1 is a desktop / laptop product (Section 3 of the migration plan).
 * Mobile is not a target -- the workflows we're building are sit-down
 * operations work, not on-the-go.
 *
 * We deliberately do NOT collapse the sidebar at narrow widths. The
 * earlier media query that did this looked broken at ~800px because
 * a navy strip stacked above the content read as "half-done hamburger
 * menu" rather than "intentional mobile layout". Better to let narrow
 * viewports show a horizontally-scrollable desktop layout (visually
 * imperfect but structurally intact) than to ship a half-implemented
 * mobile mode. If a mobile experience becomes a real requirement in
 * Phase 4+, build it deliberately rather than via a degrade-down rule. */
