/* =============================================================================
   AUTH.CSS  —  Login, registration, passkeys, trust-device, recovery
   Loaded in {% block extra_head %} on auth page templates only.
   Architecture 6 — Executive Console (§6). Single-column, max 420px,
   Heavy Cardstock card on bone canvas. No tier-pro blue, no auth-teal,
   no mkt-slate accents. Ink fills primary CTAs; Oxblood signals error.
   ============================================================================= */

@layer components {

/* ============================================================
   BORDER-BOX BASELINE (the fix for every "overhang")
   These surfaces have no global box-sizing reset, so any width:100%
   control with padding/border overflowed its container. Scope a
   border-box reset to the auth cards + their descendants so inputs,
   buttons and wrappers all measure to the same edge — now and future.
   ============================================================ */
.auth-card,
.auth-card *,
.auth-card *::before,
.auth-card *::after,
.pc-card,
.pc-card *,
.pc-card *::before,
.pc-card *::after,
.td-card,
.td-card *,
.recovery-card,
.recovery-card * {
  box-sizing: border-box;
}

/* ============================================================
   SHARED — Auth, Trust-Device, Recovery card shells
   ============================================================ */

.auth-wrap,
.td-wrap,
.recovery-page {
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 80px 24px 100px;
  background: var(--c-bone);
}

.recovery-page {
  min-height: 100vh;
}

/* Heavy Cardstock card (§8.1) */
.auth-card,
.td-card,
.recovery-card {
  width: 100%;
  max-width: 420px;
  background: var(--c-white);
  border: 1px solid var(--c-rule);
  border-radius: 0;
  padding: 48px 40px 40px;
  box-shadow: none;
}

.recovery-card {
  max-width: 400px;
  padding: 48px 40px 40px;
}

/* ============================================================
   AUTH HEADER — Trusted device + standard sign-in
   ============================================================ */

/* Icon well — neutral hairline-bordered square (no tier-blue tint) */
.auth-icon,
.td-icon {
  width: 52px;
  height: 52px;
  border-radius: 0;
  background: transparent;
  border: 1px solid var(--c-ink);
  color: var(--c-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 24px;
}
.td-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 28px;
}

.auth-title,
.td-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--c-ink);
  margin: 0 0 8px;
  line-height: 1.2;
}

.auth-email,
.td-sub {
  font-size: 14px;
  font-weight: 300;
  color: var(--c-muted);
  line-height: 1.6;
  margin: 0 0 28px;
}

/* ============================================================
   PRIMARY CTA — Passkey + Long & Lean variants (§8.2)
   ============================================================ */

.btn-passkey {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 12px 32px;
  background: var(--c-ink);
  color: var(--c-white);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: none;
  border: 1px solid var(--c-ink);
  border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  margin-bottom: 12px;
  transition: opacity 0.2s ease, box-shadow 0.2s ease;
}
.btn-passkey:hover {
  background: var(--c-ink);
  border-color: var(--c-ink);
  color: var(--c-white);
  opacity: 0.8;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.btn-passkey:active {
  opacity: 0.7;
}
.btn-passkey:disabled {
  background: var(--c-muted);
  border-color: var(--c-muted);
  color: var(--c-white);
  cursor: not-allowed;
  opacity: 0.6;
  box-shadow: none;
}

/* Ghost passkey button — secondary "use a passkey instead" affordance
   on first-visit / unknown-device. Lives below the primary password form. */
/* Passkey — de-emphasised text link (alternative sign-in method). Lighter than
   both the filled "Sign in" and the outlined "Create a free account" so the
   three actions form a clear weight ladder: filled > outlined > text. */
.btn-passkey-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 8px 0;
  margin-top: 12px;
  background: transparent;
  color: var(--c-muted);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: none;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.btn-passkey-link:hover {
  background: transparent;
  color: var(--c-ink);
  text-decoration-color: var(--c-ink);
}
.btn-passkey-link:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Create-account — outlined CTA. The prominent new-user action: heavier than
   the passkey text link, lighter than the filled "Sign in" primary. */
.auth-create-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 12px 32px;
  background: transparent;
  color: var(--c-ink);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  border: 1px solid var(--c-ink);
  border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: opacity 0.2s ease;
}
.auth-create-btn:hover {
  opacity: 0.8;
}

/* ============================================================
   ERROR + NOTICE BANNERS — Oxblood for alerts, neutral for notices
   ============================================================ */

.auth-error {
  display: none;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--c-oxblood);
  background: transparent;
  border: 1px solid var(--c-oxblood);
  border-radius: 0;
  padding: 10px 14px;
  margin-bottom: 12px;
  letter-spacing: 0.02em;
  line-height: 1.5;
}

/* Notice / disclaimer block — neutral hairline + oxblood left rule */
.auth-notice {
  margin: 0 0 16px;
  font-size: 12px;
  line-height: 1.6;
  background: transparent;
  color: var(--c-muted);
  padding: 12px 14px;
  border: 1px solid var(--c-rule);
  border-left: 2px solid var(--c-oxblood);
}

