/* vantage-buttons.css — shared Vantage app button system */
/*
 * vantage-buttons.css — Shared button system for Vantage application pages.
 *
 * The legacy size rules remain global while pages migrate. Complete visual
 * variants are opt-in through body.v-ui, which prevents changes to marketing
 * pages and unmigrated application pages.
 *
 * Size props use !important so the canonical compact size wins over any
 * higher-specificity local rule. Compact is the default everywhere; a page
 * only escapes it by NOT linking this sheet (e.g. marketing CTAs).
 *
 * Load on every app page, ideally just before </head> (after the page's own
 * inline <style>):
 *     <link rel="stylesheet" href="/vantage-buttons.css">
 *
 * Canonical size (matches the proposal-builder top-row buttons):
 *     padding: 6px 14px;  font-size: 11px;   →  ~27px tall
 *
 * Symbols inside buttons must be SVG (vantage-icons.js placeholders), never
 * emoji:
 *     <button class="btn-primary"><span data-vi-icon="camera" data-vi-size="14"></span> Import</button>
 */

/* ── Box-model + canonical size (color-agnostic) ─────────────────────────── */
/* One compact size everywhere. .btn-sm is intentionally folded in at the SAME
   size — it was a smaller tier on some pages, but "compact" is now the single
   default (matches the proposal-builder top-row buttons). */
.btn,
.btn-primary,
.btn-secondary,
.btn-outline,
.btn-gold,
.btn-ghost,
.btn-danger,
.btn-sm,
/* App-specific labeled action buttons (no unified .btn system in this app) */
.btn-submit,
.btn-add-pid,
.btn-add-project,
.btn-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 6px 14px !important;
  font-size: 11px !important;
  line-height: 1.4 !important;
  white-space: nowrap;
}

/* ── Opt-in larger size (rare — prominent CTAs) ──────────────────────────── */
.btn-lg { padding: 9px 20px !important; font-size: 12px !important; }

/* On converted (v-ui) pages EVERY legacy-named button rides the same height
   token as the canonical .v-btn-* roles — one lever, one height (2026-07-25).
   The 6px legacy padding above still applies horizontally; vertical rhythm
   comes from the token so 27/29/35px stragglers cannot exist. */
body.v-ui :is(.btn, .btn-primary, .btn-secondary, .btn-outline, .btn-gold,
  .btn-ghost, .btn-danger, .btn-sm, .btn-submit,   .btn-add-project, .btn-back) {
  box-sizing: border-box;
  min-height: var(--v-control-height, 32px);
  height: var(--v-control-height, 32px);
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* Dashboard/page-hero actions share the same control-height token as forms.
   Width is the .v-action-grid contract below; only vertical rhythm is canonical
   here. On touch/mobile the token rises from 36px to 42px.
   (`.dash-action-btn` was dropped 2026-08-03 — the class is retired, banned by
   test-shared-app-shell.js:66, and no page emitted it any more.) */
body.v-ui .v-hero-action,
body.v-ui .tdash-action-btn,
body.v-ui .page-hero .btn-back,
body.v-ui .page-hero #btn-view-proposal {
  box-sizing: border-box;
  height: var(--v-control-height, 36px) !important;
  min-height: var(--v-control-height, 36px) !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* ── Hero action grid — ONE width for every labeled action (2026-08-02) ─────
   The project and ticket dashboards stack their hero actions as labeled rows
   (General / Project Core / VTools). Flex-wrapped rows size each button to its
   own label, so the cluster reads as a ragged stack instead of a grid, and the
   two pages had drifted to different answers (admin-service-finance pinned a
   page-local width:120px, admin-projects pinned nothing). This is the single
   width contract both consume.

   A track is never allowed to clip a label: the token is the FLOOR, and a
   track grows past it if the tenant's font needs the room (--font is tenant
   configurable, so no fixed pixel width is safe on its own). Below the point
   where the hero stacks, the row becomes a wrapping equal-column grid so a
   five-action row cannot push a phone sideways.

   The floor came down from 150px to 118px (2026-08-11): at 150px a one-word
   action like "Files" carried ~60px of dead track, and the cluster read as a
   slab. 118px still holds the columns in line for the short labels while the
   long ones ("Vantage Tips" ≈ 125px at the 13px control scale) simply grow
   past it, exactly as the floor contract intends. */
