/* ============================================================
   auth-style.css
   Shared look for login / sign up / forgot / reset password.

   Same palette and type as the landing page (index.php): hearth
   browns, one gold accent, Lexend throughout. The picture side is
   a slowly moving wall of real dish photos (auth_visual.php).

   Three layouts:
   - wide landscape screens: split, the wall beside the form
   - phones: the wall as a band on top, the form in a sheet below
   - portrait tablets: the wall fills the screen behind a card

   Class names are shared with auth_form_helpers.php (server-side
   errors) and auth-interactions.js (client-side validation), so
   .form-control / .is-invalid / .field-error / .alert / .btn-auth
   / .is-loading / .pw-* keep their meaning -- restyle, don't rename.
   ============================================================ */
:root{
    --hearth:#191410;
    --hearth-2:#211b17;
    --kape:#2a221d;
    --gold:#c9a24e;
    --gold-pale:#e3c47b;
    --gold-deep:#9c7734;
    --cream:#f5efe4;
    --cream-2:rgba(245,239,228,.76);
    --muted:#a69a8d;
    --line:rgba(201,162,78,.16);
    --line-2:rgba(201,162,78,.34);

    --field-bg:rgba(245,239,228,.035);
    --field-line:rgba(245,239,228,.14);
    --field-h:48px;
    --radius:12px;

    --danger:#e8806a;
    --danger-bg:rgba(232,128,106,.1);
    --success:#8fd19e;
    --success-bg:rgba(143,209,158,.1);

    --ui:'Lexend',system-ui,-apple-system,'Segoe UI',sans-serif;
    --ease:cubic-bezier(.22,.61,.36,1);
    --ease-out:cubic-bezier(.16,1,.3,1);

    --wall-gap:14px;

    /* Older names still used by a few inline styles in the pages. */
    --gold-light:var(--gold-pale);
    --gold-accent:var(--gold);
}

*,*::before,*::after{margin:0;padding:0;box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
body{
    min-height:100vh;min-height:100dvh;
    background:var(--hearth);color:var(--cream);
    font-family:var(--ui);font-size:15px;line-height:1.55;
    -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img{display:block;max-width:100%;}
button,input{font:inherit;color:inherit;}
::selection{background:var(--gold);color:var(--hearth);}
a:focus-visible,button:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:8px;}
.checkbox-row input:focus-visible{outline:2px solid var(--gold);outline-offset:2px;}

/* ── LAYOUT ─────────────────────────────────────────────────────────────────
   The page itself scrolls (no inner scroll boxes), and the picture panel is
   sticky, so a tall form like Sign up simply makes the page longer while the
   wall stays put beside it. */
.auth-page{display:flex;min-height:100vh;min-height:100dvh;}

/* ── PICTURE PANEL ───────────────────────────────────────────────────────── */
.auth-visual{
    position:sticky;top:0;align-self:flex-start;
    flex:0 0 48%;height:100vh;height:100dvh;overflow:hidden;isolation:isolate;
    display:flex;align-items:flex-end;padding:clamp(36px,5vw,64px);
    background:var(--hearth);
}
/* Dims the photos so they sit behind the words: lightest in the middle,
   deepening under the caption, and fading along the seam into the form side
   so the two halves read as one surface. */
.auth-visual::after{
    content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
    background:
        linear-gradient(180deg,rgba(25,20,16,.5) 0%,rgba(25,20,16,.18) 28%,rgba(25,20,16,.45) 55%,rgba(25,20,16,.96) 86%),
        linear-gradient(90deg,transparent 62%,rgba(25,20,16,.9) 100%);
}
/* Fallback when the menu has too few photos: the single restaurant photo. */
.auth-visual.is-photo::before{
    content:'';position:absolute;inset:-3%;z-index:-2;
    background:url('../assets/images/bg.jpg') center/cover no-repeat;
    animation:visualSettle 2.2s var(--ease-out) both, visualDrift 30s ease-in-out 2.2s infinite alternate;
}

.auth-visual-caption{max-width:440px;animation:rise .9s var(--ease-out) .25s both;}
.auth-visual-logo{
    width:52px;height:52px;margin-bottom:22px;border-radius:50%;object-fit:cover;
    filter:brightness(0) invert(1);
}
.auth-visual-caption strong{
    animation:captionReveal 1.1s var(--ease-out) .35s both;
    display:block;font-size:clamp(2rem,3.2vw,2.8rem);font-weight:800;line-height:1.05;letter-spacing:-.035em;color:var(--cream);
}
.auth-visual-caption span{display:block;max-width:38ch;margin-top:14px;font-size:1rem;line-height:1.65;color:var(--cream-2);}
.auth-visual-rule{
    width:48px;height:2px;margin-top:26px;border-radius:2px;background:var(--gold);
    transform-origin:left center;animation:ruleIn 1s var(--ease-out) .7s both;
}

/* ── DISH WALL ──────────────────────────────────────────────────────────────
   Columns of real menu photos (auth_visual.php). Each column holds its set
   three times and scrolls exactly one set, a third of its track, before
   starting over, so it never visibly ends. Neighbours run in opposite
   directions at slightly different speeds. The wall is tilted a few degrees
   and oversized so the tilt never shows an edge. Only transform animates, so
   it runs on the compositor.

   --wall-clock is the current time, set by a line in each page's <head>. As a
   negative delay it puts the wall where it would be had it been running all
   along, so moving between the auth pages carries it on instead of
   restarting it. The clock wraps every hour, so every column's duration must
   divide 3600s (60/80/72/90 do) or the wall would jump at the wrap. */
.auth-wall{
    position:absolute;inset:-16% -22%;z-index:-2;
    display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--wall-gap);
    transform:rotate(-9deg);
}
.auth-wall-col{min-width:0;animation:wallIn 1.4s var(--ease-out) calc(.1s + var(--c,0) * .12s) both;}
.auth-wall-col:nth-child(n+4){display:none;}
.auth-wall-track{
    animation:wallScroll var(--wall-dur,60s) linear calc(var(--wall-clock,0s) * -1) infinite;
    will-change:transform;
}
.auth-wall-col:nth-child(2) .auth-wall-track{--wall-dur:80s;animation-direction:reverse;}
.auth-wall-col:nth-child(3) .auth-wall-track{--wall-dur:72s;}
.auth-wall-col:nth-child(4) .auth-wall-track{--wall-dur:90s;animation-direction:reverse;}
/* margin, not gap: every set is then exactly a third of the track. */
.auth-wall img{
    width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;margin-bottom:var(--wall-gap);
    border-radius:16px;background:var(--kape);
}
/* A guest who stops to look at a dish can. */
@media (hover:hover){
    .auth-visual:hover .auth-wall-track{animation-play-state:paused;}
}

