/* =============================================================================
   SafeSite AI — design system

   Read outdoors, in gloves, at arm's length, often one-handed. Every choice
   below follows from that:

   TYPE. One modular scale, no ad-hoc sizes. Body text bottoms out at 16px and
   secondary text at 14px, because 13px greys out in daylight. Small text gets
   weight rather than size (600-800), which survives glare where a light weight
   washes out. Numerals are tabular everywhere so counts and timers do not
   jitter as they change.

   FONT. The system stack — SF Pro on the iPhones this runs on. It has real
   optical sizing, ships with the device, and needs no network, which a field
   tool cannot assume. Citations use the system monospace so a regulation
   number reads as a code, not prose.

   COLOUR. Near-black ground, hi-vis accent borrowed from the PPE the user is
   already wearing. Severity colours are the only other saturated colours in
   the product, so red always means the same thing. Text on a severity fill is
   white, except on amber, which takes ink, like the black legend on a yellow
   CAUTION sign. White on amber is 2.2:1 and cannot be read in sun.

   SAFETY TEXT. Limitations, verification reasons, confidence and the way into
   the fix are set at body size in dark ink. They carry the product's
   invariants, so they are never the smallest or greyest text on the card.

   SPACING. A 4px grid via --s1..--s8. Touch targets are never below 44px.
   ============================================================================= */

:root{
  /* Ink and surface */
  --ink-950:#0B0F14; --ink-900:#141A21; --ink-800:#1E2731; --ink-700:#2B3440;
  --ink-500:#5A6673; --ink-400:#7C8894; --ink-200:#C3CCD4; --ink-100:#DFE5EA;
  --ink-50:#F2F5F7;  --white:#FFFFFF;

  /* Accent + severity — the only saturated colours in the product */
  --hivis:#D7F205;
  --crit:#C81E1E; --crit-bg:#FDECEC; --crit-tx:#A31515;
  --warn:#F59E0B; --warn-bg:#FFF4DE; --warn-tx:#8A4B00;
  --low:#1D4ED8;  --low-bg:#EAF1FE;  --low-tx:#1D4ED8;
  --ok:#046C4E;   --ok-bg:#E3F5EC;   --ok-tx:#046C4E;
  /* Text on a severity FILL: 5.7:1 on red, 9.0:1 ink on amber, 6.7:1 on blue */
  --crit-on:#FFFFFF; --warn-on:#0B0F14; --low-on:#FFFFFF;

  /* Type scale */
  --f-display:31px; --lh-display:36px;
  --f-title:23px;   --lh-title:29px;
  --f-head:19px;    --lh-head:25px;
  --f-body:16px;    --lh-body:23px;
  --f-sub:14.5px;   --lh-sub:21px;
  --f-meta:13.5px;  --lh-meta:19px;
  --f-label:11.5px; --lh-label:14px;

  /* Spacing (4px grid) */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s7:32px; --s8:44px;

  /* Radii + shape */
  --r-sm:8px; --r-md:12px; --r-lg:18px; --r-pill:999px;
  --tap:48px;                       /* minimum comfortable target, gloved */
  /* Screen side gutter. In landscape, viewport-fit=cover puts the notch over
     one edge; the gutter grows to clear it. Both insets are 0 in portrait. */
  --edge:max(20px, env(safe-area-inset-left), env(safe-area-inset-right));
  --safe-b:env(safe-area-inset-bottom);
}

*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* A class rule with `display` outranks the UA stylesheet's [hidden], so
   `el.hidden = true` silently fails on anything styled display:flex/grid.
   This keeps the attribute authoritative wherever it is used. */
[hidden]{display:none!important}
html,body{height:100%}
html{background:var(--ink-950)}
body{
  font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Inter,system-ui,sans-serif;
  font-size:var(--f-body); line-height:var(--lh-body);
  background:var(--white); color:var(--ink-950);
  padding-top:env(safe-area-inset-top);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1,"cv08" 1;
  text-rendering:optimizeLegibility;
}
.mono{font-family:ui-monospace,"SF Mono",SFMono-Regular,Menlo,monospace;font-weight:700;letter-spacing:-.01em}

/* Headings: tight tracking at display sizes, none below */
h1{font-size:var(--f-display);line-height:var(--lh-display);font-weight:800;letter-spacing:-.022em}
h2{font-size:var(--f-title);line-height:var(--lh-title);font-weight:800;letter-spacing:-.015em}
h3{font-size:var(--f-head);line-height:var(--lh-head);font-weight:700;letter-spacing:-.01em}

.label{font-size:var(--f-label);line-height:var(--lh-label);font-weight:800;letter-spacing:.1em;
       text-transform:uppercase;color:var(--ink-500)}
.sub{font-size:var(--f-sub);line-height:var(--lh-sub)}
.meta{font-size:var(--f-meta);line-height:var(--lh-meta);color:var(--ink-500)}

/* Screens */
.screen{display:none;min-height:100vh;min-height:100dvh;flex-direction:column}
.screen.active{display:flex;animation:screenin .2s ease}
@keyframes screenin{from{opacity:0}}
.pad{padding:0 var(--edge) var(--s5)}
.top{padding:var(--s5) var(--edge) var(--s3)}
.bottom{padding:var(--s4) var(--edge) calc(var(--s5) + var(--safe-b));margin-top:auto;
        display:flex;flex-direction:column;gap:var(--s3)}

/* -----------------------------------------------------------------------------
   Buttons — one shape language. Height >= 48px everywhere.
   -------------------------------------------------------------------------- */
.btn{display:flex;align-items:center;justify-content:center;gap:var(--s2);
     min-height:60px;padding:0 var(--s5);border-radius:var(--r-md);
     font-family:inherit;font-size:17px;font-weight:650;letter-spacing:-.01em;
     border:none;width:100%;cursor:pointer;transition:transform .12s ease,opacity .12s ease}
.btn:active{transform:scale(.985)}
.btn:disabled{background:var(--ink-100)!important;color:var(--ink-400)!important;
              border-color:transparent!important;cursor:default;transform:none}
.btn-primary{background:var(--ink-950);color:var(--white)}
.btn-secondary{background:var(--white);color:var(--ink-950);border:1.5px solid var(--ink-200)}
.btn-live{background:var(--hivis);color:var(--ink-950);font-weight:750}
.btn-ghost{background:var(--white);color:var(--ink-950);border:1.5px solid var(--ink-950)}
.btn-outline{background:none;color:var(--white);border:1.5px solid rgba(255,255,255,.4);min-height:52px}
#s-history .btn-outline,#s-insights .btn-outline,#s-account .btn-outline{color:var(--ink-950);border-color:var(--ink-200)}
.frow{display:flex;gap:var(--s3)}
.frow .btn{flex:1}
.backlink{background:none;border:none;font-family:inherit;font-size:var(--f-sub);font-weight:700;
          color:var(--hivis);padding:var(--s2) 0;cursor:pointer;display:inline-flex;align-items:center;
          gap:var(--s1);min-height:var(--s8);position:relative}
.backlink::after{content:"";position:absolute;inset:-6px -12px}
/* Two heads use this: the brief's is dark ink, the report's is white. Colour
   for the surface, not for the class. */
.backlink.dark{color:var(--ink-500)}
#s-brief .backlink.dark{color:var(--ink-200)}
.hint{font-size:var(--f-meta);line-height:var(--lh-meta);color:var(--ink-200);text-align:center}
/* Pinch-zoom is allowed (index.html) so a worker can zoom into an evidence
   photo. Controls opt out of double-tap zoom only, so a quick second tap on a
   marker toggles it instead of zooming the page. Pinch still works on them. */
