:root {
  color-scheme: light dark;
  --bg: #f6f7fb;
  --surface: #ffffff;
  --surface-hover: #f0f1f6;
  --border: #e3e5ec;
  --text: #14161a;
  --text-secondary: #5b6072;
  /* #8a8fa3 -- accessibility audit finding: 3.2:1 against --bg,
     short of WCAG AA's 4.5:1 floor for normal-size text, which
     this pervasively is (field hints, timestamps, "no data"
     placeholders across every template) -- #6b7086 clears ~4.9:1
     against both --bg and --surface while keeping the same muted
     blue-gray hue. */
  --text-muted: #6b7086;
  --accent: #4f46e5;
  --accent-text: #ffffff;
  --success: #16a34a;
  --success-bg: #e8f8ee;
  --danger: #dc2626;
  --danger-bg: #fdecec;
  --warning: #b45309;
  --warning-bg: #fdf1de;
  --success-strong: #15803d;
  --danger-strong: #b91c1c;
  /* Reserved vertical space for the sitewide sponsored bar (ads/
     _sponsored_bar.html) -- always visible on every page now (direct
     ask: "throughout the whole site"), not just conditionally after a
     scroll trigger, so unlike the old market-detail-only version this
     needs real, permanent clearance: body's own bottom padding (so a
     short page's footer doesn't render underneath it) and the two
     other fixed bottom corners (.translate-widget-floating, .season-
     prizes-teaser) both add this on top of their own 1rem inset.
     Taller on narrow screens -- see the media query near .sponsored-bar
     itself for why (its own inner content wraps to more rows there).

     This static value is only the pre-JS/no-JS fallback -- direct bug
     report, a real mobile device: the bar "only slightly" covered the
     footer, since a fixed rem guess can't match every real device's
     own font rendering and every sponsor name's own actual wrapped
     length exactly. static/js/base.js measures the bar's real rendered
     height on load (and on resize/reflow) and overrides this variable
     with that exact value -- this default only matters for the brief
     moment before that runs, or if JS is unavailable at all. */
  --sponsored-bar-height: 4.5rem;
  /* --yes-color/--no-color are deliberately NOT set here -- they come
     from the DB (ui.models.SiteSettings, staff-editable live from the
     theme-colors tool) and this is a plain static file WhiteNoise
     serves with far-future cache headers, extracted from base.html's
     own inline <style> (performance audit: ~47KB of CSS was re-sent
     and re-parsed on every single page load with no way for a browser
     to cache it separately). templates/base.html sets both in a tiny
     inline <style> block right after this file's own <link> tag
     instead -- CSS custom properties resolve at computed-value time,
     not per-stylesheet parse order, so which of the two actually
     "defines" them first has no effect on correctness or a flash of
     unstyled color, only this file's own cacheability benefits from
     being external. */
  --radius: 10px;
  --radius-sm: 6px;
  --shadow-sm: 0 1px 2px rgba(20, 22, 30, 0.06);
  --shadow-md: 0 8px 24px rgba(20, 22, 30, 0.12);
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
/* Three-state theme: no [data-theme] attribute at all follows the
   OS/browser's own prefers-color-scheme (the media query below);
   an explicit choice from the sun/moon toggle (bottom of the nav)
   stamps data-theme="light"/"dark" on <html>, which wins over the
   system setting either way -- direct ask: "can you have a
   light/dark mode?" (an iPad in light mode was stuck light here
   with no way to override it in-app). --yes-color/--no-color are
   the same literal value in every state, same as above, so
   they're omitted from both blocks below -- nothing to override. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0e1015;
    --surface: #171a22;
    --surface-hover: #1f232d;
    --border: #2a2e3a;
    --text: #f0f1f5;
    --text-secondary: #b2b7c6;
    /* #767c8f -- accessibility audit finding: 4.2:1 against
       --surface, short of WCAG AA's 4.5:1 floor -- #83899d clears
       ~5.0:1 while keeping the same muted blue-gray hue. */
    --text-muted: #83899d;
    --accent: #8b85f0;
    --accent-text: #0e1015;
    --success: #4ade80;
    --success-bg: rgba(74, 222, 128, 0.14);
    --danger: #f87171;
    --danger-bg: rgba(248, 113, 113, 0.14);
    --warning: #fbbf24;
    --warning-bg: rgba(251, 191, 36, 0.14);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.5);
  }
}
:root[data-theme="dark"] {
  --bg: #0e1015;
  --surface: #171a22;
  --surface-hover: #1f232d;
  --border: #2a2e3a;
  --text: #f0f1f5;
  --text-secondary: #b2b7c6;
  /* Same fix as the media-query block above -- #767c8f fell short
     of WCAG AA's 4.5:1 against --surface. */
  --text-muted: #83899d;
  --accent: #8b85f0;
  --accent-text: #0e1015;
  --success: #4ade80;
  --success-bg: rgba(74, 222, 128, 0.14);
  --danger: #f87171;
  --danger-bg: rgba(248, 113, 113, 0.14);
  --warning: #fbbf24;
  --warning-bg: rgba(251, 191, 36, 0.14);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.5);
}

* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  line-height: 1.5;
  font-size: 15px;
  /* Direct bug report: "in all pages (landing, notifications...)
     text fits entirely in boxes and does not span out of them" --
     a sitewide safety net for long, unpredictable text (a market
     question, a username, a comment) that would otherwise force
     its own box wider instead of wrapping. Never overrides an
     element that deliberately sets its own white-space: nowrap
     (badges, the brand mark, .pnl's numeric figures) -- that
     still wins regardless, this only helps genuinely free text
     that has nothing else stopping it from wrapping already. */
  overflow-wrap: break-word;
  /* Clears the sitewide sponsored bar (position: fixed, always
     visible) -- otherwise it renders on top of the footer on any page
     short enough not to fill the viewport on its own. */
  padding-bottom: var(--sponsored-bar-height);
}
a { color: var(--accent); }
.page { max-width: 1040px; margin: 0 auto; padding: 0 1.5rem 4rem; }
h1 { font-size: 1.6rem; margin: 0 0 1.25rem; }
h2 { font-size: 1.15rem; margin: 0 0 0.75rem; }
h3 { font-size: 1rem; margin: 0 0 0.35rem; }

