/* 01-launch.css
   launch curves, controls, leaderboard, mobile header

   Split out of styles.css. The numeric prefix is load-bearing: the server
   loads styles.css first, then styles/*.css alphabetically, and the cascade
   here is the original file's order. Renaming these out of sequence changes
   which rule wins.

   A few blocks are filed by position rather than by subject — the mobile
   header sits inside launch, a shared chart rule inside game stats — because
   moving them would reorder the cascade. Worth relocating one at a time with
   a visual check, not in bulk.
   ======================================================================== */

/* ===========================================================================
   Launch curves
   ======================================================================== */

.launch-panel {
  margin-bottom: 20px;
}

.launch-panel .panel__body {
  padding-top: 2px;
}

.launch-controls {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 16px;
}

.launch-controls__note {
  font-size: 12px;
  color: var(--ink-faint);
}

.launch-controls__label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--ink-soft);
}

.launch-controls__select {
  appearance: auto;
  min-width: 150px;
  height: 30px;
  padding: 0 8px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}

.launch-series {
  stroke-width: 1.65;
  opacity: 0.72;
  transition:
    opacity 120ms ease,
    stroke-width 120ms ease;
}

.launch-series:hover {
  opacity: 1;
  stroke-width: 3;
}

.launch-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 7px 14px;
  max-height: 92px;
  overflow: auto;
  padding: 6px 16px 2px 56px;
  border-top: 1px solid var(--line);
}

.launch-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 190px;
  color: var(--ink-soft);
  font-size: 11px;
}

.launch-legend__item > i {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
}

.launch-legend__item > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 760px) {
  .launch-controls__note {
    display: none;
  }

  .launch-controls {
    gap: 8px;
  }

  .launch-controls__select {
    min-width: 125px;
  }

  .launch-legend {
    padding-left: 14px;
  }
}


/* ===========================================================================
   Launch curve controls
   ======================================================================== */

.launch-controls {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 14px;
  margin-left: auto;
}

.launch-control {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.launch-control__label {
  color: var(--ink-faint);
  font-size: 10px;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: .045em;
}

.launch-range {
  width: 245px;
}

.launch-range__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 5px;
}

.launch-range__value {
  color: var(--ink-soft);
  font-size: 11px;
  font-weight: 500;
}

.launch-range__bottom {
  display: flex;
  align-items: center;
  gap: 9px;
}

.launch-range__slider {
  width: 115px;
  accent-color: var(--accent);
  cursor: pointer;
}

.launch-range__presets {
  display: inline-flex;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
}

.launch-range__preset {
  min-width: 33px;
  height: 27px;
  padding: 0 7px;
  border: 0;
  border-right: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink-faint);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}

.launch-range__preset:last-child {
  border-right: 0;
}

.launch-range__preset:hover {
  color: var(--ink);
  background: var(--surface-hover);
}

.launch-range__preset.is-active {
  color: var(--accent);
  background: var(--accent-soft);
}

.launch-game-control {
  position: relative;
}

.launch-game-button {
  height: 31px;
  min-width: 132px;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 10px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink-soft);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.launch-game-button:hover,
.launch-game-button[aria-expanded="true"] {
  border-color: var(--ink-faint);
  color: var(--ink);
}

.launch-game-button b {
  color: var(--accent);
  font-size: 11px;
  font-weight: 500;
}

.launch-game-button__chevron {
  color: var(--ink-faint);
}

.launch-game-menu {
  position: absolute;
  top: calc(100% + 7px);
  right: 0;
  z-index: 30;
  width: 330px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 9px;
  background: var(--surface);
  box-shadow: 0 14px 36px rgba(0, 0, 0, .28);
}

.launch-game-menu[hidden] {
  display: none;
}

.launch-game-menu__head {
  display: flex;
  gap: 7px;
  padding: 9px;
  border-bottom: 1px solid var(--line);
}