button,.mark,.card{touch-action:manipulation}

/* Focus: visible for keyboard users, invisible to a finger */
/* Hi-vis reads on the dark screens and vanishes on the light ones (1.27:1 on
   white), so the ring follows the surface too. */
:focus-visible{outline:3px solid var(--ink-950);outline-offset:2px;border-radius:var(--r-sm)}
#s-auth :focus-visible,#s-home :focus-visible,#s-capture :focus-visible,
#s-analyzing :focus-visible,.tabbar :focus-visible{outline-color:var(--hivis)}

/* -----------------------------------------------------------------------------
   Tab bar
   -------------------------------------------------------------------------- */
.tabbar{position:fixed;left:0;right:0;bottom:0;z-index:8;display:grid;grid-template-columns:repeat(4,1fr);
        background:rgba(11,15,20,.94);backdrop-filter:saturate(160%) blur(12px);
        border-top:1px solid rgba(255,255,255,.13);padding-bottom:var(--safe-b);
        padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right)}
.tabbar button{background:none;border:none;color:var(--ink-400);font-family:inherit;
               font-size:var(--f-label);font-weight:750;letter-spacing:.03em;
               padding:var(--s2) var(--s1) var(--s3);min-height:56px;
               display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;cursor:pointer}
.tabbar button span{font-size:19px;line-height:1}
.tabbar button.active{color:var(--hivis)}
body.tabbed .screen.active{padding-bottom:78px}

/* -----------------------------------------------------------------------------
   Auth
   -------------------------------------------------------------------------- */
#s-auth{background:var(--ink-950);color:var(--white);overflow-y:auto}
.auth-wrap{margin:auto;width:100%;max-width:470px;padding:var(--s7) 22px calc(var(--s6) + var(--safe-b))}
.brand{display:flex;gap:var(--s3);align-items:flex-start}
.brand .logo{width:40px;height:40px;border-radius:10px;background:var(--hivis);flex:none;
             box-shadow:inset 0 0 0 7px var(--ink-950),0 0 0 2px var(--hivis)}
#s-auth h1{color:var(--white);font-size:27px;line-height:33px;margin-top:var(--s1)}
.auth-lede{color:var(--ink-200);font-size:var(--f-body);line-height:var(--lh-body);margin:var(--s5) 0 var(--s6)}
.tabs{display:flex;gap:var(--s1);background:rgba(255,255,255,.07);padding:5px;border-radius:var(--r-md);margin-bottom:var(--s5)}
.tab{flex:1;background:none;border:none;color:var(--ink-200);font-family:inherit;
     font-size:var(--f-sub);font-weight:700;padding:var(--s3) var(--s2);min-height:var(--s8);
     border-radius:var(--r-sm);cursor:pointer;transition:background .15s}
.tab.active{background:var(--white);color:var(--ink-950)}
.fields{display:flex;flex-direction:column;gap:var(--s3);margin-bottom:var(--s3)}
.fld{display:flex;flex-direction:column;gap:var(--s1)}
.fld span{font-size:var(--f-label);font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-200)}
.fld input,.fld select{min-height:56px;border-radius:10px;border:1.5px solid rgba(255,255,255,.24);
                       background:rgba(255,255,255,.06);color:var(--white);font-family:inherit;
                       font-size:17px;padding:0 var(--s4);width:100%;appearance:none}
.fld select{background-image:linear-gradient(45deg,transparent 50%,var(--ink-200) 50%),
                             linear-gradient(135deg,var(--ink-200) 50%,transparent 50%);
            background-position:calc(100% - 21px) 50%,calc(100% - 15px) 50%;
            background-size:6px 6px,6px 6px;background-repeat:no-repeat}
.fld input::placeholder{color:var(--ink-500)}
.fld input:focus,.fld select:focus{outline:none;border-color:var(--hivis);background:rgba(255,255,255,.09)}
.formerr{background:rgba(200,30,30,.18);border:1px solid var(--crit);color:#FFD2D2;border-radius:10px;
         padding:var(--s3) var(--s4);font-size:var(--f-sub);line-height:var(--lh-sub);margin-bottom:var(--s3)}

/* -----------------------------------------------------------------------------
   Home
   -------------------------------------------------------------------------- */
#s-home{background:var(--ink-950);color:var(--white);overflow-y:auto}
#s-home h1{color:var(--white)}
#s-home .sub{color:var(--ink-200);margin-top:var(--s1)}
.sitelist{display:flex;flex-direction:column;gap:var(--s2);margin-bottom:var(--s3)}
.siterow{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);width:100%;
         background:rgba(255,255,255,.06);border:1.5px solid transparent;border-radius:var(--r-md);
         padding:var(--s4);min-height:68px;color:var(--white);font-family:inherit;text-align:left;
         cursor:pointer;transition:background .15s,border-color .15s}
.siterow:active{background:rgba(255,255,255,.11)}
.siterow.sel{border-color:var(--hivis);background:rgba(215,242,5,.11)}
.siterow b{font-size:17px;font-weight:650;display:block;letter-spacing:-.01em}
.siterow small{color:var(--ink-200);font-size:var(--f-meta);display:block;margin-top:2px}
.siterow .chev{color:var(--hivis);font-weight:800;font-size:19px;flex:none}
.recent{display:flex;align-items:center;gap:var(--s3);width:100%;background:none;border:none;
        border-top:1px solid rgba(255,255,255,.11);padding:var(--s3) 0;min-height:60px;
        color:var(--white);font-family:inherit;text-align:left;cursor:pointer}
.recent .rmeta{flex:1;min-width:0}
.recent b{font-size:var(--f-body);font-weight:650;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.recent small{color:var(--ink-200);font-size:var(--f-meta)}
.pips{display:flex;gap:var(--s1);flex:none}
.pip{font-size:12px;font-weight:800;min-width:24px;text-align:center;padding:3px 7px;
     border-radius:var(--r-pill);color:#fff}

/* -----------------------------------------------------------------------------
   Capture
   -------------------------------------------------------------------------- */
#s-capture{background:var(--ink-950);color:var(--white)}
#s-capture h1{color:var(--white)}
#s-capture .sub{color:var(--ink-200);margin-top:var(--s1)}
.thumbs{flex:1;display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);
        padding:var(--s4) var(--edge);align-content:start}
.thumb{position:relative;aspect-ratio:3/4;border-radius:10px;overflow:hidden;background:var(--ink-800)}
.thumb img{width:100%;height:100%;object-fit:cover}
.thumb .x{position:absolute;top:6px;right:6px;width:30px;height:30px;border-radius:50%;
          background:rgba(0,0,0,.7);color:#fff;border:none;font-size:15px;line-height:30px;cursor:pointer}
.thumb .x::after{content:"";position:absolute;inset:-12px}
.thumb-add{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s1);
           aspect-ratio:3/4;border:2px dashed rgba(215,242,5,.5);border-radius:10px;background:none;
           color:var(--hivis);cursor:pointer;font-family:inherit}
.thumb-add:active{background:rgba(215,242,5,.08)}
.thumb-add .big{font-size:32px;line-height:1;font-weight:300}
.thumb-add .lab{font-size:var(--f-label);font-weight:800;letter-spacing:.08em}
.btn-voice{display:flex;align-items:center;justify-content:center;gap:var(--s2);min-height:52px;
           border-radius:var(--r-md);background:none;border:1.5px solid rgba(255,255,255,.35);
           color:var(--white);font-family:inherit;font-size:var(--f-sub);font-weight:650;cursor:pointer}
.btn-voice.rec{border-color:var(--hivis);color:var(--hivis);animation:vpulse 1.2s ease infinite}
@keyframes vpulse{50%{opacity:.55}}
.notebox{display:flex;gap:var(--s3);align-items:flex-start;background:rgba(255,255,255,.08);
         border:1px solid rgba(255,255,255,.18);border-radius:var(--r-md);padding:var(--s3) var(--s4);
         color:var(--ink-200);font-size:var(--f-sub);line-height:var(--lh-sub)}
/* 44px for a glove. The negative margins sink it into the box's padding, so
   the note does not grow around it. */
.notebox .nx{margin:-10px -12px -10px auto;min-width:44px;min-height:44px;display:flex;
             align-items:center;justify-content:center;background:none;border:none;
             color:var(--white);font-size:17px;cursor:pointer;flex:none}

/* -----------------------------------------------------------------------------
   Analyzing
   -------------------------------------------------------------------------- */
#s-analyzing{background:var(--ink-950);color:var(--white);padding:0 var(--edge)}
#s-analyzing .wrap{margin:auto 0;padding:var(--s7) 0}
.an-head{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s3)}
.an-head h1{color:var(--white);font-size:28px;line-height:34px}
#timer{color:var(--hivis);font-size:18px}
#s-analyzing .sub{color:var(--ink-200);margin:var(--s3) 0 var(--s6)}
.check{display:flex;align-items:center;gap:var(--s4);padding:var(--s3) 0;
       font-size:17px;font-weight:600;line-height:23px}