/* --- Header / nav --- */
/* "Freeze panes" -- direct ask: the logo/nav/Portfolio bar always
   stays on top while scrolling, rather than scrolling away with
   the page. z-index above everything else on the page except the
   search dropdown/menu panels (which position themselves relative
   to elements inside this same header anyway, so they're never
   actually competing with it). */
.site-header { background: var(--surface); border-bottom: 1px solid var(--border); margin-bottom: 2rem; position: sticky; top: 0; z-index: 30; }
.site-footer { background: var(--surface); border-top: 1px solid var(--border); margin-top: 3rem; }
.site-footer-inner {
  max-width: 1040px; margin: 0 auto; padding: 1.5rem; display: flex; align-items: center;
  justify-content: space-between; flex-wrap: wrap; gap: 0.75rem; font-size: 0.85rem;
}
.site-footer-links { display: flex; gap: 1.1rem; }
.site-footer-links a { color: var(--text-secondary); text-decoration: none; font-weight: 600; }
.site-footer-links a:hover { color: var(--accent); }
.header-inner {
  max-width: 1040px; margin: 0 auto; padding: 0.85rem 1.5rem;
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
}
.brand { font-weight: 800; font-size: 1.05rem; text-decoration: none; color: var(--text); display: flex; align-items: center; gap: 0.4em; white-space: nowrap; }
.brand-mark { color: var(--accent); }
.primary-nav { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.primary-nav a { color: var(--text-secondary); text-decoration: none; font-weight: 600; font-size: 0.92rem; padding: 0.3em 0.1em; border-bottom: 2px solid transparent; }
.primary-nav a:hover { color: var(--text); }
.primary-nav a.active { color: var(--text); border-bottom-color: var(--accent); }
.header-actions { margin-left: auto; display: flex; align-items: center; gap: 0.6rem; }
.menu { position: relative; }
.menu > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.4em; padding: 0.4em 0.8em; border-radius: var(--radius-sm); border: 1px solid var(--border); font-weight: 600; font-size: 0.88rem; background: var(--surface); color: var(--text); }
.menu > summary::-webkit-details-marker { display: none; }
.menu[open] > summary { background: var(--surface-hover); }
/* max-height + its own scrollbar, not just overflow left to the page --
   direct bug report: this panel hangs off .site-header, which is
   position: sticky (pinned to the viewport top), so scrolling the page
   never moves the panel at all. A long menu (the Staff section can add
   half a dozen extra rows) could run off the bottom of the viewport
   with genuinely no way to ever reach its last few items -- "even when
   sliding down i cant reach the end of the list."

   Second direct bug report, after the menu grew a few more rows
   (Private Bets, more staff links): "even with the scroll" the last
   item or two were still unreachable -- calc(100vh - 5rem) assumed a
   fixed ~5rem of chrome above the panel, but .header-inner's own nav
   can wrap onto a second line on a narrower window, pushing the
   summary (and this panel's own top) further down than that fixed
   budget accounted for. Once the panel's own box is taller than the
   *actual* remaining space below it, part of its box renders past the
   viewport's own bottom edge -- genuinely unreachable by any scrolling
   at that point, since overflow-y here only ever reveals content
   taller than the panel's *own* box, not content clipped by the
   viewport itself. min() with a more conservative vh-relative cap
   fixes this regardless of how tall the header ends up being, at the
   cost of asking for a scroll a little earlier than strictly
   necessary on a tall screen. overscroll-behavior keeps that scroll
   from leaking into the page behind it once the mouse is over it.

   Third direct bug report, on phone: "if i scroll down the dropdown
   from username, the sponsor box blocks the last bit (log out)."
   Raised past .sponsored-bar's own z-index: 40 (this file) so an open
   menu always paints in front of the fixed bottom bar rather than
   behind it -- necessary, but not sufficient on its own (see below).

   Fourth direct bug report, same phone, right after: "still cant go
   down enough to see log out" -- the real, remaining cause is this
   rule's own max-height, in two compounding ways. First, plain `vh`
   on a real phone browser is the *largest possible* viewport (address
   bar hidden), not the actually-visible one right now (address bar
   shown) -- `calc(100vh - 8rem)` can allow a taller box than the
   screen genuinely has room for, so scrolling to this panel's own
   "bottom" can still land short of the true visible bottom edge.
   Switched every 100vh here to 100dvh (dynamic viewport height),
   which tracks the browser's actual visible area as its chrome
   shows/hides, instead. Second, and the more direct cause of this
   specific report: the calc's fixed "8rem" budget (already raised
   once before, from 5rem, for header wrapping alone) never accounted
   for .sponsored-bar's own reserved height at all -- exactly the
   space Log out needs to clear now that the panel renders in front of
   it. Subtracting var(--sponsored-bar-height) (already the real,
   JS-measured height used for body's own bottom padding and the two
   floating corner widgets) instead of a second guessed constant means
   this stays correct however tall the bar's own content wraps to. */
