/**
 * account.autowire.app — account page
 *
 * Only what this page has and the marketing site does not: the account
 * header/footer extras, definition lists, the Kontingent meter, dialogs,
 * plan cards, and the state-visibility matrix that decides what is on
 * screen. Everything else — reset, layout, header, footer, buttons, cards,
 * forms, badges — comes from base.css and components.css, which are shared
 * with autowire.app.
 *
 * Load order:  tokens.css → tokens-app.css → base.css → components.css → account.css
 *
 * Every colour is a token. There is no raw hex below this comment.
 *
 * Contents
 *   1  Surface density
 *   2  Header and footer extras
 *   3  Page headings
 *   4  Definition lists
 *   5  Meter (Kontingent)
 *   6  Form status (notices)
 *   7  Dialogs and plan cards
 *   8  Loading, empty, overlay
 *   9  STATE VISIBILITY MATRIX  — the single place that decides what shows
 *  10  Responsive
 *  11  Environment banner
 */


/* ═══ 1  SURFACE DENSITY ═════════════════════════════════════════════════
   The design system's rhythm is set for marketing pages: tall bands, big
   section headings, cards holding two lines of text. This is a settings
   screen — it holds more per card and scrolls less well, so it turns four
   tokens down. Overriding the tokens keeps every shared rule intact; do not
   redefine .section-inner or .card here. */

body {
  --section-py:         clamp(40px, 6vw, 72px);
  --section-py-compact: clamp(32px, 5vw, 56px);
  --text-h-section:     clamp(26px, 3vw, 32px);
  --card-gap:           var(--space-5);   /* cards hold sections, not two lines */
}


/* ═══ 2  HEADER AND FOOTER EXTRAS ════════════════════════════════════════ */

/* "Konto" beside the wordmark: this is the account surface, not the site. */
.site-logo-sub {
  font-family: var(--font-mono);
  font-size: var(--text-mono-xs);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary-strong);
  padding-left: var(--space-3);
  border-left: 1px solid var(--border-default);
  margin-left: var(--space-1);
}

