/* ==========================================================================
   THE SHOP SKIN - trial branch trial/human-skin, 2026-09-16.

   Owner, after a maintenance group read the screenshots: one man took his
   comment down saying it looked like AI slop, another opened with "while you
   used ai heavily in this". The brief: keep the colours, keep the structure,
   change the LOOK so the first thought is "a person who has turned a wrench
   built this", not "a machine generated this".

   What reads as machine-made, and what this file does about it:
     emoji icons            -> drawn line icons (core/icons.js), same hand as
                               the wrench on urwrench.com
     everything a soft card -> square corners, hairlines, no glow, no bloom
     even, airy spacing     -> tighter rows; a screen shows more work
     round icon discs       -> no discs; the icon sits in the text
     bubbly pills           -> square tags, mono, uppercase
     one weight everywhere  -> a condensed face for headings and labels, the
                               way a shop drawing, a nameplate or a parts
                               catalogue is set

   Loaded LAST in index.html, so this file alone carries the skin and pulling
   one line out of index.html puts the old look back. Nothing here changes a
   screen's structure, its copy or its behaviour.
   ========================================================================== */

:root{
  /* Corners: a tool is machined, not moulded. */
  --r-sm:2px; --r-md:3px; --r-lg:3px; --r-btn:2px; --r-pill:2px;

  /* Depth by line, not by shadow. A dark shop screen with glowing cards is
     the giveaway; a hairline is what a drawing uses. */
  --shadow:0 1px 0 rgba(3,8,20,.55);
  --shadow-sm:none;
  --glow:transparent;

  /* A condensed, engineering-drawing face for headings, labels and controls.
     Every name here ships with the platform: Bahnschrift is the DIN face on
     Windows, DIN Alternate and Avenir Next Condensed are on iOS and macOS,
     Roboto Condensed is on Android. No file is downloaded and nothing is
     fetched from anyone, so the "no third-party runtime code, system fonts
     only" line in the audit still holds. */
  --cond:"Bahnschrift","DIN Alternate","Roboto Condensed","Avenir Next Condensed",
         "Segoe UI Semibold",var(--sans);
}

/* ---------- the drawn icons ---------- */
/* One weight for every icon, taking its colour from the text beside it.
   Qualified to svg.ic on purpose: mod/docs.css already owns a plain .ic for
   the document-kind slot (a 30px div), and an unqualified rule fought it. */
svg.ic{
  width:1.06em; height:1.06em; flex:none; vertical-align:-.15em;
  stroke:currentColor; fill:none; stroke-width:1.75;
  stroke-linecap:round; stroke-linejoin:round;
}
/* An icon with words after it needs a gap. It cannot be done with
   :not(:only-child): CSS counts only ELEMENT children, and the label beside an
   icon is a TEXT node, so the icon still matches :only-child and "Full screen"
   and "Light" came out jammed against their marks. Every icon gets the gap;
   the controls that are an icon alone take it back. */
svg.ic{margin-right:.42em;}
button.ico svg.ic,.rolebtn .rn svg.ic,.tile .ti svg.ic,.feature-list .fi svg.ic,
button.x svg.ic,.chip button svg.ic,a.cbtn .ci svg.ic{margin-right:0;}
/* The documents list owns .ic for its kind slot (mod/docs.css: a 30px box at
   22px type) and passes a glyph through el(), so a drawing now sits INSIDE
   that box. .doc .ic is (0,2,0) and beats a bare svg.ic (0,1,1), which
   stretched the drawing to the box. Size it here, at (0,2,1). */
.doc svg.ic{width:22px; height:22px; margin-right:0;}
button svg.ic, a.cbtn svg.ic{opacity:.92;}

/* ---------- type ---------- */
h1,h2,h3,.tile .tn,.hub-label,.topbar h2,.hero-title,.hero-line,
button,.admtab,.tabs button,label,.kv dt{font-family:var(--cond);}
h1{letter-spacing:.005em; font-weight:700;}
h2{letter-spacing:.01em; font-weight:700;}
/* Section headings: a shop label, not a blue banner. */
h3{
  font-size:12px; letter-spacing:.14em; color:var(--muted); font-weight:700;
  margin:20px 0 8px; padding-bottom:5px; border-bottom:1px solid var(--line);
}
/* A form's field label reads as a small stamped caption. NOT a label that
   wraps a control: permission rows, the My KPIs picker and the PM checklist
   are built as <label><input> ... </label>, and uppercasing those turned whole
   sentences into shouting. */
