
@property --quiet-caret-ink { syntax: '<color>'; inherits: false; initial-value: transparent; }
:root { --quiet-caret-step: 7px; }
:is(input, textarea):read-write::placeholder { text-indent: var(--quiet-caret-step); }
:is(input, textarea):read-write:focus:placeholder-shown {
  caret-color: transparent !important;
  --quiet-caret-ink: color-mix(in srgb, var(--text-muted, #8a8178) 45%, transparent);
  background-image: linear-gradient(var(--quiet-caret-ink), var(--quiet-caret-ink)) !important;
  background-repeat: no-repeat !important;
  background-origin: content-box !important;
  background-clip: border-box !important;
  background-size: 1px var(--quiet-caret-height, 1.31em) !important;
  background-position: 0 calc(50% - (1lh - var(--quiet-caret-height, 1.31em)) / 2 + round(down, (1lh - var(--quiet-caret-height, 1.31em)) / 2, 1px)) !important;
  animation: quiet-caret 1.7s ease-in-out infinite;
}
textarea:read-write:focus:placeholder-shown {
  background-position: 0 round(down, (1lh - var(--quiet-caret-height, 1.31em)) / 2, 1px) !important;
}
@keyframes quiet-caret {
  0%, 100% { --quiet-caret-ink: color-mix(in srgb, var(--text-muted, #8a8178) 60%, transparent); }
  50% { --quiet-caret-ink: color-mix(in srgb, var(--text-muted, #8a8178) 10%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  :is(input, textarea):read-write:focus:placeholder-shown { animation: none; }
}

/* The overlay and its lift-out card. */
.sq-overlay {
  position: fixed; inset: 0; z-index: 300;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(26, 19, 24, 0.22);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: sqFadeIn 220ms ease both;
}
.sq-overlay.is-closing { animation: sqFadeOut 170ms ease both; }
.sq-card {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  padding: 48px;
  background: var(--bg-primary);
  border: 1px solid var(--bg-tertiary, rgba(26, 19, 24, 0.1)); border-radius: 18px;
  box-shadow: 0 1px 2px rgba(26, 19, 24, 0.05), 0 12px 28px rgba(26, 19, 24, 0.1), 0 40px 90px rgba(26, 19, 24, 0.16);
  animation: sqRise 300ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.sq-overlay.is-closing .sq-card { animation: sqSink 170ms ease-in both; }
.sq-close {
  position: absolute; top: 12px; right: 12px;
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; padding: 0; cursor: pointer;
  color: var(--text-muted, rgba(26, 19, 24, 0.55));
  transition: background 160ms, color 160ms;
}
.sq-close:hover { background: var(--bg-secondary); color: var(--text-primary); }
@keyframes sqFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes sqFadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes sqRise {
  from { opacity: 0; transform: translateY(10px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
@keyframes sqSink {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(6px) scale(0.98); }
}
@media (prefers-reduced-motion: reduce) {
  .sq-overlay, .sq-card, .sq-overlay.is-closing, .sq-overlay.is-closing .sq-card { animation-duration: 1ms; }
}

/* The card's contents. Both boxes keep one fixed size: focus changes only
   colour, and the icon slot crossfades between arrow, tick and cross without
   moving anything. */
.invite-card {
  width: min(420px, 100%);
  align-items: stretch;
  padding: 50px 28px 28px;
  text-align: left;
  font-family: var(--font-serif), ui-serif, Georgia, serif;
  color: var(--text-primary);
}
.invite-card .invite-fields { display: flex; flex-direction: column; gap: 10px; width: 100%; }
/* Why the pop-up opened, when a link the person followed no longer works. */
.invite-card .invite-note {
  margin: -18px 0 16px; padding: 0 2px; width: 100%;
  font-size: 14px; line-height: 1.5; letter-spacing: 0.01em; text-wrap: pretty;
  color: var(--text-secondary, rgba(26, 19, 24, 0.75));
}

.invite-card .invite-box {
  display: flex; align-items: center; width: 100%; box-sizing: border-box; height: 54px;
  padding: 0 16px 0 18px;
  background: var(--bg-secondary);
  border: 1px solid var(--bg-tertiary, rgba(26, 19, 24, 0.14)); border-radius: 9px;
  font-family: inherit; font-size: 16px; letter-spacing: 0.01em; color: var(--text-primary);
  cursor: text;
  transition: border-color 200ms ease, background-color 220ms ease, color 220ms ease;
}
.invite-card .invite-box:hover,
.invite-card .invite-box.is-focused { border-color: var(--text-muted, rgba(26, 19, 24, 0.42)); }
/* The waitlist is the fallback: the same box, quieter until it is used. */
.invite-card .invite-box.is-quiet {
  background: transparent;
  color: var(--text-muted, rgba(26, 19, 24, 0.55));
  cursor: pointer;
}
.invite-card .invite-box.is-quiet:hover { border-color: var(--bg-tertiary, rgba(26, 19, 24, 0.24)); color: var(--text-secondary, #4d4640); }
/* A way in that is a step rather than a field (sign in, join alexandria):
   the same box, as clear as the code box beside it, so both ways read as
   open (founder, 8 October 2026: "they'll have the two boxes light up"). */
.invite-card a.invite-box, .invite-card button.invite-box { cursor: pointer; text-decoration: none; color: var(--text-primary); text-align: left; }
.invite-card a.invite-box > span:first-child, .invite-card button.invite-box > span:first-child { flex: 1; min-width: 0; }
.invite-card button.invite-box[disabled] { cursor: default; color: var(--text-muted, rgba(26, 19, 24, 0.55)); }
/* The way into a locked piece: two boxes and nothing else, so the card is
   even all round, numbered faintly so the order reads without a word. The
   first is who you are: signed out, sign in, the whole box a link; signed
   in, the account, filled and with nothing to press. */
.invite-card.is-two { padding: 28px; }
.invite-card .invite-fields.is-steps { counter-reset: way-in; }
.invite-card .invite-fields.is-steps > .invite-box::before {
  counter-increment: way-in; content: counter(way-in);
  flex: none; width: 0.6em; margin-right: 14px;
  font-size: 15px; font-variant-numeric: lining-nums tabular-nums;
  color: var(--text-ghost, rgba(26, 19, 24, 0.4));
}
/* The step to take now has the darker edge and full ink; the one beside it
   stands back, quiet (is-quiet), still there to press unless it is locked. */
.invite-card .invite-box.is-next { border-color: color-mix(in srgb, var(--text-primary, #1a1318) 45%, transparent); color: var(--text-primary); }
.invite-card .invite-box.is-next:hover { border-color: color-mix(in srgb, var(--text-primary, #1a1318) 60%, transparent); }
/* A second step that cannot be pressed until the first is done. */
.invite-card .invite-box.is-locked, .invite-card .invite-box.is-locked input { cursor: default; }
.invite-card .invite-box.is-locked .invite-icon.is-on { opacity: 0.4; }
.invite-card .invite-box.is-locked:hover { border-color: var(--bg-tertiary, rgba(26, 19, 24, 0.14)); color: var(--text-muted, rgba(26, 19, 24, 0.55)); }
/* A value that arrives a moment late (a price) fades in where it will stay. */
.invite-card .invite-value { opacity: 0; transition: opacity 220ms ease; }
.invite-card .invite-value.is-on { opacity: 1; }
.invite-card .invite-box.is-done { cursor: default; color: var(--text-secondary, #4d4640); }
.invite-card .invite-box.is-done:hover { border-color: var(--bg-tertiary, rgba(26, 19, 24, 0.14)); }
.invite-card .invite-box.is-done > span:first-child { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Who gets what, before anything is paid: one faint line under the boxes. */
.invite-card .invite-split { margin: 2px 2px 0; font-size: 13px; line-height: 1.5; color: var(--text-muted, rgba(26, 19, 24, 0.55)); text-align: left; }
/* A gentle no: a single soft sway that dies away, never a shake (Taste.md). */
.invite-card .invite-box.is-shaking { animation: inviteShake 560ms cubic-bezier(0.37, 0, 0.63, 1) both; }

.invite-card .invite-box input {
  /* What is typed starts 18px in, where an empty field's caret stands, and
     the grey words wait a step after it (lib/quiet-caret). */
  flex: 1; min-width: 0; height: 22px; padding: 0; margin: 0;
  background: transparent; border: none; outline: none;
  font: inherit; line-height: 22px; letter-spacing: inherit; color: inherit;
  -webkit-text-size-adjust: 100%;
}
.invite-card .invite-box input::placeholder { color: var(--text-muted, rgba(26, 19, 24, 0.45)); opacity: 1; transition: color 220ms ease; }
.invite-card .invite-box.is-quiet input { cursor: pointer; }
.invite-card .invite-box.is-quiet input::placeholder { color: inherit; }
.invite-card .invite-box input[readonly] { cursor: default; }

/* One fixed slot; its three icons sit on top of each other and crossfade. */
.invite-card .invite-slot { position: relative; flex: none; width: 22px; height: 22px; margin-left: 12px; }
.invite-card .invite-icon {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 0; background: none; border: none;
  color: var(--text-muted, rgba(26, 19, 24, 0.5));
  opacity: 0; transform: scale(0.72); pointer-events: none;
  transition: opacity 200ms ease, transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1), color 200ms ease;
}
.invite-card .invite-icon.is-on { opacity: 1; transform: none; pointer-events: auto; }
.invite-card .invite-icon .door-glyph { display: block; }
.invite-card button.invite-icon { cursor: pointer; border-radius: 50%; }
.invite-card button.invite-icon:hover,
.invite-card .invite-box.has-value button.invite-icon { color: var(--text-primary); }
.invite-card button.invite-icon:focus-visible { box-shadow: 0 0 0 2px var(--focus, var(--accent)); outline: none; }
.invite-card .invite-icon.is-checking { animation: invitePulse 900ms ease-in-out infinite; }
.invite-card .invite-ok { color: var(--text-primary); }
/* What went wrong, in words, just before the icon slot. It takes only the
   room it needs, so the box keeps its size and the typed text gives way. */
.invite-card .invite-says {
  flex: none; max-width: 0; overflow: hidden; white-space: nowrap;
  margin-left: 0; font-size: 14px; letter-spacing: 0.01em;
  color: var(--text-muted, rgba(26, 19, 24, 0.6));
  opacity: 0; transition: opacity 200ms ease;
}
.invite-card .invite-says.is-on { max-width: 16em; margin-left: 10px; opacity: 1; }

.invite-card .invite-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

@keyframes inviteShake {
  0%, 100% { transform: translateX(0); }
  30% { transform: translateX(-3px); }
  65% { transform: translateX(0.8px); }
}
@keyframes invitePulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }

@media (max-width: 639px) {
  .invite-card { padding: 48px 20px 22px; }
  .invite-card.is-two { padding: 20px; }
}
@media (prefers-reduced-motion: reduce) {
  .invite-card .invite-icon, .invite-card .invite-says { transition: opacity 120ms ease; transform: none; }
  .invite-card .invite-icon.is-checking,
  .invite-card .invite-box.is-shaking { animation: none; }
}

/* A way in that is a link, not a field (sign in): the quiet box, as a link. */
.invite-card a.invite-box, .invite-card a.invite-box:hover { text-decoration: none !important; justify-content: space-between; }
.invite-card a.invite-box:hover { color: var(--text-primary); }
/* The same boxes, set on a page instead of lifted out in a card. */
.invite-card.is-inline { width: min(360px, 100%); margin: 2.2rem auto 0; padding: 0; background: none; border: 0; box-shadow: none; animation: none; }
