/*
 * brand.css — Out Sauce / The Kitchen brand component kit (D3.1)
 *
 * Standalone, additive stylesheet for the brand component kit rendered by the
 * partials under app/views/shared/brand/. Every selector is scoped under
 * `.brand-*` so nothing collides with the existing application.css. Ported
 * from the approved brand HTML (outsauce-brand: paraplanner-comms.html,
 * letterhead.html) and the POC design system (.rebrand/POC-DESIGN-SYSTEM.md).
 *
 * Design tokens (--batch, --block-*, --content-*, --success, fonts, etc.) are
 * defined in application.css :root — this file only consumes them. brand.css
 * is auto-loaded by `stylesheet_link_tag :app` (Propshaft directory group) and
 * loads after application.css alphabetically. Safe to delete wholesale once
 * the kit is retired.
 */

/* ============================================================
   SECTION HERO — editorial masthead (ports .section-hero)
   ============================================================ */
.brand-section-hero {
  background: var(--batch);
  padding: 48px 48px 44px;
  transition: background-color 0.5s ease;
}

.brand-section-hero-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  color: #0A0A0A;
  margin-bottom: 14px;
}

.brand-section-hero-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 36px;
  color: #0A0A0A;
  line-height: 1.1;
  text-transform: uppercase;
  max-width: 600px;
}

.brand-section-hero-meta {
  display: flex;
  gap: 12px;
  margin-top: 20px;
  flex-wrap: wrap;
}

.brand-hero-tag {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  padding: 5px 14px;
  background: rgba(0, 0, 0, 0.08);
  color: #0A0A0A;
}

.brand-hero-tag.highlight {
  background: #0A0A0A;
  color: var(--batch);
  transition: color 0.5s ease;
}

/* ============================================================
   COMPACT HERO — functional page header (ports letterhead .header)
   ============================================================ */
.brand-compact-hero {
  background: var(--batch);
  padding: 36px 48px 32px;
  margin-bottom: var(--spacing-xl);
  transition: background-color 0.5s ease;
}

.brand-compact-hero-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 28px;
}

.brand-compact-hero-mark {
  display: flex;
  align-items: center;
  gap: 12px;
}

.brand-monogram {
  width: 32px;
  height: 32px;
  border: 2px solid #0A0A0A;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 14px;
  color: #0A0A0A;
  line-height: 1;
  letter-spacing: -0.02em;
}

.brand-wordmark {
  font-family: var(--font-display);
  font-size: 15px;
  color: #0A0A0A;
  letter-spacing: 0.02em;
  line-height: 1;
}

.brand-compact-hero-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.brand-compact-hero-eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  color: #0A0A0A;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 10px;
}

.brand-compact-hero-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 40px;
  color: #0A0A0A;
  line-height: 0.92;
  letter-spacing: -0.03em;
  text-transform: uppercase;
}

/* Hero action button — dark fill so it reads on the batch-coloured compact
   hero. The codebase .btn-primary is batch-on-batch and disappears here;
   this mirrors the section hero's .brand-hero-tag.highlight dark-chip. */
.brand-hero-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: var(--button-height);
  padding: 0 18px;
  background: #0A0A0A;
  color: var(--batch);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  border: none;
  transition: opacity 0.15s ease, color 0.5s ease;
}

.brand-hero-btn:hover {
  opacity: 0.85;
}

/* Destructive hero action — keeps the dark-pill language but signals
   danger via coral text (a solid red fill would clash with the rotating
   batch-coloured hero background). */
.brand-hero-btn--danger {
  color: #FF6B6B;
}

/* button_to renders a wrapping <form>; keep it neutral inside the
   actions flex row so the pill aligns with sibling link pills. */
.brand-compact-hero-actions form {
  margin: 0;
  display: inline-flex;
}

.brand-hero-btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* ============================================================
   BRAND BUTTON — generic non-hero action button family
   ============================================================
   Mirrors .brand-hero-btn's dark-pill language but sized for
   in-page actions (forms, cards, tables, callouts) instead of
   the hero row only. Variants cover the legacy .btn-primary /
   .btn-secondary / .btn-danger / .btn-batch surfaces.            */

.brand-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: var(--button-height);
  padding: 0 18px;
  background: #0A0A0A;
  color: var(--batch);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  border: none;
  transition: opacity 0.15s ease, color 0.5s ease,
              background-color 0.15s ease, border-color 0.15s ease;
}

.brand-btn:hover {
  opacity: 0.85;
}

.brand-btn:focus-visible {
  outline: 2px solid var(--batch);
  outline-offset: 2px;
}

.brand-btn:disabled,
.brand-btn[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
}

.brand-btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* --primary is an explicit alias for the dark-pill base so call
   sites read consistently (always pair .brand-btn with a variant). */
.brand-btn--primary {
  background: #0A0A0A;
  color: var(--batch);
}

/* --secondary: outline on light surfaces. Hover snaps border +
   text to the batch accent. */
.brand-btn--secondary {
  background: transparent;
  color: var(--content-text);
  border: 2px solid var(--content-border);
}

.brand-btn--secondary:hover {
  opacity: 1;
  color: var(--batch);
  border-color: var(--batch);
}

/* --danger: destructive actions (delete, revoke). Solid red, white
   text — distinct from batch so it never blends with the picker. */
.brand-btn--danger {
  background: var(--danger);
  color: #FFFFFF;
}

.brand-btn--danger:focus-visible {
  outline-color: var(--danger);
}

/* --ghost: text-only, no chrome. For inline tertiary actions
   (cancel, dismiss) next to a primary/secondary button. */
.brand-btn--ghost {
  background: transparent;
  color: var(--content-text);
  border: none;
  padding: 0 8px;
}

.brand-btn--ghost:hover {
  opacity: 1;
  color: var(--batch);
}

/* --sm: compact size for table rows + dense toolbars. */
.brand-btn--sm {
  height: 32px;
  padding: 0 12px;
  font-size: 11px;
}

.brand-btn--sm.brand-btn--ghost {
  padding: 0 6px;
}

.brand-btn--sm svg {
  width: 14px;
  height: 14px;
}

/* ============================================================
   SECTION LABEL + SECTION TITLE
   ============================================================ */
.brand-section-label {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  color: var(--batch);
  margin-top: 48px;
  margin-bottom: 8px;
  transition: color 0.5s ease;
}

.brand-section-label:first-child {
  margin-top: 0;
}

/* Accent-bar header for white content areas (POC-DESIGN-SYSTEM) */
.brand-section-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 14px;
  color: var(--content-text);
  text-transform: uppercase;
  margin: 24px 0 16px;
}

.brand-section-title::before {
  content: "";
  width: 4px;
  height: 22px;
  background: var(--batch);
  transition: background-color 0.5s ease;
}

/* ============================================================
   DIVIDERS
   ============================================================ */
.brand-divider {
  height: 1px;
  background: var(--content-border);
  margin: 40px 0;
}

.brand-divider-accent {
  height: 2px;
  background: var(--batch);
  margin: 40px 0;
  transition: background-color 0.5s ease;
}