label:not(:has(input)):not(:has(select)):not(:has(textarea)){
  font-size:12px; letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
}
/* Numbers line up in columns the way they do on a parts list. */
.mono,.kv dd,.ano b,.brow .bn,.srow .n,.item .h .n,table.ord td,table.ord th,
.ord .ov,.ord .od,.badge,.pill{font-variant-numeric:tabular-nums;}

/* ---------- controls ---------- */
button{
  border-radius:var(--r-btn); font-size:15px; letter-spacing:.02em; font-weight:600;
  padding:10px 14px;
}
button.primary{border-color:var(--brand); font-weight:700;}
button.small{font-size:13.5px; padding:6px 10px; min-height:32px;}
@media (pointer:coarse){ button.small{min-height:40px;} }
input,textarea,select{border-radius:var(--r-btn);}
input:focus,textarea:focus,select:focus{box-shadow:none; border-color:var(--accent); outline:1px solid var(--accent);}

/* Actions sit at their own width on a wide screen instead of three stretched
   bars across a card; they still stretch on a phone, where thumbs need it. */
@media (min-width:601px){
  .btnrow{gap:6px; flex-wrap:wrap;}
  .btnrow > *{flex:0 1 auto;}
  .btnrow > .spacer{flex:1 1 auto;}
}

/* On a phone the three actions on a job used to be three stacked slabs, with
   "Open machine" breaking onto two lines. Same three buttons, sized like
   controls instead of banners, each on one line. */
@media (max-width:600px){
  .btnrow{gap:6px;}
  .btnrow button{font-size:13.5px; min-height:40px; padding:8px 9px; white-space:nowrap;}
  .kpi-chips button.seg,.kpi-groups button.seg{font-size:12.5px; padding:5px 10px; min-height:34px;}
  .kpi-barbtns button{font-size:13.5px;}
}

/* ---------- surfaces ---------- */
.card,.item,.vaddr,.permlist,#findWrap,.mailbody{border-radius:var(--r-md); box-shadow:none;}
.card{padding:14px;}
.item{padding:11px 12px; margin-bottom:8px;}
#toast{border-radius:var(--r-md); box-shadow:0 2px 0 rgba(3,8,20,.6);}

/* Tags, not bubbles: square, mono, small caps, colour on the edge. */
.pill{
  border-radius:var(--r-pill); font-size:11px; letter-spacing:.06em;
  text-transform:uppercase; padding:3px 7px; background:transparent;
}
.pill.accent{background:transparent;}
/* Two chip treatments on a job card, not five. A boxed chip means severity or
   state (SAFETY, HIGH, EMERGENCY, WAITING TO BE ASSIGNED). What KIND of job it
   is (MACHINE, BUILDING, OTHER, PM, a marked spot) is just a word: no box, no
   dashed edge. The dashed borders came from routing.css and map.css and taught
   the reader nothing, which is how a screen ends up looking auto-generated. */
.pill.cat,.pill.spot,.pill.uncounted{
  border-color:transparent; background:transparent; color:var(--muted);
  padding-left:0; padding-right:10px; border-style:solid;
}
/* ...but the marked spot is a CONTROL, not a classification: one tap opens the
   map centred on the place the reporter marked (queue.js, myrequests.js).
   Flattened in with the tags above it became two grey words that look exactly
   like the inert OTHER beside them. It gets the one cue a person already reads
   as "this goes somewhere" - the accent, and a rule under the words. No box, so
   the plain tags stay plain.
   Listed twice on purpose. Bare, .pill.spot is (0,2,0): enough in dark, where
   it beats routing.css:33 on load order. In LIGHT it would lose to theme.css:45
   html[data-theme="light"] .pill (0,2,1), which is the same arithmetic that put
   the boxes back on the category chips. The second selector is (0,3,1) and takes
   that one on class count, 3 > 2, so both themes get the same treatment. */
.pill.spot,
html[data-theme="light"] .pill.spot{
  color:var(--accent); border-width:1px; border-color:transparent;
  border-bottom:1px solid var(--accent-line); padding-right:3px;
}
/* routing.css:34 paints all four edges accent on hover, which would put the box
   back on the way past. Same (0,3,0) as that rule, later file, so this wins. */
