/**
 * gf-auth.css — the auth and onboarding surface.
 *
 * Tasks GF-23 and GF-24 of docs/plans/2026-08-29-goflorasuite-ui-uplift.md. Five templates share it:
 *
 *   Resources/Views/signin.leaf                 (base.leaf shell)      /client/signin
 *   Resources/Views/signup.leaf                 (base.leaf shell)      /client/signup
 *   Resources/Views/auth/login.leaf             (transport shell)      /products/gofloratransport/login
 *   Resources/Views/auth/register.leaf          (transport shell)      /products/gofloratransport/register
 *   Resources/Views/client/profile-registration.leaf (base.leaf shell) /client/profile/register
 *
 * # Why a scoped stylesheet rather than Tailwind utilities
 *
 * The plan line for GF-23 says "Tailwind + gf-*", but neither /css/tailwind.css nor
 * /css/transport/design-system.css can be added to a base.leaf page without also adding a global
 * reset — Tailwind ships Preflight, design-system.css opens with `* { margin: 0; padding: 0 }` and
 * restyles `body`. Those pages have rendered against Bootstrap's Reboot for their whole life, and
 * swapping the base layer under them is exactly the change GF-16 defers until there is a visual
 * pass. So the auth surface gets its own file, scoped entirely under `.gf-auth`, that changes
 * nothing outside the card.
 *
 * # Tokens
 *
 * Every value is read from the design-system variable with the same literal as its fallback. On the
 * transport shell design-system.css is loaded and its tokens win; on base.leaf the surrounding
 * base.css tokens win where they exist (`--color-text-primary`, `--color-text-secondary`,
 * `--color-border`) and the fallbacks cover the rest. The card therefore harmonises with whichever
 * shell it lands in instead of fighting it, and it needs no updating when GF-20 makes
 * design-system.css global.
 *
 * `box-sizing` is declared on the subtree on purpose: today it is inherited from Bootstrap's
 * Reboot, and GF-16 deletes Bootstrap from base.leaf.
 */

.gf-auth,
.gf-auth *,
.gf-auth *::before,
.gf-auth *::after {
  box-sizing: border-box;
}

