/* ============================================================================
   L2Everdream — account pages (login · register · dashboard)
   ----------------------------------------------------------------------------
   Layered ON TOP of site.css — every color, font and radius here is an existing
   token. No new palette, no admin-dashboard theme: these pages are part of the
   site, so they inherit the blurple-on-twilight ground and use the lantern only
   where it earns it (the single warm "your light" accent, used sparingly).
   ========================================================================== */

/* ---------- The narrow column both auth forms sit in ---------- */
.auth-wrap {
  max-width: 460px;
  margin: 0 auto;
  padding: 72px 28px 96px;
}
.auth-head { text-align: center; margin-bottom: 34px; }
.auth-head .eyebrow {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.3em;
  text-transform: uppercase; color: var(--blurple-lit);
  margin: 0 0 14px;
}
.auth-head h1 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(30px, 5vw, 40px); line-height: 1.15;
  margin: 0 0 12px; color: var(--starlight);
}
.auth-head p { color: var(--body); margin: 0; font-size: 15.5px; }

/* ---------- The card ---------- */
.auth-card {
  background: linear-gradient(180deg, var(--surface) 0%, var(--field) 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 30px 28px;
}

/* ---------- Fields ---------- */
.field { margin-bottom: 20px; }
.field label {
  display: block; font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--light-blurple); margin-bottom: 7px;
}
.field input, .field select {
  width: 100%;
  background: var(--void);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--starlight);
  font-family: var(--sans);
  font-size: 16px; /* 16px avoids iOS zoom-on-focus */
  padding: 12px 14px;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.field input:focus, .field select:focus {
  outline: none;
  border-color: var(--blurple-hi);
  box-shadow: 0 0 0 3px rgba(88, 101, 242, 0.22);
}
.field .hint { display: block; margin-top: 7px; font-size: 12.5px; color: var(--greyple); }
/* "Forgot password?" — same slot/typography as .hint, but a real link. */
.field .field-link { display: inline-block; margin-top: 7px; font-size: 12.5px; color: var(--blurple-lit); }
.field .field-link:hover { color: var(--light-blurple); text-decoration: underline; }

/* ---------- Buttons ---------- */
/* ⚠️ AMBER, because a form's submit button IS "the one real action on whatever
   page you're on" (Chris 2026-07-27 — the rule behind option C). /login and
   /register exist to be submitted; making that button an outline would give the
   page's whole purpose the weakest treatment on it. Outline is for genuinely
   secondary actions.
   Was var(--blurple) = #5865F2, the same Discord blurple every other primary
   wore. Dark ink on amber, matching .connect-btn. */
.btn-primary {
  display: block; width: 100%;
  background: linear-gradient(180deg, #F6C67A, var(--lantern)); color: #2a1c07;
  border: 0; border-radius: var(--radius-sm);
  font-family: var(--sans); font-size: 15.5px; font-weight: 600;
  padding: 13px 20px; cursor: pointer;
  transition: background 140ms ease, transform 140ms ease;
}
@media (hover: hover) {
  .btn-primary:hover { background: linear-gradient(180deg, #FFD79A, #F6C67A); }
}
.btn-primary:active { transform: translateY(1px); }
.btn-primary:disabled { opacity: 0.55; cursor: not-allowed; }

/* ---------- Messages ---------- */
.alert {
  border-radius: var(--radius-sm);
  padding: 12px 15px; margin-bottom: 22px;
  font-size: 14.5px; line-height: 1.5;
}
.alert-error {
  background: rgba(240, 122, 122, 0.10);
  border: 1px solid rgba(240, 122, 122, 0.34);
  color: #F5C6C6;
}
.alert-ok {
  background: rgba(147, 192, 172, 0.10);
  border: 1px solid rgba(147, 192, 172, 0.34);
  color: var(--verdance);
}
.alert-note {
  background: var(--wash);
  border: 1px solid var(--line);
  color: var(--body);
}

.auth-alt { text-align: center; margin: 22px 0 0; font-size: 14.5px; color: var(--greyple); }

/* ---------- Dashboard ---------- */
.dash-head {
  border-bottom: 1px solid var(--line-soft);
  padding: 54px 0 26px; margin-bottom: 34px;
}
.dash-head .dash-in {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 20px; flex-wrap: wrap;
}
.dash-head h1 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(28px, 4.4vw, 38px); margin: 0 0 6px; color: var(--starlight);
}
.dash-head .who { font-family: var(--mono); font-size: 13px; color: var(--greyple); }

/* A quiet secondary action — sign out shouldn't compete with the primary CTA. */
.btn-quiet {
  background: transparent; color: var(--greyple);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-family: var(--sans); font-size: 14px; font-weight: 500;
  padding: 9px 16px; cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease;
}
.btn-quiet:hover { color: var(--light-blurple); border-color: var(--blurple-hi); }

.section-title {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin: 0 0 18px;
}
/* ⚠️ BREATHING ROOM BETWEEN SECTIONS (Chris 2026-08-23, from a screenshot:
   "'game accounts' need top margin"). The first section-title ("The launcher")
   already gets its gap from .dash-head's own bottom margin; every section
   AFTER the first was sitting flush against whatever card/grid came before it. */
.section-title:not(:first-of-type) { margin-top: 44px; }
.section-title h2 {
  font-family: var(--serif); font-weight: 400; font-size: 23px;
  margin: 0; color: var(--starlight);
}
.section-title .count { font-family: var(--mono); font-size: 12.5px; color: var(--greyple); }

/* ---------- The account grid ---------- */
.acct-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: 16px;
  margin-bottom: 44px;
}
.acct-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  transition: border-color 160ms ease;
}
.acct-card:hover { border-color: rgba(136, 148, 247, 0.28); }

