/*
 * ui.css — Pásalas component layer.
 *
 * Reusable, token-driven components folded out of the "Fiesta" prototype.
 * Consumes tokens.css only; never hard-codes a color or size that a token
 * already names. Section sheets (marketing.css, app.css…) compose these.
 */

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

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

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text);
  background:
    radial-gradient(1200px 600px at 50% -200px, var(--cream-glow), transparent),
    var(--color-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a {
  color: var(--color-primary-strong);
}

/* ===== Icons ============================================================
   Inline SVG (see IconHelper). currentColor + em sizing so an icon takes the
   color and scale of whatever text or control it sits in. */
.icon {
  width: 1.1em;
  height: 1.1em;
  flex: none;
  vertical-align: -0.18em;
}
.btn .icon { width: 1.15em; height: 1.15em; }
.toast .icon { width: 1.05em; height: 1.05em; }
.link .icon { width: 1em; height: 1em; }

:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ===== Layout =========================================================== */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

.container--narrow {
  max-width: var(--container-narrow);
}

.container--wide {
  max-width: var(--container-wide);
}

.stack > * + * {
  margin-top: var(--space-4);
}

/* Visually hidden but available to screen readers and keyboard focus — used for
   accessible section headings and for native inputs a styled label fronts. */
.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;
}

/* ===== Brand & decoration =============================================== */
.brand {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
  color: var(--color-primary-strong);
  text-decoration: none;
}

/* Papel-picado strip — the signature Fiesta motif. Decorative; mark aria-hidden. */
.picado {
  height: 28px;
  background: repeating-linear-gradient(
    90deg,
    var(--terracotta) 0 14.28%,
    var(--marigold) 14.28% 28.56%,
    var(--teal) 28.56% 42.84%,
    var(--rose) 42.84% 57.12%,
    var(--terracotta) 57.12% 71.4%,
    var(--marigold) 71.4% 85.68%,
    var(--teal) 85.68% 100%
  );
  -webkit-mask: radial-gradient(circle 9px at 14px 28px, transparent 9px, #000 9.5px) 0 0 / 28px 28px repeat-x;
  mask: radial-gradient(circle 9px at 14px 28px, transparent 9px, #000 9.5px) 0 0 / 28px 28px repeat-x;
}

/* ===== Header =========================================================== */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-5) var(--page-gutter) var(--space-1);
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* ===== Typography helpers ============================================== */
.eyebrow {
  margin: 0 0 var(--space-3);
  font-weight: var(--weight-extrabold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  font-size: var(--text-xs);
  color: var(--color-eyebrow);
}

.display {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-4);
}

.title {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  margin: 0 0 var(--space-2);
}

.lede {
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--color-text-muted);
  margin: 0;
}

.muted {
  color: var(--color-text-muted);
}

.link {
  color: var(--color-primary-strong);
  font-weight: var(--weight-bold);
  text-decoration: none;
}

.link:hover {
  text-decoration: underline;
}

/* ===== Buttons ========================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-weight: var(--weight-extrabold);
  font-size: var(--text-base);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  padding: var(--space-3) var(--space-6);
  border: 0;
  border-radius: var(--radius-pill);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast);
}

.btn--primary {
  background: var(--color-primary-strong);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-primary);
}

.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-primary-hover);
}

.btn--ghost {
  background: transparent;
  color: var(--color-primary-strong);
  border: 2px solid var(--color-primary);
}

.btn--ghost:hover {
  background: var(--color-primary-strong);
  border-color: var(--color-primary-strong);
  color: var(--color-on-primary);
}

.btn--lg {
  font-size: var(--text-md);
  padding: var(--space-4) var(--space-8);
}

.btn--block {
  width: 100%;
}

.btn__icon {
  font-size: 1.15em;
}

/* ===== Chips & badges =================================================== */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-extrabold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
}

