/* helm admin density tweaks layered on top of local Bulma.
   No external resources are referenced from this file by design. */

html {
  font-size: 15px;
}

body {
  background-color: #fafafa;
}

/* Retheme `is-primary` from Bulma's default muted turquoise (which reads as a
   disabled button) to a confident blue. This recolours every primary submit
   button app-wide (Save, Sign in, Grant access, …). We reuse Bulma's own
   link-blue HSL so these match the blue already used for navigation buttons. */
:root {
  --bulma-primary-h: 233deg;
  --bulma-primary-s: 100%;
  --bulma-primary-l: 63%;
  /* Bulma derives is-primary's text from a light shade of the base colour,
     which lands too dark to read on this blue. Force the button text white. */
  --bulma-primary-invert-l: 100%;
}

/* Default link color: a muted olive that complements the dark charcoal navbar,
   instead of Bulma's bright default link blue. The base rule only outranks
   Bulma's element-level `a`, so class-based links (.navbar-item, .button) keep
   their own colors. The hover is scoped to in-page content (.section, where the
   navbar never lives) and excludes buttons so it can't bleed into either. */
a {
  color: #6b6233;
}
.section a:not(.button):hover,
.section a:not(.button):focus {
  color: #544d28;
}

.section {
  padding: 1.5rem 1.5rem;
}

/* Public key-claim page. Bulma paints a white background on <html>, so the
   body's grey only reaches the content height; min-height makes the grey fill
   the viewport. The copy is also given roomier line spacing for easy reading,
   and the intro subtitle isn't pulled tight under the greeting. */
.claim-page {
  min-height: 100vh;
  line-height: 1.7;
}
.claim-page .title:not(.is-spaced) + .subtitle {
  margin-top: 0.5rem;
}
.claim-logo {
  height: 5rem;
  width: auto;
}

.container {
  max-width: 1140px;
}

/* Align the navbar's contents with the page body's column. The body insets its
   .container via .section's 1.5rem padding, which sits *outside* the centred
   1140px column; the previous rule instead padded the navbar's inner .container,
   which eats *into* that column and (together with the navbar-item's own 0.75rem
   padding) pushed the header ~2.25rem further right than the body. Mirror the
   body by putting the inset on the .navbar element so its .container lands at the
   same x, then cancel the edge navbar-items' 0.75rem padding with negative
   margins so the brand and right-hand items sit flush with the body content. */
.navbar {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}
.navbar-brand {
  margin-left: -0.75rem;
}
/* The right-hand group only sits at the column's edge once the navbar is
   horizontal (desktop); scoped so it can't shift the collapsed mobile menu. */
@media screen and (min-width: 1024px) {
  .navbar-end {
    margin-right: -0.75rem;
  }
}

/* Header links: pure white. Bulma dims dark-navbar items to 90% lightness;
   bumping the lightness var to 100% keeps the hover/active states white too.
   The burger defaults to Bulma's link colour; force it white so the
   hamburger and its open "X" (spans inherit currentColor) match. */
.navbar.is-dark {
  --bulma-navbar-item-color-l: 100%;
  --bulma-navbar-burger-color: #fff;
}

/* Brand logo: drop a PNG at src/public/logo.png (served at
   /assets/logo.png). Bulma caps navbar images at 1.75rem; allow a
   slightly taller mark. The alt text shows until the file exists. */
.navbar-item.brand-logo img {
  max-height: 2rem;
}

/* The collapsed navbar opens as a full-width drawer below Bulma's 1024px
   breakpoint. Bulma stacks the items but leaves the account block (avatar +
   log out) visually fused to the page links and the log-out button floating as
   a small pill. Tidy the drawer: roomier rows, a divider before the account
   block, a clear account row, and a full-width log-out button. */
@media screen and (max-width: 1023px) {
  .navbar.is-dark .navbar-menu {
    padding-bottom: 1rem;
    box-shadow: 0 8px 16px rgba(10, 10, 10, 0.3);
  }
  .navbar-menu .navbar-item {
    padding: 0.85rem 1.5rem;
  }
  /* Separate the account block from the page links above it. */
  .navbar-menu .navbar-end {
    margin-top: 0.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
  }
  /* The username reads as the section's heading rather than another link. */
  .navbar-end .navbar-user span {
    font-weight: 600;
  }
  /* The log-out control fills its row at a comfortable touch size instead of
     sitting as a small pill against the left edge. */
  .navbar-end .navbar-item:has(form) {
    padding-top: 0.25rem;
  }
  .navbar-end .navbar-item form {
    width: 100%;
  }
  .navbar-end .navbar-item form .button.is-small {
    width: 100%;
    justify-content: center;
    font-size: 1rem;
    height: 2.75rem;
  }
}