/* ============================================================
   DIVIDER — "or use password"
   ============================================================ */

.auth-divider {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--c-pale);
  margin: 24px 0;
}
.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--c-rule);
}

/* ============================================================
   FORM — Labels, inputs, consent rows
   ============================================================ */

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.auth-label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-muted);
  margin: 16px 0 6px;
  display: block;
}
.auth-label:first-child {
  margin-top: 0;
}

/* Label + inline action row (e.g. Password label + "Forgot?" link) */
.auth-label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 16px 0 6px;
}
.auth-label-row .auth-label {
  margin: 0;
}

.auth-forgot-link {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--c-muted);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.auth-forgot-link:hover {
  color: var(--c-ink);
  text-decoration-color: var(--c-ink);
}

/* Forgot-password link on its own line below the password field — keeps the
   right edge clear of the SHOW toggle (no more floating label-row link). */
.auth-forgot-below {
  display: block;
  text-align: right;
  margin-top: 10px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--c-muted);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.auth-forgot-below:hover {
  color: var(--c-ink);
  text-decoration-color: var(--c-ink);
}

/* Back-to-sign-in link — used at the bottom of password reset cards */
.auth-back {
  display: block;
  text-align: center;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--c-rule);
  font-size: 12px;
  font-weight: 400;
  color: var(--c-muted);
  text-decoration: none;
  letter-spacing: 0.02em;
}
.auth-back:hover {
  color: var(--c-ink);
}

/* Password fallback collapse */
.auth-details summary {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--c-ink);
  cursor: pointer;
  list-style: none;
  margin: 8px 0 16px;
  text-align: center;
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.auth-details summary:hover {
  text-decoration-color: var(--c-ink);
}
.auth-details summary::-webkit-details-marker {
  display: none;
}
.auth-details[open] summary {
  margin-bottom: 18px;
}

/* Consent checkbox rows */
.auth-consent-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  cursor: pointer;
  margin-top: 12px;
  font-size: 12px;
  color: var(--c-muted);
  line-height: 1.6;
}
.auth-consent-row input[type="checkbox"] {
  margin-top: 3px;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  accent-color: var(--c-ink);
}
.auth-consent-row .hint {
  margin: 0;
  line-height: 1.6;
}

.auth-consent-section {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--c-rule);
}

/* ============================================================
   FOOTER LINKS
   ============================================================ */

.auth-foot {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--c-rule);
  font-size: 12px;
  color: var(--c-muted);
  text-align: center;
}
.auth-foot a {
  color: var(--c-ink);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.auth-foot a:hover {
  text-decoration-color: var(--c-ink);
}

.auth-forget {
  display: block;
  text-align: center;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--c-pale);
  margin-top: 20px;
  text-decoration: none;
}
.auth-forget:hover {
  color: var(--c-ink);
}

/* Signup CTA — prominent footer for first-time visitors.
   Heavier than .auth-foot because for unknown-device users this is
   the most likely action they need to take. */
.auth-signup-cta {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--c-rule);
  font-size: 13px;
  color: var(--c-muted);
  text-align: center;
}
.auth-signup-cta a {
  color: var(--c-ink);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  margin-left: 4px;
}
.auth-signup-cta a:hover {
  text-decoration-color: var(--c-ink);
}

/* New-user section — a labelled hairline divider, then a prominent ghost CTA
   (.btn-passkey-link) and a secondary "planning check first" link. Replaces
   the old faint two-line text block so first-time visitors can't miss it. */
.auth-alt {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 28px 0 16px;
}
.auth-alt::before,
.auth-alt::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--c-rule);
}
.auth-alt__label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-muted);
  white-space: nowrap;
}
.auth-alt__link {
  display: block;
  text-align: center;
  margin-top: 14px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--c-ink);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.auth-alt__link:hover {
  text-decoration-color: var(--c-ink);
}

.auth-link {
  color: var(--c-ink);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.auth-link:hover {
  text-decoration-color: var(--c-ink);
}

/* ============================================================
   TRUST DEVICE PAGE
   ============================================================ */

.td-card {
  text-align: center;
}

.td-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.td-detail {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--c-rule);
  font-size: 11px;
  color: var(--c-pale);
  line-height: 1.6;
}
.td-detail a {
  color: var(--c-ink);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.td-detail a:hover {
  text-decoration-color: var(--c-ink);
}

/* ============================================================
   RECOVERY LOGIN — Emergency Access
   ============================================================ */

.recovery-icon {
  width: 56px;
  height: 56px;
  border: 1px solid var(--c-oxblood);
  color: var(--c-oxblood);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  margin-bottom: 24px;
}

.recovery-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--c-ink);
  margin: 0 0 8px;
  line-height: 1.2;
}

