/* ─────────────────────────────────────────────
   FirstSnap.net — mobile / responsive layer

   Loaded LAST on every firstsnap page, after styles.css and whatever
   page stylesheet that page pulls in. Load order is the whole point: the
   per-page sheets (landing.css, today.css, …) already carry their own
   @media blocks at the same specificity as anything written here, so a
   rule that lives in styles.css loses to them. This sheet loads after
   all of them and wins without needing !important.

   What belongs here: anything that only exists because the viewport is
   narrow or the input is a finger. Desktop layout stays in the page
   sheets. If a rule would apply at 1440px, it does not belong in this
   file.

   Breakpoints, matching what the page sheets already use:
     1100px  the /app dashboard drops its sidebar column
     1000px  top nav collapses into the hamburger
      900px  "mobile" — where the layout stops assuming a mouse
      700px  phone portrait — the dense grids go to one column
      420px  small phone (iPhone SE / Galaxy A-series) — tighten gutters

   Touch affordances key off (pointer: coarse) as well as width, so a
   1024px touch tablet gets them and a narrow desktop window does not.

   Reference device is a Pixel 9a (412 x 915 CSS px, DPR 2.625), but the
   layout is written against the breakpoints, not that device: 320px is
   the narrowest viewport the site is expected to survive.
───────────────────────────────────────────── */

/* ══ 1. Base guards — all widths ══════════════════════════════════ */

html {
  /* Android Chrome and iOS Safari inflate the font of any block they
     decide is the main column when the page is zoomed out. On a page
     that already sets its own type scale that shows up as one paragraph
     rendering a size larger than its neighbours. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  /* styles.css sets overflow-x: hidden. `clip` does the same clipping
     without turning the body into a scroll container, which is what
     makes position: sticky work reliably inside it — the nav is sticky
     and hidden costs it its stickiness in some engines. */
  overflow-x: clip;
  /* The URL bar retracts on scroll, so 100vh is taller than what you
     can see when the page loads. dvh tracks the visible box. */
  min-height: 100dvh;
}

/* Media never sets the floor for how wide a row has to be. */
img, svg, video, canvas, iframe { max-width: 100%; }
img, video { height: auto; }

/* iOS Safari zooms the whole page in when a focused field's type is
   under 16px and never zooms back out. max() keeps any field that was
   deliberately set larger. */
input, select, textarea {
  font-size: max(16px, 1em);
}

/* The default is an opaque grey wash on every tap. Key it to the chalk
   so a tapped card reads as ours rather than as a browser default. */
* { -webkit-tap-highlight-color: rgba(232, 195, 58, 0.16); }

/* Momentum scrolling for the horizontal strips below, and no rubber-band
   chaining out to the page behind them. */
.section-tabs,
.fs-tscroll,
.nav-mobile {
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}


/* ══ 1b. The painted field, cropped ═══════════════════════════════
   styles.css fits the whole 53⅓-yard width of the field into the
   window, which sets one yard at 100vw / 53.3333. On a 1440px desktop
   that is a 27px yard: 5-yard lines 135px apart, single-yard ticks
   every 27px. On a 412px phone the same rule gives a 7.7px yard —
   lines 39px apart and a tick every 8px, four columns of them. At that
   density the marks stop reading as a field and start reading as
   corduroy behind the type.

   The fix is not to redraw the field smaller but to show less of it. A
   phone gets a crop: the yard holds at the size it had where the full
   width last fitted (1000px ÷ 53.3333 = 18.75px), so the marks keep
   their desktop rhythm and the viewport simply covers ~22 yards of
   width instead of 53. That is also what a broadcast camera does — it
   does not letterbox the field to fit, it moves in.

   Cropping means the sidelines are off screen, so the two sideline
   verticals and the two tick columns that run inside them are dropped
   here. What is left is what a centred crop would actually show: the
   two hash columns and the 5-yard lines. The hashes stop being a fixed
   percentage of the window — 44.219% / 55.781% is only their position
   when the whole width is in frame — and become their true offset from
   the centre line, 3.083 yd (26.667 half-width less 23.583 to the
   hash), measured in the cropped yard.

   The numerals come with the crop. On the real field they sit 13.67 yd
   off centre, which in the cropped yard is ~256px from the middle of a
   phone — just outside the frame. Rather than lose them, each column is
   brought in to sit centred in the strip between its hash column and
   the screen edge, the same relationship to the hashes a camera crop
   would show. Sized off the cropped yard alone: the desktop rule caps
   them by the gutter outside the 1440px shell, and there is no gutter
   here. They paint under the page's own columns, and that is the
   correct read — the numbering is on the turf, and an opaque card laid
   over it simply hides that patch, as the hero band does on desktop. */