/* Tighter tables for a dense admin UI. */
.table td,
.table th {
  padding: 0.4em 0.6em;
  vertical-align: middle;
}

/* Sortable column headers: keep the header text in the normal dark colour
   (not the olive link colour) and show a muted sort glyph that darkens on
   hover and when its column is the active sort. */
.table th a.th-sort {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  color: inherit;
  white-space: nowrap;
}
.table th a.th-sort .icon {
  color: #b5b1a0;
}
.table th a.th-sort:hover,
.table th a.th-sort:hover .icon,
.table th a.th-sort.is-active .icon {
  color: #4a4524;
}

/* Constrain stacked forms to a comfortable reading width. */
.form-grid {
  max-width: 32rem;
}

/* Two-factor setup: a scannable QR plus the manual-entry secret beneath it. */
.totp-qr {
  width: 12rem;
  height: 12rem;
  margin-bottom: 1rem;
  padding: 0.5rem;
  background: #fff;
  border: 1px solid #e8e6da;
  border-radius: 6px;
}
.totp-qr svg {
  display: block;
  width: 100%;
  height: 100%;
}
.totp-secret {
  font-size: 1rem;
  letter-spacing: 0.08em;
  word-break: break-all;
}

/* Group related fields (e.g. the USD:CAD rate and the CAD amount) in a tinted,
   bordered box so they read as one unit. */
.field-group {
  min-width: 0;
  margin: 0 0 0.75rem;
  padding: 0.85rem 1rem 1rem;
  background-color: #f3f2ea;
  border: 1px solid #e8e6da;
  border-radius: 6px;
}
.field-group > .field:last-child {
  margin-bottom: 0;
}
.field-group-title {
  margin-bottom: 0.6rem;
  font-weight: 600;
  color: #4a4524;
}

.box {
  margin-bottom: 1.25rem;
}

/* Section title for a .box. Distinct from Bulma's tiny uppercase .heading label
   (still used for the stat columns): a proper heading in the brand olive, led by
   an accent bar and closed by a hairline divider across the box. */
.box-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid #e8e6da;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #4a4524;
}
.box-title::before {
  content: "";
  flex: none;
  width: 0.25rem;
  height: 1.15em;
  border-radius: 2px;
  background-color: #6b6233;
}
/* Secondary note pinned to the right of a .box-title (e.g. last-synced time). */
.box-title-note {
  margin-left: auto;
  font-size: 0.8rem;
  font-weight: 400;
  letter-spacing: 0;
  color: #8a8568;
}

/* Mobile-only stacked cards: the per-period sales figures, one card each, used
   in place of the wide table on narrow screens. */
