/* Juntos shared component layer. Authored here, copied verbatim into every vanilla app
 * by scripts/generate-ui-css.js — do not edit the copy in an app's public/, it is
 * overwritten on the next sync.
 *
 * Depends on juntos-tokens.css being linked FIRST (it supplies every custom property
 * used below). Link order in a page's <head>:
 *     <link rel="stylesheet" href="/juntos-tokens.css">
 *     <link rel="stylesheet" href="/juntos-ui.css">
 *
 * EVERY CLASS IS PREFIXED `ju-`, deliberately. These apps already define .card (26
 * occurrences), .btn (13) and .field (38) with their own meanings; an unprefixed
 * component layer would collide on contact and silently restyle pages nobody touched.
 * The token layer is deliberately UNPREFIXED for the opposite reason — those property
 * names already match what the pages reference, so matching them is the point.
 *
 * Nothing here applies until a page opts in by using a class. Adding the file changes no
 * pixels; that separation is what makes adoption reviewable one page at a time.
 */

/* ─────────────────────────────────────────────────────────────────────────────
 * Container — the single highest-value thing in this file.
 *
 * An audit of all five apps found the platform has ONE layout, a phone layout, and it is
 * hard-capped: every vanilla app declares only max-width breakpoints, none above 600px.
 * El Rebaño's care dashboard caps at 560px, so on a 1440px monitor it uses 39% of the
 * screen and the rest is empty margin — on the app staff use at a desk.
 *
 * This container starts at the same comfortable reading width and actually widens. It is
 * mobile-first (min-width), so on a phone it behaves exactly like the max-width rules it
 * replaces — which is why adopting it can't regress the one layout that works today.
 * ───────────────────────────────────────────────────────────────────────────── */
.ju-container {
  width: 100%;
  max-width: 36rem;              /* 576px — today's effective cap, kept as the phone base */
  margin-inline: auto;
  padding-inline: var(--space-4);
}
@media (min-width: 768px)  { .ju-container { max-width: 45rem; padding-inline: var(--space-6); } }
@media (min-width: 1024px) { .ju-container { max-width: 60rem; } }
@media (min-width: 1280px) { .ju-container { max-width: 72rem; } }

/* Opt-out for genuinely full-bleed surfaces (a kiosk screen, a two-pane workspace). */
.ju-container--wide { max-width: none; }

/* For pages whose content should NOT use the extra width — single-column forms above all.
 * A prayer request or connect card stretched to 1152px is worse than one at 576px: the
 * label-to-input distance grows, the eye has to track further on every row, and nothing
 * is gained because a form has no second column to fill. Widening is right for lists and
 * dashboards, wrong for a form, and the difference is worth a modifier rather than a
 * per-page override.
 *
 * Declared after the base container's media queries deliberately — same specificity
 * (0,1,0), so source order is what makes these win. */
.ju-container--narrow { max-width: 36rem; }
@media (min-width: 768px) { .ju-container--narrow { max-width: 40rem; } }

/* ── Layout primitives ────────────────────────────────────────────────────────
 * `gap` rather than per-element margins: margins collapse and double in ways that are
 * invisible until a sibling is conditionally rendered, which is most of this platform.
 * ───────────────────────────────────────────────────────────────────────────── */
.ju-stack   { display: flex; flex-direction: column; gap: var(--space-4); }
.ju-stack--tight { gap: var(--space-2); }
.ju-stack--loose { gap: var(--space-6); }

.ju-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.ju-cluster--between { justify-content: space-between; }

.ju-grid { display: grid; gap: var(--space-4); grid-template-columns: 1fr; }
@media (min-width: 768px)  { .ju-grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .ju-grid--3 { grid-template-columns: repeat(3, 1fr); } }

/* Wide content (tables, timelines, code) scrolls inside its OWN container so the page
 * body never scrolls sideways. The audit found The Huddle pairs six `nowrap` rules with
 * zero scroll containers — the standard recipe for clipped text at narrow widths. */
.ju-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ── Card ─────────────────────────────────────────────────────────────────── */
.ju-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--space-4);
}
.ju-card--raised { box-shadow: var(--shadow-sm); }
.ju-card--quiet  { background: var(--surface-raised); border-color: transparent; }
.ju-card__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); margin-bottom: var(--space-3);
}
.ju-card__title { font-size: var(--text-md); font-weight: 600; color: var(--text-1); margin: 0; }

/* ── Button ───────────────────────────────────────────────────────────────────
 * min-height 44px is not decorative. Three of the four screens audited declare NO minimum
 * control height at all, and the heights present (28/30/36px) sit under the 44x44 target
 * guideline — on apps used one-handed, on a phone, mid-service.
 * ───────────────────────────────────────────────────────────────────────────── */