.check .dot{width:20px;height:20px;border-radius:50%;border:2px solid rgba(255,255,255,.25);flex:none}
.check.active .dot{border:3px solid var(--hivis);animation:vpulse 1.1s ease infinite}
.check.done .dot{background:var(--hivis);border-color:var(--hivis)}
.check.fail .dot{background:none;border:3px solid var(--crit)}
.check.fail{color:#F0A0A0}
.check.pending{color:var(--ink-200);opacity:.8}

/* -----------------------------------------------------------------------------
   Report
   -------------------------------------------------------------------------- */
#s-report{background:var(--white)}
#s-report .head{padding:var(--s5) var(--edge) var(--s4)}
#s-report .meta{margin-top:var(--s1)}
.counts{display:flex;justify-content:space-between;gap:var(--s3);background:var(--ink-50);
        padding:var(--s4) var(--edge)}
.count b{font-size:30px;font-weight:800;letter-spacing:-.025em;display:block;line-height:1.1}
.count .cl{display:flex;align-items:center;gap:var(--s1);font-size:var(--f-label);
           font-weight:800;letter-spacing:.09em;color:var(--ink-500);margin-top:3px}
.count .sq{width:9px;height:9px;border-radius:2px}
.flist{padding:var(--s4) var(--edge) calc(90px + var(--safe-b));display:flex;flex-direction:column;gap:var(--s4)}
.photo-wrap{position:relative;border-radius:var(--r-md);overflow:hidden;margin:0 var(--edge) var(--s1)}
.photo-wrap img{width:100%;display:block}
.bbox{position:absolute;border:3px solid;border-radius:3px;display:none;pointer-events:none}
.bbox.show{display:block}
.bbox .tag{position:absolute;bottom:calc(100% - 4px);left:var(--tag-l,-3px);right:var(--tag-r,auto);
           color:#fff;font-size:var(--f-label);font-weight:800;
           letter-spacing:.06em;padding:3px 7px;border-radius:3px;width:max-content;
           max-width:calc(50vw - var(--edge));overflow:hidden;text-overflow:ellipsis;z-index:3}
.bbox.edge .tag{top:-3px;bottom:auto;border-radius:var(--tag-corner,3px 0 3px 0)}
/* The tag stays inside the photo. It is the only on-photo text naming the
   severity, and hung from the left corner of a box near the right edge it was
   cut to "2 C". A box whose left edge is past the middle hangs its tag from
   its right corner instead, so either corner has at least half the photo
   beside it, and max-width is that half: a longer tag ("1 CRITICAL ·
   DISMISSED") wraps upward, off the box, instead of running out of the photo.
   The half is read off the box's inline style, as the amber rule below reads
   its colour: app.js writes left as a % and the CSSOM keeps it as "left: N%",
   so a two-digit N from 50 up is the right half ("left: 5%", "left: 9.9%" are
   not). The tag sits above the markers: on a box smaller than the disc, the
   disc covered the tag's end ("2 CRITICA"), and the tag carries its number. */
.bbox:is([style*="left: 5"],[style*="left: 6"],[style*="left: 7"],[style*="left: 8"],[style*="left: 9"]):not(
      [style*="left: 5%"],[style*="left: 6%"],[style*="left: 7%"],[style*="left: 8%"],[style*="left: 9%"],
      [style*="left: 5."],[style*="left: 6."],[style*="left: 7."],[style*="left: 8."],[style*="left: 9."]){
  --tag-l:auto;--tag-r:-3px;--tag-corner:0 3px 0 3px}
.mark{position:absolute;width:29px;height:29px;border-radius:50%;transform:translate(-50%,-50%);z-index:2;
      display:flex;align-items:center;justify-content:center;color:#fff;font-size:13px;font-weight:800;
      border:2px solid #fff;box-shadow:0 1px 7px rgba(0,0,0,.6);cursor:pointer;
      user-select:none;-webkit-user-select:none;transition:opacity .2s,transform .12s}
.mark:active{transform:translate(-50%,-50%) scale(.9)}
.mark.dim{opacity:.26}
/* The disc stays 29px so it hides little of the photo. The hit area is 44px,
   centred, for a gloved fingertip. It is round, so it overlaps a close
   neighbour's area as little as possible. */
.mark::after{content:"";position:absolute;left:50%;top:50%;width:44px;height:44px;
             transform:translate(-50%,-50%);border-radius:50%}
/* Amber fills take ink, not white (see COLOUR). app.js paints every severity
   fill inline from SEV.hex, so the amber is matched on the style attribute,
   both as written (#F59E0B, via innerHTML) and as the CSSOM re-serialises it
   (rgb(245, 158, 11), via el.style.background). An inline colour set by
   app.js still wins. */
.mark[style*="F59E0B" i],.mark[style*="245, 158, 11"],
.pip[style*="F59E0B" i],.pip[style*="245, 158, 11"],
.bbox .tag[style*="F59E0B" i],.bbox .tag[style*="245, 158, 11"],
.bitem .bnum[style*="F59E0B" i],.bitem .bnum[style*="245, 158, 11"]{color:var(--warn-on)}
.leader{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1}
.ptag{position:absolute;top:var(--s2);left:var(--s2);background:rgba(11,15,20,.8);color:#fff;
      font-size:var(--f-label);font-weight:800;letter-spacing:.08em;padding:4px 9px;border-radius:3px}
/* Docked right on two lines ("See #27" / "details ↓"), and the chip row
   keeps out of its lane (.mchips). Centred on one line, it sat on the middle
   chips right under the photo, where they are when a marker is tapped, and a
   gloved tap aimed at a chip hit the pill and scrolled away. 122px holds
   "See #128" but not "See #1 details", so the break falls in the same place. */
.gochip{position:fixed;right:var(--edge);bottom:120px;z-index:6;display:none;max-width:122px;
        background:rgba(11,15,20,.94);color:#fff;border:1px solid rgba(255,255,255,.3);
        border-radius:var(--r-pill);padding:10px 16px;min-height:var(--s8);font-family:inherit;
        font-size:var(--f-sub);line-height:var(--lh-sub);font-weight:800;letter-spacing:.04em;
        text-align:center;cursor:pointer;box-shadow:0 3px 16px rgba(0,0,0,.4)}
.gochip.show{display:block}
.gochip:active{transform:scale(.96)}

/* Hazard-type groups */
.grp{border:1px solid var(--ink-100);border-radius:var(--r-md);overflow:hidden}
.ghead{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);width:100%;
       background:var(--ink-50);border:none;font-family:inherit;cursor:pointer;
       padding:var(--s4);min-height:60px;text-align:left}
