/* G&G Data Inventory. Light mode only, dense dashboard. */

:root {
  --colour-primary: #1E40AF;
  --colour-primary-soft: #E4EBFA;
  --colour-secondary: #3B82F6;
  --colour-accent: #D97706;
  --colour-accent-soft: #FDF1DC;
  /* Same hue, dark enough to read at 11px. --colour-accent is a
     border and fill colour; on the page background it is ~3.4:1. */
  --colour-accent-text: #92400E;
  --colour-background: #F8FAFC;
  --colour-surface: #FFFFFF;
  --colour-text: #0F172A;
  --colour-text-muted: #475569;
  --colour-border: #DBEAFE;
  --colour-border-firm: #C7D9F5;
  --colour-critical: #DC2626;
  --colour-critical-soft: #FBE6E6;
  --colour-settled: #047857;
  --colour-settled-soft: #E0F0EA;

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
  --space-4: 16px; --space-5: 24px; --space-6: 32px;

  --radius: 6px;
  --sidebar: 232px;
  --shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .04);

  --font-text: 'Space Grotesk', system-ui, sans-serif;
  --font-value: 'Noto Sans', system-ui, sans-serif;
}

* { box-sizing: border-box; }

body.nav-collapsed { --sidebar: 60px; }

/* Visible to assistive technology only. */
.sr {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

html { color-scheme: light; }

body {
  margin: 0;
  background: var(--colour-background);
  color: var(--colour-text);
  font-family: var(--font-text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.value, td.num, .kpi-value, .stat {
  font-family: var(--font-value);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

a { color: var(--colour-primary); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--colour-primary); color: #FFFFFF;
  padding: var(--space-3) var(--space-4); border-radius: 0 0 var(--radius) 0;
  font-weight: 600; text-decoration: none;
}
.skip:focus { left: 0; }

/* ---------------------------------------------------------------- layout */

.shell { display: flex; min-height: 100dvh; }

/* Collapsed, the sidebar keeps its icons and drops the labels. The width is
   a variable so the transition is one property and the main column reflows
   with it. */
.sidebar {
  width: var(--sidebar);
  flex: 0 0 var(--sidebar);
  transition: width 160ms ease-out, flex-basis 160ms ease-out;
  background: var(--colour-surface);
  border-right: 1px solid var(--colour-border);
  padding: var(--space-5) var(--space-3);
  position: sticky;
  top: 0;
  height: 100dvh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.brand {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 0 var(--space-2) var(--space-5);
  font-weight: 700; font-size: 15px; letter-spacing: -.01em;
}
.brand svg { color: var(--colour-primary); flex: 0 0 auto; }

.nav { display: flex; flex-direction: column; gap: 2px; }

.nav a {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: 44px; padding: 0 var(--space-3);
  border-radius: var(--radius);
  color: var(--colour-text); text-decoration: none;
  font-weight: 500; font-size: 14px;
  transition: background 150ms ease-out, color 150ms ease-out;
  cursor: pointer;
}
.nav a:hover { background: var(--colour-primary-soft); }
.nav a[aria-current='page'] {
  background: var(--colour-primary); color: #FFFFFF; font-weight: 600;
}
.nav a:focus-visible, .tab:focus-visible, button:focus-visible, th button:focus-visible {
  outline: 3px solid var(--colour-secondary); outline-offset: 2px;
}
.nav svg { flex: 0 0 auto; }

.nav-flag {
  margin-left: auto;
  font-family: var(--font-value);
  font-size: 12px; font-weight: 600;
  min-width: 22px; height: 20px; padding: 0 6px;
  border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--colour-critical); color: #FFFFFF;
}
.nav a[aria-current='page'] .nav-flag { background: #FFFFFF; color: var(--colour-critical); }

.main { flex: 1 1 auto; min-width: 0; }
.content { max-width: 1440px; padding: var(--space-5); margin: 0 auto; }

/* ---------------------------------------------------------------- header */

.page-head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--space-3) var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--colour-border);
  margin-bottom: var(--space-5);
}
h1 { font-size: 24px; font-weight: 700; letter-spacing: -.02em; margin: 0; }
h2 { font-size: 16px; font-weight: 600; letter-spacing: -.01em; margin: 0; }
h3 { font-size: 13px; font-weight: 600; margin: 0; color: var(--colour-text-muted); }

.head-facts { display: flex; flex-wrap: wrap; gap: var(--space-5); margin-left: auto; }
.head-fact { display: flex; align-items: baseline; gap: var(--space-2); }
.head-fact .k { font-size: 12px; font-weight: 500; color: var(--colour-text-muted); }
.head-fact .v { font-family: var(--font-value); font-size: 13px; font-weight: 600; }

/* ---------------------------------------------------------------- cards */

.grid { display: grid; gap: var(--space-3); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.span2 { grid-column: span 2; }

.card {
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-4);
}
.card-head {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.card-head h2 { margin-right: auto; }

.kpi { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2); }
.kpi-label { font-size: 12px; font-weight: 500; color: var(--colour-text-muted); }
.kpi-value { font-size: 28px; font-weight: 600; line-height: 1.1; letter-spacing: -.02em; }
.kpi-unit { font-family: var(--font-text); font-size: 13px; font-weight: 500; color: var(--colour-text-muted); }

/* ---------------------------------------------------------------- status */

.status {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 8px; border-radius: 4px;
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.status svg { flex: 0 0 auto; }
.status-critical  { background: var(--colour-critical-soft); color: var(--colour-critical); }
.status-attention { background: var(--colour-accent-soft);   color: #9A5B05; }
.status-settled   { background: var(--colour-settled-soft);  color: var(--colour-settled); }

.card-critical  { border-left: 3px solid var(--colour-critical); }
.card-attention { border-left: 3px solid var(--colour-accent); }
.card-settled   { border-left: 3px solid var(--colour-settled); }

/* ---------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; border-radius: var(--radius); }

table { border-collapse: collapse; width: 100%; font-size: 13px; }
caption { text-align: left; font-weight: 600; padding-bottom: var(--space-3); }

th {
  text-align: left; font-weight: 600; font-size: 12px;
  color: var(--colour-text-muted);
  padding: 0 var(--space-3);
  border-bottom: 1px solid var(--colour-border-firm);
  white-space: nowrap; position: sticky; top: 0; background: var(--colour-surface);
}
th button {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
  min-height: 44px; font: inherit; color: inherit;
}
th button:hover { color: var(--colour-primary); }

td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--colour-border);
  vertical-align: top;
}
td.num, th.num { text-align: right; }
tbody tr { transition: background 150ms ease-out; }
tbody tr:hover { background: var(--colour-primary-soft); }
.mono-path { color: var(--colour-text-muted); font-size: 12px; }

/* ---------------------------------------------------------------- charts */

.chart { width: 100%; max-width: 100%; display: block; }
.chart text { font-family: var(--font-value); font-variant-numeric: tabular-nums; fill: var(--colour-text); }
.chart text.label { font-family: var(--font-text); }
.chart .axis { stroke: var(--colour-border); stroke-width: 1; }
.chart .bar { transition: opacity 150ms ease-out; }
.chart .bar:hover { opacity: .78; }

.legend { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-3); }
.legend span { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; }
.swatch { width: 12px; height: 12px; border-radius: 2px; flex: 0 0 auto; }

/* ---------------------------------------------------------------- misc */

.view { animation: fade 200ms ease-out; }
.view[hidden] { display: none !important; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.stack { display: flex; flex-direction: column; gap: var(--space-5); }
.row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

.empty { padding: var(--space-6); text-align: center; color: var(--colour-text-muted); font-weight: 500; }

.skeleton {
  height: 96px; border-radius: var(--radius);
  background: linear-gradient(90deg, #EEF2F8 25%, #F6F9FC 50%, #EEF2F8 75%);
  background-size: 200% 100%;
  animation: shimmer 1.2s linear infinite;
}
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

.tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--colour-border); margin-bottom: var(--space-4); }
.tab {
  all: unset; cursor: pointer; min-height: 44px; padding: 0 var(--space-4);
  font-weight: 500; font-size: 13px; color: var(--colour-text-muted);
  border-bottom: 2px solid transparent;
  transition: color 150ms ease-out, border-colour 150ms ease-out;
}
.tab:hover { color: var(--colour-text); }
.tab[aria-selected='true'] { color: var(--colour-primary); border-bottom-color: var(--colour-primary); font-weight: 600; }

/* ---------------------------------------------------------------- responsive */

/* ----------------------------------------------------------------- map */

.map-host { margin-top: var(--space-2); }
.map, .map-skeleton {
  height: 460px;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  overflow: hidden;
}
/* The Fullscreen widget promotes this element itself, so it has to fill the
   screen rather than keep the height it has inside the card. */
.map:fullscreen { height: 100%; border: 0; border-radius: 0; }

.map-tools {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  margin-top: var(--space-3);
}
.map-tools label {
  font-size: 11px; font-weight: 500; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--colour-text-muted);
}
.map-tools input {
  width: 8rem; min-height: 36px; padding: 0 var(--space-2);
  font-family: var(--font-value); font-size: 13px; font-weight: 600;
  color: var(--colour-text); background: var(--colour-surface);
  border: 1px solid var(--colour-border-firm); border-radius: var(--radius);
}
.map-tools input:focus-visible {
  outline: 3px solid var(--colour-secondary); outline-offset: 1px;
}
.crs-btn {
  border: 1px solid var(--colour-border-firm); border-radius: var(--radius);
  min-height: 36px;
}
.crs-status { display: inline-flex; align-items: center; font-size: 12px; }

.map-facts {
  display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
  margin-top: var(--space-4); padding-top: var(--space-4);
  border-top: 1px solid var(--colour-border);
}
.map-fact { display: flex; flex-direction: column; gap: 3px; }
.map-fact .k {
  font-size: 11px; font-weight: 500; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--colour-text-muted);
}
.map-fact .v { font-size: 13px; font-weight: 600; }

