/* PolyMoby — minimal custom styles over Bulma. */

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;
}

.is-monospace {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  word-break: break-all;
}

/* Wallet display names can be long ENS names. Truncate with an ellipsis and
   reveal the full name on hover via the `title` attribute tooltip. */
.wallet-name {
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  vertical-align: middle;
}

/* The trades table's market names can be long questions. Truncate on desktop
   with an ellipsis (the full text stays in the DOM and in the `title` tooltip);
   `ch` units make the 30-character budget literal. */
.market-name {
  max-width: 30ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  vertical-align: middle;
}

.wallet-address {
  white-space: nowrap;
}

/* Muted table header typography (scoped to Bulma's specificity). */
table.table thead th {
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.table td {
  vertical-align: middle;
}

/* Nine columns of numbers AND a bar in each of the four split-by-outcome ones:
   the default cell padding is far more horizontal room than the table can spare.
   Trimming it is what keeps the question table as close to fitting its container
   as a nine-column analyst table can get. */
table.table th,
table.table td {
  padding-left: 0.4rem;
  padding-right: 0.4rem;
}

/* The table's scroll container is the POSITIONING context for the
   `visually-hidden` hint spans inside it. Those spans are `position: absolute`;
   with no positioned ancestor they resolve against the initial containing block
   and sit at the wide table's static x, escaping this container's
   `overflow-x: auto` clip — giving /questions a page-level horizontal scrollbar
   at 769-999px. As the containing block, the container clips them instead. */
.table-container {
  position: relative;
}

/* A question can be arrived at by fragment when a wallet's position table links
   to it (`#q-<condition_id>`). The scroll brings that question's row into view;
   this marks WHICH row the reader was sent to, because the page around it holds
   up to two hundred others. */
#questions-table tbody td:target {
  background-color: var(--bulma-scheme-main-bis);
  box-shadow: inset 3px 0 0 0 currentColor;
}

/* Per-cell label for the small-screen card layout. Hidden on DESKTOP, where the
   <th> already associates each cell with its column — the repo's rule is that a
   value is announced once, never twice (see the split bar's aria rule). Below
   768px the <thead> leaves the accessibility tree, so this real DOM text (not
   CSS-generated content, which screen readers do not reliably announce) is what
   keeps each value labelled for a phone user. */
.cell-label {
  display: none;
}

/* --- the split bar of a question row (ticket 03) ---------------------------
   Fixed width and split only: the bar carries the direction (green = the
   outcome named Yes, red = No, grey = no Yes/No pair) and never the size of the
   numbers behind it. The percentages arrive as inline widths computed in
   app/services/bars.py. */
.split-bar {
  display: inline-flex;
  width: 2.25rem;
  height: 0.5rem;
  vertical-align: middle;
  background: #dbdbdb;
  border-radius: 2px;
  overflow: hidden;
}

.split-seg {
  height: 100%;
  display: inline-block;
}

.split-yes {
  background: #48c774; /* Bulma success */
}

.split-no {
  background: #f14668; /* Bulma danger */
}

.split-neutral {
  background: #b5b5b5;
}

/* A bar whose values were never recorded: hatched, and NOT the same grey as the
   track, so an unmeasured split cannot be mistaken for a confident one OR for
   the empty bar a question with no split renders (the hint carries the reason). */
