/* ============================================================
   LUMEN MOBILE LAYER ,  single owner for the phone shell
   ------------------------------------------------------------
   Replaces, in load order:
     mobile-ui/lumen-mobile.css
     mobile-ui/lumen-mobile-chrome.css
     mobile-ui/mobile-redesign.css
     mobile-ui/mobile-topbar.css

   Rules are scoped to the phone media query where they always were;
   the relative order of the four parts is unchanged. Verified at
   390 px against the pre-merge tree (home, study workspace, Reader).
   ============================================================ */

/* ============ LUMEN MOBILE ,  single authoritative block. Load AFTER core, BEFORE study views.
   (originally loaded at head position 2, merged here 2026-11-11) ============ */

/* ============================================================
   LUMEN MOBILE ,  single authoritative block. Load LAST.
   ============================================================ */

html, body, html *{
  -webkit-text-size-adjust: 100% !important;
  text-size-adjust: 100% !important;
}

html{
  background-color: var(--surface, #15151a) !important;
  min-height: 100vh;
  min-height: 100dvh;
  padding-top: env(safe-area-inset-top, 0px);
  box-sizing: border-box;
}
body{
  background: var(--bg);
  background-attachment: fixed;
}

/* ============================================================
   NAV HEIGHT ,  one variable, three uses, always in sync.
   The nav, the .view offset and #pxStudio all read --nav-h,
   so a gap between them is now impossible.
   ============================================================ */
:root{
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  /* Desktop default ,  matches the fixed 56px in core-styles-01.css */
  --nav-h: calc(56px + var(--safe-t));
}
/* Mobile only: the nav shrinks to 48px. */
@media (max-width: 820px){
  :root{ --nav-h: calc(42px + var(--safe-t)); }
}

.top-nav{
  height: var(--nav-h) !important;
  padding-top: var(--safe-t) !important;
  padding-bottom: 0 !important;
  padding-left: calc(12px + env(safe-area-inset-left, 0px)) !important;
  padding-right: calc(12px + env(safe-area-inset-right, 0px)) !important;
}
/* Desktop stops forcing a solid bar on the custom wallpaper skin: that skin
   paints translucent by design, and the bar must blur with it. On phones the
   explicit height/background/blur rules below keep their mobile behaviour. */
html:not([data-skin="custom"]) .top-nav{
  background: var(--surface) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.view{
  padding-top: calc(var(--nav-h) + var(--banner-h, 0px)) !important;
  padding-bottom: env(safe-area-inset-bottom, 0px) !important;
}
/* The brand is 56px tall in the base stylesheet; on a 48px mobile nav
   let it grow with the row instead of overflowing upward. */
.brand{ height: auto !important; align-self: center !important; }

@media (max-width: 820px){

  /* ---------- Top nav internals ---------- */
  .brand{ font-size: 20px !important; height: auto !important; }
  .top-nav .ibtn{
    width: 44px !important; height: 44px !important;
    min-width: 44px !important; min-height: 44px !important;
    border-radius: 9px !important;
  }
  .top-nav .ibtn svg{ width: 15px !important; height: 15px !important; }
  .ai-model-select{
    flex: 1 1 40px !important; min-width: 0 !important;
    max-width: 130px !important;
    font-size: 11px !important; padding: 5px 8px !important;
    border-radius: 9px !important;
  }
  .net-badge{ padding: 4px 6px !important; min-width: 30px !important; }
  .net-badge .net-text{ display: none !important; }

  /* ---------- Study rail: icon-only, 54px ---------- */
  .rail{
    width: 54px !important; min-width: 54px !important; max-width: 54px !important;
    flex: 0 0 54px !important;
    padding: 5px 3px !important;
    gap: 1px !important;
    /* The rail scrolls. It did not: the overflow was clipped, so on a phone
       with ten destinations in a column taller than the screen the last of
       them - the calendar - could not be reached at all, and there was no
       way to know it was there. The bar looks the same; it just moves now. */
    overflow-x: hidden !important;
    overflow-y: auto !important;
    overscroll-behavior: contain !important;
    scrollbar-width: none !important;
    background: var(--surface) !important;
  }
  .rail::-webkit-scrollbar{ display: none !important; }
  .rail button{
    width: 100% !important; height: auto !important;
    min-height: 44px !important;
    flex-direction: column !important;
    padding: 7px 0 !important;
    gap: 0 !important;
    border-radius: 8px !important;
    border: 1px solid transparent !important;
    background: transparent !important;
    flex: none !important;
  }
  .rail button > svg,
  .rail button > :is(i[data-lucide],svg[data-lucide]){ width: 18px !important; height: 18px !important; }
  .rail button > span{ display: none !important; }
  .rail button.on{
    background: color-mix(in srgb, var(--accent) 14%, transparent) !important;
    border-color: color-mix(in srgb, var(--accent) 38%, transparent) !important;
    color: var(--accent) !important;
  }
  .rail button.on::before{ display: none !important; }

  /* ---------- Study topbar: single scrollable row ---------- */
  #view-study .topbar{
    gap: 4px !important;
    padding: 0 6px !important;
    min-height: 44px !important;
    max-height: 44px !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    scrollbar-width: none !important;
    background: var(--surface) !important;
    backdrop-filter: none !important;
  }
  #view-study .topbar::-webkit-scrollbar{ display: none !important; }
  #view-study .topbar > *{ flex: 0 0 auto !important; }
  #view-study .brand{ font-size: 16px !important; }
  #view-study .brand .scrawl{ display: none !important; }
  .top-actions{ gap: 4px !important; flex-wrap: nowrap !important; margin-left: 0 !important; }
  .top-actions .btn{ padding: 5px 9px !important; font-size: 11px !important; }
  .top-actions .ibtn{
    width: 44px !important; height: 44px !important;
    min-width: 44px !important; min-height: 44px !important;
  }
  .top-actions .ibtn svg{ width: 13px !important; height: 13px !important; }
  .top-actions .chip{
    padding: 4px 8px !important; font-size: 10px !important;
    max-width: 110px !important;
  }
  .top-actions .chip .ellip{ max-width: 75px !important; }
  #nbSaveChip .nb-text{ display: none !important; }

  /* ---------- Generic vbar / tool-head ---------- */
  .vbar{ padding: 3px 8px !important; gap: 4px !important; min-height: 44px !important; max-height: 44px !important; }
  .vbar .vtitle{ font-size: 14px !important; }
  .vbar .rname{ max-width: 100px !important; font-size: 10px !important; }
  .vbar .btn{ padding: 5px 9px !important; font-size: 11px !important; }

  .tool-head{
    padding: 5px 8px !important; gap: 5px !important;
    min-height: 44px !important;
    background: var(--surface) !important;
  }
  .tool-head .tool-title{ font-size: 17px !important; }
  .tool-head .tool-sub{ display: none !important; }

  /* ---------- Home ---------- */
  #view-home > div{
    padding-left: 12px !important;
    padding-right: 12px !important;
    padding-bottom: 30px !important;
  }
  #view-home .pt-10{ padding-top: 1rem !important; }
  .hero-title{ font-size: clamp(34px, 11vw, 46px) !important; }
  .hero-sub{ font-size: 12px !important; margin-top: 8px !important; }
  .hero-note{ font-size: 8.5px !important; margin-top: 10px !important; padding: 3px 8px !important; }
  .home-search{
    margin: 14px auto 0 !important;
    padding: 8px 12px !important;
    background: var(--surface) !important;
  }
  .home-search input{ font-size: 16px !important; }
  .home-search kbd{ display: none !important; }
  .cat-label{ margin-top: 16px !important; margin-bottom: 6px !important; font-size: 10px !important; }
  .fallback-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 8px !important; }
  .tool-card{ padding: 9px !important; gap: 8px !important; }
  .tool-card .tc-icon{ width: 30px !important; height: 30px !important; }
  .tool-card .tc-icon svg{ width: 15px !important; height: 15px !important; }
  .tool-card h3{ font-size: 11.5px !important; white-space: normal !important; }
  .tool-card p{
    font-size: 9.5px !important;
    -webkit-line-clamp: 2 !important;
    display: -webkit-box !important;
    -webkit-box-orient: vertical !important;
    overflow: hidden !important;
    white-space: normal !important;
  }

  /* ---------- iOS zoom guard ---------- */
  input:not([type=range]):not([type=checkbox]):not([type=radio]):not([type=color]):not([type=file]),
  textarea, select{ font-size: 16px !important; }

  /* ---------- Dialogs ---------- */
  /* The width and the cap are gone; the full-screen rule further down owns the
     box now. Leaving "max-height: 92vh" here meant the settings panel stopped
     8% short of the bottom of the screen and showed a band of the page under
     itself - the black bar at the foot of the settings on a phone. */
  .dlg-head{ padding: 12px 14px 10px !important; }
  .dlg-title{ font-size: 17px !important; }
  .dlg-body{ padding: 12px 14px !important; gap: 10px !important; }
  .dlg-foot{ padding: 12px 14px !important; }
}