.site-head-user { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.site-head-company {
  font-size: var(--text-body-s);
  color: var(--fg-secondary-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 34ch;
}

.site-foot-word    { font-size: 20px; font-weight: var(--fw-black); color: var(--color-white); letter-spacing: var(--ls-snug); }
.site-foot-tagline { font-family: var(--font-mono); font-size: 13px; color: var(--fg-on-dark-muted); }
.site-foot-legal   { font-family: var(--font-mono); font-size: var(--text-mono-xs); color: var(--fg-on-dark-faint); }


/* ═══ 3  PAGE HEADINGS ═══════════════════════════════════════════════════ */

.page-head { display: flex; flex-direction: column; gap: var(--space-3); }

/* Support / debug strings: visible, but clearly not addressed to the customer. */
.tiny {
  font-family: var(--font-mono); font-size: var(--text-mono-xxs);
  color: var(--fg-secondary-strong); hyphens: none; word-break: break-all;
}


/* ═══ 4  DEFINITION LISTS ════════════════════════════════════════════════ */

.dl { display: flex; flex-direction: column; }

/* The divider is a border-TOP, not a bottom. Rows are shown and hidden by
   the state matrix, so :last-child is unreliable — it can land on a hidden
   row and leave a rule under nothing. :first-child is safe, because the
   first row ("Betrieb") is visible in every state. */
.dl-row {
  display: grid;
  grid-template-columns: var(--dl-label-col) minmax(0, 1fr);
  gap: var(--dl-row-gap);
  align-items: baseline;
  padding: var(--dl-row-py) 0;
  border-top: 1px solid var(--border-default);
}
.dl-row:first-child { padding-top: 0; border-top: 0; }

/* Short lists inside a card read better as plain stacked lines. */
.dl-plain { gap: var(--space-3); }
.dl-plain .dl-row { border-top: 0; padding: 0; }

.dl-term { font-size: var(--dl-label-fs); color: var(--dl-label-fg); }
.dl-desc {
  font-size: var(--dl-value-fs); color: var(--dl-value-fg);
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
}
.dl-desc .u-mono { font-size: var(--text-mono-s); color: var(--fg-primary); }
.dl-note  { font-size: var(--text-caption); color: var(--fg-tertiary); line-height: var(--lh-relaxed); }
.dl-empty { color: var(--fg-tertiary); }

/* The end date is the one value a customer is looking for once a cancellation
   is pending, so the state matrix emphasises it. */
body[data-vis~="endsHighlight"] .f-ends .dl-desc { font-weight: var(--fw-medium); }


/* ═══ 5  METER (Kontingent) ══════════════════════════════════════════════ */

.allow-bignum { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.allow-count  {
  font-family: var(--font-sans); font-size: var(--text-bignum);
  font-weight: var(--fw-bold); line-height: var(--lh-tight);
  letter-spacing: var(--ls-snug);
}
.allow-of     { font-size: var(--text-body-m); color: var(--fg-secondary-strong); }

.meter       { display: flex; flex-direction: column; gap: var(--space-2); }
.meter-track {
  height: var(--meter-h); border-radius: var(--radius-pill);
  background: var(--meter-track-bg); overflow: hidden;
}
.meter-fill {
  height: 100%; border-radius: inherit;
  background: var(--meter-fill);
  width: var(--meter-value, 0%);
  transition: width var(--transition-base);
}
.meter.is-spent .meter-fill   { background: var(--meter-fill-spent); }
.meter.is-warning .meter-fill { background: var(--meter-fill-warn); }
.meter-legend {
  display: flex; justify-content: space-between; gap: var(--space-4);
  font-family: var(--font-mono); font-size: var(--text-mono-xs);
  color: var(--fg-secondary-strong); hyphens: none;
}


/* ═══ 6  FORM STATUS (NOTICES) ═══════════════════════════════════════════
   The page's single notice component — page-level messages and the errors
   inside the sign-in form and the cancellation dialog all use it.

   This is components.css's .banner with a different class API, not a second
   design: the box and every tone come from the same tokens. It keeps its own
   names because render.js picks a tone at runtime by building `is-${kind}`,
   so the tone classes must be .is-* state names rather than .banner-* ones.
   Change one, change the other. */
.form-status {
  font-size: 15px; line-height: 1.55;
  padding: var(--banner-py) var(--banner-px);
  border-radius: var(--banner-radius);
  display: none;
}
.form-status.is-visible { display: block; }
.form-status.is-error   { background: var(--bg-danger-soft);  color: var(--fg-danger); }
.form-status.is-success { background: var(--bg-success-soft); color: var(--fg-success); }
.form-status.is-info    { background: var(--bg-info-soft);    color: var(--fg-info); }
.form-status.is-neutral { background: var(--bg-neutral-soft); color: var(--fg-neutral); }


/* ═══ 7  DIALOGS AND PLAN CARDS ══════════════════════════════════════════ */

/* Native <dialog> — it brings the focus trap, Escape-to-close and inertness
   of the page behind it for free. No hand-rolled focus management. */
.dialog {
  width: min(var(--dialog-max-w), calc(100vw - 2 * var(--space-5)));
  max-height: calc(100vh - 2 * var(--space-8));
  padding: var(--dialog-pad);
  border: 1px solid var(--border-default);
  border-radius: var(--dialog-radius);
  background: var(--bg-card);
  color: var(--fg-primary);
  overflow: auto;
}
.dialog::backdrop { background: var(--backdrop); }
.dialog-title { font-size: var(--text-h-card); font-weight: var(--fw-bold); line-height: var(--lh-snug); }
.dialog-body  { font-size: var(--text-body-m); line-height: var(--lh-loose); color: var(--fg-secondary); }
.dialog-body strong { color: var(--fg-primary); font-weight: var(--fw-medium); }
.dialog-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }

.plan-list { display: flex; flex-direction: column; gap: var(--space-3); }
.plan-card {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  padding: var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-3);
}
.plan-card.is-current { border-color: var(--border-strong); }
.plan-name  { font-size: var(--text-body-l); font-weight: var(--fw-bold); }
.plan-price { font-family: var(--font-mono); font-size: var(--text-mono-m); color: var(--fg-primary); hyphens: none; }
.plan-meta  { font-size: var(--text-body-s); color: var(--fg-secondary-strong); }
.plan-current-label { font-size: var(--text-body-s); color: var(--fg-secondary-strong); }


/* ═══ 8  LOADING, EMPTY, OVERLAY ═════════════════════════════════════════ */

.skel {
  background: var(--bg-skeleton);
  border-radius: var(--radius-sm);
  height: 1em;
  animation: skel 1.2s ease-in-out infinite;
}
.skel-title { height: 1.6em; width: 40%; }
.skel-line  { width: 100%; }
.skel-line-short { width: 60%; }
@keyframes skel { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }

.spinner {
  width: 28px; height: 28px; flex: none;
  border-radius: 50%;
  border: 3px solid var(--color-gray-300);
  border-top-color: var(--color-dark);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* A centred column for the boot, error and empty screens. Not .u-center,
   which only sets text-align. */
.stack-centered {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-4); text-align: center;
  padding: var(--section-py) 0;
}

.overlay {
  position: fixed; inset: 0; z-index: 50;
  display: none;
  align-items: center; justify-content: center;
  background: var(--bg-screen);
}

.auth-card { max-width: 460px; }
/* Nine fields, two of them paired side by side, need more room than a
   sign-in box. The container widens rather than the form escaping it. */
body[data-shell="A1C"] .auth-card,
body[data-shell="A2C"] .auth-card,
body[data-shell="A3C"] .auth-card { max-width: 620px; }

/* A German address is written street + number, then postcode + town. The
   pairs stay on one line until the narrow column stops fitting them. */
.reg-line { display: grid; gap: var(--space-4); }
.reg-line-street { grid-template-columns: minmax(0, 1fr) 7rem; }
.reg-line-city   { grid-template-columns: 7rem minmax(0, 1fr); }
.auth-divider { border: 0; border-top: 1px solid var(--border-default); width: 100%; }


/* ═══ 9  STATE VISIBILITY MATRIX ═════════════════════════════════════════
   Everything the page shows or hides is decided here, keyed off data
   attributes on <body>:
       data-shell  A0…A10   which screen (boot / auth / account)
       data-auth   in|out   is there a session
       data-role   ADMIN|READONLY
       data-sub    C0…C10   subscription state
       data-allow  K0…K4    allowance state
       data-vis    space-separated tokens for the parts that are visible;
                   matched with [data-vis~="token"]. Computed once, by
                   visibleParts() in js/state.js.
   No el.style.display assignments anywhere in the JavaScript.
   ══════════════════════════════════════════════════════════════════════ */

/* ── screens ── */
.screen { display: none; }

body[data-shell="A0"]  .screen-boot,
body[data-shell="A1"]  .screen-auth,
body[data-shell="A1B"] .screen-auth,
body[data-shell="A1C"] .screen-auth,
body[data-shell="A1D"] .screen-auth,
body[data-shell="A2"]  .screen-auth,
body[data-shell="A2C"] .screen-auth,
body[data-shell="A3"]  .screen-auth,
body[data-shell="A3C"] .screen-auth,
body[data-shell="A9"]  .screen-auth,
body[data-shell="A4"]  .screen-account,
body[data-shell="A5"]  .screen-account,
body[data-shell="A6"]  .screen-account,
body[data-shell="A7"]  .screen-account,
body[data-shell="A8"]  .screen-account,
body[data-shell="A10"] .screen-account { display: block; }

/* ── cards inside the auth screen ──
   Same idiom as .acct-panel below: hidden by default, shown for the states
   that own them. Listing the states is deliberate — a `:not()` rule silently
   showed the wrong card the moment a new auth state was added. */
.auth-panel { display: none; }

body[data-shell="A1"]  .auth-signin,
body[data-shell="A2"]  .auth-signin,
body[data-shell="A3"]  .auth-signin,
body[data-shell="A9"]  .auth-signin,
body[data-shell="A1"]  .auth-appblock,
body[data-shell="A2"]  .auth-appblock,
body[data-shell="A3"]  .auth-appblock,
body[data-shell="A9"]  .auth-appblock,
body[data-shell="A1B"] .auth-reset,
body[data-shell="A1C"] .auth-register,
body[data-shell="A2C"] .auth-register,
body[data-shell="A3C"] .auth-register,
body[data-shell="A1D"] .auth-confirm { display: flex; }

/* ── panels inside the account screen ── */
.acct-panel { display: none; }
body[data-shell="A4"]  .acct-loading,
body[data-shell="A5"]  .acct-error,
body[data-shell="A6"]  .acct-nocompany,
body[data-shell="A7"]  .acct-ready,
body[data-shell="A8"]  .acct-ready,
body[data-shell="A10"] .acct-pending { display: block; }

/* ── signing-out overlay ── */
body[data-shell="A8"] .overlay-signout { display: flex; }

/* ── header ── */
body[data-auth="out"] .site-head-user { display: none; }

/* ── role gate ──
   Belt and braces. render.js physically removes [data-admin-only] nodes for
   non-admins (a greyed-out "Kündigen" invites clicks and makes support
   tickets); this rule only prevents a flash before that happens. */
body[data-role="READONLY"] [data-admin-only] { display: none !important; }

/* ── everything data-driven ──
   Default hidden; shown only when visibleParts() emitted the token.
   The display value has to be restored explicitly because .dl-row is a grid
   and the cards are flex columns. */
.f-address, .f-plan, .f-started, .f-billing-period,
.f-next-billing, .f-committed, .f-ends, .f-extra, .f-nodocs { display: none; }

body[data-vis~="address"]       .f-address,
body[data-vis~="plan"]          .f-plan,
body[data-vis~="started"]       .f-started,
body[data-vis~="billingPeriod"] .f-billing-period,
body[data-vis~="nextBilling"]   .f-next-billing,
body[data-vis~="committed"]     .f-committed,
body[data-vis~="endsAt"]        .f-ends,
body[data-vis~="extraRow"]      .f-extra,
body[data-vis~="noNewDocs"]     .f-nodocs { display: grid; }

/* sections are blocks, cards are flex columns — restore each correctly */
.section-docs, .section-mgmt { display: none; }
body[data-vis~="sectionDocs"] .section-docs,
body[data-vis~="mgmt"]        .section-mgmt { display: block; }

.card-allowance, .card-nodocs, .readonly-hint { display: none; }
body[data-vis~="allowanceCard"] .card-allowance,
body[data-vis~="nodocsCard"]    .card-nodocs { display: flex; }
body[data-role="READONLY"]      .readonly-hint { display: flex; }

.act-choose-plan, .act-portal, .act-invoices, .act-buy-extra,
.act-cancel, .act-resume, .act-reactivate, .act-reload, .act-support { display: none; }

body[data-vis~="choosePlan"] .act-choose-plan,
body[data-vis~="portal"]     .act-portal,
body[data-vis~="invoices"]   .act-invoices,
body[data-vis~="buyExtra"]   .act-buy-extra,
body[data-vis~="cancel"]     .act-cancel,
body[data-vis~="resume"]     .act-resume,
body[data-vis~="reactivate"] .act-reactivate,
body[data-vis~="reload"]     .act-reload,
body[data-vis~="support"]    .act-support { display: inline-flex; }

/* ── allowance sub-states ── */
body[data-allow="K4"] .allow-bignum,
body[data-allow="K4"] .allow-resets,
body[data-allow="K4"] .meter { display: none; }
body[data-allow="K3"] .card-allowance { border-color: var(--border-warning); }

/* Running low or out is when buying more stops being an afterthought. */
body[data-allow="K1"] .act-buy-extra,
body[data-allow="K3"] .act-buy-extra {
  background: var(--btn-primary-bg); color: var(--btn-primary-fg); box-shadow: none;
}

.allow-readonly-note { display: none; }
body[data-role="READONLY"][data-allow="K3"] .allow-readonly-note { display: block; }

.allow-note { display: none; font-size: var(--text-body-s); line-height: var(--lh-loose); color: var(--fg-secondary-strong); }
body[data-vis~="allowNote"] .allow-note { display: block; }
body[data-allow="K1"] .allow-note,
body[data-allow="K3"] .allow-note { color: var(--fg-warning); }

.allow-note-title { display: none; font-size: var(--text-h3); font-weight: var(--fw-bold); }
body[data-allow="K3"] .allow-note-title { display: block; }

/* ── extra-credit preservation note (C3, C8, C9) ── */
.extra-keep-note { display: none; }
body[data-vis~="extraKeepNote"] .extra-keep-note { display: block; }

/* ── support / raw status line (C10) ── */
.sub-raw { display: none; }
body[data-vis~="rawStatus"] .sub-raw { display: block; }


/* ═══ 10  RESPONSIVE ═════════════════════════════════════════════════════
   base.css already handles .wrap, .site-head-inner, .site-nav and the
   footer's .g-foot columns. Only the account's own parts are here. */

@media (max-width: 760px) {
  .site-head-user { width: 100%; justify-content: space-between; }
  .site-head-company { max-width: none; }
  .site-logo-sub { display: none; }
}

@media (max-width: 560px) {
  .dl-row { grid-template-columns: 1fr; gap: var(--space-1); }
  .reg-line-street, .reg-line-city { grid-template-columns: minmax(0, 1fr); }
  .dialog { padding: var(--space-5); }
  .dialog-actions { flex-direction: column; align-items: stretch; }
  .dialog-actions > .btn { width: 100%; }
}

@media (max-width: 380px) {
  .card { padding: var(--space-5); }
}


/* ═══ 11  ENVIRONMENT BANNER ═════════════════════════════════════════════
   Only ever visible outside production (main.js unhides it). Brand yellow on
   black rather than a warning red: this is not an error, it is a statement of
   which database you are looking at. */

.env-banner {
  background: var(--color-dark);
  color: var(--color-brand);
  font-family: var(--font-mono);
  font-size: var(--text-mono-xs);
  text-align: center;
  padding: var(--space-2) var(--space-4);
  letter-spacing: var(--ls-wide);
}
.env-banner strong { color: var(--color-brand); font-weight: var(--fw-medium); }
.env-banner[hidden] { display: none; }
