/* ============================================================
   VIREVO — SIGN IN
   ------------------------------------------------------------
   Standalone: this page deliberately does not load style.css or
   products.css. Those two carry the whole marketing site — the
   scroll engine's variables, the pinned-section machinery, the
   canvas grid — and none of it applies to a single centred card.
   Pulling 380KB of stylesheet in to draw one form would also make
   the page inherit rules nobody here is thinking about.
   ============================================================ */

/* Bebas Neue is self-hosted for the whole site. Because this page does not
   load style.css, the face has to be declared here too — same URL and same
   ?v=1, so the browser reuses the file it already has rather than fetching
   a second copy. The 100-900 range means a request for 700 is synthesised
   from this single weight instead of falling through to the next family. */
@font-face{
  font-family:'Bebas Neue';
  src:url("../../fonts/BebasNeue-Regular.ttf?v=1") format("truetype");
  font-weight:100 900;
  font-style:normal;
  font-display:swap;
}

:root{
  --lg-bg:#080b09;
  --lg-card:#161a17;
  --lg-line:rgba(255,255,255,.07);
  --lg-ink:#f4f2ec;
  --lg-dim:rgba(244,242,236,.52);
  --lg-faint:rgba(244,242,236,.34);
  --lg-green:#1f5c33;
  --lg-green-hi:#2c7a44;
  --lg-gold:#c9a45f;
}

*{box-sizing:border-box;}
html,body{height:100%;}
/* A BACKDROP WITH SOMETHING IN IT, BECAUSE THE CARD IS GLASS NOW.
   backdrop-filter blurs whatever is behind it, so over a near-flat black
   it has nothing to work with and the panel just reads as slightly
   lighter black — the effect is invisible and the cost is real. These
   pools are the material the blur bends: wide, soft, well clear of each
   other, and placed so the diagonal between the two chamfered corners
   crosses both. Deliberately still the site's green and gold rather than
   the reference's orange — the shape is what was being matched, not the
   palette. */
body.lg-page{
  margin:0;
  font-family:'Poppins',system-ui,-apple-system,sans-serif;
  color:var(--lg-ink);
  background:var(--lg-bg);
  background-image:
    radial-gradient(1000px 700px at 18% 12%,  rgba(44,122,68,.30),  transparent 62%),
    radial-gradient(900px 620px at 84% 22%,   rgba(201,164,95,.16), transparent 64%),
    radial-gradient(1200px 780px at 72% 92%,  rgba(44,122,68,.22),  transparent 66%),
    radial-gradient(760px 560px at 8% 88%,    rgba(201,164,95,.10), transparent 68%);
  background-attachment:fixed;
  -webkit-font-smoothing:antialiased;
}

.lg-wrap{
  min-height:100%;
  display:flex;align-items:center;justify-content:center;
  padding:clamp(20px,5vh,64px) clamp(16px,5vw,40px);
}

/* ============ THE GLASS PANEL ============
   Two corners are CUT, two are ROUNDED — top-left and bottom-right take a
   diagonal chamfer, top-right and bottom-left stay round. That mix cannot
   be expressed with border-radius, so the whole silhouette is one
   clip-path polygon.

   clip-path has no notion of a rounded vertex, so each round corner is a
   four-point approximation of a quarter circle (samples at 0/30/60/90
   degrees, which is why the .134 and .5 factors appear). --c and --r are
   the only two numbers to touch; the shape rebuilds itself from them, so
   the narrow-screen override further down only has to restate those.

   THE BORDER IS A LAYER, NOT A `border`.
   A real border follows the padding box and would keep drawing square
   corners underneath the clip, so the 1px edge is drawn as a shape of its
   own: ::before fills the full silhouette in the line colour, ::after
   covers it from 1px inward with the glass fill, and what stays visible
   between them is a 1px rule that traces the chamfers exactly.

   backdrop-filter stays on .lg-card itself rather than on either
   pseudo-element. It has to sit on the element that owns the clip-path,
   or the blur spills past the cut corners — and it must never sit under a
   `filter`, which is why the open animation below moves and fades the
   card but deliberately does not blur it: any filter, even blur(0),
   makes the element a backdrop root and kills the glass for good. */
