/* ================================================================
   39 Cheval Place — Portal FRONT DOOR (login + passkey registration)
   ================================================================
   Consumes the token layer from portal.css. Never redefines :root.

   Load order on login.php AND register-passkey.php:
       /css/vN/shared-base.css
       /css/vN/portal.css          <- tokens + .btn/.form-group/.banner
       /css/vN/portal-login.css    <- this file (overrides body to ink)

   Layout: a full-bleed 3-section grid, NO vertical centring, NO
   400px card in a void. The old page had ~330px of dead space above
   the card on desktop and 260px on iPhone, and told a first-time
   visitor nothing about the project.

     Desktop (>768px)        Mobile (<=768px)
     +-----------+------+    +-------------------+
     |  brand    |      |    |  brand            |
     +-----------+ panel|    +-------------------+
     |  contents |      |    |  panel (sign in)  |
     +-----------+------+    +-------------------+
                             |  contents         |
                             +-------------------+

   DOM order is brand -> panel -> contents in BOTH cases, so the
   passkey button lands ~260px down the phone screen, well above the
   fold, without any source reordering.

   min-height:100dvh lives on .login-shell (not body): on iOS Safari
   100vh exceeds the visible viewport and pushed the old card down
   behind the collapsed toolbar, giving the page a phantom scroll.
   ================================================================ */

/* Two values portal.css has no token for yet (requested): a translucent danger
   tint that works on ink, and the survey-grid hairline. Declared once here on
   .login-shell rather than repeated as raw rgba() in six rules. */
.login-shell {
    --ink-danger-bg: rgba(220, 38, 38, .14);   /* danger tint that reads on ink */
    --ink-grid:      rgba(255, 255, 255, .035); /* survey-grid hairline */
}

body {
    background: var(--c-ink);
    color: var(--c-ink-text);
    font-family: var(--font-body);
    font-size: var(--text-base);
    /* no flex centring — the shell owns the layout */
}

.login-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 400px;
    grid-template-areas:
        'brand panel'
        'contents panel';
    grid-template-rows: max-content 1fr;
    min-height: 100dvh;
}


/* Two-area variant for register-passkey.php: brand + panel only, no contents
   list (a first-time visitor there already knows why they came). */
.login-shell-2col {
    grid-template-areas: 'brand panel';
    grid-template-rows: 1fr;
}


/* ---------------------------------------------------------------
   Brand panel — the sense of place, with zero external assets.
   The faint survey grid is two repeating-linear-gradients.
   --------------------------------------------------------------- */
.login-brand {
    grid-area: brand;
    background: var(--c-ink);
    border-right: 1px solid var(--c-ink-border);
    padding: 3rem 3.5rem 2rem;
    display: flex;
    flex-direction: column;
    gap: .75rem;
    background-image:
        repeating-linear-gradient(0deg,  var(--ink-grid) 0 1px, transparent 1px 32px),
        repeating-linear-gradient(90deg, var(--ink-grid) 0 1px, transparent 1px 32px);
}

/* The 39CH wordmark at 2x the header size. Reuses .portal-logo from portal.css
   for the colours; this only scales it. */
.login-brand .portal-logo { font-size: 2.1rem; letter-spacing: .5px; }
.login-brand .portal-logo::before { width: 5px; height: 34px; margin-right: 14px; }

.login-brand h1 {
    font-size: var(--text-2xl);
    font-weight: 700;
    color: var(--c-ink-text);
    letter-spacing: .01em;
    margin: .35rem 0 0;
}

.login-addr {
    font-size: var(--text-sm);
    color: var(--c-ink-muted);
    text-transform: uppercase;
    letter-spacing: .08em;
}

.login-lede {
    font-size: var(--text-base);
    color: var(--c-ink-muted);
    max-width: 46ch;
    line-height: 1.55;
    margin-top: .35rem;
}

/* Dense definition grid: 4 non-sensitive project facts. */
.login-facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 1rem;
    row-gap: .3rem;
    margin-top: 1rem;
    max-width: 56ch;
}
.login-facts dt {
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--c-ink-faint);
    align-self: baseline;
}
.login-facts dd {
    font-size: var(--text-sm);
    color: var(--c-ink-text);
    margin: 0;
}


/* ---------------------------------------------------------------
   Contents — what is inside, in two hairline-ruled columns.
   PUBLIC-SAFE labels only (no "Valuation", no money words).
   --------------------------------------------------------------- */