/* Esri ships its own type stack. Match the dashboard instead of fighting it. */
.esri-widget, .esri-popup, .esri-view { font-family: var(--font-text); }
.pop { display: flex; flex-direction: column; gap: 6px; }
.pop-title { font-size: 13px; font-weight: 600; }
.pop-sep {
  width: 100%; margin: var(--space-2) 0;
  border: 0; border-top: 1px solid var(--colour-border);
}
.pop-row {
  display: flex; justify-content: space-between; gap: var(--space-4);
  font-size: 12px;
}
.pop-k { color: var(--colour-text-muted); }
.pop-v { font-weight: 600; }

@media (max-width: 1023px) {
  .shell { flex-direction: column; }
  .sidebar {
    width: 100%; flex: none; height: auto; position: sticky; top: 0; z-index: 20;
    border-right: none; border-bottom: 1px solid var(--colour-border);
    padding: var(--space-3);
  }
  .brand { padding-bottom: var(--space-3); }
  .nav { flex-direction: row; overflow-x: auto; gap: var(--space-1); }
  .nav a { white-space: nowrap; }
  .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .g3, .g2 { grid-template-columns: minmax(0, 1fr); }
  .span2 { grid-column: auto; }
}

@media (max-width: 767px) {
  .content { padding: var(--space-4); }
  .map, .map-skeleton { height: 340px; }
  .g4 { grid-template-columns: minmax(0, 1fr); }
  .head-facts { margin-left: 0; gap: var(--space-4); }
  .kpi-value { font-size: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

/* --------------------------------------------------------------- training */
/* Training tab: the manual on the left, help chat on the right.
   Everything here reuses the tokens above; the only new ones are the
   highlight washes and a z-index scale, both of which are local to this view. */

:root {
  /* A named scale, so overlay order is a decision rather than a race of
     bigger numbers. The PDF canvas sits at 0. */
  --z-highlight: 10;
  --z-gutter: 20;
  --z-bar: 30;

  /* Washes sit BEHIND the PDF's own black text, so they stay light enough to
     keep that text at full contrast. The cited-source ring carries the
     meaning; colour alone never does, because the gutter marks and the
     citation list say the same thing. */
  --hl-active: rgba(217, 119, 6, .28);
  --hl-active-edge: var(--colour-accent);
  --hl-other: rgba(30, 64, 175, .14);
  --hl-other-edge: var(--colour-secondary);
}

/* The dashboard centres content in a 1440px column. The manual and the chat
   want the whole window instead, so this view opts out of that box. */
.content.content-wide {
  max-width: none;
  height: 100dvh;                 /* dvh, not vh: mobile browser chrome */
  display: flex;
  flex-direction: column;
  padding-bottom: 0;
}
.content-wide .page-head { margin-bottom: var(--space-4); }

/* The height has to be handed down every level or the scroll container grows
   to fit its content instead of scrolling, which silently defeats both the
   lazy page rendering and the gutter's sense of scale. #views and .view are
   built by app.js and carry no layout of their own, so they are opted in here
   rather than changed there. */
.content-wide #views,
.content-wide #views > .view,
.content-wide .training-host {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.content-wide .training-host { gap: var(--space-2); }

.training {
  flex: 1 1 auto;
  min-height: 0;                  /* lets the children scroll instead of the page */
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(360px, 1fr);
  gap: var(--space-4);
  padding-bottom: var(--space-4);
}

.training-pane {
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.pane-bar {
  position: sticky; top: 0; z-index: var(--z-bar);
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--colour-border);
  background: var(--colour-surface);
  min-height: 44px;
  flex: 0 0 auto;
}
.pane-bar h2 { font-size: 13px; margin: 0; font-weight: 600; }
.pane-bar .spacer { margin-left: auto; }
.pane-link {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0 var(--space-3);
  border-radius: var(--radius);
  font-size: 13px; font-weight: 600; text-decoration: none;
}
.pane-link:hover { background: var(--colour-primary-soft); }
/* Also used as a button in the chat bar, where it needs a button's reset. */
button.pane-link { border: 0; background: transparent; font: inherit; font-size: 13px;
  font-weight: 600; color: var(--colour-primary); cursor: pointer; }
button.pane-link:disabled { color: var(--colour-text-muted); opacity: .5; cursor: not-allowed; }
button.pane-link:disabled:hover { background: transparent; }

/* ---- document side */

.doc-wrap { position: relative; flex: 1 1 auto; min-height: 0; display: flex; }

.doc-scroll {
  flex: 1 1 auto; min-width: 0;
  overflow: auto;
  display: flex; flex-direction: column; align-items: center;
  scroll-behavior: smooth;
  background: var(--colour-background);
  padding: var(--space-3);
}
@media (prefers-reduced-motion: reduce) {
  .doc-scroll { scroll-behavior: auto; }
}

/* Each page keeps its aspect ratio before it renders, so the scrollbar and
   the gutter marks are correct from the first paint and nothing jumps when a
   canvas finally arrives (CLS). */
.pdf-page {
  position: relative;
  margin: 0 auto var(--space-3);
  background: #FFFFFF;
  box-shadow: var(--shadow);
  /* Deliberately no max-width. Clamping the page to the pane makes zooming in
     past "fit" a no-op; a zoomed page is meant to overflow and scroll. */
  flex: 0 0 auto;
}
.pdf-page canvas { display: block; width: 100%; height: auto; }

.pdf-page .textLayer {
  position: absolute; inset: 0;
  overflow: hidden;
  opacity: 1;
  line-height: 1;
  forced-color-adjust: none;
}
.pdf-page .textLayer :is(span, br) {
  position: absolute;
  white-space: pre;
  cursor: text;
  transform-origin: 0 0;
  color: transparent;             /* the canvas draws the glyphs; this layer
                                     exists so the text can be selected, found
                                     and read aloud */
}
.pdf-page .textLayer ::selection { background: rgba(59, 130, 246, .35); }

.doc-scroll:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: -3px; }

.hl {
  position: absolute;
  z-index: var(--z-highlight);
  pointer-events: none;
  border-radius: 2px;
  background: var(--hl-other);
  box-shadow: inset 0 0 0 1px var(--hl-other-edge);
}
.hl.hl-active {
  background: var(--hl-active);
  box-shadow: inset 0 0 0 2px var(--hl-active-edge);
}

/* ---- gutter: where every cited passage sits in the whole document */

.gutter {
  position: relative; z-index: var(--z-gutter);
  flex: 0 0 18px;
  border-left: 1px solid var(--colour-border);
  background: var(--colour-surface);
}
.gutter-mark {
  position: absolute; left: 3px; right: 3px;
  min-height: 10px;
  padding: 0; border: 0;
  border-radius: 2px;
  background: var(--hl-other-edge);
  cursor: pointer;
}
.gutter-mark.is-active { background: var(--hl-active-edge); }
/* The visible mark is a few pixels tall, so the hit area is widened invisibly
   rather than the mark being drawn big enough to meet the target size. */
.gutter-mark::after {
  content: ''; position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px;
}
.gutter-mark:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: 1px; }

/* ---- chat side */

.chat-log {
  flex: 1 1 auto; min-height: 0;
  overflow: auto;
  padding: var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-4);
}