.menu-panel { position: absolute; right: 0; top: calc(100% + 0.4rem); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-md); min-width: 210px; padding: 0.4rem; z-index: 45; max-height: min(70dvh, calc(100dvh - 8rem - var(--sponsored-bar-height))); overflow-y: auto; overscroll-behavior: contain; }
.menu-panel a, .menu-panel button { display: block; width: 100%; text-align: left; padding: 0.55em 0.7em; border-radius: var(--radius-sm); text-decoration: none; color: var(--text); font-size: 0.88rem; background: none; border: none; font: inherit; cursor: pointer; }
.menu-panel a:hover, .menu-panel button:hover { background: var(--surface-hover); }
.menu-eyebrow { padding: 0.3em 0.7em; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.menu-divider { border: none; border-top: 1px solid var(--border); margin: 0.35rem 0; }

/* --- Buttons --- */
button, input[type="submit"] {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4em;
  padding: 0.55em 1.1em; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font: inherit; font-weight: 600; font-size: 0.88rem;
  cursor: pointer;
}
button:hover, input[type="submit"]:hover { background: var(--surface-hover); }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4em;
  padding: 0.55em 1.1em; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font: inherit; font-weight: 600; font-size: 0.88rem;
  cursor: pointer; text-decoration: none; transition: background-color .15s, border-color .15s, transform .05s;
}
.btn:hover { background: var(--surface-hover); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn-primary:hover { filter: brightness(1.08); }
.btn-buy { background: var(--success-strong); border-color: var(--success-strong); color: #fff; }
.btn-buy:hover { filter: brightness(1.1); }
.btn-sell { background: var(--danger-strong); border-color: var(--danger-strong); color: #fff; }
.btn-sell:hover { filter: brightness(1.1); }
/* .btn-yes/.btn-no -- direct ask: "EVERYWHERE there is a Call
   Yes/No formatting, use the relevant purple/pink colours instead
   of what is currently in place." Distinct from .btn-buy/.btn-sell
   above (green/red), which stay as-is for actions that aren't
   literally labeled "Call Yes"/"Call No" (Accept, Approve,
   Resolve Yes/No, Import). */
.btn-yes { background: var(--yes-color); border-color: var(--yes-color); color: #fff; }
.btn-yes:hover { filter: brightness(1.1); }
.btn-no { background: var(--no-color); border-color: var(--no-color); color: #fff; }
.btn-no:hover { filter: brightness(1.1); }
.btn-danger { background: transparent; border-color: var(--danger-strong); color: var(--danger-strong); }
.btn-danger:hover { background: var(--danger-bg); }
.btn-ghost { background: transparent; }
.btn-sm { padding: 0.35em 0.75em; font-size: 0.8rem; }
.btn-block { width: 100%; }

/* --- Cards --- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.25rem; margin-bottom: 1rem; box-shadow: var(--shadow-sm); }
a.card { display: block; text-decoration: none; color: inherit; transition: box-shadow .15s, transform .1s, border-color .15s; }
a.card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }

/* --- Badges / tags --- */
.badge { display: inline-flex; align-items: center; gap: 0.3em; padding: 0.18em 0.65em; border-radius: 999px; font-size: 0.74rem; font-weight: 700; white-space: nowrap; }
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-neutral { background: var(--surface-hover); color: var(--text-secondary); border: 1px solid var(--border); }
.badge-accent { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); }
/* .badge-yes/.badge-no -- same direct ask as .btn-yes/.btn-no
   above: everywhere a badge names which side an order or trade
   took, color it with the site's own yes/no palette instead of
   the generic win/loss green/red -- those stay reserved for an
   actual resolved outcome or a real P&L, a different thing
   entirely. */
.badge-yes { background: color-mix(in srgb, var(--yes-color) 14%, transparent); color: var(--yes-color); }
.badge-no { background: color-mix(in srgb, var(--no-color) 14%, transparent); color: var(--no-color); }
.side-badge { display: inline-block; padding: 0.08em 0.5em; border-radius: 4px; font-size: 0.68rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; }
/* Direct bug report: Call Yes/Call No here read green/red instead
   of the site's own two-color scheme -- same badge-yes/badge-no
   tokens as everywhere else a Yes/No side is shown. */
.side-long { background: color-mix(in srgb, var(--yes-color) 14%, transparent); color: var(--yes-color); }
.side-short { background: color-mix(in srgb, var(--no-color) 14%, transparent); color: var(--no-color); }

/* --- P&L coloring (never color alone -- arrow carries the meaning too) --- */
.pnl { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
/* .pnl's own white-space: nowrap is right for the short numeric
   figures it's built for, but wrong for a notification's full,
   arbitrary-length message text reusing it just for the color --
   real bug found auditing text overflow: a long message never
   wrapped, forcing the notification card wider than the page. */
.pnl-message { white-space: normal; }
.pnl-positive { color: var(--success); }
.pnl-negative { color: var(--danger); }
.pnl-zero { color: var(--text-secondary); font-weight: 500; }
.pnl-muted { color: var(--text-muted); font-weight: 500; }
.pnl-arrow { font-size: 0.75em; }

/* --- Stat tiles (portfolio/dashboard KPIs) --- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.85rem; margin-bottom: 1.5rem; }
.stat-tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.2rem; }
.stat-tile.stat-hero { grid-column: 1 / -1; padding: 1.4rem 1.5rem; }
.stat-label { font-size: 0.74rem; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.4rem; font-weight: 600; }
.stat-value { font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.stat-hero .stat-value { font-size: 2.1rem; }
.stat-sub { font-size: 0.85rem; color: var(--text-secondary); margin-top: 0.3rem; }

/* --- Tables --- */
table.data-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.data-table th { text-align: left; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); padding: 0.55rem 0.75rem; border-bottom: 1px solid var(--border); font-weight: 700; }
.data-table td { padding: 0.65rem 0.75rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover td { background: var(--surface-hover); }

/* --- Position cards: mobile-first redesign of the portfolio
   dashboard's own "Open positions" table, direct ask. A 7-column
   table (Market/Contracts/Avg cost/Mark price/Value/Unrealized P&L/
   Resolution date) already had a working fallback -- .table-wrap's
   own overflow-x:auto, this project's general answer for any wide
   table -- but "working" isn't "designed for mobile": scrolling
   sideways through seven columns to compare positions is a real
   usability cost a phone visitor pays on their single most-used
   page. Below the same 640px breakpoint the rest of this file's
   mobile-first pass already uses, the table swaps for a purpose-
   built card per position instead of the same columns simply
   stacked -- three numbers that actually matter at a glance (side/
   size, current value, unrealized P&L) promoted into their own
   row, everything else (avg cost, mark price, resolution date)
   demoted to a smaller detail line underneath. Two parallel markup
   blocks (table + cards), toggled by this same media query rather
   than one CSS trick reshaping the table in place -- deliberate:
   a `content: attr(data-label)`-based table-to-card transform is
   the more common approach, but several of these cells already
   nest their own `<div class="subtle">` sub-line (mark price's
   source, P&L's own multiplier), which that generic transform
   handles badly (the label and the nested sub-line both fight for
   the same row). Real markup, not a trick reused past where it fits.
   Applies to Open positions specifically -- the dashboard's other
   three tables (outstanding bids, past trades, calibration) are
   lower-traffic and simpler (fewer, shorter columns), so they keep
   the existing horizontal-scroll fallback rather than each getting
   its own bespoke card layout too. */
.position-cards { display: none; }
@media (max-width: 640px) {
  .position-cards { display: block; }
  .position-cards + .table-wrap { display: none; }
  .position-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 0.9rem 1rem; margin-bottom: 0.75rem; background: var(--surface); }
  .position-card:last-child { margin-bottom: 0; }
  .position-card-question { font-weight: 700; margin-bottom: 0.65rem; display: block; }
  .position-card-stats { display: flex; gap: 0.5rem; margin-bottom: 0.6rem; }
  .position-card-stats > div { flex: 1; text-align: center; padding: 0.4rem 0.3rem; background: var(--surface-hover); border-radius: 6px; }
  .position-card-stats .stat-label { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-secondary); font-weight: 700; margin-bottom: 0.2rem; }
  .position-card-detail { font-size: 0.8rem; color: var(--text-secondary); display: flex; flex-wrap: wrap; gap: 0.3rem 0.6rem; }
}
/* "Flag yourself in the leaderboard to see where you are" -- direct ask. */
.my-leaderboard-row td { background: var(--accent-bg, rgba(99, 102, 241, 0.08)); font-weight: 600; }
/* Community disagreement rating -- direct ask: "user can choose to
   disagree by clicking on a flame scale (1-5 flames)." Each button
   IS a tiny form (a real POST, no JS) so it works with JS
   disabled too; .flame-rating-btn-mine marks whichever flame count
   is the viewer's own current rating. */
.flame-rating-btn { font-size: 1.1rem; padding: 0.3rem 0.6rem; line-height: 1; }
.flame-rating-btn-mine { background: var(--accent-bg, rgba(99, 102, 241, 0.12)); border-color: var(--accent); }
.community-disagreement-summary { font-size: 0.9rem; margin-top: 0.6rem; }
/* Distinct username colors for the admin/AI accounts, on top of
   their own 👑/🤖 icons -- direct ask. */
.username-admin { color: #b45309; font-weight: 700; }
.username-ai { color: #6d28d9; font-weight: 700; }
@media (prefers-color-scheme: dark) {
  .username-admin { color: #f6ad55; }
  .username-ai { color: #b794f6; }
}
/* Staff-menu "new item" markers -- direct ask: "a red dot ... like
   in messaging apps when you have a new unseen message." */
.unseen-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--danger, #dc2626); vertical-align: middle;
}
.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; }

/* --- Forms --- */
label { display: block; font-weight: 600; font-size: 0.86rem; margin-bottom: 0.3rem; }
input[type=text], input[type=number], input[type=url], input[type=password],
input[type=datetime-local], select, textarea {
  width: 100%; max-width: 340px; padding: 0.5em 0.7em; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  font: inherit; font-size: 0.9rem;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
fieldset { border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.1rem; margin: 0 0 1rem; }
legend { font-weight: 700; padding: 0 0.4em; font-size: 0.92rem; }
.field { margin-bottom: 0.9rem; }
.field-hint { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.3rem; }
/* accounts.forms.SignupForm's own "website" honeypot -- off-screen via
   position, not display:none/visibility:hidden, which some scripted
   form-fillers specifically check for and skip. A real browser never
   renders it in the visible page at all, so no visitor (sighted or a
   screen reader, which skips absolutely-positioned-off-canvas content
   the same as a display:none one) ever notices it's there. */
.hp-field { position: absolute; left: -9999px; top: -9999px; }

/* Direct bug report, a real mobile phone: markets/list.html's own
   sort .segmented (5 options -- Newest/Hot/Most traded/Trending/
   Closing soonest) is one indivisible inline-flex block that can't
   wrap internally the way the rest of that filter form's own plain
   <select>s do, so on a narrow screen it's wider than the viewport --
   "can't scroll right fully for the filter buttons." max-width caps it
   at the viewport itself (matching .season-prizes-teaser's own
   convention just above) and overflow-x: auto makes *this* element
   scroll to reach its own hidden-past-the-edge options, rather than
   however much of it doesn't fit just being unreachable. Plain
   `overflow: hidden` (desktop, and this element's own vertical axis
   here) stays for the rounded-corner clipping it was already doing --
   only horizontal changes on a narrow screen. */
.segmented { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 0.9rem; max-width: 100%; }
.segmented label { margin: 0; display: flex; align-items: center; gap: .4em; padding: 0.55em 1.1em; cursor: pointer; font-weight: 700; font-size: 0.88rem; background: var(--surface); color: var(--text-secondary); white-space: nowrap; }
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label:has(input:checked) { background: var(--accent); color: var(--accent-text); }
.segmented label:has(input[value="buy"]:checked) { background: var(--success-bg); color: var(--success-strong); }
.segmented label:has(input[value="sell"]:checked) { background: var(--danger-bg); color: var(--danger-strong); }
.segmented label:has(input:checked) + label { border-left: 1px solid var(--border); }
.segmented label:not(:last-child) { border-right: 1px solid var(--border); }
@media (max-width: 640px) {
  .segmented { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* --- Alerts / flash messages --- */
.messages { list-style: none; padding: 0; margin: 0 0 1.25rem; display: flex; flex-direction: column; gap: 0.5rem; }
.messages li { padding: 0.65em 1em; border-radius: var(--radius-sm); font-size: 0.9rem; border: 1px solid transparent; font-weight: 500; }
.messages .success { background: var(--success-bg); color: var(--success); }
.messages .error { background: var(--danger-bg); color: var(--danger); }
.messages .warning { background: var(--warning-bg); color: var(--warning); }

.callout { border-radius: var(--radius); padding: 0.85rem 1.1rem; margin-bottom: 1rem; font-size: 0.88rem; border: 1px solid var(--border); background: var(--surface-hover); color: var(--text-secondary); }
.callout-warning { background: var(--warning-bg); color: var(--warning); border-color: transparent; }

/* --- Misc --- */
.muted { color: var(--text-secondary); font-size: 0.9em; }
.subtle { color: var(--text-muted); }
.tag { display: inline-block; font-size: 0.75em; padding: 0.15em 0.6em; border-radius: 999px; border: 1px solid var(--border); color: var(--text-secondary); }
/* Tap-to-reveal alternative to a `title` tooltip -- direct ask: "for
   people on mobile allow an alternative to hover." A touchscreen has
   no hover at all, so every one of this site's many `title="..."`
   explainers (liquidity vs. volume, disagreement flames, the split
   bar, etc.) was silently unreachable there. See the shared script
   at the bottom of base.html for which elements this applies to and
   why (plain info-carrying tags only, never something a tap already
   has a real job to do, like a link or a checkbox's own label).
   Gated to `(hover: none)` so a mouse/trackpad user's existing hover
   tooltip is completely untouched -- this only ever adds a second,
   touch-only way to reach the same text, never changes the first. */
@media (hover: none) {
  span[title], div[title], td[title], th[title], strong[title] {
    text-decoration: underline dotted 1px;
    text-underline-offset: 2px;
    cursor: pointer;
  }
}
.tap-tooltip {
  position: absolute; z-index: 60; max-width: 260px;
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  padding: 0.55em 0.8em; font-size: 0.82rem; line-height: 1.4;
}
.price { font-variant-numeric: tabular-nums; font-weight: 700; }
/* markets/detail.html's own guided first-trade walkthrough -- direct
   ask: "a walk through first trade option." Outlines whichever real
   form element the current step is talking about, rather than a
   separate floating tooltip that would need to track a form that
   itself changes shape as Buy/Sell toggles. border-radius: inherit
   would fight elements that set their own (a radio-filled .segmented
   already has one) -- a fixed value reads fine on every step's target. */
.walkthrough-highlight {
  outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 6px;
  animation: walkthrough-pulse 1.4s ease-in-out infinite;
}
@keyframes walkthrough-pulse {
  0%, 100% { outline-color: var(--accent); }
  50% { outline-color: transparent; }
}
@media (prefers-reduced-motion: reduce) { .walkthrough-highlight { animation: none; } }
/* "Make probabilities visually addictive" -- direct ask. The bar
   itself already existed (a plain static fill); this adds a
   sweep-in on every render plus a slow shimmer, both pure CSS
   (transform/background-position only, so they're cheap and don't
   fight the inline width= that sets the actual probability) so a
   probability *reads* like a live, moving thing rather than a
   static fact, without misrepresenting the number itself. Respects
   prefers-reduced-motion, same convention as the landing page's
   intro animation. */
.probability-bar { position: relative; height: 8px; border-radius: 999px; background: var(--danger-bg); overflow: hidden; margin: 0.5rem 0; }
.probability-bar-fill {
  position: absolute; inset: 0 auto 0 0; border-radius: 999px 0 0 999px;
  background: linear-gradient(90deg, var(--success), #34d399);
  transform-origin: left; animation: probability-fill-in 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.probability-bar-fill::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
  background-size: 200% 100%; animation: probability-shimmer 2.4s ease-in-out infinite;
}
@keyframes probability-fill-in { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes probability-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .probability-bar-fill, .probability-bar-fill::after { animation: none; }
}

/* "Experiment with having a box covering 100, with call yes ...
   and on the right the call no ... so user gets that its 100
   total," direct ask -- a bigger, labeled sibling of the thin
   probability-bar above, for a market's own detail page
   specifically. --yes-color/--no-color -- see templates/base.html's
   own inline <style> for where these are actually set and why.
   Labels sit *above* the bar, never inside its own colored fill --
   direct follow-up after shipping the first version: "when the
   yes/no is super small i can barely see 1/2 letters." A lopsided
   market (e.g. 3%/97%) has a sliver too narrow to hold "Call Yes
   3¢" in any font size; anchoring each label to its own edge of
   the bar (not clipped to its own segment's width) keeps both
   always fully readable regardless of how skewed the split is. */
.split-bar-labels { display: flex; justify-content: space-between; font-weight: 700; font-size: 0.9rem; margin: 0.75rem 0 0.3rem; gap: 0.5rem; }
.split-bar-labels span { white-space: nowrap; }
.split-bar-label-yes { color: var(--yes-color); }
.split-bar-label-no { color: var(--no-color); text-align: right; }
.split-bar { display: flex; height: 20px; border-radius: 8px; overflow: hidden; margin-bottom: 0.75rem; }
.split-bar-yes, .split-bar-no { transition: width 0.3s ease; }
.split-bar-yes { background: var(--yes-color); }
.split-bar-no { background: var(--no-color); }
.empty-state { color: var(--text-muted); padding: 1.5rem; text-align: center; border: 1px dashed var(--border); border-radius: var(--radius); }
.activity-row { display: flex; gap: 0.75rem; align-items: flex-start; padding: 0.8rem 1rem; border: 1px solid var(--border); border-left-width: 4px; border-radius: var(--radius); background: var(--surface); margin-bottom: 0.6rem; }
.activity-icon { font-size: 1.05rem; line-height: 1.4; }
.activity-buy, .activity-sell { border-left-color: var(--accent); }
.activity-win { border-left-color: var(--success); }
.activity-charge { border-left-color: var(--danger); }
.activity-resolved { border-left-color: var(--text-muted); background: var(--surface-hover); }

/* --- Order book depth rows --- */
.book-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.book-row {
  position: relative; display: flex; justify-content: space-between; align-items: center;
  gap: 0.5rem; padding: 0.4rem 0.65rem; font-size: 0.88rem; border-radius: 5px; overflow: hidden; margin-bottom: 3px;
}
/* Direct finding, a mobile-first pass: side-by-side at 1fr 1fr, each
   column left too little room for quantity + price + the Execute
   button all in one `justify-content: space-between` row -- the
   three squeezed together edge to edge (confirmed live at 390px:
   the quantity and price numbers rendered with no visible gap
   between them at all). The explicit `gap` above keeps a minimum
   breathing room between them regardless; stacking Bids above Asks
   below this width is what actually gives the row enough of its
   own space back, rather than relying on the gap alone to save a row that's
   fundamentally too narrow for all three pieces side by side. */
@media (max-width: 640px) {
  .book-columns { grid-template-columns: 1fr; gap: 1.25rem; }
  /* Mobile-first redesign pass (direct ask), continuing the finding
     above: stacking Bids/Asks fixed the row being too narrow, but
     didn't touch the row's own content once given that extra room
     back. Two real thumb/readability issues confirmed by measuring
     against standard touch-target guidance (Apple/Google both
     recommend >=44px): the Execute button's desktop padding
     (0.15em 0.6em, ~24px tall at this font-size) is a mouse-sized
     target, not a thumb-sized one, and the P&L preview line
     (book-row-detail) -- the actual "if correct: +X, if wrong: -Y"
     someone taps Execute based on -- rendered at 0.72rem, smaller
     than this project's own general body text, on the one row
     where reading it correctly before a real credit-moving tap
     matters most. */
  .book-row-take .btn { padding: 0.55em 0.9em; min-height: 44px; display: inline-flex; align-items: center; font-size: 0.85rem; }
  .book-row-detail { font-size: 0.82rem; line-height: 1.4; padding-bottom: 0.75rem; }
}
.book-bar { position: absolute; inset: 0 auto 0 0; z-index: 0; }
.book-bid .book-bar { background: var(--success-bg); }
.book-ask .book-bar { background: var(--danger-bg); }
.book-row span { position: relative; z-index: 1; }
.book-bid .book-price { color: var(--success); font-weight: 700; }
.book-ask .book-price { color: var(--danger); font-weight: 700; }
.book-col-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); font-weight: 700; margin-bottom: 0.4rem; }
/* "A very explicit way to match the opposing side ... a button to
   execute" -- direct ask. book-row-take is the small inline form;
   book-row-detail is the p&l preview line right under each row. */
.book-row-take { position: relative; z-index: 1; }
.book-row-take .btn { padding: 0.15em 0.6em; font-size: 0.78rem; }
.book-row-detail { font-size: 0.72rem; padding: 0 0.65rem 0.5rem; margin-top: -0.35rem; }
/* "Make it clear what is my orders," direct ask -- a visibly
   distinct outline, not just the small "Yours" badge alone, so
   your own resting orders stand out from the book at a glance. */
.book-row-mine { outline: 2px solid var(--accent); outline-offset: -2px; }

/* --- Price history chart --- */
.price-chart { width: 100%; }
.chart-wrap { position: relative; }
.chart-svg { width: 100%; height: 220px; display: block; }
.chart-svg.has-hover { cursor: crosshair; }
.chart-line { fill: none; stroke-width: 2; }
.chart-line-local { stroke: var(--accent); }
.chart-line-polymarket { stroke: var(--text-muted); stroke-dasharray: 4 3; }
.chart-gridline { stroke: var(--border); stroke-width: 1; }
.chart-axis-label { font-size: 9px; fill: var(--text-muted); }
.chart-crosshair { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
.chart-dot { fill: var(--accent); stroke: var(--surface); stroke-width: 1.5; pointer-events: none; }
.chart-dot-polymarket { fill: var(--text-muted); stroke: var(--surface); stroke-width: 1.5; pointer-events: none; }
.chart-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
.chart-range-group { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.chart-range-btn { border: none; border-right: 1px solid var(--border); background: var(--surface); color: var(--text-secondary); font: inherit; font-size: 0.78rem; font-weight: 700; padding: 0.3em 0.75em; cursor: pointer; }
.chart-range-btn:last-child { border-right: none; }
.chart-range-btn:hover { background: var(--surface-hover); }
.chart-range-btn.active { background: var(--accent); color: var(--accent-text); }
.chart-summary { font-size: 0.8rem; color: var(--text-secondary); display: flex; gap: 1rem; }
.chart-summary strong { color: var(--text); }
.chart-tooltip {
  position: absolute; pointer-events: none; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md); padding: 0.4em 0.65em; font-size: 0.78rem;
  white-space: nowrap; transform: translate(-50%, -100%); top: 0; left: 0; opacity: 0; transition: opacity 0.06s;
  z-index: 5; line-height: 1.5;
}
.chart-tooltip.visible { opacity: 1; }
.chart-tooltip-time { color: var(--text-muted); }
.chart-tooltip-row strong { color: var(--text); }
.chart-tooltip-row .chart-swatch { margin-right: 0.3em; }

/* --- Order book depth chart --- */
.depth-chart { width: 100%; margin-bottom: 1rem; }
.depth-chart .chart-svg { height: 140px; }
.depth-area-bid { fill: var(--success); fill-opacity: 0.22; stroke: var(--success); stroke-width: 1.5; }
.depth-area-ask { fill: var(--danger); fill-opacity: 0.22; stroke: var(--danger); stroke-width: 1.5; }
.chart-axis-dates { display: flex; justify-content: space-between; font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; }
.chart-legend { display: flex; gap: 1rem; font-size: 0.8rem; color: var(--text-secondary); }
.chart-legend-item { display: inline-flex; align-items: center; gap: 0.35rem; }
.chart-swatch { display: inline-block; width: 14px; height: 2px; border-radius: 1px; }
.chart-swatch-local { background: var(--accent); }
.chart-swatch-polymarket { background: var(--text-muted); background-image: linear-gradient(90deg, var(--text-muted) 60%, transparent 60%); background-size: 6px 2px; }

/* --- Market grid (list/watchlist pages) --- */
.market-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1rem; align-items: start; }
.market-card { padding: 0; overflow: hidden; }
.market-card-image { width: 100%; height: 130px; object-fit: cover; display: block; background: var(--surface-hover); }
.market-card > .space-between { padding: 1rem 1.1rem; }
.split-bar-sm { height: 6px; border-radius: 4px; margin-bottom: 0; }

/* --- Multi-outcome grouped card (markets/landing pages) -- direct
   ask: "redesign the multioutcome system so all multioutcome bets
   are seen in one box only... with a specific design so we
   understand what prices go with which outcome." A top accent bar
   (rather than the ordinary card's own photo) is this box's own
   visual signal that it's a group, not a single market; each row
   pairs one candidate's own short, distinguishing label with its
   own mini price bar and number, tabular-nums so a column of
   prices lines up instead of jittering by digit count. --- */
.multi-outcome-card { padding: 1rem 1.1rem; border-top: 3px solid var(--accent); }
.multi-outcome-title { font-weight: 600; margin: 0.15rem 0 0.7rem; }
.multi-outcome-rows { display: flex; flex-direction: column; gap: 0.55rem; }
.multi-outcome-row {
  display: grid; grid-template-columns: 1fr 56px 46px; align-items: center; gap: 0.6rem;
  padding: 0.2rem 0.3rem; margin: 0 -0.3rem; border-radius: var(--radius-sm);
  text-decoration: none; color: inherit;
}
.multi-outcome-row:hover { background: var(--surface-hover); }
.multi-outcome-row-label { font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.multi-outcome-row-price { font-variant-numeric: tabular-nums; font-weight: 600; text-align: right; font-size: 0.88rem; }
.multi-outcome-more { display: block; margin-top: 0.7rem; font-size: 0.85rem; }

/* --- Notifications --- */
.notification-unread { border-left: 3px solid var(--accent); font-weight: 600; }

/* --- Live search dropdown --- */
.search-with-suggestions { position: relative; }
.search-dropdown {
  position: absolute; top: 100%; left: 0; right: 0; margin-top: 0.25rem; z-index: 20;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0,0,0,0.12); max-height: 320px; overflow-y: auto;
}
.search-dropdown-item { display: block; padding: 0.5em 0.75em; color: var(--text); text-decoration: none; font-size: 0.9rem; border-bottom: 1px solid var(--border); }
.search-dropdown-item:last-child { border-bottom: none; }
.search-dropdown-item:hover { background: var(--bg); }

/* --- Streaks --- */
.streak-pill { cursor: default; background: var(--warning-bg); color: var(--warning); border-color: transparent; font-weight: 700; }

/* --- Direct challenges --- */
.challenge-disclosure { margin-top: 1.1rem; padding-top: 1rem; border-top: 1px dashed var(--border); }
.challenge-disclosure summary { cursor: pointer; font-weight: 700; font-size: 0.9rem; color: var(--accent); list-style: none; }
.challenge-disclosure summary::-webkit-details-marker { display: none; }
form.inline { display: inline; }
.stack { display: flex; flex-direction: column; gap: 0.5rem; }
.row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.space-between { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
hr.divider { border: none; border-top: 1px solid var(--border); margin: 1.25rem 0; }

/* Google's free website-translator widget -- "if easy go ahead"
   (direct ask), machine translation into any language a visitor
   picks, no maintenance as new pages/features ship. Direct
   feedback: the raw widget sitting in the header row "isn't very
   pretty" -- tucked away instead as a small, muted globe button
   fixed to the side of the page; clicking it reveals Google's own
   dropdown right next to it, hidden again the rest of the time.
   Hides the "powered by Google" iframe banner Google otherwise
   inserts at the very top of the page (pushing the whole layout
   down) -- attribution still shows in the revealed dropdown itself. */
.translate-widget-floating {
  position: fixed; left: 1rem; bottom: calc(var(--sponsored-bar-height) + 1rem); z-index: 40;
  display: flex; align-items: flex-end; gap: 0.5rem;
}
/* season_prizes_teaser.html's own floating card -- opposite corner from the
   translate widget above so the two never collide. max-width caps at the
   viewport itself (minus its own side margins) rather than hiding outright
   on a narrow/mobile screen -- direct bug report: "i cant see the prize
   teaser," and hiding it below 640px was the actual reason why. Both this
   and the translate widget sit above the sitewide sponsored bar (bottom:
   calc(--sponsored-bar-height + 1rem), not a plain 1rem) now that the bar
   is permanently visible on every page rather than an occasional scroll-
   triggered one on a market's own detail page. */
.season-prizes-teaser {
  position: fixed; right: 1rem; bottom: calc(var(--sponsored-bar-height) + 1rem); z-index: 40;
  max-width: min(260px, calc(100vw - 2rem));
  background: var(--surface); border: 1px solid var(--border); border-radius: 0.6rem;
  padding: 0.75rem 1.5rem 0.75rem 0.9rem; box-shadow: 0 2px 12px rgba(0,0,0,0.15);
}
/* Direct finding, a mobile-first pass: this floats over whatever's
   currently in view at the bottom of the viewport -- confirmed live
   at 390px, it landed squarely on top of the portfolio dashboard's
   own Cash Balance figure. Can't avoid overlapping *something* while
   staying fixed and visible (the whole point of the earlier "i cant
   see the prize teaser" fix), so this shrinks its own footprint
   instead on a narrow screen: title + dismiss only, the full
   explanation dropped (still just as reachable by not dismissing it
   and reading it on a wider screen, or after tapping through to the
   leaderboard link it already points at). */
@media (max-width: 480px) {
  .season-prizes-teaser { padding: 0.55rem 1.6rem 0.55rem 0.75rem; max-width: min(200px, calc(100vw - 2rem)); }
  .season-prizes-teaser .subtle { display: none; }
}
/* Sitewide sponsored bottom bar (ads/_sponsored_bar.html) -- direct
   ask, follow-up on two earlier passes that were "not exactly what I
   want": always visible from page load (no scroll trigger, no JS at
   all), no dismiss control, never shows a price. Was previously
   market-detail-only and scroll-triggered (that version's own CSS
   lived inline in the partial, since it only ever rendered on one page
   template); now sitewide via templates/base.html, so it earns a real
   place in this already-cached stylesheet instead of repeating an
   inline <style> block on every single response. */
.sponsored-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  background: var(--surface); border-top: 1px solid var(--border); box-shadow: var(--shadow-md);
  animation: sponsored-bar-in 0.22s ease-out;
}
@keyframes sponsored-bar-in { from { transform: translateY(100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .sponsored-bar { animation: none; } }
.sponsored-bar-inner { max-width: 1040px; margin: 0 auto; padding: 0.75rem 1.25rem; display: flex; align-items: center; gap: 1rem; }
.sponsored-bar-dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; flex-shrink: 0; }
.sponsored-bar-text { flex: 1; min-width: 0; }
.sponsored-bar-label {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 4px; padding: 0.1rem 0.4rem;
}
.sponsored-bar-tagline { margin: 0.15rem 0 0; color: var(--text-secondary); }
.sponsored-bar-cta { flex-shrink: 0; color: #fff; border-color: transparent; }
@media (max-width: 640px) {
  :root { --sponsored-bar-height: 6.5rem; }
  .sponsored-bar-inner { flex-wrap: wrap; }
  .sponsored-bar-text { order: 1; width: 100%; }
  .sponsored-bar-dot { order: 0; }
}

/* Adcash 728x90 Display banner (templates/base.html, top of every
   page) -- a fixed-size creative, so this centers it and scrolls
   horizontally on a narrower screen instead of overflowing the page
   (matches this site's own no-horizontal-scroll convention elsewhere)
   rather than trying to resize a fixed ad unit. */
.adcash-banner-slot {
  display: flex; justify-content: center; overflow-x: auto;
  padding: 0.6rem 1rem; background: var(--surface); border-bottom: 1px solid var(--border);
}
.translate-toggle-btn {
  width: 2.25rem; height: 2.25rem; border-radius: 50%; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-secondary); font-size: 1.1rem; line-height: 1;
  cursor: pointer; box-shadow: var(--shadow-sm); opacity: 0.7; transition: opacity 0.15s;
}
.translate-toggle-btn:hover { opacity: 1; }
#google_translate_element { display: none; }
#google_translate_element.is-open { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.4rem; box-shadow: var(--shadow-sm); }
#google_translate_element select.goog-te-combo {
  font-family: inherit; font-size: 0.82rem; padding: 0.35em 0.5em;
  border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--surface); color: var(--text);
}
.goog-te-banner-frame { display: none !important; }
body { top: 0 !important; }

@media (max-width: 640px) {
  .header-inner { gap: 0.75rem; }
  .primary-nav { gap: 0.85rem; order: 3; width: 100%; }
  .page { padding: 0 1rem 3rem; }
  .stat-hero .stat-value { font-size: 1.7rem; }
  /* Direct finding, a real accessibility/mobile pass: .header-actions
     (theme toggle, notifications, credits/streak pills, account
     menu, translate toggle) has no flex-wrap of its own -- on a
     narrow phone width there simply isn't room for all of them on
     one row, and with no wrap fallback they overflowed the row
     instead, dragging the *entire page* into unwanted horizontal
     scroll (confirmed live: document.documentElement.scrollWidth
     exceeded the viewport width on every page, not just one).
     .header-inner already wraps its own children (this and
     .primary-nav) just fine; this is the one row that didn't wrap
     internally when it ran out of room itself. */
  .header-actions { flex-wrap: wrap; row-gap: 0.4rem; }
}

/* "When an @ is written, dynamically load usernames below," direct
   ask -- see attachMentionAutocomplete in base.html (league chat/market
   comments). */
.mention-dropdown { position: absolute; z-index: 50; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow-md); max-width: 240px; margin-top: 2px; overflow: hidden; }
.mention-dropdown-item { padding: 0.35rem 0.65rem; cursor: pointer; font-size: 0.85rem; }
.mention-dropdown-item:hover, .mention-dropdown-item.active { background: var(--surface-hover); }
