/* ==========================================================================
   Orcheum · Authentication Layout (split: form pane + hero pane)
   Source of truth: Figma node 404:4919 ("Sign up").
   Contains: split shell, logo, glass backdrop + glow, hero canvas + prompt.
   Reusable — namespaced under .oc-auth / .oc-logo / .oc-hero.
   ========================================================================== */

/* ---- Split shell — Figma 540:1599 ------------------------------------- */
.oc-auth {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  /* The page warms downward into peach — the light the hero's card is cut out
     of, so the two halves read as one surface rather than a form beside a
     picture.

     These stops are the WORKSPACE's (workspace-shell.css), not this frame's.
     Figma 540:1599 still says 0%/100%, but 576:1781 moved its end stop to
     186.31% — almost a full frame below the fold — so the workspace only
     travels about half way to #ffe2ca. Matching the old full-strength ramp
     here put a visible step in warmth on the sign-up → workspace hop, and the
     softer bottom also treats these fields better: their fill is only
     rgba(218,217,215,0.2), which goes muddy over saturated peach. Deliberate
     divergence from this node — keep the two pages in step. */
  background: linear-gradient(180deg, #fbf7ef 11.71%, #ffe2ca 186.31%);
  overflow: hidden;

  /* This frame runs a warmer, darker ink than the app shell: foreground
     #1b1818 and text/secondary #4a4242 in Figma 540:1599's variable scope,
     against the shell's #24252d / #7c746f. Scoped here so the title, field
     labels, checkbox copy, divider and footer all take it at once without
     moving the global tokens under every other page. */
  --color-foreground: #1b1818;
  --color-text-secondary: #4a4242;
}

/* Buttons on this page are 6px — Figma 540:1615 / 540:1621 / 540:1622 — where
   the shared control is 8px. Scoped rather than changed in button.css, which
   dresses the landing page and the workspace too. */
.oc-auth .oc-btn { border-radius: 6px; }

/* ---- Form pane (left) — Figma 404:4929 body -------------------------- */
.oc-auth__form-pane {
  position: relative;
  /* 50/50 split — Figma 538:2444 (756px each at 1512). Basis must be 50%, not 0:
     with a 0 basis the hero's horizontal padding is added on top of the evenly
     distributed free space, widening the hero and shrinking this pane. */
  flex: 1 1 50%;
  box-sizing: border-box;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow-x: hidden;
  overflow-y: auto;
}

/* The Spectre glow that used to wash the form pane is gone. It was node
   540:1600 in the previous cut of this frame; in the current one 540:1599 has
   exactly two children — the body and the hero — and no glow behind the form.

   Its removal is also what the gradient requires. The asset baked the flat
   cream page colour into its own pixels, which is what let it composite
   seamlessly before; against a gradient that cream stops matching below the
   top edge, and the export's 672x517 box appears as a bright rectangle across
   the middle of the pane. One warm light, and it now comes from the page. */

.oc-auth__body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);            /* 24px */
  width: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  /* Figma centres the column outright: 610 tall in a 900 pane, 145 of clear
     air above and below. The old 120px top padding was clearing the pinned
     logo, but on a full-height viewport it pushed the whole composition 33px
     down. Symmetric padding restores the centring; the logo (51 → 93) still
     has 52px of slack under it at the design height. */
  padding: 48px var(--space-6);
}

/* Only when the viewport is too short to hold the column does the logo become
   a collision risk — the pane scrolls, and the card would start above the
   wordmark's baseline. Below that height, clear it explicitly instead. */
@media (max-height: 780px) {
  .oc-auth__body { padding-top: 104px; }
}

/* ---- Logo — Figma 538:2547 "Combined Logo" -------------------------- */
.oc-logo {
  display: inline-flex;
  align-items: center;
  gap: 4.934px;
  padding: 6.167px 9.867px;
  color: var(--color-foreground);
}

