/* ==========================================================================
   WrenchUr CMMS - component styles shared by the feature modules.
   Carried over from the demo (app/demo-src/demo-extra.css) when the real app
   was built, session 04. Map, chips, asset detail, lists, admin, modals.
   ========================================================================== */

/* ---- unlock screen ---- */
.step{font-family:var(--mono); font-size:11px; color:var(--accent); letter-spacing:.12em;}
.safe{background:rgba(61,220,132,.08); border:1px solid rgba(61,220,132,.32);
  border-radius:10px; padding:11px 13px; font-size:12.5px; margin:14px 0 4px; line-height:1.5;}
.safe b{color:var(--good);}

/* ---- role picker ---- */
.rolebtn{display:flex; align-items:center; gap:12px; text-align:left; padding:13px 14px;}
.rolebtn .rn{flex:none; width:26px; height:26px; border-radius:8px; font-size:12px; font-weight:700;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-dim); border:1px solid var(--accent-line); color:var(--accent);}
.rolebtn .rt{flex:1;}
.rolebtn .rt b{display:block; font-size:15px;}
.rolebtn .rt span{display:block; font-size:12px; color:var(--muted); margin-top:1px;}

/* ---- map ---- */
#mapWrap{position:absolute; inset:0; overflow:hidden; touch-action:none; background:#0a0d11;
  -webkit-user-select:none; user-select:none;}
#mapWorld{position:absolute; left:0; top:0; transform-origin:0 0;}
#mapImg{position:absolute; left:0; top:0; image-rendering:auto;}
#mapSvg{position:absolute; left:0; top:0; overflow:visible;}
.mapbar{position:absolute; left:0; right:0; bottom:0; z-index:5;
  display:flex; gap:8px; padding:10px 12px calc(10px + var(--sab));
  background:linear-gradient(transparent, rgba(13,16,21,.92) 34%);}
.mapbar button{flex:1;}
.maphint{position:absolute; top:10px; left:50%; transform:translateX(-50%); z-index:5;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--r-pill);
  padding:6px 14px; font-size:12px; color:var(--muted); white-space:nowrap;
  box-shadow:var(--shadow-sm);}
/* On a phone the hint wraps inside the screen instead of running off both
   edges (seen in the browser suite's 390 px screenshots, 2026-09-04). */
@media (max-width:560px){
  .maphint{white-space:normal; max-width:calc(100% - 24px); text-align:center; border-radius:var(--r-md); line-height:1.3;}
}

/* ---- target / department chips ---- */
/* Chips sit in one row and wrap only when they must, and stay small: the
   owner, 2026-09-11 - "the bubbles take up too much room ... which starts to
   fill the screen up". */
.chips{position:absolute; top:8px; left:50%; transform:translateX(-50%); z-index:6;
  display:flex; flex-direction:row; flex-wrap:wrap; justify-content:center; gap:5px; align-items:center;
  max-width:calc(100% - 16px);}
.chip{display:flex; align-items:center; gap:6px; padding:3px 4px 3px 11px;
  border-radius:var(--r-pill); font-size:12.5px; font-family:var(--mono);
  background:var(--panel); box-shadow:var(--shadow); max-width:100%;}
