/* ---------- self-hosted faces ----------
   These used to come from fonts.googleapis.com behind a render-blocking
   stylesheet, which cost a DNS lookup, a TLS handshake and a round trip to a
   third party before a single glyph could paint — and told Google who was
   reading the page. Same files, same origin, one year immutable.
   Archivo is the VARIABLE cut, so one file covers 500-800 rather than four.
   unicode-range keeps latin-ext off the wire for anyone who never needs it. */
@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/anton-latin.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;
}
@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/anton-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/archivo-latin.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;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* AWAKE Accounts — collage tokens, quiet account chrome */
:root {
  --paper: #ece7db;
  --paper-deep: #e0dac9;
  --ink: #141312;
  --mint: #d9e8cf;
  /* matched to style.css / awake.css: #6b675f was 4.03:1 on --paper-deep,
     under AA, and this token carries every 10-11px label on these pages */
  --muted: #57534b;
  --font: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --display: "Anton", "Archivo", sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* The [hidden] attribute is how every script on these pages shows and hides
   things, but the browser's own `[hidden] { display: none }` is a USER-AGENT
   rule — any author rule that sets `display` beats it, and the element stays
   on screen with `.hidden = true` quietly doing nothing. It has already bitten
   .skeleton, .uid-copy and #pwMeter here. One rule closes the whole class. */
[hidden] { display: none !important; }

body {
  font-family: var(--font);
  background: var(--paper);
  color: var(--ink);
  min-height: 100vh;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
}

.grain {
  position: fixed; inset: 0; z-index: 100; pointer-events: none; opacity: 0.45;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.10 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

.wrap {
  position: relative; z-index: 1;
  max-width: 420px;
  margin: 0 auto;
  padding: 88px 22px 64px;
}

.brand {
  display: inline-block;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--display);
  font-size: 22px;
  letter-spacing: 0.02em;
  padding: 8px 14px;
  text-decoration: none;
  margin-bottom: 28px;
}

h1 {
  font-family: var(--display);
  font-size: clamp(40px, 10vw, 56px);
  line-height: 0.92;
  text-transform: uppercase;
  margin: 0 0 10px;
}

.lede {
  color: var(--muted);
  font-size: 14px;
  margin-bottom: 28px;
}

label {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 8px;
}

/* password was missing here, so the change-password fields rendered at the
   browser default width while the two above them were full width */
input[type="email"],
input[type="password"],
input[type="text"] {
  width: 100%;
  border: 1.5px solid var(--ink);
  background: var(--paper-deep);
  color: var(--ink);
  font: 500 15px/1.3 var(--font);
  padding: 12px 14px;
  margin-bottom: 16px;
}

button,
.btn {
  display: inline-block;
  border: 1.5px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font: 700 11px/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 12px 16px;
  cursor: pointer;
  text-decoration: none;
}

button.ghost,
.btn.ghost {
  background: var(--paper-deep);
  color: var(--ink);
}

button:disabled,
.btn:disabled {
  opacity: 0.5;
  cursor: default;
}

/* a hard-edged double ring — the registration-mark motif — replaces the
   browser's default blue glow, which was the loudest "unfinished" tell on
   a warm-paper B&W page. :focus-visible so a mouse click never leaves one. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
.linkish:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px var(--paper), 0 0 0 6px var(--ink);
}

.row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 8px; }

.msg {
  margin: 16px 0;
  padding: 12px 14px;
  border: 1.5px solid var(--ink);
  background: var(--mint);
  font-size: 13px;
}

.msg.error { background: #f0d9d4; }
.msg.soft { background: var(--paper-deep); color: var(--muted); }

.meta {
  margin-top: 28px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.meta a { color: var(--ink); }

/* the split-second the success message actually gets to register before
   the tab navigates away — letter-spacing has no layout cost to animate */
button.submit-ok {
  background: var(--ink);
  color: var(--paper);
  letter-spacing: 0.14em;
  transition: letter-spacing 0.2s ease;
}

.profile {
  border: 1.5px solid var(--ink);
  background: var(--paper-deep);
  padding: 16px;
  margin: 18px 0;
}

.profile dt {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 10px;
}
.profile dt:first-child { margin-top: 0; }
.profile dd { font-size: 15px; margin-top: 4px; }

/* the user id is the one field on this page a dev actually wants to grab */
.uid-chip {
  font-family: var(--mono);
  font-size: 12px;
  word-break: break-all;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
}
.uid-copy {
  border: 1px solid var(--ink);
  background: var(--paper);
  /* the base `button` rule sets color: var(--paper); without this the label
     was paper on paper — a 1.00:1 button that only appeared once you'd
     already clicked it */
  color: var(--ink);
  font: 700 9px/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  /* padded past the 5px the brief spec'd — 9px/1 type at 5px top/bottom
     lands ~21px tall, under the 24px minimum tap target */
  padding: 7px 10px;
  cursor: pointer;
  flex-shrink: 0;
}
.uid-copy.copied { background: var(--ink); color: var(--paper); }

/* skeleton rows fill the gap between paint and getSession() resolving —
   a real IdP account page never shows a blank beat under the h1. Hatch
   pattern (not a smooth shimmer) so it reads as print texture. */
.skeleton { display: flex; flex-direction: column; gap: 10px; margin: 18px 0; }
.skeleton span {
  display: block;
  height: 14px;
  background: repeating-linear-gradient(45deg, var(--paper-deep) 0 4px, var(--ink) 4px 5px);
  opacity: 0.3;
}
.skeleton span:nth-child(1) { width: 60%; }
.skeleton span:nth-child(2) { width: 40%; }
@media (prefers-reduced-motion: no-preference) {
  .skeleton span { animation: skel-pulse 1.1s ease-in-out infinite; }
}
@keyframes skel-pulse {
  0%, 100% { opacity: 0.22; }
  50% { opacity: 0.45; }
}

.scopes {
  list-style: none;
  margin: 16px 0;
}
.scopes li {
  border: 1px solid var(--ink);
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--paper-deep);
  font-size: 13px;
}

