/* Proline Cleaning Solutions
   Tokens from the badge: navy, gold, cream. Restrained on purpose — the logo is
   the only decorative element on the page. */

:root {
  --navy: #1d396e;
  --navy-deep: #13264a;
  --gold: #c9992e;
  --gold-ink: #96690f;
  --cream: #faf7ee;
  --cream-line: #ece3cd;

  --ink: #0f1728;
  --body: #4a5568;
  --muted: #6b7686;
  --line: #e4e8ef;
  --line-soft: #f1f4f8;
  --line-strong: #cbd3e0;
  --surface-soft: #fafbfd;
  --gold-deep: #a97f22;
  --on-navy: #eaf0fa;
  --on-navy-soft: #c2d2ec;
  --danger: #b42318;
  --ok: #027a48;

  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 20px;
  --pill: 999px;
  --shadow-sm: 0 1px 2px rgba(15, 23, 40, 0.04);
  --shadow: 0 8px 28px rgba(15, 23, 40, 0.07);
  --shadow-lg: 0 18px 44px rgba(15, 23, 40, 0.1);
  /* One gold top edge, used only to single a card out. */
  --accent-top: inset 0 3px 0 var(--gold);
  --t: 0.15s ease;
  --tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");

  --max: 1140px;
  --gutter: 24px;
  --section: 88px;

  --font-display: "Archivo", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-body: "Karla", ui-sans-serif, system-ui, -apple-system, sans-serif;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: #fff;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  margin: 0;
  color: var(--ink);
  letter-spacing: -0.025em;
  line-height: 1.08;
  text-wrap: balance;
}

h1 { font-size: clamp(2.25rem, 4.4vw, 3.35rem); font-weight: 700; }
h2 { font-size: clamp(1.6rem, 2.6vw, 2.15rem); font-weight: 700; }
h3 { font-size: 1.06rem; font-weight: 600; letter-spacing: -0.01em; }
p { margin: 0; }

a { color: var(--navy); text-decoration: none; transition: color var(--t); }
a:hover { color: var(--navy-deep); }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 4px; }
/* Containers we focus in code so a screen reader announces the new panel -- a
   wizard step, the confirmation, the publish dialog. They carry tabindex="-1",
   so no keyboard user can ever reach them by tabbing and the ring tells nobody
   anything; it just drew a gold box around the whole form on first paint. The
   controls inside keep their own rings. */
[tabindex="-1"]:focus, [tabindex="-1"]:focus-visible { outline: none; }

img { max-width: 100%; display: block; }

/* Flex and grid components override [hidden]; make it win everywhere. */
[hidden] { display: none !important; }

/* ---------- layout ---------- */

.goldbar { height: 4px; background: var(--gold); }
.container { max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }

section { padding-block: var(--section); }
section + section { padding-top: 0; }
.band section { padding-block: var(--section); }

.band-cream { background: var(--cream); border-block: 1px solid var(--cream-line); }
.band-navy { background: var(--navy-deep); color: #fff; }
.band-navy h2, .band-navy h3 { color: #fff; }

.grid-2 { display: grid; gap: 40px; grid-template-columns: 1fr; align-items: center; }
.grid-3 { display: grid; gap: 20px; grid-template-columns: 1fr; align-items: stretch; }
.stack { display: flex; flex-direction: column; gap: 18px; }
.row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

@media (min-width: 880px) {
  .grid-2 { grid-template-columns: 1fr 1fr; gap: 56px; }
  .grid-2.lean { grid-template-columns: 1.05fr 0.95fr; }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- type helpers ---------- */

.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gold-ink);
}
.eyebrow::before { content: ""; width: 26px; height: 2px; background: var(--gold); flex: none; }

.lead { font-size: 1.06rem; line-height: 1.65; color: var(--body); max-width: 56ch; }
.note { font-size: 0.82rem; line-height: 1.5; color: var(--muted); }
.tag {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--gold-ink);
}
.section-head { max-width: 54ch; margin-bottom: 36px; display: flex; flex-direction: column; gap: 14px; }

/* ---------- header ---------- */

.site-header { border-bottom: 1px solid var(--line); background: #fff; }
.site-header .container {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; min-height: 76px;
  padding-block: 12px;
}

.brand { display: flex; align-items: center; gap: 11px; color: var(--ink); }
.brand img { width: 42px; height: 42px; border-radius: 50%; flex: none; }
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-name {
  font-family: var(--font-display); font-weight: 700; font-size: 1.06rem;
  color: var(--navy); letter-spacing: 0.04em;
}
.brand-sub {
  font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-ink); font-weight: 600;
}

