/* ══════════════════════════════════════════════════════════════════════════
   Auth — the shared shell for login.html, join.html and setup.html.
   ──────────────────────────────────────────────────────────────────────────
   Phase 9 Wave 3. These three pages are reached by people who are not signed
   in and have no household bound, so they intentionally do not extend
   base.html: the nav, the profile menu, the theme picker and the toast system
   are either broken or meaningless to a stranger, and a page reached by
   strangers should load nothing it does not need (see the original note this
   file consolidates, previously repeated in each template).

   That includes base.html's runtime theme engine. Without it there is no
   saved preference to read and no CheckScheme.apply() to derive contrast-safe
   accent variants, so this file locks the four base tokens — and the two
   values that engine would otherwise compute — to fixed values instead of
   reading design-system.css's runtime-driven ones. That is also why these
   three templates are not on test_ui_invariants.py's MIGRATED ledger: its
   "no literal colours" rule assumes a page that inherits its palette from the
   runtime engine, which by design these do not.

   The values below are THEMES.light from base.html (the app's default
   theme), so a signed-out visitor and a freshly signed-in one see the same
   product:

     --auth-bg / --auth-fg / --auth-panel / --auth-border / --auth-accent
       copied verbatim from THEMES.light in base.html. If that entry ever
       changes, this block should change with it.

     --auth-accent-on / --auth-accent-ink
       what base.html's CheckScheme (rgb/lum/contrast/onColor/readable) would
       compute for THEMES.light, worked out the same way and pinned here:
         onColor(#c47d5a)            -> contrast(white)=3.27, contrast(#111113)=5.77
                                         -> #111113 wins, so accent-on is dark text
         readable(#c47d5a, #faf6f0)  -> raw copper is 3.03:1 on the panel, which
                                         fails 4.5:1; stepping toward black lands
                                         on #935e44 at the first passing mix
       A dark-text primary button is a real difference from an earlier version
       of these pages, which used a hand-darkened copper fill with white text
       instead — a plausible guess that did not actually match what
       .ds-btn--primary renders for Light everywhere else in the product. This
       is the value that does.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  --auth-bg:         #f0ebe3;
  --auth-fg:         #5a5248;
  --auth-panel:      #faf6f0;
  --auth-border:     #d4cdc2;
  --auth-accent:     #c47d5a;
  --auth-accent-on:  #111113;
  --auth-accent-ink: #935e44;

  /* Matches design-system.css's own static --danger-ink: error text is not
     theme-accented, so it does not need the same derivation as the above. */
  --auth-danger: #b91c1c;

  /* The rest of the semantic ramp, for .auth-flash. Copied verbatim from
     design-system.css's light-theme block (--ok-ink / --warn-ink / --info-ink
     and their -mark pairs) for the same reason --auth-danger is: these are
     static in the design system too, so there is nothing to derive.

     The tints mirror design-system.css's own `-bg` recipe, with --auth-panel
     substituted for --panel — these pages are always on the light card, so the
     mix has a fixed base rather than a runtime one. */
  --auth-ok:    #15803d;  --auth-ok-mark:    #16a34a;
  --auth-warn:  #a1620a;  --auth-warn-mark:  #f59e0b;
  --auth-info:  #1d4ed8;  --auth-info-mark:  #3b82f6;
  --auth-danger-mark: #ef4444;

  --auth-ok-bg:     color-mix(in srgb, var(--auth-ok-mark)     11%, var(--auth-panel));
  --auth-warn-bg:   color-mix(in srgb, var(--auth-warn-mark)   13%, var(--auth-panel));
  --auth-info-bg:   color-mix(in srgb, var(--auth-info-mark)   11%, var(--auth-panel));
  --auth-danger-bg: color-mix(in srgb, var(--auth-danger-mark) 11%, var(--auth-panel));

  --auth-muted: color-mix(in srgb, var(--auth-fg) 70%, transparent);
  --auth-ghost: color-mix(in srgb, var(--auth-fg) 45%, transparent);
  --auth-code-bg: color-mix(in srgb, var(--auth-fg) 12%, var(--auth-bg));

  --auth-r-sm: 8px;
  --auth-r-lg: 14px;

  /* dough.css reads --red for Dough's prop accent (--dough-accent: var(--red,
     #7c3aed)). Without this, every mascot on these pages renders his prop in
     the design system's fallback violet instead of the Light theme's copper —
     a real mismatch on a page whose whole point is "this looks like Dough,"
     caught while giving error.html the same treatment for the same reason. */
  --red: var(--auth-accent);
}