/* Tier badge: Free (marigold) vs Paid (terracotta) */
.chip--free {
  color: var(--color-tier-text);
  background: var(--color-tier-bg);
  border-color: var(--color-tier-border);
}

.chip--paid {
  color: var(--color-on-primary);
  background: var(--color-primary-strong);
  border-color: var(--color-primary-strong);
}

/* Expiry chip (issue 10): the calm "Caduca el ..." indicator on a Free Event's
   console and dashboard card. Deliberately quiet (sunk paper, muted ink) so it
   informs without alarming, and tonally distinct from the marigold Tier badge
   beside it. Its sparkles glyph picks up the warm gold ink. */
.chip--expiry {
  text-transform: none;
  letter-spacing: normal;
  font-weight: var(--weight-bold);
  color: var(--color-text-muted);
  background: var(--color-surface-sunk);
  border-color: var(--color-border);
}
.chip--expiry .icon { width: 1em; height: 1em; color: var(--color-eyebrow); }

.badge-live {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--color-live);
}

.badge-live::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-live);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-live) 50%, transparent);
  animation: pulse 1.8s infinite;
}

@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-live) 50%, transparent); }
  70% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--color-live) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-live) 0%, transparent); }
}

/* ===== Form fields ===================================================== */
.field {
  display: block;
}

.field__label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--color-text);
  margin-bottom: var(--space-2);
}

.field__hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-2);
}

.input,
.textarea {
  width: 100%;
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--color-text-faint);
}

.input:focus,
.textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent);
}

.textarea {
  min-height: 6rem;
  resize: vertical;
}

/* ===== Toggle / switch (a checkbox, dressed as a switch) ===============
   A real <input type="checkbox" role="switch"> visually hidden over a track,
   so keyboard, focus, and screen-reader state come for free. */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
}

.switch__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.switch__track {
  position: relative;
  flex: none;
  width: 2.75rem;
  height: 1.5rem;
  border-radius: var(--radius-pill);
  background: var(--color-surface-sunk);
  border: 1px solid var(--color-border);
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.switch__thumb {
  position: absolute;
  top: 50%;
  left: 3px;
  width: 1.125rem;
  height: 1.125rem;
  transform: translateY(-50%);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast);
}

.switch__input:checked + .switch__track {
  background: var(--color-primary-strong);
  border-color: var(--color-primary-strong);
}

.switch__input:checked + .switch__track .switch__thumb {
  transform: translate(1.25rem, -50%);
}

.switch__input:focus-visible + .switch__track {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

.switch__input:disabled + .switch__track {
  opacity: 0.5;
}

.switch:has(.switch__input:disabled) {
  cursor: not-allowed;
}

.switch__label {
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--color-text);
}

/* ===== Select (native dropdown) =======================================
   Native <select> styled to match .input; the chevron is decorative and
   lets clicks fall through to the control. */
.select {
  position: relative;
  display: block;
}

.select__input {
  appearance: none;
  width: 100%;
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-10) var(--space-3) var(--space-4);
  cursor: pointer;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.select__input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 22%, transparent);
}

.select__input:disabled {
  cursor: not-allowed;
  color: var(--color-text-muted);
  background: var(--color-surface-sunk);
}

.select__chevron {
  position: absolute;
  top: 50%;
  right: var(--space-4);
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  color: var(--color-text-muted);
  pointer-events: none;
}

/* ===== Media grid (polaroid masonry) =================================== */
.media-grid {
  column-count: 3;
  column-gap: var(--space-5);
}

@media (max-width: 720px) {
  .media-grid { column-count: 2; }
}

@media (max-width: 460px) {
  .media-grid { column-count: 1; }
}

.polaroid {
  break-inside: avoid;
  position: relative; /* anchors __badge / __actions / __play overlays */
  margin: 0 0 var(--space-5);
  background: var(--color-surface);
  padding: var(--space-3) var(--space-3) 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition), box-shadow var(--transition);
}