/* ============================================================
   PROSE — editorial body-text wrapper (ports .section-body)
   ============================================================ */
.brand-prose {
  max-width: 820px;
}

.brand-prose p {
  margin-bottom: 16px;
  color: var(--content-secondary);
  font-size: 14px;
  line-height: 1.75;
}

.brand-prose strong {
  color: var(--content-text);
  font-weight: 600;
}

.brand-prose h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.4rem;
  color: var(--content-text);
  margin-top: 40px;
  margin-bottom: 16px;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.brand-prose h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.05rem;
  color: var(--content-text);
  margin-top: 32px;
  margin-bottom: 12px;
}

/* ============================================================
   BLOCKQUOTE
   ============================================================ */
.brand-blockquote {
  border-left: 3px solid var(--batch);
  padding: 16px 24px;
  margin: 24px 0;
  background: var(--content-surface);
  color: var(--content-secondary);
  font-size: 14px;
  line-height: 1.7;
  transition: border-color 0.5s ease;
}

.brand-blockquote strong {
  color: var(--content-text);
  font-weight: 600;
}

/* ============================================================
   STAR LIST + NUMBERED LIST
   ============================================================ */
.brand-star-list,
.brand-numbered-list {
  margin-bottom: 16px;
  padding-left: 0;
  list-style: none;
}

.brand-numbered-list {
  counter-reset: brand-item;
}

.brand-star-list li,
.brand-numbered-list li {
  margin-bottom: 8px;
  color: var(--content-secondary);
  font-size: 14px;
  position: relative;
  line-height: 1.7;
}

.brand-star-list li {
  padding-left: 20px;
}

.brand-numbered-list li {
  padding-left: 24px;
  counter-increment: brand-item;
}

.brand-star-list li::before {
  content: "\2605";
  position: absolute;
  left: 0;
  top: 5px;
  color: var(--batch);
  font-size: 8px;
  transition: color 0.5s ease;
}

.brand-numbered-list li::before {
  content: counter(brand-item);
  position: absolute;
  left: 0;
  top: 2px;
  font-family: var(--font-display);
  font-size: 11px;
  color: var(--batch);
  transition: color 0.5s ease;
}

.brand-star-list li strong,
.brand-numbered-list li strong {
  color: var(--content-text);
  font-weight: 600;
}

/* ============================================================
   TABLE — editorial data table (ports .table-wrap table)
   ============================================================ */
.brand-table-wrap {
  margin: 24px 0 32px;
  border: 1px solid var(--content-border);
  overflow-x: auto;
}

.brand-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.brand-table thead tr {
  background: var(--block-bg);
}

.brand-table thead th {
  padding: 10px 16px;
  text-align: left;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
  white-space: nowrap;
}

.brand-table tbody tr {
  border-bottom: 1px solid var(--content-border);
  transition: background-color 0.15s ease;
}

/* :last-of-type / :nth-of-type (not :last-child / :nth-child) — row partials
   such as jobs/_job_row emit a trailing <style> element that the HTML parser
   leaves interleaved in <tbody> ([tr, style, tr, style, …]). Type-scoped
   selectors count only <tr> siblings so striping and the final-row rule hold
   regardless. Identical to :nth-child for pure-<tr> tables (the styleguide). */
.brand-table tbody tr:last-of-type {
  border-bottom: none;
}

.brand-table tbody tr:nth-of-type(even) {
  background: var(--table-stripe);
}

.brand-table tbody tr:hover {
  background: var(--batch-subtle);
}

.brand-table tbody td {
  padding: 12px 16px;
  color: var(--content-secondary);
  vertical-align: top;
  font-size: 13px;
}

.brand-table tbody td:first-child {
  font-weight: 500;
  color: var(--content-text);
}

.brand-table tfoot td {
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--content-text);
  border-top: 2px solid var(--block-bg);
}

/* ============================================================
   BADGES
   ============================================================ */
.brand-badge {
  display: inline-block;
  padding: 3px 10px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
}

.brand-badge-better {
  background: var(--block-bg);
  color: var(--success);
}

.brand-badge-neutral {
  background: var(--block-bg);
  color: rgba(255, 255, 255, 0.5);
}

.brand-badge-new {
  background: var(--block-bg);
  color: var(--os-blue);
}

.brand-badge-same {
  background: var(--block-bg);
  color: rgba(255, 255, 255, 0.3);
}

/* ============================================================
   FAQ ITEM
   ============================================================ */
.brand-faq-q {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1rem;
  color: var(--content-text);
  margin-top: 32px;
  margin-bottom: 12px;
  padding-left: 20px;
  position: relative;
}

.brand-faq-q::before {
  content: "\2605";
  position: absolute;
  left: 0;
  top: 3px;
  color: var(--batch);
  font-size: 10px;
  transition: color 0.5s ease;
}

.brand-faq-a p {
  margin-bottom: 12px;
  color: var(--content-secondary);
  font-size: 14px;
  line-height: 1.75;
}

.brand-faq-a p:last-child {
  margin-bottom: 0;
}

.brand-faq-a strong {
  color: var(--content-text);
  font-weight: 600;
}

/* ============================================================
   SIGNATURE
   ============================================================ */
.brand-signature {
  margin-top: 40px;
  padding: 28px 32px;
  background: var(--block-bg);
  color: #FFFFFF;
}

.brand-signature p {
  margin-bottom: 4px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.5);
  font-size: 14px;
}

.brand-sig-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.1rem;
  color: #FFFFFF;
  margin-bottom: 2px;
}

.brand-sig-badge {
  display: inline-block;
  margin-top: 10px;
  padding: 4px 14px;
  background: var(--batch);
  color: #0A0A0A;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  transition: background-color 0.5s ease;
}

.brand-sig-contact {
  margin-top: 12px;
  font-family: var(--font-body);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.4);
}

/* ============================================================
   CONTACT BLOCK
   ============================================================ */
.brand-contact-block {
  margin-top: 40px;
  background: var(--block-bg);
  padding: 32px 36px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 20px;
}

.brand-contact-left h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 18px;
  color: #FFFFFF;
  text-transform: uppercase;
  margin-bottom: 4px;
}

.brand-contact-title {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  color: var(--batch);
  transition: color 0.5s ease;
}

.brand-contact-right {
  text-align: right;
}

.brand-contact-line {
  font-family: var(--font-body);
  font-size: 13px;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 6px;
}

.brand-contact-line:last-child {
  margin-bottom: 0;
}

.brand-contact-line a {
  color: rgba(255, 255, 255, 0.5);
  text-decoration: none;
}

.brand-contact-line a:hover {
  color: var(--batch);
}

.brand-contact-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  color: var(--batch);
  margin-right: 8px;
  transition: color 0.5s ease;
}

/* ============================================================
   DOC FOOTER
   ============================================================ */
