/* ==========================================================================
   Shell: phone dock (<= 760), compact rail (761-1099), full rail (>= 1100),
   app bar, "what now" ribbon, connection banner, page header, sticky next-step bar, supervision bar.
   Tokens only. Not linked yet.
   ========================================================================== */
.app { min-height: 100vh; min-height: 100dvh; }
.app__body { min-width: 0; padding-bottom: calc(var(--dock-h) + var(--safe-b)); }

/* ---------- App bar ---------- */
.appbar { position: sticky; top: var(--support-h, 0px); z-index: 60; display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: calc(var(--appbar-h) + var(--safe-t)); padding: var(--safe-t) var(--pad) 0; background: var(--appbar-bg); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); border-bottom: 1px solid var(--line); }
.brand { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; color: var(--ink); text-decoration: none; font-weight: 750; font-size: 1.25rem; letter-spacing: -.02em; }
.brand__mark { width: 34px; height: 34px; border-radius: 10px; background: var(--brand-bg); border: 1px solid var(--accent-line); display: grid; place-items: center; color: var(--accent); box-shadow: 0 0 0 4px var(--accent-halo); }
.brand__mark svg { width: 20px; height: 20px; stroke-width: 2.6; }
.appbar__side { display: flex; align-items: center; gap: 8px; min-width: 0; margin-left: auto; }
.balance-chip { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px 0 12px; border-radius: var(--r-pill); background: var(--s2); border: 1px solid var(--line-strong); color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.balance-chip:hover { background: var(--s3); }
.balance-chip .icon { color: var(--accent); }
.balance-chip small { font-size: var(--fs-sm); font-weight: 600; color: var(--accent); }
.balance-chip.is-low { border-color: var(--warn-line); } .balance-chip.is-low .icon, .balance-chip.is-low small { color: var(--warn); }
.balance-chip.is-empty { border-color: var(--danger-line); } .balance-chip.is-empty .icon, .balance-chip.is-empty small { color: var(--danger); }
.appbar__ribbon { display: none; }

/* ---------- Ribbon: "what now" on every other view ---------- */
.ribbon { display: flex; align-items: center; gap: 10px; min-height: 48px; margin: 12px var(--pad) 0; padding: 4px 8px 4px 14px; border-radius: 14px; background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--ink); text-decoration: none; font-size: var(--fs-sm); }
.ribbon:hover { background: var(--accent-wash); }
.ribbon__tag { font-weight: 750; color: var(--accent); white-space: nowrap; }
.ribbon__text { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ribbon .icon { color: var(--accent); }
.ribbon--live { background: var(--accent-faint); }
.ribbon--warn { background: var(--warn-soft); border-color: var(--warn-line); } .ribbon--warn .ribbon__tag, .ribbon--warn .icon { color: var(--warn); }

/* ---------- Phone dock ---------- */
.dock { position: fixed; z-index: 100; left: 0; right: 0; bottom: 0; display: flex; gap: 2px; padding: 6px 6px calc(6px + var(--safe-b)); background: var(--dock-bg); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); border-top: 1px solid var(--line-strong); }
.dock__link { position: relative; flex: 1 1 auto; min-width: 44px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 56px; padding: 2px 4px; border-radius: 14px; color: var(--muted); text-decoration: none; font-size: var(--fs-cap); font-weight: 650; line-height: 1.2; text-align: center; }
.dock__icon { position: relative; width: min(56px, 100%); height: 30px; border-radius: 16px; display: grid; place-items: center; transition: background var(--t-base); }
.dock__link:hover { color: var(--ink); }
.dock__link[aria-current="page"] { color: var(--accent); }
.dock__link[aria-current="page"] .dock__icon { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line); }
.nav-badge { position: absolute; top: -7px; right: -4px; min-width: 26px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--accent); color: var(--accent-ink); font-size: var(--fs-cap); font-weight: 800; line-height: 20px; text-align: center; font-variant-numeric: tabular-nums; }
.nav-badge--warn { background: var(--warn); }
.nav-badge--dot { min-width: 12px; width: 12px; height: 12px; padding: 0; border-radius: 50%; top: -2px; right: 8px; border: 2px solid var(--badge-ring); }
.nav-badge--live { animation: pulse 1.6s ease-in-out infinite; }

