/* Account entry: /login/, /admin/login/ and /accept/ share one layout built from the approved
   dashboard system in apex-app.css: tokens, .app-logo, .btn pill press springs, 12px fields,
   nest rows with 32px row icons. White page, no card, photo or marketing panel.
   Controllers own visibility through [hidden]; src/auth-entry.js mirrors their DOM into
   body[data-entry-state] and body[data-entry-tone], which compose the states below. */
body[data-page=login],body[data-page=owner-login],body[data-page=accept]{background:#fff}
.entry{display:grid;grid-template-rows:auto 1fr auto;min-height:100dvh;padding:0 28px}
.entry-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:80px}
.entry-nav{display:flex;align-items:center;gap:4px;margin-right:-10px}
.entry-nav .btn-quiet{font-size:13.5px}
.entry-main{display:grid;justify-items:center;align-content:start;min-width:0;padding:clamp(24px,10vh,112px) 0 56px}
.entry-stage{width:min(400px,100%);min-width:0}
.entry-head h1{font:600 31px/1.08 "DM Sans",sans-serif;letter-spacing:-.035em;color:var(--ink)}
.entry-sub{margin-top:8px;font-size:14.5px;line-height:1.5;color:var(--ink-2)}
.entry-body{margin-top:28px}
.entry-body>:not([hidden])~:not([hidden]){margin-top:16px}
.entry-form{display:grid;gap:16px}
.entry-form[hidden]{display:none!important}
.entry-field{display:grid;gap:8px}
.entry-field label{font-size:13.5px;font-weight:500;color:var(--ink)}
.entry-field label span{font-weight:400;color:var(--ink-3)}
.entry-hint{font-size:13px;line-height:1.5;color:var(--ink-3)}
.entry-fine{font-size:12.5px;line-height:1.5;color:var(--ink-3)}