/* ── FORM SIDE ───────────────────────────────────────────────────────────── */
.auth-form-side{
    flex:1 1 auto;min-width:0;
    display:flex;flex-direction:column;align-items:center;justify-content:center;
    padding:40px clamp(24px,5vw,72px);
    background:
        radial-gradient(60% 50% at 50% 40%,rgba(201,162,78,.05),transparent 70%),
        var(--hearth);
}
.auth-wrap{width:100%;max-width:400px;}

/* Brand + a way back to the homepage. On the split layout the picture panel
   already carries the brand, so only the back link shows there. */
.auth-topbar{
    display:flex;align-items:center;justify-content:space-between;gap:16px;
    margin-bottom:clamp(28px,6vh,52px);
    animation:rise .7s var(--ease-out) both;
}
.auth-brand{display:inline-flex;align-items:center;gap:10px;min-height:44px;text-decoration:none;}
.auth-brand img{width:34px;height:34px;border-radius:50%;object-fit:cover;filter:brightness(0) invert(1);}
.auth-brand span{font-size:1.05rem;font-weight:800;letter-spacing:.04em;color:var(--cream);}
.auth-back{
    display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:6px 2px;
    font-size:.85rem;font-weight:500;color:var(--muted);text-decoration:none;white-space:nowrap;
    transition:color .2s var(--ease),background-color .2s var(--ease);
}
.auth-back i{font-size:.72rem;transition:transform .25s var(--ease);}
.auth-back:hover{color:var(--gold-pale);}
.auth-back:hover i{transform:translateX(-3px);}

/* The form sits straight on the page -- no box around it on wide screens. */
.auth-card{background:none;border:0;padding:0;}
/* Tabs, title, subtitle, alerts, then the form's own fields one by one, and
   the footer last. */
