/* ============================================================================
   Account portal (docs/website-portal.md)

   Built on the marketing site's own tokens from styles.css -- the portal is
   the same product, not a second one, so it inherits the palette rather than
   introducing another. Only layout and the few components the landing page
   has no use for live here.
   ============================================================================ */

/* Every component below sets `display`, and a class outranks the user agent's
   [hidden] { display: none }. Without this the login, registration and
   password-reset forms all render at once and the sign-out button shows while
   signed out. The same trap caught the desktop client's walkthrough --
   docs/tutorial.md -- so it is handled once, here, rather than per element. */
.portal-body [hidden] {
  display: none !important;
}

.portal-body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--ground);
}

/* The portal uses the shared site header (tools/website_frame.py). It stays
   in the flow here instead of floating over the content, at the same height
   and padding as on every other page, so switching pages does not move it. */
.portal-header {
  position: sticky;
  top: 0;
}

.portal-header .portal-identity {
  color: rgba(255, 255, 255, 0.82);
}

.portal-header .portal-ghost {
  border-color: rgba(255, 255, 255, 0.42);
  color: #fff;
}

/* Signed in, the portal's own name/logout block replaces the account button. */
.portal-identity:not([hidden]) ~ .profile-button {
  display: none;
}

.portal-identity {
  color: rgba(255, 255, 255, 0.82);
}

.portal-header .portal-ghost {
  border-color: rgba(255, 255, 255, 0.42);
  color: #fff;
}

.portal-identity {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
  color: var(--ink-soft);
}

.portal-icon {
  width: 18px;
  height: 18px;
  flex: none;
}

.portal-main {
  flex: 1;
  width: min(1120px, calc(100vw - 32px));
  margin: 0 auto;
  padding: 32px 0 56px;
}

/* ---- signed out ---------------------------------------------------------- */

.portal-auth {
  display: grid;
  place-items: center;
  min-height: 60vh;
}

.portal-auth-card {
  width: min(420px, 100%);
}

.portal-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--line);
}

.portal-tabs button {
  flex: 1;
  padding: 10px 8px;
  border: none;
  background: none;
  font: inherit;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  cursor: pointer;
}

.portal-tabs button.active {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--brand-accent);
}

/* ---- signed in ----------------------------------------------------------- */