.brand-doc-footer {
  padding: 20px 48px;
  border-top: 1px solid var(--content-border);
  background: var(--content-bg);
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.brand-footer-legal {
  font-size: 11px;
  color: var(--text-muted);
}

.brand-footer-web {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  color: var(--content-text);
  text-decoration: none;
}

.brand-footer-web:hover {
  color: var(--batch);
}

/* ============================================================
   DARK ACTION CARD — CTA (ports POC .action-card)
   ============================================================ */
.brand-dark-card {
  display: block;
  background: var(--block-bg);
  border: 2px solid transparent;
  padding: 24px;
  text-decoration: none;
  transition: border-color 0.15s ease;
}

a.brand-dark-card:hover {
  border-color: var(--batch);
}

.brand-dark-card-icon {
  color: var(--batch);
  font-size: 22px;
  line-height: 1;
  margin-bottom: 16px;
  transition: color 0.5s ease;
}

.brand-dark-card-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 14px;
  color: #FFFFFF;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.brand-dark-card-desc {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--block-tag);
  margin-top: 8px;
  line-height: 1.6;
}

/* ============================================================
   KPI STAT + DARK STAT BAR — data-page rhythm (POC dashboard)
   ============================================================ */
.brand-dark-stat-bar {
  background: var(--block-bg);
}

.brand-stat-bar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 48px;
}

.brand-stat-bar-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 13px;
  color: #FFFFFF;
}

.brand-stat-bar-label {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--batch);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  transition: color 0.5s ease;
}

.brand-stat-bar-divider {
  height: 3px;
  background: var(--batch);
  transition: background-color 0.5s ease;
}

.brand-stat-bar-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  padding: 28px 48px 32px;
}

.brand-kpi-stat {
  flex: 1;
  min-width: 120px;
  text-align: center;
}

.brand-kpi-value {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 30px;
  color: #FFFFFF;
  line-height: 1;
}

.brand-kpi-value.success {
  color: var(--success);
}

.brand-kpi-value.warning {
  color: var(--warning);
}

.brand-kpi-value.danger {
  color: var(--danger);
}

.brand-kpi-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.65);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-top: 8px;
}

/* ============================================================
   DATA TABLE — functional application data table (D3.1b)
   Ports dashboard-design-poc .data-table. For application data
   tables (jobs, invoices, contacts). The editorial .brand-table
   above stays for document/comparison tables only.
   ============================================================ */
.brand-data-table-wrap {
  margin: 24px 0 32px;
  border: 1px solid var(--content-border);
  background: var(--content-bg);
  overflow-x: auto;
}

.brand-data-table {
  width: 100%;
  border-collapse: collapse;
}

.brand-data-table thead tr {
  background: var(--block-bg);
}

.brand-data-table thead th {
  padding: 12px 16px;
  text-align: left;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--block-tag);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  white-space: nowrap;
}

/* :nth-of-type / :last-of-type (not :nth-child) — jobs/_job_row wraps each
   row in a <turbo-frame>; the HTML parser foster-parents non-<tr> nodes, so
   counting only <tr> siblings keeps striping stable whatever lands in
   <tbody>. Same lesson as .brand-table above. */
.brand-data-table tbody tr {
  border-bottom: 1px solid var(--content-border);
  border-left: 3px solid transparent;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.brand-data-table tbody tr:last-of-type {
  border-bottom: none;
}

.brand-data-table tbody tr:nth-of-type(even) {
  background: var(--table-stripe);
}

.brand-data-table tbody tr:hover {
  background: color-mix(in srgb, var(--batch) 6%, transparent);
  border-left-color: var(--batch);
}

.brand-data-table tbody td {
  padding: 14px 16px;
  font-size: 14px;
  color: var(--content-secondary);
  vertical-align: middle;
}

/* Opt-in bold treatment for the primary name/title cell (POC .col-name). */
.brand-data-table .brand-col-name {
  font-weight: 600;
  color: var(--content-text);
}

.brand-data-table tfoot td {
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--content-text);
  border-top: 2px solid var(--block-bg);
}

/* Cluster wrapper — keeps in-row actions on one line with even gaps. */
.brand-table-actions {
  display: flex;
  gap: 6px;
  white-space: nowrap;
}

/* Primary link in the name cell (e.g. a job title) — inherits the bold dark
   .brand-col-name colour; the batch shows only as a hover underline, so the
   title stays high-contrast (not low-contrast batch-on-white text). */
.brand-data-table .brand-col-name a {
  color: inherit;
  text-decoration: none;
}

.brand-data-table .brand-col-name a:hover {
  text-decoration: underline;
  text-decoration-color: var(--batch);
  text-underline-offset: 3px;
}

/* Secondary sub-line under a primary cell value (e.g. "6 business days"). */
.brand-data-table .brand-cell-sub {
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--content-muted);
}

/* Monospace cell — invoice numbers, references, money totals. Keeps codes
   and amounts in the brand mono face, distinct from the body-font cells. */
.brand-data-table .brand-cell-mono {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--content-text);
}

/* Row state — semantic left-border accent (overdue / on-hold jobs). Declared
   after tr:hover so the state colour holds while the row is hovered;
   brand-row-warning is declared last so it wins when a row is both overdue
   and on-hold (preserves the pre-rebrand precedence). */
.brand-data-table tbody tr.brand-row-danger {
  border-left-color: var(--danger);
}

.brand-data-table tbody tr.brand-row-warning {
  border-left-color: var(--warning);
}

/* ============================================================
   STATUS PILL — record lifecycle state (D3.1b)
   Outlined chip + square status dot. Distinct vocabulary from the
   filled .brand-data-badge: the pill is record state, the badge a
   flag. Default dot is muted; variants recolour the dot only.
   ============================================================ */
.brand-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 11px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  white-space: nowrap;
  background: var(--content-bg);
  border: 1.5px solid var(--content-border);
}

.brand-status-pill::before {
  content: "";
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  background: var(--content-muted);
}

.brand-status-pill--info::before    { background: var(--os-blue); }
.brand-status-pill--warning::before { background: var(--warning); }
.brand-status-pill--danger::before  { background: var(--danger); }
.brand-status-pill--success::before { background: var(--success); }

.brand-status-pill--active::before {
  background: var(--batch);
  transition: background-color 0.5s ease;
}

/* ============================================================
   ROLE BADGE — coloured pill for user role (admin/contractor/client) (D7.27)
   Stable identity tag, distinct from the lifecycle .brand-status-pill.
   Ports the .admin-users-role-badge--* chrome that landed in D7.26 when
   users/index was rebuilt; promoted to a shared partial here because
   D7.27 brings the second + third consumers online (users/show +
   tenants/show drive-by). Three role variants: admin (danger-red tint),
   contractor (batch-blue tint), client (success-green tint).
   ============================================================ */
.brand-role-badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 0;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.brand-role-badge--sm {
  padding: 2px 8px;
  font-size: 9px;
}

/* Identity colours — square, flat, non-semantic (D8). Admin reads as the
   elevated role via a dark fill; contractor carries the brand batch accent;
   client is a neutral tag. Replaces the rounded translucent-pastel chips
   whose red/green tints mis-read as danger/success lifecycle states. */
.brand-role-badge--admin {
  background: #0A0A0A;
  color: #FFFFFF;
}

