/* tylersowards.com · hand-built, no frameworks
   palette lifted from my logcompilation dashboard:
   graphite grounds · bright-sky accent · leaf/pollen/watermelon semantics
   type: Rubik (same face as the dashboard), self-hosted, OFL licensed */

@font-face{
  font-family:'Rubik';
  src:url('../fonts/rubik-latin.woff2') format('woff2');
  font-weight:300 900; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Rubik';
  src:url('../fonts/rubik-italic-latin.woff2') format('woff2');
  font-weight:300 900; font-style:italic; font-display:swap;
}

:root{
  --bg:#FDFDFF; --bg-soft:#F4F5F8; --panel:#FFFFFF; --well:#EDEFF3;
  --ink:#232326; --ink-soft:#5D5D63; --ink-faint:#9C9CA3;
  --line:#E0E1E6; --line-strong:#C9CAD1;
  --accent:#018BB3; --accent-hi:#01BAEF; --accent-tint:rgba(1,186,239,0.10);
  --ok:#43A03E; --warn:#C49E2D; --crit:#B83540; --violet:#7457D1;
  --head:#141416; --chrome:#F0F1F5;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,"Cascadia Code",Menlo,Consolas,monospace;
  --sans:'Rubik',system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --maxw:1180px;
  /* structural tokens: the aesthetic styles in themes.css reshape these */
  --r1:3px; --r2:4px; --r3:5px; --r3l:6px; --r4:9px; --r4l:14px; --r5:16px; --rp:20px;
  --shadow-win:none; --shadow-card:none;
}
@media (prefers-color-scheme:dark){
  :root{
    --bg:#17171A; --bg-soft:#1E1E22; --panel:#232327; --well:#101013;
    --ink:#DCDDE2; --ink-soft:#A0A0A6; --ink-faint:#69696F;
    --line:#323236; --line-strong:#47474C;
    --accent:#01BAEF; --accent-hi:#3FD0FA; --accent-tint:rgba(1,186,239,0.12);
    --ok:#5BCB55; --warn:#F9CB40; --crit:#E84855; --violet:#A58BFF;
    --head:#FDFDFF; --chrome:#2A2A2F;
  }
}
:root[data-theme="light"]{
  --bg:#FDFDFF; --bg-soft:#F4F5F8; --panel:#FFFFFF; --well:#EDEFF3;
  --ink:#232326; --ink-soft:#5D5D63; --ink-faint:#9C9CA3;
  --line:#E0E1E6; --line-strong:#C9CAD1;
  --accent:#018BB3; --accent-hi:#01BAEF; --accent-tint:rgba(1,186,239,0.10);
  --ok:#43A03E; --warn:#C49E2D; --crit:#B83540; --violet:#7457D1;
  --head:#141416; --chrome:#F0F1F5;
}
:root[data-theme="dark"]{
  --bg:#17171A; --bg-soft:#1E1E22; --panel:#232327; --well:#101013;
  --ink:#DCDDE2; --ink-soft:#A0A0A6; --ink-faint:#69696F;
  --line:#323236; --line-strong:#47474C;
  --accent:#01BAEF; --accent-hi:#3FD0FA; --accent-tint:rgba(1,186,239,0.12);
  --ok:#5BCB55; --warn:#F9CB40; --crit:#E84855; --violet:#A58BFF;
  --head:#FDFDFF; --chrome:#2A2A2F;
}

*{box-sizing:border-box}
body{
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--sans); font-size:16px; line-height:1.65;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
::selection{background:var(--accent-tint); color:var(--head);}
a{color:var(--accent); text-decoration:none;}
a:hover{text-decoration:underline;}
a:focus-visible,button:focus-visible,input:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
.wrap{max-width:var(--maxw); margin:0 auto; padding:0 26px;}
.mono{font-family:var(--mono);}
.num{font-variant-numeric:tabular-nums;}

/* ── status strip ── */
.strip{
  border-bottom:1px solid var(--line); font-family:var(--mono); font-size:11px;
  letter-spacing:.05em; color:var(--ink-faint);
  position:sticky; top:0; z-index:30;
  background:color-mix(in srgb,var(--bg) 90%,transparent); backdrop-filter:blur(8px);
}
.strip .row{display:flex; align-items:center; gap:16px; height:40px;}
.strip .host{color:var(--head); font-weight:600;}
.dot{display:inline-block; width:7px; height:7px; border-radius:50%; margin-right:6px; vertical-align:1px;}
.dot.ok{background:var(--ok);}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.45}}
.dot.live{animation:pulse 2.4s ease-in-out infinite;}
.strip nav{margin-left:auto; display:flex; gap:14px; align-items:center;}
.strip nav a{color:var(--ink-faint); font-size:11px;}
.strip nav a:hover{color:var(--accent); text-decoration:none;}
.tbtn{cursor:pointer; border:1px solid var(--line); background:transparent; color:var(--ink-soft);
  border-radius:var(--r1); font-size:11px; font-family:var(--mono); padding:3px 8px;}
.tbtn:hover{border-color:var(--accent); color:var(--accent);}
@media (max-width:700px){.strip .hide-m{display:none}}

/* ── window chrome (utility style, decidedly not cupertino) ── */
.win{border:1px solid var(--line); border-radius:var(--r2); background:var(--panel); overflow:hidden; box-shadow:var(--shadow-win);}
.win .bar{
  display:flex; align-items:center; gap:10px; height:34px; padding:0 12px;
  background:var(--chrome); border-bottom:1px solid var(--line);
  font-family:var(--mono); font-size:11px; color:var(--ink-soft); letter-spacing:.04em;
}
.win .bar .st{width:8px; height:8px; background:var(--ok); border-radius:1px; flex:none;}
.win .bar.restrict .st{background:var(--warn);}
.win .bar .ttl{overflow:hidden; white-space:nowrap;}
.win .bar .end{margin-left:auto; color:var(--ink-faint); flex:none;}
@media (max-width:700px){.win .bar .end{display:none}}

/* ── hero ── */
.hero{padding:80px 0 30px;}
@media (max-width:700px){.hero{padding:56px 0 24px}}
.sysline{font-family:var(--mono); font-size:12px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-soft); margin-bottom:26px;}
.sysline .ok{color:var(--ok);}
h1{font-size:clamp(28px,4.6vw,54px); line-height:1.15; letter-spacing:-.015em;
  font-weight:600; color:var(--head); margin:0 0 20px; max-width:24ch; text-wrap:balance;}
h1 em{font-style:normal; color:var(--accent);}
.hero .sub{font-size:clamp(17px,2.2vw,20px); color:var(--ink-soft); max-width:54ch; margin:0 0 34px;}
.hero .sub b{color:var(--ink); font-weight:600;}
/* hero rack: every system on the page as a unit list, each row a jump link.
   Desktop only, where the hero otherwise leaves its right half empty. */
.herogrid{display:grid; grid-template-columns:minmax(0,1fr); gap:48px; align-items:center;}
.rack{display:none;}
@media (min-width:1000px){
  .herogrid{grid-template-columns:minmax(0,1fr) 372px;}
  .rack.ready{display:block;}
}
.racklist{list-style:none; margin:0; padding:6px 0; font-family:var(--mono); font-size:11.5px;}
.racklist li{margin:0;}
.racklist a{display:grid; grid-template-columns:8px minmax(0,1fr) auto; gap:10px; align-items:center;
  padding:3.5px 14px; color:var(--ink-soft); text-decoration:none;}
.racklist a:hover,.racklist a:focus-visible{background:var(--accent-tint); color:var(--head); text-decoration:none;}
.racklist .led{width:7px; height:7px; border-radius:1px; background:var(--ok);}
.racklist .led.pre{background:var(--accent);} .racklist .led.rst{background:var(--warn);}
.racklist .nm{color:var(--ink); white-space:nowrap;}
.racklist a:hover .nm{color:var(--head);}
.racklist .kd{color:var(--ink-faint); font-size:10px; letter-spacing:.06em; text-transform:uppercase; white-space:nowrap;}
html[data-boot="up"] .rack .racklist li{animation:pwfade .4s ease both; animation-delay:calc(.7s + var(--i,0) * 45ms);}
@media (prefers-reduced-motion:reduce){html[data-boot="up"] .rack .racklist li{animation:none}}
.cta{display:flex; gap:14px; flex-wrap:wrap; align-items:center; margin-bottom:44px;}
.btn{font-family:var(--sans); font-size:15px; font-weight:600; cursor:pointer;
  padding:12px 22px; border-radius:var(--r2); border:1px solid var(--line-strong);
  background:transparent; color:var(--ink); text-decoration:none;}
.btn:hover{border-color:var(--accent); color:var(--accent); text-decoration:none;}
.btn.primary{background:var(--accent); border-color:var(--accent); color:var(--bg);}
.btn.primary:hover{filter:brightness(1.07); color:var(--bg);}

/* ── TylerOS boot + power-on theater ──
   boot.js gates the overlay (once per session, skippable, never on reduced
   motion, never over a deep link). The overlay only renders while <html>
   carries data-boot, which only boot.js sets: no-JS visitors never see it.
   .pw/.on is the scroll power-on that main.js arms. */
.boot{display:none;}
html[data-boot="hold"]{overflow:hidden;}
html[data-boot] .boot{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  position:fixed; inset:0; z-index:99; background:var(--bg); color:var(--ink);
  font-family:var(--mono); cursor:pointer;
}
.boot .bwrap{width:min(600px,86vw);}
.boot .bhead{margin:0 0 16px; font-size:12px; letter-spacing:.1em; color:var(--ink-faint); text-transform:uppercase;}
.boot .blog{min-height:230px;}
.boot .brow{display:flex; align-items:baseline; gap:10px; font-size:13px; line-height:2.1;}
.boot .brow .lb{white-space:nowrap;}
.boot .brow i{flex:1; border-bottom:1px dotted var(--line-strong); transform:translateY(-5px);}
.boot .brow b{font-weight:400; color:var(--ink-faint); min-width:2ch; text-align:right;}
.boot .brow.done b{font-weight:700; color:var(--ok);}
.boot .brow.fin{color:var(--ok); font-weight:700; margin-top:12px;}
.boot .brow.fin::after{content:"█"; color:var(--accent); margin-left:8px; animation:ezblink 1s steps(1) infinite;}
.boot .bskip{position:fixed; left:0; right:0; bottom:20px; text-align:center; font-size:10.5px; letter-spacing:.1em; color:var(--ink-faint); margin:0;}
.boot.lift{animation:bootlift .42s linear forwards; pointer-events:none;}
@keyframes bootlift{0%{opacity:1}28%{opacity:.25}44%{opacity:.85}100%{opacity:0; visibility:hidden}}
@media (max-width:700px){.boot .brow{font-size:11.5px} .boot .blog{min-height:200px}}

/* after the overlay lifts: the strip flickers on and the hero types in */
html[data-boot="up"] .strip{animation:pwflick .5s steps(1,end) both;}
html[data-boot="up"] .sysline{animation:pwtype .55s steps(28,end) both .18s;}
html[data-boot="up"] .hero h1{animation:pwfade .55s ease both .34s;}
html[data-boot="up"] .hero .sub{animation:pwfade .55s ease both .5s;}
html[data-boot="up"] .hero .cta{animation:pwfade .55s ease both .66s;}
@keyframes pwflick{0%{opacity:0}18%{opacity:.7}37%{opacity:.15}55%{opacity:.9}72%{opacity:.4}100%{opacity:1}}
@keyframes pwtype{from{clip-path:inset(-2px 100% -2px 0)}to{clip-path:inset(-2px 0 -2px 0)}}
@keyframes pwfade{from{opacity:0}to{opacity:1}}

/* scroll power-on: quiet by design (the card-level flicker was tried and
   looked like a strobe; Tyler killed it). The card itself never hides or
   flashes. What powers on is the small stuff: the mono stateline types
   itself in, its numbers count up (main.js), the window LED settles from
   warn to ok, and the section rule draws itself. */
.pw .stateline{clip-path:inset(-2px 100% -2px 0);}
.pw.on .stateline{animation:pwtype .65s steps(30,end) both;}
.pw .stateline.wrapped{clip-path:none; opacity:0;}
.pw.on .stateline.wrapped{animation:pwfade .6s ease both;}
.pw.on .win .bar:not(.restrict) .st{animation:pwled .8s steps(1,end) both;}
@keyframes pwled{0%,55%{background:var(--warn)}70%{background:var(--ok)}82%{background:var(--warn)}100%{background:var(--ok)}}
.seclabel.pw::after{transform:scaleX(0); transform-origin:left;}
.seclabel.pw.on::after{animation:pwline .8s ease .25s both;}
@keyframes pwline{to{transform:scaleX(1)}}

