/* Password screen for protected projects (markup and motion in js/lock.js). The project's tile fills the
   popup, blurred and dimmed, with a scan line passing over it; the vault dial and the form sit in the middle. */
.case-locked { display: grid; }
.lock-stage { height: 100dvh; min-height: 560px; overflow: hidden; }
.lock-blur { object-fit: cover; filter: blur(26px) brightness(0.45); transform: scale(1.08); }
/* A thin light sweeping down the blurred screen, as if it were being scanned. */
.lock-scan { position: absolute; inset: 0; pointer-events: none; background: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.025) 0 1px, transparent 1px 4px); }
.lock-scan::after { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 2px; background: linear-gradient(90deg, transparent, var(--ui), transparent); box-shadow: 0 0 18px 4px rgba(25, 194, 255, 0.45); animation: lock-scan 3.6s var(--ease) infinite; }
@keyframes lock-scan { from { transform: translateY(0); opacity: 0; } 12% { opacity: 1; } 88% { opacity: 1; } to { transform: translateY(100dvh); opacity: 0; } }

.lock { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: var(--gutter); text-align: center; }
.lock-dial { width: clamp(140px, 22vh, 190px); height: auto; margin-bottom: 6px; overflow: visible; }
.lock-tick { stroke: rgba(255, 255, 255, 0.25); stroke-width: 1.5; stroke-linecap: round; transition: stroke 0.25s, filter 0.25s; }
.lock-tick.is-lit { stroke: var(--ui); filter: drop-shadow(0 0 3px var(--ui)); }
.lock-orbit { fill: none; stroke: rgba(255, 255, 255, 0.4); stroke-width: 1; stroke-dasharray: 2 9; }
.lock-track { fill: none; stroke: var(--line); stroke-width: 3; }
/* Starts empty (offset 1 of a path length of 1) and fills as the password is typed. */
.lock-progress { fill: none; stroke: var(--ui); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; transform: rotate(-90deg); transform-origin: 100px 100px; filter: drop-shadow(0 0 6px rgba(25, 194, 255, 0.7)); }
.lock-shackle { fill: none; stroke: var(--text); stroke-width: 6; stroke-linecap: round; }
.lock-body { fill: var(--text); }
.lock-hole { fill: var(--ink); }

.lock-title { font-size: clamp(30px, 4.4vw, 54px); line-height: 1; font-weight: 800; text-transform: uppercase; }
.lock-note { max-width: 36ch; color: var(--muted); font-size: 17px; }
.lock-field { display: flex; gap: 10px; width: min(420px, 100%); margin-top: 8px; }
.lock-input { flex: 1; min-width: 0; min-height: 50px; padding: 10px 22px; border: 1px solid var(--line); border-radius: 999px; background: rgba(0, 0, 0, 0.6); color: var(--text); font: inherit; font-size: 17px; letter-spacing: 0.12em; transition: border-color 0.2s, box-shadow 0.2s; }
.lock-input::placeholder { color: var(--muted); letter-spacing: normal; }
.lock-input:focus { outline: none; border-color: var(--ui); box-shadow: 0 0 0 3px rgba(25, 194, 255, 0.25); }
.lock-submit:disabled { opacity: 0.6; cursor: progress; }
.lock-msg { min-height: 1.4em; color: var(--muted); font-size: 15px; }
@media (max-width: 480px) { .lock-field { flex-direction: column; } }

/* Checking: the dial ring breathes while the server answers. */
.lock.is-checking .lock-progress { animation: lock-pulse 0.7s ease-in-out infinite alternate; }
@keyframes lock-pulse { from { opacity: 0.35; } to { opacity: 1; } }
/* Wrong password: everything that was blue turns pink for a moment. */
.lock.is-wrong .lock-progress, .lock.is-wrong .lock-input { stroke: var(--ai); border-color: var(--ai); }
.lock.is-wrong .lock-tick.is-lit { stroke: var(--ai); filter: drop-shadow(0 0 3px var(--ai)); }
.lock.is-wrong .lock-msg { color: var(--ai); }
/* Unlocked: every tick lights up before the dial opens. */
.lock.is-open .lock-tick { stroke: var(--ui); filter: drop-shadow(0 0 3px var(--ui)); }

@media (prefers-reduced-motion: reduce) {
  .lock-scan::after, .lock.is-checking .lock-progress { animation: none; }
}