.lg-card{
  --c:clamp(26px,7vw,40px);   /* the diagonal cut: top-left, bottom-right */
  --r:16px;                   /* the round corners: top-right, bottom-left */
  --shape:polygon(
    var(--c) 0,
    calc(100% - var(--r)) 0,
    calc(100% - var(--r) * .5) calc(var(--r) * .134),
    calc(100% - var(--r) * .134) calc(var(--r) * .5),
    100% var(--r),
    100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%,
    var(--r) 100%,
    calc(var(--r) * .5) calc(100% - var(--r) * .134),
    calc(var(--r) * .134) calc(100% - var(--r) * .5),
    0 calc(100% - var(--r)),
    0 var(--c)
  );
  position:relative;
  width:100%;max-width:572px;
  padding:clamp(30px,5vw,56px) clamp(22px,5vw,60px) clamp(28px,4.5vw,48px);
  text-align:center;
  clip-path:var(--shape);
  -webkit-backdrop-filter:blur(26px) saturate(140%);
  backdrop-filter:blur(26px) saturate(140%);
  box-shadow:0 40px 90px rgba(0,0,0,.55);
}
/* the 1px edge — see the note above on why this is a layer */
.lg-card::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  clip-path:var(--shape);
  /* Brightest exactly where the two chamfers are. A flat line colour makes
     the cuts disappear against the page; catching the light along that
     one diagonal is what reads as a bevelled edge rather than a notch. */
  background:linear-gradient(135deg,
    rgba(255,255,255,.38) 0%,
    rgba(255,255,255,.08) 26%,
    rgba(255,255,255,.06) 74%,
    rgba(255,255,255,.32) 100%);
}
/* the glass fill, held 1px inside so the layer above shows as an edge */
.lg-card::after{
  content:"";position:absolute;inset:1px;z-index:0;pointer-events:none;
  clip-path:var(--shape);
  background:linear-gradient(160deg,
    rgba(32,40,35,.62) 0%,
    rgba(14,19,16,.72) 100%);
}
/* the form itself rides above both layers */
.lg-card > *{position:relative;z-index:1;}

/* ---- the open ----
   macOS launches a window by scaling it up from slightly small, letting it
   run a little past full size, then settling back. That overshoot is the
   whole character of the move, and it lives in the easing curve rather
   than in keyframes: the third control point of cubic-bezier sits above 1,
   so the curve genuinely passes its target and eases back down. Keyframed
   overshoot would need its own deceleration written by hand at every stop
   and would fight whatever easing was applied on top.

   Both properties ride the same curve on purpose. Opacity clamps at 1 the
   moment the curve crosses it, so the card is fully solid slightly before
   it finishes settling — which is exactly how a native window reads: it is
   *there*, and the last of the motion is just the frame coming to rest.

   The card also lifts 12px as it grows. Pure scale from centre reads as a
   flat zoom; the small rise gives it somewhere to arrive from.

   No blur here, deliberately — see the backdrop-filter note above. */
/* THE FADE AND THE GROWTH ARE TWO ANIMATIONS, AND THAT IS THE WHOLE TRICK.
   Run as one, this did not read as a launch at all. An ease-out-back curve
   is heavily front-loaded, so with opacity riding the same curve the card
   was already at 95% of full size by the time it was even half visible —
   measured, not assumed. Every bit of the growth happened while it was
   still transparent, and what was left to actually watch was a fade.

   So opacity gets its own much shorter animation. The card goes solid at
   ~160ms, while the scale animation is only a fifth of the way through its
   travel, which means the visitor sees it genuinely small and then watches
   it grow, overshoot and settle. That sequence — small, solid, then out —
   is what macOS actually does when an app opens.

   .70 rather than the .9 this started on, for the same reason: "scales up
   from a small origin point" needs a real size delta or the motion has
   nothing to show. */
/* ============ THE GENIE ============
   A scale animation cannot do this, and no amount of tuning was going to
   get it there. transform:scale is an AFFINE map — it takes straight lines
   to straight lines. A genie is a CURVED deformation: the sheet is pinched
   to a neck at the bottom and fans out as it rises, so its sides bow. That
   is a different class of transform and CSS has no property for it.

   What CSS does have is enough transforms to build a mesh out of. The card
   is cloned into N horizontal strips (see runGenie() in login.js), each
   clipped to its own band and given its own translateY and scaleX. Each
   strip is still affine on its own, but because the parameters vary
   smoothly from strip to strip the STACK is piecewise-curved — the same
   way a curve is drawn as many short straight segments. Twenty strips is
   enough that the bowed edge reads as smooth rather than stepped.

   These rules only dress the clones; the motion is all in the script. */
