/* Auth: the /login card and the placeholder dashboard. */

.auth-page {
  display: grid;
  place-items: center;
  min-height: 60vh;
  padding: var(--space-8) var(--space-4);
}

.auth-card {
  width: min(26rem, 100%);
  background: var(--paper-card);
  border: var(--border-hard);
  border-radius: var(--radius-md);
  box-shadow: 6px 6px 0 rgba(16, 16, 16, 0.9);
  padding: var(--space-7) var(--space-6);
  text-align: center;
}

.auth-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--accent);
  margin-bottom: var(--space-2);
}

.auth-card h1 {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  line-height: 1.05;
  margin-bottom: var(--space-3);
}

.auth-copy {
  color: var(--ink-soft);
  margin-bottom: var(--space-5);
}

.auth-alert {
  font-size: var(--text-sm);
  color: #b3261e;
  border: 1px solid #b3261e;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-4);
}

.btn-google {
  width: 100%;
  background: var(--ink);
  color: var(--paper-card);
  box-shadow: 4px 4px 0 rgba(43, 60, 255, 0.9);
}

.btn-google:hover {
  transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 rgba(43, 60, 255, 0.9);
}

.btn-google:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 rgba(43, 60, 255, 0.9);
}

.google-mark {
  background: #fff;
  border-radius: 50%;
  padding: 2px;
  flex-shrink: 0;
}

.auth-switch {
  font-size: var(--text-sm);
  color: var(--ink-soft);
  margin-top: var(--space-4);
}

.auth-switch a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.auth-fine {
  font-size: var(--text-xs);
  color: var(--ink-soft);
  margin-top: var(--space-3);
}

/* The workspace is the page (2026-07-24). A space-8 pad plus a display
   h1 plus a plan sentence spent ~270px before the first control, which
   pushed the rail's pinned render button under the fold on arrival. The
   greeting collapses to one row; its height is --dash-chrome, which the
   rail subtracts. Keep the two in step if either changes. */
.dash-page {
  padding: var(--space-5) 0 var(--space-7);
  min-height: 50vh;
}

/* The two sit together as one line. space-between across a 68rem
   container stranded the plan label at the far right edge, a screen away
   from the name it qualifies. */
.dash-bar {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin-bottom: var(--space-4);
}

.dash-plan::before {
  content: "";
  display: inline-block;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentcolor;
  vertical-align: 0.25em;
  margin-right: var(--space-3);
}

.dash-page h1 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.2;
  margin-bottom: 0;
}

.dash-plan {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
}

/* The count sentence under My designs (USAGE.md decision 2): the one
   place a subscriber reads the integer unprompted. Mono like the plan
   line, sentence case since it is a sentence. */
.dash-usage {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink-soft);
  margin-top: var(--space-1);
}

/* The refresh phrase holds together across a wrap. */
.dash-usage span {
  white-space: nowrap;
}

.dash-page .auth-copy {
  max-width: 34rem;
}

.dash-flash {
  font-size: var(--text-sm);
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-4);
  max-width: 34rem;
}

/* Right end of the greeting row (2026-07-24), not the foot of the page.
   margin-left: auto rather than space-between on .dash-bar: the plan
   label qualifies the name and stays beside it, only the actions go to
   the far edge. */
.dash-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.dash-actions form {
  margin: 0;
}

.upload-card {
  background: var(--paper-card);
  border: var(--border-hard);
  border-radius: var(--radius-md);
  box-shadow: 5px 5px 0 rgba(16, 16, 16, 0.9);
  padding: var(--space-5);
  max-width: 34rem;
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.upload-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
}

.upload-thumb {
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}

/* Once a photo exists the card is a status row, not a form: thumbnail
   and Replace sit on one line instead of stacking a full-width preview
   over a full-width button. Recovers ~200px of rail for the controls
   that actually gate a render. */
.upload-current {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.upload-current .upload-thumb {
  width: 5.5rem;
  flex: none;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.upload-current .upload-form {
  gap: var(--space-2);
}

.upload-form {
  display: grid;
  gap: var(--space-3);
  justify-items: start;
}

.upload-error {
  font-size: var(--text-sm);
  color: #b3261e;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.upload-fine {
  font-size: var(--text-xs);
  color: var(--ink-soft);
}

/* Login form: the Turnstile widget (when enabled) sits above the button */

.login-form {
  display: grid;
  gap: var(--space-3);
  justify-items: start;
}

/* Email sign-in (MAGIC_LINK.md, 2026-09-02): the "or" rule between the
   two options, a full-width input in the card's hard-edged language,
   and the send button stretched to match the Google one so the two
   read as equals. One Turnstile widget above both forms (flexible
   size, so it spans the card like the buttons). */

/* The widget slot sits between the field and the button and is empty
   height for most visitors (interaction-only appearance, REVEAL.md).
   A grid gap would still open 12px around that empty slot, so the form
   spaces its children with margins the slot opts out of; the iframe
   brings its own top margin only when Turnstile shows it. */

.turnstile-slot {
  margin: 0;
}

.turnstile-slot .cf-turnstile {
  width: 100%;
}

.email-form {
  gap: 0;
}

.email-form > * + * {
  margin-top: var(--space-3);
}

/* The visually-hidden label precedes the input; no margin above the field. */
.email-form > .email-input,
.email-form > .turnstile-slot {
  margin-top: 0;
}

.turnstile-slot iframe {
  display: block;
  margin-top: var(--space-3);
}

/* A visible challenge stands in for the (disabled) submit button rather
   than pushing it down: the card grows by the widget's extra height
   only, not by a whole row (turnstile_controller toggles the class). */
.auth-options.is-interactive .btn-email {
  display: none;
}

.auth-options.is-solved .turnstile-slot {
  display: none;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-4) 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-soft);
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}

.email-form {
  justify-items: stretch;
}

.email-input {
  width: 100%;
  min-width: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.2;
  padding: 0.85em 1em;
  border: var(--border-hard);
  border-radius: var(--radius-pill);
  background: var(--paper);
  color: var(--ink);
  text-align: center;
}

.email-input::placeholder {
  color: var(--ink-soft);
}

.email-input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn-email {
  width: 100%;
}

.auth-email {
  overflow-wrap: anywhere;
}
