/* portal.css — manager-side mobile pass. Loaded AFTER style.css so it survives the
   shared-style.css redeploys (see 2026-08-22 mobile-patterns note). Mirrors what the
   service contour already does; touches only manager/leadership screens.
   Semantic colours (green/amber/red) are never redefined here. */

/* ── Tablet / half-screen / browser zoom (641–1100px): the topbar is ~1091px wide and
   does not wrap on its own, so the page slides sideways and rows look like they overflow.
   Force it to wrap, same as the phone rule does below 640px. ─────────────────────── */
@media (min-width:641px) and (max-width:1100px){
  .topbar-inner{flex-wrap:wrap;gap:8px 14px}
  .topbar nav{width:100%;flex-wrap:wrap;gap:6px 8px}
  .nav-uname{display:none}
}

/* ── Wide tables always scroll inside their own box (never clipped). The shared
   `table.grid{overflow:hidden}` otherwise cuts columns mid-word. ─────────────────── */
.scroll,.hist-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* ── Pills / filter rows wrap instead of stretching the page sideways. ───────────── */
.subtabs,.viewpills,.filters,.selectors,.vexport{flex-wrap:wrap}
/* Desktop: the search+city wrapper is transparent to layout (children flow inline with
   the fold toolbar). On mobile the @media rule below turns it into their own row. */
.card-filters{display:contents}

/* ── Phone (≤640px) ─────────────────────────────────────────────────────────────── */
@media (max-width:640px){
  /* iOS zooms the whole page when a focused field is < 16px. Never below 16. */
  input,select,textarea{font-size:16px}

  /* Comfortable tap targets (≥44px) for the controls managers actually poke — form
     fields, primary and status buttons, pills, arrows. Dense inline chips are left as
     they are so long lists don't turn into a ladder. */
  .btn,.filters select,.filters input,.selectors select,.selectors input,
  .addtask input,.addtask select,.addcomment input,.addcomment .grow,
  .viewpills .vp,.weekpick select,.station-q{min-height:46px}
  .btn.small{min-height:40px}
  .task-actions .mini{min-height:42px;padding:9px 14px}
  .nav-arrow,.navback{min-width:46px;min-height:46px}
  .task-sched{min-height:36px;padding:6px 12px;font-size:13px}

  /* Cards edge-to-edge: page gutters (0 14px on <main>) otherwise eat ~20% of a
     375px screen. Content padding inside the card stays. */
  .card{margin-left:-14px;margin-right:-14px;border-radius:0;border-left:0;border-right:0}

  /* Add-task / comment rows stack full-width instead of squeezing side by side. */
  .addtask,.addcomment{flex-wrap:wrap}
  .addtask input,.addtask select,.addtask .btn,
  .addcomment input,.addcomment .grow,.addcomment .btn{width:100%}
  .addtask .narrow,.addcomment .narrow{width:100%}

  /* Filter selects go full-width so they're easy to hit and read. */
  .filters select,.filters input:not([type=checkbox]),.selectors select,.selectors label,.station-q{width:100%}
  .filters .vexport,.filters .btn{width:auto}
  /* The multi-select enhancer swaps the <select> for its own button+panel, so the
     rule above misses it — size the visible control and its panel for the phone. */
  .filters .msf{display:block;width:100%}
  .filters .msf-btn{width:100%;max-width:none;min-height:46px}
  .filters .msf-panel{position:static;margin-top:4px;box-shadow:none;left:auto;right:auto;width:auto;min-width:0;max-width:none;max-height:50vh}
  .filters > .msf-apply{width:100%;min-height:46px}
  /* The list itself: bigger rows and checkboxes so options are easy to hit/read. */
  .msf-opt{font-size:15px;padding:11px 12px;white-space:normal}
  .msf-opt input{width:20px;height:20px}
  .msf-panel{max-height:60vh}
  .filters .msf-panel .msf-apply{min-height:44px;font-size:15px}

  /* Fold toolbar (Tasks · Hot · Calendar · search · city) wraps cleanly. Search and the
     city select share one row rather than stacking full-width. */
  .taskfold-sum{flex-wrap:wrap;gap:8px}
  .card-filters{display:flex;flex:1 1 100%;gap:8px}
  .card-vs{flex:1 1 60%;min-width:0}
  .card-vs .vq{width:100%}
  .card-city{flex:1 1 38%;width:auto;min-width:0}

  /* Phone: smaller title so the "Reactivate … 306d" line flows to ~2 lines, not 3. The
     column layout + head/tools placement are global (below), so nothing else needed here. */
  .task-title{font-size:14.5px;line-height:1.35}

  /* Flag drill-down rows (Week → open a flag). The row is one nowrap flex line
     (name · vending · city · Nd · +task · in progress · service). On a phone the
     buttons don't shrink, so the name column collapses to near-zero and the venue
     name breaks one word per line. Fix: let the row wrap, give the name the whole
     first line so it reads as a phrase, then flow the vending badge / city / age /
     action pills onto the line(s) below. Bigger pills = real tap targets. */
  .flag-venues li{flex-wrap:wrap;align-items:center;row-gap:7px}
  .flag-venues li>.venue-link,
  .flag-venues li>.fv-name{flex:1 1 100%;min-width:0;line-height:1.25}
  .flag-venues .fv-val{margin-left:0}          /* was margin-left:auto (desktop right-align) */
  .flag-venues .fv-task{flex-wrap:wrap;gap:6px}
  .fv-add{padding:6px 12px;font-size:12px}     /* touch-friendly action pills */
  /* Keep the action pills together on their own row: "+ task" and "in progress" sit
     side by side (and service joins them when present) instead of each dropping to a
     separate line. */
  .flag-venues li>.fv-acts{flex:1 1 100%;gap:8px}
}

