/* ═══════════════════════════════════════════════════════════════════════════
   AI Analyst — RAISON

   The Data & AI department's own system, not a new one: indigo #4f46e5 and
   sky #0ea5e9 on white with a dotted grid, DM Sans — "Style B" from the
   division deck (02_Areas/Data_Automation/.../Round3). The app is the
   department's product, so it wears the department's colours.

   Structure still comes from hairlines and space rather than shadows or
   floating grey cards, and numbers still carry the page: set large, in
   tabular figures, with a qualifier that says which figure they are.

   Fonts are self-hosted (CSP forbids every external origin). English sets in
   DM Sans, Arabic in IBM Plex Sans Arabic; the page switches as a whole and
   the two never mix in one view. RAISON's wordmark sets in Michroma.

   Every directional property is LOGICAL (inline-start/end, padding-inline), and
   the few directional GLYPHS are flipped explicitly under [dir="rtl"], so the
   Arabic layout is this stylesheet mirrored rather than a second one.
   ═══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: "DM Sans";
  src: url("/static/fonts/DMSans-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("/static/fonts/DMSans-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  src: url("/static/fonts/IBMPlexSansArabic-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  src: url("/static/fonts/IBMPlexSansArabic-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  /* surface — white with the deck system's dotted grid */
  --paper:        #ffffff;
  --paper-raised: #ffffff;
  --paper-sunk:   #f8fafc;

  /* ink */
  --ink:          #0f172a;
  --ink-soft:     #475569;
  --ink-faint:    #94a3b8;

  /* structure */
  --rule:         #e2e8f0;
  --rule-strong:  #cbd5e1;

  /* RAISON: indigo primary, sky secondary — kept in lockstep with charts.py */
  --accent:       #4f46e5;
  --accent-2:     #0ea5e9;
  --accent-soft:  #0ea5e9;
  --accent-wash:  #eef2ff;

  /* semantics */
  --positive:     #15803d;
  --negative:     #b91c1c;
  --flag:         #b45309;
  --flag-wash:    #fffbeb;

  --measure:      1180px;
  --radius:       3px;
}

* { box-sizing: border-box; }

html {
  background: var(--paper);
  color: var(--ink);
  /* The deck system's dotted grid, drawn as a radial-gradient — no image and
     no network request, which the CSP would refuse anyway. */
  background-image: radial-gradient(circle, #e2e8f0 1px, transparent 1px);
  background-size: 22px 22px;
  background-position: -1px -1px;
}

html[lang="en"] body { font-family: "DM Sans", sans-serif; }
html[lang="ar"] body { font-family: "IBM Plex Sans Arabic", sans-serif; }

body {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Every figure in the product is tabular: columns of numbers must align, and
   a digit must never change width as a value updates. */
.figure, .tile-value, .stat-value, table td, table th,
.prov-strip, .spark-wrap, .qa-sentence { font-variant-numeric: tabular-nums; }

a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 1px;
}

h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.018em; }
p { margin: 0 0 .8rem; }

/* ── the micro-label: uppercase, tracked, used for every eyebrow and caption ─
   Arabic does not have letter case, and tracking damages joined script — so
   the treatment applies to the Latin page only and Arabic gets weight and
   colour instead. */
.eyebrow {
  font-size: 10.5px;
  color: var(--ink-faint);
  font-weight: 700;
  line-height: 1.3;
}
html[lang="en"] .eyebrow { text-transform: uppercase; letter-spacing: .15em; }
html[lang="ar"] .eyebrow { font-size: 11.5px; letter-spacing: 0; }

/* ═══ header ═══════════════════════════════════════════════════════════════ */

.site-header {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0 1.75rem;
  height: 60px;
  border-block-end: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  position: sticky;
  top: 0;
  z-index: 20;
}