.auth-card > *{animation:rise .7s var(--ease-out) both;}
.auth-card > :nth-child(1){animation-delay:.05s;}
.auth-card > :nth-child(2){animation-delay:.1s;}
.auth-card > :nth-child(3){animation-delay:.15s;}
.auth-card > :nth-child(4){animation-delay:.2s;}
.auth-card > :nth-child(n+5){animation-delay:.4s;}
.auth-card > form{animation:none;}
.auth-card > form > *{animation:rise .65s var(--ease-out) both;}
.auth-card > form > :nth-child(2){animation-delay:.2s;}
.auth-card > form > :nth-child(3){animation-delay:.26s;}
.auth-card > form > :nth-child(4){animation-delay:.32s;}
.auth-card > form > :nth-child(5){animation-delay:.38s;}
.auth-card > form > :nth-child(6){animation-delay:.44s;}
.auth-card > form > :nth-child(n+7){animation-delay:.5s;}
.auth-card > .alert-error{animation:rise .7s var(--ease-out) .1s both, shake .5s var(--ease) .95s;}
/* After the entrance rules on purpose: same specificity, so this one wins. */
form.is-shaking{animation:shake .45s var(--ease);}

.auth-title{font-size:clamp(1.7rem,2.4vw,2rem);font-weight:700;line-height:1.15;letter-spacing:-.03em;color:var(--cream);}
.auth-subtitle{margin:8px 0 30px;font-size:.93rem;line-height:1.6;color:var(--muted);}
.auth-subtitle strong{font-weight:600;}

/* ── FIELDS ──────────────────────────────────────────────────────────────── */
.form-group{margin-bottom:18px;}
.form-row{display:flex;gap:14px;}
.form-row .form-group{flex:1;min-width:0;}
.form-group label{display:block;margin-bottom:8px;font-size:.85rem;font-weight:500;color:var(--cream-2);transition:color .2s var(--ease);}
.form-group:focus-within > label{color:var(--gold-pale);}
.label-optional{font-weight:400;color:var(--muted);}

/* On focus a gold line sweeps in along the bottom of the field, left to
   right. It is a background layer, since an <input> can't have ::after, so
   anything that sets the field's background must set background-color only. */
.form-control{
    width:100%;height:var(--field-h);padding:0 15px;
    border-radius:var(--radius);border:1px solid var(--field-line);
    background:linear-gradient(var(--gold),var(--gold)) left bottom / 0 2px no-repeat, var(--field-bg);
    color:var(--cream);font-size:.95rem;
    transition:border-color .2s var(--ease),background-color .2s var(--ease),background-size .45s var(--ease-out);
}
.form-control::placeholder{color:rgba(166,154,141,.7);}
.form-control:hover{border-color:rgba(245,239,228,.26);}
.form-control:focus{outline:none;border-color:rgba(201,162,78,.7);background-color:rgba(245,239,228,.06);background-size:100% 2px;}
/* Browser autofill would otherwise paint a pale box into the dark form. */
.form-control:-webkit-autofill,
.form-control:-webkit-autofill:hover,
.form-control:-webkit-autofill:focus{
    -webkit-text-fill-color:var(--cream);caret-color:var(--cream);
    -webkit-box-shadow:0 0 0 1000px #251f1a inset;box-shadow:0 0 0 1000px #251f1a inset;
    transition:background-color 9999s;
}

.input-wrap,.password-field{position:relative;}
.leading-icon{
    position:absolute;left:15px;top:50%;transform:translateY(-50%);z-index:2;pointer-events:none;
    font-size:.85rem;color:var(--muted);transition:color .2s var(--ease);
}
.input-wrap:focus-within .leading-icon,
.password-field:focus-within .leading-icon{color:var(--gold);}
.form-control.has-leading{padding-left:42px;}
.form-control.has-icon{padding-right:48px;}

.password-toggle{
    position:absolute;right:4px;top:50%;transform:translateY(-50%);
    width:40px;height:40px;display:grid;place-items:center;
    border:0;border-radius:8px;background:none;color:var(--muted);font-size:.9rem;cursor:pointer;
    transition:color .2s var(--ease),background-color .2s var(--ease);
}
.password-toggle:hover{color:var(--gold-pale);background:rgba(245,239,228,.06);}
.password-toggle i{transition:transform .2s var(--ease);}
.password-toggle:active i{transform:scale(.82);}

/* ── 6-DIGIT CODE ────────────────────────────────────────────────────────
   One real input laid invisibly over six boxes (reset_password.php). The
   input still takes every tap, keystroke, paste and SMS/email autofill; the
   boxes only draw it: one digit each, the next one to fill outlined in gold
   with a blinking caret. auth-interactions.js (1b) copies the digits across. */
