/* =====================================================================================================================
   THE DASHBOARD ON A PHONE: the shell, and the conventions every section pass builds on.
   "Ruling 103" (owner ruling, 14 Oct 2026: "this one is huge"): the app on a phone is OPTIMIZED, not desktop shrunk;
   "mobile cant show as much informaiton at the same time", so a phone screen shows less at once. The sidebar gets a
   close/open control. Hover-only affordances gain a tap path; dialogs and popups fit the viewport; the empty-state and
   border laws hold at phone width.

   Section passes: read this block first, then write your phone CSS in your own file.

   1. ONE BREAKPOINT. A phone is under 768px wide, or a touch screen under 501px tall (a phone on its side):
      @media (max-width:767px),(pointer:coarse) and (max-height:500px) in CSS, PlinthMobile.PHONE and
      PlinthMobile.phone() in JS (js/plinth-mobile.js). Use no other phone width. Up to 900px the page is drawn at true
      size (no interface-scale zoom) with touch ergonomics (44px targets, 16px inputs, dashboard-f27.css).
   2. THE SHELL IS NOT YOURS. At phone width the sidebar is a drawer, closed on every load. It opens over the page and
      never squeezes it, from the Menu button, which sits in the top bar beside the zone's title and can be dragged
      anywhere (r144, 16 Oct 2026; js/plinth-menu-drag.js); the same button closes it (bottom-left while the drawer is open), and so do a
      tap on the dimmed page, Esc and picking a zone. From 768px up the sidebar docks with its own close control and the
      choice is remembered. Never hide, move or restyle .shell, #side, #view's padding or the Menu button; the state
      lives in <html data-side="open|closed">.
   3. NO CORNER TO KEEP CLEAR. The Menu button lives in the zone's top bar (r144, 16 Oct 2026), so the bottom-left
      corner is free: #view pads its bottom by 16px and the safe area only, sheets dock 12px from the screen's edge, and
      nothing declares a pinned bar (--m-fab-lift, data-m-bar and plinthPinnedBar are gone). Only the open drawer uses
      the corner: the same button is its Close there, and the drawer's foot band is var(--m-fab-clear) tall for it.
      While a text field has focus at phone width (the keyboard is up) the button hides, so it never covers the next
      field; it comes back on blur.
   4. ONE COLUMN. At phone width content is one column: grids become minmax(0,1fr) and side-by-side panes stack.
      .m-cols is --cols columns above the breakpoint and one below. Show less at once: fold the secondary behind a tap
      (details/summary or a button), and drop what a phone does not need with .m-hide (.m-only is the reverse).
   5. GUTTERS AND TAPS. The page gutter is --m-gutter (16px); stacked blocks are --m-gap apart (.m-stack). Anything
      tappable is at least --m-tap (44px) each way (.m-tap). Inputs are 16px so iOS never zooms.
   6. NOTHING RUNS SIDEWAYS. The page never scrolls sideways. A row that cannot fit is a chip row (.m-chips): one line
      that scrolls inside itself and never wraps, its chosen chip kept in view, a fade at the edge where more chips
      sit. Tab rows and step bars in #view ([role=tablist] and the known tab classes) get this by default up to
      900px wide and on a phone on its side: they never wrap.
   7. HOVER BECOMES TAP. Nothing is hover-only. A "?" or a hint is a .tap-tip[data-tap-tip] holding a .tap-tip-pop:
      a mouse hover shows it beside the term; a tap opens it (at phone width as a bottom sheet drawn over everything);
      a tap anywhere else or Esc closes it. A floating layer you position yourself registers with
      PlinthMobile.tapAway(layer, { keep: '<its triggers>', close }) for the same closing (a tap on a modal
      dialog's backdrop counts as outside it), and carries .m-sheet. A <dialog data-tap-away> needs no code: a tap
      outside its box closes it. Esc that closes any of these, or the drawer, is spent: preventDefault and
      stopPropagation, so no page handler sees it (check e.defaultPrevented in yours).
   8. POPUPS FIT. .m-sheet (and every .tap-tip-pop) docks to the bottom of a phone screen, 12px from its edges, at most
      70% of the screen tall so a strip of page always shows to tap away on, and scrolls inside itself; dialogs are
      capped to the viewport. Draw a section's sheet on <body>: const release = PlinthMobile.sheet(el, { close, keep })
      when it opens, release() when it closes. On <body> it sits flush over the Menu button; inside #view it cannot
      (#view is its own layer, under the button). Bind the sheet's handlers on the sheet, not by delegation from #view.
   9. THE LAWS HOLD. Borders drawn and strong, empty states local, no zero counts: at phone width as everywhere.

   Everything a section may restyle sits in :where(), at zero specificity, so a section's own rule always wins. The
   shell's own rules key on #side and #view so the older generations' sidebar rules can't reach them.
   ===================================================================================================================== */

