/* ============================================================
   FieldRunner Design System — RESPONSIVE TIERS
   Loaded on every console page LAST (after every surface stylesheet) — see layout.php.
   It owns the tier policy, and media queries add no specificity, so it must win ties.

   THE POLICY (see docs/design-system.md §Responsive):
     FULL     >1080px   desktop — every surface, full density. The design target.
     COMPACT  821-1080   laptop/landscape tablet — context panel narrows.
     TABLET   621-820    the context panel + rail leave the grid and become a DRAWER.
     PHONE    <=620      phone tier — single column, condensed chrome, capability banner.

   FieldRunner is a desktop-first OPERATOR CONSOLE. We do NOT force every surface into
   620px. Each surface declares a MOBILE POSTURE instead (.fr-posture strip below):
     full        — fully usable on a phone.
     summary     — read-only/summary view; the authoring UI is desktop-only.
     desktop     — not available on a phone; tells the user why + what to do.
   Wide data stays reachable via horizontal scroll containers (.fr-scroll-x), never
   by shrinking type below legibility.

   RULE FOR NEW SURFACES: every surface stylesheet ends with a
   `@media (max-width:620px)` PHONE TIER block. No surface ships without one.
   ============================================================ */

/* ---------- base ergonomics (all widths) ---------- */
html { -webkit-text-size-adjust: 100%; }               /* no surprise reflow on orientation change */

/* Horizontal-scroll container — THE approved way to show wide content (tables, matrices,
   timelines) on a narrow screen. Momentum scrolling + a hairline edge so it reads as scrollable. */
.fr-scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}
.fr-scroll-x > * { min-width: max-content; }

/* ============================================================
   COMPACT (<=1080) — the top bar must never force the shell open
   `.topnav` is a flex row whose children are all `flex:0 0 auto` with `white-space:nowrap`, so
   nothing could yield and the bar set a hard floor on the whole `.app` grid. That floor is ~940px,
   which is INSIDE the compact tier — at 900px the document rendered 942px wide and dragged every
   surface with it. This was a live bug at 821-1080 that went unnoticed only because desktops are
   usually wider than 1080. Making the brand and account picker shrinkable, and retiring the
   telemetry pill before it gets crushed, removes the floor.
   ============================================================ */
@media (max-width: 1080px) {
  .topnav { gap: 12px; min-width: 0; }
  .brand, .acct-switch { min-width: 0; }
  .acct-switch-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .acct-switch-input { min-width: 0; }
}
/* the telemetry pill's detail lives in the drawer/panel's Logs -> System view */
@media (max-width: 1023px) { .telemetry { display: none; } }

/* ============================================================
   TABLET & BELOW (<=820) — the context panel becomes a slide-out DRAWER
   The panel + rail leave the document grid entirely (position:fixed) and slide in
   OVER the surface from the right. The rail rides along as a horizontal icon strip
   at the top of the drawer, so every view (Notifications/Logs/Help/Account/Settings)
   stays reachable — on mobile they were previously unreachable.
   ============================================================ */
