#logo img {
  height: 55px;
}

* {
  font-family: Montserrat;
}

button {
  cursor: pointer !important;
}

body {
  margin: 0;
  /* warm gradient — the mobile view's photo covers this, so it only shows
     on the laptop/tablet layout */
  background: linear-gradient(135deg, #faf4ec 0%, #f6e7dc 55%, #f0d6c6 100%);
}

/* ============================================================
   Laptop foundations. Apply on wide screens OR any landscape
   orientation (iPad / Next Hub landscape → photo-wall UI).
   Portrait phones & tablets keep the mobile sheet instead.
   ============================================================ */
@media (min-width: 1367px), (orientation: landscape) {
  * {
    font-family: "DM Sans", sans-serif;
  }
  body {
    position: relative;
    min-height: 100vh;
    overflow: hidden;
  }
  .popup-heading span {
    font-family: inherit;
  }
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

input {
  padding: 10px;
  font-size: 20px;
  border: 1px solid #d9d9d9;
  border-radius: 0.3rem;
  width: 380px;
  max-width: 100%;
  box-sizing: border-box;
  margin: 0 auto 30px auto;
}

input[type=number] {
  -moz-appearance: textfield;
}

.pin-code {
  padding: 0;
  margin: 0 auto;
  width: 100%;
  display: flex;
  gap: 10px;
}

/* The same field as the ones above it: six equal cells across the same width,
   with the phone field's height, wash, border and corner. They used to be fixed
   44px grey boxes, which read as a different form. */
.pin-code input {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  height: 54px;
  margin: 0;
  padding: 10px 0;
  text-align: center;
  font-size: 18px;
  font-weight: 600;
  color: #2b211c;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(176, 148, 117, 0.45);
  border-radius: 12px;
}

.pin-code input:focus {
  outline: none;
  /* The focused field takes the page's own warm accent, the tone the wash and
     the labels are built from, rather than the WhatsApp green, which belongs to
     the button. */
  border-color: #b09475;
  box-shadow: 0 0 0 3px rgba(176, 148, 117, 0.18);
}

/* Chrome counts a pasted OTP as an autofill and paints its own opaque
   rgb(232,240,254) over the cell, which background-color cannot override. Cover
   it with an inset shadow in the cell's own colour. Same fix as #s-n-phone. */
.pin-code input:-webkit-autofill,
.pin-code input:-webkit-autofill:hover,
.pin-code input:-webkit-autofill:focus,
.pin-code input:-webkit-autofill:active {
  -webkit-box-shadow: inset 0 0 0 100px #fdfaf6;
  /* Chrome also forces its own text colour, with !important, so colour has to
     come back through text-fill. inherit is the digit colour these cells
     already show. */
  -webkit-text-fill-color: inherit;
}
/* Firefox has no :-webkit-autofill, only the standard :autofill, and it tints
   the cell with a background IMAGE rather than a colour. Its own block, because
   a pseudo-class an engine does not know throws away the whole selector list it
   appears in, which would take the rule above down with it in Chrome. */
.pin-code input:autofill,
.pin-code input:autofill:hover,
.pin-code input:autofill:focus,
.pin-code input:autofill:active {
  background-image: none;
  box-shadow: inset 0 0 0 100px #fdfaf6;
  -webkit-text-fill-color: inherit;
}


.pin-code input::-webkit-outer-spin-button,
.pin-code input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* ============================================================
   Laptop "warm wash" login: sign-in floating on the left, a
   staggered photo wall on the right. The whole layout is capped
   and centred at the 1620 design target so it stays balanced —
   the form never strands — on wider monitors.
   ============================================================ */
.main-login {
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  /* left column holds the wider form + cream gap; right column gets the rest
     for larger photo tiles */
  grid-template-columns: 700px 1fr;
  /* Fixed 1620x900 reference canvas, uniformly scaled (see --fit-scale in
     login.html) and centred. Because the whole canvas scales as one unit,
     the composition looks identical — never stretched — on every laptop and
     iPad; the scale is capped at 1 so it never zooms past its natural size.
     overflow:visible lets the photo wall grow past the 900px canvas to the
     real viewport edges (body still clips). */
  width: 1620px;
  height: 900px;
  overflow: visible;
  transform: translate(-50%, -50%) scale(var(--fit-scale, 1));
  box-sizing: border-box;
}

.slider {
  /* full-bleed hero is mobile-only; the laptop view uses the photo wall */
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.slider img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Cinematic gradient — darkens the edges so the logo, caption
   and glass card stay legible while the centre of the photo
   remains bright and immersive. */
.slider::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.15) 45%, rgba(0, 0, 0, 0.10) 100%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.40) 0%, rgba(0, 0, 0, 0.00) 28%, rgba(0, 0, 0, 0.00) 65%, rgba(0, 0, 0, 0.45) 100%);
}

/* The sign-in floats directly on the warm wash — no card, no border */
.signin-box {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 46px 52px;
  background: none;
}

/* Keep every fixed-width control inside the card bounds */
.signin-box input,
.signin-box .phoneInput,
.signin-box .iti,
.signin-box .WA-desktop button,
.signin-box .toast {
  max-width: 100%;
}

.popup-heading {
  margin: 0 0 28px 0;
  font-family: "Playfair Display", serif;
  font-weight: 600;
  font-size: 46px;
  line-height: 1.05;
  text-align: left;
  color: #2b211c;
  letter-spacing: 0.3px;
  padding: 0;
}

/* "Sign in to relive it" is the mobile-only heading; desktop keeps "Sign-In" */
.heading-relive {
  display: none;
}

.sign-in-input {
  width: 100%;
  margin-bottom: 30px;
  color: #495057;
  background-color: #fff;
  background-clip: padding-box;
  border: 1px solid #ced4da;
  border-radius: 0.25rem;
  transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
  padding: 0.375rem 0.75rem;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
}

/* :not() because the country dropdown the plugin appends to <body> also carries
   the .iti class, and this !important was stretching it to the viewport width. */
.iti:not(.iti--container) {
  width: 100% !important;
}


