/* flows.css — cart, devis/quote, personnaliser, orders, brand-card auth
   (split from storefront.css, move-only). */

/* view-level errors (wrong PIN, account exists, invalid input) — must read as an
   error, not a muted price hint. Uses the reserved --action red. */
.alert { color:var(--action); background:#fdece9; border:1px solid var(--action);
  border-radius:var(--radius); padding:.6rem .85rem; font-weight:700; font-size:.9rem;
  margin:.5rem 0; }

/* logo personalization stage — hosts the shared _bag.html bag (size colour
   photo, blank until upload) instead of a static product photo. */
.logo-stage { position:relative; border-radius:var(--radius-lg); overflow:hidden;
  background:#fff; box-shadow:var(--shadow); padding:2rem 0; }
.logo-stage .bag { max-width:340px; margin:0 auto; }

/* cart lines */
.cart-line { display:flex; gap:1rem; align-items:flex-start; background:#fff;
  border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow);
  padding:1rem; }
.cart-line > img { width:84px; height:84px; object-fit:cover; border-radius:12px;
  background:var(--kraft); flex:none; }
.cart-line__info { flex:1; display:flex; flex-direction:column; gap:.45rem; min-width:0; }
.cart-line__actions { display:flex; flex-direction:column; gap:.5rem; align-items:flex-end; }
.cart-empty { text-align:center; padding:3rem 0; }
.cart-empty svg { width:64px; height:64px; margin:0 auto 1rem; fill:none;
  stroke:var(--muted); stroke-width:1.5; }
@media (max-width:640px) {
  .cart-line { flex-wrap:wrap; }
  .cart-line__actions { flex-direction:row; width:100%; justify-content:space-between;
    align-items:center; }
}