.otp{position:relative;}
.otp-boxes{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px;}
.otp-box{
    position:relative;display:grid;place-items:center;height:60px;
    border-radius:var(--radius);border:1px solid var(--field-line);background:var(--field-bg);
    font-size:1.55rem;font-weight:700;font-variant-numeric:tabular-nums;color:var(--cream);
    transition:border-color .2s var(--ease),background-color .2s var(--ease),transform .2s var(--ease);
}
.otp-box.is-filled{border-color:rgba(245,239,228,.26);background:rgba(245,239,228,.06);animation:otpPop .22s var(--ease-out);}
/* Each selector is one step more specific than the .form-control state it
   undoes (:hover, :focus, .is-invalid paint borders and a gold/red line), so
   the input stays invisible in every state, whatever the source order. */
.otp .code-input,
.otp .code-input:hover,
.otp .code-input:focus,
.otp .code-input.is-invalid,
.otp .code-input.is-invalid:hover,
.otp .code-input.is-invalid:focus{
    position:absolute;inset:0;z-index:1;width:100%;height:100%;padding:0;
    border:0;background:transparent;color:transparent;caret-color:transparent;
    font-size:16px;letter-spacing:0;cursor:text;
}
.otp .code-input::selection{background:transparent;}
/* An autofilled code would otherwise paint the browser's own box over the six. */
.otp .code-input:-webkit-autofill,
.otp .code-input:-webkit-autofill:hover,
.otp .code-input:-webkit-autofill:focus{-webkit-text-fill-color:transparent;-webkit-box-shadow:none;box-shadow:none;}
.otp .code-input:focus + .otp-boxes .otp-box.is-active{border-color:var(--gold);background:rgba(245,239,228,.06);}
.otp .code-input:focus + .otp-boxes .otp-box.is-active:empty::after{
    content:'';width:2px;height:26px;border-radius:2px;background:var(--gold);
    animation:otpCaret 1.05s steps(1) infinite;
}
.otp .code-input.is-invalid + .otp-boxes .otp-box{border-color:var(--danger);}
@keyframes otpPop{from{transform:scale(.9);}to{transform:none;}}
@keyframes otpCaret{50%{opacity:0;}}

/* ── FIELD ERRORS ─────────────────────────────────────────────────────────
   One short line under the field it's about, and the field outlined. Same
   markup from auth_form_helpers.php (server) and auth-interactions.js
   (browser). Declared after :hover/:focus so the red wins the tie. */
.form-control.is-invalid,
.form-control.is-invalid:hover{border-color:var(--danger);background-image:linear-gradient(var(--danger),var(--danger));}
.form-control.is-invalid:focus{border-color:var(--danger);}
.field-error{
    display:flex;align-items:flex-start;gap:7px;margin-top:7px;
    font-size:.8rem;line-height:1.45;color:#f0a794;animation:fadeIn .2s var(--ease) both;
}
.field-error i{flex-shrink:0;margin-top:3px;font-size:.74rem;}