.brand {
  display: flex;
  align-items: center;
  gap: .7rem;
  white-space: nowrap;
}
/* The wordmark is outlined paths inheriting currentColor, so it is a single
   flat colour and stays crisp at any size. 12px cap height keeps it clearly
   subordinate to the page's own headings. */
.brand-mark { color: var(--accent); display: flex; }
.brand-mark svg { height: 12px; width: auto; display: block; }
.brand-sep {
  width: 1px;
  height: 15px;
  background: var(--rule-strong);
  flex: none;
}
.brand-product {
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.nav-links { display: flex; gap: .25rem; margin-inline-start: 1rem; }
.nav-links a {
  padding: .3rem .7rem;
  font-size: 14px;
  color: var(--ink-soft);
  border-radius: var(--radius);
}
.nav-links a:hover { color: var(--ink); background: var(--paper-sunk); }
.nav-links a[aria-current="page"] { color: var(--ink); font-weight: 700; }

.header-actions {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: 1rem;
}

.lang-toggle { display: flex; align-items: center; gap: .1rem; }
.lang-form { margin: 0; display: inline; }
.lang-btn {
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 700;
  color: var(--ink-faint);
  padding: .25rem .45rem;
  border-radius: var(--radius);
}
.lang-btn:hover { color: var(--ink); background: var(--paper-sunk); }
.lang-btn.active { color: var(--accent); }
.lang-sep { color: var(--rule-strong); font-size: 12px; }

.logout-form { margin: 0; }
.logout-form button, .promote-form button {
  background: none;
  border: 1px solid var(--rule-strong);
  color: var(--ink-soft);
  font: inherit; font-size: 13px;
  padding: .3rem .8rem;
  border-radius: var(--radius);
  cursor: pointer;
}
.logout-form button:hover, .promote-form button:hover {
  border-color: var(--ink-soft); color: var(--ink);
}

main.content {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 2.5rem 1.75rem 5rem;
}

/* ═══ the board ════════════════════════════════════════════════════════════ */

.board-lede {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
  margin-block-end: 2.25rem;
}
.board-lede h1 { font-size: 27px; }
.board-stamp { font-size: 12.5px; color: var(--ink-faint); }
.board-stamp b { color: var(--ink-soft); font-weight: 700; }

.board-section { margin-block-end: 2.75rem; }

/* Section heading sits ON the hairline: label, then the rule runs to the edge.
   Cheaper and calmer than boxing each section. */
.board-section h2 {
  display: flex;
  align-items: center;
  gap: .9rem;
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft);
  margin-block-end: 1rem;
}
html[lang="en"] .board-section h2 { text-transform: uppercase; letter-spacing: .16em; }
html[lang="ar"] .board-section h2 { font-size: 13px; letter-spacing: 0; }
.board-section h2::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* Hairlines are drawn by the tiles themselves (block-end + inline-end), with
   the container supplying the opening two edges. The obvious alternative — a
   1px grid gap over a rule-coloured background — paints every EMPTY cell in
   the last row as a solid block, so a section with 3 cards in a 4-wide grid
   renders a dark slab where nothing exists. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(252px, 1fr));
  gap: 0;
  border-block-start: 1px solid var(--rule);
  border-inline-start: 1px solid var(--rule);
}

/* Tiles share hairlines via a 1px grid gap over a rule-coloured background —
   one continuous ledger of figures rather than 25 floating boxes. */
.card-tile {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  min-height: 148px;
  padding: 1rem 1.1rem 1.05rem;
  background: var(--paper-raised);
  border-block-end: 1px solid var(--rule);
  border-inline-end: 1px solid var(--rule);
  position: relative;
  transition: background .12s ease;
  animation: tile-in .34s ease-out both;
}
.card-tile:hover { background: var(--paper-sunk); }
/* The accent bar on hover is a 2px inline-start rule — it grows from the
   edge, so it reads as the row being selected in a ledger. */
.card-tile::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform .16s ease;
}
.card-tile:hover::before, .card-tile:focus-visible::before { transform: scaleY(1); }