/* ── point cloud viewer ── */
.cloudwin{position:relative;}
.cloudwin canvas{display:block; width:100%; height:480px; background:var(--well); cursor:grab; touch-action:none;}
.cloudwin canvas:active{cursor:grabbing;}
@media (max-width:700px){.cloudwin canvas{height:340px}}
.hud{
  position:absolute; right:8px; top:42px; width:152px; padding:7px 8px;
  background:color-mix(in srgb,var(--panel) 88%,transparent); backdrop-filter:blur(6px);
  border:1px solid var(--line); border-radius:var(--r2);
  font-family:var(--mono); font-size:9px; color:var(--ink-soft);
}
.hud .hrow{display:flex; align-items:center; gap:5px; margin-bottom:5px;}
.hud label{flex:none; width:64px; letter-spacing:.02em; line-height:1.3; white-space:nowrap;}
.hud input[type=range]{flex:1; accent-color:var(--accent); min-width:0; height:10px;}
.hud .stat{color:var(--ink-faint); border-top:1px solid var(--line); padding-top:5px; margin-top:1px; line-height:1.6; font-size:8.5px;}
.hud .rbtn{width:100%; margin-top:5px; cursor:pointer; border:1px solid var(--line);
  background:transparent; color:var(--ink-soft); border-radius:var(--r1);
  font-family:var(--mono); font-size:9px; padding:2px 0;}
.hud .rbtn:hover{border-color:var(--accent); color:var(--accent);}
.hud.collapsed .hbody{display:none;}
.hud .htog{cursor:pointer; background:none; border:none; color:var(--ink-soft);
  font-family:var(--mono); font-size:9px; padding:0; width:100%; text-align:left; letter-spacing:.04em;}
.hud .htog:hover{color:var(--accent);}
@media (max-width:700px){.hud{width:132px; right:6px; top:40px}}
.hint{font-family:var(--mono); font-size:10.5px; color:var(--ink-faint); padding:6px 4px 0;}

/* ── sections ── */
section{padding:76px 0 0;}
.seclabel{font-family:var(--mono); font-size:12px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-soft); display:flex; align-items:center; gap:12px; margin-bottom:48px;}
.seclabel::after{content:""; flex:1; height:1px; background:var(--line);}
.seclabel .n{color:var(--accent);}

/* ── case blocks ── */
.case{display:grid; grid-template-columns:minmax(0,5fr) minmax(0,6fr); gap:44px; align-items:center; padding:38px 0;}
.case.flip{grid-template-columns:minmax(0,6fr) minmax(0,5fr);}
.case + .case{border-top:1px solid var(--line);}
.case.flip .txt{order:2;} .case.flip .exh{order:1;}
.case.wide{grid-template-columns:minmax(0,1fr);}
/* side-by-side cards: the exhibit window stretches to the height of the
   text beside it and its body takes the extra room, so a short demo never
   floats in a band of empty page. The text stays centered when the
   exhibit is the taller of the two. */
@media (min-width:841px){
  .case:not(.wide){align-items:stretch;}
  .case:not(.wide) > .txt{align-self:center;}
  .case:not(.wide) > .exh{display:flex; flex-direction:column;}
  .case:not(.wide) > .exh > .win:first-child{flex:1; display:flex; flex-direction:column;}
  .case:not(.wide) > .exh > .win:first-child > :not(.bar){flex:1;}
}
/* desktop: wide cards split their text into a head column and a body column
   instead of one full-width paragraph (the stretched-phone look) */
@media (min-width:841px){
  .case.wide .txt{display:grid; grid-template-columns:minmax(0,2fr) minmax(0,3fr); column-gap:44px; align-items:start;}
  .case.wide .txt .stateline{grid-column:1/-1;}
  /* heading + tag + side images are one grid item (.lsscol) so their own
     short content never has to share row-tracks with the long paragraphs
     in the body column, sharing a row track with a spanning paragraph
     forces that row tall, which used to leave a large gap under .tag
     before the images (a spanning column's height couples row heights
     across every column in that row, even a column with short content) */
  .case.wide .txt .lsscol{grid-column:1; grid-row:2 / span 8; align-self:start;}
  /* the other wide cards carry heading, tagline and stack chips in that
     same left column, so it is not a heading floating over blank space */
  .case.wide .txt .whead{grid-column:1; grid-row:2 / span 8; align-self:start;}
  .case.wide .txt .whead .chips{margin:6px 0 0 !important;}
  /* first paragraph sits beside the heading; any further ones stack under it */
  .case.wide .txt p.body{grid-column:2; max-width:66ch;}
  .case.wide .txt p.body:first-of-type{grid-row:2/span 2;}
  .case.wide .txt .chips{grid-column:2;}
}
@media (max-width:840px){
  .case,.case.flip{grid-template-columns:minmax(0,1fr); gap:22px}
  .case.flip .txt{order:1} .case.flip .exh{order:2}
}
.stateline{font-family:var(--mono); font-size:11.5px; letter-spacing:.1em; margin-bottom:14px; color:var(--ink-faint);}
.stateline .run{color:var(--ok); font-weight:700;}
.stateline .restrict{color:var(--warn); font-weight:700;}
.case h3{font-size:clamp(20px,2.8vw,30px); font-weight:600; letter-spacing:-.01em;
  color:var(--head); margin:0 0 6px; line-height:1.15;}
.case .tag{font-size:16px; color:var(--ink-soft); margin:0 0 16px; font-weight:500;}
.case p.body{margin:0 0 18px; font-size:15.5px;}
.case p.body b{color:var(--head); font-weight:600;}
.chips{display:flex; flex-wrap:wrap; gap:8px;}
.chip{font-family:var(--mono); font-size:11px; color:var(--ink-soft);
  border:1px solid var(--line); border-radius:var(--r1); padding:4px 9px; background:var(--bg-soft);}
.gate{margin-top:20px; border-left:3px solid var(--warn); background:var(--bg-soft);
  padding:12px 16px; font-size:14px; color:var(--ink-soft); max-width:60ch; border-radius:0 var(--r2) var(--r2) 0;}
.gate b{color:var(--warn);}

/* Geomatics ERP redacted window */
.redact{position:relative; background:var(--well); overflow:hidden;}
.skel{position:absolute; border-radius:var(--r2); background:var(--line); opacity:.7; filter:blur(2px);}
.redact .stamp{position:absolute; inset:0; display:flex; align-items:center; justify-content:center; transform:rotate(-9deg); z-index:2;}
/* a slow classification-scanner sweep over the blurred skeleton */
.redact::after{content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(105deg,transparent 42%,color-mix(in srgb,var(--ink) 8%,transparent) 50%,transparent 58%);
  transform:translateX(-70%); animation:redsweep 4.2s ease-in-out infinite;}
@keyframes redsweep{55%,100%{transform:translateX(70%)}}
@media (prefers-reduced-motion:reduce){.redact::after{animation:none; display:none}}
.redact .stamp span{
  font-family:var(--mono); font-weight:700; font-size:clamp(16px,2.6vw,24px); letter-spacing:.18em;
  color:var(--warn); border:3px double var(--warn); padding:10px 22px; border-radius:var(--r2);
  background:color-mix(in srgb,var(--bg) 55%,transparent); text-transform:uppercase; text-align:center;
}
.redact .foot{position:absolute; left:0; right:0; bottom:0; z-index:2; padding:8px 12px;
  font-family:var(--mono); font-size:10.5px; color:var(--ink-faint);
  background:color-mix(in srgb,var(--bg) 70%,transparent); border-top:1px dashed var(--line);}

/* ── two-up exhibit row for wide cases ── */
.exh2{display:grid; grid-template-columns:1fr 1fr; gap:18px; align-items:start;}
@media (max-width:840px){.exh2{grid-template-columns:1fr}}