.recovery-sub {
  font-size: 13px;
  font-weight: 300;
  color: var(--c-muted);
  margin: 0 0 32px;
  line-height: 1.6;
}

.recovery-label {
  display: block;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-muted);
  margin: 0 0 6px;
}

.recovery-input {
  display: block;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--c-rule);
  border-radius: 0;
  font-family: var(--font-sans);
  font-size: 14px;
  margin-bottom: 16px;
  background: var(--c-white);
  color: var(--c-ink);
  box-sizing: border-box;
  transition: border-color 0.15s, background 0.15s;
}
.recovery-input:focus {
  outline: none;
  border-color: var(--c-ink);
  background: var(--c-bone);
}
.recovery-input--mono {
  font-family: var(--font-mono);
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;
}

.recovery-submit {
  width: 100%;
  padding: 12px 32px;
  background: var(--c-ink);
  color: var(--c-white);
  border: 1px solid var(--c-ink);
  border-radius: 0;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.05em;
  cursor: pointer;
  margin-top: 4px;
  transition: opacity 0.2s ease, box-shadow 0.2s ease;
}
.recovery-submit:hover {
  opacity: 0.8;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

.recovery-error {
  background: transparent;
  border: 1px solid var(--c-oxblood);
  border-radius: 0;
  padding: 10px 14px;
  font-size: 12px;
  font-weight: 500;
  color: var(--c-oxblood);
  margin-bottom: 20px;
  letter-spacing: 0.02em;
  line-height: 1.5;
}

.recovery-warning-bar {
  background: transparent;
  border: 1px solid var(--c-rule);
  border-left: 2px solid var(--c-oxblood);
  border-radius: 0;
  padding: 12px 14px;
  font-size: 11px;
  color: var(--c-muted);
  margin-bottom: 24px;
  line-height: 1.6;
}

.recovery-back {
  display: block;
  text-align: center;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--c-rule);
  font-size: 11px;
  font-weight: 400;
  color: var(--c-pale);
  text-decoration: none;
}
.recovery-back:hover {
  color: var(--c-ink);
}

/* ============================================================
   PASSKEYS MANAGEMENT PAGE
   ============================================================ */

.pk-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 80px 24px 120px;
}

.pk-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 40px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--c-rule);
  gap: 16px;
  flex-wrap: wrap;
}

.pk-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--c-ink);
  margin: 0;
  line-height: 1.2;
}

.pk-subtitle {
  font-size: 13px;
  font-weight: 300;
  color: var(--c-muted);
  margin: 6px 0 0;
  line-height: 1.5;
}

.btn-add-key {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 32px;
  background: var(--c-ink);
  color: var(--c-white);
  border: 1px solid var(--c-ink);
  border-radius: 0;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.05em;
  cursor: pointer;
  white-space: nowrap;
  transition: opacity 0.2s ease, box-shadow 0.2s ease;
}
.btn-add-key:hover {
  opacity: 0.8;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

/* ── Key cards ── */
.pk-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  border-top: 1px solid var(--c-rule);
}

.pk-card {
  background: var(--c-white);
  border: none;
  border-bottom: 1px solid var(--c-rule);
  border-radius: 0;
  padding: 20px 0;
  display: flex;
  align-items: center;
  gap: 16px;
}

.pk-card__icon {
  width: 36px;
  height: 36px;
  border-radius: 0;
  background: var(--c-stone);
  border: 1px solid var(--c-rule);
  color: var(--c-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.pk-card__body {
  flex: 1;
  min-width: 0;
}

.pk-card__name {
  font-size: 14px;
  font-weight: 500;
  color: var(--c-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.01em;
}

.pk-card__meta {
  font-size: 11px;
  font-weight: 400;
  color: var(--c-pale);
  margin-top: 4px;
  letter-spacing: 0.02em;
}

.pk-card__actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

/* ── Toggle switch — Ink-on (active), Rule-off ── */
.pk-toggle {
  position: relative;
  width: 40px;
  height: 22px;
  cursor: pointer;
}
.pk-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}
.pk-toggle__track {
  position: absolute;
  inset: 0;
  border-radius: 0;
  background: var(--c-rule);
  border: 1px solid var(--c-rule);
  transition: background 0.2s, border-color 0.2s;
}
.pk-toggle input:checked ~ .pk-toggle__track {
  background: var(--c-ink);
  border-color: var(--c-ink);
}
.pk-toggle__thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--c-white);
  border: 1px solid var(--c-ink);
  box-shadow: none;
  transition: left 0.2s;
}
.pk-toggle input:checked ~ .pk-toggle__thumb {
  left: 22px;
}