.phoneInput {
  position: relative;
}

#chNum {
  cursor: pointer;
  /* Out of flow, over the field's right edge. In flow it took its own width out
     of the row, which is why the phone field came up short of the WhatsApp
     button and the password field above and below it. */
  position: absolute;
  right: 16px;
  top: 0;
  bottom: 0;
  align-items: center;
  display: flex;
  z-index: 1;
}

/* Every later step is the same field as the phone one, so they all take its box
   and its colours: same height, padding, corner, wash and border. Bootstrap's
   own input look (white, 4px corner, its own height) is what made them read as
   a different form. */
#s-pwrd,
#l-name,
#l-eml,
.email-row-div .form-control {
  width: 100%;
  height: 54px;
  padding: 10px 16px;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  color: #2b211c;
  background: rgba(255, 255, 255, 0.55);
  background-clip: padding-box;
  border: 1px solid rgba(176, 148, 117, 0.45);
  border-radius: 12px;
  /* auto side margins come from the base input rule and centred these fields in
     their rows, so they started further in than the phone field above them */
  margin: 0 auto 30px 0;
}

#s-pwrd::placeholder,
#l-name::placeholder,
#l-eml::placeholder {
  color: #b09475;
}

#s-pwrd:focus,
#l-name:focus,
#l-eml:focus {
  outline: none;
  /* The focused field takes the page's own warm accent, the tone the wash and
     the labels are built from, rather than the WhatsApp green, which belongs to
     the button. */
  border-color: #b09475;
  box-shadow: 0 0 0 3px rgba(176, 148, 117, 0.18);
}

/* The row this field sits in centres its content; the phone row does not, so
   left edges only line up once this one starts at the start too. */
.signin-box .FC {
  justify-content: flex-start;
}

/* Bootstrap's row gutter pulls this row wider on each side than the phone row,
   which is not a .row, so the field started further left and ran longer. Its
   stylesheet loads after this one, so plain .passwd-row-div would tie on
   specificity and lose; the parent in front of it settles that. */
.signin-box .passwd-row-div {
  margin-left: 0;
  margin-right: 0;
}
/* A bootstrap row pads its children too, not just itself, which is the rest of
   the inset between this field and the phone field above it. */
.signin-box .passwd-row-div > * {
  padding-left: 0;
  padding-right: 0;
}

/* Cinematic narrative caption over the hero (mobile hero only) */
.overlay-slider {
  display: none;
  position: absolute;
  left: 6vw;
  top: 50%;
  transform: translateY(-50%);
  max-width: 46%;
  z-index: 2;
  text-align: left;
  color: #ffffff;
  padding: 0;
  background: none;
}

.overlay-eyebrow {
  display: block;
  font-family: 'Montserrat', sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  margin-bottom: 18px;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.5);
}
/* Same footprint as the fields above it: the form's width, the phone field's
   height and corner, so a message does not read as a different form. Selectors
   carry .signin-box because bootstrap is loaded after this file and would
   otherwise win on equal specificity. The border goes so the min-height is the
   height, rather than the height less two pixels. */
.signin-box .toast {
  width: 400px;
  max-width: 100%;
  border: none;
  border-radius: 12px;
  /* Clear of whatever it lands under, which is the Next button once the OTP is
     being typed. The bootstrap mt-3 / mb-3 utilities are off the markup: only
     one of the two carried a top margin, so the error message sat against the
     button, and their !important would beat the height animation below. */
  margin: 16px 0 0 0;
  /* for the collapse: the height is animated from login-util.js, which is also
     where the two events that drive it are explained */
  overflow: hidden;
  transition: max-height 0.18s ease, margin-top 0.18s ease;
}
/* Bootstrap 4's stylesheet is loaded after 5's and its .toast.showing rule pins
   opacity at 1, so neither of 5's own fades ever ran: the message appeared and
   vanished in a single frame. These are animations rather than transitions
   because an animation outranks that rule without needing !important. */
.signin-box .toast.show {
  animation: toast-in 0.2s ease-out both;
}
.signin-box .toast.toast-leaving {
  animation: toast-out 0.16s ease-in both;
}
@keyframes toast-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes toast-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
.signin-box .toast > .d-flex {
  align-items: center;
  min-height: 54px;
}
.signin-box .toast-body {
  padding: 10px 16px;
  flex: 1;
}
/* Close stays on the right, inset from the edge by the same 16px the message
   text is inset on its side, instead of sitting against it. Bootstrap's own icon
   is a near-black SVG, which disappears into the green and reads as a smudge on
   the red, so it takes the filter its .btn-close-white uses. The bootstrap
   spacing utilities are off the button in login.html: they carry !important and
   would pin their own margins over these. */
.signin-box .toast .btn-close {
  margin: 0 16px 0 0;
  filter: invert(1) grayscale(100%) brightness(200%);
  opacity: 0.9;
}

.next-login-btn {
  padding: 0.6rem 1.6rem;
  color: #ffffff;
  background-color: #319795;
  border-radius: 0.4rem;
  border: 2px solid #319795;
  font-weight: 600;
  transition: background-color .2s ease, border-color .2s ease, transform .1s ease;
}

.next-login-btn:hover {
  background-color: #26706e;
  border-color: #26706e;
  color: #ffffff;
}

.next-login-btn:active {
  transform: translateY(1px);
}

.otp-login,
#loginwith-otp,
#loginwith-pass {
  color: #319795 !important;

}

#login-form {
  width: 400px;
  max-width: 100%;
  margin: 0;
}

#phone-n-submit {
  display: flex;
  justify-content: flex-end;
}

.overlay-slider h3 {
  font-size: clamp(2.2rem, 3.4vw, 3.4rem);
  font-family: 'Taviraj', serif;
  font-weight: 500;
  line-height: 1.3;
  margin: 0;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
}

/* Own full-width row inside the .input-group so the resend control never
   toggles beside/below the pins as the countdown text width changes. */
.otp-resend-row {
  flex: 0 0 100%;
  width: 100%;
  display: flex;
  justify-content: center;
  margin-top: 16px;
}