.brand-role-badge--contractor {
  background: var(--batch);
  color: #0A0A0A;
  transition: background-color 0.5s ease;
}

.brand-role-badge--client {
  background: var(--content-surface, #F2F2F2);
  color: var(--content-secondary, #4A4E5A);
  border: 1px solid var(--content-border, #E5E7EB);
}

/* ============================================================
   DATA BADGE — flat filled badge for flags / SLA (D3.1b)
   Ports dashboard-design-poc .badge. Optional leading SVG icon.
   ============================================================ */
.brand-data-badge {
  display: inline-flex;
  align-items: center;
  /* align-self keeps the badge content-sized inside a flex container (e.g. the
     flex-column kanban .job-card) — a badge must never stretch. Ignored in
     non-flex contexts like a table cell. */
  align-self: flex-start;
  gap: 5px;
  padding: 4px 10px;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.brand-data-badge svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

.brand-data-badge--neutral {
  background: var(--content-surface);
  color: var(--content-secondary);
}

.brand-data-badge--success {
  background: #E8F5E9;
  color: #2E7D32;
}

.brand-data-badge--warning {
  background: #FEF3E2;
  color: #B45309;
}

.brand-data-badge--danger {
  background: #FDEAEA;
  color: #C0392B;
}

.brand-data-badge--batch {
  background: var(--batch);
  color: #0A0A0A;
  transition: background-color 0.5s ease;
}

/* ============================================================
   PRIORITY CHIP + INLINE TOGGLE — Job Priority Flag
   Dark/monochrome, deliberately OFF the SLA red/amber/green axis
   (decision #10): SLA owns the clock colours (overdue/warning/on-
   track); Priority owns "do this next". They must read as
   different signals, so the chip is ink-on-white, never tinted.
   ============================================================ */
.brand-data-badge.priority-badge {
  background: var(--content-text, #1A1D26);
  color: #FFFFFF;
}

/* The firm/admin inline control doubles as the on/off indicator:
   off = a quiet ghost flag, on = the same dark chip as the badge. */
.priority-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid var(--content-border, #E5E7EB);
  background: transparent;
  color: var(--content-secondary, #4A4E5A);
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.priority-toggle svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

.priority-toggle:hover {
  border-color: var(--content-text, #1A1D26);
  color: var(--content-text, #1A1D26);
}

.priority-toggle--on,
.priority-toggle--on:hover {
  background: var(--content-text, #1A1D26);
  border-color: var(--content-text, #1A1D26);
  color: #FFFFFF;
}

.priority-toggle:disabled {
  opacity: 0.6;
  cursor: progress;
}

/* Client-only "X of 3 slots used" affordance on the job index. */
.priority-slots-note {
  margin: 0 0 12px;
  font-size: 13px;
  color: var(--content-secondary, #4A4E5A);
}

.priority-slots-note strong {
  color: var(--content-text, #1A1D26);
}

/* Form "Mark as Priority" check row. */
.priority-form-check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

/* ============================================================
   TABLE ACTION — small in-row action link (D3.1b)
   Ports the POC secondary outline button; hover goes to batch.
   ============================================================ */
.brand-table-action {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 30px;
  padding: 0 12px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  color: var(--content-secondary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
  background: transparent;
  border: 1px solid var(--content-border);
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}

.brand-table-action:hover {
  border-color: var(--batch);
  color: var(--content-text);
  background: var(--batch-subtle);
}

.brand-table-action svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}

/* ============================================================
   FORM SELECT — branded native <select> (D3.1b)
   A CSS class, not a partial: a <select> needs Rails form helpers
   per use-site, so the class is the right unit of reuse. Apply via
   the `class:` option on select_tag / f.select — used for the
   inline job-status dropdown in the data table.
   ============================================================ */
.brand-select {
  appearance: none;
  -webkit-appearance: none;
  /* width: auto overrides the app's global select { width: 100% } reset — a
     status dropdown sizes to its content, never the full cell/container. */
  width: auto;
  min-width: 140px;
  height: 32px;
  padding: 0 30px 0 11px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background-color: var(--content-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7' fill='none'%3E%3Cpath d='M1 1.5L5 5.5L9 1.5' stroke='%231A1D26' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  border: 1.5px solid var(--content-border);
  border-radius: 0;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

.brand-select:hover,
.brand-select:focus {
  outline: none;
  border-color: var(--batch);
}

/* ============================================================
   FILTER BAR — index-page filter chrome (D6.5)
   Paired with shared/brand/_filter_bar partial. Sits OUTSIDE any
   card, directly above tables. Flex row with auto-wrap; selects
   are 40px tall to match the .brand-btn baseline; controls all
   snap to --batch on hover/focus the same way form chrome does.
   ============================================================ */
.brand-filter-bar {
  margin-bottom: 24px;
}

.brand-filter-form {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 16px;
}

.brand-filter-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 160px;
  min-width: 0;
}

.brand-filter-group--search {
  flex: 2 1 240px;
}

.brand-filter-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.brand-filter-select,
.brand-filter-search-input {
  width: 100%;
  height: 40px;
  padding: 0 14px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--content-text);
  background-color: var(--content-bg);
  border: 1.5px solid var(--content-border);
  border-radius: 0;
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color 0.15s ease;
}

.brand-filter-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7' fill='none'%3E%3Cpath d='M1 1.5L5 5.5L9 1.5' stroke='%231A1D26' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 40px;
  cursor: pointer;
}

.brand-filter-select:hover,
.brand-filter-select:focus,
.brand-filter-search-input:hover,
.brand-filter-search-input:focus {
  border-color: var(--batch);
}

.brand-filter-search-input::placeholder {
  color: var(--content-muted);
}

/* Search variant — wraps the input so a magnifier glyph sits inside
   the left padding. The icon is decorative; the label sits above per
   .brand-filter-group rhythm. */
.brand-filter-search {
  position: relative;
  display: block;
}

.brand-filter-search-icon {
  position: absolute;
  top: 50%;
  left: 12px;
  width: 14px;
  height: 14px;
  color: var(--content-muted);
  transform: translateY(-50%);
  pointer-events: none;
}

.brand-filter-search .brand-filter-search-input {
  padding-left: 34px;
}

/* Actions — Clear + optional Apply (when auto_submit is off). Pinned
   to the bottom-right of the row; wraps below filters on narrow
   viewports. */
.brand-filter-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  align-self: end;
}

/* Active-filter chip cluster — sits on its own row above the form so
   users can see and dismiss applied filters at a glance. Each chip
   links back to the same path with that filter cleared. */
.brand-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.brand-filter-active-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 28px;
  padding: 0 10px 0 12px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: var(--content-surface);
  border: 1.5px solid var(--content-border);
  border-radius: 0;
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.brand-filter-active-chip:hover,
.brand-filter-active-chip:focus-visible {
  outline: none;
  border-color: var(--batch);
  color: var(--batch);
}

.brand-filter-active-chip svg {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
}

/* ============================================================
   FORM FIELD FAMILY — full-width form chrome (D6.3)
   Paired with shared/brand/_form_field + _form_actions partials.
   The select variant here is full-width (form-shaped) — the
   smaller inline-toolbar select stays as .brand-select above.
   ============================================================ */
.brand-form-group {
  margin-bottom: 22px;
}

.brand-form-group:last-child {
  margin-bottom: 0;
}

.brand-form-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 8px;
}

.brand-form-required {
  color: var(--danger);
  margin-left: 4px;
  font-weight: 700;
}

.brand-form-input,
.brand-form-textarea,
.brand-form-select {
  display: block;
  width: 100%;
  /* Override the global `input, textarea, select { height: var(--button-height) }`
     reset: with our 11/14 padding + 1.5 line-height the line-box doesn't fit a
     fixed 40px box, so descenders ("p", "y", "g") clip on the bottom edge. Use
     auto height + min-height = button-height so the box still meets the rhythm
     baseline but grows for descenders. */
  height: auto;
  min-height: var(--button-height);
  line-height: 1.5;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--content-text);
  background-color: var(--content-bg);
  border: 1.5px solid var(--content-border);
  border-radius: 0;
  padding: 11px 14px;
  outline: none;
  transition: border-color 0.15s ease;
  appearance: none;
  -webkit-appearance: none;
}

.brand-form-input::placeholder,
.brand-form-textarea::placeholder {
  color: var(--content-muted);
}

.brand-form-input:hover,
.brand-form-textarea:hover,
.brand-form-select:hover,
.brand-form-input:focus,
.brand-form-textarea:focus,
.brand-form-select:focus {
  border-color: var(--batch);
}

.brand-form-input:focus-visible,
.brand-form-textarea:focus-visible,
.brand-form-select:focus-visible {
  outline: none;
}

.brand-form-input:disabled,
.brand-form-textarea:disabled,
.brand-form-select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: var(--content-surface);
}

.brand-form-textarea {
  min-height: 120px;
  resize: vertical;
  line-height: 1.55;
}

.brand-form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7' fill='none'%3E%3Cpath d='M1 1.5L5 5.5L9 1.5' stroke='%231A1D26' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 40px;
  cursor: pointer;
}

/* Validation: red border swap on the group ripples down to the input. */
.brand-form-group--has-error .brand-form-input,
.brand-form-group--has-error .brand-form-textarea,
.brand-form-group--has-error .brand-form-select {
  border-color: var(--danger);
}

/* Secret input with show/hide toggle (#60 advice-software vault). Masked by
   default (type=password); the eye button overlays the right edge and the
   input reserves room via padding. The `.is-revealed` class (set by the
   secret-field controller) swaps the eye / eye-off glyph. */
.brand-secret-field-wrap { position: relative; display: block; }
.brand-secret-field-input { padding-right: 44px; }
.brand-secret-field-toggle {
  position: absolute; top: 0; right: 0; height: 100%; width: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; background: transparent; border: none; cursor: pointer;
  color: var(--content-muted); transition: color 0.15s ease;
}
.brand-secret-field-toggle:hover { color: var(--batch); }
.brand-secret-field-toggle:focus-visible { outline: 2px solid var(--batch); outline-offset: -2px; }
.brand-secret-field .eye-off { display: none; }
.brand-secret-field.is-revealed .eye-on { display: none; }
.brand-secret-field.is-revealed .eye-off { display: block; }

/* ── Listbox (#29) — on-brand replacement for the native <select> open list ──
   Progressive enhancement: the `listbox` Stimulus controller attaches to a
   native <select>, hides it (inline styles — it stays the form's source of
   truth + no-JS fallback), and builds this styled trigger + panel beside it.
   The trigger is a <button>, so the global `input,textarea,select{width:100%}`
   footgun never touches it. Default = full-width form/filter control;
   `--inline` = compact uppercase control for table rows / toolbars. */
.brand-listbox {
  position: relative;
  width: 100%;
}

.brand-listbox--inline {
  width: auto;
  display: inline-block;
}

.brand-listbox.is-enhanced .brand-listbox__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm);
  width: 100%;
  min-height: var(--button-height);
  padding: 11px 14px;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  text-align: left;
  color: var(--content-text);
  background-color: var(--content-bg);
  border: 1.5px solid var(--content-border);
  border-radius: 0;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

.brand-listbox__trigger:hover,
.brand-listbox__trigger:focus-visible,
.brand-listbox.is-open .brand-listbox__trigger {
  border-color: var(--batch);
  outline: none;
}

.brand-listbox__trigger:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: var(--content-surface);
}

.brand-listbox__label {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.brand-listbox__label--placeholder {
  color: var(--content-muted);
}

.brand-listbox__caret {
  flex: 0 0 auto;
  width: 10px;
  height: 7px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7' fill='none'%3E%3Cpath d='M1 1.5L5 5.5L9 1.5' stroke='%231A1D26' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  transition: transform 0.15s ease;
}

.brand-listbox.is-open .brand-listbox__caret {
  transform: rotate(180deg);
}

/* REWORK-9 / A1 item 6 — VIEWPORT-positioned, not absolute. The controller
   writes top/bottom/left/width/max-height on open (see listbox_controller.js
   `#positionPanel`). Two bugs die here: a panel near the foot of the page now
   flips above its trigger instead of rendering off-screen, and a panel inside
   `.brand-data-table-wrap` (overflow-x: auto, which forces overflow-y: auto)
   is no longer clipped by its own row — a fixed box is laid out against the
   viewport, so scroll/clip ancestors cannot cut it.
   Do NOT reintroduce `top`/`left`/`right` here: the controller owns them, and
   a static offset would fight it. */
.brand-listbox.is-enhanced .brand-listbox__panel {
  display: block;
  position: fixed;
  z-index: 60;
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 280px;
  overflow-y: auto;
  background-color: var(--content-bg);
  border: 1.5px solid var(--content-border);
  border-radius: var(--border-radius-md);
  box-shadow: var(--shadow-elevated);
}

.brand-listbox__panel[hidden] {
  display: none;
}

.brand-listbox__option {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  padding: 9px 12px;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.4;
  color: var(--content-text);
  border-radius: var(--border-radius-sm);
  cursor: pointer;
}

.brand-listbox__option--placeholder {
  color: var(--content-muted);
}

/* Keyboard/hover focus — driven by the controller, not :hover, so they agree. */
.brand-listbox__option.is-active {
  background-color: var(--batch-subtle);
}

.brand-listbox__option.is-selected {
  font-weight: 600;
  color: var(--content-text);
}

/* Check mark on the selected row, drawn with the accent. */
.brand-listbox__option.is-selected::after {
  content: "";
  flex: 0 0 auto;
  margin-left: auto;
  width: 14px;
  height: 11px;
  background-color: var(--batch);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='11' viewBox='0 0 14 11' fill='none'%3E%3Cpath d='M1 5.5L5 9.5L13 1.5' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='11' viewBox='0 0 14 11' fill='none'%3E%3Cpath d='M1 5.5L5 9.5L13 1.5' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
}

/* Inline variant — mirrors .brand-select: compact, content-width, uppercase
   mono. Used for table-row / toolbar status dropdowns.
   The trigger selector carries .is-enhanced so it out-specifies the default
   trigger rule `.brand-listbox.is-enhanced .brand-listbox__trigger` (0,3,0).
   A bare `.brand-listbox--inline .brand-listbox__trigger` (0,2,0) loses the
   cascade: the trigger keeps the default 14px/40px size (only text-transform,
   unset by the default rule, leaks through) while the panel options shrink to
   11px — the oversized-trigger mismatch. */
.brand-listbox.is-enhanced.brand-listbox--inline .brand-listbox__trigger {
  min-height: 32px;
  min-width: 140px;
  padding: 0 11px;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* `min-width` is set in px by the controller (a percentage would resolve
   against the viewport now the panel is fixed, not against the trigger). */
.brand-listbox--inline .brand-listbox__panel {
  width: max-content;
  max-width: 280px;
}

.brand-listbox--inline .brand-listbox__option {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Checkbox + radio: native control + sibling label text on one line.
   Group variants stack multiple checkboxes/radios with consistent rhythm. */
.brand-form-checkbox-group,
.brand-form-radio-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.brand-form-checkbox,
.brand-form-radio {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--content-text);
  cursor: pointer;
}

.brand-form-checkbox input[type="checkbox"],
.brand-form-radio input[type="radio"] {
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--batch);
  cursor: pointer;
}

.brand-form-checkbox input[type="checkbox"]:disabled,
.brand-form-radio input[type="radio"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.brand-form-checkbox-label {
  line-height: 1.4;
}

/* ============================================================
   CHECKBOX GROUP — card variant (D7.28)
   Bordered selectable rows with primary text + optional mono
   secondary meta. Used for list-of-resources picks like the
   contractor-firms assignment grid in admin/users/{edit,new}
   and the contractor-assignment grid in admin/tenants/{edit,new}.
   Visual: flat square 1.5px batch border, batch-subtle bg, batch
   hover border — matches the .brand-form-input form chrome.
   ============================================================ */
.brand-form-checkbox-group--card {
  gap: 8px;
}

.brand-form-checkbox--card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--batch-subtle);
  border: 1.5px solid var(--content-border);
  border-radius: 0;
  transition: border-color 0.15s ease;
}

.brand-form-checkbox--card:hover {
  border-color: var(--batch);
}

.brand-form-checkbox-card-text {
  flex: 1;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--content-text);
}

.brand-form-checkbox-card-meta {
  font-size: 12px;
  color: var(--content-secondary);
}

.brand-form-empty {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--content-muted);
  margin: 4px 0 0 0;
}

.brand-form-hint {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--content-muted);
  line-height: 1.55;
  margin-top: 6px;
}

.brand-form-error {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  color: var(--danger);
  margin-top: 6px;
}

/* Actions row — submit + optional cancel, paired with .brand-btn family. */
.brand-form-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 24px;
}

/* Chrome inline-flex + <input type="submit"> stretches the submit to fill
   its flex line. Forces auto width with a min-width floor so brand-btn
   submits in legacy `.form-actions` containers (notification_preferences,
   documents/_upload_form, quotes/_calculator_form) keep their pill shape. */
.form-actions .brand-btn {
  width: auto;
  min-width: 160px;
}

/* ============================================================
   CARD — neutral light wrapper (D6.4)
   The light/neutral counterpart to .brand-dark-card. Wraps any
   panel that groups page content (form sections, identity
   snapshots, summary panels, sidebar callouts). Flat, square,
   white surface, 1.5px brand border. Header + body + footer
   slots are independent; padding lives on each slot so --flush
   variants can drop body padding cleanly for embedded tables.
   ============================================================ */
.brand-card {
  background: var(--content-bg);
  border: 1.5px solid var(--content-border);
  margin-bottom: 24px;
}

.brand-card:last-child {
  margin-bottom: 0;
}

.brand-card-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 24px;
  border-bottom: 1px solid var(--content-border);
}

