/* ============================================================
   Mailbox Portal — shared design system
   Ported from the original index.html mockup. Brand tokens are
   CSS variables so a per-brand theme only has to override :root.
   ============================================================ */

:root{
  --ink:        #16233A;
  --ink-deep:   #0F1826;
  --brass:      #B8874A;
  --brass-light:#D7AF74;
  --paper:      #F6F3EC;
  --paper-line: #E4DFD2;
  --ink-text:   #1B2733;
  --slate:      #6B7686;
  --lit:        #3F7D5B;
  --error:      #B3432B;

  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'IBM Plex Sans', -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;
}

/* Dark theme: same shape, inverted paper/ink relationship. */
[data-theme="dark"]{
  --ink:        #EDE7DA;
  --ink-deep:   #F6F3EC;
  --paper:      #12141A;
  --paper-line: #262A33;
  --ink-text:   #EAEAEA;
  --slate:      #9098A6;
}

/* Canadian theme: brass swapped for a maple red accent. */
[data-theme="canadian"]{
  --brass:      #B3432B;
  --brass-light:#D97A63;
  --lit:        #3F7D5B;
}

*{ box-sizing:border-box; }
html,body{ margin:0; padding:0; }
body{
  font-family: var(--font-body);
  color: var(--ink-text);
  background: var(--paper);
  min-height:100vh;
}
a{ color: inherit; }
h1,h2,h3{ font-family: var(--font-display); font-weight: 500; margin: 0; }