@keyframes lgOpenFade{
  from{opacity:0;}
  to  {opacity:1;}
}

/* HELD UNTIL THE PAGE IS ACTUALLY READY.
   .lg-js is set by an inline script in the head (so it applies before
   first paint, with no flash of an un-held card) and .lg-ready is added on
   window load. Both come from that same inline script rather than from
   login.js: if login.js ever failed to load, a card held at opacity 0 with
   nothing left to release it would be an unusable page. And .lg-js gating
   the held state means no-JS visitors simply get the card, un-animated,
   instead of a permanently invisible one. */
.lg-js .lg-card{opacity:0;}
/* THE FALLBACK PATH ONLY — a plain fade, used when the genie is not
   running (script missing, or it bailed out). The genie rules below
   outrank this whenever it is armed. */
.lg-js.lg-ready .lg-card{
  animation:lgOpenFade .32s cubic-bezier(.22,1,.36,1) both;
}

/* `html` is on these selectors for specificity, not decoration: the
   fallback rule above scores 0,3,0 and so would a bare `.lg-js.lg-armed`,
   which would leave the two settling it by source order — fragile. The
   element selector makes the genie rules 0,3,1 and 0,4,1 so they win
   wherever they sit in the file. */
html.lg-js.lg-genie-armed .lg-card{opacity:0;animation:none;}
html.lg-js.lg-genie-armed.lg-genie-done .lg-card{opacity:1;animation:none;}

/* THE STRIPS MUST OUT-SPECIFY THE HOLD, AND FORGETTING THAT MADE THE
   WHOLE EFFECT INVISIBLE.
   The hold directly above is `html.lg-js.lg-genie-armed .lg-card` — 0,3,1 —
   and it matches the CLONES as well as the real card, because every strip
   is itself a .lg-card. The strip block below scores only 0,2,0, so its
   `opacity:1` lost and all twenty strips were painted at opacity 0. The
   genie ran, correctly, for its full 640ms, and could not be seen; the
   only thing the visitor ever saw was the finished card popping in when
   .lg-genie-done landed. It reads exactly like "the animation is broken"
   when in fact only its visibility was.
   This rule carries the same html-prefix the hold does — 0,4,1 — so the
   strips win wherever either rule sits in the file. */
html.lg-js.lg-genie-armed .lg-genie .lg-card{opacity:1;}