/* Logo pinned to the top-center of the form pane — Figma 538:2547 (top 51px). */
.oc-auth__logo {
  position: absolute;
  top: 51px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
}
.oc-logo__mark {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: block;
}
.oc-logo__mark img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.oc-logo__word {
  font-family: var(--font-serif);
  font-weight: var(--font-weight-normal);
  font-size: 24.669px;
  line-height: 1.25;
  white-space: nowrap;
}

/* ---- Hero pane (right) — Figma 540:1629 ----------------------------- */
.oc-auth__hero {
  flex: 1 1 50%;                           /* 50/50 split — see .oc-auth__form-pane */
  box-sizing: border-box;
  align-self: stretch;
  display: flex;
  min-width: 0;
  padding: 40px;                           /* Figma 538:2474 · inset around image */
}

/* Figma 540:1630 — the card. No fill and no shadow of its own: the canvas
   covers it edge to edge. (A left-edge inset shadow used to live here; the
   export shows Figma's left and right edges are identical, so it was wrong.) */
.oc-hero {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  border-radius: 16px;
}

/* Hero canvas — Figma 540:1631 "image": inset -42/-18/-34/-23 past the card,
   radius 24, clipped. It holds the dusty-mauve field; the sun and its
   reflection are the real Figma ellipses (.oc-hero__sun / .oc-hero__reflection).

   The field: Figma's codegen does not emit this frame's fill, so the stops
   below are MEASURED off a 2x export of 540:1631, sampled down the two columns
   that fall outside both ellipses' painted boxes (so no glow contaminates
   them) and averaged over a band to cancel the grain. It is a pure vertical
   gradient — the left and right columns agree within 3/255 at every row, which
   is why there are no side washes. 21 stops reconstruct the measured curve to
   a max channel error of 3/255. Re-measure rather than eyeball if it changes. */
.oc-hero__canvas {
  position: absolute;
  inset: -42px -18px -34px -23px;
  border-radius: var(--radius-card);       /* 24px */
  overflow: hidden;
  background-color: #b09e9a;
  background-image:
    linear-gradient(180deg,
      #b09e9a 6.9%,
      #b29f9d 11.4%,
      #b2a09f 15.8%,
      #b4a1a2 20.3%,
      #b5a2a5 24.8%,
      #b6a3a8 29.2%,
      #b6a3aa 33.7%,
      #b6a3ab 38.2%,
      #b09da4 42.6%,
      #aa949c 47.1%,
      #a38c95 51.6%,
      #9c848d 56.0%,
      #957b85 60.5%,
      #8f747d 65.0%,
      #8f737b 69.4%,
      #917378 73.9%,
      #937475 78.3%,
      #957473 82.8%,
      #9b7873 87.3%,
      #bc9085 91.7%,
      #d5a293 95.1%
    );
  transform-origin: 50% 30%;
  /* Very slow breathing glow — light gently swelling, not looping motion. */
  animation: oc-hero-breathe 13s ease-in-out infinite;
  will-change: transform, filter;
}
/* ---- The light — Figma 540:1631 -----------------------------------------
   Both layers are the ellipse exports themselves: a vertical gradient
   (#BCD7AE sage crown → #FC9B4C at 57.2% → #FF6FB0 transparent) wrapped in
   the turbulence/displacement + noise filter, all baked into the SVG.
   Each ellipse's artwork bleeds past its layout box by the filter's margin,
   so the painted size is the SVG viewBox, centred on the same point Figma
   centres the box on. Do not re-tune these by eye — they are measured.
   -------------------------------------------------------------------------*/

/* Sun — 540:1633. Box 455.737px centred at (50% + 0.5px, 50% − 94.81px);
   bleed 16.83% → 609.137px painted. */
.oc-hero__sun {
  position: absolute;
  left: calc(50% + 0.5px);
  top: calc(50% - 94.81px);
  width: 609.137px;
  height: 609.137px;
  transform: translate(-50%, -50%);
  background: url("../../assets/illustrations/auth/hero-sun.svg") center / 100% 100% no-repeat;
  pointer-events: none;
}