.gname{font-size:17px;font-weight:800;letter-spacing:-.01em;color:var(--ink-950)}
.gmeta{display:flex;align-items:center;gap:var(--s3)}
.gc{display:inline-flex;align-items:center;gap:5px;font-size:var(--f-sub);font-weight:800;color:var(--ink-700)}
.gc .sq{width:10px;height:10px;border-radius:2px}
.gchev{font-size:13px;color:var(--ink-500);transition:transform .2s}
.grp.collapsed .gchev{transform:rotate(-90deg)}
.gbody{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s3)}
.grp.collapsed .gbody{display:none}

/* Finding cards */
.card{border:1px solid var(--ink-100);border-radius:var(--r-md);overflow:hidden;display:flex;
      cursor:pointer;transition:box-shadow .3s}
.card.flash{box-shadow:0 0 0 3px var(--hivis)}
.card .bar{width:6px;flex:none}
.card .in{padding:var(--s4);display:flex;flex-direction:column;gap:var(--s2);flex:1;min-width:0}
.rowx{display:flex;justify-content:space-between;align-items:center;gap:var(--s2)}
.badge{display:inline-flex;align-items:center;gap:var(--s1);font-size:var(--f-label);font-weight:800;
       letter-spacing:.08em;padding:5px 9px;border-radius:5px}
.badge .sq{width:9px;height:9px;border-radius:2px}
.rank{font-size:var(--f-meta);font-weight:800;color:var(--ink-500)}
button.rank{border:1px solid var(--ink-100);background:none;padding:8px 11px;border-radius:5px;
            cursor:pointer;font-family:inherit;position:relative;min-height:var(--s8)}
button.rank::after{content:"";position:absolute;inset:-10px}
button.rank:active{background:var(--ink-50)}
.card h3{font-size:var(--f-head);line-height:var(--lh-head)}
.card .obs{font-size:var(--f-sub);line-height:var(--lh-sub);color:var(--ink-700)}
.cite-row{display:flex;justify-content:space-between;align-items:center;gap:var(--s2);
          border-top:1px solid var(--ink-100);padding-top:var(--s2);flex-wrap:wrap}
.cite{font-size:var(--f-meta)}
/* Safety text (see SAFETY TEXT): body size, dark ink, weight. "Confidence:
   low" sat in 13.5px grey under a saturated CRITICAL badge, so glare left the
   badge and lost the doubt. */
.conf{font-size:var(--f-body);line-height:var(--lh-body);font-weight:650;color:var(--ink-700)}
.verify{background:var(--warn-bg);color:var(--warn-tx);border:1px solid var(--warn);border-radius:var(--r-sm);
        padding:var(--s3);font-size:var(--f-body);line-height:var(--lh-body)}
.mit{font-size:var(--f-sub);line-height:var(--lh-sub);color:var(--ink-700);display:none}
.card.open .mit{display:block}
/* The only cue that a fix exists, so it reads as a control, not a footnote. */
.fixhint{font-size:var(--f-body);line-height:var(--lh-body);font-weight:800;letter-spacing:.04em;color:var(--ink-950)}
.fixhint::after{content:"SHOW FIX ▾"}
.card.open .fixhint::after{content:"HIDE FIX ▴"}
/* "What the photos could not show" carries invariant 4 ("cannot establish
   working height"). app.js writes those lines with inline 13px/12px grey, and
   only !important reaches an inline style. If the lines move to a class, this
   rule matches nothing and can go. */
#repBody div[style*="font-size:13px"],#repBody div[style*="font-size:12px"]{
  font-size:var(--f-body)!important;line-height:var(--lh-body)!important;color:var(--ink-700)!important}
#repBody div[style*="font-size:12px"]{font-weight:700}

.footer{position:fixed;left:0;right:0;bottom:0;background:var(--white);border-top:1px solid var(--ink-100);
        padding:var(--s3) var(--edge) calc(var(--s4) + var(--safe-b));display:flex;flex-direction:column;
        gap:var(--s2);z-index:5}
/* Invariant 3's standing notice: never below the meta size, never light grey. */
.disc{font-size:var(--f-meta);line-height:var(--lh-meta);font-weight:600;color:var(--ink-700)}
.footer .btn{min-height:52px;font-size:var(--f-body)}
.errbox{margin:0 var(--edge);background:var(--crit-bg);color:var(--crit-tx);border:1.5px solid var(--crit);
        border-radius:10px;padding:var(--s3) var(--s4);font-size:var(--f-sub);line-height:var(--lh-sub)}
.okbox{margin:var(--s4) var(--edge);background:var(--ok-bg);color:var(--ok-tx);border-radius:10px;
       padding:var(--s4);font-size:var(--f-body);line-height:var(--lh-body)}

/* Competent-person sign-off */
.decide{display:flex;gap:var(--s2);margin-top:var(--s2)}
.decide button{flex:1;min-height:var(--s8);border-radius:var(--r-sm);border:1.5px solid var(--ink-200);
               background:var(--white);font-family:inherit;font-size:var(--f-meta);font-weight:800;
               letter-spacing:.04em;cursor:pointer}
.decide button:active{background:var(--ink-50)}
.decide button.on[data-d="confirmed"]{background:var(--ok-bg);border-color:var(--ok-tx);color:var(--ok-tx)}
.decide button.on[data-d="dismissed"]{background:var(--ink-50);border-color:var(--ink-500);color:var(--ink-500)}
/* Label leading: at the body's 23px a wrapped sign-off state read as two labels */
.decided{font-size:var(--f-label);line-height:var(--lh-label);font-weight:800;letter-spacing:.06em;
         color:var(--ok-tx);margin-top:var(--s2)}
.decided.dismissed{color:var(--ink-500)}

/* -----------------------------------------------------------------------------
   History / Insights / Account
   -------------------------------------------------------------------------- */
#s-history,#s-insights,#s-account{background:var(--white);overflow-y:auto}
#s-history .top,#s-insights .top,#s-account .top{padding:var(--s5) var(--edge) var(--s4);background:var(--ink-950)}
#s-history h1,#s-insights h1,#s-account h1{color:var(--white)}
#s-history .sub,#s-insights .sub,#s-account .sub{color:var(--ink-200);margin-top:var(--s1)}
.hrow{display:flex;align-items:center;gap:var(--s3);width:100%;background:none;border:none;
      border-bottom:1px solid var(--ink-100);padding:var(--s4) 0;min-height:64px;
      font-family:inherit;text-align:left;cursor:pointer}
.hrow:active{background:var(--ink-50)}
.hrow .hmeta{flex:1;min-width:0}
.hrow b{font-size:var(--f-body);font-weight:700;display:block;letter-spacing:-.01em}
/* Block, so the Incomplete / awaiting flags always start on a line of their own
   rather than running on from the meta text on a wide screen. */
