/* --------------------------------------------------------------------------
   The shell: a column of areas on the left, the work on the right.
   On a phone the column becomes a drawer, because a phone has room for one
   thing at a time.
   -------------------------------------------------------------------------- */
.app-shell{min-height:100dvh;display:flex}
#nav{width:236px;flex:0 0 236px;background:var(--brand);color:#fff;
  display:flex;flex-direction:column;position:sticky;top:0;height:100dvh}

.navtop{padding:16px 16px 12px;display:flex;align-items:center;gap:8px}
.brandlink{display:flex;align-items:center;gap:10px;text-decoration:none;color:#fff;
  flex:1;min-width:0}
.brandlink img{width:30px;height:30px}
.brandlink .wm{font-family:FrankRuhl,'Assistant',serif;font-size:17px;font-weight:500}

.navlist{flex:1;overflow-y:auto;padding:4px 10px 10px;display:flex;flex-direction:column;gap:1px;
  /* His, 15 October 2026: "it should be the same green as the rest of the app" —
     the browser's grey-and-white bar on a computer; the sub-menus' own (.nvsub). */
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.28) transparent}
.navlist::-webkit-scrollbar{width:6px}
.navlist::-webkit-scrollbar-track{background:transparent}
.navlist::-webkit-scrollbar-thumb{background:rgba(255,255,255,.24);border-radius:3px}
.navlist::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.4)}
/* ⚠⚠ NOTHING IN THE LIST MAY SHRINK — 22 September 2026, his and a rebbi's:
   *"when click an item from the menu in the side panel it doesnt work … only
   when clicking the header then clicking within that page does it work."*
   `.nvsub` scrolls, and a flex item that scrolls has a minimum height of
   NOUGHT — so whenever the menu was taller than the screen the browser took
   the overflow out of the open sub-lists instead of scrolling the list. On a
   phone copy at 390×844 with the carets open, Attendance's one-row list showed
   6px of its 32px; the rows kept their geometry inside that sliver, and the
   thing painted where "Mark attendance" appeared to be was the Bussing header
   underneath. A tap went to the Bussing hub. Every child under every caret was
   the same, on the desktop sidebar too. `flex:none` on every child of the
   list: the list scrolls, as it was always meant to, and an open sub-list is
   as tall as what is in it. → tools/probe_menu.cjs measured it. */
.navlist>*{flex:none}
.nv{display:flex;align-items:center;gap:8px;text-decoration:none;color:rgba(255,255,255,.86);
  font-size:15px;font-weight:600;padding:9px 12px;border-radius:9px;line-height:1.3}