@media (max-width: 400px){
  .rail{ width: 48px !important; min-width: 48px !important; max-width: 48px !important; flex-basis: 48px !important; }
  .rail button > svg, .rail button > :is(i[data-lucide],svg[data-lucide]){ width: 16px !important; height: 16px !important; }
  .hero-title{ font-size: clamp(30px, 10vw, 40px) !important; }
  .tool-card p{ display: none !important; }
  .tool-card h3{ font-size: 11px !important; }
}

@media (pointer: coarse){
  .tool-card:hover{ transform: none !important; }
  .tool-card:hover .tc-icon{ transform: none !important; }
  .btn:hover{ transform: none !important; }
  .ibtn:hover{ transform: none !important; }
}

/* ============================================================
   Brand: force the dot inline, never wrap
   ============================================================ */
.brand{
  display: inline-flex !important;
  align-items: baseline !important;
  flex-wrap: nowrap !important;
  white-space: nowrap !important;
  flex-shrink: 0 !important;
}
.brand > span{
  display: inline-flex !important;
  align-items: baseline !important;
  gap: 0 !important;
  white-space: nowrap !important;
}
.brand em{
  display: inline !important;
  margin-left: 0 !important;
  animation: none !important;   /* the pulsing scale was fighting the layout */
}
.brand .brand-back{
  align-self: center !important;
  margin-right: 6px !important;
}

@media (max-width: 720px){
  .brand{ font-size: 20px !important; }
  .top-nav .brand{ font-size: 19px !important; }
}

/* ============================================================
   Chat composer: tighter so it never dominates the screen
   ============================================================ */
@media (max-width: 720px){
  /* Textarea shrinks to a single line by default */
  #chatIn{
    min-height: 44px !important;
    max-height: 100px !important;
    padding: 9px 12px !important;
    font-size: 16px !important;
    border-radius: 12px !important;
    line-height: 1.35 !important;
  }

  /* Send button matches the textarea height */
  #chatSend, #chatStop{
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    border-radius: 10px !important;
  }
  #chatSend svg{ width: 16px !important; height: 16px !important; }

  /* The whole composer block loses its padding and gaps */
  .composer{
    padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px)) !important;
    gap: 0 !important;
  }
  .inputrow{ gap: 6px !important; }
  .ctxrow{
    margin-bottom: 5px !important;
    gap: 6px !important;
    flex-wrap: wrap !important;
  }
  .ctxrow .sw{ font-size: 11px !important; }
  .ctxrow .sw .knob{ width: 24px !important; height: 14px !important; }
  .ctxrow .sw .knob::after{ width: 8px !important; height: 8px !important; top: 2px !important; left: 2px !important; }
  .ctxrow .sw input:checked + .knob::after{ left: 12px !important; }
  .ctxrow .seg button{ padding: 3px 8px !important; font-size: 10px !important; }
  .ctxrow .chip{ padding: 3px 7px !important; font-size: 10px !important; }
  .sysdet summary{ padding: 2px 0 !important; font-size: 9px !important; }

  /* Message bubbles also shrink */
  .msgs{ padding: 10px 10px !important; }
  .msg{ margin-bottom: 12px !important; max-width: 100% !important; }
  .msg .bubble{ font-size: 14px !important; line-height: 1.5 !important; }
  .msg.user .bubble{ padding: 8px 11px !important; }
  .msg.ai .bubble{ padding: 2px 3px 2px 9px !important; }
}

/* ============================================================
   Mobile pass 4 ,  chat composer, Study Desk, home tool cards.
   Placed last so it always wins the cascade on phones.
   ============================================================ */
@media (max-width: 820px){

  /* ---- Chat composer: MUCH thinner ---- */
  .study-view[data-view="chat"] .vbar{
    padding: 2px 8px !important;
    min-height: 44px !important;
    gap: 4px !important;
  }
  .study-view[data-view="chat"] .vbar .vtitle{
    font-size: 13px !important;
    font-style: normal !important;
    font-weight: 600 !important;
    font-family: var(--sans) !important;
  }
  .study-view[data-view="chat"] .vbar > .hint{ display: none !important; }

  /* Composer: hard-cap its height */
  .composer{
    padding: 5px 8px calc(6px + env(safe-area-inset-bottom, 0px)) !important;
    max-height: 130px !important;
    gap: 0 !important;
  }
  .sysdet{ margin-bottom: 2px !important; }
  .sysdet summary{ padding: 1px 0 !important; font-size: 9px !important; }
  .ctxrow{
    margin-bottom: 4px !important;
    gap: 4px !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    scrollbar-width: none !important;
  }
  .ctxrow::-webkit-scrollbar{ display: none !important; }
  .ctxrow > *{ flex: 0 0 auto !important; }
  .ctxrow .sw{ font-size: 10.5px !important; }
  .ctxrow .seg button{ padding: 2px 7px !important; font-size: 9.5px !important; }
  .ctxrow .chip{ padding: 2px 6px !important; font-size: 9.5px !important; max-width: 130px !important; }

  /* The textarea itself: single line by default */
  #chatIn{
    min-height: 44px !important;
    max-height: 48px !important;
    height: 44px !important;
    padding: 7px 10px !important;
    font-size: 16px !important;
    line-height: 1.25 !important;
    border-radius: 10px !important;
    overflow-y: auto !important;
  }
  #chatSend, #chatStop{
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    border-radius: 9px !important;
  }
  #chatSend svg{ width: 15px !important; height: 15px !important; }
  .inputrow{ gap: 5px !important; align-items: flex-end !important; }

  /* ---- Study Desk action buttons: scrollable row, no overflow ---- */
  #homeDesk .dash-qa{
    display: flex !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    gap: 6px !important;
    padding: 10px 12px 0 !important;
    scrollbar-width: none !important;
    -webkit-overflow-scrolling: touch !important;
  }
  #homeDesk .dash-qa::-webkit-scrollbar{ display: none !important; }
  #homeDesk .dash-qa .btn{
    flex: 0 0 auto !important;
    white-space: nowrap !important;
    min-width: auto !important;
    padding: 7px 12px !important;
    font-size: 12px !important;
    min-height: 44px !important;
    height: auto !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-indent: 0 !important;
    line-height: 1.15 !important;
  }
  #homeDesk .dash-qa .btn.primary{ color: var(--accent-ink) !important; }

  /* ---- Home tool cards: bigger tap targets, less cramped ---- */
  .fallback-grid{
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 10px !important;
  }
  .tool-card{
    padding: 12px 11px !important;
    gap: 10px !important;
    min-height: 66px !important;
  }
  .tool-card .tc-icon{
    width: 44px !important;
    height: 44px !important;
    border-radius: 10px !important;
  }
  .tool-card .tc-icon svg{ width: 19px !important; height: 19px !important; }
  .tool-card h3{ font-size: 13px !important; line-height: 1.25 !important; }
  .tool-card p{ font-size: 10.5px !important; }
}

/* ============================================================
   TOOL-CARD BADGES ,  small pills for "new" and "smart" tools
   ============================================================ */
.tool-card .tc-new{
  position:absolute;
  top:10px; right:10px;
  z-index:2;
  font:700 8.5px var(--mono);
  letter-spacing:.14em;
  text-transform:uppercase;
  padding:2px 7px;
  border-radius:99px;
  background:var(--accent);
  color:var(--accent-ink);
  box-shadow:0 2px 8px -2px color-mix(in srgb,var(--accent) 55%,transparent);
  pointer-events:none;
}
[data-skin="paper"] .tool-card .tc-new,
[data-skin="comfy"] .tool-card .tc-new{
  box-shadow:0 2px 6px -2px color-mix(in srgb,var(--accent) 45%,transparent);
}
/* ============================================================
   MOBILE USABILITY PASS (appended)
   ============================================================ */