/* ── Status badges — White-on-Ink active, transparent muted off ── */
.pk-badge {
  font-size: 9px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 0;
  background: var(--c-ink);
  color: var(--c-white);
  border: 1px solid var(--c-ink);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.pk-badge--off {
  background: transparent;
  color: var(--c-muted);
  border: 1px solid var(--c-rule);
}

/* Delete button */
.btn-del {
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 6px;
  color: var(--c-pale);
  border-radius: 0;
  display: flex;
  align-items: center;
  transition: color 0.15s, border-color 0.15s;
}
.btn-del:hover {
  color: var(--c-oxblood);
  border-color: var(--c-oxblood);
  background: transparent;
}

/* Empty state */
.pk-empty {
  text-align: center;
  padding: 80px 24px;
  color: var(--c-muted);
  font-size: 13px;
  font-weight: 300;
  border: 1px dashed var(--c-rule);
  border-radius: 0;
  background: transparent;
}

/* ── Overlay dialog ── */
.pk-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(26, 26, 26, 0.55);
  z-index: 9999;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.pk-overlay.open {
  display: flex;
  animation: astor-rise 0.22s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.pk-dialog {
  background: var(--c-white);
  border: 1px solid var(--c-rule);
  border-radius: 0;
  padding: 40px 36px 32px;
  width: 100%;
  max-width: 420px;
  box-shadow: none;
  position: relative;
}

.pk-dialog__title {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--c-ink);
  margin: 0 0 20px;
  line-height: 1.2;
}

.pk-dialog__body {
  font-size: 13px;
  font-weight: 300;
  color: var(--c-muted);
  line-height: 1.6;
}

.pk-dialog input[type=text] {
  display: block;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--c-rule);
  border-radius: 0;
  font-family: var(--font-sans);
  font-size: 14px;
  margin-top: 12px;
  background: var(--c-white);
  color: var(--c-ink);
  box-sizing: border-box;
  transition: border-color 0.15s, background 0.15s;
}
.pk-dialog input:focus {
  outline: none;
  border-color: var(--c-ink);
  background: var(--c-bone);
}

.pk-dialog__msg {
  margin-top: 14px;
  font-size: 12px;
  font-weight: 500;
  min-height: 22px;
  letter-spacing: 0.02em;
}
.pk-dialog__msg--ok {
  color: var(--c-ink);
}
.pk-dialog__msg--err {
  color: var(--c-oxblood);
}

.pk-dialog__foot {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--c-rule);
}

/* ── Dialog buttons — Long & Lean small variants ── */
.btn-primary-sm,
.btn-ghost-sm,
.btn-danger-sm {
  padding: 8px 24px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: none;
  border-radius: 0;
  cursor: pointer;
  transition: opacity 0.2s ease, box-shadow 0.2s ease;
  white-space: nowrap;
}

.btn-primary-sm {
  background: var(--c-ink);
  color: var(--c-white);
  border: 1px solid var(--c-ink);
}
.btn-primary-sm:hover {
  opacity: 0.8;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.btn-primary-sm:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.btn-ghost-sm {
  background: transparent;
  color: var(--c-ink);
  border: 1px solid var(--c-ink);
}
.btn-ghost-sm:hover {
  background: transparent;
  opacity: 0.7;
  box-shadow: none;
}

.btn-danger-sm {
  background: var(--c-oxblood);
  color: var(--c-white);
  border: 1px solid var(--c-oxblood);
}
.btn-danger-sm:hover {
  background: var(--c-oxblood-dk);
  border-color: var(--c-oxblood-dk);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
  opacity: 1;
}

.pk-close {
  position: absolute;
  top: 16px;
  right: 16px;
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--c-pale);
  padding: 2px 8px;
  border-radius: 0;
  transition: color 0.15s, border-color 0.15s;
}
.pk-close:hover {
  color: var(--c-ink);
  border-color: var(--c-rule);
  background: transparent;
}

/* ============================================================
   RESPONSIVE — Mobile baseline
   ============================================================ */

@media (max-width: 768px) {
  /* iOS zoom prevention — inputs must be ≥ 16px */
  .auth-form .input,
  .pc-form .input,
  .recovery-input,
  .pk-dialog input[type=text] {
    font-size: 16px;
  }
}

@media (max-width: 480px) {
  .auth-wrap,
  .td-wrap,
  .recovery-page {
    padding: 56px 18px 80px;
  }
  .auth-card,
  .td-card,
  .recovery-card {
    padding: 36px 28px 28px;
  }
  .pk-page {
    padding: 56px 18px 80px;
  }
  .pk-card {
    flex-wrap: wrap;
  }
}

/* ============================================================
   FORM FIELDS — §6 Executive Console
   1px hairline box, 0 radius, box-sizing border-box (no overflow),
   focus -> Warm Bone fill + Inky Black border. Scoped to the auth +
   signup forms so it overrides the global underline-only .input there.
   ============================================================ */