/* ---------- Rail (tablet compact, desktop full) ---------- */
.rail { display: none; }
@media (min-width: 761px) {
  .app { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); }
  .dock { display: none; }
  .rail { position: sticky; top: 0; height: 100vh; height: 100dvh; display: flex; flex-direction: column; gap: 6px; padding: 14px 8px; background: var(--rail-bg); border-right: 1px solid var(--line); overflow-y: auto; }
  .rail__brand { display: grid; place-items: center; padding: 6px 0 14px; }
  .rail__brand .brand > span:last-child { display: none; }
  .rail__brand .brand { min-width: 44px; justify-content: center; }
  .rail__nav { display: grid; gap: 4px; }
  .rail__link { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 64px; padding: 8px 2px; border-radius: 14px; color: var(--muted); text-decoration: none; font-size: var(--fs-cap); font-weight: 650; text-align: center; line-height: 1.2; }
  .rail__link:hover { background: var(--wash); color: var(--ink); }
  .rail__link[aria-current="page"] { background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-line); }
  .rail__link .icon { width: 24px; height: 24px; }
  .rail__link .nav-badge { top: 4px; right: 12px; }
  .rail__link .nav-badge--dot { top: 8px; right: 22px; }
  .rail__camino, .rail__account { display: none; }
  .appbar { padding-left: var(--pad); }
  .appbar .brand { display: none; }
  .appbar__ribbon { display: flex; flex: 1; min-width: 0; }
  .appbar__ribbon .ribbon { margin: 0; flex: 1; max-width: 560px; }
  .ribbon--phone { display: none; }
}
@media (min-width: 1100px) {
  .rail { padding: 18px 14px; gap: 10px; }
  .rail__brand { place-items: start; padding: 4px 8px 18px; }
  .rail__brand .brand > span:last-child { display: inline; }
  .rail__link { flex-direction: row; justify-content: flex-start; gap: 14px; min-height: 48px; padding: 8px 14px; font-size: 15px; text-align: left; }
  .rail__link .nav-badge { position: static; margin-left: auto; }
  .rail__link .nav-badge--dot { margin-right: 4px; }
  .rail__camino { display: block; margin-top: 14px; padding: 16px 8px 8px; border-top: 1px solid var(--line); }
  .rail__camino-title { display: flex; align-items: baseline; justify-content: space-between; padding: 0 8px 6px; font-size: var(--fs-sm); font-weight: 700; }
  .rail__camino-title span { color: var(--muted); font-weight: 600; }
  .rail__account { display: block; margin-top: auto; padding: 14px 10px 4px; border-top: 1px solid var(--line); font-size: var(--fs-sm); }
  .rail__account strong { display: block; font-size: var(--fs-md); }
  .rail__account .muted { display: block; }
  .rail__account .link { font-size: var(--fs-sm); }
  .appbar__ribbon { display: none; }
}
/* compact route inside the rail */
.route--rail .route__link { grid-template-columns: 28px 1fr; min-height: 44px; gap: 12px; padding: 6px 8px 6px 4px; }
.route--rail .route__node { width: 28px; height: 28px; font-size: 13px; }
.route--rail .route__node .icon { width: 14px; height: 14px; }
.route--rail .route__step::before { left: 17px; }
.route--rail .route__title { font-size: 15px; font-weight: 650; }
.route--rail .route__value, .route--rail .route__go { display: none; }

/* ---------- Views & page header ---------- */
.view { width: 100%; max-width: var(--content-max); margin: 0 auto; padding: var(--sp-6) var(--pad) var(--sp-10); }
.page-head { display: grid; gap: 6px; margin-bottom: var(--sp-6); }
.page-head h1 { font-size: var(--fs-2xl); letter-spacing: -.03em; overflow-wrap: anywhere; min-width: 0; }      /* "Hola, <60 unbroken letters>" wraps (S10 round 1) */
.page-head .lead { color: var(--muted); font-size: var(--fs-lg); max-width: 62ch; }
.page-head__row .btn { padding: 0 12px; }
.page-head__row .cluster { gap: 8px; }
.page-head__row { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--sp-4); }
@media (min-width: 1100px) { .page-head h1 { font-size: var(--fs-3xl); } .view { padding-top: var(--sp-8); } }

@media (min-width: 1100px) { body[data-view="campana"] .rail__camino { display: none; } }

/* ---------- Balance chip: the "+" says "tap to top up" (one source for the balance) ---------- */
.balance-chip__plus { color: var(--accent); margin-left: 2px; }

/* ---------- Rail: campaign card while running, one-liner when ready ---------- */
.rail-run { display: grid; gap: 10px; padding: 12px; border-radius: var(--r-md); background: var(--s2); border: 1px solid var(--line-strong); }
.rail-run .chip { justify-self: start; }
.rail-run__n { font-weight: 700; }
.rail-run .progress { height: 8px; }
.rail-done { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; padding: 10px 12px; min-height: 52px; border-radius: var(--r-md); background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--ink); text-decoration: none; }
.rail-done b { display: block; font-size: var(--fs-sm); }
.rail-done small { display: block; font-size: var(--fs-sm); color: var(--muted); }
.rail-done__mark { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; background: var(--accent); color: var(--accent-ink); }
.rail-done__mark .icon { width: 16px; height: 16px; stroke-width: 3; }