@media (max-width: 820px){
  html, body { overflow-x: clip !important; }
  #app, .view, .shell, .study-view, .tool-body, .rbody, .vbody,
  .panel, .card, .box { min-width: 0; box-sizing: border-box; }
  img, canvas, video, svg { max-width: 100% !important; height: auto; }

  /* Touch targets */
  @media (pointer: coarse){
    .btn, .ibtn, button { min-height: 44px !important; min-width: 44px !important; }
  }

  /* Full-screen dialogs on phones

     The panel is meant to be the whole screen, and it was not: the box was
     given a height in viewport units, and the units it used were dropped by
     any browser that does not know them - so the box fell back to being only
     as tall as its content, and the settings stopped short of the bottom of
     the screen with a black band of the page showing underneath.

     The box is now pinned to the four edges and given no height of its own.
     That makes it exactly the screen whatever the viewport units mean, and
     the body inside it scrolls instead of deciding how tall the panel is. */
  dialog, .modal, .dlg, .overlay-card {
    width: 100vw !important;
    max-width: 100vw !important;
    height: auto !important;
    max-height: none !important;
    top: 0 !important;
    bottom: 0 !important;
    left: 0 !important;
    right: 0 !important;
    margin: 0 !important;
    border-radius: 0 !important;
    inset: 0 !important;
    padding: 0 !important;
  }
  /* The body of a full-screen panel takes the room the head leaves and
     scrolls inside it. Without this the body keeps its own cap - 66vh for
     the settings - and the panel is still shorter than the screen. */
  dialog > .dlg-body,
  dialog > .pref-body,
  .overlay-card > .dlg-body {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
  }

  /* Workspace panels become bottom sheets */
  .ws-win, [class*="ws-win"] {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    top: auto !important;
    width: 100vw !important;
    max-width: 100vw !important;
    max-height: 88vh !important;
    border-radius: 16px 16px 0 0 !important;
  }

  /* Dock: horizontal scroll, no overlap */
  .lsw-dock, .dock {
    left: 0 !important;
    right: 0 !important;
    bottom: env(safe-area-inset-bottom, 0px) !important;
    width: 100vw !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
  }

  /* The shared header and composer own their safe-area insets. */
  .view { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important; }
}

@media (max-width: 480px){
  .fallback-grid { grid-template-columns: 1fr !important; }
  .tool-card { min-height: 56px !important; }
}

/* ============================================================
   MOBILE OPTIMISATIONS & USABILITY (appended)
   ============================================================ */
@media (max-width: 820px){
  /* Smooth, momentum scrolling everywhere */
  * { -webkit-overflow-scrolling: touch; }

  /* Prevent long content overflow

     `anywhere` breaks a word in the middle to make it fit. That is a last
     resort for a single very long word - a URL, an identifier - and it is
     what turned the whiteboard's settings into "Expor / t PNG" and "Temp /
     lates": the words were not too long for the screen, they were too long
     for the column they had been squeezed into, and `anywhere` made them
     break rather than the column give way.

     `break-word` only breaks a word that cannot fit the line at all, and
     the panels below keep their width, so the words stay whole. */
  body, .view, .panel, .card, .bubble { word-wrap: break-word; overflow-wrap: break-word; }

  /* Long code and wide tables scroll inside their own region. Inline code
     and ordinary links keep their natural place in surrounding text. */
  table, pre, .code-block { max-width: 100%; overflow-x: auto; }
  pre, .code-block { display: block; }
  .list-row { min-height: 44px; }

  /* Hide non-essential decorative chrome on phones */
  .starfield, .bg-glow, .hero-note { display: none !important; }

  /* Bottom safe-area padding for fixed bars */
  .top-nav, .composer, .dock { padding-bottom: env(safe-area-inset-bottom, 0px) !important; }

  /* Text entry stays readable without stretching sliders, uploads, or buttons. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="button"]):not([type="submit"]):not([type="reset"]),
  textarea, select { font-size: 16px !important; padding: 10px 12px !important; }
  /* A box is not a field. The field's padding around a checkbox is padding
     around a mark drawn in a box, and it is what made every checkbox in the
     whiteboard's settings look like an empty field of its own. */
  input[type="checkbox"], input[type="radio"] {
    padding: 0 !important;
    min-width: 0 !important;
    min-height: 0 !important;
    font-size: inherit !important;
  }

  /* Images responsive */
  img { max-width: 100% !important; height: auto !important; }
}

/* Performance: reduce paint on low-end devices */
@media (prefers-reduced-motion: reduce), (max-width: 820px){
  .backdrop-blur, [class*="blur"] { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
}

/* LaTeX view mobile pass */
@media (max-width: 720px) {
  #view-latex-pdf .tp-tools { flex-wrap: wrap; gap: 6px; }
  #view-latex-pdf .lt-live { font-size: 12px; }
  #view-latex-pdf #ltSrc { min-height: 320px !important; font-size: 12.5px; }
  #view-latex-pdf .ltgal-grid { grid-template-columns: 1fr; }
  .lt-ai-card { width: 96vw; max-height: 92vh; }
  .lt-ai-diff { max-height: 180px; }
}

/* ============ LUMEN ,  mobile chrome compression
   (originally loaded at head position 3, merged here 2026-11-11) ============ */

/* ============================================================
   LUMEN ,  mobile chrome compression
   ------------------------------------------------------------
   Goals on phones (≤820 px):
     · one top bar, not three
     · no clipped empty-state text
     · floating pills re-anchored into the column
     · composer reachable without hunting
   ============================================================ */

@media (max-width: 820px) {

  /* ---------- 1. One top row, on every device ---------- */

  /* The contextual bar lives inside the global top row, so that row has to
     stay. Hiding it here is what left the study workspace and Praxis with no
     controls at all on a phone ,  the bar was laid out inside a display:none
     container, so every button in it was unclickable and every dropdown dead.
     What is redundant on a phone is each view's *own* header, not the shared
     row, so that is what goes instead. */
  body.study-mode > nav.top-nav,
  body.praxis-mode > nav.top-nav { display: flex !important; }

  /* The per-view headers duplicate the shared row: their controls have already
     been adopted into it, so on a phone they are a second, near-empty strip
     below it. The pieces that are genuinely their own (the rail toggle and the
     notebook status) move into the chrome sheet on phones. */
  #view-study > .topbar { display: none !important; }
  #view-praxis > .px-topbar { display: none !important; }

  /* ---------- 2. Single compact study topbar ------------------- */

  #view-study > .topbar {
    padding: 6px 10px !important;
    gap: 6px !important;
    min-height: 44px;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  #view-study > .topbar::-webkit-scrollbar { display: none; }

  #view-study > .topbar .brand {
    font-size: 15px;
    flex: none;
  }
  /* Hide the decorative scrawl on phones ,  it eats 40 px. */
  #view-study > .topbar .brand .scrawl { display: none; }

  #view-study > .topbar > .btn { padding: 6px 9px; font-size: 12px; flex: none; }
  #view-study > .topbar .top-actions { gap: 4px; flex: none; }
  #view-study > .topbar .chip { max-width: 140px; }

  /* ---------- 3. vbar wraps instead of squeezing --------------- */

  .study-view > .vbar {
    flex-wrap: wrap;
    row-gap: 6px;
    column-gap: 6px;
    padding: 8px 10px;
    align-items: center;
  }
  .study-view > .vbar .vtitle { flex: none; font-size: 14px; }
  .study-view > .vbar .hint {
    flex-basis: 100%;
    order: 99;
    font-size: 11.5px;
    line-height: 1.4;
    opacity: .75;
    margin: 0;
  }
  /* Chat's history / memory buttons were orphaned ,  bring them home. */
  .study-view[data-view="chat"] > .vbar button {
    flex: none;
    padding: 6px 10px;
    font-size: 12px;
  }
  .study-view[data-view="chat"] > .vbar .spacer { display: none; }

  /* ---------- 4. Empty-state that no longer clips -------------- */

  .chat-empty,
  .study-view .empty {
    max-width: 100% !important;
    padding: 18px 16px !important;
    box-sizing: border-box;
  }
  .chat-empty h2,
  .study-view .empty h2 {
    font-size: 22px !important;
    line-height: 1.25 !important;
    letter-spacing: -.01em;
    word-break: normal;
    hyphens: auto;
  }
  .chat-empty p,
  .study-view .empty p {
    font-size: 13.5px !important;
    line-height: 1.55 !important;
    max-width: 42ch;
    margin-inline: auto;
  }

  /* ---------- 5. Suggestions stack full width ------------------ */

  .sugs {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    width: 100% !important;
    max-width: 480px;
    margin-inline: auto;
  }
  .sugs .btn {
    width: 100% !important;
    padding: 12px 14px !important;
    font-size: 13px !important;
    text-align: center !important;
    justify-content: center;
  }

  /* ---------- 6. Stranded floating pills ----------------------- */

  /* The AI/Web segmented control and any right-floated chips that
     normally sit inline must not float off-column on phones. */
  .composer > .ctxrow,
  .composer .inputrow {
    flex-wrap: wrap;
    gap: 6px;
  }
  .composer .seg#chatModeSeg {
    flex: none;
    order: 20;
    margin-left: auto;
  }
  .composer .chip#provChip {
    order: 21;
    flex-basis: 100%;
    max-width: 100%;
    margin-top: 4px;
  }

  /* The "what to do" hint widget on the right of the chat header
     should collapse ,  it duplicates the empty-state text. */
  .study-view[data-view="chat"] .kbd-hint,
  .study-view[data-view="chat"] .hint-pill { display: none !important; }

  /* ---------- 7. Composer sits above the keyboard safely ------- */

  .composer { padding: 8px 10px calc(8px + env(safe-area-inset-bottom)); }
  .composer .inputrow textarea { font-size: 16px; padding: 10px 12px; min-height: 44px; }
  .composer .inputrow .btn { padding: 10px 12px; }

  /* ---------- 8. Rail (left icon strip) narrower ---------------- */

  #view-study .shell .rail {
    width: 54px !important;
    flex-basis: 54px !important;
  }
  #view-study .shell .rail button {
    padding: 10px 0 !important;
    justify-content: center !important;
  }
  #view-study .shell .rail button span:not(.badge) { display: none !important; }
  #view-study .shell .rail button i,
  #view-study .shell .rail button svg { margin: 0 !important; }
}