* { box-sizing: border-box; }

body.auth-shell {
  margin: 0;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--auth-bg);
  color: var(--auth-fg);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* ── Layout ────────────────────────────────────────────────────────────── */

.auth-wrap { width: 320px; }

/* login.html only: Dough overlaps the card's top edge, so the first thing on
   screen is the character rather than a form. */
.auth-hello {
  display: flex;
  justify-content: center;
  margin-bottom: -26px;
  position: relative;
  z-index: 1;
}

/* ── Brand lockup ──────────────────────────────────────────────────────────
   The mascot — above the card on login/forgot/reset, beside it on
   register/join — is the only branding these pages carry, so it is also the
   first thing somebody clicks when they want to get back out, and until it was
   a link, clicking it did nothing at all. The markup is one partial:
   templates/_auth_brand.html, which is also where the reasoning about *which*
   pages get it lives.

   The wordmark sits *above* Dough, not below him, because below is where
   .auth-hello's negative margin puts him over the card: a word there would
   land inside the card's padding, on top of "Welcome back". It is hidden
   (still in the accessible name) on the one page whose next line already says
   "Hi! I'm Dough."

   Nothing here is a button. The link inherits the page's own type and the
   focus ring shape .auth-btn and .auth-cta already use, so the brand reads as
   branding rather than as a second action competing with Sign in.
   ────────────────────────────────────────────────────────────────────────── */
.auth-brand {
  /* inline-flex, not flex: in .auth-intro this link replaced a bare mascot and
     must keep sitting wherever that column's text-align puts it — left on a
     desktop grid, centred once the columns stack. A block-level box would be
     the full width of the column and would centre the mascot on both. Inside
     .auth-hello it is a flex item either way, so nothing changes there. */
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-decoration: none;
  color: inherit;
  border-radius: var(--auth-r-lg);
}

/* --auth-fg rather than --auth-muted: at .8rem this is small text, and the
   muted mix lands at 3.3:1 on --auth-bg. A wordmark nobody can read is not a
   wordmark. */
.auth-brand__word {
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--auth-fg);
}
.auth-brand:hover .auth-brand__word { color: var(--auth-accent-ink); }
.auth-brand:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--auth-bg), 0 0 0 4px var(--auth-accent);
}

/* ── Back to the public page ───────────────────────────────────────────────
   Outside the card rather than in it: this is navigation away from the page,
   not a third thing to do with the form. That also keeps it clear of the
   flash banners, which stack at the top of the card — a message and the way
   out never compete for the same space, on a phone or anywhere else.
   ────────────────────────────────────────────────────────────────────────── */
.auth-back {
  margin: 14px 0 0;
  text-align: center;
  font-size: .78rem;
}
/* Two classes deep on purpose: join.html's dead-invitation branch renders this
   inside .auth-intro, whose own `a` rule is one class *and* one type and would
   otherwise win. The way out should read the same on every page it appears on. */
.auth-back .auth-back__link {
  color: var(--auth-fg);
}
.auth-back__link {
  display: inline-block;
  /* Padding rather than a height: it takes the target past the 24px WCAG 2.5.8
     asks for -- .78rem of text is about 15px on its own -- without giving the
     link a box a reader could mistake for a button. */
  padding: 6px 12px;
  border-radius: var(--auth-r-sm);
  text-decoration: none;
}
.auth-back__link:hover { color: var(--auth-accent-ink); text-decoration: underline; }
.auth-back__link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--auth-bg), 0 0 0 4px var(--auth-accent);
}
/* The glyph is decoration -- the word "Back" already says it -- and a screen
   reader that announced it would read "left arrow" mid-sentence. */
.auth-back__arrow { margin-right: .4em; }

/* join.html / setup.html: an introduction column beside the card. On a phone
   the columns stack, mascot first. */
.auth-split {
  width: auto;
  display: grid;
  grid-template-columns: minmax(0, 300px) 320px;
  gap: 40px;
  align-items: center;
}
@media (max-width: 700px) {
  .auth-split { grid-template-columns: 1fr; gap: 20px; max-width: 340px; }
  .auth-intro { text-align: center; }
  /* .dough is display:block, so text-align on the column does not centre it
     on its own — it needs its own margin. */
  .auth-intro .dough { margin: 0 auto; }
}