.v-action-grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(var(--v-action-btn-w, 118px), max-content);
  gap: 6px;
}
.v-action-grid > * { width: 100%; }
@media (max-width: 1180px) {
  .v-action-grid {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fit, minmax(var(--v-action-btn-w, 118px), max-content));
  }
}

/* Square icon-only button (no label) */
.btn-icon { padding: 6px !important; gap: 0; }

/* ── Inline SVG icons (from vantage-icons.js) sit flush with the label ────── */
.btn svg,
.btn-primary svg,
.btn-secondary svg,
.btn-outline svg,
.btn-gold svg,
.btn-ghost svg,
.btn-danger svg,
.btn-submit svg { flex-shrink: 0; }

/* ── Complete visual system (opt-in per migrated app page) ───────────────── */
body.v-ui .btn,
body.v-ui .btn-primary,
body.v-ui .btn-secondary,
body.v-ui .btn-outline,
body.v-ui .btn-gold,
body.v-ui .btn-ghost,
body.v-ui .btn-danger,
body.v-ui .btn-submit,
body.v-ui .btn-add-pid,
body.v-ui .btn-add-project,
body.v-ui .btn-back {
  border: 1px solid transparent;
  border-radius: 6px;
  font-family: var(--font);
  font-weight: 500;
  letter-spacing: 1.2px;
  text-decoration: none;
  text-transform: none;
  cursor: pointer;
  transition: background 0.16s, border-color 0.16s, color 0.16s, box-shadow 0.16s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
}

body.v-ui .btn-primary,
body.v-ui .btn-gold,
body.v-ui .btn-submit {
  border-color: var(--gold);
  background: var(--gold);
  color: var(--bg);
}

body.v-ui .btn-primary:hover,
body.v-ui .btn-gold:hover,
body.v-ui .btn-submit:hover {
  border-color: var(--gold-light);
  background: var(--gold-light);
  color: var(--bg);
  box-shadow: 0 2px 12px rgba(var(--gold-rgb), 0.22);
}

body.v-ui .btn-secondary,
body.v-ui .btn-outline,
body.v-ui .btn-add-project,
body.v-ui .btn-back {
  border-color: var(--gold-dim);
  background: transparent;
  color: var(--gold-light);
}

body.v-ui .btn-secondary:hover,
body.v-ui .btn-outline:hover,
body.v-ui .btn-add-project:hover,
body.v-ui .btn-back:hover {
  border-color: var(--gold);
  background: rgba(var(--gold-rgb), 0.07);
  color: var(--gold);
  box-shadow: 0 2px 12px rgba(var(--gold-rgb), 0.18);
}

body.v-ui .btn-ghost,
body.v-ui .btn-add-pid {
  border-color: var(--gold-dim);
  background: rgba(var(--gold-rgb), 0.04);
  color: var(--gold-light);
}

body.v-ui .btn-add-pid {
  width: 100%;
  margin-bottom: 20px;
  border-style: dashed;
}

body.v-ui .btn-ghost:hover,
body.v-ui .btn-add-pid:hover {
  border-color: var(--gold);
  background: rgba(var(--gold-rgb), 0.09);
  color: var(--gold);
  box-shadow: 0 2px 12px rgba(var(--gold-rgb), 0.18);
}

body.v-ui .btn-danger {
  border-color: var(--red);
  background: transparent;
  color: var(--red);
}