/* Very small phones ,  400px and below */
@media (max-width: 400px) {
  #view-study > .topbar { padding: 4px 8px !important; }
  #view-study > .topbar .brand { font-size: 14px; }
  .chat-empty h2 { font-size: 20px !important; }
  .chat-empty p  { font-size: 12.5px !important; }
  .sugs .btn     { font-size: 12.5px !important; padding: 11px 12px !important; }
}

/* ============ LUMEN MOBILE REDESIGN ,  touch targets, safe areas, overflow
   (originally loaded only in the phone media query; @media preserved) ============ */

/* ============================================================
   LUMEN MOBILE REDESIGN ,  new folder, desktop untouched.
   Loaded only on small screens via media attribute in app/index.html.
   ============================================================ */
@media (max-width: 820px) {
  :root {
    --m-touch: 44px;
    --m-gap: 12px;
    --m-radius: 14px;
  }

  /* Larger, comfortable tap targets everywhere */
  button, .btn, .ibtn, [role="button"] {
    min-height: var(--m-touch) !important;
    min-width: var(--m-touch) !important;
  }

  /* Override lumen-mobile pinned sizes */
  .top-nav .ibtn {
    width: 44px !important; height: 44px !important;
    min-width: 44px !important; min-height: 44px !important;
  }
  .ibtn, .btn.icon {
    width: 44px !important; height: 44px !important;
    min-width: 44px !important; min-height: 44px !important;
  }
  .btn, .btn.sm, .btn.primary {
    height: auto !important;
    min-height: var(--m-touch) !important;
    padding: 8px 14px !important;
  }
  #homeDesk .dash-qa .btn,
  #homeDesk .dash-qa .btn.primary {
    min-height: var(--m-touch) !important;
    height: auto !important;
  }
  .net-badge { min-height: var(--m-touch) !important; }

  /* Prevent horizontal overflow */
  html, body { overflow-x: hidden !important; }
  img, video, canvas, svg { max-width: 100% !important; height: auto !important; }

  /* Cards and panels breathe */
  .card, .panel, .tile, .box {
    border-radius: var(--m-radius) !important;
    padding: var(--m-gap) !important;
    margin-bottom: var(--m-gap) !important;
  }

  /* Typography tuned for small screens */
  body { font-size: 15px !important; line-height: 1.55 !important; }
  h1 { font-size: 22px !important; }
  h2 { font-size: 18px !important; }
  h3 { font-size: 16px !important; }

  /* Forms: full width inputs */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="button"]):not([type="submit"]):not([type="reset"]),
  textarea, select {
    box-sizing: border-box !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    font-size: 16px !important;
    padding: 10px 12px !important;
    border-radius: 10px !important;
  }

  /* …except the boxes, which are not fields.

     A checkbox and a radio are a fixed mark, not a line of text. The
     rule above handed them the field's whole width, so inside a label
     that sits beside a word they took the entire line and pushed that
     word into a column a few pixels wide. That is what made the
     whiteboard's settings read as "Expor / t PNG", "Temp / lates" and
     "Rese / t view", and what turned the Compact / Medium choice into
     two rows with a sliver of a third: the mark was as wide as the
     label, so the label had nowhere to stand.

     They keep their own size, and they do not inherit the field's
     padding either - padding on a checkbox is the padding of a box
     drawn around a mark, and it is why the mark read as an empty
     square in a row of its own. */
  input[type="checkbox"],
  input[type="radio"] {
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    border-radius: 0 !important;
    font-size: inherit !important;
    flex: none !important;
    accent-color: var(--accent);
  }

  /* Bottom safe-area padding for fixed bars */
  .view, main, #app {
    padding-bottom: calc(var(--safe-b, 0px) + 12px) !important;
  }

  /* Keep each screen's intended grid; collapse only when its own content
     cannot fit, instead of flattening every dashboard and card layout. */
  .grid, .tool-grid, .cards { gap: var(--m-gap) !important; }

  /* Scrollable horizontal rows keep momentum */
  .row, .topbar {
    -webkit-overflow-scrolling: touch !important;
    scroll-snap-type: x proximity !important;
  }

  /* The rail is a COLUMN, not a row.

     It was in the list above, so it was given a horizontal scroll
     snap - which it cannot use, because it scrolls vertically. Worse,
     the rail's own rule clips its overflow, so with the snap asking
     for horizontal movement and the clip refusing it, the column of
     icons could not be reached at all: the rail was a list with no
     way to scroll it. It scrolls vertically here, and the snap goes
     with the content. */
  .rail {
    scroll-snap-type: none !important;
  }
}

/* Phone tool directory: keep two readable columns on compact screens. */
@media (max-width: 480px) {
  .fallback-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 10px !important; }
  .tool-card { min-width: 0 !important; min-height: 88px !important; align-items: flex-start !important; }
  .tool-card h3 { font-size: 13px !important; line-height: 1.3 !important; overflow-wrap: normal !important; }
  .tool-card p {
    display: -webkit-box !important;
    -webkit-box-orient: vertical !important;
    -webkit-line-clamp: 2 !important;
    overflow: hidden !important;
    white-space: normal !important;
    font-size: 10.5px !important;
    line-height: 1.35 !important;
  }
}
@media (max-width: 360px) {
  .fallback-grid { grid-template-columns: 1fr !important; }
  .tool-card { min-height: 76px !important; }
}

/* ============ LUMEN ,  MOBILE TOP BAR, the phone's own two-row chrome
   (originally loaded LAST; every rule here is inside the phone media query,
    which preserves the "phone chrome wins over earlier phone rules" order) ============ */

/* ============================================================
   LUMEN ,  MOBILE TOP BAR
   ------------------------------------------------------------
   A separate system for phones. The desktop bar is one row, and
   its width decides how many of the open tool's buttons stay on
   screen. A phone cannot do that in 390 px, so the phone gets its
   own shape:

     row 1   chrome   back · title · timer · athena · settings ·
                      connection · more
     row 2   strip    the open view's own controls, icon only, one
                      line, scrollable

   Two consequences that the desktop rules get wrong:

     · The strip is measured against the leftover in the chrome
       row, so on a phone it kept four buttons and parked the
       rest. The strip has a line of its own; its budget is that
       line (see ctxBudget in app.js).

     · The overflow menu is a floating panel anchored to a
       button. On a phone it is a sheet off the bottom edge,
       full width, above the home indicator.

   Loaded last, and every rule in it is inside the phone media
   query, so the desktop row is not restyled by any of it.
   ============================================================ */

