/* 10-shell.css — see 00-contract.css for the rules this file obeys.
   Every rule below is inside a max-width or pointer:coarse media query.

   Owns, at compact/touch widths only: the hamburger toggle in
   _topbar.html, .sidebar as an off-canvas drawer (reusing .panel's own
   slide/visibility idiom from app.css), the .scrim it slides over
   (reusing the sign dialog's .scrim rather than a second dimming
   backdrop), the topbar's phone-width layout, safe-area padding for the
   topbar/drawer/.panel, and touch-target sizing for the topbar's icon
   buttons, the sidebar's nav rows and .panel-h__close.

   Jeremy's ask this answers: "the left menu no longer can be fixed" —
   below 900px app.css/the modern-uzh theme used to just delete the
   sidebar outright (display:none), leaving a phone user with no
   navigation at all except search/"New entry"/the avatar menu. Both of
   those two display:none blocks (app.css ~line 697, the theme's
   10-shell.css ~line 150) have been edited in place to say what they
   mean now — see their own comments — rather than leaving a
   contradictory display:none for this file to silently overrule. */

@media (max-width: 900px) {
  /* ---- A. the hamburger toggle -----------------------------------------
     _topbar.html ships this button with the `hidden` attribute and no
     class that anything unconditional already styles, specifically so it
     is invisible above this breakpoint with nothing but markup — see
     that template's own comment for why (in short: the mobile layer may
     only ever narrow, so there is no legal place for a "display: none
     above 900px" rule to live; `hidden` is a browser-default style any
     author rule beats for free, so this block simply turning it on here
     is the only side of the toggle that needs to exist anywhere). */
  .topbar__nav-toggle {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radius);
    color: var(--ink-3);
    flex: none;
    /* Deliberately NOT the .icon-btn class, even though this hand-copies
       its look: app.css's `.icon-btn { display: grid; ... }` is
       unconditional, so giving this button that class would make it
       visible on every screen size regardless of the `hidden` attribute
       or this media query — author rules beat the `hidden` attribute's
       UA-origin display:none no matter how they're scoped. */
  }
  .topbar__nav-toggle:hover { background: var(--surface-2); color: var(--ink); }
  .topbar__nav-toggle svg { width: 16px; height: 16px; }

  /* ---- A. the sidebar becomes an off-canvas drawer ----------------------
     Same slide-over idiom .panel (app.css) already uses: transform for
     the slide, and visibility stepped on the transition so a closed
     drawer drops out of the tab order (rather than leaving its off-screen
     links reachable by Tab) without losing the animation on open. Reusing
     the technique — not the class — because .sidebar carries its own
     desktop layout (fixed column, sibling to .shell__body) that .panel
     doesn't have to unwind. mobile_nav.js toggles .is-open, exactly as
     it does for every other .panel in the app. */
  .sidebar {
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--drawer-w);
    border-right: 0;
    /* Elevated off the page like every other slide-over (.panel,
       .swatch-popup, .user-menu__popup) rather than the hairline border
       the fixed desktop column uses, which would read as a seam rather
       than a surface floating above the scrim. */
    box-shadow: var(--shadow-pop);
    /* Above .scrim (app.css, z-index: 80) — this is the topmost surface
       on the page while it's open, same reasoning as the sign dialog
       sitting above everything else via that same .scrim. Below nothing:
       nothing in this app opens two full-screen overlays at once. */
    z-index: 85;
    transform: translateX(-100%);
    transition: transform 0.22s cubic-bezier(0.3, 0.8, 0.4, 1),
                visibility 0s linear 0.22s;
    visibility: hidden;
    /* Safe areas: the drawer is pinned to the left edge and spans full
       height, so it can catch a landscape notch on the left, the
       Dynamic Island/status bar at the top, and the home indicator at
       the bottom, all at once. --gutter-compact (00-contract.css) is the
       drawer's own base padding, kept the same number the rest of the
       compact chrome uses so its content lines up with everything else
       down the left edge; env() adds only what a notch actually needs on
       top of that (0 on every other device). */
    padding: calc(var(--gutter-compact) + env(safe-area-inset-top))
             var(--gutter-compact)
             calc(var(--gutter-compact) + env(safe-area-inset-bottom))
             calc(var(--gutter-compact) + env(safe-area-inset-left));
  }
  .sidebar.is-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform 0.22s cubic-bezier(0.3, 0.8, 0.4, 1), visibility 0s linear 0s;
  }

  /* Locks the page behind the drawer from scrolling while it's open —
     set on <body> by mobile_nav.js's onOpen/onClose, the same moment
     .scrim and .sidebar get their own .is-open. Without it, a touch-drag
     aimed at a long nav list scrolls the canvas underneath the drawer
     instead once the drawer's own content is taller than the viewport,
     and the drawer visibly detaches from its scrim. */
  body.nav-open { overflow: hidden; }

  /* ---- C. safe areas: the topbar --------------------------------------
     box-sizing: content-box, scoped to just this element and only here:
     .topbar has a literal `height` this file has no business knowing or
     restating (46px baseline, 56px under modern-uzh) — doing so would
     silently un-theme it the moment a theme picked a third number. Under
     the app's global border-box reset, padding eats into a fixed height
     and squashes the bar's content; under content-box, whatever `height`
     is already in force keeps meaning "the content area", and the
     safe-area padding added here simply grows the box around it — so the
     visible bar stays exactly as tall as its theme intends, notched
     device or not. */
  .topbar {
    box-sizing: content-box;
    padding-top: env(safe-area-inset-top);
    padding-left: calc(var(--gutter-compact) + env(safe-area-inset-left));
    padding-right: calc(var(--gutter-compact) + env(safe-area-inset-right));
  }

  /* ---- C. safe areas: .panel (the notes rail / sequence tools) --------
     Pinned to the right edge and full height, so it can catch a
     landscape notch on the right and the home indicator at the bottom.
     Nothing to add for the top: .panel-h already sits below any status
     bar with room to spare at 900px+ widths, and the phone-only
     full-width variant below adds the left edge once .panel actually
     reaches it. */
  .panel {
    padding-right: env(safe-area-inset-right);
    padding-bottom: env(safe-area-inset-bottom);
  }
}