.brand-card-title-text {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.2;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin: 0;
}

.brand-card-title-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.brand-card-body {
  padding: 24px;
}

.brand-card-footer {
  padding: 16px 24px;
  border-top: 1px solid var(--content-border);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--content-secondary);
}

/* Flush — drop body padding so a brand-data-table sits edge-to-edge
   inside the card frame. Header + footer keep their padding. */
.brand-card--flush > .brand-card-body {
  padding: 0;
}

/* Muted — subtle surface tint for secondary/aside panels that need
   to recede behind a primary card on the same row. */
.brand-card--muted {
  background: var(--content-surface);
}

/* Accent — 3px batch top-rule for emphasis (matches .brand-stat-card
   accent language). Use sparingly — reserved for status/featured
   cards, not every panel. */
.brand-card--accent {
  border-top: 3px solid var(--batch);
  transition: border-top-color 0.5s ease;
}

/* ============================================================
   STATUS CARD — readiness/status sidebar callout (D6.7)
   Parallel primitive to .brand-card (NOT a variant of it). Adds an
   icon cue + 3px semantic top-rule so a readiness/connection/SLA
   panel reads at a glance. Use for multi-line sidebar callouts;
   for a single-line inline banner use .brand-alert instead (D6.8).
   Variant accent: --success/--warning/--danger fixed semantic
   tokens; --info follows --batch (workflow picker); --neutral
   uses --content-muted.
   ============================================================ */
