:root{
  /* page-specific surfaces/dividers, derived from base.css tokens */
  --panel:    color-mix(in srgb, var(--bg) 88%, white 12%);
  --rule:     color-mix(in srgb, var(--muted) 16%, transparent);
  --bg-input: color-mix(in srgb, var(--bg) 78%, white 22%);
  /* matches account.css's --success for cross-page consistency; kept as
     its own name since base.css has no shared "success" token */
  --pw-success: #4A8C6A;
}
*{ margin:0; padding:0; box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{ -webkit-font-smoothing:antialiased; }
a{ color:inherit; }
:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }

.reveal{ opacity:0; transform:translateY(24px); transition:opacity 0.7s ease, transform 0.7s ease; }
.reveal.is-visible{ opacity:1; transform:translateY(0); }

/* Pins the page to exactly one viewport (header clearance + card + the
   footer's bottom bar) so it never needs to scroll vertically, on any
   device. min-width is a hard floor — real viewports narrower than 340px
   can't actually be forced wider, so overflow-x:auto is the fallback for
   that (rare) case: the page becomes horizontally scrollable rather than
   silently clipping content off the right edge. Overriding base.css's
   global `body{ overflow-x:hidden }` here is intentional and scoped to
   `.login-page` only — every other page keeps that default. */
body.login-page{
  height:100svh;
  min-width:340px;
  overflow-x:auto;
  overflow-y:hidden;
  display:flex;
  flex-direction:column;
}

/* ---------- LAYOUT ----------
   body.login-page (above) is pinned to 100svh with overflow hidden and
   split into two flex children — this .auth region and the footer — so
   .auth only ever gets the space the footer doesn't need. Every vertical
   measurement inside the card (padding, gaps, control heights) is a
   clamp() against `vh`, so as that available space shrinks the card
   actually shrinks with it — nothing gets clipped, nothing needs a
   transform-based scale hack, and it re-fits live as the window is
   resized since it's plain CSS, no resize listener required. */
.auth{
  flex:1 1 auto;
  min-height:0;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
  padding:
    calc(var(--header-h, 64px) + clamp(0.6rem, 2.2vh, 2rem))
    6vw
    clamp(0.6rem, 2.2vh, 1.5rem);
}

/* ---------- CARD ---------- */
.auth__card{
  position:relative;
  background:var(--panel);
  border:1px solid var(--rule);
  border-radius:6px;
  padding:clamp(0.9rem, 3vh, 2.2rem) clamp(1.3rem, 3vw, 2.6rem) clamp(1rem, 3vh, 2.6rem);
  width:100%;
  max-width:440px;
  max-height:100%;
  overflow:hidden;
  box-shadow:0 30px 60px -30px rgba(0,0,0,0.6);
}

.auth__tabs{ position:relative; display:flex; border-bottom:1px solid var(--rule); margin:0 -0.4rem clamp(0.55rem, 2vh, 1.6rem); }
.auth__tab{
  flex:1;
  background:none;
  border:none;
  color:var(--muted);
  font-family:var(--f-mono);
  font-size:0.72rem;
  letter-spacing:0.1em;
  text-transform:uppercase;
  padding:clamp(0.5rem, 1.8vh, 0.9rem) 0.4rem;
  cursor:pointer;
  transition:color 0.2s;
}
.auth__tab:hover{ color:var(--text); }
.auth__tab[aria-selected="true"]{ color:var(--accent); }

/* A single continuous bar, not a per-tab underline — sliding via
   transform so it reads as one piece moving between tabs rather than one
   underline disappearing while another appears. Both tabs are `flex:1`
   (always exactly equal width), so the indicator can just be 50% wide and
   toggle between translateX(0%) and translateX(100%) — that's one
   indicator-width, i.e. exactly the second tab's position — with no JS
   measurement of tab geometry needed at any viewport size. */
.auth__tab-indicator{
  position:absolute;
  left:0;
  bottom:-1px;
  width:50%;
  height:2px;
  background:var(--accent);
  transform:translateX(0%);
  transition:transform 0.3s cubic-bezier(0.65, 0, 0.35, 1);
  pointer-events:none;
}
.auth__tabs[data-active="signup"] .auth__tab-indicator{
  transform:translateX(100%);
}

.auth__flash{
  background:color-mix(in srgb, var(--danger) 12%, transparent);
  border:1px solid color-mix(in srgb, var(--danger) 35%, transparent);
  border-radius:4px;
  padding:0.7rem 0.9rem;
  margin-bottom:1.4rem;
}
.auth__flash p{ color:var(--danger); font-size:0.85rem; line-height:145%; }
.auth__flash p + p{ margin-top:0.3rem; }

/* The card is capped (max-height:100%, no scroll — see .auth__card) so a
   flash banner's extra height has to come out of the fields, not grow the
   card. Only kicks in when a banner is actually present, and each nudge
   is small on its own — they just add up to roughly the banner's height. */