/* ── Geomatics ERP architecture diagram ── */
.arch{background:var(--well); padding:10px 8px 6px; display:flex; align-items:center; justify-content:center;}
.arch svg{display:block; width:100%; max-height:100%; height:auto;}
.arch .abox{fill:var(--panel); stroke:var(--line-strong);}
.arch .asvc{fill:var(--bg-soft); stroke:var(--line);}
.arch .aline{stroke:var(--line-strong); stroke-width:1; fill:none;}
.arch .atxt{fill:var(--ink-soft); font-family:var(--mono); font-size:9.5px;}
.arch .atxt2{fill:var(--ink-faint); font-family:var(--mono); font-size:8px;}
.arch .adot{fill:var(--accent);}
/* knock the connector lines out from behind the services caption */
.arch .acapbg{fill:var(--well);}
/* hand-drawn style: wobble the diagram's rules so it matches the rest of the page */
:root[data-style="sketch"] .arch .aline,:root[data-style="sketch"] .arch .abox,
:root[data-style="sketch"] .arch .msvc .box,:root[data-style="sketch"] .arch .mroute{filter:url(#archSketch);}
/* packets: pk1/pk2 ride the live route into the selected service and pk3
   carries its write down to PostGIS (widgets.js sets those offset-paths on
   every selection); pk4/pk5 are ambient traffic to the rest of the rack */
.arch .apkt{offset-rotate:0deg; opacity:0; animation:apkt linear infinite;}
.arch .pk1{offset-path:path('M 350 48 L 350 70 L 20 70 L 20 99 L 27 99'); animation-duration:2.6s;}
.arch .pk2{offset-path:path('M 350 48 L 350 70 L 20 70 L 20 99 L 27 99'); animation-duration:2.6s; animation-delay:1.3s;}
.arch .pk3{offset-path:path('M 27 99 L 20 99 L 20 216 L 112 216 L 112 238'); animation-duration:2.8s; animation-delay:.9s;}
.arch .pk4{offset-path:path('M 350 48 L 350 70 L 515 70 L 515 84'); animation-duration:4.6s; animation-delay:1.9s; fill:var(--ink-faint);}
.arch .pk5{offset-path:path('M 405 190 L 405 216 L 284 216 L 284 238'); animation-duration:4.2s; animation-delay:.4s; fill:var(--ink-faint);}
@keyframes apkt{0%{offset-distance:0%; opacity:0}10%{opacity:1}88%{opacity:1}100%{offset-distance:100%; opacity:0}}
@supports not (offset-path:path('M 0 0 L 1 1')){.arch .apkt{display:none}}
@media (prefers-reduced-motion:reduce){.arch .apkt{animation:none; display:none}}

/* ── Geomatics ERP module explorer: full-width topology, inspector below ── */
.modfull{border-bottom:1px solid var(--line);}
@media (max-width:700px){
  .modfull{overflow-x:auto; -webkit-overflow-scrolling:touch; justify-content:flex-start;}
  .modfull svg{min-width:560px;}
}
.arch .msvc{cursor:pointer; transition:opacity .25s;}
.arch .msvc .box{fill:var(--panel); stroke:var(--line); transition:fill .2s,stroke .2s;}
.arch .msvc:hover .box{stroke:var(--line-strong);}
.arch .msvc.sel .box{fill:var(--accent-tint); stroke:var(--accent);}
.arch .msvc text{fill:var(--ink-soft); font-family:var(--mono); font-size:9.5px; font-weight:600; pointer-events:none;}
.arch .msvc.sel text{fill:var(--head); font-weight:700;}
.arch .msvc.dim{opacity:.22;}
.arch .msvc:focus{outline:none;}
.arch .msvc:focus-visible .box{stroke:var(--accent); stroke-width:1.6;}
/* the live route: gateway → bus → selected service, dashes flowing */
.arch .mroute{fill:none; stroke:var(--accent); stroke-width:1.5; stroke-dasharray:5 5; opacity:.9;
  animation:mflow 1.1s linear infinite;}
.arch .mroute.data{opacity:.45;}
@keyframes mflow{to{stroke-dashoffset:-20}}
@media (prefers-reduced-motion:reduce){.arch .mroute{animation:none}}
.modbar{display:flex; align-items:center; gap:10px 14px; flex-wrap:wrap; padding:10px 14px;
  border-bottom:1px solid var(--line);}
.modlegend{display:flex; flex-wrap:wrap; gap:6px;}
.modchip{cursor:pointer; font-family:var(--mono); font-size:11px; letter-spacing:.04em;
  padding:4px 10px; border-radius:var(--r1); background:var(--bg-soft); border:1px solid var(--line); color:var(--ink-soft);}
.modchip:hover{border-color:var(--line-strong);}
.modchip.on{border-color:var(--accent); color:var(--accent);}
.modchip .sw{display:inline-block; width:8px; height:8px; border-radius:1px; margin-right:6px; vertical-align:-1px;}
.mdnav{margin-left:auto; display:flex; gap:8px; align-items:center;}
.mdcount{font-family:var(--mono); font-size:11px; color:var(--ink-faint); margin-left:4px;}
.mdbody{display:grid; grid-template-columns:minmax(0,2fr) minmax(0,3fr); gap:8px 44px;
  padding:22px 24px 20px; min-height:200px; align-items:start;}
.mdbody.modswap{animation:modin .28s ease;}
@keyframes modin{from{opacity:0; transform:translateY(5px)}}
.mdcat{display:inline-flex; align-items:center; gap:7px; font-family:var(--mono); font-size:10px;
  font-weight:700; letter-spacing:.16em; text-transform:uppercase; color:var(--ink-faint); margin-bottom:12px;}
.mdcat .sw{width:9px; height:9px; border-radius:1px; flex:none;}
.mdbody h4{margin:0 0 8px; font-size:clamp(19px,2.4vw,26px); font-weight:700; letter-spacing:-.012em;
  color:var(--head); line-height:1.15;}
.mdrole{margin:0; font-size:15px; font-weight:600; color:var(--accent);}
.mddesc{margin:0 0 14px; font-size:15px; line-height:1.65; color:var(--ink-soft); max-width:66ch;}
.mdcaps{list-style:none; margin:0 0 16px; padding:0; font-family:var(--mono); font-size:11.5px;
  line-height:2; color:var(--ink-soft);}
.mdcaps li::before{content:"▸ "; color:var(--accent);}
.redwide{height:230px;}
@media (max-width:840px){
  .mdbody{grid-template-columns:1fr; gap:14px 0; min-height:0; padding:18px 16px 16px;}
  .mdrole{margin-bottom:2px;}
  .redwide{height:200px;}
}
@media (prefers-reduced-motion:reduce){.mdbody.modswap{animation:none}}

/* ── sanitized portal UI preview: lives in the geomatics_erp_ui window ── */
.uibody.uidemo{padding:14px 16px 16px; background:var(--panel); display:flex; flex-direction:column;}
/* one stage height for all eighteen previews, so switching services never
   moves the page: the mock frame stretches to fill whatever it does not use */
@media (min-width:841px){
  .uibody.uidemo{min-height:548px;}
  .mdbody{min-height:272px;}
}
.uibody.uidemo .mockwrap{flex:1; display:flex; flex-direction:column;}
.uibody.uidemo .mock{flex:1;}
.uibody.uidemo .mock-body{flex:1;}
/* a demo's main stage takes whatever height the fixed preview stage has
   left over, so short previews fill the frame instead of ending early */
@media (min-width:841px){
  /* basis 0: the stage takes exactly the room left in the frame, so a long
     side list scrolls inside it instead of stretching the frame. The fixed
     stages keep their old heights as floors; list stages size to content. */
  .uibody.uidemo .mock-body > [class*="-stage"],.uibody.uidemo .m-chat{flex:1 1 0px; height:auto;}
  .uibody.uidemo .m-gis-stage{min-height:322px;} .uibody.uidemo .m-etl-stage{min-height:172px;}
  .uibody.uidemo .m-vis-stage{min-height:190px;} .uibody.uidemo .m-bus-stage{min-height:152px;}
  .uibody.uidemo .m-chat{min-height:200px;}
  .uibody.uidemo .m-bus-chart{height:auto;}
  /* a canvas sized from its own box would grow that box on every redraw;
     pinned absolutely, it takes the panel's size and never feeds back */
  .uibody.uidemo .m-canpanel > .m-cv{position:absolute; inset:0; width:100%; height:100%;}
}
.mddemo-cap{font-family:var(--mono); font-size:10px; letter-spacing:.03em; color:var(--ink-faint);
  margin:0 0 10px; display:flex; align-items:center; gap:7px;}
.mddemo-cap::before{content:"◆"; color:var(--accent); font-size:8px;}
.mockwrap{border:1px solid var(--line); border-radius:var(--r3); overflow:hidden; background:var(--well);}
.mock{display:flex; flex-direction:column;}
.mock-bar{display:flex; align-items:center; gap:12px; padding:8px 12px; background:var(--chrome);
  border-bottom:1px solid var(--line); font-family:var(--mono); font-size:11px; color:var(--ink-soft);}
.mock-views{display:inline-flex; border:1px solid var(--line); border-radius:var(--r2); overflow:hidden;}
.mock-views .mv{cursor:pointer; border:none; background:transparent; color:var(--ink-soft);
  font-family:var(--mono); font-size:10.5px; padding:4px 12px; letter-spacing:.03em;}
.mock-views .mv+.mv{border-left:1px solid var(--line);}
.mock-views .mv.on{background:var(--accent); color:var(--bg);}
.mock-views .mv:not(.on):hover{color:var(--accent);}
.mock-title{color:var(--ink-faint); overflow:hidden; white-space:nowrap; text-overflow:clip;}
.mock-live{margin-left:auto; display:inline-flex; align-items:center; gap:6px; color:var(--ok); flex:none; letter-spacing:.04em;}
.mock-live .ld{width:7px; height:7px; border-radius:50%; background:var(--ok); animation:mklive 1.6s ease-in-out infinite;}
@keyframes mklive{0%,100%{opacity:.35}50%{opacity:1}}

/* board */
.mock-stage.board{display:flex; gap:9px; padding:12px; overflow-x:auto; -webkit-overflow-scrolling:touch;
  background:var(--bg-soft); align-items:flex-start;}
.kcol{flex:1 0 158px; min-width:158px; background:var(--well); border:1px solid var(--line);
  border-radius:var(--r3); padding:8px 8px 10px; transition:border-color .15s,background .15s;}
.kcol.kcol-over{border-color:var(--accent); background:var(--accent-tint);}
.kcol-head{display:flex; align-items:center; justify-content:space-between; font-family:var(--mono);
  font-size:10.5px; letter-spacing:.04em; color:var(--ink-soft); text-transform:uppercase; margin:0 2px 9px;}
.kcol-n{color:var(--ink-faint); background:var(--bg-soft); border:1px solid var(--line);
  border-radius:var(--rp); padding:0 7px; font-size:10px;}
.kcol-list{display:flex; flex-direction:column; gap:8px; min-height:26px;}
.kc{position:relative; background:var(--panel); border:1px solid var(--line); border-radius:var(--r3);
  padding:9px 10px 8px 13px; cursor:grab; touch-action:none; user-select:none;
  box-shadow:0 1px 2px rgba(0,0,0,.04);}
.kc::before{content:""; position:absolute; left:0; top:0; bottom:0; width:3px; border-radius:var(--r3) 0 0 var(--r3); background:var(--ink-faint);}
.kc.pri-high::before{background:var(--crit);}
.kc.pri-med::before{background:var(--warn);}
.kc.pri-low::before{background:var(--ok);}
.kc:hover{border-color:var(--line-strong);}
.kc-top{display:flex; align-items:center; justify-content:space-between; margin-bottom:5px;}
.kc-code{font-family:var(--mono); font-size:10px; color:var(--ink-faint); letter-spacing:.02em;}
.kc-type{font-family:var(--mono); font-size:9px; color:var(--ink-soft); background:var(--bg-soft);
  border:1px solid var(--line); border-radius:var(--r1); padding:1px 5px;}
.kc-title{font-size:12.5px; font-weight:600; color:var(--head); line-height:1.3; margin-bottom:7px;}
.kc-ctx{display:flex; flex-wrap:wrap; gap:4px 9px; margin-bottom:8px;}
.kc-cx{display:inline-flex; align-items:center; gap:4px; font-family:var(--mono); font-size:9.5px; color:var(--ink-soft);}
.kc-cx.ok{color:var(--ok);}
.kc-dot{width:6px; height:6px; border-radius:50%; flex:none;}
.kc-foot{display:flex; justify-content:flex-end;}
.kc-who{width:21px; height:21px; border-radius:50%; display:grid; place-items:center;
  font-family:var(--mono); font-size:9px; font-weight:700; color:var(--accent);
  background:var(--accent-tint); border:1px solid var(--accent);}
.kc.kc-flash{animation:kcflash 1.1s ease;}
@keyframes kcflash{0%{background:var(--accent-tint); border-color:var(--accent)}100%{background:var(--panel)}}
.kc.kc-drag{position:fixed; z-index:60; cursor:grabbing; box-shadow:0 10px 26px rgba(0,0,0,.28);
  transform:rotate(1.5deg); pointer-events:none; margin:0;}

/* list */
.mock-stage.list{padding:12px; background:var(--bg-soft); overflow-x:auto;}
.klist{min-width:520px; border:1px solid var(--line); border-radius:var(--r3); overflow:hidden; background:var(--panel);}
.klr{display:grid; grid-template-columns:82px minmax(0,1.6fr) 96px minmax(0,1.5fr); gap:12px;
  align-items:center; padding:8px 12px; border-bottom:1px solid var(--line); font-size:12px;}
.klr:last-child{border-bottom:none;}
.klh{font-family:var(--mono); font-size:9.5px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-faint); background:var(--well);}
.kl-code{font-family:var(--mono); font-size:11px; color:var(--ink-faint);}
.kl-title{color:var(--head); font-weight:600; overflow:hidden; white-space:nowrap; text-overflow:clip;
  display:flex; align-items:center; gap:7px;}
.kl-title em{font-style:normal; font-family:var(--mono); font-size:9px; color:var(--ink-soft);
  border:1px solid var(--line); border-radius:var(--r1); padding:1px 5px; flex:none;}
.pri-tick{width:7px; height:7px; border-radius:2px; flex:none; background:var(--ink-faint);}
.pri-tick.pri-high{background:var(--crit);} .pri-tick.pri-med{background:var(--warn);} .pri-tick.pri-low{background:var(--ok);}
.kl-stage{font-family:var(--mono); font-size:10.5px; color:var(--ink-soft);}
.kl-ctx{font-family:var(--mono); font-size:10px; overflow:hidden; white-space:nowrap; text-overflow:clip;}
.klr.kc-flash{animation:klflash 1.1s ease;}
@keyframes klflash{0%{background:var(--accent-tint)}100%{background:transparent}}

/* live feed footer */
.mock-feed{padding:7px 12px; background:var(--chrome); border-top:1px solid var(--line);
  font-family:var(--mono); font-size:10px; color:var(--ink-soft); min-height:15px; overflow:hidden;}
.mock-feed .fl{display:block; animation:mkfeed .4s ease;}
.mock-feed .fl.ok{color:var(--ok);} .mock-feed .fl.me{color:var(--accent);}
.mock-feed .fl::before{content:"› "; color:var(--ink-faint);}
@keyframes mkfeed{from{opacity:0; transform:translateX(-4px)}}
@media (prefers-reduced-motion:reduce){
  .mock-live .ld{animation:none} .kc.kc-flash,.klr.kc-flash,.mock-feed .fl{animation:none}
}

/* ══ shared demo toolkit: every sanitized portal preview composes these ══ */
.mock-body{padding:11px; background:var(--panel); display:flex; flex-direction:column; gap:9px;}
.mock-title{margin-right:auto;}
.m-tb{display:flex; align-items:center; gap:9px; flex-wrap:wrap;}
.m-note{font-family:var(--mono); font-size:10px; color:var(--ink-faint); line-height:1.45;}
.m-mono{font-family:var(--mono); font-variant-numeric:tabular-nums;}
.m-right{color:var(--ink-faint);}
.m-btn{cursor:pointer; border:1px solid var(--line-strong); background:transparent; color:var(--ink-soft);
  border-radius:var(--r2); font-family:var(--mono); font-size:10.5px; letter-spacing:.02em; padding:5px 11px;
  transition:border-color .15s,color .15s,background .15s;}
.m-btn:hover{border-color:var(--accent); color:var(--accent);}
.m-btn.on{border-color:var(--accent); color:var(--accent);}
.m-btn.prim{background:var(--accent); border-color:var(--accent); color:var(--bg);}
.m-btn.prim:hover{filter:brightness(1.07); color:var(--bg);}
.m-btn.wide{width:100%; text-align:center;}
.m-btn[disabled]{opacity:.6; cursor:default;}
.m-seg{display:inline-flex; border:1px solid var(--line); border-radius:var(--r3); overflow:hidden;}
.m-seg .m-btn{border:none; border-radius:0;}
.m-seg .m-btn+.m-btn{border-left:1px solid var(--line);}
.m-badge{display:inline-block; font-family:var(--mono); font-size:9px; letter-spacing:.02em; padding:1px 6px;
  border-radius:var(--rp); border:1px solid var(--line-strong); color:var(--ink-soft); white-space:nowrap;}
.m-badge.ok{color:var(--ok); border-color:color-mix(in srgb,var(--ok) 50%,transparent);}
.m-badge.warn{color:var(--warn); border-color:color-mix(in srgb,var(--warn) 50%,transparent);}
.m-badge.crit{color:var(--crit); border-color:color-mix(in srgb,var(--crit) 50%,transparent);}
.m-badge.mut{color:var(--ink-faint);}
.m-badge.ink{color:var(--ink-soft); background:var(--well);}
.m-side{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:8px 9px; overflow:auto; min-width:0;}
.m-side-h{font-family:var(--mono); font-size:9.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-faint); margin-bottom:7px;}
.m-side-f{font-family:var(--mono); font-size:9px; color:var(--ink-faint); margin-top:8px; line-height:1.45;}
.m-lrow{display:flex; align-items:center; gap:7px; padding:5px 2px; border-bottom:1px solid var(--line); font-size:11.5px; color:var(--ink-soft);}
.m-lrow:last-child{border-bottom:none;}
.m-lhead{font-family:var(--mono); font-size:9px; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-faint);}
.m-lname{flex:1; min-width:0; color:var(--head); font-weight:500; overflow:hidden; white-space:nowrap; text-overflow:clip;}
.m-lname b{font-weight:700;}
.m-empty{font-family:var(--mono); font-size:10px; color:var(--ink-faint); line-height:1.5; padding:6px 0;}
.m-canpanel{position:relative; background:var(--bg-soft); border:1px solid var(--line); border-radius:var(--r3); overflow:hidden; min-height:0;}
.m-cv{display:block; width:100%; height:100%;}
.m-prog{height:4px; background:var(--well); border-radius:var(--r1); overflow:hidden;}
.m-prog>i{display:block; height:100%; width:0; background:var(--accent); transition:width .12s linear;}
.m-in{font-family:var(--mono); font-size:11px; color:var(--head); background:var(--well); border:1px solid var(--line); border-radius:var(--r2); padding:6px 8px;}
.m-mini-btn{cursor:pointer; font-family:var(--mono); font-size:9.5px; color:var(--ink-soft); background:transparent; border:1px solid var(--line-strong); border-radius:var(--r2); padding:2px 8px;}
.m-mini-btn:hover{border-color:var(--accent); color:var(--accent);}
.m-scan{font-family:var(--mono); font-size:10px; color:var(--accent); padding:2px 0;}
.m-kpis{display:grid; grid-template-columns:repeat(3,1fr); gap:7px;}
.m-kpi{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:8px 10px; display:flex; flex-direction:column; gap:2px;}
.m-kv{font-size:17px; font-weight:700; color:var(--head); line-height:1.1;}
.m-kl{font-family:var(--mono); font-size:9px; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-faint);}
.m-mini{background:var(--panel); border:1px solid var(--line); border-radius:var(--r3); padding:4px 10px;}
.m-tabs{display:flex; gap:5px; flex-wrap:wrap;}
.m-tab{padding:4px 12px;}
.m-splitmap{display:grid; grid-template-columns:1.55fr 1fr; gap:9px; height:236px;}
.m-splitmap .m-canpanel,.m-splitmap .m-side{height:100%;}