.brand-status-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
  background: var(--content-bg);
  border: 1.5px solid var(--content-border);
  border-top-width: 3px;
  margin-bottom: 24px;
}

.brand-status-card:last-child {
  margin-bottom: 0;
}

.brand-status-card--success { border-top-color: var(--success); }
.brand-status-card--success .brand-status-card-icon { color: var(--success); }

.brand-status-card--warning { border-top-color: var(--warning); }
.brand-status-card--warning .brand-status-card-icon { color: var(--warning); }

.brand-status-card--danger { border-top-color: var(--danger); }
.brand-status-card--danger .brand-status-card-icon { color: var(--danger); }

.brand-status-card--info {
  border-top-color: var(--batch);
  transition: border-top-color 0.5s ease;
}
.brand-status-card--info .brand-status-card-icon {
  color: var(--batch);
  transition: color 0.5s ease;
}

.brand-status-card--neutral { border-top-color: var(--content-muted); }
.brand-status-card--neutral .brand-status-card-icon { color: var(--content-muted); }

.brand-status-card-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.2;
  color: var(--content-text);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin: 0;
}

.brand-status-card-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: inline-flex;
}

.brand-status-card-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.brand-status-card-body {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: var(--content-secondary);
  margin: 0;
}

.brand-status-card-body strong {
  color: var(--content-text);
  font-weight: 600;
}

.brand-status-card-list {
  list-style: disc;
  padding-left: 20px;
  margin: 0;
  color: var(--content-secondary);
  font-size: 13px;
  line-height: 1.55;
}

.brand-status-card-list li + li {
  margin-top: 2px;
}