.nv:hover{background:rgba(255,255,255,.10);color:#fff}
.nv.on{background:rgba(255,255,255,.17);color:#fff}
.nv.soon{color:rgba(255,255,255,.5);font-weight:500}
.nv.soon:hover{color:rgba(255,255,255,.8)}
.nv i{margin-left:auto;font-style:normal;font-size:10px;font-weight:700;
  text-transform:uppercase;letter-spacing:.8px;opacity:.6;
  border:1px solid rgba(255,255,255,.3);border-radius:4px;padding:1px 5px}

/* ---- Classes, which opens in place ---------------------------------------
   A button rather than a link, because it has nowhere of its own to go — the
   classes underneath it are the destinations. So it needs the button reset that
   a link does not.
   ------------------------------------------------------------------------- */
.nv.nvx{width:100%;background:none;border:0;cursor:pointer;text-align:left;
  font-family:inherit}
.nv.nvx .caret{margin-left:auto;border:0;padding:0;opacity:.65;font-size:15px;
  transform:rotate(0deg);transition:transform .15s}
.nv.nvx.open .caret{transform:rotate(90deg)}

/* ---- a parent with a screen of its own -----------------------------------
   Attendance: the word is a link to the rebbi's screen, the caret opens the
   rest of the morning underneath. Two targets in one row, because one control
   cannot honestly do both — tapping "Attendance" should take a rebbi to his
   class, not make him open a menu first.

   The row is laid out by the navlist, so the link and its toggle are pulled
   onto one line here rather than each taking a row of their own.
   ------------------------------------------------------------------------- */
.nvrow{display:flex;align-items:stretch;gap:2px}
.nvrow .nv{flex:1;min-width:0}
.nvtog{flex:0 0 34px;display:flex;align-items:center;justify-content:center;
  background:none;border:0;cursor:pointer;color:rgba(255,255,255,.7);
  border-radius:8px;padding:0}
.nvtog:hover{background:rgba(255,255,255,.12);color:#fff}
.nvtog .caret{font-style:normal;font-size:15px;line-height:1;
  transform:rotate(0deg);transition:transform .15s}
.nvtog.open .caret{transform:rotate(90deg)}
/* A thumb needs more than a mouse pointer does, and this one sits right beside a
   link that goes somewhere else — a near miss should not navigate. */
@media (max-width:899px){ .nvtog{flex:0 0 44px} .nvrow .nv{padding-right:6px} }

/* The classes themselves. Indented, quieter than the areas above them, and the
   kita leads because that is the name the yeshiva says out loud.

   CAPPED, and scrolling on its own. Thirteen rows — twelve classes and the
   archive — dropped into a menu that already had ten pushed Academics and
   everything under it off the bottom, and made the whole sidebar scroll. Now
   only this list scrolls and the areas below it stay where they were.

   The cap is deliberately not a round number of rows: it lands mid-row so half
   a class is always visible at the edge, which says "there is more here" far
   better than a scrollbar does. `overscroll-behavior: contain` stops a flick
   inside this list carrying on into the drawer once it reaches the end. */
.nvsub{display:flex;flex-direction:column;gap:1px;margin:1px 0 4px;
  max-height:206px;overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.28) transparent}
.nvsub::-webkit-scrollbar{width:6px}
.nvsub::-webkit-scrollbar-track{background:transparent}
.nvsub::-webkit-scrollbar-thumb{background:rgba(255,255,255,.24);border-radius:3px}
.nvsub::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.4)}

/* A soft edge wherever there is more list. Landing on כיתה ח׳ scrolls the list
   so it is in view, and the top then cut off cleanly at a row boundary — which
   read as though the classes began at 4th Grade and Nursery did not exist. The
   fade says "there is more this way" without adding furniture. Toggled from
   nav.js, because CSS cannot ask whether a box is scrolled. */
