/* controls.css — how the small controls feel. Policy: MOTION.md.
 *
 * One vocabulary, "the stamp" (already the look of the buttons):
 *   hover   the button lifts (translate -1px, hard shadow grows)     — style.css
 *   press   it sinks (translate +1px, shadow shrinks)                 — here
 *   select  the chosen one lands (t-pulse) and its mark draws in      — here
 *
 * Loaded AFTER style.css and staples.css so it wins on equal specificity.
 * Nothing here changes a size, a position or a resting colour. Only
 * transform, opacity, colour, border-colour and the small hard shadow animate
 * (never `all`, never width/height/padding/margin).
 */

/* ---- 1. One transition for every button -------------------------------- */
.font-btn,
.spread-merge-btn,
#page-tools button,
.zone-fit button,
.qr-toggle-btn,
.confirm-btn {
  transition:
    transform        var(--dur-micro) var(--ease-out),
    box-shadow       var(--dur-micro) var(--ease-out),
    background-color var(--dur-micro) var(--ease-out),
    color            var(--dur-micro) var(--ease-out),
    border-color     var(--dur-micro) var(--ease-out),
    opacity          var(--dur-micro) var(--ease-out);
}

/* ---- 1b. Hover must not repaint a selected or coloured button ------------ */
/* style.css's `.font-btn:hover` fills the button with the page background. It
   out-ranks `.active` (dark fill, light text) and the swatch colours, so hovering
   a selected button left light text on a light fill, and a black swatch turned
   pale. Keep each button's own fill. */
.font-btn.active:not(.swatch-btn):hover:not(:disabled) {
  background-color: var(--text);
  color: var(--bg-card);
}
.swatch-btn.sw-white:hover:not(:disabled),
.font-btn.sw-white.active:hover:not(:disabled) {
  background-color: #ffffff;
  color: #111111;
}
.swatch-btn.sw-black:hover:not(:disabled),
.font-btn.sw-black.active:hover:not(:disabled) {
  background-color: #111111;
  color: #ffffff;
}
/* A swatch keeps its colour on hover, so its cue is the border going navy. */
.swatch-btn:hover:not(:disabled) { border-color: var(--stamp); }

/* ---- 2. Press: the stamp sinks ----------------------------------------- */
/* (.confirm-btn, .qr-toggle-btn and .export-btn already had this.) */
/* .font-btn is flat (hover = fill only, selected = dark fill), so it has no
   press-sink either: nothing moves, nothing casts a shadow. */
.spread-merge-btn:active:not(:disabled) {
  transform: translate(1px, 1px);
  box-shadow: 1px 1px 0 var(--accent);
}
#page-tools button:active:not(:disabled),
.zone-fit button:active {
  transform: translateY(1px);
}

/* ---- 3. Select: the chosen button lands -------------------------------- */
/* Only `from` is given, so the animation ends on whatever the button rests
   at (including the hover lift): no jump when it stops. */
@keyframes t-pulse {
  from { transform: scale(0.94); }
}
.t-pulse { animation: t-pulse var(--dur-state) var(--ease-out); }

/* A colour swatch's check draws itself in. The check path is ~20 units long. */
@keyframes t-draw {
  from { stroke-dashoffset: 21; }
  to   { stroke-dashoffset: 0; }
}
.swatch-btn.t-pulse svg path {
  stroke-dasharray: 21;
  animation: t-draw var(--dur-state) var(--ease-out) both;
}

/* ---- 4. Checkboxes and radios ------------------------------------------ */
/* A native checkbox cannot animate, so WRAP's is drawn by hand at the SAME size
   as before: the check draws in left to right (checkbox-check recipe). The
   export dialog's radios and checkboxes stay native: each engine aligns its
   native box differently (Chromium on the baseline, WebKit at the top, 13px vs
   12px), so a custom one cannot match both without shifting the dialog.
   Rule: restyle a native control only where its size can be pinned exactly. */
.wrap-check input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  /* inline-block, not grid: it keeps the native checkbox's baseline, so the
     label lines up exactly as before. */
  display: inline-block;
  position: relative;
  /* Without its native look an input has no intrinsic size: WRAP's is 14px, as
     it was. */
  box-sizing: border-box;
  width: 14px;
  height: 14px;
  margin: 0;
  border: 1px solid var(--text);
  border-radius: 2px;
  background: var(--bg-card);
  cursor: pointer;
  transition:
    background-color var(--dur-micro) var(--ease-out),
    box-shadow       var(--dur-micro) var(--ease-out),
    outline-offset   var(--dur-micro) var(--ease-out);
}

.wrap-check input:checked { background: var(--text); }
.wrap-check input:not(:disabled):hover { box-shadow: 1px 1px 0 var(--accent); }
.wrap-check input:disabled { cursor: not-allowed; }

.wrap-check input[type="checkbox"]::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 78%;
  height: 78%;
  background: var(--bg-card);
  -webkit-mask: var(--check-mask) center / contain no-repeat;
  mask: var(--check-mask) center / contain no-repeat;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--dur-state) var(--ease-out);
}
.wrap-check input[type="checkbox"]:checked::before { clip-path: inset(0 0 0 0); }

:root {
  /* The check mark: the same stroke as icons.js `check`. */
  --check-mask: 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.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
}

/* ---- 5. Keyboard focus -------------------------------------------------- */
/* Only for keyboard users (:focus-visible); the mouse sees no change. The ring
   grows out from the control instead of popping in. */
.font-btn, .spread-merge-btn, #page-tools button, .zone-fit button,
.qr-toggle-btn, .confirm-btn,
.wrap-check input {
  outline: 2px solid transparent;
  outline-offset: 0;
}
.swatch-btn { outline-offset: 1px; } /* its resting ring is reserved by style.css */
.font-btn:focus-visible, .spread-merge-btn:focus-visible, #page-tools button:focus-visible,
.zone-fit button:focus-visible, .qr-toggle-btn:focus-visible, .confirm-btn:focus-visible,
.wrap-check input:focus-visible {
  outline-color: var(--stamp);
  outline-offset: 2px;
}
.swatch-btn:focus-visible { outline-color: var(--text); }

/* ---- 6. The ↺ reset chip over a photo (Staples' free placement) ---------- */
/* Same stamp: hover lifts, press sinks. Enabling / disabling it (a photo gets
   moved, or reset) fades through opacity, so it never blinks; it changes no size. */
.reset-btn {
  transition:
    transform        var(--dur-micro) var(--ease-out),
    box-shadow       var(--dur-micro) var(--ease-out),
    background-color var(--dur-micro) var(--ease-out),
    opacity          var(--dur-state) var(--ease-out);
}
.reset-btn:hover:not(:disabled) {
  transform: translate(-1px, -1px);
  box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.55);
}
.reset-btn:active:not(:disabled) {
  transform: translate(1px, 1px);
  box-shadow: none;
}
.reset-btn:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

@media (prefers-reduced-motion: reduce) {
  .font-btn, .spread-merge-btn, #page-tools button, .zone-fit button,
  .qr-toggle-btn, .confirm-btn, .reset-btn,
  .wrap-check input,
  .wrap-check input::before {
    transition: none !important;
  }
  .t-pulse, .swatch-btn.t-pulse svg path { animation: none !important; }
}
