
/* report.web.css — DO NOT EDIT BY HAND.
   Generated from style/design_tokens.yaml + style/templates/web/report.web.css.j2.
   Run: python scripts/extract_style.py --render-web
*/

@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Brand + semantic colour tokens — shared with the PDF stylesheet. */
  --color-text:            #000000;
  --color-text-muted:      #737377;
  --color-surface:         #FFFFFF;
  --color-surface-shaded:  #EBF5FF;
  --color-rule:            #E0E0E0;
  --color-pill-bg:         #0000FF;
  --color-pill-fg:         #FFFFFF;
  --color-heading:         #0000FF;
  --color-table-header-bg: #000080;
  --color-current-period:  #EBF5FF;
  --color-accent:          #28F9FF;
  --color-accent-alt:      #8F00FF;
  --color-cover-bg:        #000000;
  --color-chrome:          #0A0A23;

  /* Spacing + radius — shared. */
  --spacing-xs:  0.15em;
  --spacing-sm:  0.25em;
  --spacing-md:  0.4em;
  --spacing-lg:  0.6em;
  --spacing-xl:  0.9em;
  --spacing-2xl: 1.5em;
  --radius-pill: 1em;

  /* Type scale — body / small / footer reused from the deck tokens.
     Heading sizes use clamp() for fluid scaling; the deck values
     (cover_title 96pt, hero_title 39pt, hero_value 80pt) are the
     desktop ceiling. */
  --font-heading: 'Inter', system-ui, sans-serif;
  --font-body:    'Inter', system-ui, sans-serif;
  --size-body:    1rem;
  --size-small:   0.875rem;
  --size-footer:  0.75rem;
  --size-h1:      clamp(1.75rem, 1.2rem + 2.5vw, 2.5rem);
  --size-h2:      clamp(1.375rem, 1rem + 1.6vw, 1.75rem);
  --size-h3:      clamp(1.125rem, 0.95rem + 0.8vw, 1.375rem);
  --size-pill:    clamp(1.125rem, 0.9rem + 1.2vw, 1.5rem);
  --size-hero:    clamp(2rem, 1.4rem + 3vw, 3rem);
  --size-hero-value: clamp(2.25rem, 1.6rem + 4vw, 3.75rem);
  --size-cover-title: clamp(2rem, 1.5rem + 4vw, 4.25rem);
  --line-height: 1.65;

  /* Layout. */
  --measure: 70ch;             /* comfortable reading width */
  --gutter: 1.25rem;
  --gutter-lg: 2rem;
  --content-max: 64rem;
  --header-height: 3.5rem;
  --transition: 200ms ease;

  /* Statement-table border weights + indent — shared semantics with the
     PDF stylesheet (#123). Borders are pt in PDF, px on web; for screen
     rendering at typical zoom levels 1px / 3px reads as 1pt / 3pt and
     avoids sub-pixel artifacts. Indent + pad use the same em-relative
     values as the PDF (cell_pad_em 0.7, cell_indent_em 2.2 — measured
     from the reference, see docs/TABLE_STYLE_RESEARCH.md §1). */
  --rule-subtotal: 1px;
  --rule-major:    3px;
  --cell-pad:      0.7em;
  --cell-indent:   2.2em;
}

@media (min-width: 1024px) {
  :root {
    --gutter: 2rem;
    --gutter-lg: 3rem;
    --header-height: 4rem;
  }
}

/* ---------- Reset + base ------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--size-body);
  line-height: var(--line-height);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* The report body is wrapped in `.dwf-report` (base.html) so its bare
   element rules stay scoped and cannot bleed into the captured global site
   nav (`.dwf-site-nav`, #186) sitting above it — nor the nav's own inlined
   styles into the report. Keep page-level rules (`*`, `html`, `body`,
   `:focus-visible`) global; scope every content-element rule under
   `.dwf-report`. The CSS-scoping BDD scenario (site_nav.feature) is the
   strict guard on this boundary. */
.dwf-report img, .dwf-report picture { max-width: 100%; height: auto; display: block; }
.dwf-report a { color: var(--color-pill-bg); text-decoration: underline; text-underline-offset: 0.15em; }
.dwf-report a:hover, .dwf-report a:focus-visible { text-decoration-thickness: 2px; }
/* Buttons are <a class="btn ...">; the blanket link rule above (specificity
   0,1,1) would otherwise repaint their text the blue link colour and underline
   them — blue-on-blue on .btn-primary's blue background (#191). Re-assert the
   button look at higher specificity (`.dwf-report a.btn*` = 0,2,1) so buttons
   keep their own styling without inflating the link rule (which would override
   the 0,2,0 nav/TOC link rules and turn those blue+underlined). */
.dwf-report a.btn { text-decoration: none; }
.dwf-report a.btn-primary { color: var(--color-pill-fg); }
/* Chat source chips are <a class="chat-citation"> inside .dwf-report, so the
   same blanket link rule repaints their text the blue pill colour — blue-on-
   blue on the chip's blue background (#174/#191). Re-assert the chip text at
   higher specificity (0,2,1), like the button above. */
