/* Ads Maker — dark editorial UI in the Cruip "Open" idiom: near-black blue-black
   canvas, ambient indigo glows, gradient-clipped display type, hairline gradient
   borders, and a mouse-tracked spotlight over the format grid. */

:root {
  color-scheme: dark;

  --bg: #080a12;
  --bg-2: #0b0e18;
  --surface: rgba(19, 22, 34, 0.72);
  --surface-2: rgba(26, 30, 44, 0.7);
  --surface-3: rgba(33, 38, 55, 0.68);

  --line: rgba(255, 255, 255, 0.07);
  --line-strong: rgba(255, 255, 255, 0.13);

  --text: #eef0f6;
  --text-dim: #b3b9c9;
  --muted: #7d859a;
  --faint: #575e73;

  /* Indigo → violet is the primary system; amber marks the proven angles. */
  --indigo: #6366f1;
  --indigo-light: #818cf8;
  --indigo-soft: #a5b4fc;
  --violet: #8b5cf6;
  --amber: #f0b429;
  --amber-soft: rgba(240, 180, 41, 0.14);

  --ok: #34d399;
  --warn: #fbbf24;
  --err: #f87171;

  --grad-display: linear-gradient(96deg, #e6e9f5 4%, #a5b4fc 34%, #ffffff 58%, #c7cbe0 92%);
  --grad-primary: linear-gradient(180deg, #7c7ff5 0%, #5b5ce4 100%);
  --grad-hairline: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.02) 55%);

  --radius: 14px;
  --radius-lg: 20px;

  --shadow-card: 0 20px 50px -24px rgba(0, 0, 0, 0.9), 0 1px 0 rgba(255, 255, 255, 0.05) inset;
  --shadow-cta: 0 10px 30px -10px rgba(99, 102, 241, 0.55), 0 1px 0 rgba(255, 255, 255, 0.22) inset;

  /* The stock CSS easings are too weak to read as intentional. These are the
     strong variants: --ease-out for anything entering or exiting (starts fast,
     so the UI feels like it responds instantly), --ease-in-out for things
     moving on screen. Never ease-in on UI — it delays the first frame, exactly
     where the eye is looking. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --z-toast: 50;
}

/* ---------- motion ----------
   Entrances are seen once per load, so they can afford ~500ms. Everything the
   user triggers repeatedly stays under 250ms. */

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* Never from scale(0) — nothing in the real world appears out of nothing. */
@keyframes pop-in {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to { opacity: 1; transform: none; }
}

.nav { animation: rise 460ms var(--ease-out) both; }
.hero .eyebrow { animation: rise 520ms var(--ease-out) 60ms both; }
.hero .lede { animation: rise 520ms var(--ease-out) 200ms both; }
/* .display carries its own two-animation shorthand below — declaring it here
   too would out-specify that rule and silently drop the gradient drift. */
main > .panel:first-of-type { animation: rise 560ms var(--ease-out) 280ms both; }

/* The display gradient drifts slowly so the headline reads as alive rather
   than printed. background-size lives on the .display rule itself — the
   `background` shorthand there would reset it from here. */
.display {
  animation: rise 520ms var(--ease-out) 130ms both, drift 14s ease-in-out 900ms infinite;
}
@keyframes drift {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.6 Geist, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Ambient layer: two soft indigo/violet blooms plus a fading grid, all fixed so
   the page scrolls over a still backdrop. Purely decorative. */
.ambient {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(680px 420px at 18% -6%, rgba(99, 102, 241, 0.22), transparent 68%),
    radial-gradient(760px 460px at 88% 4%, rgba(139, 92, 246, 0.16), transparent 70%),
    radial-gradient(900px 600px at 50% 108%, rgba(76, 81, 191, 0.12), transparent 72%);
}
.ambient::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.028) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(circle at 50% 0%, #000 0%, transparent 62%);
  -webkit-mask-image: radial-gradient(circle at 50% 0%, #000 0%, transparent 62%);
}

main {
  position: relative;
  z-index: 1;
  max-width: 1080px;
  margin: 0 auto;
  padding: 28px 20px 96px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- nav ---------- */

.nav {
  position: relative;
  z-index: 2;
  /* A floating pill must never touch the viewport edge — inset it on small
     screens while still centering at full width on desktop. */
  max-width: min(1080px, calc(100% - 32px));
  margin: 16px auto 0;
  padding: 10px 14px 10px 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: rgba(14, 17, 27, 0.66);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-radius: 999px;
}
.nav::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: var(--grad-hairline); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; }

.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: inherit; }
.brand-mark {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  border-radius: 10px;
  background: var(--grad-primary);
  color: #fff;
  box-shadow: 0 6px 18px -8px rgba(99, 102, 241, 0.9), 0 1px 0 rgba(255, 255, 255, 0.25) inset;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-weight: 600; font-size: 14.5px; letter-spacing: -0.01em; }
.brand-sub { font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; }

.chip {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 11px; color: var(--text-dim);
  padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.03);
}

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