.gf-auth {
  --gfa-surface: var(--color-surface, #ffffff);
  --gfa-text: var(--color-text-primary, #0f172a);
  --gfa-text-2: var(--color-text-secondary, #475569);
  --gfa-text-3: var(--color-text-tertiary, #64748b);
  --gfa-border: var(--color-border, #e2e8f0);
  --gfa-primary: var(--color-primary-600, #059669);
  --gfa-primary-light: var(--color-primary-500, #10b981);
  --gfa-primary-dark: var(--color-primary-700, #047857);
  --gfa-primary-50: var(--color-primary-50, #ecfdf5);
  --gfa-primary-100: var(--color-primary-100, #d1fae5);
  --gfa-primary-700: var(--color-primary-700, #047857);
  --gfa-radius: var(--radius-xl, 1rem);
  --gfa-radius-sm: var(--radius-lg, 0.75rem);
  --gfa-shadow: var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05));
  --gfa-touch: var(--touch-target, 48px);
  --gfa-font: var(--font-family-base, 'Plus Jakarta Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
  --gfa-error: var(--color-error, #e11d48);
  --gfa-error-bg: #fef2f2;
  --gfa-error-border: #fecaca;
  --gfa-error-text: #991b1b;
  --gfa-success-text: #065f46;

  /* dvh, not vh: on iOS the address bar is subtracted from vh only after the first scroll, which
     left the card visibly off-centre. A *minimum* rather than a fixed height so a tall form (sign
     up on a 320px-wide phone) still grows instead of clipping. */
  min-height: 60dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-top: clamp(1rem, 5vw, 3rem);
  padding-bottom: calc(clamp(1rem, 5vw, 3rem) + env(safe-area-inset-bottom, 0px));
  overflow-x: hidden;
  font-family: var(--gfa-font);
}

/* ============================================
   CARD
   ============================================ */
.gf-auth__card {
  width: 100%;
  min-width: 0;
  max-width: 26rem;
  padding: clamp(1.25rem, 5vw, 2rem);
  background: var(--gfa-surface);
  border: 1px solid var(--gfa-border);
  border-radius: var(--gfa-radius);
  box-shadow: var(--gfa-shadow);
}

/* Sign-up and the transport register form carry more fields; a little more width keeps the
   hint text off three lines. */
.gf-auth__card--wide {
  max-width: 30rem;
}

/* ============================================
   HEADER
   ============================================ */
.gf-auth__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin: 0 0 1.25rem;
}

.gf-auth__brand-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 0.9rem;
  font-size: 1.3rem;
  color: #fff;
  background: linear-gradient(135deg, var(--gfa-primary-light) 0%, var(--gfa-primary) 100%);
}

.gf-auth__brand-name {
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--gfa-text);
}

.gf-auth__title {
  margin: 0 0 0.35rem;
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--gfa-text);
  text-align: center;
}

.gf-auth__subtitle {
  margin: 0 0 1.5rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--gfa-text-2);
  text-align: center;
}

/* ============================================
   ALERTS
   ============================================ */
.gf-auth__alert {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin: 0 0 1.1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid transparent;
  border-radius: var(--gfa-radius-sm);
  font-size: 0.875rem;
  line-height: 1.45;
}

.gf-auth__alert i {
  flex: none;
  margin-top: 0.15rem;
}

.gf-auth__alert--error {
  background: var(--gfa-error-bg);
  border-color: var(--gfa-error-border);
  color: var(--gfa-error-text);
}

.gf-auth__alert--success {
  background: var(--gfa-primary-50);
  border-color: var(--gfa-primary-100);
  color: var(--gfa-success-text);
}

/* ============================================
   FIELDS
   ============================================ */
.gf-auth__field {
  margin: 0 0 1rem;
}

.gf-auth__label {
  display: block;
  margin: 0 0 0.4rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--gfa-text-2);
}

.gf-auth__control {
  position: relative;
  display: flex;
  align-items: center;
}

.gf-auth__icon {
  position: absolute;
  left: 0.9rem;
  font-size: 0.9rem;
  color: var(--gfa-text-3);
  pointer-events: none;
}

.gf-auth__input {
  width: 100%;
  min-width: 0;
  min-height: var(--gfa-touch);
  padding: 0.75rem 0.9rem 0.75rem 2.5rem;
  /* 1rem is the floor, not a preference: iOS Safari force-zooms the viewport on focus for anything
     under 16px and never zooms back out, which breaks every layout constraint on the page. */
  font: 400 1rem/1.4 var(--gfa-font);
  color: var(--gfa-text);
  background: var(--gfa-surface);
  border: 1px solid var(--gfa-border);
  border-radius: var(--gfa-radius-sm);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

.gf-auth__input::placeholder {
  color: var(--gfa-text-3);
}

.gf-auth__input:focus {
  outline: none;
  border-color: var(--gfa-primary);
  box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.15);
}

.gf-auth__input[aria-invalid="true"] {
  border-color: var(--gfa-error);
}

.gf-auth__input[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px rgba(225, 29, 72, 0.15);
}

/* Room for the visibility toggle. */
.gf-auth__input--toggleable {
  padding-right: 3.25rem;
}

.gf-auth__hint {
  display: block;
  margin: 0.4rem 0 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--gfa-text-3);
}

.gf-auth__toggle {
  position: absolute;
  right: 0.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  color: var(--gfa-text-3);
  background: none;
  border: 0;
  border-radius: var(--gfa-radius-sm);
  cursor: pointer;
  touch-action: manipulation;
}

.gf-auth__toggle:hover {
  color: var(--gfa-text-2);
}

.gf-auth__toggle:active {
  background: var(--gfa-primary-50);
  color: var(--gfa-primary-dark);
}

.gf-auth__textarea {
  padding-left: 0.9rem;
  min-height: 5.5rem;
  line-height: 1.55;
  resize: vertical;
}

/* Server-supplied and not editable here (name and email come from the account). Reads as
   information rather than as an input the user is failing to fill in. */
.gf-auth__input--readonly {
  background: var(--gfa-primary-50);
  border-color: transparent;
  color: var(--gfa-text-2);
  cursor: default;
}

.gf-auth__input--readonly:focus {
  border-color: var(--gfa-border);
  box-shadow: none;
}

/* Two fields per row from 480px up. Deliberately not Bootstrap's `row g-2 / col-md-6`, whose
   breakpoint is 768px — on a 600px-wide tablet that left two half-width fields stacked with the
   gutters still applied. */
.gf-auth__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 0.75rem;
}

@media (min-width: 480px) {
  .gf-auth__grid {
    grid-template-columns: 1fr 1fr;
  }
}

.gf-auth__grid > .gf-auth__field {
  min-width: 0;
}

/* ============================================
   AVATAR PREVIEW
   ============================================ */
.gf-auth__avatar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin: 0 0 1rem;
}

.gf-auth__avatar-frame {
  flex: none;
  display: grid;
  place-items: center;
  width: 4rem;
  height: 4rem;
  overflow: hidden;
  border-radius: 50%;
  background: var(--gfa-primary-50);
  border: 2px solid var(--gfa-primary-100);
  color: var(--gfa-primary-700);
  font-size: 1.5rem;
  font-weight: 800;
}

.gf-auth__avatar-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Hidden until the URL resolves to something that actually loads — gf-auth.js swaps these on the
   image's load/error events, so a broken link shows the initial instead of a broken-image glyph. */
.gf-auth__avatar-frame img[hidden],
.gf-auth__avatar-initial[hidden] {
  display: none;
}

/* The 14rem basis is chosen so the URL field drops below the avatar on a 320px screen rather than
   being squeezed into ~120px next to it. */
.gf-auth__avatar-body {
  flex: 1 1 14rem;
  min-width: 0;
  margin: 0;
}

/* ============================================
   PASSWORD REQUIREMENTS
   ============================================ */
.gf-auth__reqs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.85rem;
  margin: 0.55rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.75rem;
  color: var(--gfa-text-3);
}

.gf-auth__reqs li {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

/* fa-circle / fa-check, drawn from the Font Awesome both shells already load. */
.gf-auth__reqs li::before {
  content: '\f111';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  font-size: 0.5rem;
}

.gf-auth__reqs li.is-met {
  font-weight: 600;
  color: var(--gfa-primary-700);
}

.gf-auth__reqs li.is-met::before {
  content: '\f00c';
  font-size: 0.65rem;
}

/* ============================================
   CHECKBOX + OPTIONS ROW
   ============================================ */
.gf-auth__check {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin: 0 0 1.25rem;
}

.gf-auth__check input[type="checkbox"] {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin: 0.15rem 0 0;
  accent-color: var(--gfa-primary);
}

/* The label carries the tap target, not the 1.15rem box — padding takes the whole row past 44px
   while keeping the checkbox visually aligned to the first line of a wrapping label. */
.gf-auth__check label {
  padding: 0.6rem 0;
  margin: -0.6rem 0;
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--gfa-text-2);
  cursor: pointer;
}

.gf-auth__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  margin: 0 0 1.25rem;
}