.dwf-report a.chat-citation { color: var(--color-pill-fg); text-decoration: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.dwf-report h1, .dwf-report h2, .dwf-report h3, .dwf-report h4 {
  font-family: var(--font-heading);
  color: var(--color-heading);
  line-height: 1.2;
  margin: 0 0 var(--spacing-md) 0;
  font-weight: 700;
}
.dwf-report h1 { font-size: var(--size-h1); }
.dwf-report h2 { font-size: var(--size-h2); }
.dwf-report h3 { font-size: var(--size-h3); }
.dwf-report p  { margin: 0 0 var(--spacing-lg) 0; }

.skip-to-content {
  position: absolute;
  top: -40px; left: 0;
  background: var(--color-pill-bg);
  color: var(--color-pill-fg);
  padding: 0.5rem 1rem;
  z-index: 1000;
  transition: top var(--transition);
}
.skip-to-content:focus { top: 0; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* ---------- Site chrome (header + footer) ------------------------------- */

.site-header {
  position: sticky; top: 0; z-index: 50;
  /* Dark site chrome, matching the captured global nav above it (#191). */
  background: var(--color-chrome);
  color: var(--color-pill-fg);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  min-height: var(--header-height);
}

/* Anchor-link targets must sit below the sticky header — without this,
   clicking an in-page link (e.g. the on-this-page dropdown's "Note 3")
   scrolls the heading underneath the header chrome and out of view.
   `:where()` keeps specificity at 0 so individual blocks can override. */
:where(h1, h2, h3, h4, h5, h6) {
  scroll-margin-top: calc(var(--header-height) + 1rem);
}
.site-header-inner {
  display: flex;
  align-items: center;
  gap: var(--spacing-lg);
  /* Header chrome spans the full viewport width (with edge padding)
     so the chapter nav has room to lay out side-by-side regardless
     of the content column. The main `.site-main` block keeps its
     `max-width: var(--content-max)` for prose readability. */
  margin: 0 auto;
  padding: 0 var(--gutter);
  min-height: var(--header-height);
  max-width: 1600px;
}
/* The brand (logo + company name) moved to the global site nav above this
   header (#186), where the logo links home. The report header is now
   section-nav only, so `.site-brand` rules are gone — the chapter nav
   left-aligns and the actions sit at the right (see the desktop block). */

.nav-toggle {
  margin-left: auto;
  background: transparent; border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 0.25rem;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  color: var(--color-pill-fg);
}
.nav-toggle-icon {
  display: block; width: 18px; height: 2px;
  background: currentColor;
  position: relative;
}
.nav-toggle-icon, .nav-toggle-icon::before, .nav-toggle-icon::after {
  transition: transform var(--transition), top var(--transition),
              background var(--transition);
}
.nav-toggle-icon::before, .nav-toggle-icon::after {
  content: ''; position: absolute; left: 0; right: 0; height: 2px;
  background: currentColor;
}
.nav-toggle-icon::before { top: -6px; }
.nav-toggle-icon::after  { top:  6px; }
/* Morph the three bars into an X while the menu is open, matching the live
   site's close icon (#191). */
.nav-toggle[aria-expanded="true"] .nav-toggle-icon { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-icon::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-icon::after  { top: 0; transform: rotate(-45deg); }

.primary-nav {
  display: none;
  flex: 1;
}
.primary-nav > ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.25rem 1rem;
}
.primary-nav > ul > li {
  position: relative;
}
.primary-nav a {
  display: inline-block;
  padding: 0.4rem 0.5rem;
  color: var(--color-pill-fg);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.primary-nav a:hover, .primary-nav a:focus-visible {
  color: var(--brand-orange);
}
.primary-nav a[aria-current="page"] {
  color: var(--brand-orange);
  border-bottom-color: transparent;
}

/* Disclosure for grouped chapters (e.g. Financial statements). On
   desktop the parent's hover/focus exposes the sub-list as a dropdown
   panel; on mobile the panel renders inline (handled in the
   data-open block below). The CSS-only disclosure keeps the chrome
   accessible without JS, but the parent <a> is still a real link to
   the first sub-chapter so click-through stays usable on touch. */
.primary-nav .has-children > a::after {
  content: '';
  display: inline-block;
  margin-left: 0.4em;
  border: 4px solid transparent;
  border-top-color: currentColor;
  vertical-align: 0.15em;
}
.primary-nav-sub {
  list-style: none; margin: 0; padding: 0;
}
@media (min-width: 1024px) {
  .primary-nav .has-children > .primary-nav-sub {
    position: absolute;
    top: 100%; left: 0;
    min-width: 16rem;
    background: var(--color-chrome);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 0.375rem;
    padding: 0.5rem 0;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--transition), transform var(--transition);
    z-index: 51;
  }
  .primary-nav .has-children:hover > .primary-nav-sub,
  .primary-nav .has-children:focus-within > .primary-nav-sub {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }
  .primary-nav-sub li a {
    display: block;
    padding: 0.45rem 1rem;
    border-bottom: 0;
    white-space: normal;
  }
}

/* Visible at EVERY width (#228). The language switcher and the PDF download
   are the only route to the other language and to the report file, and
   `.site-actions` is a SIBLING of `#primary-nav` -- so the hamburger, which
   targets `#primary-nav`, can never reveal them. This was `display: none`
   below 1024px with no mobile counterpart, leaving phones and tablets with
   neither control and no way to reach either. */
.site-actions {
  display: inline-flex;
  align-items: center; gap: 0.75rem;
  margin-left: auto;
}

.lang-switcher {
  display: inline-flex; gap: 0.25rem;
  font-size: var(--size-small);
}
.lang-switcher a, .lang-switcher .lang-disabled {
  padding: 0.25rem 0.5rem;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.7);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}
.lang-switcher a:hover, .lang-switcher a:focus-visible { color: var(--brand-orange); }
.lang-switcher a[aria-current="true"] { color: var(--brand-orange); }
.lang-switcher .lang-disabled {
  opacity: 0.5; cursor: not-allowed;
}

.btn {
  display: inline-block;
  padding: 0.55rem 1rem;
  border-radius: 0.375rem;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--size-small);
  text-decoration: none;
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.btn-primary {
  background: var(--color-pill-bg);
  color: var(--color-pill-fg);
}
.btn-primary:hover, .btn-primary:focus-visible {
  background: var(--color-text);
}
.btn-secondary {
  background: transparent;
  color: var(--color-pill-bg);
  border-color: var(--color-pill-bg);
}
.btn-secondary:hover, .btn-secondary:focus-visible {
  background: var(--color-pill-bg);
  color: var(--color-pill-fg);
}
/* The nav "Download PDF" button (a .btn-primary) fills white with inverted
   dark text on hover, matching the white-fill hover of the outline buttons
   on digitalworkforce.com — instead of darkening to near-black. Scoped
   `.dwf-report a.download-pdf` (0,3,1) so it outranks `.dwf-report
   a.btn-primary` (0,2,1, line ~129) which would otherwise keep the text white. */
.dwf-report a.download-pdf:hover, .dwf-report a.download-pdf:focus-visible {
  background: var(--color-pill-fg);
  color: var(--color-text);
}

/* Mobile-collapsed nav toggled by JS via aria-expanded. */
.primary-nav[data-open="true"] {
  display: block;
  position: absolute;
  top: var(--header-height); left: 0; right: 0;
  /* Dark panel matching the section nav — its links are white, so a white
     panel would be white-on-white (#191). */
  background: var(--color-chrome);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  padding: var(--gutter);
  max-height: calc(100vh - var(--header-height));
  overflow-y: auto;
}
.primary-nav[data-open="true"] > ul {
  flex-direction: column; gap: 0;
}
/* Top-level items mirror the live digitalworkforce.com hamburger menu: white,
   UPPERCASE, bold, large, generously spaced, no separator lines (#191). */
.primary-nav[data-open="true"] a {
  display: block; padding: 0.4rem 0;
  border-bottom: none;
  white-space: normal;
}
.primary-nav[data-open="true"] > ul > li > a {
  text-transform: uppercase;
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: 0.01em;
  padding: 0.85rem 0;
}
/* Chevron pushed to the right edge for items with a submenu, as on the
   live site. The base caret (a CSS triangle in currentColor) is re-shown. */
.primary-nav[data-open="true"] .has-children > a {
  display: flex; align-items: center; justify-content: space-between;
}
.primary-nav[data-open="true"] .has-children > a::after {
  display: inline-block; margin-left: 0.5em;
}
.primary-nav[data-open="true"] .primary-nav-sub {
  padding-left: 1rem;
  border-left: 2px solid rgba(255, 255, 255, 0.14);
  margin: 0.25rem 0 0.75rem 0.25rem;
}
.primary-nav[data-open="true"] .primary-nav-sub a {
  font-size: var(--size-small);
  font-weight: 500;
  text-transform: none;
  padding: 0.5rem 0;
}

@media (min-width: 1024px) {
  .nav-toggle { display: none; }
  /* No brand on the left any more (#186): the chapter nav fills from the
     left and the actions (lang + PDF) sit at the right. */
  .primary-nav { display: block; }
  .primary-nav ul { justify-content: flex-start; }
}

/* Below the desktop breakpoint the hamburger, EN/FI and the PDF button share
   a ~350px bar on a phone. The button gives up padding and type size so all
   three fit without the header overflowing sideways (#228). */
@media (max-width: 1023px) {
  .site-actions { gap: 0.4rem; }
  .site-actions .download-pdf {
    padding: 0.4rem 0.7rem;
    font-size: var(--size-small);
    white-space: nowrap;
  }
  .lang-switcher a, .lang-switcher .lang-disabled { padding: 0.25rem 0.35rem; }
}

/* The report footer is now the global Digital Workforce footer
   (style/templates/web/_site_footer.html, #191) — site chrome rendered
   OUTSIDE `.dwf-report` with its own inlined stylesheet, like the captured
   site nav. So the old `.site-footer` report-only rules are gone. */

.correction-notice {
  background: var(--color-surface-shaded);
  border-left: 4px solid var(--color-pill-bg);
  padding: var(--spacing-md) var(--gutter);
  margin: 0;
  font-size: var(--size-small);
}
.correction-notice p { margin: 0; }

/* ---------- Page shell -------------------------------------------------- */

.site-main {
  display: block;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--spacing-xl) var(--gutter);
}