/* Reflection — 540:1632. The same ellipse mirrored (-scale-y-100) and blurred
   (stdDeviation 41.03, in the SVG). Box 445.185px centred at
   (50% + 0.5px, 50% + 355.65px); bleed 19.92% → 622.581px painted. */
.oc-hero__reflection {
  position: absolute;
  left: calc(50% + 0.5px);
  top: calc(50% + 355.65px);
  width: 622.581px;
  height: 622.581px;
  transform: translate(-50%, -50%) scaleY(-1);
  background: url("../../assets/illustrations/auth/hero-sun-reflection.svg") center / 100% 100% no-repeat;
  pointer-events: none;
}

/* Grain on the FIELD only — Figma's field carries a noise texture that codegen
   can't express, so it's approximated here. It must paint UNDER the sun and
   the reflection (::before, ahead of them in DOM order): those SVGs already
   bake their own noise in, and layering this on top of them double-grains the
   dome into a visibly coarser stipple than Figma's. */
.oc-hero__canvas::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.06;
  mix-blend-mode: overlay;
  pointer-events: none;
}
@keyframes oc-hero-breathe {
  0%, 100% { transform: scale(1); filter: brightness(1) saturate(1); }
  50%      { transform: scale(1.03); filter: brightness(1.05) saturate(1.06); }
}

/* Hero headline — Figma 540:1634 · Instrument Serif 56px, lower-left.
   Figma: left 104, top 585 in the 676×820 card; the line box is 84px
   (56 × 1.5), so the bottom gap is 820 − 585 − 84 = 151. Anchored to the
   bottom rather than the top so a shorter viewport crops the field, not the
   headline — identical at the 756×900 design size. */
.oc-hero__title {
  position: absolute;
  left: 104px;
  bottom: 151px;
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--font-weight-normal);
  font-size: 56px;
  line-height: 1.5;
  letter-spacing: -1.12px;
  color: #fdfcfb;                   /* Figma `background` var in this frame */
  white-space: nowrap;
}

/* ---- Prompt input preview — Figma 540:1635 --------------------------
   Figma pins it at left 82.5 / top 357 in the 676×820 card. That is 2.5px
   left of centre (right gap 87.5) — a deliberate nudge, not centring. */
.oc-hero__prompt {
  position: absolute;
  left: 82.5px;
  top: 357px;
  display: flex;
  align-items: center;
  gap: 12.138px;
  width: 506px;
  max-width: calc(100% - 48px);
  padding: 16px 24.277px;
  background: rgba(244, 241, 236, 0.7);       /* card/background · #f4f1ecb2 */
  border-radius: 24.277px;
  /* Figma's stroke is drawn inside the frame: its height is exactly
     16 + 38.203 (send button) + 16 = 70.203, with the 1.214 stroke adding
     nothing. A CSS `border` would grow the box to 72.63, so draw it inset. */
  box-shadow: inset 0 0 0 1.214px var(--color-field-border);  /* #d9d1cb */
  backdrop-filter: blur(50.981px);
  -webkit-backdrop-filter: blur(50.981px);
  overflow: hidden;
}
.oc-hero__prompt-text {
  flex: 1 1 0;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-normal);
  font-size: 16.994px;
  line-height: 1.25;
  color: #1b1818;                   /* Figma 538:2482 */
  white-space: nowrap;
  overflow: hidden;
}
/* Caret — Figma "Line 4" (540:1644): a 1px stroke 24.598px long, rotated 90°,
   in #1B1818, sitting immediately after the prompt text. */