@media (max-width: 1000px) {
  :root {
    /* max(), not min(): below 1000px the window stops setting the scale
       and the scale starts setting how much window you see. The height
       veto in the desktop rule kept a wide, short window from scaling
       the field up until a numeral was clipped; the yard has a floor
       here and never scales up with height, so the veto has nothing to
       do and goes. A short viewport clips a row at the edge, the way a
       tighter camera shot would. */
    --yard: max(18.75px, calc(100vw / 53.3333));
    --hash-off: calc(var(--yard) * 3.0833);
  }

  body::before {
    background-image:
      /* 1-yard ticks at each hash */
      var(--ticks), var(--ticks),
      /* 5-yard lines, edge to edge */
      linear-gradient(to bottom, rgba(238, 242, 238, 0.055) 2px, transparent 2px);
    background-size:
      var(--tick) calc(var(--yard) * 5),
      var(--tick) calc(var(--yard) * 5),
      100% calc(var(--yard) * 5);
    /* Same 2.5-yard vertical offset as the desktop rule, for the same
       reason: it lands a 5-yard line dead centre instead of stranding
       one 2.5 yd above the middle. */
    background-position:
      calc(50% - var(--hash-off) - var(--tick)) calc(50% + var(--yard) * 2.5),
      calc(50% + var(--hash-off)) calc(50% + var(--yard) * 2.5),
      center calc(50% + var(--yard) * 2.5);
    background-repeat: repeat-y, repeat-y, repeat-y;
  }

  /* The desktop cap on font-size measures against --gutter, which is
     negative below the 1440px shell and takes the numerals to nothing.
     A painted numeral is 2 yd tall; see the desktop rule for the 2.28. */
  .fs-field span {
    font-size: calc(var(--yard) * 2.28);
  }
  /* Centred in the strip outside each hash column: the strip runs from
     the screen edge to 50% - --hash-off, so its middle is half that. */
  .fs-field .col-l { left: calc(25% - var(--hash-off) / 2); }
  .fs-field .col-r { left: calc(75% + var(--hash-off) / 2); }
}

/* Above the crop the field still fits the window, and there the height
   veto matters — but 100vh is the wrong height to measure against on a
   touch device: it counts the space behind the URL bar, so the whole
   field resizes the moment the bar retracts on first scroll and the
   yard lines slide up the screen mid-read. svh is the URL-bar-visible
   height, which does not move. */
@supports (height: 100svh) {
  @media (min-width: 1001px) {
    :root {
      --yard: min(calc(100vw / 53.3333), calc((100svh - var(--hdr)) / 27));
    }
  }
}


/* ══ 2. Safe areas — notch, punch-hole, gesture bar ═══════════════ */

/* Landscape on a notched phone puts the cutout over the left or right
   edge of the bar; portrait on any phone with a gesture bar puts the
   home indicator over the last ~20px of the page. */
.nav {
  padding-left: max(24px, env(safe-area-inset-left));
  padding-right: max(24px, env(safe-area-inset-right));
}

.page,
.lp-page,
.td-page,
.tr-page,
.mt-page,
.tn-page,
.bk-page,
.gd-page {
  padding-bottom: calc(60px + env(safe-area-inset-bottom));
}

