/* body stylings */
body {
  margin: 0;
  padding: 0;
  font-family: 'Montserrat', sans-serif;
  min-height: 100vh;
  display: flex;
  flex-direction: column;

  background: linear-gradient(to bottom, #0a0a0c 0%, #1a1a1f 100%);
  /* solid fallback under the gradient (after the shorthand, which resets it) -
     the app's WebView showed white without it (2026-09-30) */
  background-color: #0a0a0c;
  color: #f0f0f0;
}

/* noise texture */
body::before {
  content: "";
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  opacity: 0.03;
  pointer-events: none;
  z-index: 0;
}

/* login / hero header */
.login-hero-header {
  width: 100%;
  text-align: center;
  margin-top: 0rem;
  margin-bottom: 0rem;
  z-index: 2;
}

.login-hero-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  text-align: center;
}

/* brand title */
.brand-title {
  font-family: 'Montserrat', arial, sans-serif;
  font-size: 2.4rem;
  font-weight: 600;
  color: #f5f7fb;
  letter-spacing: 0.03em;
  line-height: 1.1;
  margin-top: 3.5rem;
  margin-bottom: 0.5rem;
  text-shadow: none;
  animation: none;
  text-transform: none;
  text-align: center;
}

/* tagline */
.login-hero-center h2 {
  font-size: 1.1rem;
  color: var(--text-soft);
  margin: 0.25rem 0 1.25rem;
}

/* read-only fields */
input[readonly] {
  background: rgba(255,255,255,0.12);
  color: var(--text);
  border: 1px solid rgba(255,255,255,0.25);
  cursor: default;
}

/* page-specific subtitle title, sibling to the site-header brand block
   (promoted from event.css/events.css, which had identical copies) */
.page-header {
    font-size: 1.25rem;
    font-weight: 500;
    color: #6bb6ff;
    margin-top: 0.25rem;
    margin-bottom: 1rem;
    letter-spacing: 0.5px;
}

/* page-subtitle-block: a richer subtitle area (paragraph + status banners)
   used on new_play.php/pickem_play.php - previously this content lived
   inside a mis-scoped <header class="page-header"> wrapping BOTH the
   brand title and the subtitle, colliding with the .page-header class
   above. Same visual weight as .page-header, just on a <div> that can
   hold more than a single title line. */
.page-subtitle-block {
    text-align: center;
    margin-top: 0.25rem;
    margin-bottom: 1rem;
}

.page-subtitle {
    font-size: 1.25rem;
    font-weight: 500;
    color: #6bb6ff;
    letter-spacing: 0.5px;
    margin: 0 0 0.5rem;
}

/* universal tagline */
.brand-tagline {
  font-family: 'Montserrat', arial, sans-serif;
  font-size: 1.1rem;
  font-weight: 400;
  color: var(--text-soft);
  margin: 0.25rem 0 1.25rem;
  text-align: center;
  font-style: italic;
  opacity: 0.95;
}

.login-column {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.2rem;
}

.login-page-layout {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 0rem;
  position: relative;
}

/* universal footer */
.site-footer {
  background-color: var(--neutral-900);
  color: #aaa;
  font-size: 0.85rem;
  padding: 0.4rem 0.8rem;
  text-align: center;
  border-top: 0.1rem solid var(--neutral-700);
  width: 100%;
}

.site-footer a {
  color: #aaa;
  margin: 0 0.6rem;
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--text-inverse);
}

.site-footer nav {
  display: inline-block;
}

/* page container */
.page-container {
  max-width: 70rem;
  margin: 0 auto;
}

/* pick grid */
.pick-grid {
  display: grid;
  grid-template-columns:
    1.2rem
    1rem
    12rem
    2rem
    1.2rem
    1rem
    12rem;
  align-items: center;
}

.pick-grid input[type="radio"] {
  margin: 0;
}

.pick-grid label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* gap splitter */
.gap-tny { margin-top: 0.25rem; }
.gap-sm  { margin-top: 0.5rem; }
.gap-sm-md  { margin-top: 0.6rem; }
.gap-md  { margin-top: .75rem; }
.gap-md-lg  { margin-top: 1rem; }
.gap-lg-sm  { margin-top: 1.25rem; }
.gap-lg-md  { margin-top: 1.5rem; }
.gap-lg-lg  { margin-top: 1.75rem; }
.gap-hg  { margin-top: 2rem; }
.gap-mg  { margin-top: 3rem; }