/* Breadcrumb trail (#185) — wires the report into the live IR taxonomy.
   Sits at the top of <main>, inheriting its content width. The final
   crumb is the current page: a non-linked <span aria-current="page">. */
/* Dark full-width breadcrumb bar, sitting just under the section nav so the
   whole header region follows the site colour scheme (#191). Rendered above
   <main> (base.html) so it spans the viewport; the list re-centres to the same
   max-width as the section-nav inner. */
.breadcrumbs {
  background: var(--color-chrome);
  font-size: var(--size-small);
  margin: 0;
}
.breadcrumbs-list {
  list-style: none;
  max-width: 1600px;
  margin: 0 auto;
  padding: var(--spacing-sm) var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-xs);
  color: rgba(255, 255, 255, 0.7);
}
.breadcrumbs-item {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
}
.breadcrumbs-item + .breadcrumbs-item::before {
  content: "\203a";
  color: rgba(255, 255, 255, 0.4);
}
.breadcrumbs-item a {
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
}
.breadcrumbs-item a:hover {
  color: var(--brand-orange);
  text-decoration: none;
}
.breadcrumbs-item [aria-current="page"] {
  color: var(--color-pill-fg);
  font-weight: 600;
}

/* ---------- Cover ------------------------------------------------------- */

.web-cover {
  position: relative;
  isolation: isolate;
  margin: calc(-1 * var(--spacing-xl)) calc(-1 * var(--gutter)) var(--spacing-2xl);
  /* Hero shrinks to fit its overlaid text plus a small breathing margin
     (#144); the previous `min-height: 60vh` left a tall band of
     uncropped image above and below the title. The padding here IS
     the margin around the text. */
  padding: var(--spacing-xl) var(--gutter);
  display: flex;
  align-items: center;
  background: var(--color-cover-bg);
  color: var(--color-pill-fg);
  overflow: hidden;
}
.web-cover-bg {
  position: absolute; inset: 0; z-index: -1;
}
.web-cover-bg img {
  width: 100%; height: 100%; object-fit: cover; object-position: center;
  opacity: 0.55;
}
.web-cover-content { max-width: 40rem; }
.web-cover-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: var(--size-small);
  margin: 0 0 var(--spacing-md) 0;
  opacity: 0.8;
}
.web-cover-title h1, .web-cover-title h2 {
  color: var(--color-pill-fg);
  font-size: var(--size-cover-title);
  margin: 0 0 var(--spacing-md) 0;
}
.web-cover-title h2 {
  font-size: var(--size-h2);
  font-weight: 500;
  opacity: 0.9;
}
.web-cover-actions {
  display: flex; flex-wrap: wrap; gap: 0.75rem;
  margin: var(--spacing-xl) 0 0 0;
}
.web-cover-actions .btn-secondary {
  color: var(--color-pill-fg); border-color: var(--color-pill-fg);
}
.web-cover-actions .btn-secondary:hover, .web-cover-actions .btn-secondary:focus-visible {
  background: var(--color-pill-fg); color: var(--color-pill-bg);
}

