/* ============================================================
   FACTERRA — UI mockups
   HTML recreations of the real product UI, populated with
   renewables / critical-facilities content instead of the
   food-processing data in the original screenshots.
   Layout, hierarchy and states mirror the shipped product.
   ============================================================ */

.ui{
  --ui-bg:#FFFFFF; --ui-panel:#F7F8FA; --ui-line:#E3E7EB;
  --ui-ink:#1B2229; --ui-ink-2:#5A646E; --ui-ink-3:#8B949D;
  --ui-blue:#2E6FC4; --ui-blue-bg:#EAF1FA;
  --ui-green:#1F7A4D; --ui-amber:#B26A00; --ui-red:#A8322A;
  font-family:var(--font);
  background:var(--ui-bg);color:var(--ui-ink);
  border:1px solid var(--line);border-radius:var(--radius-lg);
  overflow:hidden;font-size:13px;line-height:1.45;
  /* Lifted and tilted a fraction of a degree, like the real captures, so these
     read as depictions of the app rather than as live UI embedded in the page.
     Kept smaller than the screenshots' tilt: these are dense tables, and text
     rendered on a rotated element loses crispness faster than a bitmap does. */
  transform:rotate(-0.5deg);
  box-shadow:0 14px 34px rgba(16,24,32,.16), 0 3px 10px rgba(16,24,32,.10);
}
/* Mirrored tilt for the second of a stacked pair. */
.ui-tilt-right{transform:rotate(0.5deg);}
@media (max-width:900px){
  .ui,.ui-tilt-right{transform:none;}
}
@media (prefers-reduced-motion:reduce){
  .ui,.ui-tilt-right{transform:none;}
}

/* --- App chrome --- */
.ui-bar{display:flex;align-items:center;gap:10px;padding:10px 14px;
  border-bottom:1px solid var(--ui-line);background:var(--ui-bg);}
.ui-crumb{font-size:12.5px;color:var(--ui-ink-2);}
.ui-crumb b{color:var(--ui-ink);font-weight:600;}
.ui-spacer{flex:1;}
.ui-dot{width:22px;height:22px;border-radius:50%;background:var(--ui-panel);
  border:1px solid var(--ui-line);flex:none;}
.ui-body{display:flex;min-height:100px;}
.ui-rail{width:44px;border-right:1px solid var(--ui-line);background:var(--ui-panel);
  padding:12px 0;display:flex;flex-direction:column;align-items:center;gap:16px;flex:none;}
