/* ============================================================
   Spyne — authentication screens
   Sign in · Sign up · Password reset · Confirmation · Unlock
   ============================================================ */
:root{
  --pine:#0B6B4E;
  --pine-dark:#07452F;
  --pine-deep:#062E20;
  --ink:#0D1F18;
  --slate:#54685F;
  --mist:#E7F0EB;
  --paper:#F7FAF8;
  --line:#DCE7E1;
  --teal:#14B8A6;
  --cobalt:#2563EB;
  --spine:linear-gradient(180deg,#14B8A6 0%,#2563EB 100%);
  --amber:#B97F14;
  --amber-bg:#FBF0D7;
  --danger:#B4432C;
  --danger-bg:#FBE9E5;
  --ok:#0B6B4E;
  --ok-bg:#DCF3E7;
  --font-display:"Bricolage Grotesque",system-ui,-apple-system,sans-serif;
  --font-body:"Inter",system-ui,-apple-system,sans-serif;
  --font-mono:"IBM Plex Mono",ui-monospace,monospace;
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{
  font-family:var(--font-body);
  color:var(--ink);
  background:var(--paper);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--pine);text-decoration:none;font-weight:500}
a:hover{text-decoration:underline}
img,svg{display:block;max-width:100%}
:focus-visible{outline:3px solid rgba(20,184,166,.55);outline-offset:2px;border-radius:6px}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}

/* ---------------- shell ---------------- */
.auth{display:grid;grid-template-columns:minmax(0,46fr) minmax(0,54fr);min-height:100vh}

/* ---------------- left brand panel ---------------- */
.auth-aside{
  background:var(--pine-deep);
  color:#DCEAE3;
  padding:44px 52px;
  display:flex;
  flex-direction:column;
  overflow:hidden;
  /* Sized by the viewport, not the form column: stretching with the form
     made margin-top:auto on .aside-body shift the copy down whenever a
     hint or error line appeared on the right. */
  position:sticky;
  top:0;
  align-self:start;
  min-height:100vh;
}
.auth-aside::before{ /* ambient glow */
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(520px 340px at 12% 6%,rgba(20,184,166,.20),transparent 62%),
    radial-gradient(460px 380px at 92% 96%,rgba(37,99,235,.18),transparent 60%);
}
.auth-aside::after{ /* the spine */
  content:"";position:absolute;left:0;top:0;bottom:0;width:5px;background:var(--spine);
}
.auth-aside > *{position:relative;z-index:1}