/* Attention "+ task" pill states (AJAX add — see fvAct in base.html). The action is
   now explicit: the pill dims while posting, then turns solid green when the task is
   in. Applies on every screen — the reload used to make the click feel dead. */
.fv-add.fv-busy{opacity:.55;cursor:default;pointer-events:none}
.fv-add.fv-done,
.fv-add.fv-done:hover{background:var(--green-bg);border-color:transparent;
  color:var(--green-fg);opacity:1;cursor:default;pointer-events:none}

/* 90-day money-value badge on flag rows (A/B/C/D · €). Same A/B/C/D language as the
   service queue, but defined here so the manager side never depends on service.css.
   A = the venues carrying the money, D = earned nothing in the window. */
.vval{display:inline-flex;align-items:center;border-radius:6px;padding:0 6px;font-size:11px;
  font-weight:700;line-height:1.7;vertical-align:middle;white-space:nowrap}
.vval-A{background:var(--red-bg);color:var(--red-fg)}
.vval-B{background:var(--amber-bg);color:var(--amber-fg);font-weight:600}
.vval-C{background:var(--surface-1);color:var(--text-secondary);font-weight:600}
.vval-D{background:transparent;color:var(--text-muted);border:1px solid var(--border);font-weight:600}

/* Carried-over task badge — a task dragging forward from a previous week. Distinct
   outlined-accent chip so the drag-forward pile is visible at a glance; pairs with the
   "↪ Carried (N)" filter toggle in the Tasks fold header. */
.badge.b-carried{background:transparent;color:var(--accent);border:1px solid var(--accent);
  font-weight:600}

/* Venue grouping: one physical venue = one row even across vendings/badges. */
.fv-acts{display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap}
.fv-nst{font-size:10px;font-weight:600;color:var(--text-muted);background:var(--surface-1);
  border-radius:6px;padding:0 6px;white-space:nowrap}
.fv-xflag{font-size:10px;font-weight:600;color:var(--text-accent);background:var(--bg-accent);
  border:0.5px solid var(--border-accent);border-radius:6px;padding:0 6px;white-space:nowrap}

/* Low-value tail (C+D) folded under a toggle so a flag is a short actionable list,
   not a wall the manager can't clear. */
.flag-venues li.fv-lowwrap{display:block;padding:0;margin-top:2px}
.fv-lowfold>summary{cursor:pointer;color:var(--text-secondary);font-size:11px;font-weight:600;
  list-style:none;padding:5px 0}