.ju-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  background: var(--accent);
  /* NOT #ffffff. --accent is overwritten at runtime with the CHURCH's own colour by each
     app's branding.js, so the ink on top cannot be a constant: white on The Gathering New
     Jersey's #bad415 is 1.68:1, measured in production. juntos-ink.js computes --accent-ink
     beside the colour (white, or Core's navy where that reads better -- navy on that lime is
     10.25:1). The #fff fallback is exactly the old behaviour wherever that script is absent. */
  color: var(--accent-ink, #ffffff);
  transition: background-color .15s ease, border-color .15s ease;
}
.ju-btn:hover  { background: var(--accent-dark); }
.ju-btn:disabled, .ju-btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }

.ju-btn--secondary { background: var(--surface); color: var(--text-1); border-color: var(--text-3); }
.ju-btn--secondary:hover { background: var(--surface-raised); }

/* --text-3, NOT --border. --border is rgba/near-white and composites to ~1.2:1, which is
   fine for a card edge (1.4.11 exempts non-interactive elements) and fails outright for a
   control boundary, which needs 3:1. Same defect shipped in The Huddle four times over. */
.ju-btn--quiet { background: transparent; color: var(--accent); }
.ju-btn--quiet:hover { background: var(--accent-light); }

/* Destructive actions read as destructive BEFORE the confirm dialog, not after. */
/* --coral-dark, NOT --status-critical: coral cannot carry readable text at ANY ink -- 4.13:1
   with white and 4.16:1 with navy, both under AA's 4.5:1. This is the only role where that
   matters, because a chip or a left border carries no text ON the colour. --status-critical
   is unchanged everywhere else. Hover lightens within the same ramp, with computed ink. */
.ju-btn--danger { background: var(--coral-dark); color: #ffffff; }
/* Hover DARKENS. The first attempt sent it to --coral, which is lighter: white on coral is
   4.13:1, so hovering a destructive button would have made it LESS readable, and nothing
   sets a --coral-ink for it to fall back to. Core's ramp has no step below coral-dark, so
   the darken is computed -- toward --navy rather than pure black, because this file's own
   test forbids a hardcoded hex and the palette's own ink is the better mix anyway. Where
   color-mix is unsupported the declaration is simply dropped
   and the button keeps its base colour -- no hover change, never an unreadable one. */
.ju-btn--danger:hover { background: color-mix(in srgb, var(--coral-dark) 82%, var(--navy)); }

/* Full-width on phones is the norm in these apps; opt in rather than assume. */
.ju-btn--block { display: flex; width: 100%; }

/* ── Status chip ──────────────────────────────────────────────────────────────
 * Status is carried by BOTH colour and text, never colour alone — roughly 1 in 12 men has
 * some form of colour vision deficiency, and a red/green dot is the classic failure.
 * ───────────────────────────────────────────────────────────────────────────── */
.ju-chip {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--r-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  background: var(--surface-raised);
  color: var(--text-2);
}
.ju-chip--good     { background: var(--status-good-quiet);     color: var(--sage-dark); }
.ju-chip--warning  { background: var(--status-warning-quiet);  color: var(--amber-dark); }
.ju-chip--critical { background: var(--status-critical-quiet); color: var(--coral-dark); }
.ju-chip--info     { background: var(--status-info-quiet);     color: var(--purple); }

/* ── Form controls ────────────────────────────────────────────────────────────
 * font-size 16px on inputs is deliberate and NOT a design preference: iOS Safari zooms the
 * viewport on focus for anything smaller, which on a kiosk or a phone check-in flow throws
 * the user into a zoomed layout they then have to pinch back out of.
 * ───────────────────────────────────────────────────────────────────────────── */
.ju-field { display: flex; flex-direction: column; gap: var(--space-1); }
.ju-field__label { font-size: var(--text-sm); font-weight: 600; color: var(--text-2); }
.ju-field__hint  { font-size: var(--text-xs); color: var(--text-3); }
.ju-field__error { font-size: var(--text-xs); color: var(--status-critical); font-weight: 600; }

.ju-input, .ju-select, .ju-textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--text-3);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-1);
  font: inherit;
  font-size: 16px;
  /* No `outline: none` here, deliberately. 42 of those across three apps are why the
     shared focus ring needed !important to work at all — this layer will not add a 43rd. */
}
.ju-input:focus, .ju-select:focus, .ju-textarea:focus { border-color: var(--accent); }
.ju-textarea { min-height: 6rem; resize: vertical; line-height: 1.5; }
.ju-field--invalid .ju-input,
.ju-field--invalid .ju-select,
.ju-field--invalid .ju-textarea { border-color: var(--status-critical); }

/* ── Text helpers ─────────────────────────────────────────────────────────── */
.ju-muted { color: var(--text-3); }
.ju-label {
  font-size: var(--text-xs); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-3);
}
/* Keeps running text near 65 characters regardless of how wide the container gets. */
.ju-prose { max-width: 65ch; line-height: 1.6; }

/* Visually hidden but available to screen readers — for a label a sighted user gets from
 * context and a screen-reader user otherwise wouldn't get at all. */
.ju-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
