/*
 * System panel — the "status window" chrome used by the auth screens.
 *
 * Tokens mirror the iOS splash (Soul-Bound---IOS/SplashView.swift) so the
 * handoff from the native splash into the web view is seamless: same base
 * navy, same cyan, same 36px grid spacing.
 */

/* Tokens live in system.css — the single source of truth for the whole app.
   This file only styles the auth screens. */

/* ---------------------------------------------------------------- screen -- */

/* Fixed rather than painting <body>, so these styles stay scoped to the auth
   screens and don't darken the rest of the (currently unstyled) app. */
/* The app ships no reset, so text inputs default to content-box and their
   padding would push them past the panel edge. Scoped so the rest of the
   (unstyled) app is untouched. */
.sys-screen,
.sys-screen *,
.sys-screen *::before,
.sys-screen *::after {
  box-sizing: border-box;
}

/* Normal flow rather than `position: fixed; inset: 0` with its own scroll
   container. Fixed keeps the full viewport height when the iOS keyboard opens,
   so the panel stayed centred against a height half-hidden behind the keyboard
   while the inner scroller fought the browser trying to reveal the focused
   field — which is what made typing on the goal wizard feel stuck. `dvh`
   shrinks with the keyboard and lets the page scroll normally. */
.sys-screen {
  position: relative;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Extra headroom above safe-area-inset-top so the panel clears whatever
     bar sits above the web view on these full-bleed screens. */
  padding: calc(72px + env(safe-area-inset-top)) 20px calc(28px + env(safe-area-inset-bottom));
  color-scheme: dark;
  font-family: var(--sys-font);
  /* Grid alpha is set literally rather than via --sys-line-soft: it has to read
     as texture against a near-black base, so it sits far below border alpha. */
  background:
    radial-gradient(circle at 50% 42%, var(--sys-bg-glow), transparent 62%),
    repeating-linear-gradient(to right, rgba(34, 211, 238, 0.055) 0 1px, transparent 1px var(--sys-grid)),
    repeating-linear-gradient(to bottom, rgba(34, 211, 238, 0.055) 0 1px, transparent 1px var(--sys-grid)),
    var(--sys-bg);
}

/* ----------------------------------------------------------------- panel -- */

/* Notched frame: the outer element paints the 1px border as its background and
   the inner element covers all but that 1px. Both share a clip-path, which is
   what produces the cut corners. drop-shadow (not box-shadow) is used for the
   glow because filters follow the clipped silhouette; box-shadow would be
   sliced off at the clip edge. */
.sys-panel {
  --notch: 18px;
  width: 100%;
  max-width: 390px;
  padding: 1px;
  clip-path: polygon(
    var(--notch) 0,
    100% 0,
    100% calc(100% - var(--notch)),
    calc(100% - var(--notch)) 100%,
    0 100%,
    0 var(--notch)
  );
  background: linear-gradient(
    160deg,
    rgba(34, 211, 238, 0.75),
    rgba(34, 211, 238, 0.22) 45%,
    rgba(34, 211, 238, 0.55)
  );
  filter: drop-shadow(0 0 22px rgba(34, 211, 238, 0.22));
  animation: sys-panel-in 0.8s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.sys-panel__inner {
  position: relative;
  clip-path: inherit;
  padding: 34px 28px 28px;
  background: linear-gradient(170deg, rgba(10, 17, 36, 0.95), rgba(5, 8, 18, 0.97));
}

/* Scanlines. */
.sys-panel__inner::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.022) 0 1px,
    transparent 1px 3px
  );
}

/* Corner bracket on the two square corners — the notch handles the other two.
   Mirrors CornerBracket in the iOS splash. */
.sys-panel__inner::after {
  content: "";
  position: absolute;
  top: 8px;
  right: 8px;
  width: 12px;
  height: 12px;
  pointer-events: none;
  border-top: 1px solid var(--sys-cyan);
  border-right: 1px solid var(--sys-cyan);
  opacity: 0.7;
}

@keyframes sys-panel-in {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
    filter: drop-shadow(0 0 22px rgba(34, 211, 238, 0.22));
  }
}