/* ---------------- Split-panel auth pages (login) ---------------- */
.auth-layout{ display:flex; min-height:100vh; }
.stage{
  position:relative;
  flex: 1 1 46%;
  min-width: 340px;
  background: linear-gradient(160deg, var(--ink) 0%, var(--ink-deep) 100%);
  color: #EDE7DA;
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  padding: 3rem 3rem 2.5rem;
  overflow:hidden;
}
.stage-brand{ position:relative; z-index:2; }
.stage-mark{
  width:38px; height:38px;
  border: 1.5px solid var(--brass-light);
  border-radius: 3px;
  display:flex; align-items:center; justify-content:center;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--brass-light);
  margin-bottom: 1.4rem;
}
.stage-brand h1{ font-size: 1.7rem; margin: 0 0 0.5rem; letter-spacing: 0.01em; }
.stage-brand p{ font-size: 0.92rem; color: #B9C2CE; max-width: 26ch; line-height: 1.5; margin:0; }

.boxgrid{
  position:relative; z-index:1;
  display:grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 9px;
  margin: 2.4rem 0;
  flex: 1;
  align-content:center;
}
.box{
  aspect-ratio: 1;
  border: 1px solid rgba(216,175,116,0.28);
  border-radius: 2px;
  display:flex; align-items:flex-end; justify-content:flex-end;
  padding: 4px 5px;
  font-family: var(--font-mono);
  font-size: 0.55rem;
  color: rgba(216,175,116,0.45);
  background: rgba(255,255,255,0.015);
}
.box.lit{
  border-color: var(--lit);
  color: #DCEEE3;
  background: rgba(63,125,91,0.18);
  box-shadow: 0 0 0 1px rgba(63,125,91,0.25), 0 0 14px rgba(63,125,91,0.25);
  animation: glow 3.2s ease-in-out infinite;
}
@keyframes glow{
  0%, 100% { box-shadow: 0 0 0 1px rgba(63,125,91,0.25), 0 0 10px rgba(63,125,91,0.18); }
  50%      { box-shadow: 0 0 0 1px rgba(63,125,91,0.4), 0 0 18px rgba(63,125,91,0.35); }
}
@media (prefers-reduced-motion: reduce){ .box.lit{ animation:none; } }

.stage-foot{
  position:relative; z-index:2;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: #7C8798;
  letter-spacing: 0.03em;
  border-top: 1px solid rgba(255,255,255,0.08);
  padding-top: 1rem;
}
/* Second line of the customer sign-in stage footer (the copyright line). */
.stage-foot-copy{ display:block; margin-top: 0.4rem; font-size: 0.68rem; letter-spacing: 0.01em; }

.panel{ flex: 1 1 54%; display:flex; align-items:center; justify-content:center; padding: 2.5rem 2rem; }
.form-wrap{ width:100%; max-width: 380px; }
.form-wrap .eyebrow{
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 0.6rem;
}
.form-wrap h2{ font-size: 1.65rem; margin: 0 0 0.4rem; }
.form-wrap .sub{ color: var(--slate); font-size: 0.92rem; margin: 0 0 2rem; }

.field{ margin-bottom: 1.15rem; }
.field label{ display:block; font-size: 0.82rem; font-weight: 500; margin-bottom: 0.4rem; color: var(--ink-text); }
.field input, .field select, .field textarea{
  width:100%;
  padding: 0.72rem 0.85rem;
  border: 1.5px solid var(--paper-line);
  border-radius: 6px;
  background: #FFFFFF;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink-text);
  transition: border-color .15s ease;
}
.field input::placeholder{ color: #A6ADB8; }
.field textarea{ resize: vertical; font-family: var(--font-body); }
.field input:focus, .field select:focus, .field textarea:focus{
  outline: 2px solid var(--brass);
  outline-offset: 1px;
  border-color: var(--brass);
}
/* Opt-in toggle switch (email/SMS notification preferences) — a labeled
   on/off switch rather than a bare checkbox, so what it controls is obvious
   at a glance. */
.toggle-row{ display:flex; align-items:center; gap:0.85rem; cursor:pointer; }
.toggle-row + .toggle-row{ margin-top:0.9rem; }
.toggle-switch{ position:relative; display:inline-block; width:42px; height:24px; flex:none; }
.toggle-switch input{ opacity:0; width:0; height:0; position:absolute; }
.toggle-slider{ position:absolute; inset:0; background:#D7D2C4; border-radius:999px; transition:background-color .15s ease; }
.toggle-slider::before{ content:''; position:absolute; height:18px; width:18px; left:3px; top:3px; background:#fff; border-radius:50%; transition:transform .15s ease; box-shadow:0 1px 2px rgba(0,0,0,0.25); }
.toggle-switch input:checked + .toggle-slider{ background: var(--lit); }
.toggle-switch input:checked + .toggle-slider::before{ transform: translateX(18px); }
.toggle-switch input:focus-visible + .toggle-slider{ outline:2px solid var(--brass); outline-offset:2px; }
.toggle-label{ font-size:0.92rem; color: var(--ink-text); }
.toggle-label strong{ display:block; font-weight:500; }
.toggle-label small{ display:block; color: var(--slate); font-weight:400; font-size:0.78rem; margin-top:0.1rem; }

.field-pass-wrap{ position:relative; }
.toggle-pass{
  position:absolute; right:0.7rem; top:50%; transform:translateY(-50%);
  background:none; border:none; cursor:pointer;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--slate);
  padding: 0.2rem 0.3rem;
}
.toggle-pass:focus-visible{ outline: 2px solid var(--brass); outline-offset:1px; border-radius:3px; }

.row-between{ display:flex; align-items:center; justify-content:space-between; margin: 0.3rem 0 1.6rem; font-size: 0.85rem; }
.remember{ display:flex; align-items:center; gap:0.45rem; color: var(--slate); }
.remember input{ accent-color: var(--brass); }
.forgot-link{ color: var(--ink); text-decoration: underline; text-decoration-color: var(--paper-line); text-underline-offset: 3px; }
.forgot-link:hover{ text-decoration-color: var(--brass); }

.btn-primary{
  display:inline-block;
  width:100%;
  padding: 0.8rem 1rem;
  background: var(--ink);
  color: #F6F3EC;
  border: none;
  border-radius: 6px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  cursor:pointer;
  text-align:center;
  text-decoration:none;
  transition: background .15s ease, transform .1s ease;
}
.btn-primary:hover{ background: var(--ink-deep); }
.btn-primary:focus-visible{ outline: 2px solid var(--brass); outline-offset: 2px; }
.btn-primary:active{ transform: translateY(1px); }
.btn-primary.btn-auto{ width:auto; }

.btn-secondary{
  display:inline-block;
  padding: 0.65rem 1rem;
  background: #fff;
  color: var(--ink-text);
  border: 1.5px solid var(--paper-line);
  border-radius: 6px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.9rem;
  cursor:pointer;
  text-decoration:none;
}
.btn-secondary:hover{ border-color: var(--brass); }

.error-box, .success-box{
  background: #FBEFEC;
  border: 1px solid #EACBC0;
  color: var(--error);
  font-size: 0.85rem;
  padding: 0.7rem 0.85rem;
  border-radius: 6px;
  margin-bottom: 1.1rem;
}
.success-box{ background: #EDF5EF; border-color: #C7DECD; color: var(--lit); }

.divider{ display:flex; align-items:center; gap:0.75rem; color: var(--slate); font-size: 0.78rem; margin: 1.7rem 0 1.3rem; }
.divider::before, .divider::after{ content:''; flex:1; height:1px; background: var(--paper-line); }

.staff-link{
  display:block; text-align:center;
  font-size: 0.85rem;
  color: var(--slate);
  border: 1.5px solid var(--paper-line);
  border-radius: 6px;
  padding: 0.65rem;
  text-decoration:none;
}
.staff-link:hover{ border-color: var(--brass); color: var(--ink-text); }

.foot-note{ margin-top: 2.2rem; font-size: 0.78rem; color: var(--slate); text-align:center; line-height: 1.6; }
.foot-note a{ color: var(--slate); text-decoration: underline; text-decoration-color: var(--paper-line); }

@media (max-width: 860px){
  .auth-layout{ flex-direction:column; }
  .stage{ flex: 0 0 auto; min-width: 0; padding: 1.6rem 1.5rem; flex-direction: row; align-items:center; justify-content:space-between; }
  .boxgrid{ display:none; }
  .stage-foot{ display:none; }
  .stage-brand p{ display:none; }
  .stage-mark{ margin-bottom:0; }
  .panel{ padding: 2.2rem 1.4rem 3rem; }
}

/* ---------------- Logged-in app shell (dashboards) ---------------- */
.app-topbar{
  display:flex; align-items:center; justify-content:space-between;
  padding: 0.9rem 1.6rem;
  background: var(--ink);
  color: #EDE7DA;
}
.app-topbar .brand{ display:flex; align-items:center; gap:0.7rem; font-family: var(--font-display); font-size:1.15rem; }
.app-topbar .brand .mark{
  width:30px; height:30px;
  border: 1.5px solid var(--brass-light);
  border-radius: 3px;
  display:flex; align-items:center; justify-content:center;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--brass-light);
}
.app-topbar .who{ display:flex; align-items:center; gap:1rem; font-size:0.86rem; color:#C7CEDA; }
.app-topbar .who .role-badge{
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing:0.04em;
  text-transform:uppercase;
  color: var(--brass-light);
  border: 1px solid rgba(216,175,116,0.4);
  border-radius: 3px;
  padding: 0.15rem 0.45rem;
}
.app-topbar a{ color:#C7CEDA; text-decoration:none; }
.app-topbar a:hover{ color:#fff; }

.app-footer{ text-align:center; padding:1.1rem 1rem; font-size:0.78rem; color: var(--slate); border-top:1px solid var(--paper-line); }

.app-body{ display:flex; min-height: calc(100vh - 58px); }
.app-nav{
  flex: 0 0 200px;
  background: #fff;
  border-right: 1px solid var(--paper-line);
  padding: 1.2rem 0.8rem;
}
.app-nav a{
  display:block;
  padding: 0.55rem 0.7rem;
  margin-bottom: 0.2rem;
  border-radius: 6px;
  font-size: 0.88rem;
  text-decoration:none;
  color: var(--ink-text);
}
.app-nav a:hover{ background: var(--paper); }
.app-nav a.active{ background: var(--ink); color:#F6F3EC; }

/* min-width:0 overrides the flex-item default of min-width:auto — without
   it, a wide descendant (e.g. the dashboard's "Recent mail" table) forces
   this whole column, and everything inside it, wider than the viewport on
   narrow screens instead of wrapping/scrolling. Re-added 2026-09-18 — this
   line was found missing from a re-synced copy of this file; see
   oct1-cutover-readiness.md for what happened. */
.app-main{ flex:1; min-width:0; padding: 1.8rem 2rem; max-width: 1100px; }
.app-main h1{ font-size: 1.5rem; margin-bottom: 0.3rem; }
.app-main .page-sub{ color: var(--slate); font-size: 0.92rem; margin-bottom: 1.6rem; }

/* ---------------- Mobile nav (hamburger drawer) ---------------- */
/* Added 2026-09-18, per Patrick: mail intake needs to work from a staff
   phone (taking photos at the counter, not carrying a laptop over), and
   .app-nav below was a permanent 200px sidebar with no small-screen
   handling at all — at phone width it would eat roughly half the screen
   and leave .app-main crushed into what's left. Everything in this block
   only takes effect under the 860px breakpoint (the same breakpoint the
   auth pages already use above); above it .app-nav/.app-topbar are
   untouched, so desktop looks exactly as it did before. */
.nav-toggle{
  display:none;
  background:none;
  border:1px solid rgba(216,175,116,0.4);
  border-radius:6px;
  color:#EDE7DA;
  padding:0.35rem 0.65rem;
  font-size:1.15rem;
  line-height:1.2;
  cursor:pointer;
}
.nav-toggle:focus-visible{ outline:2px solid var(--brass); outline-offset:2px; }

.app-nav-backdrop{
  display:none;
  position:fixed;
  inset:0;
  background: rgba(15,24,38,0.45);
  z-index:40;
}
.app-nav-backdrop.is-open{ display:block; }

@media (max-width: 860px){
  .app-topbar{ padding: 0.8rem 1rem; gap:0.6rem; flex-wrap:wrap; }
  .app-topbar .brand{ font-size:1.05rem; gap:0.55rem; }
  .app-topbar .who{ gap:0.55rem; font-size:0.78rem; row-gap:0.3rem; }
  .nav-toggle{ display:inline-flex; align-items:center; justify-content:center; order:-1; }

  .app-body{ position:relative; }
  .app-nav{
    position:fixed;
    top:0;
    bottom:0;
    left:0;
    width:78vw;
    max-width:280px;
    z-index:50;
    background:#fff;
    transform: translateX(-100%);
    transition: transform .2s ease;
    box-shadow: 2px 0 18px rgba(0,0,0,0.2);
    overflow-y:auto;
    padding: 1.6rem 0.8rem;
  }
  .app-nav.is-open{ transform: translateX(0); }
  .app-nav a{ padding:0.7rem 0.75rem; font-size:0.95rem; }

  .app-main{ padding: 1.2rem 1rem 2.2rem; max-width:none; }
  .card{ padding: 1.1rem 1rem; }

  /* iOS Safari auto-zooms the whole page when a focused text input,
     select, or textarea computes under 16px — every one of these was
     0.85–0.95rem (≈13.6–15.2px). Staff typing tracking numbers or notes
     mid-intake on a phone would get an unwanted zoom-in on every tap into
     a field; 16px is the documented threshold that avoids it. Scoped to
     this breakpoint only, so desktop field density is unchanged. */
  .field input, .field select, .field textarea,
  .recipient-edit-form input[type="text"], .recipient-add-form input[type="text"],
  .verify-offline-row input[type="text"],
  .request-form textarea, .request-form select,
  .request-queue-actions input[type="text"],
  .request-queue-actions input[type="date"],
  .list-search, .list-location-filter{
    font-size: 16px;
  }

  /* Customer List toolbar (search + Administrator-only location filter):
     without a wrap, a long location name in the select plus the search
     input's own min-content width could in principle force the row wider
     than the screen, same flexbox min-width:auto trap fixed elsewhere in
     this file — wrap here is cheap insurance since the toolbar has no
     table-like unbreakable content forcing a specific width. */
  .list-toolbar{ flex-wrap:wrap; }
  .list-search{ flex:1 1 100%; max-width:none; order:3; }
  .list-location-filter{ flex:1 1 auto; }

  /* table.data-table's scroll-container behavior (display:block +
     overflow-x:auto) used to be defined here, mobile-only. It's now part of
     the base rule above so it applies at every screen width — see the
     comment there (2026-09-19) for why. Nothing phone-specific left to add
     here; kept as a marker in case another table-only mobile tweak is ever
     needed. */
}

/* Page title + top-right action button (e.g. "Add customer" on the
   Customers list — admin/customers.php). The action no longer gets its own
   left-nav line; it lives beside the title it belongs to instead. */
.page-header-row{
  display:flex;
  align-items:flex-start;
  gap:1rem;
  flex-wrap:wrap;
}
.page-header-row h1{ margin-bottom: 0.3rem; }
.page-header-row .page-sub{ margin-bottom: 0; }
/* margin-left:auto (not justify-content:space-between) so the button stays
   pinned to the right even if the row wraps to two lines on a narrow
   screen — space-between would drop it back to the left edge on its own
   wrapped line instead of keeping it right-aligned. */
.page-header-row .btn-primary{ flex:none; margin-top: 0.15rem; margin-left:auto; }

.stat-row{ display:flex; gap:1rem; flex-wrap:wrap; margin-bottom: 1.8rem; }
.stat-tile{
  background:#fff;
  border: 1px solid var(--paper-line);
  border-radius: 10px;
  padding: 1.1rem 1.3rem;
  min-width: 150px;
  flex: 1 1 150px;
}
.stat-tile .n{ display:inline-block; font-family: var(--font-display); font-size: 1.7rem; color: var(--ink); }
.stat-tile .l{ font-size: 0.8rem; color: var(--slate); margin-top:0.2rem; }
/* Only the number itself is a link through to the list behind it (round 19,
   2026-09-11 — Patrick's feedback: the whole tile, label included, reading
   as clickable was more than he wanted) — reset the default link styling on
   just that element and add a hover cue there. Tiles with nothing to link to
   yet (e.g. "Pickups this week" — pickup scheduling isn't built) simply
   render .n as a plain div instead of an <a>, so no extra class is needed to
   opt out. */
.stat-tile a.n{ text-decoration:none; color: var(--ink); cursor:pointer; }
.stat-tile a.n:hover{ color: var(--brass); text-decoration:underline; }
/* Documents-to-review gets a visible nudge once there's something waiting —
   the whole point is staff noticing without having to open every customer's
   record (round 18, 2026-09-11). */
.stat-tile-alert{ border-color: var(--error); background: #FBEFEC; }
.stat-tile-alert .n{ color: var(--error); }
.stat-tile-alert a.n:hover{ color: var(--error); opacity:0.8; }

.card{ background:#fff; border: 1px solid var(--paper-line); border-radius: 10px; padding: 1.4rem 1.5rem; margin-bottom:1.4rem; }
.card h2{ font-size: 1.1rem; margin-bottom: 1rem; }

/* display:block + overflow-x:auto turns the table itself into its own
   horizontal scroll container, so a table wider than its card scrolls
   inside the card instead of overflowing past its white background into
   the page (found 2026-09-19 on the customer-import preview table's 9
   columns, at full desktop width — this behavior used to be scoped to the
   860px mobile breakpoint only, on the assumption a wide table was a
   phone-only problem; it isn't, so it's unconditional now. Harmless when a
   table already fits its card, which is the common case. thead/tbody/tr/td
   keep their normal table rendering; only the outer <table> box changes. */
table.data-table{ display:block; max-width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch; width:100%; border-collapse: collapse; font-size: 0.88rem; }
table.data-table th{
  text-align:left;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing:0.04em;
  text-transform:uppercase;
  color: var(--slate);
  padding: 0.5rem 0.6rem;
  border-bottom: 1.5px solid var(--paper-line);
}
table.data-table td{ padding: 0.65rem 0.6rem; border-bottom: 1px solid var(--paper-line); }
table.data-table tr:last-child td{ border-bottom:none; }
.empty-row{ color: var(--slate); text-align:center; padding: 1.6rem 0 !important; }

.badge{ display:inline-block; padding: 0.15rem 0.55rem; border-radius: 20px; font-size: 0.74rem; font-weight:500; }
.badge-pending{ background:#F3EADB; color:#8A6420; }
.badge-active{ background:#EDF5EF; color: var(--lit); }
.badge-suspended, .badge-failed{ background:#FBEFEC; color: var(--error); }
.badge-neutral{ background:#EDEEF1; color: var(--slate); }

/* Brand/location "which locations does this apply to" checklist (admin/brands.php)
   — grouped by province, laid out as a fixed-column grid so entries line up
   across rows instead of wrapping raggedly. See project-plan.md section 2u. */
.location-groups{ margin-top:0.3rem; }
.location-province-group{ padding-bottom:0.9rem; margin-bottom:0.9rem; }
/* A visible rule between one province's location list and the next group's
   heading — not just whitespace — so scanning down a long brand's location
   list has a clear stopping point per province. The last group gets no
   trailing rule/margin since the field ends there anyway. */
.location-province-group + .location-province-group{ border-top: 1px solid var(--paper-line); padding-top:0.9rem; }
.location-province-group:last-child{ margin-bottom:0; padding-bottom:0; }
.location-province-label{
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing:0.04em;
  text-transform:uppercase;
  color: var(--slate);
  margin: 0 0 0.45rem;
}
/* Fixed 5-column grid (stepping down on narrow screens) so checkbox rows
   line up instead of wrapping raggedly. Selector is scoped through both
   ancestor classes (higher specificity than the generic ".field label"
   block-label rule elsewhere in this file) so the flex layout below always
   wins regardless of stylesheet order. */
.location-grid{
  display:grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.55rem 1rem;
}
.location-groups .location-grid label{
  display:flex;
  align-items:center;
  gap:0.4rem;
  font-size:0.9rem;
  font-weight:400;
  min-width:0;
  margin-bottom:0;
}
/* The checkbox and the "inactive" badge keep their natural size; the name
   gets whatever room is left in the column and only then ellipsizes —
   without flex:none here the badge (present on most not-yet-launched
   locations) would compete for space and the name would be squeezed down
   to a sliver instead. */
.location-groups .location-grid label input[type="checkbox"]{ flex:none; width:auto; }
.location-groups .location-grid label .badge{ flex:none; }
.location-groups .location-grid label span.loc-name{ flex:1 1 0%; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
@media (max-width: 900px){ .location-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px){ .location-grid{ grid-template-columns: 1fr; } }

/* Support-call-friendly mailbox identifier, e.g. "CAM-111" — customer
   profile page header. See includes/mailbox-address.php. */
.mailbox-code-badge{
  font-family: var(--font-mono);
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--brass);
  background: #FBF6EE;
  border: 1.5px solid var(--brass-light);
  border-radius: 8px;
  padding: 0.35rem 0.85rem;
  line-height: 1.2;
}

/* Mail intake — customer search & photo previews */
.intake-results{
  position:relative;
  margin-top:0.4rem;
  border: 1.5px solid var(--paper-line);
  border-radius: 6px;
  background:#fff;
  max-height: 260px;
  overflow-y:auto;
}
.intake-results[hidden]{ display:none; }
.intake-result{ padding:0.6rem 0.85rem; font-size:0.88rem; cursor:pointer; border-bottom:1px solid var(--paper-line); }
.intake-result:last-child{ border-bottom:none; }
.intake-result:hover{ background: var(--paper); }
.intake-result strong{ font-weight:500; }
.intake-result-empty{ padding:0.6rem 0.85rem; font-size:0.85rem; color: var(--slate); }
/* Shown under a live-search result when the hit came from a trade name,
   alias, or additional recipient rather than the customer's own name — so
   staff can tell which mailbox a shared recipient name belongs to. */
.intake-result-match{ font-size:0.78rem; color: var(--slate); margin-top:0.15rem; }
.intake-selected{
  margin-top:0.8rem;
  padding:0.7rem 0.9rem;
  background: var(--paper);
  border: 1px solid var(--paper-line);
  border-radius: 6px;
  font-size:0.9rem;
}
.intake-selected[hidden]{ display:none; }
.intake-selected a{ margin-left:0.6rem; color: var(--ink); text-decoration:underline; text-decoration-color: var(--paper-line); font-size:0.82rem; }

/* Mail intake — photo capture. Added 2026-09-18: staff take photos at the
   counter on a phone, so "Take a photo" (opens the camera directly via
   capture="environment") sits next to "Choose from library" (the original
   multi-select file picker); both feed the same hidden #photos input via
   the DataTransfer merge in mail-intake.php's script, so the server side
   (includes/uploads.php) needed no changes. */
/* flex:1 1 0 (not flex-wrap:wrap, which was the original approach) keeps
   "Take a photo" and "Choose from library" side by side at any width,
   splitting the row evenly — on a narrow phone the label text wraps onto a
   second line inside the button instead of the buttons themselves stacking
   into two full-width rows. Fixed 2026-09-18 — Patrick noted the original
   flex-wrap version looked fine on a computer but stacked into two separate
   rows on a phone, unlike the paired look on desktop. */
.intake-photo-actions{ display:flex; gap:0.6rem; margin-bottom:0.9rem; }
.intake-photo-actions label{ flex:1 1 0; text-align:center; }
.intake-photo-previews{ display:flex; flex-wrap:wrap; gap:0.6rem; margin-top:0.9rem; }
.intake-photo-previews .photo-thumb{ position:relative; width:96px; height:96px; }
.intake-photo-previews .photo-thumb img{ width:96px; height:96px; object-fit:cover; border-radius:6px; border:1px solid var(--paper-line); display:block; }
.intake-photo-previews .photo-thumb .photo-remove{
  position:absolute; top:-8px; right:-8px;
  width:22px; height:22px;
  border-radius:50%;
  background: var(--ink);
  color:#fff;
  border:1.5px solid #fff;
  font-size:0.8rem;
  line-height:1;
  cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  padding:0;
}
.intake-photo-previews .photo-thumb .photo-remove:focus-visible{ outline:2px solid var(--brass); outline-offset:1px; }
/* Rotate — bottom-left, distinct position from Remove (top-right) so the
   two are never confused at a glance or fat-fingered on a small screen. */
.intake-photo-previews .photo-thumb .photo-rotate{
  position:absolute; bottom:-8px; left:-8px;
  width:24px; height:24px;
  border-radius:50%;
  background: var(--brass);
  color:#fff;
  border:1.5px solid #fff;
  font-size:0.95rem;
  line-height:1;
  cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  padding:0;
}
.intake-photo-previews .photo-thumb .photo-rotate:hover{ background: var(--brass-light); }
.intake-photo-previews .photo-thumb .photo-rotate:focus-visible{ outline:2px solid var(--ink); outline-offset:1px; }
.intake-photo-previews .photo-thumb .photo-rotate:disabled{ opacity:0.6; cursor:default; }

/* Mail intake — tracking number + barcode scan. Added 2026-09-18: UPS/FedEx/
   Canada Post tracking numbers are long enough that mistyping on a phone
   keyboard is a real risk, so "Scan" decodes the barcode with the camera
   instead (client-side, via the ZXing library — see mail-intake.php). The
   button self-hides via JS when the browser has no camera API. */
.tracking-input-row{ display:flex; gap:0.5rem; align-items:stretch; }
.tracking-input-row input{ flex:1; min-width:0; }
.tracking-input-row .btn-scan{ flex:none; white-space:nowrap; }

.scanner-modal{
  position:fixed; inset:0; z-index:200;
  background: rgba(15,24,38,0.85);
  display:flex; align-items:center; justify-content:center;
  padding:1.2rem;
}
.scanner-modal[hidden]{ display:none; }
.scanner-modal-inner{
  background:#fff; border-radius:10px; padding:1.2rem;
  width:100%; max-width:420px;
  display:flex; flex-direction:column; align-items:center; gap:0.9rem;
}
.scanner-modal-inner video{
  width:100%; max-width:380px; aspect-ratio: 4 / 3;
  background:#000; border-radius:6px; object-fit:cover;
}
.scanner-hint{ font-size:0.85rem; color: var(--slate); text-align:center; margin:0; }
.scanner-error{ font-size:0.82rem; color: var(--error); text-align:center; margin:0; }
.scanner-error[hidden]{ display:none; }

/* Location choice / switching — admin/choose-location.php. Deliberately its
   own list container (.location-choice-list) rather than the generic
   ".field" wrapper used elsewhere: ".field input"/".field label" are styled
   for text inputs (full-width, padded, bordered) and, nested inside .field,
   those rules out-specificity the ones below — stretching the radio to a
   full-width box and collapsing this row to display:block. Patrick flagged
   the result as "too much spacing around the checkboxes" (2026-09-14); the
   real cause was this specificity clash, not just loose spacing — fixed by
   never nesting a .location-choice inside .field. */
.location-choice-list{ display:flex; flex-direction:column; gap:0.55rem; margin-bottom:1.3rem; }
.location-choice{
  display:flex; align-items:center; gap:0.7rem;
  padding:0.85rem 1rem;
  border: 1.5px solid var(--paper-line);
  border-radius: 8px;
  cursor:pointer;
  font-size:0.95rem;
  transition: border-color .15s ease, background-color .15s ease;
}
.location-choice:hover{ border-color: #C9BFA8; }
.location-choice:has(input:checked){ border-color: var(--brass); background: var(--paper); }
.location-choice input{ accent-color: var(--brass); width:auto; flex:none; margin:0; padding:0; border:none; }
.location-choice-name{ flex:1; }
.app-topbar .who .location-badge{
  display:flex; align-items:center; gap:0.4rem;
}
.app-topbar .who .location-badge a{ font-size:0.78rem; text-decoration:underline; text-decoration-color:#48566B; }

/* Customer List — search toolbar, sortable headers, pagination */
.list-toolbar{ display:flex; align-items:center; gap:0.6rem; margin-bottom:1.2rem; }
.list-search{
  flex:1; max-width:420px;
  padding: 0.6rem 0.8rem;
  border: 1.5px solid var(--paper-line);
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 0.9rem;
  color: var(--ink-text);
  background: #fff;
}
.list-search:focus{ outline:none; border-color: var(--brass); }
.list-location-filter{
  flex:none; min-width:0;
  padding: 0.6rem 0.8rem;
  border: 1.5px solid var(--paper-line);
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 0.9rem;
  color: var(--ink-text);
  background: #fff;
}
.list-location-filter:focus{ outline:none; border-color: var(--brass); }
.list-clear{ font-size:0.85rem; color: var(--slate); text-decoration:underline; }
table.data-table th a.sort-link{ color: inherit; text-decoration:none; }
table.data-table th a.sort-link:hover{ text-decoration:underline; }
table.data-table th .sort-arrow{ font-size:0.65rem; color: var(--brass); }
.pagination{ display:flex; gap:0.4rem; margin-top:1.2rem; flex-wrap:wrap; }
.pagination a, .pagination .page-current{
  display:inline-block;
  min-width:1.9rem;
  text-align:center;
  padding:0.3rem 0.5rem;
  border-radius:6px;
  font-size:0.85rem;
  text-decoration:none;
  color: var(--ink-text);
}
.pagination a{ border: 1px solid var(--paper-line); }
.pagination a:hover{ background: var(--paper); }
.pagination .page-current{ background: var(--ink); color:#F6F3EC; }

/* Additional recipients — one row per recipient (an edit form + a separate
   remove form, side by side), plus an "add" form at the bottom. */
.recipient-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:0.6rem;
  padding:0.7rem 0;
  border-bottom:1px solid var(--paper-line);
  flex-wrap:wrap;
}
.recipient-row:last-of-type{ border-bottom:none; }
.recipient-edit-form, .recipient-add-form{
  display:flex;
  align-items:center;
  gap:0.6rem;
  flex-wrap:wrap;
}
.recipient-edit-form{ flex:1; min-width:0; }
.recipient-add-form{ margin-top:0.9rem; padding-top:0.9rem; border-top:1px solid var(--paper-line); }
.recipient-edit-form input[type="text"], .recipient-add-form input[type="text"]{
  padding:0.55rem 0.7rem;
  border:1.5px solid var(--paper-line);
  border-radius:6px;
  background:#fff;
  font-family: var(--font-body);
  font-size:0.9rem;
  color: var(--ink-text);
  flex:1;
  min-width:130px;
}
.recipient-edit-form input[type="text"]:focus, .recipient-add-form input[type="text"]:focus{
  outline: 2px solid var(--brass);
  outline-offset: 1px;
  border-color: var(--brass);
}

/* "Mark verified in person" — offline ID verification, on the customer
   detail page's Verification & agreements card. */
.verify-offline-form{ margin-top:0.9rem; padding-top:0.9rem; border-top:1px solid var(--paper-line); }
.verify-offline-label{ display:block; font-size:0.85rem; color: var(--slate); margin-bottom:0.4rem; }
.verify-offline-row{ display:flex; align-items:center; gap:0.6rem; flex-wrap:wrap; }
.verify-offline-row input[type="text"]{
  padding:0.55rem 0.7rem;
  border:1.5px solid var(--paper-line);
  border-radius:6px;
  background:#fff;
  font-family: var(--font-body);
  font-size:0.9rem;
  color: var(--ink-text);
  flex:1;
  min-width:260px;
}
.verify-offline-row input[type="text"]:focus{
  outline: 2px solid var(--brass);
  outline-offset: 1px;
  border-color: var(--brass);
}

/* Customer List — the chevron toggle column and the expandable trade-names/
   aliases/recipients row nested under each customer, PostScanMail-style.
   Rows the current search matched via a recipient/alias/trade name (rather
   than the customer's own name) render already expanded, with the matching
   text in <mark>, so staff never have to guess which mailbox a shared
   recipient name belongs to. */
table.data-table th.col-toggle, table.data-table td.col-toggle{ width:2rem; padding-left:0.4rem; padding-right:0.2rem; }
.list-toggle{
  background:none;
  border:none;
  cursor:pointer;
  color: var(--brass);
  font-size:0.85rem;
  line-height:1;
  padding:0.2rem 0.3rem;
  border-radius:4px;
}
.list-toggle:hover{ background: var(--paper); }
tr.recipient-detail-row td{ background: var(--paper); border-bottom:1px solid var(--paper-line); padding:0.75rem 0.9rem; }
.recipient-detail{ display:flex; flex-direction:column; gap:0.3rem; font-size:0.85rem; color: var(--ink-text); }
.recipient-detail strong{ font-weight:600; color: var(--slate); margin-right:0.3rem; }
.recipient-detail mark{ background: var(--brass-light); color: var(--ink-deep); padding:0 0.2rem; border-radius:3px; }

/* Customer portal — mail item detail page: one small form per available
   request type (open & scan, forward, pickup, discard, long-term storage). */
.request-actions{ display:grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap:1.1rem; }
.request-form{
  border: 1px solid var(--paper-line);
  border-radius: 8px;
  padding: 1rem 1.1rem;
  display:flex;
  flex-direction:column;
  gap:0.6rem;
}
.request-form h3{ font-size:1rem; margin:0; }
.request-form textarea, .request-form select{
  width:100%;
  padding:0.6rem 0.7rem;
  border:1.5px solid var(--paper-line);
  border-radius:6px;
  background:#fff;
  font-family: var(--font-body);
  font-size:0.88rem;
  color: var(--ink-text);
  resize: vertical;
}
.request-form textarea:focus, .request-form select:focus{
  outline: 2px solid var(--brass);
  outline-offset: 1px;
  border-color: var(--brass);
}
.request-form textarea[name="comments"]{ min-height:2.6rem; }
.request-radio{ display:flex; align-items:center; gap:0.5rem; font-size:0.88rem; cursor:pointer; }
.request-radio input{ accent-color: var(--brass); }

/* Staff-facing, read-only list of a customer's submitted requests — no
   complete/cancel actions yet, that's the pending-request queue (build
   order item 8). */
.request-list-row{ display:flex; align-items:center; justify-content:space-between; gap:0.8rem; padding:0.65rem 0; border-bottom:1px solid var(--paper-line); flex-wrap:wrap; }
.request-list-row:last-child{ border-bottom:none; }
.request-list-meta{ color: var(--slate); font-size:0.82rem; }

/* Pending-request queue (admin/requests.php, build order item 8) — one row
   per open request, with Start/Cancel plus the type-specific fulfillment
   form (scan upload, tracking number, pickup/discard confirm, long-term
   storage date) inline. */
.request-queue-row{
  border: 1px solid var(--paper-line);
  border-radius: 8px;
  padding: 1rem 1.1rem;
  margin-bottom: 0.9rem;
  display:flex;
  flex-direction:column;
  gap:0.8rem;
}
.request-queue-row:last-child{ margin-bottom:0; }
.request-queue-actions{ display:flex; flex-wrap:wrap; gap:0.9rem; align-items:flex-end; }
.request-queue-actions form{ display:flex; flex-direction:column; gap:0.35rem; }
.request-queue-actions label{ font-size:0.78rem; color: var(--slate); }
.request-queue-actions input[type="text"],
.request-queue-actions input[type="date"],
.request-queue-actions input[type="file"]{
  padding:0.5rem 0.65rem;
  border:1.5px solid var(--paper-line);
  border-radius:6px;
  background:#fff;
  font-family: var(--font-body);
  font-size:0.85rem;
  color: var(--ink-text);
}
.request-queue-actions input[type="text"]:focus,
.request-queue-actions input[type="date"]:focus{
  outline: 2px solid var(--brass);
  outline-offset: 1px;
  border-color: var(--brass);
}
.request-queue-cancel-form{ margin-left:auto; }
.request-queue-cancel-form input[type="text"]{ min-width:200px; }

/* ============================================================
   Two-step verification (added 2026-09-21) — code entry, QR setup,
   recovery codes. See includes/mfa.php.
   ============================================================ */
.mfa-code-input{ font-family: var(--font-mono); font-size: 1.25rem; letter-spacing: 0.22em; text-align: center; }
.mfa-qr{ display:inline-block; padding: 0.7rem; background:#fff; border: 1px solid var(--paper-line); border-radius: 8px; line-height:0; }
.mfa-qr svg{ display:block; width: 190px; height: 190px; }
.mfa-key{ font-family: var(--font-mono); font-size: 0.95rem; letter-spacing: 0.06em; word-break: break-all; background: var(--paper); border: 1px solid var(--paper-line); border-radius: 6px; padding: 0.25rem 0.55rem; }
.mfa-steps{ padding-left: 1.2rem; margin: 0.6rem 0 0; }
.mfa-steps > li{ margin-bottom: 1.1rem; }
.mfa-codes{ list-style: none; margin: 1rem 0 0; padding: 1rem 1.1rem; display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.55rem 1.4rem; font-family: var(--font-mono); font-size: 1.05rem; letter-spacing: 0.05em; background: var(--paper); border: 1px dashed var(--brass); border-radius: 8px; }
.mfa-actions{ display: flex; flex-wrap: wrap; gap: 0.6rem; }
.info-box{ background: #F3EADB; border: 1px solid #E5D3B0; color: #6E5220; border-radius: 8px; padding: 0.7rem 0.9rem; font-size: 0.9rem; margin: 0 0 1rem; }
.sr-only{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
@media print{
  .app-topbar, .app-nav, .nav-toggle, .app-nav-backdrop, .mfa-noprint{ display:none !important; }
}