.gf-auth__row .gf-auth__check {
  margin: 0;
}

/* ============================================
   SUBMIT
   ============================================ */
.gf-auth__submit {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  min-height: var(--gfa-touch);
  padding: 0 1.25rem;
  font: 700 1rem/1 var(--gfa-font);
  color: #fff;
  background: var(--gfa-primary);
  border: 0;
  border-radius: var(--gfa-radius-sm);
  cursor: pointer;
  touch-action: manipulation;
  transition: background 150ms ease, transform 150ms ease;
}

.gf-auth__submit:hover {
  background: var(--gfa-primary-dark);
}

.gf-auth__submit:active {
  transform: translateY(1px);
}

/* Loading state. The label is hidden rather than removed so the button keeps its width and the
   page does not reflow at the moment of submission. */
.gf-auth__submit.is-loading {
  pointer-events: none;
  background: var(--gfa-primary-dark);
}

.gf-auth__submit.is-loading > * {
  visibility: hidden;
}

.gf-auth__submit.is-loading::after {
  content: '';
  position: absolute;
  width: 1.15rem;
  height: 1.15rem;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: gf-auth-spin 0.7s linear infinite;
}

@keyframes gf-auth-spin {
  to { transform: rotate(360deg); }
}

/* The spinner is the only signal that the submission is in flight, so it slows down rather than
   stopping — a frozen circle would read as a broken button. */
@media (prefers-reduced-motion: reduce) {
  .gf-auth__submit.is-loading::after {
    animation-duration: 2.5s;
  }
  .gf-auth__submit,
  .gf-auth__input,
  .gf-auth__toggle {
    transition: none;
  }
}

/* ============================================
   FOOTER
   ============================================ */
.gf-auth__footer {
  margin: 1.25rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--gfa-border);
  font-size: 0.88rem;
  color: var(--gfa-text-2);
  text-align: center;
}

.gf-auth__footer p {
  margin: 0;
}

.gf-auth__link {
  display: inline-block;
  padding: 0.55rem 0.3rem;
  font-weight: 600;
  color: var(--gfa-primary);
  text-decoration: none;
}

.gf-auth__link:hover {
  color: var(--gfa-primary-dark);
  text-decoration: underline;
}

/* Inside a sentence (the terms checkbox) the padded tap target would break the line box, and the
   surrounding label is already the target. */
.gf-auth__check label .gf-auth__link {
  display: inline;
  padding: 0;
}

.gf-auth__link--muted {
  font-weight: 500;
  color: var(--gfa-text-3);
}

.gf-auth__link--muted:hover {
  color: var(--gfa-text-2);
}

/* ============================================
   DARK MODE
   ============================================ */
/* Only the values that are not already tokens. The token-driven properties follow whichever
   [data-theme="dark"] block the shell provides; GF-52 unifies these. */
[data-theme="dark"] .gf-auth {
  --gfa-error-bg: rgba(225, 29, 72, 0.12);
  --gfa-error-border: rgba(225, 29, 72, 0.35);
  --gfa-error-text: #fda4af;
  --gfa-success-text: #6ee7b7;
  --gfa-primary-50: rgba(16, 185, 129, 0.12);
  --gfa-primary-100: rgba(16, 185, 129, 0.3);
  --gfa-primary-700: #34d399;
}