/* ---------- TOC --------------------------------------------------------- */

.web-toc {
  margin: var(--spacing-xl) 0;
}
.web-toc-heading {
  font-size: var(--size-h2);
  margin-bottom: var(--spacing-lg);
}
.web-toc-prose {
  max-width: var(--measure);
  color: var(--color-text-muted);
  margin-bottom: var(--spacing-xl);
}
.web-toc-list {
  list-style: none; padding: 0; margin: 0;
  counter-reset: toc;
  display: grid;
  gap: var(--spacing-sm);
}
.web-toc-list li {
  counter-increment: toc;
  border-top: 1px solid var(--color-rule);
}
.web-toc-list li:last-child { border-bottom: 1px solid var(--color-rule); }
.web-toc-list a, .web-toc-list > li > span {
  display: flex; align-items: baseline;
  gap: var(--spacing-md);
  padding: var(--spacing-md) 0;
  text-decoration: none;
  color: var(--color-text);
  font-family: var(--font-heading);
  font-weight: 600;
}
.web-toc-list a::before, .web-toc-list > li > span::before {
  content: counter(toc, decimal-leading-zero);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  min-width: 2.5em;
}
.web-toc-list a:hover { color: var(--color-pill-bg); }

/* ---------- Chapter shell ---------------------------------------------- */

.chapter { display: block; }
.chapter-header { margin-bottom: var(--spacing-xl); }
.chapter-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--color-text-muted);
  font-size: var(--size-small);
  margin: 0 0 var(--spacing-sm) 0;
}
.chapter-title {
  font-size: var(--size-h1);
  margin: 0;
}
.chapter-meta {
  color: var(--color-text-muted);
  font-size: var(--size-small);
  margin: var(--spacing-sm) 0 0 0;
  display: inline-flex; align-items: center; gap: 0.4em;
}
.chapter-meta::before {
  content: '';
  display: inline-block;
  width: 0.7em; height: 0.7em; border-radius: 50%;
  background: var(--color-accent);
}
.chapter-pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-md);
  margin: var(--spacing-2xl) 0 0 0;
  border-top: 1px solid var(--color-rule);
  padding-top: var(--spacing-lg);
}
.chapter-pager a {
  display: flex; flex-direction: column; gap: 0.15rem;
  padding: var(--spacing-md);
  text-decoration: none;
  color: var(--color-text);
  border: 1px solid var(--color-rule);
  border-radius: 0.375rem;
}
.chapter-pager a:hover { border-color: var(--color-pill-bg); }
.chapter-pager-prev { grid-column: 1; }
.chapter-pager-next { grid-column: 2; text-align: right; }
.chapter-pager-direction {
  font-size: var(--size-small);
  color: var(--color-text-muted);
}
.chapter-pager-title {
  font-family: var(--font-heading);
  font-weight: 600;
}

/* ---------- Section heading ------------------------------------------- */

.web-section { margin-bottom: var(--spacing-2xl); }
/* Section headings render as plain typography (#144). The navy pill
   that previously wrapped each section's leading H1 was redundant
   with the chapter-title <h1> above it (every chapter title equalled
   the section pill text it preceded). Section H1s that match the
   chapter title are stripped upstream in build.py; remaining leading
   H1s — sub-statement titles like "Group balance sheet (FAS)" or
   the all-caps strapline on the hero section — flow through to
   <h2> via `_demote_section_headings` and pick up the default
   `.web-prose h2` styling below. */
.web-section-heading-plain {
  margin: var(--spacing-xl) 0 var(--spacing-md) 0;
}
.web-section-heading-plain h1,
.web-section-heading-plain h2 {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--color-heading);
  margin: 0;
}
.web-section > .web-prose > h2:first-child {
  /* The first <h2> in a section is the demoted leading H1 — i.e.
     the section's own heading. Give it a touch more air above so
     it reads as a section break rather than a sub-paragraph
     heading. */
  margin-top: var(--spacing-xl);
}

/* ---------- Prose ------------------------------------------------------- */

/* Prose flows to the same width as tables and callouts within the
   chapter container (`var(--content-max)`). The PDF's narrow
   multi-column reading width is a screen-deck concern; on web the
   page chrome already constrains the main column, so an additional
   per-paragraph max-width felt visibly narrow next to the
   wider tables and KPI banners. */
.web-prose h2 {
  margin-top: var(--spacing-xl);
}
.web-prose h3 {
  margin-top: var(--spacing-lg);
}
.web-prose ul, .web-prose ol {
  padding-left: 1.25rem;
  margin: 0 0 var(--spacing-lg) 0;
}
.web-prose li { margin-bottom: var(--spacing-sm); }
.web-prose blockquote {
  margin: var(--spacing-lg) 0;
  padding-left: var(--gutter);
  border-left: 4px solid var(--color-accent);
  color: var(--color-text-muted);
  font-style: italic;
}


/* Pull-quotes — `{{QUOTE: text | …}}` placeholders render as
   `<blockquote class="inline-quote">`. Reference uses a thin
   sans-serif quote at ~1.25em (no italic) with big brand-blue
   open/close glyphs anchored at the top-left and bottom-right corners.
   Mirrors `style/templates/report.css.j2` §inline-quote (#124). The
   selector wins specificity over the generic `.web-prose blockquote`
   rule above. */