.login-contents-wrap {
    grid-area: contents;
    background: var(--c-ink);
    border-right: 1px solid var(--c-ink-border);
    border-top: 1px solid var(--c-ink-border);
    padding: 1.5rem 3.5rem 2.5rem;
    /* flex column so .login-legal can sit on the baseline of a tall left column
       instead of leaving ~380px of empty ink under the list at 1440x1000 */
    display: flex;
    flex-direction: column;
    /* same survey grid, so the whole left column reads as one panel */
    background-image:
        repeating-linear-gradient(0deg,  var(--ink-grid) 0 1px, transparent 1px 32px),
        repeating-linear-gradient(90deg, var(--ink-grid) 0 1px, transparent 1px 32px);
}
.login-contents-title {
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--c-ink-faint);
    margin-bottom: .6rem;
}
/* Column COUNT is not fixed: column-width lets the list use whatever room the
   left column actually has (3 columns at 1440, 2 at ~1000, 1 on a phone) instead
   of two narrow columns stranded beside 450px of empty ink. */
.login-contents {
    column-width: 17rem;
    column-gap: 2rem;
    list-style: none;
    margin: 0;
    padding: 0;
}
.login-contents li {
    padding: .28rem 0;
    border-bottom: 1px solid var(--c-ink-border);
    break-inside: avoid;
    font-size: var(--text-sm);
    color: var(--c-ink-muted);
}


/* Baseline note under the contents list: says what the site is and that access is
   recorded. margin-top:auto pins it to the bottom of the column. */
.login-legal {
    margin-top: auto;
    padding-top: 1.5rem;
    font-size: var(--text-xs);
    color: var(--c-ink-faint);
    max-width: 88ch;
}


/* ---------------------------------------------------------------
   Sign-in panel — the control surface.
   --------------------------------------------------------------- */
.login-panel {
    grid-area: panel;
    background: var(--c-ink-2);
    border-left: 1px solid var(--c-ink-border);
    /* Top-aligned, not vertically centred: centred, the panel floated in the
       middle of a 1000px column and left ~300px of dead space under the contents
       list on the left. Aligning it with the brand block puts the one control on
       the page at the height the eye already is. */
    padding: 3.4rem 2rem;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: var(--sp-3);
}
.login-panel h2 {
    font-size: var(--text-xl);
    font-weight: 700;
    color: var(--c-ink-text);
    margin: 0;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--c-ink-border);
}

/* role="alert" + the hidden attribute (never inline style.display) */
.login-err {
    background: var(--ink-danger-bg);
    border-left: 2px solid var(--c-danger-bright);
    color: var(--c-ink-danger);
    padding: .5rem .7rem;
    border-radius: var(--radius);
    font-size: var(--text-base);
}

/* Primary action: full width, 48px, autofocus (Enter works on load). */
.btn-passkey {
    width: 100%;
    min-height: 48px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: .6rem 1.1rem;
    background: var(--c-primary);
    color: var(--c-white);
    border: 1px solid var(--c-primary);
    border-radius: var(--radius);
    font-size: var(--text-lg);
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background .12s;
}
.btn-passkey:hover { background: var(--c-primary-hover); }
.btn-passkey:disabled { opacity: .6; cursor: wait; }
/* The button is focused on load so Enter signs you in. The default 2px blue ring
   is invisible on a blue button, so the ring is white and offset here — it has to
   read as "this is where the keyboard is", not as a rendering artefact. */
.btn-passkey:focus-visible { outline: 2px solid var(--c-primary-lt); outline-offset: 2px; }
.btn-passkey svg { width: 16px; height: 16px; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.8; }

.login-hint {
    font-size: var(--text-sm);
    color: var(--c-ink-muted);
    margin: -.35rem 0 0;
}

/* Secondary: the password fallback toggle. A real button, not body copy with
   an underline — it is the only route in for anyone whose passkey fails on site. */
.login-alt-toggle {
    width: 100%;
    min-height: var(--tap-lg);   /* 44px — it is a primary route in on site */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--c-ink-border);
    border-radius: var(--radius);
    color: var(--c-ink-muted);
    font-size: var(--text-base);
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    padding: 0 1rem;
}
.login-alt-toggle:hover { color: var(--c-ink-text); border-color: var(--c-ink-faint); background: var(--c-ink-3); }

/* The password panel. Hidden via the `hidden` ATTRIBUTE (portal.css has
   [hidden]{display:none!important}) — never via a CSS display:none rule, which
   is what made the old toggle need two clicks (section.style.display was ''). */