.auth-form .input,
/* ── The form's shape: wider, and paired where the answers are short ────────
   Cain, 2026-08-26: *"I would also like to address our form and see if we
   can't make it slightly wider, but slightly less long"* and *"i want you to
   stack the questions side by side where it makes sense and is efficient
   rather than just having very long boxes that could never reasonably be
   filled that much."*

   640px -> 880px, and the short questions pair up: 30 questions in 30 rows
   became 35 in 24. WHICH questions pair is decided per question in
   `lender/intake_fields.py` (`Field.row_width`), not here — the segmented
   controls, the option cards, the scheme chips and Notes keep the whole row
   because their OPTIONS need it, and a question left alone at the end of a
   section stays half width rather than stretching to fill one. */
.pc-main--wide { max-width: 880px; }
.pc-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 22px; }
/* A long answer beside a short one — the site address and its postcode. */
.pc-pair--21 { grid-template-columns: 2fr 1fr; }
/* One column on a phone. A 300px box for an email address is worse than a
   longer page, which is the trade this whole change is balancing. */
@media (max-width: 720px) {
  .pc-pair, .pc-pair--21 { grid-template-columns: 1fr; }
}

.pc-form .input {
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--c-rule);
  border-radius: 0;
  background: var(--c-white);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.4;
  color: var(--c-ink);
}
.auth-form .input::placeholder,
.pc-form .input::placeholder {
  color: var(--c-pale);
}
.auth-form .input:focus,
.pc-form .input:focus {
  outline: none;
  background: var(--c-bone);
  border-color: var(--c-ink);
}

/* Signup labels (.field-label) match the §6 login labels (.auth-label) */
.field-label {
  display: block;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-muted);
  margin: 16px 0 6px;
}

/* ── SHOW / HIDE password toggle (injected by auth_enhance.js) ──
   The wrapper becomes the bordered field box; the inner input is
   borderless so [ input | SHOW ] read as one §6 control. No absolute
   positioning, box-sizing border-box -> never overflows or collides. */
.pw-field {
  box-sizing: border-box;
  display: flex;
  align-items: stretch;
  width: 100%;
  border: 1px solid var(--c-rule);
  border-radius: 0;
  background: var(--c-white);
}
.pw-field:focus-within {
  background: var(--c-bone);
  border-color: var(--c-ink);
}
.auth-form .pw-field .input,
.pc-form .pw-field .input {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;          /* shrink so the button fits inside the box */
  border: 0;
  background: transparent;
}
.auth-form .pw-field .input:focus,
.pc-form .pw-field .input:focus {
  background: transparent;   /* the wrapper owns the focus styling */
  border: 0;
}
.pw-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
  padding: 0 14px;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--c-rule);   /* hairline divider inside the box */
  box-shadow: none;
  border-radius: 0;
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-muted);
  cursor: pointer;
  white-space: nowrap;
}
.pw-toggle:hover {
  color: var(--c-ink);
}
.pw-toggle:focus-visible {
  outline: 1px solid var(--c-ink);
  outline-offset: -2px;
}

/* ============================================================
   HONEYPOT — bot trap, hidden from humans (signup). Deliberately
   NOT display:none (some bots skip those); pushed off-screen instead.
   ============================================================ */
.hp-field {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

} /* end @layer components */

/* ═══════════════════════════════════════════════════════════════════════
   DEAL INTAKE — public, white-labelled surfaces
   The broker-facing form, its confirmation and the resume page. Loaded by
   the same {% block extra_head %} the sign-up page uses, so these ride on
   the §6 Executive Console form primitives (.pc-card / .input / .field-label)
   rather than introducing a second form vocabulary.
   ═══════════════════════════════════════════════════════════════════════ */

/* White-label lockup. base.html's site header hard-codes the Astor mark and
   BRAND_NAME, so a page carrying a LENDER's name needs its own identity band.
   Ink on bone, hairline under, 0 radius — §2 / §3. */
.wl-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 14px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--c-rule);
}
.wl-head__logo {
  max-height: 34px;
  max-width: 190px;
  display: block;
}
.wl-head__name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--c-ink);
}
.wl-head__tagline {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-muted);
}
.wl-head__powered {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--c-pale);
}

/* Required marker. Ink, not oxblood: §2 reserves oxblood for critical risk,
   and "we need this field" is not a risk finding. */