.pill.spot:hover,.pill.spot:focus-visible,
html[data-theme="light"] .pill.spot:hover,
html[data-theme="light"] .pill.spot:focus-visible{
  color:var(--accent); border-color:transparent; border-bottom-color:var(--accent);
}
.chip.spot,.chip.gps.sim{border-style:solid;}
.chip{border-radius:var(--r-md); box-shadow:none;}
.chip button{border-radius:var(--r-btn);}
button.seg,button.vend,a.cbtn{border-radius:var(--r-btn);}
.badge{border-radius:2px; min-width:19px; height:19px; font-family:var(--mono); font-weight:700;}

/* ---------- the top bar ---------- */
.topbar h2{
  font-size:15px; letter-spacing:.12em; text-transform:uppercase; font-weight:700;
}
/* the blue rule under the title: a stamped underline, not a rounded pill */
#modTitle::after{width:22px; height:2px; border-radius:0; margin-top:5px;}
.topbar button{border-radius:var(--r-btn); font-size:13px; letter-spacing:.04em;}

/* ---------- the hub ---------- */
/* A faint diagonal hatch, the way a drawing shades a cut face. 2%: texture,
   never something to look at. */
#screen-hub::before{
  content:''; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.022;
  background:repeating-linear-gradient(45deg, var(--brand-lt) 0 1px, transparent 1px 9px);
}
.hub-ornament{opacity:.03;}
.hub-label{
  color:var(--muted); font-size:11px; letter-spacing:.2em; margin:4px 2px 9px;
  padding-bottom:6px; border-bottom:1px solid var(--line);
}
.hub-grid{gap:8px; grid-template-columns:repeat(auto-fill, minmax(158px, 1fr));}
.tile{
  min-height:0; padding:12px 13px 13px; gap:7px; border-radius:var(--r-md);
  background:var(--chrome);
}
/* no disc: the icon is a drawing on the tile, in the accent, sized like a
   stamped mark in the corner of a drawing */
.tile .ti{
  width:26px; height:26px; border-radius:0; background:transparent; border:0;
  color:var(--accent); overflow:visible;
}
.tile .ti svg.ic{width:26px; height:26px; stroke-width:1.6;}
.tile:hover .ti,.tile:focus-visible .ti{background:transparent; border:0;}
.tile .tn{font-size:15px; letter-spacing:.03em; font-weight:700;}
.tile .td{font-size:11.5px; line-height:1.35; color:var(--muted);}
/* the top rule on hover: a full-width machined edge */
.tile::before{left:0; right:0; height:2px; border-radius:0;}
.tile .badge{top:9px; right:9px;}
.hub-foot{font-size:12px; letter-spacing:.16em;}
/* On a monitor the old 640px column left half the screen empty, which reads as
   a phone app stretched wide. The same tiles, in the same order, filling the
   bench. */
@media (min-width:900px){
  .hub-in{max-width:1040px;}
  .hub-grid{grid-template-columns:repeat(auto-fill, minmax(196px, 1fr)); gap:10px;}
  .tile{padding:14px 15px 15px;}
  .tile .ti,.tile .ti svg.ic{width:28px; height:28px;}
}

/* ---------- landing ---------- */
.landing-glow{display:none;}
.landing-motif{opacity:.045;}
.hero-title{letter-spacing:.1em;}
.landing-band{border-radius:0;}
.feature-list .fi{
  width:28px; height:28px; border-radius:0; background:transparent;
  border:0; color:var(--accent);
}
.feature-list .fi svg.ic{width:24px; height:24px;}

/* ---------- lists and rows: more work per screen ---------- */
.arow,.vrow,.srow,.urow,.contact,.entry{padding-top:9px; padding-bottom:9px;}
.brow{padding:9px 6px;}
.ord{padding:10px 0;}
.tabs button{border-radius:var(--r-sm) var(--r-sm) 0 0; font-family:var(--cond); letter-spacing:.04em;}
button.admtab{border-radius:var(--r-sm) var(--r-sm) 0 0; letter-spacing:.05em;}
.ahead .no{letter-spacing:0;}
.photos img,button.pcell,button.pthumb,button.pthumb img,img.preview{border-radius:var(--r-sm);}
.ptag{border-radius:var(--r-sm); font-variant-numeric:tabular-nums;}