/* the strip stack, pinned over wherever the real card is */
.lg-genie{position:fixed;z-index:50;pointer-events:none;}
.lg-genie .lg-card{
  position:absolute;inset:0;margin:0;
  width:100%;height:100%;max-width:none;
  opacity:1;animation:none;
  transform-origin:50% 50%;   /* scaleX pinches toward the card's centre line */
  will-change:transform;
  box-shadow:none;
  /* A blur cannot survive being sliced twenty ways and warped — each strip
     would sample its own backdrop at its own offset and the glass would
     break into bands. The strips carry a flat stand-in instead, matched to
     what the blurred panel resolves to over this backdrop, and the real
     card (with its real blur) is swapped back in the moment the motion
     ends. */
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
.lg-genie .lg-card::after{
  background:linear-gradient(160deg,rgba(28,35,30,.95),rgba(12,17,14,.97));
}

/* ---- the lockup ---- */
.lg-logo{margin-bottom:clamp(22px,4vh,36px);}
.lg-lockup{
  display:block;margin:0 auto;
  /* sized against the card, not the viewport: the card is now capped well
     below its old width, so a vw-based size would keep growing past it */
  width:min(100%, 300px);height:auto;
}
/* .lg-tag removed: the tagline lives inside the lockup artwork. */

/* ---- headings ---- */
.lg-title{
  margin:0;
  /* Bebas is condensed all-caps: its cap height fills far less of the em box
     than a serif's, so the same visual size needs a larger font-size and a
     touch of tracking to stop the caps crowding. */
  font-family:'Bebas Neue',var(--font-display,sans-serif);
  font-size:clamp(40px,8vw,56px);line-height:1;font-weight:400;
  letter-spacing:.03em;
}
.lg-sub{
  margin:10px 0 clamp(24px,4vh,34px);
  font-size:clamp(13px,2.2vw,16px);color:var(--lg-dim);
}

/* ---- the form ---- */
.lg-form{text-align:left;}
.lg-label{
  display:block;margin-bottom:10px;
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  font-weight:600;color:var(--lg-faint);
}
.lg-field{position:relative;display:flex;align-items:center;}
.lg-ico{
  position:absolute;left:18px;width:19px;height:19px;
  fill:none;stroke:var(--lg-faint);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;pointer-events:none;
}
.lg-input{
  width:100%;
  padding:17px 18px 17px 52px;
  border-radius:11px;
  border:1px solid var(--lg-line);
  background:rgba(0,0,0,.28);
  color:var(--lg-ink);
  font:inherit;font-size:clamp(13px,2.2vw,15px);
  outline:none;
  transition:border-color .18s ease, box-shadow .18s ease;
}
.lg-input::placeholder{color:rgba(244,242,236,.28);}
.lg-input:focus-visible{
  border-color:rgba(44,122,68,.75);
  box-shadow:0 0 0 3px rgba(44,122,68,.18);
}
.lg-input[aria-invalid="true"]{border-color:rgba(214,106,86,.8);}

.lg-err{
  margin:10px 0 0;font-size:12.5px;color:#e08b76;
}
.lg-err[hidden]{display:none;}

/* ---- step 2: the one-time code ---- */
.lg-step2[hidden]{display:none;}

/* A grid of six equal fractions rather than fixed-width boxes: at 320px the
   card has ~244px of content width, and fixed boxes plus gaps overflow it.
   1fr columns simply get narrower instead. */
.lg-otp{
  display:grid;
  grid-template-columns:repeat(6,1fr);
  gap:clamp(6px,2vw,11px);
}
.lg-otp input{
  width:100%;min-width:0;
  padding:15px 0;
  text-align:center;
  border-radius:11px;
  border:1px solid var(--lg-line);
  background:rgba(0,0,0,.28);
  color:var(--lg-ink);
  font-family:var(--font-mono,'Poppins',sans-serif);font-weight:600;
  font-size:clamp(17px,3.4vw,21px);font-weight:500;
  outline:none;
  transition:border-color .18s ease, box-shadow .18s ease;
  -moz-appearance:textfield;
}
.lg-otp input::-webkit-outer-spin-button,
.lg-otp input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.lg-otp input:focus-visible{
  border-color:rgba(44,122,68,.85);
  box-shadow:0 0 0 3px rgba(44,122,68,.18);
}
.lg-otp.is-bad input{border-color:rgba(214,106,86,.8);}

/* "OTP has been sent to your mail Id", sitting directly above Resend. */
.lg-sent{
  margin:clamp(18px,3vh,24px) 0 0;
  text-align:center;
  font-size:clamp(12.5px,2.1vw,13.5px);
  color:var(--lg-dim);
}
.lg-resend{margin:6px 0 0;text-align:center;}
.lg-back{margin:14px 0 0;text-align:center;}

/* A button, not an <a href="#">: these do something on the page rather than
   go somewhere, so they get button semantics and keyboard behaviour for free
   while being styled as links. */
.lg-link{
  appearance:none;background:none;border:0;
  font:inherit;font-size:inherit;font-weight:600;
  color:var(--lg-gold);cursor:pointer;
  display:inline-block;padding:6px 4px;margin:-6px -4px;
  border-radius:4px;
}
.lg-link:hover:not(:disabled){text-decoration:underline;}
.lg-link:focus-visible{outline:2px solid var(--lg-gold);outline-offset:2px;}
.lg-link:disabled{color:var(--lg-faint);cursor:default;font-weight:400;}
.lg-link-dim{color:var(--lg-dim);font-weight:400;font-size:12.5px;}
.lg-link-dim:focus-visible{outline-color:var(--lg-dim);}

.lg-btn{
  width:100%;margin-top:clamp(18px,3vh,26px);
  padding:17px 24px;border:0;border-radius:11px;
  background:linear-gradient(180deg,var(--lg-green-hi),var(--lg-green));
  color:#fff;font:inherit;font-size:clamp(14px,2.3vw,16px);font-weight:600;
  cursor:pointer;
  transition:filter .18s ease, transform .18s ease;
}
.lg-btn:hover{filter:brightness(1.08);}
.lg-btn:active{transform:translateY(1px);}
.lg-btn:focus-visible{outline:2px solid var(--lg-gold);outline-offset:3px;}

.lg-note{
  margin:16px 0 0;font-size:13px;line-height:1.55;
  color:var(--lg-dim);text-align:left;
}
.lg-note[hidden]{display:none;}

/* ---- divider ---- */
/* [hidden] has to be spelled out: display:flex below is an author rule, and
   at equal specificity author beats the user-agent stylesheet that would
   otherwise turn the "hidden" attribute into display:none. Without this,
   #lgOr stayed a visible flex row across the step1/step2 swap regardless of
   its hidden property — just not one anybody happened to scroll to. */
.lg-or[hidden]{display:none;}
.lg-or{
  display:flex;align-items:center;gap:16px;
  margin:clamp(22px,4vh,30px) 0;
  color:var(--lg-faint);
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;
}
.lg-or::before,.lg-or::after{
  content:"";flex:1 1 auto;height:1px;background:var(--lg-line);
}

/* ---- sign-up panel: social buttons + email ---- */
.lg-signup[hidden]{display:none;}

/* White, not the card's own dark surface: Google and Apple both specify the
   mark on a light ground, and a dark "Continue with Google" button is the
   one part of this page that would not pass as their button at all. */
.lg-oauth{
  width:100%;display:flex;align-items:center;justify-content:center;gap:10px;
  padding:15px 20px;border-radius:11px;
  border:1px solid rgba(0,0,0,.06);
  background:#f5f4f0;color:#1c1f1a;
  font:inherit;font-size:clamp(13.5px,2.2vw,15px);font-weight:600;
  cursor:pointer;
  transition:filter .18s ease, transform .18s ease;
}
.lg-oauth + .lg-oauth{margin-top:12px;}
.lg-oauth:hover{filter:brightness(.97);}
.lg-oauth:active{transform:translateY(1px);}
.lg-oauth:focus-visible{outline:2px solid var(--lg-gold);outline-offset:3px;}
.lg-oauth-ic{width:20px;height:20px;flex:0 0 auto;}

.lg-signup .lg-or{margin:clamp(20px,3.4vh,26px) 0;}
.lg-signup .lg-back{margin-top:clamp(16px,2.6vh,22px);}

.lg-alt{margin:0;font-size:clamp(12.5px,2.1vw,14.5px);color:var(--lg-dim);}
.lg-alt a{
  color:var(--lg-gold);font-weight:600;text-decoration:none;
  /* the link's own line box is ~17px tall, under the 24px minimum for a
     pointer target (WCAG 2.5.8). Padding makes it hittable without moving
     the baseline; the negative margin keeps the sentence's spacing intact. */
  display:inline-block;padding:6px 4px;margin:-6px -4px;
}
.lg-alt a:hover{text-decoration:underline;}
.lg-alt a:focus-visible{outline:2px solid var(--lg-gold);outline-offset:2px;border-radius:4px;}

/* Desktop only: 15% off the card, 572 -> 486px. Scoped to the site's own
   >=981px breakpoint rather than just lowering max-width, because the card is
   width:100% below ~610px — narrowing the cap there would do nothing, but
   keeping the change inside the query means mobile provably cannot be
   touched by it. */
@media (min-width:981px){
  .lg-card{max-width:437px;}   /* 572 -> 486 -> 437: 15%, then 10% more */
}

/* iOS Safari zooms the whole page when a focused input is under 16px, which
   throws the centred card off-screen mid-typing. 16px is the floor, not a
   design choice. */
@media (max-width:980px){
  .lg-input{font-size:16px;}
  .lg-otp input{font-size:16px;}
}

@media (prefers-reduced-motion:reduce){
  .lg-btn{transition:none;}
  /* The card still has to ARRIVE, and here that is a specificity problem
     rather than a motion one. The hold and the spring are gated on
     `.lg-js` / `.lg-js.lg-ready`, which score 0,2,0 and 0,3,0; a bare
     `.lg-card` is 0,1,0 and a media query adds nothing. So the plain
     selector this used to carry lost to `.lg-js .lg-card{opacity:0}` and
     pinned the card invisible FOREVER for exactly the people who cannot
     see an animation bring it back. The selectors below match the gated
     ones so they can actually win. */
  .lg-card,
  .lg-js .lg-card,
  .lg-js.lg-ready .lg-card{animation:none;opacity:1;transform:none;}
}