.nvsub.fade-up{-webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 15px);
               mask-image:linear-gradient(to bottom,transparent 0,#000 15px)}
.nvsub.fade-down{-webkit-mask-image:linear-gradient(to top,transparent 0,#000 15px);
                 mask-image:linear-gradient(to top,transparent 0,#000 15px)}
.nvsub.fade-up.fade-down{
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 15px,
                                     #000 calc(100% - 15px),transparent 100%);
  mask-image:linear-gradient(to bottom,transparent 0,#000 15px,
                             #000 calc(100% - 15px),transparent 100%)}
.nvc{display:flex;align-items:baseline;gap:9px;text-decoration:none;
  color:rgba(255,255,255,.74);font-size:13.5px;font-weight:600;
  padding:7px 12px 7px 24px;border-radius:8px;line-height:1.3}
.nvc:hover{background:rgba(255,255,255,.09);color:#fff}
.nvc.on{background:rgba(255,255,255,.15);color:#fff}
/* The class leads; the rebbi sits to the right of it, quieter, and is the part
   that gets cut if the drawer is narrow — you can find 3rd Grade without being
   told whose it is, but not the other way round. */
.nvc .k{flex:none;font-size:13.5px}
.nvc .r{margin-left:auto;text-align:right;color:rgba(255,255,255,.5);
  font-size:11.5px;font-weight:500;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nvc:hover .r,.nvc.on .r{color:rgba(255,255,255,.7)}
/* The archive, and it should read like one. */
.nvc.quiet{color:rgba(255,255,255,.5);font-weight:500;margin-top:3px}
.nvc.quiet:hover{color:rgba(255,255,255,.8)}
.nvc.loading{color:rgba(255,255,255,.45);font-weight:500;font-style:italic}

.navfoot{border-top:1px solid rgba(255,255,255,.16);padding:10px;
  padding-bottom:calc(10px + env(safe-area-inset-bottom))}
.navme{padding:10px 12px 4px;line-height:1.35}
.navme b{display:block;font-size:14px;font-weight:600}
.navme span{font-size:11.5px;opacity:.6}
.navout{width:100%;margin-top:8px;background:rgba(255,255,255,.13);border:0;color:#fff;
  border-radius:8px;padding:9px;font:600 13.5px 'Assistant',sans-serif;cursor:pointer}
.navout:hover{background:rgba(255,255,255,.22)}

/* ---- folding the menu away -------------------------------------------------
   Menachem, 12 August, marking twenty desks on an iPad held landscape: "on ipad
   i should be able to press the menu button to collapse the menu so i have a
   bigger marking grid."

   ⚠ THIS IS A TABLET AND DESKTOP CONTROL ONLY. Below 900px the menu is already
   a drawer and is already out of the way; folding it there would be a second
   answer to a question that has one. An iPad in landscape is 1024–1366 CSS
   pixels, which is the far side of that line — so the menu is a permanent 236px
   column, a fifth of the screen, on the one device this screen was designed for.

   IT FOLDS TO A RAIL, NEVER TO NOTHING. A control that vanishes is not a
   collapse, it is a disappearance, and the way back has to be in the place the
   way out was. 236px becomes 54px: the seal, which is still the way home, and
   the same button.
   -------------------------------------------------------------------------- */
/* ⚠ `width` AS WELL AS `flex-basis`. When the rail stacks these the navtop turns
   into a column, `flex:0 0 34px` starts meaning HEIGHT, and the button shrank to
   the 14px of its own glyph — a tap target a third of the size, in the one state
   where it is the only control on the screen. Measured, not noticed. */
.navfold{flex:0 0 34px;width:34px;height:34px;display:none;align-items:center;
  justify-content:center;background:rgba(255,255,255,.13);border:0;border-radius:9px;
  color:#fff;font-size:16px;line-height:1;cursor:pointer;padding:0}
.navfold:hover{background:rgba(255,255,255,.24)}
.navfold:focus-visible{outline:2px solid #fff;outline-offset:2px}

@media (min-width: 900px){
  .navfold{display:flex}
  #nav{transition:width .16s ease, flex-basis .16s ease}
  body.navshut #nav{width:54px;flex:0 0 54px}
  /* The list and the footer are not narrowed, they are gone. A 54px rail of
     truncated words would be a menu you cannot read and cannot use. */
  body.navshut .navlist,
  body.navshut .navfoot{display:none}
  body.navshut .navtop{flex-direction:column;gap:10px;padding:10px 8px}
  body.navshut .brandlink{flex:none}
  body.navshut .brandlink .wm{display:none}

  /* ⚠⚠ SOMEBODY HAS TO PAY THE TOP INSET, AND ABOVE 900px NOBODY WAS —
     16 September 2026. Menachem, having tried three machines: *"its all the
     tabs at the top on an ipad not on pc and phone"*, then *"even on my app the
     top tabs in landscape arent working"*. Landscape, and not portrait, IS this
     media query: an iPad is 820-834px standing up and 1024-1366 lying down, so
     turning it crosses exactly this line.

     Every page in the app carries `viewport-fit=cover` and
     `apple-mobile-web-app-status-bar-style: black-translucent`, which together
     mean the app is drawn UNDERNEATH the iPad's status bar and must hold its
     own content clear of it. Below 900px `.topbar` does that — `padding-top:
     env(safe-area-inset-top)`, twelve lines down from here. Up here `.topbar`
     is `display:none`, because the sidebar is the navigation, AND NOTHING TOOK
     OVER THE JOB. So the strip — 40px tall, the first thing in `.work`, sitting
     at y=0 — has its top twenty-odd pixels under the status bar, which belongs
     to iOS and swallows what lands on it. The tabs are drawn, they are correct,
     and half of each one is behind a piece of the system.

     ⚠ IT IS NOT ONLY THE STRIP. The sidebar's seal — the way home — is at the
     top of `#nav` and was under the same bar, and so is the first line of every
     screen that does not build its own green header.

     ⚠ AND IT IS A NO-OP WHERE THERE IS NO INSET. On a desktop, on Android and
     in a browser tab `env(safe-area-inset-top)` is 0px, so nothing moves — which
     is why it could sit here unnoticed while working perfectly on his PC.

     ⚠ THE BARS THAT STILL PAY IT THEMSELVES UP HERE MUST STOP, or they pay it
     twice. There are three, and WHICH three was read out of the stylesheets
     rather than assumed — the first draft of this block guessed at a fourth and
     broke it:

       · `.rbar` (records.css) keeps `height: 62px + inset` above 900
       · `#previewbar` keeps `padding-top: 9px + inset` at every width

     ⚠ `.bar` IS DELIBERATELY LEFT ALONE, and that too was read rather than
     assumed. style.css still styles it as a green 60px top bar with a name in
     it — but NOTHING carries it that way any more: the four places that use the
     class today (davening.html, photoload.html, archive.js, daventhemes.js) are
     all PROGRESS bars, and none of them wants a rule about status bars. Fixing
     a top bar nobody has, at the price of touching the davening board, is not a
     trade. It is written down because the next person to read style.css will
     see that rule and reach the same wrong conclusion the first draft did.

     ⚠ `.abar` IS NOT ONE OF THEM, and assuming it was is what the check caught.
     attendance.css's own 900px block already resets it to
     `position:static; padding:15px 22px 17px` — no inset at all — so those five
     screens were under the status bar in landscape for exactly the same reason
     every other screen was, and `.work` above is their whole fix. Overriding
     their padding here took the desktop bar from 15px to 11px, which is a
     change to five live screens in payment for nothing.

     ⚠ AND THE STICKY ONES NEED `top`, NOT JUST PADDING. A sticky `top: 0` is
     measured against the WINDOW, and the window starts under the status bar —
     so once the page is scrolled the bar climbs back under it. `.work .rbar`
     rather than `.rbar` because records.css is loaded AFTER this file and would
     otherwise win; `#previewbar` needs no such help because style.css is loaded
     BEFORE it. */
  #nav{padding-top:env(safe-area-inset-top)}
  .work{padding-top:env(safe-area-inset-top)}
  .work .rbar{height:62px;top:env(safe-area-inset-top)}
  #previewbar{padding-top:9px;top:env(safe-area-inset-top)}
}

/* ---- the work ------------------------------------------------------------ */
.work{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{display:none}
#scrim{display:none}

/* ---- phone --------------------------------------------------------------- */
@media (max-width: 899px) {
  .app-shell{display:block}
  #nav{position:fixed;top:0;left:0;z-index:40;transform:translateX(-100%);
    transition:transform .18s ease;box-shadow:6px 0 24px rgba(0,0,0,.24);width:264px}
  body.navopen #nav{transform:none}
  #scrim{display:block;position:fixed;inset:0;background:rgba(23,26,33,.45);z-index:30;
    opacity:0;pointer-events:none;transition:opacity .18s}
  body.navopen #scrim{opacity:1;pointer-events:auto}

  .topbar{display:flex;align-items:center;gap:12px;background:var(--brand);color:#fff;
    padding:0 14px;height:calc(56px + env(safe-area-inset-top));
    padding-top:env(safe-area-inset-top);position:sticky;top:0;z-index:20}
  .topbar #burger{background:rgba(255,255,255,.13);border:0;color:#fff;width:38px;height:38px;
    border-radius:9px;font-size:18px;line-height:1;cursor:pointer;flex:none}
  .topbar .t{font-size:17px;font-weight:700}
  .topbar .heb{margin-left:auto;font-family:FrankRuhl,'Assistant',serif;font-size:15px;
    opacity:.75}
  body.navopen{overflow:hidden}
}

/* A printed page never wants the phone's header. It only ever showed inside the
   narrow media query, so this had never come up — until the burger started being
   built for every screen, and two of the screens that had been missing it are
   pages whose whole purpose is to be printed and carried. */
@media print{ .topbar{display:none !important} }
/* ⚠ AND NEVER THE MENU, OR ITS SHADOW — 15 October 2026, his, on a printed
   elective list: "whenever you make me a list there is a dark shade on the
   left". A Letter page is 816px wide, under the 899px phone rule above, so in
   print the menu became the phone's drawer: fixed, slid off to the left, and
   still casting its 24px shadow onto the sheet's left edge. Every printed page
   inside the shell carried it. */
@media print{ #nav, #scrim{display:none !important;box-shadow:none !important} }

/* ---- the honest "not built yet" page ------------------------------------- */
.soonwrap{width:100%;max-width:640px;margin:0 auto;padding:38px 22px 70px}
.soonwrap h1{font-size:28px;font-weight:700;margin:0 0 4px;letter-spacing:-.5px}
.soonwrap .kicker{font-size:12px;text-transform:uppercase;letter-spacing:.9px;
  color:var(--ink-3);font-weight:700;margin:0 0 10px}
.soonwrap .blurb{font-size:16.5px;line-height:1.65;color:var(--ink-2);margin:0 0 24px}
.soonbox{background:var(--sand-soft);border:1px solid var(--sand-line);color:var(--sand-ink);
  border-radius:11px;padding:15px 18px;font-size:14.5px;line-height:1.65}
.soonbox b{font-weight:700}
.soonwrap .backto{display:inline-block;margin-top:24px;color:var(--ink-2);font-size:14.5px}

/* ---- the admin index ----------------------------------------------------- */
.adminwrap{width:100%;max-width:820px;margin:0 auto;padding:26px 22px 70px}
.adminwrap h1{font-size:26px;font-weight:700;margin:0 0 4px;letter-spacing:-.4px}
.adminwrap .lede{color:var(--ink-2);font-size:15.5px;margin:0 0 22px;max-width:60ch}
.adminlist{display:grid;gap:10px;grid-template-columns:1fr}
a.adm{display:block;text-decoration:none;color:inherit;background:var(--panel);
  border:1px solid var(--line);border-radius:11px;padding:15px 18px;
  box-shadow:0 1px 2px rgba(23,26,33,.04)}
a.adm:hover{border-color:var(--brand);box-shadow:0 2px 10px rgba(20,82,79,.09)}
a.adm b{display:flex;align-items:center;gap:9px;font-size:16.5px;font-weight:600;
  margin-bottom:3px}
a.adm b i{font-style:normal;font-size:10px;font-weight:700;text-transform:uppercase;
  letter-spacing:.8px;color:var(--sand-ink);background:var(--sand-soft);
  border:1px solid var(--sand-line);border-radius:4px;padding:1px 6px}
a.adm span{font-size:14px;color:var(--ink-2);line-height:1.55}
a.adm.soon{opacity:.72}
/* ⚠ THE ONE CARD THAT STARTS A PRINTER — 2 September 2026, the emergency class
   lists. A coloured LEFT EDGE and not a red card: docs/COLORS.md spends red on
   "somebody must act", and a whole red panel sitting permanently in the Classes
   hub would read as something already wrong rather than as something to reach
   for when it is. The same treatment the maintenance queue gives an unsafe job.
   ⚠ And the colour is never the message — the word "Emergency" is the first
   word of the label, which is what a colourblind reader and a printed page
   both get. */
a.adm.urgent{border-left:4px solid var(--crit)}
a.adm.urgent b{color:var(--crit-ink)}
a.adm.urgent:hover{border-color:var(--crit);border-left-color:var(--crit);
  box-shadow:0 2px 10px rgba(208,59,59,.13)}
@media (min-width: 760px){ .adminlist{grid-template-columns:1fr 1fr} }

/* HIS SHORTCUTS, pinned at the top of the menu — 24 September 2026,
   paintPins() in nav.js, chosen with Customize on the front door. */
.nvpins{display:flex;flex-direction:column;gap:1px;margin:0 0 8px;padding:0 0 8px;
  border-bottom:1px solid rgba(255,255,255,.14)}
.nvpins[hidden]{display:none}
.nvpinh{margin:6px 12px 4px;font-size:11px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:rgba(255,255,255,.6)}

/* A TEACHER'S MENU IS HEADINGS, NOT FOLDERS — 25 September 2026, teacherMenu()
   in nav.js. My class · The school · Ask for, each over lines one tap deep.
   The same quiet capitals as "Your shortcuts" above, so the menu has one kind
   of heading and not two. */
.nvsec{margin:12px 12px 3px;font-size:11px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:rgba(255,255,255,.6)}

/* SEARCH THE APP — 7 October 2026, menusearch.js. His: a magnifying glass at
   the top of the menu that opens a search for everything but the boys. The
   glass is the fold button's twin, so the menu's top bar has one kind of
   button; on a phone (no fold button) it sits at the right of the bar. */
.navglass{flex:0 0 34px;width:34px;height:34px;display:flex;align-items:center;
  justify-content:center;background:rgba(255,255,255,.13);border:0;border-radius:9px;
  color:#fff;cursor:pointer;padding:0;margin-left:auto}
.navglass:hover{background:rgba(255,255,255,.24)}
.navglass:focus-visible{outline:2px solid #fff;outline-offset:2px}
.navglass .icn{width:18px;height:18px}
body.navshut .navglass{margin-left:0}

.msk{position:fixed;inset:0;z-index:60;background:rgba(23,26,33,.42);display:flex;
  align-items:flex-start;justify-content:center;padding:70px 16px 16px}
.msd{width:100%;max-width:560px;max-height:calc(100vh - 100px);overflow:auto;
  background:var(--panel);border-radius:14px;box-shadow:0 18px 50px rgba(0,0,0,.22)}
.msq{display:flex;align-items:center;gap:10px;padding:14px 16px;
  border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--panel)}
.msq .icn{width:20px;height:20px;color:var(--ink-3);flex:none}
.msq input{flex:1;min-width:0;border:0;outline:0;font:inherit;font-size:18px;
  font-weight:500;color:var(--ink);background:none;-webkit-appearance:none}
.msq input::-webkit-search-cancel-button{display:none}
.msx{border:0;background:none;color:var(--ink-2);font:inherit;font-size:14px;
  font-weight:600;cursor:pointer;padding:6px}
.msg{padding:10px 0 4px}
.msg h4{margin:0;padding:6px 18px;font-size:11px;font-weight:700;letter-spacing:.8px;
  text-transform:uppercase;color:var(--ink-3)}
.msr{display:flex;align-items:center;gap:12px;padding:10px 18px;text-decoration:none;color:var(--ink)}
.msr:hover,.msr.on{background:var(--brand-soft)}
.msic{flex:none;width:34px;height:34px;border-radius:9px;background:var(--bg);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center;
  color:var(--brand);font-size:13px;font-weight:700}
.msic .icn{width:16px;height:16px}
.mstx{display:block;min-width:0;color:var(--ink)}
.mstx b{display:block;font-size:16px;font-weight:600;color:var(--ink)}
.mstx mark{background:none;color:var(--brand);text-decoration:underline;text-underline-offset:2px}
.mssub{display:block;font-size:13px;color:var(--ink-3);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
/* A Hebrew title ("לכו נרננה") reads right to left but sits beside its icon,
   like every other line — not across the box at the far edge. */
.mstx [dir="auto"]{text-align:left}
/* A boy in the search — his face first (14 October 2026). */
.msboy .avatar{flex:none}
.msnoface{display:block;font-size:12px;color:var(--warn-ink)}
.msnone{margin:0;padding:16px 18px;font-size:14px;color:var(--ink-3)}
.msfoot{margin:0;padding:10px 18px 14px;font-size:12.5px;color:var(--ink-3);
  border-top:1px solid var(--line-2)}
@media (max-width: 600px){
  .msk{padding:0}
  .msd{max-width:none;height:100%;max-height:none;border-radius:0}
}
@media print{ .msk,.navglass{display:none!important} }