/* forms */
.form-section { margin:1.25rem 0; }
.form-section__title { font-size:1.05rem; margin-bottom:.6rem; }
.form-field { display:flex; flex-direction:column; gap:.3rem; margin:.6rem 0; }
.form-field label { font-family:var(--font-head); font-weight:700; font-size:.9rem; }
.form-field--required label::after { content:" *"; color:var(--action); }
.form-field input, .form-field select, .form-field textarea { width:100%; padding:.7rem .85rem;
  border:1px solid var(--line); border-radius:12px; font-family:var(--font-body);
  font-size:1rem; background:#fff; }
.form-field .errorlist { color:var(--action); font-size:.85rem; margin:.15rem 0 0;
  padding:0; list-style:none; font-weight:700; }
.form-hint { color:var(--muted); font-size:.85rem; }

/* field-error state (client-batch Task 8) — red border on the input itself,
   inline message below; aria-invalid/aria-describedby carry the same
   relationship for assistive tech (storefront/_form_field.html). */
.form-field--error input, .form-field--error select, .form-field--error textarea {
  border-color:var(--action); }
.form-field--error input:focus, .form-field--error select:focus, .form-field--error textarea:focus {
  outline:none; box-shadow:0 0 0 3px rgba(215,56,44,.15); }
.form-field__error { color:var(--action); font-size:.85rem; margin:.15rem 0 0; font-weight:700; }

/* toast notifications (client-batch Task 8) — fixed stack, bottom-right,
   slide up on entry, plain JS (toast.js) drives add/remove. */
.toasts { position:fixed; z-index:1000; right:1rem; bottom:1rem; left:1rem;
  display:flex; flex-direction:column; gap:.6rem; align-items:flex-end;
  pointer-events:none; }
.toast { pointer-events:auto; max-width:360px; background:var(--ink); color:#fff;
  border-radius:var(--radius); box-shadow:var(--shadow); padding:.75rem 1rem;
  font-size:.9rem; font-weight:700; animation:ok-toast-in .2s ease-out; }
.toast--error { background:var(--action); }
.toast--success { background:var(--green); }
.toast--info { background:var(--ink); }
@keyframes ok-toast-in { from { transform:translateY(12px); opacity:0; } to { transform:translateY(0); opacity:1; } }
@media (prefers-reduced-motion: reduce) { .toast { animation:none; } }

/* brand card — customer auth + devis, echoing the okraft identity */
.brand-wrap { display:flex; justify-content:center; padding:clamp(1.5rem,5vw,3.5rem) 1rem;
  background:radial-gradient(120% 90% at 50% 0%, var(--paper) 0%, var(--kraft) 100%); }
.brand-card { width:100%; max-width:460px; background:#fff; border-radius:var(--radius-lg);
  box-shadow:0 10px 40px rgba(43,43,40,.10); padding:clamp(1.75rem,4vw,2.75rem); }
.brand-card--wide { max-width:640px; }
.brand-card__logo { display:block; height:46px; width:auto; margin:0 auto 1.25rem; }
.brand-card h1 { text-align:center; font-size:clamp(1.4rem,3.4vw,1.8rem); margin:0 0 .35rem; }
.brand-card__sub { text-align:center; color:var(--muted); margin:0 auto 1.5rem; max-width:34ch; }
:is(.brand-card,.devis-form) :is(input[type=text],input[type=tel],input[type=email],input[type=password],select) {
  width:100%; height:52px; border:1px solid var(--line); border-radius:10px; padding:0 14px;
  font:inherit; font-size:1rem; background:#fff; transition:border-color .15s, box-shadow .15s; }
:is(.brand-card,.devis-form) textarea { width:100%; border:1px solid var(--line); border-radius:10px; padding:12px 14px;
  font:inherit; font-size:1rem; background:#fff; transition:border-color .15s, box-shadow .15s; }
:is(.brand-card,.devis-form) :is(input,select,textarea):focus { outline:none; border-color:var(--green);
  box-shadow:0 0 0 3px rgba(107,182,47,.15); }
.brand-card .btn { width:100%; justify-content:center; height:52px; margin-top:.25rem; }
.brand-card__alt { text-align:center; color:var(--muted); margin-top:1.25rem; font-size:.92rem; }
.brand-card__alt a { color:var(--green); text-decoration:none; font-weight:700; }
.brand-card__alt a:hover { text-decoration:underline; }
@media (prefers-reduced-motion: reduce) { :is(.brand-card,.devis-form) :is(input,select,textarea) { transition:none; } }

/* cart polish */
.cart-line { border-radius:var(--radius); }
.cart-line > img { border-radius:12px; }
.cart-foot { margin-top:1.75rem; padding:clamp(1.25rem,3vw,1.6rem); border:1px solid var(--line);
  border-radius:var(--radius-lg); background:#fff; box-shadow:var(--shadow);
  display:flex; flex-direction:column; align-items:center; gap:1rem; text-align:center; }
.cart-foot__note { margin:0; color:var(--muted); font-size:.9rem; max-width:46ch; }
.cart-foot__cta { width:100%; max-width:360px; justify-content:center; height:54px; font-size:1.05rem; }
.cart-foot__links { display:flex; gap:1.5rem; flex-wrap:wrap; justify-content:center; }
.cart-foot__link { background:none; border:0; cursor:pointer; font:inherit; font-size:.88rem;
  font-family:var(--font-head); font-weight:700; color:var(--green); text-decoration:none; padding:.2rem; }
.cart-foot__link:hover { text-decoration:underline; }
.cart-foot__link--danger { color:var(--muted); }
.cart-foot__link--danger:hover { color:var(--action); }

/* devis request — two-column (summary + form), required-first fields */
.devis-page { max-width:960px; }
.devis-page > h1 { margin-bottom:.2rem; }
.devis-page__sub { color:var(--muted); margin:0 0 1.5rem; max-width:56ch; }
.devis-grid { display:grid; gap:clamp(1.25rem,3vw,2rem); align-items:start; }
@media (min-width:820px) { .devis-grid { grid-template-columns:minmax(240px,320px) 1fr; } }
.devis-summary { background:var(--green-tint); border:1px solid var(--line);
  border-radius:var(--radius-lg); padding:1.35rem 1.4rem; }
@media (min-width:820px) { .devis-summary { position:sticky; top:88px; } }
.devis-summary h2 { font-size:1rem; margin:0 0 .9rem; display:flex; align-items:center; gap:.5rem; }
.devis-summary h2 svg { width:20px; height:20px; fill:none; stroke:var(--green); stroke-width:2; }
.devis-summary ul { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.7rem; }
.devis-summary li { font-size:.9rem; line-height:1.4; display:flex; gap:.4rem; flex-wrap:wrap;
  align-items:baseline; }
.devis-summary li b { color:var(--ink); font-family:var(--font-head); }
.devis-summary__edit { display:inline-block; margin-top:1rem; font-weight:700; color:var(--green);
  text-decoration:none; font-size:.9rem; }
.devis-summary__edit:hover { text-decoration:underline; }
.devis-form { background:#fff; border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); padding:clamp(1.5rem,4vw,2.25rem); }
.devis-fieldset { border:0; padding:0; margin:0 0 1.6rem; }
.devis-fieldset__legend { font-family:var(--font-head); font-weight:700; font-size:1rem;
  color:var(--ink); margin:0 0 .4rem; padding:0; display:flex; align-items:baseline; gap:.5rem; }
.devis-fieldset__legend small { color:var(--muted); font-weight:600; font-size:.78rem; }
.devis-form .btn { width:100%; justify-content:center; height:52px; margin-top:.4rem; }

/* flow header (devis) — branded kraft band + step indicator */
.flow-head { background:var(--kraft); border-bottom:1px solid var(--line); padding:1.75rem 0 1.5rem; }
.flow-head h1 { margin:0 0 .3rem; color:var(--green); font-size:clamp(1.5rem,3.4vw,2.1rem); }
.flow-head__sub { margin:0; color:var(--muted); max-width:54ch; }
.flow-steps { display:flex; list-style:none; margin:0 0 1.15rem; padding:0; max-width:420px; }
.flow-steps__step { flex:1; position:relative; display:flex; flex-direction:column;
  align-items:center; gap:.4rem; font-family:var(--font-head); font-weight:700;
  font-size:.8rem; color:var(--muted); text-align:center; }
.flow-steps__step:not(:first-child)::before { content:""; position:absolute; top:14px;
  right:50%; width:100%; height:2px; background:var(--line); }
.flow-steps__step.is-done::before, .flow-steps__step.is-current::before { background:var(--green); }
.flow-steps__dot { position:relative; z-index:1; width:30px; height:30px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; background:#fff;
  border:2px solid var(--line); color:var(--muted); font-size:.85rem; }
.flow-steps__step.is-done { color:var(--ink); }
.flow-steps__step.is-done .flow-steps__dot { background:var(--green); border-color:var(--green); color:#fff; }
.flow-steps__step.is-current { color:var(--ink); }
.flow-steps__step.is-current .flow-steps__dot { border-color:var(--green); color:var(--green);
  box-shadow:0 0 0 3px rgba(107,182,47,.15); }

/* logo upload dropzone (personnaliser) */
.logo-drop { display:flex; align-items:center; justify-content:center; cursor:pointer;
  min-height:220px; padding:1.5rem; border:2px dashed var(--line); border-radius:var(--radius-lg);
  background:var(--paper); text-align:center; transition:border-color .15s, background .15s; }
.logo-drop:hover { border-color:var(--green); background:var(--green-tint); }
.logo-drop--filled { border-style:solid; border-color:var(--line); background:#fff; }
.logo-drop__img { max-width:100%; max-height:300px; border-radius:var(--radius); }
.logo-drop__prompt { display:flex; flex-direction:column; align-items:center; gap:.5rem; color:var(--muted); }
.logo-drop__prompt svg { width:44px; height:44px; fill:none; stroke:var(--green);
  stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.logo-drop__prompt strong { font-family:var(--font-head); color:var(--ink); font-size:1.05rem; }
.logo-drop__prompt small { font-size:.82rem; }
@media (prefers-reduced-motion: reduce) { .logo-drop { transition:none; } }

/* personnaliser (logo upload) — branded card + how-it-works strip */
.perso-card { max-width:520px; }
.perso-back { display:inline-flex; align-items:center; gap:.35rem; color:var(--muted);
  font-weight:700; font-size:.85rem; font-family:var(--font-head); background:var(--green-tint);
  padding:.42rem .85rem .42rem .62rem; border-radius:999px; margin-bottom:1.25rem;
  transition:color .15s, transform .15s; }
.perso-back svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:2.2;
  stroke-linecap:round; stroke-linejoin:round; }
.perso-back:hover { color:var(--green); transform:translateX(-2px); }
.perso-badge { display:flex; width:60px; height:60px; margin:0 auto .85rem; border-radius:50%;
  background:var(--green-tint); align-items:center; justify-content:center; }
.perso-badge svg { width:30px; height:30px; fill:none; stroke:var(--green); stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round; }
.perso-replace { text-align:center; color:var(--muted); font-size:.8rem; margin:-.4rem 0 0; }
/* The "bail out without designing" escape hatch. `.studio-dock__later` (the
   mobile shell's own duplicate of this control) shared this rule until the
   2026-07-26 simplification removed the shell and its duplicates -- the page
   is a single scrolling card again, so there is one of each control. */
.perso-later { align-self:center; background:none; border:0; color:var(--muted);
  cursor:pointer; font:inherit; font-size:.9rem; min-height:44px;
  text-decoration:underline; padding:.2rem; }
.perso-later:hover { color:var(--green); }
.perso-fee { color:var(--muted); font-size:.8rem; margin:.25rem 0 0; text-align:center; }
.how-steps { list-style:none; margin:.25rem 0; padding:1rem 0; border-top:1px solid var(--line);
  border-bottom:1px solid var(--line); display:grid; grid-template-columns:repeat(3,1fr); gap:.6rem; }
.how-steps li { display:flex; flex-direction:column; align-items:center; gap:.45rem; text-align:center;
  font-family:var(--font-head); font-weight:700; font-size:.76rem; color:var(--ink); line-height:1.25; }
.how-steps__ic { width:38px; height:38px; border-radius:50%; background:var(--green-tint);
  display:flex; align-items:center; justify-content:center; flex:none; }
.how-steps__ic svg { width:20px; height:20px; fill:none; stroke:var(--green); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }

/* logo drag-over + detected-colours swatches */
.logo-drop--drag { border-color:var(--green); background:var(--green-tint); }
.perso-colors { border:1px solid var(--line); border-radius:var(--radius); padding:1rem;
  background:var(--paper); }
.perso-colors__hint { margin:0 0 .7rem; font-size:.82rem; color:var(--muted); }
.perso-colors__sw { display:flex; gap:.55rem; flex-wrap:wrap; }
/* Task E4 touch ergonomics (binding checklist, spec section 6): the old
   small dots grow to the same >=44px floor as every other studio control --
   width/height set explicitly (not min-width/min-height) since border-
   radius:50% needs an actually-square box, not just a floor. */
.perso-colors__dot { width:44px; height:44px; border-radius:50%; padding:0; cursor:pointer; border:0;
  outline:2px solid transparent; outline-offset:2px; box-shadow:inset 0 0 0 1px rgba(0,0,0,.14);
  position:relative; transition:opacity .12s, outline-color .12s, transform .1s; }
.perso-colors__dot:not(.off) { outline-color:var(--green); }
.perso-colors__dot:hover { transform:scale(1.08); }
.perso-colors__dot:active { transform:scale(.94); }
.perso-colors__dot.off { opacity:.32; }
.perso-colors__dot.off::after { content:""; position:absolute; left:50%; top:50%; width:130%; height:2px;
  background:var(--muted); transform:translate(-50%,-50%) rotate(-45deg); }
.perso-colors__tier { margin:.75rem 0 0; font-size:.82rem; color:var(--muted); text-align:center; }
.perso-colors__tier strong { color:var(--ink); font-family:var(--font-head); }
@media (prefers-reduced-motion: reduce) { .perso-colors__dot { transition:none; } }

/* flow-head title icon badge (panier / devis / quote-result) */
.flow-head h1 { display:inline-flex; align-items:center; gap:.6rem; }
.flow-head__badge { display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:42px; height:42px; border-radius:50%; background:#fff; border:1px solid var(--line); }
.flow-head__badge svg { width:22px; height:22px; fill:none; stroke:var(--green); stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round; }

/* client orders page */
.orders-head { display:flex; align-items:center; gap:1rem; margin-bottom:1.5rem; }
.orders-head__badge { width:52px; height:52px; border-radius:50%; background:var(--green-tint);
  display:flex; align-items:center; justify-content:center; flex:none; }
.orders-head__badge svg { width:26px; height:26px; fill:none; stroke:var(--green); stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; }
.orders-head h1 { margin:0; }
.orders-head__sub { margin:.15rem 0 0; color:var(--muted); font-size:.92rem; }
.orders-list { display:flex; flex-direction:column; gap:.75rem; }
.order-card { display:flex; align-items:center; gap:1rem; background:#fff; border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:var(--shadow); padding:1rem 1.15rem;
  transition:transform .12s, box-shadow .12s; }
.order-card:hover { transform:translateY(-2px); box-shadow:0 12px 26px rgba(0,0,0,.10); }
.order-card__link { display:flex; align-items:center; gap:1rem; flex:1; min-width:0; color:inherit; }
.order-card__main { display:flex; flex-direction:column; gap:.15rem; flex:1; min-width:0; }
.order-card__ref { font-family:var(--font-head); }
.order-card__date { color:var(--muted); font-size:.85rem; }
.order-card__end { display:flex; flex-direction:column; align-items:flex-end; gap:.35rem; }
.order-card__total { font-weight:700; white-space:nowrap; }
.order-card__chev { width:20px; height:20px; fill:none; stroke:var(--muted); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; flex:none; }
.order-card__reorder { flex:none; margin-left:.25rem; }
.order-card__reorder .btn { padding:.55rem 1rem; font-size:.85rem; }
.status-pill { font-family:var(--font-head); font-weight:700; font-size:.72rem; padding:.18rem .6rem;
  border-radius:999px; white-space:nowrap; }
.status-pill--recue { background:#eef0f2; color:#5b6470; }
.status-pill--preparation { background:#fff3e0; color:#b26a00; }
.status-pill--prete { background:#e3f0ff; color:#1f5fa8; }
.status-pill--livree { background:var(--green-tint); color:#3f7a12; }
.status-pill--annulee { background:#fdece9; color:var(--action); }
.orders-empty { text-align:center; padding:3rem 1rem; }
.orders-empty svg { width:64px; height:64px; fill:none; stroke:var(--muted); stroke-width:1.5;
  stroke-linecap:round; stroke-linejoin:round; margin:0 auto 1rem; }
@media (prefers-reduced-motion: reduce) { .order-card { transition:none; } }

/* customer's own order-detail per-face design previews (Studio Task 9,
   closes the audited gap where a customer could never see their own
   submitted design again) */
.ok-design-previews { display:flex; flex-wrap:wrap; gap:.6rem; margin:.3rem 0 .6rem; }
.ok-design-preview { margin:0; text-align:center; }
.ok-design-preview img { width:72px; height:72px; object-fit:cover; border-radius:8px;
  border:1px solid var(--line); display:block; }
.ok-design-preview figcaption { font-size:.72rem; color:var(--muted); margin-top:.2rem; }

/* order card status progress bar */
.order-progress { height:4px; background:var(--line); border-radius:999px; overflow:hidden;
  margin-top:.5rem; max-width:220px; }
.order-progress span { display:block; height:100%; background:var(--green); border-radius:999px;
  transition:width .3s; }
@media (prefers-reduced-motion: reduce) { .order-progress span { transition:none; } }

/* ---------------------------------------------------------------------
   /personnaliser -- the simplified studio (2026-07-26 simplification round,
   docs/superpowers/plans/2026-07-26-studio-simplification.md).

   The screen is a plain scrolling card at EVERY width again: one preview
   canvas, the « Recto verso » checkbox, the colour chips, the Fond swatches,
   the bag-colour swatches, the fee chip, Valider and Remplacer. Every rule
   that styled the removed editor is gone with the markup it targeted:
     .studio-arrow                    face cycling (no faces to cycle)
     .studio-logo-box                 the selection box (nothing to select)
     .studio-handle-layer/.studio-handle   rotate + resize handles
     touch-action:none                only ever scoped to those two
     .studio-guide(--v/--h)           drag snap guides
     p.studio-locked                  the per-face lock veil
     .studio-add-btn/.studio-paste-btn    "Ajouter le logo"/"Coller ici"
     .studio-instance-actions/.studio-action-btn(--danger)
     .studio-drawer* (tabs, panel, actions row + its label, bags copy)
     .studio-field-row/.studio-field(--slider)/__label/__control/__input
     .studio-slider                   Taille/Rotation sliders
     .studio-strip*                   the face strip
     .studio-topbar*                  the mobile topbar + Recommencer confirm
     .studio-stage-frame/.studio-dock(+ __valider/__later)  the mobile shell
     .perso-card--studio-open, body.studio-locked, and the whole
     @media (max-width:768px) block they lived in.
   The layout contract that described those invariants is rewritten in the
   same commit (docs/design/studio-layout-contract.md).

   Surviving classes, for anyone tracing the markup:
     .perso-card, .perso-back(+svg), .perso-badge(+svg), .perso-later,
     .perso-fee, .how-steps(+children), .logo-drop(+ __prompt/--drag),
     .perso-colors(+ __hint/__sw/__dot/.off/__tier), .perso-flow,
     .perso-studio, .perso-bags(+__label), .bag-swatch(+.on),
     .perso-replace-btn, .studio-stage, .studio-canvas-wrap,
     .studio-canvas, .studio-field__hint (generic centred hint).
   --------------------------------------------------------------------- */
.perso-flow { display:flex; flex-direction:column; gap:1rem; }
.perso-studio { display:flex; flex-direction:column; align-items:center; gap:1rem; width:100%; }
.perso-bags { display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; justify-content:center; }
.perso-bags__label { font-family:var(--font-head); font-weight:700; font-size:.82rem;
  color:var(--muted); margin-right:.2rem; }
/* This button IS the swatch (a plain solid circle via its own inline
   `background:{{ hex }}`, no separate inner dot element), so width/height
   grow the visible circle along with the >=44px hit area -- the same
   treatment .perso-colors__dot already had. */
/* With the Fond retired (2026-07-26) the bag colour IS the background
   choice, and the only swatch row left on this screen -- so it carries the
   44px touch floor as an explicit minimum (not just width/height, which a
   flex row is free to shrink) and its own pressed state, both inherited from
   the swatches it replaces. */
.bag-swatch { width:44px; height:44px; min-width:44px; min-height:44px;
  border-radius:50%; padding:0; cursor:pointer; border:0;
  outline:2px solid transparent; outline-offset:2px;
  /* the « Blanc » swatch is a white circle on a white card -- the inset ring
     is what makes it a swatch rather than a gap (same reason as the mat). */
  box-shadow:inset 0 0 0 1px rgba(43,43,40,.32);
  transition:outline-color .12s, transform .1s; }
.bag-swatch:hover { transform:scale(1.08); }
.bag-swatch:active { transform:scale(.94); }
.bag-swatch.on { outline-color:var(--green); }
.perso-replace-btn { display:inline-flex; align-items:center; gap:.4rem; cursor:pointer;
  min-height:44px; font-family:var(--font-head); font-weight:700; font-size:.85rem; color:var(--green);
  background:var(--green-tint); padding:.45rem .95rem; border-radius:999px; }
.perso-replace-btn:hover { filter:brightness(1.03); }
@media (prefers-reduced-motion: reduce) { .bag-swatch { transition:none; } }

/* The one preview. `.studio-canvas-wrap` is still the measured box the
   ResizeObserver watches and the canvas sizes itself from (studio.js's
   `_renderActive` reads its clientWidth); it simply has no overlay children
   left to be a containing block for. `max-width:340px` keeps the canvas from
   dominating a wide card; `width:100%; height:auto` on the canvas keeps a
   375px phone free of any horizontal scroll. */
.studio-stage { display:flex; align-items:center; justify-content:center; width:100%; }
/* THE MAT (arrival-paint fix, 2026-07-26). « Blanc » is `#ffffff` in live
   BagColor data, and the preview is a bitmap FILLED with the bag colour: a
   white bag was being painted onto a white canvas (`background:#fff`) inside a
   white card (`.brand-card`), so the owner's phone showed a large empty box
   with a hairline border and nothing else -- the paint had run perfectly and
   painted nothing perceptible. A canvas cannot fix that from the inside, so
   the fix is the SURROUND: the wrap draws a kraft-toned mat with a darker
   edge, and the bag sits on it as an object. Any bag colour, white included,
   now reads as a bag. */
.studio-canvas-wrap { position:relative; flex:1; max-width:340px;
  background:var(--kraft); border:1px solid #d8cbb4; border-radius:calc(var(--radius) + 6px);
  padding:.7rem; box-shadow:inset 0 1px 3px rgba(43,43,40,.07); }
/* The DISPLAY width is set inline by studio.js's _renderActive, which fits the
   preview into both the mat's width and a height budget (STAGE_MAX_VH) -- the
   bag it used to fit was a tall sacherie shape, so at 302px wide the preview
   came out ~477px and on a 390x844 phone « Valider » landed 468px below the
   fold, more than a full screen of scrolling to finish a design. The same fit
   now bounds the LOGO's own aspect. It has to be JS, not CSS: the aspect is
   per-image, and the BITMAP has to be sized to the same box or the canvas is
   upscaled (blurry) or rendered at 1:1 bitmap size (tiny).

   THE CHECKERBOARD (client round 2026-07-27, task 2). The canvas no longer
   paints a bag under the logo, so wherever the logo is transparent the canvas
   itself is transparent -- that IS the "transparency honoured" part of the
   owner's ask, and it is also how a customer sees that their PNG has no
   background. A flat `background:#fff` would have hidden both, and would have
   re-created, one layer up, the exact bug the mat above exists for: a mostly
   white logo painted onto white and reading as an empty box. The checkerboard
   is the conventional transparency indicator and it contrasts with black and
   white alike. Kept in CSS, never painted into the bitmap: the exported JPEG
   (studio.js::_offscreenFace) is a real bag composite for infographics and
   must not inherit a screen affordance. */
.studio-canvas { display:block; height:auto; max-width:100%; margin-inline:auto;
  border-radius:var(--radius);
  border:1px solid #cbbda4; box-shadow:var(--shadow);
  background-color:#fff;
  background-image:
    linear-gradient(45deg, #dcd2bf 25%, transparent 25%, transparent 75%, #dcd2bf 75%),
    linear-gradient(45deg, #dcd2bf 25%, transparent 25%, transparent 75%, #dcd2bf 75%);
  background-size:18px 18px;
  background-position:0 0, 9px 9px; }

/* « Recto verso » (2026-07-26 owner decision): the ONE control that decides
   how many faces are printed, and therefore the only thing besides the kept
   colours that moves the fee. A whole-row <label> so the 44px floor covers
   the text as well as the box itself -- the checkbox alone would be a ~16px
   target. `accent-color` matches the native slider/checkbox treatment the
   owner asked for elsewhere ("a real control, not a text box"). */
.studio-recto { display:flex; align-items:center; gap:.7rem; width:100%; min-height:44px;
  padding:.6rem .8rem; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--paper); cursor:pointer; }
.studio-recto__box { flex:none; width:22px; height:22px; margin:0; accent-color:var(--green);
  cursor:pointer; }
.studio-recto__text { display:flex; flex-direction:column; gap:.15rem; min-width:0; }
.studio-recto__text strong { font-family:var(--font-head); font-size:.9rem; }
.studio-recto__text small { color:var(--muted); font-size:.78rem; }

/* The Fond (backing) swatches are RETIRED with their control (owner,
   2026-07-26: the background of a logo is the sacherie it prints on -- see
   apps/devis/templates/devis/personnaliser.html where the block used to be).
   `.studio-field__hint` stays: it is the generic centred hint style, not the
   Fond's own. */
.studio-field__hint { margin:0; text-align:center; font-size:.8rem; color:var(--muted); }

/* « Utiliser le même logo » (client round 2026-07-27, task 4): the logos
   already staged for OTHER cart lines, offered instead of making the customer
   find and re-upload the same file. A row of real thumbnails, because a logo
   is recognised by sight -- the line it came from is only there to tell two
   similar logos apart. Each card is a 44px-floor tap target like every other
   control on this screen. */
.perso-reuse { display:flex; flex-direction:column; gap:.5rem; width:100%; }
.perso-reuse__hint, .perso-reuse__note { margin:0; font-size:.8rem; color:var(--muted);
  text-align:center; }
.perso-reuse__list { display:flex; flex-direction:column; gap:.5rem; }
.perso-reuse__item { display:flex; align-items:center; gap:.7rem; width:100%;
  min-height:44px; padding:.5rem .7rem; cursor:pointer; text-align:left;
  border:1px solid var(--line); border-radius:var(--radius); background:var(--paper); }
.perso-reuse__item:hover { border-color:var(--green); }
.perso-reuse__item:active { transform:scale(.99); }
.perso-reuse__item[disabled] { opacity:.55; cursor:default; }
/* The thumbnail is the customer's own file, transparency and all -- same
   checkerboard reasoning as the preview canvas above, at strip size. */
.perso-reuse__thumb { flex:none; width:44px; height:44px; object-fit:contain;
  border-radius:calc(var(--radius) - 2px); border:1px solid var(--line);
  background-color:#fff;
  background-image:
    linear-gradient(45deg, #dcd2bf 25%, transparent 25%, transparent 75%, #dcd2bf 75%),
    linear-gradient(45deg, #dcd2bf 25%, transparent 25%, transparent 75%, #dcd2bf 75%);
  background-size:12px 12px; background-position:0 0, 6px 6px; }
.perso-reuse__text { display:flex; flex-direction:column; gap:.15rem; min-width:0; }
.perso-reuse__text strong { font-family:var(--font-head); font-size:.88rem; color:var(--green); }
.perso-reuse__text small { color:var(--muted); font-size:.78rem;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* « Finalement, sans personnalisation » -- the way out (client round
   2026-07-27, task 1). Deliberately quieter than `.perso-later` and much
   quieter than Valider: it is an escape hatch, not a third equal choice, and
   a customer who is happy with their design should never be drawn to it. It
   still carries the 44px floor, because an escape hatch nobody can tap on a
   phone is not one. */
.perso-abandon { display:block; width:100%; min-height:44px; cursor:pointer;
  background:none; border:0; padding:.6rem; font-size:.82rem; color:var(--muted);
  text-decoration:underline; }
.perso-abandon:hover { color:var(--ink); }

/* The live fee line. `.perso-colors__tier` (unchanged, above) still carries
   the typography; this modifier is the condensed pill treatment, which used
   to be scoped to the mobile shell only and is now simply how the chip
   looks -- there is no shell left to split it against. */
.studio-fee-chip { margin:0; background:var(--green-tint); color:var(--ink); font-weight:700;
  border-radius:999px; padding:.5rem .9rem; text-align:center; }

@media (prefers-reduced-motion: reduce) {
  .bag-swatch { transition:none; }
}

/* Phone: the studio is a working tool, not a landing page. The decorative
   badge (aria-hidden, purely ornamental) and the roomy hero spacing together
   cost ~150px above the preview -- paid for by the customer in scrolling, on
   the one screen where every control matters. Reclaimed under 640px only; the
   desktop card keeps its full presentation. */
@media (max-width:640px) {
  .perso-card .perso-badge { display:none; }
  .perso-card h1 { font-size:1.35rem; margin-bottom:.35rem; }
  .perso-card .brand-card__sub { font-size:.88rem; margin-bottom:.6rem; }
}

/* --- Order confirmation (devis/confirmation.html) -------------------------
   Visual pass, 2026-07-26. The page a customer lands on right after
   committing to an order: it has to say "it worked", say what happens next,
   and give ONE obvious action. Sized against the same 560px column it always
   used, so nothing else on the page moves. */
.confirm { max-width:600px; }
.confirm__head { text-align:center; padding:.5rem 0 1.4rem; }
.confirm__mark { display:inline-flex; align-items:center; justify-content:center;
  width:64px; height:64px; margin-bottom:.9rem; border-radius:50%;
  background:var(--green-tint); color:var(--green); }
.confirm__mark svg { width:32px; height:32px; }
.confirm__head h1 { font-size:1.5rem; line-height:1.25; margin:0 0 .6rem; }
.confirm__ref { margin:0 0 .55rem; color:var(--muted); font-size:.95rem; }
/* the reference is the one string customers copy into a WhatsApp message */
.confirm__ref strong { font-family:var(--font-head); font-size:1.1rem; color:var(--ink);
  letter-spacing:.02em; user-select:all; }
.confirm__pill { display:inline-block; background:var(--green); color:#fff;
  font-family:var(--font-head); font-weight:700; font-size:.8rem;
  padding:.3rem .8rem; border-radius:999px; }
.confirm__sub { margin:.55rem 0 0; color:var(--muted); font-size:.92rem; }

/* What happens next -- the question every customer asks after ordering. */
.confirm__steps { list-style:none; margin:0 0 1.4rem; padding:1rem;
  background:var(--paper); border:1px solid var(--line); border-radius:var(--radius);
  display:flex; flex-direction:column; gap:.85rem; }
.confirm__steps li { display:flex; gap:.75rem; align-items:flex-start; }
.confirm__steps strong { display:block; font-family:var(--font-head); font-size:.95rem; }
.confirm__steps small { display:block; color:var(--muted); font-size:.85rem; line-height:1.35; }
.confirm__step-n { flex:0 0 26px; height:26px; border-radius:50%; display:flex;
  align-items:center; justify-content:center; font-family:var(--font-head);
  font-weight:700; font-size:.8rem; background:#fff; color:var(--muted);
  border:1px solid var(--line); }
.confirm__steps li.is-done .confirm__step-n { background:var(--green); color:#fff;
  border-color:var(--green); }

.confirm__card { background:#fff; border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:var(--shadow); padding:1.1rem; margin-bottom:1.2rem; }
.confirm__card-title { font-size:1rem; margin:0 0 .8rem; }
.confirm__line { display:flex; justify-content:space-between; gap:1rem;
  padding:.55rem 0; border-bottom:1px solid var(--line); }
.confirm__line:last-of-type { border-bottom:0; }
.confirm__line-name { font-size:.95rem; }
.confirm__line-name small { display:block; color:var(--muted); font-size:.85rem; margin-top:.15rem; }
.confirm__line-size { color:var(--muted); }
.confirm__tag { display:inline-block; margin-left:.35rem; background:var(--green-tint);
  color:var(--green); font-size:.72rem; font-weight:700; padding:.1rem .45rem;
  border-radius:999px; vertical-align:middle; }
.confirm__line-total { white-space:nowrap; font-weight:700; font-size:.95rem; }

/* Contact facts, deliberately NOT `.confirm__totals`: that block is money,
   and mixing the two put a zone NAME one row above a delivery FEE. Same
   layout, different meaning, different class. */
.confirm__facts { display:flex; flex-direction:column; gap:.35rem; }
.confirm__facts > div { display:flex; justify-content:space-between; gap:1rem;
  font-size:.95rem; }
.confirm__facts > div > span:first-child { color:var(--muted); }

.confirm__totals { margin-top:.9rem; padding-top:.9rem; border-top:2px solid var(--line);
  display:flex; flex-direction:column; gap:.35rem; }
.confirm__totals > div { display:flex; justify-content:space-between; gap:1rem;
  font-size:.95rem; color:var(--muted); }
.confirm__grand { margin-top:.35rem; padding-top:.55rem; border-top:1px solid var(--line);
  font-family:var(--font-head); font-weight:700; font-size:1.15rem; color:var(--ink) !important; }

/* ONE primary action. Everything else is a quiet link -- four equally loud
   buttons meant none of them answered "what now". */
.confirm__cta { width:100%; justify-content:center; }
.confirm__wa { display:flex; flex-direction:column; gap:.5rem; margin-top:.8rem; }
.confirm__wa .btn { width:100%; justify-content:center; }
.confirm__links { text-align:center; margin:1rem 0 0; font-size:.92rem; }
.confirm__links a { color:var(--muted); text-decoration:underline; }
.confirm__links a:hover { color:var(--ink); }

.confirm__nudge { margin-top:1.4rem; padding:1.1rem; text-align:center;
  background:var(--green-tint); border-radius:var(--radius); }
.confirm__nudge-title { margin:0 0 .3rem; font-family:var(--font-head); font-weight:700; }
.confirm__nudge-text { margin:0 0 .9rem; color:var(--muted); font-size:.9rem; }

@media (max-width:640px) {
  .confirm__head h1 { font-size:1.3rem; }
  .confirm__card { padding:.9rem; }
}