.login-pw { display: flex; flex-direction: column; gap: .5rem; }

/* Form fields on ink. .form-group geometry comes from portal.css; only the
   ink colours are set here. */
.login-panel .form-group { margin-bottom: .5rem; }
.login-panel .form-group label { color: var(--c-ink-muted); }
.login-panel .form-group input {
    background: var(--c-ink);
    border-color: var(--c-ink-border);
    color: var(--c-ink-text);
}
.login-panel .form-group input:focus {
    border-color: var(--c-primary);
    box-shadow: 0 0 0 2px var(--c-primary-ring);
}

.btn-password {
    width: 100%;
    min-height: var(--tap-lg);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--c-ink-3);
    color: var(--c-ink-text);
    border: 1px solid var(--c-ink-border);
    border-radius: var(--radius);
    font-size: var(--text-base);
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}
.btn-password:hover { background: var(--c-ink-border); }
.btn-password:disabled { opacity: .5; cursor: wait; }

/* Fine print, but it is the only instruction for someone whose passkey is missing
   on a rainy site — so hierarchy comes from SIZE, not from a low-contrast grey
   (--c-ink-faint lands ~4.4:1 on the panel, under AA for body text). */
.login-foot {
    font-size: var(--text-xs);
    color: var(--c-ink-muted);
    border-top: 1px solid var(--c-ink-border);
    padding-top: .75rem;
    margin-top: .25rem;
    line-height: 1.5;
}

/* Legacy classes from the old inline <style>, kept sane so nothing looks broken
   mid-migration. .login-card / .subtitle / .address / .divider / .toggle-link /
   .error-msg were the whole old page. */
.login-card {
    background: var(--c-ink-2);
    border: 1px solid var(--c-ink-border);
    border-radius: var(--radius);
    padding: 2rem 1.75rem;
    width: 100%;
    max-width: 400px;
    margin: 2rem auto;
}
.login-card h1 { font-size: var(--text-2xl); color: var(--c-ink-text); }
.subtitle { color: var(--c-ink-muted); font-size: var(--text-base); margin-bottom: 1rem; }
.address { color: var(--c-ink-faint); font-size: var(--text-xs); letter-spacing: .06em; text-transform: uppercase; margin-bottom: 1rem; }
.divider { display: flex; align-items: center; gap: .75rem; margin: 1rem 0; color: var(--c-ink-faint); font-size: var(--text-sm); }
.divider::before, .divider::after { content: ''; flex: 1; border-top: 1px solid var(--c-ink-border); }
.toggle-link {
    background: none; border: 0; color: var(--c-ink-muted);
    font-size: var(--text-base); font-family: inherit; cursor: pointer;
    text-decoration: underline; display: block; width: 100%; min-height: var(--tap);
}
.toggle-link:hover { color: var(--c-primary-lt); }
.error-msg {
    background: var(--ink-danger-bg);
    border-left: 2px solid var(--c-danger-bright);
    color: var(--c-ink-danger);
    padding: .5rem .7rem;
    border-radius: var(--radius);
    font-size: var(--text-base);
    margin-bottom: .75rem;
}


/* ================================================================
   PASSKEY REGISTRATION (register-passkey.php)
   Reuses .login-shell / .login-brand / .login-panel so registration
   and sign-in are visibly the same product.
   ================================================================ */
.register-card {
    /* legacy wrapper — flat, no bubble, sits in the panel column */
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    width: 100%;
    max-width: 400px;
}
.register-card h1 { font-size: var(--text-2xl); color: var(--c-ink-text); margin-bottom: .15rem; }

.user-info {
    background: var(--c-ink-3);
    border-left: 2px solid var(--c-primary-lt);
    padding: .6rem .8rem;
    margin-bottom: .9rem;
    border-radius: var(--radius);
}
.user-info strong { color: var(--c-ink-text); font-size: var(--text-md); }
.user-info .detail { color: var(--c-ink-muted); font-size: var(--text-sm); }

.instructions {
    font-size: var(--text-base);
    color: var(--c-ink-muted);
    line-height: 1.5;
    margin-bottom: 1rem;
    max-width: 52ch;
}

.btn-register {
    width: 100%;
    min-height: 48px;
    display: inline-flex; align-items: center; justify-content: center; gap: 9px;
    background: var(--c-primary);
    color: var(--c-white);
    border: 1px solid var(--c-primary);
    border-radius: var(--radius);
    font-size: var(--text-lg);
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}
.btn-register:hover { background: var(--c-primary-hover); }
.btn-register:disabled { opacity: .6; cursor: wait; }