/* gis: real Leaflet parcel map */
.m-gis-stage{display:grid; grid-template-columns:1.7fr 1fr; gap:9px; height:322px;}
.m-gis-stage .m-side{height:100%;}
.m-gis-map{height:100%; border:1px solid var(--line); border-radius:var(--r3); overflow:hidden; z-index:0;}
.leaflet-container{background:var(--bg-soft); font-family:var(--mono); font-size:11px;}
.leaflet-container a{color:var(--accent);}
.leaflet-bar a,.leaflet-bar a:hover{background:var(--panel); color:var(--ink-soft); border-bottom-color:var(--line);}
.leaflet-touch .leaflet-bar a{border-color:var(--line);}
.leaflet-control-attribution{background:color-mix(in srgb,var(--panel) 86%,transparent)!important; color:var(--ink-faint)!important; font-size:9px!important;}
.leaflet-control-attribution a{color:var(--accent)!important;}
.m-legend{display:flex; gap:12px; flex-wrap:wrap; font-family:var(--mono); font-size:9.5px; color:var(--ink-faint); align-items:center;}
.m-legend i{display:inline-block; width:10px; height:10px; border-radius:2px; margin-right:4px; vertical-align:-1px; border:1px solid var(--line-strong);}
/* gis: prior-job list rows, project cards, map markers */
.m-jrow{display:flex; align-items:center; gap:7px; width:100%; text-align:left; cursor:pointer; background:transparent; border:none; border-bottom:1px solid var(--line); padding:6px 2px; font-size:11.5px; color:var(--ink-soft);}
.m-jrow:last-child{border-bottom:none;}
.m-jrow:hover{background:color-mix(in srgb,var(--accent) 8%,transparent);}
.m-jrow.on{background:var(--accent-tint);}
.m-jrow .m-lname{color:var(--head);}
.m-jno{font-family:var(--mono); font-size:9.5px; color:var(--accent); letter-spacing:.02em; flex:none;}
.m-jno.big{font-size:15px; font-weight:700;}
.m-jcard{background:var(--well); border:1px solid var(--line); border-radius:var(--r3l); padding:9px 10px; margin-bottom:10px;}
.m-jc-top{display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:5px;}
.m-jc-name{font-size:13px; font-weight:700; color:var(--head); line-height:1.25; margin-bottom:8px;}
.m-jc-grid{display:grid; grid-template-columns:auto 1fr; gap:3px 10px; font-size:11px; align-items:center;}
.m-jc-grid span{font-family:var(--mono); font-size:9px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint);}
.m-jc-grid b{color:var(--ink-soft); font-weight:600;}
.m-jmk{filter:drop-shadow(0 1px 2px rgba(0,0,0,.55));}
.leaflet-tooltip{font-family:var(--mono); font-size:10px;}

/* gis / fleet / recon / geom crew + parcel side rows */
.m-crow{display:flex; align-items:center; gap:7px; width:100%; text-align:left; cursor:pointer; background:transparent; border:none; border-bottom:1px solid var(--line); padding:6px 2px; font-size:11.5px;}
.m-crow:last-child{border-bottom:none;}
.m-crow.on{background:var(--accent-tint);}
.m-crow .m-lname{color:var(--head);}
.m-arrow{color:var(--accent);}
.m-code-h{font-family:var(--mono); font-size:9px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint); margin:9px 0 4px;}

/* etl */
.m-etl-stage{display:grid; grid-template-columns:1.15fr 1fr; gap:9px; height:172px;}
.m-etl-stage .m-canpanel{height:100%;}
.m-ledger{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); overflow:auto; font-size:11px;}
.m-ledger .m-lrow{display:grid; grid-template-columns:44px 1fr 1fr 30px 42px; gap:6px; padding:3px 8px;}
.m-ledger .m-lhead{position:sticky; top:0; background:var(--well); color:var(--ink-faint);}

/* rag */
.m-chat{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:10px; height:200px; overflow:auto; display:flex; flex-direction:column; gap:8px;}
.m-msg{max-width:84%; font-size:12px; line-height:1.5; padding:7px 10px; border-radius:var(--r4);}
.m-msg.me{align-self:flex-end; background:var(--accent); color:var(--bg); border-bottom-right-radius:2px;}
.m-msg.bot{align-self:flex-start; background:var(--panel); border:1px solid var(--line); color:var(--ink-soft); border-bottom-left-radius:2px;}
.m-tool{display:inline-block; font-family:var(--mono); font-size:9px; color:var(--accent); background:var(--accent-tint); border:1px solid color-mix(in srgb,var(--accent) 40%,transparent); border-radius:var(--r1); padding:1px 6px; margin:0 4px 4px 0;}
.m-dots{display:inline-flex; gap:3px; vertical-align:middle;}
.m-dots i{width:5px; height:5px; border-radius:50%; background:var(--ink-faint); animation:mdot 1s infinite;}
.m-dots i:nth-child(2){animation-delay:.15s;} .m-dots i:nth-child(3){animation-delay:.3s;}
@keyframes mdot{0%,100%{opacity:.3}50%{opacity:1}}
.m-ans{color:var(--head); min-height:1em;}
.m-cite{margin-top:6px; font-family:var(--mono); font-size:9px; color:var(--ink-faint);}
.m-qbar{display:flex; flex-wrap:wrap; gap:6px;}
.m-qchip{cursor:pointer; text-align:left; font-size:10.5px; color:var(--ink-soft); background:var(--well); border:1px solid var(--line); border-radius:var(--r4l); padding:4px 10px;}
.m-qchip:hover{border-color:var(--accent); color:var(--accent);}

/* hub */
.m-hub-form{display:flex; flex-wrap:wrap; gap:8px; align-items:flex-end;}
.m-fld{display:flex; flex-direction:column; gap:3px; font-family:var(--mono); font-size:9px; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-faint);}
.m-hub-flow{background:var(--bg-soft); border:1px solid var(--line); border-radius:var(--r3); padding:12px; display:flex; flex-direction:column; align-items:center; gap:10px;}
.m-hub-src{font-family:var(--mono); font-size:10px; color:var(--accent); border:1px solid var(--accent); border-radius:var(--rp); padding:3px 12px; background:var(--accent-tint);}
.m-hub-fan{display:grid; grid-template-columns:repeat(2,1fr); gap:8px; width:100%;}
.m-node{display:flex; align-items:center; gap:8px; background:var(--panel); border:1px solid var(--line); border-radius:var(--r3); padding:8px 10px; font-size:11.5px; color:var(--ink-soft); opacity:.5; transition:opacity .3s,border-color .3s;}
.m-node.run{opacity:1; border-color:var(--warn);}
.m-node.done{opacity:1; border-color:color-mix(in srgb,var(--ok) 50%,transparent);}
.m-ndot{width:9px; height:9px; border-radius:2px; flex:none;}
.m-nst{margin-left:auto; font-family:var(--mono); font-size:9px; color:var(--ink-faint);}
.m-node.done .m-nst{color:var(--ok);}

/* vision */
.m-vis-stage{display:grid; grid-template-columns:1fr 1fr; gap:9px; height:190px;}
.m-vis-stage .m-canpanel{height:100%;}
.m-deed{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:9px; overflow:auto;}
.m-deed-h{font-family:var(--mono); font-size:9px; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-faint); margin-bottom:6px;}
.m-deed-l{font-family:var(--mono); font-size:10.5px; color:var(--ink-soft); line-height:1.6;}
.m-vtbl{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:4px 8px;}
.m-vtbl-h,.m-vrow{display:grid; grid-template-columns:24px 1fr 1fr; gap:8px; padding:3px 2px; font-size:11px; border-bottom:1px solid var(--line);}
.m-vtbl-h{font-family:var(--mono); font-size:9px; text-transform:uppercase; color:var(--ink-faint);}
.m-vrow{color:var(--ink-soft);}
.m-vrow:last-child{border-bottom:none;}
.m-vstats{display:flex; flex-wrap:wrap; gap:6px; padding:8px 2px 3px;}

/* field (phone) */
.m-field{align-items:center;}
.m-phone{width:232px; max-width:100%; border:1px solid var(--line-strong); border-radius:var(--r5); background:var(--panel); overflow:hidden; box-shadow:0 4px 18px rgba(0,0,0,.10);}
.m-ph-top{background:var(--chrome); border-bottom:1px solid var(--line); padding:9px 12px; font-family:var(--mono); font-size:10px; color:var(--ink-soft); text-align:center;}
.m-ph-map{position:relative; height:150px; background:var(--bg-soft);}
.m-ph-body{padding:11px; display:flex; flex-direction:column; gap:8px;}
.m-ph-note{font-family:var(--mono); font-size:10px; color:var(--ink-faint); text-align:center;}
.m-ph-drop{cursor:pointer; border:1px dashed var(--line-strong); background:var(--well); color:var(--ink-soft); border-radius:var(--r4); padding:12px; font-family:var(--mono); font-size:10.5px; text-align:center;}
.m-ph-drop:hover{border-color:var(--accent); color:var(--accent);}

/* job */
.m-job-pane{background:var(--bg-soft); border:1px solid var(--line); border-radius:var(--r3); padding:11px; min-height:172px;}
.m-job-map{height:150px;}
.m-photos{display:grid; grid-template-columns:repeat(6,1fr); gap:6px;}
.m-photo{aspect-ratio:1; border-radius:var(--r2); background:hsl(calc(var(--h)*1deg) 45% 62%); animation:mkfeed .3s ease;}

/* iam */
.m-iam-stage{display:grid; grid-template-columns:1fr 1fr; gap:9px;}
.m-sdot{width:8px; height:8px; border-radius:50%; flex:none; background:var(--ink-faint);}
.m-sdot.ok{background:var(--ok);}
.m-role{cursor:pointer; font-family:var(--mono); font-size:9.5px; color:var(--accent); background:var(--accent-tint); border:1px solid color-mix(in srgb,var(--accent) 40%,transparent); border-radius:var(--r2); padding:2px 8px;}
.m-role:hover{filter:brightness(1.06);}

/* vault */
.m-vault-list{display:flex; flex-direction:column; gap:7px;}
.m-vfile{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); overflow:hidden;}
.m-vhead{display:flex; align-items:center; gap:8px; width:100%; text-align:left; cursor:pointer; background:transparent; border:none; padding:8px 10px; font-size:12px; color:var(--head);}
.m-vcar{color:var(--ink-faint); font-size:10px;}
.m-vname{flex:1; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:clip;}
.m-vhist{border-top:1px solid var(--line); padding:6px 12px 9px;}
.m-vh-row{display:flex; justify-content:space-between; font-family:var(--mono); font-size:10px; color:var(--ink-soft); padding:3px 0;}
.m-vh-act{margin-top:5px;}

/* bus */
.m-bus-stage{display:grid; grid-template-columns:1.5fr 1fr; gap:9px; height:152px;}
.m-bus-chart{height:100%;}
.m-rank{font-family:var(--mono); font-size:10px; color:var(--ink-faint); width:14px; flex:none;}