@media (max-width: 820px) {
  /* the surface takes the full width; panel + rail no longer occupy grid tracks */
  .app.has-ctx .body,
  .app.has-ctx.ctx-collapsed .body { grid-template-columns: minmax(0, 1fr); }

  .ctx-panel,
  .app.ctx-collapsed .ctx-panel {
    display: flex;
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(92vw, 400px);
    /* the rail strip sits at the drawer's top edge */
    padding-top: 52px;
    z-index: 60;
    background: var(--bg);
    border-left: 1px solid var(--line);
    box-shadow: -18px 0 40px rgba(0, 0, 0, .55);
    transform: translateX(101%);
    transition: transform .22s ease;
    will-change: transform;
  }
  .ctx-rail {
    display: flex;
    position: fixed;
    top: 0; right: 0;
    width: min(92vw, 400px);
    height: 52px;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 2px;
    /* ⭐ 12px on the right is NOT arbitrary: it matches .topnav's padding, which puts the drawer's close
       button in the SAME PLACE as the Menu button that opened it. Tap, panel in; tap again, panel out.
       ⓘ The toggle is still in the DOM and still keyboard-reachable while the drawer is open (only .main goes
       inert), so aria-expanded stays honest — but a THUMB lands on the close button, because the drawer is
       painted over the top bar. That overlap was luck until this line made it a rule. */
    padding: 0 12px 0 8px;
    z-index: 61;
    background: var(--card-hi, rgba(255, 255, 255, .04));
    border-left: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    transform: translateX(101%);
    transition: transform .22s ease;
  }
  /* the desktop collapse chevron is meaningless in drawer mode — the close button replaces it */
  .ctx-rail .rail-collapse { display: none; }

  /* ⚠ THE RAIL CHANGES AXIS HERE, AND ONE RULE DID NOT GET THE MEMO.
     notify.css gives the You icon `margin-top:auto`, which on the desktop rail (a COLUMN) pushes it and the
     icons after it down to the bottom — the intended grouping. In this block the rail is a ROW, so `auto` on
     the top margin resolves against the CROSS axis instead and drops that one icon a few pixels below the
     others. Reported as "the user icon sits 5-10px lower"; that is exactly the leftover vertical space.
     ⓘ Reset rather than removed: the desktop grouping is still wanted, it just has no meaning in a row. */
  .ctx-rail .rail-icon-foot { margin-top: 0; }

  .app.ctx-drawer-open .ctx-panel,
  .app.ctx-drawer-open .ctx-rail { transform: translateX(0); }

  /* scrim — dims the surface behind the open drawer; tapping it closes */
  .ctx-scrim {
    position: fixed; inset: 0;
    z-index: 59;
    background: rgba(0, 0, 0, .55);
    opacity: 0;
    pointer-events: none;
    transition: opacity .22s ease;
  }
  .app.ctx-drawer-open ~ .ctx-scrim,
  .ctx-scrim.is-open { opacity: 1; pointer-events: auto; }

  /* drawer close button (hidden on desktop, shown in the rail strip on mobile) */
  .ctx-drawer-close {
    display: grid; place-items: center;
    width: 40px; height: 40px;
    margin-left: auto;
    border-radius: 8px;
    color: var(--muted);
  }
  .ctx-drawer-close:hover { color: var(--text); background: rgba(255, 255, 255, .05); }

  /* the topnav bell becomes the drawer opener */
  .nav-bell { cursor: pointer; }

  /* ⭐⭐ THE PANEL TOGGLE — the drawer had no visible door.
     The bell opens it (and still does), but a bell names ONE of the six views behind it; nothing on a phone
     screen suggested that Logs, Help, You, Account & Users and Settings had gone anywhere. Verified on the rig:
     the drawer opened correctly on all nine console surfaces and still read as "the sidebar is not accessible on
     mobile", because the affordance was unreadable. This is the labeled control. */
  .nav-panel {
    display: grid; place-items: center; position: relative;
    min-width: 44px; min-height: 44px; cursor: pointer;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--card-hi, rgba(255, 255, 255, .04));
    color: var(--text);
  }
  /* ⓘ Pressed state, not a hover — a phone has no hover, and an unstyled toggle gives no feedback that the tap
     landed. `is-open` is set by mobile.js alongside the drawer class. */
  .nav-panel.is-open { border-color: var(--green); color: var(--green); }
  /* an unread marker: the drawer is now the only route to notifications, so the door has to carry the signal */
  .nav-panel .nav-dot {
    position: absolute; top: 7px; right: 7px;
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--amber);
    box-shadow: 0 0 0 2px var(--bg);
  }
  /* --- topnav must fit the TABLET tier too, not just the phone tier ---
     The bar is a flex row of brand + account switcher + telemetry + actions, all `flex:0 0 auto`
     with `white-space:nowrap`. Nothing could yield, so it held the whole `.app` grid open: at 768px
     the document rendered 843px wide, dragging every surface with it. Dropping the telemetry pill
     (its detail lives in the drawer's Logs → System view) and letting the brand and account picker
     shrink brings it back inside the viewport. */
  .topnav { gap: 12px; padding: 0 14px; }
  .brand { min-width: 0; overflow: hidden; }
  .telemetry { display: none; }
  .acct-switch { min-width: 0; max-width: 190px; padding-left: 10px; }
  .acct-switch-input { min-width: 0; width: 100%; }
  .acct-switch-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* keep the drawer affordances out of the desktop layout entirely */
