/* ═══════════════════════════════════════════════════════════════════════════
   ERP · CONSOLE SURFACE

   Colin, on this page: "our ERP page is CRAP. it doesnt look like cloud
   computing or showcase our advantage over other ERP's at all ... I want it to
   have KPI tiles and a complete futeristic look that is still grounded."

   He is right about the diagnosis and the second half of that sentence is the
   whole design. What was here was a well-typeset WHITE DOCUMENT with a dark
   hero on top — a page you would print. Every ERP this product competes with
   sells itself with a page that looks like a printed brochure, and the one
   thing WhiteOak has that they do not is that it is a live instrument: eight
   control totals proved from the postings at the moment you look. A page that
   reads like paper is arguing against itself.

   So the surface goes to a console: one deep field, light falling from two
   corners, a hairline grid you can only just see, and every band an instrument
   panel rather than a sheet of paper.

   AND THEN "STILL GROUNDED", WHICH IS THE HARDER HALF.

   Futuristic on a finance page has an obvious failure mode: invented numbers,
   fake dashboards, a chart of nothing. This page has neither a district's
   money on it nor a single figure that is not checkable in the repository —
   160 screens, 51 doors, 10 statutes, 8 controls, 118 doors on the database,
   63 tenanted tables. Every KPI tile below carries a figure somebody can go
   and count. The look is a console; the content is an inventory.

   Linked AFTER site-aurora.css, which paints a light field for the five other
   marketing pages. Those pages are unchanged: this block is scoped to
   body.erp-console and nothing else on the site carries that class.
   ═══════════════════════════════════════════════════════════════════════════ */

body.erp-console{
  --con-bg:    #05090F;
  --con-panel: rgba(255,255,255,.035);
  --con-hair:  rgba(255,255,255,.085);
  --con-hair2: rgba(255,255,255,.055);
  --con-ink:   #E8EFF4;
  --con-ink2:  rgba(232,239,244,.60);
  --con-ink3:  rgba(232,239,244,.38);
  --con-grn:   #12C776;
  --con-grn-d: #0A9E5C;
  --con-amb:   #E0A32E;
  background:var(--con-bg);
  color:var(--con-ink);
}

/* ── THE FIELD ─────────────────────────────────────────────────────────────
   Two light sources and a grid. Fixed to the viewport rather than the
   document, so the light stays where the light is instead of scrolling off
   after two screens — the same rule site-aurora.css follows on the light
   pages, for the same reason.

   The grid is at 3% and 44px. Any stronger and it reads as a table nobody can
   click; any weaker and the page is flat. It is what makes a dark background
   feel like a surface rather than an absence. */
body.erp-console::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(64% 48% at 4% -8%,   rgba(18,199,118,.13) 0%, transparent 62%),
    radial-gradient(58% 46% at 102% 6%,  rgba(46,120,190,.10) 0%, transparent 60%),
    radial-gradient(70% 55% at 50% 112%, rgba(18,199,118,.06) 0%, transparent 64%);
}
body.erp-console::after{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:
    linear-gradient(to right,  rgba(255,255,255,.030) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.030) 1px, transparent 1px);
  background-size:44px 44px;
  mask-image:radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 78%);
  -webkit-mask-image:radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 78%);
}
body.erp-console nav,
body.erp-console .lp-hero,
body.erp-console .eb-band,
body.erp-console .lp-cta,
body.erp-console footer,
body.erp-console .kpi-wrap{position:relative;z-index:1;}

/* ── EVERY BAND IS AN INSTRUMENT PANEL ─────────────────────────────────────
   The page already carried .dark and .deep variants of every component,
   written for the two bands that were dark. Making the field dark means the
   variants become the DEFAULT rather than the exception, which is why this
   costs a dozen selectors instead of a rewrite: the shapes were already there
   and only the light ones had to go. */
body.erp-console .eb-band,
body.erp-console .eb-band.tint,
body.erp-console .lp-body{background:transparent;}
body.erp-console .eb-band.dark,
body.erp-console .eb-band.deep{
  background:linear-gradient(180deg, rgba(255,255,255,.028) 0%, rgba(255,255,255,.012) 100%);
  border-top:1px solid var(--con-hair2);
  border-bottom:1px solid var(--con-hair2);
}
body.erp-console .eb-h2,
body.erp-console .lp-sec > h2{color:var(--con-ink);}
body.erp-console .eb-h2 em{color:var(--con-grn);}
body.erp-console .eb-sub,
body.erp-console .lp-sec p,
body.erp-console .lp-sec li{color:var(--con-ink2);}
/* ── AND THE SUB-HEADING NOBODY LISTED ─────────────────────────────────────
   h2, p and li were named; h3 was not, and h3 keeps `color:var(--text)` — the
   dark ink of the light pages. On the legal pages, whose bodies are mostly h3
   sub-headings over paragraphs, that is near-black on near-black: "Information
   you provide" and "Information collected automatically" were rendering at a
   luminance of 24 against a background of 9, which is invisible.

   Found by a contrast sweep rather than by looking: walk every element with
   text in it, resolve the background it actually sits on by climbing until
   something paints, and flag any pair closer than 28 points of luminance. It
   is the same shape of check as the light-tile sweep above and it belongs
   beside it — a dark-mode conversion fails by leaving ONE property behind, and
   the property it leaves behind is never the one you thought to look at. */