/* bids */
.m-bids-pane{display:flex; flex-direction:column; gap:9px;}
.m-goal{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:10px 11px;}
.m-goal-l{font-family:var(--mono); font-size:9px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint); margin-bottom:6px;}
.m-goal-bar{height:8px; background:var(--bg-soft); border-radius:var(--r3); overflow:hidden;}
.m-goal-bar>i{display:block; height:100%; background:var(--accent);}
.m-riskbtn{align-self:flex-start;}
.m-risknote{display:flex; flex-wrap:wrap; gap:6px;}

/* cycle */
.m-search{width:100%;}
.m-cycle-list{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:6px 10px;}
.m-arch-h{margin-top:10px;}
.m-arch{opacity:.7;}

/* pulse */
.m-gauges{display:grid; grid-template-columns:repeat(4,1fr); gap:8px;}
.m-gauge{background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:8px 9px;}
.m-gauge-l{display:flex; justify-content:space-between; font-family:var(--mono); font-size:9.5px; color:var(--ink-soft); margin-bottom:5px;}
.m-gauge-bar{height:6px; background:var(--bg-soft); border-radius:var(--r2); overflow:hidden;}
.m-gauge-bar>i{display:block; height:100%; transition:width .5s ease;}
.m-pulse-stage{display:grid; grid-template-columns:1fr 1fr; gap:9px;}

/* gate */
.m-gate-top{font-family:var(--mono); font-size:10px; color:var(--ink-soft); background:var(--well); border:1px solid var(--line); border-radius:var(--r3); padding:7px 10px;}
.m-gate-hi{color:var(--ok); font-weight:600;}
.m-steps{display:flex; align-items:center; gap:4px;}
.m-step{display:flex; align-items:center; gap:6px; font-family:var(--mono); font-size:10px; color:var(--ink-faint); white-space:nowrap;}
.m-step-d{width:18px; height:18px; border-radius:50%; display:grid; place-items:center; border:1px solid var(--line-strong); font-size:9px; flex:none;}
.m-step.now{color:var(--head);} .m-step.now .m-step-d{border-color:var(--accent); color:var(--accent); background:var(--accent-tint);}
.m-step.done{color:var(--ink-soft);} .m-step.done .m-step-d{border-color:var(--ok); color:var(--ok);}
.m-step-line{flex:1; height:1px; background:var(--line); min-width:6px;}
.m-gate-stage{display:grid; grid-template-columns:1fr 1fr; gap:9px;}

/* narrow viewports: stack the two-column demo stages */
@media (max-width:560px){
  .m-splitmap,.m-etl-stage,.m-vis-stage,.m-bus-stage,.m-iam-stage,.m-pulse-stage,.m-gate-stage,.m-gis-stage{grid-template-columns:1fr; height:auto;}
  .m-splitmap .m-canpanel,.m-etl-stage .m-canpanel,.m-vis-stage .m-canpanel,.m-bus-chart{height:170px;}
  .m-gis-map{height:240px;}
  .m-hub-fan,.m-photos{grid-template-columns:repeat(3,1fr);}
  .m-gauges{grid-template-columns:repeat(2,1fr);}
}
@media (prefers-reduced-motion:reduce){
  .m-photo,.m-msg,.mock-body .fl{animation:none}
  .m-dots i{animation:none}
  .m-node,.m-gauge-bar>i,.m-prog>i,.m-goal-bar>i{transition:none}
}

/* ── equal-height exhibit bodies inside two-up rows ── */
.exbody{height:400px;}
@media (max-width:840px){.exbody{height:340px}}
/* aegis carries the recent-flows list under the device bars, so the pair runs taller */
.exbody.aegbody,.exbody.flowbody{height:486px;}
@media (max-width:840px){.exbody.aegbody{height:340px} .exbody.flowbody{height:auto}}

/* ── screenshot exhibit + lightbox ── */
.lightbox{position:fixed; inset:0; z-index:100; background:rgba(8,9,12,.9);
  display:none; align-items:center; justify-content:center; padding:28px; cursor:zoom-out;}
.lightbox.open{display:flex;}
.lightbox img{max-width:100%; max-height:100%; border-radius:var(--r2);}

/* ── bare metal host panel ── */
.hostbody{background:var(--well); padding:16px; font-family:var(--mono);
  display:flex; flex-direction:column; gap:11px; overflow:hidden;}
.hlbl{display:flex; justify-content:space-between; font-size:11px; color:var(--head); font-weight:700;}
.hbar{height:10px; background:var(--line-soft); border:1px solid var(--line); border-radius:2px;
  overflow:hidden; margin:4px 0 3px;}
.hbar i{display:block; height:100%; width:0; background:var(--ok); transition:width .8s;}
.hsub{display:flex; justify-content:space-between; font-size:9.5px; color:var(--ink-faint);}
.hnet{display:grid; grid-template-columns:1fr 1fr; gap:14px; border-top:1px solid var(--line); padding-top:11px;}
.hnet .side2{text-align:right;}
.hnl{display:block; font-size:9px; letter-spacing:.12em; color:var(--ink-soft);}
.hnv{display:block; font-size:13.5px; font-weight:700; margin-top:2px;}
.hnv.rx{color:var(--accent-hi);} .hnv.tx{color:var(--violet);}
/* area sparklines: one SVG per direction, stretched to the column */
.hspark{height:30px; margin-top:6px; color:var(--accent-hi);}
.hspark.tx{color:var(--violet);}
.hspark svg{display:block; width:100%; height:100%; overflow:visible;}
.hspark .ar{fill:currentColor; opacity:.16;}
.hspark .ln{fill:none; stroke:currentColor; stroke-width:1.4; vector-effect:non-scaling-stroke; stroke-linejoin:round;}
.hup{display:flex; justify-content:space-between; border-top:1px solid var(--line);
  padding-top:10px; font-size:10px; letter-spacing:.1em; color:var(--ink-soft); font-weight:700;}
.hup .ok{color:var(--ok);}

/* ── shard: map + live feed ── */
.shardgrid{display:grid; grid-template-columns:1.25fr .75fr; min-height:320px;}
@media (max-width:700px){.shardgrid{grid-template-columns:1fr}}
#shardCanvas{display:block; width:100%; height:100%; min-height:320px; background:var(--well);
  touch-action:none; cursor:grab;}
#shardCanvas:active{cursor:grabbing;}
.shardfeed{border-left:1px solid var(--line); background:var(--well); display:flex; flex-direction:column; min-height:320px;}
@media (max-width:700px){.shardfeed{border-left:none; border-top:1px solid var(--line); min-height:200px;}}
.shardfeed .fhead{font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-faint); padding:10px 12px 6px; display:flex; justify-content:space-between;}
.shardfeed .fhead .mode{color:var(--warn); font-weight:700;}
.shardfeed .fhead .mode.live{color:var(--ok);}
.shardevents{flex:1; overflow-y:auto; padding:0 12px 10px; font-family:var(--mono); font-size:11px;
  line-height:1.8; color:var(--ink-soft); max-height:290px;}
.shardevents .t{color:var(--ink-faint); margin-right:8px;}
.shardevents .who{color:var(--accent); font-weight:600;}
.shardevents .ev-combat{color:var(--violet);}
.shardevents .ev-trade{color:var(--ok);}
.shardevents .ev-death{color:var(--crit);}

/* ── telemetry exhibit: miniature of the real container-health cards ── */
.telbody{background:var(--well); padding:14px; display:flex; flex-direction:column;}
.telbody .tgrid{flex:none; align-content:start;}
.tgrid{display:grid; grid-template-columns:repeat(3,1fr); gap:8px; margin-bottom:12px;}
@media (max-width:420px){.tgrid{grid-template-columns:repeat(2,1fr)}}
.tcard{border:1px solid var(--line); border-radius:var(--r2); background:var(--panel);
  padding:8px 9px; font-family:var(--mono); font-size:10px;}
.tc-head{display:flex; align-items:center; gap:6px; margin-bottom:6px;}
.tdot{width:7px; height:7px; border-radius:50%; background:var(--ok); flex:none; transition:background .3s;}
.tcard.warn .tdot{background:var(--warn);}
.tcard.down .tdot{background:var(--crit);}
.tc-name{font-weight:700; color:var(--head); white-space:nowrap; overflow:hidden;}
.tc-up{margin-left:auto; color:var(--ink-faint); font-size:9.5px; flex:none;}
.tc-row{display:grid; grid-template-columns:24px 1fr 46px; gap:6px; align-items:center;
  color:var(--ink-faint); font-size:9px; margin:3px 0;}
.tc-row .tval{text-align:right; color:var(--ink-soft);}
.tmeter{height:3px; background:var(--line-soft); border-radius:2px; overflow:hidden;}
.tmeter i{display:block; height:100%; width:0; background:var(--accent); transition:width .6s;}
.tcard.down .tmeter i{width:0 !important;}
.tbadge{width:12px; height:12px; border-radius:50%; background:var(--warn); color:#1A1A1A;
  font-size:8.5px; font-weight:800; display:inline-flex; align-items:center; justify-content:center; flex:none;}
.tc-btns{display:flex; gap:6px; margin-top:7px; border-top:1px dashed var(--line); padding-top:7px;}
.tc-btns button{flex:1; font-family:var(--mono); font-size:9px; padding:3px 0; cursor:pointer;
  border:1px solid var(--line); background:var(--bg-soft); color:var(--ink-soft); border-radius:var(--r1);}
.tc-btns button:hover{border-color:var(--accent); color:var(--accent);}
.tellog{font-family:var(--mono); font-size:11px; line-height:1.8; color:var(--ink-soft);
  flex:1; min-height:86px; overflow:hidden; border-top:1px solid var(--line); padding-top:8px;
  display:flex; flex-direction:column; justify-content:flex-end;}
.tellog .t{color:var(--ink-faint); margin-right:8px;}
.tellog .lv{font-weight:700; margin-right:8px;}
.lv-i{color:var(--accent);} .lv-o{color:var(--ok);} .lv-w{color:var(--warn);}

/* ── aegis exhibit: stacked bandwidth graph + flow table ── */
.aegbody{background:var(--well); display:flex; flex-direction:column;}
.aegbody canvas{display:block; flex:1; width:100%; min-height:0;}
.aeglegend{display:flex; flex-wrap:wrap; gap:6px; padding:10px 12px; border-top:1px solid var(--line); flex:none;}
.aegchip{cursor:pointer; font-family:var(--mono); font-size:10px; letter-spacing:.04em;
  padding:3px 9px; border-radius:var(--r1); background:var(--panel); border:1px solid var(--line); color:var(--ink-soft);}
.aegchip:hover{border-color:var(--line-strong);}
.aegchip.off{opacity:.35;}
.aegchip.off .sw{background:var(--ink-faint) !important;}
.aegchip .sw{display:inline-block; width:8px; height:8px; border-radius:1px; margin-right:6px; vertical-align:-1px;}
.flowbody{background:var(--well); padding:14px; display:flex; flex-direction:column; font-family:var(--mono);}
.flowrows{display:flex; flex-direction:column; gap:10px; overflow:hidden;}
.flowrecent{flex:1; margin-top:14px; border-top:1px dashed var(--line); padding-top:10px; overflow:hidden; min-height:0;}
.flowrecent .frh{font-family:var(--mono); font-size:9.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-faint); margin-bottom:6px;}
.flowrecent .fr{display:grid; grid-template-columns:62px 104px minmax(0,1fr) 62px; gap:8px; font-family:var(--mono); font-size:10px;
  line-height:1.9; color:var(--ink-soft); animation:mkfeed .35s ease;}
.flowrecent .fd{color:var(--head); font-weight:700;} .flowrecent .fa{color:var(--accent);}
.flowrecent .fh{color:var(--ink-faint); overflow-wrap:anywhere;} .flowrecent .fs{text-align:right;}
.flowrow{display:grid; grid-template-columns:104px 1fr 64px; gap:10px; align-items:center; font-size:10.5px;}
.flowrow .fdev{color:var(--head); font-weight:700; overflow-wrap:anywhere;}
.flowrow .fapp{display:block; color:var(--ink-faint); font-size:9px; font-weight:400;}
.flowrow .frail{height:6px; border-radius:var(--r1); background:var(--line); overflow:hidden;}
.flowrow .frail i{display:block; height:100%; width:0; border-radius:var(--r1); background:var(--accent); transition:width .9s ease;}
.flowrow .fval{text-align:right; color:var(--ink-soft);}
.flowfoot{display:flex; justify-content:space-between; border-top:1px solid var(--line);
  padding-top:10px; margin-top:12px; font-size:10px; color:var(--ink-faint); flex:none;}
.flowfoot .z{color:var(--ok);}

/* ── palette town exhibit: working mini generator ── */
.palbody{display:flex; flex-direction:column;}
.palrow{display:flex; min-height:300px; flex:1;}
@media (max-width:700px){.palrow{height:220px}}
.palcol{flex:1; position:relative; border:none; padding:0 0 14px; cursor:pointer;
  display:flex; flex-direction:column; justify-content:flex-end; align-items:center; gap:8px;
  font-family:var(--mono); transition:flex .25s ease;}