/* negative gaps */
.gap-tny-neg { margin-top: -0.25rem; }
.gap-sm-neg  { margin-top: -0.5rem; }
.gap-sm-md-neg  { margin-top: -0.6rem; }
.gap-md-neg  { margin-top: -0.75rem; }
.gap-md-lg-neg  { margin-top: -1rem; }
.gap-lg-sm-neg  { margin-top: -1.25rem; }
.gap-lg-md-neg  { margin-top: -1.5rem; }
.gap-lg-lg-neg  { margin-top: -1.75rem; }
.gap-hg-neg  { margin-top: -2rem; }
.gap-mg-neg  { margin-top: -3rem; }

/* horizontal gaps */
.gap-tny-h     { display: inline-block; margin-left: 0.25rem; }
.gap-sm-h      { display: inline-block; margin-left: 0.5rem; }
.gap-sm-md-h   { display: inline-block; margin-left: 0.6rem; }
.gap-md-h      { display: inline-block; margin-left: 0.75rem; }
.gap-md-lg-h   { display: inline-block; margin-left: 1rem; }
.gap-hg-h      { display: inline-block; margin-left: 2rem; }
.gap-mg-h      { display: inline-block; margin-left: 3rem; }

/* negative horizontal gaps */
.gap-tny-h-neg   { display: inline-block; margin-left: -0.25rem; }
.gap-sm-h-neg    { display: inline-block; margin-left: -0.5rem; }
.gap-sm-md-h-neg { display: inline-block; margin-left: -0.6rem; }
.gap-md-h-neg    { display: inline-block; margin-left: -0.75rem; }
.gap-md-lg-h-neg { display: inline-block; margin-left: -1rem; }
.gap-hg-h-neg    { display: inline-block; margin-left: -2rem; }
.gap-mg-h-neg    { display: inline-block; margin-left: -3rem; }

/* global scrollbar styling */
/* firefox */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.25) rgba(255,255,255,0.08);
}

/* chrome / edge / safari */
*::-webkit-scrollbar {
    width: 0.5rem;
    height: 0.5rem;
}

*::-webkit-scrollbar-track {
    background: rgba(255,255,255,0.08);
    border-radius: 0.25rem;
}

*::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.25);
    border-radius: 0.25rem;
}

*::-webkit-scrollbar-thumb:hover {
    background: rgba(255,255,255,0.35);
}

/* global nav */
.global-nav {
  text-align: center;
  /* Universal standard: the gap between the brand title and the navbar.
     One lever, every page with a navbar. */
  margin-top: 4rem;
  margin-bottom: 2rem;
}

.global-nav-inner {
  /* Split when it gets too big: wrap into centered rows once the buttons
     exceed a comfortable width, instead of one overflowing line. The
     max-width is the lever — a normal button set stays on one row; a heavy
     row (admin tools + page actions) breaks onto a second centered row. */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.7rem 1.2rem;
  max-width: 68rem;
  margin: 0 auto;
  padding: 0 1rem;
}

h1 {
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 0.75rem 0;
  line-height: 1.25;
  letter-spacing: 0.01rem;
}

h2 {
  font-size: 1.15rem;
  font-weight: 600;
  color: #dce3ea;
  margin: 0.5rem 0 0.5rem 0;
  line-height: 1.3;
  letter-spacing: 0.005rem;
}

h3 {
  font-size: 1.05rem;
  font-weight: 600;
  color: #c9d2db;
  margin: 0.4rem 0 0.4rem 0;
  line-height: 1.35;
  letter-spacing: 0.003rem;
}

/* "your pick" panel — the viewer's own leg + provisional live status */
.pick-panel {
    max-width: 30rem;
    margin: 0 auto 1.25rem;
    background: rgba(255, 255, 255, 0.05);
    border: 0.0625rem solid rgba(255, 255, 255, 0.15);
    border-radius: 0.5rem;
    padding: 0.85rem 1.1rem;
    text-align: center;
}