.chip.target{border:1px solid var(--target);}
.chip.dept{border:1px solid var(--target);}
.chip b{color:var(--target); font-weight:700;}
.chip .cn{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.chip button{min-height:26px; padding:2px 9px; font-size:12px; border-radius:var(--r-pill);}
.chip button.x{padding:2px 8px; font-size:15px; line-height:1; color:var(--muted);}

/* ---- find target marker ---- */
@keyframes tpulse{
  0%{r:14; opacity:.95}
  70%{r:40; opacity:0}
  100%{r:40; opacity:0}
}
.tTag circle.ring{fill:none; stroke:var(--target); stroke-width:3;
  animation:tpulse 1.4s ease-out infinite;}
.tTag circle.core{fill:var(--target); stroke:#fff; stroke-width:2;}
.tTag text{font-family:var(--mono); font-size:14px; font-weight:700; fill:var(--target);
  paint-order:stroke; stroke:rgba(13,16,21,.9); stroke-width:4px;}

/* ---- department highlight ---- */
/* The selected department flashes between SOLID WHITE and its own colour in
   hard steps — not a soft fade between two shades. Owner, 2026-09-02: "the
   two shades thing does not work for color blind people, in fact we have a
   grey scale worker that only sees in greys." White against any block reads
   as a flash in greyscale. */
@keyframes dblink{0%,49.9%{opacity:1} 50%,100%{opacity:0}}
#deptMask{position:absolute; left:0; top:0; pointer-events:none;
  animation:dblink 1s steps(1, end) infinite; image-rendering:pixelated;}
@media (prefers-reduced-motion:reduce){
  #deptMask{animation:none; opacity:.6;}
  .tTag circle.ring{animation:none; opacity:.8;}
}
.aTag{cursor:pointer;}
.aTag text{font-family:var(--mono); font-size:13px; fill:#0d1015; paint-order:stroke;
  stroke:rgba(255,255,255,.92); stroke-width:3.5px; font-weight:600;}
/* Two circles per marker: an invisible tap target and the visible dot.
   Style ONLY .dot — never bare `circle` — or the status colours below will
   also paint the 15px hit target and every flagged machine becomes a blob. */
/* --pin, not --accent: the marker colour was tuned in the field against the
   coloured floor plan (v13) and does not follow the brand pass. */
.aTag circle.dot{fill:var(--pin); stroke:#fff; stroke-width:1.5;}
.aTag circle.hit{fill:none; stroke:none; pointer-events:all;}
/* The pin is ONE shape, ONE size, the same white outline, in every state —
   only the fill changes (owner, 2026-09-04, D74: "the circles are always
   supposed to be the same shape and size and nothing around them but just
   the color changes"). No dashed outlines, no heavy strokes, no rings.
     blue    (--pin)        nothing on it, or the job is done
     orange  (--pin-job)    a job on it; blinking until the technician accepts it
     red     (--pin-safety) a safety related job (D71); blinking the same way
   The colours are fixed, not the theme's warn/bad: the light theme's warn
   is a brown chosen for text contrast and read as brown on the map. */
.aTag.job circle.dot{fill:var(--pin-job);}
.aTag.job.safety circle.dot{fill:var(--pin-safety);}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.25}}
.aTag.blink circle.dot{animation:pulse 1s infinite;}
@media (prefers-reduced-motion:reduce){ .aTag.blink circle.dot{animation:none;} }