/* ---------------------------------------------------------------- header -- */

.sys-panel__head {
  position: relative;
  text-align: center;
}

.sys-panel__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--sys-cyan);
  /* letter-spacing pads the final glyph; pull it back to stay optically centred. */
  text-indent: 0.42em;
}

.sys-panel__eyebrow::before,
.sys-panel__eyebrow::after {
  content: "";
  width: 5px;
  height: 5px;
  flex: none;
  background: var(--sys-cyan);
  transform: rotate(45deg);
  box-shadow: 0 0 8px rgba(34, 211, 238, 0.8);
}

.sys-panel__title {
  margin: 0;
  font-size: 22px;
  font-weight: 200;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 0 20px rgba(34, 211, 238, 0.45);
}

.sys-panel__note {
  margin: 12px 0 0;
  font-size: 11px;
  line-height: 1.6;
  letter-spacing: 0.08em;
  color: var(--sys-text-dim);
}

.sys-rule {
  height: 1px;
  margin: 20px 0;
  border: 0;
  background: linear-gradient(to right, transparent, var(--sys-line), transparent);
}

.sys-rule--faint {
  background: linear-gradient(to right, transparent, var(--sys-line-soft), transparent);
}

/* Flash is styled once, in system.css, and shared by every screen (auth
   included) via shared/_flash.html.erb — nothing to override here. */

/* ------------------------------------------------------------------ form -- */

/* f.error_notification on the sign-up / reset forms. */
.sys-form .error_notification {
  margin-bottom: 18px;
  padding: 11px 14px;
  border-left: 2px solid var(--sys-danger);
  background: rgba(255, 93, 115, 0.09);
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 0.08em;
  color: #ffc7cf;
}

/* simple_form's `hint:` option (password length). */
.sys-form .form-text {
  display: block;
  margin-top: 6px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(232, 244, 255, 0.38);
}

/* simple_form emits Bootstrap wrapper markup here — simple_form_bootstrap.rb
   sets default_wrapper = :vertical_form and loads after simple_form.rb, so the
   `:default` wrapper configured there never takes effect. Bootstrap's own CSS
   isn't loaded, so these class names are just markup hooks. */
.sys-form .mb-3 {
  margin-bottom: 18px;
}

/* The boolean wrapper is a <fieldset>; drop the UA border. */
.sys-form fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.sys-form .form-label {
  display: block;
  margin-bottom: 7px;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--sys-text-dim);
}

.sys-form .form-control {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--sys-line-soft);
  border-radius: 2px;
  background: rgba(3, 7, 18, 0.65);
  color: var(--sys-text);
  /* 16px minimum: anything smaller makes iOS zoom the web view on focus. */
  font-size: 16px;
  font-family: inherit;
  letter-spacing: 0.05em;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.sys-form input::placeholder {
  color: rgba(232, 244, 255, 0.25);
}

.sys-form .form-control:focus {
  outline: none;
  border-color: var(--sys-line);
  box-shadow: 0 0 0 1px rgba(34, 211, 238, 0.22), 0 0 20px rgba(34, 211, 238, 0.16);
}

.sys-form .is-invalid {
  border-color: rgba(255, 93, 115, 0.6);
}

/* Safari's autofill repaint would otherwise drop a light background into the
   middle of a dark panel. */
.sys-form input:-webkit-autofill,
.sys-form input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--sys-text);
  -webkit-box-shadow: 0 0 0 1000px #070c1a inset;
  caret-color: var(--sys-text);
}

/* Checkbox and its label are siblings inside .form-check. */
.sys-form .form-check {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sys-form .form-check-label {
  margin: 0;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sys-text-dim);
  cursor: pointer;
}

