/* ============================================================================
   HashQA — stylesheet

   Built for the two places it is actually used: an admin on a laptop reading
   tables, and a tester on a phone working down a checklist with one thumb.
   The checklist is therefore mobile-first and its controls are large; the
   admin tables scroll sideways rather than reflow, because a results table
   squeezed into a phone column is unreadable either way.
   ============================================================================ */

/* The palette is the Hashback brand set: green as the action colour, blue as
   the structural accent, on a blue-shifted near-black. It is a single dark
   theme rather than a light/dark pair — a tester comparing a screen against a
   checklist should not have the tool's own chrome change under them. */

:root {
  /* ── Primary green ── */
  --primary: #41aa28;
  --primary-d: #41aa28;
  --primary-l: #41aa28;

  /* ── Blue accent ── */
  --blue: #4154f1;
  --blue-d: #2d3ecf;
  --blue-l: #6b7fff;
  --blue-glow: rgba(65, 84, 241, .35);
  --blue-soft: rgba(65, 84, 241, .1);
  --blue-border: rgba(65, 84, 241, .25);

  /* ── Gradients ── */
  --grad-primary: linear-gradient(135deg, #00b300 0%, #4154f1 100%);
  --grad-soft: linear-gradient(135deg, rgba(0, 179, 0, .12) 0%, rgba(65, 84, 241, .12) 100%);
  --grad-glow: linear-gradient(135deg, rgba(0, 179, 0, .06) 0%, rgba(65, 84, 241, .08) 100%);

  /* ── Backgrounds (blue-shifted darks) ── */
  --dark: #090b12;
  --dark2: #0f1118;
  --dark3: #161a28;
  --card-bg: #111520;

  /* ── Borders ── */
  --border: rgba(65, 84, 241, .16);
  --border-g: rgba(0, 179, 0, .18);

  /* ── Text ── */
  --text-muted: #7a85b0;
  --text-body: #c2c8e8;
  --white: #f0f2ff;
  --grad:       linear-gradient(135deg,#00b300 0%,#4154f1 100%);
  --sidebar-w:  240px;
  --topbar-h:   58px;
  --amber:      #febc2e;
  --red:        #e06c75;
  --purple:     #c792ea;

  /* ── Roles the rest of the stylesheet asks for ──
     Mapped onto the brand set above so a palette change happens in one
     place; the views only ever name these or the brand tokens. */
  --bg: var(--dark);
  --surface: var(--card-bg);
  --surface-2: var(--dark3);
  --text: var(--text-body);
  --muted: var(--text-muted);

  /* Result colours. The tinted backgrounds are the status colour at low alpha
     rather than fixed hexes, so they sit on the dark surface without the
     washed-out look a light-theme tint gets here. */
  --pass: #5ec945;
  --pass-bg: rgba(65, 170, 40, .16);
  --fail: var(--red);
  --fail-bg: rgba(224, 108, 117, .14);
  --blocked: var(--amber);
  --blocked-bg: rgba(254, 188, 46, .14);
  --na: var(--text-muted);
  --na-bg: rgba(122, 133, 176, .14);

  --focus-ring: 0 0 0 3px var(--blue-glow);

  --radius: 12px;
  --gap: 1rem;
  --gap-sm: 0.5rem;
  --gap-lg: 1.75rem;
}

/* Tell the browser the page is dark so native widgets — scrollbars, the date
   picker, form autofill — are drawn to match instead of arriving white. */
:root { color-scheme: dark; }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;

  /* A single fixed wash of the brand gradient, not a repeating one: it keeps
     the near-black from reading as flat without moving while the page
     scrolls, which on a long checklist would be a distraction. */
  background-image: var(--grad-glow);
  background-attachment: fixed;
  min-height: 100vh;
}

.shell { width: min(1180px, 100% - 2rem); margin-inline: auto; }
.main { padding-block: var(--gap-lg); }

a { color: inherit; }
a:hover { color: var(--primary); }

h1, h2, h3, h4, strong, b { color: var(--white); }
h1 { font-size: 1.6rem; margin: 0 0 0.25rem; }
h2 { font-size: 1.2rem; margin: var(--gap-lg) 0 var(--gap-sm); }
h3 { font-size: 1rem; margin: 0 0 0.25rem; }
p { margin: 0 0 var(--gap-sm); }
.muted { color: var(--muted); }
.small { font-size: 0.875rem; }

/* Reported user agents and other verbatim strings. Unstyled they were a run
   of body text; the box marks where the quoted value starts and ends. */
code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: var(--dark2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.1em 0.35em;
  overflow-wrap: anywhere;
}

/* ─── Top bar ─────────────────────────────────────────────────────────────── */

.topbar {
  background: var(--dark2);
  color: var(--white);
  position: sticky;
  top: 0;
  z-index: 20;

  /* The gradient hairline is the only place the brand's two colours meet at
     full strength; everything else uses them muted. */
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 0 var(--blue-soft), 0 8px 24px rgba(0, 0, 0, .35);
}

.topbar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
  padding-block: 0.7rem;
  min-height: var(--topbar-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--white);
}

