/* The sign-in page, on its own (docs/OPTIMIZATION.md Phase 2a).

   login.html used to link style.css — the whole teacher app's CSS, and through
   its imports every page and game sheet and 306 KB of Japanese font slices:
   about 1.5 MB to draw one card. It now links tokens-core.css, base.css,
   manrope.css, controls.css and this file, which holds every rule the page
   uses and nothing else. The rules below were moved out of style.css
   unchanged; a computed-style comparison of the page before and after, in
   three themes and four states, is the proof they still draw the same thing.

   The title speaks in Zen Maru Gothic 700 (DESIGN.md "Typography"). Rather
   than the full 366-slice declaration file, this page declares only the three
   700-weight slices that cover Latin text — the same lines, byte for byte, as
   zen-maru-gothic.css (web/tests/login-css.test.mjs holds them together).
   Japanese typed into a field here falls back to the system face; nothing on
   this page is Japanese. */

@font-face{font-family:"Zen Maru Gothic";font-style:normal;font-weight:700;font-display:swap;src:url("/vendor/excalidraw-0.18.1-fonts/fonts/ZenMaruGothic/700-360.woff2") format("woff2");unicode-range:U+21-22, U+27-2a, U+2c-3b, U+3f, U+41-4d, U+4f-5d, U+61-7b, U+7d, U+ab, U+ae, U+b2-b3, U+b7, U+bb, U+c9, U+cd, U+d6, U+d8, U+dc, U+e0-e5, U+e7-ed, U+ef, U+f1-f4, U+f6, U+f8, U+fa, U+fc-fd, U+103, U+14d, U+1b0, U+300-301, U+1ebf, U+1ec7, U+2013-2014, U+201c-201d, U+2039-203a, U+203c, U+2048-2049, U+2113, U+2122, U+65e5, U+6708, U+70b9}
@font-face{font-family:"Zen Maru Gothic";font-style:normal;font-weight:700;font-display:swap;src:url("/vendor/excalidraw-0.18.1-fonts/fonts/ZenMaruGothic/700-361.woff2") format("woff2");unicode-range:U+20, U+2027, U+3001-3002, U+3041-307f, U+3081-308f, U+3091-3093, U+3099-309a, U+309d-309e, U+30a1-30e1, U+30e3-30ed, U+30ef-30f0, U+30f2-30f4, U+30fb-30fe, U+ff0c, U+ff0e}
@font-face{font-family:"Zen Maru Gothic";font-style:normal;font-weight:700;font-display:swap;src:url("/vendor/excalidraw-0.18.1-fonts/fonts/ZenMaruGothic/700-365.woff2") format("woff2");unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

/* ---- sign-in page --------------------------------------------------------
   One job, one window. The card is the app's window idiom (DESIGN.md
   "Windows": --raised, --radius-window, --shadow-window) on the app's own
   graph-paper ground, painted in the teacher's saved theme before the first
   frame (auth/theme-boot.js). Sign-in leads; recovery and sign-up are quiet
   links that open one panel at a time. Every colour below is a theme token,
   measured on all eleven themes. */
.auth-body {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}
/* Dark themes ask the browser for dark form controls and autofill too, or the
   terms checkbox is a white square on a dark card. */
body.auth-body:is([data-theme="onedark"], [data-theme="night"], [data-theme="tokyo-storm"],
  [data-theme="ayu-mirage"], [data-theme="ayu-dark"], [data-theme="violet-hour"]) { color-scheme: dark; }
.auth-body ::selection { background: color-mix(in srgb, var(--accent-edge) 26%, transparent); color: var(--ink); }
.auth-card {
  position: relative;
  width: 100%;
  max-width: 23rem;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-window);
  padding: 1.75rem 1.75rem 1.5rem;
  box-shadow: var(--shadow-window);
}
.auth-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.4rem;
}
/* The page's one display moment (DESIGN.md "Typography"). */
.auth-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
  color: var(--ink);
}
.auth-sub { margin: 0 0 1.4rem; color: var(--muted); font-size: 0.9rem; line-height: 1.5; }

/* Light or dark. A quiet icon control in the card's corner — sized for a
   finger, drawn in the app's 1.8 stroke — that shows where it will take you:
   the moon on a light theme, the sun on a dark one. */