/* Two lines' worth of reserved height so the figures below sit on a shared
   baseline across a row — titles wrap at different lengths, and a ledger whose
   numbers stagger up and down is harder to scan than one that does not. */
.tile-title {
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.01em;
  min-height: 2.7em;
}

/* The figure sits directly under the (fixed-height) title, so every number in
   a row shares one baseline whether or not that card has a sparkline. The
   spark is what absorbs the slack, pinned to the floor of the tile. */
.tile-figure { margin-block-start: 0; }

.tile-value {
  font-size: 25px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.035em;
}
.tile-label {
  font-size: 11.5px;
  color: var(--ink-soft);
  margin-block-start: .15rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The qualifier — "highest", "latest", "rows". Without it a tile figure could
   be mistaken for a total, which it never is. */
.tile-caption { color: var(--accent); }

.spark-wrap { margin-block-start: auto; padding-block-start: .5rem; height: 30px; }
.spark { display: block; }

.tile-empty, .tile-failed {
  font-size: 12.5px;
  color: var(--ink-faint);
  margin-block-start: auto;
}
.tile-failed { color: var(--negative); }

@keyframes tile-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ═══ card page ════════════════════════════════════════════════════════════ */

.back-link { margin-block-end: 1.25rem; font-size: 13px; }
.back-link a { color: var(--ink-soft); }
.back-link a:hover { color: var(--accent); }

.card-page-header {
  display: flex;
  align-items: center;
  gap: .9rem;
  flex-wrap: wrap;
  margin-block-end: 1.5rem;
}
.card-page-header h1 { font-size: 25px; }

.badge-approved, .badge-novel {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: 11px;
  font-weight: 700;
  padding: .25rem .6rem;
  border-radius: 100px;
  white-space: nowrap;
}
html[lang="en"] .badge-approved, html[lang="en"] .badge-novel {
  text-transform: uppercase; letter-spacing: .1em;
}
/* Icon AND label carry the state, never colour alone — but the ICON ALREADY
   LIVES IN THE TRANSLATED STRING ("✅ Approved answer" / "⚠️ Novel query —
   unverified"), so adding a pseudo-element here renders a double tick. Colour
   and shape only; i18n owns the glyph. */
.badge-approved { background: var(--accent-wash); color: var(--accent); }
.badge-novel { background: var(--flag-wash); color: var(--flag); }

.chart-box {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  padding: 1.5rem;
  overflow-x: auto;
}
.chart-box svg { max-width: 100%; height: auto; display: block; }

.draft-banner {
  background: var(--flag-wash);
  border-inline-start: 3px solid var(--flag);
  color: var(--flag);
  padding: .7rem 1rem;
  font-size: 13.5px;
  margin-block-end: 1.25rem;
}

.card-error {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-inline-start: 3px solid var(--negative);
  color: var(--negative);
  padding: 1rem 1.15rem;
  font-size: 14px;
}

/* ── provenance: a strip, not a form ───────────────────────────────────────
   Six labelled facts that must always be visible but must never outweigh the
   answer. Set small, in a single ruled band under the chart. */
.provenance {
  margin-block-start: 1.25rem;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  padding: .9rem 1.15rem;
}
.provenance h3 {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--ink-faint);
  margin-block-end: .7rem;
}
html[lang="en"] .provenance h3 { text-transform: uppercase; letter-spacing: .15em; }

.provenance dl {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
  gap: .75rem 1.5rem;
}
.provenance dt {
  font-size: 10.5px;
  color: var(--ink-faint);
  font-weight: 700;
  margin-block-end: .15rem;
}
html[lang="en"] .provenance dt { text-transform: uppercase; letter-spacing: .1em; }
.provenance dd {
  margin: 0;
  font-size: 13px;
  color: var(--ink);
  line-height: 1.4;
}
.provenance dt.dq-note, .provenance dd.dq-note { color: var(--flag); }
.provenance dd.dq-note { grid-column: 1 / -1; }

