/* ==========================================================================
   The New Beginning Church — admin

   Shares the website's navy/gold/cream and its two typefaces, so the tool feels
   like it belongs to the same church rather than to a different decade. It is
   still a working instrument, not a brochure: dense where dense is useful,
   generous where a person has to read or decide something.
   ========================================================================== */

@font-face {
  font-family: 'Cormorant Garamond';
  src: url('/fonts/cormorant-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  --navy-deep: #0c174d;
  --navy: #182868;
  --navy-mid: #283878;
  --gold: #f8d808;
  --gold-light: #fef253;
  --amber: #e89828;

  /* Warm-neutral canvas, not cool blue-grey. Premium admin tools (Notion,
     Stripe) warm the greys so the tool reads welcoming rather than clinical —
     the right register for a church. */
  --bg: #fafaf8;
  --panel: #ffffff;
  --sink: #f5f5f2;

  /* Hairlines, not solid grey lines. rgba at ~8% is the single biggest
     cheap-to-expensive jump — a solid #ddd border is the #1 template tell. */
  --line: rgba(24, 27, 45, 0.09);
  --line-strong: rgba(24, 27, 45, 0.16);
  --line-soft: rgba(24, 27, 45, 0.06);

  --ink: #1a1c2e;
  --muted: #5d6486;
  --ok: #0f7a5a;
  --warn: #9a6700;
  --err: #b3261e;

  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --serif: 'Cormorant Garamond', Georgia, serif;

  --r: 12px;
  --r-sm: 9px;
  /* Navy-tinted, not black — this is the detail that makes a shadow read as
     expensive rather than muddy (Stripe's recipe). */
  --shadow-1: 0 1px 2px rgba(12, 23, 77, 0.06), 0 1px 3px rgba(12, 23, 77, 0.04);
  --shadow-2: 0 8px 24px rgba(12, 23, 77, 0.08), 0 2px 6px rgba(12, 23, 77, 0.04);
  --shadow-3: 0 20px 48px rgba(12, 23, 77, 0.18);
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  /* 13.5px, not 15. An admin is a dense instrument: the operator wants to see a
     whole form at once, not scroll through six fields. The website is where
     type gets generous. */
  font-family: var(--sans);
  font-size: 13.5px;
  line-height: 1.5;
  letter-spacing: -0.006em;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  /* Tabular figures everywhere by default — every count, date, phone number and
     amount lines up. It is one of the top signals that reads as "financial
     grade" and costs nothing. */
  font-variant-numeric: tabular-nums;
}

/* Icons are drawn SVG, sized to the text and inheriting its colour. */
.ico { display: inline-flex; flex: 0 0 auto; }
.ico svg { display: block; }
.nav .ico { opacity: 0.72; }
.nav button:hover .ico, .nav button.is-on .ico { opacity: 1; }
.nav .lock { margin-left: auto; opacity: 0.45; font-size: 0.9rem; }

h1, h2, h3 { margin: 0 0 0.35rem; letter-spacing: -0.011em; }
h2 { font-size: 1.22rem; font-weight: 600; }
h3 { font-size: 0.95rem; font-weight: 600; }
.muted { color: var(--muted); font-size: 0.84rem; margin: 0; }
code {
  background: var(--sink); padding: 0.14em 0.42em; border-radius: 5px;
  font-size: 0.86em; font-family: ui-monospace, monospace;
}

/* --------------------------------------------------------------- buttons -- */
.btn {
  font: inherit; font-size: 0.845rem; font-weight: 550;
  padding: 0.52rem 1rem; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
  cursor: pointer; white-space: nowrap;
  box-shadow: var(--shadow-1);
  transition: transform 0.12s var(--ease), box-shadow 0.18s var(--ease),
              background 0.15s var(--ease), border-color 0.15s var(--ease);
}
.btn:hover { border-color: var(--line-strong); background: var(--sink); }
/* A half-pixel press instead of a lift — reads as engineered, not bouncy. Every
   serious tool (Linear/Stripe/Vercel) uses the quiet press, not the hover jump. */
.btn:active { transform: translateY(0.5px); }

/* Flat single-colour primary. The gradient was the loudest "template" tell —
   no premium admin ships gradient buttons in 2026. */
.btn.primary {
  background: var(--navy); border-color: var(--navy); color: #fff;
  box-shadow: 0 1px 2px rgba(12, 23, 77, 0.16);
}
.btn.primary:hover { background: #1c2d72; border-color: #1c2d72; }
.btn.primary:active { background: var(--navy-deep); }
.btn.primary:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.btn.subtle { background: transparent; box-shadow: none; }
.btn.subtle:hover { background: rgba(24, 27, 45, 0.05); border-color: transparent; }
.btn.danger, .icon-btn.danger { color: var(--err); }

:focus-visible { outline: 2.5px solid var(--navy); outline-offset: 2px; border-radius: 6px; }
::selection { background: var(--gold); color: var(--navy-deep); }

/* ---------------------------------------------------------------- login --- */
.login {
  min-height: 100vh; display: grid; place-items: center; padding: 1.5rem;
  background:
    radial-gradient(900px 480px at 50% -10%, #1d2f70 0%, transparent 70%),
    linear-gradient(170deg, var(--navy-deep), #0a1238);
}
.login-card {
  background: var(--panel); padding: 2.2rem; border-radius: 18px;
  width: min(100%, 380px); box-shadow: 0 30px 80px rgba(4, 10, 40, 0.45);
}
.login-logo { display: block; width: 168px; height: auto; margin: 0 auto 1.3rem; }
.login-card { text-align: center; }
.login-card label { text-align: left; }
.login-card h1 {
  font-family: var(--serif); font-size: 1.5rem; font-weight: 600;
  color: var(--navy-deep); letter-spacing: -0.01em;
}
.login-card label { display: block; margin: 1.05rem 0 0; font-size: 0.8rem; font-weight: 600; }
.login-card input {
  width: 100%; margin-top: 0.34rem; padding: 0.62rem 0.75rem; font: inherit;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: #fcfdff;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.login-card input:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(24, 40, 104, 0.13); }
.login-card .btn { width: 100%; margin-top: 1.4rem; padding-block: 0.65rem; }
.error { color: var(--err); font-size: 0.84rem; margin: 0.8rem 0 0; }

/* ----------------------------------------------------------------- shell -- */
.app { display: grid; grid-template-columns: 232px 1fr; height: 100vh; }
.app.with-preview { grid-template-columns: 232px minmax(340px, 1fr) minmax(400px, 1.05fr); }
.app:not(.with-preview) .preview { display: none; }

/* With the preview closed the editor gets the whole width. Capping the form and
   letting the slack pile up on the right read as an empty third column — so it
   is centred, and wide enough that the two-up fields actually use the room. */
.app:not(.with-preview) .form,
.app:not(.with-preview) #church {
  max-width: 1180px;
  margin-inline: auto;
  width: 100%;
}

.sidebar {
  background: linear-gradient(178deg, var(--navy-deep) 0%, #0a1339 100%);
  color: #d8def2; display: flex; flex-direction: column; overflow-y: auto;
}
.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.14); border-radius: 8px; }

.brand { padding: 1rem 0.9rem 0.9rem; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
.brand-plate {
  background: var(--bg); border-radius: 10px; padding: 0.6rem 0.8rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
}
.brand-plate img { display: block; width: 100%; height: auto; }
.brand .muted { color: #94a1cd; font-size: 0.72rem; margin-top: 0.55rem; padding-left: 0.15rem; }

.nav { flex: 1; padding: 0.55rem 0.5rem; }
.nav-group {
  padding: 0.95rem 0.6rem 0.32rem; font-size: 0.63rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: #7c8ac0;
}
.nav button {
  display: flex; align-items: center; gap: 0.6rem; width: 100%;
  padding: 0.5rem 0.6rem; margin-bottom: 1px; border-radius: 8px;
  font: inherit; font-size: 0.855rem; text-align: left;
  background: none; border: 0; color: #d8def2; cursor: pointer;
  transition: background 0.13s var(--ease), color 0.13s var(--ease);
}
.nav button:hover { background: rgba(255, 255, 255, 0.075); color: #fff; }
.nav button.is-on {
  background: rgba(255, 255, 255, 0.12); color: #fff; font-weight: 600;
  box-shadow: inset 2.5px 0 0 var(--gold);
}
.nav .dot {
  width: 7px; height: 7px; border-radius: 50%; margin-left: auto;
  background: var(--gold); box-shadow: 0 0 0 3px rgba(248, 216, 8, 0.18);
}
/* A quiet line, not a yellow blob. It has to persist until acted on, which
   means it must be liveable with — an alert box you see every day stops being
   an alert and starts being furniture you resent. */
.nudge {
  display: flex; align-items: center; gap: 0.5rem;
  margin: 0.5rem 0.6rem; padding: 0.5rem 0.65rem;
  font: inherit; font-size: 0.78rem; text-align: left;
  background: rgba(248, 216, 8, 0.09); color: #f4dd7a;
  border: 1px solid rgba(248, 216, 8, 0.24); border-radius: 8px;
  cursor: pointer; transition: background 0.14s var(--ease);
}
.nudge::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--gold); flex: 0 0 auto;
}
.nudge:hover { background: rgba(248, 216, 8, 0.16); }

.sidebar-foot {
  padding: 0.6rem; display: grid; gap: 0.3rem;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}
.sidebar-foot .btn {
  color: #d8def2; border-color: rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.05); box-shadow: none;
}
.sidebar-foot .btn:hover { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.28); }

/* --------------------------------------------------------------- editor --- */
.editor { display: flex; flex-direction: column; overflow: hidden; border-right: 1px solid var(--line); }
.bar {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
  padding: 1rem 1.35rem; background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(10px); border-bottom: 1px solid var(--line);
}
.bar h2 { font-family: var(--serif); font-size: 1.32rem; color: var(--navy-deep); }
.bar-actions { display: flex; align-items: center; gap: 0.5rem; }
.status { font-size: 0.77rem; color: var(--muted); min-width: 70px; text-align: right; }
.status.saving { color: var(--warn); }
.status.saved { color: var(--ok); font-weight: 600; }

.form, #church { padding: 1.35rem; overflow-y: auto; flex: 1; }

.field { margin-bottom: 0.8rem; }
.field > label, .group > legend {
  display: block; font-size: 0.755rem; font-weight: 600; margin-bottom: 0.26rem;
  color: #46527d; letter-spacing: 0.005em;
}
.field input[type='text'], .field input[type='number'], .field input[type='date'],
.field input[type='tel'], .field input[type='email'], .field input[type='password'],
.field input[type='search'], .field textarea, .field select,
.panel input, .panel select, .filters input, .filters select {
  width: 100%; padding: 0.44rem 0.62rem; font: inherit; font-size: 0.855rem;
  /* Inputs get the STRONGER hairline than cards — Stripe's insight: a slightly
     more visible border is what tells the eye "this is fillable". */
  border: 1px solid var(--line-strong); border-radius: 7px; background: var(--panel);
  transition: border-color 0.14s var(--ease), box-shadow 0.14s var(--ease), background 0.14s var(--ease);
}
.field input:hover, .field textarea:hover, .field select:hover { border-color: rgba(24, 27, 45, 0.28); }
.field input:focus, .field textarea:focus, .field select:focus,
.panel input:focus, .panel select:focus, .filters input:focus {
  outline: none; border-color: var(--navy); background: #fff;
  box-shadow: 0 0 0 3px rgba(24, 40, 104, 0.11);
}
.field textarea { min-height: 88px; resize: vertical; line-height: 1.55; }

.hint { font-size: 0.76rem; color: var(--muted); margin: 0.3rem 0 0; }
.count { float: right; font-size: 0.71rem; color: var(--muted); font-weight: 500; }
.count.over { color: var(--err); font-weight: 600; }

/* A titled card, not a <fieldset> with its border sliced by the legend. The
   heading sits on its own band above the fields, which reads as deliberate. */
.group {
  border: 1px solid var(--line); border-radius: var(--r); padding: 0;
  margin-bottom: 1rem; background: var(--panel); box-shadow: var(--shadow-1);
  min-width: 0;
}
.group > legend {
  float: left; width: 100%; margin: 0; padding: 0.62rem 1rem;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.13em; text-transform: uppercase;
  color: #6b779e; background: #fafbfe;
  border-bottom: 1px solid var(--line); border-radius: var(--r) var(--r) 0 0;
}
.group > legend + * { clear: both; }

/* Short fields sit two-up. A settings form with twenty single-column inputs is
   a scroll, not a form — you cannot see what you are editing. */
.group {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0 1rem; align-content: start;
}
.group > legend { grid-column: 1 / -1; float: none; }
.group > .field { padding-inline: 1rem; }
.group > .field:last-child { margin-bottom: 1rem; }
.group > .field { margin-bottom: 0.85rem; }
.group > .field:nth-last-child(-n + 2) { margin-bottom: 1rem; }

/* Anything long keeps the full width. */
.group > .field:has(textarea),
.group > .field:has(.imagefield),
.group > .field:has(> div > .list-item) { grid-column: 1 / -1; }

.check { display: flex; align-items: center; gap: 0.55rem; }
.check input { width: 17px; height: 17px; accent-color: var(--navy); }
.check label { font-size: 0.87rem; font-weight: 500; margin: 0; }

/* lists in the schema editor */
.list-item {
  border: 1px solid var(--line); border-radius: var(--r); padding: 0.95rem;
  margin-bottom: 0.6rem; background: var(--panel); box-shadow: var(--shadow-1);
  transition: box-shadow 0.18s var(--ease);
}
.list-item:hover { box-shadow: var(--shadow-2); }
.list-head { display: flex; align-items: center; gap: 0.32rem; margin-bottom: 0.7rem; }
.list-head strong { flex: 1; font-size: 0.85rem; color: var(--navy-deep); }
.icon-btn {
  border: 1px solid var(--line); background: var(--panel); border-radius: 7px;
  width: 29px; height: 29px; cursor: pointer; font-size: 0.85rem; line-height: 1;
  transition: border-color 0.14s var(--ease), background 0.14s var(--ease);
}
.icon-btn:hover:not(:disabled) { border-color: #c2cce2; background: var(--sink); }
.icon-btn:disabled { opacity: 0.35; cursor: not-allowed; }

/* image field */
.imagefield { display: flex; gap: 0.85rem; align-items: flex-start; }
.imagefield img, .imagefield .empty {
  width: 116px; height: 84px; border-radius: var(--r-sm); flex: 0 0 auto;
}
.imagefield img { object-fit: cover; border: 1px solid var(--line); box-shadow: var(--shadow-1); }
.imagefield .empty {
  border: 1.5px dashed var(--line); display: grid; place-items: center;
  color: var(--muted); font-size: 0.74rem; background: var(--sink);
}
.imagefield .meta { flex: 1; display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: flex-start; }
.imagefield .meta .hint { width: 100%; }

.errors {
  margin: 0; padding: 0.85rem 1.35rem; font-size: 0.83rem;
  border-bottom: 1px solid #f2d9d6;
}
.errors strong { display: block; margin-bottom: 0.2rem; }
.errors ul { margin: 0.2rem 0 0.5rem; padding-left: 1.1rem; }
.locked { padding: 2rem; color: var(--muted); text-align: center; }

/* ------------------------------------------------------- church screens -- */
/* Section rhythm. The screen headings used to carry inline margin-top:1.6rem in
   church.js — a 26px gap before every list. Governed here instead so the whole
   database keeps ONE rhythm, tightened to 18px so sections read as related
   rather than as separate pages stacked up. */
#church > h3 {
  margin: 1.15rem 0 0.55rem; font-size: 0.9rem; font-weight: 600; color: var(--navy-deep);
}
#church > h3:first-child { margin-top: 0.2rem; }

/* Screen action toolbar (dashboard shortcuts, a form's save/cancel row).
   church.js referenced `.actions` but it was never defined, so the buttons laid
   themselves out on inline-block whitespace — the spacing was an accident. */
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; }
/* When a toolbar closes out a form panel it needs a little air above it. */
.panel .actions { margin-top: 1rem; }

.stat-row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 1.1rem; }
.stat {
  /* Capped so a screen with only two or three KPIs (giving totals, a service's
     adults/children/named) reads as a row of tiles rather than two cards each
     stretched half the page wide with a lonely number adrift inside. Five KPIs
     still grow to fill the row. */
  flex: 1 1 150px; max-width: 260px; padding: 0.68rem 0.85rem; border: 1px solid var(--line);
  border-radius: var(--r); background: var(--panel); box-shadow: var(--shadow-1);
  position: relative; overflow: hidden;
}
.stat::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 2.5px;
  background: linear-gradient(90deg, var(--gold), var(--amber));
}
.stat b {
  /* 1.5rem, down from 1.85. A headcount does not need to be a billboard — the
     old size was the same "everything is oversized" habit the church clients
     flag on the websites, in miniature. */
  display: block; font-family: var(--serif); font-size: 1.5rem; line-height: 1.1;
  color: var(--navy-deep);
  /* Cormorant defaults to old-style figures, which drop 3 and 9 below the
     baseline and render 1 and 0 close enough to I and O to be misread. These
     are counts of people — they have to be scannable at a glance. */
  font-variant-numeric: lining-nums tabular-nums;
}
.stat span {
  font-size: 0.66rem; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.11em; font-weight: 600;
}