.oc-hero__caret {
  display: inline-block;
  flex: 0 0 auto;
  width: 1px;
  height: 24.598px;
  margin-left: 1px;
  background: #1b1818;
  animation: oc-caret-blink 1.1s steps(1) infinite;
}
@keyframes oc-caret-blink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}
.oc-hero__send {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 5.458px;
  border: 0;
  border-radius: 100px;
  background: var(--color-btn-dark-send);   /* #252222 · Figma 538:2488 */
  cursor: pointer;
}
.oc-hero__send img {
  display: block;
  width: 27.288px;
  height: 27.288px;
  transform: scaleY(-1);   /* raw glyph points down; Figma flips it to point up */
}

/* ---- Responsive (desktop composition unchanged ≥1337px) -------------
   Below the 756×900 design size the card is no longer 676×820, so the pinned
   Figma coordinates stop meaning anything — fall back to a centred prompt.

   The breakpoint is derived, not chosen. The hero pane is half the page with
   40px of padding, so card = viewport/2 − 80, and each pinned child needs:

     headline  left 104   + 463.4 wide  → card 567.4 → viewport 1295
     prompt    left 82.5  + 506   wide  → card 588.5 → viewport 1337

   The prompt binds, so 1336px is the last width that must be overridden. It
   used to say 1200px, which left both children clipped from 1201–1336 — a band
   containing 1280, one of the commonest laptop widths. Note the prompt's own
   `max-width: calc(100% - 48px)` cannot save it: at left 82.5 the right edge
   lands at card + 34.5 however narrow the box gets, so it always overhangs.
   If either the headline's size or the prompt's width changes, recompute
   these two lines rather than nudging the number until it looks right. */
@media (max-width: 1336px) {
  .oc-hero__title {
    left: clamp(28px, 8%, 104px);
    bottom: clamp(56px, 12%, 151px);
    font-size: 44px;
  }
  .oc-hero__prompt {
    left: 50%;
    top: 47.8%;
    transform: translate(-50%, -50%);
    width: min(440px, calc(100% - 40px));
  }
}

@media (max-width: 960px) {
  .oc-hero__title { font-size: 36px; }
}

@media (max-width: 860px) {
  .oc-auth {
    justify-content: center;
  }
  .oc-auth__hero {
    display: none;
  }
  .oc-auth__form-pane {
    flex: 1 1 100%;
  }
  .oc-auth__logo {
    top: 32px;
  }
}


/* ---- Entrance reveal ------------------------------------------------
   The page arrives in three beats, outside-in: the hero light is already
   there, the brand follows, then the form you came to fill in. Pure CSS —
   it runs on first paint, needs no JS, and cannot leave anything stuck
   invisible if a script fails.

   Only this component's own three elements move; the card's internals are
   auth-card's business, and animating them from here would reach across
   the boundary. `both` holds the from-state before the delay elapses, so
   nothing flashes in at full opacity first.

   Note the logo keeps its translateX(-50%) in every frame — that -50% is
   what centres it (see .oc-auth__logo), not part of the animation. */
@keyframes oc-auth-reveal {
  from { opacity: 0; transform: translate3d(0, 12px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes oc-auth-reveal-logo {
  from { opacity: 0; transform: translateX(-50%) translate3d(0, -8px, 0); }
  to   { opacity: 1; transform: translateX(-50%) translate3d(0, 0, 0); }
}

@keyframes oc-auth-reveal-hero {
  from { opacity: 0; transform: scale(1.015); }
  to   { opacity: 1; transform: scale(1); }
}

.oc-auth__hero {
  animation: oc-auth-reveal-hero 900ms cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

.oc-auth__logo {
  animation: oc-auth-reveal-logo 700ms cubic-bezier(0.215, 0.61, 0.355, 1) 90ms both;
}

.oc-auth__body {
  animation: oc-auth-reveal 700ms cubic-bezier(0.215, 0.61, 0.355, 1) 150ms both;
}

/* ---- Reduced motion — honor the OS setting -------------------------- */
@media (prefers-reduced-motion: reduce) {
  .oc-hero__canvas,
  .oc-hero__caret,
  .oc-auth__hero,
  .oc-auth__logo,
  .oc-auth__body {
    animation: none !important;
  }
}