.sql-details {
  margin-block-start: 1.25rem;
  border-block-start: 1px solid var(--rule);
  padding-block-start: .9rem;
}
.sql-details summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--ink-faint);
  font-weight: 700;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .4rem;
}
html[lang="en"] .sql-details summary { text-transform: uppercase; letter-spacing: .12em; }
.sql-details summary::-webkit-details-marker { display: none; }
/* A chevron is a DIRECTIONAL GLYPH, not a layout property — logical CSS does
   not flip it. Pointing right on an Arabic page means pointing backwards. */
.sql-details summary::before { content: "▸"; color: var(--accent); font-size: 10px; }
html[dir="rtl"] .sql-details summary::before { content: "◂"; }
.sql-details[open] summary::before,
html[dir="rtl"] .sql-details[open] summary::before { content: "▾"; }
.sql-details summary:hover { color: var(--ink-soft); }
.sql-details pre {
  margin: .8rem 0 0;
  padding: 1rem 1.15rem;
  background: var(--paper-sunk);
  border-inline-start: 2px solid var(--rule-strong);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-soft);
  overflow-x: auto;
  /* SQL is LTR even on the Arabic page — mirroring it makes it unreadable. */
  direction: ltr;
  text-align: left;
}

/* ═══ ask — the conversation ═══════════════════════════════════════════════ */

/* The composer sits at the bottom of the VIEWPORT on a short thread and at the
   bottom of the CONTENT once the conversation outgrows the screen — so an
   empty chat does not leave the input stranded halfway up a blank page. */
.ask-page {
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 60px - 7.5rem);
}
/* Clearance so the sticky composer never sits on top of the last answer's
   "Show the SQL" row. */
.thread { flex: 1; padding-block-end: 1.5rem; }

.ask-lede { margin-block-end: 1.75rem; }
.ask-lede h1 { font-size: 25px; margin-block-end: .4rem; }
.ask-lede p { color: var(--ink-soft); font-size: 14px; margin: 0; }

/* Suggestion chips — the 25 approved questions are the best possible prompt
   library, so the empty state hands four of them over instead of showing a
   blank box and hoping. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-block-end: 2rem;
}
.chip {
  border: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  color: var(--ink-soft);
  font: inherit;
  font-size: 13px;
  text-align: start;
  padding: .5rem .85rem;
  border-radius: 100px;
  cursor: pointer;
  transition: border-color .12s ease, color .12s ease;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }

.thread { display: flex; flex-direction: column; gap: 2.25rem; }
/* Each chip is its own one-field form (no JavaScript anywhere in this app);
   display:contents lets the buttons pack as flex items instead of the forms
   wrapping as blocks and leaving ragged holes. */
.chips form { display: contents; }

.qa-entry {
  display: flex;
  flex-direction: column;
  gap: .9rem;
  animation: tile-in .3s ease-out both;
}

/* The question reads as something the person said: set in the accent, on the
   inline-end side, with a rule under it. Not a chat bubble — bubbles would
   fight the ledger language of the rest of the product. */
.qa-question {
  align-self: flex-end;
  max-width: 88%;
  margin: 0;
  padding: .55rem 0 .6rem;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--accent);
  text-align: end;
  border-block-end: 2px solid var(--accent-wash);
}

.qa-answer {
  display: flex;
  flex-direction: column;
  gap: .9rem;
}

/* The sentence IS the answer. Everything else on the page supports it. */
.qa-sentence {
  margin: 0;
  font-size: 18px;
  line-height: 1.5;
  letter-spacing: -0.012em;
}

.qa-meta { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }

/* Composer pinned to the bottom of the viewport: a chat you can keep typing
   into without scrolling back. */