.ui-rail i{width:16px;height:16px;border-radius:3px;background:#D5DAE0;display:block;}
.ui-rail i.on{background:var(--ui-blue);}
.ui-main{flex:1;padding:14px;min-width:0;}

/* --- Status tags & people ---
   Shared by the equipment table, evidence pack and phone screens. */
.tag{font-size:10px;font-weight:600;padding:2px 6px;border-radius:3px;
  border:1px solid var(--ui-line);color:var(--ui-ink-2);background:var(--ui-panel);
  white-space:nowrap;}
.tag.blue{color:var(--ui-blue);background:var(--ui-blue-bg);border-color:#CFE0F4;}
.tag.red{color:var(--ui-red);background:#FBEDEC;border-color:#F2D6D3;}
.tag.amber{color:var(--ui-amber);background:#FBF3E6;border-color:#F0E0C4;}
.tag.green{color:var(--ui-green);background:#E9F4EE;border-color:#CFE6DA;}
.who{display:flex;align-items:center;gap:4px;margin-left:auto;}
.av{width:17px;height:17px;border-radius:50%;background:#CBD2D9;flex:none;
  font-size:8.5px;display:flex;align-items:center;justify-content:center;
  color:#4A545E;font-weight:700;}
.sub-badge{font-size:9.5px;font-family:var(--mono);color:var(--ui-blue);
  border:1px solid #CFE0F4;background:var(--ui-blue-bg);border-radius:3px;padding:1px 4px;}
.chip{font-size:10.5px;padding:3px 9px;border-radius:999px;border:1px solid var(--ui-line);
  color:var(--ui-ink-2);display:flex;align-items:center;gap:5px;background:var(--ui-bg);}
.chip::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;}

/* --- Equipment page / alerts table --- */
.eq-head{display:flex;gap:18px;flex-wrap:wrap;padding:12px 14px;
  border-bottom:1px solid var(--ui-line);background:var(--ui-panel);}
.eq-f{min-width:88px;}
.eq-f dt{font-size:9.5px;font-family:var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ui-ink-3);}
.eq-f dd{margin:2px 0 0;font-size:12px;font-weight:600;}
.eq-tabs{display:flex;gap:2px;padding:0 14px;border-bottom:1px solid var(--ui-line);}
.eq-tab{font-size:12px;padding:9px 11px;color:var(--ui-ink-2);border-bottom:2px solid transparent;}
.eq-tab.on{color:var(--ui-blue);border-bottom-color:var(--ui-blue);font-weight:600;}
.ui table{width:100%;min-width:0;border-collapse:collapse;font-size:12px;}
.ui th{font-size:9.5px;font-family:var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ui-ink-3);text-align:left;padding:9px 12px;border-bottom:1px solid var(--ui-line);
  font-weight:500;}
.ui td{padding:10px 12px;border-bottom:1px solid var(--ui-line);color:var(--ui-ink-2);}
.ui tbody tr:last-child td{border-bottom:none;}
.ui td b{color:var(--ui-ink);font-weight:600;}
.ui td .mono{font-family:var(--mono);font-size:11.5px;}
.toggle{width:26px;height:15px;border-radius:999px;background:var(--ui-blue);position:relative;
  display:inline-block;}
.toggle::after{content:"";position:absolute;top:2px;right:2px;width:11px;height:11px;
  border-radius:50%;background:#fff;}
.toggle.off{background:#CBD2D9;}
.toggle.off::after{right:auto;left:2px;}

/* --- Asset hierarchy tree ---
   Site → block → equipment → component. The depth is the message:
   a flat CMMS list cannot draw this picture. */
.tree{font-size:12.5px;line-height:1.45;}
.tree-row{display:flex;align-items:baseline;gap:8px;padding:6.5px 12px;
  border-bottom:1px solid var(--ui-line);}
.tree-row:last-child{border-bottom:none;}
.tree-glyph{font-family:var(--mono);color:var(--ui-ink-3);flex:none;font-size:11px;}
.tree-name{font-weight:600;color:var(--ui-ink);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;}
.tree-name .mono{color:var(--ui-ink-2);font-weight:500;}
.tree-meta{margin-left:auto;display:flex;gap:5px;align-items:center;flex:none;}
.tree-count{font-family:var(--mono);font-size:10.5px;color:var(--ui-ink-3);}

/* Sub-tabs on the equipment page (Calendar | List | Plans) */
.eq-subtabs{display:flex;gap:2px;padding:8px 14px 0;}
.eq-subtab{font-size:11px;padding:4px 9px;border-radius:3px;color:var(--ui-ink-3);}
.eq-subtab.on{background:var(--ui-blue-bg);color:var(--ui-blue);font-weight:600;}

/* Phone: document list rows (QR → documentation) */
.ph-doc{display:flex;gap:8px;align-items:center;padding:8px 0;
  border-bottom:1px solid var(--ui-line);font-size:11.5px;line-height:1.3;}
.ph-doc:last-child{border-bottom:none;}
.ph-doc-ic{width:24px;height:24px;border-radius:3px;background:var(--ui-panel);
  border:1px solid var(--ui-line);flex:none;display:flex;align-items:center;
  justify-content:center;font-family:var(--mono);font-size:7.5px;color:var(--ui-ink-3);}
.ph-doc-meta{display:block;font-family:var(--mono);font-size:9px;color:var(--ui-ink-3);
  margin-top:1px;}

/* --- Phone: subcontractor link --- */
/* .phone renders as a sibling of .ui, not a descendant, so it cannot inherit
   the --ui-* tokens declared on .ui. Redeclare them here or every token this
   subtree references resolves to nothing (checked boxes lose their fill and
   checkmark, and the screen reads as an empty form). */
.phone{
  --ui-bg:#FFFFFF; --ui-panel:#F7F8FA; --ui-line:#E3E7EB;
  --ui-ink:#1B2229; --ui-ink-2:#5A646E; --ui-ink-3:#8B949D;
  --ui-blue:#2E6FC4; --ui-blue-bg:#EAF1FA;
  --ui-green:#1F7A4D; --ui-amber:#B26A00; --ui-red:#A8322A;
  width:250px;border:1px solid var(--line);border-radius:20px;background:#fff;
  padding:9px;flex:none;box-shadow:none;}
.phone-scr{border:1px solid var(--ui-line);border-radius:13px;overflow:hidden;background:#fff;}
.ph-top{background:var(--ui-panel);border-bottom:1px solid var(--ui-line);padding:9px 11px;}
.ph-url{font-family:var(--mono);font-size:9.5px;color:var(--ui-ink-3);
  background:#fff;border:1px solid var(--ui-line);border-radius:3px;padding:3px 7px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.ph-body{padding:12px 11px;}
.ph-kicker{font-size:9.5px;font-family:var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ui-ink-3);}
.ph-title{font-size:14px;font-weight:660;line-height:1.25;margin-top:3px;}
.ph-asset{font-family:var(--mono);font-size:11px;color:var(--ui-blue);margin-top:3px;}
.ph-check{display:flex;gap:8px;align-items:flex-start;padding:8px 0;
  border-bottom:1px solid var(--ui-line);font-size:11.5px;line-height:1.35;}
.ph-box{width:13px;height:13px;border:1.5px solid var(--ui-ink-3);border-radius:2.5px;flex:none;
  margin-top:1px;}
.ph-box.on{background:var(--ui-green);border-color:var(--ui-green);position:relative;}
.ph-box.on::after{content:"";position:absolute;left:3.5px;top:.5px;width:3.5px;height:7px;
  border:solid #fff;border-width:0 1.7px 1.7px 0;transform:rotate(45deg);}
.ph-photos{display:flex;gap:5px;margin-top:9px;}
.ph-photo{flex:1;aspect-ratio:1;border-radius:3px;background:var(--ui-panel);
  border:1px solid var(--ui-line);display:flex;align-items:center;justify-content:center;
  font-size:14px;color:var(--ui-ink-3);position:relative;overflow:hidden;}
/* A captured slot reads as holding image data without inventing a photograph:
   an abstract gradient, not a fake site picture. */
.ph-photo.has{background:
  linear-gradient(160deg,#C9D4DF 0%,#9FB0C0 38%,#7E93A6 62%,#5E7386 100%);
  border-color:#8FA1B2;}
.ph-ph-tag{position:absolute;left:0;right:0;bottom:0;font-family:var(--mono);
  font-size:7.5px;color:#fff;background:rgba(20,27,34,.62);text-align:center;
  padding:1px 0;letter-spacing:.02em;}

/* Job progress */
.ph-prog{height:3px;border-radius:999px;background:var(--ui-line);margin-top:11px;
  overflow:hidden;}
.ph-prog-bar{display:block;height:100%;background:var(--ui-green);border-radius:999px;}
.ph-prog-lab{display:flex;justify-content:space-between;gap:8px;margin-top:5px;
  font-size:9.5px;color:var(--ui-ink-3);}
.ph-prog-lab .mono{font-family:var(--mono);}
.ph-check.done span:last-child{color:var(--ui-ink-2);}
.ph-stamp{display:block;font-family:var(--mono);font-size:9px;color:var(--ui-green);
  margin-top:2px;}
.ph-btn{margin-top:11px;background:var(--ui-green);color:#fff;text-align:center;
  padding:9px;border-radius:4px;font-size:12.5px;font-weight:650;}
.ph-note{font-size:9.5px;color:var(--ui-ink-3);text-align:center;margin-top:7px;
  font-family:var(--mono);}

/* --- Product screenshots ---
   Real captures of the shipped app. The source images carry their own
   white plate and soft shadow, so the frame stays a hairline and the
   plate is painted behind them: on dark, a transparent-margin PNG would
   otherwise sit on page background and read as a floating cut-out. --- */
.shot{border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;
  background:#FFFFFF;line-height:0;}
.shot img{display:block;width:100%;height:auto;}
/* Shots are captured at ~850-900px. Cap at native width so the UI stays
   crisp instead of upscaling into mush in the 1092px column. */
.shot-cap{max-width:896px;}
.shot-cap.center{margin-left:auto;margin-right:auto;}
/* Some captures ship with their own white plate and drop shadow baked in.
   Framing those again produces a card-inside-a-card, so .shot-bare drops the
   border and lets the image's own plate be the edge. */
.shot-bare{border:none;border-radius:0;background:transparent;}
.shot-bare img{border-radius:var(--radius-lg);}

/* Lift the flat captures off the page and tilt them a degree or so, matching
   the hero composite, so a screenshot reads as an image of the product rather
   than as page furniture the reader might try to click.
   The transform goes on the frame, not the img: .shot sets overflow:hidden for
   its rounded corners, and a rotated child would be clipped by it. The shadow
   likewise belongs on the frame, which is the element with the plate — on
   .shot-bare the plate is the image's own, so that one gets a drop-shadow
   filter instead, which follows the artwork's alpha rather than its box. */
.shot{transform:rotate(-0.7deg);
  box-shadow:0 14px 34px rgba(16,24,32,.16), 0 3px 10px rgba(16,24,32,.10);}
.shot-bare{box-shadow:none;filter:drop-shadow(0 14px 30px rgba(16,24,32,.20));}
/* Alternate the tilt where two shots stack, so they don't read as one skewed
   column. */
.shot-tilt-right{transform:rotate(0.7deg);}
/* On a phone the frame scrolls horizontally and sits nearly edge-to-edge; a
   tilt there just crops corners against the gutter and fights the scroll. */
@media (max-width:900px){
  .shot,.shot-tilt-right{transform:none;}
}
@media (prefers-reduced-motion:reduce){
  .shot,.shot-tilt-right{transform:none;}
}
/* Never upscale past the capture's native width — these are UI screenshots,
   where soft text reads as a low-quality product. */
.shot-845{max-width:845px;}

/* --- Evidence pack --- */
.ev-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;
  padding-bottom:12px;border-bottom:1px solid var(--ui-line);margin-bottom:12px;flex-wrap:wrap;}
.ev-title{font-size:14px;font-weight:660;}
.ev-sub{font-size:11.5px;color:var(--ui-ink-3);font-family:var(--mono);margin-top:3px;}
.ev-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:12px;}
.ev-stat{border:1px solid var(--ui-line);border-radius:4px;padding:9px 11px;}
.ev-num{font-size:19px;font-weight:660;letter-spacing:-.02em;}
.ev-lab{font-size:9.5px;font-family:var(--mono);letter-spacing:.07em;text-transform:uppercase;
  color:var(--ui-ink-3);margin-top:2px;}
/* Per-row evidence composition: what was actually captured on the job, and
   what wasn't. .ev-miss is the whole argument of this section — a gap is
   rendered as a gap rather than quietly omitted. */
.ev-by{font-family:var(--font);font-size:10.5px;color:var(--ui-ink-3);margin-top:3px;
  letter-spacing:0;}
.ev-items{display:flex;flex-wrap:wrap;gap:4px;}
.ev-item{font-size:10px;font-weight:600;padding:2px 6px;border-radius:3px;
  color:var(--ui-green);background:#E9F4EE;border:1px solid #CFE6DA;white-space:nowrap;}
.ev-item.ev-miss{color:var(--ui-red);background:#FBEDEC;border-color:#F2D6D3;}
.ev-when{font-size:10px;color:var(--ui-ink-3);margin-top:5px;}
.ev-foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  border-top:1px solid var(--ui-line);margin-top:12px;padding-top:11px;
  font-size:10.5px;color:var(--ui-ink-3);}
.ev-gap{color:var(--ui-red);font-weight:600;}
.ev-spacer{flex:1;}

@media (max-width:820px){
  .kan{grid-template-columns:repeat(2,1fr);}
  .reg{grid-template-columns:repeat(2,1fr);}
  .ev-stats{grid-template-columns:repeat(2,1fr);}
}

/* Below ~900px a dense UI capture scaled to fit is unreadable — it becomes
   grey texture. Let the frame scroll at a legible width instead of shrinking
   the whole app to thumbnail size. The scroll stays inside the frame, so the
   page itself never scrolls sideways. */
@media (max-width:900px){
  .shot{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .shot img{max-width:none;width:760px;}
  .shot-845 img{width:720px;}
  /* Tell the reader it scrolls; a clipped screenshot with no affordance just
     looks broken. This used to hang off the visible caption below the frame;
     the captions are gone, so it sits on the frame's own wrapper instead. */
  .shot-scroll{position:relative;}
  .shot-scroll::after{content:"Scroll to see the full screen →";
    display:block;font-family:var(--mono);font-size:11px;color:var(--ink-3);
    margin-top:8px;line-height:1.4;}
}
@media (max-width:560px){
  .kan{grid-template-columns:1fr;}
  .reg{grid-template-columns:1fr;}
  .ui-rail{display:none;}
  /* A dense product table cannot reflow to 327px without becoming unreadable.
     .ui clips (overflow:hidden, for the rounded frame), so a wide table is
     silently cut with no affordance. Let the table scroll inside its own pane
     instead — the frame keeps its edge and the page never scrolls sideways. */
  .ui-main{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .ui-main table{min-width:440px;}
  /* Six tabs never fit a phone. Scroll the strip, the way the real app does,
     rather than wrapping it into two ragged rows. */
  .eq-tabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
  .eq-tabs::-webkit-scrollbar{display:none;}
  .eq-tab{white-space:nowrap;flex:none;}
  /* The equipment header wraps its field pairs rather than scrolling: they are
     independent labels, so wrapping loses nothing. */
  .eq-head{gap:12px;}
}

@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .ui{
    --ui-bg:#141B22; --ui-panel:#1A222A; --ui-line:#2A343E;
    --ui-ink:#E9ECEF; --ui-ink-2:#A8B2BC; --ui-ink-3:#7C858E;
    --ui-blue:#5B96DE; --ui-blue-bg:#16263A;
  }
  :root:not([data-theme="light"]) .av{background:#38424C;color:#C9D1D9;}
  :root:not([data-theme="light"]) .phone{background:var(--surface);}
  :root:not([data-theme="light"]) .phone-scr,
  :root:not([data-theme="light"]) .ph-body{background:#141B22;}
  :root:not([data-theme="light"]) .tag.blue{border-color:#274563;}
  :root:not([data-theme="light"]) .tag.red{background:#2E1A18;border-color:#4A2723;}
  :root:not([data-theme="light"]) .tag.amber{background:#2B2113;border-color:#463620;}
  :root:not([data-theme="light"]) .tag.green{background:#152A20;border-color:#234534;}
  :root:not([data-theme="light"]) .ev-item{background:#152A20;border-color:#234534;color:#5FBF8C;}
  :root:not([data-theme="light"]) .ev-item.ev-miss{background:#2E1A18;border-color:#4A2723;color:#E4867C;}
  :root:not([data-theme="light"]) .ev-gap{color:#E4867C;}
  :root:not([data-theme="light"]) .ph-stamp{color:#5FBF8C;}
  /* These are light-UI captures, so the plate stays white in dark mode. On a
     .shot-bare the image's transparent margin would otherwise let the dark
     page show through around a white screenshot. Paint the plate onto the
     image itself and soften it slightly so it isn't a glaring white block. */
  :root:not([data-theme="light"]) .shot-bare img{background:#FFFFFF;}
  :root:not([data-theme="light"]) .shot{filter:brightness(.94) saturate(.96);}
}
