/* vibe.css — the live "restyle this page" demo, integrated as a compact hero
 * feature (not a standalone section). Light-first; semantic tokens only.
 * The restyle eases smoothly because, during the ~0.76s window, we transition the
 * actual color PROPERTIES (which read from the swapped CSS custom props). */

.restyle {
  position: relative; /* the mood pill floats over the label line — applying a
                         theme must never grow the hero (fold guarantee) */
  margin-top: 1.6rem;
  max-width: 46rem;
}
@media (max-height: 840px) {
  .restyle { margin-top: 1.1rem; }
}
.restyle__label {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  margin: 0 0 0.8rem;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  color: var(--ink-mute);
}
.restyle__spark {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

.restyle__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 0.9rem;
}

.restyle__swatches { display: inline-flex; align-items: center; gap: 0.5rem; }
.restyle__swatch {
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  background: none;
  display: grid;
  place-items: center;
  transition: transform var(--dur-fast) var(--ease-out);
}
.restyle__swatch > span {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18), 0 2px 6px -2px rgba(20, 22, 50, 0.35);
}
.restyle__swatch:hover,
.restyle__swatch:focus-visible { transform: translateY(-2px) scale(1.1); }
.restyle__surprise {
  font-size: 0.9rem;
  line-height: 1;
  filter: grayscale(0.3);
}

.restyle__form { flex: 1 1 210px; min-width: 0; }
.restyle__input {
  width: 100%;
  padding: 0.55rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 70%, transparent);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.restyle__input::placeholder { color: var(--ink-mute); }
.restyle__input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.restyle__form.is-busy .restyle__input { opacity: 0.6; }

/* While a theme is active the pill takes over the label line (same slot →
   the hero can never grow, and nothing overlaps). */
.restyle.has-vibe .restyle__label { opacity: 0; pointer-events: none; }
.restyle__pill {
  position: absolute;
  top: -0.45rem;
  left: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.4rem 0.3rem 0.75rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  font-size: var(--fs-xs);
  color: var(--ink);
}
.restyle__pill b {
  font-weight: 600;
  max-width: min(58vw, 22ch);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.restyle__pill button {
  padding: 0.16rem 0.6rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-dim);
  font-size: var(--fs-xs);
  cursor: pointer;
  transition: color var(--dur-fast), border-color var(--dur-fast);
}
.restyle__pill button:hover { color: var(--ink); border-color: var(--accent); }
.restyle__pill[hidden] { display: none; }

/* ── "thinking" state: shown while the model designs a theme ───── */
.restyle.is-thinking .restyle__label { opacity: 0; pointer-events: none; }
.restyle.is-thinking .restyle__swatches,
.restyle.is-thinking .restyle__input { opacity: 0.5; transition: opacity 0.2s ease; }
/* the thinking chip and the mood pill share the SAME slot — while thinking, the
   chip owns it (hide the pill) and lock the controls so nothing can race the
   in-flight request. */
.restyle.is-thinking .restyle__pill { display: none; }
.restyle.is-thinking .restyle__swatches { pointer-events: none; }
.restyle__thinking {
  position: absolute;
  top: -0.5rem;
  left: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.32rem 0.85rem 0.32rem 0.55rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.02em;
  color: var(--ink);
  white-space: nowrap;
}
.restyle__thinking[hidden] { display: none; }
.restyle__thinking b { font-weight: 500; }
.restyle__orb {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0%, var(--accent) 90%);
  -webkit-mask: radial-gradient(farthest-side, transparent 56%, #000 58%);
          mask: radial-gradient(farthest-side, transparent 56%, #000 58%);
  animation: vibe-spin 0.8s linear infinite;
}
@keyframes vibe-spin { to { transform: rotate(1turn); } }
@media (max-width: 900px) { .restyle__thinking { position: static; } }

/* ── cinematic apply sweep (vibe.js injects one, then removes it) ──
   A soft vertical strip of the new palette — a bright leading edge trailing a wash —
   GPU-translates smoothly left→right across the page while the colours crossfade, so
   the reskin reads as a real-time reveal, not a snap. */
.vibe-sweep {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  width: 42vw;
  z-index: 9998;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--wash) 60%,
    var(--edge2) 84%,
    var(--edge) 96%,
    transparent 100%
  );
  transform: translateX(-125%);
  opacity: 0;
  animation: vibe-sweep 0.9s cubic-bezier(0.5, 0, 0.15, 1) forwards;
  will-change: transform, opacity;
  /* blend is set inline per-apply (screen on dark themes, multiply on light) */
}
@keyframes vibe-sweep {
  0% { transform: translateX(-125%); opacity: 0; }
  12% { opacity: 1; }
  86% { opacity: 1; }
  100% { transform: translateX(360%); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .vibe-sweep { display: none; } }

/* rate-limit / status note reuses the thinking chip: static dot, wrap allowed. */
.restyle.is-note .restyle__orb {
  animation: none;
  -webkit-mask: none;
  mask: none;
  background: var(--accent);
}
.restyle.is-note .restyle__thinking {
  white-space: normal;
  max-width: min(92vw, 40ch);
  line-height: 1.3;
}

@media (max-width: 900px) {
  /* narrow screens scroll anyway — let the pill flow in the row, and fully
     remove (not just hide) the emptied label so no blank row is left behind. */
  .restyle__pill { position: static; }
  .restyle.has-vibe .restyle__label { display: none; }
}
@media (max-width: 560px) {
  .restyle__form { flex-basis: 100%; order: 3; }
}

/* The smooth restyle: while the body carries .vibe-restyling, ease the real color
 * properties so the swapped custom-prop values animate instead of snapping. */
body.vibe-restyling,
body.vibe-restyling *:not(canvas) {
  transition:
    background-color 0.72s ease,
    color 0.66s ease,
    border-color 0.72s ease,
    box-shadow 0.72s ease,
    border-radius 0.6s ease,
    fill 0.72s ease,
    stroke 0.72s ease !important;
}
@media (prefers-reduced-motion: reduce) {
  body.vibe-restyling, body.vibe-restyling *:not(canvas) { transition: none !important; }
}