/* Fields: dashboard geometry, one neutral border, no shadow, no browser tint. */
.entry :is(input[type=email],input[type=password],input[type=text]){display:block;width:100%;min-width:0;height:44px;min-height:44px;padding:0 14px;border:1px solid var(--line-2);border-radius:var(--r-field);background:#fff;color:var(--ink);font:400 15px/1.4 "DM Sans",sans-serif;box-shadow:none;outline:none;transition:border-color .2s,background-color .2s;-webkit-tap-highlight-color:transparent}
.entry input::placeholder{color:var(--ink-3)}
.entry input:hover:not(:disabled):not(:focus){border-color:#cdcdcd}
.entry input:is(:focus,:focus-visible){border-color:#b8b8b8;box-shadow:none;outline:none}
.entry input[aria-invalid=true]{border-color:var(--danger)}
.entry input:disabled{background:var(--nest);color:var(--ink-3);cursor:not-allowed}
.entry input:-webkit-autofill,.entry input:-webkit-autofill:hover,.entry input:-webkit-autofill:focus{-webkit-text-fill-color:var(--ink);caret-color:var(--ink);filter:none;transition:background-color 600000s 0s,color 600000s 0s}
.entry input:autofill{filter:none}

/* Controls: dashboard .btn supplies the pill, colours and spring press. */
.entry-wide{width:100%;min-height:44px;font-size:15px}
.entry .btn img{width:18px;height:18px}
#google-access{display:grid;gap:16px}
.entry-divider{display:flex;align-items:center;gap:12px;font-size:12.5px;color:var(--ink-3)}
.entry-divider::before,.entry-divider::after{content:"";flex:1;height:1px;background:var(--line)}
.entry-links{display:flex;flex-wrap:wrap;justify-content:center;gap:0 18px}
.entry-text-button{min-height:44px;padding:0 4px;border:0;background:transparent;color:var(--ink-2);font:500 13.5px/1 "DM Sans",sans-serif;cursor:pointer;text-underline-offset:4px;transition:color .2s}
.entry-text-button:hover:not(:disabled){color:var(--ink);text-decoration:underline}
.entry-text-button:disabled{opacity:.42;cursor:not-allowed}
.entry-text-button[hidden]{display:none!important}

/* One message row. Quiet text while working; a nest row with a 32px icon when it matters. */
.entry-note{display:grid;grid-template-columns:minmax(0,1fr);align-items:center;gap:12px}
.entry-body>.entry-note:has([data-status]:empty){margin-top:0}
.entry-note [data-status]{display:block;margin:0;font-size:13.5px;line-height:1.5;color:var(--ink-2);overflow-wrap:anywhere}
.entry-note-icon{display:none;place-items:center;width:32px;height:32px;border-radius:50%;background:#fff;color:var(--ink)}
.entry-note-icon .icon{display:none;width:16px;height:16px}
body:is([data-entry-tone=error],[data-entry-tone=success],[data-entry-tone=sent],[data-entry-tone=progress]) .entry-note:not(:has([data-status]:empty)){grid-template-columns:32px minmax(0,1fr)}
body:is([data-entry-tone=error],[data-entry-tone=success],[data-entry-tone=sent],[data-entry-tone=progress]) .entry-note:not(:has([data-status]:empty)) .entry-note-icon{display:grid}
body:is([data-entry-tone=error],[data-entry-tone=success],[data-entry-tone=sent]) .entry-note:not(:has([data-status]:empty)){padding:12px 14px;border-radius:var(--r-row);background:var(--nest)}
body:is([data-entry-tone=error],[data-entry-tone=success],[data-entry-tone=sent]) .entry-note [data-status]{color:var(--ink)}
body[data-entry-tone=error] .entry-note-icon{background:var(--danger-soft);color:var(--danger)}
body[data-entry-tone=error] .entry-note-icon [data-icon=alert],body[data-entry-tone=success] .entry-note-icon [data-icon=success],body[data-entry-tone=sent] .entry-note-icon [data-icon=sent]{display:block}
body[data-entry-tone=progress] .entry-note-icon{background:transparent}

/* The single connecting element: a 32px ring, shown only while a session or callback
   settles. It fades in late so fast restores never flash, and stops itself. */
.entry .entry-pending{display:none;justify-items:center;min-height:0;padding:72px 0}
.entry-pending:not([hidden]).login-pending,body[data-page=owner-login] .entry-stage:not(:has(#owner-login:not([hidden]),#owner-setup:not([hidden]),[data-setup-state]:not([hidden]),[data-status]:not(:empty))) .entry-pending{display:grid}
body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening]) .entry-note{grid-template-columns:32px minmax(0,1fr)}
body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening]) .entry-note-icon{display:grid;background:transparent}
.entry-pending::before,body[data-entry-tone=progress] .entry-note-icon::before,body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening]) .entry-note-icon::before{content:"";width:32px;height:32px;border:2px solid var(--line-2);border-top-color:var(--ink);border-radius:50%}
.entry-pending::before{animation:entry-spin .9s linear 14,entry-fade .24s ease-out .16s backwards}
body[data-entry-tone=progress] .entry-note-icon::before,body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening]) .entry-note-icon::before{animation:entry-spin .9s linear 14,entry-fade .24s ease-out .16s backwards}
@keyframes entry-spin{to{transform:rotate(1turn)}}
@keyframes entry-fade{from{opacity:0}}
body[data-page=owner-login] .entry-stage:not(:has(#owner-login:not([hidden]),#owner-setup:not([hidden]),[data-setup-state]:not([hidden]),[data-status]:not(:empty))) :is(.entry-head,.entry-body){display:none}

/* Unavailable: a quiet alert row instead of the form. */
.entry-alert{display:grid;grid-template-columns:32px minmax(0,1fr);align-items:center;gap:12px;padding:12px 14px;border-radius:var(--r-row);background:var(--nest);font-size:13.5px;line-height:1.5}
.entry-alert .row-icon{background:var(--danger-soft);color:var(--danger)}
.entry-alert[hidden]{display:none!important}

/* Recovery states. */
body[data-entry-state=recovery-complete] #access-intro{display:none}
body[data-entry-state=recovery-complete] .entry-links{display:grid;justify-content:stretch}
body[data-entry-state=recovery-complete] #recovery-back{width:100%;min-height:44px;padding:0 18px;border-radius:999px;background:var(--ink);color:#fff;font-size:15px;text-decoration:none}
body[data-entry-state=recovery-complete] #recovery-back:hover{background:#2b2b2b}
body[data-entry-state=recovery-sent] #recovery-request .btn-primary{border-color:var(--line-2);background:#fff;color:var(--ink)}
body[data-entry-state=recovery-sent] #recovery-request .btn-primary:hover:not(:disabled){background:var(--nest)}

/* Owner one-time setup. A failed link leaves only its message; once the password form is
   open, the confirm-step intro has done its job. */
body[data-entry-state=owner-setup][data-entry-tone=error] #owner-setup{display:none}
body[data-entry-state=owner-setup][data-entry-tone=error] .entry-body>.entry-note{margin-top:0}
body[data-entry-state=owner-password] #owner-setup-intro{display:none}

/* Invitation: steps, then the password form. Waiting and blocked states keep the heading
   and swap the form for the message row, so nothing jumps or flashes. */
.entry-steps{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:18px;list-style:none;font-size:13px;color:var(--ink-3)}
.entry-steps li{display:inline-flex;align-items:center;gap:8px;white-space:nowrap}
.entry-steps li span{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--nest);color:var(--ink-2);font:600 11px/1 "DM Sans",sans-serif;font-variant-numeric:tabular-nums}
.entry-steps li[aria-current]{color:var(--ink)}
.entry-steps li[aria-current] span{background:var(--ink);color:#fff}
.entry-blocked-action{display:none}
body[data-entry-state=blocked] .entry-blocked-action{display:inline-flex}
body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening],[data-entry-state=blocked]) :is(#invite-form,.entry-fine){display:none}
body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening],[data-entry-state=blocked]) .entry-body>.entry-note{margin-top:0}
body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening]) :is(.entry-steps,.entry-disclosure){display:none}
body[data-page=accept]:is([data-entry-state=checking],[data-entry-state=opening]) .entry-body{margin-top:24px}