.polaroid > img,
.polaroid__img {
  border-radius: var(--radius-sm);
  width: 100%;
  height: auto;
}

.polaroid__caption {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-align: center;
  padding: var(--space-2) var(--space-1) var(--space-3);
}

/* Hand-pinned tilt; cycle three angles down a grid with :nth-child or modifiers */
.polaroid--tilt-1 { transform: rotate(-1.4deg); }
.polaroid--tilt-2 { transform: rotate(1deg); }
.polaroid--tilt-3 { transform: rotate(-0.4deg); }

.polaroid:hover {
  transform: rotate(0) scale(1.02);
  box-shadow: var(--shadow-md);
  position: relative;
  z-index: 2;
}

/* ===== Callout / upsell ================================================ */
.callout {
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--color-accent) 12%, var(--color-surface)),
    color-mix(in srgb, var(--color-accent) 22%, var(--color-surface))
  );
  border: 1.5px dashed var(--color-accent);
  border-radius: var(--radius-xl);
  padding: var(--space-8) var(--space-8);
  text-align: center;
}

.callout__title {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-xl);
  margin: 0 0 var(--space-2);
}

.callout__body {
  margin: 0 0 var(--space-5);
  color: var(--color-text-muted);
}

/* ===== Footer ========================================================== */
.footer-note {
  text-align: center;
  margin-top: var(--space-10);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.footer-note strong {
  color: var(--color-primary-strong);
}

/* Shared site footer (the shared/_footer partial): legal links above the
   keepsake note. Global so it styles the marketing surfaces and the legal
   pages alike. */
.site-footer {
  margin-top: var(--space-16);
  padding: var(--space-8) var(--page-gutter) var(--space-12);
  text-align: center;
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-5);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
}

.site-footer__legal a {
  color: var(--color-text-muted);
  text-decoration: none;
}

.site-footer__legal a:hover {
  color: var(--color-primary-strong);
  text-decoration: underline;
}

.site-footer .footer-note {
  margin-top: 0;
}

/* ===== Section rhythm ================================================== */
.section {
  padding-block: var(--space-10);
}

.section--hero {
  text-align: center;
  padding-block: var(--space-8) var(--space-6);
}

/* ===== Cards ============================================================ */

/* Generic surface card — composes Event cards, panels, plan cards, auth. */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform var(--transition), box-shadow var(--transition);
}

.card--link:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.card__media {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--color-surface-sunk);
}
.card__body { padding: var(--space-5); }

.card__title {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  margin: 0 0 var(--space-1);
}
.card__meta { font-size: var(--text-sm); color: var(--color-text-muted); margin: 0; }

.card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--color-border);
}

/* The Tier + Expiry chips share the left of the card foot, wrapping on a narrow
   card before the manage link is pushed off. */
.card__chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* Auto-fill grid for dashboards (consumer Event cards). */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-6);
}

/* ===== Icon button ===================================================== */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  font-size: var(--text-md);
  line-height: 1;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: transform var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}
.icon-btn:hover { transform: translateY(-1px); color: var(--color-text); }
.icon-btn--sm { width: 2rem; height: 2rem; font-size: var(--text-sm); }

.icon-btn--danger:hover {
  color: var(--color-on-primary);
  background: var(--color-danger);
  border-color: var(--color-danger);
}

/* Overlay variant — sits on top of media (self-delete, moderate, lightbox close).
   The one sanctioned use of backdrop blur: it separates a control from the
   arbitrary photo behind it. Do not spread glassmorphism elsewhere. */
.icon-btn--overlay {
  color: var(--color-on-dark);
  background: var(--color-scrim);
  border-color: rgb(255 255 255 / 25%);
  backdrop-filter: blur(4px);
}
.icon-btn--overlay:hover { background: var(--color-scrim-strong); color: var(--color-on-dark); }