.web-prose blockquote.inline-quote {
  /* Cancel the generic blockquote chrome (italic / gray / left border)
     so the pull-quote stands on its own typographic treatment. */
  font-style: normal;
  color: var(--color-text);
  border-left: 0;
  padding: 1.6em 0.4em;
  margin: var(--spacing-xl) 0;
  max-width: 32em;
  position: relative;
}
.web-prose blockquote.inline-quote p {
  font-family: var(--font-heading);
  font-size: 1.25em;
  font-weight: 300;
  line-height: 1.4;
  margin: 0;
  color: var(--color-text);
}
.web-prose blockquote.inline-quote::before,
.web-prose blockquote.inline-quote::after {
  position: absolute;
  color: var(--color-pill-bg);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 3em;
  line-height: 1;
}
.web-prose blockquote.inline-quote::before {
  content: "\201C";  /* curly left double quote */
  top: 0;
  left: 0;
}
.web-prose blockquote.inline-quote::after {
  content: "\201D";  /* curly right double quote */
  bottom: 0;
  right: 0;
}
/* Reference omits the attribution / speaker name. Keep `cite` in the
   DOM for accessibility tools but suppress visually. */
.web-prose blockquote.inline-quote cite {
  display: none;
}

.web-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: var(--size-small);
  color: var(--color-text-muted);
  margin: 0 0 var(--spacing-sm) 0;
}
.web-eyebrow p { margin: 0; }

.web-preamble {
  font-size: var(--size-h3);
  font-family: var(--font-heading);
  font-weight: 500;
  color: var(--color-heading);
  max-width: var(--measure);
  margin: var(--spacing-lg) 0;
}

/* ---------- Layout blocks + inline images ------------------------------ */

/* PDF layout-block markers (`layout-block-span-N`, `layout-block-pin-*`,
   `layout-block-columns-N`) emit on the web too because the inline-
   placeholder substitution is shared. The web doesn't honour
   multi-column flow or absolute pin positioning — flatten to a normal
   block stack. Per-page overrides below add layout where the PDF's
   structure carries semantic meaning (CEO portrait beside its quote). */
.web-prose .layout-block {
  margin: 0;
}
.web-prose figure.inline-image {
  margin: var(--spacing-lg) 0;
}
.web-prose figure.inline-image img {
  width: 100%;
  height: auto;
}
/* Photo credit / caption beneath an inline image (the `caption:` arg on
   an IMAGE placeholder) — e.g. the CEO portrait's photographer attribution. */
.web-prose figure.inline-image figcaption.image-credit,
.web-photo-quote figure.inline-image figcaption.image-credit {
  margin-top: var(--spacing-xs);
  font-family: var(--font-heading);
  font-size: 0.8rem;
  line-height: 1.3;
  color: var(--color-text-muted);
}


/* Photo + pull-quote pair (#144 follow-up — CEO's Review). Sections
   that author both an inline image and a `{{QUOTE: …}}` placeholder
   get restructured upstream (`build.py:_restructure_photo_quote`):
   the figure is moved out of its column-1 wrapper and grouped with
   the blockquote in a `.web-photo-quote` row at the end of the
   prose. Prose flows full-width above; on tablet/desktop the photo
   sits in column 1 and the quote in column 2 of an even split.
   Stacks vertically on phones. The selector is content-based so
   it works regardless of language slug (EN's `ceos-review` /
   FI's `toimitusjohtajan-katsaus`). */

.web-photo-quote {
  margin-top: var(--spacing-xl);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--spacing-lg);
  align-items: center;
}
.web-photo-quote figure.inline-image {
  margin: 0;
}
.web-photo-quote figure.inline-image img {
  max-width: 100%;
  margin: 0 auto;
}
.web-photo-quote blockquote.inline-quote {
  margin: 0;
}
@media (min-width: 768px) {
  .web-photo-quote {
    grid-template-columns: 1fr 1fr;
    gap: var(--gutter-lg);
  }
}

/* ---------- Balance-sheet side-by-side --------------------------------- */


/* Statement sections with two `{{TABLE: …}}` placeholders are balance
   sheets (assets + equity-and-liabilities). On desktop they render
   the two halves side by side; on narrow viewports they stack so each
   table can keep its horizontal-scroll-with-sticky-first-column
   behaviour without competing for width. The first table in source
   order (Assets / Group change in equity) renders left at desktop
   and on top when stacked — same visual order as the PDF's left
   column (#144). */

@media (min-width: 1024px) {
  .web-statement.n-tables-2 .web-prose {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--gutter-lg);
    align-items: start;
  }
  .web-statement.n-tables-2 .web-prose .inline-table {
    margin-top: 0;
  }
  /* Body prose paragraphs that appear before/after the tables span
     both grid columns so they read as introductory / closing text
     rather than columnated next to the tables. */
  .web-statement.n-tables-2 .web-prose > p,
  .web-statement.n-tables-2 .web-prose > h2,
  .web-statement.n-tables-2 .web-prose > h3,
  .web-statement.n-tables-2 .web-prose > ul,
  .web-statement.n-tables-2 .web-prose > ol {
    grid-column: 1 / -1;
  }
}


/* Inline-table `width: NN%` placeholder arg is a PDF-only directive
   tuned for the 1920pt deck (#144). On the web's narrower content
   column those percentages produce unusably narrow tables (Gross
   profit at 60% of ~1000px ≈ 600px, Cash flow at 70%, Equity
   halves at 33% inside a 50% grid column). Override to fill the
   parent — the balance-sheet `.n-tables-2` grid above already
   limits each table to its half-column. */

.web-prose .inline-table.has-width {
  max-width: 100% !important;
  width: 100% !important;
}

/* ---------- Financial tables ------------------------------------------- */

/* Row-label footnote reference (mirrors the PDF `.footnote-ref`): small
   superscript digit on a table row label whose source carried a `[^N]`. */
.footnote-ref {
  font-size: 0.6em;
  vertical-align: super;
  line-height: 0;
  font-weight: 700;
  margin-left: 0.1em;
}