/* ---- RTU air units ---- */
.rTag{cursor:pointer;}
.rTag circle.hit{fill:none; stroke:none; pointer-events:all;}
.rTag rect{fill:#2b6cb0; stroke:#fff; stroke-width:1.5; rx:4;}
.rTag text.rn{font-family:var(--mono); font-size:11px; font-weight:700; fill:#fff;
  paint-order:normal; stroke:none;}
.rTag text{font-family:var(--mono); font-size:12px; fill:#0d1015; font-weight:600;
  paint-order:stroke; stroke:rgba(255,255,255,.92); stroke-width:3.5px;}
.rTag.on rect{fill:var(--target);}
.rTag.on text{stroke:rgba(255,220,235,.95);}
.chip.rtu{border:1px solid #2b6cb0;}
.chip.rtu b{color:#7fb3e8;}

/* ---- machine being placed ---- */
.pendTag circle{fill:none; stroke:var(--pin); stroke-width:2.5;}
.pendTag line{stroke:var(--pin); stroke-width:2.5;}
.pendTag text{font-family:var(--mono); font-size:14px; fill:var(--pin); font-weight:700;
  paint-order:stroke; stroke:rgba(13,16,21,.85); stroke-width:4px;}

/* ---- book search result ---- */
.brow{display:flex; align-items:center; gap:10px; padding:11px 6px;
  border-bottom:1px solid var(--line); cursor:pointer;}
.brow:hover{background:var(--panel);}
.brow.on{opacity:.45; cursor:default;}
.brow .bn{font-family:var(--mono); font-size:15px; min-width:62px;}
.brow .bd{flex:1; min-width:0;}
.brow .bd b{display:block; font-size:13.5px; font-weight:500;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.brow .bd span{font-size:11.5px; color:var(--muted);}

/* ---- Find: a small box over the map (owner, 2026-09-04: "a small window
   that lets me type it out and as im doing it it auto fills ... click the
   asset i want ... and it instantly shows it"). The map stays visible
   behind it; the list scrolls inside the box, never the page. */
#findWrap{position:absolute; left:10px; bottom:calc(66px + var(--sab)); z-index:10;
  width:min(380px, calc(100% - 20px)); max-height:min(62%, 440px);
  background:var(--bg); border:1.5px solid var(--line); border-radius:var(--r-md);
  box-shadow:0 8px 28px rgba(0,0,0,.35);
  display:flex; flex-direction:column; overflow:hidden;}
#findWrap .hd{padding:10px; border-bottom:1px solid var(--line); display:flex; gap:8px; align-items:center;}
#findWrap .hd input{flex:1; min-width:0; margin:0;}
#findWrap .hd button.x{flex:none; width:38px; padding:0; font-size:16px;}
#findWrap .scroll{overflow:auto; min-height:0;}
#findWrap .srow{padding:9px 12px;}
.srow{display:flex; justify-content:space-between; align-items:center; gap:10px;
  padding:12px 14px; border-bottom:1px solid var(--line); cursor:pointer;}
.srow:hover{background:var(--panel);}
/* "report it anyway" — sits at the top, so mark it as the odd one out
   rather than letting it look like just another search hit. */
.srow.useThis{background:rgba(255,182,72,.07); border-left:3px solid var(--warn);
  padding-left:11px;}
.srow.useThis:hover{background:rgba(255,182,72,.14);}
.srow .n{font-family:var(--mono); font-size:15px; color:var(--text);}
.srow .d{font-size:12px; color:var(--muted); margin-top:2px;}

/* ---- lists ---- */
.item{padding:14px; border:1px solid var(--line); border-radius:var(--r-md);
  background:var(--chrome); margin-bottom:10px;}
.item .h{display:flex; align-items:center; gap:9px; margin-bottom:6px;}
.item .h .n{font-family:var(--mono); font-size:15px; font-weight:600;}
.item .b{font-size:14px; line-height:1.5;}
.item .m{font-size:12px; color:var(--muted); margin-top:8px;}

/* ---- asset detail ---- */
/* screens.css gives every child of .modroot flex:1, which is right for a
   single scrolling body but on a tall PC window it stretched the machine
   header and the tab bar to a third of the screen each. Only the scrolling
   body should grow. */
.modroot > .ahead, .modroot > .tabs, .modroot > span{flex:none;}
.ahead{padding:16px; border-bottom:1px solid var(--line);}
.ahead .no{font-family:var(--mono); font-size:26px; font-weight:700; letter-spacing:-.01em;}
.ahead .nm{font-size:15px; margin-top:2px;}
.kv{display:grid; grid-template-columns:auto 1fr; gap:4px 14px; font-size:13px; margin-top:12px;}
.kv dt{color:var(--muted);}
.kv dd{margin:0; font-family:var(--mono);}
.tabs{display:flex; gap:4px; padding:10px 12px 0; border-bottom:1px solid var(--line);}
.tabs button{flex:1; min-height:38px; border-radius:var(--r-sm) var(--r-sm) 0 0;
  border-bottom:2px solid transparent; background:transparent; font-size:13.5px;}
.tabs button.on{border-bottom-color:var(--accent); color:var(--accent); background:var(--accent-dim);}
/* QA audit 2026-09-03 P1: six tabs were 451 px wide in a 390 px phone and the
   page dragged sideways to reach Docs. On a narrow screen the strip wraps into
   rows of three; the body never scrolls sideways. */
@media (max-width:600px){
  .tabs{flex-wrap:wrap; gap:4px 3px;}
  .tabs button{flex:1 1 30%; min-width:30%; padding-left:6px; padding-right:6px; font-size:14px;}
}
/* QA audit P2: floor-action buttons met 36 px against the app's own 44 px
   touch target. On a touch screen every small button is at least 44 px. */
@media (pointer:coarse){
  .item button.small, .btnrow button.small, .urow button.small, .arow button.small,
  .vrow button.small, .modroot .tabs button{min-height:44px;}
  /* The map's chips are the exception (owner, 2026-09-11: they filled the
     phone's screen at 44 px): 36 px, still a comfortable thumb target. */
  .chip button{min-height:36px;}
}
.entry{display:flex; gap:11px; padding:12px 0; border-bottom:1px solid var(--line);}
/* The timeline marker says what kind of entry it is by SHAPE as well as
   colour (rule 8; QA audit 2026-09-03): repair = filled circle, request =
   diamond, note = square, photo = hollow ring. */
.entry .dot{flex:none; width:9px; height:9px; border-radius:50%; margin-top:6px; background:var(--muted);}
.entry.repair .dot{background:var(--good);}
.entry.req .dot{background:var(--warn); border-radius:1px; transform:rotate(45deg) scale(.9);}
.entry.note .dot{background:var(--accent); border-radius:2px;}
.entry.photo .dot{background:transparent; border:2px solid var(--muted); width:8px; height:8px;}
.entry .c{flex:1; min-width:0;}
.entry .c .t{font-size:14px; line-height:1.45;}
.entry .c .m{font-size:11.5px; color:var(--muted); margin-top:3px; font-family:var(--mono);}
.photos{display:grid; grid-template-columns:repeat(auto-fill,minmax(96px,1fr)); gap:8px; padding:2px 0 12px;}
button.pcell{padding:0; border:0; background:none; position:relative; min-height:0;
  border-radius:var(--r-sm); overflow:hidden; width:100%;}
.photos img{width:100%; aspect-ratio:1; object-fit:cover; border-radius:var(--r-sm);
  border:1px solid var(--line); background:var(--panel); display:block;}
button.pcell:hover img{border-color:var(--accent-line);}
.ptag{position:absolute; left:5px; bottom:5px; font-size:9.5px; font-family:var(--mono);
  background:rgba(11,22,48,.85); color:var(--ink-muted); padding:1px 6px; border-radius:var(--r-pill);}

/* photo attached to an activity entry */
button.pthumb{padding:0; border:0; background:none; min-height:0; margin-top:7px;
  border-radius:var(--r-sm); overflow:hidden; display:block; width:120px;}
button.pthumb img{width:120px; height:90px; object-fit:cover; display:block;
  border:1px solid var(--line); border-radius:var(--r-sm);}
button.pthumb:hover img{border-color:var(--accent-line);}

/* preview inside a modal */
img.preview{width:100%; max-height:38vh; object-fit:contain; border-radius:var(--r-md);
  background:var(--chrome); border:1px solid var(--line); display:block;}
img.preview.big{max-height:60vh;}
/* ---- purchase history ---- */
.ord{padding:12px 0; border-bottom:1px solid var(--line);}
.ord .oh{display:flex; align-items:baseline; gap:9px; margin-bottom:5px;}
.ord .od{font-family:var(--mono); font-size:12.5px; color:var(--muted);}
.ord .op{font-family:var(--mono); font-size:12.5px; color:var(--accent);}
.ord .ov{font-family:var(--mono); font-size:14px; font-weight:600;}
.ord .ot{font-size:14px; line-height:1.45; margin-bottom:4px;}
.ord .om{font-family:var(--mono); font-size:11.5px; color:var(--muted); line-height:1.5;}
button.vend{margin-top:9px; min-height:30px; padding:5px 11px; font-size:12.5px;
  border-radius:var(--r-pill); background:var(--accent-dim); border-color:var(--accent-line);
  color:var(--accent); width:auto;}
button.vend:hover{background:var(--accent-hi);}

/* ---- search field selector ---- */
.segs{display:flex; gap:6px; margin-top:9px; flex-wrap:wrap;}
button.seg{min-height:30px; padding:5px 13px; font-size:12.5px; border-radius:var(--r-pill);
  background:transparent; color:var(--muted); border:1px solid var(--line); width:auto;}
button.seg:hover{color:var(--text); border-color:var(--accent-line);}
button.seg.on{background:var(--accent-dim); border-color:var(--accent-line); color:var(--accent);
  font-weight:600;}
/* the Assets tile's kind switch — Machines | Air units — a bigger pair at the top */
.segs.kinds{margin:0 0 12px;}
.segs.kinds button.seg{flex:1; min-height:40px; font-size:14.5px;}

/* ---- asset register ---- */
.arow{display:flex; align-items:center; gap:11px; padding:12px 0;
  border-bottom:1px solid var(--line); cursor:pointer;}
.arow:hover{background:var(--panel);}
.ano{flex:none; min-width:64px; display:flex; align-items:center; gap:6px;}
.ano b{font-family:var(--mono); font-size:15px;}
.dot-on{width:6px; height:6px; border-radius:50%; background:var(--accent); flex:none;}
.ainfo{flex:1; min-width:0;}
.ainfo b{display:block; font-size:14px; font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.ainfo span{display:block; font-size:11.5px; color:var(--muted); margin-top:1px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.ainfo .atags{font-family:var(--mono); color:var(--accent); opacity:.8;}
.arow .chev{flex:none; color:var(--muted); font-size:20px; line-height:1;}
/* why this row matched, when it was not the asset number */
.arow .why, .vrow .why{flex:none; font-size:10.5px; font-family:var(--mono);
  color:var(--warn); border:1px solid rgba(255,182,72,.35); border-radius:var(--r-pill);
  padding:2px 8px; white-space:nowrap;}

/* full record, as a spec sheet */
.kv.spec{grid-template-columns:auto 1fr; gap:7px 16px; font-size:13.5px; margin:2px 0 0;}
.kv.spec dt{color:var(--muted); white-space:nowrap;}
.kv.spec dd{font-family:var(--mono); word-break:break-word;}

/* ---- vendor directory ---- */
.vrow{display:flex; align-items:center; gap:9px; padding:12px 0;
  border-bottom:1px solid var(--line);}
.vinfo{flex:1; min-width:0; cursor:pointer;}
.vinfo b{display:block; font-size:14px; font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.vinfo span{display:block; font-size:11.5px; color:var(--muted); margin-top:2px;
  font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.vrow:hover .vinfo b{color:var(--accent);}

/* ---- vendor contact card ---- */
.cbtns{display:flex; flex-wrap:wrap; gap:7px; margin-top:7px;}
a.cbtn{display:inline-flex; align-items:center; gap:7px; text-decoration:none;
  min-height:36px; padding:7px 13px; border-radius:var(--r-pill);
  border:1px solid var(--line); background:var(--panel); color:var(--text);
  font-size:12.5px; font-family:var(--mono); max-width:100%;}
a.cbtn:hover{border-color:var(--accent-line); background:var(--panel-2);}
a.cbtn span:last-child{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
a.cbtn.mail{background:var(--accent-dim); border-color:var(--accent-line); color:var(--accent);}
a.cbtn.mail:hover{background:var(--accent-hi);}
a.cbtn .ci{flex:none; font-family:var(--sans); font-size:13px;}

.vaddr{margin-top:14px; padding:12px 13px; background:var(--panel);
  border:1px solid var(--line); border-radius:var(--r-md);
  font-size:13px; line-height:1.55;}
.vaddr .vmeta{margin-top:7px; font-size:11.5px; color:var(--muted); font-family:var(--mono);}

.contact{padding:11px 0; border-bottom:1px solid var(--line);}
.contact:last-child{border-bottom:0;}
.mailbody{margin:8px 0 0; padding:10px 11px; background:var(--chrome);
  border:1px solid var(--line); border-radius:var(--r-sm);
  font-family:var(--mono); font-size:11.5px; line-height:1.55; color:var(--muted);
  white-space:pre-wrap; word-break:break-word; overflow-x:auto;}

.contact b{display:block; font-size:14px;}
.contact .cpos{display:block; font-size:11.5px; color:var(--muted); margin-top:2px; line-height:1.45;}

table.ord{width:100%; border-collapse:collapse; font-size:12px; font-family:var(--mono);}
table.ord th{text-align:left; color:var(--muted); font-weight:600; padding:6px 8px;
  border-bottom:1px solid var(--line); white-space:nowrap;}
table.ord td{padding:6px 8px; border-bottom:1px solid var(--line); white-space:nowrap;}
.tblwrap{overflow-x:auto; -webkit-overflow-scrolling:touch;}

/* ---- admin ---- */
.urow{display:flex; align-items:center; gap:10px; padding:12px 0; border-bottom:1px solid var(--line);}
.urow .ui{flex:1; min-width:0;}
.urow .ui b{display:block; font-size:14.5px;}
.urow .ui span{font-size:12px; color:var(--muted); font-family:var(--mono);}
.urow.off{opacity:.45;}
/* Admin tabs (owner, 2026-09-03: one tab per section, up top). The chosen
   tab is bold with a thick underline and a frame — never a hue alone (rule 8).
   Scrolls sideways on a phone instead of wrapping into a wall of buttons. */
.admtabs{display:flex; gap:4px; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:thin;
  border-bottom:2px solid var(--line); margin:0 0 14px; padding:0 0 0; position:sticky; top:0; z-index:2; background:var(--bg);}
.admtabs::-webkit-scrollbar{height:4px;}
button.admtab{flex:0 0 auto; appearance:none; background:transparent; border:1px solid transparent; border-bottom:none;
  border-radius:8px 8px 0 0; padding:9px 13px; margin-bottom:-2px; font:inherit; font-size:13.5px; color:var(--muted);
  cursor:pointer; white-space:nowrap; border-bottom:3px solid transparent;}
button.admtab:hover{color:var(--text); background:var(--panel);}
button.admtab.on{color:var(--text); font-weight:700; border-color:var(--line); border-bottom:3px solid var(--text); background:var(--panel);}
button.admtab:focus-visible{outline:2px solid var(--text); outline-offset:-2px;}
@media (pointer:coarse){ button.admtab{min-height:44px;} }
@media print{ .admtabs{display:none;} }

/* the rotorhead badge in the hub tiles is styled beside the tile rules in
   screens.css (owner, 2026-09-04) */
.lockrow{display:flex; justify-content:space-between; gap:10px; padding:8px 0;
  border-bottom:1px solid var(--line); font-size:13px; font-family:var(--mono);}

/* A tall modal must SCROLL, not overflow. app.css centres it with
   align-items:center and no overflow, so a card taller than the viewport
   gets clipped at both ends — putting Save and Cancel off-screen. Reaching
   for them then hits the backdrop, which dismisses and discards the edit.
   flex-start + margin:auto keeps short cards centred and lets tall ones scroll. */
.modal{align-items:flex-start; overflow-y:auto; -webkit-overflow-scrolling:touch;}
.modal .card{margin:auto;}
/* EVERY box sits at the top on a touch screen, where the on-screen keyboard
   would cover a centered one (owner, 2026-09-11: "do the same for all pop ups
   so the writers can see what they are typing in any field"). Still centered
   with a mouse. docs.js builds its own .modal and gets this too. */
@media (pointer:coarse){
  .modal .card{margin:8px auto auto;}
}

/* ---- permission toggles ---- */
.permlist{max-height:38vh; overflow-y:auto; margin-top:6px;
  border:1px solid var(--line); border-radius:var(--r-md); padding:4px 12px;}
.permlist h3{margin:14px 0 4px; font-size:11px;}
.permrow{display:flex; align-items:center; gap:10px; padding:8px 0; margin:0;
  font-size:13.5px; color:var(--text); cursor:pointer; border-bottom:1px solid var(--line);}
.permrow:last-child{border-bottom:0;}
.permrow input{width:auto; flex:none; margin:0; accent-color:var(--accent);
  width:18px; height:18px; cursor:pointer;}
.permrow span{flex:1; line-height:1.35;}
.permnote{font-size:12px; color:var(--muted); margin:10px 0 0; line-height:1.5;}