/* The alerts drawer is fixed to the right edge and full-height. */
.fs-drawer {
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
}


/* ══ 3. The mobile nav ════════════════════════════════════════════ */

/* The hamburger and its panel are inert above 1000px — the inline
   .nav-links carry the same set there. Below it the inline links are
   hidden and this is the only way to reach anything but the current
   page, which is what the bar was missing: styles.css took .nav-links
   away at 900px and put nothing in their place, so a signed-out phone
   visitor had no navigation at all. */

.nav-burger {
  display: none;
  flex: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: 4px;
  align-self: center;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
}
.nav-burger:hover { background: var(--surface); }
.nav-burger-bar {
  display: block;
  width: 18px;
  height: 2px;
  background: currentColor;
  transition: transform .16s var(--easing), opacity .12s;
}
.nav-burger-bar + .nav-burger-bar { margin-top: 4px; }

/* Open state: top and bottom rules cross, middle one drops out. */
.nav-burger[aria-expanded="true"] { color: var(--chalk); border-color: var(--chalk-border); }
.nav-burger[aria-expanded="true"] .nav-burger-bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-burger[aria-expanded="true"] .nav-burger-bar:nth-child(2) { opacity: 0; }
.nav-burger[aria-expanded="true"] .nav-burger-bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.nav-mobile {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 60;
  flex-direction: column;
  background: var(--bg-deep);
  border-bottom: 2px solid var(--chalk);
  /* Long link sets on a short landscape screen still have to reach the
     last item. */
  max-height: calc(100dvh - var(--hdr));
  overflow-y: auto;
  padding-bottom: env(safe-area-inset-bottom);
}
.nav-mobile[hidden] { display: none; }

.nav-mobile .nav-link,
.nav-mobile-link {
  display: flex;
  align-items: center;
  min-height: 52px;
  padding: 0 24px;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-2);
  border: 0;
  border-bottom: 1px solid var(--border-soft);
  border-left: 4px solid transparent;
  margin: 0;
  background: transparent;
  width: 100%;
  text-align: left;
  cursor: pointer;
}
.nav-mobile .nav-link.active,
.nav-mobile-link.active {
  color: var(--chalk);
  border-left-color: var(--chalk);
  background: var(--surface);
}
.nav-mobile .nav-link:active,
.nav-mobile-link:active { background: var(--surface); }

/* The signed-out CTA pair moves into the sheet on the narrowest phones
   (see §4) and needs to look like buttons, not like more links. */
.nav-mobile-cta {
  display: flex;
  gap: 10px;
  padding: 14px 24px calc(18px + env(safe-area-inset-bottom));
}
.nav-mobile-cta .btn { flex: 1 1 0; min-height: 44px; }

/* styles.css hides .nav-links at 900px, but the bar is already out of room
   above that: at 901–1000px the five condensed links wrap onto a second
   line and the bar grows to two rows. The sheet takes over from 1000px
   instead — the same width at which the painted field drops out. */
@media (max-width: 1000px) {
  .nav-links { display: none; }
  .nav-burger { display: inline-flex; }
  .nav-mobile { display: flex; }
  .nav-mobile[hidden] { display: none; }
}


/* ══ 4. Nav bar itself, narrow ════════════════════════════════════ */

@media (max-width: 1000px) {
  .nav {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
    gap: 8px;
  }
  .nav-brand { padding-right: 0; margin-right: auto; min-width: 0; }
  .nav-brand-name { font-size: 22px; }
  .nav-actions { padding-left: 0; gap: 6px; min-width: 0; }

  /* 30px was under every touch-target guideline going. The box stays
     30px so the bar keeps its height; the hit area is grown past the
     paint with a pseudo-element. */
  .nav-icon-btn { position: relative; }
  .nav-icon-btn::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
  }
  .user-chip { min-height: 44px; }
}