/* the client name resolves async — hatch it out rather than let the
   generic "An app" fallback read as final copy on a slow connection */
.lede strong.loading {
  background: repeating-linear-gradient(45deg, var(--muted) 0 3px, transparent 3px 6px);
  color: transparent;
  display: inline-block;
  min-width: 64px;
}

/* the one moment that visually confirms the grant happened before the
   browser leaves the page — .wrap is already position:relative */
.stamp {
  position: absolute;
  top: 38%;
  left: 50%;
  font-family: var(--display);
  font-size: 36px;
  letter-spacing: 0.04em;
  border: 3px solid var(--ink);
  padding: 4px 14px;
  transform: translate(-50%, -50%) rotate(-8deg) scale(0.6);
  opacity: 0;
  transition: transform 0.22s cubic-bezier(0.2, 1.4, 0.4, 1), opacity 0.22s linear;
  pointer-events: none;
}
.stamp.show { opacity: 1; transform: translate(-50%, -50%) rotate(-8deg) scale(1); }

/* ---------- password field: show/hide, caps warning, strength ----------
   Added when email+password became the primary rail (magic link alone left
   the IdP with no working sign-in whenever mail was down). */
.pw-field { position: relative; }
.pw-field input { width: 100%; padding-right: 62px; box-sizing: border-box; }
.pw-peek {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  font: inherit;
  font-size: 12px;
  padding: 6px 8px;
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  opacity: 0.7;
}
.pw-peek:hover, .pw-peek[aria-pressed="true"] { opacity: 1; border-color: currentColor; }

/* closed by default, opens on .on — the warning most likely to arrive
   mid-keystroke deserves to announce itself, not flicker via [hidden]. */
.caps {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  margin: 0;
  padding: 0 8px;
  font-size: 12px;
  font-weight: 600;
  background: #141312;
  color: #ece7db;
  transition: max-height 0.16s ease, opacity 0.16s ease, padding 0.16s ease, margin 0.16s ease;
}
.caps.on { max-height: 32px; opacity: 1; margin: 6px 0 0; padding: 5px 8px; }
@media (prefers-reduced-motion: reduce) {
  .caps { transition: none; }
}