.palcol:hover{flex:1.25;}
.palcol .palhex{font-size:11.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;}
.palcol .pallock{cursor:pointer; border:1px solid transparent; background:transparent; border-radius:var(--r1);
  font-family:var(--mono); font-size:9.5px; padding:2px 7px; opacity:0; transition:opacity .2s;}
.palcol:hover .pallock,.palcol .pallock.on{opacity:1;}
.palcol .pallock:hover{border-color:currentColor;}
.palbar{display:flex; gap:10px; align-items:center; padding:10px 12px; border-top:1px solid var(--line);}
.palbtn{cursor:pointer; border:1px solid var(--line); background:transparent; color:var(--ink-soft);
  border-radius:var(--r1); font-family:var(--mono); font-size:10.5px; padding:4px 10px; flex:none;}
.palbtn:hover{border-color:var(--accent); color:var(--accent);}
.palmsg{font-family:var(--mono); font-size:10px; color:var(--ink-faint); margin-left:auto;
  overflow:hidden; white-space:nowrap; text-overflow:clip;}
@media (max-width:520px){.palmsg{display:none}}

/* ── land survey simulator ── */
/* the two prototypes are served from /lss as their own pages and framed here.
   Same-origin only: nginx sets frame-ancestors 'self' and X-Frame-Options
   SAMEORIGIN for exactly this. Both frames arm lazily (see main.js). */
.lssframe{position:relative; height:460px; background:#0B100F;}
.lssframe.tall{height:540px; background:var(--well);}
.lssframe iframe{position:relative; z-index:1; width:100%; height:100%; border:0; display:block;}
.lssframe::after{content:'loading the site package'; position:absolute; inset:0; z-index:0;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--mono); font-size:11px; color:var(--ink-faint); letter-spacing:.08em;}
@media (max-width:700px){.lssframe{height:340px} .lssframe.tall{height:440px}}
/* captures from the running build: one hero, then a 2x2 */
.lssside{display:flex; flex-direction:column; gap:16px; margin:6px 0 22px;}
.lssside figure{margin:0; min-width:0; border:1px solid var(--line); border-radius:var(--r2);
  overflow:hidden; background:var(--well);}
.lssside img{width:100%; height:auto; display:block; cursor:zoom-in;}
.lssside figcaption{font-family:var(--mono); font-size:10.5px; line-height:1.65;
  color:var(--ink-faint); padding:9px 11px; border-top:1px solid var(--line);}

/* ── console ── */
.console-out{padding:14px 16px; height:220px; overflow-y:auto; font-size:12.5px; line-height:1.8;
  background:var(--well); font-family:var(--mono);}
.console-out .t{color:var(--ink-faint); margin-right:10px;}
.console-out pre{margin:2px 0; color:var(--accent); line-height:1.3; font-size:11px; overflow-x:auto;}
.lvl{display:inline-block; min-width:5ch; margin-right:10px; font-weight:600;}
.lvl.info{color:var(--accent);} .lvl.warn{color:var(--warn);} .lvl.dbg{color:var(--ink-faint);} .lvl.ok{color:var(--ok);}
.echo{color:var(--head);}
.console-in{display:flex; align-items:center; gap:10px; padding:10px 16px; border-top:1px solid var(--line);}
.console-in label{color:var(--accent); font-size:13px; white-space:nowrap; font-family:var(--mono);}
.console-in input{flex:1; background:transparent; border:none; color:var(--ink);
  font-family:var(--mono); font-size:13.5px; padding:4px 0;}
.console-in input::placeholder{color:var(--ink-faint);}

/* ── history + stack ── */
.hist{border-top:1px solid var(--line);}
/* scoped to .hist: the point cloud HUD also has .hrow rows, and these used to leak into it */
.hist .hrow{display:grid; grid-template-columns:170px 1fr; gap:30px; padding:20px 0; border-bottom:1px solid var(--line);}
@media (max-width:700px){.hist .hrow{grid-template-columns:1fr; gap:4px; padding:16px 0}}
.hist .hrow .yr{font-family:var(--mono); font-size:13px; color:var(--accent); padding-top:3px;}
.hist .hrow strong{display:block; font-size:16.5px; color:var(--head); font-weight:700;}
.hist .hrow span{color:var(--ink-soft); font-size:14.5px;}
.stackgrid{display:grid; grid-template-columns:repeat(3,1fr); gap:40px;}
@media (max-width:760px){.stackgrid{grid-template-columns:1fr; gap:26px}}
.stackcol h4{font-family:var(--mono); font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--accent); margin:0 0 14px; padding-bottom:10px; border-bottom:1px solid var(--line);}
.stackcol ul{list-style:none; margin:0; padding:0;}
.stackcol li{padding:4px 0; color:var(--ink); font-size:15px;}

/* ── basement ── */
#basement{display:none; margin-top:76px;}
#basement.reveal{display:block;}
#basement .box{border:1px dashed var(--warn); border-radius:var(--r3l); padding:28px 30px; background:var(--bg-soft);}
#basement h3{margin:0 0 6px; font-size:20px; color:var(--head); font-weight:600;}
#basement .blurb{color:var(--ink-soft); font-size:14px; margin:0 0 20px;}
#basement .egg{display:grid; grid-template-columns:170px 1fr; gap:20px; padding:14px 0; border-top:1px solid var(--line); align-items:start;}
@media (max-width:700px){#basement .egg{grid-template-columns:1fr; gap:4px}}
#basement .egg .nm{font-family:var(--mono); font-size:13px; font-weight:700; color:var(--warn);}
#basement .egg .ds{color:var(--ink-soft); font-size:14.5px;}
.spin{cursor:pointer; border:1px solid var(--warn); background:transparent; color:var(--warn);
  border-radius:var(--r1); font-family:var(--mono); font-size:11px; padding:4px 10px; margin-top:8px;}
.spin:hover{background:var(--warn); color:var(--bg);}
#plotout{font-family:var(--mono); font-size:12px; color:var(--head); margin-top:10px; min-height:1.5em; max-width:60ch;}

/* ── contours demo ── */
.ctbody{height:340px; display:flex; flex-direction:column; background:var(--panel-deep,var(--panel));}
.ctbody canvas{flex:1; min-height:0; width:100%; display:block;}
.ctexports{display:flex; gap:6px; flex-wrap:wrap; padding:10px 12px; border-top:1px solid var(--line);}
.ctexports span{font-family:var(--mono); font-size:10px; letter-spacing:.06em; padding:3px 8px;
  border:1px solid var(--line); border-radius:var(--r1); color:var(--ink-faint); opacity:.35; transition:opacity .4s, color .4s, border-color .4s;}
.ctexports span.on{opacity:1; color:var(--accent); border-color:var(--accent);}
.ctreport{height:340px; overflow:hidden; padding:10px 14px 12px; display:flex; flex-direction:column; gap:0;}
.ctrow{display:grid; grid-template-columns:130px 1fr auto; gap:10px; align-items:baseline;
  font-size:12.5px; line-height:1.45; padding:7px 0; border-bottom:1px solid var(--line); opacity:0; transform:translateY(4px);
  transition:opacity .45s, transform .45s;}
.ctrow.on{opacity:1; transform:none;}
.ctrow .k{font-family:var(--mono); font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-faint);}
.ctrow .v{color:var(--ink-soft);}
.ctrow .b{font-family:var(--mono); font-size:10px; padding:2px 7px; border-radius:var(--r1); font-weight:700;}
.ctrow .b.ok{color:var(--ok); border:1px solid var(--ok);}
.ctrow .b.warn{color:var(--warn); border:1px solid var(--warn);}
.ctrow .b.crit{color:var(--crit); border:1px solid var(--crit);}
.ctfoot{margin-top:auto; padding-top:10px; display:flex; justify-content:space-between; align-items:center; gap:10px;}
@media (max-width:700px){.ctbody{height:300px} .ctreport{height:auto; min-height:300px} .ctrow{grid-template-columns:104px 1fr auto}}

/* ── plotcheck demo ── */
.pcbody{padding:14px; display:flex; flex-direction:column; gap:12px; min-height:380px;}
.pcprog{height:4px; background:var(--line); border-radius:2px; overflow:hidden;}
.pcprog i{display:block; height:100%; width:0%; background:var(--accent); transition:width .5s;}
.pclog{font-family:var(--mono); font-size:11px; line-height:1.9; color:var(--ink-faint); min-height:76px;}
.pclog .st-a{color:var(--accent);} .pclog .st-ok{color:var(--ok);} .pclog .st-cut{color:var(--crit);}
.pcfind{border:1px solid var(--line); border-radius:var(--r2); padding:14px 16px; background:var(--bg-soft);
  opacity:0; transform:translateY(5px); transition:opacity .45s, transform .45s; min-height:150px;}
.pcfind.on{opacity:1; transform:none;}
.pcfind .fb{display:flex; gap:8px; align-items:center; margin-bottom:8px; flex-wrap:wrap;}
.pcfind .fb span{font-family:var(--mono); font-size:10px; font-weight:700; padding:2px 8px; border-radius:var(--r1);}
.pcfind .fb .kind{color:var(--accent); border:1px solid var(--accent);}
.pcfind .fb .sev-hi{color:var(--crit); border:1px solid var(--crit);}
.pcfind .fb .sev-md{color:var(--warn); border:1px solid var(--warn);}
.pcfind .fb .loc{color:var(--ink-faint); border:1px solid var(--line);}
.pcfind .fb .ver{color:var(--ok); border:1px solid var(--ok); margin-left:auto;}
.pcfind h5{margin:0 0 6px; font-size:14.5px; color:var(--head); font-weight:600;}
.pcfind .why{font-size:12.5px; color:var(--ink-soft); margin:0 0 10px;}
.pcfind blockquote{margin:0 0 6px; padding:6px 10px; border-left:2px solid var(--accent);
  font-size:12px; color:var(--ink-soft); font-style:italic; background:var(--panel);}
.pcfind blockquote .ch{font-family:var(--mono); font-size:9.5px; font-style:normal; color:var(--ink-faint); display:block; margin-bottom:2px;}
.pcbar{display:flex; align-items:center; gap:12px; margin-top:auto;}

/* ── webaesthetics demo: one mockup, six skins ── */
.wabody{padding:14px; display:flex; flex-direction:column; gap:12px; min-height:380px;}
.wastage{flex:1; display:flex; align-items:center; justify-content:center; border:1px solid var(--line);
  border-radius:var(--r2); padding:20px; transition:background .6s;}
.wapage{width:100%; max-width:340px; border-radius:6px; padding:22px 24px; text-align:center;
  transition:all .6s;}