body.v-ui .btn-danger:hover {
  background: color-mix(in srgb, var(--red) 10%, transparent);
  box-shadow: 0 2px 12px color-mix(in srgb, var(--red) 24%, transparent);
}

body.v-ui .btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s, background 0.16s;
}

body.v-ui .btn-icon:hover,
body.v-ui .btn-icon:focus-visible {
  border-color: var(--gold-dim);
  background: rgba(var(--gold-rgb), 0.06);
  color: var(--gold);
  outline: none;
}

body.v-ui .btn:active,
body.v-ui .btn-primary:active,
body.v-ui .btn-secondary:active,
body.v-ui .btn-outline:active,
body.v-ui .btn-gold:active,
body.v-ui .btn-ghost:active,
body.v-ui .btn-danger:active,
body.v-ui .btn-submit:active,
body.v-ui .btn-add-pid:active,
body.v-ui .btn-add-project:active,
body.v-ui .btn-back:active { transform: translateY(1px); }

body.v-ui .btn:focus-visible,
body.v-ui .btn-primary:focus-visible,
body.v-ui .btn-secondary:focus-visible,
body.v-ui .btn-outline:focus-visible,
body.v-ui .btn-gold:focus-visible,
body.v-ui .btn-ghost:focus-visible,
body.v-ui .btn-danger:focus-visible,
body.v-ui .btn-submit:focus-visible,
body.v-ui .btn-add-pid:focus-visible,
body.v-ui .btn-add-project:focus-visible,
body.v-ui .btn-back:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