/* The logo is a wordmark, so it is sized by height and left to set its own
   width — a fixed box would letterbox or stretch it. Its own type is white
   with the green/blue mark, which is why nothing is inverted or filtered
   here: it was drawn for a dark ground. */
.brand-logo {
  display: block;
  height: 26px;
  width: auto;
  max-width: min(60vw, 190px);
  object-fit: contain;
}

/* Larger on the sign-in card, where the lockup is the page's only header. */
.gate-brand .brand-logo { height: 32px; }

/* "QA" beside the logo: the product name, kept quieter than the wordmark so
   the two read as one lockup rather than as two logos. */
.brand-name {
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-body);
  padding-left: 0.55rem;
  border-left: 1px solid var(--border);
}

.topnav {
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
  font-size: 0.9rem;
}

.topnav a { color: var(--text-body); text-decoration: none; }
.topnav a:hover { color: var(--primary); }
.topnav .who { color: var(--text-muted); }
.topnav .who strong { color: var(--white); }
.inline { display: inline; margin: 0; }

.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--text-muted);
  cursor: pointer;
  text-decoration: underline;
}
.linkish:hover { color: var(--primary); }

/* ─── Surfaces ────────────────────────────────────────────────────────────── */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--gap);
}

.card:hover { border-color: var(--blue-border); }

.card + .card { margin-top: var(--gap); }
.stack > * + * { margin-top: var(--gap); }

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

.foot {
  padding-block: var(--gap-lg);
  color: var(--muted);
  font-size: 0.875rem;
}

/* ─── Notes ───────────────────────────────────────────────────────────────── */

.note {
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  margin-bottom: var(--gap);
}

.note-ok { background: var(--pass-bg); border-color: var(--border-g); color: var(--pass); }
.note-bad { background: var(--fail-bg); border-color: rgba(224, 108, 117, .3); color: var(--fail); }

/* ─── Forms ───────────────────────────────────────────────────────────────── */

label { display: block; font-weight: 500; margin-bottom: 0.3rem; font-size: 0.9rem; }

/* Every text-like control, styled once.
 *
 * `input:not([type])` is the important one and was the bug: an `<input>` with
 * no type attribute is a text field, but it does *not* match `input[type=text]`,
 * so most of the forms in this app were rendering completely unstyled. Listing
 * the types explicitly (rather than `input:not([type=checkbox])`) keeps
 * checkboxes, radios and buttons out of it without a pile of negations. */
.input,
input:not([type]),
input[type="text"],
input[type="tel"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="search"],
input[type="url"],
input[type="date"],
input[type="datetime-local"],
select,
textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--dark2);
  color: var(--white);

  /* 16px minimum on touch devices, or iOS Safari zooms the page on focus and
     leaves the form half off-screen. `font: inherit` alone inherits whatever
     the container set, which is smaller inside .small blocks. */
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.4;

  transition: border-color 0.15s, box-shadow 0.15s;
  -webkit-appearance: none;
  appearance: none;
}