.wahead{font-size:21px; font-weight:800; margin-bottom:4px; transition:all .6s;}
.wasub{font-size:12.5px; margin-bottom:16px; opacity:.85;}
.wabtns{display:flex; gap:10px; justify-content:center; margin-bottom:16px;}
.wabtn{font-size:12px; font-weight:700; padding:7px 14px; border-radius:6px; transition:all .6s; white-space:nowrap;}
.wacard{font-size:11px; padding:9px 12px; border-radius:6px; transition:all .6s;}
/* geocities 1996 */
.wa-geo{background:#008080;}
.wa-geo .wapage{background:#c0c0c0; color:#000; border:3px outset #fff; border-radius:0; font-family:"Times New Roman",serif;}
.wa-geo .wahead{color:#f00; text-decoration:underline; font-family:"Comic Sans MS","Times New Roman",cursive;}
.wa-geo .wabtn{background:#c0c0c0; color:#00e; border:2px outset #fff; border-radius:0; text-decoration:underline;}
.wa-geo .wacard{background:#ff0; color:#000; border:1px dashed #f0f; border-radius:0;}
/* web 2.0 glossy 2006 */
.wa-glossy{background:#eaf4fb;}
.wa-glossy .wapage{background:linear-gradient(#fff,#dcedf8); color:#333; border:1px solid #b5d2e6; border-radius:14px; box-shadow:0 2px 6px rgba(0,0,0,.15); font-family:"Lucida Grande",Verdana,sans-serif;}
.wa-glossy .wahead{color:#2a6fa8; text-shadow:0 1px 0 #fff;}
.wa-glossy .wabtn{background:linear-gradient(#8cc63f,#5a9e1b); color:#fff; border:1px solid #4c8517; border-radius:999px; text-shadow:0 -1px 0 rgba(0,0,0,.3); box-shadow:inset 0 1px 0 rgba(255,255,255,.5);}
.wa-glossy .wabtn.wa2{background:linear-gradient(#5fa8dd,#2a6fa8); border-color:#235e8f;}
.wa-glossy .wacard{background:#fff; color:#556; border:1px solid #cfe2ef; border-radius:10px;}
/* vaporwave 2015 */
.wa-vapor{background:linear-gradient(160deg,#2b1055,#7597de);}
.wa-vapor .wapage{background:linear-gradient(180deg,#ff71ce22,#01cdfe22), #1a0b3b; color:#fff; border:1px solid #ff71ce; border-radius:0; font-family:var(--mono);}
.wa-vapor .wahead{color:#01cdfe; text-transform:uppercase; letter-spacing:.25em; text-shadow:2px 2px 0 #ff71ce;}
.wa-vapor .wabtn{background:transparent; color:#ff71ce; border:1px solid #ff71ce; border-radius:0; letter-spacing:.1em;}
.wa-vapor .wabtn.wa2{color:#05ffa1; border-color:#05ffa1;}
.wa-vapor .wacard{background:#0d0524; color:#b967ff; border:1px solid #b967ff; border-radius:0;}
/* neubrutalism 2021 */
.wa-neub{background:#f5f1e8;}
.wa-neub .wapage{background:#fff; color:#111; border:3px solid #111; border-radius:10px; box-shadow:6px 6px 0 #111;}
.wa-neub .wahead{color:#111; letter-spacing:-.02em;}
.wa-neub .wabtn{background:#ffd23f; color:#111; border:3px solid #111; border-radius:8px; box-shadow:3px 3px 0 #111;}
.wa-neub .wabtn.wa2{background:#ff6b9d;}
.wa-neub .wacard{background:#a8e6cf; color:#111; border:3px solid #111; border-radius:8px;}
/* glassmorphism 2020 */
.wa-glass{background:linear-gradient(135deg,#5b3fa8,#2a7bb8,#d05fa0);}
.wa-glass .wapage{background:rgba(255,255,255,.18); color:#fff; border:1px solid rgba(255,255,255,.4); border-radius:18px; backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);}
.wa-glass .wahead{color:#fff;}
.wa-glass .wabtn{background:rgba(255,255,255,.28); color:#fff; border:1px solid rgba(255,255,255,.45); border-radius:12px;}
.wa-glass .wacard{background:rgba(255,255,255,.14); color:#f0eaff; border:1px solid rgba(255,255,255,.3); border-radius:12px;}
/* aurora gradient 2024 */
.wa-aurora{background:#0a0a12;}
.wa-aurora .wapage{background:radial-gradient(120% 90% at 20% 0%,#3b2a6d55,transparent 60%),radial-gradient(120% 90% at 90% 100%,#0e5f5a55,transparent 60%),#101018; color:#e8e8f2; border:1px solid #26263a; border-radius:16px;}
.wa-aurora .wahead{background:linear-gradient(90deg,#a78bfa,#5eead4); -webkit-background-clip:text; background-clip:text; color:transparent;}
.wa-aurora .wabtn{background:#e8e8f2; color:#101018; border:0; border-radius:999px;}
.wa-aurora .wabtn.wa2{background:transparent; color:#a78bfa; border:1px solid #3a3a55;}
.wa-aurora .wacard{background:#16161f; color:#9a9ab0; border:1px solid #26263a; border-radius:12px;}

/* the four catalog sites, 2x2 */
.wafrow{grid-column:1 / -1;}
.case:has(> .wafrow){row-gap:24px;}
.wafam{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:10px; margin-top:0;}
@media (max-width:840px){.wafam{grid-template-columns:1fr 1fr;}}
.wsite{display:flex; flex-direction:column; gap:3px; padding:12px 14px; border:1px solid var(--line);
  border-radius:var(--r3); background:var(--well); text-decoration:none;
  transition:border-color .15s, transform .15s;}
.wsite:hover{border-color:var(--accent); transform:translateY(-1px);}
.wsname{font-weight:700; color:var(--head); font-size:14px;}
.wsdom{font-family:var(--mono); font-size:10.5px; color:var(--accent);}
.wsd{font-size:12px; color:var(--ink-soft); line-height:1.4; margin-top:2px;}
.wsct{font-family:var(--mono); font-size:10.5px; color:var(--ink-faint); margin-top:auto; padding-top:4px;}
@media (max-width:480px){.wafam{grid-template-columns:1fr;}}

/* ── tallyman journal rows (mini card demo) ── */
.tmmini{display:flex; flex-direction:column; gap:10px;}
.tmtx{border:1px solid var(--line); border-radius:var(--r2); overflow:hidden; opacity:0; transform:translateY(5px); transition:opacity .4s, transform .4s;}
.tmtx.on{opacity:1; transform:none;}
.tmtx.tmold .row{background:var(--panel); padding:6px 12px; font-size:12px; color:var(--ink-soft);}
.tmtx .row{display:flex; justify-content:space-between; gap:10px; padding:8px 12px; font-size:13px; color:var(--ink); background:var(--bg-soft); align-items:baseline;}
.tmtx .row .cat{font-family:var(--mono); font-size:10px; color:var(--ink-faint); letter-spacing:.06em;}
.tmtx .row .amt{font-family:var(--mono); font-weight:700;}
.tmtx .row .amt.in{color:var(--ok);} .tmtx .row .amt.out{color:var(--ink);}
.tmtx .jl{display:grid; grid-template-columns:1fr auto auto; gap:4px 16px; padding:7px 12px; border-top:1px dashed var(--line);
  font-family:var(--mono); font-size:10.5px; color:var(--ink-faint);}
.tmtx .jl .dr,.tmtx .jl .cr{text-align:right; min-width:72px;}
.tmtx .jl .hdr{color:var(--ink-faint); opacity:.7; letter-spacing:.08em;}
.tmtrial{border-top:1px solid var(--line); padding-top:10px; display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap;
  font-family:var(--mono); font-size:11px; color:var(--ink-soft);}
.tmtrial b{color:var(--ok); font-weight:700;}
.tmbar{display:flex; align-items:center; gap:12px; margin-top:auto;}

/* ── mini cards: the smaller residents ── */
.minihead{font-family:var(--mono); font-size:11.5px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-faint); margin:44px 0 18px; padding-top:34px; border-top:1px solid var(--line);}
.minigrid{display:grid; grid-template-columns:1fr 1fr; gap:22px;}
@media (max-width:840px){.minigrid{grid-template-columns:1fr}}
.mini{border:1px solid var(--line); border-radius:var(--r2); background:var(--panel); padding:22px 24px;
  display:flex; flex-direction:column; gap:0; box-shadow:var(--shadow-win);}
.mini.mwide{grid-column:1 / -1;}
/* a wide mini on desktop reads as text beside its demo, not one long measure */
@media (min-width:841px){
  .mini.mwide.split{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); column-gap:34px; align-items:start;}
  .mini.mwide.split > *{grid-column:1;}
  .mini.mwide.split > .mdemo{grid-column:2; grid-row:1 / span 6; margin:0;}
}
.mini .stateline{margin-bottom:10px;}
.mini h4{margin:0 0 4px; font-size:19px; font-weight:600; letter-spacing:-.01em; color:var(--head);}
.mini .tag{font-size:14.5px; color:var(--ink-soft); margin:0 0 12px; font-weight:500;}
.mini .mbody{font-size:14px; color:var(--ink); margin:0 0 16px; line-height:1.65;}
.mini .mbody b{color:var(--head); font-weight:600;}
/* the demo sits on the card's floor, just above the chips, so every row of
   minis lines its demos up regardless of how long each body runs */
.mini .mdemo{flex:1 0 auto; display:flex; flex-direction:column;}
.mini .mdemo > *{flex:1 0 auto;}
/* inside a grown demo, the running tally or notes take the slack */
.tmmini .tmtrial{margin-top:auto;}
.salsa .snotes{flex:1;}
.mini .chips{margin-top:0;}
.mini .chips .chip{font-size:10.5px;}
.mdemo{border:1px solid var(--line); border-radius:var(--r2); background:var(--bg-soft); padding:12px 14px; margin:0 0 16px;}

/* softater mini: a mock app you can pin notes to */
.sfdemo{display:flex; flex-direction:column; gap:9px;}
.sfbar{display:flex; justify-content:space-between; gap:8px; flex-wrap:wrap; font-family:var(--mono); font-size:10px; color:var(--ink-faint);}
.sfbar .sfmode{color:var(--accent);}
.sfstage{position:relative;}
.sfapp{border:1px solid var(--line); border-radius:var(--r3); background:var(--panel); padding:9px 10px; display:flex; flex-direction:column; gap:8px; font-size:11.5px; cursor:crosshair; user-select:none;}
.sfapp header,.sfapp section,.sfapp ul{margin:0; padding:0; border:0; min-height:0;}
.sfapp .topbar{display:flex; justify-content:space-between; align-items:center; gap:8px; flex-wrap:wrap;}
.sfapp .brand{color:var(--head); font-weight:600;}
.sfapp .tabs{display:flex; gap:10px;} .sfapp .tab{color:var(--ink-faint); font-size:11px;}
.sfapp .kpis{display:grid; grid-template-columns:repeat(3,1fr); gap:6px;}
.sfapp .kpi{border:1px solid var(--line); border-radius:var(--r1); padding:5px 7px; display:flex; flex-direction:column;}
.sfapp .kpi .lbl{font-family:var(--mono); font-size:9.5px; color:var(--ink-faint);}
.sfapp .kpi .val{font-weight:600; font-size:15px; color:var(--head);} .sfapp .kpi .val.warn{color:var(--warn);}
.sfapp .jobs{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:3px;}
.sfapp .job{display:flex; justify-content:space-between; gap:8px; font-size:11px; color:var(--ink-soft);}
.sfapp .job em{font-style:normal; font-family:var(--mono); font-size:9.5px; color:var(--ink-faint);}
.sfapp .btn{align-self:flex-start; font:inherit; font-size:11px; padding:4px 10px; border-radius:var(--r1); border:1px solid var(--accent); background:var(--accent-tint); color:var(--accent); cursor:crosshair;}
.sfhover{position:absolute; border:1.5px dashed var(--accent); border-radius:3px; pointer-events:none; background:color-mix(in srgb,var(--accent) 8%,transparent);}
.sfpins{position:absolute; inset:0; pointer-events:none;}
.sfpin{position:absolute; width:16px; height:16px; border-radius:50%; background:var(--accent); color:var(--bg); font-family:var(--mono); font-size:9.5px; font-weight:700; display:flex; align-items:center; justify-content:center; box-shadow:0 1px 3px rgba(0,0,0,.25);}
.sfpin.gone{background:transparent; color:var(--accent); border:1.5px dotted var(--accent);}
.sfnotes{display:flex; flex-direction:column; gap:5px; min-height:232px;}   /* room for the four-pin tour, so pins never push the page */
.sfnote{display:grid; grid-template-columns:16px 1fr; gap:8px; font-size:11px; align-items:start;}
.sfnote .no{width:16px; height:16px; border-radius:50%; background:var(--accent); color:var(--bg); font-family:var(--mono); font-size:9.5px; font-weight:700; display:flex; align-items:center; justify-content:center;}
.sfnote .bd{display:flex; flex-direction:column; gap:1px; min-width:0;}
.sfnote b{color:var(--head); font-weight:600;}
.sfnote code{font-family:var(--mono); font-size:10px; color:var(--accent); overflow-wrap:anywhere;}
.sfnote .bx{font-family:var(--mono); font-size:9.5px; color:var(--ink-faint);}
.sfempty{font-family:var(--mono); font-size:10.5px; color:var(--ink-faint);}
.sfmd{margin:0; font-family:var(--mono); font-size:10px; line-height:1.6; color:var(--ink-soft); white-space:pre-wrap; overflow-wrap:anywhere; max-height:190px; overflow:auto;}
.sffoot,.sfoot{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.sfhint,.smeta{font-family:var(--mono); font-size:9.5px; color:var(--ink-faint);}

/* trope machine mini: genre chips + three stacked reels */
.trope{display:flex; flex-direction:column; gap:10px;}
.tgen{display:flex; gap:6px; flex-wrap:wrap;}
.tchip{cursor:pointer; font-family:var(--mono); font-size:10px; padding:3px 9px; border-radius:var(--rp); border:1px solid var(--line); background:transparent; color:var(--ink-soft);}
.tchip.on{border-color:var(--accent); color:var(--accent); background:var(--accent-tint); font-weight:700;}
.trl{display:flex; flex-direction:column; gap:6px;}
.treel{display:grid; grid-template-columns:1fr auto; gap:3px 10px; align-items:center; border:1px solid var(--line); border-radius:var(--r3); background:var(--panel); padding:7px 10px;}
.treel.on{border-color:var(--ok); box-shadow:inset 0 0 0 1px var(--ok);}
.treel .tcat{grid-column:1 / -1; font-family:var(--mono); font-size:9px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-faint);}
.treel .ttx{font-size:12.5px; line-height:1.4; color:var(--head);}
.treel .slk{margin-top:0;}
.treel.on .slk{border-color:var(--ok); color:var(--ok); font-weight:700;}

/* life app mini: desk row, markers, quick queries, context budget */
.lifeo{display:flex; flex-direction:column; gap:10px;}
.lcv{display:block; width:100%; height:210px; cursor:pointer;}
/* the canvas carries the office; the desk buttons below are the compact,
   keyboard-reachable roster for the same four agents */
.lifeo .ldesk{padding:6px 4px 5px;}
.lifeo .ldesk .lav,.lifeo .ldesk .lmk{display:none;}
.ldesks{display:grid; grid-template-columns:repeat(4,1fr); gap:6px;}
@media (max-width:480px){.ldesks{grid-template-columns:repeat(2,1fr)}}
.ldesk{position:relative; cursor:pointer; font:inherit; text-align:center; border:1px solid var(--line); border-radius:var(--r3); background:var(--panel); padding:10px 4px 7px; display:flex; flex-direction:column; align-items:center; gap:3px; color:var(--ink);}
.ldesk.sel{border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent);}
.ldesk.off{opacity:.62;}
.lav{width:26px; height:26px; border-radius:6px; background:var(--accent-tint); color:var(--accent); font-family:var(--mono); font-weight:700; font-size:12px; display:flex; align-items:center; justify-content:center; image-rendering:pixelated;}
.lnm{font-size:11px; font-weight:600; color:var(--head);}
.lst{font-family:var(--mono); font-size:9px; color:var(--ink-faint); display:flex; align-items:center; gap:4px;}
.lst i{width:6px; height:6px; border-radius:50%; background:var(--line-strong);} .lst i.on{background:var(--ok);}
.lmk{position:absolute; top:-7px; right:-5px; width:17px; height:17px; border-radius:4px; font-family:var(--mono); font-weight:700; font-size:11px; display:flex; align-items:center; justify-content:center; color:#17171A;}
.lmk.q{background:var(--warn);} .lmk.b{background:var(--crit); color:#fff;}
.lpanel{display:flex; flex-direction:column; gap:8px; min-height:112px;}
.lqq{display:flex; gap:6px; flex-wrap:wrap;} .lqq .palbtn{font-size:10.5px;}
.lthread{display:flex; flex-direction:column; gap:6px;}
.lb{font-size:11.5px; line-height:1.45; padding:6px 9px; border-radius:var(--r3); max-width:88%;}
.lb.me{align-self:flex-end; background:var(--accent-tint); color:var(--head);}
.lb.them{align-self:flex-start; background:var(--panel); border:1px solid var(--line); color:var(--ink);}
.lctx{display:grid; grid-template-columns:1fr auto; gap:3px 8px; font-family:var(--mono); font-size:9.5px; color:var(--ink-faint);}
.lctx .rail{grid-column:1 / -1; height:4px; background:var(--line); border-radius:2px; overflow:hidden;}
.lctx .rail i{display:block; height:100%; background:var(--accent);}

/* salsa slot machine mini: reels, locks, heat, pairings */
.salsa{display:flex; flex-direction:column; gap:10px;}
.srl{display:grid; grid-template-columns:repeat(auto-fit,minmax(86px,1fr)); gap:6px;}
.sreel{border:1px solid var(--line); border-radius:var(--r3); background:var(--panel); padding:8px 7px 7px; display:flex; flex-direction:column; align-items:center; gap:5px; text-align:center; transition:border-color .2s;}
.sreel.on{border-color:var(--ok); box-shadow:inset 0 0 0 1px var(--ok);}
.sreel .scat{font-family:var(--mono); font-size:9px; letter-spacing:.06em; color:var(--ink-faint); text-transform:uppercase;}
.sreel .snm{font-size:12.5px; font-weight:600; color:var(--head); line-height:1.25; min-height:2.5em; display:flex; align-items:center;}
.sheat{display:flex; gap:2px;} .sheat i{width:9px; height:4px; border-radius:2px; background:var(--line);}
.sheat i.f{background:var(--crit);} .sheat i.r{background:color-mix(in srgb,var(--crit) 45%,var(--line));}
.slk{cursor:pointer; margin-top:auto; font-family:var(--mono); font-size:9.5px; padding:2px 8px; border-radius:var(--r1); border:1px solid var(--line); background:transparent; color:var(--ink-soft);}
.sreel.on .slk{border-color:var(--ok); color:var(--ok); font-weight:700;}
.snotes{display:flex; flex-direction:column; gap:5px; min-height:52px;}
.snote{font-size:11px; line-height:1.5; color:var(--ink-soft); border-left:3px solid var(--line); padding:3px 0 3px 9px;}
.snote b{display:block; color:var(--head); font-weight:600; font-size:11px;}
.snote.pub{border-left-color:var(--ok);} .snote.inf{border-left-color:var(--accent);} .snote.cau{border-left-color:var(--warn);}
.snote.dim{font-family:var(--mono); font-size:10px; color:var(--ink-faint);}
.saudit{display:grid; grid-template-columns:repeat(4,1fr); gap:6px;}
.saudit span{border:1px solid var(--line); border-radius:var(--r3); background:var(--panel); padding:6px 8px;
  font-family:var(--mono); font-size:9.5px; color:var(--ink-faint); letter-spacing:.04em;}
.saudit b{display:block; font-size:15px; color:var(--head); font-weight:700; letter-spacing:0;}
@media (max-width:420px){.saudit{grid-template-columns:repeat(2,1fr)}}


/* ezunraid terminal */
.ezterm{font-family:var(--mono); font-size:11px; line-height:1.85; color:var(--ink-soft); min-height:118px;}
.ezterm .p{color:var(--ok); font-weight:700;}
.ezterm .d{color:var(--ink-faint);}
.ezterm .c{color:var(--accent);}
.ezterm .cur{display:inline-block; width:7px; height:12px; background:var(--accent); vertical-align:-2px; animation:ezblink 1s steps(1) infinite;}
@keyframes ezblink{50%{opacity:0}}
@media (prefers-reduced-motion:reduce){.ezterm .cur{animation:none}}

/* ── wenab full card: the plan screen ── */
.wbbody{padding:14px; display:flex; flex-direction:column; gap:12px; min-height:340px;}
.wbgrid{display:flex; flex-direction:column; gap:8px;}
.wbgroup{font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent); padding:6px 0 2px; border-bottom:1px solid var(--line);}
.wbrow{display:grid; grid-template-columns:96px 1fr auto auto; gap:10px; align-items:center; font-size:11.5px;}
.wbrow .nm{font-family:var(--mono); font-size:10.5px; color:var(--ink-soft); white-space:nowrap;}
.wbrow .rail{height:6px; background:var(--line); border-radius:var(--r1); overflow:hidden;}
.wbrow .rail i{display:block; height:100%; width:0%; background:var(--accent); border-radius:var(--r1); transition:width .3s ease;}
.wbrow .rail i.ok{background:var(--ok);} .wbrow .rail i.warn{background:var(--warn);}
.wbrow .val{font-family:var(--mono); font-size:9.5px; color:var(--ink-faint); text-align:right; min-width:118px;}
.wbrow .pill{font-family:var(--mono); font-size:9px; padding:2px 7px; border-radius:var(--r1); min-width:86px; text-align:center;
  border:1px solid var(--line); color:var(--ink-faint);}
.wbrow .pill.ok{border-color:var(--ok); color:var(--ok); font-weight:700;}
.wbbar{display:flex; align-items:center; gap:12px; margin-top:auto;}
@media (max-width:560px){.wbrow{grid-template-columns:82px 1fr auto} .wbrow .val{display:none}}

/* ── ezunraid full card: tabbed workbench ── */
.ezwb{display:flex; min-height:300px;}
.ezmain{flex:1; min-width:0; display:flex; flex-direction:column;}
/* the discovery sidebar: what the appdata walk found, paired to live containers */
.ezside{flex:none; width:176px; border-right:1px solid var(--line); background:var(--bg-soft); padding:10px 0;
  font-family:var(--mono); font-size:10.5px; display:flex; flex-direction:column;}
.ezside .ezh{padding:2px 12px 6px; font-size:9.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-faint);}
.ezside .ezh + .ezh,.ezside .ezp + .ezh{margin-top:10px;}
.ezside button{display:flex; align-items:center; gap:7px; width:100%; text-align:left; font:inherit; color:var(--ink-soft);
  background:none; border:none; padding:3px 12px; cursor:pointer;}
.ezside button:hover,.ezside button:focus-visible{background:var(--accent-tint); color:var(--head);}
.ezside button.on{color:var(--head); font-weight:700;}
.ezside .dt{width:6px; height:6px; border-radius:1px; background:var(--ok); flex:none;}
.ezside .ezp .dt{background:none; border:1px solid var(--ink-faint);}
@media (max-width:600px){.ezside{display:none}}
.eztabs{display:flex; gap:2px; padding:8px 10px 0; border-bottom:1px solid var(--line); flex-wrap:wrap;}
.eztab{font-family:var(--mono); font-size:10px; letter-spacing:.04em; padding:6px 12px; cursor:pointer;
  border:1px solid var(--line); border-bottom:none; border-radius:var(--r2) var(--r2) 0 0;
  background:var(--bg-soft); color:var(--ink-faint);}
.eztab.on{background:var(--panel); color:var(--head); border-color:var(--line-strong); font-weight:700;}
.ezpane{flex:1; padding:12px 14px; min-height:196px;}
.ezmain > .ezpane{flex:1;}

/* ── switchboard full card: interactive chat client ── */
.sbwrap{display:flex; min-height:340px; max-height:560px;}
.sbside{flex:none; width:132px; border-right:1px solid var(--line); padding:10px 0; background:var(--bg-soft); cursor:pointer;}
.sbch{display:flex; align-items:center; gap:6px; padding:7px 12px; font-family:var(--mono); font-size:10.5px;
  color:var(--ink-faint); letter-spacing:.02em;}
.sbch:hover{color:var(--ink-soft);}
.sbch.on{color:var(--head); background:var(--panel); font-weight:700; box-shadow:inset 2px 0 0 var(--accent);}
.sbchn{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.sbbadge{margin-left:auto; flex:none; background:var(--accent); color:var(--bg); font-size:9px; line-height:1;
  padding:2.5px 5.5px; border-radius:999px; font-weight:700;}
.sbmain{flex:1; min-width:0; display:flex; flex-direction:column; min-height:0;}
.sbmsgs{flex:1; min-height:0; overflow-y:auto; padding:12px 14px; display:flex; flex-direction:column; gap:8px;}
/* newest messages sit on the composer, like any chat client */
.sbmsgs > :first-child{margin-top:auto;}
.sbrow{font-family:var(--mono); font-size:11px; line-height:1.6; animation:mkfeed .35s ease; word-break:break-word;}
.sbauth{font-weight:700; margin-right:7px;}
.sbtxt{color:var(--ink-soft);}
.sbevent .sbevt{color:var(--ink-faint); font-style:italic;}
.sbsys{color:var(--warn); font-style:italic;}
.sbwait{padding:0 14px 6px; font-family:var(--mono); font-size:10px; color:var(--ink-faint); font-style:italic;}
.sbcomposer{display:flex; gap:8px; padding:10px 12px; border-top:1px solid var(--line); background:var(--bg-soft); flex:none;}
.sbhandle{width:64px; flex:none;}
.sbtext{flex:1; min-width:0;}
.sbhandle,.sbtext{font-family:var(--mono); font-size:11px; background:var(--panel); color:var(--ink);
  border:1px solid var(--line); border-radius:var(--r1); padding:6px 9px;}
.sbhandle:focus,.sbtext:focus{outline:none; border-color:var(--accent);}
.sbsend{cursor:pointer; border:1px solid var(--line); background:var(--accent); color:var(--bg);
  border-radius:var(--r1); font-family:var(--mono); font-size:10.5px; font-weight:700; padding:6px 14px; flex:none;}
.sbsend:hover{background:var(--accent-hi);}
.sbsend:disabled{opacity:.45; cursor:not-allowed; background:var(--ink-faint);}
@media (max-width:640px){.sbside{width:100px} .sbrow{font-size:10.5px} .sbhandle{width:52px}}


/* ── footer ── */
footer{margin-top:96px; border-top:1px solid var(--line); padding:60px 0 52px;}
footer .big{font-size:clamp(24px,4vw,42px); font-weight:600; letter-spacing:-.015em;
  color:var(--head); margin:0 0 14px; line-height:1.12;}
footer .big em{font-style:normal; color:var(--accent);}
footer p{color:var(--ink-soft); max-width:50ch; margin:0 0 24px;}
.mail{font-family:var(--mono); font-size:17px;}
.basefoot{display:flex; justify-content:space-between; align-items:center; gap:20px; flex-wrap:wrap;
  margin-top:52px; padding-top:20px; border-top:1px solid var(--line);
  font-family:var(--mono); font-size:11px; color:var(--ink-faint);}

@media (prefers-reduced-motion:reduce){
  .dot.live{animation:none}
  *{transition:none!important; scroll-behavior:auto!important}
  /* boot.js and main.js already skip the theater on reduced motion;
     these keep the page whole even if a stale class survives somewhere */
  .pw,.pw .stateline{opacity:1!important; clip-path:none!important; animation:none!important}
  .seclabel.pw::after{transform:scaleX(1)}
  html[data-boot] .boot{display:none}
}