.inline-table {
  margin: var(--spacing-xl) 0;
  /* Wide tables get horizontal scroll on narrow viewports rather than
     reflowing. The first column is sticky so labels stay visible while
     scrolling year columns. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--color-rule);
  border-radius: 0.25rem;
  max-width: 100%;
}
.inline-table-heading {
  font-size: var(--size-h3);
  margin: 0; padding: var(--spacing-md) var(--gutter);
  border-bottom: 1px solid var(--color-rule);
  background: var(--color-surface);
}

table.financial {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  font-size: var(--size-small);
}
table.financial thead {
  background: var(--color-table-header-bg);
  color: var(--color-pill-fg);
}
table.financial thead th {
  font-family: var(--font-heading);
  font-weight: 700;
  text-align: left;
  padding: 0.6em 0.75em;
  border-bottom: 0;
}
table.financial thead th.num { text-align: right; }
/* Sticky-first-column, header half. The body's `td.label` (below) pins the
   row labels while the year columns scroll; without the matching rule here
   the label column's own header scrolled away and a year header ended up
   sitting above the pinned labels, so the header row and body disagreed
   about which column was which. Opaque background (the cell is otherwise
   transparent over `thead`'s fill) so the scrolling year headers pass
   BEHIND it, and a z-index above `td.label`'s so it wins that overlap. */
table.financial thead th:first-child {
  position: sticky; left: 0;
  background: var(--color-table-header-bg);
  z-index: 2;
}
table.financial tbody td {
  padding: 0.5em 0.75em;
  vertical-align: top;
  /* No body row separator — the reference uses borders only on subtotal
     rows, not between every leaf (#101 / #123). The role-keyed rules
     below handle every rule the design actually wants. */
}
table.financial tbody td.num {
  text-align: right;
  white-space: nowrap;
}
table.financial tbody td.label {
  /* Sticky-first-column for horizontal scroll on narrow viewports. */
  position: sticky; left: 0;
  background: var(--color-surface);
  font-weight: 500;
  z-index: 1;
}

/* Role-keyed row-class rules. Mirrors style/templates/report.css.j2 (#123).
   Section-header / subtotal / heading rows are classified by the build
   pipeline (`scripts/build.py:_classify_row`); the markup hooks emit
   here regardless of which stylesheet renders them. */

/* All-caps section openers (REVENUE, ASSETS, EQUITY) — bold only, no
   border. The reference uses bold + whitespace for emphasis. */
table.financial tr.row-section td,
table.financial tr.row-subtotal td,
table.financial tr.row-significance td,
table.financial tr.row-major-total td,
table.financial tr.row-grand-total td {
  font-weight: 700;
}

/* Intermediate subtotal: 1px top border (PDF: 1pt). */
table.financial tr.row-subtotal.has-values td,
table.financial tr.row-significance.has-values td,
table.financial tr.row-closing-subtotal td {
  border-top: var(--rule-subtotal) solid var(--color-text);
  font-weight: 700;
}

/* Major total (P&L close, CF section closers): thick top, no bottom. */
table.financial tr.row-major-total.has-values td {
  border-top: var(--rule-major) solid var(--color-text);
  font-weight: 700;
}

/* Grand-total row (ASSETS TOTAL, EQUITY AND LIABILITIES TOTAL): thick
   top + thick bottom — surrounded. */
table.financial tr.row-grand-total.has-values td {
  border-top: var(--rule-major) solid var(--color-text);
  border-bottom: var(--rule-major) solid var(--color-text);
  font-weight: 700;
}

/* Workbook-cell-formatting orthogonal border classes. Used when a
   non-bold row needs a horizontal rule above (e.g. CF "Change in net
   working capital total"), or when a bold subtotal needs a thick rule
   *below* (e.g. "Restricted equity total" — thin above + thick below). */
table.financial tr.has-top-thin > td {
  border-top: var(--rule-subtotal) solid var(--color-text);
  padding-top: 0.9em;
  padding-bottom: 0.5em;
}
table.financial tr.has-top-thick > td {
  border-top: var(--rule-major) solid var(--color-text);
  padding-top: 0.9em;
  padding-bottom: 0.5em;
}
table.financial tr.has-bottom-thin > td {
  border-bottom: var(--rule-subtotal) solid var(--color-text);
}
table.financial tr.has-bottom-thick > td {
  border-bottom: var(--rule-major) solid var(--color-text);
}

/* Extra breathing room above any total / subtotal row. */
table.financial tr.row-grand-total.has-values td,
table.financial tr.row-major-total.has-values td,
table.financial tr.row-significance.has-values td,
table.financial tr.row-subtotal.has-values td,
table.financial tr.row-closing-subtotal td {
  padding-top: 0.9em;
  padding-bottom: 0.5em;
}

/* Heading rows ("Personnel expenses", "Depreciation, amortisation and
   write-offs") — sub-section opener. Reference visually separates them
   from the row above with extra air. */
table.financial tr.row-heading td {
  padding-top: 0.55em;
  font-weight: 600;
}

/* Indented hierarchy. `_depth_track` (build.py) annotates a numeric
   depth on each row; the label cell carries the `depth-N` class. Step
   is tokenised so the indent treatment can be retuned in one place. */
table.financial td.label              { padding-left: var(--cell-pad); }
table.financial td.label.depth-1      { padding-left: calc(var(--cell-pad) + 1 * var(--cell-indent)); }
table.financial td.label.depth-2      { padding-left: calc(var(--cell-pad) + 2 * var(--cell-indent)); }
table.financial td.label.depth-3      { padding-left: calc(var(--cell-pad) + 3 * var(--cell-indent)); }
table.financial td.label.depth-4      { padding-left: calc(var(--cell-pad) + 4 * var(--cell-indent)); }

/* Closing-subtotal rows have no label but the (empty) label cell still
   carries the base padding so the row aligns with its siblings. */
table.financial tr.row-closing-subtotal td.label { padding-left: var(--cell-pad); }


/* Current-period column shading — mirrors the PDF rule (#144).
   The build pipeline tags every column whose header carries the
   most-recent year token (e.g. "10-12/2025") with `td.period`;
   only those cells get the ice-blue fill. Tables with no period
   column (Subsidiaries, top-shareholders, formulas, IAC opted out
   via `{{TABLE: … | no_current_period: true}}`) keep plain white
   bodies. The previous `td:nth-child(2)` rule shaded the wrong
   column on multi-period tables (P&L, IAC reconciliation, etc.). */

.inline-table table.financial tbody td.period {
  background: var(--color-current-period);
}
.inline-table.no-current-period table.financial tbody td.period {
  background: transparent;
}

/* ---------- KPI callouts ----------------------------------------------- */

.web-callouts {
  display: grid;
  gap: var(--spacing-md);
  /* Diagonal brand gradient navy → cyan (#3, mirrors the PDF hero
     panel): deep navy at bottom-left transitioning to brand cyan in
     the top-right corner. */
  background: linear-gradient(45deg,
                              var(--color-pill-bg) 25%,
                              var(--color-accent) 100%);
  color: var(--color-pill-fg);
  padding: var(--gutter-lg) var(--gutter);
  margin: var(--spacing-2xl) calc(-1 * var(--gutter)) 0;
  border-radius: 0;
}
.web-callout {
  padding: var(--spacing-md) 0;
}
.web-callout + .web-callout {
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}
.web-callout-value {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: var(--size-hero-value);
  line-height: 1;
  margin: 0 0 var(--spacing-sm) 0;
}
.web-callout-label {
  font-size: var(--size-small);
  font-weight: 700;
  margin: 0;
  opacity: 0.85;
}

@media (min-width: 768px) {
  .web-callouts {
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
  }
  .web-callout { padding: var(--spacing-md) var(--gutter); }
  .web-callout + .web-callout {
    border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.25);
  }
}