.input:focus,
input:not([type]):focus,
input[type="text"]:focus,
input[type="tel"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: var(--focus-ring);
}

/* Chrome fills saved values with an opaque near-white block that ignores
   `background`, which on this theme means white-on-white text. The inset
   shadow is the only way to repaint it; `-webkit-text-fill-color` is the only
   way to recolour the text inside it. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--white);
  -webkit-box-shadow: 0 0 0 1000px var(--dark2) inset;
  caret-color: var(--white);
  transition: background-color 9999s ease-out 0s;
}

/* Readonly fields are for copying out of, not typing into — the invite links
   and the auto-filled screen size. They read as inert rather than broken. */
input[readonly],
.input[readonly] {
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
}

input[disabled], select[disabled], textarea[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* The arrow has to be drawn back on: `appearance: none` above removes the
   native one, which would otherwise leave a select looking like a text box. */
select {
  padding-right: 2.2rem;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position:
    calc(100% - 1.05rem) calc(50% + 2px),
    calc(100% - 0.75rem) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  cursor: pointer;
}

textarea { min-height: 5rem; resize: vertical; }

/* Checkboxes and radios keep their native look — a hand-built one is worse on
   every platform — but take the brand colour and a usable hit area. */
input[type="checkbox"], input[type="radio"] {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--primary);
  cursor: pointer;
  flex: none;
}

/* File inputs cannot be styled directly; the button inside them can. */
input[type="file"] {
  width: 100%;
  font-size: 0.9rem;
  color: var(--muted);
}

input[type="file"]::file-selector-button {
  margin-right: 0.75rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: 0.875rem;
  cursor: pointer;
}

input[type="file"]::file-selector-button:hover { border-color: var(--primary); }

.field + .field { margin-top: var(--gap); }

.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
  align-items: flex-end;
}

.row > * { flex: 1 1 200px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem 1.1rem;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--primary);

  /* Near-black on the green, not white: white gives about 3:1 against
     #41aa28, which fails on a label this size. The dark reads at roughly
     6:1 and is why every filled control here reverses the same way. */
  color: var(--dark);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: filter 0.15s, box-shadow 0.15s, border-color 0.15s;
}

/* The theme ships one green — --primary-d and --primary-l are the same
   value — so hover brightens the fill rather than swapping to a second one. */
.btn:hover { filter: brightness(1.12); color: var(--dark); box-shadow: 0 4px 14px rgba(65, 170, 40, .3); }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn-ghost { background: transparent; border-color: var(--border); color: var(--text); }
.btn-ghost:hover {
  border-color: var(--primary);
  background: var(--blue-soft);
  color: var(--white);
  filter: none;
  box-shadow: none;
}
.btn-sm { padding: 0.35rem 0.75rem; font-size: 0.875rem; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; filter: none; box-shadow: none; }

/* ─── Tables ──────────────────────────────────────────────────────────────── */

.table-wrap { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
th, td { padding: 0.6rem 0.7rem; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }
th {
  color: var(--text-muted);
  font-weight: 600;
  white-space: nowrap;
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.05em;
}
tbody tr:hover { background: var(--blue-soft); }

/* ─── Status pills ────────────────────────────────────────────────────────── */

.pill {
  display: inline-block;
  padding: 0.15em 0.65em;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;

  /* On the dark surface a tinted fill alone is nearly invisible at this size;
     the border in the same hue is what makes the pill read as a pill. */
  border: 1px solid currentColor;
  line-height: 1.5;
}

.pill-pass { background: var(--pass-bg); color: var(--pass); }
.pill-fail { background: var(--fail-bg); color: var(--fail); }
.pill-blocked { background: var(--blocked-bg); color: var(--blocked); }
.pill-na, .pill-untested { background: var(--na-bg); color: var(--na); }
.pill-p1 { background: var(--fail-bg); color: var(--fail); }
.pill-p2 { background: var(--blocked-bg); color: var(--blocked); }
.pill-p3 { background: var(--na-bg); color: var(--na); }

/* ─── Stats ───────────────────────────────────────────────────────────────── */

.stat {
  background: var(--surface);
  background-image: var(--grad-glow);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--gap);
}