:root{
  --m-gutter:16px; --m-gap:12px; --m-tap:44px;
  --m-fab:48px; --m-fab-clear:calc(var(--m-fab) + 24px);
  --m-safe-t:env(safe-area-inset-top,0px); --m-safe-b:env(safe-area-inset-bottom,0px); --m-safe-l:env(safe-area-inset-left,0px);
  --side-w:252px; --drawer-w:min(320px,86vw);
}

/* ------------------------------------------------------------------------------------------------- the shell controls */
.shell-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-width:36px;height:36px;padding:0;
  border:1px solid var(--card-edge,var(--line-2));border-radius:9px;background:var(--card);color:var(--ink);
  font:inherit;font-size:14px;font-weight:600;line-height:1;cursor:pointer;box-shadow:none;
  transition:background .15s,border-color .15s;-webkit-tap-highlight-color:transparent}
.shell-btn:hover{border-color:var(--ink-3);background:var(--card-2,var(--card))}
.shell-btn:focus-visible{outline:2px solid var(--sig);outline-offset:2px}
.shell-btn svg{width:18px;height:18px;flex:none}
html #side .side-close{position:absolute;top:26px;right:14px;z-index:2}
.shell-open,.shell-scrim{display:none}
html:not([data-side="open"]) .shell-open .so-x,html[data-side="open"] .shell-open .so-menu{display:none}

/* ------------------------------------------------------------------------------------------------- docked: 768px up */
@media (min-width:768px) and (not ((pointer:coarse) and (max-height:500px))){
  html[data-side="closed"] .shell{grid-template-columns:56px minmax(0,1fr)!important}
  html[data-side="closed"] #side{display:none!important}
  html[data-side="closed"] #view{grid-column:2}
  html[data-side="closed"] .shell-open{display:inline-flex;position:fixed;top:24px;left:8px;z-index:40;width:40px;height:40px}
  html[data-side="closed"] .shell-open .so-l{display:none}
  html[data-side="closed"] #basis-session{display:none!important}
}
/* The older generations flatten the sidebar into a strip below 900px; between 768 and 900 it stays the sidebar. */
@media (min-width:768px) and (max-width:900px) and (not ((pointer:coarse) and (max-height:500px))){
  html .shell{display:grid!important;grid-template-columns:var(--side-w) minmax(0,1fr)}
  html #side{position:sticky;top:0;height:100vh;height:100dvh;display:flex;flex-direction:column;overflow-y:auto;
    padding:24px 14px 20px!important;border-right:1px solid var(--line);border-bottom:0}
  html #side .nav{display:block;overflow:visible;margin-top:16px;padding-top:0}
  html #side .nav button{width:100%}
  html #side .sidefoot{display:block}
  html #view{min-width:0}
}