@media (max-width: 600px) {
  /* ---- B. the topbar at phone width -------------------------------------
     Four things fight for room in a 46px/56px row at 375pt: the
     hamburger, the lockup, the search field, "+" and the avatar. The
     search input's `flex: 1; max-width: 22rem` (app.css, 26rem under the
     theme) happily eats every spare pixel, which starts squeezing the
     lockup toward nothing well before either max-width is ever reached.

     Decision: the lockup gives up its wordmark first, rather than
     turning search into a second interaction mode (an icon that expands
     into a field needs its own focus/blur choreography, and a half-width
     "Notebook" title bar disagrees with every other page). "DeuelLab" and
     the separator bar are the least useful four-ish rem on a phone-width
     screen — the UZH mark alone still says which app this is — so they
     go, and the search field keeps behaving exactly as it does
     everywhere else in the app (same flex:1/max-width, same focus ring).
     _lockup.html is not this worker's file; achieved purely from CSS via
     its existing markup (an unclassed <span> holding the wordmark, and
     .bar for the separator). */
  .lockup > span:not(.bar) { display: none; }
  .lockup .bar { display: none; }
  .topbar__search { margin-left: 0; }

  /* ---- C. .panel goes full-width ----------------------------------------
     min(430px, 92vw) leaves a 30px scrim strip at 375pt — wide enough to
     look like an error, not intentional. Below 600px there's no useful
     content behind it worth peeking at, so the panel may as well have
     the whole row; the border between it and "outside" becomes moot once
     there's no visible "outside" left, so it's dropped rather than
     drawn floating at the physical edge of the glass. The left edge is
     now a physical edge too (a landscape notch can sit there), which the
     900px block's padding-right/bottom didn't need to cover. */
  .panel {
    width: 100%;
    border-left: 0;
    padding-left: env(safe-area-inset-left);
  }
}

@media (pointer: coarse) {
  /* ---- C. touch targets --------------------------------------------------
     Hit-area only, never layout: an iPad in landscape matches this query
     too but keeps the full desktop grid (.sidebar as the fixed column,
     .topbar at its desktop width), so nothing here may resize a column,
     hide anything, or otherwise touch layout — only grow what a finger
     has to land on, leaving every glyph the same size app.css/the theme
     already gave it.

     Scoped to the topbar's own icon buttons (not every .icon-btn in the
     app — the editor's docbar and formatting toolbar have their own
     touch-target story, in whichever file owns them), the sidebar's nav
     rows, and .panel-h__close, per the brief. */
  .topbar .icon-btn,
  .topbar__nav-toggle {
    min-width: var(--tap);
    min-height: var(--tap);
  }
  .sidebar__nav a {
    min-height: var(--tap);
  }
  .panel-h__close {
    min-width: var(--tap);
    min-height: var(--tap);
  }
}

@media (max-width: 600px) {
  /* The topbar search was the last input in the app still under 16px, and
     it is the one a phone user reaches for first. iOS Safari zooms the
     page whenever a focused text field's font is smaller than 16px — and
     it never zooms back out, so a single tap on "Search entries…" leaves
     the whole notebook magnified and horizontally scrollable until the
     user pinches it back themselves.

     30-sheet.css applies the same 16px floor to form controls inside
     .sheet and .panel, which is every other text input in the app; this
     field sits in the fixed chrome instead, so it is this file's to fix.
     Found by enumerating every rendered input under 16px at 375pt rather
     than by reading — the radio and file inputs that enumeration also
     turned up are UA-default sizes with no text entry and do not trigger
     the zoom, so they are deliberately left alone. */
  .topbar__search input { font-size: 16px; }
}