.sys-form .form-check-input {
  position: relative;
  flex: none;
  width: 15px;
  height: 15px;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid var(--sys-line-soft);
  border-radius: 2px;
  background: rgba(3, 7, 18, 0.65);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.sys-form .form-check-input:checked {
  border-color: var(--sys-cyan);
  box-shadow: 0 0 12px rgba(34, 211, 238, 0.3);
}

.sys-form .form-check-input:checked::after {
  content: "";
  position: absolute;
  inset: 3px;
  background: var(--sys-cyan);
}

.sys-form .error,
.sys-form .invalid-feedback {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: #ffc7cf;
}

.sys-form abbr {
  text-decoration: none;
  color: var(--sys-cyan);
}

/* ---------------------------------------------------------------- submit -- */

.sys-form .form-actions {
  margin-top: 22px;
}

.sys-form .btn {
  width: 100%;
  padding: 14px;
  border: 1px solid rgba(34, 211, 238, 0.45);
  border-radius: 2px;
  background: rgba(13, 20, 41, 0.6);
  color: #fff;
  font-family: inherit;
  font-size: 12px;
  line-height: 1.7;
  letter-spacing: 0.32em;
  text-indent: 0.32em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.sys-form .btn:hover,
.sys-form .btn:focus-visible {
  border-color: var(--sys-cyan);
  background: rgba(20, 32, 62, 0.7);
  box-shadow: 0 0 24px rgba(34, 211, 238, 0.22);
  outline: none;
}

.sys-form .btn:active {
  transform: translateY(1px);
}

/* ----------------------------------------------------------------- links -- */

.sys-links {
  text-align: center;
}

.sys-links p {
  margin: 9px 0 0;
}

.sys-links a {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--sys-text-dim);
  transition: color 0.2s ease, text-shadow 0.2s ease;
}

.sys-links a:hover {
  color: var(--sys-cyan);
  text-shadow: 0 0 12px rgba(34, 211, 238, 0.5);
}

/* ----------------------------------------------------------------- a11y -- */

@media (prefers-reduced-motion: reduce) {
  .sys-panel {
    animation: none;
  }

  .sys-form input,
  .sys-links a {
    transition: none;
  }
}

/* ----------------------------------------------------------- danger zone -- */

/* Account deletion on registrations/edit. */
.sys-panel__subhead {
  margin: 0 0 8px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--sys-text-dim);
}

.sys-danger-zone form {
  margin: 0;
}

.sys-btn-danger {
  width: 100%;
  padding: 13px;
  border: 1px solid rgba(255, 93, 115, 0.45);
  border-radius: 2px;
  background: rgba(255, 93, 115, 0.07);
  color: #ffc7cf;
  font-family: inherit;
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.sys-btn-danger:hover,
.sys-btn-danger:focus-visible {
  border-color: var(--sys-danger);
  background: rgba(255, 93, 115, 0.12);
  box-shadow: 0 0 20px rgba(255, 93, 115, 0.2);
  outline: none;
}

/* ---------------------------------------------------- sign in with apple -- */

/* Hidden by default: the native flow only exists inside the app. The bridge
   stamps data-bridge-platform on <html> once it connects, which reveals it. */
.sys-apple {
  display: none;
  margin-top: 18px;
}

html[data-bridge-platform] .sys-apple {
  display: block;
}

.sys-apple__divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  font-size: 9px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(232, 244, 255, 0.35);
}

.sys-apple__divider::before,
.sys-apple__divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--sys-line-soft);
}

/* Apple requires their button keep its own look rather than take on the
   surrounding theme, so this stays black-on-white regardless of the panel. */
.sys-apple__button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 13px;
  border: 0;
  border-radius: 6px;
  background: #fff;
  color: #000;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.sys-apple__button:active {
  opacity: 0.8;
}

.sys-apple__logo {
  font-size: 17px;
  line-height: 1;
  /* U+F8FF renders the Apple mark on Apple platforms, which is the only place
     this button is shown. */
}

/* ------------------------------------------------ character creation -- */

/* The summon screen is taller than the auth panels, so it scrolls from the top
   instead of being vertically centred. */
.sys-screen--scroll {
  align-items: flex-start;
}

.sys-panel--wide {
  max-width: 440px;
}