@media (max-width: 640px) {
  /* The signed-out bar carried brand + Sign in + Get a pass + burger,
     which is what pushed every public page 28px past the viewport. The
     word marks stay; the two CTAs move into the sheet. */
  .nav-actions .btn-ghost { display: none; }
  .nav-actions .btn-sm { font-size: 13px; padding: 6px 10px; }

  /* Signed in, the chip keeps the avatar and drops the name column —
     the same information is one tap away in the dropdown. */
  .user-chip .user-meta { display: none; }
  .user-chip .user-caret { display: none; }
  .user-chip { padding: 4px; }
}

@media (max-width: 420px) {
  .nav-brand-name { font-size: 19px; }
  .nav-brand img { width: 26px; height: 26px; }
  /* Below this the "Get a pass" pill and the burger cannot both fit
     beside the wordmark. The sheet carries both CTAs from here down. */
  .nav-actions .btn-primary { display: none; }
}

/* The user dropdown is anchored to the chip, which sits at the right
   edge — on a phone that puts half the panel off screen. */
@media (max-width: 640px) {
  .user-dropdown {
    position: fixed;
    top: var(--hdr);
    left: 8px;
    right: 8px;
    width: auto;
    min-width: 0;
    max-height: calc(100dvh - var(--hdr) - 16px);
    overflow-y: auto;
  }
  .user-dropdown-item { min-height: 46px; display: flex; align-items: center; }
}


/* ══ 5. /app — the dashboard sidebar ══════════════════════════════ */

/* The two-column grid collapses at 1100px (styles.css) and the sidebar,
   being first in the DOM, lands on top of the slate: on a 412px screen
   that is roughly 1800px of week picker, filters, badge legend and last
   week's record before the first game card.

   display: contents dissolves the <aside> box so its five sections
   become direct children of .page alongside <main>, and order puts the
   two controls above the slate and the three reference cards below it.
   The sections keep their own markup; only the box around them goes. */

@media (max-width: 1100px) {
  .page {
    display: flex;
    flex-direction: column;
    gap: 18px;
  }

  .sidebar { display: contents; }

  .sb-week      { order: 1; }
  .sb-sec-slate { order: 2; }
  .main         { order: 3; }
  .sb-sec-tools { order: 4; }
  .sb-card      { order: 5; }

  /* Week picker: a single wide control rather than a stacked block. */
  .sb-week { padding: 10px 12px; }
  .sb-week-arrow {
    width: 44px;
    height: 44px;
    font-size: 22px;
  }

  /* The slate filters were a vertical list in a 232px rail. Across a
     full-width phone that is four rows of mostly empty space, so they
     become a horizontally scrolling chip row. */
  .sb-sec-slate .sb-eyebrow { margin-bottom: 8px; }
  .sb-sec-slate .sb-group {
    flex-direction: row;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 4px;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .sb-sec-slate .sb-group::-webkit-scrollbar { display: none; }
  .sb-sec-slate .sb-nav {
    flex: 0 0 auto;
    /* .sb-nav is width: 100% for the vertical rail; in a row that makes
       the first chip eat the strip and push the rest out of sight. */
    width: auto;
    min-height: 44px;
    padding: 8px 14px;
    border-left: 0;
    border-bottom: 3px solid transparent;
    white-space: nowrap;
  }
  .sb-sec-slate .sb-nav.active { border-bottom-color: var(--chalk); }
  /* margin-left: auto pushes the count to the far edge of a full-width
     row. In a chip it just needs to sit after the label. */
  .sb-sec-slate .sb-lock { margin-left: 0; }

  /* Tools go back to full-width rows below the slate. */
  .sb-sec-tools .sb-nav { min-height: 48px; }

  /* Reference cards read as footnotes down here, side by side while
     there is room for two. */
  .sb-card { margin: 0; }
}

@media (min-width: 701px) and (max-width: 1100px) {
  .page { display: grid; grid-template-columns: 1fr 1fr; align-items: start; }
  .sb-week      { grid-column: 1 / -1; }
  .sb-sec-slate { grid-column: 1 / -1; }
  .main         { grid-column: 1 / -1; }
  .sb-sec-tools { grid-column: 1 / -1; }
}

@media (max-width: 700px) {
  .page { padding: 16px 14px 60px; }
}

@media (max-width: 420px) {
  .page { padding: 14px 10px 56px; }
}


/* ══ 6. Tables — scroll rather than crush ═════════════════════════ */

/* A five-column market table cannot be read at 320px however it is
   restyled, and stacking it loses the column-to-column comparison that
   is the reason to draw a table at all. So it keeps its shape and gets
   its own scroll box, with a fade on the right edge saying there is
   more to the right. */

.fs-tscroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  /* A scroll box is only allowed to be narrower than its contents if
     nothing upstream is sizing itself off those contents — see the
     min-width: 0 note below. */
  min-width: 0;
}