@media (max-width: 820px) {

  /* ---------- The bar's own measurements ---------- */

  body.m-topbar-on {
    --m-bar-h: 52px;
    --m-strip-h: 46px;
    /* What the shell has to clear. One number, read by the nav,
       the views and the sheet alike. */
    --nav-h: calc(var(--m-bar-h) + var(--m-strip-h) + var(--safe-t, 0px));
  }

  body.m-topbar-on .top-nav {
    height: var(--nav-h) !important;
    display: flex;
    flex-direction: column;
    /* The whiteboard is given a wrapping bar on a desktop, so that its
       forty controls can have a second line. On a phone the bar is two
       rows of its own, and a wrapping COLUMN container sends the
       second row off to the side instead of putting it underneath: the
       strip landed at x=334, on top of the chrome's own ellipsis. */
    flex-wrap: nowrap !important;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    padding-left: calc(8px + env(safe-area-inset-left, 0px)) !important;
    padding-right: calc(8px + env(safe-area-inset-right, 0px)) !important;
    padding-bottom: 0 !important;
    overflow: visible;
  }

  /* ---------- Row 1: the chrome ---------- */

  body.m-topbar-on .m-chrome {
    flex: 0 0 var(--m-bar-h);
    height: var(--m-bar-h);
    display: flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    overflow: hidden;
  }

  /* The wordmark is the desktop's title. The phone's title is the
     name of the view you are in, which is a different thing. */
  body.m-topbar-on .top-nav > .brand,
  body.m-topbar-on .top-nav > .ctx-grip,
  body.m-topbar-on .top-nav > .flex-1 {
    display: none !important;
  }

  body.m-topbar-on .m-back,
  body.m-topbar-on .m-title,
  body.m-topbar-on .m-more {
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    color: var(--fg);
    font: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    height: 44px;
    min-width: 44px;
    border-radius: 10px;
  }
  body.m-topbar-on .m-back { flex: 0 0 40px; }
  body.m-topbar-on .m-back svg { width: 44px; height: 44px; }

  /* The title is the one piece of text in the bar. It says which
     view you are in, which a row of identical squares cannot. */
  body.m-topbar-on .m-title {
    flex: 1 1 auto;
    min-width: 0;
    justify-content: flex-start;
    gap: 6px;
    padding: 0 6px;
    font: 600 15px/1 var(--sans);
    letter-spacing: -0.01em;
    color: var(--fg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  body.m-topbar-on .m-title svg {
    width: 15px; height: 15px; flex: none; opacity: .7;
  }
  body.m-topbar-on .m-title span {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  body.m-topbar-on .m-title:active { background: color-mix(in srgb, var(--fg) 8%, transparent); }

  body.m-topbar-on .m-more { flex: 0 0 40px; }
  body.m-topbar-on .m-more svg { width: 19px; height: 19px; }

  /* The app chrome inside row 1: icons, same size, same rhythm. */
  body.m-topbar-on .m-chrome > .ibtn,
  body.m-topbar-on .m-chrome > .btn.icon {
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    min-height: 44px !important;
    border-radius: 10px !important;
    padding: 0 !important;
    justify-content: center !important;
  }
  body.m-topbar-on .m-chrome > .ibtn svg,
  body.m-topbar-on .m-chrome > .btn.icon svg { width: 18px !important; height: 18px !important; }

  /* The connection badge is a fixed dot on the desktop, pinned to the
     corner of the window. In the row it has to be in the flow or it
     floats over the first control. */
  body.m-topbar-on .m-chrome > .net-badge {
    position: static !important;
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    box-shadow: none !important;
  }
  body.m-topbar-on .m-chrome > .net-badge .net-text { display: none !important; }
  body.m-topbar-on .m-chrome > .net-badge .net-dot {
    width: 8px !important; height: 8px !important; margin: 0 !important;
  }

  /* The focus timer is off on a phone.

     It is a ring, a clock and a settings button - three things the
     row does not have, and a timer you did not start is the first
     thing that should not be in your face. It is still one tap away
     in the More sheet, which switches it on; the class on the body
     is what brings the ring back into the row. */
  body.m-topbar-on .m-chrome > .pomo { display: none !important; }
  body.m-topbar-on.m-pomo-on .m-chrome > .pomo { display: flex !important; }
  body.m-topbar-on .m-chrome > .pomo { gap: 4px !important; flex: 0 0 auto; }
  body.m-topbar-on .m-chrome > .pomo .pomo-btn { width: 44px !important; height: 44px !important; }
  body.m-topbar-on .m-chrome > .pomo .pomo-btn svg.ring { width: 44px !important; height: 44px !important; }
  body.m-topbar-on .m-chrome > .pomo .pomo-ic svg { width: 11px !important; height: 11px !important; }
  body.m-topbar-on .m-chrome > .pomo .pomo-meta b { font-size: 12px !important; }
  body.m-topbar-on .m-chrome > .pomo .pomo-meta .lbl { display: none !important; }
  body.m-topbar-on .m-chrome > #pomoCfgBtn { display: none !important; }

  /* Mimir keeps her own mark; she is a taskbar button, not a
     toolbar control. */
  body.m-topbar-on .m-chrome > .uchat-fab {
    position: static !important;
    width: 44px !important; height: 44px !important;
    min-width: 44px !important; min-height: 44px !important;
    flex: 0 0 40px !important;
    transform: none !important;
  }

  /* The notebook's save state is a dot on a phone. The word "Saved"
     is two more characters the row does not have. */
  body.m-topbar-on .m-chrome > .nb-chip {
    padding: 0 !important; width: 44px !important; min-width: 44px !important;
    height: 44px !important; border: 0 !important; background: none !important;
  }
  body.m-topbar-on .m-chrome > .nb-chip .nb-text { display: none !important; }

  /* These three live in the phone's More sheet instead of the row.

     A command palette is a keyboard instrument, the notebook's state is a
     dot, and the display button is a desktop idea. None of them earns a
     permanent square in a 390 px row; all of them is one tap away in a
     sheet where each one is named.

     The sidebar's own toggle is NOT in this list. It used to be, and the
     rail was then the one part of the workspace a phone could not
     control: the button that shows and hides the left-hand column was
     in a sheet, behind an ellipsis, while the column itself was always
     on screen taking 54 px of it. The button is worth a square of its
     own - it is the one that gives the width back. */
  body.m-topbar-on .top-nav .m-chrome > #cpTrigger,
  body.m-topbar-on .top-nav .m-chrome > #nbSaveChip,
  body.m-topbar-on .top-nav .m-chrome > #timebarBtn {
    display: none !important;
  }
  /* …and it has to out-specify the desktop's own rules, which hide it
     unless the study workspace is on screen. */
  body.m-topbar-on.study-mode .top-nav .m-chrome > #railToggle,
  body.m-topbar-on .top-nav .m-chrome > #railToggle {
    display: flex !important;
    align-items: center;
    justify-content: center;
  }

  /* ---------- Row 2: the feature strip ---------- */

  /* One ellipsis, not three.

     The desktop's own overflow button is a second one in the same row,
     and the strip's own makes a third. On a phone the strip's is the
     one that opens every control of the view, so the desktop's is
     hidden: three dots in one bar is three ways to ask the same
     question and no way to tell them apart. */
  body.m-topbar-on #ctxMoreBtn { display: none !important; }

  /* A strip with nothing in it is a blank line under the bar, so it
     is taken away and the shell closes up under a one-line bar. */
  body.m-topbar-on.m-strip-empty {
    --nav-h: calc(var(--m-bar-h) + var(--safe-t, 0px));
  }
  body.m-topbar-on.m-strip-empty .m-strip { display: none !important; }

  body.m-topbar-on .m-strip {
    flex: 0 0 var(--m-strip-h);
    height: var(--m-strip-h);
    position: relative;
    min-width: 0;
    display: flex;
    align-items: center;
    border-top: 1px solid var(--line2);
    background: var(--surface);
    /* The strip's own line runs the whole width of the screen.

       The bar has eight pixels of padding at its sides so that the
       buttons do not touch the glass, and the strip's top edge was drawn
       inside that padding. So the line stopped short at both ends: the
       bar had an edge across the middle of the screen and two half-edges
       at the sides of it, which in the contrast skin read as a broken
       rule rather than a border.

       The strip now reaches the edges of the screen and keeps the
       padding for its contents, which is what the padding was for. */
    margin-left: calc(-8px - env(safe-area-inset-left, 0px));
    margin-right: calc(-8px - env(safe-area-inset-right, 0px));
    padding-left: calc(8px + env(safe-area-inset-left, 0px));
    padding-right: calc(8px + env(safe-area-inset-right, 0px));
    /* Nothing in the strip may paint outside it.

       A control taller than the line - the quiz's competency slider, a
       select with the browser's own chrome on it - used to draw over the
       bar's bottom edge. That edge is a bright line in the contrast
       skin, so the bar had a line along its left and right ends and a
       gap in the middle where a control had covered it. A control that
       does not fit the line is cut now, not laid over the page. */
    overflow: hidden !important;
  }
  /* The fade at the right edge says there is more of the row to the
     right. It used to be a gradient in the background colour laid over
     the row - and a fade to the background colour does not dim the last
     control, it ERASES it, so the control nearest the ellipsis was half
     gone and looked broken. In the contrast skin, where the surface and
     the ink are at opposite ends, it drew a bright band straight across
     the row and took the icons with it.

     The scrollable rows have their own mask for this (see .m-overflow
     below), which fades the row rather than painting over it. The strip
     does not need a second one, so there is no overlay here now. */
  body.m-topbar-on .m-strip::after { content: none; }
  /* The strip's own ellipsis: every control the open view has, by
     name, in a list you can read. It is outside the contextual row so
     the row's layout pass never counts it, never parks it and never
     moves it - it is always there. */
  body.m-topbar-on .m-all {
    order: 1;
    flex: 0 0 40px;
    width: 44px;
    height: 44px;
    margin: 0 4px 0 auto;
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    color: var(--soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    cursor: pointer;
    position: relative;
    z-index: 1;
  }
  body.m-topbar-on .m-all svg { width: 19px; height: 19px; }
  body.m-topbar-on .m-all:active { background: color-mix(in srgb, var(--fg) 8%, transparent); }

  /* The ellipsis appears only when it has something to open.

     It is the way to reach the controls that did not fit in the row, so it
     is shown when - and only when - the row had to park one. When
     everything fits, the button opens a sheet of controls that are all
     already on screen, and a three-dot button that is always there reads
     as furniture the user has to look past on every view.

     `.m-all-idle` is set by the strip's own sync, which counts the
     controls the overflow pass parked. */
  body.m-topbar-on.m-all-idle .m-all { display: none !important; }

  body.m-topbar-on #topContextual {
    display: flex !important;
    align-items: center;
    gap: 4px;
    flex: 1 1 auto !important;
    /* The whiteboard is given `order: 99` on this row, which was to
       push its controls to the end of the bar. In the strip that order
       put it AFTER the ellipsis, so the ellipsis ended up on the left
       and the controls on the right. */
    order: 0 !important;
    min-width: 0;
    width: auto;
    max-width: 100%;
    height: 100%;
    padding: 0 8px;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    flex-wrap: nowrap !important;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    background: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  body.m-topbar-on #topContextual::-webkit-scrollbar { display: none !important; }
  body.m-topbar-on #topContextual > * { flex: 0 0 auto !important; }

  /* Every control in the strip is a square with one picture in it. */
  body.m-topbar-on #topContextual button,
  body.m-topbar-on #topContextual a {
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    min-height: 44px !important;
    padding: 0 !important;
    gap: 0 !important;
    justify-content: center !important;
    border-radius: 10px !important;
    flex: 0 0 auto !important;
  }
  body.m-topbar-on #topContextual button svg,
  body.m-topbar-on #topContextual a svg { width: 18px !important; height: 18px !important; }
  body.m-topbar-on #topContextual .ctx-label { display: none !important; }

  /* Readouts are values, not labels: a page number and a zoom
     percentage keep their text, at a size that fits a strip. */
  body.m-topbar-on #topContextual .pgnav,
  body.m-topbar-on #topContextual .zgroup {
    display: inline-flex !important;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto !important;
  }
  body.m-topbar-on #topContextual .pgnav input,
  body.m-topbar-on #topContextual #rCount,
  body.m-topbar-on #topContextual #rPct {
    font-size: 16px !important;
    color: var(--soft);
    min-width: 0;
  }
  body.m-topbar-on #topContextual .pgnav input {
    width: 44px !important; height: 44px !important;
    padding: 0 4px !important; text-align: center;
  }

  /* A select stays a select ,  it is the right control for "PNG /
     JPEG / WebP" ,  but it stops being a wide one. */
  body.m-topbar-on #topContextual select,
  body.m-topbar-on #topContextual input[type="text"],
  body.m-topbar-on #topContextual input[type="search"] {
    height: 44px !important;
    min-height: 44px !important;
    font-size: 16px !important;
    padding: 4px 6px !important;
    max-width: 116px !important;
    border-radius: 9px !important;
  }
  body.m-topbar-on #topContextual .seg {
    flex: 0 0 auto !important;
    display: inline-flex !important;
    border-radius: 10px !important;
    overflow: hidden;
  }
  body.m-topbar-on #topContextual .seg button {
    min-height: 44px !important;
    padding: 0 8px !important;
    min-width: 44px !important;
    justify-content: center !important;
  }
  body.m-topbar-on #topContextual .seg button svg { width: 16px !important; height: 16px !important; }
  body.m-topbar-on #topContextual .seg button .ctx-label { display: none !important; }

  /* ---------- Rows that are wider than the phone ---------- */

  /* A row that scrolls sideways, with nothing to say so, looks cut off.
     The fade at the right edge is the sign, and it comes off again when
     the row has been scrolled to its end - so the last control in the
     row is never the one that looks broken. */
  body.m-topbar-on .m-overflow {
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
  }
  body.m-topbar-on .m-overflow.m-overflow-end {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 100%);
  }
  body.m-topbar-on .m-overflow {
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  body.m-topbar-on .m-overflow::-webkit-scrollbar { display: none !important; }

  /* ---------- The whiteboard's own toolbar ---------- */

  /* The whiteboard keeps its toolbar in a row of its own, and two of
     its controls were taking the whole row: the stroke-size slider
     and the colour palette. The slider was as wide as the screen, the
     palette as wide again, and the controls between them - undo, redo,
     the zoom readout - were squeezed down to a character wide, which
     is how "100%" came out as "7 2 %". */
  body.m-topbar-on #wbToolHead .top-actions #wbSize,
  body.m-topbar-on #wbToolHead .top-actions input[type="range"] {
    width: 84px !important;
    flex: 0 0 auto !important;
  }
  body.m-topbar-on #wbToolHead .top-actions #wbColors { flex: 0 0 auto !important; }
  /* The colour circles were the size of a touch target.

     Every button on a phone is given a 44 px box so a finger can find it,
     and a swatch is a button - so the eight circles of the palette were
     44 px each, 350 px of a 374 px row, and every other control in the
     toolbar was pushed off the screen. A circle of colour is not a
     control that needs a finger-sized box around it; it is a picture of
     a colour, and it wants to be the size of the other pictures in the
     row.

     The class is `.swatch` on one build and `.wb-swatch` on the other, so
     the rule that was meant to size them down matched only half of them
     and the circles stayed at the touch size. Both names are covered here
     so neither can drift again.

     Twenty-four is the size of the other pictures in the row, with room
     for the selected colour's ring: that ring is drawn seven pixels out
     from the circle, so a circle of thirty reached thirty-seven and was
     shaved by the edge of the line it sat in. */
  body.m-topbar-on #wbToolHead .top-actions #wbColors .swatch,
  body.m-topbar-on #wbToolHead .top-actions #wbColors .wb-swatch {
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    min-height: 44px !important;
    padding: 0 !important;
    border-width: 2px !important;
  }
  /* The selected swatch is drawn larger than the others, and a row that
     is exactly as tall as the row of swatches clips the top of it: the
     tick inside the selected colour was cut in half. The row is given
     room for the swatch to be bigger than its box - and the header is
     allowed to show it, because the ring is drawn outside the circle. */
  body.m-topbar-on #wbToolHead,
  body.m-topbar-on #wbToolHead .tool-head {
    overflow: visible !important;
  }
  body.m-topbar-on #wbToolHead .top-actions #wbColors .swatch.active,
  body.m-topbar-on #wbToolHead .top-actions #wbColors .swatch.on,
  body.m-topbar-on #wbToolHead .top-actions #wbColors .wb-swatch.active,
  body.m-topbar-on #wbToolHead .top-actions #wbColors .wb-swatch.is-on { transform: none !important; }
  /* "Add to Library" is a mark on a phone.

     The board's toolbar spells it out in full - the word beside the
     library mark - and on a 390 px row that word is worth more than
     several of the forty controls beside it. The mark says the same
     thing, and the button keeps its title and its label for anyone who
     needs to read it. */
  body.m-topbar-on #wbToolHead .top-actions #wbSaveLib .ctx-label { display: none !important; }
  body.m-topbar-on #wbToolHead .top-actions #wbSaveLib { flex: 0 0 auto !important; }

  /* The tiles have to fit the line.

     Every button on a phone is given a 44 px box, and the board's tiles
     are buttons - so a row that is meant to be 40 px tall held 44 px of
     button, and the row was clipped. Compact showed one row with the top
     and the bottom of every tile shaved off; Medium showed one whole row
     and a slice of the next, because 44 + 6 + 44 is more than the 86 px
     two whole rows are given. Changing the setting from Compact to
     Medium changed nothing a finger could see, because the row was
     already being cut.

     The tiles are drawn at 38 px on a desktop, and 40 is the line height
     that was measured from them, so that is what they are here. */
  body.m-topbar-on #wbToolHead .top-actions .ibtn {
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    min-height: 44px !important;
    padding: 0 !important;
    border-radius: 8px !important;
  }
  body.m-topbar-on #wbToolHead .top-actions .ibtn svg,
  body.m-topbar-on #wbToolHead .top-actions .ibtn :is(i[data-lucide],svg[data-lucide]) {
    width: 18px !important;
    height: 18px !important;
  }
  /* The slider is a control, not a field: it kept the form's padding and
     came out with its track inset by twelve pixels a side. */
  body.m-topbar-on #wbToolHead .top-actions input[type="range"] {
    padding: 0 !important;
    font-size: inherit !important;
    border-radius: 0 !important;
  }

  /* More of the whiteboard's toolbar at once. Its row is one line that
     scrolls sideways, so most of its forty controls are off the screen
     with nothing to say so - the user has to know they are there. Two
     lines show twice as many, and the space they take is space the
     floating dock was covering anyway. */
  body.m-topbar-on #wbToolHead .top-actions {
    flex-wrap: wrap !important;
    /* The height is the desktop's own calculation, so the Compact /
       Medium setting means what it says: a whole number of lines, at the
       height the tiles are drawn at, with the gap between them and
       nothing left over. Compact is one line of 40; Medium is two lines
       of 40 with 6 between them.

       The vertical padding the row used to carry is gone, because it was
       counted against this height - 8 px of padding in a box sized for
       86 px of rows left 78 px for rows that need 86, and the second
       line was always cut short. The room the selected colour needs is
       given to it inside its own circle instead, where no clipping can
       reach it. */
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    max-height: calc(var(--ctx-rows, 2) * var(--wb-line, 40px) + (var(--ctx-rows, 2) - 1) * 6px);
    overflow-x: auto !important;
    overflow-y: auto !important;
    align-content: flex-start;
  }
  body.m-topbar-on #wbToolHead .top-actions #wbColors .swatch.on {
    outline: none !important;
    box-shadow: 0 0 0 2px var(--accent) !important;
  }
  body.m-topbar-on #wbToolHead .top-actions > * { flex: 0 0 auto !important; }
  body.m-topbar-on #wbToolHead .top-actions .mini {
    flex: 0 0 auto !important;
    white-space: nowrap !important;
  }
  body.m-topbar-on #wbToolHead .top-actions .vsep { flex: 0 0 auto !important; }
  /* A control with a word in it must not have the word broken across
     lines to fit. */
  body.m-topbar-on #wbToolHead .top-actions .lsw-dock-b span,
  body.m-topbar-on #wbToolHead .top-actions button { white-space: nowrap !important; }

  /* ---------- The whiteboard's settings panel ---------- */

  /* The panel is a dialog on a desktop and a sheet on a phone, and it was
     neither: it kept the desktop's inset, so it stopped short of the top
     and the bottom of the screen and left a band of the board showing
     under it.

     On a phone it is the whole screen. Its rows are two across, because a
     name like "Load a saved board" needs the room: three across - which
     is what the touch-sized boxes gave - left each name a column a few
     pixels wide, and a name in a column that narrow is broken between its
     letters rather than wrapped between its words. That is where "Expor /
     t PNG" and "Temp / lates" came from. */
  body.m-topbar-on .wb-settings {
    inset: 0 !important;
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
  }
  body.m-topbar-on .wbs-head { padding: 14px 16px !important; }
  body.m-topbar-on .wbs-head h2 { font-size: 17px !important; }
  body.m-topbar-on .wbs-body { padding: 4px 16px 24px !important; }
  body.m-topbar-on .wbs-sec { padding: 14px 0 !important; }
  body.m-topbar-on .wbs-note { font-size: 12.5px !important; }
  body.m-topbar-on .wbs-grid { gap: 8px !important; }
  body.m-topbar-on .wbs-check {
    flex: 1 1 132px;
    min-width: 0;
    min-height: 44px;
    gap: 8px !important;
    font-size: 12.5px !important;
    padding: 8px 10px !important;
    /* A name is a name. It must not be broken between its letters to fit
       a box, and it must not be shrunk to nothing either. */
    overflow-wrap: normal !important;
    word-break: keep-all !important;
    text-align: left !important;
  }
  body.m-topbar-on .wbs-check input[type="checkbox"],
  body.m-topbar-on .wbs-check input[type="radio"] {
    flex: none !important;
    width: 18px !important;
    height: 18px !important;
    min-width: 18px !important;
    min-height: 18px !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  body.m-topbar-on .wbs-ic,
  body.m-topbar-on .wbs-ic svg { width: 17px !important; height: 17px !important; }
  body.m-topbar-on .wbs-chip { min-height: 44px !important; }
  body.m-topbar-on .wbs-foot { padding: 12px 16px !important; }
  body.m-topbar-on .wbs-foot .btn { flex: 1 1 auto !important; }

  /* ---------- The study workspace's own rows ---------- */

  /* The Reader's leftover row was a bar.

     Its controls have been moved into the strip, and what was left behind
     was the file's name in a row with a rule under it: a bar across the
     top of the page, with the document pushed down and cut off underneath
     it. In the contrast skin, where every rule is a bright line, that bar
     was the brightest thing on the screen and it drew a second edge under
     the bar's own.

     The name stays - it is worth knowing which document is open - but it
     stops being a bar: no rule under it, no panel behind it, and a line's
     worth of height instead of a row's. */
  body.m-topbar-on #view-study .study-view[data-view="reader"] > .vbar {
    min-height: 0 !important;
    max-height: none !important;
    padding: 3px 12px !important;
    border-bottom: 0 !important;
    background: none !important;
    flex-wrap: nowrap !important;
    overflow: hidden !important;
  }
  body.m-topbar-on #view-study .study-view[data-view="reader"] > .vbar .rname {
    border-left: 0 !important;
    padding-left: 0 !important;
  }

  /* ---------- The study workspace's own floating dock ---------- */

  /* The dock is a row of controls over the bottom of the page, and the
     last of them is Hide - the control that puts the row away.

     On a phone every button in it was given the 44 px touch box, so the
     row was forty pixels wider than the screen. It scrolled, and the
     Hide control was the last thing in a scrolling row: off the right
     edge, with the finger asked to find it. So the switcher could not
     be put away even though it was right there.

     The boxes go back to the size they are drawn at and the row fits, so
     every control in it - Hide included - is under the thumb without
     being hunted for.

     The three layout buttons go as well: tiling panels side by side and
     staggering them are things a wide window does, and on a phone they
     are three buttons' worth of room the Hide control needed. */
  body.m-topbar-on .lsw-dock {
    left: 8px !important;
    right: 8px !important;
    transform: none !important;
    flex-wrap: nowrap !important;
    justify-content: flex-start !important;
    max-width: none !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: calc(5px + env(safe-area-inset-bottom, 0px));
  }
  body.m-topbar-on .lsw-dock::-webkit-scrollbar { display: none !important; }
  body.m-topbar-on .lsw-dock-b {
    flex: 0 0 auto !important;
    width: 44px !important;
    min-width: 44px !important;
    height: 44px !important;
    min-height: 44px !important;
    padding: 0 !important;
  }
  body.m-topbar-on .lsw-dock-b svg,
  body.m-topbar-on .lsw-dock-b :is(i[data-lucide],svg[data-lucide]) { width: 17px !important; height: 17px !important; }
  body.m-topbar-on .lsw-dock-tools { flex: 0 0 auto !important; }
  body.m-topbar-on .lsw-dock-tools .lsw-dock-b[aria-label^="Tile"],
  body.m-topbar-on .lsw-dock-tools .lsw-dock-b[aria-label^="Split into rows"],
  body.m-topbar-on .lsw-dock-tools .lsw-dock-b[aria-label^="Stagger"] { display: none !important; }
  /* The Hide control used to be pinned to the end of the row with an
     opaque patch behind it, so that it stayed under the thumb while the
     row scrolled. The patch was the problem: it was the colour of the
     panel laid over the bar, so it painted out the bar's own outline
     where it sat - in the contrast skin that was a bright band across
     the bottom of the screen - and it covered the edge of the control
     beside it. The row fits now, so the control is simply there and
     there is nothing to paint over anything. */
  body.m-topbar-on .lsw-dock-tools .lsw-dock-b:last-child {
    position: static;
    background: none;
    box-shadow: none;
  }
  /* The dock floats over the page, so the page has to be taller than the
     page it floats over. */
  body.m-topbar-on #view-study .rbody,
  body.m-topbar-on #view-study .study-view { padding-bottom: 64px !important; }

  /* ---------- Sheets ---------- */

  /* Mimir is a floating window on a desktop: a panel that sits beside
     the work and can be dragged and resized. On a phone there is no
     beside to float in, and a 350 px window in the middle of the
     screen covers the page it is supposed to be about. It becomes a
     sheet of its own, under the bar and over everything else. */
  body.m-topbar-on #uchat {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    top: var(--nav-h) !important;
    bottom: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    height: auto !important;
    max-height: none !important;
    border-radius: 0 !important;
    z-index: 200 !important;
  }
  body.m-topbar-on #uchat .uchat-resize { display: none !important; }
  /* The prompt is a long sentence and the box is a third of the screen
     wide, so the placeholder wraps to two lines - and a one-line box
     clips the second one. */
  body.m-topbar-on #uchat .uchat-in { min-height: 58px !important; }

  /* The overflow menu is a sheet off the bottom edge. The panel is
     positioned by the script that opens it, so these have to win
     against an inline position. */
  body.m-topbar-on .pop.ctx-menu {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    top: auto !important;
    bottom: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    max-height: 72dvh !important;
    overflow-y: auto !important;
    overscroll-behavior: contain;
    padding: 10px 10px calc(14px + env(safe-area-inset-bottom, 0px)) !important;
    gap: 4px !important;
    border-radius: 18px 18px 0 0 !important;
    animation: m-sheet-in 0.18s ease-out;
  }
  body.m-topbar-on .pop.ctx-menu > * {
    width: 100% !important;
    min-height: 46px !important;
    justify-content: flex-start !important;
  }
  body.m-topbar-on .pop.ctx-menu .ctx-adopted,
  body.m-topbar-on .pop.ctx-menu .ibtn {
    width: 100% !important;
    height: auto !important;
    min-width: 0 !important;
    min-height: 46px !important;
    padding: 8px 12px !important;
    gap: 12px !important;
    justify-content: flex-start !important;
    border-radius: 12px !important;
    font-size: 14px !important;
  }
  body.m-topbar-on .pop.ctx-menu .ctx-menu-label {
    font-size: 14px !important;
    white-space: normal !important;
  }

  /* The phone's own sheet: the tools list and the app's overflow.
     It is above the cat and the loader - a sheet with a cat walking
     across it is a sheet you are reading through a parade. */
  body.m-topbar-on .m-sheet {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 10010;
    max-height: 76dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--surface);
    color: var(--fg);
    border-top: 1px solid var(--line2);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -12px 40px -12px rgba(0, 0, 0, 0.6);
    padding: 6px 0 calc(14px + env(safe-area-inset-bottom, 0px));
    animation: m-sheet-in 0.18s ease-out;
  }
  body.m-topbar-on .m-sheet-grip {
    width: 44px; height: 4px; border-radius: 99px;
    background: var(--line2);
    margin: 6px auto 8px;
  }
  body.m-topbar-on .m-sheet-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 2px 16px 8px;
    font: 700 11px/1 var(--mono);
    letter-spacing: .14em; text-transform: uppercase;
    color: var(--soft);
  }
  body.m-topbar-on .m-sheet-sec {
    padding: 10px 16px 4px;
    font: 700 10px/1 var(--mono);
    letter-spacing: .14em; text-transform: uppercase;
    color: var(--soft);
    opacity: .8;
  }
  body.m-topbar-on .m-sheet-row {
    display: flex; align-items: center; gap: 12px;
    width: 100%;
    min-height: 48px;
    padding: 8px 16px;
    background: none; border: 0;
    color: var(--fg);
    font: 500 15px/1.2 var(--sans);
    text-align: left;
    cursor: pointer;
  }
  body.m-topbar-on .m-sheet-row:active { background: color-mix(in srgb, var(--fg) 7%, transparent); }
  body.m-topbar-on .m-sheet-row .m-sheet-ico {
    width: 44px; height: 44px; flex: none;
    display: grid; place-items: center;
    border-radius: 9px;
    background: var(--surface-2);
    color: var(--fg);
  }
  body.m-topbar-on .m-sheet-row .m-sheet-ico svg { width: 16px; height: 16px; }
  body.m-topbar-on .m-sheet-row .m-sheet-txt { min-width: 0; }
  body.m-topbar-on .m-sheet-row .m-sheet-txt small {
    display: block; font-size: 11.5px; color: var(--soft); margin-top: 2px;
  }
  body.m-topbar-on .m-sheet-row.is-on .m-sheet-ico { color: var(--accent); }

  /* ---------- What the bar replaces ---------- */

  /* Three headers for one place is two too many.

     The phone's bar already says which view you are in, so the study
     workspace's own two header rows are left with the parts that
     are not in the bar: the notebook you are in, and the buttons that
     did not fit. The repeated titles - the breadcrumb's current
     segment and the row's own heading - go, because the bar is
     standing right above them saying the same thing. */
  body.m-topbar-on #view-study .bc-seg.bc-current,
  body.m-topbar-on #view-study .bc-sep + .bc-seg.bc-current,
  body.m-topbar-on #view-study .study-view .vbar .vtitle,
  body.m-topbar-on #view-study .ls-crumbs {
    display: none !important;
  }
  body.m-topbar-on #view-study .breadcrumbs { padding: 4px 12px !important; }

  /* The phone now has a bar of its own, so the notice that says the
     app is built for a desktop has nothing left to say. */


  /* The shell has to clear a bar that is two rows tall. */
  body.m-topbar-on .view {
    padding-top: calc(var(--nav-h) + var(--banner-h, 0px)) !important;
  }

  /* Nothing may be wider than the screen. A guide column that is
     396 px on a 390 px phone scrolls the whole page sideways. */
  body.m-topbar-on .guide-wrap { max-width: 100% !important; width: 100% !important; }

  /* The chrome sheet is opened by the phone's own module, so it is
     dismissed the same way. */
  body.m-topbar-on .m-sheet-scrim {
    position: fixed; inset: 0; z-index: 10009;
    background: rgba(0, 0, 0, 0.45);
    animation: m-fade-in 0.16s ease-out;
  }
}

