@layer components {
  /* A flow that temporarily becomes the whole product surface. The property
     wizard owns its own header, navigation and action bar, so putting it inside
     the account shell would leave two competing ways out and two navigation
     columns on screen. */
  .immersive {
    min-block-size: 100dvh;
  }

  /* The shell — the sidebar beside everything else.
   *
   * The sidebar sizes itself, so the track is auto: the rail is one property on
   * .sidebar rather than a second number here that somebody has to keep in
   * agreement with it. Below the wide band it leaves the flow to become a
   * drawer, and the grid is one column again. */
  .app-shell {
    --app-shell-content-start: var(--sidebar-expanded-width);

    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    min-block-size: 100dvh;
  }

  /* A column, so a screen can take the height the topbar and the flash bar
     leave rather than guessing at it — which is what .main--flush does with it.
     The sidebar states its own height above the wide band and is out of flow
     below it, so nothing here has to hold a column back from stretching. */
  .app-shell__body {
    display: flex;
    flex-direction: column;
    min-inline-size: 0;
  }

  .app-shell:has(.sidebar--rail) {
    --app-shell-content-start: var(--sidebar-rail-width);
  }

  /* A flush screen is as tall as the window rather than as tall as its content,
     and only this element can say so. Both halves are load bearing: the height,
     because min-block-size is a floor and something has to state a ceiling, and
     the row, because an auto row is sized by what is in it — so the height alone
     left a row twice the shell's height inside it, and the page scrolled behind
     a grid that was supposed to be doing the scrolling. minmax(0, 1fr) is the
     row saying it does not have to fit its content.

     A screen taller than the height it is given still overflows and scrolls the
     page, which is what .calendar's own floor is for. */
  .app-shell:has(.main--flush) {
    grid-template-rows: minmax(0, 1fr);
    block-size: 100dvh;
  }

  @media (width < 60rem) {
    .app-shell {
      --app-shell-content-start: 0rem;

      grid-template-columns: minmax(0, 1fr);
    }
  }

  /* All that is left of the topbar, and only where the sidebar is a drawer.
   *
   * The sidebar names the account, holds every section link, and now signs out
   * too, so above the wide band the bar has nothing in it — and a screen is
   * better off starting at the top of the window than under an empty strip.
   * Below the band it carries the one control the drawer needs, so the whole
   * element is hidden rather than only its contents: an empty bordered bar is
   * still a bordered bar. */
  .topbar {
    display: none;
    align-items: center;
    gap: var(--space);
    padding: var(--space-half) var(--space);
    border-bottom: var(--border);
  }

  @media (width < 60rem) {
    .topbar {
      display: flex;
    }
  }

  /* With no bar above it, the page title is the first thing in the window and
     wants air over it — hence block padding a step up from the gutter. The inline
     padding grows with the viewport and stops: a phone cannot spare it, and a
     wide screen has already had its line length capped by the max-width. */
  /* Every screen takes its whole line length, not only as much of it as its
     content happens to fill. In the body's flex column the auto margins turn
     stretching off, and a screen of short forms shrank to fit them and centred
     itself somewhere else than the screen beside it — so a row of tabs moved
     sideways from one tab to the next. */
  .main {
    inline-size: 100%;
    max-inline-size: var(--main-width);
    margin-inline: auto;
    padding: var(--space-and-half) var(--screen-gutter);
  }

  /* A list or a table screen: wider than a form, and still short of the wide
     variant, which is for the three-pane inbox and the calendar. */
  .main--roomy {
    max-inline-size: var(--main-width-roomy);
  }

  .main--full {
    max-inline-size: var(--main-width-wide);
  }

  /* Two screens are their own surface rather than content standing in a gutter,
     and they share the gutter's removal: a workspace, whose rail has to meet the
     account sidebar without inheriting a card-like margin around it, and a flush
     screen, which runs to the edges of the window. Each restores whatever
     padding it wants inside itself. */
  .main--workspace,
  .main--flush {
    max-inline-size: none;
    margin-inline: 0;
    padding: 0;
  }

  /* A flush screen also takes the height that is left. The calendar is the one:
     a grid that scrolls inside a page that scrolls as well reads as a calendar
     somebody put on a screen rather than as the screen. It supplies the column
     so what is inside can grow into that height without naming one, and the
     shell's own min-block-size means a window too short for it scrolls instead
     of squeezing it. */
  .main--flush {
    display: flex;
    flex-direction: column;
    flex: 1;
    /* Without this the flex item cannot go below the height of its content, and
       a screen whose whole point is that it scrolls internally has a lot of it:
       the shell would be the window's height with the page scrolling behind it
       anyway. What is inside says where it is allowed to stop. */
    min-block-size: 0;
  }

  .flash {
    padding: var(--space-half) var(--space);
    text-align: center;
  }

  .flash--alert {
    color: var(--color-negative);
  }

  /* Printed, the shell is the screen and nothing else.
   *
   * Navigation is not something you can follow on paper, a flash notice is about
   * the last thing somebody did rather than about the record, and the
   * viewport-height ceiling a flush screen takes is the one that matters: capped
   * at 100dvh a record prints as exactly one page and silently drops the rest of
   * itself.
   *
   * This is what "always ready to hand to an owner" costs — the filtered record
   * is already a URL, and printing is the browser's. */
  @media print {
    .sidebar,
    .topbar,
    .flash {
      display: none;
    }

    .app-shell,
    .app-shell:has(.main--flush) {
      display: block;
      block-size: auto;
    }
  }
}