.hrow small{display:block;color:var(--ink-500);font-size:var(--f-meta)}
.empty{color:var(--ink-500);font-size:var(--f-body);line-height:var(--lh-body);padding:var(--s6) 0}
.abar{display:flex;align-items:center;gap:var(--s3);padding:var(--s2) 0}
.abar .bl{font-size:var(--f-sub);font-weight:650;width:38%;flex:none}
.abar .btrack{display:block;flex:1;height:10px;background:var(--ink-50);border-radius:5px;overflow:hidden}
.abar .bfill{display:block;height:100%;border-radius:5px;min-width:3px}
.abar .bn{font-size:var(--f-meta);font-weight:800;color:var(--ink-500);width:28px;text-align:right}
.statrow{display:flex;gap:var(--s6);background:var(--ink-50);border-radius:var(--r-md);
         padding:var(--s4) var(--s5);margin:var(--s1) 0 var(--s5)}
.statrow b{display:block;font-size:27px;font-weight:800;letter-spacing:-.025em;line-height:1.1}
.statrow span{font-size:var(--f-label);font-weight:800;letter-spacing:.08em;color:var(--ink-500)}
.setrow{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
        border-bottom:1px solid var(--ink-100);padding:var(--s4) 0;min-height:60px}
.setrow .sk{font-size:var(--f-sub);color:var(--ink-500)}
.setrow .sv{font-size:var(--f-body);font-weight:700}
.setrow input{width:96px;min-height:var(--s8);border:1.5px solid var(--ink-200);border-radius:var(--r-sm);
              padding:0 var(--s3);font-family:inherit;font-size:var(--f-body);font-weight:700;text-align:right}

/* -----------------------------------------------------------------------------
   Job briefing
   -------------------------------------------------------------------------- */
#s-brief{background:var(--white);overflow-y:auto}
#s-brief .head{padding:var(--s5) var(--edge) var(--s4);background:var(--ink-950)}
#s-brief h1{color:var(--white)}
#s-brief .meta{color:var(--ink-200);margin-top:var(--s1)}
.bsec{padding:0 var(--edge) var(--s1)}
.bsec h2{font-size:var(--f-label);line-height:var(--lh-label);font-weight:800;letter-spacing:.1em;
         text-transform:uppercase;color:var(--ink-500);margin:var(--s6) 0 var(--s3)}
.bitem{display:flex;gap:var(--s3);padding:var(--s3) 0;border-bottom:1px solid var(--ink-100)}
.bitem .bnum{width:28px;height:28px;border-radius:50%;flex:none;color:#fff;font-size:13px;font-weight:800;
             display:flex;align-items:center;justify-content:center}
.bitem .btxt b{font-size:17px;font-weight:700;display:block;line-height:23px;letter-spacing:-.01em}
.bitem .btxt p{font-size:var(--f-sub);line-height:var(--lh-sub);color:var(--ink-700);margin-top:var(--s1)}
.bitem .btxt .bfix{font-size:var(--f-sub);line-height:var(--lh-sub);margin-top:var(--s2)}
.bnone{color:var(--ok-tx);background:var(--ok-bg);border-radius:10px;padding:var(--s4);
       font-size:var(--f-body);line-height:var(--lh-body);margin:0 var(--edge)}

/* -----------------------------------------------------------------------------
   Bottom sheet — every form and confirmation. Replaces browser prompt(),
   which cannot be styled, cannot be read in sunlight, and chains badly.
   -------------------------------------------------------------------------- */
.scrim{position:fixed;inset:0;background:rgba(11,15,20,.55);z-index:20;animation:fade .18s ease}
@keyframes fade{from{opacity:0}}
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:21;background:var(--white);
       border-radius:var(--r-lg) var(--r-lg) 0 0;padding:var(--s3) var(--edge) calc(var(--s5) + var(--safe-b));
       max-height:88vh;overflow-y:auto;animation:rise .22s cubic-bezier(.2,.8,.3,1);
       box-shadow:0 -6px 30px rgba(0,0,0,.28)}
@keyframes rise{from{transform:translateY(100%)}}
.grabber{width:38px;height:4px;border-radius:2px;background:var(--ink-100);margin:0 auto var(--s4)}
.sheet h2{font-size:var(--f-title);line-height:var(--lh-title);margin-bottom:var(--s2)}
.sheetsub{font-size:var(--f-sub);line-height:var(--lh-sub);color:var(--ink-500);margin-bottom:var(--s4)}
.sheet .fld span{color:var(--ink-500)}
.sheet .fld input,.sheet .fld select{background:var(--white);border-color:var(--ink-200);color:var(--ink-950)}
.sheet .fld input::placeholder{color:var(--ink-500)}
.sheet .fld input:focus,.sheet .fld select:focus{border-color:var(--ink-950);background:var(--white)}
.sheet .fld select{background-image:linear-gradient(45deg,transparent 50%,var(--ink-500) 50%),
                                    linear-gradient(135deg,var(--ink-500) 50%,transparent 50%)}
.formerr.light{background:var(--crit-bg);border-color:var(--crit);color:var(--crit-tx)}
.sheetbtns{display:flex;gap:var(--s3);margin-top:var(--s5)}
.sheetbtns .btn{flex:1;min-height:54px}
.sheetbtns .btn-danger{background:var(--crit);color:#fff}

/* Filter chips (history) */
.filterbar{display:flex;gap:var(--s2);overflow-x:auto;padding:var(--s3) 0 var(--s4);
           scrollbar-width:none;-webkit-overflow-scrolling:touch}
.filterbar::-webkit-scrollbar{display:none}
.chip{flex:none;background:var(--white);border:1.5px solid var(--ink-200);border-radius:var(--r-pill);
      padding:10px var(--s4);min-height:var(--s8);font-family:inherit;font-size:var(--f-meta);
      font-weight:700;color:var(--ink-700);cursor:pointer;white-space:nowrap}
.chip.on{background:var(--ink-950);border-color:var(--ink-950);color:var(--white)}

/* Awaiting-review flag (invariant 3 made visible) */
.await{display:inline-flex;align-items:center;gap:5px;font-size:var(--f-label);font-weight:800;
       letter-spacing:.05em;color:var(--warn-tx);background:var(--warn-bg);border:1px solid var(--warn);
       border-radius:var(--r-pill);padding:4px 10px;margin-top:var(--s2)}

/* Inline busy state */
.busy{display:flex;align-items:center;gap:var(--s3);color:var(--ink-500);font-size:var(--f-sub);padding:var(--s5) 0}
.spin{width:18px;height:18px;border-radius:50%;border:2.5px solid var(--ink-100);
      border-top-color:var(--ink-500);animation:spin .7s linear infinite;flex:none}
@keyframes spin{to{transform:rotate(360deg)}}
#s-home .busy{color:var(--ink-200)}
#s-home .spin{border-color:rgba(255,255,255,.2);border-top-color:var(--hivis)}

/* -----------------------------------------------------------------------------
   Landscape phone. Workers turn the phone to shoot a wide area, and the page
   comes back from the camera sideways with only 360-430px of height. The
   portrait layout broke there in two places. The stacked report footer took
   42% of the screen. Three columns of tall thumbs put Analyze about 1,000px
   down. Here the footer becomes a single row. Capture splits in two: thumbs
   on the left, and a rail on the right with Analyze at its top. The rail
   sticks while the thumbs scroll, so Analyze stays on screen and nothing
   covers the photos. max-height keeps tablets on the portrait layout.
   -------------------------------------------------------------------------- */
@media (orientation:landscape) and (max-height:500px){
  /* One row: notice on the left, actions on the right. The notice stays;
     it is the only copy of invariant 3's notice on the report screen. */
  .footer{flex-direction:row;align-items:center;gap:var(--s3);
          padding-top:var(--s2);padding-bottom:calc(var(--s2) + var(--safe-b))}
  .footer .disc{flex:1;min-width:0}
  .footer .frow,.footer .frow .btn{flex:none}
  .footer .btn{width:auto;min-height:var(--tap);padding:0 var(--s4);white-space:nowrap}

  #s-capture.active{display:grid;grid-template-columns:minmax(0,1fr) minmax(250px,34%);
                    grid-template-rows:auto 1fr}
  #s-capture .top{grid-column:1 / -1}
  #s-capture .thumbs{grid-template-columns:repeat(4,1fr);padding-right:0}
  #s-capture .bottom{position:sticky;top:0;align-self:start;margin-top:0}
  #analyzeBtn{order:-1}

  /* Report photos fit the screen. Full width, a portrait photo ran ~1,080px
     against ~325px of view, so the box a rank or chip tap revealed was
     off-screen. The rank jump centres the photo in the viewport and the ~65px
     footer covers the bottom, hence twice the footer; the chip row fits under
     it too. Markers and boxes are in % of the wrap, which shrinks to the image. */
  .photo-wrap{width:fit-content;max-width:calc(100% - 2*var(--edge))}
  .photo-wrap img{width:auto;max-width:100%;max-height:calc(100vh - 130px);max-height:calc(100dvh - 130px)}
  /* Half a 3:4 photo at that height, as the tag's room (see .bbox .tag) */
  .bbox .tag{max-width:calc(37.5vh - 46px);max-width:calc(37.5dvh - 46px)}
  /* The photo keeps to the left, so the "See #N details" pill has the free
     space on the right, wide enough for one line. Height is what is short
     here. The chip row keeps out of the pill's lane: see .mchips below. */
  .gochip{max-width:none;padding:14px 22px;white-space:nowrap}
}