.field-label .req {
  color: var(--c-ink);
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* ── TAP-CHIPS on the public form (.seg) ──────────────────────────────────
   The two classification questions — what kind of property, what the money is
   for — are asked as chips, not dropdowns. Founder, 2026-08-17: "I hate
   dropdowns"; a short known list is strictly worse hidden behind a click, and
   a broker on a phone taps once instead of opening a picker.

   THIS RESTATES app.css §PICK-ONE (.seg / .seg__opt), and it has to. This is a
   PUBLIC white-label page: base.html loads tokens/layout/home/nav, NOT app.css,
   and pulling app.css in here to reach one component would drag its bare
   `label` and `input` base rules across a form built on the §6 auth
   primitives. The rules below are the same rules — same idiom, same tokens,
   same :has(input:checked) selected state, and the SAME SELECTORS — not a
   `.pc-form`-scoped variant, because scripts/css_orphan_audit.py derives a
   primitive's defining sheets from selectors that START with the class, and a
   scoped copy is invisible to it. An audit that cannot see the second
   definition would pass while the public form rendered its radios invisible.
   If you change one, change both.
   app.css's own block carries the reasoning for the resets: `label` is styled
   as an uppercase eyebrow, and these options ARE labels, so text-transform /
   letter-spacing / font-weight / margin have to be said out loud. */
/* HUGS ITS OPTIONS. This copy had drifted to `display: flex` with no
   `width: fit-content`, so a .seg on the PUBLIC form would stretch the full
   column with a long empty tail after the last option — the full-bleed input
   the design system exists to avoid, and the opposite of what the same class
   does on every internal page. No public template renders a .seg yet, so this
   corrects the copy before the first one does rather than after. app.css
   §PICK-ONE is the original; the two are meant to be identical. */
.seg {
  display: inline-flex;
  flex-wrap: wrap;
  width: fit-content;
  border: 1px solid var(--c-rule);
  background: var(--c-white);
}
.seg__opt {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 9px 14px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1.2;
  color: var(--c-muted);
  border-right: 1px solid var(--c-rule);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 500;
  margin: 0;
  transition: background .12s, color .12s;
}
.seg__opt:last-child { border-right: none; }
/* The radio is the control; the label is the target. Hidden, not removed —
   display:none would take it out of the tab order and off screen readers. */
.seg__opt input { position: absolute; opacity: 0; pointer-events: none; }
.seg__opt:hover { background: var(--c-bone); color: var(--c-ink); }
/* THE SELECTED STATE HAS TWO SPELLINGS, AND BOTH ARE REQUIRED. `:has(input:checked)`
   covers the radio form of this control. It CANNOT cover the form where the
   options are links — a tablist that switches view by GET, which has no radio to
   check — and Settings → Lending shipped exactly that: correct `is-active` and
   `aria-selected` in the markup, and no rule in any stylesheet to draw them.
   Every tab rendered identically, so the one you were on was invisible. Cain,
   2026-08-23: "the tab doesn't show which one you are on, eg LTV or LTGDV so the
   user has to click through to figure it out." Fixed on the COMPONENT, not on
   that page, so the next link-shaped .seg is not the same bug again. */
.seg__opt:has(input:checked),
.seg__opt.is-active { background: var(--c-ink); color: var(--c-white); }
a.seg__opt { text-decoration: none; }
a.seg__opt:focus-visible { outline: 1px solid var(--c-ink); outline-offset: -2px; }
.seg__opt:has(input:focus-visible) {
  outline: 1px solid var(--c-ink);
  outline-offset: -2px;
}
/* Same oxblood hairline a text field gets when it fails validation. */
.seg--error { border-color: var(--c-oxblood); }

/* ── .chipset and .pick on the public form ────────────────────────────────
   The public counterparts of app.css §PICK-ONE, for the same reason .seg is
   restated above: this page does not load app.css. Same selectors, so
   scripts/css_orphan_audit.py can see both definitions. If you change one,
   change both.

   `.chipset` is a wrapping tap-chip row for 7+ self-explaining options (the ten
   asset classes). `.pick` is the card form for options that need a line of
   explanation (the four loan types — "Release of Equity" does not explain
   itself, and a glossary paragraph under a row of chips is not an explanation,
   it is a wall). */
.chipset { display: flex; flex-wrap: wrap; gap: 8px; }
.chipset__opt {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  padding: 10px 15px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1.2;
  color: var(--c-muted);
  border: 1px solid var(--c-rule);
  background: var(--c-white);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 500;
  margin: 0;
  transition: background .12s, color .12s, border-color .12s;
}
.chipset__opt input { position: absolute; opacity: 0; pointer-events: none; }
.chipset__opt:hover { border-color: var(--c-ink); color: var(--c-ink); }
.chipset__opt:has(input:checked) {
  background: var(--c-ink); color: var(--c-white); border-color: var(--c-ink);
}
.chipset__opt:has(input:focus-visible) { outline: 1px solid var(--c-ink); outline-offset: 2px; }
.chipset--child { margin-top: 10px; padding-left: 14px; border-left: 1px solid var(--c-rule); }

.pick { display: grid; gap: 0; border: 1px solid var(--c-rule); background: var(--c-white); }
.pick--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pick__opt {
  position: relative; display: flex; flex-direction: column; gap: 4px;
  padding: 14px 16px; cursor: pointer; margin: 0;
  text-transform: none; letter-spacing: normal;
  border-right: 1px solid var(--c-rule);
  border-bottom: 1px solid var(--c-rule);
}
.pick__opt input { position: absolute; opacity: 0; pointer-events: none; }
/* Two columns: every second option ends its row, and the last two end the grid. */
.pick--2 .pick__opt:nth-child(2n) { border-right: none; }
.pick--2 .pick__opt:nth-last-child(-n+2) { border-bottom: none; }
.pick__name { font-size: 14px; font-weight: 600; color: var(--c-ink); }
.pick__why  { font-size: 12px; font-weight: 400; color: var(--c-muted); line-height: 1.45; }
.pick__opt:hover { background: var(--c-bone); }

/* A nested family of `.pick` cards — the commercial specialisms under
   "Commercial". Restated in app.css and auth.css exactly as the rest of the
   pick-one primitives are: the PUBLIC white-label intake form loads auth.css
   and never app.css, and a copy is the price of that split.

   The left rule and indent are what say "this refines the answer above" —
   necessary because parent and children share one radio group, so picking a
   child unchecks the parent card and the geometry is the only thing left
   holding them together. The lead-in line carries the same message in words. */
.pick-child { margin-top: 10px; padding-left: 14px;
  border-left: 1px solid var(--c-rule); }

/* `hidden` MUST ACTUALLY HIDE. The reveal in intake_form.html sets
   `box.hidden = true` on a family that is not in play. `[hidden]` is a
   USER-AGENT rule (`display: none`), so ANY author `display` declaration
   outranks it — `.chipset { display: flex }` did exactly that, and the
   commercial specialisms sat on screen permanently no matter what the script
   decided. Two independent faults produced one symptom: the reveal could not
   find its parent, AND hiding did not hide.

   Author-level and specific enough to beat the component rule. Do not remove it
   because "hidden already does that" — here it did not. */
.pick-child[hidden],
.chipset--child[hidden] { display: none; }
.pick__lead { display: block; font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--c-muted);
  margin-bottom: 6px; }