@keyframes m-sheet-in {
  from { transform: translateY(14px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes m-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .m-sheet, .m-sheet-scrim, .pop.ctx-menu { animation: none !important; }
}

/* One 48px bar on whiteboard and the study viewer (7d.13): hide the
   per-view header so only the global row + contextual controls remain,
   recovering ~120px of canvas on a phone. Desktop is untouched.
   (The rule was nested @media inside @media, the only nesting in this
   file, which changed nothing about which devices match -- flattened.) */
@media (max-width: 820px) {
  #wbToolHead { display: none !important; }
  #view-study .topbar { min-height: 48px !important; }
  #view-study .vbar { min-height: 48px; }
  #wbStage, #wbCv { touch-action: none; overscroll-behavior: contain; }
  body.m-topbar-on.m-compact { --m-bar-h: 48px; --m-strip-h: 42px; }
  body.m-topbar-on.m-compact .m-chrome > .ibtn,
  body.m-topbar-on.m-compact .m-chrome > .btn.icon,
  body.m-topbar-on.m-compact #topContextual button,
  body.m-topbar-on.m-compact #topContextual a { width: 44px !important; height: 44px !important; min-width: 44px !important; min-height: 44px !important; }
}

/* (7d.12) Two global floors, stated once at the end of the mobile cascade:
   every interactive element at least 44px, every input/select/textarea at
   16px so iOS cannot focus-zoom. padding, not font-size, buys the target. */
@media (max-width: 820px) {
  button, a, [role="button"], input, select, textarea { min-height: 44px; }
  button, [role="button"] { min-width: 44px; }
  input, select, textarea { font-size: 16px; }
  /* Range/checkbox/radio are exempt: their glyphs are not touchable pixels,
     and forcing 44px height breaks the switch/knob geometry. */
  input[type="range"], input[type="checkbox"], input[type="radio"] { min-height: 0; min-width: 0; }
}