/* Who said what. The two sides differ on three axes at once -- side, colour
   and shape -- because colour alone is not a reliable signal and an answer
   that looks like a question is the main way a chat log becomes unreadable. */

.msg-row { display: flex; }
.msg-row-you { justify-content: flex-end; }
.msg-row-udd { justify-content: flex-start; }

.msg { max-width: 88%; }

.msg-you {
  background: var(--colour-primary); color: #FFFFFF;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius) var(--radius) 2px var(--radius);
}

.msg-udd {
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-left: 3px solid var(--colour-secondary);
  border-radius: 2px var(--radius) var(--radius) 2px;
  padding: var(--space-3);
  max-width: 100%;
}

.msg-from {
  font-size: 11px; font-weight: 600; letter-spacing: .05em;
  /* primary, not secondary: #3B82F6 on white is ~3.1:1, which fails at this
     size. The border below can stay the lighter blue, being decorative. */
  text-transform: uppercase; color: var(--colour-primary);
  margin-bottom: var(--space-2);
}

.answer :is(h1, h2, h3) { font-size: 14px; margin: var(--space-4) 0 var(--space-2); }
.answer :is(h1, h2, h3):first-child { margin-top: 0; }
.answer p { margin: 0 0 var(--space-3); }
.answer p:last-child, .answer ol:last-child, .answer ul:last-child { margin-bottom: 0; }
.answer ol, .answer ul { margin: 0 0 var(--space-3); padding-left: var(--space-5); }
.answer li { margin-bottom: var(--space-2); }
.answer li::marker { color: var(--colour-text-muted); font-family: var(--font-value); }
.answer strong { font-weight: 600; }
.answer code {
  font-family: var(--font-value); font-size: 13px;
  background: var(--colour-primary-soft); padding: 1px 4px; border-radius: 3px;
}