/* A grid or flex item's automatic minimum size is the min-content width
   of what it holds, and that measurement reaches straight through the
   scroll box to the table inside it. So a card in a 1fr column grows to
   the table's 420px and takes the page with it, scroll box or not.
   min-width: 0 opts the item out of that floor; the .fs-tscroll inside
   then does the scrolling it was put there to do. */
.tn-block,
.tn-two > *,
.td-block { min-width: 0; }

@media (max-width: 760px) {
  /* Blocks that hold a table give back their side padding on mobile, so
     the scroll strip starts at the card edge — a table inset by 24px on
     a 360px screen reads as clipped rather than as scrollable. */
  .td-block, .tn-block { padding-left: 16px; padding-right: 16px; }
  .td-block > .fs-tscroll,
  .tn-block > .fs-tscroll {
    margin-inline: -16px;
    padding-inline: 16px;
  }

  .fs-tscroll > table { min-width: 520px; }
  .fs-tscroll > .tn-team-table { min-width: 420px; }

  /* The drawer's market table measures ~430px of its own accord; the
     520px floor is for the page tables and here would only buy scroll
     the table does not need. */
  .drawer .fs-tscroll > table { min-width: 0; }

  /* Header labels are 10.5px caps with 0.08em tracking, and the inline
     width: 16% those columns carry leaves ~55px of content box — enough
     to break "PINNACLE" into "PINNACL / E" and stretch every row in the
     table to match. The widths are inline, so !important is what it
     takes to hand the columns back to the content. */
  .fs-tscroll > .td-mkt-table th { width: auto !important; white-space: nowrap; }

  /* Scrollbar is an affordance here, not chrome — keep it drawn. */
  .fs-tscroll::-webkit-scrollbar { height: 6px; }
  .fs-tscroll::-webkit-scrollbar-thumb { background: var(--border); }
}

/* The strip is bled out to the card edge (above), which means a swipe
   drags the table right up against the card's own border — and a table
   sliding under a hard edge reads as the page moving rather than as a
   panel scrolling inside it. Softening whichever edge still has content
   behind it is what makes it read as a window: content dissolves into
   the card instead of hitting it, and the side you have run out of
   stays sharp so the strip says where its ends are.

   tscroll.js writes data-tscroll; a strip that does not overflow is
   marked "none" and takes no mask at all, so a table that fits is never
   faded over content that is all there. With the script missing every
   strip keeps the plain edges it has today. */
.fs-tscroll[data-tscroll="start"] {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent 100%);
}
.fs-tscroll[data-tscroll="middle"] {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
}
.fs-tscroll[data-tscroll="end"] {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 22px, #000 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 22px, #000 100%);
}

@media (max-width: 420px) {
  .td-block, .tn-block { padding-left: 12px; padding-right: 12px; }
  .td-block > .fs-tscroll,
  .tn-block > .fs-tscroll { margin-inline: -12px; padding-inline: 12px; }
}


/* ══ 7. Touch targets ═════════════════════════════════════════════ */