/* Actual pill button (not bare text) so it reads as clickable. */
#otp-n-resend {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  padding: 8px 20px;
  border: 1px solid #319795;
  border-radius: 999px;
  background: transparent;
  color: #319795;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: background-color 0.15s ease, color 0.15s ease;
}
#otp-n-resend:hover {
  background: #319795;
  color: #ffffff;
}

.WA-desktop {
  margin-bottom: 30px;
  display: flex;
  justify-content: center;
  flex-direction: column;
  /* gap: 72px; */
}

.or {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-size: 14px;
  color: #b09475;
  margin: 20px 0;
}
.or::before,
.or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(176, 148, 117, 0.35);
}

.qr-container {
  display: flex;
  justify-content: center;
  flex-direction: column;
  gap: 20px;
  text-align: center;

}

.return {
  display: flex;
  justify-content: center;

}

/* .iti__country-list {
  width: 415px;
  overflow-x: hidden;
} */

/* Country dropdown. Its size, and on mobile its position, are set inline by
   positionCountryDropdown() in login-util.js; these rules only cover the look.
   Selectors carry the body prefix so they outrank intlTelInput.css, which is
   loaded after this file. */
body .iti__country-list {
  white-space: normal;
  overflow-x: hidden;
  /* the plugin's -1px would leave the list a pixel left of the field */
  margin-left: 0;
  /* The page's own cream instead of the plugin's flat white, which read as a
     panel from another site sitting on the warm wash. */
  background-color: #faf4ec;
  /* The scrollbar too: its default track is white and read as a strip down the
     right edge of the list. Firefox takes the pair here, Blink and WebKit take
     it through the pseudo-elements below. */
  scrollbar-width: thin;
  scrollbar-color: rgba(43, 33, 28, 0.35) #faf4ec;
}
body .iti__country-list::-webkit-scrollbar {
  width: 8px;
}
body .iti__country-list::-webkit-scrollbar-track {
  background-color: #faf4ec;
}
body .iti__country-list::-webkit-scrollbar-thumb {
  background-color: rgba(43, 33, 28, 0.35);
  border-radius: 4px;
}
/* The plugin's rgba(0, 0, 0, 0.05) over cream is barely a change, so the row
   under the cursor and the selected one get a deeper shade of the same cream. */
body .iti__country.iti__highlight,
body .iti__country:hover {
  background-color: #f0e3d3;
}
body .iti__divider {
  border-bottom-color: rgba(43, 33, 28, 0.15);
}
/* The list is only as wide as the phone field now, so a long country name would
   either wrap to a second line (uneven rows, and then the five-and-a-half-row
   height stops meaning five and a half countries) or run out of sight. Lay the
   row out as flag / name / dial code and let the name alone truncate, so every
   row is one line and the dial code always stays visible. */
body .iti__country {
  display: flex;
  align-items: center;
}
body .iti__country-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Search box that buildCountrySearch() in login-util.js puts inside the list.
   Sticky, so it stays in place while the countries scroll under it. */
body .iti__search {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 8px;
  background-color: #faf4ec;
  border-bottom: 1px solid rgba(43, 33, 28, 0.15);
}
body .iti__search-input {
  box-sizing: border-box;
  width: 100%;
  height: 38px;
  padding: 6px 10px;
  font-family: inherit;
  /* 16px because anything smaller makes iOS zoom the page in on focus, and the
     dropdown is positioned in script against a viewport that is not zoomed. */
  font-size: 16px;
  color: #2b211c;
  background-color: #ffffff;
  border: 1px solid rgba(176, 148, 117, 0.45);
  border-radius: 8px;
}
body .iti__search-input::placeholder {
  color: rgba(43, 33, 28, 0.45);
}
body .iti__search-input:focus {
  outline: none;
  border-color: #b09475;
  box-shadow: 0 0 0 3px rgba(176, 148, 117, 0.18);
}
body .iti__search-empty {
  padding: 12px 10px;
  font-size: 14px;
  color: rgba(43, 33, 28, 0.6);
}
/* The rows above are display: flex, which outranks the browser's own [hidden]
   rule, so without this the filter would hide nothing. */
body .iti__country[hidden] {
  display: none;
}

body.iti-mobile .iti--container {
  /* Release the two edges the fullscreen rule pins; top and left come from
     the handler. */
  bottom: auto;
  right: auto;
  /* the 1px would make the list narrower than the field */
  padding: 0;
}
body.iti-mobile .iti__country-list {
  border-radius: 12px;
}
/* Android's overlay scrollbar fades out. Keep a permanent gutter so the list
   reads as scrollable. Narrower than the base one because the list itself is
   only as wide as the phone field; its colours come from the base rules. */
body.iti-mobile .iti__country-list::-webkit-scrollbar {
  width: 6px;
}

#go-back {
  width: 50%;
  background-color: black;
  color: white;
  gap: 5px;
  /* kill the green glow inherited from `.WA-desktop button` — go-back is black */
  box-shadow: none;
}

.qr-label p {
  text-align: center;
}

#s-n-phone {
  width: 100%;
  height: 54px;
  margin: 0;
  padding: 10px 16px;
  font-size: 16px;
  color: #2b211c;
  /* semi-transparent white so the field blends into the warm wash */
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(176, 148, 117, 0.45);
  border-radius: 12px;
}
#s-n-phone::placeholder {
  color: #b09475;
}
/* Locked while an OTP is out. The field is readonly rather than disabled, so
   that the browser keeps its value across a back-forward restore, which means
   the greying the user agent used to give the disabled field is drawn here
   instead. It stays locked-looking when tapped, since readonly still takes
   focus. */