/* ⭐ THE LAUNCHER CARD — the download's home, behind the login (2026-07-26).
   A row rather than a stacked card, because it holds one action and reads better
   beside its explanation. */
.launcher-card { display: flex; align-items: center; gap: 20px; justify-content: space-between; }
.launcher-t { margin: 0 0 4px; font-weight: 600; color: var(--starlight, #F5F6FF); font-size: 15.5px; }
.launcher-d { margin: 0; color: var(--greyple, #9096B8); font-size: 14px; line-height: 1.5; max-width: 52ch; }
/* ⚠️ A DISABLED CONTROL, NOT A DEAD LINK. There is no binary yet, so this must
   not be an <a> that goes nowhere — a link that does nothing is worse than a
   control that says why. Swap it for the real anchor when the launcher ships.
   ⚠️ STYLED LIKE THE REAL DOWNLOAD BUTTON (Chris 2026-08-23: "I want at least
   a download button in the download color. even tho we dont have a download
   link yet"). Was a muted, dashed, low-contrast pill; now matches the nav's
   own solid blurple CTA (.nav-right .nav-cta) so it reads as the real thing
   even though it can't be clicked yet — "Not released yet" is what still
   signals that, not a washed-out color. */
.btn-disabled { flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 42px; padding: 0 20px; border-radius: 10px; white-space: nowrap;
  font-size: 14.5px; font-weight: 600; color: #fff;
  background: var(--blurple); border: 1px solid transparent;
  box-shadow: 0 6px 18px -10px rgba(88, 101, 242, .7);
  cursor: not-allowed; }
@media (max-width: 560px) {
  .launcher-card { flex-direction: column; align-items: stretch; gap: 14px; }
  .btn-disabled { width: 100%; }
}
.acct-card .acct-top {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 12px; margin-bottom: 6px;
}
.acct-card .login {
  font-family: var(--mono); font-size: 16px; color: var(--starlight);
  word-break: break-all;
}
.acct-card .server {
  font-size: 12.5px; color: var(--greyple); margin-bottom: 16px;
}

/* Status pill — the one place the lantern earns its warmth (a pending account
   is literally "the light is on, waiting"). */
.pill {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase; white-space: nowrap;
  padding: 4px 9px; border-radius: 999px;
}
.pill-active  { background: rgba(147, 192, 172, 0.14); color: var(--verdance);  border: 1px solid rgba(147,192,172,0.32); }
.pill-pending { background: rgba(240, 182, 122, 0.13); color: var(--lantern);   border: 1px solid rgba(240,182,122,0.30); }
.pill-failed  { background: rgba(240, 122, 122, 0.12); color: #F0A0A0;          border: 1px solid rgba(240,122,122,0.30); }

/* ---------- Characters on an account ---------- */
.chars { border-top: 1px solid var(--line-soft); padding-top: 14px; }
.chars .chars-label {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--greyple-dim); margin-bottom: 10px;
}
.char-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 5px 0; font-size: 14px;
}
.char-row .cname { color: var(--body); }
.char-row .cmeta { font-family: var(--mono); font-size: 12px; color: var(--greyple); }
.char-row .online {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--verdance); box-shadow: 0 0 6px var(--verdance);
  margin-right: 7px; vertical-align: middle;
}
.chars .none { font-size: 13.5px; color: var(--greyple-dim); font-style: italic; }

/* ---------- Empty state ---------- */
.empty {
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 40px 28px; text-align: center;
  color: var(--greyple); margin-bottom: 44px;
}
.empty p { margin: 0 0 6px; }

/* ---------- The create form on the dashboard ---------- */
.create-card {
  background: linear-gradient(180deg, var(--surface) 0%, var(--field) 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px;
  max-width: 560px;
  /* ⚠️ CENTERED, NOT FLUSH LEFT (Chris 2026-08-23: "I dont like create game
     account on the left. I would at least want center aligned"). The card was
     capped at 560px with no inline margin, so inside the wide .wrap it sat
     flush against the left edge instead of the middle. */
  margin-inline: auto;
}
.create-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 620px) { .create-grid { grid-template-columns: 1fr; gap: 0; } }

/* Turnstile widget spacing — the widget itself is an iframe we don't style. */
.turnstile-slot { margin: 4px 0 20px; min-height: 65px; }

/* Test-mode banner: a deploy must never quietly ship an ungated form, so say so. */
.test-banner {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.04em;
  color: var(--lantern); background: rgba(240, 182, 122, 0.08);
  border: 1px solid rgba(240, 182, 122, 0.26);
  border-radius: var(--radius-sm); padding: 9px 13px; margin-bottom: 20px;
}

/* ============================================================================
   AUTH v2 — the shell for /login and /register
   ----------------------------------------------------------------------------
   ⚠️ REVISED 2026-08-23 (Chris, live): "the form need to be centered. I do not
   like the 'form on left, image on right'. The form should be centered, and
   the image we can perhaps enlarge and have it behind." The two-column split
   below is GONE on desktop — the render is now a full-bleed background layer
   behind a centered card, not a competing column. Everything about the render
   itself (the feathered mask, the alpha-derived edges, `contain` vs `cover`,
   the caption) is UNCHANGED reasoning, just re-anchored to the whole viewport
   instead of a half-width panel — see the comments inline below for what
   changed and why.

   ORIGINAL RULING, kept for history (superseded above, desktop half only):
   Chris 2026-07-27, from a phone screenshot of /register: "the account
   registration was built before we settled on a style for the site … on desktop
   it could be like a split design, kinda like the hero, where you have a login
   form on the right and on the left is like a render."

   THE DEFECT WAS ORDER, NOT DECORATION. Above the fold the old page stacked nav
   → kicker → serif headline → four-line paragraph → dev warning box, and only
   then the first input. Each piece was defensible; the stack was not.

   MOBILE  — card FIRST, prose after it. One field group visible on landing.
   DESKTOP — two columns from 900px: render left, form right.

   ⚠️ Every field, button and Turnstile style is REUSED from the block above.
   This section adds the shell only; if you find yourself restyling an input
   here, it belongs up there instead.
   ========================================================================== */

.auth2 { position: relative; }

/* ---------- The render panel ---------- */
/* Hidden on mobile: at 393px a decorative half-screen image is what pushes the
   form under the fold, which is the whole bug being fixed. It earns its space
   only once there IS space. */
.auth2-art { display: none; }

/* ⚠️ WIDTH *AND* HEIGHT (Chris 2026-07-27: "I don't think we support landscape
   mode on mobile for the login and register pages — it keeps it the same width,
   it doesn't expand. It's not broken, it's just not optimized").
   MEASURED, and it was two problems wearing one coat:
     · iPhone landscape 852x393 — art stayed hidden (the old test was
       min-width:900px), so a 460px column sat on an 852px screen. That is the
       "doesn't expand".
     · Pixel landscape 915x412 — the split DID engage, and the submit button was
       still below the fold, because 412px of height cannot hold a hero image and
       a form.
   A phone in landscape is WIDE AND VERY SHORT, so a width-only query cannot tell
   it apart from a laptop. The split now requires 760px of width and 520px of
   height; below either, the compact single column wins, which is the right
   layout for a short viewport regardless of how wide it is. */
@media (min-width: 760px) and (min-height: 520px) {
  .auth2 {
    /* ⚠️ NO LONGER A GRID (2026-08-23) — the two-column split above is retired.
       The art is now a full-bleed layer BEHIND the panel (see .auth2-art below,
       now position:absolute over the whole section) and the panel is centered
       over it, so this box only needs to establish the stacking context and
       give the centered content somewhere tall enough to sit in. */
    position: relative;
    max-width: var(--wrap); margin-inline: auto; padding-inline: 26px;
    /* ⚠️ min-height, NOT height: the register form is taller than a 900px laptop
       viewport once Turnstile renders, so a hard height would clip it. */
    min-height: calc(100dvh - var(--nav-h, 72px));
    display: flex; align-items: center; justify-content: center;
  }
  .auth2-art {
    display: block;
    /* ⚠️ FULL-BLEED, BEHIND THE FORM (Chris 2026-08-23, live: "the form should
       be centered, and the image we can perhaps enlarge and have it behind").
       Was a side column at order:2; is now an absolutely-positioned backdrop
       spanning the whole section, ignoring the page gutter above (inset:0 on
       the SECTION, not the max-width wrap) so the render reaches the viewport
       edges the way a hero background does. */
    position: absolute; inset: 0; z-index: 0; overflow: hidden;
  }
  /* The caption now names the backdrop rather than a side panel — same corner,
     same mono register, just anchored to the whole section instead of a column. */
  .auth2-art-cap {
    position: absolute; left: 26px; bottom: 22px; z-index: 1; margin: 0;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--greyple); line-height: 1;
  }
  .auth2-art-img {
    position: absolute; inset: 0;
    /* ⚠️ OUR OWN GENERATED GEODATA RENDER — the same art the homepage hero uses,
       so these pages share a visual root with the site rather than just a
       palette. Decorative: the element is aria-hidden in the component. */
    /* ⚠️ `contain`, NOT `cover` (Chris 2026-07-27: "well this can't be right").
       `cover` on this near-square panel (1070x1007) scaled the 1478x1521 render
       up to fill and cropped the rest, so the visitor saw a small centre slice at
       high magnification — abstract squiggles rather than a map of anywhere.
       `contain` shows the whole render; the panel's own dark ground fills what is
       left, which is the same treatment the homepage plates use. */
    /* ⚠️ TALKING ISLAND, WHOLE, TO THE WATER (Chris 2026-07-28: "the render image
       for login and register — let's do Talking Island, the whole island, zoomed
       out to the water edges"). It is where a new character starts, which is the
       right subject for the page where an account is made.
       Rendered at r=26000 with NO --zones (he asked for the polygons gone, and
       they were what made it read as a blob) and upscaled to 3252px so the
       village walls, harbour piers and buildings stay crisp linework rather than
       mush. 98KB. `contain` shows the whole island — never `cover`, which crops
       the coastline off and is the bug this panel already had once. */
    /* ⚠️ THE PNG CARRIES ITS OWN ALPHA — the void is TRANSPARENT, not painted
       (Chris 2026-07-28: "I still see hard edges, and I think something is just
       causing it to be in general brighter when really it should be blending
       with the background colors").
       Both halves of that were one cause. The render shipped as opaque RGB, so
       the lightened void (20,17,30) filled all 3252x3252 as a SOLID RECTANGLE
       over the page ground — that rectangle was the brightness, and its edge was
       the hard line. The CSS mask could not save it: `contain` letterboxes the
       square render inside a taller panel, so the image's own opaque edge landed
       INSIDE the mask's fade and stayed visible.
       Fixed at the source instead of dimming it further: alpha is now derived
       from each pixel's distance from the void colour, so only inked geometry
       paints and the page ground IS the ocean. The mask below now feathers the
       island itself, which is what it was always meant to do. */
    background: url('/assets/generated/auth-talking-island.png') center / contain no-repeat;
    /* Higher than the old .5 because there is no longer a bright plate to hold
       down — this now sets the ISLAND's weight against the page, nothing else. */
    opacity: .62;
    /* ⚠️ FEATHER ALL FOUR EDGES (Chris 2026-07-28: "need blended into background
       — transparent edges I think, like hero"). Without it the render's own
       rectangular frame cuts a hard line against the page, which is the same
       thing he called out on the homepage on 2026-07-21: "just looks like a hard
       image and not fitting well."
       Identical treatment to .launch-art in index.astro:1097 — two gradients
       intersected so the CORNERS feather too, rather than one gradient that
       leaves two hard sides. The page ground shows through the fade and the art
       dissolves into it. */
    -webkit-mask-image:
      linear-gradient(90deg,  transparent 0, #000 14%, #000 84%, transparent 100%),
      linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    mask-image:
      linear-gradient(90deg,  transparent 0, #000 14%, #000 84%, transparent 100%),
      linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
  }
  /* ⚠️ VIGNETTE, NOT A SIDE FADE (2026-08-23). The old veil darkened one inner
     edge to blend two side-by-side boxes into one surface; there is no more
     "inner edge" once the render is a centered backdrop. Its job now is the
     opposite direction: stay light at the CORNERS (where the render should
     read) and go dark toward the CENTER (where the heading/blurb sit directly
     on the page ground, outside the card). The card itself doesn't need this —
     it carries its own solid gradient — but the eyebrow/heading/blurb above and
     below it do. */
  .auth2-art-veil {
    position: absolute; inset: 0;
    /* Same edge feather as the image below, so the vignette's own rectangle
       doesn't reintroduce the hard frame the mask exists to remove. */
    -webkit-mask-image:
      linear-gradient(90deg,  transparent 0, #000 14%, #000 84%, transparent 100%),
      linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    mask-image:
      linear-gradient(90deg,  transparent 0, #000 14%, #000 84%, transparent 100%),
      linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
    background: radial-gradient(
      ellipse 60% 55% at center,
      rgba(11,10,24,.88) 0%, rgba(11,10,24,.62) 45%, rgba(11,10,24,0) 100%
    );
  }
}

/* ---------- The form column ---------- */
.auth2-panel { display: flex; align-items: center; justify-content: center; }
.auth2-inner {
  display: flex; flex-direction: column;
  width: 100%; max-width: 440px;
  padding: clamp(28px, 5vw, 56px) 26px clamp(48px, 6vw, 72px);
}
/* ⚠️ CENTERED, ABOVE THE BACKDROP (2026-08-23). Was a left-aligned column that
   deliberately ate the grid's own gutter (padding-left:0) to sit flush with the
   art beside it. There's no gutter to share now — the panel just needs to sit
   above .auth2-art in the stacking order and stay centered like it already is
   on mobile. */
@media (min-width: 760px) and (min-height: 520px) {
  .auth2-panel { position: relative; z-index: 1; width: 100%; }
  .auth2-inner { max-width: 460px; }
}

/* ⚠️ ORDER IS THE FIX. The card is order:1 so the form is the first thing under
   the heading on a phone; the explanatory prose follows it. Both live in the
   same column on desktop, where the order is visually moot. */
/* ⚠️ HEADLINE ABOVE THE EYEBROW (Chris 2026-07-27: "Join the dream should be
   FIRST and create your master account up under it — the headline should be on
   top"). Flex order does the swap so the DOM keeps its reading order: the <h1>
   stays the first heading a screen reader meets either way, and the eyebrow
   remains associated prose rather than becoming a pseudo-heading. */
.auth2-h       { order: 0; }
.auth2-eyebrow { order: 1; }   /* margin lives in the styling block below */
.auth2-card    { order: 2; }
.auth2-blurb   { order: 3; }
.auth2-alt     { order: 4; }

.auth2-eyebrow {
  font-family: var(--mono); font-size: 11px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--blurple-lit);
  /* ⚠️ TOP MARGIN IS LOAD-BEARING (Chris 2026-07-27: "there needs to be a little
     bit more space between the header and the 'welcome back' and the 'sign in to
     your master account' — they're too close to each other"). Measured flush at
     0px before this: the order:1 rule above USED to carry `margin: 10px 0 22px`
     and this block silently overrode it — equal specificity, later wins. The
     margin now lives in exactly one place. */
  margin: 14px 0 22px;
}
/* ⚠️ ONE ACCENTED WORD — "master" (Chris 2026-07-27: "maybe emphasizing master
   in a different colour or label"). It is the word that separates this account
   from a game account, which the password hint below already leans on.
   The treatment is the SITE'S OWN, not a new idea: the wordmark accents "L2" in
   lantern against blurple, so a lantern word inside a blurple line already
   reads as Everdream. Not italic — the <em> is a semantic hook, and italics in
   a letter-spaced mono line at 11px just look broken. */
.auth2-eyebrow em { font-style: normal; color: var(--lantern); }
.auth2-h {
  font-family: var(--serif); font-weight: 600;
  font-size: clamp(30px, 4.4vw, 42px); line-height: 1.08;
  margin: 0; color: var(--starlight); text-wrap: balance;
}

/* The card idiom from /features — same gradient ground, same hairline, same
   radius — so an account page reads as one of the site's cards. */
.auth2-card {
  position: relative;
  background: linear-gradient(168deg, #141230, #100E22);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: clamp(20px, 3vw, 28px);
}
.auth2-card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  border-radius: 16px 16px 0 0;
  background: var(--blurple-lit); opacity: .5;
}
/* The last field's margin would otherwise double the card's bottom padding. */
.auth2-card .field:last-of-type { margin-bottom: 16px; }
.auth2-card .btn-primary { width: 100%; }

.auth2-blurb {
  margin: 20px 0 0; color: var(--greyple);
  font-size: 14px; line-height: 1.6;
}
.auth2-alt {
  margin: 14px 0 0; color: var(--greyple);
  font-size: 14px;
}
.auth2-alt a { color: var(--blurple-lit); }

/* The compact column — everything that is not a tall-enough desktop. */
@media (max-width: 759px), (max-height: 519px) {
  /* Centre the head on mobile to match the rest of the site's narrow pages,
     but keep the card left-to-right full width. */
  .auth2-eyebrow, .auth2-h { text-align: center; }
  .auth2-inner { max-width: 460px; margin: 0 auto; }
}

/* ---------------------------------------------------------------------------
   AUTH v2 — FIELD VISIBILITY + WCAG NON-TEXT CONTRAST
   ---------------------------------------------------------------------------
   Chris 2026-07-27: "the login form is too hard to see … I wanna make sure it's
   ADA compliant, I wanna make sure you SEE THE TEXT FIELDS and they don't blend
   in."

   ⚠️ HE WAS RIGHT AND THE a11y GATE HAD SAID PASS. Measured on /login before
   this block:
     · input background vs card ............ 1.00:1  (IDENTICAL — invisible)
     · border, alpha COMPOSITED ............ 1.22:1  (WCAG 1.4.11 needs 3.0)
     · focus border vs unfocused ........... 1.22:1  (no visible focus at all)
   The border READ as 7.12:1 if you measure the declared rgba(136,148,247,.14)
   without compositing the alpha over its backdrop. That number is a lie — the
   real edge is rgb(33,33,64). Always composite before judging an alpha border.

   ⚠️ WHY axe PASSED ANYWAY: axe-core does not check 1.4.11 non-text contrast by
   default, and it cannot see "focused looks like unfocused" at all. A green a11y
   gate is not evidence a form is usable. The gate now carries an explicit
   contrast assertion (tools/contrast.mjs) so this cannot regress silently.

   THE FIX IS SEPARATION, NOT BRIGHTNESS — the page's calm is the thing Chris
   likes. The field sits DARKER than the card it is on (a well, not a glow), and
   the border is a solid colour rather than a 14%-alpha whisper.
   ------------------------------------------------------------------------- */

.auth2-card .field input,
.auth2-card .field select {
  /* Darker than the card's #141230→#100E22 gradient, so the field reads as a
     recess even before you notice its border. */
  background: #08070F;
  /* ⚠️ #64687D IS COMPUTED, NOT CHOSEN. My first pick (#3A3A63) looked right and
     measured 1.88:1 — still a fail. Rather than guess a third time I swept a
     blurple-leaning ramp for the first value clearing 3.0:1 against BOTH the
     field well and the card gradient. This one is 3.64 / 3.37. Do not "tone it
     down" without re-running that measurement. */
  border: 1px solid #64687D;
}

.auth2-card .field input::placeholder {
  /* Was #757575 — a UA default that is neither ours nor readable. This is the
     site's own greyple, and it clears 4.5:1 on the darker field. */
  color: var(--greyple);
  opacity: 1;                      /* Firefox dims placeholders by default. */
}

/* ⚠️ FOCUS MUST BE OBVIOUS, not merely present. outline:none is kept because the
   ring is drawn with box-shadow (it follows border-radius, which an outline does
   not), but the BORDER now changes to a bright blurple as well — so focus is
   legible even where box-shadow is suppressed, and in forced-colors mode the
   outline below takes over. */
/* ⚠️ .auth2-card twice, deliberately. The generic `.field input:focus` rule
   lives LATER in this file at equal specificity, so it was winning the cascade
   and focus rendered with no ring at all (measured: box-shadow "none", focus
   border identical to unfocused). Specificity, not source order, is what makes
   this survive future edits above it. */
.auth2-card.auth2-card .field input:focus,
.auth2-card.auth2-card .field select:focus {
  border-color: var(--light-blurple);
  box-shadow: 0 0 0 3px rgba(139, 148, 247, 0.45);
}

/* Windows High Contrast / forced-colors: our colours are discarded, so restore a
   real outline rather than relying on a box-shadow the OS will drop. */
@media (forced-colors: active) {
  .auth2-card .field input:focus,
  .auth2-card .field select:focus { outline: 3px solid Highlight; outline-offset: 1px; }
}

/* ---------------------------------------------------------------------------
   SHORT VIEWPORTS — a phone in landscape (852x393, 915x412) has plenty of width
   and almost no height. Measured before this block: the submit button sat at
   590-742px on a 393-412px tall screen, i.e. the whole form was below the fold
   and you had to scroll a login page to find its button.
   The fix is to spend less vertical space, not less width: trim the outer
   padding, shrink the display heading (it is decorative here — the eyebrow
   carries the meaning), and tighten the field rhythm. Nothing is hidden.
   ------------------------------------------------------------------------- */
@media (max-height: 519px) {
  .auth2-inner { padding-top: 16px; padding-bottom: 24px; max-width: 520px; }
  .auth2-h { font-size: clamp(22px, 3.4vw, 27px); }
  .auth2-eyebrow { margin: 8px 0 12px; }
  .auth2-card { padding: 16px 18px; }
  .auth2-card .field { margin-bottom: 12px; }
  .auth2-card .field label { margin-bottom: 4px; }
  .auth2-card .field input { padding: 9px 12px; }
  .auth2-card .field .hint { margin-top: 4px; }
  .auth2-blurb { margin-top: 12px; }
  /* The Turnstile widget has a fixed 65px slot that is pure air on a short
     screen until it renders. */
  .turnstile-slot { min-height: 0; margin: 0 0 12px; }
}

/* ⚠️ SHORT **AND WIDE** — use the width, since the height is not there.
   Trimming alone was not enough: /register carries three fields plus a Turnstile
   widget, and at 393px of height a single column cannot fit them however tight
   the rhythm (measured: submit still at 531px). A landscape phone has 850-915px
   of width doing nothing, so the fields become two columns and the form halves
   its height. The submit and the Turnstile span both columns — a submit button is
   the page's one real action and should not be half-width.
   ⚠️ Only from 700px wide: below that the screen is short AND narrow (a small
   phone in landscape), where two columns would be unreadable. */
@media (max-height: 519px) and (min-width: 700px) {
  .auth2-card form {
    display: grid; grid-template-columns: 1fr 1fr; column-gap: 16px;
    align-items: start;
  }
  .auth2-card form > .field { margin-bottom: 10px; }
  /* Anything that is not a field spans the row: the Turnstile slot and the
     submit button. */
  .auth2-card form > .turnstile-slot,
  .auth2-card form > .btn-primary { grid-column: 1 / -1; }
  .auth2-inner { max-width: 640px; }
}

/* =============================================================================
   /account-access — the tabbed sign-in/sign-up page, with the download beside it
   -----------------------------------------------------------------------------
   Chris 2026-07-28, from Reborn: "their sign in form with tabs for register vs
   login, same page. And download button for the actual exe on the right side."

   ⚠️ THIS PAGE SHIPPED WITH NO STYLES AT ALL. The .astro was written and the
   build passed — Astro does not care that `.aa-tabs` matches nothing — so the
   page rendered as raw HTML: stacked labels, full-bleed inputs, an ordered list
   showing "1. 1" because the <ol> marker and the <span class="aa-n"> both drew.
   A passing build is not a rendered page, and only opening it in a browser
   found this.
   ============================================================================= */
.aa {
  max-width: var(--wrap); margin-inline: auto;
  padding: 40px 26px 72px;
  display: grid; gap: 34px;
}
/* Sized down from the /register hero treatment: there the headline IS the page,
   here it sits above a tab strip and has to leave room for it. */
.aa-h { font-size: clamp(26px, 3.4vw, 34px); margin: 0 0 20px; }
/* ---------- tabs ---------- */
.aa-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 18px; }
.aa-tab {
  display: block; text-align: left; cursor: pointer;
  padding: 13px 16px; border-radius: var(--radius);
  background: rgba(136, 148, 247, 0.05);
  border: 1px solid var(--line);
  color: var(--greyple); font: inherit;
  transition: background .16s ease, border-color .16s ease, color .16s ease;
}
/* ⚠️ aria-selected IS the styling hook, not a parallel .is-active class — the
   state a screen reader is told and the state an eye sees cannot drift apart. */
.aa-tab[aria-selected="true"] {
  background: rgba(136, 148, 247, 0.11);
  border-color: rgba(136, 148, 247, 0.38);
  color: #fff;
}
@media (hover: hover) {
  .aa-tab:hover { border-color: rgba(136, 148, 247, 0.30); color: #fff; }
}
.aa-tab:focus-visible { outline: 2px solid var(--blurple); outline-offset: 2px; }
.aa-tab-t { display: block; font-weight: 650; font-size: 15px; }
.aa-tab-d { display: block; font-size: 12.5px; margin-top: 2px; color: var(--greyple); }
.aa-tab[aria-selected="true"] .aa-tab-d { color: var(--greyple); }

.aa-card { border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; }
.aa-panel[hidden] { display: none; }

/* ---------- the steps + download ---------- */
.aa-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 22px; }
.aa-steps li { display: grid; grid-template-columns: 34px 1fr; gap: 14px; align-items: start; }
/* ⚠️ The number is a <span>, so the <ol> marker must be suppressed or the page
   reads "1. 1" — which is exactly what shipped. */
.aa-n {
  display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 9px;
  background: rgba(136, 148, 247, 0.10); border: 1px solid var(--line);
  font-family: var(--mono); font-size: 13px; color: var(--greyple);
}
.aa-steps h3 { font-size: 16px; margin: 6px 0 4px; line-height: 1.25; }
.aa-steps p { font-size: 14px; color: var(--greyple); margin: 0; line-height: 1.55; }

.aa-dl {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  margin-top: 28px; padding: 13px 22px; border-radius: var(--radius);
  background: linear-gradient(180deg, #F7C97E, #EBB463);
  color: #241a07; font-weight: 700; text-decoration: none;
  min-height: 44px;   /* WCAG 2.5.5 */
}
.aa-dl svg { width: 15px; height: 15px; flex: none; }
/* ⚠️ THE PRE-RELEASE STATE, matching .btn-disabled on /account — dashed, muted,
   not-allowed. It must not look like the amber action above; a control that
   cannot be used has to say so at a glance. */
.aa-dl-off {
  background: rgba(136, 148, 247, 0.06);
  border: 1px dashed rgba(136, 148, 247, 0.3);
  color: var(--greyple); font-weight: 500; cursor: not-allowed;
}
@media (hover: hover) {
  /* :not(.aa-dl-off) — a disabled control must not brighten under the cursor. */
  .aa-dl:not(.aa-dl-off):hover { background: linear-gradient(180deg, #FFD79A, #F6C67A); }
}
.aa-dl:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.aa-note { font-size: 13px; color: var(--greyple); margin: 14px 0 0; line-height: 1.55; }

/* ---------- two columns, same breakpoint as the auth split ---------- */
@media (min-width: 860px) {
  .aa {
    grid-template-columns: minmax(420px, 1fr) minmax(320px, 420px);
    gap: 64px; align-items: start;
    padding-top: 56px;
  }
  .aa-side { padding-top: 6px; }
}