/* Everything below was sized for a mouse. 44px is the floor Apple and
   Google both publish; where the paint has to stay small the hit area
   is grown with a pseudo-element instead of the box. */

/* Width is a proxy; the pointer is the actual condition. A touch tablet
   at 1024px needs these as much as a phone does, and a desktop window
   dragged narrow does not. */
@media (max-width: 900px), (pointer: coarse) {
  .btn-sm { min-height: 40px; }
  .btn { min-height: 44px; }

  .section-tab { min-height: 46px; padding-inline: 18px; }

  /* Inline text links that act as buttons: "See all numbers", "Got it",
     "Mark all read", "Open bankroll →". They stay text; the tap box
     grows around them. */
  .gc-more,
  .how-to-read-x,
  .fs-link,
  .sd-link,
  .sb-legend-more,
  .td-more {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 32px;
  }
  .gc-more::after,
  .how-to-read-x::after,
  .fs-link::after,
  .sd-link::after,
  .td-more::after {
    content: '';
    position: absolute;
    inset: -10px -8px;
  }

  /* 9px wide is not a target. */
  .fs-close {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
  }

  /* Rows in any list that navigates. */
  .sb-nav,
  .user-dropdown-item,
  .bk-row a,
  .tr-row a { min-height: 44px; }

  /* Footer links are set tight for desktop; on a phone they are the only
     way back to Terms, Privacy and 1-800-GAMBLER. The dashboard footer
     runs them on one line separated by middots, so they cannot become
     blocks — vertical padding on an inline box grows the hit area
     without touching line layout, which is what is wanted in both. */
  .lp-footer-col a,
  .lp-footer-bottom a,
  .foot .disc a { padding-block: 9px; }

  /* Row actions on /account are 12px text set as buttons. Same treatment as
     the inline links above. (The /game cross-sell link this also covered went
     with the NRFI callout on 2026-09-07.) */
  .ac-row-edit {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 32px;
  }
  .ac-row-edit::after {
    content: '';
    position: absolute;
    inset: -8px -6px;
  }
}


/* ══ 8. Fluid display type ════════════════════════════════════════ */

/* The broadcast face is set large on purpose. Fixed pixel sizes that
   read as a lower-third at 1440px read as a shout at 360px and wrap
   into four lines. clamp() keeps the desktop size as the ceiling and
   scales down with the viewport instead of snapping at a breakpoint. */

.lp-section-h  { font-size: clamp(26px, 5.5vw, 40px); }
.lp-final-h    { font-size: clamp(28px, 6.5vw, 56px); }
.lp-plan-price .amt { font-size: clamp(38px, 9vw, 56px); }
.hc-nspq-val   { font-size: clamp(32px, 8vw, 44px); }
.fp-headline   { font-size: clamp(27px, 7vw, 44px); }
.fp-prob-val   { font-size: clamp(30px, 8vw, 42px); }
.fc-price      { font-size: clamp(30px, 8vw, 40px); }
.td-nspq-val   { font-size: clamp(46px, 16vw, 84px); }
.td-pick-headline { font-size: clamp(24px, 6.5vw, 40px); }

@media (max-width: 700px) {
  /* .l2 is the second line of the landing headline and is set nowrap so
     the phrase never breaks mid-clause. At 320px that phrase is wider
     than the screen, so below 700px it is allowed to wrap. */
  .lp-h1 { font-size: clamp(34px, 9vw, 92px); }
  .lp-h1 .l2 { white-space: normal; }
}

/* Long unbroken strings — team slugs, market names, URLs in the legal
   pages — break rather than push the column open. */
@media (max-width: 700px) {
  .td-block, .tn-block, .tr-block, .mt-block, .lg-block,
  .gc-context, .td-reasoning, .sb-legend dd {
    overflow-wrap: anywhere;
  }
}


/* ══ 9. Page-specific narrow fixes ════════════════════════════════ */