.hero { text-align: center; padding: 72px 0 44px; }

.eyebrow {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin: 0 0 20px;
  font-size: 12.5px; font-weight: 500; letter-spacing: 0.02em;
}
.eyebrow span {
  background: linear-gradient(90deg, var(--indigo), var(--indigo-soft));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* Hairlines either side of the label, Cruip-style. */
.eyebrow::before, .eyebrow::after {
  content: ''; height: 1px; width: 42px;
  background: linear-gradient(90deg, transparent, var(--line-strong));
}
.eyebrow::after { background: linear-gradient(90deg, var(--line-strong), transparent); }

.display {
  margin: 0 0 18px;
  font-size: clamp(34px, 6vw, 58px);
  line-height: 1.04;
  font-weight: 600;
  letter-spacing: -0.032em;
  background: var(--grad-display);
  /* Wider than the box so `drift` has somewhere to travel. */
  background-size: 200% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

.lede {
  max-width: 620px; margin: 0 auto;
  color: var(--text-dim); font-size: 16.5px; line-height: 1.65;
}

/* ---------- panels ---------- */

/* Deliberately no backdrop-filter on these full-width panels: blurring a tall
   scrolling surface is the most expensive thing on the page and buys nothing
   over layered translucent gradients. The blur is spent on the nav and toast,
   where it actually reads. */
.panel {
  position: relative;
  background:
    linear-gradient(180deg, rgba(28, 32, 48, 0.72), rgba(13, 16, 26, 0.82)),
    var(--bg-2);
  border-radius: var(--radius-lg);
  padding: 30px;
  margin-bottom: 22px;
  box-shadow: var(--shadow-card);
}
.panel::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: var(--grad-hairline); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; }
@media (max-width: 560px) { .panel { padding: 22px 18px; } }

.section-title { font-size: 18px; font-weight: 600; letter-spacing: -0.015em; margin: 0; }

.banner {
  position: relative; z-index: 1;
  border-radius: var(--radius);
  border: 1px solid rgba(251, 191, 36, 0.35);
  background: rgba(251, 191, 36, 0.09);
  color: #fcd34d;
  padding: 13px 16px; margin-bottom: 20px; font-size: 13.5px;
}

/* ---------- form ---------- */

.field { margin-bottom: 22px; }
.field:last-child { margin-bottom: 0; }
.field-row { display: grid; grid-template-columns: 1fr; gap: 22px; }
@media (min-width: 760px) { .field-row { grid-template-columns: 1fr 1fr; } }

.label {
  display: block;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--muted); margin-bottom: 10px;
}
.label-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.label-row .label { margin-bottom: 10px; }
.em { text-transform: none; letter-spacing: 0.02em; color: var(--faint); }
.hint { font-size: 12.5px; color: var(--muted); margin: 10px 0 0; }
/* A hint that ends one block must not crowd the next one. */
.hint + .field, .hint + .field-row { margin-top: 24px; }

input[type="text"], textarea {
  width: 100%;
  background: rgba(8, 10, 18, 0.6);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  color: var(--text);
  font-family: inherit; font-size: 14.5px; line-height: 1.55;
  resize: vertical;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
input[type="text"]::placeholder, textarea::placeholder { color: var(--faint); }
input[type="text"]:focus, textarea:focus {
  outline: none;
  border-color: rgba(129, 140, 248, 0.55);
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.16);
}

.dropzone {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; min-height: 96px; padding: 20px;
  border-radius: var(--radius);
  border: 1px dashed rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.018);
  color: var(--text-dim);
  font: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), color 0.18s var(--ease);
}
.dropzone:hover { border-color: rgba(129, 140, 248, 0.5); background: rgba(99, 102, 241, 0.06); color: var(--text); }

.product-preview { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.product-preview img {
  width: 68px; height: 68px; object-fit: cover;
  border-radius: 12px; border: 1px solid var(--line-strong);
}
.product-meta { display: flex; flex-direction: column; gap: 4px; font-size: 13.5px; min-width: 0; }
.product-meta > span { overflow-wrap: anywhere; }

/* ---------- format picker + spotlight ---------- */

.formats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
}
@media (min-width: 640px) { .formats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 940px) { .formats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.format-group {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0 4px;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.13em;
  color: var(--indigo-soft);
}
.format-group::after { content: ''; flex: 1; height: 1px; background: linear-gradient(90deg, var(--line-strong), transparent); }
.format-group:first-child { margin-top: 0; }
/* The proven in-house angles get the warm accent so they read as a tier apart. */
.format-group[data-group="Our winning angles"] { color: var(--amber); }

.format {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  min-height: 62px; padding: 11px 13px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.022);
  color: var(--text);
  font-family: inherit; text-align: left;
  cursor: pointer;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease);
}
/* Mouse-tracked spotlight: the grid publishes --mx/--my, each tile paints the
   same radial highlight in page space, so the glow tracks across the whole set. */