/* ===== Button — destructive =========================================== */
.btn--danger {
  background: var(--color-danger);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-sm);
}
.btn--danger:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }

/* ===== Notice (inline banners) ========================================
   video-is-Paid, cap reached, errors, expiry warning. A tinted surface +
   a leading icon coin + a serif title — no one-sided accent border. */
.notice {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-text);
}

.notice__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-pill);
  color: var(--color-secondary-strong);
  background: color-mix(in srgb, var(--color-secondary) 16%, var(--color-surface));
}
.notice__icon .icon { width: 1.25rem; height: 1.25rem; }

.notice__title {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-md);
  margin: 0 0 var(--space-1);
}
.notice__body { margin: 0; color: var(--color-text-muted); font-size: var(--text-sm); }

.notice--info {
  background: color-mix(in srgb, var(--color-secondary) 6%, var(--color-surface));
  border-color: color-mix(in srgb, var(--color-secondary) 28%, var(--color-border));
}

.notice--success {
  background: color-mix(in srgb, var(--color-secondary) 8%, var(--color-surface));
  border-color: color-mix(in srgb, var(--color-secondary) 28%, var(--color-border));
}

.notice--warning {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--color-surface));
  border-color: color-mix(in srgb, var(--color-accent) 38%, var(--color-border));
}

.notice--warning .notice__icon {
  color: var(--color-tier-text);
  background: color-mix(in srgb, var(--color-accent) 26%, var(--color-surface));
}

.notice--danger {
  background: color-mix(in srgb, var(--color-danger) 8%, var(--color-surface));
  border-color: color-mix(in srgb, var(--color-danger) 30%, var(--color-border));
}

.notice--danger .notice__icon {
  color: var(--color-danger);
  background: color-mix(in srgb, var(--color-danger) 14%, var(--color-surface));
}

/* ===== Toast ========================================================== */
.toast-stack {
  position: fixed;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%);
  display: grid;
  gap: var(--space-2);
  z-index: var(--z-toast);
  width: max-content;
  max-width: calc(100vw - var(--space-8));
}

.toast {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  background: var(--color-text);
  color: var(--cream-glow);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-md);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  animation: toast-in var(--transition);
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ===== Progress / upload ============================================== */
.progress {
  height: 8px;
  background: var(--color-surface-sunk);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

/* Width driven by --value (0–1); animated via transform for cheap, jank-free
   compositing on low-end phones. */
.progress__bar {
  height: 100%;
  width: 100%;
  transform: scaleX(var(--value, 0));
  transform-origin: left center;
  background: linear-gradient(90deg, var(--color-accent), var(--color-primary));
  border-radius: inherit;
  transition: transform var(--transition);
}

.upload-item {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-2) var(--space-4);
}

.upload-item__name {
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.upload-item__pct { font-size: var(--text-xs); color: var(--color-text-muted); }
.upload-item .progress { grid-column: 1 / -1; }

/* A file whose direct upload failed: tint the bar so the Guest sees which one. */
.upload-item--error .upload-item__pct { color: var(--color-danger); }
.upload-item--error .progress__bar { background: var(--color-danger); }

/* ===== Feature list (what Paid / Studio unlocks) ====================== */
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}
.feature-list__item { display: flex; gap: var(--space-3); align-items: flex-start; }

.feature-list__item::before {
  content: "✓";
  flex: none;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  font-size: var(--text-sm);
  font-weight: var(--weight-extrabold);
  color: var(--color-secondary-strong);
  background: color-mix(in srgb, var(--color-secondary) 16%, var(--color-surface));
  border-radius: var(--radius-pill);
}
.feature-list__item--off { color: var(--color-text-muted); }

.feature-list__item--off::before {
  content: "—";
  color: var(--color-text-faint);
  background: var(--color-surface-sunk);
}

/* ===== Copy field (share link) ======================================= */
.copy-field { display: flex; gap: var(--space-2); }

.copy-field .input {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--text-sm);
}