/* `role: disclaimer` block (the hero page's "Unless otherwise stated …
   figures in parentheses …" caveat). On the PDF it's muted fine print in the
   grid; on the web build.py hoists it just before the callouts banner and it
   reads as an italic, muted caveat priming the parenthetical prior-year
   figures. Matches the PDF's role-disclaimer treatment, plus italics. */
.web-prose .layout-block-role-disclaimer {
  font-style: italic;
  color: var(--color-text-muted);
  font-size: var(--size-small);
  margin: var(--spacing-lg) 0;
}

/* Inline CALLOUTS-placeholder banner. The shared substitution emits the
   PDF markup (.inline-callouts / .callout / .callout-value / .callout-label),
   which the .web-callout* rules above don't match — so on the web the
   callouts were unstyled, a bare stack of lines. Give that markup the
   same horizontal, navy-gradient, 3-columns-at-desktop treatment as
   .web-callouts so it reads as a banner (one row of three on the web;
   the PDF keeps its own stacked layout from report.css). */
.inline-callouts {
  display: grid;
  gap: var(--spacing-md);
  background: linear-gradient(180deg,
                              var(--color-pill-bg) 0%,
                              #4D8DFF 100%);
  color: var(--color-pill-fg);
  padding: var(--gutter-lg) var(--gutter);
  margin: var(--spacing-2xl) calc(-1 * var(--gutter)) 0;
  border-radius: 0;
}
.inline-callouts .callout { padding: var(--spacing-md) 0; }
.inline-callouts .callout + .callout {
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}
.inline-callouts .callout-value {
  font-family: var(--font-heading);
  font-weight: 800;
  /* Own size, smaller than the landing hero's --size-hero-value (caps at
     60px): this inline banner reads better with a 40px max. */
  font-size: clamp(1.75rem, 1.2rem + 1.5vw, 2.5rem);
  line-height: 1;
  margin: 0 0 var(--spacing-sm) 0;
}
.inline-callouts .callout-label {
  font-size: var(--size-small);
  font-weight: 700;
  margin: 0;
  opacity: 0.85;
}
@media (min-width: 768px) {
  .inline-callouts {
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
  }
  .inline-callouts .callout { padding: var(--spacing-md) var(--gutter); }
  .inline-callouts .callout + .callout {
    border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.25);
  }
}

/* ---------- Signatures grid -------------------------------------------- */

.web-signatures-grid p {
  margin-bottom: var(--spacing-md);
}
@media (min-width: 768px) {
  /* Multi-column layout (not CSS Grid) so each name + role pair
     (`<h4>` + `<p>`) flows into the same column; CSS Grid would
     scatter them across columns row-by-row. The dated heading
     ("In Helsinki, …") and the auditor's-note heading break
     out of the column flow via `column-span: all`, giving each its
     own full-width row above/below the signer cards. */
  .web-signatures-grid {
    column-count: 3;
    column-gap: var(--gutter-lg);
  }
  .web-signatures-grid > h2,
  .web-signatures-grid > h3 {
    column-span: all;
    margin: var(--spacing-xl) 0 var(--spacing-md) 0;
  }
  .web-signatures-grid > h3:first-of-type {
    margin-top: 0;
  }
  /* Keep each signer's name with their role-line (avoid the column
     break dropping a role into the next column without its name). */
  .web-signatures-grid h4 {
    break-after: avoid;
    margin-bottom: 0.1em;
  }
  .web-signatures-grid > p {
    break-inside: avoid;
  }
}

/* Smaller signature image size */
.web-signatures-grid figure.inline-image img {
  width: auto;
  max-width: 220px;
  height: auto;
}

/* ---------- Chat widget (issue #174) ---------------------------------- */

/* Brand palette sampled from digitalworkforce.com. The orange (#FF6600) is
   the "Get Started" button and the menu-item hover colour; the blue (#0000FF)
   is the dominant brand blue (the "Orchestrated." headline). The CTA gradient
   is the 45° blue→cyan of the "Get Started" button, shared by the floating
   chat toggle and the panel's submit button so the widget reads as one CTA. */
