/* Colours come from the group's chosen look when one is applied, with the
   original value as the fallback so an unthemed page is unchanged. Only
   allowlisted tokens reach here, and every published preset passes the
   WCAG AA contrast gate, so a look cannot make a security form unreadable. */
:root {
  font-family: system-ui, sans-serif;
  color: var(--page-ink, #173333);
  background: var(--page-bg, #f5f3ed);
  font-size: 17px;
  line-height: 1.55;
}
* {
  box-sizing: border-box;
}
body {
  margin: 0;
}
main {
  max-width: 760px;
  margin: auto;
  padding: 28px 20px 70px;
}
header {
  border-bottom: 2px solid var(--surface-edge, #bbc7bd);
  margin-bottom: 28px;
  padding-bottom: 20px;
}
.eyebrow {
  font-weight: 800;
  letter-spacing: 0.18em;
  color: var(--accent, #2e665c);
}
h1 {
  font-size: clamp(2rem, 7vw, 3rem);
  line-height: 1.15;
  letter-spacing: -0.03em;
}
h2 {
  margin-top: 0;
}
section {
  background: var(--surface, white);
  border: 1px solid var(--surface-edge, #d4dbd2);
  border-radius: 14px;
  padding: 24px;
  margin: 20px 0;
}
label {
  display: block;
  font-weight: 650;
  margin: 18px 0 8px;
}
input {
  display: block;
  width: 100%;
  padding: 12px;
  border: 1px solid var(--surface-edge, #637871);
  border-radius: 7px;
  background: var(--surface, #fff);
  font: inherit;
  margin-top: 6px;
}
button {
  min-height: 48px;
  border: 0;
  border-radius: 8px;
  background: var(--accent, #20594f);
  color: var(--accent-ink, white);
  font: inherit;
  font-weight: 700;
  padding: 12px 20px;
  cursor: pointer;
  margin: 10px 8px 8px 0;
}
button.secondary {
  background: var(--mine-surface, #e5ece6);
  color: var(--mine-ink, #173e35);
}
button:disabled {
  opacity: 0.6;
  cursor: wait;
}
button:focus-visible,
input:focus-visible,
a:focus-visible {
  outline: 3px solid #9d4b11;
  outline-offset: 3px;
}
fieldset {
  border: 1px solid var(--surface-edge, #c7d0c6);
  border-radius: 8px;
  margin-top: 24px;
  padding: 16px;
}
footer {
  font-size: 0.85rem;
  margin-top: 40px;
  color: var(--page-ink, #496059);
}
#notice:not(:empty) {
  padding: 16px;
  border-left: 5px solid var(--accent, #2e665c);
  background: var(--mine-surface, #e1eae1);
  overflow-wrap: anywhere;
}
#authenticator-key,
#signup-link {
  overflow-wrap: anywhere;
}
.person {
  padding: 18px 0;
  border-bottom: 1px solid var(--surface-edge, #c7d0c6);
}
.person p {
  margin: 4px 0;
}
[hidden] {
  display: none !important;
}
@media (max-width: 450px) {
  main {
    padding: 20px 12px 40px;
  }
  section {
    padding: 18px;
  }
  button {
    width: 100%;
  }
}
@media (prefers-reduced-motion: no-preference) {
  button:hover {
    filter: brightness(0.93);
  }
}

pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font: inherit;
  background: var(--surface, #f1f5ef);
  padding: 12px;
  border-radius: 6px;
}
a {
  color: var(--link-ink, #20594f);
}

/* Password reveal toggle. The label keeps its own line so the field stays
   full width; the button sits beside the input at a touch-sized target. */
.password-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}
.password-row label {
  flex: 1;
  min-width: 0;
}
button.reveal {
  color: var(--link-ink, #20594f);
  flex: none;
  /* The narrow-width rule makes every button full width, which would take the
     whole row and collapse the field beside it to nothing. */
  width: auto;
  min-height: 48px;
  min-width: 48px;
  padding: 0;
  margin: 0;
  display: grid;
  place-items: center;
  background: none;
  border: 1px solid var(--surface-edge, #9babad);
}
button.reveal[aria-pressed="true"] {
  background: var(--mine-surface, #e7efeb);
}

/* A refusal must not wear the same green as a confirmation. "Those passwords
   don't match" in a success banner reads as "done" at a glance, which on a
   forced password change is exactly the wrong conclusion. */
#notice.problem:not(:empty) {
  border-left-color: #a2401a;
  background: #f6e7df;
}

/* ─── The shrine ──────────────────────────────────────────────────────────
   Todd, haloed, on the screen everyone passes through on the way in. It is
   decoration: pointer-events are off and it sits below the form at every
   width, so it can never swallow a tap meant for the password field. It
   appears only while signed out, because once you are in, the room is the
   point. */
main {
  position: relative;
  z-index: 1;
}
/* Give the form its own column so it never runs underneath him. Below this
   width he shrinks and steps behind instead, because the fields win. */
@media (min-width: 1120px) {
  body:has(#login-panel:not([hidden])) main {
    margin-left: max(20px, calc(50% - 660px));
    margin-right: 420px;
  }
}
#shrine {
  position: fixed;
  right: 0;
  bottom: 0;
  width: min(34vw, 380px);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
/* Hidden the moment a panel other than sign-in is showing. */
body:has(#login-panel[hidden]) #shrine {
  display: none;
}
#todd-portrait {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 10px 18px rgb(0 0 0 / 22%));
}
.rays {
  position: absolute;
  left: 52%;
  top: 4%;
  width: 190%;
  aspect-ratio: 1;
  transform: translate(-50%, -34%);
  background: repeating-conic-gradient(
    from 0deg,
    #d9b23f 0deg 3.2deg,
    transparent 3.2deg 10deg
  );
  mask-image: radial-gradient(closest-side, #000 12%, transparent 68%);
  opacity: 0.55;
}
.plaque {
  position: absolute;
  left: -14%;
  bottom: 16%;
  margin: 0;
  max-width: 62%;
  padding: 8px 12px;
  background: var(--surface, #fff);
  color: var(--surface-ink, #173333);
  border: 2px solid currentColor;
  border-radius: 20px 28px 22px 30px / 30px 20px 32px 22px;
  transform: rotate(-3deg);
  font-size: 0.72rem;
  line-height: 1.25;
  text-transform: lowercase;
  box-shadow: 3px 4px 0 rgb(0 0 0 / 14%);
}
.plaque span {
  display: block;
  font-size: 1.1rem;
  font-weight: 800;
  text-transform: none;
}
/* Slow enough to be a halo rather than a spinner, and only for people who
   have not asked for stillness. */
@media (prefers-reduced-motion: no-preference) {
  .rays {
    animation: shrine-turn 90s linear infinite;
  }
}
@keyframes shrine-turn {
  to {
    transform: translate(-50%, -34%) rotate(360deg);
  }
}
/* Below the two-column width he has to share space with the form, so he
   steps back to a presence rather than a portrait. The fields win. */
@media (max-width: 1119px) {
  #shrine {
    width: min(42vw, 230px);
    right: 0;
    opacity: 0.45;
  }
  .plaque {
    font-size: 0.62rem;
    max-width: 70%;
  }
}
@media (max-width: 560px) {
  #shrine {
    width: 165px;
    opacity: 0.32;
  }
  .plaque {
    display: none;
  }
}