/* -----------------------------------------------------------------------------
   Print report (Export PDF)
   -------------------------------------------------------------------------- */
#print-report{display:none}
/* =============================================================================
   PRINT — the report is the deliverable.

   This document gets emailed to a general contractor, filed, and occasionally
   read back months later in a dispute. So it is set like a document, not dumped
   like a screen: a serif face at a comfortable measure, one clear typographic
   hierarchy, hairline rules instead of boxes, and photographs sized as PLATES.

   Photographs were the worst of it. `img{width:100%}` turned a portrait phone
   photo into a full page and a half — a sliver of image orphaned onto the next
   sheet, then acres of white. They are now capped by height, so several sit on
   a page and the report reads as evidence rather than as a slideshow.

   Points, not pixels: print output is physical, and pt is what the page is
   actually measured in.
   ========================================================================== */
@media print{
  /* Margins are split between @page and the container ON PURPOSE.
     A print dialog set to "minimum" or "none" margins overrides @page
     entirely, which put the text hard against the paper edge. Horizontal
     padding on the block applies to EVERY page fragment, so the side margin
     survives whatever the dialog does; @page keeps the top and bottom, which
     padding cannot do because padding applies once, not per page.
       dialog honours @page  ->  6mm +14mm = 20mm sides, 14mm top/bottom
       dialog forces minimum ->  ~6mm+14mm = 20mm sides
       dialog forces none    ->  14mm sides
     The sides never collapse below 14mm in any of the three. */
  @page{ size:letter; margin:14mm 6mm }

  body>*{display:none !important}
  body>#print-report{display:block !important}
  /* html, not just body. The page canvas is painted from the ROOT element, and
     html carries the app's near-black background — resetting only body left
     every sheet past the first solid black with dark text on it. */
  html,body{background:#fff !important;color:#1A1A1A;height:auto;margin:0;padding:0}

  #print-report{
    padding:0 14mm;          /* see the @page note above — survives the dialog */
    font-family:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;
    font-size:10.5pt; line-height:1.52; color:#1A1A1A;
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
    orphans:3; widows:3;
  }
  #print-report p{margin:0 0 6pt}

  /* --- masthead ------------------------------------------------------------ */
  .pr-mast{border-bottom:1.25pt solid #1A1A1A;padding-bottom:7pt;margin-bottom:6pt}
  .pr-brand{font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text",system-ui,sans-serif;
            font-size:7.5pt;font-weight:700;letter-spacing:.2em;text-transform:uppercase;
            color:#1A1A1A;margin-bottom:11pt}
  .pr-title{font-size:27pt;line-height:1.05;font-weight:400;letter-spacing:-.012em;margin:0 0 3pt}
  .pr-sub{font-size:10.5pt;font-style:italic;color:#5A5A5A;margin:0}

  /* Facts read as a reference block, not a paragraph of slashes. */
  .pr-facts{display:grid;grid-template-columns:auto 1fr;gap:3pt 12pt;margin:11pt 0 0;font-size:9.5pt}
  .pr-facts dt{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
               font-size:7pt;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
               color:#8A8A8A;padding-top:2pt;white-space:nowrap}
  .pr-facts dd{margin:0}
  .pr-fill{display:inline-block;min-width:52mm;border-bottom:.5pt solid #9A9A9A}

  /* --- severity tally ------------------------------------------------------ */
  .pr-counts{display:flex;gap:20pt;margin:13pt 0 0;padding:8pt 0;
             border-top:.5pt solid #D8D8D8;border-bottom:.5pt solid #D8D8D8;
             font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
             font-size:8.5pt;font-weight:700;letter-spacing:.08em}
  .pr-counts .sq{display:inline-block;width:8pt;height:8pt;border-radius:1.5pt;margin-right:5pt;
                 vertical-align:-.5pt;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .pr-none{margin:13pt 0 0;padding:9pt 11pt;border-left:2pt solid #046C4E;background:#F1F9F5;
           font-style:italic;-webkit-print-color-adjust:exact;print-color-adjust:exact}

  /* --- section headings ---------------------------------------------------- */
  h2.pr-h{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
          font-size:8pt;font-weight:700;letter-spacing:.17em;text-transform:uppercase;color:#1A1A1A;
          margin:19pt 0 9pt;padding-bottom:4pt;border-bottom:.5pt solid #C4C4C4;
          break-after:avoid;page-break-after:avoid}

  /* --- findings ------------------------------------------------------------ */
  .pr-find{margin:0 0 12pt;padding-bottom:11pt;border-bottom:.5pt solid #E4E4E4;
           break-inside:avoid;page-break-inside:avoid}
  .pr-find:last-of-type{border-bottom:none}
  .pr-find h3{font-size:12.5pt;font-weight:600;line-height:1.28;letter-spacing:-.006em;margin:4pt 0 5pt}
  .pr-sev{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
          font-size:7.5pt;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
  .pr-plabel{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
             font-size:7.5pt;font-weight:700;letter-spacing:.08em;color:#8A8A8A}
  .pr-act{margin-top:5pt}
  .pr-act b{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
            font-size:7.5pt;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#5A5A5A}
  .pr-verify{border-left:2pt solid #B8860B;background:#FDF8EC;padding:7pt 10pt;margin:7pt 0;
             font-style:italic;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .pr-verify b{font-style:normal}
  .pr-cite{font-family:ui-monospace,"SF Mono",Menlo,monospace;font-size:8.5pt;font-weight:600;
           letter-spacing:-.01em}
  .pr-tags{margin-top:5pt;font-size:9pt;color:#5A5A5A}
  .pr-confirm{margin-top:7pt;padding-top:6pt;border-top:.5pt dotted #C4C4C4;
              font-size:9pt;color:#3A3A3A}

  /* --- photographic plates -------------------------------------------------- */
  .pr-plates{text-align:center;margin-top:2pt;break-before:avoid;page-break-before:avoid}
  .pr-photo{position:relative;display:inline-block;max-width:100%;margin:0 0 6pt;
            break-inside:avoid;page-break-inside:avoid}
  /* Capped by HEIGHT. A portrait phone photo at width:100% ran over a full page. */
  .pr-photo img{display:block;width:auto;height:auto;max-width:100%;max-height:80mm;
                border:.5pt solid #D8D8D8}
  .pr-cap{font-size:8.5pt;font-style:italic;color:#6A6A6A;margin:0 0 12pt;text-align:center}
  .pr-hnote{font-size:9pt;font-style:italic;color:#6A6A6A;margin:-4pt 0 9pt;
            break-after:avoid;page-break-after:avoid}
  /* "Photographs" and its note travel with the first plate. A page could end
     on the heading and the note with every plate on the next sheet. The
     break-avoid rules above hold that in Chrome; WebKit, which prints from an
     iPhone, ignores avoid between blocks and honours only break-inside. So
     the heading also carries an unbreakable reserve: an empty ::after that
     reaches the foot of the first plate (96mm: the note's two lines and an
     80mm plate), cancelled by an equal negative margin that collapses out
     through the heading's bottom. Nothing moves on the page, but where the
     plate won't fit under the heading, the heading goes over with it. Its
     rule moves onto the ::after, since a border or padding under the
     reserve would stop the margin collapsing. */
  h2.pr-h:has(+ .pr-hnote, + .pr-plates){padding-bottom:0;border-bottom:none;
                                         break-inside:avoid;page-break-inside:avoid}
  h2.pr-h:has(+ .pr-hnote, + .pr-plates)::after{content:"";display:block;margin:4pt 0 -96mm;
                                                border-top:.5pt solid #C4C4C4;height:96mm}
  .pr-mark{position:absolute;width:15pt;height:15pt;border-radius:50%;transform:translate(-50%,-50%);
           display:flex;align-items:center;justify-content:center;color:#fff;font-size:8pt;font-weight:800;
           font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
           border:1pt solid #fff;box-shadow:0 0 0 .5pt rgba(0,0,0,.35);
           -webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* Paper gets the same amber rule as the screen (see COLOUR): an ink numeral
     on an amber dot, and amber severity words in the badge's dark amber
     (#8A4B00, 6.8:1 on white, against 2.2:1 for #F59E0B). pr-sev's colour is
     inline, so only !important reaches it. */
  .pr-mark[style*="F59E0B" i],.pb-num[style*="F59E0B" i]{color:#0B0F14}
  .pr-sev[style*="F59E0B" i]{color:#8A4B00!important}
  .pr-ptag{position:absolute;top:4pt;left:4pt;background:#0B0F14;color:#fff;font-size:6.5pt;font-weight:700;
           letter-spacing:.12em;padding:2.5pt 5pt;
           font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
           -webkit-print-color-adjust:exact;print-color-adjust:exact}

  /* --- limitations ---------------------------------------------------------- */
  .pr-lims li{margin:0 0 4pt}
  .pr-lims ul{margin:0;padding-left:14pt}
  .pr-lims .pr-plabel{margin-right:4pt}
  .pr-walk{margin-top:8pt;font-style:italic;color:#5A5A5A}

  /* --- sign-off ------------------------------------------------------------- */
  .pr-sign{border:.75pt solid #1A1A1A;padding:12pt 13pt;margin-top:19pt;
           break-inside:avoid;page-break-inside:avoid}
  .pr-sign b{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
             font-size:8pt;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
  .pr-sign .line{margin-top:19pt;border-bottom:.5pt solid #1A1A1A;height:1pt}
  .pr-sign .cap{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
                font-size:7pt;letter-spacing:.12em;text-transform:uppercase;color:#8A8A8A;margin-top:3pt}
  .pr-foot{margin-top:15pt;padding-top:6pt;border-top:.5pt solid #DDD;
           font-size:8pt;font-style:italic;color:#7A7A7A;line-height:1.45}

  /* --- briefing: a different artifact, read aloud to a crew ----------------- */
  h2.pb-h{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
          font-size:8pt;font-weight:700;letter-spacing:.17em;text-transform:uppercase;
          margin:18pt 0 8pt;padding-bottom:4pt;border-bottom:1pt solid #1A1A1A;
          break-after:avoid;page-break-after:avoid}
  .pb-n{font-weight:400;color:#8A8A8A;letter-spacing:.04em}
  .pb-item{display:flex;gap:10pt;padding:8pt 0;border-bottom:.5pt solid #E4E4E4;
           break-inside:avoid;page-break-inside:avoid}
  .pb-item:last-child{border-bottom:none}
  .pb-num{width:16pt;height:16pt;border-radius:50%;flex:none;color:#fff;font-size:8pt;font-weight:800;
          font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
          display:flex;align-items:center;justify-content:center;margin-top:1.5pt;
          -webkit-print-color-adjust:exact;print-color-adjust:exact}
  .pb-txt b{font-size:11.5pt;font-weight:600;line-height:1.3}
  .pb-txt div{margin-top:3pt}
  .pb-fix{font-size:10pt}
  .pb-fix b{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
            font-size:7.5pt;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#5A5A5A}
  .pb-cite{font-family:ui-monospace,Menlo,monospace;font-size:8.5pt;font-weight:600;color:#5A5A5A}
  .pb-clear{margin:13pt 0;padding:10pt 12pt;border-left:2pt solid #046C4E;background:#F1F9F5;
            font-style:italic;-webkit-print-color-adjust:exact;print-color-adjust:exact}
}

/* Respect a user who asks for less motion */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
                       transition-duration:.001ms!important}
}

/* Remove affordance on an unused site row */
.siterm{background:none;border:none;color:var(--ink-400);font-size:17px;font-weight:700;
        padding:0 var(--s1);margin-left:var(--s2);cursor:pointer;flex:none;position:relative;
        font-family:inherit;line-height:1}
.siterm::after{content:"";position:absolute;inset:-14px}
.siterm:active{color:var(--white)}

/* Visually hidden, still announced. Colour-coded pips need a text label too. */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* Competent-person designation toggle (Account) */
.btn-desig{background:none;border:1.5px solid var(--ink-200);border-radius:var(--r-sm);
           padding:9px 13px;min-height:var(--s8);font-family:inherit;font-size:var(--f-meta);
           font-weight:800;letter-spacing:.03em;color:var(--ink-700);cursor:pointer;flex:none}
.btn-desig.on{background:var(--ok-bg);border-color:var(--ok-tx);color:var(--ok-tx)}
.btn-desig:active{background:var(--ink-50)}
#clerk-profile{--clerk-font-family:inherit}
/* Pinch-zoom is allowed, so iOS zooms into any focused field under 16px and
   leaves the page zoomed. Our fields are 16-17px. Clerk's default to about
   13px, and the ID outranks Clerk's class selectors. */
#clerk-auth input,#clerk-org input,#clerk-profile input{font-size:16px}

/* scan-flow additions
   -----------------------------------------------------------------------------
   Rules for elements app.js now builds: the report's incomplete/unsaved
   banners, the per-photo marker chips, the limitation lines (moved off inline
   styles), sign-off pending state, history flags, and the briefing's
   confidence/verification/sign-off lines. The 44px marker hit area is above. */

/* C2: a partial scan says so before anything else on the report. Amber, not
   red: red is severity, and this is about coverage. */
.incbanner{margin:14px var(--edge) 0;background:var(--warn-bg);color:var(--warn-tx);border:1.5px solid var(--warn);
           border-radius:10px;padding:var(--s3) var(--s4);font-size:var(--f-sub);line-height:var(--lh-sub);
           display:flex;flex-direction:column;gap:var(--s1)}
.incbanner>b:first-child{font-size:var(--f-body);line-height:var(--lh-body);font-weight:800;color:var(--ink-950)}
#s-brief .incbanner{margin:var(--s4) var(--edge) 0}
.incbanner .btn,.errbox .btn{min-height:var(--tap);margin-top:var(--s2);font-size:var(--f-sub)}
.okbox .okscene{font-size:var(--f-sub);line-height:var(--lh-sub);margin-top:var(--s2)}

/* A dense photo's findings as full-size targets under it */
/* The row stops short of the "See #N details" pill's lane on the right (see
   .gochip): the pill is fixed and the row scrolls under it, and full width,
   whichever chips crossed its band were covered. Every chip tap shows the
   pill. The lane is the pill (122px) plus a gap, which leaves portrait four
   chips a row; landscape's one-line pill is ~180px for "See #27 details",
   ~200px for a three-digit rank. */
.mchips{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s2) calc(var(--edge) + 134px) 0 var(--edge)}
.mchip{min-width:44px;min-height:44px;padding:0 var(--s2);border-radius:var(--r-pill);border:2px solid var(--white);
       box-shadow:0 0 0 1px var(--ink-200);font-family:inherit;font-size:var(--f-body);font-weight:800;cursor:pointer}
@media (orientation:landscape) and (max-height:500px){
  .mchips{margin-right:calc(var(--edge) + 216px)}
}
.pcap{margin:var(--s2) var(--edge) 0;font-size:var(--f-sub);line-height:var(--lh-sub);color:var(--ink-700)}

/* Low confidence beside the severity badge. Dashed: doubt, not a severity. */
.badges{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
.lowconf{display:inline-flex;align-items:center;font-size:var(--f-label);font-weight:800;letter-spacing:.08em;
         padding:4px 8px;border-radius:5px;border:1.5px dashed var(--ink-700);color:var(--ink-950);
         background:var(--white);vertical-align:middle}

/* Limitations carry invariant 4 (see SAFETY TEXT) */
.limsec{padding:0 var(--edge) var(--s4)}
.limrow{font-size:var(--f-body);line-height:var(--lh-body);color:var(--ink-700);
        padding:6px 0;border-bottom:1px solid var(--ink-50)}
.limwalk{font-size:var(--f-body);line-height:var(--lh-body);color:var(--ink-950);font-weight:700;margin-top:var(--s2)}

/* Sign-off in flight: both buttons wait for the server's answer */
.decide.pending button{opacity:.55;cursor:progress}

/* History: a partial scan is flagged, and a row being opened says so */
.incflag{display:inline-flex;align-items:center;font-size:var(--f-label);font-weight:800;letter-spacing:.05em;
         color:var(--ink-950);background:var(--ink-50);border:1.5px solid var(--ink-700);
         border-radius:var(--r-pill);padding:4px 10px;margin:var(--s2) var(--s2) 0 0}
.pip.na{background:var(--ink-500)}
.hrow.loading,.recent.loading{opacity:.55;cursor:progress}
.histmore{margin-top:var(--s4)}
.thumb-add:disabled{opacity:.4;cursor:default}

/* Briefing: what the report card shows, the briefing shows */
.bitem .btxt .verify,.bitem .btxt .decided{margin-top:var(--s2)}
.bitem .btxt .lowconf{margin-top:var(--s1)}
.bmeta{font-size:var(--f-sub);line-height:var(--lh-sub);color:var(--ink-700);margin-top:var(--s2)}
.bitem.dism .btxt>b{color:var(--ink-500)}

@media print{
  .pb-state{font-size:9pt;color:#3A3A3A}
  .pb-state b{font-size:inherit;font-weight:700}
}

/* Scan-failure sheets put what happened and what to do in two paragraphs */
.sheetsub{white-space:pre-line}
/* A briefing with nothing to act on still says what each photo was checked for */
.bnone .okscene{margin-top:var(--s2);font-size:var(--f-sub);line-height:var(--lh-sub);font-weight:500}

/* round-2 additions */
/* A finding the competent person dismissed reads as dismissed at a glance —
   grey bar and markers (painted by app.js), muted title, a DISMISSED tag —
   while its severity badge and confidence stay: they are the AI's proposal. */
.dismtag{display:none;align-items:center;font-size:var(--f-label);font-weight:800;letter-spacing:.08em;
         padding:4px 8px;border-radius:5px;background:var(--ink-700);color:var(--white)}
.card.dismissed .dismtag{display:inline-flex}
.card.dismissed{background:var(--ink-50)}
.card.dismissed h3{color:var(--ink-500)}
/* Pressed DISMISS is filled. Paler than the unpressed button, it read as disabled. */
.decide button.on[data-d="dismissed"]{background:var(--ink-700);border-color:var(--ink-700);color:var(--white)}
/* Live counts, with the dismissed counted apart on a line of their own */
.counts{flex-wrap:wrap}
.counts .cdism{flex-basis:100%;font-size:var(--f-meta);line-height:var(--lh-meta);font-weight:700;color:var(--ink-700)}
.gcounts{display:inline-flex;align-items:center;gap:var(--s3)}
.gc.gdism{font-size:var(--f-meta);font-weight:700;color:var(--ink-500);white-space:nowrap}
/* A dismissed card keeps its verify flag on the record, without the alarm colour */
.card.dismissed .verify{background:var(--white);border-color:var(--ink-200);color:var(--ink-700)}
@media print{
  /* LOW CONFIDENCE and DISMISSED are marks, not reference labels: dark, and boxed */
  .pr-lowconf,.pr-dism{font-family:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
             font-size:7.5pt;font-weight:700;letter-spacing:.12em;padding:1pt 4pt}
  .pr-lowconf{color:#1A1A1A;border:1pt dashed #1A1A1A}
  .pr-dism{color:#FFFFFF;background:#3A3A3A;border:1pt solid #3A3A3A;
           -webkit-print-color-adjust:exact;print-color-adjust:exact}
}

/* round-3 additions */
/* The photo without its markers, one tap away (V1): a disc covers a small
   hazard, and pinch-zoom scales the disc too. A box tapped open stays shown. */
.photo-wrap.nomarks .mark,.photo-wrap.nomarks .leader{visibility:hidden}
.pbar{display:flex;margin:var(--s2) var(--edge) 0}
.mtoggle{min-height:var(--tap);padding:0 var(--s4);border-radius:var(--r-pill);border:1.5px solid var(--ink-200);
         background:var(--white);color:var(--ink-950);font-family:inherit;font-size:var(--f-sub);font-weight:700;cursor:pointer}
.photo-wrap.nomarks+.pbar .mtoggle{background:var(--ink-950);border-color:var(--ink-950);color:var(--white)}