.cites { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); }
.cites-label {
  font-size: 12px; font-weight: 600; color: var(--colour-text-muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.cite {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: 44px; width: 100%;
  padding: var(--space-2) var(--space-3);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  font: inherit; color: var(--colour-text); text-align: left;
  cursor: pointer;
  transition: background 150ms ease-out, border-color 150ms ease-out;
}
.cite:hover { background: var(--colour-primary-soft); border-color: var(--colour-border-firm); }
.cite[aria-current='true'] { border-color: var(--colour-accent); background: var(--colour-accent-soft); }
.cite .pg { font-size: 12px; font-weight: 600; color: var(--colour-text-muted); flex: 0 0 auto; }
.cite .ttl { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chip {
  min-height: 44px; padding: var(--space-2) var(--space-3);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border-firm);
  border-radius: 999px;
  font: inherit; font-size: 13px; color: var(--colour-text);
  cursor: pointer; text-align: left;
}
.chip:hover { background: var(--colour-primary-soft); }

/* ---- ask bar */

.ask {
  flex: 0 0 auto;
  display: flex; gap: var(--space-2);
  padding: var(--space-3);
  border-top: 1px solid var(--colour-border);
  background: var(--colour-surface);
}
.ask-field { position: relative; flex: 1 1 auto; min-width: 0; display: flex; align-items: center; }
.ask-field input {
  flex: 1 1 auto; min-width: 0;
  min-height: 44px; padding: 0 var(--space-3) 0 44px;
  border: 1px solid var(--colour-border-firm);
  border-radius: var(--radius);
  font: inherit; font-size: 14px; color: var(--colour-text);
  background: var(--colour-surface);
}
.ask-field input:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: 1px; }

.icon-btn {
  /* relative, because of the ::after below. Without a positioned ancestor an
     absolutely-positioned pseudo-element resolves against the document and
     sits at its static position -- which for a control inside a scrolled pane
     is somewhere far down the page, stretching the document to reach it. */
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  background: transparent; border: 0; border-radius: var(--radius);
  color: var(--colour-text-muted); cursor: pointer;
}
.icon-btn:hover { background: var(--colour-primary-soft); color: var(--colour-primary); }
.icon-btn:disabled { opacity: .4; cursor: not-allowed; }
/* The visible control is 36px; the hit area is padded out to 44px rather than
   drawing a button bigger than it needs to look. */
.icon-btn::after {
  content: ''; position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px;
}
.ask-field > .icon-btn { position: absolute; left: 4px; z-index: 1; }

.ask-send {
  flex: 0 0 auto; min-height: 44px; padding: 0 var(--space-4);
  background: var(--colour-primary); color: #FFFFFF;
  border: 0; border-radius: var(--radius);
  font: inherit; font-weight: 600; cursor: pointer;
}
.ask-send:disabled { background: var(--colour-text-muted); cursor: not-allowed; }

.suggest-panel {
  position: absolute; bottom: calc(100% + 8px); left: 0; right: 0;
  z-index: var(--z-bar);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border-firm);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(15, 23, 42, .12);
  padding: var(--space-2);
  max-height: min(60vh, 460px); overflow-y: auto;
}

