/* Base styles */
html {
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  transition: background-color var(--transition-normal), color var(--transition-normal);
}

main {
  flex: 1;
}

/* Header */
/* The header is a .section so it gets main's side padding and shares its edges. */
.site-header {
  padding-block: var(--space-lg);
}

/* The header's bottom padding already separates it from the content. */
.site-header + .section {
  padding-top: 0;
}

.site-header > .container {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  column-gap: var(--space-md);
}

/* Spans the controls' column too, so a long tagline wraps later on a phone. */
.site-header .tagline {
  grid-row: 2;
  grid-column: 2 / -1;
  /* Bulma's .subtitle:not(:last-child) block spacing would add 1.5rem under the header. */
  margin-bottom: 0;
}

/* The 2rem title splits below 336px; 360 leaves room for fonts that render wider. */
@media screen and (max-width: 359px) {
  .site-header .title {
    --bulma-title-size: var(--bulma-size-4);
  }

  .site-header .brand-mark {
    height: calc(var(--bulma-size-4) * 1.125);
  }

  .site-header .tagline {
    grid-column: 1 / -1;
  }
}

.header-controls {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.theme-toggle {
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-sm);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  transition: background-color var(--transition-fast);
}

.theme-toggle:hover {
  background-color: var(--bg-tertiary);
}

.theme-toggle svg {
  width: 20px;
  height: 20px;
}

/* Filter section */
.filters {
  margin-bottom: var(--space-lg);
}

/* A country name is several times as wide as its code, so below the tablet breakpoint the exchange and the
   country each take their own line. Sharing one phone-width row truncated "KRAKEN" down to "KRA". 769px is the
   breakpoint the mobile-only/desktop-only pair below already uses. */
.filters .exchange-field {
  flex-wrap: wrap;
  row-gap: var(--space-sm);
}

.filters .exchange-field .control {
  flex: 1 0 100%;
}

/* Bulma's addons row collapses the border between controls with a -1px margin, so a stacked
   control with no neighbour beside it renders 1px wider than the row. The desktop query below
   restores the margin, where there is a neighbour to collapse against again. Same specificity
   as Bulma's rule, won on source order. */
.filters .exchange-field .control:not(:last-child) {
  margin-inline-end: 0;
}

.filters .exchange-field .select,
.filters .exchange-field select {
  width: 100%;
}

/* Bulma squares off the inner corners of an addons row. Stacked, that reads as two half-rounded boxes, so the
   corners come back. Same specificity as Bulma's rule, won on source order. */
.filters .exchange-field .control:first-child:not(:only-child) .select select,
.filters .exchange-field .control:last-child:not(:only-child) .select select {
  border-radius: var(--bulma-radius);
}

@media screen and (min-width: 769px) {
  .filters .exchange-field {
    flex-wrap: nowrap;
  }

  .filters .exchange-field .control {
    flex: 0 1 auto;
    /* A flex item's automatic min-width is its content's min-content size, so a <select> with a long
       country name option cannot shrink below that width and pushes the row past the viewport. */
    min-width: 0;
  }

  .filters .exchange-field .control.is-expanded {
    flex: 1 1 auto;
  }

  .filters .exchange-field .control:not(:last-child) {
    margin-inline-end: -1px;
  }

  .filters .exchange-field .control:first-child:not(:only-child) .select select {
    border-bottom-right-radius: 0;
    border-top-right-radius: 0;
  }

  .filters .exchange-field .control:last-child:not(:only-child) .select select {
    border-bottom-left-radius: 0;
    border-top-left-radius: 0;
  }
}

.top-presets {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}

.top-presets .button {
  min-width: 50px;
}

/* Results */
.allocation-card {
  margin-bottom: var(--space-md);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.allocation-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.allocation-card .rank {
  font-size: 1.25rem;
  font-weight: bold;
  color: var(--accent);
}

.allocation-card .coin-name {
  font-weight: 600;
}

/* Desktop table */
.allocation-table {
  width: 100%;
}

.allocation-table th {
  white-space: nowrap;
}

/* Excluded coins keep their place in the ranking but read as context, not as holdings. Draining the colour
   reads as "unavailable" without touching contrast: the grayscale matrix is the luminance one, so every pair
   inside keeps its ratio. Fading the card instead composited its tag down to 2.75:1. */
.allocation-table .excluded-row {
  filter: grayscale(1);
  background-color: var(--bg-tertiary);
  font-size: 0.875rem;
}

.allocation-card.excluded-row {
  filter: grayscale(1);
  font-size: 0.875rem;
}

/* Bulma sets display on table rows and cards, which would beat the user agent's [hidden] rule. */
.allocation-table tbody tr[hidden],
.allocation-card[hidden] {
  display: none;
}

.excluded-toggle {
  margin-top: var(--space-md);
}

/* Responsive */
.mobile-only {
  display: block;
}

.desktop-only {
  display: none;
}

@media screen and (min-width: 769px) {
  .mobile-only {
    display: none;
  }

  .desktop-only {
    display: block;
  }
}

/* Summary section */
.summary-stat {
  text-align: center;
}

.summary-stat .value {
  font-size: 1.5rem;
  font-weight: bold;
  color: var(--accent);
}

.summary-stat .heading {
  font-size: 0.875rem;
  color: var(--text-secondary);
}

/* Freshness indicator */
.freshness {
  font-size: 0.875rem;
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.freshness.fresh {
  color: var(--success);
}

.freshness.stale {
  color: var(--warning);
}

/* Language dropdown */
.lang-dropdown .dropdown-trigger .button {
  text-transform: uppercase;
  font-weight: 600;
}

/* No results state */
.no-results {
  text-align: center;
  padding: var(--space-xl);
  color: var(--text-secondary);
}

.no-results svg {
  width: 64px;
  height: 64px;
  margin-bottom: var(--space-md);
  opacity: 0.5;
}

/* Logo */

/* Matches the h1 beside it, whose line box is Bulma's title size at line-height 1.125. */
.brand-mark {
    display: block;
    height: calc(var(--bulma-size-3) * 1.125);
    width: auto;
}

.brand-footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
}

.brand-footer .brand-mark {
    height: 24px;
}

/* Brand components. Bulma's variables only take flat colours, so the gradients live here. */
.title,
.subtitle,
.summary-stat .value,
.allocation-card .rank {
    font-family: var(--hf-font-heading);
}

.title {
    letter-spacing: 0.01em;
}

.tagline {
    font-family: var(--hf-font-body);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-secondary);
    font-size: 0.75rem;
}

.tagline.is-hero {
    letter-spacing: 0.22em;
    font-size: 0.8125rem;
}

.button.is-primary {
    background-image: linear-gradient(135deg, var(--hf-blue) 0%, var(--hf-mint) 100%);
    border: none;
    color: var(--hf-night);
    font-weight: 600;
    transition: box-shadow var(--transition-fast), transform var(--transition-fast);
}

.button.is-primary:hover {
    box-shadow: var(--hf-shadow);
    transform: translateY(-1px);
}

.box,
.card {
    border: 1px solid var(--border-color);
}

/* The one pair that fails AA on a card, so it never carries text — only a 2px ring. */
:focus-visible {
    outline: 2px solid var(--hf-blue);
    outline-offset: 2px;
}
