/* ============================================================================
   INSTALLER DASHBOARD — the board, the project, the message.
   Phone-first (390px is the design width; 320px must not break), then the
   lanes spread out on a laptop. Tokens from css/styles.css; the shell's navy
   header and cards from css/installer.css. Rules honoured: 44px targets on a
   coarse pointer, 16px inputs so iOS never zooms, gold only as the one primary
   action and a selected state — never as text on white — and text ≥ 4.5:1.
   Motion: 180ms ease-out, state changes only; reduced motion goes instant.
   ============================================================================ */
:root {
  --ib-ease: cubic-bezier(.22, 1, .36, 1);
  --ib-ink: #2c2b28;
  --ib-ink-2: #5a5850;
  --ib-ink-3: #6e6e73;
  --ib-rule: #e5e3de;
  --ib-rule-firm: #cccac4;
  --ib-paper: #ffffff;
  --ib-panel: #fafaf8;
  --ib-gold: #c5a55a;
  --ib-gold-deep: #9a7a2f;
  --ib-gold-tint: #faf6ec;
  --ib-gold-pale: #f3ebcf;
  --ib-navy: #1f2533;
  --ib-green: #24583f;
  --ib-green-bg: #eef5f0;
  --ib-green-rule: #cfe3d6;
  --ib-red: #b4342c;
  --ib-red-bg: #fdf1ef;
  --ib-red-rule: #f2cfcb;
}

/* ── the shell: navy header, the work on a light surface ──────────────────
   The installer page paints itself navy to the bottom (css/installer.css);
   the board, the project and the message live on the portal's light ground
   so lane titles, meta text and cards read as they do everywhere else. The
   hero and the page head stay on the navy. */