/* ------------------------------------------------------------------------------------------------- phone: the drawer */
@media (max-width:767px),(pointer:coarse) and (max-height:500px){
  html .shell{display:block!important;padding:0!important;min-height:100dvh!important}
  html #side{position:fixed!important;inset:0 auto 0 0!important;z-index:300;width:var(--drawer-w)!important;
    height:100dvh!important;min-height:0!important;display:flex!important;flex-direction:column!important;
    align-items:stretch!important;gap:0!important;overflow-y:auto!important;overscroll-behavior:contain;
    padding:calc(22px + var(--m-safe-t)) 14px 0!important;
    border-right:1px solid var(--card-edge,var(--line-2))!important;border-bottom:0!important;
    transform:translateX(-101%);visibility:hidden;box-shadow:none;
    transition:transform .28s var(--pm-ease,cubic-bezier(.22,1,.36,1)),visibility 0s linear .28s}
  html[data-side="open"] #side{transform:none;visibility:visible;box-shadow:0 6px 18px rgba(15,18,20,.18);
    transition:transform .28s var(--pm-ease,cubic-bezier(.22,1,.36,1)),visibility 0s}
  /* The drawer's foot is a band the Close button sits on; the list scrolls under it, never under the button. */
  html #side::after{content:"";position:sticky;bottom:0;flex:none;display:block;margin:auto -14px 0;
    min-height:calc(var(--m-fab-clear) + var(--m-safe-b));background:inherit;border-top:1px solid var(--line-2)}
  html #side .nav{display:block;overflow:visible;margin-top:14px;padding-top:0}
  html #side .nav button{width:100%}
  html #side .sidefoot{display:block;padding-bottom:14px}
  html #side kbd{display:none}
  html #side .side-close{top:calc(18px + var(--m-safe-t));width:var(--m-tap);height:var(--m-tap)}
  /* Every control in the drawer is a 44px tap; no line in it reads under 12px. */
  html #side :is(.cta,.nav button,.side-utility-v22 button,.side-theme-grid-v23 button,.acct){min-height:var(--m-tap)!important}
  html #side .side-utility-v22 button{font-size:14px!important}
  html #side .side-theme-grid-v23 button{font-size:13px!important}
  html #side .side-theme-v23>span,html #side .nav .ns,html #side .acct .ae{font-size:12px!important}
  html #side .acct .mono{width:32px!important;height:32px!important;font-size:12px!important}
  html #view{margin:0!important;width:100%!important;min-width:0!important;
    padding:20px var(--m-gutter) calc(16px + var(--m-safe-b))!important}
  html[data-side="open"],html[data-side="open"] body{overflow:hidden}

  .shell-scrim{display:block;position:fixed;inset:0;z-index:299;background:rgba(14,17,19,.42);opacity:0;visibility:hidden;
    transition:opacity .28s,visibility 0s linear .28s}
  html[data-side="open"] .shell-scrim{opacity:1;visibility:visible;transition:opacity .28s,visibility 0s}
  .shell-open{display:inline-flex;position:fixed;left:calc(12px + var(--m-safe-l));
    bottom:calc(12px + var(--m-safe-b));z-index:320;width:var(--m-fab);height:var(--m-fab);
    border-radius:12px;box-shadow:0 2px 6px rgba(15,18,20,.16);transition:bottom .2s var(--pm-ease,ease)}
  .shell-open .so-l{display:none}
  .shell-open svg{width:22px;height:22px}
  /* The Menu button's home is the top bar (owner ruling r144, 16 Oct 2026: "Move it into the top bar, next to the page title.
     and draggable."): beside the zone's h1, scrolling with it, so it never covers content. js/plinth-menu-drag.js sets
     --m-menu-x/y from the title and makes room with h1[data-m-title]. While the drawer is open it keeps the bottom-left
     Close spot above. Dragged, it floats (position:fixed) where she dropped it, --m-menu-mx/my. */
  html:not([data-side="open"]) .shell-open{position:absolute;left:var(--m-menu-x,var(--m-gutter));top:var(--m-menu-y,12px);
    bottom:auto;width:var(--m-tap);height:var(--m-tap);touch-action:none;user-select:none;-webkit-user-select:none}
  html:not([data-side="open"]) .shell-open:focus-visible{outline:3px solid var(--sig);outline-offset:2px}
  html:not([data-side="open"]):not([data-menu-moved]) body:not(:has(.cv)) #view h1[data-m-title]{padding-left:calc(var(--m-tap) + 10px)}
  html:not([data-side="open"]) body:not(:has(.cv)) #view h1[data-m-title]{padding-top:8px;padding-bottom:8px}
  html[data-menu-moved]:not([data-side="open"]) body .shell-open{position:fixed!important;left:var(--m-menu-mx)!important;
    top:var(--m-menu-my)!important;right:auto!important;bottom:auto!important;background:var(--card)!important;
    border:1px solid var(--card-edge,var(--line-2))!important;box-shadow:0 2px 6px rgba(15,18,20,.16)!important;
    width:var(--m-tap)!important;height:var(--m-tap)!important;padding:0!important;transition:none}
  html[data-menu-dragging] .shell-open{box-shadow:0 6px 14px rgba(15,18,20,.22)!important;cursor:grabbing}
  /* While she types (a text field has focus, the keyboard is up) the button steps aside: it would cover the next field. */
  html[data-typing] .shell-open{display:none!important}
}
@media (prefers-reduced-motion:reduce){html #side,.shell-scrim{transition:none!important}}

/* ------------------------------------------------------------------------------------------------- section utilities */
:where(.m-cols){display:grid;grid-template-columns:repeat(var(--cols,2),minmax(0,1fr));gap:var(--m-gap)}
:where(.m-stack){display:flex;flex-direction:column;gap:var(--m-gap)}
:where(.m-stack)>*{min-width:0}
:where(.m-tap){min-width:var(--m-tap);min-height:var(--m-tap)}
:where(.m-chips){display:flex;flex-wrap:nowrap;gap:6px;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none}
:where(.m-chips)::-webkit-scrollbar{display:none}
:where(.m-chips)>*{flex:0 0 auto;white-space:nowrap}
@media (min-width:768px) and (not ((pointer:coarse) and (max-height:500px))){.m-only{display:none!important}}
@media (max-width:767px),(pointer:coarse) and (max-height:500px){
  :where(.m-cols){grid-template-columns:minmax(0,1fr)}
}
/* Tab rows and step bars stay one line up to 900px and on a phone on its side. */
@media (max-width:900px),(pointer:coarse) and (max-height:500px){
  :where(#view [role="tablist"],#view :is(.tour-activity-tabs,.deck15-tabs,.deck17-tabs,.deck17-research-tabs,.news-tabs-v12,.cp82-panel-tabs,.advanced-tabs-v3,.buyertabs)){
    display:flex;flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;max-width:100%}
  :where(#view [role="tablist"],#view :is(.tour-activity-tabs,.deck15-tabs,.deck17-tabs,.deck17-research-tabs,.news-tabs-v12,.cp82-panel-tabs,.advanced-tabs-v3,.buyertabs))>*{
    flex:0 0 auto;white-space:nowrap}
}
/* The listing video's zone header on a phone: its title and "+ Add photos or clips" share one row, the button
   compact (it reads "+ Add"; its full name stays its accessible name), so the frame under it keeps 47px more. */
@media (max-width:767px),(pointer:coarse) and (max-height:500px){
  #view .vm-head .htop{flex-wrap:nowrap;align-items:center;gap:12px}
  #view .vm-head h1{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #view .vm-head .tools{flex:none;width:auto}
  #view .vm-head .vm-add{min-height:var(--m-tap);height:var(--m-tap);padding:0 14px;font-size:0!important;white-space:nowrap}
  #view .vm-head .vm-add::before{content:"+ Add" / "";font-size:15px;font-weight:600}
}
/* The interface-scale dial only scales windows over 900px (js/dashboard-extensions.js); below that its row would do
   nothing, so it is not shown. */
@media (max-width:900px),(pointer:coarse) and (max-height:500px){#view .srow:has(.uiscale){display:none!important}}
/* More chips past the edge: the row fades there. */
[data-chips-more="end"]{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent)}
[data-chips-more="start"]{-webkit-mask-image:linear-gradient(90deg,transparent,#000 32px);mask-image:linear-gradient(90deg,transparent,#000 32px)}
[data-chips-more="both"]{-webkit-mask-image:linear-gradient(90deg,transparent,#000 32px,#000 calc(100% - 32px),transparent);mask-image:linear-gradient(90deg,transparent,#000 32px,#000 calc(100% - 32px),transparent)}

/* ------------------------------------------------------------------------------------------------- hover becomes tap */
:where(.tap-tip){position:relative;cursor:pointer;-webkit-tap-highlight-color:transparent}
:where(.tap-tip-pop){display:none;position:absolute;z-index:1000;left:0;top:calc(100% + 8px);width:max-content;
  max-width:min(320px,calc(100vw - 2 * var(--m-gutter)));padding:12px 14px;border:1px solid var(--card-edge,var(--line-2));
  border-radius:12px;background:var(--card);color:var(--ink);font-size:13.5px;font-weight:400;line-height:1.45;
  text-align:left;white-space:normal;box-shadow:0 4px 12px rgba(15,18,20,.14)}
.tap-tip[aria-expanded="true"]>.tap-tip-pop,.tap-tip:focus-visible>.tap-tip-pop{display:block}
@media (hover:hover) and (pointer:fine){.tap-tip:hover>.tap-tip-pop{display:block}}
/* At phone width the open tip's words show in one sheet on <body> (js/plinth-mobile.js), above every card and bar. */
.tap-sheet{display:block}
.tap-sheet[hidden]{display:none}
@media (max-width:767px),(pointer:coarse) and (max-height:500px){
  .tap-tip>.tap-tip-pop{display:none!important}
  :is(.m-sheet,.tap-tip-pop){position:fixed!important;left:calc(12px + var(--m-safe-l))!important;right:12px!important;
    top:auto!important;bottom:calc(12px + var(--m-safe-b))!important;width:auto!important;max-width:none!important;
    max-height:70dvh!important;overflow-y:auto!important;z-index:1000;border-radius:16px}
  :is(.m-sheet,.tap-tip-pop)::before{content:none!important}
}