/* ===== QR card / table-tent ========================================== */
.qr-card {
  max-width: 360px;
  margin-inline: auto;
  text-align: center;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  padding: var(--space-8) var(--space-6);
}

.qr-card__event {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-xl);
  margin: 0 0 var(--space-1);
}
.qr-card__instruction { color: var(--color-text-muted); margin: 0 0 var(--space-6); }

.qr-card__code {
  width: 200px;
  height: 200px;
  margin: 0 auto var(--space-5);
  display: grid;
  place-items: center;
  background: #fff; /* true white — required quiet zone for reliable QR scanning */
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.qr-card__code svg,
.qr-card__code img { width: 100%; height: 100%; }

/* ===== Empty state =================================================== */
.empty-state {
  text-align: center;
  padding: var(--space-12) var(--space-6);
  border: 1.5px dashed var(--color-border);
  border-radius: var(--radius-xl);
  background: var(--color-surface);
}
.empty-state__icon { color: var(--color-secondary-strong); }
.empty-state__icon .icon { width: 2.5rem; height: 2.5rem; }

.empty-state__title {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  margin: var(--space-3) 0 var(--space-2);
}

.empty-state__body {
  color: var(--color-text-muted);
  margin: 0 auto var(--space-6);
  max-width: 28rem;
}

/* ===== Avatar & brand lockup (Studio co-brand) ======================= */
.avatar {
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
  font-weight: var(--weight-extrabold);
  color: var(--color-on-primary);
  background: linear-gradient(160deg, var(--color-accent), var(--color-primary));
  border-radius: var(--radius-md);
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--lg { width: 3.5rem; height: 3.5rem; font-size: var(--text-lg); }
.avatar--circle { border-radius: var(--radius-pill); }

.brand-lockup { display: inline-flex; align-items: center; gap: var(--space-3); }

.brand-lockup__name {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-md);
  line-height: 1.1;
}

.brand-lockup__role {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-text-faint);
}

/* "powered by Pásalas" — the non-removable mark on free Studio galleries. */
.powered-by {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--color-text-faint);
}

.powered-by strong {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  color: var(--color-primary-strong);
}

/* ===== Roster (Studio dashboard — denser host list) ================== */
.roster {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.roster__row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
}
.roster__row + .roster__row { border-top: 1px solid var(--color-border); }
.roster__row:hover { background: var(--cream-glow); }

.roster__name {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-md);
  margin: 0;
}
.roster__meta { font-size: var(--text-sm); color: var(--color-text-muted); }
.roster__actions { display: flex; gap: var(--space-2); }

@media (max-width: 560px) {
  .roster__row { grid-template-columns: auto 1fr; }

  .roster__row .roster__meta,
  .roster__row .roster__actions { grid-column: 2; }
}

/* ===== Media: source badge, actions, featured, video ================= */

/* (.polaroid is position:relative so these anchor to it.) */
.polaroid__badge { position: absolute; top: var(--space-4); left: var(--space-4); z-index: 2; }

.polaroid__actions {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: flex;
  gap: var(--space-2);
  opacity: 0;
  transition: opacity var(--transition-fast);
  z-index: 2;
}

.polaroid:hover .polaroid__actions,
.polaroid:focus-within .polaroid__actions { opacity: 1; }

/* Action-reveal pattern (issues 05 + 06): the default control above is revealed
   on hover/focus, which has no touch equivalent. So a control that already
   belongs to THIS viewer is shown without hover via --own, since both the Guest
   and the Host are on a phone. ONE pattern, two uses:
     - Guest self-delete (issue 05): rendered hidden until JS confirms ownership,
       so non-owners never see it.
     - Host moderation (issue 06): on the owner-scoped management console every
       tile carries it, since the Host owns the whole album. */
.polaroid__actions--own { opacity: 1; }