.launch-game-search {
  min-width: 0;
  flex: 1;
  height: 30px;
  padding: 0 9px;
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  outline: 0;
  background: var(--surface-sunk);
  color: var(--ink);
  font: inherit;
  font-size: 12px;
}

.launch-game-search:focus {
  border-color: var(--accent);
}

.launch-game-actions {
  display: flex;
  gap: 4px;
}

.launch-game-actions button {
  height: 30px;
  padding: 0 8px;
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}

.launch-game-actions button:hover {
  color: var(--ink);
  background: var(--surface-hover);
}

.launch-game-list {
  max-height: 320px;
  overflow-y: auto;
  padding: 5px;
}

.launch-game-option {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 34px;
  padding: 5px 7px;
  border-radius: 5px;
  color: var(--ink-soft);
  font-size: 12px;
  cursor: pointer;
}

.launch-game-option:hover {
  background: var(--surface-hover);
  color: var(--ink);
}

.launch-game-option input {
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: var(--accent);
}

.launch-game-option span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.launch-game-empty,
.launch-empty {
  padding: 28px;
  color: var(--ink-faint);
  font-size: 12px;
  text-align: center;
}

@media (max-width: 900px) {
  .launch-controls {
    width: 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
    margin: 10px 0 0;
  }

  .launch-range {
    width: 100%;
  }

  .launch-range__slider {
    flex: 1;
  }

  .launch-game-menu {
    right: auto;
    left: 0;
    width: min(330px, calc(100vw - 40px));
  }
}


/* ===========================================================================
   Launch leaderboard
   ======================================================================== */

.launch-leaderboard-panel {
  margin-top: 16px;
}

.launch-leaderboard-panel .panel__body {
  padding: 0;
}

.launch-leaderboard-scroll {
  width: 100%;
  overflow-x: auto;
}

.launch-leaderboard {
  width: 100%;
  min-width: 760px;
  border-collapse: collapse;
  font-size: 12px;
}

.launch-leaderboard th {
  height: 38px;
  padding: 0 12px;
  border-bottom: 1px solid var(--line-strong);
  color: var(--ink-faint);
  font-size: 10px;
  font-weight: 500;
  text-align: right;
  text-transform: uppercase;
  letter-spacing: .045em;
  white-space: nowrap;
}

.launch-leaderboard th:nth-child(1),
.launch-leaderboard th:nth-child(2) {
  text-align: left;
}

.launch-leaderboard td {
  height: 45px;
  padding: 0 12px;
  border-bottom: 1px solid var(--line);
  color: var(--ink-soft);
  text-align: right;
  white-space: nowrap;
}

.launch-leaderboard td:first-child,
.launch-leaderboard td:nth-child(2) {
  text-align: left;
}

.launch-leaderboard tbody tr {
  cursor: pointer;
  outline: none;
  transition:
    background 120ms ease,
    opacity 120ms ease;
}

.launch-leaderboard tbody tr:hover {
  background: var(--surface-hover);
}

.launch-leaderboard tbody tr:focus-visible {
  box-shadow: inset 3px 0 0 var(--accent);
}

.launch-leaderboard tbody tr.is-selected {
  background: color-mix(
    in srgb,
    var(--accent) 5%,
    transparent
  );
}

.launch-leaderboard tbody tr:not(.is-selected) {
  opacity: .58;
}

.launch-leaderboard tbody tr:not(.is-selected):hover {
  opacity: .85;
}

.launch-rank-cell {
  width: 78px;
}

.launch-rank-cell small {
  margin-left: 6px;
  color: var(--ink-faint);
  font-size: 10px;
}

.launch-rank {
  display: inline-flex;
  min-width: 30px;
  height: 23px;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--surface-sunk);
  color: var(--ink-soft);
  font-size: 11px;
  font-weight: 600;
}

.launch-rank--1 {
  color: var(--accent);
  background: var(--accent-soft);
}

.launch-game-cell {
  min-width: 210px;
  max-width: 270px;
  color: var(--ink) !important;
  font-weight: 500;
}

