
/* ---- The phone tab bar ----
   The sidebar is a card in the document flow, so on a phone it sat *above* the
   content and the section list had to scroll sideways to reach Settings. This is
   the fixed bottom bar that replaces it below the same 820px breakpoint the
   brand layer hides `.wq-sidebar` at, so the two are never visible together.

   `display: none` first, unconditionally: above the breakpoint the sidebar is
   the navigation and this must not exist at all (not merely be invisible), so it
   never becomes a duplicate landmark for a screen reader. Below it the reverse
   happens to the sidebar. */
.et-tabbar { display: none; }

@media (max-width: 820px) {
  .et-tabbar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    /* Above the toast (z 60 is shared; the toast is raised instead, see below). */
    background: hsl(var(--card));
    border-top: 1px solid hsl(var(--border));
    box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.06);
    /* Room for the home indicator under the labels. */
    padding-bottom: env(safe-area-inset-bottom);
  }
  .et-tabbar-btn {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    /* 44px is the floor for the target; the icon + label want more. */
    min-height: 3.25rem;
    padding: 0.4rem 0.25rem;
    color: hsl(var(--muted-foreground));
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  .et-tabbar-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
  }
  .et-tabbar-label {
    /* 0.75rem, not 0.6875: a tab label is read at arm's length and 11px fails
       the same floor this file applies to every other small label. */
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.1;
    white-space: nowrap;
  }
  .et-tabbar-btn[data-active="true"] {
    color: hsl(var(--primary));
  }
  .et-tabbar-btn[data-active="true"] .et-tabbar-label { font-weight: 700; }
  /* A one-line accent above the active tab, the way a native tab bar reads. */
  .et-tabbar-btn[data-active="true"]::before {
    content: "";
    position: absolute;
    top: 0;
    width: 1.75rem;
    height: 2px;
    border-radius: 0 0 2px 2px;
    background: hsl(var(--primary));
  }
  .et-tabbar-btn { position: relative; }

  /* ---- The sidebar on a phone ----
     The tab bar replaces the *section* nav, so only that card is hidden. The
     PROJECTS card stays, and it has to: it holds the project list and the only
     create-project form in the app (`.et-side-new`). Hiding the whole sidebar
     — which is what this did first — made project creation impossible below the
     breakpoint while the Dashboard's empty state still pointed at it "on the
     left", and that is exactly the bug it looked like: the panel is in the DOM
     the whole time, just `display: none`, so a markup assertion still passes and
     only a rendered page shows the dead end.

     It is compacted instead: the create form goes full width under the list, and
     the card's padding tightens, so the cost is a couple of rows rather than the
     full sidebar the desktop layout puts above the content. */
  .et-sidebar { display: block; }
  .et-side-nav { display: none; }
  .et-sidebar .wq-stack-sm { grid-template-columns: minmax(0, 1fr); gap: 0.5rem; }
  .et-side-projects { padding: 0.6rem 0.7rem; }
  /* The "New project" field and its Add button stop sharing a cramped row and
     take the full width, which is both easier to tap and one less line of
     chrome. */
  .et-side-new { flex-wrap: wrap; }
  .et-side-new input { flex: 1 1 100%; width: 100%; min-width: 0; }
  .et-side-new button { flex: 1 1 auto; }

  /* Clearance for the fixed bar. It goes on `body`, not `.et-shell`, because the
     footer is a *sibling* of the shell — padding the shell alone left the
     footer sitting underneath the bar. */
  body { padding-bottom: calc(3.5rem + env(safe-area-inset-bottom)); }
  /* The toast is pinned to the bottom too, so it has to clear the bar. */
  .et-toast { bottom: calc(4.25rem + env(safe-area-inset-bottom)); }

  /* A dialog is nearly full height; keep its top clear of the sticky app bar. */
  .et-auth-dialog { margin-top: 4.5rem; }

  /* The app bar was the brand row *plus* a subtitle *plus* a full search row —
     around 250px of a 667px viewport, a third of the screen before any content.
     The subtitle is decorative, so it is the first thing to go; the search keeps
     its own row because a 44px search field is worth more than the height. */
  .wq-appbar { padding: 0.6rem 0.9rem; gap: 0.6rem; }
  .wq-appbar-sub { display: none; }
  .wq-appbar-text { gap: 0; }
  .wq-appbar-title { font-size: 1.05rem; }
  .et-topbar { padding-top: max(0.5rem, env(safe-area-inset-top)); }

  /* The guest notice is five lines beside a badge, and it was filling the whole
     first screen on a project page — the task list was entirely below the fold,
     which is the first thing a new visitor sees. Let the badge and the text each
     take a full line so the sentence uses the width instead of sharing it. */
  .et-notice { align-items: flex-start; }
  .et-notice-badge { flex: 1 0 100%; }
  .et-notice-text { flex: 1 0 100%; min-width: 0; }
}

/* ---- 44px touch targets, gated on a real finger ----
   Not on width: a narrow desktop window is still a mouse and should keep the
   compact desktop targets, and a 900px tablet is still a finger and must not be
   left with 30px buttons. A width query cannot tell those apart. */