body.erp-console .lp-sec h3,
body.erp-console h3{color:var(--con-ink);}
body.erp-console .lp-sec b,
body.erp-console .lp-sec strong{color:var(--con-ink);}
body.erp-console .lp-index .lbl,
body.erp-console .lp-card .lbl{color:var(--con-ink3);}
body.erp-console .eb-eyebrow,
body.erp-console .lp-sec > .num{color:var(--con-grn);}
body.erp-console .eb-eyebrow::before{background:var(--con-grn);}

/* Cards: glass with a hairline, one radius, and a top edge that catches the
   light. No borders drawn as outlines — an outline is a drawing of a card and
   this is meant to be an object. */
body.erp-console .eb-c,
body.erp-console .lp-vow > div,
body.erp-console .eb-mono{
  background:var(--con-panel);
  border:1px solid var(--con-hair);
  border-radius:14px;
  box-shadow:0 1px 0 rgba(255,255,255,.055) inset,
             0 18px 40px -22px rgba(0,0,0,.9);
}
body.erp-console .eb-c .h,
body.erp-console .lp-vow .s,
body.erp-console .eb-list b{color:var(--con-ink);}
body.erp-console .eb-c .b,
body.erp-console .eb-mono,
body.erp-console .eb-list div{color:var(--con-ink2);}
body.erp-console .eb-list div{border-bottom-color:var(--con-hair2);}
body.erp-console .eb-c .tag,
body.erp-console .lp-vow .t{color:var(--con-grn);background:rgba(18,199,118,.10);border-color:rgba(18,199,118,.26);}
body.erp-console .lp-vow{background:transparent;border:none;gap:12px;}
body.erp-console .eb-mono b{color:var(--con-grn);}
body.erp-console .eb-quote,
body.erp-console .lp-note{
  background:rgba(18,199,118,.07);
  border:1px solid rgba(18,199,118,.20);
  border-left:3px solid var(--con-grn);
  border-radius:0 14px 14px 0;
  color:var(--con-ink);
}
body.erp-console .lp-sec a{color:var(--con-grn);border-bottom-color:rgba(18,199,118,.4);}
body.erp-console .lp-sec strong{color:var(--con-ink);}
body.erp-console .lp-sec > hr{border-top-color:var(--con-hair2);}
body.erp-console .lp-index a{color:var(--con-ink3);}
body.erp-console .lp-index a:hover{color:var(--con-ink);}

/* The statute table stops being a table on paper and becomes a readout. */
body.erp-console .st-tbl,
body.erp-console table{
  background:var(--con-panel);
  border:1px solid var(--con-hair);
  border-radius:14px;
  overflow:hidden;
  box-shadow:0 18px 40px -22px rgba(0,0,0,.9);
}
body.erp-console table thead th{
  background:rgba(255,255,255,.05);color:var(--con-ink3);
  border-bottom:1px solid var(--con-hair);
}
body.erp-console table td{
  color:var(--con-ink2);border-bottom:1px solid var(--con-hair2);background:transparent;
}
body.erp-console table tbody tr:hover td{background:rgba(255,255,255,.028);}
body.erp-console table td:first-child{color:var(--con-ink);}

/* ── KPI TILES ─────────────────────────────────────────────────────────────
   What was here was a five-figure strip 34 pixels tall: correct, and the first
   thing your eye skipped. A KPI tile has four parts and needs all four —
   the label that says what is being counted, the figure at a size you cannot
   ignore, ONE line saying why the figure matters, and a rule underneath it
   showing the figure against something. The fourth is what stops it being a
   poster: a number with nothing to compare it to is decoration.

   Six tiles, because five is a strip and eight is a dashboard. */
.kpi-wrap{padding:0 48px 8px;margin-top:-28px;}
.kpi{max-width:1100px;margin:0 auto;display:grid;
     grid-template-columns:repeat(3,1fr);gap:14px;}
.kpi-t{
  position:relative;background:linear-gradient(180deg, rgba(255,255,255,.055) 0%, rgba(255,255,255,.022) 100%);
  border:1px solid var(--con-hair);border-radius:16px;padding:16px 18px 14px;
  box-shadow:0 1px 0 rgba(255,255,255,.07) inset, 0 22px 48px -26px rgba(0,0,0,.95);
  overflow:hidden;
}
/* One hairline of the product's green along the top edge of every tile, fading
   out. It is the only decoration on the tile and it is what makes six of them
   read as one instrument rather than six boxes. */