.stat b { display: block; font-size: 1.9rem; line-height: 1.1; color: var(--white); }
.stat span { color: var(--muted); font-size: 0.85rem; }

.bar {
  display: flex;
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--dark2);
  border: 1px solid var(--border);
  margin-top: 0.5rem;
}

.bar i { display: block; height: 100%; }
.bar .b-pass { background: var(--primary); }
.bar .b-fail { background: var(--fail); }
.bar .b-blocked { background: var(--blocked); }

/* ─── Phone entry ─────────────────────────────────────────────────────────────
   A `+` sits in its own leading cell rather than in the placeholder, so the
   requirement to include a country code is visible while typing instead of
   vanishing at the first keystroke — which is where "07…" gets entered and the
   send silently fails. */

.phone-field {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--dark2);
  overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.phone-field:focus-within {
  border-color: var(--blue);
  box-shadow: var(--focus-ring);
}

.phone-field .prefix {
  display: grid;
  place-items: center;
  padding-inline: 0.85rem;
  background: var(--surface-2);
  border-right: 1px solid var(--border);
  color: var(--muted);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  user-select: none;
}

.phone-field input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 0.7rem 0.75rem;

  /* 16px minimum: anything smaller makes iOS Safari zoom the page on focus,
     which on a phone leaves the form half off-screen. */
  font-size: 1rem;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}

.phone-field input:focus { outline: none; box-shadow: none; }

/* Placeholders across the app: Chrome and Safari default to a grey that is
   close to unreadable on the dark surface, so they are set explicitly rather
   than left to the browser. */
.phone-field input::placeholder,
.input::placeholder,
input::placeholder,
textarea::placeholder {
  color: var(--muted);
  opacity: 0.8;
}

/* ─── One-time code ───────────────────────────────────────────────────────────
   One wide box rather than six little ones. Six inputs look better in a
   screenshot and are worse to use: paste breaks across them, autofill from the
   WhatsApp notification only targets the first, and a backspace at a boundary
   behaves differently on every keyboard. */

.code-field {
  width: 100%;
  padding: 0.75rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--dark2);
  color: var(--white);

  font-size: 1.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;

  /* The trailing letter-spacing pushes the visual centre right by half a
     character; the padding compensates so the digits sit centred. */
  letter-spacing: 0.5em;
  text-indent: 0.5em;
  text-align: center;
}

/* Bright enough to read as "six digits go here" rather than as a smudge.
   --border was too close to the field itself to register as content at all. */
.code-field::placeholder {
  color: var(--muted);
  opacity: 0.75;
  font-weight: 400;
}

.code-field:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: var(--focus-ring);
}

/* Chrome and Firefox draw spinners on numeric fields; there is nothing to
   step through in a one-time code. */
.code-field::-webkit-outer-spin-button,
.code-field::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.code-field { -moz-appearance: textfield; }

@media (max-width: 380px) {
  .code-field { font-size: 1.45rem; letter-spacing: 0.35em; text-indent: 0.35em; }
}

/* Full-width primary action on a phone: a sign-in button the width of its own
   label is a small target on the screen where these forms are mostly used. */
@media (max-width: 560px) {
  .gate-card .btn { width: 100%; }
}

/* ─── Gate (sign-in pages) ────────────────────────────────────────────────── */

.gate { min-height: 100vh; display: grid; place-items: center; padding: var(--gap); }
.gate-card {
  width: min(440px, 100%);
  background: var(--surface);
  background-image: var(--grad-glow);
  border: 1px solid var(--blue-border);
  border-radius: var(--radius);
  padding: var(--gap-lg);

  /* The sign-in card is the one thing on an otherwise empty screen, so it
     gets the brand glow that would be noise repeated down a dashboard. */
  box-shadow: 0 20px 60px rgba(0, 0, 0, .5), 0 0 0 1px var(--blue-soft);
}
.gate-brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 600;
  margin-bottom: var(--gap-lg);
  padding-bottom: var(--gap);
  border-bottom: 1px solid var(--border);
}