.auth-logo{display:inline-flex;align-items:center;gap:11px;font-family:var(--font-display);
  font-weight:800;font-size:1.3rem;color:#fff;letter-spacing:-.02em}
.auth-logo:hover{text-decoration:none}
.auth-logo small{font-family:var(--font-mono);font-weight:400;font-size:.6rem;
  letter-spacing:.14em;text-transform:uppercase;color:#7FA294;margin-top:7px}

.aside-body{margin-top:auto;padding:44px 0 40px}
.aside-eyebrow{font-family:var(--font-mono);font-size:.7rem;letter-spacing:.16em;
  text-transform:uppercase;color:#7DD3B8;display:flex;align-items:center;gap:.7em;margin-bottom:20px}
.aside-eyebrow::before{content:"";width:24px;height:2px;background:var(--spine);border-radius:2px}
.auth-aside h2{font-family:var(--font-display);font-size:clamp(1.7rem,2.6vw,2.35rem);
  line-height:1.12;letter-spacing:-.025em;color:#fff;font-weight:700}
.auth-aside .aside-lede{margin-top:16px;color:#A8C4B8;font-size:1rem;max-width:34ch}

/* vertebra checklist — the ticks sit on the spine */
.aside-list{margin-top:32px;display:grid;gap:2px}
.aside-list li{display:flex;gap:14px;align-items:flex-start;padding:11px 0;font-size:.94rem;color:#CFE3DA}
.aside-list .tick{
  flex:none;width:24px;height:24px;border-radius:50%;
  background:rgba(255,255,255,.07);border:1.5px solid rgba(125,211,184,.5);
  display:grid;place-items:center;color:#7DD3B8;margin-top:1px;
}
.aside-list .tick svg{width:12px;height:12px}

/* small proof card */
.aside-proof{
  margin-top:34px;border:1px solid rgba(255,255,255,.14);border-radius:14px;
  padding:18px 20px;background:rgba(255,255,255,.045);backdrop-filter:blur(3px);
}
.aside-proof p{font-family:var(--font-display);font-size:1.02rem;line-height:1.4;
  color:#fff;font-weight:600;letter-spacing:-.01em}
.aside-proof span{display:block;margin-top:10px;font-family:var(--font-mono);
  font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:#7FA294}

.aside-foot{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.08em;color:#5E8375}

/* ---------------- optional illustration slot ----------------
   Takes the free height between the logo and the copy and centres its
   picture in it, so a tall screen shows the picture instead of a gap.
   With nothing in the slot the layout is exactly as before.

   The frame is a size container, so the picture is sized by the room this
   page's copy actually leaves it, not by the viewport: the same screen has
   space to spare under two-factor's two lines and none under sign-up's
   checklist. Being absolutely positioned, the picture can never make the
   sticky panel taller than the viewport. Thresholds are the tallest
   picture (new password: 262px full size, 209px at 80%).

   The container is the absolute frame, not the flex slot itself: Chrome
   evaluates a size query on a flex item at its zero-height measuring pass
   and never re-runs it, so on the slot every query matched as if 0px. */
.aside-visual{flex:1;position:relative;min-height:0}
.aside-visual-frame{position:absolute;inset:28px 0 0;display:grid;place-items:center start;
  container:aside-visual / size}
.aside-visual + .aside-body{margin-top:0}
@container aside-visual (height < 262px){ .aside-visual-frame > *{zoom:.8} }
@container aside-visual (height < 210px){ .aside-visual-frame > *{display:none} }

/* ---- shared illustration pieces: a white card on the dark panel, with
   up to two chips pinned to its corners ---- */
.vis-scene{position:relative;width:min(100%,380px);padding:22px 24px 26px 0}
.vis-card{position:relative;background:#fff;color:var(--ink);border-radius:16px;padding:18px 20px 20px;
  box-shadow:0 30px 60px -24px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.06);
  animation:vis-float 6s ease-in-out infinite}
.vis-chip{position:absolute;display:inline-flex;align-items:center;gap:7px;font-family:var(--font-mono);
  font-size:.64rem;letter-spacing:.06em;text-transform:uppercase;padding:6px 11px;border-radius:99px;white-space:nowrap}
.vis-chip svg{width:11px;height:11px}
.vis-chip-top{right:0;top:6px}
.vis-chip-bottom{left:16px;bottom:8px}
.vis-chip-ok{background:#DCF3E7;color:var(--pine)}
.vis-chip-muted{background:#0B3A2A;color:#A8C4B8;border:1px solid rgba(255,255,255,.14)}
.vis-chip-warn{background:#FBE9E5;color:var(--danger)}
@keyframes vis-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}

/* an email, as it lands (devise/shared/_mail_preview) */
.mail-head{display:flex;align-items:center;gap:10px}
.mail-avatar{flex:none;width:32px;height:32px;border-radius:50%;background:var(--pine-deep);display:grid;place-items:center}
.mail-from{display:grid;line-height:1.25;min-width:0}
.mail-from b{font-size:.9rem}
.mail-from span{font-size:.74rem;color:var(--slate);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mail-time{margin-left:auto;font-family:var(--font-mono);font-size:.66rem;color:var(--slate)}
.mail-subject{margin:14px 0 10px;font-family:var(--font-display);font-weight:700;font-size:1.05rem;letter-spacing:-.01em}
.mail-line{display:block;height:7px;border-radius:99px;background:var(--mist);margin-bottom:7px}
.mail-button{display:inline-block;margin-top:8px;background:var(--pine);color:#fff;font-weight:600;font-size:.8rem;
  padding:8px 15px;border-radius:10px;box-shadow:0 8px 18px -8px rgba(11,107,78,.7)}
.mail-code{display:flex;gap:7px;margin-top:4px}
.mail-code span{width:34px;height:40px;border-radius:9px;border:1.5px solid var(--line);background:var(--paper);
  display:grid;place-items:center;font-size:1.3rem;color:var(--pine)}

/* account locked (devise/unlocks/new) */
.lock-head{display:flex;align-items:center;gap:12px}
.lock-badge{flex:none;width:40px;height:40px;border-radius:12px;background:var(--danger-bg);color:var(--danger);display:grid;place-items:center}
.lock-badge svg{width:20px;height:20px}
.lock-head b{display:block;font-family:var(--font-display);font-size:1.02rem}
.lock-head span{font-size:.78rem;color:var(--slate)}
.lock-attempts{margin-top:16px;font-size:.72rem;font-family:var(--font-mono);letter-spacing:.06em;text-transform:uppercase;color:var(--slate)}
.lock-dots{display:flex;gap:6px;margin-top:8px}
.lock-dots i{flex:1;height:8px;border-radius:99px;background:var(--danger);opacity:.85}

/* new password (devise/passwords/edit) */
.pw-field{display:flex;align-items:center;gap:10px;border:1.5px solid var(--teal);border-radius:10px;padding:10px 12px;
  font-size:1.05rem;letter-spacing:.2em;color:var(--ink);box-shadow:0 0 0 3px rgba(20,184,166,.15)}
.pw-field svg{width:16px;height:16px;color:var(--slate);margin-left:auto}
.pw-meter{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:5px;margin-top:10px}
.pw-meter i{height:6px;border-radius:99px;background:var(--pine)}
.pw-strength{margin-top:6px;font-size:.74rem;font-weight:600;color:var(--pine)}
.pw-rules{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 12px;margin-top:12px}
.pw-rules li{display:flex;align-items:center;gap:6px;font-size:.76rem;color:var(--slate)}
.pw-rules svg{width:12px;height:12px;color:var(--pine);flex:none}

/* rotating product moments (devise/shared/_showcase) — 4 slides, 4s each */
.showcase{width:min(100%,400px)}
.show-stage{display:grid}
.show-slide{grid-area:1/1;margin:0;opacity:0;animation:show-cycle 16s infinite both}
.show-slide:nth-child(1){opacity:1;animation-delay:0s}
.show-slide:nth-child(2){animation-delay:4s}
.show-slide:nth-child(3){animation-delay:8s}
.show-slide:nth-child(4){animation-delay:12s}
@keyframes show-cycle{0%{opacity:0;transform:translateY(8px)}4%,22%{opacity:1;transform:none}26%,100%{opacity:0;transform:translateY(-6px)}}
.show-slide figcaption{margin-top:16px;font-family:var(--font-mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:#7DD3B8}
.show-card{background:#fff;color:var(--ink);border-radius:16px;padding:18px 20px;
  box-shadow:0 30px 60px -24px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.06)}
.show-kicker{font-family:var(--font-mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;color:var(--slate);margin-bottom:12px}
.show-checkin{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}
.show-time{font-family:var(--font-display);font-weight:700;font-size:2.1rem;letter-spacing:-.03em;line-height:1}
.show-pill{display:inline-flex;align-items:center;gap:6px;font-size:.74rem;font-weight:600;padding:5px 10px;border-radius:99px}
.show-pill svg{width:12px;height:12px}
.show-pill-ok{background:#DCF3E7;color:var(--pine)}
.show-meta{display:flex;align-items:center;gap:8px;font-size:.8rem;color:var(--slate);margin-top:6px}
.show-meta svg{width:14px;height:14px;color:var(--teal)}
.show-rows{display:grid;gap:9px}
.show-rows li{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;font-size:.82rem}
.show-rows li > span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.show-rows b{font-family:var(--font-mono);font-size:.74rem;color:var(--slate);font-weight:500}
.show-avatar{width:26px;height:26px;border-radius:50%;color:#fff;display:grid;place-items:center;font-size:.62rem;font-weight:700}
.show-balance + .show-balance{margin-top:14px}
.show-balance div{display:flex;justify-content:space-between;font-size:.84rem;margin-bottom:6px}
.show-balance span{color:var(--slate)}
.show-bar{display:block;height:8px;border-radius:99px;background:var(--mist);overflow:hidden}
.show-bar i{display:block;height:100%;border-radius:99px;background:var(--teal)}
.show-net{display:flex;justify-content:space-between;align-items:baseline;padding-bottom:10px;border-bottom:1px solid var(--line)}
.show-net span{font-size:.8rem;color:var(--slate)}
.show-net b{font-family:var(--font-display);font-size:1.6rem;letter-spacing:-.02em}
.show-lines{display:grid;gap:6px;margin-top:10px}
.show-lines li{display:flex;justify-content:space-between;font-size:.8rem;color:var(--slate)}
.show-dots{display:flex;gap:6px;margin-top:14px}
.show-dots i{width:18px;height:3px;border-radius:99px;background:rgba(255,255,255,.18);animation:show-dot 16s infinite both}
.show-dots i:nth-child(1){background:#7DD3B8;animation-delay:0s}
.show-dots i:nth-child(2){animation-delay:4s}
.show-dots i:nth-child(3){animation-delay:8s}
.show-dots i:nth-child(4){animation-delay:12s}
@keyframes show-dot{0%,24.9%{background:#7DD3B8}25%,100%{background:rgba(255,255,255,.18)}}

/* ---------------- right form panel ---------------- */
.auth-main{display:flex;flex-direction:column;padding:32px 40px 44px}
.auth-topbar{display:flex;justify-content:flex-end;align-items:center;gap:14px;
  font-size:.88rem;color:var(--slate);min-height:40px}
.auth-topbar .logo-sm{display:none}
/* Vertical rhythm for the form column: 8px inside a field, 16px between
   fields and between a control and its supporting line, 24px between
   groups (alert → heading → fields → options → button → alternatives). */
.auth-panel{margin:auto;width:100%;max-width:436px;padding:24px 0}

.auth-head{margin-bottom:24px}
.auth-head h1{font-family:var(--font-display);font-size:clamp(1.7rem,3vw,2.1rem);
  line-height:1.14;letter-spacing:-.025em;font-weight:700}
.auth-head p{margin-top:8px;color:var(--slate);font-size:.97rem}

/* ---------------- form ---------------- */
.form-row{display:grid;gap:16px;margin-bottom:16px}
.form-row.two{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.field{display:grid;gap:8px;margin-bottom:16px;align-content:start}
.field:last-of-type{margin-bottom:0}
.form-row > .field{margin-bottom:0}
/* the submit group: 24px from the last field, per the rhythm above */
.form-actions{margin-top:24px}
.field label{font-size:.87rem;font-weight:600;letter-spacing:-.005em}
.field .hint{font-size:.79rem;color:var(--slate);line-height:1.45}
.input-wrap{position:relative;display:flex;align-items:center}
.field input{
  width:100%;font-family:var(--font-body);font-size:.97rem;color:var(--ink);
  padding:13px 15px;border:1.5px solid var(--line);border-radius:11px;background:#fff;
  transition:border-color .15s,box-shadow .15s;
}
.field input::placeholder{color:#9DAFA6}
.field input:hover{border-color:#C3D5CC}
.field input:focus{outline:none;border-color:var(--teal);box-shadow:0 0 0 4px rgba(20,184,166,.14)}
.field input[type=password]{padding-right:52px;letter-spacing:.02em}
/* one-time code: monospace, spaced and centred so the six digits read as six */
.field input.code-input{font-family:var(--font-mono);font-size:1.4rem;letter-spacing:.32em;text-align:center}
.field.has-error input{border-color:var(--danger);background:#FFFCFB}
.field.has-error input:focus{box-shadow:0 0 0 4px rgba(180,67,44,.13)}
.field-error{font-size:.8rem;color:var(--danger);font-weight:500}

/* show / hide password */
.pw-toggle{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);
  background:none;border:0;cursor:pointer;color:var(--slate);
  font-family:var(--font-mono);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;
  padding:8px 10px;border-radius:8px;
}
.pw-toggle:hover{color:var(--pine);background:var(--mist)}

/* password strength */
.pw-meter{margin-top:9px}
.pw-bars{display:grid;grid-template-columns:repeat(4,1fr);gap:5px}
.pw-bars i{height:4px;border-radius:99px;background:var(--line);transition:background .25s}
.pw-meter[data-score="1"] i:nth-child(-n+1){background:#D9534F}
.pw-meter[data-score="2"] i:nth-child(-n+2){background:#E0A32E}
.pw-meter[data-score="3"] i:nth-child(-n+3){background:#4FA36B}
.pw-meter[data-score="4"] i{background:var(--pine)}
.pw-label{margin-top:7px;font-size:.78rem;color:var(--slate)}
.pw-label b{font-weight:600;color:var(--ink)}

/* checkbox + row */
.field-inline{display:flex;justify-content:space-between;align-items:center;
  gap:16px;flex-wrap:wrap;margin:16px 0 24px}
.check{display:inline-flex;align-items:center;gap:9px;font-size:.9rem;
  color:var(--slate);cursor:pointer;user-select:none}
.check input{appearance:none;width:19px;height:19px;border:1.5px solid var(--line);
  border-radius:6px;background:#fff;cursor:pointer;flex:none;position:relative;transition:.15s}
.check input:hover{border-color:#C3D5CC}
.check input:checked{background:var(--pine);border-color:var(--pine)}
.check input:checked::after{content:"";position:absolute;left:6px;top:2px;width:5px;height:10px;
  border:solid #fff;border-width:0 2px 2px 0;transform:rotate(42deg)}

/* buttons */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;width:100%;
  font-family:var(--font-body);font-weight:600;font-size:1rem;
  padding:14px 24px;border-radius:11px;border:1.5px solid transparent;cursor:pointer;
  transition:background .15s,transform .12s,box-shadow .15s;
}
.btn-primary{background:var(--pine);color:#fff;box-shadow:0 10px 24px -10px rgba(11,107,78,.62)}
.btn-primary:hover{background:var(--pine-dark);transform:translateY(-1px);text-decoration:none}
.btn-primary:active{transform:translateY(0)}
.btn-ghost{background:#fff;border-color:var(--line);color:var(--ink);font-size:.9rem;
  width:auto;padding:9px 18px;border-radius:10px}
.btn-ghost:hover{border-color:var(--pine);color:var(--pine);text-decoration:none}

/* alt links under the form */
.auth-alt{margin-top:24px;padding-top:24px;border-top:1px solid var(--line);
  font-size:.9rem;color:var(--slate)}
.auth-alt + .auth-alt{margin-top:8px;padding-top:0;border-top:0}
/* side-by-side secondary buttons; each button_to is its own <form> */
.auth-alt-actions{display:flex;flex-wrap:wrap;gap:8px}
.auth-links{margin-top:16px;display:flex;flex-wrap:wrap;gap:8px 20px;font-size:.86rem}
.auth-links a{color:var(--slate);font-weight:500}
.auth-links a:hover{color:var(--pine)}

/* reassurance strip under primary CTA */
.assure{display:flex;align-items:center;gap:9px;margin-top:16px;
  font-size:.83rem;color:var(--slate)}
.assure svg{flex:none;width:15px;height:15px;color:var(--pine)}

/* ---------------- flash / alerts ---------------- */
.alert{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-radius:12px;
  font-size:.91rem;margin-bottom:24px;border:1px solid}
.alert svg{flex:none;width:18px;height:18px;margin-top:2px}
.alert-notice{background:var(--ok-bg);border-color:#BFE5D2;color:#0A4A36}
.alert-notice svg{color:var(--ok)}
.alert-error{background:var(--danger-bg);border-color:#F1C9C0;color:#8C3320}
.alert-error svg{color:var(--danger)}
.alert-info{background:var(--amber-bg);border-color:#EFDCAE;color:#7A5409}
.alert-info svg{color:var(--amber)}
.alert h4{font-size:.92rem;font-weight:600;margin-bottom:3px}
.alert ul{list-style:none;display:grid;gap:4px;margin-top:6px}
.alert ul li{font-size:.87rem}
.alert ul li::before{content:"— ";opacity:.6}

/* ---------------- sent-state (check your inbox) ---------------- */
.sent{text-align:center;padding:8px 0}
.sent-icon{width:64px;height:64px;margin:0 auto 22px;border-radius:20px;
  background:var(--mist);color:var(--pine);display:grid;place-items:center}
.sent-icon svg{width:30px;height:30px}
.sent h1{font-family:var(--font-display);font-size:1.7rem;letter-spacing:-.02em;font-weight:700}
.sent p{margin-top:12px;color:var(--slate);font-size:.97rem}
.sent .mail{font-weight:600;color:var(--ink)}

/* ---------------- responsive ---------------- */

/* Both columns are percentages, so on a wide monitor the form column grows
   to ~1000px while the form itself stays 436px — the leftover piles up as
   dead space beside the divider, and it reads as a gap because the brand
   panel's own content hugs its left edge. Past this width the form column
   stops growing (the extra goes to the brand panel) and the brand panel
   centres its content in a column of its own, so both sides stay balanced.
   The 600px cap is inert until the panel is wider than its own padding. */
@media (min-width:1200px){
  .auth{grid-template-columns:minmax(0,1fr) minmax(560px,660px)}
  .auth-aside > *{width:100%;max-width:600px;margin-inline:auto}
}

@media (max-width:940px){
  .auth{grid-template-columns:1fr;min-height:auto}
  .auth-aside{padding:26px 26px 30px;order:-1;position:relative;min-height:0}
  .auth-aside::after{width:4px}
  .aside-body,.aside-visual + .aside-body{margin-top:26px;padding:0}
  .auth-aside h2{font-size:1.5rem}
  .aside-list,.aside-proof,.aside-foot,.aside-visual{display:none}   /* keep the mobile header tight */
  .auth-aside .aside-lede{font-size:.94rem}
  .auth-main{padding:26px 22px 40px}
  .auth-panel{padding:14px 0}
  .form-row.two{grid-template-columns:1fr}
}
/* Medium-height screens (a 1440x900 laptop is ~810px of viewport): tighten
   the copy to leave the picture room. Whether the picture then shows, and
   at what size, is the .aside-visual container's call. */
@media (min-width:941px) and (max-height:960px){
  .aside-visual-frame{top:14px}
  .aside-visual + .aside-body{padding-top:26px;padding-bottom:26px}
  .aside-visual ~ .aside-body .aside-list{margin-top:20px}
  .aside-visual ~ .aside-body .aside-list li{padding:8px 0}
  .aside-visual ~ .aside-body .aside-proof{margin-top:22px}
}
@media (max-width:420px){
  .auth-head h1{font-size:1.55rem}
  .field-inline{flex-direction:column;align-items:flex-start;gap:12px}
}

/* ---------------------------------------------------------------
   reCAPTCHA v3
   ---------------------------------------------------------------
   Google's floating badge is the attribution its terms require, so it
   stays visible (the in-form "Protected by reCAPTCHA" text was removed —
   do not hide the badge without restoring that text). Its size and
   position come from inline style="" attributes, which style-src-attr
   allows. The one rule Google injects in a <style> element — sliding the
   badge open on hover — is blocked by the nonce-based style-src, so it is
   restated here.
   --------------------------------------------------------------- */
.grecaptcha-badge:hover,
.grecaptcha-badge:focus-within { right: 4px !important; }