#s-n-phone[readonly],
#s-n-phone[readonly]:focus {
  color: #7a6a5d;
  background: rgba(255, 255, 255, 0.35);
  border-color: rgba(176, 148, 117, 0.45);
  box-shadow: none;
}
#s-n-phone:focus {
  outline: none;
  /* The focused field takes the page's own warm accent, the tone the wash and
     the labels are built from, rather than the WhatsApp green, which belongs to
     the button. */
  border-color: #b09475;
  box-shadow: 0 0 0 3px rgba(176, 148, 117, 0.18);
}
/* Chrome paints an opaque pale blue (rgb(232,240,254)) over any value it counts
   as autofilled, which includes pasting from Android's clipboard / phone-number
   suggestion chip. background-color cannot override it, so cover it with an
   inset shadow in the field's own colour. */
#s-n-phone:-webkit-autofill,
#s-n-phone:-webkit-autofill:hover,
#s-n-phone:-webkit-autofill:focus,
#s-n-phone:-webkit-autofill:active {
  -webkit-box-shadow: inset 0 0 0 100px #fdfaf6;
  -webkit-text-fill-color: #2b211c;
  caret-color: #2b211c;
}
/* Firefox: standard :autofill, background image rather than colour. See the
   .pin-code pair above for why this is a block of its own. */
#s-n-phone:autofill,
#s-n-phone:autofill:hover,
#s-n-phone:autofill:focus,
#s-n-phone:autofill:active {
  background-image: none;
  box-shadow: inset 0 0 0 100px #fdfaf6;
  -webkit-text-fill-color: #2b211c;
  caret-color: #2b211c;
}

/* Same autofill blue on the password, pasted or filled by a manager, and the
   same cover: an inset shadow in the field's own colour, with the text colour
   put back through text-fill because both engines force their own. */
#s-pwrd:-webkit-autofill,
#s-pwrd:-webkit-autofill:hover,
#s-pwrd:-webkit-autofill:focus,
#s-pwrd:-webkit-autofill:active,
#l-name:-webkit-autofill,
#l-eml:-webkit-autofill {
  -webkit-box-shadow: inset 0 0 0 100px #fdfaf6;
  -webkit-text-fill-color: #2b211c;
  caret-color: #2b211c;
}
#s-pwrd:autofill,
#s-pwrd:autofill:hover,
#s-pwrd:autofill:focus,
#s-pwrd:autofill:active,
#l-name:autofill,
#l-eml:autofill {
  background-image: none;
  box-shadow: inset 0 0 0 100px #fdfaf6;
  -webkit-text-fill-color: #2b211c;
  caret-color: #2b211c;
}


.phoneInput {
  display: flex;
  width: 100%;
  margin: 0 0 22px 0;
}

.captcha {
  display: flex;
  justify-content: flex-start;
}



.form-control {
  /* padding: 10px!important; */
  font-size: 20px !important;
}

.WA-desktop button {
  width: 100%;
  background-color: #25d366;
  padding: 15px;
  border-radius: 12px;
  font-weight: 600;
  border: none;
  font-size: 16px;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  box-shadow: 0 12px 26px rgba(37, 211, 102, 0.26);
  cursor: pointer;
}

#qrcode {
  display: flex;
  justify-content: center;
}

.WA-btn {
  display: flex;
  justify-content: center;
}

.FC {
  display: flex;
  justify-content: center;
  width: 100%;
  position: relative;
}

#loading-box {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 25px;
}

/* Phone only, the same width split login.js uses to decide the WhatsApp login:
   under 600px it opens the app instead of drawing a QR, so there is nothing on
   screen to scan and "Checking Login Status..." is just noise on a page the user
   has left. Only Go Back stays. A wider screen keeps it, because there the QR is
   on screen and the spinner is what says the page is still waiting.
   !important because validateWhatsappLoginID fades this element in and out, and
   jQuery does that by writing display straight onto the element. */
@media (max-width: 599px) {
  #loading-box {
    display: none !important;
  }
}
.login-nav-logo {
  /* pinned to the top-left corner of the viewport (outside the scaled
     canvas) so it stays in the corner on every screen size */
  position: fixed;
  top: 26px;
  left: 30px;
  padding: 0;
  z-index: 10;
}
.login-nav-logo img {
  height: 56px;
  width: auto;
  /* the brand logo asset is white; recolour it to a soft charcoal so it
     reads on the light wash (the mobile block re-inverts it to white) */
  filter: brightness(0);
  opacity: 0.85;
}
.field-icon {
  position: absolute;
  right: 25px;
  top: 15px;
  z-index: 2;
}

/* ============================================================
   Laptop-only additions: the "Phone Number" field label and
   the staggered photo wall that fills the right column.
   ============================================================ */
.field-label {
  display: block;
  margin: 0 0 8px 2px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2px;
  color: #b09475;
}

/* later steps (email) fill the left-aligned form. #s-pwrd is not here: it takes
   its width from its own rule above, which matches the phone field. */
#l-eml,
.email-row-div .form-control {
  width: 100%;
}

/* Two staggered columns of 7 unique photos each (14 total: 7 landscape + 7
   portrait), with generous warm gutters. Tile heights come from each image's
   real aspect ratio (masonry) + staggered offsets; columns start above and
   end below the wall so first/last photos are clipped mid-frame and read as
   coming in from the screen edges. Height reaches the real viewport (not
   just the 900px canvas) so no cream band shows above/below the grid. */
.photo-wall {
  /* Tile-size multiplier. 1 on the laptop; the landscape media query flips it
     to 1/0.85 so the tiles scale up to match the wall, which is grown to
     1/0.85 there to bleed to the viewport edges. Every tile height / gutter /
     offset below is written as `Npx * var(--pw-k)`, so tuning a base value in
     ONE place keeps the laptop and landscape views in sync automatically. */
  --pw-k: 1;
  /* grow past the 900px canvas to the viewport; undo parent --fit-scale so
     the wall always spans the full visible height */
  height: max(100%, calc(var(--app-height, 100vh) / var(--fit-scale, 1)));
  align-self: center;
  overflow: hidden;
  display: flex;
  gap: 18px;
  /* tight right edge so each column/tile can run wider */
  padding: 0 8px 0 20px;
  box-sizing: border-box;
}
.pw-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Natural content height (the sum of all 14 tiles) so translateY(-50%)
     lands exactly one identical set later. align-self:flex-start stops the
     parent flex row from stretching the column to the track height, which
     would otherwise break that loop math. */
  align-self: flex-start;
  height: auto;
  will-change: transform;
}
/* Infinite vertical drift. Each column renders its tile set TWICE back to
   back (see markup); translateY(-50%) scrolls exactly one set, so the wrap is
   pixel-identical — seamless, and size-independent (no hardcoded pixel
   heights), so it keeps working at every breakpoint. The two columns run
   SAME duration and opposite directions. The two columns carry a height-matched
   image set (see markup), so equal duration = equal pixel speed — the columns
   drift at the same rate, just mirrored up/down. */
