/* ============================================================
   MODALS (native <dialog>)
   ============================================================ */
.modal {
  /* explicit viewport centering — Safari can otherwise place open
     dialogs relative to the document instead of the screen */
  position: fixed;
  inset: 0;
  margin: auto;
  height: fit-content;
  background: var(--bg-raised);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 0;
  width: min(92vw, 520px);
  max-height: 85vh;
  overflow: auto;
  box-shadow: 0 40px 120px rgba(0, 0, 0, 0.7);
  /* enter animation */
  opacity: 0;
  transform: translateY(24px) scale(0.96);
}
/* The open state is declared, not left to the entrance animation's fill. Any
   later rule that sets its own `animation` would otherwise replace modal-in
   and take its `forwards` fill with it, dropping the dialog back to the
   closed opacity: 0 above and blanking the modal out. */
.modal[open] {
  opacity: 1;
  transform: none;
  animation: modal-in 0.5s var(--ease-spring);
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(24px) scale(0.96); }
}
.modal.is-closing {
  animation: modal-out 0.25s ease forwards;
}
@keyframes modal-out {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(16px) scale(0.97); }
}

.modal::backdrop {
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.modal__body { padding: var(--s-4); }
.modal__body h2 {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  letter-spacing: -0.02em;
  margin-bottom: var(--s-1);
}
.modal__sub { color: var(--ink-dim); font-size: var(--fs-small); line-height: var(--lh-small); margin-bottom: var(--s-3); }

.modal__close {
  position: absolute;
  top: 14px; right: 14px;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.07);
  font-size: 0; /* hide the &times; glyph — cross is drawn below */
  transition: background 0.25s, transform 0.35s var(--ease-spring);
  z-index: 1;
}
.modal__close::before,
.modal__close::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 14px; height: 1.5px;
  border-radius: 1px;
  background: var(--ink);
  translate: -50% -50%;
}
.modal__close::before { rotate: 45deg; }
.modal__close::after { rotate: -45deg; }
@media (hover: hover) {
  .modal__close:hover { background: rgba(255, 255, 255, 0.14); transform: rotate(90deg); }
}


/* ---------- form fields ---------- */
/* Set at body size to match .btn--pill, so a field and the button under it
   are the same text. The vertical padding drops a little to absorb the taller
   line box — the control still ends up a few px taller than before. */
.field {
  width: 100%;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--hairline);
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  transition: border-color 0.25s, background 0.25s, box-shadow 0.25s;
  margin-bottom: var(--s-2);
  resize: vertical;
}
.field:focus {
  outline: none;
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.06);
  box-shadow: 0 0 0 4px rgba(10, 132, 255, 0.18);
}
.field-label {
  display: block;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 400;
  color: var(--ink-dim);
  margin-bottom: 4px;
}
.field-label .field { margin-top: 6px; font-weight: 400; }
.field-label .opt { font-weight: 400; color: var(--ink-faint); }
.hp { position: absolute; left: -9999px; }

/* colour and hover come from .linklike; sized to match the button above it */
.modal__request {
  display: block;
  margin: var(--s-2) auto 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

/* ---------- wrong password ----------
   Sits above the field and starts at zero height, so a wrong password grows
   the modal open rather than snapping a gif into place. 0fr → 1fr animates
   to the content's own height, which a max-height guess cannot do; the inner
   wrapper carries the overflow, since the grid row is what's being sized. */
.password-denied {
  display: grid;
  grid-template-rows: 0fr;
  margin-bottom: 0;
  text-align: center;
  transition: grid-template-rows 0.42s var(--ease-out),
              margin-bottom 0.42s var(--ease-out),
              opacity 0.3s ease;
  opacity: 0;
}
.password-denied__inner { overflow: hidden; min-height: 0; }
/* self-contained rather than keyed to an ancestor, so the viewer page's copy
   of this panel opens with the same class and no second rule */
.password-denied.is-open {
  grid-template-rows: 1fr;
  margin-bottom: var(--s-3);
  opacity: 1;
}
/* The gif is 150x124 on a flat #fafafa field, sampled from its own pixels, so
   the frame carries that exact value and the two read as one panel with no
   visible seam. Held well under the modal's width: stretching it to fill was
   a 3x upscale, soft and tall enough to make the modal scroll. */
.password-denied__frame {
  display: grid;
  place-items: center;
  padding: 18px;
  background: #fafafa;
  border-radius: var(--radius-sm);
}
.password-denied img {
  display: block;
  width: 200px;      /* 1.33x native — as far as it goes before softening */
  max-width: 100%;
  height: auto;
}
.password-denied__fallback {
  display: none;
  padding: 24px 16px;
  border-radius: var(--radius-sm);
  background: rgba(252, 165, 165, 0.08);
  border: 1px solid rgba(252, 165, 165, 0.25);
  color: var(--accent-warm);
  font-weight: 400;
  animation: finger-wag 0.6s ease infinite;
}
/* no gif → hide the frame too, or an empty white panel is left behind */
.password-denied.no-gif .password-denied__frame { display: none; }
.password-denied.no-gif .password-denied__fallback { display: block; }
@keyframes finger-wag {
  0%, 100% { transform: rotate(-1.5deg); }
  50% { transform: rotate(1.5deg); }
}

/* ---------- access success ---------- */
.access-success { text-align: center; padding: var(--s-3) 0 var(--s-1); }
.access-success h3 { font-size: var(--fs-h4); line-height: var(--lh-h4); margin-bottom: 6px; color: var(--accent); }
.access-success p { color: var(--ink-dim); }