.auth-theme {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: -0.55rem -0.65rem 0 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  /* --ink, not the resting-icon --muted: a control that changes the page needs
     3:1 against the card, and muted measures 2.96:1 on One Dark. */
  color: var(--ink);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.auth-theme:hover { background: var(--surface); }
.auth-theme:focus-visible { outline: 2px solid var(--accent-edge); outline-offset: 0; }
.auth-theme svg { width: 20px; height: 20px; }
.auth-theme .auth-theme-sun,
.auth-theme[data-mode="dark"] .auth-theme-moon { display: none; }
.auth-theme[data-mode="dark"] .auth-theme-sun { display: block; }

/* The divider survives only for the dev-build master-key form. */
.auth-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.25rem 0;
  color: var(--muted);
  font-size: 0.75rem;
}
.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* The buttons that open a passkey prompt. Tall enough to be the obvious
   target on an iPad held in one hand. While a prompt is open the button IS the
   status (login.js waiting(), recover.js waitOn()): its label says so, it is
   disabled so a second tap cannot start an overlapping prompt — without
   fading, because it is busy, not unavailable — and the app's waiting sweep
   (the one Quick Access search and Boards' hand-out use) runs back and forth
   along its foot, drawn in the button's own text colour so it reads on every
   theme's accent fill. Reduced motion: the line holds still. */
/* Two app-wide button details this page used to inherit from style.css: the
   soft shadow and press of every pressable button ("soft shadows on pressable
   buttons"), and the shared transition of interactive controls. Restated here,
   scoped to the card, because this page no longer loads that file — values
   unchanged, so a button reads the same on both sides of the sign-in. */
.auth-card .btn {
  box-shadow: 0 1px 2px rgba(44, 39, 31, 0.1), 0 2px 6px rgba(44, 39, 31, 0.07);
  transition:
    background-color var(--motion-fast) var(--ease-out),
    border-color var(--motion-fast) var(--ease-out),
    color var(--motion-fast) var(--ease-out),
    box-shadow var(--motion-fast) var(--ease-out);
}
.auth-card .btn:active { box-shadow: 0 1px 2px rgba(44, 39, 31, 0.12); transform: translateY(0.5px); }

.auth-go { position: relative; overflow: hidden; min-height: 48px; font-size: 1rem; }
.auth-go:disabled { cursor: default; }
.auth-go[aria-busy="true"] { cursor: progress; opacity: 1; }
.auth-go[aria-busy="true"]::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 7px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, currentColor 75%, transparent), transparent) 0 0 / 38% 100% no-repeat;
  animation: auth-wait 1.15s cubic-bezier(.45, 0, .55, 1) infinite alternate;
}
@keyframes auth-wait { from { background-position: -10% 0; } to { background-position: 110% 0; } }
@media (prefers-reduced-motion: reduce) {
  .auth-go[aria-busy="true"]::after { animation: none; background-size: 100% 100%; opacity: 0.45; }
}

/* Messages appear beside what caused them (login.js show()). Ink for news,
   --bad-text for trouble — never --clay or --moss, which as small text measure
   2.1:1 on the default theme. Empty, it takes no space but stays in the tree,
   so screen readers still hear it. */
.auth-msg { margin: 0.7rem 0 0; font-size: 0.875rem; line-height: 1.45; color: var(--ink); overflow-wrap: anywhere; }
.auth-msg:empty { margin: 0; }
.auth-msg[data-kind="bad"] { color: var(--bad-text); }

/* The other ways in. Quiet links — the few who need them are looking for them,
   and everybody else should see one button. Ink, underlined, never muted. */
.auth-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 1.1rem;
  margin-top: 0.85rem;
}
.auth-link {
  min-height: 44px;
  padding: 0 0.3rem;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.875rem;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--ink) 40%, transparent);
  text-underline-offset: 0.22em;
  cursor: pointer;
}
.auth-link:hover { text-decoration-color: currentColor; }
.auth-link:focus-visible { outline: 2px solid var(--accent-edge); outline-offset: -4px; border-radius: 6px; }

/* A panel (recovery, sign-up) replaces the sign-in button while it is open, so
   the card only ever asks one thing. */
.auth-card[data-panel] #login-btn,
.auth-card[data-panel] .auth-sub { display: none; }
.auth-panel {
  display: grid;
  gap: 0.6rem;
  margin-top: 0.75rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
}
.auth-panel-title { margin: 0; font-size: 1rem; font-weight: 700; line-height: 1.35; color: var(--ink); }
.auth-panel-intro { margin: 0 0 0.2rem; font-size: 0.85rem; line-height: 1.5; color: var(--ink); }
/* Fields on this card follow DESIGN.md's editable-field contract: the
   field-border at rest, the accent edge for the caret and focus. */
.auth-card .input { min-height: 46px; border-color: var(--field-border); caret-color: var(--accent-edge); }
/* The app's editable-field focus (style.css, "editable fields: clearer resting
   border on every theme"), which this page no longer loads. Kept here so a
   focused field looks exactly as it did: the contrast-tested edge, outlined. */
.auth-card .input:focus { border-color: var(--accent-edge); outline: 2px solid var(--accent-edge); outline-offset: 2px; }
.auth-panel .input:disabled { opacity: 0.6; }
/* The code is read off paper, so it is set like the sheet: monospaced (it is
   data, not a costume), spaced, upper case as it is typed. */
.auth-code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: 0.04em; text-transform: uppercase;
}
.auth-code::placeholder { text-transform: none; letter-spacing: 0; font-family: var(--font); }

@media (max-width: 480px) {
  .auth-body { padding: 1rem; }
  .auth-card { padding: 1.5rem 1.25rem 1.25rem; }
  .auth-title { font-size: 1.45rem; }
}

/* ---- the content undertaking on the sign-up form ------------------------
   Shown IN FULL rather than behind a link: an undertaking nobody reads is not
   one, and a link is how you make sure nobody does. Small, but at a line
   height that means it can actually be read. */
.auth-terms {
  display: flex;
  gap: 0.55rem;
  align-items: flex-start;
  margin: 0.15rem 0 0.1rem;
  font-size: 0.78rem;
  line-height: 1.45;
  /* --ink, NOT --muted. Measured: muted grey on the sign-in card is 3.86:1,
     under the 4.5:1 floor for text this size. Grey is how you signal "you may
     skip this" — the one thing this paragraph must not say. */
  color: var(--ink);
  cursor: pointer;
}

.auth-terms input {
  margin-top: 0.2rem;
  flex: none;
  width: 1rem;
  height: 1rem;
}