.portal-shell {
  display: grid;
  grid-template-columns: 210px minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

.portal-nav {
  display: grid;
  gap: 2px;
  position: sticky;
  top: 24px;
}

.portal-nav button {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: none;
  border-radius: 10px;
  background: none;
  font: inherit;
  color: var(--ink-soft);
  text-align: left;
  cursor: pointer;
}

.portal-nav button:hover {
  background: var(--paper);
}

.portal-nav button.active {
  background: var(--paper);
  color: var(--ink);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(16, 21, 20, 0.06);
}

.portal-page {
  display: none;
  gap: 20px;
  grid-auto-rows: max-content;
}

.portal-page.active {
  display: grid;
}

.portal-page h1 {
  margin: 0;
  font-size: 26px;
}

.portal-card {
  padding: 20px 22px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.portal-card h2 {
  margin: 0 0 14px;
  font-size: 17px;
}

.portal-hint {
  background: var(--brand-accent-wash);
  border-color: transparent;
}

.portal-hint p {
  margin: 0;
  color: var(--ink-soft);
  line-height: 1.55;
}

/* ---- metrics and facts --------------------------------------------------- */

.portal-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
}

.portal-metric {
  display: grid;
  gap: 4px;
  padding: 16px 18px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.portal-metric span {
  font-size: 13px;
  color: var(--muted);
}

.portal-metric strong {
  font-size: 24px;
}

.portal-facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 8px 20px;
  margin: 0;
}

.portal-facts dt {
  color: var(--muted);
}

.portal-facts dd {
  margin: 0;
}

/* ---- rows ---------------------------------------------------------------- */

.portal-list {
  display: grid;
  gap: 12px;
}

.portal-row {
  display: grid;
  gap: 12px;
  padding: 16px 18px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.portal-row.live {
  border-color: var(--brand-accent);
}

.portal-row > div:first-child {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.portal-row span {
  font-size: 14px;
  color: var(--muted);
}

.portal-status {
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--ground);
  font-size: 13px;
}

.portal-status[data-live="true"] {
  background: var(--brand-accent-wash);
  color: var(--brand-accent-strong);
  font-weight: 600;
}

.portal-row-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  margin: 0;
}

.portal-row-facts dt {
  font-size: 12px;
  color: var(--muted);
}

.portal-row-facts dd {
  margin: 0;
  font-size: 15px;
}

.portal-row-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

/* ---- forms and buttons --------------------------------------------------- */

.portal-form {
  display: grid;
  gap: 14px;
  /* Three fields in a two-column grid would otherwise stretch the last one
     to the full row height -- the same trap the desktop client hit. */
  align-items: start;
}

.portal-form label {
  display: grid;
  gap: 6px;
  font-size: 14px;
  color: var(--ink-soft);
}

/* .portal-form label's single-column grid is meant for a text label
   stacked above its input -- applied unchanged to a checkbox+text label, it
   put the checkbox centered on its own row above the text instead of
   beside it, since a checkbox does not stretch to fill a grid track the
   way a text input does. This overrides that with a plain side-by-side row. */
.portal-form label.portal-checkbox-label {
  display: flex;
  align-items: start;
  gap: 8px;
}

.portal-checkbox-label input[type="checkbox"] {
  flex: none;
  margin-top: 3px;
}

.portal-form small {
  color: var(--muted);
}

.portal-form input {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  font: inherit;
  color: var(--ink);
}

.portal-form input:focus-visible {
  outline: 2px solid var(--brand-accent);
  outline-offset: 1px;
}

/* Password fields: a show/hide toggle inside the input, and (only where a
   `.password-strength` sibling is present -- new-password fields, never
   login or "current password") a live strength meter beneath it. Wired
   generically in portal.js; nothing here is specific to one form. */
.password-field {
  position: relative;
  display: flex;
}

.password-field input {
  flex: 1;
  padding-right: 38px;
}

.password-toggle {
  position: absolute;
  right: 2px;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  padding: 6px;
  color: var(--muted);
  display: flex;
}

.password-toggle:hover {
  background: transparent;
  color: var(--ink);
}

.password-toggle .portal-icon {
  width: 18px;
  height: 18px;
}

.password-strength {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}

.password-strength-track {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}

.password-strength-fill {
  display: block;
  height: 100%;
  width: 0%;
  border-radius: inherit;
  background: var(--coral-500);
  transition: width 120ms ease, background-color 120ms ease;
}

/* 0-4, set alongside the width by updatePasswordStrengthMeter(). This
   palette does not define an amber/gold token, so the middle tiers use raw
   values rather than inventing new tokens for one meter. */
.password-strength-fill[data-score="0"] { background: var(--coral-500); }
.password-strength-fill[data-score="1"] { background: #d98a2b; }
.password-strength-fill[data-score="2"] { background: #c9a227; }
.password-strength-fill[data-score="3"] { background: #7cb342; }
.password-strength-fill[data-score="4"] { background: var(--brand-accent-strong); }

.portal-primary,
.portal-secondary,
.portal-danger,
.portal-ghost {
  padding: 10px 16px;
  border-radius: 10px;
  border: 1px solid transparent;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.portal-primary {
  background: var(--brand-accent);
  color: #fff;
}

.portal-primary:hover:not(:disabled) {
  background: var(--brand-accent-strong);
}

.portal-secondary {
  background: var(--paper);
  border-color: var(--line);
  color: var(--ink);
}

.portal-danger {
  background: var(--paper);
  border-color: var(--coral-500);
  color: var(--coral-500);
}

.portal-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border-color: var(--line);
  color: var(--ink-soft);
  font-weight: 500;
}

.portal-primary:disabled,
.portal-secondary:disabled,
.portal-danger:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.portal-link {
  justify-self: center;
  border: none;
  background: none;
  font: inherit;
  color: var(--muted);
  text-decoration: underline;
  cursor: pointer;
}

.portal-error {
  margin: 0;
  min-height: 1em;
  color: var(--coral-500);
  font-size: 14px;
}

.portal-note {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}

.portal-warning {
  margin: 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: #fdf3d8;
  border: 1px solid #e8c766;
  color: #7a5b00;
  font-size: 14px;
  line-height: 1.5;
}

/* ---- toast --------------------------------------------------------------- */

.portal-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--surface-dark);
  color: #fff;
  font-size: 14px;
  box-shadow: 0 8px 24px rgba(16, 21, 20, 0.18);
  z-index: 40;
}

.portal-toast[data-kind="error"] {
  background: var(--coral-500);
}

.portal-body .site-footer {
  margin-top: auto;
}

/* ---- plans ----------------------------------------------------------------- */

.plan-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
}

.plan-option {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 12px;
  padding: 18px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.plan-option header {
  display: grid;
  gap: 2px;
}

.plan-option header strong {
  font-size: 17px;
}

.plan-option .plan-price {
  font-weight: 600;
  color: var(--ink-soft);
}

.plan-option header small {
  color: var(--muted);
}

#plan-current .portal-note {
  margin: -6px 0 14px;
}

.plan-option ul {
  display: grid;
  align-content: start;
  gap: 6px;
  margin: 0;
  padding-left: 18px;
  color: var(--ink-soft);
  font-size: 15px;
}

.plan-option.is-current {
  border-color: var(--brand-accent);
  box-shadow: inset 0 0 0 1px var(--brand-accent);
}

/* Paid plans: on the page so the range is visible, but plainly not bookable. */
.plan-option.is-unavailable {
  background: var(--ground);
}

.plan-option.is-unavailable header,
.plan-option.is-unavailable ul {
  opacity: 0.55;
}

/* The plan picked on the pricing section before signing in. */
.plan-option.is-wanted {
  border-color: var(--brand-accent);
  background: var(--brand-accent-wash);
}

.register-plans {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
}

.register-plans legend {
  margin-bottom: 6px;
  padding: 0;
  font-weight: 600;
}

.register-plans > div {
  display: grid;
  gap: 6px;
}

.portal-form label.portal-radio-label {
  display: flex;
  align-items: start;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
}

.portal-form label.portal-radio-label:has(input:checked) {
  border-color: var(--brand-accent);
  background: var(--brand-accent-wash);
}

.portal-radio-label input[type="radio"] {
  flex: none;
  margin-top: 4px;
  padding: 0;
  accent-color: var(--brand-accent);
}

@media (max-width: 760px) {
  .portal-shell {
    grid-template-columns: minmax(0, 1fr);
  }

  .portal-nav {
    position: static;
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    overflow-x: auto;
    padding-bottom: 4px;
  }

  .portal-facts {
    grid-template-columns: minmax(0, 1fr);
    gap: 2px 0;
  }

  .portal-facts dt {
    margin-top: 8px;
  }
}

/* On a phone the header held the wordmark, "Zur Startseite", the username and
   "Abmelden" in one row and pushed the page wider than the screen. The
   wordmark already links home, and who is signed in shows on the overview. */
@media (max-width: 560px) {

  #portal-username {
    display: none;
  }
}

/* ONBOARD-001: the invite link's welcome above the registration form. */
.portal-invite {
  display: grid;
  gap: 10px;
  margin-bottom: 18px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line, rgba(255, 255, 255, 0.12));
}

.portal-invite h2 {
  margin: 0;
}

.portal-invite-steps {
  margin: 0;
  padding-left: 1.2em;
  display: grid;
  gap: 4px;
}

.portal-invite-code {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.portal-invite-code code {
  overflow-wrap: anywhere;
  font-size: 0.9em;
}