.sales-cards {
  margin-bottom: 1rem;
}
.sales-card {
  padding: 0.6rem 0.75rem;
  border: 1px solid #e8e6da;
  border-radius: 6px;
}
.sales-card + .sales-card {
  margin-top: 0.5rem;
}
.sales-card-period {
  margin-bottom: 0.35rem;
  font-weight: 600;
  color: #4a4524;
}
.sales-card-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.15rem 0;
}
.sales-card-row > span:first-child {
  color: #8a8568;
}
.sales-card-value {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Page heading + lede pair. */
.page-head {
  margin-bottom: 1.25rem;
}
.page-head .title {
  margin-bottom: 0.25rem;
}

/* Project detail heading: the icon sits beside the title on one row. The source
   images are large (1024x1024), so we scale them right down to icon size. */
.project-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.project-head .title {
  margin-bottom: 0;
}
/* Action buttons (Revenue shares/payments, Financial access, Edit) sit grouped
   at the far right of the project heading row. */
.project-head-actions {
  margin-left: auto;
  margin-bottom: 0;
  justify-content: flex-end;
}
.project-head-actions .button {
  margin-bottom: 0;
}
.project-icon {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 8px;
  object-fit: cover;
}
/* Mobile-only replacement for the action button row: a single dropdown pushed to
   the far right of the heading, with icon + label aligned in each menu item. */
.project-head-menu {
  margin-left: auto;
}
.project-head-menu .dropdown-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Project name shown beside its icon in list/dashboard table rows. */
.project-cell {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.project-icon-sm {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 6px;
  object-fit: cover;
}
/* On narrow screens the game names crowd out the table columns, so hide the
   name and show only the icon (still a link via the surrounding anchor). */
@media (max-width: 768px) {
  .project-cell .project-name {
    display: none;
  }
  /* The Projects table has a column to spare, so keep the full game title. */
  .projects-table .project-cell .project-name {
    display: inline;
  }
  /* Drop the "Est. amount"/"Amount" prefix in table headers, leaving just the
     currency, e.g. "(USD)" / "(CAD)". */
  .amount-label {
    display: none;
  }
  /* Show the compact "06-26" period instead of "June 2026". */
  .period-long {
    display: none;
  }
  /* Show abbreviated amounts ("$128.6K") instead of full ("$128,599"). */
  .amount-full {
    display: none;
  }
  /* Generic opt-out for table columns that don't fit a phone (e.g. the key
     requests list hides Created by / Created / Expires). */
  .hide-narrow {
    display: none;
  }
}
/* The abbreviated amount is only shown on narrow screens (rule below). Declared
   after the media query that hides .amount-full so the two never collide. */
.amount-short {
  display: none;
}
/* The compact period is only shown on narrow screens (see media query above). */
.period-short {
  display: none;
}
@media (max-width: 768px) {
  .amount-short {
    display: inline;
  }
  .period-short {
    display: inline;
  }
}
/* Inline icon when a breadcrumb crumb carries one (e.g. project crumbs). */
.title .project-icon-sm {
  display: inline-block;
  vertical-align: middle;
  margin-right: 0.4rem;
}

/* Free-form list of games rendered under a bundle name on the sales-by-bundle
   report. Preserves user-entered line breaks. */
.bundle-games {
  font-size: 0.85em;
  color: #7a7a7a;
  white-space: pre-line;
  margin-top: 0.15rem;
}

/* Inline forms inside table cells should not add vertical rhythm. */
td form {
  margin: 0;
}

/* Confirmation modal: a near-black, high-opacity backdrop. */
.modal-background {
  background-color: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(2px);
}
.modal-card {
  max-width: 28rem;
}
.modal-card-foot {
  gap: 0.5rem;
}

/* Daily sales bar chart. The hover tooltip and highlight are driven by
   /assets/chart.js (data-tip attributes), replacing the slow native <title>. */
.sales-chart .bar {
  cursor: pointer;
  /* `fill` is a presentation attribute, so brightness keeps each bar's own
     colour (blue/red) while making the hovered one pop. */
  transition: filter 0.08s ease;
}
.sales-chart .bar:hover {
  filter: brightness(1.18);
}

.chart-tip {
  position: fixed;
  z-index: 50;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.06s ease;
  background-color: #1f2229;
  color: #fff;
  font-size: 0.75rem;
  line-height: 1.2;
  padding: 0.3rem 0.5rem;
  border-radius: 4px;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
.chart-tip.is-visible {
  opacity: 1;
}

/* User detail page: avatar + heading + status tags on the left, actions on
   the right. Mirrors the project-head pattern but for people. */
.user-head-info {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.user-head-info .title {
  margin-bottom: 0;
}
/* Reusable initials-in-a-circle avatar. Rendered by the `userAvatar` view
   helper so the markup stays consistent everywhere a person is shown. The
   background colour comes from a `.user-avatar-cN` class chosen by hashing
   the user's initials, so the same initials are always the same colour. */
.user-avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  font-weight: 600;
  font-size: 1.1rem;
  color: #fff;
  background: #6b6233;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1;
}
.user-avatar.is-small {
  width: 1.75rem;
  height: 1.75rem;
  font-size: 0.7rem;
}
/* 24 dark backgrounds, all chosen to keep ≥4.5:1 contrast with white text. */
.user-avatar-c0  { background: #b91c1c; } /* red */
.user-avatar-c1  { background: #991b1b; } /* deep red */
.user-avatar-c2  { background: #c2410c; } /* orange */
.user-avatar-c3  { background: #b45309; } /* amber */
.user-avatar-c4  { background: #a16207; } /* ochre */
.user-avatar-c5  { background: #4d7c0f; } /* olive */
.user-avatar-c6  { background: #15803d; } /* green */
.user-avatar-c7  { background: #166534; } /* forest */
.user-avatar-c8  { background: #047857; } /* emerald */
.user-avatar-c9  { background: #0f766e; } /* teal */
.user-avatar-c10 { background: #155e75; } /* deep cyan */
.user-avatar-c11 { background: #0e7490; } /* cyan */
.user-avatar-c12 { background: #0369a1; } /* sky */
.user-avatar-c13 { background: #1d4ed8; } /* blue */
.user-avatar-c14 { background: #1e3a8a; } /* navy */
.user-avatar-c15 { background: #4338ca; } /* indigo */
.user-avatar-c16 { background: #6d28d9; } /* violet */
.user-avatar-c17 { background: #7e22ce; } /* purple */
.user-avatar-c18 { background: #a21caf; } /* fuchsia */
.user-avatar-c19 { background: #86198f; } /* magenta */
.user-avatar-c20 { background: #be185d; } /* pink */
.user-avatar-c21 { background: #be123c; } /* rose */
.user-avatar-c22 { background: #334155; } /* slate */
.user-avatar-c23 { background: #44403c; } /* stone */

/* Navbar pairing: the small avatar sits beside the username text. */
.navbar-user {
  gap: 0.5rem;
}
/* Username + avatar pairing used in the user list table. */
.user-cell {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.user-head-tags {
  margin-top: 0.45rem;
  margin-bottom: 0;
}
.user-head-tags .tag {
  margin-bottom: 0;
}

/* Shared two-column "label / value" table used on detail pages. Caps the
   label column so values get the space; values pick up the brand text colour. */
.detail-table th {
  width: 9rem;
  color: #4a4524;
  font-weight: 600;
}
.detail-table td.num {
  font-variant-numeric: tabular-nums;
}
.user-address {
  white-space: pre-line;
}

/* Royalty payment hero: the amount paid is the headline; the status pill and
   paid-on date sit at the far right. Stacks on narrow viewports. */
.payment-hero {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.payment-hero-amount {
  flex: 1 1 16rem;
  min-width: 0;
}
.payment-hero-amount .heading {
  margin-bottom: 0.35rem;
}
.payment-hero-amount .title {
  margin-bottom: 0.25rem;
  font-variant-numeric: tabular-nums;
}
.payment-hero-unit {
  font-size: 0.55em;
  color: #7a7a7a;
  font-weight: 500;
  margin-left: 0.25rem;
  letter-spacing: 0.02em;
}
.payment-hero-cad {
  color: #4a4524;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.payment-hero-rate {
  color: #7a7a7a;
  margin-left: 0.4rem;
  font-weight: 400;
}
.payment-hero-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.6rem;
  text-align: right;
}
.payment-hero-date {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: #4a4524;
  font-weight: 500;
}

/* Calculation row: keep the "Net × Rate = Result" expression muted; the
   bolded headline amount in the hero is the answer. */
.payment-calc-formula {
  color: #7a7a7a;
}

/* Sales-periods editor: tighten the inline-edit table so date inputs, label
   and the icon-only Save/Delete actions all land on one baseline. */
.sale-periods-table td {
  vertical-align: middle;
}
/* Icon-only Save/Delete sit side by side, right-aligned. Each lives in its
   own <form> (different actions), so we wrap both forms in a flex container
   to keep them on a single row instead of letting the block-level forms
   stack vertically. */
.sale-periods-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.25rem;
}
.sale-periods-actions form {
  margin: 0;
}

/* Add form: From | To | Label (stretches) | Add. Single row on the desktop,
   stacked on mobile so the label input still gets the full width it needs. */
.sale-periods-add {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
}
.sale-periods-add .field {
  margin-bottom: 0;
}
.sale-periods-add-label {
  flex: 1 1 14rem;
}



/* Email-template body shown on a template's detail page: a monospace block that
   keeps the author's line breaks (a plain <pre>) but wraps long lines so a stray
   long URL can't force a horizontal scrollbar. */
.email-template-body {
  white-space: pre-wrap;
  word-break: break-word;
  background-color: #f7f5ec;
  border-radius: 4px;
  padding: 0.75rem 1rem;
}

/* Earnings page: rows are grouped per person, each group opened by a bold
   name row and closed by a bold subtotal row; the spacer row separates one
   person's group from the next. */
.earnings-user td,
.earnings-subtotal td {
  font-weight: 600;
}
.earnings-spacer td {
  border: none;
  padding: 0.75rem 0;
  /* Bulma paints the table white; matching the page background makes the
     spacer read as a true gap between groups rather than an empty row. */
  background-color: #fafafa;
}