/* ---------- Sticky next-step bar (phone only): the primary action stays in the thumb zone ---------- */
.actionbar { display: none; }
@media (max-width: 760px) {
  .actionbar { position: fixed; z-index: 95; left: 0; right: 0; bottom: calc(var(--dock-h) + var(--safe-b)); display: block; padding: 8px var(--pad); background: linear-gradient(180deg, var(--actionbar-from), var(--actionbar-to) 22%); pointer-events: none; }
  .actionbar .btn { pointer-events: auto; width: 100%; min-height: 52px; justify-content: space-between; border-radius: 14px; box-shadow: var(--glow), var(--e-bar); }
  body.has-actionbar .app__body { padding-bottom: calc(var(--dock-h) + var(--safe-b) + var(--action-h)); }
  body.has-actionbar .toasts { bottom: calc(var(--dock-h) + var(--safe-b) + var(--action-h) + 8px); }
  body.has-actionbar .stage-nav__missing { display: none; }      /* the same action lives in the bar: never twice on a phone */
  body.kb-open .actionbar, body.kb-open .dock { display: none; }
}
body.is-locked .actionbar, body.is-locked .supbar { display: none; }

/* ---------- Supervision bar: state derived from the supervisor's own phone; never promises server control ---------- */
.supbar { position: fixed; z-index: 96; left: 12px; right: 12px; bottom: calc(var(--dock-h) + var(--safe-b) + 10px); display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; padding: 10px 10px 10px 14px; border-radius: var(--r-lg); background: var(--supbar-bg); border: 1px solid var(--info-line); box-shadow: var(--e3); }
.supbar__led { width: 12px; height: 12px; border-radius: 50%; background: var(--info); animation: pulse 1.4s ease-in-out infinite; }
.supbar__text b { display: block; font-size: var(--fs-md); }
.supbar__text span { display: block; font-size: var(--fs-sm); color: var(--ink-2); }
@media (min-width: 761px) { .supbar { left: auto; right: 24px; bottom: 24px; width: min(460px, calc(100vw - 48px)); } body.has-supbar .toasts { bottom: 112px; } }
@media (max-width: 760px) { body.has-supbar .toasts { bottom: calc(var(--dock-h) + var(--safe-b) + 96px); } body.has-supbar .app__body { padding-bottom: calc(var(--dock-h) + var(--safe-b) + 90px); } }

/* compact rail: the n/4 badge sits on the corner of the item, never over the icon */
@media (min-width: 761px) and (max-width: 1099px) { .rail__link .nav-badge { top: 2px; right: 0; min-width: 24px; height: 18px; line-height: 18px; } .rail__link .nav-badge--dot { top: 6px; right: 10px; } }
@media (min-width: 761px) and (max-width: 1099px) { .rail__link .nav-badge--dot { min-width: 12px; width: 12px; height: 12px; line-height: 0; padding: 0; } }

.nav-badge .icon { width: 12px; height: 12px; stroke-width: 3.2; display: inline-block; vertical-align: -1px; }

/* ---------- Support banner (staff session only, SPEC 2.8): the only thing allowed above the app bar. js/views/acceso.js un-hides it and sets --support-h so the app bar sticks below it ---------- */
.admin-support-banner { position: sticky; top: 0; z-index: 70; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 12px; padding: 8px var(--pad); background: var(--supbar-bg); border-bottom: 1px solid var(--info-line); color: var(--ink); font-size: var(--fs-sm); font-weight: 650; }
.admin-support-banner [data-support-label] { color: var(--ink-2); }

/* ---------- First paint: the app bar chip is a skeleton until the first /api/status answer (no cached balance, SPEC 2.8) ---------- */
.balance-chip__value { min-width: 5ch; text-align: right; }
.balance-chip__value.skeleton { display: inline-block; height: 18px; }

/* ---------- Blocking card in <main> when the very first /api/status could not be loaded (SPEC 4.12) ---------- */
.load-error { display: grid; gap: var(--sp-3); margin-bottom: var(--sp-4); }
/* The very first /api/status failed (SPEC 4.12): the card "No hemos podido cargar tu cuenta" is the whole screen. It is a direct child of <main>, outside every .view, so it takes
   the page gutters itself (the views get theirs from `.view`) and sits centred, a readable width, with room above it. */