/* Light mode: a plain button was filling with the light-grey panel colour
   while an outlined one beside it stayed white, so "Open machine" read as
   disabled next to "Est. hours". Plain buttons are white; the primary and the
   one warm action keep their fill. */
html[data-theme="light"] button:not(.primary):not(.cta):not(.danger):not(.seg.on):not(.admtab.on){
  background:#fff;
}
/* ...but NOT the buttons sitting on a navy bar. theme.css gives those white
   text on a translucent fill so they read against the navy; the rule above was
   winning and painting them solid white, which left every top-bar button a
   blank white box in light mode (caught in the light-mode capture, 2026-09-17).
   Restore the bar's own treatment at matching specificity.
   The :not() chain on the rule above counts toward specificity (0,6,2), so a
   plain ".topbar button" (0,2,2) loses to it and the bar stayed white. These
   carry the same chain, plus the bar's own class, to win. */
html[data-theme="light"] .topbar button:not(.primary):not(.cta):not(.danger):not(.seg.on):not(.admtab.on),
html[data-theme="light"] .ahead button:not(.primary):not(.cta):not(.danger):not(.seg.on):not(.admtab.on),
html[data-theme="light"] #findWrap .hd button:not(.primary):not(.cta):not(.danger):not(.seg.on):not(.admtab.on){
  background:rgba(255,255,255,.06); color:#fff;
}
html[data-theme="light"] .topbar button:not(.primary):not(.cta):not(.danger):hover:not(:disabled),
html[data-theme="light"] .ahead button:not(.primary):not(.cta):not(.danger):hover:not(:disabled),
html[data-theme="light"] #findWrap .hd button:not(.primary):not(.cta):not(.danger):hover:not(:disabled){
  background:rgba(255,255,255,.14);
}
html[data-theme="light"] .topbar button.ghost{background:transparent;}
html[data-theme="light"] .topbar button.primary{background:var(--brand-lt);}

/* The phone's top bar was four chrome buttons over two rows, about 190px
   before any work showed. Same buttons, sized for a bar. */
@media (max-width:480px){
  .topbar{gap:7px; padding-top:calc(var(--sat) + 8px); padding-bottom:8px;}
  /* 36px, not the 32px this rule shipped with: app.css:187 already had the bar
     at 36 and the skin took 4px off the one control every module screen is left
     through. A narrow window on a mouse gets what it had; a finger gets --tap,
     in the block below. */
  .topbar button{min-height:36px; padding:5px 9px; font-size:12.5px;}
  .topbar .pill{font-size:11px; padding:3px 8px;}
  #screen-hub .topbar{row-gap:6px;}
}
/* On a real touch screen the bar carries the app's OWN target: app.css:59
   declares --tap:44px and nothing was applying it here - no (pointer:coarse)
   rule for .topbar button exists in any sheet, so a phone got 32px.
   ".topbar button" is (0,1,1) in app.css, in the phone block above, and here:
   three rules at the SAME specificity, decided by order alone. This one wins
   only by sitting after them in the last-loaded file - it must stay below the
   max-width block, never above it.
   The two-row layout is unchanged: app.css:210 already wraps the hub bar and
   app.css:217-224 the module bar, so the height lands on rows that exist. The
   bar's own padding gives 2px of it back. */
@media (pointer:coarse){
  .topbar button{min-height:var(--tap); padding-top:6px; padding-bottom:6px;}
  .topbar{padding-top:calc(var(--sat) + 7px); padding-bottom:7px;}
}

/* ---------- KPIs: a shift report, not a dashboard ----------
   The giant figure with a friendly caption under it, in a grid of identical
   soft cards, is the one layout everybody has seen a machine produce. Same
   numbers, same cards, same order; read as a report instead. */