.kpi-t::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:linear-gradient(90deg, rgba(18,199,118,.75) 0%, rgba(18,199,118,.10) 46%, transparent 78%);}
.kpi-t .k-l{font-family:var(--m);font-size:8.5px;letter-spacing:.19em;text-transform:uppercase;
  color:var(--con-ink3);margin-bottom:9px;display:flex;align-items:center;gap:7px;}
.kpi-t .k-v{font-family:var(--s);font-size:44px;line-height:1;letter-spacing:-1.4px;color:var(--con-ink);
  display:flex;align-items:baseline;gap:8px;}
.kpi-t .k-v u{text-decoration:none;font-family:var(--m);font-size:11px;letter-spacing:.06em;
  color:var(--con-ink3);}
.kpi-t.g .k-v{color:var(--con-grn);}
.kpi-t .k-s{font-size:12.5px;line-height:1.55;color:var(--con-ink2);margin-top:9px;}
/* The rule: a track and a fill. The fill is a PROPORTION somebody can check —
   8 of 8 controls holding is a full bar; 0 of 160 screens storing a figure is
   an empty one, which is the point being made. */
.kpi-t .k-bar{margin-top:12px;height:3px;border-radius:2px;background:rgba(255,255,255,.09);overflow:hidden;}
.kpi-t .k-bar i{display:block;height:100%;border-radius:2px;
  background:linear-gradient(90deg,var(--con-grn-d),var(--con-grn));}
.kpi-t .k-bar.empty i{background:rgba(255,255,255,.18);}
.kpi-t .k-f{font-family:var(--m);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--con-ink3);margin-top:7px;}

/* The live dot, which is the one thing on this page that moves. Two seconds,
   never faster: a fast pulse reads as an alarm and this is a heartbeat. */
.k-dot{width:6px;height:6px;border-radius:50%;background:var(--con-grn);
  box-shadow:0 0 0 0 rgba(18,199,118,.55);animation:kpulse 2.4s ease-out infinite;}
@keyframes kpulse{
  0%  {box-shadow:0 0 0 0 rgba(18,199,118,.5);}
  70% {box-shadow:0 0 0 7px rgba(18,199,118,0);}
  100%{box-shadow:0 0 0 0 rgba(18,199,118,0);}
}
@media(prefers-reduced-motion:reduce){.k-dot{animation:none;}}

/* ── THE HERO CARD ─────────────────────────────────────────────────────────
   Already the strongest object on the page. It gets the same glass and the
   same top edge as the tiles so the hero and the KPI band read as one
   instrument rather than a card above a strip. */
body.erp-console .lp-hero{background:transparent;border-bottom:none;}
body.erp-console .lp-card{
  background:linear-gradient(180deg, rgba(255,255,255,.06) 0%, rgba(255,255,255,.022) 100%);
  border:1px solid var(--con-hair);border-radius:18px;
  box-shadow:0 1px 0 rgba(255,255,255,.07) inset, 0 30px 70px -30px rgba(0,0,0,1);
  position:relative;overflow:hidden;
}
body.erp-console .lp-card::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:linear-gradient(90deg, rgba(18,199,118,.8) 0%, rgba(18,199,118,.12) 50%, transparent 82%);}
body.erp-console .lp-card .v{color:var(--con-grn);}
body.erp-console .lp-card .v.white{color:var(--con-ink);}
body.erp-console .lp-card .n{color:var(--con-ink2);}
body.erp-console .lp-row{border-bottom-color:var(--con-hair2);}
body.erp-console .lp-strip{display:none;}
body.erp-console .lp-stamp{background:rgba(255,255,255,.045);border-color:var(--con-hair);color:var(--con-ink2);}
body.erp-console .lp-stamp b{color:var(--con-ink);}

/* ── AND THE SHARED STYLESHEET PAINTS TILES WHITE ──────────────────────────
   Colin, pointing at the module list on this page: "fix this on the site."

   site-aurora.css gives every card-shaped thing on the site the same treatment
   — no border, one radius, altitude, and `background:rgba(255,255,255,.86)`.
   That is exactly right on the five LIGHT pages it was written for. On this
   page it painted `.eb-list > div` and `.tbl-wrap` white, and the console block
   above sets a light TEXT colour on them, so the module list rendered as nine
   pale pills with white text on them: unreadable, and the bold label clipped at
   the left edge by the `overflow:hidden` that comes with the tile shape.

   Every other card here was already overridden by name. These two were missed
   because they are the two that do not look like cards in the markup — a list
   of rows and a table wrapper — which is exactly why a blanket rule catches
   them and a hand-written override does not.

   The check that finds this class of defect is worth keeping: walk every
   element, compute the luminance of its resolved background, and flag anything
   light on a page that is meant to be dark. It found these two and nothing
   else, on both pages.

   AND WHY IT WAS NOT SEEN EARLIER. Every local render until now went through
   file://, where href="/site-aurora.css" resolves to the filesystem ROOT and
   the stylesheet silently does not load at all. The page looked right because
   half of its CSS was missing. These pages are served over http for checking
   now, which is how a browser actually gets them. */