.suggest-group + .suggest-group { margin-top: var(--space-2); }
.suggest-group-title {
  margin: 0; padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: 11px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--colour-primary);
  position: sticky; top: calc(var(--space-2) * -1);
  background: var(--colour-surface);
}
.suggest-panel[hidden] { display: none; }
.suggest-item {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; min-height: 44px;
  padding: var(--space-2) var(--space-3);
  background: transparent; border: 0; border-radius: var(--radius);
  font: inherit; font-size: 13px; color: var(--colour-text);
  text-align: left; cursor: pointer;
}
.suggest-item:hover { background: var(--colour-primary-soft); }
.suggest-item .ttl { flex: 1 1 auto; }
.suggest-item .pg { font-size: 12px; color: var(--colour-text-muted); flex: 0 0 auto; }

/* ---- zoom */

.zoom-reset {
  min-width: 52px; height: 36px; padding: 0 var(--space-2);
  background: transparent; border: 0; border-radius: var(--radius);
  font: inherit; font-size: 12px; font-weight: 600;
  color: var(--colour-text-muted); cursor: pointer;
}
.zoom-reset:hover { background: var(--colour-primary-soft); color: var(--colour-primary); }

/* Three dots while the answer is being written. The wait is ~1.2s, long
   enough that silence reads as breakage and short enough that a progress bar
   would be theatre. */