/* --- /team: matchup panel -------------------------------------- */
/* The panel was an inline `grid-template-columns: 1fr auto` with a
   220px min-width rail, which at 320px measured 640px — the page was
   twice as wide as the screen. Both halves now carry classes so the
   rail can drop under the copy. */
@media (max-width: 760px) {
  .td-matchup-grid { grid-template-columns: 1fr; gap: 18px; }
  /* 1fr still takes its floor from the column's min-content, so both
     halves have to opt out of that as well as out of the rail width. */
  .td-matchup-grid > * { min-width: 0; }
  .td-matchup-side { min-width: 0; }
}

/* --- /today, /game: pick header -------------------------------- */
@media (max-width: 700px) {
  .td-pick-row { flex-wrap: wrap; row-gap: 8px; }
  .td-actions { flex-wrap: wrap; }
  .td-actions .btn { flex: 1 1 auto; }
}

/* --- /picks: pick rows ----------------------------------------- */
/* picks.html lays each row out inline as `140px 1fr auto` with 16px
   gaps and 18px of row padding inside a 28px page gutter. At 360px that
   is 266px of content, of which the matchup column and the 80px edge
   take 252 — the market label and its tier/kickoff line were sharing
   14px and rendering one word per line, ~550px a card. Below phone
   width the matchup sits above the market and the edge keeps the right
   rail across both lines. */
@media (max-width: 700px) {
  .mp-wrap { padding-left: 18px; padding-right: 18px; }
  .mp-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "teams edge"
      "mkt   edge";
    gap: 4px 12px;
    padding: 12px 14px;
  }
  .mp-teams { grid-area: teams; }
  .mp-mkt { grid-area: mkt; min-width: 0; }
  .mp-edge { grid-area: edge; }
  /* The tier/kickoff line is inline with an 8px lead-in so it can trail
     the market label on desktop. Here it takes its own line: "Gold Zone,
     Sun 1:00p ET" never fits beside "FG Total Under" in ~180px anyway,
     and a wrap that starts mid-string reads as broken. */
  .mp-mkt .meta { display: block; margin-left: 0; margin-top: 2px; }
}

/* --- /trends: biggest edges ------------------------------------ */
/* trends.css already drops the pick and bar columns at 900px, leaving
   `24px 90px 1fr 80px` with 14px gaps: 236px of fixed track inside a
   row that has 264px of content at 360px. The matchup got 28px and set
   "ATL / @ / PIT" one token per line, the kickoff under it doing the
   same. Tier moves under the matchup and the value column sizes to its
   number, which hands the game column the width back. */
@media (max-width: 700px) {
  .tn-edge-row {
    grid-template-columns: 24px minmax(0, 1fr) auto;
    grid-template-areas:
      "rank game val"
      "rank tier val";
    gap: 2px 12px;
    padding: 10px 12px;
  }
  .tn-edge-rank { grid-area: rank; }
  .tn-edge-game { grid-area: game; min-width: 0; }
  .tn-edge-tier { grid-area: tier; margin-top: 2px; }
  .tn-edge-val { grid-area: val; }
  /* §8 lets .tn-block break anywhere so a slug cannot push a column
     open. With real width the kickoff should break at its spaces, not
     inside "1:00p". */
  .tn-edge-game { overflow-wrap: normal; }
}

/* --- landing / methodology closing CTA -------------------------- */
@media (max-width: 700px) {
  /* .btn is white-space: nowrap so a two-word label never splits across
     lines. "Read this week's free pick" measures 292px, which does not
     fit a 320px phone at all — and as the min-content of a flex item it
     drags the whole section past the viewport rather than clipping. */
  .btn { white-space: normal; }
  .lp-final,
  .lp-final-card,
  .lp-hero > * { min-width: 0; }
}

@media (max-width: 420px) {
  /* 22px of card padding either side inside a 20px page gutter leaves
     236px for content that needs 257px. Give some of both back. */
  .lp-hero { padding-left: 14px; padding-right: 14px; }
  .lp-hero-card { padding: 16px 14px 14px; }
  .lp-final { padding-left: 14px; padding-right: 14px; }
  .lp-final-card { padding: 32px 16px; }
}