/* The card plus whatever sits under it — today the way home — as a single item
   in .auth-split's second track. Auto-placement would otherwise drop that link
   into the *first* column on a new row, under the introduction instead of
   under the form it belongs to. */
.auth-column { display: flex; flex-direction: column; }

/* join.html's message-only branches (invalid link, already signed in): a
   single centred column rather than the two-column grid, which would
   otherwise reserve an empty 320px card track and push the message off
   centre. See the comment in join.html. */
.auth-solo { width: 340px; text-align: center; }
.auth-solo .auth-intro p { color: var(--auth-muted); }
.auth-solo .auth-intro .dough { margin: 0 auto; }

.auth-intro h2 {
  font-size: 1.4rem;
  margin: 14px 0 10px;
  letter-spacing: -.02em;
}
.auth-intro p {
  font-size: .85rem;
  line-height: 1.55;
  color: var(--auth-muted);
  margin: 0 0 10px;
}
.auth-intro a { color: var(--auth-accent-ink); }
.auth-intro ul { margin: 0; padding: 0; list-style: none; }
.auth-intro li {
  font-size: .85rem;
  line-height: 1.5;
  color: var(--auth-muted);
  padding-left: 20px;
  position: relative;
  margin-bottom: 8px;
}
.auth-intro li::before {
  content: '';
  position: absolute;
  left: 0; top: .5em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--auth-accent);
  opacity: .7;
}

/* ── Card ──────────────────────────────────────────────────────────────── */

.auth-card {
  background: var(--auth-panel);
  border: 1px solid var(--auth-border);
  border-radius: var(--auth-r-lg);
  box-shadow: 0 4px 24px color-mix(in srgb, black 8%, transparent);
  padding: 40px 32px 32px;
  width: 320px;
  text-align: left;
}
/* join.html / setup.html sit in the grid rather than centred alone, and their
   heading sits directly under the card's own top edge instead of overlapping
   a mascot above it. */
.auth-split .auth-card { padding: 32px; }

.auth-card h1 { font-size: 1.15rem; margin: 0 0 4px; }
.auth-card > p:not(.auth-hint) { font-size: .8rem; color: var(--auth-muted); margin: 0 0 20px; }

/* ── Form ──────────────────────────────────────────────────────────────── */

.auth-field { margin-bottom: 12px; }

/* Visible labels would duplicate the placeholder text these forms were
   designed around; hidden-but-real ones give the same accessible name to
   assistive tech without the visual redesign that showing both would need. */
.auth-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.auth-input {
  width: 100%;
  padding: 10px 12px;
  font-size: 16px; /* iOS Safari zooms the viewport below this on focus */
  font-family: inherit;
  color: inherit;
  background: var(--auth-panel);
  border: 1px solid var(--auth-border);
  border-radius: var(--auth-r-sm);
}
.auth-input:focus {
  outline: none;
  border-color: var(--auth-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--auth-accent) 22%, transparent);
}
.auth-input[aria-invalid="true"] { border-color: var(--auth-danger); }

.auth-hint {
  font-size: .72rem;
  color: var(--auth-ghost);
  margin: -6px 0 12px;
}

/* The trailing hint under a form's button -- "Forgotten your password?",
   "Already have one?" -- rather than one sitting under a field it explains.
   A class because it was three identical `style="text-align:center;
   margin-top:14px"` attributes, which is the one thing this file exists to
   stop: a page-local colour or spacing decision that no token can reach. */
.auth-hint--center {
  text-align: center;
  margin-top: 14px;
}

/* The links inside a hint -- "Forgotten your password?", "Create one",
   "Sign in" -- were the one place on these pages still rendering in the
   browser's default blue, which is a literal colour arriving by omission
   rather than by decision, and it sat next to a copper button. Same ink
   .auth-intro's links already use, and the same focus ring as every other
   control here. */
.auth-hint a {
  color: var(--auth-accent-ink);
  border-radius: 3px;
}
.auth-hint a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--auth-panel), 0 0 0 4px var(--auth-accent);
}

.auth-error {
  font-size: .8rem;
  color: var(--auth-danger);
  margin: 0 0 12px;
}