@media (pointer: coarse) {
  .et-icon-btn { width: 2.75rem; height: 2.75rem; }
  /* The finish control is a small circle by design. Growing the circle would
     change every row's look, so the *hit area* grows instead: 44px of target
     around a 24px dot, and the row does not get taller. `::before` because
     `::after` is already the `.et-busy` spinner. */
  .et-check { width: 1.5rem; height: 1.5rem; }
  .et-check::before { content: ""; position: absolute; inset: -0.625rem; }
  .et-btn, .et-btn-primary, .et-btn-sm { min-height: 2.75rem; }
  .et-tab { min-height: 2.75rem; }
  .et-chip { min-height: 2.25rem; display: inline-flex; align-items: center; }
  .et-link-btn { min-height: 2.5rem; display: inline-flex; align-items: center; }
  .et-pager a, .et-pager span { min-height: 2.5rem; display: inline-flex; align-items: center; }
  /* Every `details`-based control (account menu, project actions, a task's edit
     popover, the composer's "Priority, due date & notes") is a `summary`; a
     30px summary is unreachable one-handed. */
  summary { min-height: 2.75rem; }
  .et-side-nav .wq-nav-btn, #et-sidebar-projects .wq-nav-btn { min-height: 2.75rem; }
  .et-composer textarea { min-height: 4.5rem; }
  .et-composer input,
  .et-edit-panel input,
  .et-edit-panel select { min-height: 2.75rem; }
  /* The components-library `Input`/`Button` instances come out at 36-40px.
     Targeted by *position*, never by their generated class names — those are
     hashed per build and would rot immediately. */
  .wq-appbar input, .wq-appbar button, .wq-appbar summary { min-height: 2.75rem; }
  .et-side-new button, .et-side-new input { min-height: 2.75rem; }
  .wq-appbar-brand { min-height: 2.75rem; }
  /* The search page reuses `.et-composer` for its own form, so its Search
     button is covered by targeting the composer rather than the page. */
  .et-composer button { min-height: 2.75rem; }
  /* The theme switch on Settings is 21px tall — the worst target in the app. */
  .wq-theme-btn { min-height: 2.75rem; padding-left: 0.9rem; padding-right: 0.9rem; }
  /* A bare text link in the footer is a 16px-tall target; 0.75rem of padding
     brings the line box to the 44px floor. */
  .et-foot a { display: inline-block; padding: 0.75rem 0.2rem; }
}

/* ---- Clear the notch and the home indicator ----
   `viewport-fit=cover` in the viewport meta is what makes these resolve to
   anything but 0px; without it they are a silent no-op. `max()` keeps the
   design value as the floor, so a flat-edged phone (every inset 0) gets exactly
   the padding the desktop design uses. */
.et-topbar {
  padding-left: max(1.25rem, env(safe-area-inset-left));
  padding-right: max(1.25rem, env(safe-area-inset-right));
}
.et-shell {
  padding-left: max(1.25rem, env(safe-area-inset-left));
  padding-right: max(1.25rem, env(safe-area-inset-right));
  padding-bottom: calc(2.5rem + env(safe-area-inset-bottom));
}
/* `.et-notice` is deliberately NOT in this block. It used to be, with
   `margin-left`/`margin-right` forced to the safe-area insets, and that was
   wrong twice over. This rule set is top level, not inside a media query, so it
   applied at every width - and the notice's own rule centres itself with
   `margin: 0.75rem auto 0` plus a `width: calc(100% - 2.5rem)`, which is where
   its 1.25rem inset comes from. Overriding `auto` with two fixed margins
   therefore threw the centring away and replaced it with a hard left pin:
   measured at 1920px the notice sat 20px from the left edge and 532px from the
   right, 512px off-centre, while the app bar beside it correctly centred at
   256px. Nothing about that was phone-specific, which is why it went unnoticed.
   The base rule's `auto` margins are the correct mechanism; leave them alone. */
/* Pinned to the bottom of the viewport, so it has to clear the home bar. */
.et-toast { bottom: calc(1.25rem + env(safe-area-inset-bottom)); }

/* ---- The bar stays put ----
   Most of what "feels like an app" is this: the navigation holds while the list
   scrolls under it. The page background is the same colour, so the bar needs no
   edge bleed to look flush. */
@media (max-width: 820px) {
  .et-topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    padding-top: max(0.75rem, env(safe-area-inset-top));
    background: hsl(var(--background));
    border-bottom: 1px solid hsl(var(--border));
  }
  /* The grey flash on every tap, and the double-tap-zoom delay, are desktop
     habits that read as jank on a phone. `touch-action: manipulation` keeps
     scrolling and pinch-zoom and drops only the synthetic delay. */
  .et-topbar a, .et-topbar button, .et-topbar summary,
  .et-shell a, .et-shell button, .et-shell summary,
  .et-shell label {
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  /* No pull-to-refresh revealing a white gap under the app. */
  body { overscroll-behavior-y: contain; }
}

/* ---- A readable floor ----
   11px uppercase labels are legible on a desk monitor and not on a phone held
   at arm's length. Two of these four classes belong to the brand layer; they are
   overridden here rather than there because a legibility floor is this
   product's phone concern, and changing the shared layer would restyle Timeline
   and manage at the same time. Worth lifting into brandlib if the whole fleet
   wants it. */
@media (max-width: 820px) {
  .et-notice-badge,
  .et-section-title,
  .wq-nav-section,
  .wq-theme-btn { font-size: 0.75rem; }
}