.auth__card:has(.auth__flash) .field__control{
  height:clamp(34px, 5.6vh, 42px);
}
.auth__card:has(.auth__flash) .auth__panel{
  gap:clamp(0.35rem, 1.2vh, 0.8rem);
}
.auth__card:has(.auth__flash) .field{
  gap:clamp(0.15rem, 0.55vh, 0.35rem);
}
.auth__card:has(.auth__flash) .field-group{
  gap:clamp(0.2rem, 0.7vh, 0.4rem);
}

/* ---------- STANDALONE PAGE HEADER / FOOTNOTE ----------
   forgot_password.html / reset_password.html have no Sign In/Sign Up
   tabs, so they need their own compact heading plus a back-link under
   the form instead. */
.auth__title{
  font-family:var(--f-body);
  font-size:clamp(1.1rem, 3vh, 1.5rem);
  color:var(--text);
  margin-bottom:0.4rem;
}
.auth__subtitle{
  font-family:var(--f-body);
  font-size:0.85rem;
  color:var(--muted);
  line-height:150%;
  margin-bottom:clamp(0.8rem, 2.4vh, 1.4rem);
}
.auth__footnote{
  margin-top:clamp(0.8rem, 2.4vh, 1.4rem);
  text-align:center;
  font-family:var(--f-mono);
  font-size:0.72rem;
}
.auth__footnote a{ color:var(--muted); transition:color 0.2s; }
.auth__footnote a:hover{ color:var(--accent); }

/* ---------- ACCORDION CROSSFADE ----------
   .auth__panels animates its own height between the two forms' natural
   sizes while the outgoing/incoming form crossfades with a small vertical
   drift. Only one .auth__panel is ever in normal flow — loginv2.js toggles
   `hidden` after the fade-out completes, which is what lets the height
   transition read the incoming panel's real scrollHeight. */
.auth__panels{
  position:relative;
  overflow:hidden;
  transition:height 0.32s cubic-bezier(0.65, 0, 0.35, 1);
}

.auth__panel{
  display:flex;
  flex-direction:column;
  gap:clamp(0.45rem, 1.5vh, 1rem);
  opacity:1;
  transform:translateY(0);
  transition:opacity 0.18s ease, transform 0.18s ease;
}
.auth__panel[hidden]{ display:none; }
.auth__panel.is-leaving{ opacity:0; transform:translateY(-6px); }
.auth__panel.is-entering{ opacity:0; transform:translateY(6px); }

.field{ display:flex; flex-direction:column; gap:clamp(0.2rem, 0.7vh, 0.45rem); }
.field__label{ font-family:var(--f-mono); font-size:0.66rem; letter-spacing:0.1em; text-transform:uppercase; color:var(--muted); }
.field__control{
  display:flex;
  align-items:center;
  gap:0.6rem;
  background:var(--bg-input);
  border:1px solid var(--rule);
  border-radius:4px;
  padding:0 0.85rem;
  height:clamp(38px, 6.4vh, 48px);
  transition:border-color 0.2s, box-shadow 0.2s;
}
.field__control:focus-within{
  border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.field__icon{ width:17px; height:17px; flex-shrink:0; color:var(--muted); transition:color 0.2s; }
.field__control:focus-within .field__icon{ color:var(--accent); }
.field__control input{
  flex:1;
  min-width:0;
  background:none;
  border:none;
  outline:none;
  color:var(--text);
  font-family:var(--f-body);
  font-size:0.92rem;
}
.field__control input::placeholder{ color:color-mix(in srgb, var(--muted) 70%, transparent); }

/* iOS Safari auto-zooms on focus into any text input smaller than 16px —
   bumping to exactly 16px there (not further shrunk by a clamp) removes
   the trigger. Scoped to coarse-pointer (touch) devices only, since this
   is purely a mobile browser behavior; desktop keeps its 0.92rem. */
@media (pointer:coarse){
  .field__control input{ font-size:16px; }
}

/* Chrome (and others) paint autofilled inputs with their own opaque
   background via an internal :-webkit-autofill state that normal
   `background`/`background-color` can't override. The oversized inset
   box-shadow repaints it to match this field's own background instead;
   the absurdly long background-color transition stops that native
   background from flashing for a moment before the override applies. */
.field__control input:-webkit-autofill,
.field__control input:-webkit-autofill:hover,
.field__control input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--text);
  -webkit-box-shadow:0 0 0 1000px var(--bg-input) inset;
  box-shadow:0 0 0 1000px var(--bg-input) inset;
  caret-color:var(--text);
  transition:background-color 9999s ease-in-out 0s;
}
.field__toggle{
  background:none;
  border:none;
  color:var(--muted);
  font-family:var(--f-mono);
  font-size:0.62rem;
  letter-spacing:0.06em;
  text-transform:uppercase;
  cursor:pointer;
  flex-shrink:0;
  padding:0.4rem 0;
  transition:color 0.2s;
}
.field__toggle:hover{ color:var(--accent); }

/* Confirm Password + its checklist share one .field-group so together
   they only cost the panel a single flex `gap` slot, not two. */