.split-seg.is-unknown {
  background: repeating-linear-gradient(45deg, #dbdbdb 0 3px, #bbbbbb 3px 6px);
}

/* The labelled Yes/No numbers beside a bar: the side's name on the LEFT and its
   number on the RIGHT of the cell, one side per line — so the numbers line up
   down the column however wide the labels are. The colours are Bulma's
   scheme-aware success/danger: the darker shades this used were unreadable once
   the OS asks for a dark scheme. */
.yes-no-side {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  white-space: nowrap;
}

/* Every split-by-outcome column pairs its bar with its labelled numbers: the bar
   sits at the left of a right-aligned cluster and the two labelled rows sit
   beside it, vertically centred — instead of the bar floating on its own line
   above numbers it was not aligned with. */
.split-pair {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
}

.outcome-yes {
  color: var(--bulma-success-on-scheme);
}

.outcome-no {
  color: var(--bulma-danger-on-scheme);
}

.outcome-neutral {
  color: var(--bulma-text-weak);
}

/* The whale-capital TOTAL is money, not a "Yes". It was green, which is this
   table's word for the outcome named Yes, so a green total read as one. Bulma's
   `has-text-info` is a fixed pale cyan (1.7:1 on white) and the link colour is
   the largest-position column's, so this takes the info hue at a lightness that
   clears 4.5:1 on white and on the dark scheme's surface, and stays clear of both
   the green/red outcomes and the indigo links. */
.whale-total {
  color: hsl(var(--bulma-info-h), var(--bulma-info-s), 34%);
}

@media (prefers-color-scheme: dark) {
  .whale-total {
    color: hsl(var(--bulma-info-h), var(--bulma-info-s), 72%);
  }
}

/* Hint text that is present for screen readers and for tests, but not shown.
   Every `title` hint repeats here, because `title` reaches neither touch nor a
   screen reader. */
.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;
}

/* A data-dense app: Bulma caps the container at 1152px on a 1280px screen, which
   is narrower than the nine-column question table now needs. From the desktop
   breakpoint up, give the content Bulma's own xl width (1344px) so the table
   fits its container instead of scrolling horizontally inside it. */
@media screen and (min-width: 1024px) {
  /* a data-dense table needs the width more than the page needs its gutter */
  main.section {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }

  /* match Bulma's own selector specificity (.container:not(...):not(...)),
     or its 1152px rule wins the cascade */
  .container:not(.is-max-tablet):not(.is-max-desktop) {
    max-width: 1344px;
  }
}

/* Root cause behind the muted text on every tinted panel. Bulma's own
   `--bulma-text-weak-l` is 48% (light) / 53% (dark), which against Bulma's OWN
   `--bulma-scheme-main-bis` surfaces — the `.site-intro` panel, the `.footer`,
   the `.how-ranked` summary — measures 4.49:1 and 4.41:1, both under AA. The
   token is re-pointed at 44% / 60% once, so every muted paragraph follows: those
   measure 5.19:1 / 5.67:1 on the tinted panels and 5.43:1 / 5.94:1 on the page,
   with the muted hierarchy still visibly lighter than body text. */
:root {
  --bulma-text-weak-l: 44%;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bulma-text-weak-l: 60%;
  }
}

/* Bulma's colour HELPERS are fixed values with no dark-scheme arm: measured,
   `.has-text-grey` (#69748c) is 3.68:1 on the dark surface and 4.49:1 on white —
   both under AA, and the dark case was a REGRESSION on the very panel this
   revision made scheme-aware. `.has-text-success` (#48c774) is 2.14:1 on white.
   The scheme-aware tokens measure 4.63:1 dark / 4.68:1 light (text-weak) and
   8.17:1 / 8.48:1 (success-on-scheme), so the three helpers are re-pointed here
   once rather than at every use site. Bulma marks them `!important`, hence this. */
.has-text-grey {
  color: var(--bulma-text-weak) !important;
}

.has-text-success {
  color: var(--bulma-success-on-scheme) !important;
}

.has-text-danger {
  color: var(--bulma-danger-on-scheme) !important;
}

/* ONE control per page puts away every explanation block - the definitions, the
   caveats, the nav notes, the freshness stamp. The state lives in a hidden but
   FOCUSABLE checkbox, reachable by keyboard, and the hiding is done by `:has()`
   on the body, so the page still ships no JavaScript.

   The `@supports` gate is load-bearing: without `:has()` the hiding rule would be
   dropped and the toggle would be a control that does nothing when checked, which
   is worse than no control at all. So the toggle only appears where it works. */
.hide-explanations {
  display: none; /* re-enabled by @supports */
  text-align: right;
  /* Bulma's `.columns` carries a -0.75rem top margin, which pulled a following
     section up over this control's lower 9px and swallowed real clicks on it.
     The control keeps its own bottom margin so it can never be overlapped. */
  margin-bottom: 0.75rem;
}

.hide-explanations .when-hidden {
  display: none;
}