.site-nav {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px;
  width: 100%; order: 3; padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.site-nav .navlink {
  font-size: 0.94rem; color: var(--body); font-weight: 500; padding-block: 6px;
  border-bottom: 2px solid transparent;
}
.site-nav .navlink:hover { color: var(--ink); }
.site-nav .navlink[aria-current="page"] { color: var(--navy); border-bottom-color: var(--gold); }
.site-nav .phone { font-size: 0.94rem; font-weight: 600; color: var(--ink); white-space: nowrap; }
.site-nav .lang {
  font-size: 0.75rem; font-weight: 600; color: var(--muted); letter-spacing: 0.08em;
  border: 1px solid var(--line); border-radius: var(--pill); padding: 6px 11px;
  transition: border-color var(--t), color var(--t);
}
.site-nav .lang:hover { border-color: var(--line-strong); color: var(--navy); }

/* The sticky mobile bar already carries the primary CTA, so drop it here. */
.site-nav .btn { display: none; }
@media (min-width: 880px) {
  .site-nav {
    width: auto; order: 0; margin-left: auto; gap: 26px;
    padding-top: 0; border-top: 0;
  }
  .site-nav .btn { display: inline-flex; }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 12px 24px; border-radius: var(--pill);
  font-family: var(--font-body); font-size: 0.94rem; font-weight: 600;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: background var(--t), border-color var(--t), transform 0.1s ease;
}
/* Specificity high enough to beat contextual link colours (.site-nav a, footer a). */
a.btn, button.btn { text-decoration: none; }
a.btn-primary, button.btn-primary { background: var(--navy); color: #fff; border-color: var(--navy); }
a.btn-primary:hover, button.btn-primary:hover { background: var(--navy-deep); color: #fff; }
a.btn-gold, button.btn-gold { background: var(--gold); color: var(--ink); border-color: var(--gold); }
a.btn-gold:hover, button.btn-gold:hover { background: var(--gold-deep); color: var(--ink); }
a.btn-ghost, button.btn-ghost { background: #fff; color: var(--ink); border-color: var(--line); }
a.btn-ghost:hover, button.btn-ghost:hover { border-color: var(--navy); color: var(--navy); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; }
.btn-lg { min-height: 52px; padding-inline: 30px; font-size: 1rem; }

/* ---------- hero ---------- */

.hero { padding-block: clamp(48px, 7vw, 80px) var(--section); }
.hero h1 { margin-block: 4px 0; }

.pathcards { display: grid; gap: 14px; grid-template-columns: 1fr; margin-top: 8px; }
@media (min-width: 560px) { .pathcards { grid-template-columns: 1fr 1fr; } }

.pathcard {
  display: flex; flex-direction: column; gap: 6px;
  padding: 20px; border: 1px solid var(--line); border-radius: var(--radius);
  background: #fff; color: var(--ink); box-shadow: var(--shadow-sm);
  transition: border-color var(--t), box-shadow var(--t), transform var(--t);
}
.pathcard:hover { border-color: var(--navy); box-shadow: var(--shadow); transform: translateY(-2px); color: var(--ink); }
.pathcard strong { font-family: var(--font-display); font-size: 1rem; }
.pathcard span { font-size: 0.88rem; color: var(--body); line-height: 1.5; }
.pathcard em { font-style: normal; font-size: 0.88rem; font-weight: 600; color: var(--navy); margin-top: 4px; }
.pathcard--lead { border-color: var(--navy); box-shadow: var(--accent-top), var(--shadow-sm); }

/* Photo slots: a quiet panel, not a pattern. No gold edge, unlike the cards:
   a straight bar cannot follow the corner radius, and the accent means more
   when it marks a highlighted card only. */
.photo {
  position: relative; border-radius: var(--radius-lg); background: var(--cream);
  border: 1px solid var(--cream-line); aspect-ratio: 4 / 3;
  display: grid; place-items: center; overflow: hidden;
}
.photo--wide { aspect-ratio: 16 / 10; }
.photo--strip { aspect-ratio: 21 / 9; }
.photo img { width: 100%; height: 100%; object-fit: cover; }

/* Hero photos are cropped square, so the near-square hero box loses almost
   nothing to object-fit. Narrow screens show the square whole. */
.hero .photo { aspect-ratio: 1 / 1; }
@media (min-width: 880px) {
  .hero .grid-2 { align-items: stretch; }
  .hero .stack { justify-content: center; }
  .hero .photo { aspect-ratio: auto; height: 100%; min-height: 440px; }
  .hero .photo img { object-position: 50% 50%; }
}

/* Narrow screens lead with the photo, like the sections above it. */
@media (max-width: 879px) {
  #apres-travaux .photo,
  #equipe .photo { order: -1; }
}

/* ---------- before / after pair ---------- */

.ba { display: grid; gap: 22px; grid-template-columns: 1fr; margin-top: 44px; }
@media (min-width: 720px) { .ba { grid-template-columns: 1fr 1fr; gap: 26px; } }
.ba figure { margin: 0; }
.ba .photo { aspect-ratio: 4 / 3; }
.ba figcaption {
  display: flex; align-items: center; gap: 11px; margin-top: 13px;
  font-size: 0.88rem; color: var(--body); line-height: 1.45;
}
.ba-tag {
  flex: none; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.13em;
  text-transform: uppercase; padding: 5px 12px; border-radius: var(--pill);
  background: #fff; border: 1px solid var(--line); color: var(--muted);
}
.ba-tag--after { background: var(--navy); border-color: var(--navy); color: #fff; }

/* ---------- trust strip ---------- */

.trust { display: grid; gap: 14px; grid-template-columns: 1fr; padding-block: 22px; }
@media (min-width: 720px) { .trust { grid-template-columns: repeat(4, 1fr); gap: 20px; } }
.trust-item { display: flex; align-items: center; gap: 11px; font-size: 0.88rem; color: var(--on-navy); }
.trust-badge {
  width: 32px; height: 32px; border-radius: 50%; border: 1.5px solid var(--gold);
  display: grid; place-items: center; flex: none; color: var(--gold);
}
.trust-badge svg { width: 15px; height: 15px; }

/* ---------- cards ---------- */

.card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 24px; display: flex; flex-direction: column; gap: 10px;
  box-shadow: var(--shadow-sm); transition: border-color var(--t), box-shadow var(--t);
}
.card:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.card p { font-size: 0.88rem; color: var(--body); line-height: 1.55; }
.card .tag { margin-top: auto; padding-top: 4px; }
.card--feature { border-color: var(--navy); box-shadow: var(--accent-top), var(--shadow-sm); }

/* The gold top edge marks the one card picked out of a group of peers, so only
   .pathcard--lead and .card--feature carry it. It is an inset shadow, not a
   border-top, so it follows the corner radius. The price panel has no peers to
   stand out from: it gets the navy frame alone. */

.icon-dot {
  width: 42px; height: 42px; border-radius: 50%; background: var(--cream);
  border: 1px solid var(--cream-line); display: grid; place-items: center; color: var(--navy);
  margin-bottom: 4px;
}
.icon-dot svg { width: 19px; height: 19px; }

.tick-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.tick-list li { display: flex; gap: 10px; align-items: flex-start; font-size: 0.94rem; color: var(--body); }
.tick-list svg { width: 17px; height: 17px; color: var(--gold); flex: none; margin-top: 4px; }

.step { display: flex; flex-direction: column; gap: 10px; }
.step-num {
  width: 46px; height: 46px; border-radius: 50%; border: 1.5px solid var(--gold);
  display: grid; place-items: center; font-family: var(--font-display);
  font-weight: 700; font-size: 0.94rem; color: var(--navy); margin-bottom: 4px;
}
.step p { font-size: 0.94rem; color: var(--body); line-height: 1.55; }

/* ---------- CTA band ---------- */

.cta {
  background: var(--navy); color: #fff; border-radius: var(--radius-lg);
  padding: clamp(28px, 4vw, 44px); display: flex; flex-wrap: wrap; gap: 24px;
  align-items: center; justify-content: space-between; border: 1px solid var(--navy);
}
.cta h2 { color: #fff; max-width: 22ch; }
.cta p { color: var(--on-navy-soft); font-size: 1rem; max-width: 46ch; margin-top: 8px; }

/* ---------- forms ---------- */

.field { display: flex; flex-direction: column; gap: 7px; margin-bottom: 18px; }
.field > label, .field-label { font-size: 0.82rem; font-weight: 600; color: var(--body); }
.field-group { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 620px) { .field-group { grid-template-columns: 1fr 1fr; } }

/* `input:not([type])` is load-bearing, not a flourish. A bare `<input>` is a text
   input to the browser but does NOT match `input[type="text"]`, and every field on
   /admin/tarifs is written bare -- the eight in the markup and every one rates.js
   generates. Without this line the whole rate-card screen rendered in the browser's
   default control style: Arial digits, pure black, square 2px inset borders, in the
   middle of a page set in Karla with 10px radii. It read as a design problem and was
   really a selector that never matched. */
input:not([type]),
input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
input[type="date"], input[type="password"], select, textarea {
  width: 100%; min-height: 46px; padding: 11px 13px; font: inherit; font-size: 16px;
  color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: var(--radius-sm);
  transition: border-color var(--t), box-shadow var(--t);
}
input:focus, select:focus, textarea:focus {
  border-color: var(--navy); box-shadow: 0 0 0 3px rgba(29, 57, 110, 0.1); outline: none;
}
textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%236b7686' stroke-width='1.8'%3E%3Cpath d='M1 1l5 5 5-5'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 36px; }

.choice-row { display: flex; flex-wrap: wrap; gap: 10px; }
.choice {
  position: relative; display: inline-flex; align-items: center; min-height: 46px;
  padding: 11px 18px; border: 1px solid var(--line); border-radius: var(--pill);
  cursor: pointer; font-size: 0.94rem; color: var(--body); background: #fff;
  transition: border-color var(--t), background var(--t), color var(--t);
}
.choice:hover { border-color: var(--line-strong); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice:has(input:checked) {
  border-color: var(--navy); background: var(--cream); color: var(--navy); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--navy);
}
.choice:has(input:focus-visible) { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Extras: one row each, because an extra can carry a quantity and a unit price.
   The list is rendered from the active rate card, so nothing here names one. */
.extras { display: grid; gap: 10px; }
.extra { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.extra .choice { flex: 1 1 260px; justify-content: space-between; gap: 16px; }
/* With a quantity column in play, every row shares the same two tracks, so the
   pills line up whether or not that row has a stepper. */
/* Only from 620px up: on a phone a pill and a stepper side by side leave the
   label two words per line and the two controls touching. There, the quantity
   goes under the extra it belongs to and both run the full width. */
@media (min-width: 620px) {
  @supports (grid-template-columns: subgrid) {
    .extras[data-steppers] { grid-template-columns: minmax(0, 1fr) auto; }
    .extras[data-steppers] .extra {
      display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center;
    }
    .extras[data-steppers] .extra .choice { flex: none; }
    .extras[data-steppers] .extra-note { grid-column: 1 / -1; }
  }
}
@media (max-width: 619px) {
  .extra .choice { flex: 1 1 100%; }
  .extra .stepper { width: 100%; }
  .extra .stepper .stepper-input { flex: 1 1 auto; width: auto; }
}
.extra-price { color: var(--muted); font-size: 0.88rem; font-weight: 500; white-space: nowrap; }
.choice:has(input:checked) .extra-price { color: var(--gold-ink); }
.extra-note { flex: 1 1 100%; margin: 0; padding-left: 18px; font-size: 0.82rem; color: var(--muted); }
.extra[data-on="no"] .extra-note { display: none; }
.field[data-empty] { display: none; }

.stepper {
  display: inline-flex; align-items: stretch; height: 46px; flex: none;
  border: 1px solid var(--line); border-radius: var(--pill); background: #fff; overflow: hidden;
  transition: border-color var(--t), box-shadow var(--t);
}
.stepper:focus-within { border-color: var(--navy); box-shadow: 0 0 0 3px rgba(29, 57, 110, 0.1); }
.stepper-btn {
  width: 42px; border: 0; background: transparent; cursor: pointer;
  color: var(--navy); font-size: 1.06rem; line-height: 1; padding: 0;
  transition: background var(--t);
}
.stepper-btn:hover { background: var(--cream); }
.stepper .stepper-input {
  width: 56px; min-height: 0; padding: 0; text-align: center;
  font-weight: 600; color: var(--navy);
  border: 0; border-inline: 1px solid var(--line); border-radius: 0;
  -moz-appearance: textfield; appearance: textfield;
}
.stepper .stepper-input::-webkit-outer-spin-button,
.stepper .stepper-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper .stepper-input:focus { border-color: var(--line); box-shadow: none; }

.line-qty { color: var(--muted); font-weight: 500; }

.checkbox-row { display: flex; align-items: flex-start; gap: 11px; font-size: 0.94rem; margin-bottom: 18px; color: var(--body); }
.checkbox-row input { width: 19px; height: 19px; margin-top: 2px; accent-color: var(--navy); flex: none; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* A button that reads as a link: used inside an error message, where a full
   button would shout louder than the sentence it belongs to. */
.linkbtn {
  border: 0; background: none; padding: 0; margin-left: 4px;
  font: inherit; color: inherit; text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer; font-weight: 600;
}
.linkbtn:hover { text-decoration: none; }

.alert { background: #fef3f2; color: var(--danger); border: 1px solid #fecdc9; border-radius: var(--radius-sm); padding: 13px 15px; font-size: 0.88rem; margin-bottom: 16px; }

.steps { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 28px; }
.step-pill {
  border: 1px solid var(--line); border-radius: var(--pill); padding: 10px 16px;
  font-size: 0.82rem; font-weight: 600; color: var(--muted); background: #fff;
  font-family: inherit; transition: border-color var(--t), color var(--t), background var(--t);
}
/* A step you have already completed is a way back; one you have not reached is not
   a control at all, so it does not pretend to be clickable. */
.step-pill[data-state="done"] { cursor: pointer; color: var(--navy); border-color: var(--line-strong); }
.step-pill[data-state="done"]:hover { border-color: var(--navy); background: var(--cream); }
.step-pill[data-state="locked"] { cursor: default; opacity: 0.55; }
.step-pill[aria-current="step"] {
  background: var(--navy); border-color: var(--navy); color: #fff; cursor: default; opacity: 1;
}
.step-pill[data-state="done"]::before {
  content: ""; display: inline-block; width: 13px; height: 13px; margin-right: 7px;
  vertical-align: -2px; background: currentColor;
  -webkit-mask: var(--tick) center / contain no-repeat; mask: var(--tick) center / contain no-repeat;
}
fieldset.wizard-step { border: 0; padding: 0; margin: 0; min-width: 0; }
.wizard-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }

/* ---------- property type tiles ---------- */

.typegroups { display: grid; gap: 20px; margin-top: 6px; }
.typegroup-label {
  display: block; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gold-ink); margin-bottom: 9px;
}
.tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (min-width: 520px) { .tiles { grid-template-columns: repeat(3, 1fr); } }
.tile {
  position: relative; display: flex; flex-direction: column; align-items: stretch;
  padding: 0; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: #fff; cursor: pointer; font-size: 0.88rem; font-weight: 500; color: var(--ink);
  transition: border-color var(--t), box-shadow var(--t);
}
.tile input { position: absolute; opacity: 0; width: 0; height: 0; }
/* The illustration sits on its own cream panel; object-fit keeps it centred. */
.tile img {
  display: block; width: 100%; height: 80px; object-fit: contain;
  padding: 10px 0; background: var(--cream); border-bottom: 1px solid var(--cream-line);
}
@media (min-width: 520px) { .tile img { height: 100px; padding: 12px 0; } }
.tile span { padding: 11px 13px; }
.tile:hover { border-color: var(--line-strong); }
.tile:has(input:checked) { border-color: var(--navy); box-shadow: inset 0 0 0 1px var(--navy); }
/* Gold check, because a border alone is easy to miss on an illustrated card. */
.tile:has(input:checked)::after {
  content: ""; position: absolute; top: 8px; right: 8px; width: 19px; height: 19px;
  border-radius: 50%; background: var(--gold) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 11px 11px no-repeat;
  box-shadow: 0 1px 3px rgba(15, 23, 40, 0.18);
}
.tile:has(input:focus-visible) { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ---------- inline field errors ---------- */

.field-error { font-size: 0.82rem; color: var(--danger); margin-top: 7px; }
.field input[aria-invalid="true"], .field select[aria-invalid="true"] { border-color: var(--danger); }

/* ---------- running price bar (small screens) ---------- */

.pricebar {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 30;
  display: none; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px 16px calc(11px + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, 0.97); border-top: 1px solid var(--line);
  backdrop-filter: blur(8px);
}
.pricebar-label { font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.pricebar-value { font-family: var(--font-display); font-size: 1.25rem; font-weight: 700; color: var(--navy); }
.pricebar-value.is-text { font-family: var(--font-body); font-size: 0.88rem; font-weight: 600; line-height: 1.3; }
@media (max-width: 879px) {
    .pricebar { display: flex; }
}

.summary {
  border: 1px solid var(--navy); border-radius: var(--radius);
  padding: 24px; display: flex; flex-direction: column; gap: 14px;
  background: #fff; box-shadow: var(--shadow);
  align-self: start; position: sticky; top: 24px;
}
.price { font-family: var(--font-display); font-size: 2.4rem; font-weight: 700; color: var(--navy); line-height: 1.1; }
.summary-line { display: flex; justify-content: space-between; gap: 16px; font-size: 0.88rem; }
.summary-line span:first-child { color: var(--body); }
.summary-line.subtotal {
  margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--line-soft); font-weight: 600;
}
.summary hr { border: 0; border-top: 1px solid var(--line); margin: 2px 0; }
/* Tapping this to call should not need a precise finger. */
.summary a[href^="tel:"] { display: inline-block; padding-block: 7px; }

/* ---------- footer ---------- */

.site-footer { border-top: 3px solid var(--gold); background: var(--surface-soft); padding-block: 48px 28px; }
.footer-grid { display: grid; gap: 32px; grid-template-columns: 1fr; }
@media (min-width: 880px) { .footer-grid { grid-template-columns: 1.6fr 1fr 1fr 1.2fr; gap: 40px; } }
.footer-col { display: flex; flex-direction: column; gap: 9px; font-size: 0.88rem; }
.footer-col h4 { font-family: var(--font-body); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold-ink); margin: 0 0 2px; }
.footer-col a:not(.btn) { color: var(--navy); padding-block: 4px; }
.footer-col a:not(.btn):hover { color: var(--navy-deep); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 879px) { .footer-col a:not(.btn), .footer-bottom a { padding-block: 7px; } }
.footer-col p { font-size: 0.88rem; color: var(--body); line-height: 1.6; }
.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between;
  border-top: 1px solid var(--line); margin-top: 32px; padding-top: 18px;
  font-size: 0.82rem; color: var(--muted);
}
.footer-bottom a { color: var(--muted); display: inline-block; padding-block: 6px; }

/* ---------- mobile call bar ---------- */

.callbar {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 30;
  display: flex; gap: 10px; padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, 0.97); border-top: 1px solid var(--line);
  backdrop-filter: blur(8px);
}
.callbar .btn { flex: 1; min-height: 48px; }
@media (min-width: 880px) { .callbar { display: none; } }
@media (max-width: 879px) { body { padding-bottom: 82px; } }

/* ---------- admin ---------- */

/* Wider than the site. --max is a reading measure for prose; the admin is a
   data screen, and at 1140px the three columns left the price matrix 438px --
   22px short of its own minimum, so it scrolled sideways inside its card. */
.admin-wrap { padding-block: 40px; max-width: 1400px; }
.stat-row { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 24px; }
.stat { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 20px; min-width: 116px; background: #fff; box-shadow: var(--shadow-sm); }
.stat b { display: block; font-family: var(--font-display); font-size: 1.5rem; color: var(--navy); }
.stat span { font-size: 0.75rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: #fff; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; min-width: 900px; }
.admin-table th, .admin-table td { text-align: left; padding: 13px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.admin-table thead th { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); background: var(--surface-soft); position: sticky; top: 0; }
.admin-table tbody tr:hover { background: var(--surface-soft); }
.admin-table input, .admin-table select { min-height: 38px; font-size: 0.88rem; padding: 6px 10px; }

.chip { display: inline-block; padding: 3px 11px; border-radius: var(--pill); font-size: 0.75rem; font-weight: 600; background: var(--cream); color: var(--gold-ink); }
.chip--new { background: #eef4ff; color: var(--navy); }
.chip--quoted { background: #fff6e5; color: var(--gold-ink); }
.chip--won { background: #ecfdf3; color: var(--ok); }
.chip--lost { background: #fef3f2; color: var(--danger); }

/* The status control. It reads as the chip it replaces and it is the chip: the
   row used to carry a chip AND a select under it, both showing the same value,
   in the narrowest column on the screen. `width: auto` sizes every one of them
   to the longest label, so the column stays a straight edge down the table. */
.statuspick {
  /* Fixed, not auto: Chrome sizes an appearance:none select from the option text
     alone and ignores the padding the caret sits in, so the caret landed on top
     of the last letter. A set width also keeps the column a straight edge. */
  appearance: none; width: 108px; min-height: 32px;
  padding: 5px 28px 5px 13px; border-radius: var(--pill);
  border: 1px solid transparent;
  font-family: inherit; font-size: 0.75rem; font-weight: 600; line-height: 1.3;
  cursor: pointer;
  background-position: right 11px center;
  transition: border-color var(--t), background-color var(--t);
}
.statuspick[data-status="new"] { background-color: #eef4ff; color: var(--navy); border-color: #d7e3fb; }
.statuspick[data-status="quoted"] { background-color: #fff6e5; color: var(--gold-ink); border-color: var(--cream-line); }
.statuspick[data-status="won"] { background-color: #ecfdf3; color: var(--ok); border-color: #c3ecd6; }
.statuspick[data-status="lost"] { background-color: #fef3f2; color: var(--danger); border-color: #fecdc9; }
.statuspick:hover { border-color: var(--line-strong); }
.statuspick:focus { box-shadow: 0 0 0 3px rgba(29, 57, 110, 0.12); }

/* No price yet: a queue, not a blank. */
.todo { color: var(--gold-ink); font-size: 0.82rem; font-weight: 600; }

/* The tallies. `data-status=""` is the Total tile, which stays plain. */
.stat[data-status="new"] b { color: var(--navy); }
.stat[data-status="quoted"] b { color: var(--gold-ink); }
.stat[data-status="won"] b { color: var(--ok); }

/* A row that just saved. Brief, because the point is "that landed", not applause. */
.admin-table tr.saved > td { background: #f2fbf6; transition: background 0.9s ease; }

/* Extras on a request row. Not `.tag`, which is the public site's eyebrow label. */
.need-tags { display: inline-flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
/* An answer about the job, not a thing added to it: navy rather than gold, so
   the two read as different kinds of fact at a glance. */
.need-tag--mod { background: #eef4ff; border-color: #d7e3fb; color: var(--navy); }
.need-tag {
  padding: 2px 9px; border-radius: var(--pill); background: var(--cream);
  border: 1px solid var(--cream-line); color: var(--gold-ink);
  font-size: 0.75rem; font-weight: 600; white-space: nowrap;
}

/* ---------- admin sign-in ---------- */

.admin-body { background: var(--cream); }

/* ---------- the admin type scale ----------

   The site is set at 17px because it is prose: a reading measure, generous
   leading, headings that carry a page. The admin is a control surface -- nine
   rows of one number each -- and it was borrowing the prose sizes, which is why
   it read flat. Measured, everything on /admin/tarifs sat between 9.9px and 17px
   with a 32px title above it: a section heading the same size as body text, a
   label two points from its own hint, and the number -- the only thing on the
   screen that matters -- smaller than the button beside it.

   So: px, not rem. These are control sizes and must not drift with a reading
   measure. Five steps, each far enough from the next to be read as a different
   level, and the VALUE outranks its own label, because on this screen the value
   is the content and the label is the chrome. */
/* On `.admin-body`, not `.admin-wrap`: the publish dialog is a sibling of <main>
   rather than a descendant, and it lists money too. Keyed to the wrap it inherited
   none of this and quietly fell back to the prose sizes. */
.admin-body {
  --fs-title: 26px;   /* the page's one h1 */
  --fs-head: 15px;    /* a card's heading */
  --fs-value: 15px;   /* what you type -- and what you came to read */
  --fs-label: 13.5px; /* the name of the thing */
  --fs-hint: 12px;    /* descriptions and computed consequences */
  --fs-micro: 11px;   /* rail groups, column heads, badges */
}

/* A tool screen, not a landing page. This was an inline `font-size:2rem` on the
   h1 of both admin pages, patching over the site's hero clamp; it belongs here,
   once, where the rest of the scale lives. */
.admin-wrap > .section-head { margin-bottom: 20px; }
.admin-wrap > .section-head h1 {
  font-size: var(--fs-title); line-height: 1.15; letter-spacing: -0.02em;
}
.admin-wrap > .section-head .lead { font-size: 14px; line-height: 1.5; max-width: 62ch; }

/* Digits in a column have to line up, or a 4 next to a 1 looks like a different
   magnitude. Every field on this screen holds a number. */
.admin-body input, .admin-body .derived, .admin-body .was, .admin-body .stat b,
.admin-body .money, .admin-body .admin-table td {
  font-variant-numeric: tabular-nums;
}

.rate-layout { display: grid; gap: 22px; grid-template-columns: 1fr; align-items: start; }
/* 1200, not 1080: between the two, three columns left the price matrix below
   its own minimum width and it scrolled sideways inside its card. Under this the
   rail lies down and the editor takes the full width. */
@media (min-width: 1200px) {
  /* Rail, editor, tester. The rail earns its column because the editor is one
     section at a time now: the page used to be a single scroll through eight
     boxes, and every later phase adds another. */
  .rate-layout { grid-template-columns: 208px minmax(0, 1fr) minmax(300px, 340px); gap: 28px; }
}
.rate-col { min-width: 0; }

.rail { display: flex; flex-direction: column; gap: 2px; }
/* These four words are the map of the whole screen -- they say which part of the
   pricing you are standing in -- and they were the smallest, faintest type on the
   page at 0.62rem (9.9px) in muted grey. Uppercase that small with 0.16em tracking
   is also past the point where the letterforms stay distinguishable. Now they
   outrank the items they head: 12px, 700, in ink, with the tracking eased off
   because size and weight already do the work that tracking was compensating for. */
.rail-group {
  font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink); font-weight: 700; margin: 22px 0 7px 13px;
}
.rail-group:first-child { margin-top: 0; }
.rail-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; text-align: left; font-family: inherit; font-size: var(--fs-label);
  padding: 9px 13px; border: 1px solid transparent; border-radius: var(--pill);
  background: transparent; color: var(--body); cursor: pointer;
  transition: background var(--t), color var(--t);
}
.rail-item:hover { background: #fff; color: var(--ink); }
.rail-item[aria-current="true"] {
  background: var(--navy); color: #fff; font-weight: 600;
}
/* Replaces `.rail-badge`, which showed a number. See renderRail in rates.js for
   why the number was wrong; here it is enough to say the dot means "edited, not
   yet published" and needs no reading. */
.rail-dot {
  flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--gold); box-shadow: 0 0 0 3px rgba(201, 153, 46, 0.18);
}
.rail-item[aria-current="true"] .rail-dot {
  background: #fff; box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.25);
}

/* Under the three-column breakpoint the rail lies down and scrolls sideways,
   which keeps every section one tap away without eating a screen of height. */
@media (max-width: 1199px) {
  .rail {
    flex-direction: row; gap: 8px; overflow-x: auto; padding-bottom: 4px;
    scrollbar-width: thin;
  }
  .rail-group { display: none; }
  .rail-item { width: auto; white-space: nowrap; border-color: var(--line); background: #fff; }
}
.rate-box {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 22px 24px; box-shadow: var(--shadow-sm); margin-bottom: 18px;
}
.rate-box[data-section] { margin-bottom: 0; }
.rate-box > h2 { font-size: var(--fs-head); line-height: 1.3; margin-bottom: 3px; }
.rate-box > .note { font-size: var(--fs-hint); margin-bottom: 14px; }

/* table-layout: fixed. With auto layout the columns are sized by content, so a
   bathroom count with no price in any row -- every cell just a "+ ajouter"
   button -- collapsed to 66px against its neighbours' 156px and the label wrapped
   onto two lines. Fixed layout gives every bathroom column the same width
   whether or not anything in it is priced. */
.grid-matrix {
  width: 100%; border-collapse: collapse; font-size: 0.88rem; min-width: 460px;
  table-layout: fixed;
}
.grid-matrix th:first-child, .grid-matrix .corner { width: 94px; }
.grid-matrix th {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted);
  font-weight: 600; padding: 0 8px 9px; text-align: center;
}
/* Each axis named once, quietly, instead of "sdb" repeated across the top and
   "chambres" down the side with an empty corner explaining neither. */
.grid-matrix .axis { color: var(--gold-ink); }
.grid-matrix .corner { border: 0; background: transparent; padding: 0; }
/* The counts are headings for their row, so they sit tight against it. */
.grid-matrix tbody th {
  font-size: var(--fs-label); font-weight: 600; color: var(--ink); text-transform: none;
  letter-spacing: 0; text-align: right; padding: 4px 14px 4px 0; white-space: nowrap;
}
.grid-matrix td { padding: 4px; }
.grid-matrix td:first-child { font-weight: 600; white-space: nowrap; padding-right: 12px; }
.cell { position: relative; }
.cell input {
  width: 100%; min-height: 38px; text-align: right; padding: 6px 26px 6px 10px;
  font-size: var(--fs-value); font-weight: 600; color: var(--ink);
}
.cell input.bad { border-color: var(--danger); }
.cell.changed input { border-color: var(--navy); }
.cell-remove {
  position: absolute; right: 8px; top: 12px; width: 17px; height: 17px; line-height: 15px;
  border: 0; border-radius: 50%; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 0.94rem; padding: 0; opacity: 0;
  transition: opacity var(--t), color var(--t);
}
.cell:hover .cell-remove, .cell input:focus + .cell-remove { opacity: 1; }
.cell-remove:hover { color: var(--danger); }
.was { display: block; font-size: 0.68rem; color: var(--muted); text-align: right; margin-top: 3px; }
.cell.empty button {
  width: 100%; min-height: 40px; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
  background: transparent; color: var(--muted); font-size: 0.75rem; cursor: pointer;
  font-family: inherit; transition: border-color var(--t), color var(--t);
}
.cell.empty button:hover { border-color: var(--navy); color: var(--navy); }

/* Three columns on one line: the name, what the number works out to, the number.

   The computed hint used to sit under the label, which put an effect in the
   column of causes -- nine gold lines stacked under nine names, each describing a
   figure three inches to its right. Moving it under its own field was worse: the
   row grew to 113px to hold a single digit, and the hint ended up nearer the NEXT
   row's label than its own.

   Beside the field it is unambiguous, adjacent to what it is derived from, and
   the row collapses to one line. `auto` on the middle column so it takes only the
   width of its sentence and gives the rest back to the label. */
.pair-row {
  display: grid; grid-template-columns: 1fr auto 118px; gap: 8px 14px; align-items: center;
  padding: 9px 0; border-bottom: 1px solid var(--line-soft);
}
.pair-row:last-child { border-bottom: 0; }
.pair-row label {
  display: block; font-size: var(--fs-label); font-weight: 500;
  line-height: 1.35; color: var(--ink);
}
.pair-row .note { font-size: var(--fs-hint); line-height: 1.4; margin-top: 3px; }
.pair-row input {
  grid-column: 3; min-height: 38px; text-align: right; padding: 7px 11px;
  font-size: var(--fs-value); font-weight: 600; color: var(--ink);
}
.pair-row input.bad { border-color: var(--danger); }
.pair-row .derived { grid-column: 2; text-align: right; white-space: nowrap; }

/* Narrow: the hint has nowhere to sit beside a field, so it goes back under the
   label -- where, with only one row's worth of content on screen at a time, the
   ambiguity that ruled it out on the desktop layout does not arise. */
@media (max-width: 560px) {
  .pair-row { grid-template-columns: 1fr 118px; }
  .pair-row .derived { grid-column: 1; text-align: left; }
}

/* The admin scale is declared on `.admin-wrap`, and `.derived` only ever appears
   inside it -- but the fallback keeps this rule honest if it is ever reused. */
.derived { color: var(--gold-ink); font-weight: 600; font-size: var(--fs-hint, 0.75rem); }

/* One extra: its name, its price, what the price is per, and a worked example.
   Not a .pair-row, because an extra is four fields rather than one. */
.extra-edit { padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
.extra-edit:last-of-type { border-bottom: 0; }
/* `minmax(0, 320px)` on the name, not `1fr`. With `1fr` the name field took every
   pixel the other three did not want -- a 540px box holding the word "Plinthes",
   four times the width of the price beside it and the widest thing in the card,
   for the least consequential field in the row. It is a short label; give it a
   short field and let the row end where the controls end. */
.extra-edit-main {
  display: grid; grid-template-columns: minmax(0, 320px) 104px 128px 34px;
  gap: 8px; align-items: center;
}
.extra-more { margin-top: 6px; }
.extra-more > summary {
  display: inline-block; cursor: pointer; list-style: none;
  font-size: var(--fs-hint); color: var(--muted); padding: 2px 0;
}
.extra-more > summary::-webkit-details-marker { display: none; }
.extra-more > summary::before { content: "▸ "; }
.extra-more[open] > summary::before { content: "▾ "; }
.extra-more > summary:hover { color: var(--navy); }
.extra-edit-more { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.extra-edit-more input { flex: 1 1 140px; min-width: 0; }
.extra-edit input, .extra-edit select {
  min-height: 38px; font-size: var(--fs-label); padding: 6px 10px; color: var(--ink);
}
/* 600 and right-aligned is the treatment for a NUMBER. A name is prose: it reads
   left to right at label weight, so the eye can tell at a glance which fields on
   this row it is meant to compare. */
.extra-edit input[data-kind="money"] {
  text-align: right; font-size: var(--fs-value); font-weight: 600;
}
.extra-edit input.bad { border-color: var(--danger); }
.extra-edit .extra-name-input { font-weight: 500; color: var(--ink); }
.extra-edit > .note { font-size: var(--fs-hint); margin-top: 6px; }
.extra-del {
  min-height: 40px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: #fff; color: var(--muted); cursor: pointer; font-size: 1.06rem; line-height: 1;
  transition: border-color var(--t), color var(--t);
}
.extra-del:hover { border-color: var(--danger); color: var(--danger); }
/* A modifier: the question, then one row per answer with its two knobs and the
   worked example. Four columns, because "× 1,4" is not checkable on its own. */
.mod-edit { padding: 15px 0; border-bottom: 1px solid var(--line-soft); }
.mod-edit:last-of-type { border-bottom: 0; }
/* Capped, like the extras name: a question is longer than a label but it is
   still a sentence, not a paragraph, and a field spanning the whole card reads as
   the most important thing on it. */
.mod-head {
  display: grid; grid-template-columns: minmax(0, 560px) 34px; gap: 8px; align-items: center;
}
.mod-name { font-weight: 500; color: var(--ink); font-size: var(--fs-label); }
.mod-edit input, .mod-edit select {
  min-height: 38px; font-size: var(--fs-label); padding: 6px 10px; color: var(--ink);
}
/* Same rule as the extras: the two knobs are numbers and wear the number
   treatment; the answer text beside them is prose and does not. */
.mod-opt input[data-kind] { font-size: var(--fs-value); font-weight: 600; }
.mod-opts { margin-top: 9px; display: grid; gap: 6px; }
.mod-opt {
  display: grid; grid-template-columns: minmax(0, 1.4fr) 96px 104px minmax(0, 1.2fr);
  gap: 14px; align-items: center;
}
.mod-opt input[data-kind] { text-align: right; }
.mod-opt--head span {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--muted); font-weight: 600;
}
.mod-opt--head span:nth-child(2), .mod-opt--head span:nth-child(3) { text-align: right; }
.mod-opt .derived { font-size: var(--fs-hint); }
.mod-edit .extra-more { margin-top: 10px; }
@media (max-width: 719px) {
  .mod-opt { grid-template-columns: 1fr 1fr; }
  .mod-opt--head { display: none; }
  .mod-opt .derived { grid-column: 1 / -1; }
}

/* An empty section has to explain itself: a worked example beats a paragraph
   about what the feature does. */
.empty-state { padding: 4px 0 2px; }
.empty-state > p { font-size: var(--fs-label); line-height: 1.55; color: var(--body); }
.empty-example {
  margin-top: 12px; padding: 14px 16px; border-radius: var(--radius-sm);
  background: var(--cream); border: 1px solid var(--cream-line);
}
.empty-example > .note { display: block; margin-bottom: 4px; }
.empty-example p { font-size: var(--fs-label); color: var(--body); line-height: 1.6; }
.empty-example em { font-style: normal; font-weight: 600; color: var(--ink); }

.extra-add { padding-top: 13px; }
.extra-add button {
  min-height: 40px; padding: 0 16px; border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm); background: transparent; color: var(--muted);
  font-family: inherit; font-size: var(--fs-label); cursor: pointer;
  transition: border-color var(--t), color var(--t);
}
.extra-add button:hover { border-color: var(--navy); color: var(--navy); }
@media (max-width: 719px) {
  .extra-edit-main { grid-template-columns: 1fr 1fr; }
  .extra-edit-main .extra-name-input { grid-column: 1 / -1; }
}

.draftbar {
  position: sticky; top: 0; z-index: 20; background: rgba(255, 255, 255, 0.97);
  backdrop-filter: blur(8px); border-bottom: 1px solid var(--line);
}
.draftbar .container { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding-block: 12px; }
.draftbar-grow { flex: 1 1 auto; min-width: 200px; }
.draftbar-title { font-family: var(--font-display); font-weight: 700; color: var(--navy); font-size: 0.94rem; margin-right: 8px; }

.tester {
  position: sticky; top: 84px; background: #fff; border: 1px solid var(--navy);
  border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow);
}
/* A <button> now, not a <div>: it was unreachable by keyboard, and the selected
   one was marked by colour alone. */
.scenario {
  display: block; width: 100%; text-align: left; font-family: inherit; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px;
  margin-bottom: 9px; cursor: pointer; background: #fff;
  transition: border-color var(--t), background var(--t);
}
.scenario:hover { border-color: var(--line-strong); }
.scenario.on { border-color: var(--navy); background: var(--cream); box-shadow: inset 0 0 0 1px var(--navy); }
/* Not colour alone: the chosen scenario says so. */
.scenario.on b::after { content: " ✓"; color: var(--gold-ink); }
.scenario b { display: block; font-size: 0.88rem; }
.scenario span { font-size: 0.75rem; color: var(--muted); }
.delta {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--line-soft); font-size: 0.88rem;
}
.delta:last-of-type { border-bottom: 0; }
.delta b { font-family: var(--font-display); font-size: 1.25rem; color: var(--navy); }
.up { color: var(--ok); font-weight: 600; font-size: 0.82rem; }
.down { color: var(--danger); font-weight: 600; font-size: 0.82rem; }

.warnbox {
  border: 1px solid #fecdc9; background: #fef3f2; color: var(--danger);
  border-radius: var(--radius-sm); padding: 11px 13px; font-size: 0.82rem; margin-top: 14px; line-height: 1.5;
}
.warnbox.amber { border-color: #f5d9a8; background: #fff6e5; color: var(--gold-ink); }

.killrow { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.switch {
  width: 48px; height: 28px; border-radius: var(--pill); border: 0; padding: 0; flex: none;
  background: var(--line-strong); position: relative; cursor: pointer; transition: background var(--t);
}
.switch[aria-checked="true"] { background: var(--ok); }
.switch::after {
  content: ""; position: absolute; left: 3px; top: 3px; width: 22px; height: 22px;
  border-radius: 50%; background: #fff; transition: transform var(--t);
}
.switch[aria-checked="true"]::after { transform: translateX(20px); }

.histrow {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--line-soft); font-size: 0.88rem;
}
.histrow:last-child { border-bottom: 0; }

.modal {
  position: fixed; inset: 0; z-index: 50; background: rgba(15, 23, 40, 0.45);
  display: flex; align-items: center; justify-content: center; padding: 24px;
  overflow-y: auto;
}
.modal-card {
  background: #fff; border-radius: var(--radius); padding: 28px; max-width: 620px; width: 100%;
  box-shadow: var(--shadow-lg); max-height: 90vh; overflow-y: auto;
}
.review-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; margin-top: 10px; }
.review-table td { padding: 8px 6px; border-bottom: 1px solid var(--line-soft); }
.review-table .from { color: var(--muted); text-align: right; }
.review-table .arrow { color: var(--muted); width: 22px; text-align: center; }
.review-table .to { font-weight: 600; color: var(--navy); text-align: right; white-space: nowrap; }
.review-table .to.big { color: var(--gold-ink); }

/* Editing a price matrix on a phone invites the decimal slip this screen exists to
   prevent. Below the two-column breakpoint it reads; the kill switch still works.

   It has to cover every control, not just <input>. The extras editor's unit
   select, its remove buttons and "+ Ajouter un extra" were left live, so a phone
   could retire an extra or change how it is billed -- writing to the same draft
   in localStorage -- but could not type a price, publish, or discard it. That
   left a draft only a desktop could clear. */
@media (max-width: 879px) {
  .rate-box input, .rate-box select, .grid-matrix input { pointer-events: none; background: var(--surface-soft); }
  .cell.empty button, .cell-remove, .extra-del, .extra-add { display: none; }
  .draftbar #publish-btn, .draftbar #discard-btn { display: none; }
  /* The kill switch is a button, not an input, so it was never frozen -- but say
     so, rather than leaving the exemption as a rule that matches nothing. */
  .rate-box.killrow { pointer-events: auto; }
}

.login-screen {
  min-height: 100dvh; display: grid; place-items: center; padding: 32px 20px;
  background:
    radial-gradient(circle at 50% -10%, rgba(29, 57, 110, 0.07), transparent 60%),
    var(--cream);
}
.login-card {
  width: 100%; max-width: 400px; background: #fff; border: 1px solid var(--cream-line);
  border-top: 3px solid var(--gold); border-radius: var(--radius-lg);
  padding: 36px 32px 30px; box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; gap: 4px; text-align: left;
}
.login-card > img { margin: 0 auto 6px; border-radius: 50%; }
.login-head { text-align: center; display: flex; flex-direction: column; margin-bottom: 18px; }
.login-card h1 { font-size: 1.5rem; margin-bottom: 4px; }
.login-card > .note { margin-bottom: 20px; }
.login-card .field { margin-bottom: 16px; }
.login-card a.note { margin-top: 16px; display: block; color: var(--muted); }

/* The offer preview. Monospace and pre-wrapped because this is the literal text
   that will arrive in the client's inbox -- proportional type would reflow it
   into something that reads differently from what gets sent. */
.offer-preview {
  margin: 0; padding: 14px 16px; max-height: 300px; overflow-y: auto;
  background: var(--surface-soft); border: 1px solid var(--line);
  border-radius: var(--radius-sm); white-space: pre-wrap; word-break: break-word;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: var(--fs-hint, 0.75rem); line-height: 1.55; color: var(--ink);
}
.btn-sm { min-height: 34px; padding: 6px 14px; font-size: var(--fs-label, 0.82rem); }
.offer-btn[disabled] { opacity: 0.45; cursor: not-allowed; }