/* Disclosure: the dashboard nest row with a spring chevron (height spring in motion.js). */
.entry-disclosure{border-radius:var(--r-row);background:var(--nest)}
.entry-disclosure>summary{display:flex;align-items:center;gap:12px;min-height:48px;padding:0 16px;border-radius:var(--r-row);list-style:none;cursor:pointer;font-size:14px;font-weight:500}
.entry-disclosure>summary,.entry-disclosure>summary *{-webkit-tap-highlight-color:transparent}
.entry-disclosure>summary:focus:not(:focus-visible){outline:none}
.entry-disclosure>summary::-webkit-details-marker{display:none}
.entry-disclosure>summary:focus-visible{outline-offset:-2px}
.entry-disclosure .disclosure-chevron{margin-left:auto;width:18px;height:18px;color:var(--ink-2);transition:transform 560ms var(--spring-bouncy)}
.entry-disclosure[open]>summary .disclosure-chevron{transform:rotate(180deg)}
.entry-disclosure-body{display:grid;justify-items:start;gap:8px;padding:0 16px 16px;font-size:13.5px;line-height:1.5;color:var(--ink-2)}
.entry-disclosure-body a{color:var(--ink);font-weight:500;text-underline-offset:4px}

.entry-foot{display:flex;align-items:center;min-height:64px}
.entry-foot nav{display:flex;gap:18px;font-size:12.5px}
.entry-foot a{color:var(--ink-3);text-decoration:none}
.entry-foot a:hover{color:var(--ink);text-decoration:underline;text-underline-offset:4px}

@media(max-width:700px){
 .entry{padding:0 20px}
 .entry-bar{min-height:64px}
 .entry-main{padding:24px 0 40px}
 .entry-head h1{font-size:28px}
 .entry-body{margin-top:24px}
 .entry :is(input[type=email],input[type=password],input[type=text]){font-size:16px}
 .entry-foot{min-height:56px}
}
@media(max-width:360px){
 .entry{padding:0 16px}
 .entry-steps{gap:8px 14px}
}
/* Short landscape viewports: tighter rhythm, same order. Portrait phones keep their
   fixed rhythm so an opening keyboard never moves the heading. */
@media(max-height:560px) and (min-width:701px){
 .entry-bar{min-height:56px}
 .entry-main{padding:12px 0 32px}
 .entry-body{margin-top:20px}
 .entry-pending{padding:40px 0}
}
@media(prefers-reduced-motion:reduce){
 .entry *,.entry *::before,.entry *::after{animation:none!important;transition:none!important}
}