.composer {
  position: sticky;
  bottom: 0;
  margin-block-start: 2.5rem;
  padding-block: 1rem;
  background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, var(--paper) 22%);
}
.ask-form {
  display: flex;
  gap: .6rem;
  align-items: stretch;
}
.ask-form input[type="text"] {
  flex: 1;
  font: inherit;
  font-size: 15px;
  padding: .8rem 1rem;
  border: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  color: var(--ink);
  border-radius: var(--radius);
}
.ask-form input[type="text"]::placeholder { color: var(--ink-faint); }
.ask-form input[type="text"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
.ask-form button[type="submit"] {
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  padding: .8rem 1.5rem;
  background: var(--ink);
  color: var(--paper-raised);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  cursor: pointer;
  white-space: nowrap;
}
.ask-form button[type="submit"]:hover { background: var(--accent); border-color: var(--accent); }

.thread-empty {
  border: 1px dashed var(--rule-strong);
  padding: 2rem 1.5rem;
  text-align: center;
  color: var(--ink-faint);
  font-size: 14px;
}

/* ═══ auth ═════════════════════════════════════════════════════════════════ */

.auth-card {
  max-width: 360px;
  margin: 7vh auto 0;
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  padding: 2.25rem 2rem;
}
.auth-card h1 { font-size: 21px; margin-block-end: 1.5rem; }
.auth-card label {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--ink-faint);
  margin-block-end: .3rem;
}
html[lang="en"] .auth-card label { text-transform: uppercase; letter-spacing: .12em; }
.auth-card input[type="text"], .auth-card input[type="password"] {
  width: 100%;
  font: inherit;
  padding: .65rem .8rem;
  margin-block-end: 1.1rem;
  border: 1px solid var(--rule-strong);
  background: var(--paper);
  color: var(--ink);
  border-radius: var(--radius);
}
.auth-card input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
.auth-card button[type="submit"] {
  width: 100%;
  font: inherit;
  font-weight: 700;
  padding: .7rem;
  background: var(--ink);
  color: var(--paper-raised);
  border: 0;
  border-radius: var(--radius);
  cursor: pointer;
}
.auth-card button[type="submit"]:hover { background: var(--accent); }
.error {
  color: var(--negative);
  font-size: 13.5px;
  margin-block-end: 1rem;
}

/* ═══ admin ════════════════════════════════════════════════════════════════ */

.admin-page h1 { font-size: 25px; margin-block-end: 1.5rem; }
.admin-section { margin-block-end: 2.5rem; }
.admin-section h2 {
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft);
  margin-block-end: .9rem;
}
html[lang="en"] .admin-section h2 { text-transform: uppercase; letter-spacing: .16em; }

.admin-table-wrap { overflow-x: auto; border: 1px solid var(--rule); }
.admin-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--paper-raised);
  font-size: 13px;
}
.admin-table th {
  text-align: start;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--ink-faint);
  padding: .7rem .9rem;
  border-block-end: 1px solid var(--rule-strong);
  white-space: nowrap;
}
html[lang="en"] .admin-table th { text-transform: uppercase; letter-spacing: .1em; }
.admin-table td {
  padding: .65rem .9rem;
  border-block-end: 1px solid var(--rule);
  vertical-align: top;
}
.admin-table tbody tr:last-child td { border-block-end: 0; }
.admin-empty { color: var(--ink-faint); font-size: 13.5px; }

/* ═══ motion ═══════════════════════════════════════════════════════════════ */

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

/* ═══ narrow screens ═══════════════════════════════════════════════════════ */

@media (max-width: 640px) {
  .site-header { padding-inline: 1rem; gap: .75rem; }
  .nav-links { margin-inline-start: 0; }
  main.content { padding: 1.75rem 1rem 4rem; }
  .card-grid { grid-template-columns: 1fr; }
  .board-lede h1, .card-page-header h1, .ask-lede h1 { font-size: 21px; }
  .qa-question { max-width: 100%; }
}