.pw-meter { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; }
.pw-bar { flex: 1; height: 4px; background: #e0dac9; border: 1px solid #6b675f; }
/* strength differentiates by pattern, not just fill width — a B&W product's
   equivalent of color-coding, and legible from shape alone even zoomed out. */
.pw-bar i { display: block; height: 100%; width: 0; transition: width 0.18s ease; }
.pw-bar i.weak { background: repeating-linear-gradient(45deg, #141312 0 2px, transparent 2px 4px); }
.pw-bar i.ok { background: repeating-linear-gradient(90deg, #141312 0 6px, transparent 6px 8px); }
.pw-bar i.strong { background: #141312; }
.pw-word { font-size: 11px; font-weight: 600; opacity: 0.75; min-width: 46px; text-align: right; }

/* a button that reads as a link — used for the email-dependent fallbacks */
/* "Forgot password" and "email me a link instead" are the two things a stuck
   person needs most, and they were 11px of text with no padding — roughly a
   13px-tall target, well under the 24px minimum and miserable on a thumb.
   The padding grows the hit area; the matching negative margin keeps the page
   looking exactly the same. */
.linkish {
  font: inherit;
  background: none;
  border: none;
  display: inline-block;
  padding: 9px 4px;
  margin: -9px -4px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  color: inherit;
}
.linkish:hover { background: var(--paper-deep); }
/* same treatment for the plain anchors that sit in these rows */
.meta a {
  display: inline-block;
  padding: 9px 4px;
  margin: -9px -4px;
}
.meta a:hover { background: var(--paper-deep); }
.meta.fine { font-size: 12px; opacity: 0.75; }

/* ---------- owner stats (only ever rendered for the owner account) ---------- */
.stats-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 28px 0 10px;
  border-bottom: 1.5px solid var(--ink);
  padding-bottom: 6px;
}
.stats-tag {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
}
.stats-sub {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  color: var(--muted);
}
/* a degraded health check is the one thing on this page that should shout */
.stats-sub.is-bad {
  background: var(--ink);
  color: var(--paper);
  padding: 2px 6px;
}
.stats-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 12px;
  margin-bottom: 16px;
}
.stats-grid dt {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  align-self: center;
}
.stats-grid dd {
  font-family: var(--display);
  font-size: 22px;
  line-height: 1;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.stats-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.stats-table th {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-align: left;
  color: var(--muted);
  border-bottom: 1px solid var(--ink);
  padding: 4px 0;
}
.stats-table th:last-child, .stats-table td:last-child { text-align: right; }
.stats-table td {
  font-family: var(--mono);
  font-size: 12px;
  padding: 5px 0;
  border-bottom: 1px dashed var(--muted);
}

/* ---------- editable name row ---------- */
.name-row { display: flex; align-items: center; }
.name-view,
.name-edit {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  width: 100%;
}
.name-edit input[type="text"] { flex: 1; min-width: 120px; margin-bottom: 0; }

/* ---------- password-manager username anchor ----------
   Chrome and Safari won't offer to update a saved credential on a form
   with no username field. This one is real (its value is set from the
   session) but must never use display:none or [hidden] — either makes
   password managers skip it outright. Off-screen via clip, not display. */
.pm-username {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- connected apps / devices ----------
   Same card language as .scopes, extended with an info column + an action
   so a row can carry "what" and "revoke it" without a second component. */
.app-list { list-style: none; margin: 16px 0; }
.app-list li {
  border: 1px solid var(--ink);
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--paper-deep);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.app-info { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.app-name { font-size: 14px; font-weight: 600; word-break: break-word; }
.app-meta {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--muted);
  word-break: break-word;
}
.app-list button { flex-shrink: 0; }

/* ---------- consent facts (who/where, on the highest-trust screen) ---------- */
.consent-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 12px;
  margin: 16px 0;
  padding: 12px;
  border: 1px solid var(--ink);
  background: var(--paper-deep);
}
.consent-facts dt {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.consent-facts dd { font-size: 13px; word-break: break-all; }
/* padded to clear the 24px tap-target minimum — a bare inline link at
   13px/1.4 is only ~18px tall */
.consent-facts a {
  color: var(--ink);
  display: inline-block;
  padding: 5px 2px;
  margin: -5px -2px;
}
/* full ink/paper inversion, not --mint — mint is reserved for live/risk
   states elsewhere on the site and this warning is exactly that kind of
   risk state here, but the brief's palette keeps mint off account chrome. */
.consent-warn { background: var(--ink); color: var(--paper); padding: 4px 6px; grid-column: 1 / -1; }