.hide-explanations > input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.hide-explanations > label {
  cursor: pointer;
  font-size: 0.75rem;
  text-decoration: underline;
  text-underline-offset: 2px;
  opacity: 0.75;
}

.hide-explanations > label:hover {
  opacity: 1;
}

.hide-explanations > input:focus-visible ~ label {
  outline: 2px solid currentColor;
  outline-offset: 2px;
  border-radius: 2px;
}

@supports selector(:has(*)) {
  .hide-explanations {
    display: block;
  }

  body:has(#hide-explanations-toggle:checked) .dismissible {
    display: none;
  }

  body:has(#hide-explanations-toggle:checked) .hide-explanations .when-shown {
    display: none;
  }

  body:has(#hide-explanations-toggle:checked) .hide-explanations .when-hidden {
    display: inline;
  }
}


/* The current tab is marked on the (always dark) navbar with a translucent pill
   and an underline, so it reads the same whether the page follows a light or a
   dark scheme — Bulma's own .is-active background was too faint to spot. */
.navbar .navbar-item.is-active {
  font-weight: 700;
  background-color: hsla(0, 0%, 100%, 0.18);
  border-radius: 4px;
  box-shadow: inset 0 -2px 0 0 currentColor;
}

/* The navbar-end holds the share row (D14). Bulma already puts it at the right
   on the desktop bar; this only makes it a centred flex row so the label and the
   pills line up with the nav items. */
.navbar .navbar-end {
  display: flex;
  align-items: center;
}

/* Reference prose — how a term is defined, how a category's bar was derived — is
   needed but was fifteen lines between the reader and the table. One summary line
   states the rule and the detail opens on request; a native <details> keeps that
   detail keyboard-reachable, JavaScript-free, and in the DOM for anything reading
   the page rather than looking at it. */
.how-ranked {
  border: 1px solid var(--bulma-border-weak);
  border-radius: 6px;
  padding: 0.35rem 0.75rem;
  background: var(--bulma-scheme-main-bis);
}

.how-ranked > summary {
  cursor: pointer;
  color: var(--bulma-text-weak);
}

.how-ranked > summary strong {
  color: var(--bulma-text);
}

.how-ranked[open] > summary {
  margin-bottom: 0.6rem;
}

/* The homepage's intro panel, replacing a `hero is-light`: that hero kept a
   fixed light background while its paragraph used a scheme-aware grey, which the
   OS dark scheme turned into light grey on white — unreadable. */
.site-intro {
  background: var(--bulma-scheme-main-bis);
  border: 1px solid var(--bulma-border-weak);
  border-radius: 6px;
  padding: 1.25rem 1.5rem;
}

/* The hero's data line (ticket 02): the published run's figures, the homepage's
   single freshness statement and its own htmx poll. The prose is muted, so the
   figures take body weight to read as the page's evidence; a long run of text
   (a compact figure, a wallet count) wraps INSIDE the panel rather than widening
   it and giving a phone a horizontal scroll. */
.headline-stats {
  margin-top: 0.75rem;
  line-height: 1.6;
  overflow-wrap: break-word;
}

.headline-stats strong {
  color: var(--bulma-text);
}

/* The homepage teasers: one compact, scheme-aware list per section, so both the
   wallets and the questions ranking are visible side by side. */
/* Bulma's `.columns` wraps, and a nowrap teaser row gives its column a ~640px
   min-content, so the two panels STACKED on every desktop below ~1373px instead
   of sitting two-up as designed (`min-content: 0` lets them shrink, and the
   teaser name then ellipsises). */
.teaser-column {
  min-width: 0;
}

.teaser-list {
  list-style: none;
  margin: 0;
}

.teaser-list li {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--bulma-border-weak);
}

.teaser-list li:last-child {
  border-bottom: 0;
}

.teaser-rank {
  flex: none;
  width: 1.5rem;
  color: var(--bulma-text-weak);
}

.teaser-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.teaser-value {
  flex: none;
  font-weight: 600;
}

/* --- the share row and the outbound marker (ticket 02) ---------------------
   The share row (partials/share.html) renders ONCE now, in the dark navbar's
   top-right corner (`base.html`'s `navbar-end`, D14) — gated by the route
   registry's `share` policy, so only the data pages carry it (D3/D15). It is a
   label and three intent links; separating the label from the links and the
   links from each other is what makes the row parse as "share this page" rather
   than as three stray words. */
