/*
 * The app shell.
 *
 * Two shapes, one markup tree:
 *
 *   Phone / PWA (< 56rem)   Laptop (>= 56rem)
 *   ┌──────────────┐        ┌────────┬──────────────┐
 *   │   masthead   │ fixed  │        │   masthead   │ sticky
 *   ├──────────────┤        │  side  ├──────────────┤
 *   │     body     │ scroll │  nav   │     body     │ scrolls with page
 *   ├──────────────┤        │        ├──────────────┤
 *   │     cta      │ pinned │        │  cta inline  │
 *   └──────────────┘        └────────┴──────────────┘
 *
 * The phone case is a real app shell — only the middle scrolls — because a
 * pinned primary action is the point of the design: the thing you owe the game
 * this week is always under your thumb. That needs dvh (not vh) so the bar
 * doesn't hide behind Safari's collapsing chrome, and safe-area insets so it
 * clears the home indicator when installed to the home screen.
 *
 * Requires `viewport-fit=cover` on the viewport meta or env() resolves to 0.
 */

@layer layout {
  .shell {
    display: grid;
    grid-template-columns: 1fr;
    min-block-size: 100svh;
    min-block-size: 100dvh;
  }

  /* ── Screen ──────────────────────────────────────────────────────────────── */
  .screen {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    /* Exactly the viewport: the body scrolls, the frame does not. */
    block-size: 100svh;
    block-size: 100dvh;
    overflow: hidden;
    background: var(--bg);
    color: var(--fg);
  }

  .screen__masthead {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-6);
    padding-block-start: calc(var(--space-3) + env(safe-area-inset-top));
    padding-inline-start: calc(var(--space-6) + env(safe-area-inset-left));
    padding-inline-end: calc(var(--space-6) + env(safe-area-inset-right));
    border-block-end: var(--hairline) solid var(--fg);
    background: var(--bg);
  }

  .screen__masthead > :first-child {
    justify-self: start;
  }

  .screen__masthead > :last-child {
    justify-self: end;
  }

  .screen__mark {
    grid-column: 2;
    justify-self: center;
    font-family: var(--font-serif);
    font-size: var(--text-2xl);
    line-height: 1;
    text-transform: lowercase;
    color: var(--fg);
  }

  .screen__body {
    overflow-y: auto;
    /* Stop a scroll at the end of the list from pulling the whole PWA. */
    overscroll-behavior: contain;
    padding: var(--space-5) var(--space-6) var(--space-3);
    padding-inline-start: calc(var(--space-6) + env(safe-area-inset-left));
    padding-inline-end: calc(var(--space-6) + env(safe-area-inset-right));
  }

  /* The scrollbar is chrome the design does not want, but the region must stay
     scrollable by keyboard and assistive tech — so hide the bar, not the
     overflow. */
  .screen__body {
    scrollbar-width: none;
  }

  .screen__body::-webkit-scrollbar {
    inline-size: 0;
  }

  .screen__cta {
    padding: var(--space-4) var(--space-6) var(--space-6);
    padding-block-end: calc(var(--space-6) + env(safe-area-inset-bottom));
    padding-inline-start: calc(var(--space-6) + env(safe-area-inset-left));
    padding-inline-end: calc(var(--space-6) + env(safe-area-inset-right));
    border-block-start: var(--hairline) solid var(--line);
    background: var(--bg);
  }

  /* A screen with no primary action collapses the bar rather than leaving a
     hairline floating above nothing. */
  .screen__cta:empty {
    display: none;
  }

  /* On most screens the CTA bar is what gives the last element room to breathe.
     Screens without one (settings, rules) had their final control sitting flush
     against the bottom edge, so the body carries that space itself. */
  .screen:not(:has(.screen__cta)) .screen__body {
    padding-block-end: calc(var(--space-8) + env(safe-area-inset-bottom));
  }

  /* Notices consume space inside the phone viewport, not above a second full
     viewport. Otherwise a sign-in error or Spotify banner hides the pinned CTA. */
  @media (width < 56rem) {
    .shell {
      block-size: 100svh;
      block-size: 100dvh;
    }

    .shell__main,
    .public-layout > main:has(> .screen) {
      display: flex;
      flex-direction: column;
      min-block-size: 0;
      block-size: 100svh;
      block-size: 100dvh;
      overflow: hidden;
    }

    .shell__main > :not(.screen),
    .public-layout > main:has(> .screen) > :not(.screen) {
      flex-shrink: 0;
    }

    .shell__main > .screen,
    .public-layout > main > .screen {
      flex: 1;
      min-block-size: 0;
      block-size: auto;
    }

    /* A notice above the screen already carries the top safe area. */
    :is(.flash, .banner, .impersonation) ~ .screen .screen__masthead {
      padding-block-start: var(--space-3);
    }
  }

  /* ── Sidebar ─────────────────────────────────────────────────────────────── */
  /* Hidden on phones, where the group switcher in the masthead does this job. */
  .shell__nav {
    display: none;
  }

  /* ── Laptop ──────────────────────────────────────────────────────────────── */
  @media (min-width: 56rem) {
    .shell {
      grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
      block-size: 100dvh;
      overflow: hidden;
    }

    .shell__nav {
      display: flex;
      flex-direction: column;
      gap: var(--space-2);
      overflow-y: auto;
      padding: var(--space-7) var(--space-6) var(--space-5);
      background: var(--sidebar-bg);
      color: var(--fg);
      border-inline-end: var(--hairline) solid var(--line);
    }

    /* The screen stops being a fixed frame and becomes an ordinary page: the
       masthead sticks, the CTA rejoins the flow, the main column scrolls. */
    .shell__main {
      overflow-y: auto;
      background: var(--bg);
    }

    .screen {
      display: block;
      block-size: auto;
      min-block-size: 100%;
      overflow: visible;
    }

    /* Public/auth pages have no height-constrained shell parent, so 100% cannot
       fill the viewport. Keep their theme covering the canvas below short forms. */
    .public-layout .screen {
      min-block-size: 100svh;
      min-block-size: 100dvh;
    }

    .screen__masthead,
    .screen__body,
    .screen__cta {
      inline-size: 100%;
      max-inline-size: var(--reading-width);
      margin-inline: auto;
    }

    .screen__masthead {
      position: sticky;
      inset-block-start: 0;
      z-index: var(--z-sticky);
      padding: var(--space-6) var(--space-6) var(--space-5);
    }

    .screen__body {
      overflow: visible;
      padding: 1.875rem var(--space-6) 0;
    }

    .screen__cta {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--space-3) var(--space-7);
      padding: var(--space-6) var(--space-8) var(--space-9);
      border-block-start: 0;
      background: transparent;
    }

    /* Drop and vote actions are deadlines, not footers. Keep them visible on
       laptops just as the phone shell does instead of making players discover
       them after the roster at the bottom of the page. */
    .screen--desktop-action-pinned .screen__body {
      padding-block-end: 8rem;
    }

    .screen--desktop-action-pinned .screen__cta {
      position: fixed;
      inset-block-end: 0;
      inset-inline-start: calc(50% + var(--sidebar-width) / 2);
      z-index: var(--z-sticky);
      /* A compact floating action, not another card-width bar. */
      inline-size: min(26rem, calc(100vw - var(--sidebar-width) - 2 * var(--space-6)));
      max-inline-size: none;
      margin-inline: 0;
      translate: -50% 0;
      padding: var(--space-3);
      border: var(--hairline) solid var(--line);
      background: var(--bg);
    }
  }

  /* ── Masthead sub-parts ──────────────────────────────────────────────────── */
  /* Back button, account chip and flon switcher sit on one line, so they share
     --masthead-control as their visible height. The 44px touch target is added
     by ::after rather than by growing the box, which is what made the back
     button read as twice the weight of the switcher beside it. */
  .masthead-back {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-inline-size: var(--masthead-control);
    block-size: var(--masthead-control);
    padding-inline: var(--space-3);
    border: var(--hairline) solid var(--fg);
    color: var(--fg);
    font-family: var(--font-mono);
    font-size: var(--text-md);
    font-weight: 700;
    line-height: 1;
  }

  /* Invisible hit area, centred on the control. */
  .masthead-back::after,
  .masthead-account::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-start: 50%;
    translate: 0 -50%;
    block-size: var(--tap-target);
  }

  .masthead-back:hover {
    background: var(--fg);
    color: var(--bg);
  }

  .masthead-back__label {
    font-size: var(--text-3xs);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    max-inline-size: 7.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .masthead-label {
    font-family: var(--font-mono);
    font-size: var(--text-3xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--mut);
    white-space: nowrap;
  }

  .masthead-account {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: var(--masthead-control);
    block-size: var(--masthead-control);
    padding-inline: var(--space-2);
    border: var(--hairline) solid var(--fg);
    background: var(--fg);
    color: var(--bg);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    font-weight: 600;
  }
}