.fv-lowfold>summary::-webkit-details-marker{display:none}
.fv-lowfold>summary::before{content:'\25B8 ';color:var(--text-muted)}
.fv-lowfold[open]>summary::before{content:'\25BE '}
.fv-lowtag{color:var(--text-muted);font-weight:600}
.flag-venues.fv-lowlist{border-top:0;padding:2px 0 2px;opacity:.9}

/* iOS safe-area: viewport-fit=cover + translucent status bar (standalone PWA) let the
   sticky top bar slide UNDER the clock/notch. Pad it down by the top inset so brand,
   back button and nav sit below the status bar. env()=0 on devices without an inset. */
.topbar{padding-top:env(safe-area-inset-top,0px)}
.imp-banner{padding-top:calc(7px + env(safe-area-inset-top,0px))}
@supports (padding:env(safe-area-inset-top)){
  main{padding-left:calc(14px + env(safe-area-inset-left,0px));
       padding-right:calc(14px + env(safe-area-inset-right,0px))}
}

/* Task-tag categories that live only on the manager side (style.css has the rest).
   low_rev = watch (amber), offline = hardware down / urgent (red). Loaded after
   style.css so these win and survive its redeploys. */
.ttag-low_rev{background:var(--amber-bg);color:var(--amber-fg)}
.ttag-offline{background:var(--red-bg);color:var(--red-fg)}

/* Offline service tasks live as ordinary rows in the 📋 Tasks list (no separate block),
   marked only by the 📴 Offline tag; the inline courier control sits under the row. */
.offline-task .sv-handoff{display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  margin-top:5px}
.offline-task .sv-handoff select,
.offline-task .sv-handoff input[type=date]{font-size:12px;padding:4px 6px}
@media (max-width:640px){
  .offline-task .sv-handoff{flex:1 1 100%}
  .offline-task .sv-handoff select{flex:1 1 60%}
}


/* ── Board & Queue on the phone: stack each row into a card so the wide table never
   scrolls sideways — the whole row fits the screen width. Hiding <thead> also drops the
   board's per-column find-row (it lives in the head); filtering stays in the Filters
   panel + the visible Sort. Both tabs use .sv-board, so they look identical. ───────── */
@media (max-width:640px){
  .sv-board thead{display:none}
  .sv-board, .sv-board tbody, .sv-board tr, .sv-board td{display:block;width:auto}
  .sv-board tr{border:1px solid var(--border);border-radius:12px;margin:0 0 10px;
    padding:8px 12px;background:var(--surface-2)}
  .sv-board td{border:0;padding:3px 0;font-size:13.5px}
  .sv-board td[data-l]::before{content:attr(data-l) ": ";color:var(--text-secondary);font-weight:600}
  .sv-board td.sv-c-id{font-weight:700;font-size:14px;margin-bottom:2px}
  .sv-board td.sv-c-open{margin-top:6px}
  .sv-board td.sv-c-open .btn{display:flex;align-items:center;justify-content:center;width:100%;text-align:center;background:var(--surface-1);font-weight:600;font-size:15px}
  .sv-board .sv-desc{max-width:none}
  /* sv-board rows are block-stacked above, so its .scroll has nothing to scroll; the
     wide grid tables (Outcomes / Tasks) MUST keep overflow-x:auto to swipe sideways —
     so no global .scroll override here (a previous overflow-x:visible broke them). */
}

/* ── Phone: wide grid tables (Outcomes W1..W4, Tasks) swipe sideways inside their
   .scroll wrapper instead of breaking the layout, with tighter type/padding so more
   fits on screen. ─────────────────────────────────────────────────────────────── */