.kpi-card{padding:13px 14px;}
.kpi-hero{
  font-size:30px; font-weight:700; letter-spacing:0; font-family:var(--cond);
  font-variant-numeric:tabular-nums; margin:1px 0 5px;
}
.kpi-tile{border-radius:var(--r-md); padding:10px;}
.kpi-tile .v{font-size:21px; font-family:var(--cond); font-variant-numeric:tabular-nums;}
.kpi-mini .v b{font-size:17px; font-variant-numeric:tabular-nums;}
.kpi-h{font-family:var(--cond); letter-spacing:.1em; text-transform:uppercase; font-size:12.5px;}
.kpi-sub{margin-bottom:9px;}
/* deltas, the "showing" mark and the parts tag: square stamps */
.kpi-delta,.kpi-showing,.kpi-hero .kpi-tag{border-radius:var(--r-pill);}
.kpi-delta{background:transparent;}
/* bars and meters end square, the way a gauge scale does */
.kpi-hbar,.kpi-stack span:last-child{border-radius:0;}
.kpi-meter,.kpi-meter i{border-radius:0;}
.kpi-meter{height:10px;}
.kpi-more .kpi-morehead{border-radius:var(--r-md); padding:10px 13px;}
.kpi-tip{border-radius:var(--r-md); box-shadow:none;}
.kpi-legend i{border-radius:0;}
/* The three states of open work were a lightness ramp and nothing else
   (--viz-o1/o2/o3, kpi.css:17), and kpi.js seg() gives each span a title and no
   text - so at 14px on a phone, or in greyscale, the bar reads as one bar. The
   house rule is that nothing signals by hue alone, and kpi.css:180
   (.kpi-hbar.hatched) already uses the technique. Each state now carries its own
   WEAVE as well as its own step: solid, one diagonal, the other diagonal. The
   legend swatch carries the same weave, so the key still matches the bar.
   Set as background-IMAGE over kpi.css:205's background-COLOUR shorthand, so the
   step stays exactly the colour the ramp chose. .kpi-stack .kpi-o2 is (0,2,0)
   and .kpi-legend i.kpi-o2 is (0,2,1); both beat the bare .kpi-o2 (0,1,0).
   White at 55% over any step of the ramp, in either theme. */
.kpi-stack .kpi-o2,.kpi-legend i.kpi-o2{
  background-image:repeating-linear-gradient(135deg, rgba(255,255,255,.55) 0 2px, transparent 2px 5px);
}
.kpi-stack .kpi-o3,.kpi-legend i.kpi-o3{
  background-image:repeating-linear-gradient(45deg, rgba(255,255,255,.55) 0 2px, transparent 2px 5px);
}
/* The caveat block (kpi.js captionMore) is honest and must not go missing, but
   on a phone it runs five wrapped lines between the range chips and the first
   figure. Its size and margin are set INLINE at kpi.js:776, which no selector
   can reach; leading is not, so the lines tighten here. .kpi-caption (0,1,0)
   ties app.css:99 .sub and wins on order. The real fix is a disclosure control
   and belongs in kpi.js. */
@media (max-width:600px){
  .kpi-caption{line-height:1.35;}
  .kpi-bar{margin-bottom:8px;}
}
button.small.kpi-everyone,.kpi-segs button.seg{border-radius:var(--r-btn);}

/* ---------- light mode keeps the same discipline ---------- */
html[data-theme="light"] .tile .ti,
html[data-theme="light"] .feature-list .fi{border:0; background:transparent; color:var(--accent);}
html[data-theme="light"] .pill{background:transparent;}
/* The classification tags stay PLAIN in light too. theme.css:45
   html[data-theme="light"] .pill is (0,2,1) and beats this file's
   .pill.cat,.pill.spot,.pill.uncounted (0,2,0) whatever the order, so light was
   painting a 1.5px #26313F box back onto every MACHINE / BUILDING / OTHER /
   NOT COUNTED YET tag: "two chip treatments, not five" held in dark only.
   Repeated here at (0,3,1), which takes it on class count, 3 > 2. Width is
   matched to dark's 1px so the two themes measure the same; the colour is
   transparent in both. .pill.spot is deliberately NOT in this list - it is a
   control, and keeps the accent rule it is given above. */
html[data-theme="light"] .pill.cat,
html[data-theme="light"] .pill.uncounted{
  border-width:1px; border-color:transparent; color:var(--muted);
}
html[data-theme="light"] #screen-hub::before{opacity:.04;}
/* theme.css lifts the mark to 26% on white so it does not vanish; against the
   hatch and the square tiles that reads as wallpaper. Texture, not a picture.
   (Same specificity as theme.css, and this file loads after it.) */
html[data-theme="light"] .hub-ornament{opacity:.05;}
html[data-theme="light"] .landing-motif{opacity:.06;}
html[data-theme="light"] .hub-label{color:var(--muted);}