.thinking { display: flex; align-items: center; gap: var(--space-2); color: var(--colour-text-muted); }
.thinking i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--colour-text-muted);
  animation: blip 1.2s ease-in-out infinite;
}
.thinking i:nth-child(2) { animation-delay: .15s; }
.thinking i:nth-child(3) { animation-delay: .3s; }
@keyframes blip { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .thinking i { animation: none; opacity: .6; }
}

/* ---- narrow screens: side by side stops working well below ~1000px, so the
   two panes become one and a pair of tabs switches between them. */

.training-switch { display: none; gap: var(--space-2); }
.training-switch button {
  flex: 1 1 0; min-height: 44px;
  border: 1px solid var(--colour-border-firm); background: var(--colour-surface);
  border-radius: var(--radius); font: inherit; font-weight: 600; cursor: pointer;
}
.training-switch button[aria-selected='true'] {
  background: var(--colour-primary); color: #FFFFFF; border-color: var(--colour-primary);
}

@media (max-width: 1000px) {
  .training { grid-template-columns: minmax(0, 1fr); }
  .training-switch { display: flex; }
  .training[data-show='chat'] .training-pane-doc { display: none; }
  .training[data-show='doc'] .training-pane-chat { display: none; }
}

/* ------------------------------------------------------- sidebar collapse */

/* The toggle sits at the foot of the rail, pushed there by margin-top:auto,
   so it never competes with the logo for the top-left corner. */
.nav-toggle {
  flex: 0 0 auto;
  margin-top: auto;
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; min-height: 44px; padding: 0 var(--space-3);
  background: transparent; border: 0; border-radius: var(--radius);
  border-top: 1px solid var(--colour-border);
  color: var(--colour-text-muted); cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 500;
}
.nav-toggle-icon { flex: 0 0 auto; transition: transform 160ms ease-out; }
body.nav-collapsed .nav-toggle-icon { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .nav-toggle-icon { transition: none; } }
.nav-toggle:hover { background: var(--colour-primary-soft); color: var(--colour-primary); }
.nav-toggle:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: 2px; }

body.nav-collapsed .sidebar { padding-left: var(--space-2); padding-right: var(--space-2); }
body.nav-collapsed .brand { justify-content: center; }
body.nav-collapsed .brand span { display: none; }
body.nav-collapsed .nav-toggle { justify-content: center; padding: 0; gap: 0; }
/* The label is hidden, not removed: it stays the accessible name of the link
   and the tooltip, so a collapsed rail is still navigable and still readable
   to a screen reader. */
body.nav-collapsed .nav a { justify-content: center; padding: 0; gap: 0; }
body.nav-collapsed .nav a .nav-text,
body.nav-collapsed .nav-toggle .nav-text { display: none; }
body.nav-collapsed .nav-flag {
  position: absolute; top: 4px; right: 6px;
  min-width: 16px; height: 16px; font-size: 10px; padding: 0 4px;
}
body.nav-collapsed .nav a { position: relative; }

@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
}

@media (max-width: 720px) {
  /* Below this the rail costs more than it gives, so it is always collapsed
     and the toggle is hidden rather than offering a state that does not fit. */
  :root { --sidebar: 60px; }
  .nav-toggle { display: none; }
  .brand span { display: none; }
  .nav a { justify-content: center; padding: 0; gap: 0; }
  .nav a .nav-text { display: none; }
}

.suggest-empty {
  padding: var(--space-3);
  font-size: 13px; color: var(--colour-text-muted);
}

/* --------------------------------------------------------------- sign in */

/* An overlay, not a page swap: the dashboard shell stays in the DOM so the
   references app.js holds to #nav and #views survive a sign-in. */
body.signed-out .shell { display: none; }

.auth-screen {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5);
  background: var(--colour-background);
  overflow-y: auto;
}

.auth-card {
  width: 100%; max-width: 380px;
  display: flex; flex-direction: column; gap: var(--space-3);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px rgba(15, 23, 42, .10);
  padding: var(--space-6);
}

.auth-brand {
  display: flex; align-items: center; gap: var(--space-2);
  font-weight: 700; font-size: 15px; letter-spacing: -.01em;
  margin-bottom: var(--space-2);
}
.auth-brand svg { color: var(--colour-primary); flex: 0 0 auto; }

.auth-card h1 { font-size: 20px; margin: 0; letter-spacing: -.01em; }
.auth-sub, .auth-hint { margin: 0; font-size: 13px; color: var(--colour-text-muted); }
.auth-hint { margin-top: calc(var(--space-2) * -1); }