/* Source badge: studio pro shot vs guest candid. */
.badge-source {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-extrabold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-sm);
}
.badge-source--pro { background: var(--color-primary-strong); }
.badge-source--guest { background: var(--color-secondary-strong); }

/* Featured — the studio hero set (straightened, accent ring). */
.polaroid--featured {
  transform: none;
  box-shadow: 0 0 0 3px var(--color-accent), var(--shadow-md);
}
.polaroid--featured:hover { transform: scale(1.02); }

/* ===== Client proofing: the culling grid (studio-proofing issue 03) =====
   Each Proof tile is a tap-to-select toggle button (button_to). No Turbo: the
   button posts a PATCH and the page refreshes, so the server stays the source of
   truth for the selection cap. The tile reuses the .polaroid card; a check badge
   and a terracotta ring mark a Proof that is in the Client's Selection. */
.proof-pick {
  display: block;
  width: 100%;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: inherit;
  -webkit-appearance: none;
  appearance: none;
}

/* The select indicator: an empty ring on an unpicked Proof, a filled terracotta
   check once it is in the Selection. Always visible (no hover) because the Client
   culls on a phone — the same rationale as the --own action-reveal. */
.proof-pick__check {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  color: transparent;
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-fast), border-color var(--transition-fast),
    color var(--transition-fast);
}
.proof-pick__check .icon { width: 1.1em; height: 1.1em; }

/* Selected — straighten the tile out of the masonry tilt and ring it, like the
   featured hero set but in terracotta so the Client's pick reads as their own. */
.proof-pick--selected {
  transform: none;
  box-shadow: 0 0 0 3px var(--color-primary-strong), var(--shadow-md);
}
.proof-pick--selected:hover { transform: scale(1.02); }

.proof-pick--selected .proof-pick__check {
  background: var(--color-primary-strong);
  border-color: var(--color-primary-strong);
  color: var(--color-on-primary);
}

/* The running "N / X elegidas" count under the title. */
.proofing-count { margin-top: var(--space-3); }
.proofing-count__chip .icon { width: 1em; height: 1em; }

/* Video tile (poster + play + processing status). */
.polaroid__play { position: absolute; inset: 0; margin: auto; width: 3.5rem; height: 3.5rem; z-index: 2; }

.polaroid__status {
  position: absolute;
  left: var(--space-4);
  bottom: var(--space-6);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--color-on-dark);
  background: var(--color-scrim-media);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
}
.polaroid__status .icon { width: 1em; height: 1em; }

/* Video tile media holds a fixed shape so the masonry never reflows as the poster
   image or the <video> metadata loads in (the poster placeholder, the processing
   poster, and the ready player all share one tile). cover crops to fill, matching
   how photo thumbnails sit in the grid. */
.polaroid--video .polaroid__img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

/* Poster placeholder: a video uploaded but not yet transcoded has no poster, so
   show a festive teal-to-terracotta block with the video glyph until the ffmpeg
   job attaches one. The strong stops keep the white glyph readable across it. */
.polaroid__poster--empty {
  display: grid;
  place-items: center;
  background: linear-gradient(160deg, var(--color-secondary-strong), var(--color-primary-strong));
  color: var(--color-on-primary);
}
.polaroid__poster--empty .icon { width: 2.4rem; height: 2.4rem; }

.spinner {
  width: 0.85em;
  height: 0.85em;
  border: 2px solid rgb(255 255 255 / 40%);
  border-top-color: #fff;
  border-radius: var(--radius-pill);
  animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* ===== Lightbox (full-screen Media viewer) ========================== */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: var(--space-6);
  background: var(--color-scrim-strong);
}
.lightbox[hidden] { display: none; }