.pick__opt:has(input:checked) { background: var(--c-ink); }
.pick__opt:has(input:checked) .pick__name { color: var(--c-white); }
.pick__opt:has(input:checked) .pick__why  { color: rgba(255,255,255,0.68); }
.pick__opt:has(input:focus-visible) { outline: 1px solid var(--c-ink); outline-offset: -2px; }
@media (max-width: 620px) {
  .pick--2 { grid-template-columns: 1fr; }
  .pick--2 .pick__opt { border-right: none; }
  .pick--2 .pick__opt:nth-last-child(-n+2) { border-bottom: 1px solid var(--c-rule); }
  .pick--2 .pick__opt:last-child { border-bottom: none; }
}

/* ── The disclosure that opens the "already filled in the PDF" upload ──────
   Every other <details> on the site kills the native marker (app.css does it
   for .lp-menu__trigger, .bpl-a4-detail and .bi-a4-detail). This one did not,
   so a raw browser ">" triangle appeared on a page where that glyph exists
   nowhere else. Cain, 2026-08-21: "the upload the pdf is using > which is used
   nowhere else in the website." */
.pc-disclosure > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--c-muted);
  padding: 2px 0;
}
.pc-disclosure > summary::-webkit-details-marker { display: none; }
.pc-disclosure > summary:hover { color: var(--c-ink); }
/* Astor's own affordance in place of the triangle: a hairline that lengthens
   when the panel is open. Same idea as the nav underline, no new glyph. */
.pc-disclosure > summary::before {
  content: ""; width: 14px; height: 1px; background: currentColor;
  transition: width .15s;
}
.pc-disclosure[open] > summary::before { width: 26px; }

/* ── The money row: the amount and every way of reaching it, on ONE line ──
   Cain, 2026-08-21: "my scope was efficient use of space and to be KISS. we can
   put these on a single row (day one advance number, % and %)". Before this the
   £ box spanned the page and the two percentages sat on a line of their own,
   which is three rows for one question.

   Also his standing rule, 2026-08-17: no "input boxes that span the whole page
   for zero reason". A seven-digit figure needs about eleven characters, so the
   money box is sized for its content and the row keeps the rest of the width
   for the instruments that belong to it. */
.pc-row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 10px;
}
/* £ and % sit INSIDE the field's border, so the unit reads as part of the
   figure rather than as a label floating beside it. */
.pc-row__money, .pc-row__pct {
  display: inline-flex;
  align-items: center;
  gap: 0;
  border: 1px solid var(--c-rule);
  background: var(--c-white);
}
.pc-row__money:focus-within, .pc-row__pct:focus-within {
  border-color: var(--c-ink);
  background: var(--c-bone);
}
.pc-row__unit {
  font-style: normal;
  font-size: 14px;
  color: var(--c-pale);
  padding: 0 0 0 13px;
}
.pc-row__pct .pc-row__unit { padding: 0 13px 0 0; }
.pc-row__in {
  box-sizing: border-box;
  width: 168px;
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.4;
  padding: 12px 13px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--c-ink);
  font-variant-numeric: tabular-nums;
}
.pc-row__in:focus { outline: none; }
.pc-row__in--pct { width: 76px; text-align: right; padding-right: 6px; }
.pc-row__money:has(.has-error), .pc-row__pct:has(.has-error) { border-color: var(--c-oxblood); }
/* The caption belongs to the percentage box it labels, so it sits in the row
   rather than under it. */