.auth-field { display: flex; flex-direction: column; gap: var(--space-1); }
.auth-field label { font-size: 13px; font-weight: 600; }
.auth-field input {
  min-height: 44px; padding: 0 var(--space-3);
  border: 1px solid var(--colour-border-firm);
  border-radius: var(--radius);
  font: inherit; font-size: 14px; color: var(--colour-text);
  background: var(--colour-surface);
}
.auth-field input:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: 1px; }

.auth-error {
  margin: 0; padding: var(--space-2) var(--space-3);
  background: var(--colour-critical-soft);
  border-left: 3px solid var(--colour-critical);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 13px; color: var(--colour-text);
}
.auth-error[hidden] { display: none; }

.auth-submit {
  min-height: 44px; margin-top: var(--space-2);
  background: var(--colour-primary); color: #FFFFFF;
  border: 0; border-radius: var(--radius);
  font: inherit; font-weight: 600; cursor: pointer;
}
.auth-submit:disabled { background: var(--colour-text-muted); cursor: not-allowed; }

/* ------------------------------------------------------------ account row */

.account {
  margin-top: auto;
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--colour-border);
}
/* The collapse control also claims margin-top:auto; once the account panel is
   above it, only one of them may push. */
.account ~ .nav-toggle { margin-top: 0; }

.account-who { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.account-name {
  font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account-meta { font-size: 11px; color: var(--colour-text-muted); }

.account-out {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  background: transparent; border: 0; border-radius: var(--radius);
  color: var(--colour-text-muted); cursor: pointer;
}
.account-out:hover { background: var(--colour-critical-soft); color: var(--colour-critical); }
.account-out:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: 2px; }

body.nav-collapsed .account { justify-content: center; padding: var(--space-2) 0; }
body.nav-collapsed .account-who { display: none; }

/* ------------------------------------------------------ locked (unlicensed) */

/* Faded, but still legible and still reachable by keyboard: the point is to
   show what the package does not include, not to hide it. Opacity alone would
   drop the label under the contrast floor, so the colour is set explicitly
   rather than inherited through a transparency. */
.nav a.nav-locked { color: var(--colour-text-muted); }
.nav a.nav-locked svg { opacity: .55; }
.nav a.nav-locked:hover { background: var(--colour-background); }
.nav a.nav-locked[aria-current='page'] {
  background: var(--colour-background);
  color: var(--colour-text);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--colour-border-firm);
}
.nav-lock { margin-left: auto; display: inline-flex; color: var(--colour-text-muted); }
.nav a.nav-locked[aria-current='page'] .nav-lock { color: var(--colour-accent); }

.locked-view {
  max-width: 560px; margin: var(--space-6) auto;
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-6);
  text-align: center;
}
.locked-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; margin-bottom: var(--space-4);
  border-radius: 50%;
  background: var(--colour-accent-soft); color: var(--colour-accent);
}
.locked-view h2 { font-size: 18px; margin: 0 0 var(--space-2); letter-spacing: -.01em; }
.locked-what {
  margin: 0 0 var(--space-3); font-size: 14px; font-weight: 600;
  color: var(--colour-text);
}
.locked-body { margin: 0 0 var(--space-5); color: var(--colour-text-muted); }

.locked-list {
  text-align: left;
  border-top: 1px solid var(--colour-border);
  padding-top: var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-2);
}
.locked-item {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: 13px;
}
.locked-item svg { flex: 0 0 auto; color: var(--colour-text-muted); align-self: center; }
.locked-item-name { font-weight: 600; flex: 0 0 auto; }
.locked-item-desc {
  color: var(--colour-text-muted); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.locked-contact {
  margin: var(--space-5) 0 0; padding-top: var(--space-4);
  border-top: 1px solid var(--colour-border);
  font-weight: 600;
}

/* ----------------------------------------------------------- administration */

.admin-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

.admin-select {
  min-height: 32px; padding: 0 var(--space-2);
  border: 1px solid var(--colour-border-firm); border-radius: var(--radius);
  background: var(--colour-surface); color: var(--colour-text);
  font: inherit; font-size: 13px;
}
.admin-select:focus-visible { outline: 3px solid var(--colour-secondary); outline-offset: 1px; }

.muted { color: var(--colour-text-muted); font-size: 12px; }

/* The licence x feature grid. Row headers carry the feature name so a screen
   reader announces which permission a checkbox belongs to. */
table.matrix th[scope='row'] { text-align: left; font-weight: 500; }
table.matrix th[scope='row'] .muted { display: block; }
table.matrix td.num { text-align: center; }
table.matrix input[type='checkbox'] { width: 18px; height: 18px; cursor: pointer; }
table.matrix input[type='checkbox']:focus-visible {
  outline: 3px solid var(--colour-secondary); outline-offset: 2px;
}
table.matrix thead .muted { display: block; font-weight: 400; }

/* A one-time password cannot be shown again, so it is given a dialog that has
   to be dismissed rather than a notice that fades on its own. */
.reveal-backdrop {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5);
  background: rgba(15, 23, 42, .45);
}
.reveal {
  width: 100%; max-width: 440px;
  display: flex; flex-direction: column; gap: var(--space-3);
  background: var(--colour-surface);
  border-radius: var(--radius);
  box-shadow: 0 12px 36px rgba(15, 23, 42, .22);
  padding: var(--space-5);
}
.reveal h2 { margin: 0; font-size: 17px; letter-spacing: -.01em; }
.reveal p { margin: 0; font-size: 13px; color: var(--colour-text-muted); }
.reveal-value {
  display: block; padding: var(--space-3);
  background: var(--colour-primary-soft);
  border-radius: var(--radius);
  font-family: var(--font-value); font-size: 15px; font-weight: 600;
  word-break: break-all; user-select: all;
}
.reveal-actions {
  display: flex; justify-content: flex-end; gap: var(--space-2);
  margin-top: var(--space-2);
}
.reveal-actions .tab { min-height: 40px; padding: 0 var(--space-4); }