/* CTA wrapper — keeps button_to's form full-width so the brand-btn
   below renders edge-to-edge inside the card. */
.brand-status-card-cta,
.brand-status-card-cta-form {
  display: block;
  width: 100%;
  margin: 0;
}

.brand-status-card-cta .brand-btn {
  width: 100%;
}

.brand-status-card-hint {
  font-family: var(--font-body);
  font-size: 12px;
  font-style: italic;
  color: var(--content-muted);
  line-height: 1.5;
  margin: 0;
}

/* ============================================================
   ALERT / CALLOUT — inline banner (D6.8)
   Single-line cousin to .brand-status-card. Use for thin
   warning/info strips above a form or inside a card body. No
   list, no CTA — if a callout needs either, reach for
   .brand-status-card instead.
   Variant tint: --success/--warning/--danger fixed semantic
   tokens; --info follows --batch (workflow picker); --neutral
   uses --content-muted. Each variant tints background +
   border via color-mix so the strip reads as a coloured wash
   on the parent surface.
   ============================================================ */
.brand-alert {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--content-text);
  background: var(--content-bg);
  border: 1px solid var(--content-border);
  border-left-width: 3px;
  margin-bottom: 16px;
}

.brand-alert:last-child {
  margin-bottom: 0;
}

.brand-alert--success {
  background: color-mix(in srgb, var(--success) 8%, var(--content-bg));
  border-color: color-mix(in srgb, var(--success) 35%, var(--content-border));
  border-left-color: var(--success);
}
.brand-alert--success .brand-alert-icon { color: var(--success); }

.brand-alert--warning {
  background: color-mix(in srgb, var(--warning) 10%, var(--content-bg));
  border-color: color-mix(in srgb, var(--warning) 40%, var(--content-border));
  border-left-color: var(--warning);
}
.brand-alert--warning .brand-alert-icon { color: var(--warning); }

.brand-alert--danger {
  background: color-mix(in srgb, var(--danger) 8%, var(--content-bg));
  border-color: color-mix(in srgb, var(--danger) 35%, var(--content-border));
  border-left-color: var(--danger);
}
.brand-alert--danger .brand-alert-icon { color: var(--danger); }

.brand-alert--info {
  background: color-mix(in srgb, var(--batch) 6%, var(--content-bg));
  border-color: color-mix(in srgb, var(--batch) 30%, var(--content-border));
  border-left-color: var(--batch);
  transition: background 0.5s ease, border-color 0.5s ease;
}
.brand-alert--info .brand-alert-icon {
  color: var(--batch);
  transition: color 0.5s ease;
}

.brand-alert--neutral {
  border-left-color: var(--content-muted);
}
.brand-alert--neutral .brand-alert-icon { color: var(--content-muted); }

.brand-alert-icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  display: inline-flex;
  margin-top: 1px;
}

.brand-alert-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.brand-alert-content {
  flex: 1;
  min-width: 0;
}

.brand-alert-content strong {
  font-weight: 600;
  color: var(--content-text);
}

.brand-alert-content p {
  margin: 0;
}

.brand-alert-content p + p {
  margin-top: 4px;
}

.brand-alert-dismiss {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 4px;
  color: var(--content-muted);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.brand-alert-dismiss:hover,
.brand-alert-dismiss:focus-visible {
  background: rgba(0, 0, 0, 0.06);
  color: var(--content-text);
}

.brand-alert-dismiss:focus-visible {
  outline: 2px solid var(--batch);
  outline-offset: 1px;
}

.brand-alert-dismiss svg {
  width: 14px;
  height: 14px;
  display: block;
}

/* ============================================================
   TWO-COLUMN LAYOUT — main + sticky aside (D6.9)
   Canonical replacement for hand-rolled .invoice-layout /
   .invoice-main / .invoice-aside, .job-content-layout /
   .job-main-column / .job-sidebar-column, and friends. Main
   column flexes (minmax(0,1fr) so wide tables can scroll, not
   overflow). Aside is a fixed 360px sticky rail pinned just
   below the app header. Below 1024px both columns stack and
   the aside drops BELOW main (visual order matches DOM order).
   ============================================================ */
.brand-two-col {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: var(--spacing-lg);
  align-items: start;
}

.brand-two-col-main {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
  min-width: 0;
}

.brand-two-col-aside {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
  position: sticky;
  top: calc(var(--header-height) + var(--spacing-md));
  align-self: start;
}

@media (max-width: 1024px) {
  .brand-two-col {
    grid-template-columns: 1fr;
  }

  .brand-two-col-aside {
    position: static;
    top: auto;
  }
}

/* ============================================================
   METADATA GRID — key/value display chrome (D6.6)
   Canonical replacement for hand-rolled .info-grid / .summary-grid /
   .job-details-list / raw <dl>. Renders semantic <dl> with each
   dt+dd grouped in a .brand-metadata-item wrapper so CSS Grid can
   lay them out in 1/2/3 columns while keeping the pair atomic.
   Typically lives inside a .brand-card body.
   ============================================================ */
.brand-metadata-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px 24px;
  margin: 0;
}

.brand-metadata-grid--cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.brand-metadata-grid--cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.brand-metadata-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.brand-metadata-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin: 0;
}

.brand-metadata-value {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.45;
  color: var(--content-text);
  margin: 0;
  word-break: break-word;
}

/* Mono variant — for IDs, references, amounts, ABNs. */
.brand-metadata-value--mono {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: -0.01em;
}

/* Muted variant — secondary info, "Not set" fallbacks, audit context. */
.brand-metadata-value--muted {
  color: var(--content-muted);
}

@media (max-width: 720px) {
  .brand-metadata-grid--cols-2,
  .brand-metadata-grid--cols-3 {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   STAT CARD — light KPI summary card (D3.3)
   Flat, square, brand-language summary card for data-page index
   headers (invoices, remittances). The light-content-area
   counterpart to the dark .brand-kpi-stat: same role, white
   surface. The batch top-rule responds to the active colour.
   ============================================================ */
.brand-stat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin: 24px 0;
}

/* Two-up variant — for an index page with a pair of summary cards (e.g. an
   account-summary or upcoming-invoice panel). Declared before the media
   queries below so they still collapse it to 1-up on narrow viewports. */
.brand-stat-grid--2 {
  grid-template-columns: repeat(2, 1fr);
}

.brand-stat-card {
  background: var(--content-bg);
  border: 1.5px solid var(--content-border);
  border-top: 3px solid var(--batch);
  padding: 20px 22px;
  transition: border-top-color 0.5s ease;
}

.brand-stat-card-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--content-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 14px;
}

.brand-stat-card-value {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1;
  color: var(--content-text);
}

/* Mono variant — for code-shaped values (an invoice number, a reference). */
.brand-stat-card-value--mono {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.brand-stat-card-value--muted {
  color: var(--content-muted);
}

/* Warning tint — an outstanding balance or an amount that needs attention.
   Light-card parity with .brand-kpi-value.warning. */
.brand-stat-card-value--warning {
  color: var(--warning);
}

.brand-stat-card-meta {
  margin-top: 10px;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--content-secondary);
}