/* A slim inline notice — for a nudge that needs to be seen but not obeyed this
   second (photo consent, an empty state worth acting on). Replaces the habit of
   using a full .panel card for two lines of text, which read as an alert three
   times louder than it should be. Same gold language as the sidebar .nudge, on
   the light canvas. */
.notice {
  display: flex; gap: 0.6rem; align-items: flex-start;
  padding: 0.65rem 0.8rem; margin: 1.15rem 0 0;
  background: rgba(248, 216, 8, 0.07);
  border: 1px solid rgba(248, 216, 8, 0.26);
  border-left: 3px solid var(--gold); border-radius: var(--r-sm);
}
.notice .ico { color: var(--warn); margin-top: 1.5px; }
.notice > div { min-width: 0; }
.notice strong { display: block; font-size: 0.845rem; font-weight: 600; color: var(--navy-deep); }
.notice p { margin: 0.1rem 0 0; font-size: 0.795rem; color: var(--muted); }

.filters { display: flex; gap: 0.5rem; margin-bottom: 0.95rem; }
/* The search takes the room; the status select stays its natural size. Without
   width:auto both inherit width:100% from the shared input rule and fight,
   which collapsed the search to a sliver. */
.filters input { flex: 1 1 auto; width: auto; min-width: 0; }
.filters select { flex: 0 0 auto; width: auto; min-width: 150px; }