/* ── PASSWORD STRENGTH ───────────────────────────────────────────────────── */
.pw-strength{display:flex;gap:4px;margin-top:9px;}
.pw-bar{flex:1;height:3px;border-radius:3px;background:rgba(245,239,228,.1);transition:background-color .3s var(--ease);}
.pw-bar.weak{background:var(--danger);}
.pw-bar.fair{background:#e0b870;}
.pw-bar.strong{background:var(--success);}
.pw-hint{min-height:1em;margin-top:6px;font-size:.74rem;color:var(--muted);}

/* ── SMALL ROWS + LINKS ──────────────────────────────────────────────────── */
.form-row-between{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:-6px 0 18px;font-size:.87rem;color:var(--muted);}
.form-row-between > a:only-child{margin-left:auto;}
.form-row-between a{display:inline-block;padding:8px 0;color:var(--gold-pale);font-weight:500;text-decoration:none;}
.form-row-between a:hover{text-decoration:underline;text-underline-offset:3px;}

.checkbox-row{display:flex;align-items:center;gap:9px;font-size:.85rem;color:var(--muted);}
.checkbox-row input[type="checkbox"]{width:16px;height:16px;accent-color:var(--gold);cursor:pointer;}

/* ── LOG IN | SIGN UP SWITCH ─────────────────────────────────────────────
   Two real links (login.php / sign_up.php), styled as a segmented control.
   The raised pill is the active page; between the two pages it slides
   across (see PAGE-TO-PAGE TRANSITIONS). */
.auth-tabs{
    display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-bottom:26px;padding:4px;
    border-radius:14px;background:rgba(0,0,0,.22);border:1px solid rgba(245,239,228,.07);
}
.auth-tab{
    display:flex;align-items:center;justify-content:center;height:42px;border-radius:10px;
    font-size:.9rem;font-weight:600;color:var(--muted);text-decoration:none;
    transition:color .2s var(--ease),background-color .2s var(--ease);
}
.auth-tab:hover{color:var(--cream);}
.auth-tab.is-active{
    color:var(--cream);background:#3a3029;
    box-shadow:0 8px 18px -10px rgba(0,0,0,.8),inset 0 1px 0 rgba(255,255,255,.07);
}

/* Shown under a password field while Caps Lock is on (auth-interactions.js). */
.caps-hint{display:flex;align-items:center;gap:7px;margin-top:7px;font-size:.8rem;color:var(--gold-pale);}
.caps-hint[hidden]{display:none;}
.caps-hint i{font-size:.72rem;}

/* ── BUTTONS ─────────────────────────────────────────────────────────────── */
.btn-auth{
    position:relative;
    width:100%;height:50px;padding:0 16px;border:0;border-radius:var(--radius);
    background:var(--gold);color:var(--hearth);
    font-size:.95rem;font-weight:600;letter-spacing:.01em;cursor:pointer;
    transition:background-color .2s var(--ease),transform .15s var(--ease),opacity .2s;
}
.btn-auth:hover{background:var(--gold-pale);}
.btn-auth:active{transform:scale(.985);}
.btn-auth:disabled{opacity:.6;cursor:not-allowed;transform:none;}

/* Shown on submit: no double posts, and a clear "working on it". */
.btn-auth.is-loading{color:transparent;pointer-events:none;opacity:1;}
.btn-auth.is-loading::before{
    content:'';position:absolute;top:50%;left:50%;width:18px;height:18px;margin:-9px 0 0 -9px;
    border:2px solid rgba(25,20,16,.3);border-top-color:var(--hearth);border-radius:50%;
    animation:btnSpin .7s linear infinite;
}
@keyframes btnSpin{to{transform:rotate(360deg);}}

/* Secondary action (Reset password: "Skip for now"). */
.btn-skip{
    display:flex;align-items:center;justify-content:center;width:100%;height:50px;padding:0 16px;
    border-radius:var(--radius);border:1px solid var(--line-2);background:transparent;
    color:var(--gold-pale);font-size:.95rem;font-weight:500;cursor:pointer;
    transition:background-color .2s var(--ease),border-color .2s var(--ease),color .2s var(--ease);
}
.btn-skip:hover{border-color:var(--gold);background:rgba(201,162,78,.08);color:var(--cream);}

.verified-badge{
    display:inline-flex;align-items:center;gap:7px;margin-bottom:16px;padding:6px 12px;border-radius:999px;
    font-size:.8rem;font-weight:600;color:var(--success);background:var(--success-bg);border:1px solid rgba(143,209,158,.28);
}

.divider{display:flex;align-items:center;gap:14px;margin:24px 0;font-size:.78rem;color:var(--muted);}
.divider::before,.divider::after{content:'';flex:1;height:1px;background:var(--line);}

.auth-footer{margin-top:28px;padding-top:22px;border-top:1px solid var(--line);text-align:center;font-size:.9rem;color:var(--muted);}
.auth-footer a{display:inline-block;padding:6px 2px;color:var(--gold-pale);font-weight:600;text-decoration:none;}
.auth-footer a:hover{text-decoration:underline;text-underline-offset:3px;}

/* ── FORM-LEVEL ALERT ─────────────────────────────────────────────────────
   Only for what isn't about one field (wrong credentials, an expired
   session, a lockout), so there is at most one, never a stack. */
.alert{
    display:flex;align-items:flex-start;gap:10px;margin-bottom:22px;padding:12px 14px;
    border-radius:var(--radius);border:1px solid transparent;
    font-size:.86rem;line-height:1.5;text-align:left;
}
.alert > i{flex-shrink:0;margin-top:2px;font-size:.95rem;}
.alert strong{font-weight:600;color:var(--cream);}
.alert-error{background:var(--danger-bg);border-color:rgba(232,128,106,.3);color:#f3b8a8;}
.alert-error > i{color:var(--danger);}
.alert-success{background:var(--success-bg);border-color:rgba(143,209,158,.28);color:#c3e6cb;}
.alert-success > i{color:var(--success);}
.alert-info{background:rgba(201,162,78,.1);border-color:rgba(201,162,78,.3);color:var(--cream);}
.alert-info > i{color:var(--gold);}

/* ── MOTION ──────────────────────────────────────────────────────────────── */
@keyframes rise{from{opacity:0;transform:translateY(14px);}to{opacity:1;transform:none;}}
@keyframes fadeIn{from{opacity:0;}to{opacity:1;}}
@keyframes visualSettle{from{transform:scale(1.08);filter:brightness(.6);}to{transform:none;filter:none;}}
@keyframes visualDrift{from{transform:none;}to{transform:scale(1.06) translate(-1.2%,-1%);}}
@keyframes captionReveal{from{clip-path:inset(0 0 100% 0);transform:translateY(28px);}to{clip-path:inset(-20% -5% -20% -5%);transform:none;}}
@keyframes shake{0%,100%{transform:none;}15%{transform:translateX(-7px);}30%{transform:translateX(6px);}45%{transform:translateX(-4px);}60%{transform:translateX(3px);}75%{transform:translateX(-1px);}}
@keyframes ruleIn{from{transform:scaleX(0);}to{transform:none;}}
@keyframes wallScroll{from{transform:translateY(0);}to{transform:translateY(calc(-100% / 3));}}
@keyframes wallIn{from{opacity:0;transform:translateY(48px);}to{opacity:1;transform:none;}}
@keyframes sheetUp{from{opacity:0;transform:translateY(56px);}to{opacity:1;transform:none;}}

/* ── SPLIT LAYOUT ONLY ───────────────────────────────────────────────────── */
@media (min-width:901px) and (orientation:landscape){
    .auth-brand{display:none;}
}
/* A wide panel takes a fourth column, so the photos don't grow huge. */
@media (min-width:1500px) and (orientation:landscape){
    .auth-wall{grid-template-columns:repeat(4,minmax(0,1fr));}
    .auth-wall-col:nth-child(4){display:block;}
}

/* ── PHONES: the wall as a band on top, the form in a sheet below ─────────
   The usual pattern for food and restaurant apps: the photos set the mood,
   the form sits in a full-width sheet that overlaps the band's lower edge,
   and its button lands in thumb reach. The band is sized from the viewport
   height, so on a short screen the form keeps its room. Safe-area insets keep
   it clear of notches and the home indicator (needs viewport-fit=cover, set
   in each page's <meta name="viewport">). */
@media (max-width:900px), (orientation:portrait){
    :root{
        --band-h:clamp(168px,30dvh,300px);
        --sheet-overlap:28px;
        --wall-gap:10px;
    }
    .auth-page{display:block;position:relative;}

    /* align-self back to auto: Chrome applies align-self to positioned boxes
       too, and the split layout's flex-start would shrink the portrait-tablet
       panel (pinned top and bottom, no set height) to its content, 0px. */
    .auth-visual{
        position:absolute;top:0;left:0;right:0;align-self:auto;
        height:var(--band-h);padding:0;display:block;
    }
    .auth-visual-caption{display:none;}
    /* Dark at the top so the brand and back link read over any photo, clear
       through the middle, then melting into the page behind the sheet. */
    .auth-visual::after{
        background:linear-gradient(180deg,rgba(25,20,16,.78) 0%,rgba(25,20,16,.2) 34%,rgba(25,20,16,.3) 62%,var(--hearth) 100%);
    }
    .auth-visual.is-photo::before{background-position:center 30%;}
    .auth-wall{inset:-40% -24%;}
    .auth-wall img{border-radius:12px;}

    /* Positioned so it paints above the band, which is absolutely positioned. */
    .auth-form-side{
        position:relative;z-index:1;
        display:block;min-height:100vh;min-height:100dvh;padding:0;
        background:transparent;
    }
    .auth-wrap{display:flex;flex-direction:column;min-height:100vh;min-height:100dvh;max-width:none;}

    .auth-topbar{
        flex:none;align-items:flex-start;margin:0;
        height:calc(var(--band-h) - var(--sheet-overlap));
        padding:max(10px,env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) 0 max(16px,env(safe-area-inset-left));
    }
    /* A pill, so it stays readable over whichever photo drifts behind it. */
    .auth-back{
        min-height:40px;margin-top:2px;padding:0 15px;border-radius:999px;
        color:var(--cream);background:rgba(25,20,16,.62);border:1px solid rgba(245,239,228,.14);
    }
    .auth-back:hover{color:var(--cream);background:rgba(25,20,16,.8);}

    .auth-card{
        flex:1;width:100%;max-width:600px;margin:0 auto;
        padding:24px max(22px,env(safe-area-inset-right)) calc(28px + env(safe-area-inset-bottom)) max(22px,env(safe-area-inset-left));
        border-radius:28px 28px 0 0;
        background:var(--hearth-2);border:1px solid var(--line);border-bottom:0;
        box-shadow:0 -24px 48px -28px rgba(0,0,0,.9);
        animation:sheetUp .8s var(--ease-out) both;
    }
    .auth-tabs{margin-bottom:22px;}
    .auth-tab{height:44px;}
    .auth-title{font-size:1.65rem;}
    .auth-subtitle{margin-bottom:24px;}

    /* Bigger fields and button for thumbs, and 16px text so iOS doesn't zoom
       into a field when it's tapped. */
    .form-control{height:52px;font-size:16px;scroll-margin-block:16px 96px;}
    .otp-boxes{gap:8px;}
    .otp-box{height:58px;}
    .btn-auth,.btn-skip{height:54px;font-size:1rem;}
    .auth-footer{margin-top:24px;padding-top:18px;}
}

/* Compact phones (667px tall and under): a shorter band and tighter spacing,
   so the Log in button still lands on the first screen. */
@media (max-width:900px) and (max-height:700px){
    :root{--band-h:clamp(150px,26dvh,190px);}
    .auth-tabs{margin-bottom:18px;}
    .auth-subtitle{margin-bottom:20px;}
}

/* Short screens: phones held sideways, and on Android a portrait phone with
   the keyboard open (interactive-widget=resizes-content shrinks the viewport,
   so this query applies while typing). The band steps aside for the form. */
@media (max-width:900px) and (max-height:560px), (max-height:500px) and (orientation:landscape){
    :root{--band-h:124px;--sheet-overlap:22px;}
    .auth-card{padding-top:18px;}
    .auth-tabs{margin-bottom:16px;}
    .auth-subtitle{margin-bottom:18px;}
}

/* Portrait tablets: the wall fills the screen and the form sits on it in a
   card, centred. */
@media (min-width:600px) and (max-width:1100px) and (orientation:portrait){
    :root{--wall-gap:16px;}
    .auth-visual{position:fixed;inset:0;height:auto;}
    .auth-visual::after{
        background:
            radial-gradient(70% 55% at 50% 50%,rgba(25,20,16,.55),rgba(25,20,16,.82) 100%),
            rgba(25,20,16,.35);
    }
    .auth-wall{inset:-12% -22%;grid-template-columns:repeat(4,minmax(0,1fr));}
    .auth-wall-col:nth-child(4){display:block;}
    .auth-wall img{border-radius:16px;}

    .auth-form-side{display:flex;align-items:center;justify-content:center;padding:48px 24px;}
    .auth-wrap{flex:none;min-height:0;width:100%;max-width:480px;margin:0 auto;}
    .auth-topbar{height:auto;padding:0;margin-bottom:22px;align-items:center;}
    .auth-card{
        flex:none;padding:32px 32px 30px;border-radius:24px;border-bottom:1px solid var(--line);
        background:rgba(33,27,23,.94);box-shadow:0 30px 70px -30px rgba(0,0,0,.95);
    }
}

@media (max-width:480px){
    .form-row{flex-direction:column;gap:0;}
}

/* ── PHONES: just the form ──────────────────────────────────────────────────
   Phones (under 600px, and phones held sideways) drop the photo band: on a
   small screen it pushed the form halfway down for decoration. The wall's
   photos are loading="lazy", so hidden they aren't even downloaded.
   Back to home keeps its place, top right. The logo sits centred in its own
   row below it -- centred on the screen whatever the width, where sharing
   the back link's row would have pushed it off-centre on a narrow phone.
   Then the form, straight on the page like the desktop layout, no sheet.
   Comes after the band/sheet rules above, which it overrides. */
@media (max-width:599px), (max-width:900px) and (max-height:500px){
    .auth-visual{display:none;}

    .auth-form-side{
        background:
            radial-gradient(120% 38% at 50% 0%,rgba(201,162,78,.09),transparent 70%),
            var(--hearth);
    }

    .auth-topbar{
        display:grid;grid-template-columns:1fr auto;align-items:center;row-gap:14px;
        height:auto;margin:0;
        /* Same 22px sides as the form below, so the back link lines up with
           the fields' right edge. */
        padding:max(12px,env(safe-area-inset-top)) max(22px,env(safe-area-inset-right)) 4px max(22px,env(safe-area-inset-left));
    }
    /* Plain text like on desktop: the pill (background + border) was only
       there to stay readable over the photo band, which phones no longer
       show. The 44px height keeps it an easy tap target. */
    .auth-back{
        grid-column:2;grid-row:1;justify-self:end;margin-top:0;
        min-height:44px;padding:6px 2px;border:0;border-radius:8px;
        background:none;color:var(--muted);
    }
    .auth-back:hover{background:none;color:var(--gold-pale);}

    .auth-brand{
        display:flex;grid-column:1 / -1;grid-row:2;justify-self:center;
        flex-direction:column;gap:8px;min-height:0;
    }
    .auth-brand img{width:56px;height:56px;}
    .auth-brand span{font-size:1.15rem;letter-spacing:.08em;}

    .auth-card{
        width:100%;max-width:480px;margin:0 auto;
        padding:22px max(22px,env(safe-area-inset-right)) calc(28px + env(safe-area-inset-bottom)) max(22px,env(safe-area-inset-left));
        border:0;border-radius:0;background:none;box-shadow:none;
        animation:rise .6s var(--ease-out) both;
    }
    .auth-title{font-size:1.6rem;}
}

/* Phones held sideways: little height, so the logo goes beside its name. */
@media (max-width:900px) and (max-height:500px){
    .auth-topbar{row-gap:4px;}
    .auth-brand{flex-direction:row;gap:10px;}
    .auth-brand img{width:36px;height:36px;}
    .auth-card{padding-top:14px;}
}

/* ── PAGE-TO-PAGE TRANSITIONS ─────────────────────────────────────────────
   The four auth pages opt in to cross-document View Transitions (Chrome /
   Edge 126+, Safari 18.2+; other browsers simply load the page as before).
   Moving between Log in, Sign up, Forgot and Reset: the dish wall and top
   bar stay perfectly still (the wall keeps its place through --wall-clock),
   the form panel morphs to its new size while its contents crossfade, and the
   Log in / Sign up pill slides across. Only same-origin pages that both carry
   this rule take part, so leaving for the homepage or a dashboard is an
   ordinary page load. */
@view-transition{navigation:auto;}
.auth-visual{view-transition-name:auth-visual;}
.auth-visual-caption{view-transition-name:auth-caption;}
.auth-topbar{view-transition-name:auth-topbar;}
.auth-card{view-transition-name:auth-card;}
.auth-tab.is-active{view-transition-name:auth-tab;}

::view-transition-group(*){animation-duration:.5s;animation-timing-function:cubic-bezier(.22,.61,.36,1);}
/* Identical on every page: swap instantly, never blink. A crossfade of the
   moving wall would show two copies of it, a fraction of a second apart. */
::view-transition-old(auth-topbar),
::view-transition-old(auth-visual){animation:none;opacity:0;}
::view-transition-new(auth-topbar),
::view-transition-new(auth-visual){animation:none;}
::view-transition-group(auth-tab){animation-duration:.45s;animation-timing-function:cubic-bezier(.34,1.3,.64,1);}

/* A view transition already animates the new page in, so the first-load
   entrances would only double up. auth pages add .vt-nav on <html> when a
   transition is running (a pagereveal listener in each page's <head>). */
.vt-nav .auth-card,
.vt-nav .auth-card > *,
.vt-nav .auth-card > form > *,
.vt-nav .auth-topbar,
.vt-nav .auth-visual-caption,
.vt-nav .auth-visual-rule,
.vt-nav .auth-visual-caption strong,
.vt-nav .auth-wall-col{animation:none;}

.vt-nav .auth-visual.is-photo::before{animation:visualDrift 30s ease-in-out infinite alternate;}
.vt-nav .auth-card > .alert-error{animation:shake .5s var(--ease) .35s;}

/* The wall holds still (it stops on a frame identical to its first), and
   everything else appears without moving. */
@media (prefers-reduced-motion:reduce){
    @view-transition{navigation:none;}
    *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;}
}