main > .load-error { width: calc(100% - 2 * var(--pad)); max-width: 36rem; margin: var(--sp-8) auto; }

/* ---------- Skeleton first paint: shapes of the final content, the views stay hidden until the first answer (body.is-loading is removed) ---------- */
.boot-skeleton, .boot-loading-text { display: none; }
body.is-loading .boot-skeleton { display: grid; gap: var(--sp-4); }
body.is-loading .boot-loading-text { display: block; }
body.is-loading main > section[data-view] { display: none; }
/* The very first /api/status failed (js/app.js initBackend puts body.is-load-failed on): ONLY the "No hemos podido cargar tu cuenta" card is left on screen, with its
   Reintentar. The default account that the renderers paint (no plan, 0,00 EUR, no agents) belongs to nobody: no view, no plan banner (renderSubscription would
   say "Suscripción inactiva" to a paying customer), no chip value (renderBalanceChip waits for an answer). The first answer takes the class off. */
body.is-load-failed main > section[data-view] { display: none; }
.balance-chip[aria-disabled="true"] { cursor: default; }
.balance-chip[aria-disabled="true"]:hover { background: var(--s2); }
/* The balance chip says nothing while the amount is on its way: the wallet and an empty pill, no "+" */
.balance-chip[aria-disabled="true"] .balance-chip__plus { display: none; }
.boot-skeleton__title { height: 40px; width: 55%; }
.boot-skeleton__hero { height: 220px; border-radius: var(--r-xl); }
.boot-skeleton__row { height: 68px; border-radius: var(--r-md); }

/* ---------- Large text (SPEC 9: nothing is wider than the screen at 200 %) ---------- */
/* What the 200% text zoom at 360 px needed from the shell (the app bar and the ribbon pushed every view 23 px sideways). They override the rules above, so they come last. */
/* The app bar wraps instead of overflowing: the chip drops under the brand when both do not fit (large text), and the brand and the chip never get wider than the screen */
.appbar { flex-wrap: wrap; row-gap: 0; }
.appbar .brand { min-width: 0; flex: 0 1 auto; }
.appbar__side { min-width: 0; max-width: 100%; flex: 0 1 auto; }
.balance-chip { max-width: 100%; min-width: 0; }
.balance-chip__value { min-width: 0; }
.balance-chip__tag { flex: none; }
/* The ribbon says it in words, whatever the size of the text: no ellipsis, no sideways push */
.ribbon { min-width: 0; padding-top: 6px; padding-bottom: 6px; }
.ribbon__text { overflow: visible; text-overflow: clip; white-space: normal; overflow-wrap: anywhere; }
.ribbon__tag { white-space: normal; }
@media (min-width: 761px) { .appbar__ribbon .ribbon { min-width: 0; } }
/* The sticky next-step bar: the label may take two lines at large text; the button grows with it */
.actionbar .btn { height: auto; min-height: 52px; padding-top: 8px; padding-bottom: 8px; text-align: left; }
.actionbar .btn span { min-width: 0; overflow-wrap: anywhere; }
/* The labels of the dock are 12 px whatever the size of the text (SPEC 2.2: "icon over a 12 px label, never icon-only"; like the bottom bars of the platforms): five words must share
   360 px, and at 200% a label that grows with the text can only end in an ellipsis ("He...") and the navigation is unreadable. The words stay whole; the ellipsis is only the net
   under a word that is longer than its item (a language with longer words). The badge keeps its size too, so it sits on the corner of the icon and never over it. */
.dock__link { font-size: min(var(--fs-cap), 12px); }
.dock__link > span:last-child { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-badge { font-size: min(var(--fs-cap), 12px); }
@media (min-width: 761px) and (max-width: 1099px) { .rail__link { font-size: min(var(--fs-cap), 12px); } }


/* ---------- Short viewports (S10 round 1; WCAG 1.4.10 reflow, 2.4.11) ----------
   400 % zoom on a 1080p screen is 480 x 237 CSS px, 300 % on a 1366 x 768 laptop about 455 x 170: a fixed app bar (56) and a fixed dock (69) there are half the screen, three quarters with the
   sticky next-step bar. Below 520 px of height the chrome scrolls away with the page; only the supervision bar stays, and it never takes more than a quarter of the height. */
@media (max-height: 520px) {
  html { scroll-padding-top: 16px; scroll-padding-bottom: 16px; }
  .appbar, .dock, .actionbar { position: static; }
  .app__body, body.has-actionbar .app__body { padding-bottom: 0; }
  .supbar { max-height: 25vh; overflow-y: auto; }
}