.pw-col-a {
  margin-top: calc(-30px * var(--pw-k));
  animation: pw-drift-up 50s linear infinite;
}
.pw-col-b {
  margin-top: calc(-90px * var(--pw-k));
  animation: pw-drift-down 50s linear infinite;
}
/* Hover freezes the hovered column ONLY — applied to the column itself, not
   the parent, so the sibling column keeps moving. */
.pw-col:hover {
  animation-play-state: paused;
}
@keyframes pw-drift-up {
  from { transform: translateY(0); }
  to   { transform: translateY(-50%); }
}
@keyframes pw-drift-down {
  from { transform: translateY(-50%); }
  to   { transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .pw-col-a,
  .pw-col-b {
    animation: none;
  }
  /* The message still opens and closes, it just does it at once. */
  .signin-box .toast {
    transition: none;
  }
  .signin-box .toast.show,
  .signin-box .toast.toast-leaving {
    animation: none;
  }
}
.pw-tile {
  width: 100%;
  overflow: hidden;
  border-radius: 16px;
  /* barely-there lift so photos still sit flat on the shared wash */
  box-shadow: 0 6px 16px rgba(92, 58, 20, 0.07);
  background: #efe2d2;
  flex-shrink: 0;
  /* Spacing lives on the tile (not the column's flex `gap`) so EVERY tile —
     including the last of each set — carries the same bottom margin. That
     keeps the two stacked sets pixel-identical, so the -50% wrap is seamless
     (a flex `gap` omits the gap at the wrap boundary and would jump). */
  margin-bottom: calc(22px * var(--pw-k));
}
.pw-tile img {
  display: block;
  width: 100%;
  height: 100%;
  /* fill the tile without stretching or tiling and keep the subject
     centred — the <img> equivalent of background-size:cover +
     background-repeat:no-repeat + background-position:center */
  object-fit: cover;
  object-position: center;
}
/* Each tile's height is derived from its image's real aspect ratio (width is
   always 100% of the column), so the photo fills the tile edge-to-edge with NO
   crop and NO letterbox — every image is fully visible. Because height is
   width-driven, it scales with the column at every breakpoint (including the
   landscape transform) without a fixed-px --pw-k height multiplier. Set 1 and
   its duplicate share the same class, so both copies match and the -50% loop
   stays seamless. */
.pw-tile--ls-32  { aspect-ratio: 3 / 2; }   /* landscape 4000x2667 */
.pw-tile--ls-169 { aspect-ratio: 16 / 9; }  /* landscape 1280x720  */
.pw-tile--pt-23  { aspect-ratio: 2 / 3; }   /* portrait  2667x4000 */
.pw-tile--pt-45  { aspect-ratio: 4 / 5; }   /* portrait  1080x1350 */

@media (max-width: 1366px) and (orientation: portrait) {
  /* ==========================================================
     Mobile + tablet portrait only: full-bleed photo with a
     frosted-glass bottom-sheet sign-in. Landscape (any device)
     uses the laptop photo-wall UI instead.
     ========================================================== */
  .main-login {
    /* undo the desktop scaled/centred canvas — mobile is a full-bleed hero + sheet */
    position: relative;
    top: auto;
    left: auto;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    transform: none;
    width: auto;
    height: auto;
    padding: 0 16px calc(16px + env(safe-area-inset-bottom));
    /* The photo always fills the screen; the card is anchored to the
       bottom of the visible (dynamic) viewport. dvh only: --app-height is the
       VISUAL viewport, which on Android can be shorter than dvh (it also excludes
       the URL bar), and taking the smaller of the two left the photo short of the
       screen with a strip of page colour under it, the keyboard below that. */
    min-height: 100vh;
    min-height: 100dvh;
  }

  .slider {
    display: block;
  }

  /* The photo is deliberately left exactly as it is everywhere else: unpinned,
     so it bounces with the logo and the form rather than sitting still while they
     slide over it, which is what reads as the content moving inside the page. And
     no taller than the page it sits in, because an absolutely positioned box that
     overflows its container is itself something to scroll, which is the same bug
     from the other end. */

  /* iOS only: stop the page scrolling inside itself without locking it.
     dvh is the viewport with the URL bar in its CURRENT state, and at rest that
     is the tall one, so the document came out taller than what is actually
     visible and a drag scrolled the logo and the form. svh is the SMALL viewport,
     the height with the browser chrome shown, so the document is never taller
     than the visible area and there is nothing to scroll.

     Deliberately not overflow:hidden or position:fixed on html/body: on iOS
     pull-to-refresh IS the document scroller's own overscroll, so locking the
     scroller takes the gesture with it. Leaving the document a normal,
     non-overflowing scroller keeps the gesture and still has nothing to scroll,
     and with nothing to scroll iOS never retracts the URL bar either, so the
     small viewport is what stays on screen. */
  html.overlay-keyboard .main-login {
    min-height: 100svh;
  }

  /* Second net for the same strip: paint the canvas near-black so anything iOS
     opens up past the end of the document reads as more photo instead of a band
     of cream. On the root, not on body, because body carries the cream inline
     and an inline style would win. Setting a root background also stops body's
     cream from propagating to the canvas, which is the point. */
  html.overlay-keyboard {
    background-color: #17171b;
  }

  /* the laptop-only pieces are hidden on mobile */
  .photo-wall {
    display: none;
  }
  .field-label {
    display: none;
  }

  /* Portrait sheet sits over the darkened photo, so the OTP button reads white
     (text + icon inherit) with a translucent white outline. Uses the #otp-reveal
     id so it beats the later, equal-specificity base `.otp-reveal-btn` colour
     rule (a media query adds no specificity, so source order would otherwise
     win). */
  #otp-reveal.otp-reveal-btn {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.5);
  }

  /* Darken the top (logo) and the area behind the card while
     keeping the couple in the middle bright */
  .slider::after {
    background: linear-gradient(
      180deg,
      rgba(0, 0, 0, 0.4) 0%,
      rgba(0, 0, 0, 0) 20%,
      rgba(0, 0, 0, 0) 52%,
      rgba(0, 0, 0, 0.32) 100%
    );
  }

  .signin-box {
    /* Widen by 1/scale so that after the transform below the card's
       *visual* width fills to the normal 16px side margins (otherwise
       scaling down would leave extra empty space left/right). */
    width: calc(100% / var(--card-scale, 1));
    /* No cap: the 1/scale width above makes the visual width equal the parent
       (viewport - 32) on every device, so the sheet spans full width edge to
       edge on phones AND big portrait tablets alike. */
    max-width: none;
    flex-shrink: 0;
    max-height: calc(var(--app-height, 100dvh) - 24px);
    align-items: stretch;
    justify-content: flex-start;
    padding: 18px 20px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 24px;
    /* The panel is designed once, then scaled as a whole to the phone's
       visual viewport (JS sets --card-scale) so it looks identical on
       every device instead of ballooning on short screens. */
    transform: scale(var(--card-scale, 1));
    transform-origin: bottom center;
    /* Neutral WHITE frosted glass — a white frost over a cool neutral
       base, with reduced saturation so the warm sand behind it doesn't
       tint the panel yellow */
    background:
      linear-gradient(rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.10)),
      rgba(36, 36, 42, 0.38);
    -webkit-backdrop-filter: blur(24px) saturate(80%);
    backdrop-filter: blur(24px) saturate(80%);
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.42);
    color: #ffffff;
  }

  /* Keep the card opaque enough to read where blur is unsupported */
  @supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .signin-box {
      background: rgba(36, 36, 42, 0.9);
    }
  }

  .overlay-slider {
    display: none;
  }

  /* Elegant serif heading from the mockup */
  .heading-default {
    display: none;
  }
  .heading-relive {
    display: block;
  }
  /* Drop the fixed-height <br> spacers so the panel scales cleanly;
     spacing is controlled by the fluid margins below */
  .signin-box br {
    display: none;
  }

  .popup-heading {
    font-family: 'Taviraj', serif;
    font-size: 28px;
    font-weight: 500;
    line-height: 1.2;
    color: #ffffff;
    letter-spacing: 0.3px;
    padding: 0 0 12px;
    text-align: center;
    width: 100%;
  }

  #login-form {
    width: 100%;
    max-width: 100%;
    margin: 0 auto;
  }

  /* WhatsApp CTA — same brand green, full width, softer corners */
  .WA-desktop {
    margin-bottom: 12px;
  }
  .WA-desktop button {
    width: 100%;
    background-color: #00cf66;
    padding: 13px;
    border-radius: 14px;
    font-weight: 700;
    border: none;
    font-size: 18px;
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 10px 24px rgba(0, 207, 102, 0.35);
  }

  /* "Or" with flanking rules */
  .or {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    font-size: 15px;
    color: rgba(255, 255, 255, 0.85);
    margin-bottom: 12px;
  }
  .or::before,
  .or::after {
    content: "";
    flex: 1;
    height: 1px;
    background: rgba(255, 255, 255, 0.28);
  }

  /* Phone number — translucent glass pill with flag / dial code */
  .phoneInput {
    width: 100%;
    margin-bottom: 14px;
  }
  /* see the base rule: the appended dropdown is .iti too */
  .iti:not(.iti--container) {
    width: 100% !important;
    border: none;
  }
  #s-n-phone {
    width: 100%;
    height: 52px;
    padding: 10px 14px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.3);
    color: #ffffff;
  }
  #s-n-phone::placeholder {
    color: rgba(255, 255, 255, 0.7);
  }
  #s-n-phone:focus {
    outline: none;
    border-color: rgba(255, 255, 255, 0.6);
    background: rgba(255, 255, 255, 0.18);
  }
  /* Same autofill blue as the base rule, but here the field is translucent glass
     over the photo, so covering it with an opaque colour would flatten it. Two
     mechanisms because the two engines paint it differently, and both are
     harmless where they are not needed:
     - Blink (Android Chrome) ANIMATES the blue in, so a transition long enough
       means it never arrives.
     - WebKit (every iOS browser, Safari and Chrome for iOS alike) paints it at
       once and ignores the transition, but it paints it as the element's
       background, so clipping the background to the text leaves nothing of it to
       see. That clips the glass too, hence the shadow, which repaints the same
       translucent white over the same blurred photo. The field looks unchanged.
     Text colour has to come back through text-fill either way, since both
     engines force their own with !important. */
  #s-n-phone:-webkit-autofill,
  #s-n-phone:-webkit-autofill:hover,
  #s-n-phone:-webkit-autofill:focus,
  #s-n-phone:-webkit-autofill:active {
    transition: background-color 600000s 0s;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.12);
    -webkit-text-fill-color: #ffffff;
    caret-color: #ffffff;
  }
  /* Firefox, which knows only the standard :autofill. Its own block for the
     reason given on the base rule. */
  #s-n-phone:autofill,
  #s-n-phone:autofill:hover,
  #s-n-phone:autofill:focus,
  #s-n-phone:autofill:active {
    background-image: none;
    background-clip: text;
    box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.12);
    -webkit-text-fill-color: #ffffff;
    caret-color: #ffffff;
  }
  .iti__selected-flag {
    border-radius: 14px 0 0 14px;
  }
  .iti__selected-dial-code,
  .iti .iti__selected-flag {
    color: #ffffff;
  }

  .FC {
    display: flex;
    align-items: center;
    flex-direction: row;
    justify-content: center;
  }

  /* Translucent glass inputs for the later steps (name / email /
     password / OTP) so they match the frosted card */
  .signin-box input,
  .signin-box .form-control {
    width: 100%;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.3);
    color: #ffffff;
    border-radius: 12px;
  }
  .signin-box input::placeholder,
  .signin-box .form-control::placeholder {
    color: rgba(255, 255, 255, 0.7);
  }
  .signin-box input:focus,
  .signin-box .form-control:focus {
    outline: none;
    border-color: rgba(255, 255, 255, 0.6);
    background: rgba(255, 255, 255, 0.18);
    color: #ffffff;
  }
  .signin-box .pin-code {
    gap: 10px;
    width: 100%;
    max-width: 340px;
    margin: 0 auto;
  }
  .signin-box .pin-code input {
    /* Fluid equal-width cells so six digits always fit and stay
       centred, whatever the phone width. */
    flex: 1 1 0;
    width: auto;
    min-width: 0;
    height: 54px;
    margin-right: 0;
    padding: 0;
    font-size: 22px;
    font-weight: 600;
    text-align: center;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.45);
    color: #ffffff;
  }
  .signin-box .pin-code input:focus {
    border-color: #7fe9e5;
    background: rgba(255, 255, 255, 0.2);
    outline: none;
  }
  /* Autofill blue on a pasted OTP, handled exactly the way #s-n-phone above is:
     stalled transition for Blink, background clipped to the text for WebKit, and
     the cell's own translucent white repainted with a shadow so the glass
     survives the clip. 0.14 is what these cells carry. */
  .signin-box .pin-code input:-webkit-autofill,
  .signin-box .pin-code input:-webkit-autofill:hover,
  .signin-box .pin-code input:-webkit-autofill:focus,
  .signin-box .pin-code input:-webkit-autofill:active {
    transition: background-color 600000s 0s;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.14);
    -webkit-text-fill-color: #ffffff;
    caret-color: #ffffff;
  }
  /* Firefox, standard :autofill. Own block, same reason as the base rule. */
  .signin-box .pin-code input:autofill,
  .signin-box .pin-code input:autofill:hover,
  .signin-box .pin-code input:autofill:focus,
  .signin-box .pin-code input:autofill:active {
    background-image: none;
    background-clip: text;
    box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.14);
    -webkit-text-fill-color: #ffffff;
    caret-color: #ffffff;
  }
  /* The OTP block is an .input-group with no top spacing of its own, so
     it rode up under the field above (email/phone). Give it the same
     rhythm as the other fields and kill any inherited gap collapse. */
  .signin-box .otp-row-div {
    margin-top: 16px;
    margin-bottom: 20px;
  }
  .signin-box .otp-row-div .input-group {
    margin: 0;
  }
  /* The phone field's box at this breakpoint, so every step reads as the same
     field: same height, padding, corner, glass and border. */
  #l-name,
  #l-eml,
  #s-pwrd,
  .email-row-div .form-control {
    width: 100%;
    height: 52px;
    padding: 10px 14px;
    font-size: 16px;
    border-radius: 14px;
    color: #ffffff;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.3);
  }
  #l-name::placeholder,
  #l-eml::placeholder,
  #s-pwrd::placeholder {
    color: rgba(255, 255, 255, 0.7);
  }
  #l-name:focus,
  #l-eml:focus,
  #s-pwrd:focus {
    outline: none;
    border-color: rgba(255, 255, 255, 0.6);
    background: rgba(255, 255, 255, 0.18);
    box-shadow: none;
  }
  /* Glass over the photo here, so the same treatment #s-n-phone gets: stall the
     transition for Blink, clip the background to the text for WebKit, and put the
     glass back with a shadow in the field's own translucent white. */
  #s-pwrd:-webkit-autofill,
  #s-pwrd:-webkit-autofill:hover,
  #s-pwrd:-webkit-autofill:focus,
  #s-pwrd:-webkit-autofill:active,
  #l-name:-webkit-autofill,
  #l-eml:-webkit-autofill {
    transition: background-color 600000s 0s;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.12);
    -webkit-text-fill-color: #ffffff;
    caret-color: #ffffff;
  }
  #s-pwrd:autofill,
  #s-pwrd:autofill:hover,
  #s-pwrd:autofill:focus,
  #s-pwrd:autofill:active,
  #l-name:autofill,
  #l-eml:autofill {
    background-image: none;
    background-clip: text;
    box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.12);
    -webkit-text-fill-color: #ffffff;
    caret-color: #ffffff;
  }

  .field-icon {
    color: rgba(255, 255, 255, 0.85);
  }

  #chNum {
    cursor: pointer;
    position: absolute;
    right: 14px;
    top: 0;
    bottom: 0;
    align-items: center;
    display: flex;
    z-index: 1;
    color: rgba(255, 255, 255, 0.85);
  }

  /* Secondary links / helper text, readable on the dark card */
  .otp-login,
  #loginwith-otp,
  #loginwith-pass {
    color: #7fe9e5 !important;
  }
  #otp-n-resend {
    color: #7fe9e5;
    border-color: #7fe9e5;
  }
  #otp-n-resend:hover {
    background: #7fe9e5;
    color: #1f2430;
  }
  .qr-label p,
  #loading-box {
    color: #ffffff;
  }

  .captcha {
    display: flex;
    justify-content: center;
    margin-top: 6px;
  }

  /* Restore a small gap before the submit button (the <br> is hidden) */
  #phone-n-submit {
    margin-top: 12px;
  }

  .next-login-btn {
    border-radius: 12px;
  }

  #go-back {
    width: 80%;
    background-color: rgba(0, 0, 0, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 10px;
    color: white;
    gap: 5px;
  }

  /* the sheet's own field corner and height, see the base rule */
  .signin-box .toast {
    width: 100%;
    max-width: 100%;
    border-radius: 14px;
  }
  .signin-box .toast > .d-flex {
    min-height: 52px;
  }

  .login-nav-logo {
    position: absolute;
    top: 14px;
    left: 8px;
    padding: 10px;
    z-index: 3;
  }
  .login-nav-logo img {
    width: 72px;
    height: auto;
    filter: brightness(0) invert(1) drop-shadow(0 2px 8px rgba(0, 0, 0, 0.45));
  }

  .row > * {
    margin-right: 0 !important;
    margin-left: 0 !important;
  }
}