:root {
  --brand-orange: #FF6600;
  --brand-blue: #0000FF;
  --brand-cta-gradient: linear-gradient(45deg, #0000FF 0%, #00FFFF 100%);
}
.chat-widget {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 100;
  font-family: var(--font-body);
}
.chat-widget[hidden] { display: none; }
.chat-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  border-radius: 999px;
  border: none;
  background: var(--brand-cta-gradient);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.chat-toggle:hover, .chat-toggle:focus-visible {
  background: var(--brand-cta-gradient);
  filter: brightness(1.08);
  outline: none;
}
.chat-toggle-icon {
  display: inline-flex;
  width: 1.5rem;
  height: 1.5rem;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  font-weight: 700;
}
/* Robot-logo mark on the closed toggle. White disc keeps the logo legible
   over the blue portion of the gradient. */
.chat-toggle-logo {
  display: inline-flex;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  object-fit: contain;
  background: #fff;
  padding: 2px;
  box-sizing: border-box;
}
.chat-panel {
  position: absolute;
  bottom: calc(100% + 0.75rem);
  right: 0;
  /* Wider reading column so answers + citations don't read "through a
     keyhole"; still clamps to the viewport (minus a 2rem gutter) on phones. */
  width: min(34rem, calc(100vw - 2rem));
  max-height: min(34rem, calc(100vh - 2rem));
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-rule);
  border-radius: 0.75rem;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18);
  overflow: hidden;
}
.chat-panel[hidden] { display: none; }
.chat-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--color-rule);
}
.chat-panel-header h2 {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}
.chat-panel-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.chat-close {
  background: transparent;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  color: var(--color-text-muted);
}
.chat-close:hover, .chat-close:focus-visible { color: var(--color-text); outline: none; }
.chat-clear {
  background: transparent;
  border: none;
  padding: 0.15rem 0.4rem;
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
  color: var(--color-text-muted);
  border-radius: 0.3rem;
}
.chat-clear:hover, .chat-clear:focus-visible {
  color: var(--color-text);
  background: var(--color-surface-shaded);
  outline: none;
}
.chat-panel-intro {
  margin: 0;
  padding: 0.6rem 1rem;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-rule);
}
.chat-messages {
  list-style: none;
  margin: 0;
  padding: 0.75rem 1rem;
  overflow-y: auto;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.chat-message { display: flex; flex-direction: column; gap: 0.25rem; }
.chat-message-user { align-items: flex-end; }
.chat-message-assistant, .chat-message-error { align-items: flex-start; }
.chat-bubble {
  display: inline-block;
  padding: 0.5rem 0.75rem;
  border-radius: 0.6rem;
  background: var(--color-surface-shaded);
  font-size: 0.9rem;
  line-height: 1.4;
  white-space: pre-wrap;
  max-width: 100%;
}
.chat-bubble p {
  margin: 0;
  white-space: normal;
}
.chat-bubble p + p,
.chat-bubble p + ol,
.chat-bubble p + ul,
.chat-bubble ol + p,
.chat-bubble ul + p {
  margin-top: 0.5rem;
}
.chat-bubble ol,
.chat-bubble ul {
  margin: 0.4rem 0 0.4rem 1.4rem;
  padding: 0;
  white-space: normal;
}
.chat-bubble li {
  margin: 0.2rem 0;
}
.chat-bubble li::marker {
  color: var(--color-text-muted);
}
.chat-bubble strong {
  font-weight: 700;
}
.chat-message-user .chat-bubble {
  background: var(--brand-blue);
  /* White text on the brand-blue bubble. NOT --color-cover-bg: that token is
     brand.black (#000000), which rendered the reader's own message as black on
     blue — unreadable. Matches the white-on-brand of .chat-submit / .chat-toggle. */
  color: #fff;
}
.chat-message-error .chat-bubble {
  background: #fde7e7;
  color: #842029;
}
.chat-message-thinking .chat-bubble {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.7rem 0.85rem;
}
.chat-thinking-dot {
  display: inline-block;
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--color-text-muted);
  opacity: 0.35;
  animation: chat-thinking-pulse 1.2s infinite ease-in-out;
}
.chat-thinking-dot:nth-child(2) { animation-delay: 0.18s; }
.chat-thinking-dot:nth-child(3) { animation-delay: 0.36s; }
@keyframes chat-thinking-pulse {
  0%, 60%, 100% { opacity: 0.35; transform: scale(1); }
  30%           { opacity: 1;    transform: scale(1.25); }
}
@media (prefers-reduced-motion: reduce) {
  .chat-thinking-dot { animation: none; opacity: 0.7; }
}
.chat-citations {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.chat-citation {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--color-pill-bg);
  color: var(--color-pill-fg);
  font-size: 0.75rem;
  text-decoration: none;
}
.chat-citation:hover, .chat-citation:focus-visible {
  text-decoration: underline;
  outline: none;
}
.chat-form {
  display: flex;
  gap: 0.5rem;
  padding: 0.6rem 1rem 0.85rem;
  border-top: 1px solid var(--color-rule);
}
.chat-form textarea {
  flex: 1 1 auto;
  resize: vertical;
  min-height: 2.6rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--color-rule);
  border-radius: 0.4rem;
  font: inherit;
  font-size: 0.9rem;
}
/* Panel submit shares the brand CTA gradient with the floating toggle
   (item 1). Declared after `.btn-primary` (same specificity) so it wins on
   source order and the button reads as the Get Started blue→cyan. */
.chat-submit {
  flex: 0 0 auto;
  background: var(--brand-cta-gradient);
  color: #fff;
  border-color: transparent;
}
.chat-submit:hover, .chat-submit:focus-visible {
  background: var(--brand-cta-gradient);
  filter: brightness(1.08);
}
.chat-submit[aria-busy="true"] { opacity: 0.6; cursor: progress; }

/* AI-transparency + data disclosures (EU AI Act Art. 50 + GDPR — #200).
   Muted footer notes under the form: clear and distinguishable per
   Art. 50(9) without competing with the conversation. */
.chat-panel-privacy, .chat-panel-disclaimer {
  margin: 0;
  padding: 0.45rem 1rem;
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--color-text-muted);
}
.chat-panel-privacy {
  border-top: 1px solid var(--color-rule);
}
.chat-panel-disclaimer {
  padding-top: 0;
}

/* ---------- Print fallback -------------------------------------------- */

@media print {
  .site-header, .dwf-site-footer, .chapter-pager, .nav-toggle,
  .web-cover-actions, .on-this-page, .chat-widget { display: none; }
  .site-main { max-width: none; padding: 0; }
}