.format::after {
  content: '';
  position: absolute; inset: -1px;
  border-radius: inherit;
  background: radial-gradient(220px circle at var(--mx, -999px) var(--my, -999px), rgba(129, 140, 248, 0.22), transparent 42%);
  opacity: 0;
  transition: opacity 0.25s var(--ease);
  pointer-events: none;
}
.formats:hover .format::after { opacity: 1; }
.format:hover { border-color: rgba(129, 140, 248, 0.42); background: rgba(255, 255, 255, 0.04); }
.format.selected {
  border-color: rgba(129, 140, 248, 0.75);
  background: linear-gradient(180deg, rgba(99, 102, 241, 0.2), rgba(99, 102, 241, 0.08));
  box-shadow: 0 0 0 1px rgba(99, 102, 241, 0.32), 0 8px 22px -14px rgba(99, 102, 241, 0.9);
}
/* Tiles cascade in once the list loads. --i comes from JS; the delay is capped
   so the tail of 44 tiles never feels like waiting. */
.format, .format-group { animation: pop-in 340ms var(--ease-out) both; animation-delay: min(calc(var(--i, 0) * 14ms), 320ms); }
/* Press feedback: the tile should feel like it heard the click. */
.format:active { transform: scale(0.985); }
.format-label { font-size: 13.5px; font-weight: 600; letter-spacing: -0.005em; position: relative; z-index: 1; }
.format-tag { font-size: 10.5px; color: var(--muted); position: relative; z-index: 1; }
.format.selected .format-tag { color: var(--indigo-soft); }

/* ---------- segmented controls ---------- */

.seg {
  display: flex; gap: 4px; padding: 4px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(8, 10, 18, 0.55);
}
.seg-btn {
  flex: 1; min-height: 38px;
  border: none; border-radius: 9px; padding: 8px 10px;
  background: none; color: var(--muted);
  font: inherit; font-size: 12.5px; font-weight: 600; white-space: nowrap;
  cursor: pointer;
  transition: color 0.18s var(--ease), background 0.18s var(--ease);
}
.seg-btn:hover { color: var(--text); }
.seg-btn.active {
  background: var(--grad-primary);
  color: #fff;
  box-shadow: 0 6px 16px -10px rgba(99, 102, 241, 0.95), 0 1px 0 rgba(255, 255, 255, 0.2) inset;
}

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

.btn-primary {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 46px; padding: 12px 24px;
  border: none; border-radius: 12px;
  background: var(--grad-primary);
  color: #fff;
  font: inherit; font-size: 14.5px; font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow-cta);
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), opacity 0.18s var(--ease);
}
/* A slow sheen sweeping the CTA — the one piece of ambient motion on the page. */
.btn-primary::after {
  content: '';
  position: absolute; top: 0; bottom: 0; width: 45%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.22), transparent);
  transform: translateX(-160%);
  animation: sheen 4.5s var(--ease) infinite;
}
@keyframes sheen { 0%, 62% { transform: translateX(-160%); } 100% { transform: translateX(320%); } }
.btn-primary:not(:disabled):hover { transform: translateY(-1px); box-shadow: 0 14px 34px -12px rgba(99, 102, 241, 0.75), 0 1px 0 rgba(255, 255, 255, 0.25) inset; }
.btn-primary:not(:disabled):active { transform: scale(0.97); transition-duration: 110ms; }
.btn-primary:disabled { opacity: 0.42; cursor: not-allowed; box-shadow: none; }
.btn-primary:disabled::after { animation: none; }

.btn-ghost {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 9px 16px;
  border: 1px solid var(--line-strong); border-radius: 11px;
  background: rgba(255, 255, 255, 0.035);
  color: var(--text);
  font: inherit; font-size: 13.5px; font-weight: 600;
  text-decoration: none; cursor: pointer;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.14s var(--ease-out);
}
.btn-ghost:hover { border-color: rgba(129, 140, 248, 0.5); background: rgba(99, 102, 241, 0.1); }
.btn-ghost:active { transform: scale(0.97); }

.link-btn {
  background: none; border: none; padding: 0;
  color: var(--indigo-light);
  font: inherit; font-size: 12.5px; font-weight: 600;
  text-decoration: none; cursor: pointer;
}
.link-btn:hover { color: var(--indigo-soft); text-decoration: underline; }
.bulk { display: flex; align-items: center; gap: 10px; }
.bulk-sep { color: var(--faint); }