.share-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/* On the dark bar the label needs its own colour: Bulma's light-scheme greys
   nearly vanish against the navbar. */
.share-row-label {
  margin-right: 0.25rem;
  color: hsla(0, 0%, 100%, 0.75);
}

/* A share link is a real control, not body text: a bordered pill with enough
   height and padding to be a comfortable touch target on a phone. The colours
   are the dark-bar set — a light-on-dark pill that clears the navbar
   background — and the focus ring is kept, drawn from the current colour. */
.share-link {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  padding: 0 0.75rem;
  border: 1px solid hsla(0, 0%, 100%, 0.4);
  border-radius: var(--bulma-radius-small);
  color: hsl(0, 0%, 100%);
  text-decoration: none;
}

.share-link:hover {
  border-color: hsl(0, 0%, 100%);
  background-color: hsla(0, 0%, 100%, 0.14);
  color: hsl(0, 0%, 100%);
}

.share-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* The outbound button beside a position's market name
   (partials/position_rows.html): a compact ↗ that used to read as stray
   punctuation. A small bordered square gives it an affordance edge, and hover
   and focus name it as a control that leaves the site. Kept inline so it sits
   on the market-name line rather than below it. */
.position-outbound {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0 0.3rem;
  border: 1px solid var(--bulma-border);
  border-radius: var(--bulma-radius-small);
  color: var(--bulma-text-weak);
  text-decoration: none;
  line-height: 1.5;
}

.position-outbound:hover {
  border-color: var(--bulma-link-text-hover);
  color: var(--bulma-link-text-hover);
}

.position-outbound:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* --- navigation on small screens -------------------------------------------
   Bulma hides .navbar-menu below 1024px and expects a .navbar-burger to toggle
   .is-active; this app ships no burger, so the whole navigation (Questions, Top
   Wallets, Methodology, About) was invisible and unreachable on every phone.
   Four short items do not need a collapsed menu, so the menu is simply shown as
   a wrapping row instead of adding a burger and its JS. */
@media screen and (max-width: 1023px) {
  .navbar .navbar-menu {
    display: block;
    box-shadow: none;
    padding: 0 0.5rem 0.35rem;
  }

  .navbar .navbar-start,
  .navbar .navbar-end {
    display: flex;
    flex-wrap: wrap;
    margin: 0;
  }

  .navbar .navbar-item {
    display: block;
    padding: 0.4rem 0.7rem;
  }
}

/* --- data tables on small screens ------------------------------------------
   The leaderboard, the question ranking and the position table are read-only,
   so ONE source row can be re-laid-out into a card per record: no duplicated
   markup, and nothing that breaks form serialization (there are no inputs).
   Each cell shows its own label from a real `span.cell-label` (hidden on
   desktop, where the `<th>` already names the column); the lead cell
   (`cell-title`) becomes the card's heading. Desktop keeps the real table. */
@media screen and (max-width: 768px) {
  #wallets-table thead,
  #questions-table thead,
  #positions-table thead {
    display: none;
  }

  #wallets-table tbody tr,
  #questions-table tbody tr,
  #positions-table tbody tr {
    display: block;
    border: 1px solid var(--bulma-border);
    border-radius: 6px;
    padding: 0.6rem 0.8rem;
    margin-bottom: 0.8rem;
    background: var(--bulma-scheme-main);
  }

  #wallets-table td,
  #questions-table td,
  #positions-table td {
    display: block;
    overflow: hidden;
    border: 0;
    padding: 0.3rem 0;
    text-align: right;
  }

  /* The label floats left and the value right-aligns on the same line. A BLOCK
     cell matters here where a flex row does not: the whale cells carry a number
     AND a split bar, and the outcome cells stack two labels — a flex row spread
     or clipped them at the card edge, while a block lets the value wrap inside
     the card and keeps each outcome line together. */
  /* one column per card: the bar goes back above its numbers */
  .split-pair {
    display: block;
  }

  #wallets-table td .cell-label,
  #questions-table td .cell-label,
  #positions-table td .cell-label {
    display: block;
    float: left;
    max-width: 55%;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--bulma-text-weak);
  }

  /* The lead cell is the card's heading: full width, no label of its own. */
  #wallets-table td.cell-title,
  #questions-table td.cell-title,
  #positions-table td.cell-title {
    display: block;
    text-align: left;
    font-size: 1.02rem;
    padding-bottom: 0.45rem;
    margin-bottom: 0.3rem;
    border-bottom: 1px solid var(--bulma-border-weak);
  }

  /* The trades table is NOT in the card layout — it scrolls horizontally — so
     the market name must WRAP here instead of being cut: a hover-only tooltip is
     unusable on touch and a 30-character cut would make the name unreadable. The
     full text stays in the DOM, so copy and screen readers still get it whole. */
  .market-name {
    max-width: none;
    white-space: normal;
  }

  .table-container {
    overflow: visible;
  }
}