/* ── Flashed messages ──────────────────────────────────────────────────────
   Why a system, when .auth-error above is one line: .auth-error is *this
   form's* validation result and belongs beside the fields it invalidated.
   These are about something that already happened somewhere else — a sign-out,
   an expiry, a password change — and read as a banner over the whole card.

   Sized to the 320px card, which is also the phone width: the card does not
   change size across breakpoints (only .auth-split's surrounding grid does),
   so this needs no media query to work on a phone. `overflow-wrap: anywhere`
   is what actually earns that — the longest message here is comfortably over
   one line at 320px.
   ────────────────────────────────────────────────────────────────────────── */
.auth-flashes {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 16px;
}

.auth-flash {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--auth-border);
  /* Colour is carried by a left rule and a tint, never by the text alone —
     the same pattern as .ds-toast, and the reason the message still reads as
     the right kind of message in a screenshot with no colour. */
  border-left: 3px solid var(--auth-ghost);
  border-radius: var(--auth-r-sm);
  background: var(--auth-panel);
}

.auth-flash__msg {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  margin: 0;
  font-size: .8rem;
  line-height: 1.5;
}

.auth-flash--ok     { border-left-color: var(--auth-ok-mark);     background: var(--auth-ok-bg); }
.auth-flash--warn   { border-left-color: var(--auth-warn-mark);   background: var(--auth-warn-bg); }
.auth-flash--info   { border-left-color: var(--auth-info-mark);   background: var(--auth-info-bg); }
.auth-flash--danger { border-left-color: var(--auth-danger-mark); background: var(--auth-danger-bg); }

.auth-flash--ok     .auth-flash__msg { color: var(--auth-ok); }
.auth-flash--warn   .auth-flash__msg { color: var(--auth-warn); }
.auth-flash--info   .auth-flash__msg { color: var(--auth-info); }
.auth-flash--danger .auth-flash__msg { color: var(--auth-danger); }

.auth-flash__close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 24px, not the 16px the glyph wants. This is the only control on the page
     that is not full width, and on a phone it is the one that gets missed. */
  width: 24px;
  height: 24px;
  margin: -2px -4px 0 0;
  padding: 0;
  border: 0;
  border-radius: var(--auth-r-sm);
  background: transparent;
  color: currentColor;
  opacity: .6;
  font-family: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.auth-flash__close:hover { opacity: 1; }
.auth-flash__close:focus-visible {
  outline: none;
  opacity: 1;
  box-shadow: 0 0 0 2px var(--auth-panel), 0 0 0 4px var(--auth-accent);
}

.auth-btn {
  width: 100%;
  padding: 10px;
  font-size: .9rem;
  font-weight: 600;
  font-family: inherit;
  color: var(--auth-accent-on);
  background: var(--auth-accent);
  border: none;
  border-radius: var(--auth-r-sm);
  cursor: pointer;
}
.auth-btn:hover { background: color-mix(in srgb, var(--auth-accent) 86%, var(--auth-fg)); }
.auth-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--auth-panel), 0 0 0 4px var(--auth-accent);
}

/* ── Notice (error.html) ───────────────────────────────────────────────────
   No card — the message sits directly on the page background, since there is
   nothing to separate it from: this is the whole page. ───────────────────── */

.auth-notice { max-width: 30rem; padding: 2.5rem 2rem; text-align: center; }
/* Full frame, not the avatar disc: this is an empty state, and it is the one
   place `searching` needs its magnifier — a tight crop drops props.
   inline-flex so the SVG centres on the block instead of sitting on a text
   baseline with a descender gap under it. */
.auth-notice__hero { display: flex; justify-content: center; }
.auth-notice h1 { font-size: 1.35rem; font-weight: 650; margin: 1.25rem 0 .5rem; }
.auth-notice p { color: var(--auth-muted); line-height: 1.6; margin: 0 0 1.5rem; }
.auth-notice__ref { font-size: .78rem; color: var(--auth-muted); margin-top: 2rem; }
.auth-notice__ref code {
  background: var(--auth-code-bg);
  padding: .15em .45em;
  border-radius: 4px;
  font-size: .95em;
  user-select: all;
}

.auth-cta {
  display: inline-block;
  padding: .6rem 1.1rem;
  border-radius: var(--auth-r-sm);
  background: var(--auth-accent);
  color: var(--auth-accent-on);
  text-decoration: none;
  font-size: .9rem;
  font-weight: 550;
}
.auth-cta:hover { background: color-mix(in srgb, var(--auth-accent) 86%, var(--auth-fg)); }
.auth-cta:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--auth-bg), 0 0 0 4px var(--auth-accent);
}