/* --------------------------------------------------- pdf loading placeholder */

.doc-loading {
  display: flex; align-items: center; justify-content: center; gap: var(--space-3);
  padding: var(--space-6); margin: auto;
  color: var(--colour-text-muted); font-size: 14px;
}
.doc-spinner {
  width: 18px; height: 18px; flex: 0 0 auto;
  border: 2px solid var(--colour-border-firm);
  border-top-color: var(--colour-primary);
  border-radius: 50%;
  animation: doc-spin 700ms linear infinite;
}
@keyframes doc-spin { to { transform: rotate(360deg); } }

/* A page box with no canvas yet is a blank white rectangle, which reads as a
   broken viewer rather than a loading one. The shimmer stops the moment the
   canvas is inserted, because the class goes with it. */
.pdf-page.is-loading {
  background: linear-gradient(100deg,
    #FFFFFF 30%, var(--colour-background) 50%, #FFFFFF 70%);
  background-size: 300% 100%;
  animation: doc-shimmer 1.4s ease-in-out infinite;
}
@keyframes doc-shimmer { to { background-position: -150% 0; } }

@media (prefers-reduced-motion: reduce) {
  .doc-spinner { animation: none; border-top-color: var(--colour-border-firm); }
  .pdf-page.is-loading { animation: none; background: var(--colour-background); }
}

/* ----------------------------------------------------------- exchange summary */

.summary-bar {
  display: flex; justify-content: flex-end;
  margin-top: var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px solid var(--colour-border);
}
.summary-btn {
  position: relative;                 /* containing block for the ::after below */
  min-height: 32px; padding: 0 var(--space-3);
  background: transparent; border: 0; border-radius: var(--radius);
  font: inherit; font-size: 12px; font-weight: 600;
  color: var(--colour-primary); cursor: pointer;
}
.summary-btn:hover { background: var(--colour-primary-soft); }
.summary-btn:disabled { color: var(--colour-text-muted); cursor: not-allowed; }
/* 32px tall to sit quietly under an answer, with the hit area padded out to
   the 44px minimum rather than drawing a button that large. */
.summary-btn::after {
  content: ''; position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px;
}

.summary {
  margin-top: var(--space-3);
  padding: var(--space-3);
  background: var(--colour-background);
  border-left: 3px solid var(--colour-accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.summary[hidden] { display: none; }
.summary-label {
  font-size: 11px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--colour-accent-text);
  margin-bottom: var(--space-2);
}
.summary .answer { font-size: 13px; }

/* PDF.js appends this to <body> as scratch space for measuring text. It is
   zero-height but display:inline, so it takes a line box of its own after the
   950px shell and makes the whole page scroll by ~21px. Taking it out of flow
   fixes that without removing it: the text layer still needs to measure
   against it, so it is positioned away rather than display:none. */
canvas.hiddenCanvasElement {
  position: absolute;
  top: 0; left: 0;
  width: 0; height: 0;
  visibility: hidden;
  pointer-events: none;
}

/* --------------------------------------------------------------- embedded */

/* Mounted inside another product's page: it supplies the navigation, the
   header and the account menu, so ours would be a second set of all three. */
body.embed .sidebar,
body.embed .page-head,
body.embed .account,
body.embed .nav-toggle { display: none; }
body.embed .content.content-wide { padding: 0; }
body.embed .training { padding-bottom: 0; }