/* ─── Checklist (the tester's main screen) ────────────────────────────────── */

/* Sticky progress: on a long run the tester needs to know where they are
   without scrolling back to the top. */
.progress {
  position: sticky;
  /* Clears the top bar by its own declared height rather than a guessed
     value, so the two cannot overlap if the bar's padding changes. */
  top: calc(var(--topbar-h) + 0.25rem);
  z-index: 10;

  /* Opaque, not translucent: the checklist scrolls underneath it. */
  background: var(--dark2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.7rem var(--gap);
  margin-bottom: var(--gap);
}

/* Below roughly 620px the nav wraps under the logo and the bar is a row
   taller, so the offset above would let the progress slide behind it. There
   is no CSS way to read the bar's rendered height, hence the second number. */
@media (max-width: 620px) {
  .progress { top: calc(var(--topbar-h) + 1.4rem); }
}

.progress-line {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  align-items: center;
  font-size: 0.85rem;
}

.case {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--blue-border);
  border-radius: var(--radius);
  padding: var(--gap);
  margin-bottom: var(--gap);
}

.case[data-status="pass"] { border-left-color: var(--pass); }
.case[data-status="fail"] { border-left-color: var(--fail); }
.case[data-status="blocked"] { border-left-color: var(--blocked); }
.case[data-status="na"] { border-left-color: var(--na); }

.case-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
  margin-bottom: 0.5rem;
}

.case-ref { font-weight: 700; font-family: ui-monospace, monospace; color: var(--blue-l); }
.case-title { font-weight: 600; flex: 1 1 240px; }

.case-block { margin-top: 0.75rem; }
.case-block h4 {
  margin: 0 0 0.2rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.case-block p { white-space: pre-line; margin: 0; }

/* Big, obvious, thumb-sized choices. A tester works through a hundred of
   these — anything fiddly costs real time and invites mis-taps. */
.choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
  gap: 0.4rem;
  margin-top: 0.85rem;
}

.choice {
  position: relative;
  display: block;
}

.choice input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.choice span {
  display: block;
  text-align: center;
  padding: 0.65rem 0.3rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  background: var(--dark2);
  color: var(--text-body);
  transition: border-color 0.15s, background 0.15s;
}

.choice span:hover { border-color: var(--blue-border); color: var(--white); }

.choice input:focus-visible + span { outline: 2px solid var(--blue-l); outline-offset: 2px; }
.choice input:checked + span[data-v="pass"] { background: var(--primary); border-color: var(--primary); color: var(--dark); }
.choice input:checked + span[data-v="fail"] { background: var(--fail); border-color: var(--fail); color: var(--dark); }
/* Every filled status reverses to the page's near-black: white clears 4.5:1
   on none of these four fills, and the dark clears it on all of them. */
.choice input:checked + span[data-v="blocked"] { background: var(--blocked); border-color: var(--blocked); color: var(--dark); }
.choice input:checked + span[data-v="na"] { background: var(--na); border-color: var(--na); color: var(--dark); }

.notes-wrap { margin-top: 0.7rem; }

.saved {
  font-size: 0.8rem;
  color: var(--muted);
  margin-left: auto;
  opacity: 0;
  transition: opacity 0.2s;
}
.saved.on { opacity: 1; }
.saved.err { color: var(--fail); }

@media (prefers-reduced-motion: reduce) {
  .saved { transition: none; }
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: var(--gap);
}

.filters button {
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--dark2);
  color: var(--text-body);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.filters button:hover { border-color: var(--blue-border); color: var(--white); }

.filters button[aria-pressed="true"] {
  background: var(--primary);
  border-color: transparent;
  color: var(--dark);
}

.hidden { display: none !important; }