body.v-ui button:disabled,
body.v-ui .btn.disabled,
body.v-ui [class*="btn-"][aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.48;
  pointer-events: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Canonical button primitives — UNGATED (2026-07-25).

   .v-btn-primary / .v-btn-secondary / .v-btn-danger are the three roles;
   .v-btn-compact and .v-btn-icon are modifiers. No outline or ghost family.

   These are standalone so any page can adopt canonical buttons WITHOUT taking
   the whole body.v-ui.v-face cascade — component-by-component opt-in. On a
   facelift page the --vf-* variables resolve and these render identically to
   the gated copies in vantage-facelift.css (which win on specificity and are
   deleted when the rollout completes). Elsewhere they fall back to the tenant
   brand variables that vantage-brand.js provides on every app page.

   Sizes: 32px standard (var --v-control-height), 28px compact. Approved
   2026-07-25 so buttons sit comfortably inline in modals and toolbars.
   ═══════════════════════════════════════════════════════════════════════════ */
.v-btn-primary,
.v-btn-secondary,
.v-btn-danger,
.v-btn-compact {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: var(--v-control-height, 32px);
  height: var(--v-control-height, 32px);
  padding: 0 14px;
  border-radius: var(--vf-r-sm, 8px);
  font-family: var(--font);
  font-size: 13px !important;
  font-weight: 500 !important;
  letter-spacing: 0.01em;
  text-transform: none;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.13s, border-color 0.13s, color 0.13s,
    transform 0.06s, box-shadow 0.13s;
}
:is(.v-btn-primary, .v-btn-secondary, .v-btn-danger):active {
  transform: translateY(1px);
}
:is(.v-btn-primary, .v-btn-secondary, .v-btn-danger):disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.v-btn-primary {
  border: 1px solid var(--vf-accent, var(--gold));
  background: var(--vf-accent, var(--gold));
  color: var(--vf-on-accent, var(--bg));
}
.v-btn-primary:hover {
  background: color-mix(in srgb, var(--vf-accent, var(--gold)) 88%, var(--vf-text, var(--gold-light)));
  border-color: color-mix(in srgb, var(--vf-accent, var(--gold)) 88%, var(--vf-text, var(--gold-light)));
  color: var(--vf-on-accent, var(--bg));
  box-shadow: 0 2px 12px var(--vf-focus, rgba(var(--gold-rgb), 0.22));
}

.v-btn-secondary {
  border: 1px solid var(--vf-line, var(--gold-dim));
  background: transparent;
  color: var(--vf-text, var(--gold-light));
}
.v-btn-secondary:hover {
  border-color: var(--vf-accent-line, var(--gold));
  background: var(--vf-accent-soft, rgba(var(--gold-rgb), 0.07));
  color: var(--vf-text, var(--gold));
  box-shadow: 0 2px 12px var(--vf-focus, rgba(var(--gold-rgb), 0.18));
}

/* ── C35 — AFFIRMATIVE + INFORMATIONAL ARE MODIFIERS, NOT NEW ROLES ────────
   (Nate, approved 2026-07-27: "i liked the green accept and blue forward.")

   WHY THESE EXIST. The three roles carry INTENT, not hue: primary = the main
   action, danger = destructive. Two client-facing actions on the proposal
   viewer need a third and fourth intent the roles cannot express:
     - Accept Proposal — an irreversible, legally-binding YES. Gold is also
       every neutral primary in the app, so an affirmative cannot be told from
       an ordinary next-step. Green is the signal.
     - Forward this Proposal — a benign informational share sitting beside
       Accept and Decline; it must NOT read as either.

   THEY ARE MODIFIERS, exactly like .v-ai (C29) — NOT a fourth and fifth button
   family. They contribute ONLY accent color. Height, radius, padding,
   typography, gap, active and disabled behavior all inherit from the role they
   modify, so they can never drift into a separate size or type scale. Valid
   only on the role named in each selector:
     <button class="v-btn-primary v-affirm">Accept</button>
     <button class="v-btn-secondary v-info">Forward</button>

   Color comes from --v-ok / --v-info (vantage-ui.css). Literal fallbacks match
   the token values so the modifier still paints on a page that has not taken
   the body.v-ui cascade — the same lesson .v-fab records: an unresolved var()
   invalidates the whole declaration and silently drops the paint.

   Hover intensifies the SAME properties, so the C11 hover contract holds.
   The body.v-ui.v-face twins exist only to out-specify the gated facelift
   role copies (they beat a bare two-class modifier) and are deleted with them. */
.v-btn-primary.v-affirm,
body.v-ui.v-face .v-btn-primary.v-affirm {
  border-color: var(--v-ok, #2ecc71);
  background: var(--v-ok, #2ecc71);
  color: var(--vf-on-accent, var(--bg));
}
.v-btn-primary.v-affirm:hover,
body.v-ui.v-face .v-btn-primary.v-affirm:hover {
  background: color-mix(in srgb, var(--v-ok, #2ecc71) 88%, var(--vf-text, #ffffff));
  border-color: color-mix(in srgb, var(--v-ok, #2ecc71) 88%, var(--vf-text, #ffffff));
  color: var(--vf-on-accent, var(--bg));
  box-shadow: 0 2px 12px color-mix(in srgb, var(--v-ok, #2ecc71) 26%, transparent);
}
.v-btn-secondary.v-info,
body.v-ui.v-face .v-btn-secondary.v-info {
  border-color: color-mix(in srgb, var(--v-info, #5dade2) 55%, transparent);
  color: var(--v-info, #5dade2);
}
.v-btn-secondary.v-info:hover,
body.v-ui.v-face .v-btn-secondary.v-info:hover {
  border-color: var(--v-info, #5dade2);
  background: color-mix(in srgb, var(--v-info, #5dade2) 9%, transparent);
  color: var(--v-info, #5dade2);
  box-shadow: 0 2px 12px color-mix(in srgb, var(--v-info, #5dade2) 24%, transparent);
}

/* ── C29 — VANTaiGE IS SECONDARY WITH A PURPLE GLOW (Nate, 2026-07-26) ─────
   .v-ai is a MODIFIER on the canonical Secondary role. It contributes ONLY
   border color, a resting outer glow, and the mark color; height, radius,
   padding, typography, disabled and active behavior all inherit from
   .v-btn-secondary. No gradient, no italic, no second type scale, no
   letter-spacing override — the old VANTaiGE fourth family is retired (C29).
   The RESTING GLOW is a DELIBERATE departure from Secondary: an assistant
   action should read as available before hover. Do NOT "fix" it in a later
   audit. Hover intensifies the same property (border/background/glow), so
   the C11 hover contract is satisfied. Tokens are product color from
   vantage-brand.js (ONE seed #8b5cf6, hue 258 — clear of the C27b teal
   window), emitted for both appearances; fallbacks here match the compiler
   output so the modifier renders before brand CSS lands. */
/* The body.v-ui.v-face twin exists ONLY to out-specify the gated facelift
   Secondary copies (they beat a bare two-class modifier); it is deleted with
   them when the rollout completes. */
.v-btn-secondary.v-ai,
body.v-ui.v-face .v-btn-secondary.v-ai {
  border-color: var(--v-ai-line, rgba(139, 92, 246, 0.45));
  box-shadow: 0 0 10px var(--v-ai-glow, rgba(139, 92, 246, 0.16));
}
.v-btn-secondary.v-ai:hover,
body.v-ui.v-face .v-btn-secondary.v-ai:hover {
  border-color: rgba(var(--v-ai-rgb, 139, 92, 246), 0.78);
  background: rgba(var(--v-ai-rgb, 139, 92, 246), 0.10);
  box-shadow: 0 0 18px rgba(var(--v-ai-rgb, 139, 92, 246), 0.32);
}
.v-btn-secondary.v-ai .v-ai-mark {
  color: var(--v-ai-mark, #c4a8f0);
  display: inline-flex;
}

.v-btn-danger {
  border: 1px solid color-mix(in srgb, var(--vf-danger, var(--red, #c0392b)) 42%, transparent);
  background: color-mix(in srgb, var(--vf-danger, var(--red, #c0392b)) 6%, transparent);
  color: var(--vf-danger, var(--red, #c0392b));
}
.v-btn-danger:hover {
  border-color: color-mix(in srgb, var(--vf-danger, var(--red, #c0392b)) 65%, transparent);
  background: color-mix(in srgb, var(--vf-danger, var(--red, #c0392b)) 12%, transparent);
  box-shadow: 0 2px 12px color-mix(in srgb, var(--vf-danger, var(--red, #c0392b)) 24%, transparent);
}

:is(.v-btn-primary, .v-btn-secondary, .v-btn-danger):focus-visible {
  outline: 2px solid var(--vf-accent, var(--gold));
  outline-offset: 2px;
}

.v-btn-compact {
  min-height: var(--v-control-height-compact, 28px);
  height: var(--v-control-height-compact, 28px);
  padding: 0 10px;
  font-size: 12px !important;
}
.v-btn-icon {
  width: var(--v-control-height, 32px);
  padding: 0;
}
.v-btn-compact.v-btn-icon {
  width: var(--v-control-height-compact, 28px);
}
/* Chip size (2026-08-27). A control that has to sit INSIDE a line of table text
   rather than beside it: the canonical chip's geometry (3px 10px, 20px radius,
   11.5px) on a canonical button role, so a chip that does something is still one
   of the three roles and not a fourth button family.

   Origin: the PO card's "x3 Lines" rolled-group marker, which Nate asked to make
   "an actual button that splits them, then turn it into Roll Up once its split".
   The 28px compact tier is a third the height of the row it sits in and 20px too
   wide for the item column, which is what made a page-local pill tempting. This
   is that pill, promoted, so no page owns button chrome. */
.v-btn-chip {
  min-height: 22px;
  height: 22px;
  padding: 0 10px;
  border-radius: 20px;
  font-size: 11.5px !important;
  letter-spacing: 0.02em;
}
:is(.v-btn-primary, .v-btn-secondary, .v-btn-danger, .v-btn-compact) svg {
  flex-shrink: 0;
}