body.erp-console .eb-list > div{
  background:transparent;border-radius:0;overflow:visible;
  -webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;
  border-bottom:1px solid var(--con-hair2);
}
body.erp-console .eb-list > div:last-child{border-bottom:none;}
body.erp-console .tbl-wrap{
  background:transparent;box-shadow:none;border:0;
  -webkit-backdrop-filter:none;backdrop-filter:none;
  border-radius:14px;overflow:hidden;
}
body.erp-console .lp-index{
  background:var(--con-panel);border:1px solid var(--con-hair);
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:0 18px 40px -22px rgba(0,0,0,.9);
}

/* ── AND A STRIPE PAINTED IN #FAFAFA IS INVISIBLE UNTIL THE PAGE GOES DARK ──
   .stbl and .ctbl stripe alternate rows with a near-white, which is a fifth of
   a shade on a white page and a wall of white on a dark one: the statute table
   came out as five unreadable white bands over five readable dark ones. Every
   dark-mode conversion has this defect in it somewhere — a colour chosen to be
   almost invisible against the OLD background is maximally visible against the
   new one. The stripe is what it was meant to be: barely there. */
body.erp-console .stbl tbody tr:nth-child(even) td,
body.erp-console .ctbl tbody tr:nth-child(even) td{background:rgba(255,255,255,.030);}
body.erp-console .stbl tbody tr,
body.erp-console .ctbl tbody tr{border-bottom-color:var(--con-hair2);}
body.erp-console .stbl thead th,
body.erp-console .ctbl thead th{background:rgba(255,255,255,.055);color:var(--con-ink3);}
body.erp-console .stbl td,
body.erp-console .ctbl td{color:var(--con-ink2);}
body.erp-console .stbl td:first-child,
body.erp-console .ctbl td:first-child{color:var(--con-ink);}

/* ── THE COMPARISON ────────────────────────────────────────────────────────
   Colin: the page "doesnt ... showcase our advantage over other ERP's at all."
   That was true, and it was a CONTENT gap rather than a visual one — the page
   explained what this product does and never once said what a district is
   living with instead. A business official reads the left column and
   recognises their Tuesday; that recognition is the whole argument.

   No vendor is named and none needs to be. Every line on the left is a
   PATTERN, not a product, and a reader who has run a district ERP will
   recognise every one of them. Naming a competitor would make it a fight
   about that competitor rather than about the pattern, and the pattern is
   what is wrong. */
.cmp{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:26px;}
.cmp-col{border:1px solid var(--con-hair);border-radius:16px;overflow:hidden;
  background:var(--con-panel);box-shadow:0 18px 44px -26px rgba(0,0,0,.95);}
.cmp-col.them{background:rgba(255,255,255,.018);}
.cmp-col.us{background:linear-gradient(180deg, rgba(18,199,118,.075) 0%, rgba(255,255,255,.022) 100%);
  border-color:rgba(18,199,118,.26);}
.cmp-h{padding:13px 18px;border-bottom:1px solid var(--con-hair);
  font-family:var(--m);font-size:9px;letter-spacing:.19em;text-transform:uppercase;
  display:flex;align-items:center;gap:8px;}
.cmp-col.them .cmp-h{color:var(--con-ink3);}
.cmp-col.us   .cmp-h{color:var(--con-grn);border-bottom-color:rgba(18,199,118,.22);}
.cmp-r{padding:13px 18px;border-bottom:1px solid var(--con-hair2);font-size:13.5px;
  line-height:1.6;color:var(--con-ink2);}
.cmp-r:last-child{border-bottom:none;}
.cmp-col.us .cmp-r{color:var(--con-ink);}
.cmp-r b{display:block;font-family:var(--m);font-size:8.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--con-ink3);margin-bottom:5px;font-weight:500;}
.cmp-col.us .cmp-r b{color:rgba(18,199,118,.7);}
@media(max-width:820px){ .cmp{grid-template-columns:1fr;} }

@media(max-width:980px){ .kpi{grid-template-columns:repeat(2,1fr);} }
@media(max-width:640px){
  .kpi-wrap{padding:0 24px 8px;margin-top:-16px;}
  .kpi{grid-template-columns:1fr;}
  .kpi-t .k-v{font-size:38px;}
}