.pick-header {
    text-transform: lowercase;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    color: var(--text-muted, #9a9a9a);
    margin-bottom: 0.4rem;
}

.pick-body {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.pick-what {
    font-weight: 600;
    font-size: 1rem;
    color: var(--text-inverse);
}

.pick-status {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: lowercase;
    padding: 0.15rem 0.6rem;
    border-radius: 1rem;
    white-space: nowrap;
}

.pick-status--good    { background: #2e7d32; color: var(--text-inverse); }
.pick-status--bad     { background: #b23b3b; color: var(--text-inverse); }
.pick-status--even    { background: #6b6b6b; color: var(--text-inverse); }
.pick-status--pending { background: transparent; color: var(--text-muted, #9a9a9a); border: 0.0625rem solid rgba(255, 255, 255, 0.25); }

.pick-note {
    margin-top: 0.45rem;
    font-size: 0.72rem;
    color: var(--text-muted, #9a9a9a);
}

/* uniform vertical spacing between the stacked "forms" on the details pages
   (team box, your-pick, live boxes, note, button row). adjust --form-gap to taste. */
.mlb-details-page,
.nfl-details-page {
    --form-gap: 2rem;
}

.mlb-details-page > .login-hero-center > *,
.nfl-details-page > .login-hero-center > * {
    margin-top: 0;
    margin-bottom: var(--form-gap);
}

.mlb-details-page > .login-hero-center > *:last-child,
.nfl-details-page > .login-hero-center > *:last-child {
    margin-bottom: 0;
}

/* Interior pages (those wrapped in .site-header) don't need the full hero
   top gap the login/landing page uses. Trim it here; the global .brand-title
   keeps its airy 3.5rem on the login hero, which does not use .site-header. */
.site-header .brand-title {
    margin-top: 2rem;
}


/* Fiery crown label (shared) — the branded header image. Mirrors the Parlor's
   own rule so any page loading common.css can use it in place of .brand-title. */
.parlor-crown {
    display: block;
    width: 100%;
    max-width: min(38rem, 88%);
    height: auto;
    margin: 0 auto 0.25rem;
    filter: drop-shadow(0 0.4rem 1.1rem rgba(0,0,0,.55));
}

/* ---------------------------------------------------------------------
   STANDARD PAGE TOP — label, message, navbar. One rhythm, every page.

   THE SLIPPAGE THIS FIXES. Every page positioned its own top block by
   hand, with the .gap-* spacer divs: `gap-hg` on one page, `gap-md-lg`
   on the next, `gap-lg-neg` on a third to claw back the 4rem margin
   .global-nav sets on itself, and several pages with no spacer at all.
   So the crown landed at a different height on every page and appeared
   to jump as you clicked through — and the message was sometimes above
   the navbar, sometimes below it, sometimes an <h3>, sometimes an
   <h2 class="brand-tagline">, sometimes a bare <div class="message">.

   THE FIX IS TO TAKE THE GAPS AWAY FROM THE PAGE. Pages do not write
   this markup at all any more — includes/page_top.php emits it, and a
   page that needs the standard top block includes that. This file is
   only the spacing behind it.

   ORDER IS page_top.php's, spacing is this file's:

       label  (header.site-header, the crown)
       gap    --page-gap
       message form  (p.info-message)
       gap    --page-gap
       navbar (global_nav.php)
       gap    --page-gap
       ...and every block the page adds after that, automatically

   ONE LEVER: --page-gap. Change it here and every page moves together.
   A per-page override is legitimate but should be rare and deliberate:
   body.page-standard.some-page { --page-gap: 2rem; }

   A CONVERTED PAGE CARRIES NO .gap-* SPACER IN ITS TOP BLOCK. If you
   find yourself adding one back, --page-gap is what you actually want.

   OPT-IN ON PURPOSE. Only pages carrying .page-standard are affected,
   so the conversion can go page by page and be reviewed as it goes.
--------------------------------------------------------------------- */
.page-standard {
    --page-gap: 3rem;
}

/* The label sits as close to the top as is reasonable, and 0.75rem now
   MEANS 0.75rem.

   It did not used to. images/real_odd_games_header.png carried a soft
   glow that faded to fully transparent well inside its frame — 120 dead
   rows along the top edge and 53 along the bottom, of 920. That padding
   was part of the image's box, so the crown floated ~29px lower than its
   margin claimed and a 3rem gap below it READ as 4rem, which is why the
   message box sat low while measuring correct.

   The image was cropped to its own ink on 2026-09-20 (920 -> 747 rows,
   width untouched at 3360 so the wordmark renders at exactly the same
   size everywhere). The kept region is pixel-identical to the original;
   the discarded rows, composited over the page background, deviated from
   it by at most 2.88/255.

   THERE IS THEREFORE NO TRIM CONSTANT HERE, and there should never be
   one again. If a future header image reintroduces the problem, crop the
   image — do not correct for it in CSS. To check one:

       python3 -c "from PIL import Image; import numpy as np; \
       a=np.asarray(Image.open(P).convert('RGBA').split()[3]); \
       r=np.nonzero(a.max(axis=1)>3)[0]; \
       print('dead rows: top',r[0],'bottom',a.shape[0]-1-r[-1])"
   --------------------------------------------------------------------- */
.page-standard .site-header {
    margin-top: 0.75rem;
}

/* .parlor-crown ships `margin: 0 auto 0.25rem`, which collapses out to
   the header's bottom edge and lands on top of --page-gap. The stack
   owns the gap, so zero it. */
.page-standard .parlor-crown {
    margin-bottom: 0;
}

/* FLEX, NOT BLOCK, and not for layout — for margin behaviour. In a block
   container the first child's margin-top collapses through the parent
   and escapes the stack, which is exactly the kind of gap that reads as
   correct on one page and 3rem too tall on the next. A flex container
   does not collapse margins, so --page-gap means --page-gap everywhere.
   align-items stays at its `stretch` default: each child is full width
   and centres itself the way it already did (.info-message by its auto
   side margins, .global-nav by text-align + its inner's auto margins). */
.page-standard .page-stack {
    display: flex;
    flex-direction: column;
}

/* Every child is separated by exactly one gap and sets no margin of its
   own. This single rule is what stops the bouncing — and it applies to
   the page's own content too, not just the top block, so a page never
   has to space its sections by hand either. */
.page-standard .page-stack > * {
    margin-top: var(--page-gap);
    margin-bottom: 0;
}

/* THE SHELL OWNS THE HEADER BLOCK.

   Page stylesheets had been reaching inside it, which is the other half of
   the header-bouncing — the half that survived the page migration, because
   it lives in CSS rather than in the markup. Found 2026-09-21 by measuring
   the crown across pages:

     mlb_details.css and nfl_details.css each added
     `.login-hero-header { margin-bottom: 1.5625rem }`, injecting 25px inside
     the header on those two pages alone;

     contact / under_construction / demo_logged_in / tracker each resized or
     recoloured `.info-message`, so the message box was 26rem here, 32rem
     there, 1.1rem here, 0.95rem there.

   Those rules are gone from the page sheets now. This block is the guard, so
   the next one cannot land: inside .page-standard the shell's geometry wins.
   Note the scoping to `.site-header` — mlb_details and nfl_details also use
   `.login-hero-center` as a CONTENT wrapper further down the page, and that
   one keeps its own max-width. */
.page-standard .site-header .login-hero-center,
.page-standard .site-header .login-hero-header {
    max-width: none;
    margin: 0 auto;
    padding: 0;
}

/* .info-message is max-width 32rem and centres itself with `margin: 1rem
   auto 1.5rem` — the stack rule above replaces only its top and bottom, so
   the auto side margins survive. The width and size are restated here so
   neither a page sheet nor a future edit to app_core.css can change the
   shape of the box from one page to the next. */
.page-standard .page-stack > .info-message {
    margin-left: auto;
    margin-right: auto;
    max-width: 32rem;
    font-size: 0.95rem;
}

/* .global-nav still ships margin-top: 4rem / margin-bottom: 2rem for the
   pages not yet converted. Inside the stack the gap belongs to the
   stack, so it is zeroed — this is what the `gap-lg-neg` spacers
   scattered through the pages were fighting. */
.page-standard .page-stack > .global-nav {
    margin-top: var(--page-gap);
    margin-bottom: 0;
}