:where(button, a, input, textarea, summary):focus-visible {
  outline: 2px solid var(--indigo-light);
  outline-offset: 2px;
  border-radius: 8px;
}

.run-row { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 28px; }
.cost { font-family: "Geist Mono", ui-monospace, monospace; font-size: 12.5px; color: var(--muted); }

.log-wrap { margin-top: 20px; }
.log-wrap summary { cursor: pointer; font-size: 12.5px; color: var(--muted); }
.log-wrap summary:hover { color: var(--text-dim); }
pre {
  margin: 12px 0 0; padding: 14px;
  background: rgba(4, 5, 10, 0.7);
  border: 1px solid var(--line);
  border-radius: 12px;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 11.5px; line-height: 1.7; color: var(--text-dim);
  max-height: 220px; overflow: auto; white-space: pre-wrap;
}

/* ---------- results ---------- */

.results-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; }
.actions { display: flex; gap: 10px; flex-wrap: wrap; }

.results { display: grid; grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); gap: 16px; }
.result {
  position: relative;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.022);
  overflow: hidden;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
/* Applied on insert only — the row's innerHTML is rewritten on every status
   update, so animating the row itself would replay the entrance each time. */
.result.entering { animation: pop-in 380ms var(--ease-out) both; }
.result[data-status="done"]:hover { border-color: rgba(129, 140, 248, 0.4); }
/* The finished ad fades up rather than snapping in over the skeleton. */
.result img { animation: reveal 420ms var(--ease-out) both; }
@keyframes reveal {
  from { opacity: 0; transform: scale(1.02); }
  to { opacity: 1; transform: none; }
}
.result-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 11px 13px; }
.result-name { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.result img { width: 100%; display: block; }
.result a { display: block; }
/* Reserve the tile's space before the image lands so the grid never jumps. */
.placeholder {
  aspect-ratio: 4 / 5;
  background:
    linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.045) 50%, transparent 80%),
    rgba(255, 255, 255, 0.022);
  background-size: 200% 100%, auto;
  animation: shimmer 1.6s linear infinite;
}
@keyframes shimmer { to { background-position: -200% 0, 0 0; } }
.result-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 13px; min-height: 38px; font-family: "Geist Mono", ui-monospace, monospace; font-size: 11px; color: var(--muted); }
.result-error { padding: 0 13px 12px; font-size: 12px; line-height: 1.5; color: var(--err); overflow-wrap: anywhere; }

.pill {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em;
  padding: 4px 9px; border-radius: 999px; white-space: nowrap;
}
.pill-pending { background: rgba(255, 255, 255, 0.07); color: var(--muted); }
/* A slow breath on the in-flight pill — the one honest signal that work is
   still happening while the tile sits empty. */
.pill-generating { background: rgba(251, 191, 36, 0.15); color: var(--warn); animation: breathe 1.8s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: 0.55; } }
.pill-done { background: rgba(52, 211, 153, 0.14); color: var(--ok); }
.pill-failed { background: rgba(248, 113, 113, 0.15); color: var(--err); }

/* ---------- toast ---------- */

.toast {
  position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%);
  z-index: var(--z-toast);
  max-width: min(440px, calc(100vw - 40px));
  padding: 13px 20px;
  border-radius: 12px;
  border: 1px solid var(--line-strong);
  background: rgba(16, 19, 30, 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.9);
  font-size: 13.5px;
  /* Transitions, not keyframes: toasts can be replaced while one is still on
     screen, and a transition retargets smoothly where a keyframe restarts. */
  opacity: 1;
  transition: opacity 200ms var(--ease-out), transform 260ms var(--ease-out);
}
/* Enters from below and leaves the same way, so the motion has one direction. */
.toast.leaving { opacity: 0; transform: translateX(-50%) translateY(14px); }
@starting-style { .toast { opacity: 0; transform: translateX(-50%) translateY(14px); } }
.toast.ok { border-color: rgba(52, 211, 153, 0.45); }
.toast.err { border-color: rgba(248, 113, 113, 0.45); }

.hidden { display: none !important; }

/* Reduced motion means fewer and gentler animations, not zero. Opacity and
   colour changes still carry state, so they stay; everything that moves goes.
   Entrances use `both`, so collapsing the duration lands them on their final
   frame rather than hiding them. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 120ms !important;
  }
  .btn-primary:hover, .btn-primary:active,
  .btn-ghost:active, .format:active,
  .result img { transform: none !important; }
  .toast, .toast.leaving { transform: translateX(-50%) !important; }
}

/* Hover lifts are for real pointers — on touch, a tap latches the hover state
   and leaves the element visually displaced. */
@media (hover: none) {
  .btn-primary:hover { transform: none; }
}