.pc-row__pct small {
  font-size: 10px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--c-muted);
  padding-right: 12px;
  white-space: nowrap;
}

/* One tap for the whole development budget. ALWAYS on the page — it used to be
   hidden until a build cost existed, so the maximum Cain asked for twice was
   invisible to anyone who had not yet scrolled back and filled one in. Disabled
   and saying why is honest; absent is not. */
.pc-row__max {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 1px;
  font-family: var(--font-sans);
  cursor: pointer;
  padding: 6px 14px;
  border: 1px solid var(--c-rule);
  border-radius: 0;
  background: var(--c-white);
  text-align: left;
}
/* IT HAS TO LOOK PRESSABLE. Enabled, this carried the same hairline border and
   white fill as the money inputs beside it, so the one-tap maximum read as a
   third read-only box. Cain, 2026-08-24: "The UI on the max £150k should be
   more obviously a button." Enabled = an inked border and the ink fill on
   hover, the same language as every other button; DISABLED stays quiet,
   because an affordance that cannot be used should not shout. */
.pc-row__max:not(:disabled) { border-color: var(--c-ink); color: var(--c-ink); }
.pc-row__max:hover:not(:disabled) { background: var(--c-ink); }
.pc-row__max:hover:not(:disabled) .pc-row__maxlbl,
.pc-row__max:hover:not(:disabled) .pc-row__maxval { color: var(--c-white); }
.pc-row__max:not(:disabled) .pc-row__maxlbl { color: var(--c-ink); font-weight: 600; }
.pc-row__max:focus-visible { outline: 2px solid var(--c-ink); outline-offset: 2px; }
.pc-row__max:disabled { cursor: default; }
/* The derived loan type, read back where the question used to be. Bordered like
   the scheme block's echo, because it is the same idea: the form telling you
   what it made of your answers, not asking you another one. */
.pc-derived { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
              margin: 0 0 var(--space-5); padding: 10px 14px;
              border: 1px solid var(--c-rule); border-left: 2px solid var(--c-ink);
              background: var(--c-white); }
.pc-derived__lbl { font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
                   color: var(--c-muted); }
.pc-derived__val { font-size: 15px; font-weight: 600; color: var(--c-ink); }
.pc-derived__why { font-size: 12px; color: var(--c-muted); flex: 1 1 100%; }

.pc-row__maxlbl {
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-muted);
}
.pc-row__maxval {
  font-size: 14px;
  color: var(--c-ink);
  font-variant-numeric: tabular-nums;
}
.pc-row__max:disabled .pc-row__maxval {
  font-size: 11px;
  color: var(--c-pale);
  font-variant-numeric: normal;
}
@media (max-width: 560px) {
  .pc-row__in { width: 100%; }
  .pc-row__money { flex: 1 1 100%; }
}

/* ── The live check ───────────────────────────────────────────────────────
   What the broker's own numbers come to, as they type. Every figure here is
   arithmetic on what THEY entered — no threshold of ours appears, so the panel
   cannot leak appetite. It answers the question a broker actually has, which
   is "is this the kind of deal you do", without us saying so. */
.pc-live {
  border: 1px solid var(--c-rule);
  background: var(--c-white);
  padding: 16px 18px;
  margin-top: 18px;
}
.pc-live__hd {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-pale);
  margin: 0 0 12px;
}
.pc-live__row { display: flex; flex-wrap: wrap; gap: 22px 30px; }
.pc-live__item { display: flex; flex-direction: column; gap: 3px; }
.pc-live__val {
  font-size: 20px;
  font-weight: 500;
  color: var(--c-ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.pc-live__lbl {
  font-size: 10px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--c-muted);
}

/* Per-field error. Sits under the input it belongs to and names the fix. */
.pc-field-error {
  margin: 6px 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--c-oxblood);
}
.pc-form .input.has-error { border-color: var(--c-oxblood); }

.pc-form-error {
  border: 1px solid var(--c-oxblood);
  border-left-width: 3px;
  padding: 14px 16px;
  margin-bottom: 18px;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--c-ink);
}

/* The sender's own resume link on the Received page. It was a readonly
   <input>: copyable but not clickable, so opening your own link took a copy
   and a paste. An anchor reads as the field it replaces and still selects
   cleanly for copying. break-all because a signed token has no spaces. */
.intake-resume-link {
  display: block;
  padding: 12px 14px;
  border: 1px solid var(--c-rule);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--c-ink);
  word-break: break-all;
  text-decoration: underline;
}
.intake-resume-link:hover,
.intake-resume-link:focus-visible { border-color: var(--c-ink); }

/* The "what this gets to" checklist on the submit card. */
.pc-check { display: flex; align-items: baseline; gap: 10px; }
.pc-check__mark {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--c-muted);
  flex: none;
}
