/* Index Data app styles, copied verbatim from Index/API GC/epra_api_new26/frontend/index.html (<style> block,
   lines 23-761) on 21 Oct 2026 so this app looks and behaves the same. Do not edit here: app-specific rules go
   in app.css. Re-copy when the Index Data page changes. */
    /* ---- EPRA brand palette ----
       Tokens now come from the vendored assets/design-system/foundations/colors_and_type.css
       (linked in <head> BEFORE this block), not redefined here. This block only bridges
       fen-api's existing --epra-navy/-gold/-grey/... variable names to the canonical ones, so
       the ~150 existing var(--epra-navy)/var(--epra-muted)/etc. references throughout this file
       keep working without a full rename sweep — same approach used for BPR's Phase 1 migration.
       Real value changes, not just renames: fen-api's old navy (#0A4D8C) and gold (#F5B833) were
       TMT-aligned, not the canonical brand blue (#12497F)/orange (#EBA61C) — deliberately switched
       to canonical now rather than waiting for TMT's own Phase 3 migration (2026-09-08 decision).
       --epra-blue/--epra-light-blue/--epra-europe/--epra-na/--epra-apac/--epra-em were defined
       but never referenced anywhere else in this file — dropped as dead code. */
    :root {
      --epra-navy:       var(--epra-blue);
      --epra-navy-dark:  var(--epra-blue-dark);
      --epra-gold:       var(--epra-orange);
      --epra-grey:       var(--epra-paper-tint);
      --epra-grey-2:     var(--color-border);
      --epra-text:       var(--epra-blue);
      --epra-muted:      var(--color-fg-muted);
      --epra-pos:        var(--color-success);
      --epra-neg:        var(--color-danger);
    }
    * { box-sizing: border-box; }
    /* bootstrap-overrides.css (linked above) sets this to --color-paper-alt
       (#f9fbfc, the real theme's near-white form-control background) --
       overridden to literal white here per the user's call, 2026-09-17.
       Mirrored in the concrete-package copy's fen.css (which doesn't even
       load bootstrap-overrides.css in production, a separate gap fixed the
       same way there). */
    .form-select, .form-control { background-color: white; }
    body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
      /* Real theme's main page background ($body-bg in the theme's own SCSS)
         is #F0F0F0 -- confirmed against the theme's compiled source,
         2026-09-10. Was a hand-picked close approximation (#EFEFF0) before;
         now the actual canonical token. */
      background: var(--color-bg-page);
      color: var(--epra-text);
      font-size: 14px;
      overflow-x: hidden;          /* page can never scroll sideways */
    }
    /* Sticky top: banner + tabs always visible while scrolling */
    /* z-index: only needs to clear this page's OWN content scrolling beneath
       it (plain static flow, z-index: auto) -- kept at 2, matching the CMS
       package's fen.css, where 100 turned out high enough to paint over the
       site theme's own header mega-menu once this tab bar goes sticky
       (confirmed on the live site, 2026-09-30). No competing header on this
       standalone page, but kept in sync rather than letting the two drift. */
    .topbar {
      position: sticky;
      top: 0; left: 0; right: 0;
      z-index: 2;
      background: var(--color-bg-page);
      /* Matches main's own 28px horizontal padding so the tab bar lines up
         with the content below it -- the removed .tabs-wrap used a
         slightly different 20px before. */
      padding: 0 28px;
    }
    main { padding: 12px 28px 22px; max-width: 1500px; margin: 0 auto; }

    /* ---- Tabs ----
       2026-09-15 restyle: each tab is now its own fully-enclosed, rounded
       "chip" (echoing BPR's .tile cards at a much smaller scale -- a
       bordered surface with a shadow and a hover lift) instead of
       Bootstrap's classic notebook-tab look (one shared bottom border,
       square bottom corners merging into the panel below). That old look
       read as its own separate mini-app sitting on the page; this reads as
       a normal part of the page instead, matching the broader move away
       from the dashboard looking like a self-contained app.
       Border stays a UNIFORM 1px on every side, in every state -- an
       earlier version tried a thicker border-top (or an inset box-shadow
       imitating one) for the active-tab accent, but a rounded corner with
       mismatched widths on adjacent sides renders as a chunky, visibly
       disconnected blob right at the curve (confirmed via a 4x-zoomed
       screenshot) -- a well-known CSS quirk, not a one-off rendering bug.
       The accent is now a short bar drawn via ::before, inset far enough
       from the sides that it never touches the rounded corners at all, so
       it can't collide with that same rendering issue. */
    /* Same technique as .dkpi's own top-accent cards (see the Dashboard tab
       further down this file): NO real border on the sides/bottom at all --
       a spread-only, zero-blur box-shadow (0 0 0 1px) stands in for one
       instead. A real border participates in the browser's per-side corner
       math, so a THICKER colored border-top next to THINNER plain sides
       visibly clashes right at the curve (this took three attempts to
       track down: an inset shadow, then a mismatched-radius ::before bar,
       both had the same root cause). box-shadow doesn't have that problem
       -- it always traces the element's own border-radius as a single,
       uniform sweep regardless of what real border is also present, so a
       border-top can be layered on top of it with no seam. Only the truly
       active tab gets a real border-top; padding-top is reduced by exactly
       its width so the tab's total height and the text's vertical position
       stay identical to the inactive tabs -- nothing shifts on select. */
    /* margin-top/margin-left: .epra-fen-app sets overflow-x:hidden on
       itself (stops the page scrolling sideways) -- .epra-tmt-app has no
       such property on its own wrapper at all, only on unrelated inner
       components. An ancestor's overflow clips anything a descendant's
       box-shadow bleeds past its own edge (the "fake border" trick here
       spreads 1px beyond the tab's own box), so without this buffer the
       first tab's outline gets clipped flush against .epra-fen-app's own
       left/top edge -- confirmed by testing in devtools; TMT never hits
       this since it has no matching overflow to clip against. */
    .nav-tabs { border-bottom: none; gap: 8px; margin: 4px 0 0 2px; }
    .nav-tabs .nav-link {
      margin-bottom: 0;
      border: none;
      border-radius: 10px;
      padding: 9px 18px;
      background: white;
      color: var(--epra-muted);
      /* .epra-fen-app sets a page-wide font-size:14px (own convention,
         untouched -- not part of this pass), but .epra-tmt-app never sets
         its own font-size at all, so its tabs inherit the real theme's
         actual body font-size (16px, confirmed against the theme's
         compiled SCSS -- stock Bootstrap default, never customized).
         Pinned explicitly here so this one shared component renders
         pixel-identically in both apps regardless of each app's own
         broader (and different) font-size convention elsewhere. */
      font-size: 16px;
      font-weight: 600;
      box-shadow: 0 0 0 1px var(--epra-grey-2), 0 1px 2px rgba(10,77,140,0.06);
      transition: transform .15s ease, box-shadow .15s ease, color .15s ease;
    }
    /* The outline stays neutral grey on hover -- only the truly active tab
       gets the blue outline + top accent. Coloring it blue on hover too
       (an earlier version did this) made a merely-hovered tab look
       basically indistinguishable from the actually-active one. */
    .nav-tabs .nav-link:hover:not(.active) {
      color: var(--epra-blue);
      transform: translateY(-1px);
      box-shadow: 0 0 0 1px var(--epra-grey-2), 0 3px 8px rgba(10,77,140,0.14);
    }
    .nav-tabs .nav-link.active {
      color: var(--epra-blue);
      border-top: 4px solid var(--epra-blue);
      padding-top: 5px;
      box-shadow: 0 0 0 1px var(--epra-grey-2), 0 2px 6px rgba(10,77,140,0.12);
    }

    /* ---- Panels ---- */
    .panel {
      background: white; border: 1px solid var(--epra-grey-2);
      border-radius: 6px; padding: 16px; margin-bottom: 14px;
      box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    }
    .panel h2 {
      margin: 0 0 14px; font-size: 12px; font-weight: 700;
      color: var(--epra-navy); text-transform: uppercase; letter-spacing: 0.08em;
    }

    /* ---- Controls ---- */
    .controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; align-items: end; }
    .field { display: flex; flex-direction: column; gap: 5px; }
    .field label { font-size: 11px; color: var(--epra-navy); font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; }
    /* .form-select visuals now come from Bootstrap (background/arrow/
       border-radius fixed at the shared bootstrap-overrides.css level,
       2026-09-10) -- select-standardization pass. .field input (date/text
       fields, not part of this pass) keeps its own bespoke styling. */
    .field input {
      padding: 6px 10px; border: 1px solid var(--epra-grey-2); border-radius: 5px;
      background: white; font-size: 13px; font-family: inherit; color: var(--epra-navy);
      font-weight: 500; cursor: text;
    }
    .field input:focus {
      outline: 2px solid var(--epra-navy); outline-offset: 0;
      border-color: var(--epra-navy);
    }

    /* button.primary / button.secondary visuals now come from Bootstrap
       (btn-primary / btn-outline-primary) -- 2026-09-10 button-standardization
       pass, same as BPR. Old bespoke uppercase/letter-spacing treatment
       dropped in favour of Bootstrap's standard button typography. */

    /* Horizon quick-pick buttons. Visuals now come from Bootstrap
       (btn-group of btn-outline-primary btn-sm) -- 2026-09-10
       button-standardization pass. flex-wrap kept: unlike a typical
       .btn-group these need to wrap in narrow layouts (9-10 buttons). */
    .horizons { display: flex; flex-wrap: wrap; margin-top: 12px; }

    .actions { margin-top: 14px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
    .status { color: var(--epra-muted); font-size: 13px; }
    .status.error { color: var(--epra-neg); font-weight: 600; }

    /* ---- Charts ---- */
    .chart-wrap { position: relative; height: 460px; }

    /* ---- Tables (unified, lean style across the dashboard) ---- */
    table {
      width: 100%;
      border-collapse: collapse;
      font-size: 13px;
    }
    th, td {
      padding: 8px 14px;
      white-space: nowrap;
      border: 0;
    }
    /* Default: first column left, others right-aligned */
    th, td { text-align: right; }
    th:first-child, td:first-child { text-align: left; }
    /* Header band — navy, spans every column including the first */
    thead th {
      background: var(--epra-navy);
      color: white;
      font-weight: 600;
      text-transform: uppercase;
      font-size: 11px;
      letter-spacing: 0.04em;
    }
    /* Sub-header band — for the dates row under the horizons */
    thead th.subhead {
      background: var(--epra-grey);
      color: var(--epra-muted);
      font-weight: 500;
      font-size: 11px;
      text-transform: none;
      letter-spacing: 0;
    }
    /* Body rows */
    tbody td {
      color: var(--epra-text);
      border-bottom: 1px solid var(--epra-grey-2);
    }
    tbody tr:last-child td { border-bottom: 0; }
    /* Light zebra striping for the data-heavy tables (Performance, Time series,
       Constituents) to make wide rows easier to follow. */
    #an-ret-table tbody tr:nth-child(even) td,
    #an-vol-table tbody tr:nth-child(even) td,
    #ts-table    tbody tr:nth-child(even) td,
    #cn-table    tbody tr:nth-child(even) td { background: #f4f7fb; }
    tbody tr:hover td { background: rgba(10, 77, 140, 0.08) !important; }

    /* Returns & risk: numeric cells centred, first column left */
    table.an-table th, table.an-table td { text-align: center; }
    table.an-table th:first-child, table.an-table td:first-child { text-align: left; }
    /* Two-row header bands: navy + grey sit flush, no white seam */
    table.an-table thead tr:first-child th { border-bottom: 0; padding-bottom: 8px; }
    table.an-table thead tr:nth-child(2) th { border-top: 0; padding-top: 6px; }

    /* Compact (single-horizon) variant — tighter padding for the side-by-side layout */
    table.an-table.compact th, table.an-table.compact td { padding: 6px 10px; font-size: 12px; }

    /* R&R page: settings | full returns + volatility tables. */
    .an-page {
      display: grid;
      grid-template-columns: 300px minmax(0, 1fr);
      gap: 16px;
      align-items: stretch;
      justify-content: center;
    }
    .an-note { font-size: 11px; color: var(--epra-muted); margin-top: 12px; line-height: 1.5; }
    .an-pa-note { font-size: 11px; font-weight: 400; color: var(--epra-muted); text-transform: none; letter-spacing: 0; }
    .an-page > .panel { margin-bottom: 0; }
    .an-controls { grid-template-columns: 1fr; }
    .an-col-settings {
      position: sticky;
      top: 152px;
      align-self: start;
      z-index: 1;
      background: white;
    }
    .an-col-table { display: flex; flex-direction: column; min-width: 0; }
    .an-col-table .scroll { max-height: none; min-height: 0; }
    /* Both tables side by side so returns + volatility are always visible together */
    .an-tables {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 16px;
      align-items: start;
    }
    .an-tables > .panel { margin-bottom: 0; min-width: 0; }
    @media (max-width: 1150px) { .an-tables { grid-template-columns: 1fr; } }
    /* Denser cells so all 9 horizons fit side by side */
    .an-tables table.an-table.compact th,
    .an-tables table.an-table.compact td { padding: 5px 4px; font-size: 11px; }
    .an-tables table.an-table.compact th:first-child,
    .an-tables table.an-table.compact td:first-child {
      max-width: 104px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .an-col-chart { display: flex; flex-direction: column; min-width: 0; }
    .an-col-chart .an-chart-fill {
      flex: 1; height: 100%; min-height: 480px; min-width: 0;
    }
    @media (max-width: 800px) {
      .an-page { grid-template-columns: 1fr; }
      .an-col-settings { position: static; z-index: auto; }
    }

    /* Scroll wrapper + sticky header (entire thead as a block) */
    .scroll {
      max-height: 380px; overflow: auto;
      border: 1px solid var(--epra-grey-2); border-radius: 4px;
    }
    /* Sticky <thead> keeps both header rows pinned together as one block,
       so there's never a sub-pixel white gap between the navy and grey rows
       and they can't visually overlap body content. */
    .scroll table { border-collapse: separate; border-spacing: 0; }
    .scroll table thead {
      position: sticky;
      top: 0;
      z-index: 2;
    }
    .num.pos { color: var(--epra-pos); font-weight: 600; }
    .num.neg { color: var(--epra-neg); font-weight: 600; }
    .hidden { display: none; }

    /* Smooth tab content swap */
    section[id^="view-"] { animation: fadeIn 0.18s ease; }
    @keyframes fadeIn { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: none; } }

    /* Color customization panel */
    details.color-panel { margin-top: 12px; }
    details.color-panel > summary {
      cursor: pointer; font-size: 12px; font-weight: 600;
      color: var(--epra-navy); padding: 4px 0;
      list-style: none;
    }
    details.color-panel > summary::before {
      content: "▸ "; display: inline-block; transition: transform 0.15s ease;
    }
    details.color-panel[open] > summary::before { content: "▾ "; }
    .color-row {
      display: flex; align-items: center; gap: 8px;
      padding: 4px 0; font-size: 12px;
    }
    .color-row .label { flex: 1; color: var(--epra-text); }
    .palette { display: inline-flex; gap: 4px; }
    .palette .swatch {
      width: 18px; height: 18px; border-radius: 3px;
      border: 2px solid transparent; cursor: pointer; padding: 0;
      transition: transform 0.1s ease, border-color 0.1s ease;
    }
    .palette .swatch:hover { transform: scale(1.1); }
    .palette .swatch.selected { border-color: var(--epra-navy); }
    .color-row button.reset {
      background: transparent; border: 1px solid var(--epra-grey-2);
      color: var(--epra-muted); padding: 2px 8px; border-radius: 4px;
      font-size: 11px; cursor: pointer; font-family: inherit;
    }
    .color-row button.reset:hover { background: var(--epra-grey); color: var(--epra-navy); }

    /* Mode toggle (Search / Regions / Sectors) — segmented control */
    /* Four options (Search / Regions / Sectors / Countries) have to fit the
       narrow settings column, so the padding is tight, Search is reduced to a
       magnifier, and the row wraps rather than overflowing. */
    .mode-switch {
      display: inline-flex; flex-wrap: wrap; gap: 2px;
      background: white; border: 1px solid var(--epra-grey-2);
      border-radius: 4px; padding: 3px; margin-bottom: 6px;
      /* the settings column is a flex container, so without align-self the
         control would stretch the full panel width instead of hugging its
         buttons */
      align-self: flex-start; width: fit-content; max-width: 100%;
    }
    .mode-switch button {
      background: transparent; color: var(--epra-muted); border: none;
      padding: 5px 9px; border-radius: 3px; cursor: pointer;
      font-size: 11px; font-weight: 600; letter-spacing: 0.03em;
      text-transform: uppercase; font-family: inherit;
      transition: all 0.15s ease; white-space: nowrap;
    }
    .mode-switch button.icon-only { padding: 5px 8px; display: inline-flex; align-items: center; }
    .mode-switch button.icon-only svg { display: block; width: 13px; height: 13px; }
    .mode-switch button:hover:not(.active) { color: var(--epra-navy); background: rgba(18,73,127,0.06); }
    .mode-switch button.active {
      background: var(--epra-navy); color: white;
    }
    .mode-hint {
      font-size: 12px; color: var(--epra-muted);
      padding: 6px 10px; background: var(--epra-grey);
      border-radius: 4px; line-height: 1.4;
    }

    /* Region pills (multi-select toggle). Visuals now come from Bootstrap
       (btn-outline-primary btn-sm) -- 2026-09-10 button-standardization
       pass. Kept as a flex-wrap group, not a .btn-group -- these are
       independently-toggled multi-select pills, not a joined segmented
       control, so pill-shaped individual buttons with a gap read better
       than a fused strip. */
    .region-pills { display: flex; flex-wrap: wrap; gap: 6px; }

    /* Time series page: controls on the LEFT (sticky), chart+table on the RIGHT */
    .ts-page {
      display: grid;
      grid-template-columns: 300px minmax(0, 1fr);  /* minmax allows the chart to shrink */
      gap: 16px;
      align-items: stretch;
    }
    .ts-page > .panel,
    .ts-page > .ts-col-right > .panel { margin-bottom: 0; }
    .ts-controls { grid-template-columns: 1fr; gap: 10px; }
    .ts-col-settings {
      position: sticky;
      top: 152px;
      align-self: start;
      padding: 14px;
    }
    .ts-col-settings .actions { margin-top: 10px; }
    /* Start & End dates each on their own row (stacked, not side-by-side) */
    .ts-dates {
      display: grid;
      grid-template-columns: 1fr;
      gap: 10px;
    }
    .ts-dates .field { gap: 4px; }
    /* Make the D/M/Q/Y buttons square and uniform */
    #ts-frequency-strip button {
      min-width: 28px;
      padding: 4px 8px;
      font-weight: 700;
    }
    .ts-col-right { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
    .ts-col-right .panel { margin-bottom: 0; min-width: 0; }
    .ts-col-right .chart-wrap { min-width: 0; }
    /* Keep the sticky settings cleanly above any chart overflow */
    .ts-col-settings { z-index: 1; background: white; }
    /* Collapse earlier so a narrow viewport doesn't squeeze the chart */
    @media (max-width: 1100px) {
      .ts-page { grid-template-columns: 1fr; }
      .ts-col-settings { position: static; z-index: auto; }
    }

    /* Regions page: controls on the LEFT, charts on the RIGHT */
    .rg-page {
      display: grid;
      grid-template-columns: 300px minmax(0, 1fr);
      gap: 16px;
      align-items: stretch;
    }
    .rg-page > .panel { margin-bottom: 0; }
    .rg-controls { grid-template-columns: 1fr; }
    .rg-col-charts { display: flex; flex-direction: column; min-width: 0; }

    /* Settings panel stays pinned just below the topbar while charts scroll */
    .rg-col-settings {
      position: sticky;
      top: 152px;                            /* clear the banner + tabs */
      align-self: start;                     /* don't stretch in the grid row */
    }
    /* Compact region picker: 2-column grid, smaller pills */
    .rg-col-settings .region-pills {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 4px;
    }
    .rg-col-settings .region-pills button {
      padding: 4px 8px;
      font-size: 11px;
      letter-spacing: 0.02em;
    }

    /* Chart grid inside the right column. auto-fit/minmax, not a fixed column
       count + viewport breakpoint -- see fen.css's matching rule for the full
       reasoning (container-xl caps width independent of viewport, so a
       viewport breakpoint can't track it). This reference copy doesn't sit
       inside a CMS container itself, but kept in sync with fen.css anyway.
       2026-10-02. */
    .rg-grid {
      display: grid;
      gap: 14px;
      grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
      margin: 0;
    }
    @media (max-width: 760px) {
      .rg-page { grid-template-columns: 1fr; }
      .rg-grid { grid-template-columns: 1fr; }
    }
    .rg-card {
      background: white;
      border: none;
      border-radius: 6px;
      padding: 8px 8px 4px;
      width: 100%;
    }
    .rg-card h3 {
      margin: 0 0 6px; text-align: center;
      color: var(--epra-navy); font-size: 14px; font-weight: 600;
      letter-spacing: 0.02em;
    }
    .rg-card .chart-wrap-rg { position: relative; height: 430px; }

    /* ---- Searchable multi-select ---- */
    .smselect { position: relative; }
    .smselect-input {
      width: 100%; padding: 8px 10px; border: 1px solid var(--epra-grey-2);
      border-radius: 4px; background: white; font-size: 14px; font-family: inherit;
      cursor: pointer;
    }
    .smselect-input:focus { outline: none; border-color: var(--epra-navy); box-shadow: 0 0 0 2px rgba(0,47,95,0.15); }
    .smselect-dropdown {
      position: absolute; left: 0; right: 0; top: 100%; z-index: 50;
      background: white; border: 1px solid var(--epra-navy); border-top: none;
      max-height: 280px; overflow-y: auto; box-shadow: 0 4px 12px rgba(0,0,0,0.1);
      display: none;
    }
    .smselect.open .smselect-dropdown { display: block; }
    .smselect-option {
      padding: 7px 10px; font-size: 13px; cursor: pointer;
      border-bottom: 1px solid var(--epra-grey);
    }
    .smselect-option:hover { background: var(--epra-grey); }
    .smselect-option.selected { background: rgba(0,47,95,0.08); font-weight: 600; color: var(--epra-navy); }
    .smselect-option .check { color: var(--epra-gold); margin-right: 4px; }
    .smselect-chips {
      display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px;
    }
    .chip {
      display: inline-flex; align-items: center; gap: 6px;
      background: var(--epra-navy); color: white;
      padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 500;
    }
    .chip .x { cursor: pointer; opacity: 0.8; font-weight: 700; }
    .chip .x:hover { opacity: 1; }
    /* ===================== DASHBOARD TAB ===================== */
    .db-wrap { display: flex; flex-direction: column; gap: 16px; }
    /* Controls row -- each .field is its own label-above-control column
       (the base .field rule above already gives it that), laid out in a
       flex row with align-items: flex-end so every field's control lines
       up along its bottom edge regardless of the field's own height (date
       input vs. btn-group vs. select vs. the label-less .actions buttons/
       status) -- same technique as .controls further up this file.
       flex-wrap lets fields reflow onto a second line once they no longer
       fit, rather than running off the panel edge: an earlier grid-based
       version (grid-auto-flow: column) only reflowed below 760px, which
       Constituents -- the tab with the most fields -- could exceed well
       before reaching a narrow/mobile width (confirmed on the live site,
       2026-09-30: the actions/status group ran off the right edge at
       ordinary desktop widths). */
    .db-controls-row {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-end;
      column-gap: 16px;
      row-gap: 12px;
    }
    .db-controls-row .actions { margin-top: 0; }
    @media (max-width: 760px) {
      .db-controls-row { flex-direction: column; align-items: stretch; }
    }

    /* Hero band */
    .dhero {
      background: linear-gradient(135deg, var(--epra-navy) 0%, var(--epra-navy-dark) 100%);
      color: white; border-radius: 12px; padding: 22px 28px;
      display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 24px; align-items: center;
      box-shadow: 0 4px 14px rgba(10,77,140,0.18);
    }
    .dhero .lbl { font-size: 11px; text-transform: uppercase; letter-spacing: 0.8px; color: rgba(255,255,255,0.75); font-weight: 600; }
    .dhero .big { font-size: 34px; font-weight: 800; letter-spacing: -0.5px; margin: 4px 0 0; line-height: 1.05; }
    .dhero .ds { display: flex; gap: 28px; flex-wrap: wrap; }
    .dhero .d .l { display: block; color: rgba(255,255,255,0.75); text-transform: uppercase; letter-spacing: 0.5px; font-size: 10px; margin-bottom: 2px; }
    .dhero .d .v { font-weight: 700; font-size: 22px; }
    .dhero .d .v.up { color: #5BE5A0; }
    .dhero .d .v.down { color: #FF9A8C; }
    .dhero .d .v.flat { color: rgba(255,255,255,0.8); }

    /* Sector trends: region selector as a single-select line + tall wide chart.
       Visuals now come from Bootstrap (.btn-group of btn-outline-primary
       btn-sm) -- 2026-09-10 button-standardization pass, single-select
       exclusive like .db-quick/.horizons, so fused (no gap) is correct here,
       unlike the multi-select .region-pills above. flex-wrap kept as a
       narrow-viewport safety net. */
    .st-region-line { display: flex; flex-wrap: wrap; }
    .st-chart-wrap { position: relative; width: 100%; height: 540px; }

    /* Snapshot quick-pick strip. Visuals now come from Bootstrap (.btn-group
       of btn-outline-primary btn-sm, pill-radius via bootstrap-overrides.css)
       -- 2026-09-10 button-standardization pass, single-select exclusive so
       no gap: a true fused strip, rounded only at the two outer ends. */
    .db-quick { display: inline-flex; flex-wrap: wrap; }

    /* 5-up KPI boxes */
    .db-kpis { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; }
    @media (max-width: 1100px) { .db-kpis { grid-template-columns: repeat(3, 1fr); } }
    @media (max-width: 620px)  { .db-kpis { grid-template-columns: repeat(2, 1fr); } }
    .db-kpi {
      background: white; border-radius: 10px; padding: 16px 18px;
      box-shadow: 0 1px 3px rgba(10,77,140,0.06);
      border-top: 4px solid var(--epra-navy);
      display: flex; flex-direction: column; gap: 6px;
    }
    .db-kpi.eur { border-top-color: var(--epra-gold); }
    .db-kpi.na  { border-top-color: #0B3863; }
    .db-kpi.ap  { border-top-color: #5BA7E0; }
    .db-kpi.em  { border-top-color: #3FB8AF; }
    .db-kpi.gl  { border-top-color: var(--epra-navy); }
    .db-kpi .l { font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--epra-muted); font-weight: 700; }
    .db-kpi .fig { font-size: 24px; font-weight: 700; color: var(--epra-navy); letter-spacing: -0.3px; }
    .db-kpi .sub { font-size: 12px; color: var(--epra-muted); display: flex; gap: 12px; flex-wrap: wrap; }
    .db-kpi .sub strong { color: var(--epra-text); }
    .db-kpi-rets { display: flex; gap: 14px; margin-top: 2px; padding-top: 8px; border-top: 1px solid var(--epra-grey-2); }
    .db-kpi-rets .rr { display: flex; flex-direction: column; gap: 1px; }
    .db-kpi-rets .rl { font-size: 9px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--epra-muted); font-weight: 700; }
    .db-kpi-rets .rv { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
    .db-kpi-rets .rv.up { color: var(--epra-pos); }
    .db-kpi-rets .rv.down { color: var(--epra-neg); }
    .db-kpi-rets .rv.flat { color: var(--epra-muted); }

    /* 5-up region pie grid */
    .db-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
    @media (max-width: 1100px) { .db-grid { grid-template-columns: repeat(3, 1fr); } }
    @media (max-width: 620px)  { .db-grid { grid-template-columns: repeat(2, 1fr); } }
    .db-card {
      background: white; border: 1px solid var(--epra-grey-2); border-radius: 8px;
      padding: 14px 12px; display: flex; flex-direction: column; align-items: center; gap: 8px;
      box-shadow: 0 1px 2px rgba(0,0,0,0.04);
      min-width: 0;   /* allow grid item to shrink below the canvas intrinsic width */
    }
    /* Title box is always two lines tall, so a title that wraps ("Developed
       North America (EGNA)" at 5-up) no longer pushes its pie below the others. */
    .db-card h3 {
      margin: 0; font-size: 12px; font-weight: 700; color: var(--epra-navy);
      text-transform: uppercase; letter-spacing: 0.5px; text-align: center;
      line-height: 1.3; min-height: 2.6em;
      display: flex; align-items: center; justify-content: center;
    }
    .db-pie { position: relative; width: 100%; height: 140px; }
    .db-donut-center {
      position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
      text-align: center; pointer-events: none;
    }
    .db-donut-center .l { font-size: 8px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--epra-muted); font-weight: 700; }
    .db-donut-center .v { font-size: 13px; font-weight: 800; color: var(--epra-navy); letter-spacing: -0.3px; }
    .db-card .db-total { font-size: 16px; font-weight: 800; color: var(--epra-navy); letter-spacing: -0.3px; }
    .db-card .db-total-lbl { font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--epra-muted); font-weight: 600; margin-top: -4px; }
    .db-rets { display: flex; gap: 20px; margin-top: 2px; }
    .db-rets .r { text-align: center; }
    .db-rets .r .l { display: block; font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--epra-muted); font-weight: 600; }
    .db-rets .r .v { font-size: 15px; font-weight: 700; }
    .db-rets .r .v.up { color: var(--epra-pos); }
    .db-rets .r .v.down { color: var(--epra-neg); }
    .db-rets .r .v.flat { color: var(--epra-muted); }

    /* Shared sector legend */
    .db-legend {
      display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 22px;
      background: white; border: 1px solid var(--epra-grey-2); border-radius: 8px;
      padding: 14px 18px; box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    }
    .db-legend .li { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--epra-text); }
    .db-legend .li .dot { width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0; }

    /* ===================== CONSTITUENTS TAB ===================== */
    /* Checkbox dropdown (country / sector) with select-all controls. The
       trigger button carries the real .form-select class (added in JS,
       CheckDropdown constructor) so it renders with whatever the live
       theme's actual select look is -- background, arrow icon, border,
       radius, padding, font -- instead of a hand-copied approximation that
       would drift the next time the theme changes. Only the bits a real
       <select> wouldn't need are set here: it isn't natively full-width,
       and a <button>'s default text-align is center, not left. */
    .cn-multi { position: relative; }
    .cn-multi-btn {
      width: 100%; min-width: 150px; text-align: left; cursor: pointer;
    }
    .cn-multi-btn:hover { border-color: var(--epra-navy); }
    .cn-multi-panel {
      position: absolute; top: calc(100% + 4px); left: 0; z-index: 60;
      background: white; border: 1px solid var(--epra-grey-2); border-radius: 5px;
      box-shadow: 0 4px 14px rgba(10,77,140,0.15);
      min-width: 210px; max-width: 280px;
    }
    .cn-multi-actions {
      display: flex; gap: 6px; padding: 8px;
      border-bottom: 1px solid var(--epra-grey-2);
    }
    .cn-multi-actions button {
      flex: 1; background: white; border: 1px solid var(--epra-grey-2);
      border-radius: 4px; padding: 4px 6px; font-size: 10px; font-weight: 700;
      text-transform: uppercase; letter-spacing: 0.03em;
      color: var(--epra-navy); cursor: pointer; font-family: inherit;
    }
    .cn-multi-actions button:hover { background: var(--epra-grey); border-color: var(--epra-navy); }
    .cn-multi-list { max-height: 240px; overflow-y: auto; padding: 6px; }
    .cn-multi-list label {
      display: flex; align-items: center; gap: 7px; padding: 4px 6px;
      font-size: 12px; color: var(--epra-text); cursor: pointer;
      border-radius: 3px; white-space: nowrap;
    }
    .cn-multi-list label:hover { background: rgba(10,77,140,0.06); }
    .cn-multi-list input[type="checkbox"] { accent-color: var(--epra-navy); cursor: pointer; }

    /* "incl. free-float cap" — tiny label centred above the download button at month end.
       Absolutely positioned so it never shifts the row of buttons. Sits back in
       the top .actions row (2026-10-02), pushed to the far right of that row --
       .actions is already display:flex, so margin-left: auto on this one child
       is enough, no extra wrapper needed. */
    .cn-dl-wrap { position: relative; display: inline-flex; margin-left: auto; }
    .cn-dl-note {
      position: absolute; bottom: calc(100% + 2px); left: 0; right: 0;
      text-align: center; font-size: 9px; line-height: 1; white-space: nowrap;
      color: var(--epra-muted); pointer-events: none;
    }

    .cn-scroll { max-height: calc(100vh - 300px); }
    table.cn-table th, table.cn-table td { padding: 5px 8px; font-size: 11px; }
    /* Name column: left-aligned, truncated with tooltip */
    table.cn-table td:first-child {
      text-align: left; max-width: 210px;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    table.cn-table th:first-child { text-align: left; }
    /* Sortable headers */
    table.cn-table thead th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
    table.cn-table thead th.sortable:hover { background: var(--epra-navy-dark); }
    table.cn-table thead th .arrow { opacity: 0.55; font-size: 9px; margin-left: 2px; }
    .cn-reit-tag {
      display: inline-block; padding: 1px 5px; border-radius: 3px;
      font-size: 9px; font-weight: 700; letter-spacing: 0.3px;
    }
    .cn-reit-tag.yes { background: rgba(10,77,140,0.10); color: var(--epra-navy); }
    .cn-reit-tag.no  { background: var(--epra-grey); color: var(--epra-muted); }

    /* Top 5 countries by region — "league" grid */
    .db-league-card {
      background: white; border: 1px solid var(--epra-grey-2); border-radius: 8px;
      padding: 16px 18px; box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    }
    .db-league-card h3 {
      margin: 0 0 12px; font-size: 12px; font-weight: 700; color: var(--epra-navy);
      text-transform: uppercase; letter-spacing: 0.6px;
    }
    .db-league { display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: 10px; align-items: start; }
    @media (max-width: 1100px) { .db-league { grid-template-columns: repeat(3, 1fr); } }
    @media (max-width: 700px)  { .db-league { grid-template-columns: repeat(2, 1fr); } }
    @media (max-width: 520px)  { .db-league { grid-template-columns: 1fr; } }
    .dlcol { border-radius: 8px; overflow: hidden; border: 1px solid var(--epra-grey-2); }
    .dlcol-hdr { padding: 8px 10px 7px; border-bottom: 1px solid var(--epra-grey-2); }
    .dlcol-hdr .reg-name { display: block; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--epra-muted); }
    .dlcol-hdr .reg-total { display: block; font-size: 13px; font-weight: 700; color: var(--epra-navy); font-variant-numeric: tabular-nums; margin-top: 1px; }
    .dlrow { display: grid; grid-template-columns: 16px minmax(0,1fr) auto; gap: 4px; align-items: start; padding: 5px 10px; border-bottom: 1px dashed var(--epra-grey-2); }
    .dlrow:last-child { border-bottom: none; }
    .dlrow .rank { font-size: 10px; color: var(--epra-muted); font-weight: 700; padding-top: 1px; }
    .dlrow .name-wrap .name { display: block; font-size: 12px; color: var(--epra-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .dlrow .name-wrap .bar { height: 3px; background: rgba(10,77,140,0.08); border-radius: 2px; margin-top: 3px; overflow: hidden; }
    .dlrow .name-wrap .bar > span { display: block; height: 100%; border-radius: 2px; }
    .dlrow .nums { text-align: right; }
    .dlrow .nums .val { display: block; font-size: 11px; font-weight: 700; color: var(--epra-navy); font-variant-numeric: tabular-nums; }
    .dlrow .nums .pct { display: block; font-size: 10px; color: var(--epra-muted); font-variant-numeric: tabular-nums; }