/* --- the dashboard's four capital visualisations (ticket 04) ----------------
   Server-rendered bars over a CAPITAL palette — never the question row's Yes/No
   green/red, because these bars are not a Yes/No split: a solid capital blue for
   the leading part (the top-N, whale capital, the capital a bucket holds) and a
   light blue tint for the rest of that measure; the one count measure — the wallet
   count (D4.3) — takes its own amber instead, so "blue = capital, amber = wallets"
   is a rule a reader can hold. Every bar is decorative (aria-hidden,
   set in split_bar) and the numbers behind it are DOM text beside it (ADR-0014,
   D10). The shared `split_bar` macro is reused untouched, so the dashboard bar
   takes its full width and its scheme-aware track through these descendant rules
   rather than by changing the question row's component. */
.dashboard-bars .split-bar,
.dashboard-cell-bar .split-bar {
  width: 100%;
  height: 0.75rem;
  background: #dbdbdb;
}

/* Blue reads as CAPITAL — the site's OWN info hue, the one `.whale-total` already
   paints whale money with — so a bar's blue and the whale figure agree: solid =
   the emphasised part, tint = the rest of the capital. The wallet COUNT is a
   second, separate measure, so it takes a second hue — amber, Bulma's warning
   hue — because blue vs. amber is the colourblind-safe pair, and it lets the
   distribution's inversion read by colour as well as by width. Every fill clears
   3:1 against what it borders (light scheme, measured): blue 3.4:1 on the track
   and 3.3:1 against its own tint; amber 3.1:1 on the track. */
.split-strong {
  background: hsl(var(--bulma-info-h), 68%, 38%);
}

.split-soft {
  background: hsl(var(--bulma-info-h), 62%, 82%);
}

.split-wallets {
  background: hsl(var(--bulma-warning-h), 90%, 33%);
}

/* The labelled chart row: label, bar, figures. It fixes NO width of its own and
   lets a long label break, so a phone never gets a horizontal scroll — the same
   rule the homepage stat strip follows. */
.dashboard-bar-row {
  display: grid;
  grid-template-columns: minmax(5.5rem, min-content) 1fr auto;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
  overflow-wrap: anywhere;
}

.dashboard-bar-label {
  color: var(--bulma-text-weak);
}

.dashboard-bar-value {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.dashboard-bars {
  margin: 0.5rem 0 1rem;
}

/* A bar drawn inside a table cell, under the number it measures. */
.dashboard-cell-bar {
  display: block;
  margin-top: 0.35rem;
}

.dashboard-cell-value {
  display: block;
  font-size: 0.75rem;
  color: var(--bulma-text-weak);
  white-space: nowrap;
}

.dashboard-legend {
  font-size: 0.85rem;
  color: var(--bulma-text-weak);
}

@media (prefers-color-scheme: dark) {
  .dashboard-bars .split-bar,
  .dashboard-cell-bar .split-bar {
    background: #4a4a4a;
  }

  .split-strong {
    background: hsl(var(--bulma-info-h), 70%, 62%);
  }

  .split-soft {
    background: hsl(var(--bulma-info-h), 45%, 32%);
  }

  .split-wallets {
    background: hsl(var(--bulma-warning-h), 90%, 62%);
  }
}