/* --- alerts drawer --------------------------------------------- */
@media (max-width: 480px) {
  /* 380px of drawer on a 360px screen leaves no backdrop to tap out on
     and clips the close button off the edge. */
  .fs-drawer { width: min(100vw - 32px, 380px); }
}

/* ══ 10. Landscape on a short screen ══════════════════════════════ */

/* A phone turned sideways is ~360px tall. A 56px sticky bar plus a
   72px hero eyebrow leaves nothing for content, and the mobile sheet's
   52px rows run off the bottom. */
@media (max-height: 480px) and (orientation: landscape) {
  :root { --hdr: 46px; }
  .nav { min-height: 46px; }
  .nav-burger { width: 40px; height: 40px; }
  .nav-mobile .nav-link,
  .nav-mobile-link { min-height: 42px; font-size: 17px; }
  .lp-hero { padding-top: 28px; padding-bottom: 24px; }
  .sidebar { position: static; max-height: none; }
}


/* ══ 11. Pointer-coarse affordances ═══════════════════════════════ */

/* Hover states never fire on a touch screen, so anything whose only
   affordance is :hover is invisible there. These carry a persistent
   resting state instead. */
@media (hover: none) {
  .gc-more,
  .td-more,
  .sd-link,
  .sb-legend-more { text-decoration: underline; text-underline-offset: 3px; }

  /* :hover styles that latch after a tap on touch — the element keeps
     the hover paint until you tap elsewhere. Scope them out. */
  .nav-link:hover,
  .sb-nav:hover,
  .nav-burger:hover { background: transparent; }
  .sb-nav.active:hover { background: var(--surface); }
}


/* ══ 12. The game drawer ══════════════════════════════════════════ */

/* The drawer is a fixed panel the full width of a phone, so anything
   inside it that overruns scrolls the panel itself — and a panel that
   IS the viewport sliding sideways is indistinguishable from the page
   coming apart. styles.css now pins overflow-x: hidden on it; what is
   left is making the two things that overran fit. */

@media (max-width: 760px) {
  /* 22px team names plus "Open in full ↗" and the close button measure
     ~415px against a 375px screen, and .drawer-head is a two-item flex
     row where neither item was allowed to shrink. */
  .drawer-head { padding: 12px 16px; gap: 10px; align-items: flex-start; }
  .dr-header-teams { font-size: 17px; gap: 8px; flex-wrap: wrap; }
  .dr-header-side { gap: 8px; }
  .dr-header-meta { font-size: 12px; line-height: 1.45; }
  .dr-head-actions { gap: 6px; }

  /* The drawer already fills the screen here, so "open in full" is a
     permalink rather than a bigger view and the label is describing a
     difference the reader cannot see. Dropping it to the arrow alone,
     sized to match the close button, is also what stops it reading as
     a button floating beside a control instead of one of a pair. */
  .dr-head-full-label { display: none; }
  .dr-head-full-icon { display: inline; }
  /* Both at 40px — the floor §7 already gives .btn-sm on a touch
     screen, and the size the close button was missing. Matching boxes
     are also what makes them read as a pair. */
  .dr-head-full,
  .drawer-close {
    flex: none;
    width: 40px; height: 40px; min-height: 40px;
    padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
  }

  /* One line per row. Left to wrap, the name column breaks "Who wins
     the game" over four lines and nearly doubles the height of the
     strip; the table is scrolling sideways either way, so let it be
     wide and short rather than narrow and tall. */
  .drawer .mkt-table th,
  .drawer .mkt-table .mkt-name { white-space: nowrap; }

  .drawer-body { padding: 16px; }
  /* A column flex item stretches to the line, but its automatic minimum
     size is still the min-content width of what it holds — which reads
     straight through a scroll box to the table inside it. */
  .drawer-body > * { min-width: 0; }
}