.status { font-size: var(--text-base); color: var(--c-ink-muted); margin-top: .7rem; }
.status.ok  { color: var(--c-ink-ok); }
.status.err { color: var(--c-ink-danger); }
.status a { color: var(--c-primary-lt); }

/* .pk-callout — the "check your email" block. Replaces a 1.5rem/800 shouty
   inline-styled box built inside innerHTML. Sentence case, on-scale, radius 0. */
.pk-callout {
    background: var(--c-ink-3);
    border-left: 3px solid var(--c-warn-bright);
    color: var(--c-ink-warn);
    padding: .9rem 1rem;
    border-radius: var(--radius);
    margin-top: .5rem;
    font-size: var(--text-base);
    line-height: 1.5;
}
.pk-callout strong { display: block; font-size: var(--text-lg); font-weight: 700; margin-bottom: .25rem; }

.error-card {
    background: var(--ink-danger-bg);
    border-left: 3px solid var(--c-danger-bright);
    color: var(--c-ink-danger);
    padding: .8rem 1rem;
    border-radius: var(--radius);
    font-size: var(--text-base);
    line-height: 1.5;
}
.error-card a { color: var(--c-primary-lt); }
/* The "Back to sign in" escape hatch is a 44px control, not a 19px inline link —
   it is the only way out of a dead invite, often tapped with gloves on. */
.error-card + .login-alt-toggle { margin-top: .7rem; text-decoration: none; }

/* The register panel heading is an h2 (the brand column already owns the page h1),
   so it picks up .login-panel h2. Only the spacing below it is page-specific. */
.register-card h2 { margin-bottom: .75rem; }
.register-card .login-foot { margin-top: .9rem; }


/* ================================================================
   RESPONSIVE — 390px is the primary target
   ================================================================ */
/* Tablet portrait / small laptop: keep both columns but stop the 3.5rem gutters
   from squeezing the brand copy into a 280px ribbon. */
@media (min-width: 769px) and (max-width: 1100px) {
    .login-shell { grid-template-columns: minmax(0, 1fr) 340px; }
    .login-brand { padding: 2rem 1.75rem 1.5rem; }
    .login-contents-wrap { padding: 1.25rem 1.75rem 2rem; }
    .login-panel { padding: 2rem 1.5rem; }
}

@media (max-width: 768px) {
    .login-shell {
        grid-template-columns: 1fr;
        grid-template-areas:
            'brand'
            'panel'
            'contents';
        /* max-content on the first two rows: `auto` tracks STRETCH to fill
           min-height:100dvh, which padded 35px of dead ink under the address line
           and pushed the passkey button down the phone screen. Slack goes to the
           contents row instead. */
        grid-template-rows: max-content max-content 1fr;
    }
    .login-shell-2col { grid-template-rows: max-content 1fr; }

    .login-brand {
        /* Tight bottom padding: the sign-in panel must start high enough that the
           passkey button is on screen without a scroll on a 390x844 iPhone. */
        padding: 1rem 1rem .9rem;
        gap: .25rem;
        border-right: 0;
        border-bottom: 1px solid var(--c-ink-border);
    }
    .login-brand .portal-logo { font-size: 1.6rem; }
    .login-brand .portal-logo::before { height: 26px; width: 4px; margin-right: 11px; }
    .login-brand h1 { font-size: var(--text-xl); margin-top: .1rem; }
    /* Drop the lede + facts on the phone so the passkey button stays above the
       fold; the contents list below still explains what is inside. */
    .login-lede, .login-facts { display: none; }
    /* The brand block's baseline note (register page) would land ABOVE the fold on a
       phone and push the ceremony down; the login page keeps its copy in the
       contents column, where it is still at the bottom of the page. */
    .login-brand .login-legal { display: none; }

    .login-panel {
        padding: 1.25rem 1rem 1.5rem;
        justify-content: flex-start;
        gap: .6rem;
    }
    .login-panel h2 { font-size: var(--text-lg); }

    .login-contents-wrap {
        padding: 1rem 1rem 2rem;
        border-right: 0;
        border-top: 1px solid var(--c-ink-border);
    }
    .login-contents { columns: 1; font-size: var(--text-xs); }
    .login-contents li { font-size: var(--text-xs); }

    /* iOS zoom-on-focus guard: a hard 16px, not a token. */
    .login-panel input,
    .login-card input { font-size: 16px; min-height: var(--tap); }
}