.ib-shell .installer-main { padding: 0 0 calc(72px + env(safe-area-inset-bottom)); max-width: none; background: #f4f3f0; min-height: calc(100vh - 124px); min-height: calc(100dvh - 124px); }
.ib-hero { color: #fff; padding: 18px 16px 16px; display: flex; flex-direction: column; gap: 6px; background: linear-gradient(180deg, rgba(43,48,64,.94), rgba(31,37,51,.98)); }
.ib-hero + .ib-chips { padding-top: 14px; }
.ib-shell .dash-signout-btn {
  min-height: 44px; padding: 0 14px; border-radius: 8px; border: 1px solid rgba(255,255,255,.28);
  background: transparent; color: #fff; font: 600 13px/1 var(--font-sans); cursor: pointer;
  transition: background-color .18s var(--ib-ease);
}
.ib-shell .dash-signout-btn:hover { background: rgba(255,255,255,.1); }
.ib-shell .dash-signout-btn:focus-visible { outline: 2px solid var(--ib-gold); outline-offset: 2px; }
.ib-hero h1 { font-family: var(--font-serif); font-size: 24px; line-height: 1.15; font-weight: 700; margin: 0; }
.ib-hero p { margin: 0; color: rgba(255,255,255,.72); font-size: 13px; line-height: 1.5; }
/* The phone header is one line: logo, the installer's name (never wrapped),
   Sign out (never wrapped). Then the two tabs, then a short hero. About 200px
   of chrome before the first card, down from 440. */
@media (max-width: 640px) {
  .ib-shell .installer-topbar { min-height: 56px; padding: 8px 10px 8px 14px; gap: 10px; align-items: center; }
  .ib-shell .installer-logo { width: 84px; height: 30px; }
  .ib-shell .installer-brand { min-width: 0; flex: 1 1 auto; }
  .ib-shell .installer-brand-title { font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ib-shell .installer-brand-subtitle { display: none; }
  .ib-shell .installer-spacer { display: none; }
  .ib-shell .installer-topbar-actions > span { display: none; }
  .ib-shell .dash-signout-btn { min-height: 40px; padding: 0 12px; white-space: nowrap; flex: none; }
  .ib-shell .installer-view-tabs { padding: 0 8px; }
  .ib-hero { padding: 14px 16px 12px; gap: 4px; }
  .ib-hero h1 { font-size: 21px; }
  .ib-hero p { font-size: 12.5px; }
  .ib-hero + .ib-chips { padding-top: 12px; }
}

/* ── controls ─────────────────────────────────────────────────────────────── */
.ib-chips { display: flex; gap: 6px; padding: 0 16px 12px; overflow-x: auto; scrollbar-width: none; }
.ib-chips::-webkit-scrollbar { display: none; }
.ib-chip {
  flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--ib-rule-firm);
  background: var(--ib-paper); color: var(--ib-ink); font: 500 13px/1 var(--font-sans); cursor: pointer;
  transition: background-color .18s var(--ib-ease), border-color .18s var(--ib-ease);
}
.ib-chip[aria-pressed="true"] { background: var(--ib-gold-pale); border-color: var(--ib-gold); color: var(--ib-navy); font-weight: 600; }
.ib-chip:focus-visible, .ib-card:focus-visible, .ib-row:focus-visible, .ib-btn:focus-visible, .ib-back:focus-visible { outline: 2px solid var(--ib-gold); outline-offset: 2px; }

.ib-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  min-height: 48px; padding: 0 20px; border-radius: 8px; border: 0; cursor: pointer;
  background: var(--ib-gold); color: var(--ib-navy); font: 600 14px/1 var(--font-sans); text-decoration: none;
  transition: background-color .18s var(--ib-ease), transform .12s var(--ib-ease);
}
.ib-btn:hover { background: #d6bc78; }
.ib-btn:active { transform: translateY(1px); }
.ib-btn:disabled { background: var(--ib-gold-pale); color: var(--ib-ink-3); cursor: not-allowed; transform: none; }
.ib-btn.secondary { background: var(--ib-paper); color: var(--ib-ink); border: 1px solid var(--ib-rule-firm); }
.ib-btn.secondary:hover { background: var(--ib-panel); border-color: var(--ib-gold); }
.ib-btn.quiet { background: transparent; color: var(--ib-navy); min-height: 44px; width: auto; padding: 0 10px; }
.ib-btn.quiet:hover { background: var(--ib-gold-tint); }
.ib-btn svg { flex: none; }

/* ── the board ─────────────────────────────────────────────────────────────
   On a phone the stages STACK: one vertical list, each stage title a section
   head, the whole page one thumb-scroll. The horizontal kanban this replaced
   showed one card and a sliver of the next, and on iOS Safari a horizontal
   snap container the height of the screen swallowed the vertical swipe — the
   board could not be scrolled at all. Lanes go side by side only from 900px,
   where there is room for them, and never with scroll snapping. */
.ib-lanes { display: flex; flex-direction: column; gap: 18px; padding: 0 16px 16px; }
.ib-lane { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ib-lane-head { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 4px 2px; }
.ib-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.ib-lane-title { font: 600 13px/1.3 var(--font-sans); color: var(--ib-navy); }
.ib-lane-count { font: 400 12.5px/1 var(--font-sans); color: var(--ib-ink-3); }
.ib-lane-empty { padding: 18px 8px; text-align: center; border: 1px dashed var(--ib-rule-firm); border-radius: 8px; color: var(--ib-ink-3); font: 400 12.5px/1.5 var(--font-sans); }
@media (min-width: 900px) {
  .ib-lanes { flex-direction: row; align-items: flex-start; gap: 12px; padding: 0 28px 28px; overflow-x: auto; scrollbar-width: thin; }
  .ib-lane { flex: 0 0 236px; }
}

.ib-card {
  display: flex; flex-direction: column; gap: 8px; width: 100%; text-align: left;
  padding: 12px 12px 10px; border-radius: 8px; border: 1px solid rgba(43,48,64,.12);
  background: var(--ib-paper); box-shadow: var(--shadow-md, 0 8px 28px -14px rgba(43,48,64,.28)); cursor: pointer;
  font-family: var(--font-sans); color: var(--ib-ink);
  transition: border-color .18s var(--ib-ease), transform .18s var(--ib-ease);
}
.ib-card:hover { border-color: var(--ib-gold); }
.ib-card:active { transform: translateY(1px); }
.ib-card.is-flagged { border-color: var(--ib-gold); box-shadow: inset 0 0 0 1px var(--ib-gold); }
.ib-card-title { font: 600 15px/1.3 var(--font-sans); color: var(--ib-navy); }
.ib-card-town { font: 400 12px/1.4 var(--font-sans); color: var(--ib-ink-3); }
.ib-card-line { display: flex; align-items: center; gap: 6px; font: 500 12.5px/1.4 var(--font-sans); color: var(--ib-ink-2); }
.ib-card.is-flagged .ib-card-line { color: var(--ib-navy); font-weight: 600; }
.ib-card-when { font: 400 12px/1.4 var(--font-sans); color: var(--ib-ink-3); }

.ib-empty { margin: 8px 16px; padding: 24px 16px; text-align: center; border: 1px dashed var(--ib-rule-firm); border-radius: 8px; color: var(--ib-ink-2); font: 400 14px/1.5 var(--font-sans); background: var(--ib-panel); }
.ib-swipe { display: none; align-items: center; gap: 6px; padding: 0 28px 12px; color: var(--ib-ink-3); font: 400 12px/1.4 var(--font-sans); }
@media (min-width: 900px) { .ib-swipe { display: flex; } }

/* skeletons: the board's shape appears instantly, never a spinner in space */
.ib-sk { border-radius: 8px; background: linear-gradient(90deg, var(--ib-rule) 0%, #f0eee8 50%, var(--ib-rule) 100%); background-size: 200% 100%; animation: ib-shimmer 1.2s linear infinite; }
.ib-sk-card { height: 88px; }
.ib-sk-head { height: 20px; width: 60%; }
@keyframes ib-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ── the project ──────────────────────────────────────────────────────────── */
.ib-page { display: flex; flex-direction: column; gap: 14px; padding: 14px 16px 24px; }
.ib-page-head { display: flex; align-items: center; gap: 8px; min-height: 64px; padding: 8px 8px 8px 0; color: #fff; }
.ib-back { width: 44px; height: 44px; flex: none; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 8px; background: transparent; color: #fff; cursor: pointer; }
.ib-back:hover { background: rgba(255,255,255,.1); }
.ib-page-title { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ib-page-title h1 { margin: 0; font: 700 17px/1.2 var(--font-serif); color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ib-page-title p { margin: 0; font: 400 12px/1.4 var(--font-sans); color: rgba(255,255,255,.72); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 900px) { .ib-page { max-width: 720px; margin: 0 auto; padding: 20px 28px 28px; } .ib-page-head { max-width: 720px; margin: 0 auto; width: 100%; } .ib-hero { padding: 24px 28px 20px; } .ib-hero h1 { font-size: 28px; } .ib-chips { padding: 14px 28px 12px; } }

.ib-card-static { display: flex; flex-direction: column; gap: 12px; padding: 16px; border-radius: 8px; border: 1px solid rgba(43,48,64,.12); background: var(--ib-paper); box-shadow: var(--shadow-md, 0 8px 28px -14px rgba(43,48,64,.28)); }
.ib-kv { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 12px; margin: 0; font: 400 12.5px/1.45 var(--font-sans); }
.ib-kv dt { color: var(--ib-ink-3); align-self: baseline; }
.ib-kv dd { margin: 0; color: var(--ib-ink); overflow-wrap: anywhere; }
.ib-kv a { color: var(--ib-navy); font-weight: 600; text-decoration: underline; text-decoration-color: var(--ib-gold); text-underline-offset: 2px; }
/* A phone number in a line of text is still a 44px target: pad the link without moving the line. */
.ib-kv a { display: inline-block; padding: 10px 0; margin: -10px 0; }
.ib-pill { display: inline-flex; align-items: center; min-height: 26px; padding: 4px 10px; border-radius: 999px; background: var(--ib-gold-tint); border: 1px solid var(--ib-gold-pale); color: #2b3040; font: 600 12px/1 var(--font-sans); white-space: nowrap; }
.ib-pill.green { background: var(--ib-green-bg); border-color: var(--ib-green-rule); color: var(--ib-green); }
.ib-pill.red { background: var(--ib-red-bg); border-color: var(--ib-red-rule); color: var(--ib-red); }
.ib-pill.navy { background: #eef1f7; border-color: #d7dce8; color: #2b3040; }
.ib-pill.gray { background: #f4f3f0; border-color: var(--ib-rule); color: var(--ib-ink-2); }

.ib-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 4px 2px 0; }
.ib-section-head h2 { margin: 0; font: 600 13px/1.3 var(--font-sans); color: var(--ib-ink); }
.ib-section-head span { font: 400 12.5px/1.3 var(--font-sans); color: var(--ib-ink-3); }
.ib-bar { height: 3px; border-radius: 2px; background: var(--ib-rule); overflow: hidden; }
.ib-bar > i { display: block; height: 100%; border-radius: 2px; background: var(--ib-gold); }

.ib-list { display: flex; flex-direction: column; gap: 8px; }
.ib-row {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 64px; padding: 10px 12px; text-align: left;
  border: 1px solid var(--ib-rule); border-radius: 8px; background: var(--ib-paper); color: var(--ib-ink); cursor: pointer;
  font-family: var(--font-sans); transition: border-color .18s var(--ib-ease), background-color .18s var(--ib-ease);
}
.ib-row:hover { background: var(--ib-panel); }
.ib-row.is-next { border-color: var(--ib-gold); box-shadow: inset 0 0 0 1px var(--ib-gold); }
.ib-row.is-static { cursor: default; }
.ib-row.is-static:hover { background: var(--ib-paper); }
.ib-row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ib-row-name { font: 600 14px/1.3 var(--font-sans); color: var(--ib-ink); }
.ib-row-meta { font: 400 12.5px/1.35 var(--font-sans); color: var(--ib-ink-3); }
.ib-row-meta b { color: var(--ib-green); font-weight: 600; }
.ib-state { width: 24px; height: 24px; border-radius: 50%; flex: none; display: flex; align-items: center; justify-content: center; border: 1.5px solid var(--ib-rule-firm); color: #fff; }
.ib-state.done { background: #2f6b4f; border-color: #2f6b4f; }
.ib-state.part { border-color: var(--ib-gold); }
.ib-state.part::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--ib-gold); }
.ib-state.warn { border-color: var(--ib-red); color: var(--ib-red); }
.ib-chev { color: var(--ib-ink-3); flex: none; }

.ib-note { display: flex; align-items: flex-start; gap: 9px; padding: 10px 12px; border: 1px solid var(--ib-rule); border-radius: 6px; background: var(--ib-paper); font: 400 12.5px/1.45 var(--font-sans); color: var(--ib-ink); }
.ib-note svg { flex: none; margin-top: 1px; }
.ib-note.ok { background: var(--ib-green-bg); border-color: var(--ib-green-rule); }
.ib-note.warn { background: #fdf7e6; border-color: #e6c46b; }
.ib-note.bad { background: var(--ib-red-bg); border-color: var(--ib-red-rule); }

/* ── the message ──────────────────────────────────────────────────────────── */
.ib-label { font: 600 12px/1.3 var(--font-sans); color: var(--ib-ink-2); }
.ib-kinds { display: flex; gap: 6px; flex-wrap: wrap; }
.ib-textarea {
  width: 100%; min-height: 128px; padding: 12px; border: 1px solid var(--ib-rule-firm); border-radius: 6px; background: var(--ib-paper);
  font: 400 16px/1.45 var(--font-sans); color: var(--ib-ink); resize: vertical;
}
.ib-textarea::placeholder { color: var(--ib-ink-3); }
.ib-textarea:focus { outline: 2px solid var(--ib-gold); outline-offset: 1px; border-color: var(--ib-gold); }
.ib-msg { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: 8px; border: 1px solid var(--ib-rule); background: var(--ib-paper); }
.ib-msg.is-reply { background: var(--ib-gold-tint); border-color: var(--ib-gold-pale); }
.ib-msg-head { display: flex; justify-content: space-between; gap: 8px; font: 600 13px/1.3 var(--font-sans); color: var(--ib-ink); }
.ib-msg-head span:last-child { font-weight: 400; color: var(--ib-ink-3); }
.ib-msg-body { font: 400 13px/1.5 var(--font-sans); color: var(--ib-ink); white-space: pre-wrap; }
.ib-toast { position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom)); max-width: calc(100vw - 32px); box-sizing: border-box; transform: translateX(-50%); z-index: 350; padding: 12px 16px; border-radius: 8px; background: var(--ib-navy); color: #fff; font: 500 13px/1.3 var(--font-sans); box-shadow: 0 10px 30px -12px rgba(0,0,0,.5); }
.ib-error { padding: 12px 14px; border-radius: 8px; border: 1px solid var(--ib-red-rule); background: var(--ib-red-bg); color: var(--ib-red); font: 500 13px/1.45 var(--font-sans); }

.ib-divider { height: 1px; background: var(--ib-rule); }

/* Tickets ride inside the same shell: the page padding the board's main lost
   (the lanes carry their own), and the title in ink — the ticket sheet's
   heading token was written for the navy ground the old page painted. */
.ib-tickets { padding-top: 18px; }
.ib-tickets .ticket-page { width: 100%; }
.ib-tickets .ticket-heading { margin-bottom: 18px; }
/* tickets.css paints `.installer-shell .ticket-heading` for the navy ground
   the old installer page had; inside the dashboard shell the tickets sit on
   the light ground, so the heading goes back to ink at a higher specificity. */
.ib-shell .ib-tickets .ticket-heading h1 { color: var(--ib-navy); font-size: 26px; }
.ib-shell .ib-tickets .ticket-heading p { color: var(--ib-ink-2); }
.ib-inline-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }

@media (prefers-reduced-motion: reduce) {
  .ib-chip, .ib-btn, .ib-card, .ib-row { transition: none; }
  .ib-sk { animation: none; }
}

/* ── Capture: before/after photos, the charger check, the final pass ────────
   The same record the CRM card shows, written from the field. Big camera
   buttons, one row per shot, queued chips when there is no service. */
.ib-cap-head { padding: 4px 2px 0; }
.ib-cap-street { font: 600 16px/1.3 var(--font-sans); color: var(--ib-ink); }
.ib-cap-sub { font: 400 13px/1.5 var(--font-sans); color: var(--ib-ink-2); margin-top: 2px; max-width: 60ch; }
.ib-cap-slot { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ib-rule); border-radius: 8px; background: var(--ib-paper); }
.ib-cap-slot.has-shot { border-color: var(--ib-green-rule); }
.ib-cap-slot.is-next { border-color: var(--ib-gold); box-shadow: inset 0 0 0 1px var(--ib-gold); }
.ib-cap-slot-head { display: flex; align-items: center; gap: 12px; }
.ib-cap-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ib-cap-btn { position: relative; overflow: hidden; }
.ib-cap-btn input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: 16px; }
.ib-cap-btn.is-disabled { background: var(--ib-gold-pale); color: var(--ib-ink-3); pointer-events: none; }
.ib-cap-btn.secondary.is-disabled { background: var(--ib-panel); }
.ib-shots { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ib-shot { position: relative; width: 84px; height: 84px; border-radius: 6px; overflow: hidden; background: var(--ib-panel); border: 1px solid var(--ib-rule); }
.ib-shot-open { display: block; width: 100%; height: 100%; }
.ib-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ib-shot-doc { display: flex; align-items: center; justify-content: center; height: 100%; font: 700 11px/1 var(--font-sans); color: var(--ib-ink-2); }
.ib-shot-tag { position: absolute; left: 4px; bottom: 4px; padding: 1px 5px; border-radius: 4px; background: rgba(31,37,51,.72); color: #fff; font: 700 9.5px/1.3 var(--font-sans); text-transform: uppercase; letter-spacing: .04em; }
.ib-shot-tag-lh { left: auto; right: 4px; text-transform: none; letter-spacing: 0; }
.ib-shot-rm { position: absolute; top: 0; right: 0; width: 36px; height: 36px; border: 0; background: transparent; display: flex; align-items: flex-start; justify-content: flex-end; padding: 4px; cursor: pointer; }
.ib-shot-rm svg { background: rgba(31,37,51,.72); border-radius: 50%; padding: 6px; width: 24px; height: 24px; }
.ib-shot-ask { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; background: rgba(31,37,51,.86); color: #fff; font: 600 11px/1 var(--font-sans); }
.ib-shot-ask span { display: flex; gap: 6px; }
.ib-shot-ask button { min-height: 28px; padding: 0 10px; border: 0; border-radius: 6px; font: 600 11px/1 var(--font-sans); cursor: pointer; }
.ib-shot-ask .yes { background: var(--ib-red); color: #fff; }
.ib-shot-ask .no { background: rgba(255,255,255,.18); color: #fff; }
.ib-queued { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 4px 10px; border-radius: 999px; background: #fdf7e6; border: 1px solid #e6c46b; color: #6b4e0b; font: 500 12px/1.3 var(--font-sans); }
.ib-scan { position: relative; border-radius: 10px; overflow: hidden; background: #0f1117; aspect-ratio: 3 / 4; max-height: 62vh; }
.ib-scan video { width: 100%; height: 100%; object-fit: cover; display: block; }
.ib-scan-frame { position: absolute; inset: 14% 12%; border: 2px solid rgba(255,255,255,.85); border-radius: 12px; pointer-events: none; }
.ib-scan-cap { position: absolute; left: 0; right: 0; bottom: 12px; text-align: center; color: rgba(255,255,255,.85); font: 500 13px/1.3 var(--font-sans); }
.ib-scan-off { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; height: 100%; padding: 24px; text-align: center; color: rgba(255,255,255,.82); font: 400 13px/1.5 var(--font-sans); }
.ib-input { width: 100%; min-height: 48px; padding: 0 14px; border-radius: 8px; border: 1px solid var(--ib-rule-firm); background: var(--ib-paper); color: var(--ib-ink); font: 400 16px/1.3 var(--font-sans); }
.ib-input:focus { outline: 2px solid var(--ib-gold); outline-offset: 1px; border-color: var(--ib-gold); }
.ib-unit { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; border-radius: 8px; border: 1px solid var(--ib-rule); background: var(--ib-paper); }
.ib-unit-name { font: 600 16px/1.3 var(--font-sans); color: var(--ib-ink); }
.ib-unit-meta { font: 400 13px/1.45 var(--font-sans); color: var(--ib-ink-2); }
.ib-check { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 2px; font: 400 13.5px/1.4 var(--font-sans); color: var(--ib-ink); }
.ib-check.is-done { color: var(--ib-ink-2); }
.ib-note .ib-inline-actions { margin-top: 8px; }