.brand-stat-card-meta--accent {
  color: var(--batch);
  font-weight: 600;
  transition: color 0.5s ease;
}

@media (max-width: 900px) {
  .brand-stat-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 600px) {
  .brand-stat-grid {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   FULL-BLEED — break full-width brand-kit sections out of the
   .app-main { padding: var(--spacing-xl) } content padding, so heros,
   the dark stat bar and the doc footer reach the content-area edges.
   Mirrors the legacy-shell bleed rule in application.css.
   ============================================================ */
.brand-compact-hero,
.brand-section-hero,
.brand-dark-stat-bar,
.brand-doc-footer {
  margin-left: calc(-1 * var(--spacing-xl));
  margin-right: calc(-1 * var(--spacing-xl));
}

/* Hero also breaks out of the top padding so the banner sits flush against
   the topbar (no grey buffer). Hero only — it's the first child of
   .app-main; the stat bar and doc footer must keep their normal flow. */
.brand-compact-hero,
.brand-section-hero {
  margin-top: calc(-1 * var(--spacing-xl));
}

/* The styleguide gallery frames each component in a .brand-sg-demo box —
   neutralise the bleed there so demos stay inside their frame. */
.brand-sg-demo .brand-compact-hero,
.brand-sg-demo .brand-section-hero,
.brand-sg-demo .brand-dark-stat-bar,
.brand-sg-demo .brand-doc-footer {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 768px) {
  .brand-section-hero {
    padding: 32px 24px 28px;
  }

  .brand-section-hero-title {
    font-size: 26px;
  }

  .brand-compact-hero {
    padding: 28px 24px 24px;
  }

  .brand-compact-hero-title {
    font-size: 30px;
  }

  .brand-stat-bar-header,
  .brand-stat-bar-stats,
  .brand-doc-footer {
    padding-left: 24px;
    padding-right: 24px;
  }

  .brand-contact-block {
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
  }

  .brand-contact-right {
    text-align: left;
  }
}

/* ============================================================
   STYLEGUIDE PAGE CHROME — dev tooling for /internal/styleguide
   ============================================================ */
.brand-sg-intro {
  margin-bottom: 40px;
}

/* Page chrome uses the native --text-* tokens (these are dark-mode patched)
   so the styleguide stays readable in both light and dark mode. */
.brand-sg-lede {
  max-width: 820px;
  margin-top: 16px;
  font-size: 14px;
  line-height: 1.7;
  color: var(--text-body);
}

.brand-sg-section {
  margin-bottom: 48px;
}

.brand-sg-heading {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 16px;
  color: var(--text-primary);
  text-transform: uppercase;
  margin-bottom: 4px;
}

.brand-sg-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 16px;
}

.brand-sg-demo {
  border: 1px solid var(--content-border);
  background: var(--content-bg);
  padding: 24px;
}

.brand-sg-demo + .brand-sg-demo {
  margin-top: 16px;
}

.brand-sg-demo--flush {
  padding: 0;
  overflow: hidden;
}

.brand-sg-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}


/* ============================================================
   TWO-FACTOR (TOTP) — enrollment + backup codes (Slice 2)
   ============================================================ */
.account-two-factor-show > * + *,
.account-two-factor-new > * + *,
.account-two-factor-backup-codes > * + * {
  margin-top: 24px;
}

.two-factor-note {
  margin-bottom: 16px;
  color: var(--content-secondary);
  font-size: 14px;
  line-height: 1.6;
}

.two-factor-qr {
  display: flex;
  justify-content: center;
  padding: 20px;
  background: #FFFFFF;
  border: 1px solid var(--content-border, #E3DDD1);
  border-radius: 8px;
  margin-bottom: 20px;
}

.two-factor-qr svg {
  width: 220px;
  height: 220px;
}

.two-factor-secret code {
  display: inline-block;
  font-family: var(--font-mono, 'Space Mono', monospace);
  font-size: 15px;
  letter-spacing: 0.12em;
  padding: 8px 14px;
  background: var(--surface-muted, #F4F1EA);
  border-radius: 6px;
  word-break: break-all;
}

/* One code per line (10 rows), full 32-char code shown without clipping — these
   must be copied exactly, and with no leading number to grab by accident. */
.two-factor-backup-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 16px 0 20px;
  list-style: none;
  padding: 0;
}

.two-factor-backup-list li {
  padding: 12px 18px;
  background: var(--surface-muted, #F4F1EA);
  border: 1px solid var(--content-border, #E3DDD1);
  border-radius: 8px;
}

.two-factor-backup-list code {
  font-family: var(--font-mono, 'Space Mono', monospace);
  font-size: 16px;
  letter-spacing: 0.18em;
  color: var(--content-primary, #1A1A1A);
  word-break: break-all;
}

/* Audited bank-details reveal on the admin user show card (CONTRACTOR-7,
   decision D1-A). The status span and the values span swap places: only one is
   ever unhidden. Values are painted by the `contractor-bank-reveal` controller
   out of an audited POST — they are never in the page's initial HTML. */
.contractor-bank-reveal {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
}

.contractor-bank-reveal__toggle {
  flex: none;
}

.contractor-bank-reveal__values {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
}

.contractor-bank-reveal__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.contractor-bank-reveal__row-label {
  flex: none;
  min-width: 108px;
  font-size: 12px;
  color: var(--content-muted);
}

.contractor-bank-reveal__row-value {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  letter-spacing: 0.04em;
  color: var(--content-primary, #1A1A1A);
  word-break: break-all;
}

/* ============================================================
   MODAL — brand-kit overlay dialog (REWORK-9)
   Extracted as a primitive rather than hand-rolled a fourth
   time. Three bespoke copies of this chrome already exist
   (jobs/_complete_modal, the kb-prompt modal, the xplan popup);
   the reassign dialog A1 item 2 requires would have been the
   fourth, which is exactly the "siloed parallel implementation"
   the slice quality bar forbids. New dialogs use these classes.
   Migrating the three existing copies onto them is deliberately
   NOT done here — they are load-bearing ceremonies and this
   slice does not own them.
   Markup: shared/brand/_modal.html.erb.
   ============================================================ */
.brand-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-md);
  background: rgba(0, 0, 0, 0.7);
}

.brand-modal[hidden] {
  display: none;
}

.brand-modal__card {
  width: 100%;
  max-width: 520px;
  max-height: 92vh;
  overflow-y: auto;
  background: var(--content-bg);
  border: 1px solid var(--content-border);
  border-top: 3px solid var(--batch);
  padding: var(--spacing-xl);
  box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
}

.brand-modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-md);
}

.brand-modal__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--content-text);
}

.brand-modal__close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: 1px solid var(--content-border);
  color: var(--content-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.brand-modal__close:hover {
  border-color: var(--batch);
  color: var(--content-text);
}

.brand-modal__description {
  margin: 0 0 var(--spacing-lg);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--content-secondary);
}

.brand-modal__body > * + * {
  margin-top: var(--spacing-lg);
}