@media (min-width: 821px) {
  /* ⓘ .nav-panel too: above the breakpoint the panel and its rail are simply visible, so a control that
     summons them is noise — and would be a second, contradictory way to reach what is already on screen. */
  .ctx-scrim,
  .nav-panel,
  .ctx-drawer-close { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .ctx-panel, .ctx-rail, .ctx-scrim { transition: none !important; }
}

/* ============================================================
   PHONE TIER (<=620) — the shell
   ============================================================ */
@media (max-width: 620px) {
  /* --- shell frame ---
     `auto` (not a fixed 52px) for the header row, because the top bar wraps to TWO rows here:
     identity + actions on row one, the account switcher on its own row beneath. */
  .app { grid-template-rows: auto minmax(0, 1fr) auto; }

  /* --- top nav: identity + actions on row 1; the ACCOUNT SWITCHER gets its own row ---
     Which account you're operating on is the single most consequential piece of state in the
     console — it must not be the thing that gets dropped for space. It's too wide to share a
     393px row with the wordmark and the nav actions, so it wraps to a full-width row of its own. */
  /* ⚠⚠ `min-height` RESERVES BOTH ROWS — this is the single largest layout shift on the console, on every page.
     account_switcher.php server-renders an EMPTY `hidden` div and account-switcher.js fills it, commented
     "Hidden until hydrated to avoid layout shift". Hiding it avoids an empty box but reserves NO SPACE, so the bar
     starts as one 61px row and becomes two (94px) the instant JS lands — shoving every surface's content down 33px.
     Measured CLS from this alone: ~0.09-0.10 on surf-query, surf-analyze, surf-dictionary and surf-report alike.
     ⚠ Reserving on the placeholder itself does NOT work: shell.css sets `[hidden]{display:none !important}` (so a
     class rule can never leave a hidden element visible), which no specificity here can or should beat.
     ⓘ 94px = the hydrated two-row bar. Re-measure with tools/rig/mobile_audit.js if the bar's contents change.
     Too small reintroduces the jump; too large only costs a little dead space, so err high. */
  .topnav { gap: 10px 12px; padding: 8px 12px; flex-wrap: wrap; min-height: 94px; align-content: flex-start; }
  /* the brand must be allowed to give way — it's `flex:0 0 auto` on desktop, which would push
     the nav actions off-screen before it yielded a pixel */
  .brand { min-width: 0; overflow: hidden; }
  .brand .wordmark { height: 14px; max-width: 100%; }
  .brand-tag,
  .telemetry,
  .acct-name,
  .role-chip { display: none; }          /* role is shown in the Account drawer view instead */
  .nav-right { margin-left: auto; gap: 2px; }

  /* the switcher's own row — `order` puts it after the nav actions regardless of DOM position,
     and the vertical divider becomes a horizontal rule since it now separates rows, not columns */
  .acct-switch {
    order: 10;
    flex: 1 1 100%;
    max-width: none;
    min-width: 0;
    gap: 9px;
    padding: 7px 0 1px;
    margin-left: 0;
    border-left: none;
    border-top: 1px solid var(--line);
  }
  .acct-switch-label { flex: 0 0 auto; }
  .acct-switch-input { flex: 1 1 auto; width: 100%; min-width: 0; }
  .acct-switch-name { flex: 1 1 auto; min-width: 0; }
  /* 44px touch targets on every nav action */
  .nav-icon, .nav-acct { min-width: 44px; min-height: 44px; }
  .nav-icon { display: grid; place-items: center; }

  /* --- main --- */
  .main { padding: 12px 14px 24px; }
  .crumb { font-size: 10.5px; flex-wrap: wrap; }

  /* --- footer: keep it to a single line (copyright + version); the status pill lives in the drawer --- */
  .footer, .foot { font-size: 10px; padding: 6px 12px; line-height: 1.5; gap: 8px; }
  .footer .ft-mid { display: none; }

  /* --- forms: <16px inputs make iOS Safari auto-zoom the page on focus and never zoom back.
         16px is a hard floor on phones for anything focusable. --- */
  input, select, textarea { font-size: 16px !important; }
  input, select, textarea, button { max-width: 100%; }

  /* --- tap targets --- */
  button, .btn, [role="button"] { min-height: 36px; }

  /* --- tables: never let a wide table blow out the layout --- */
  table { max-width: 100%; }

  /* --- media --- */
  img, svg, canvas, video { max-width: 100%; }
}

/* ============================================================
   SHARED SURFACE PATTERNS (phone tier)
   These two patterns repeat IDENTICALLY across every surface, so they live here once rather than
   as six copies. Anything surface-SPECIFIC still belongs in that surface's own stylesheet, in its
   own `@media (max-width:620px)` block.
   ============================================================ */
@media (max-width: 620px) {

  /* --- 1. TAB STRIPS -> horizontal scroller ---
     Every surface's tab bar is a non-wrapping flex row, so tabs past the 4th were simply cut off
     with no way to reach them. Scrolling beats wrapping here: a surface like the Account Dictionary
     has 8 tabs, and wrapping would eat three rows of vertical space before any content. */
  /* NOTE: .dx-subtabs is deliberately NOT in this list — it hosts the Explore search input as a
     flex child, and a nowrap scroller would push the search box off-screen. dictionary.css wraps
     it instead (and must, since this file loads later and would win a flex-wrap tie). */
  .dx-tabs,
  .dd-tabs, .dd-subtabs, .dd-up-tabs,
  .q-tabs,
  .rp-tabs,
  .vz-tabs,
  .xc-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;                 /* the border-bottom already reads as an edge */
  }
  .dx-tabs::-webkit-scrollbar,
  .dd-tabs::-webkit-scrollbar, .dd-subtabs::-webkit-scrollbar, .dd-up-tabs::-webkit-scrollbar,
  .q-tabs::-webkit-scrollbar, .rp-tabs::-webkit-scrollbar, .vz-tabs::-webkit-scrollbar,
  .xc-tabs::-webkit-scrollbar { display: none; }
  .dx-tabs > *,
  .dd-tabs > *, .dd-subtabs > *, .dd-up-tabs > *,
  .q-tabs > *, .rp-tabs > *, .vz-tabs > *,
  .xc-tabs > * { flex: 0 0 auto; white-space: nowrap; }

  /* --- 2. MULTI-COLUMN SPLITS -> one column ---
     Every one of these is a master/detail or builder layout with a fixed sidebar track. A 320px
     sidebar next to a 1fr pane inside 365px of content box leaves the main pane ~40px wide, which
     is what crushed the LakeView Pulse columns into one-letter-per-line. */
  .dd-work,
  .qb3, .dsb, .ask2, .dash-cols,
  .dx-split, .dx-xsplit, .dx-rsplit, .dx-msg-split, .dx-proj-split { grid-template-columns: minmax(0, 1fr); }

  /* label/field rows that pin a fixed label column */
  .qb-row, .dxd-mfield { grid-template-columns: minmax(0, 1fr); gap: 4px; }

  /* --- wide data: scroll, never squeeze --- */
  .ds-tablewrap, .dx-xtable, .adm-table, .ds-table, .rl-table, .meta-table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* ============================================================
   MOBILE POSTURE STRIP — how a surface tells the user what it can do here.
   Rendered by Fr\Shared\MobilePosture::strip(); hidden above the phone tier.
   ============================================================ */
.fr-posture { display: none; }
@media (max-width: 620px) {
  .fr-posture {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 0 0 11px;
    padding: 8px 11px;
    border: 1px solid var(--line);
    border-left-width: 3px;
    border-radius: 8px;
    background: rgba(255, 255, 255, .022);
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--text-2);
  }
  .fr-posture svg { flex: 0 0 auto; margin-top: 1px; }
  .fr-posture-t { display: block; font-weight: 600; color: var(--text); margin-bottom: 2px; }
  .fr-posture-summary { border-left-color: var(--amber); }
  .fr-posture-summary svg { color: var(--amber); }
  .fr-posture-desktop { border-left-color: var(--blue, #4b8fd6); }
  .fr-posture-desktop svg { color: var(--blue, #4b8fd6); }
}

/* ============================================================
   CAPABILITY BANNER — one-time, dismissable, shown below the phone breakpoint.
   Sets the expectation on arrival: this is a desktop console; here's what to expect.
   Dismissal persists in localStorage (per device) — key `fr.mobileBanner.dismissed`.
   ============================================================ */
.fr-mobile-banner {
  display: none;
  position: relative;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 11px;
  padding: 9px 34px 9px 11px;
  border: 1px solid var(--amber-soft, rgba(214, 158, 46, .35));
  border-left: 3px solid var(--amber);
  border-radius: 8px;
  background: rgba(214, 158, 46, .07);
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-2);
}
@media (max-width: 620px) { .fr-mobile-banner.is-on { display: flex; } }
.fr-mobile-banner svg { flex: 0 0 auto; margin-top: 1px; color: var(--amber); }
.fr-mobile-banner-t { display: block; font-weight: 600; color: var(--text); margin-bottom: 2px; }
.fr-mobile-banner-x {
  position: absolute; top: 4px; right: 4px;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  color: var(--muted); font-size: 17px; line-height: 1;
  border-radius: 6px;
}
.fr-mobile-banner-x:hover { color: var(--text); background: rgba(255, 255, 255, .06); }