.launch-game-cell span {
  display: inline-block;
  max-width: 230px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}

.launch-game-state {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 8px;
  border: 1px solid var(--ink-faint);
  border-radius: 50%;
  vertical-align: middle;
}

.is-selected .launch-game-state {
  border-color: var(--accent);
  background: var(--accent);
}

.launch-current-cell strong {
  color: var(--ink);
  font-weight: 600;
}

.launch-current-cell small {
  display: block;
  margin-top: 2px;
  color: var(--ink-faint);
  font-size: 9px;
  font-weight: 400;
}

.launch-median-delta {
  font-size: 11px;
  font-weight: 500;
}

.launch-median-delta.is-up {
  color: var(--positive);
}

.launch-median-delta.is-down {
  color: var(--negative);
}

.launch-leaderboard .is-muted {
  color: var(--ink-faint);
}

@media (prefers-reduced-motion: reduce) {
  .launch-series,
  .launch-leaderboard tbody tr {
    transition: none !important;
    animation: none !important;
  }
}



/* Prevent layout shift while Launch chart redraws */

.launch-panel .panel__body {
  min-height: 500px;
}

.launch-panel .chart {
  display: block;
}

.launch-panel .launch-empty {
  min-height: 450px;
  display: flex;
  align-items: center;
  justify-content: center;
}


/* Clickable launch-age links in leaderboard */

.launch-day-link {
  display: inline;
  margin-left: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink-faint);
  font: inherit;
  font-size: 10px;
  cursor: pointer;
  text-decoration: none;
}

