Files
geointel/frontend/src/styles/geointel-system.css
T
Jens b18e8460da
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s
Keep live analysis status clear on mobile maps
2026-08-01 13:03:42 +02:00

1650 lines
48 KiB
CSS

/* ============================================================================
GeoIntel designsysteem
----------------------------------------------------------------------------
Eén bron van waarheid voor tokens, layout en paneelchroom.
Achtergrond: de vijf oudere stylesheets definieerden dezelfde selectors
meerdere keren met tegenstrijdige waarden. Het scherpste voorbeeld was
.geo-explorer-layout, dat twaalf concurrerende grid-template-columns kreeg
uit vier bestanden. Omdat media queries geen specificiteit toevoegen, won
steeds de laatste onvoorwaardelijke regel en was al het responsieve werk
dode code.
Dit bestand wordt als laatste geladen en is leidend. Waar het een eigenschap
zet, is dat de geldende waarde. De breedtes gebruiken clamp() in plaats van
breakpoints, zodat één regel het hele desktopbereik dekt.
========================================================================== */
/* ---------------------------------------------------------------- tokens -- */
:root {
/* Merk. Diepe teal-groen, ontleend aan het GeoIntel-logo. */
--gi-brand-950: #06251f;
--gi-brand-900: #0a352d;
--gi-brand-800: #0d4a40;
--gi-brand-700: #0f6154;
--gi-brand-600: #12796a;
--gi-brand-500: #189384;
--gi-brand-300: #7fc9bd;
--gi-brand-100: #d8f0eb;
--gi-brand-50: #eef8f6;
/* Neutraal. Licht koel-groen getint zodat wit naast de kaart niet schreeuwt. */
--gi-ink-950: #101d1a;
--gi-ink-800: #22322e;
--gi-ink-600: #465954;
--gi-ink-400: #6b7e79;
--gi-ink-300: #8b9c97;
--gi-canvas: #f1f5f3;
--gi-surface: #ffffff;
--gi-surface-soft: #f8fbfa;
--gi-surface-sunken: #e9efec;
--gi-line: #dde6e3;
--gi-line-strong: #c3d2ce;
--gi-line-accent: #b6ded5;
/* Statuskleuren. Toegankelijk op wit, elk met een zachte achtergrond. */
--gi-ok: #1a7f5a;
--gi-ok-soft: #e4f5ed;
--gi-info: #2f6285;
--gi-info-soft: #e8f1f7;
--gi-warn: #9a5a18;
--gi-warn-soft: #fdf1e3;
--gi-danger: #a1332f;
--gi-danger-soft: #fdedec;
/* Typografische schaal, 1.2 ratio op een basis van 13px. */
--gi-text-3xs: 0.625rem;
--gi-text-2xs: 0.6875rem;
--gi-text-xs: 0.75rem;
--gi-text-sm: 0.8125rem;
--gi-text-md: 0.875rem;
--gi-text-lg: 1rem;
--gi-text-xl: 1.25rem;
--gi-text-2xl: 1.5rem;
--gi-text-3xl: 1.9rem;
--gi-leading-tight: 1.2;
--gi-leading-snug: 1.35;
--gi-leading-normal: 1.55;
/* Ruimte, 4px-grid. */
--gi-space-1: 0.25rem;
--gi-space-2: 0.5rem;
--gi-space-3: 0.75rem;
--gi-space-4: 1rem;
--gi-space-5: 1.25rem;
--gi-space-6: 1.5rem;
--gi-space-8: 2rem;
--gi-space-10: 2.5rem;
/* Vorm. Eén schaal; de oude sheets wisselden tussen 4px en 24px. */
--gi-radius-xs: 4px;
--gi-radius-sm: 6px;
--gi-radius-md: 10px;
--gi-radius-lg: 14px;
--gi-radius-pill: 999px;
/* Hoogte. Drie niveaus, zacht en groen getint. */
--gi-shadow-xs: 0 1px 2px rgba(6, 37, 31, 0.06);
--gi-shadow-sm: 0 2px 8px rgba(6, 37, 31, 0.07);
--gi-shadow-md: 0 12px 28px rgba(6, 37, 31, 0.1);
--gi-shadow-lg: 0 24px 60px rgba(6, 37, 31, 0.16);
/* Beweging. */
--gi-ease: cubic-bezier(0.32, 0.72, 0.32, 1);
--gi-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--gi-dur-1: 120ms;
--gi-dur-2: 220ms;
--gi-dur-3: 420ms;
/* Shell-maten. De zijbalk is een icoonrail: 216px voor een handvol
werkbladen was verspilde breedte in een kaartgereedschap. */
--gi-sidebar-w: 4.75rem;
--gi-topbar-h: 3.25rem;
--gi-focus-ring: 0 0 0 2px var(--gi-surface), 0 0 0 4px var(--gi-brand-500);
/* Aliassen zodat de bestaande stylesheets meelopen met het nieuwe palet
in plaats van hun eigen, afwijkende waarden te blijven gebruiken. */
--atlas-canvas: var(--gi-canvas);
--atlas-surface: var(--gi-surface);
--atlas-surface-soft: var(--gi-surface-soft);
--atlas-ink: var(--gi-ink-950);
--atlas-ink-soft: var(--gi-ink-800);
--atlas-muted: var(--gi-ink-400);
--atlas-line: var(--gi-line);
--atlas-line-strong: var(--gi-line-strong);
--atlas-primary: var(--gi-brand-700);
--atlas-primary-strong: var(--gi-brand-800);
--atlas-primary-soft: var(--gi-brand-50);
--atlas-950: var(--gi-brand-950);
--atlas-900: var(--gi-brand-900);
--atlas-800: var(--gi-brand-800);
--atlas-700: var(--gi-brand-700);
--atlas-600: var(--gi-brand-600);
--atlas-500: var(--gi-brand-500);
--atlas-100: var(--gi-brand-100);
--atlas-50: var(--gi-brand-50);
--ink-950: var(--gi-ink-950);
--ink-700: var(--gi-ink-600);
--ink-500: var(--gi-ink-400);
--canvas: var(--gi-canvas);
--paper: var(--gi-surface);
--paper-muted: var(--gi-surface-soft);
--atlas-shadow-xs: var(--gi-shadow-xs);
--atlas-shadow-sm: var(--gi-shadow-sm);
--atlas-shadow-md: var(--gi-shadow-md);
--atlas-shadow-floating: var(--gi-shadow-lg);
--atlas-radius: var(--gi-radius-sm);
--atlas-radius-sm: var(--gi-radius-sm);
--atlas-radius-md: var(--gi-radius-md);
--atlas-radius-lg: var(--gi-radius-lg);
--atlas-radius-xl: var(--gi-radius-lg);
}
/* ------------------------------------------------------------ typografie -- */
.workbench-shell {
color: var(--gi-ink-950);
font-size: var(--gi-text-sm);
line-height: var(--gi-leading-normal);
font-synthesis-weight: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
.workbench-shell :where(h1, h2, h3, h4, h5) {
margin: 0;
color: var(--gi-ink-950);
line-height: var(--gi-leading-tight);
letter-spacing: -0.011em;
text-wrap: balance;
}
.workbench-shell :where(p) {
line-height: var(--gi-leading-snug);
text-wrap: pretty;
}
/* Tekst brak per letter af zodra een kolom smal werd. Alleen echt lange,
onbreekbare strings (URL's, bestandspaden, NIS-codes) mogen hard breken;
normale zinnen breken op woordgrenzen. */
.workbench-shell :where(p, span, small, strong, li, td, th, h1, h2, h3, h4, h5) {
overflow-wrap: break-word;
word-break: normal;
}
.workbench-shell :where(code, .gi-mono, [data-mono]) {
overflow-wrap: anywhere;
font-variant-numeric: tabular-nums;
}
/* Cijfers in tabellen en meetwaarden mogen niet dansen bij verversing. */
.workbench-shell :where(td, .metric-value, .geo-metric strong, [data-numeric]) {
font-variant-numeric: tabular-nums;
}
/* Eyebrow-labels: klein, opgesloten, maar leesbaar gespatieerd. */
.workbench-shell :where(.gi-eyebrow, .context-bar > div > span) {
color: var(--gi-ink-400);
font-size: var(--gi-text-3xs);
font-weight: 700;
letter-spacing: 0.09em;
text-transform: uppercase;
}
/* ------------------------------------------------------------ app-shell -- */
.workbench-layout {
display: grid;
grid-template-columns: var(--gi-sidebar-w) minmax(0, 1fr);
min-height: 100dvh;
background: var(--gi-canvas);
}
.workbench-sidebar {
display: flex;
flex-direction: column;
min-width: 0;
gap: var(--gi-space-2);
padding: var(--gi-space-3) var(--gi-space-2);
background: linear-gradient(180deg, var(--gi-brand-950), var(--gi-brand-900) 55%, #08302a);
color: #e8f4f1;
}
/* Merkzone: alleen het beeldmerk in de rail; de woordmerk-tekst verdwijnt. */
.workbench-sidebar .sidebar-brand {
display: grid;
gap: 0;
place-items: center;
padding: var(--gi-space-1) 0 var(--gi-space-3);
}
.workbench-sidebar .sidebar-brand :where(p, small, span:not([class])) {
display: none;
}
/* Navigatie-item: icoon boven, label eronder, alles gecentreerd. */
.workbench-sidebar .nav-item {
display: grid;
gap: 3px;
place-items: center;
width: 100%;
min-height: 0;
padding: var(--gi-space-2) var(--gi-space-1);
border: 0;
border-radius: var(--gi-radius-sm);
background: transparent;
color: #b9d8d1;
text-align: center;
cursor: pointer;
}
.workbench-sidebar .nav-item > :where(span, svg, i) {
flex: 0 0 auto;
}
.workbench-sidebar .nav-item :where(small, span:last-child) {
font-size: var(--gi-text-3xs);
font-weight: 650;
letter-spacing: 0.04em;
line-height: 1.15;
text-transform: uppercase;
}
.workbench-sidebar .nav-item:hover {
background: rgba(255, 255, 255, 0.08);
color: #ffffff;
}
.workbench-sidebar .nav-item[aria-current],
.workbench-sidebar .nav-item.is-active {
background: rgba(255, 255, 255, 0.14);
color: #ffffff;
box-shadow: inset 2px 0 0 var(--gi-brand-300);
}
/* De ITWorx-ondertekening past niet in een rail van 76px. */
.workbench-sidebar .itworx-signature {
justify-items: center;
padding-top: var(--gi-space-2);
font-size: var(--gi-text-3xs);
}
.workbench-sidebar .itworx-signature :where(p, small) {
display: none;
}
.workbench-sidebar nav {
display: flex;
flex: 1 1 auto;
flex-direction: column;
justify-content: flex-start;
min-height: 0;
gap: 2px;
overflow-y: auto;
overscroll-behavior: contain;
}
/* De navigatiegroep stond onderaan de zijbalk: een oude regel gaf de laatste
groep margin-top: auto, wat in deze flexkolom uitkwam op 769px. De selector
moet de specificiteit van die regel evenaren om hem te overschrijven. */
.workbench-sidebar nav > .nav-group,
.workbench-sidebar nav > .nav-group:last-child {
margin-block: 0;
align-content: start;
}
.workbench-stage {
display: grid;
grid-template-rows: auto auto minmax(0, 1fr);
min-width: 0;
min-height: 100dvh;
}
/* Drie zones: context (rekt mee), gezondheidsindicator, sessie. Een flexrij
liet de contextbalk inklappen tot één kolom van 198px met vier gestapelde
rijen; een expliciet raster met minmax(0, 1fr) houdt de rij op één regel. */
.workbench-topbar {
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
gap: var(--gi-space-4);
align-items: center;
min-height: var(--gi-topbar-h);
padding: var(--gi-space-2) var(--gi-space-5);
border-bottom: 1px solid var(--gi-line);
background: var(--gi-surface);
}
.workbench-topbar > * {
min-width: 0;
}
/* Het werkgebied vult wat er over is in plaats van te rekenen met vaste
hoogtes. De oude opbouw verbruikte 317px aan koppen, banners en padding
voordat de kaart begon — een kwart van het venster. */
.workbench-content {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
padding: var(--gi-space-3);
overflow: auto;
}
.workbench-content > * {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0;
padding: var(--gi-space-3) var(--gi-space-4) var(--gi-space-4) !important;
}
.workspace-persistent-map {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0;
gap: var(--gi-space-3);
}
/* Paginakop compacter: titel en toelichting dichter op elkaar, minder lucht
eronder. De actieknoppen staan al rechts uitgelijnd. */
.workspace-heading h2,
.workbench-content h2 {
font-size: var(--gi-text-xl);
letter-spacing: -0.015em;
}
.workspace-heading > p,
.workspace-heading-actions > p {
margin-top: 2px;
color: var(--gi-ink-400);
font-size: var(--gi-text-xs);
}
/* Het werkblad vult de resterende hoogte. */
.geo-explorer {
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: var(--gi-space-2);
min-height: 0;
}
/* Paginakop op één rij: titel en toelichting links, moduskeuze rechts.
Als blok kostte de kop samen met de melding 149px verticale ruimte op een
venster van 1215px — een kwart van het scherm voordat de kaart begon. */
.geo-explorer-header,
.workbench-shell-guest .geo-explorer-header {
display: flex;
flex: 0 0 auto;
flex-flow: row wrap;
gap: var(--gi-space-2) var(--gi-space-5);
align-items: center;
justify-content: space-between;
/* De oude sheets hielden deze kop op 5.25rem (gast) tot 6rem (operator),
ongeacht de inhoud. De hoogte volgt nu de tekst. */
min-height: 0;
padding: var(--gi-space-2) var(--gi-space-3);
}
.geo-explorer-header > div:first-child {
display: flex;
flex: 1 1 22rem;
flex-flow: row wrap;
gap: 0 var(--gi-space-3);
align-items: baseline;
min-width: 0;
}
.geo-explorer-header h2 {
font-size: var(--gi-text-lg);
letter-spacing: -0.012em;
}
.geo-explorer-header p {
margin: 0;
color: var(--gi-ink-400);
font-size: var(--gi-text-xs);
}
/* Melding- en demobanners: één regel in plaats van een blok van drie. */
.workbench-content :where(.geo-data-notice, .demo-notice, .guest-mode-banner) {
display: flex;
flex: 0 0 auto;
flex-flow: row wrap;
gap: var(--gi-space-1) var(--gi-space-2);
align-items: center;
padding: var(--gi-space-2) var(--gi-space-3);
font-size: var(--gi-text-xs);
line-height: var(--gi-leading-snug);
}
.workbench-content
:where(.geo-data-notice, .demo-notice, .guest-mode-banner)
:where(p, span, strong, small) {
margin: 0;
}
/* --------------------------------------------------------- contextbalk -- */
/* De rij Werkruimte / Gebied / Bron / Kaartlaag. Elke cel krijgt dezelfde
breedte en mag inkorten in plaats van de rij te laten overlopen. */
.context-bar {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
gap: var(--gi-space-2);
min-width: 0;
}
.context-bar > div {
display: grid;
gap: 1px;
min-width: 0;
padding: var(--gi-space-2) var(--gi-space-3);
border: 1px solid var(--gi-line);
border-radius: var(--gi-radius-sm);
background: var(--gi-surface-soft);
}
.context-bar > div > strong {
overflow: hidden;
color: var(--gi-ink-950);
font-size: var(--gi-text-sm);
font-weight: 650;
white-space: nowrap;
text-overflow: ellipsis;
}
/* ------------------------------------------------------ explorer-layout -- */
/* Twaalf concurrerende regels vervangen door één vloeiende definitie.
clamp() schaalt de zijpanelen mee met het venster, zodat er tussen 1280px
en 3440px geen breakpoint meer nodig is. */
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
display: grid;
grid-template-columns:
clamp(15rem, 13vw, 20rem)
minmax(0, 1fr)
clamp(18rem, 16vw, 25rem);
grid-template-rows: minmax(0, 1fr);
gap: 0;
flex: 1 1 auto;
min-width: 0;
min-height: 26rem;
height: auto;
overflow: hidden;
border: 1px solid var(--gi-line);
border-radius: var(--gi-radius-lg);
background: var(--gi-surface);
box-shadow: var(--gi-shadow-sm);
}
.geo-theme-panel,
.geo-map-stage,
.geo-results-panel {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
height: 100%;
border: 0;
border-radius: 0;
background: var(--gi-surface);
box-shadow: none;
}
.geo-theme-panel {
border-right: 1px solid var(--gi-line);
}
.geo-results-panel {
border-left: 1px solid var(--gi-line);
}
.geo-map-stage {
background: var(--gi-surface-sunken);
}
/* De panelen scrollen zelfstandig; de kop blijft staan. */
.geo-theme-panel > :not(.geo-panel-heading),
.geo-results-panel > :not(.geo-panel-heading) {
min-height: 0;
}
/* ------------------------------------------------------------- paneelkop -- */
/* De kern van de layoutbug: het raster reserveerde kolom 1 (1.65rem) voor een
icoon, maar de panelen renderen alleen een tekstblok. Dat blok belandde in
de icoonkolom van 26px en brak per letter af. Flex maakt het icoon optioneel. */
.geo-panel-heading {
display: flex;
flex: 0 0 auto;
gap: var(--gi-space-2);
align-items: flex-start;
min-height: 0;
padding: var(--gi-space-3) var(--gi-space-4);
border-bottom: 1px solid var(--gi-line);
background: var(--gi-surface-soft);
}
.geo-panel-heading > * {
min-width: 0;
}
.geo-panel-heading > div {
display: grid;
flex: 1 1 auto;
gap: 2px;
}
.geo-panel-heading > span {
display: grid;
flex: 0 0 auto;
place-items: center;
width: 1.5rem;
height: 1.5rem;
border-radius: var(--gi-radius-xs);
background: var(--gi-brand-800);
color: #ffffff;
font-size: var(--gi-text-2xs);
font-weight: 800;
}
.geo-panel-heading h3 {
display: flex;
gap: var(--gi-space-2);
align-items: baseline;
color: var(--gi-ink-950);
font-size: var(--gi-text-md);
font-weight: 650;
}
.geo-panel-heading h3 small {
flex: 0 0 auto;
margin: 0;
padding: 1px var(--gi-space-2);
border-radius: var(--gi-radius-pill);
background: var(--gi-brand-50);
color: var(--gi-brand-700);
font-size: var(--gi-text-3xs);
font-weight: 700;
letter-spacing: 0.07em;
text-transform: uppercase;
}
.geo-panel-heading p {
margin: 0;
color: var(--gi-ink-400);
font-size: var(--gi-text-xs);
line-height: var(--gi-leading-snug);
}
/* --------------------------------------------------------------- panelen -- */
.geo-theme-panel > :where(div, ul, ol, section):not(.geo-panel-heading) {
padding-inline: var(--gi-space-3);
}
.geo-theme-list {
display: grid;
gap: var(--gi-space-2);
min-height: 0;
padding-block: var(--gi-space-3);
overflow-y: auto;
overscroll-behavior: contain;
}
/* Drie zones: statuskleur, tekst, statuslabel. De kaart groeit mee met de
tekst; een vaste hoogte liet de tweede regel over het statuslabel lopen. */
.geo-theme-option {
display: grid;
grid-template-columns: 3px minmax(0, 1fr) auto;
gap: var(--gi-space-3);
align-items: start;
width: 100%;
min-height: 3.25rem;
height: auto;
padding: var(--gi-space-3);
border: 1px solid var(--gi-line);
border-radius: var(--gi-radius-md);
background: var(--gi-surface);
text-align: left;
cursor: pointer;
transition:
border-color var(--gi-dur-1) var(--gi-ease),
box-shadow var(--gi-dur-1) var(--gi-ease),
transform var(--gi-dur-1) var(--gi-ease);
}
.geo-theme-option:hover {
border-color: var(--gi-line-accent);
box-shadow: var(--gi-shadow-sm);
transform: translateY(-1px);
}
.geo-theme-option[aria-pressed='true'],
.geo-theme-option.is-active {
border-color: var(--gi-brand-500);
background: var(--gi-brand-50);
box-shadow: inset 0 0 0 1px var(--gi-brand-300);
}
/* De tekstkolom: titel boven, toelichting eronder, beide binnen de kolom. */
.geo-theme-option > span {
display: grid;
gap: 2px;
min-width: 0;
align-content: start;
height: auto;
}
.geo-theme-option > span > small {
display: block;
overflow: visible;
color: var(--gi-ink-400);
font-size: var(--gi-text-2xs);
line-height: var(--gi-leading-snug);
-webkit-line-clamp: none;
}
/* Het statuslabel rechts blijft op één regel en botst niet met de tekst. */
.geo-theme-option > i {
flex: 0 0 auto;
align-self: start;
color: var(--gi-ink-400);
font-size: var(--gi-text-3xs);
font-style: normal;
font-weight: 700;
letter-spacing: 0.07em;
text-transform: uppercase;
white-space: nowrap;
}
/* ------------------------------------------------------------ leeg beeld -- */
.geo-empty-state {
display: grid;
gap: var(--gi-space-3);
place-content: center;
justify-items: center;
min-height: 0;
padding: var(--gi-space-8) var(--gi-space-5);
text-align: center;
}
.geo-empty-state h4 {
color: var(--gi-ink-800);
font-size: var(--gi-text-md);
font-weight: 650;
}
.geo-empty-state p {
max-width: 26ch;
color: var(--gi-ink-400);
font-size: var(--gi-text-xs);
}
/* ----------------------------------------------------------- interactie -- */
.workbench-shell :where(button, [role='button'], a, input, select, textarea, summary):focus-visible {
outline: none;
box-shadow: var(--gi-focus-ring);
}
.workbench-shell :where(button, a) {
transition:
background-color var(--gi-dur-1) var(--gi-ease),
border-color var(--gi-dur-1) var(--gi-ease),
color var(--gi-dur-1) var(--gi-ease);
}
/* -------------------------------------------------------------- responsief -- */
/* Eén set breakpoints in plaats van 1120/1240/1361/1500/1800/2400/2800 verspreid
over vijf bestanden. */
/* Tablet en smalle laptop: inzichtenpaneel onder de kaart. */
@media (max-width: 1200px) {
:root {
--gi-sidebar-w: 11.5rem;
}
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
grid-template-columns: clamp(14rem, 22vw, 17rem) minmax(0, 1fr);
grid-template-rows: minmax(30rem, 1fr) auto;
height: auto;
overflow: visible;
}
.geo-results-panel {
grid-column: 1 / -1;
border-top: 1px solid var(--gi-line);
border-left: 0;
}
}
/* Mobiel: één kolom, kaart met vaste hoogte. */
@media (max-width: 900px) {
.workbench-layout {
grid-template-columns: minmax(0, 1fr);
}
.workbench-sidebar {
flex-direction: row;
align-items: center;
overflow-x: auto;
}
.workbench-sidebar nav {
flex-direction: row;
}
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
grid-template-columns: minmax(0, 1fr);
grid-template-rows: auto minmax(24rem, 60vh) auto;
}
.geo-theme-panel {
border-right: 0;
border-bottom: 1px solid var(--gi-line);
}
.workbench-content {
padding: var(--gi-space-3);
}
}
/* ============================================================================
Kaart-eerst herschikking
----------------------------------------------------------------------------
Uitgangspunt: de kaart is de werkruimte, niet een kaartje in een kader.
1. Geen marges rond het werkblad. De keten viewport -> kaart bevatte 20px
content-padding plus 30/36/48px wrapper-padding plus een rand met 14px
radius. Samen kostte dat ruim 100px aan alle zijden.
2. Het inzichtenpaneel is geen vaste derde kolom meer maar een lade over de
kaart. Zonder selectie staat er toch niets in; die 400px hoort dan aan de
kaart. De lade opent vanzelf zodra er resultaten zijn.
========================================================================== */
/* -- 1. Volledig beeld, geen marges ---------------------------------------- */
.workbench-content {
padding: 0;
}
.workbench-content > * {
padding: 0 !important;
}
.workspace-persistent-map,
.geo-explorer {
gap: 0;
}
/* Deze sectie had zelf nog een rand met 7px radius, goed voor 17px inham
rechts van het werkblad. */
.geo-explorer {
padding: 0;
border: 0;
border-radius: 0;
background: var(--gi-surface);
}
.geo-explorer-header {
border-bottom: 1px solid var(--gi-line);
background: var(--gi-surface);
}
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
position: relative;
border: 0;
border-radius: 0;
box-shadow: none;
}
/* -- 2. Inzichten als lade over de kaart ----------------------------------- */
/* Twee kolommen: bedieningspaneel en kaart. De lade zweeft over de kaart. */
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
grid-template-columns: clamp(14rem, 12vw, 17rem) minmax(0, 1fr);
}
.geo-results-panel {
position: absolute;
z-index: 5;
inset-block: 0;
right: 0;
width: clamp(20rem, 21vw, 26rem);
border-left: 1px solid var(--gi-line);
background: var(--gi-surface);
box-shadow: var(--gi-shadow-lg);
transition: transform var(--gi-dur-3) var(--gi-ease-out);
}
/* Zonder selectie schuift de lade weg en blijft alleen een greep zichtbaar.
.geo-results-empty is het element dat "Nog geen gebied geselecteerd" toont;
zodra er echte resultaten staan verdwijnt het en opent de lade vanzelf. */
.geo-explorer-layout:has(.geo-results-empty) .geo-results-panel {
transform: translateX(calc(100% - 2.5rem));
}
/* Hover of toetsenbordfocus opent de lade alsnog. */
.geo-explorer-layout:has(.geo-results-empty) .geo-results-panel:hover,
.geo-explorer-layout:has(.geo-results-empty) .geo-results-panel:focus-within {
transform: translateX(0);
}
/* De greep: een verticale tab langs de rand van de kaart. */
.geo-results-panel::before {
position: absolute;
top: 0;
bottom: 0;
left: 0;
display: grid;
width: 2.5rem;
align-content: center;
justify-items: center;
background: var(--gi-brand-800);
color: #ffffff;
content: 'INZICHTEN';
font-size: var(--gi-text-3xs);
font-weight: 750;
letter-spacing: 0.14em;
opacity: 0;
pointer-events: none;
transition: opacity var(--gi-dur-2) var(--gi-ease);
writing-mode: vertical-rl;
}
.geo-explorer-layout:has(.geo-results-empty) .geo-results-panel::before {
opacity: 1;
}
.geo-explorer-layout:has(.geo-results-empty) .geo-results-panel:hover::before,
.geo-explorer-layout:has(.geo-results-empty) .geo-results-panel:focus-within::before {
opacity: 0;
}
/* De lege toestand vult de lade niet meer met een leeg kader. */
.geo-results-empty {
display: grid;
gap: var(--gi-space-2);
place-content: center;
justify-items: center;
height: auto;
padding: var(--gi-space-8) var(--gi-space-4);
border: 0;
background: none;
text-align: center;
}
/* -- 3. Bedieningspaneel compacter ----------------------------------------- */
/* Het statuslabel stond in een derde kolom en duwde de titel kapot
("Bestuurl ijke indeling"). Het staat nu onder de tekst. */
.geo-theme-option {
grid-template-columns: 3px minmax(0, 1fr);
gap: var(--gi-space-2);
padding: var(--gi-space-2) var(--gi-space-3);
}
.geo-theme-option > i {
grid-column: 2;
justify-self: start;
}
.geo-theme-option > span:nth-child(2) > :where(strong, b) {
font-size: var(--gi-text-xs);
font-weight: 650;
}
/* -- 4. Rail: breed genoeg voor de labels, en sluitend --------------------- */
/* 76px was te smal: "Beeldanalyse", "Downloads" en de ITWorx-ondertekening
liepen onder de kaart door. 108px past het langste label op twee regels
en blijft ruim compacter dan de oorspronkelijke 216px. */
:root {
--gi-sidebar-w: 6.75rem;
}
/* Niets mag buiten de rail vallen. */
.workbench-sidebar,
.workbench-sidebar > * {
overflow: hidden;
}
.workbench-sidebar nav {
overflow-y: auto;
}
.workbench-sidebar .sidebar-brand {
display: grid;
gap: var(--gi-space-1);
place-items: center;
padding: var(--gi-space-1) 0 var(--gi-space-4);
text-align: center;
}
.workbench-sidebar .sidebar-brand-copy {
display: grid;
gap: 0;
justify-items: center;
min-width: 0;
}
.workbench-sidebar .sidebar-brand-copy strong {
color: #ffffff;
font-size: var(--gi-text-xs);
font-weight: 650;
letter-spacing: 0.01em;
}
.workbench-sidebar .brand-mark {
width: 1.75rem;
height: 1.75rem;
}
.workbench-sidebar .nav-item :where(small, span:last-child) {
overflow: visible;
max-width: 100%;
font-size: 0.5938rem;
letter-spacing: 0.02em;
line-height: 1.15;
text-overflow: clip;
white-space: normal;
overflow-wrap: break-word;
hyphens: auto;
}
/* De ontwikkelaarsvermelding: gecentreerd en binnen de rail. */
.workbench-sidebar .itworx-signature {
display: grid;
flex: 0 0 auto;
gap: var(--gi-space-1);
justify-items: center;
padding-top: var(--gi-space-3);
text-align: center;
}
.workbench-sidebar .itworx-signature :where(span, strong, p, small) {
max-width: 100%;
font-size: 0.5625rem;
line-height: 1.2;
text-align: center;
}
.workbench-sidebar .itworx-signature :where(img, svg) {
max-width: 100%;
height: auto;
}
/* -- 5. Inzichten: leesbare, scrollbare inhoud ----------------------------- */
/* De inhoud liep tot 1167px in een lade van 927px. Zonder scroll schoven de
onderste blokken over elkaar heen. De kop blijft staan, de rest scrollt. */
.geo-results-panel {
overflow-y: auto;
overscroll-behavior: contain;
}
.geo-results-panel > .geo-panel-heading {
position: sticky;
top: 0;
z-index: 2;
}
.geo-results-panel > * {
flex: 0 0 auto;
margin: 0;
padding-inline: var(--gi-space-4);
}
.geo-results-panel > *:not(.geo-panel-heading) {
padding-block: var(--gi-space-3);
border-top: 1px solid var(--gi-line);
}
.geo-results-panel > .geo-panel-heading + * {
border-top: 0;
}
/* Kerncijfers als drie gelijke kolommen met rustige typografie. */
.geo-primary-metrics {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: var(--gi-space-2);
}
.geo-primary-metrics > div {
display: grid;
gap: 2px;
align-content: start;
min-width: 0;
padding: var(--gi-space-2);
border-radius: var(--gi-radius-sm);
background: var(--gi-surface-soft);
}
.geo-primary-metrics :where(span, small):first-child {
color: var(--gi-ink-400);
font-size: var(--gi-text-3xs);
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.geo-primary-metrics :where(strong, b) {
color: var(--gi-ink-950);
font-size: var(--gi-text-lg);
font-weight: 650;
font-variant-numeric: tabular-nums;
line-height: 1.15;
}
.geo-supporting-metrics > div {
display: flex;
gap: var(--gi-space-2);
align-items: baseline;
justify-content: space-between;
font-size: var(--gi-text-xs);
}
.geo-results-title-row {
display: flex;
gap: var(--gi-space-2);
align-items: baseline;
justify-content: space-between;
}
.geo-results-title-row h4 {
font-size: var(--gi-text-md);
font-weight: 650;
}
.geo-theme-result-row {
display: grid;
gap: 2px;
padding: var(--gi-space-2);
border-radius: var(--gi-radius-sm);
background: var(--gi-surface-soft);
font-size: var(--gi-text-xs);
}
/* Toelichtingen en waarschuwingen: rustig, met een accentrand links. */
.geo-results-panel .geo-data-notice {
border-left: 3px solid var(--gi-warn);
background: var(--gi-warn-soft);
color: var(--gi-ink-800);
font-size: var(--gi-text-xs);
}
.geo-result-actions {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
gap: var(--gi-space-2);
align-items: stretch;
}
.geo-result-actions > button {
align-self: stretch;
min-height: 2.25rem;
/* De twee knoppen hadden verschillende eigen padding en werden 43 en 36px. */
padding-block: 0;
padding-inline: var(--gi-space-3);
border: 1px solid var(--gi-line-strong);
border-radius: var(--gi-radius-sm);
background: var(--gi-surface);
font-size: var(--gi-text-xs);
font-weight: 600;
cursor: pointer;
}
.geo-result-actions > button:hover {
border-color: var(--gi-brand-500);
background: var(--gi-brand-50);
}
.geo-performance-status {
color: var(--gi-ink-400);
font-size: var(--gi-text-2xs);
}
/* ------------------------------------------------------- release-correcties -- */
/* Chromium plaatst de geopende inhoud van <details> in een interne
::details-content-container. Daardoor werd die container zelf het eerste
grid-item en kregen alle kwaliteitssecties slechts de smalle eerste kolom.
Leg het raster op de echte inhoudscontainer; de secties behouden zo hun
bestaande, semantische kolomtoewijzing. */
.quality-advanced-disclosure[open] {
display: block;
min-height: 0;
overflow: visible;
}
.quality-advanced-disclosure[open] > summary {
margin-bottom: var(--gi-space-2);
}
.quality-advanced-disclosure[open]::details-content {
display: grid;
grid-template-columns:
minmax(16rem, 0.7fr)
minmax(27rem, 1.35fr)
minmax(19rem, 0.95fr);
grid-template-rows: minmax(22rem, auto) minmax(18rem, auto);
gap: var(--gi-space-2);
overflow: visible;
}
/* De oorspronkelijke rijnummers telden <summary> mee als eerste gridrij.
In ::details-content staat summary erbuiten, dus schuiven de inhoudsrijen
één positie omhoog en ontstaat er geen lege rij boven het bewijs. */
.quality-advanced-disclosure[open] > .quality-evidence-surface {
grid-column: 1;
grid-row: 1;
}
.quality-advanced-disclosure[open] > .quality-control-surface {
grid-column: 1;
grid-row: 2;
}
.quality-advanced-disclosure[open] > .quality-history-surface {
grid-column: 2;
grid-row: 1 / 3;
}
.quality-advanced-disclosure[open] > .quality-drilldown-surface {
grid-column: 3;
grid-row: 1 / 3;
}
/* De linker contextkolom en rechter inspector zijn bewust smal. Hun interne
drie-kolomsrasters maakten bestandsnamen en bewijslabels onleesbaar; kaarten
stapelen binnen die rails en gebruiken de volledige beschikbare breedte. */
.quality-evidence-surface .quality-handoff-grid,
.quality-drilldown-surface .quality-drilldown-grid,
.quality-drilldown-surface .quality-evidence-token-grid,
.quality-drilldown-surface .quality-feature-evidence-grid,
.quality-drilldown-surface .quality-provenance-grid {
grid-template-columns: minmax(0, 1fr);
}
/* De resultatenlade heeft drie kerncijfers. 320px was onvoldoende voor
labels en waarden zoals "5,1% dekking"; 25vw houdt ze leesbaar zonder de
kaart op normale desktopbreedtes te verdringen. */
.geo-results-panel {
width: clamp(23rem, 25vw, 28rem);
}
.geo-primary-metrics :where(strong, b) {
overflow: visible;
white-space: normal;
text-overflow: clip;
}
/* De kaart-eerstregels staan later in dit bestand dan de oorspronkelijke
responsive regels. Herhaal de definitieve contracts hier zodat de lade op
smalle laptops onder de kaart komt en niet vrijwel het hele kaartbeeld
bedekt. */
@media (max-width: 1240px) {
.workspace-persistent-map {
overflow-y: auto;
overscroll-behavior: contain;
}
.geo-explorer {
overflow-y: auto;
overscroll-behavior: contain;
}
.quality-advanced-disclosure[open]::details-content {
grid-template-columns: minmax(16rem, 0.7fr) minmax(26rem, 1.3fr);
grid-template-rows: auto auto;
}
.quality-advanced-disclosure[open] > .quality-evidence-surface {
grid-column: 1;
grid-row: 1;
}
.quality-advanced-disclosure[open] > .quality-control-surface {
grid-column: 2;
grid-row: 1;
}
.quality-advanced-disclosure[open] > .quality-history-surface {
grid-column: 1;
grid-row: 2;
}
.quality-advanced-disclosure[open] > .quality-drilldown-surface {
grid-column: 2;
grid-row: 2;
}
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
grid-template-columns: clamp(14rem, 22vw, 17rem) minmax(0, 1fr);
grid-template-rows: 30rem max-content;
flex: 0 0 auto;
height: max-content;
overflow: visible;
}
.geo-results-panel {
position: static;
grid-column: 1 / -1;
width: auto;
height: auto;
max-height: none;
overflow: visible;
transform: none !important;
border-top: 1px solid var(--gi-line);
border-left: 0;
box-shadow: none;
}
.geo-results-panel::before {
display: none;
}
}
@media (max-width: 920px) {
.quality-advanced-disclosure[open]::details-content {
display: flex;
flex-direction: column;
}
.quality-advanced-disclosure[open] > :where(
.quality-evidence-surface,
.quality-control-surface,
.quality-history-surface,
.quality-drilldown-surface
) {
grid-column: auto;
grid-row: auto;
}
.geo-explorer-layout,
.workbench-shell-guest .geo-explorer-layout {
grid-template-columns: minmax(0, 1fr);
grid-template-rows: auto minmax(24rem, 60vh) auto;
}
.geo-theme-panel {
border-right: 0;
border-bottom: 1px solid var(--gi-line);
}
}
@media (prefers-reduced-motion: reduce) {
.workbench-shell *,
.workbench-shell *::before,
.workbench-shell *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
/* ==========================================================================
Sprint 231 - motion language and interactive AI pipeline
========================================================================== */
.ai-pipeline {
position: relative;
isolation: isolate;
overflow: hidden;
padding: clamp(1rem, 2vw, 1.5rem);
border: 1px solid color-mix(in srgb, var(--gi-brand-500) 25%, var(--gi-line));
border-radius: var(--gi-radius-lg);
color: #edfdf8;
background:
linear-gradient(115deg, rgba(255,255,255,.035), transparent 38%),
radial-gradient(circle at 82% 10%, rgba(69, 209, 177, .15), transparent 20rem),
#082f2b;
box-shadow: var(--gi-shadow-md);
}
.overview-command-center { display: grid; gap: var(--gi-space-4); padding: clamp(1rem, 2vw, 1.5rem); border: 1px solid var(--gi-line); border-radius: var(--gi-radius-lg); background: var(--gi-surface); box-shadow: var(--gi-shadow-sm); }
.overview-command-heading { display: flex; gap: var(--gi-space-4); align-items: end; justify-content: space-between; }
.overview-command-heading h2 { margin: .2rem 0 0; font: 700 clamp(1.15rem, 2vw, 1.55rem)/1.2 Manrope, sans-serif; }
.overview-command-grid { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: var(--gi-space-3); }
.overview-command-card { position: relative; display: grid; gap: .35rem; min-width: 0; min-height: 8rem; padding: var(--gi-space-4); border: 1px solid var(--gi-line); border-radius: var(--gi-radius-md); color: var(--gi-ink-800); background: var(--gi-surface-soft); text-align: left; transition: transform .2s var(--gi-ease), border-color .2s var(--gi-ease), box-shadow .2s var(--gi-ease); }
button.overview-command-card { cursor: pointer; }
.overview-command-card:hover { transform: translateY(-2px); border-color: var(--gi-line-accent); box-shadow: var(--gi-shadow-md); }
.overview-command-card > span { color: var(--gi-ink-400); font-size: var(--gi-text-3xs); font-weight: 750; letter-spacing: .08em; text-transform: uppercase; }
.overview-command-card > strong { overflow: hidden; color: var(--gi-ink-950); font: 700 1.2rem/1.2 Manrope,sans-serif; text-overflow: ellipsis; white-space: nowrap; }
.overview-command-card > p { margin: 0; color: var(--gi-ink-400); font-size: var(--gi-text-2xs); line-height: 1.55; }
.overview-command-card-progress { color: #fff; background: linear-gradient(145deg,var(--gi-brand-800),#0a5148); }
.overview-command-card-progress > :where(span,strong,p) { color: inherit; }
.overview-command-card-progress > span, .overview-command-card-progress > p { color: rgba(239,255,250,.66); }
.overview-command-card-progress > div { align-self: end; height: 4px; overflow: hidden; border-radius: 999px; background: rgba(255,255,255,.14); }
.overview-command-card-progress > div > i { display: block; height: 100%; border-radius: inherit; background: #84e0c9; transition: width .5s var(--gi-ease-out); }
.ai-pipeline::before {
position: absolute;
z-index: -1;
inset: 0;
background-image:
linear-gradient(rgba(150, 232, 212, .055) 1px, transparent 1px),
linear-gradient(90deg, rgba(150, 232, 212, .055) 1px, transparent 1px);
background-size: 3rem 3rem;
content: '';
mask-image: linear-gradient(90deg, transparent, #000 25%, #000);
}
.ai-pipeline-heading {
display: flex;
gap: var(--gi-space-5);
align-items: start;
justify-content: space-between;
}
.ai-pipeline-heading .eyebrow { color: #84dfca; }
.ai-pipeline-heading h3 { margin: .25rem 0 0; color: #fff; font: 700 clamp(1.15rem, 2vw, 1.55rem)/1.15 Manrope, sans-serif; }
.ai-pipeline-heading p:last-child { max-width: 68ch; margin: .45rem 0 0; color: rgba(231, 251, 245, .65); font-size: var(--gi-text-xs); line-height: 1.6; }
.ai-pipeline-gpu { display: inline-flex; flex: 0 0 auto; gap: .45rem; align-items: center; padding: .48rem .65rem; border: 1px solid rgba(255,255,255,.16); border-radius: 999px; background: rgba(255,255,255,.06); font-size: var(--gi-text-2xs); font-weight: 700; }
.ai-pipeline-gpu i { width: .48rem; height: .48rem; border-radius: 50%; background: #e3b867; }
.ai-pipeline-gpu-ready i { background: #67e0bc; box-shadow: 0 0 0 5px rgba(103,224,188,.12); animation: ai-gpu-pulse 2.4s ease-out infinite; }
.ai-pipeline-track { position: relative; display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: .55rem; margin-top: 1.35rem; }
.ai-pipeline-flow { position: absolute; top: 1.55rem; right: 8%; left: 8%; height: 2px; overflow: hidden; background: rgba(154, 228, 211, .15); }
.ai-pipeline-flow::after { position: absolute; inset: 0; background: linear-gradient(90deg, transparent, #76e1c7, transparent); content: ''; transform: translateX(-100%); animation: ai-flow 4.8s ease-in-out infinite; }
.ai-pipeline-stage { position: relative; z-index: 1; display: grid; gap: .28rem; justify-items: center; min-width: 0; padding: .65rem .4rem; border: 1px solid rgba(190, 235, 224, .12); border-radius: .8rem; color: rgba(232, 249, 244, .58); background: rgba(4, 39, 36, .82); text-align: center; cursor: pointer; transition: transform .22s ease, border-color .22s ease, background .22s ease; }
.ai-pipeline-stage:hover, .ai-pipeline-stage:focus-visible { transform: translateY(-3px); border-color: rgba(131, 226, 204, .52); }
.ai-pipeline-stage[aria-selected='true'] { border-color: #79d9c3; color: #fff; background: rgba(25, 102, 89, .88); box-shadow: 0 12px 30px rgba(0,0,0,.2); }
.ai-pipeline-stage > span { display: grid; width: 2rem; height: 2rem; place-items: center; border: 1px solid rgba(255,255,255,.15); border-radius: .65rem; background: rgba(255,255,255,.06); }
.ai-pipeline-stage-ready > span { color: #8ce6d1; }
.ai-pipeline-stage svg { width: 1rem; height: 1rem; }
.ai-pipeline-stage strong { overflow: hidden; max-width: 100%; font-size: var(--gi-text-2xs); text-overflow: ellipsis; white-space: nowrap; }
.ai-pipeline-stage small { color: rgba(231, 250, 245, .45); font-size: var(--gi-text-3xs); text-transform: uppercase; }
.ai-pipeline-detail { display: grid; grid-template-columns: auto minmax(0,1fr); gap: .8rem; align-items: center; margin-top: .8rem; padding: .8rem; border-left: 2px solid #76dfc6; border-radius: 0 .7rem .7rem 0; background: rgba(255,255,255,.055); animation: ai-detail-in .36s ease both; }
.ai-pipeline-detail > span { color: #7edfc9; font: 700 1.35rem/1 Manrope, sans-serif; }
.ai-pipeline-detail strong { color: #fff; font-size: var(--gi-text-sm); }
.ai-pipeline-detail p { margin: .2rem 0 0; color: rgba(233, 250, 246, .61); font-size: var(--gi-text-2xs); line-height: 1.55; }
/* Micro-interactions stay functional rather than decorative. */
.workbench-content > * { animation: gi-workspace-enter .32s var(--gi-ease-out) both; }
.status-tile, .workflow-guidance-step, .quality-history-list > *, .latest-artifact-card { transition: transform .2s var(--gi-ease), box-shadow .2s var(--gi-ease), border-color .2s var(--gi-ease); }
.status-tile:hover, .workflow-guidance-step:hover, .quality-history-list > *:hover, .latest-artifact-card:hover { transform: translateY(-2px); box-shadow: var(--gi-shadow-md); }
.result-state-loading, .geo-results-loading { position: relative; overflow: hidden; }
.result-state-loading::after, .geo-results-loading::after { position: absolute; inset: 0; background: linear-gradient(105deg, transparent 20%, rgba(116, 218, 194, .13) 42%, transparent 64%); content: ''; transform: translateX(-100%); animation: gi-skeleton-sweep 1.8s ease-in-out infinite; }
.result-state-error { animation: gi-error-enter .32s ease both; }
.geo-results-panel:not(:has(.geo-results-empty)) { animation: gi-drawer-enter .3s var(--gi-ease-out) both; }
@keyframes ai-flow { 55%,100% { transform: translateX(100%); } }
@keyframes ai-gpu-pulse { 70% { box-shadow: 0 0 0 9px rgba(103,224,188,0); } }
@keyframes ai-detail-in { from { opacity: 0; transform: translateY(5px); } }
@keyframes gi-workspace-enter { from { opacity: 0; transform: translateY(6px); } }
@keyframes gi-skeleton-sweep { 60%,100% { transform: translateX(100%); } }
@keyframes gi-error-enter { from { opacity: 0; transform: translateX(-4px); } }
@keyframes gi-drawer-enter { from { opacity: .4; transform: translateX(12px); } }
@media (max-width: 840px) {
.ai-pipeline-heading { flex-direction: column; }
.ai-pipeline-track { grid-template-columns: repeat(5, minmax(6.5rem, 1fr)); overflow-x: auto; padding-bottom: .35rem; }
.ai-pipeline-flow { display: none; }
.overview-command-grid { grid-template-columns: repeat(2,minmax(0,1fr)); }
}
@media (max-width: 560px) {
.overview-command-heading { align-items: stretch; flex-direction: column; }
.overview-command-grid { grid-template-columns: minmax(0,1fr); }
}
@media (prefers-reduced-motion: reduce) {
.ai-pipeline *, .ai-pipeline *::before, .ai-pipeline *::after,
.workbench-content > *, .result-state-loading::after, .geo-results-loading::after,
.geo-results-panel:not(:has(.geo-results-empty)) {
animation: none !important;
transition-duration: .01ms !important;
}
}
/* De marketingillustratie wordt hier een echte productstatus. Alle stappen
volgen API- en hookstate uit MapWorkspace; de laag onderschept geen kaartinput. */
.live-analysis-journey {
position: absolute;
z-index: 4;
inset: 0;
overflow: hidden;
color: #f5fffc;
pointer-events: none;
}
.live-analysis-status-card,
.live-analysis-proof,
.live-analysis-steps {
border: 1px solid rgba(190, 244, 232, 0.24);
background: rgba(4, 45, 40, 0.86);
box-shadow: 0 14px 36px rgba(2, 28, 25, 0.24);
backdrop-filter: blur(12px);
}
.live-analysis-status-card {
position: absolute;
top: var(--gi-space-4);
left: var(--gi-space-4);
display: grid;
gap: 2px;
width: min(14rem, calc(100% - 2rem));
border-radius: var(--gi-radius-md);
padding: 0.72rem 0.82rem;
}
.live-analysis-kicker {
color: #8ee7d2;
font-size: 0.55rem;
font-weight: 800;
letter-spacing: 0.1em;
text-transform: uppercase;
}
.live-analysis-kicker i {
display: inline-block;
width: 0.42rem;
height: 0.42rem;
margin-right: 0.4rem;
border-radius: 50%;
background: #77e2ca;
box-shadow: 0 0 0 5px rgba(119, 226, 202, 0.12);
}
.live-analysis-status-card strong {
font-family: Manrope, sans-serif;
font-size: 0.88rem;
}
.live-analysis-status-card small {
overflow: hidden;
color: rgba(245, 255, 252, 0.68);
font-size: 0.62rem;
line-height: 1.35;
text-overflow: ellipsis;
}
.live-analysis-steps {
position: absolute;
bottom: var(--gi-space-4);
left: var(--gi-space-4);
display: grid;
grid-template-columns: repeat(4, minmax(3.6rem, 1fr));
width: min(25rem, calc(100% - 2rem));
margin: 0;
border-radius: var(--gi-radius-md);
padding: 0.52rem 0.62rem;
list-style: none;
}
.live-analysis-step {
position: relative;
display: grid;
gap: 0.24rem;
justify-items: center;
color: rgba(245, 255, 252, 0.45);
}
.live-analysis-step:not(:last-child)::after {
position: absolute;
top: 0.68rem;
left: calc(50% + 0.9rem);
width: calc(100% - 1.8rem);
border-top: 1px dashed rgba(142, 231, 210, 0.3);
content: '';
}
.live-analysis-step > span {
display: grid;
z-index: 1;
place-items: center;
width: 1.45rem;
height: 1.45rem;
border: 1px solid rgba(190, 244, 232, 0.24);
border-radius: 50%;
background: #103f3a;
}
.live-analysis-step svg {
width: 0.72rem;
height: 0.72rem;
}
.live-analysis-step small {
font-size: 0.54rem;
font-weight: 750;
}
.live-analysis-step-active,
.live-analysis-step-complete {
color: #a8f3e2;
}
.live-analysis-step-active > span {
border-color: #8ee7d2;
box-shadow: 0 0 0 5px rgba(119, 226, 202, 0.12);
}
.live-analysis-step-complete > span {
border-color: #66d6bd;
background: #176a5c;
}
.live-analysis-step-error,
.live-analysis-journey-error .live-analysis-kicker {
color: #ffd2c2;
}
.live-analysis-step-error > span,
.live-analysis-journey-error .live-analysis-status-card {
border-color: rgba(255, 137, 105, 0.7);
}
.live-analysis-proof {
position: absolute;
top: var(--gi-space-4);
right: var(--gi-space-4);
display: flex;
gap: 0.46rem;
align-items: center;
max-width: min(15rem, 42%);
border-radius: var(--gi-radius-md);
padding: 0.62rem 0.72rem;
color: rgba(245, 255, 252, 0.64);
font-size: 0.59rem;
font-weight: 700;
}
.live-analysis-proof svg {
flex: 0 0 auto;
width: 0.88rem;
height: 0.88rem;
color: #8ee7d2;
}
.live-analysis-proof-ready {
border-color: rgba(142, 231, 210, 0.62);
color: #f5fffc;
}
.live-analysis-journey-running::after {
position: absolute;
top: 0;
bottom: 0;
left: 16%;
width: 2px;
background: linear-gradient(180deg, transparent, rgba(174, 255, 237, 0.86), transparent);
filter: drop-shadow(0 0 7px #7be6d1);
content: '';
animation: gi-live-analysis-scan 3.8s ease-in-out infinite;
}
.live-analysis-journey-running .live-analysis-kicker i {
animation: gi-live-analysis-pulse 1.8s ease-out infinite;
}
@keyframes gi-live-analysis-scan {
0%, 100% { opacity: 0; transform: translateX(0); }
15%, 85% { opacity: 0.72; }
50% { opacity: 0.92; transform: translateX(34vw); }
}
@keyframes gi-live-analysis-pulse {
50% { box-shadow: 0 0 0 9px rgba(119, 226, 202, 0); }
}
@media (max-width: 720px) {
.live-analysis-status-card {
top: 5.25rem;
left: var(--gi-space-3);
width: min(12rem, calc(100% - 6rem));
}
.live-analysis-proof {
top: 5.25rem;
right: var(--gi-space-3);
width: 2rem;
min-height: 2rem;
padding: 0;
justify-content: center;
}
.live-analysis-proof span {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
}
.live-analysis-steps {
right: var(--gi-space-3);
bottom: var(--gi-space-3);
left: var(--gi-space-3);
grid-template-columns: repeat(4, minmax(0, 1fr));
width: auto;
}
}
@media (prefers-reduced-motion: reduce) {
.live-analysis-journey *,
.live-analysis-journey::after {
animation: none !important;
transition-duration: 0.01ms !important;
}
}