@media (max-width:640px){
  .oc-table,.tasks-table{font-size:12px}
  .oc-table th,.oc-table td,.tasks-table th,.tasks-table td{padding:5px 6px}
  .oc-table td.ocw,.oc-table th.ocw{font-size:11px}
  .oc-table td:first-child,.oc-table th:first-child{position:sticky;left:0;
    background:var(--surface-1,#fff);z-index:1}
  .selectors .oc-xls{width:100%;justify-content:center}
  .oc-search .station-q,.oc-search{width:100%}
  .scroll,.tasks-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
}

/* Outcomes — weekly W1..W4 cells (status symbol + paid·revenue). Colours are semantic,
   never the accent; loaded after style.css so these win. */
.oc-table th.ocw{white-space:nowrap}
.oc-table td.ocw{white-space:nowrap;font-variant-numeric:tabular-nums;font-size:12px}
.ocw .ocw-sym{font-weight:700}
.ocw-good .ocw-sym{color:var(--green-fg,#137333)}
.ocw-bad  .ocw-sym{color:var(--red-fg,#b3261e)}
.ocw-watch{color:var(--text-secondary)}
.ocw-watch .ocw-sym{color:var(--amber-fg,#8a6d00)}
.ocw-muted{color:var(--text-muted)}
.ocw-pending,.ocw-pend{color:var(--text-muted);opacity:.5}
.ocw-good{background:color-mix(in srgb,var(--green-bg,#e6f4ea) 30%,transparent)}
.ocw-bad{background:color-mix(in srgb,var(--red-bg,#fce8e6) 22%,transparent)}

/* Outcomes ⬇ Excel button — align to the row's baseline (not centred) and match the
   select boxes' height so it doesn't read as a short, floating chip. */
.selectors .oc-xls{align-self:flex-end;padding:8px 14px;font-size:14px;line-height:1.25;
  height:auto;display:inline-flex;align-items:center}

/* Outcomes — settled venues fold (the 4-week window has passed). Default view shows only
   venues still in tracking; the rest live behind this disclosure. */
.oc-settled{margin-top:8px}
.oc-settled>summary{cursor:pointer;color:var(--text-secondary);font-size:13px;
  padding:8px 2px;list-style:none}
.oc-settled>summary::-webkit-details-marker{display:none}
.oc-settled>summary::before{content:'▸ ';color:var(--text-muted)}
.oc-settled[open]>summary::before{content:'▾ '}
.oc-table tr.oc-none td{padding:12px 6px}

/* "+ task" pill raised from an Outcomes row — small, next to the verdict badge. */
.oc-task{margin-left:8px;padding:2px 9px;font-size:11px;vertical-align:middle}

/* Task card stacks vertically: head (title + done) · meta · tools · comments. done sits
   top-right of the head and never overlaps the title (which wraps in its own flex column).
   Schedule/Photo + thumbnails share the tools row below the meta, left-aligned. */
.task{flex-direction:column;align-items:stretch;gap:5px}
/* The per-element margin-tops below come from the old inline task layout; in this
   column layout they ADD to the flex gap, so the row grew a different amount of air
   above each line. One gap, applied once. */
.task>.task-detail,.task>.task-meta,.task>.taskc{margin-top:0}
.task-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.task-head .task-title{flex:1 1 auto;min-width:0}
.task-done{flex-shrink:0}
.task-tools{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-start;align-items:center}
/* Unified light-grey rounded chip for both 📅 Schedule and 📷 Photo — same size. */
.task-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 11px;font-size:12px;
  line-height:1.2;border-radius:8px;background:var(--surface-2,#eef1f4);
  border:1px solid var(--border);color:var(--text-secondary);cursor:pointer;
  white-space:nowrap}
.task-chip:hover{background:var(--surface-1,#fff);border-color:var(--accent,#2b6cb0)}
label.task-chip.fv-busy{opacity:.6;cursor:default}
.task-photos{display:flex;flex-wrap:wrap;gap:6px;align-items:center;justify-content:flex-end;
  max-width:190px;margin:0}
.tphoto{position:relative;display:inline-flex}
.tphoto img{width:44px;height:44px;object-fit:cover;border-radius:8px;
  border:1px solid var(--border);display:block;background:var(--surface-2)}
.tphoto-x{position:absolute;top:-6px;right:-6px;width:18px;height:18px;line-height:15px;
  border-radius:50%;border:1px solid var(--border);background:var(--surface-1,#fff);
  color:var(--text-secondary);font-size:11px;cursor:pointer;padding:0;text-align:center}
/* File input triggered by clicking its label — visually hidden but focusable. */
.tphoto-input{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;opacity:0}

/* Escalate a task to the market lead — badge + inline actions on the task row. */
.badge.b-esc{background:var(--amber-bg,#fff4d6);color:var(--amber-fg,#8a6d00)}
.badge.b-fromsvc{background:#e8f1f8;color:#2c5d84;border:1px solid #bcd7ea;margin-left:6px;vertical-align:baseline}
.task-esc-btn{margin-left:6px;padding:2px 9px;font-size:11px;border:1px solid var(--border);
  border-radius:999px;background:transparent;color:var(--accent,#2b6cb0);cursor:pointer}
.task-esc-btn:hover{background:var(--surface-2)}
/* In the action row the Ask control stands next to Schedule / Photo, so it takes the
   chip's geometry — same height, same radius — and keeps its accent colour to stay
   readable as the one control that asks someone else for help. */
.task-tools .task-esc-btn{margin-left:0;padding:6px 11px;font-size:12px;line-height:1.2;
  border-radius:8px;background:var(--surface-2,#eef1f4)}
.task-tools .task-esc-btn:hover{background:var(--surface-1,#fff);border-color:var(--accent,#2b6cb0)}
.task-esc-x{margin-left:3px;padding:0 6px;font-size:11px;border:1px solid var(--border);
  border-radius:999px;background:transparent;color:var(--text-secondary);cursor:pointer}

/* Escalated-to-lead badge in the Attention row (before Other) + jump-to-task flash. */
.flag-esc>summary .flag-label{color:var(--red-fg,#b3261e)}
.task-flash{animation:taskFlash 1.6s ease-out}
@keyframes taskFlash{0%,30%{background:var(--amber-bg,#faeeda)}100%{background:transparent}}

/* Lead's single "Escalated to you" inbox at the top of Week (always shown for a lead /
   admin, even when empty), plus the per-card ⬆ Escalated badge state. */
.esc-inbox{background:var(--surface-2);border:0.5px solid var(--border);
  border-left:3px solid var(--red-fg,#b3261e);border-radius:12px;padding:10px 14px;margin:0 0 14px}
.esc-inbox-head{font-weight:600;font-size:14px;display:flex;align-items:center;gap:8px}
.esc-inbox-count{display:inline-flex;min-width:22px;height:22px;align-items:center;
  justify-content:center;border-radius:999px;background:var(--surface-1);
  color:var(--text-secondary);font-size:12px;padding:0 7px}
.esc-inbox-count.has{background:var(--red-bg,#fcebeb);color:var(--red-fg,#b3261e)}
.esc-inbox-list{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:2px}
.esc-inbox-list a{display:flex;gap:10px;align-items:baseline;padding:6px 8px;
  border-radius:8px;text-decoration:none;color:inherit}
.esc-inbox-list a:hover{background:var(--surface-1)}
.esc-mgr{color:var(--text-secondary);font-size:12px;min-width:112px}
.esc-ttl{flex:1;min-width:0;font-size:13px}
.esc-when{color:var(--text-muted);font-size:12px;white-space:nowrap}
.esc-inbox-empty{color:var(--text-muted);font-size:13px;margin-top:6px}
@media (max-width:640px){ .esc-mgr{min-width:0} .esc-inbox-list a{flex-wrap:wrap;gap:4px 10px} }

/* "Worked before": the venue was handled, sat out its 30-day hold and came back. Read
   as context, not as a new alarm — outline only, no fill, sand rather than red. */
.fv-revisit{display:inline-block;margin-left:6px;padding:0 6px;border-radius:9px;
  font-size:11px;font-weight:600;white-space:nowrap;color:#8a5a00;
  background:transparent;border:1px solid #d9b779}
.task .fv-revisit{margin-left:4px}

/* Task-list tail: laid out only after "Show more". Keeps a phone card from running to
   twenty screens, where Safari paints blank bands while scrolling. */
.tasklist.tmore-on .task.t-more{display:none}
.tmore-btn{margin:8px 0 2px;width:100%}