.gender-toggle {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

.gender-toggle__option {
  flex: 1;
  padding: 10px;
  border: 1px solid var(--sys-line-soft);
  border-radius: 2px;
  background: rgba(3, 7, 18, 0.6);
  color: var(--sys-text-dim);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.gender-toggle__option--selected {
  border-color: var(--sys-line);
  color: var(--sys-text);
  box-shadow: 0 0 16px rgba(34, 211, 238, 0.16);
}

.class-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 20px;
}

.class-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 10px 16px;
  border: 1px solid var(--sys-line-soft);
  border-radius: 2px;
  background: linear-gradient(170deg, rgba(10, 17, 36, 0.9), rgba(5, 8, 18, 0.95));
  color: var(--sys-text-dim);
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
}

.class-option--selected {
  border-color: var(--sys-cyan);
  box-shadow: 0 0 26px rgba(34, 211, 238, 0.22), inset 0 0 30px rgba(34, 211, 238, 0.06);
  transform: translateY(-2px);
}

/* Fixed height so switching gender or class never reflows the grid. */
.class-option__stage {
  position: relative;
  display: block;
  width: 100%;
  height: 180px;
}

/* A floor glow, so the sprite reads as standing on something. */
.class-option__stage::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 6px;
  width: 78px;
  height: 10px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(34, 211, 238, 0.35), transparent 70%);
}

.class-option__sprite {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  display: none;
}

/* Only the male warrior sheet's art is off-centre within its own frame —
   checked all four sheets directly: mage (both genders) and the female
   warrior already sit at their frame's horizontal middle, but the male
   warrior's sits ~40px (of the 128px frame) left of it, scaled by the same
   1.4x the sprite itself renders at. */
.class-option[data-class-type="warrior"] .class-option__sprite[data-sprite-gender="male"] {
  transform: translateX(-50%) translateX(42px);
}

/* Only the sprite matching the chosen gender is shown; the others stay in the
   DOM so their sheets are already decoded. */
[data-gender="male"] .class-option__sprite[data-sprite-gender="male"],
[data-gender="female"] .class-option__sprite[data-sprite-gender="female"] {
  display: block;
}

.class-option__name {
  font-size: 12px;
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  text-transform: uppercase;
  color: var(--sys-text);
}

.class-option--selected .class-option__name {
  color: #fff;
  text-shadow: 0 0 14px rgba(34, 211, 238, 0.6);
}

.class-option__blurb {
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--sys-text-faint);
}

/* ------------------------------------------------------- goal wizard -- */

/* A filling bar rather than discrete pips — three questions read better as
   continuous progress, and it reuses .sys-bar so it stays in step with the XP
   and achievement bars elsewhere. */
.wizard-progress {
  margin-top: 18px;
}

/* Matches the .sys-eyebrow treatment (uppercase, wide tracking, cyan) rather
   than reading as a plain question — kept a bit larger since it's a full
   sentence, not a short label. */
.wizard-question {
  margin-bottom: 16px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--sys-cyan);
}

.wizard-input {
  width: 100%;
  padding: 14px;
  border: 1px solid var(--sys-line-soft);
  border-radius: 2px;
  background: rgba(3, 7, 18, 0.65);
  color: var(--sys-text);
  /* 16px minimum, or iOS zooms the web view on focus. */
  font-size: 16px;
  font-family: inherit;
  line-height: 1.6;
  letter-spacing: 0.03em;
  resize: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.wizard-input:focus {
  outline: none;
  border-color: var(--sys-line);
  box-shadow: 0 0 0 1px rgba(34, 211, 238, 0.22), 0 0 20px rgba(34, 211, 238, 0.16);
}

.wizard-input::placeholder {
  color: rgba(232, 244, 255, 0.25);
}

.wizard-actions {
  display: flex;
  gap: 10px;
  align-items: stretch;
  margin-top: 20px;
}

/* The Back link is a link, not a button, so it needs the sizing a form control
   would get for free. */
.wizard-actions .sys-btn--ghost {
  width: auto;
  flex: 0 0 auto;
  padding-inline: 18px;
  text-decoration: none;
}

/* simple_form wraps even hidden inputs in a .mb-3 wrapper, so each one adds
   18px of empty space. Bootstrap's .hidden isn't loaded to collapse them. */
.sys-form .mb-3.hidden {
  display: none;
  margin: 0;
}