/* ============================================================
   LANDSCAPE on any non-laptop device — phones, iPads, Surface, and
   smart displays (Nest Hub / Nest Hub Max) rotated to landscape.

   These all show the laptop composition, but the base --fit-scale is
   min(w/1620, h/900): on a squarish tablet (iPad ~1.33, Surface Pro
   ~1.5) that's WIDTH-driven, so the whole composition shrinks to fit
   the width and the form ends up small with big vertical cream bands.
   To stay consistent across every aspect ratio we instead drive the
   framing off HEIGHT (--ls-scale = 0.85 * h/900, set in login.html)
   and size the canvas to the viewport's OWN aspect ratio
   (--ls-canvas-width = 900 * w/h). The scaled canvas then always
   renders to ~85% of BOTH the viewport width and height — a uniform
   ~7.5% margin on any device — with the form a consistent size and
   the photo wall bleeding to the top/bottom edges.

   For wide (height-driven) phones --ls-scale equals the old
   fit*0.85 and --ls-canvas-width equals the old app-width/fit-scale,
   so the phones are UNCHANGED; only the squarish tablets change.

   Scoped to max-width:1400px so it covers every phone/tablet/display
   (incl. the Surface Pro 7 at 1368px) while true laptops/desktops
   (>=1441px standard resolutions) keep their untouched base UI.
   ============================================================ */