.launch-day-link:hover {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.launch-day-link:focus-visible {
  color: var(--accent);
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

.launch-current-cell .launch-day-link {
  display: block;
  margin: 2px 0 0;
}



/* MOBILE HEADER V2 */

@media (max-width: 760px) {

  /* ---------------------------------------------------------
     Main shell
     --------------------------------------------------------- */

  .shell {
    display: block;
    min-width: 0;
  }

  .main {
    width: 100%;
    min-width: 0;
  }

  /* ---------------------------------------------------------
     Mobile navigation
     --------------------------------------------------------- */

  .rail {
    position: sticky;
    top: 0;
    z-index: 50;

    display: grid;
    /* One row now. The page list is a drawer (below), so the header carries
       the menu button, the wordmark, the app switcher and the account row —
       and nothing scrolls sideways. Its own sheet (00-app-nav.css) styles the
       switcher tiles; this only places the block. */
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "menu brand apps foot";

    width: 100%;
    height: auto;

    background: transparent;

    border-right: 0;
    border-bottom: 1px solid var(--line);

    padding-top: env(safe-area-inset-top);
  }

  /* The translucent blur lives on a pseudo-element, not on `.rail` itself.
     `backdrop-filter` makes an element the containing block for its
     `position: fixed` descendants — so with it on the rail, the drawer below
     was positioned against a 46px-tall header instead of the viewport and came
     out 45px high, off to the left, ignoring `left: 0`. The effect is
     identical; it just no longer traps what is inside it. */
  .rail::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;

    background: color-mix(in srgb, var(--surface) 94%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }

  .apps {
    grid-area: apps;
    align-self: center;
    padding: 4px 2px;
    border: 0;
  }

  .rail__brand {
    grid-area: brand;

    min-width: 0;

    padding: 9px 14px 7px;

    display: flex;
    align-items: baseline;
    gap: 7px;
  }

  .rail__mark {
    flex: 0 0 auto;
    font-size: 15px;
  }

  .rail__model {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    font-size: 10.5px;
  }

  .rail__foot {
    grid-area: foot;

    border: 0;
    padding: 7px 14px 6px 8px;

    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 7px;
  }

  .rail__who {
    display: none;
  }

  .rail__foot .linkish {
    white-space: nowrap;
    font-size: 11px;
  }

  /* ---------------------------------------------------------
     The drawer
     --------------------------------------------------------- */

  .rail__menu {
    grid-area: menu;
    display: flex;
    align-items: center;
    justify-content: center;

    width: 38px;
    min-height: 38px;
    margin-left: 6px;

    border: 0;
    border-radius: 9px;
    background: none;
    color: var(--ink-soft);
    cursor: pointer;
  }

  .rail__menu svg {
    width: 20px;
    height: 20px;
  }

  .rail__menu[aria-expanded='true'] {
    background: var(--surface-2, rgba(127, 127, 127, 0.16));
    color: var(--ink);
  }

  /* Fixed, so it covers the dashboard rather than pushing it, and full height
     so a long page list scrolls inside the drawer instead of the page. Off to
     the left until opened — `transform` rather than `left`, so it composites
     and does not relayout the shell behind it every frame. */
  .rail__nav {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 60;

    width: min(78vw, 300px);
    max-width: 100%;

    padding: calc(env(safe-area-inset-top) + 12px) 12px
             calc(env(safe-area-inset-bottom) + 16px);

    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;

    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;

    background: var(--surface);
    border-right: 1px solid var(--line);

    transform: translateX(-100%);

    /* `visibility` rather than `display`, and delayed by the length of the
       slide: a drawer that is `display: none` cannot animate out, and one that
       is merely translated off-screen is still in the tab order — you would
       tab from the header straight into twelve invisible links. Hiding after
       the transition gets both. */
    visibility: hidden;
    transition: transform 0.22s var(--ease, ease), visibility 0s linear 0.22s;
  }

  body.rail-menu-open .rail__nav {
    transform: none;
    visibility: visible;
    transition: transform 0.22s var(--ease, ease), visibility 0s;
  }

  /* Not toggled with the `hidden` attribute: `display: none` cannot fade, and
     the scrim appearing instantly under a drawer that slides looks like two
     unrelated things happening. `pointer-events` is what actually makes it
     inert when closed. */
  /* Below the rail, not above it. The drawer lives *inside* `.rail`, and
     `.rail` has `z-index: 50` — a stacking context — so nothing inside it can
     paint above a sibling stacked higher, however large its own z-index. At 55
     the scrim covered the drawer it was supposed to sit behind. */
  .rail__scrim {
    /* styles.css hides both the button and the scrim outright, so mobile has
       to put this one back — the button gets its `display: flex` above. */
    display: block;

    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, 0.45);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s var(--ease, ease);
  }

  body.rail-menu-open .rail__scrim {
    opacity: 1;
    pointer-events: auto;
  }

  /* Asked not to animate: appear and disappear, still usable. */
  @media (prefers-reduced-motion: reduce) {
    .rail__nav,
    body.rail-menu-open .rail__nav,
    .rail__scrim {
      transition: none;
    }
  }

  /* The drawer scrolls; the dashboard behind it must not. */
  body.rail-menu-open {
    overflow: hidden;
  }

  /* The headings come back. They were hidden on the strip because a heading
     cannot divide a horizontal list; a vertical drawer is exactly where they
     earn their place, and it is the same grouping people know from desktop. */
  .rail__section {
    display: flex;
  }

  .rail__group,
  .rail__group[hidden] {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .rail__group[hidden] {
    display: none;
  }

  .rail__link {
    width: 100%;
    min-height: 40px;
    padding: 9px 10px;
    gap: 10px;
    border-radius: 8px;
    font-size: 13px;
  }

  .rail__link svg {
    width: 16px;
    height: 16px;
  }

  /* ---------------------------------------------------------
     Page header
     --------------------------------------------------------- */

  /* Sticks under the rail rather than scrolling away with the page. The date
     range and the data-mode switch are what a phone reader reaches for most
     and the hardest things to get back to once gone — a phone shows a couple
     of panels at a time, so the filters were always several flicks behind
     wherever you were reading.

     `--rail-height` is measured and published by `ui/header-offset.js`; the
     fallback is only for the frame before that first runs. It cannot be a
     constant because the rail grows by the safe-area inset on a notched
     phone.

     z-index below the rail's 50 so the drawer and its scrim still cover this,
     and above the page so content scrolls under it rather than through it. */
  .topbar {
    position: relative;
    top: auto;
    z-index: 10;

    padding: 12px 14px;

    display: flex;
    flex-direction: column;
    align-items: stretch;

    gap: 10px;
  }

  .topbar > div:first-child {
    width: 100%;
    min-width: 0;
  }

  /* Only where the screen can spare it. The rail and the header together come
     to about 165px: a fifth of a portrait phone, which is a fair price for
     keeping the range and the data-mode switch reachable, and 42% of a
     landscape one, which is not — that leaves barely two rows of a table
     visible. Portrait phones start around 667px tall and landscape ones top
     out around 430, so the threshold sits in the gap rather than on a device. */
  @media (min-height: 500px) {
    /* Stuck by minus its own lead, so the title and the date line ride up
       under the rail and only the filter row comes to rest. A phone shows a
       couple of panels at a time and the header is the third of them; the
       title says which page you are on, which you know, while the range and
       the data-mode switch are what you reach for. Keeping the label costs a
       panel of reading for nothing.

       `--topbar-lead` is measured and published by `ui/header-offset.js`
       alongside `--rail-height`. With a 0 fallback the header simply sticks
       whole, which is where this started — the worst case is the old
       behaviour, not a broken one. What rides up is covered by the rail
       rather than clipped: the rail is opaque enough at 94% and sits two
       stacking levels above. */
    .topbar {
      position: sticky;
      top: calc(var(--rail-height, 46px) - var(--topbar-lead, 0px));
      z-index: 30;
    }
  }

  .topbar__title {
    font-size: 18px;
    line-height: 1.15;
  }

  .topbar__meta {
    max-width: 100%;

    margin-top: 3px;

    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    font-size: 11px;
  }

  /* ---------------------------------------------------------
     Wide tables
     --------------------------------------------------------- */

  /* No `max-height` here, and that is the whole fix for sideways scrolling.

     With one, the wrap scrolls in both axes — 2,300px of rows and 1,700px of
     columns inside a 620px box — and a touch drag locks to whichever axis it
     started in. On a phone that is almost always the vertical one, so the
     columns to the right were unreachable, and the table trapped the page
     scroll as well: a finger inside it could not move the page.

     Without it the wrap is as tall as its rows, so there is nothing to scroll
     vertically and the page does that instead. The wrap is left scrolling only
     sideways, which is unambiguous — any horizontal drag pans the columns.
     Nothing is hidden either way; every column is there to be scrolled to.

     Lazy row loading used to hang off this element's vertical scroll and now
     uses an observer, because that scroll no longer happens here. */
  .table-wrap {
    max-height: none;
  }

  /* Something has to say the table continues past the right edge: iOS shows no
     scrollbar until you are already scrolling, which is too late to be a hint.
     A fade over the right edge, removed once the last column is in view.
     `table.js` sets `is-cut-off`, because whether it overflows depends on the
     column set the reader has chosen, not on the breakpoint. */
  .table-wrap {
    position: relative;
  }

  .table-wrap.is-cut-off::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 24px;
    height: 100%;
    background: linear-gradient(to right, transparent, var(--surface));
    pointer-events: none;
  }

  /* ---------------------------------------------------------
     One column at a time

     Free sideways scrolling on a phone leaves you reading a figure with half
     its neighbour beside it and the header of neither fully in view. These
     tables are a name and then a run of interchangeable money columns, so the
     only question a sideways drag ever asks is "and what is the next one" —
     which is a step, not a distance.

     So the columns are re-sized to exactly one per screenful beside the frozen
     name, and the scroller snaps to them. `mandatory` because there is no
     halfway worth resting at, and `scroll-snap-stop: always` so a hard flick
     advances one column rather than skidding past four — the whole point is
     that you can get to the next one and know you got there.

     `--snap-lead` is the frozen column's width, published by `table.js` where
     the width is decided. As `scroll-padding-left` it moves every snap
     position out from under the frozen name, which is pinned over the left of
     the scroller and would otherwise cover the column just snapped into view.

     Only `x`. The wrap has no `max-height` here, so the page owns the vertical
     scrolling and it stays free — snapping rows would fight every read.
     --------------------------------------------------------- */
  .table-wrap.is-snapping {
    scroll-snap-type: x mandatory;
    scroll-padding-left: var(--snap-lead, 0px);
  }

  /* Narrower than the free-scrolling fade, and exactly the cell's own right
     padding. A column that ends at the screen edge puts its last digit 12px
     in, and the 24px fade was landing on it — a greyed-out final digit on
     every figure in the table, which is a worse misreading than no hint at
     all. At 12px the fade covers the gutter and stops where the number
     starts. It is still needed, and more than before: with one column filling
     the screen there is no sliver of the next one showing to say there is
     one. */
  .table-wrap.is-snapping.is-cut-off::after {
    width: 12px;
  }

  .table-wrap.is-snapping table.data th[data-key]:not(.is-frozen),
  .table-wrap.is-snapping table.data td[data-key]:not(.is-frozen) {
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }

  /* The disclosure panel spans every column, so at one column per screen it is
     a dozen screens wide and all but the first of them empty. Its content is
     pinned to the left of the scroller instead — the row it belongs to is
     open, and the panel stays where it was opened however far the columns are
     scrolled. Width comes from the wrap, via the same measurement that sized
     the columns. */
  .table-wrap.is-snapping table.data tr.is-detail > td > * {
    position: sticky;
    left: 0;
    width: var(--snap-view, 100%);
    max-width: var(--snap-view, 100%);
  }

  /* ---------------------------------------------------------
     Date controls
     --------------------------------------------------------- */

  .filters {
    width: 100%;
    min-width: 0;

    display: flex;
    align-items: center;
    gap: 7px;
  }

  .range {
    flex: 1 1 auto;
    min-width: 0;

    display: flex;
  }

  /* `auto` rather than `0`: equal thirds clipped "Today" against its
     neighbour once there were five presets, and the abbreviations beside it
     need nothing like the same room. */
  .range > button {
    flex: 1 1 auto;

    min-width: 0;

    padding: 7px 3px;

    font-size: 11px;

    white-space: nowrap;
  }

  .range__long {
    display: none;
  }

  .range__short {
    display: inline;
  }

  /* The calendar segment keeps its glyph's width while the presets share what
     is left — it has no label to shrink. */
  .date-picker {
    flex: 0 0 auto;
  }

  .date-picker__toggle {
    padding: 7px 7px;
  }

  .date-picker__pop {
    max-width: calc(100vw - 20px);
  }

  /* Icon-only refresh on mobile */
  .filters > .btn {
    flex: 0 0 34px;

    width: 34px;
    height: 32px;

    padding: 0;

    justify-content: center;

    font-size: 0;
  }

  .filters > .btn svg {
    width: 15px;
    height: 15px;
  }

  /* ---------------------------------------------------------
     Content
     --------------------------------------------------------- */

  .content {
    width: 100%;
    min-width: 0;

    padding: 14px 12px 40px;
  }

}


/* Very narrow phones */

@media (max-width: 370px) {

  .rail__model {
    display: none;
  }

  .rail__link {
    padding-left: 9px;
    padding-right: 9px;
  }

  /* Five presets, a two-state mode toggle and two icon buttons cannot share a
     320px row without clipping the labels — the mode toggle alone wants a
     third of it. A second row costs one button's height and keeps every
     label readable. */
  .filters {
    flex-wrap: wrap;
  }

  .data-mode {
    flex: 1 1 100%;
  }

  .range > button {
    font-size: 10.5px;
    padding-left: 2px;
    padding-right: 2px;
  }


}