.list {
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  background: var(--panel); box-shadow: var(--shadow-1);
}
.row {
  display: flex; align-items: center; gap: 0.7rem; width: 100%;
  padding: 0.6rem 0.9rem; font: inherit; text-align: left;
  background: none; border: 0; border-top: 1px solid var(--line-soft); cursor: pointer;
  transition: background 0.12s var(--ease);
}
.row:first-child { border-top: 0; }
button.row:hover { background: var(--sink); }
.row strong { flex: 1; min-width: 0; font-size: 0.875rem; font-weight: 550; }
.row .muted { font-size: 0.79rem; white-space: nowrap; }

/* Initials disc. Turns a wall of names into something that scans like a real
   directory, and costs nothing — no photos to source, no layout height (it fits
   inside the existing row). Navy on a soft tinted disc, matching the brand. */
.avatar {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.01em; color: var(--navy);
  background: linear-gradient(150deg, #eef1fb, #dfe6f7);
  border: 1px solid var(--line); font-variant-numeric: normal;
}

/* Clickable rows get a quiet chevron, so it reads as "opens a profile" rather
   than as static text. Non-clickable div.row (member lists with their own
   controls) deliberately does not. */
button.row { padding-right: 2rem; position: relative; }
button.row::after {
  content: ''; position: absolute; right: 0.9rem; top: 50%; margin-top: -4px;
  width: 7px; height: 7px; border-right: 1.6px solid var(--muted);
  border-bottom: 1.6px solid var(--muted); transform: rotate(-45deg);
  opacity: 0.3; transition: opacity 0.14s var(--ease);
}
button.row:hover::after { opacity: 0.7; }
/* The group "Add someone" rows carry an explicit "Add →", so the generic chevron
   would be a second arrow saying the same thing. */
#group-picker button.row { padding-right: 0.9rem; }
#group-picker button.row::after { content: none; }

.pill {
  font-size: 0.655rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  padding: 0.19rem 0.52rem; border-radius: 999px; background: var(--sink); color: var(--muted);
}
.pill--member   { background: #e0f2ea; color: #0b6247; }
.pill--regular  { background: #e6ecfb; color: var(--navy); }
/* Darkened from var(--warn)/#8a93a8: both failed WCAG AA for small bold text on
   their tints (4.1:1 and 2.7:1). These clear 4.5:1. */
.pill--visitor  { background: #fdf0dc; color: #7a5200; }
.pill--inactive { background: #eef0f4; color: #59617a; }

.two-col { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 0 1.3rem; }

.panel {
  border: 1px solid var(--line); border-radius: var(--r);
  padding: 1.15rem 1.25rem; background: var(--panel);
  margin-bottom: 1.25rem; box-shadow: var(--shadow-1);
}
.panel h3 { margin-bottom: 0.85rem; font-family: var(--serif); font-size: 1.08rem; color: var(--navy-deep); }

/* Twelve numbers do not need a charting library. */
.spark {
  display: flex; align-items: flex-end; gap: 5px; height: 116px;
  padding: 0.6rem 0.9rem; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow-1);
}
.spark-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; text-align: center; }
.spark-bar {
  background: linear-gradient(180deg, #3c50a6, var(--navy)); border-radius: 5px 5px 0 0;
  min-height: 3px; transition: opacity 0.15s var(--ease);
}
.spark-col:hover .spark-bar { opacity: 0.75; }
.spark-col span { font-size: 0.6rem; color: var(--muted); margin-top: 4px; }

/* -------------------------------------------------------------- preview --- */
.preview { display: flex; flex-direction: column; background: var(--sink); overflow: hidden; }
.preview-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.55rem 0.8rem; background: var(--panel); border-bottom: 1px solid var(--line);
}
.tabs, .preview-tools { display: flex; gap: 0.22rem; }
.tab {
  font: inherit; font-size: 0.78rem; font-weight: 500; padding: 0.36rem 0.72rem;
  border: 1px solid transparent; border-radius: 7px; background: none;
  cursor: pointer; color: var(--muted); transition: background 0.13s var(--ease), color 0.13s var(--ease);
}
.tab:hover { background: var(--sink); color: var(--ink); }
.tab.is-on { background: var(--navy); color: #fff; }

.preview-frame { flex: 1; position: relative; display: grid; place-items: center; overflow: auto; }
.preview-frame iframe { width: 100%; height: 100%; border: 0; background: #f8f8e8; }
.preview-frame.phone { padding: 1.1rem; }
.preview-frame.phone iframe {
  width: 390px; height: 100%; max-height: 844px;
  border-radius: 26px; box-shadow: 0 20px 54px rgba(12, 23, 77, 0.28);
}
.preview-off { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; background: var(--sink); }

/* -------------------------------------------------------------- dialogs --- */
.dialog {
  border: 0; border-radius: 18px; padding: 1.5rem; max-width: 560px; width: 92vw;
  box-shadow: 0 30px 80px rgba(8, 16, 50, 0.32);
}
.dialog.wide { max-width: 800px; }
.dialog h3 { font-family: var(--serif); font-size: 1.3rem; color: var(--navy-deep); }
.dialog::backdrop { background: rgba(10, 18, 56, 0.55); backdrop-filter: blur(3px); }
.dialog form { margin-top: 1rem; }
.dialog .field span { display: block; font-size: 0.79rem; font-weight: 600; margin-bottom: 0.3rem; }
.dialog .field input {
  width: 100%; padding: 0.55rem 0.7rem; font: inherit; font-size: 0.885rem;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: #fcfdff;
}
.dialog .field input:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(24, 40, 104, 0.11); }

/* -------------------------------------------------- account profile ---- */
/* A real account panel, not a bare password box: identity header, the facts
   worth seeing at a glance, then editable details and security, with a fixed
   header/footer and a scrolling middle. */
.dialog.account {
  max-width: 480px; width: 94vw; padding: 0; overflow: hidden; max-height: 90vh;
}
/* The flex layout MUST be scoped to [open]. As a bare `.dialog.account { display:flex }`
   it is an author rule that beats the browser's `dialog:not([open]) { display:none }`
   (author origin always wins over UA, regardless of specificity) — so the dialog
   stayed visible inline after .close(), which read as "the close button doesn't
   work". Qualifying it with [open] lets the UA rule hide it again when closed. */
.dialog.account[open] { display: flex; flex-direction: column; }
.account-head {
  display: flex; align-items: flex-start; gap: 0.9rem;
  padding: 1.3rem 1.35rem 1.15rem;
  background: linear-gradient(150deg, #eef1fb, #fff 70%);
  border-bottom: 1px solid var(--line);
}
.account-avatar {
  flex: 0 0 auto; width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--serif); font-size: 1.35rem; font-weight: 600; color: #fff;
  background: linear-gradient(150deg, #34489c, var(--navy-deep));
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.45), 0 4px 12px rgba(12, 23, 77, 0.25);
}
.account-id { flex: 1; min-width: 0; }
.account-id h3 { font-family: var(--serif); font-size: 1.3rem; color: var(--navy-deep); margin: 0.1rem 0 0; }
.account-handle { display: flex; align-items: center; gap: 0.5rem; margin: 0.35rem 0 0; flex-wrap: wrap; }
.account-handle .muted { font-size: 0.82rem; }

.role-badge {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  padding: 0.16rem 0.5rem; border-radius: 999px; background: var(--sink); color: var(--muted);
}
.role-badge--admin  { background: #e6ecfb; color: var(--navy); }
.role-badge--editor { background: #e0f2ea; color: var(--ok); }

.account-body { overflow-y: auto; flex: 1; }

.account-meta {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.25rem 1rem;
  margin: 0; padding: 0.95rem 1.35rem;
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.account-meta div { min-width: 0; }
.account-meta dt {
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 0.2rem;
}
.account-meta dd {
  margin: 0; font-size: 0.845rem; font-weight: 500; color: var(--ink);
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.account-section { padding: 1.15rem 1.35rem; border-bottom: 1px solid var(--line-soft); }
.account-section:last-of-type { border-bottom: 0; }
.account-section h4 {
  margin: 0 0 0.85rem; font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.13em; text-transform: uppercase; color: #6b779e;
}
.account form { margin-top: 0; }
.account .field { margin-bottom: 0.7rem; }
.account .two-up { display: grid; grid-template-columns: 1fr 1fr; gap: 0 0.9rem; }
@media (max-width: 460px) { .account .two-up { grid-template-columns: 1fr; } }
.account-actions { display: flex; justify-content: flex-end; margin-top: 0.9rem; }
.account-foot {
  display: flex; justify-content: space-between; gap: 0.5rem;
  padding: 0.85rem 1.35rem; background: var(--sink); border-top: 1px solid var(--line);
}
.ok-msg { margin: 0.6rem 0 0; font-size: 0.82rem; font-weight: 600; color: var(--ok); }

.versions { max-height: 52vh; overflow-y: auto; margin-top: 0.9rem; }
.version {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.68rem 0; border-top: 1px solid var(--line-soft); font-size: 0.86rem;
}
.version .v {
  font-weight: 700; min-width: 38px; color: var(--navy);
  font-variant-numeric: lining-nums tabular-nums;
}

/* Anywhere a number carries meaning, keep the figures lining and aligned. */
.row strong, .giving-number, .spark-col span { font-variant-numeric: lining-nums tabular-nums; }
.version .meta { flex: 1; color: var(--muted); font-size: 0.78rem; }

.upload { display: flex; align-items: center; gap: 0.85rem; margin: 0.9rem 0; }
.picker-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 0.55rem; max-height: 48vh; overflow-y: auto; padding-top: 0.4rem;
}
.picker-grid button {
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--panel);
  padding: 3px; cursor: pointer; transition: border-color 0.14s var(--ease), transform 0.14s var(--ease);
}
.picker-grid button:hover { border-color: var(--navy); transform: translateY(-2px); }
.picker-grid img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 6px; display: block; }
.picker-grid span { display: block; font-size: 0.65rem; color: var(--muted); padding: 3px 2px 1px; word-break: break-all; }

@media (max-width: 1100px) {
  .app { grid-template-columns: 196px 1fr; }
  .preview { display: none; }
}

/* ==========================================================================
   Cohesion pass — the unified shell, church headers, feedback and motion
   ========================================================================== */

/* ---------------------------------------------------- header action slot -- */
.bar-title { min-width: 0; }
/* Contextual per-screen actions live here; the website editor's fixed buttons
   follow. Empty on Home, so it collapses rather than leaving a gap. */
.bar-slot { display: flex; align-items: center; gap: 0.5rem; }
.bar-slot:empty { display: none; }
.bar-slot .back .ico { opacity: 0.7; }

/* Icon-only buttons (preview device/reload, the dialog close ✕) centre their
   glyph now that the emoji are gone. */
.tab.icon-only { display: inline-grid; place-items: center; padding: 0.36rem 0.5rem; }
.tab.icon-only .ico { opacity: 0.75; }
.tab.icon-only:hover .ico { opacity: 1; }
.icon-btn { display: inline-grid; place-items: center; }
.icon-btn .ico { opacity: 0.7; }
.icon-btn:hover:not(:disabled) .ico { opacity: 1; }

/* -------------------------------------------------------- sidebar: Home --- */
.nav .nav-home { margin-bottom: 0.1rem; }

/* --------------------------------------------------------------- toasts --- */
/* Transient confirmations and errors, replacing alert(): they belong to the
   admin's own visual language instead of an OS dialog, and never block. */
.toasts {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 60;
  display: flex; flex-direction: column; gap: 0.5rem; max-width: min(92vw, 380px);
}
.toast {
  display: flex; align-items: flex-start; gap: 0.55rem;
  padding: 0.7rem 0.85rem; border-radius: var(--r-sm);
  background: var(--panel); color: var(--ink); font-size: 0.85rem;
  border: 1px solid var(--line); border-left: 3px solid var(--navy);
  box-shadow: var(--shadow-2); animation: toast-in 0.22s var(--ease) both;
}
.toast.is-out { animation: toast-out 0.2s var(--ease) both; }
.toast--error { border-left-color: var(--err); }
.toast--error .ico { color: var(--err); }
.toast--ok { border-left-color: var(--ok); }
.toast--ok .ico { color: var(--ok); }
.toast .ico { margin-top: 1px; flex: 0 0 auto; }
.toast > span { min-width: 0; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(6px); } }

/* ------------------------------------------------------------ ask dialog -- */
.dialog.ask { max-width: 440px; }
.dialog.ask h3 { margin-bottom: 0.9rem; }
.ask-label { display: block; font-size: 0.8rem; font-weight: 600; margin-bottom: 0.35rem; color: #46527d; }
.dialog.ask textarea {
  width: 100%; padding: 0.55rem 0.7rem; font: inherit; font-size: 0.885rem; line-height: 1.5;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: #fff; resize: vertical;
}
.dialog.ask textarea:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(24, 40, 104, 0.11); }
.ask-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1rem; }

/* ---------------------------------------------- church: unified content --- */
/* Church edit forms sit in a card, matching the website's settings groups, so a
   person form and a settings form read as the same product rather than two. */
.form-card {
  border: 1px solid var(--line); border-radius: var(--r); background: var(--panel);
  box-shadow: var(--shadow-1); padding: 1.15rem 1.25rem; margin-bottom: 1.1rem;
}
.form-card > .two-col { gap: 0 1.3rem; }

/* Inline role select on group-member rows — was a hard-coded inline style. */
.role-select {
  padding: 0.3rem 0.5rem; border: 1px solid var(--line-strong); border-radius: 6px;
  font: inherit; font-size: 0.8rem; background: var(--panel);
}
/* Empty-state line inside a list — was repeated inline padding in church.js. */
.empty-row { padding: 0.85rem 0.9rem; margin: 0; color: var(--muted); font-size: 0.82rem; }

/* Attendance present/absent — a real checkbox affordance, not a ☑/☐ glyph.
   aria-pressed carries the state to a screen reader; the fill, to everyone. */
.check-row::after { content: none !important; }
.check-box {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 6px;
  border: 1.6px solid var(--line-strong); background: var(--panel);
  display: grid; place-items: center; color: #fff;
  transition: background 0.14s var(--ease), border-color 0.14s var(--ease);
}
.check-box .ico { opacity: 0; transform: scale(0.6); transition: opacity 0.14s var(--ease), transform 0.14s var(--ease); }
.check-row[aria-pressed="true"] .check-box { background: var(--navy); border-color: var(--navy); }
.check-row[aria-pressed="true"] .check-box .ico { opacity: 1; transform: none; }

/* ------------------------------------------------------ team & access ----- */
.urow { flex-wrap: wrap; }
.urow-id { flex: 1 1 190px; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.urow-id strong { font-size: 0.9rem; }
.urow-id .muted { font-size: 0.78rem; white-space: normal; }
.urow-tags { display: flex; gap: 0.35rem; align-items: center; flex-wrap: wrap; }
.urow-actions { display: flex; gap: 0.3rem; align-items: center; flex-wrap: wrap; }
.urow-actions .btn { padding: 0.34rem 0.6rem; font-size: 0.8rem; }
.role-badge--finance { background: #fdf3d6; color: #7a5200; }

/* The one-time invite/reset link, surfaced once with a Copy button. */
.link-card {
  border: 1px solid rgba(24, 40, 104, 0.2); border-left: 3px solid var(--navy);
  background: linear-gradient(180deg, #f4f7ff, #fff); border-radius: var(--r);
  padding: 1rem 1.1rem; margin-bottom: 1.1rem; box-shadow: var(--shadow-1);
}
.link-card-head { display: flex; align-items: center; gap: 0.5rem; }
.link-card-head .ico { color: var(--navy); }
.link-card-head strong { font-size: 0.95rem; color: var(--navy-deep); }
.link-card > .muted { margin: 0.35rem 0 0.75rem; }
.link-row { display: flex; gap: 0.5rem; }
.link-row input {
  flex: 1; min-width: 0; padding: 0.5rem 0.6rem; font: inherit; font-size: 0.8rem;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: #fff;
  font-family: ui-monospace, monospace;
}
.link-card .actions { margin-top: 0.7rem; }

.team-dialog { max-width: 460px; }
.team-dialog h3 { margin-bottom: 1rem; }
.team-dialog .field { margin-bottom: 0.85rem; }
.team-dialog .field > span { display: block; font-size: 0.79rem; font-weight: 600; margin-bottom: 0.3rem; color: #46527d; }
.team-dialog .field input, .team-dialog .field select {
  width: 100%; padding: 0.5rem 0.65rem; font: inherit; font-size: 0.87rem;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: #fff;
}
.team-dialog .field input:focus, .team-dialog .field select:focus {
  outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(24, 40, 104, 0.11);
}
.team-dialog .check { margin: 0.5rem 0 0.3rem; }

/* -------------------------------------------------------- screen motion --- */
/* One gentle rise when a screen's content appears — enough to feel alive, not
   enough to notice. Runs on section/screen change, never on a keystroke. */
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.form > *, #church > * { animation: rise 0.2s var(--ease) both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  .btn:hover, .picker-grid button:hover { transform: none; }
  .form > *, #church > * { animation: none; }
}