.lightbox__stage {
  max-width: min(92vw, 1100px);
  max-height: 88vh;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.lightbox__close { position: absolute; top: var(--space-5); right: var(--space-5); }

.lightbox__caption {
  position: absolute;
  bottom: var(--space-6);
  left: 0;
  right: 0;
  text-align: center;
  color: var(--cream-glow);
  font-family: var(--font-serif);
  font-style: italic;
}

/* ===== Stage (big-screen Slideshow — Noche-dark) ==================== */
.stage {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 9;
  width: 100%;
  background: var(--color-stage);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.stage__media { max-width: 100%; max-height: 100%; object-fit: contain; }
.stage__brand { position: absolute; top: var(--space-5); left: var(--space-6); color: var(--cream-glow); }
.stage__live { position: absolute; top: var(--space-5); right: var(--space-6); }

.stage__caption {
  position: absolute;
  bottom: var(--space-6);
  left: var(--space-6);
  color: var(--cream-glow);
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--text-lg);
}

/* ===== Segmented filter (Todas / Pro / Invitados) ==================== */
.segmented {
  display: inline-flex;
  gap: var(--space-1);
  padding: var(--space-1);
  background: var(--color-surface-sunk);
  border-radius: var(--radius-pill);
}

.segmented__item {
  appearance: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--color-text-muted);
  background: transparent;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.segmented__item:hover { color: var(--color-text); }

.segmented__item[aria-pressed="true"],
.segmented__item.is-active {
  color: var(--color-text);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
}

/* ===== Menu (disclosure dropdown — row/event actions) =================
   Built on <details>/<summary> so it opens by click and keyboard with no JS.
   (A JS enhancement — Escape, outside-click, arrow-key roving — can layer on
   later via Stimulus.) */
.menu {
  position: relative;
  display: inline-block;
}

.menu__trigger {
  list-style: none;
  cursor: pointer;
}
.menu__trigger::-webkit-details-marker { display: none; }
.menu__trigger .icon { transition: transform var(--transition-fast); }
.menu[open] .menu__trigger .icon--chevron { transform: rotate(180deg); }

.menu__panel {
  position: absolute;
  z-index: var(--z-header);
  top: calc(100% + var(--space-2));
  left: 0;
  min-width: 13rem;
  padding: var(--space-2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}
.menu__panel--right { left: auto; right: 0; }

.menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--color-text);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.menu__item .icon { color: var(--color-text-muted); }
.menu__item:hover { background: var(--cream-glow); }
.menu__item--danger { color: var(--color-danger); }
.menu__item--danger .icon { color: var(--color-danger); }

.menu__item--danger:hover {
  background: var(--color-danger);
  color: var(--color-on-primary);
}
.menu__item--danger:hover .icon { color: var(--color-on-primary); }

.menu__sep {
  height: 1px;
  margin: var(--space-2) var(--space-1);
  background: var(--color-border);
}

/* ===== Dialog / modal (confirm delete, upgrade prompt) =============== */
.dialog {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: var(--space-6);
  background: var(--color-scrim);
}
.dialog[hidden] { display: none; }

.dialog__panel {
  width: min(30rem, 100%);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: var(--space-8);
  text-align: center;
}

.dialog__title {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--text-xl);
  margin: 0 0 var(--space-2);
}
.dialog__body { color: var(--color-text-muted); margin: 0 0 var(--space-6); }
.dialog__actions { display: flex; gap: var(--space-3); justify-content: center; flex-wrap: wrap; }

/* ===== Icon sizing inside icon-only buttons ========================== */
.icon-btn .icon { width: 1.2rem; height: 1.2rem; }
.icon-btn--sm .icon { width: 1rem; height: 1rem; }

/* ===== Reduced motion ================================================
   tokens.css already zeroes --transition* (so every `transition:` snaps).
   These stop the keyframe animations that run independently of those tokens:
   the looping live pulse, the upload spinner, and the toast entrance. */
@media (prefers-reduced-motion: reduce) {
  .badge-live::before { animation: none; }
  .spinner { animation: none; border-top-color: rgb(255 255 255 / 40%); }
  .toast { animation: none; }
}