.field-group{
  display:flex;
  flex-direction:column;
  gap:clamp(0.3rem, 0.9vh, 0.55rem);
}

/* First/Last Name side by side — same idea as .field-group: two fields
   sharing one .auth__panel gap slot instead of two, at every viewport
   width (no stacking breakpoint), which is what actually shrinks Sign
   Up's height on mobile. Columns are equal `fr` shares, so the pair
   always fills the row's full width — whatever that is at the card's
   current size — split evenly between the two fields, growing together
   as the card grows. minmax(0, …) still lets each column shrink on
   narrow phones without overflowing. */
.field-row{
  display:grid;
  grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);
  gap:0.6rem;
}

.pw-checklist{
  list-style:none;
  display:flex;
  flex-direction:column;
  gap:clamp(0.12rem, 0.45vh, 0.28rem);
}
.pw-checklist__item{
  display:flex;
  align-items:center;
  gap:0.4rem;
  font-family:var(--f-mono);
  font-size:clamp(0.6rem, 1.5vh, 0.68rem);
  line-height:1.2;
  letter-spacing:0.02em;
  color:var(--muted);
  transition:color 0.15s ease;
}
.pw-checklist__icon{
  width:6px;
  height:6px;
  border-radius:50%;
  flex-shrink:0;
  background:currentColor;
  opacity:0.5;
  transition:opacity 0.15s ease;
}
.pw-checklist__item.is-valid{ color:var(--pw-success); }
.pw-checklist__item.is-invalid{ color:var(--danger); }
.pw-checklist__item.is-valid .pw-checklist__icon,
.pw-checklist__item.is-invalid .pw-checklist__icon{ opacity:1; }

.checkbox-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:0.6rem;
}
.checkbox{
  display:flex;
  align-items:center;
  gap:0.55rem;
  font-family:var(--f-mono);
  font-size:0.78rem;
  color:var(--muted);
  cursor:pointer;
}
.checkbox input{ accent-color:var(--accent); width:15px; height:15px; }

.auth__forgot-link{
  font-family:var(--f-body);
  font-size:0.72rem;
  letter-spacing:0.04em;
  color:var(--muted);
  text-decoration:none;
  transition:color 0.2s;
}
.auth__forgot-link:hover{ color:var(--accent); }

.auth__submit{
  margin-top:0.2rem;
  height:clamp(40px, 6.4vh, 50px);
  border:none;
  border-radius:4px;
  background:var(--accent);
  color:var(--bg);
  font-family:var(--f-mono);
  font-size:0.78rem;
  letter-spacing:0.1em;
  text-transform:uppercase;
  cursor:pointer;
  transition:background 0.2s, transform 0.15s;
}
.auth__submit:hover{ background:color-mix(in srgb, var(--accent) 85%, white 15%); }
.auth__submit:active{ transform:translateY(1px); }

/* ---------- FOOTER OVERRIDE (login page only) ----------
   The shared footer partial ships an About/Categories/Subscribe top
   section plus a logo+links bottom bar. The login page only wants the
   bottom bar. Scoped to `.login-page` — rather than editing the shared
   footer files — so every other page that includes the same partial
   (about, process, ...) keeps its top section. (The bottom bar's
   desktop-everywhere layout is handled globally in footer.css itself,
   since that should apply to every page, not just this one.) */
body.login-page .footer-top{ display:none; }

/* header2.js hides the header/menu-bar on scroll-down (adds `.is-hidden`
   / removes `.is-visible`) — a shared, cross-page script we don't want
   to edit. On the login page the header should just always stay put, so
   this neutralizes those toggled states here instead. Plain specificity
   (no !important) is enough: each of these at rest has fewer classes
   than its `.header.is-visible …`/`.menu-bar.is-hidden` counterpart in
   header2.css, so they still lose gracefully to those rules when the
   state they'd set is the same anyway (visible+clickable either way).
   `.header-inner` (now the home link itself) needs its own pointer-events
   override alongside its children's, since header2.css keeps it
   unclickable by default until `.header.is-visible` — here it should
   always be clickable, matching that it's always visible. `.cart-btn`
   now mirrors `.menu-bar`'s scroll-hide behavior too, so it gets the
   same treatment here. */
body.login-page .header-inner{
  pointer-events:auto;
}
body.login-page .header-inner > *{
  transform:translateX(0);
  opacity:1;
  pointer-events:auto;
}
body.login-page .menu-bar.is-hidden{
  transform:translateX(0);
  opacity:1;
}
body.login-page .cart-btn.is-hidden{
  transform:translateX(0);
  opacity:1;
}

/* ---------- RESPONSIVE ----------
   Horizontal-only: vertical sizing is already fluid via the clamp()s
   above, which respond continuously to viewport height on their own. */
@media (max-width: 560px){
  .auth{ padding-left:5vw; padding-right:5vw; }
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  .reveal{ transition:opacity 0.2s linear; transform:none; }
  .auth__panels{ transition:none; }
  .auth__panel{ transition:none; }
  .auth__tab-indicator{ transition:none; }
}