@media (orientation: landscape) and (max-width: 1400px) {
  /* Pin the body (the absolute .main-login's offset parent) to the REAL
     visible height. The shared laptop block sets min-height:100vh, but on a
     phone 100vh counts the area behind the URL bar, so it is taller than
     --app-height (visualViewport) that the scale is derived from. That
     mismatch made top:50% centering drop the composition down and leave a
     cream band at the top on real devices (devtools has no URL bar, so it
     looked fine). Using --app-height here makes the centering box match the
     scaled canvas exactly — no band. */
  body {
    min-height: var(--app-height, 100vh);
    height: var(--app-height, 100vh);
  }
  .main-login {
    /* canvas matches the viewport's aspect ratio (900 * w/h), scaled
       off height, so it frames with a uniform ~7.5% margin */
    width: var(--ls-canvas-width, 1620px);
    /* Fill the FULL viewport height so there is no empty framing band at the
       top/bottom (the base 900px canvas, once scaled by --ls-scale, is shorter
       than the screen and would leave a cream strip up top). height /
       --ls-scale means the post-scale height equals the real viewport height,
       so the composition bleeds top-to-bottom; the ~7.5% side margins remain
       because the width is still the aspect-matched --ls-canvas-width. */
    height: calc(var(--app-height, 100vh) / var(--ls-scale, 1));
    /* share the width the laptop's way (700/1620 ~= 43% form, rest
       photo wall) so the form gets its fair share, not just the wall */
    grid-template-columns: 43% 1fr;
    transform: translate(-50%, -50%) scale(var(--ls-scale, 1));
  }
  /* Scale the form content to the laptop's share of the canvas
     (400/1620 ~= 0.247) so it grows on wider screens, but never below
     400px so the fixed-size reCAPTCHA (~304px) always fits, and cap it
     so it can't get unwieldy on very wide screens. */
  #login-form {
    width: clamp(400px, calc(var(--ls-canvas-width, 1620px) * 0.247), 560px);
    max-width: 100%;
  }
  /* Keep the photo wall FULL-BLEED vertically (off the top & bottom
     edges) like the laptop, rather than framed with the rest of the
     composition: grow it so that after --ls-scale it fills the real
     viewport height. (app-height / ls-scale is a constant ~1059px.) */
  .photo-wall {
    height: max(100%, calc(var(--app-height, 100vh) / var(--ls-scale, 1)));
    /* The wall above is grown to 1/0.85 of the 900px canvas so it bleeds to
       the real viewport edges (undoing the 0.85 framing the rest of the
       composition gets). Bumping --pw-k to the same 1/0.85 scales every tile
       height / gutter / offset up to match, so the wall crops EXACTLY like the
       laptop canvas — and it tracks any base-height edit automatically, since
       the tiles all read `Npx * var(--pw-k)`. */
    --pw-k: calc(1 / 0.85);
  }
  .login-nav-logo {
    top: 18px;
    left: 20px;
    /* shrink the fixed logo by the same factor as the canvas so it
       stays proportional to the composition */
    transform: scale(var(--ls-scale, 1));
    transform-origin: top left;
  }
}

/* ============================================================
   "Login with OTP" secondary button + accordion reveal.
   Resting screen shows the ghost button in place of the phone
   field + reCAPTCHA; tapping it slides/fades them open (~0.3s).
   ============================================================ */
.otp-reveal-btn {
  width: 100%;
  padding: 15px;
  margin-top: 4px;
  background: transparent;
  border: 1px solid rgba(176, 148, 117, 0.55);
  border-radius: 12px;
  font-size: 16px;
  font-weight: 600;
  color: #2b211c;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.otp-reveal-btn:hover {
  background: rgba(176, 148, 117, 0.08);
  border-color: #b09475;
}

.otp-accordion {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.3s ease, opacity 0.3s ease;
}
.otp-accordion.open {
  max-height: 400px;
  opacity: 1;
}
/* Where the keyboard overlays the page, the reveal must not still be changing
   the layout after the field is focused: WebKit picks its scroll position at
   that instant and never revisits it, and the focus cannot be postponed because
   iOS only raises the keyboard for a focus inside the tap itself. So the height
   is taken at once and only the fade is animated. Everywhere else the slide
   stays exactly as it was. */
html.overlay-keyboard .otp-accordion {
  transition: opacity 0.3s ease;
}
