/* buttons — système unifié (réf. vivante : /design/boutons). Deux axes : EMPHASE
   (neutre/marque, plein→discret) × INTENTION (la couleur porte le sens). Géométrie
   unique ; graisse : fonds pleins 600 (porter sur la couleur), autres 500. */
/* min-height locks the box so siblings align regardless of content: an icon
   (15px) would otherwise make a button 1px taller than a text-only one (14px
   line-box), misaligning header action rows. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: var(--control-h); padding: 8px 14px; border-radius: var(--radius); font-size: var(--fs-14);
  font-family: inherit; font-weight: var(--fw-medium); line-height: 1; border: 1px solid transparent;
  cursor: pointer; white-space: nowrap; user-select: none;
  transition: background .12s, border-color .12s, color .12s, filter .12s; }
.btn:hover { text-decoration: none; }
.btn .ic-inline { width: 15px; height: 15px; }
/* fonds pleins = texte blanc sur couleur saturée → 600 */
.btn-primary, .btn-secondary, .btn-success, .btn-danger, .btn-warn, .btn-info { font-weight: var(--fw-semibold); }

/* — Emphase — */
/* background-image (pas `background`) + background-origin: border-box : le bord 1px reste
   net (cf. commentaire d'origine). Le hover NE redéclare PAS `background`. */
.btn-primary { background-image: var(--brand-grad); background-origin: border-box;
  color: var(--white); }
.btn-primary:hover { color: var(--white); filter: brightness(1.07); }
.btn-secondary { background: var(--ink); color: var(--white); }
.btn-secondary:hover { background: color-mix(in srgb, var(--ink), #fff 16%); }
.btn-soft { background: var(--brand-wash); color: var(--brand-d); }
.btn-soft:hover { background: color-mix(in srgb, var(--brand-wash), var(--brand) 12%); }
.btn-outline { background: var(--white); border-color: var(--line); color: var(--ink); }
.btn-outline:hover { border-color: var(--muted); }
.btn-quiet { background: transparent; color: var(--link); }
.btn-quiet:hover { background: var(--brand-wash); color: var(--brand-d); }

/* — Intentions sémantiques : plein (fort) | doux (retrait) — */
.btn-success { background: var(--ok); color: var(--white); }
.btn-success:hover { filter: brightness(1.07); }
.btn-success-soft { background: var(--ok-wash); color: var(--ok-d); }
.btn-success-soft:hover { background: color-mix(in srgb, var(--ok-wash), var(--ok) 12%); }
.btn-danger { background: var(--bad); color: var(--white); }
.btn-danger:hover { filter: brightness(1.07); }
.btn-danger-outline { background: var(--white); border-color: var(--bad-line); color: var(--bad); }
.btn-danger-outline:hover { background: var(--bad); border-color: var(--bad); color: var(--white); }
.btn-danger-soft { background: var(--bad-wash); color: var(--bad-d); }
.btn-danger-soft:hover { background: color-mix(in srgb, var(--bad-wash), var(--bad) 12%); }
.btn-warn { background: var(--warn); color: var(--white); }
.btn-warn:hover { filter: brightness(1.07); }
.btn-warn-soft { background: var(--warn-wash); color: var(--warn-d); }
.btn-warn-soft:hover { background: color-mix(in srgb, var(--warn-wash), var(--warn) 12%); }
/* « Info » en violet --accent (plus mat que --brand) → garde l'esprit du site, pas un bleu. */
.btn-info { background: var(--accent); color: var(--white); }
.btn-info:hover { filter: brightness(1.08); }
.btn-info-soft { background: var(--accent-wash); color: var(--accent); }
.btn-info-soft:hover { background: color-mix(in srgb, var(--accent-wash), var(--accent) 12%); }

/* — Tailles & états — */
.btn-sm { min-height: var(--control-h-sm); padding: 5px 10px; font-size: var(--fs-13); }
.btn-sm .ic-inline { width: 14px; height: 14px; }
.btn.block, .btn-block { width: 100%; justify-content: center; margin-top: 6px; }
.btn:disabled, .btn.btn-disabled { opacity: .5; cursor: not-allowed; pointer-events: none; filter: none; animation: none; }
.link { color: var(--link); }
.link:hover { color: var(--brand-d); }
/* delete cross — small, prominent red button (clear target, easy to hit) */
.link-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 1px solid var(--bad-wash); border-radius: 7px; background: var(--bad-wash); color: var(--bad-d); font-size: var(--fs-15); line-height: 1; cursor: pointer; transition: background .12s, color .12s, border-color .12s; }
.link-btn:hover { background: var(--bad); border-color: var(--bad); color: var(--white); text-decoration: none; }
.link-btn.danger { color: var(--bad-d); font-size: var(--fs-15); }
/* neutral icon button (edit) — same target as the delete cross, non-destructive color */
.link-btn.neutral { border-color: var(--line); background: var(--white); color: var(--ink-2); }
.link-btn.neutral:hover { background: var(--ink); border-color: var(--ink); color: var(--white); }

/* Action column (ui.table empty-header column): every row's buttons grouped and
   right-aligned (it is always the trailing column, so they hug the table edge),
   laid out side by side and wrapping to stacked when cramped. One factored rule —
   no route lays out its own action cell. In-row buttons are real `.btn` (quiet /
   danger-soft, btn-sm) — the action column hosts them without bespoke styling. */
.td-actions { text-align: right; vertical-align: middle; }
.col-actions { display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px; }
.col-actions form { margin: 0; }
/* Secondary line under a main label (catalogue brand under the article name,
   exploded kit component under its kit head line): smaller + muted, no margin. */
.sub-line { color: var(--ink-2); font-size: var(--fs-12); }

/* Quote-wide product reference / manufacturer brand, printed UNDER the line label on the
   editing screen (block, muted, small, tight under the label so the row stays short). On
   the printed devis/facture they are baked inline into the label via composeLineLabel. */
.line-ref, .line-brand { display: block; color: var(--muted); font-size: var(--fs-12); line-height: 1.25; margin-top: 0; }

/* Quote line label cell: the article link + inline kit caret on one baseline. */
.line-label { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.line-inline-form { display: inline; margin: 0; }
/* Kit Détailler/Replier caret: a bare disclosure triangle, no button chrome. */
.kit-caret { background: none; border: 0; padding: 0 2px; cursor: pointer; color: var(--muted); font-size: var(--fs-13); line-height: 1; }
.kit-caret:hover { color: var(--ink); }

/* Selected quote line (click-to-select): the shared brand wash, like a picked
   mailbox row. The whole row is the affordance — double-click edits, SUPPR removes. */
[data-quote-line] { cursor: pointer; }
tr.row-selected > td { background: var(--brand-wash); }

/* Comment line: a full-width muted row spanning the table; italic, no figures. */
tr.line-comment > td { color: var(--muted); font-style: italic; }
/* Order comment line: label left, delete × right, on a single row. */
tr.line-comment > td:has(.line-comment-text) { display: flex; align-items: center; gap: 8px; }
.line-comment-text { flex: 1 1 auto; }
/* In-place edit row: the inline edit form spans the whole row, no column chrome. */
tr.line-edit-row > td { padding: 8px 13px; }
.line-edit { padding-top: 0; border-top: 0; flex-wrap: wrap; align-items: flex-end; }
.line-edit .comment-edit-field { flex: 1 1 320px; }

