/* ===== The desktop roster grid, one table split in panes (Plan 16, spec 2026-10-17 §1) =====

   The grid stays ONE table. gridsplit.js measures it and sets, on each
   .grid-pane[data-grid-split]:
     data-gmode = plain   everything fits: one table, as it always was
                  split   the staff group (drag, staff, select) is fixed; the
                          week (the days + Total) scrolls with .grid-scroll;
                          the extras (data-gx cells) are pinned to the right
                          and scroll on their own (--gx-off)
                  cards   too narrow even for three days (cards.css)
                  measure a transient pass at natural widths
     .g-compact    under 1100 px of grid width
   and the widths, in px: --gs-l-staff / --gs-l-sel (the sticky left offsets
   of the staff and select columns), --gs-staff-w, --gs-week-w, --gx-w (the
   extras' visible width), --gs-clip-w, --gx-off, and per extras key K
   --gx-r-K (its sticky `right`) and --gx-cl-K (how much of its left is
   hidden behind the week).

   How the split works: every extras cell is sticky on the right, at the
   offset that lines the extras block up against the grid's right edge, and
   clip-path hides the part that has scrolled out of the extras pane. .gs-clip
   is only as wide as what the split shows and clips the rest
   (overflow-x:clip is not a scroll container, so the sticky cells and the
   sticky thead still answer to .grid-scroll), so the extras' hidden part
   adds no scroll width: .grid-scroll's own range is exactly the week's.

   Without a data-gmode (no JS yet, or the print page, which has no
   .grid-pane) none of this applies and the grid looks as it did before.
   Nothing in split mode may change a column's width — the offsets were
   measured without it — so the split rules only move, clip and paint. */

/* the arrows: hidden unless the grid is split */
.gs-nav{display:none}
.grid-pane[data-gmode="split"] .gs-nav{display:block;position:sticky;top:0;left:0;height:0;z-index:5}
.gs-arrow{position:absolute;top:6px;width:28px;height:28px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--border,#e3dccb);border-radius:50%;background:rgba(255,255,255,.95);
  box-shadow:var(--shadow,0 1px 3px rgba(0,0,0,.15));color:var(--accent,#A8842C);
  font-size:calc(12px * var(--fs, 1));line-height:1;cursor:pointer}
.gs-arrow[hidden]{display:none}
.gs-arrow:disabled{opacity:.3;cursor:default}
.gs-arrow:focus-visible{outline:2px solid var(--accent,#A8842C);outline-offset:1px}
.gs-arrow[data-pane="week"][data-dir="-1"]{left:calc(var(--gs-staff-w, 0px) + 4px)}
.gs-arrow[data-pane="week"][data-dir="1"]{left:calc(var(--gs-staff-w, 0px) + var(--gs-week-w, 0px) - 32px)}
.gs-arrow[data-pane="extras"][data-dir="-1"]{left:calc(var(--gs-staff-w, 0px) + var(--gs-week-w, 0px) + 4px)}
.gs-arrow[data-pane="extras"][data-dir="1"]{left:calc(var(--gs-staff-w, 0px) + var(--gs-week-w, 0px) + var(--gx-w, 0px) - 32px)}

/* natural widths: the table is as wide as its columns want, not the pane */
.grid-pane[data-gmode="measure"] .grid,
.grid-pane[data-gmode="split"] .grid{width:max-content}

/* the clip wrapper: as wide as the split shows; what lies beyond is cut off
   and scrolls nowhere */
.grid-pane[data-gmode="split"] .gs-clip{width:var(--gs-clip-w);overflow-x:clip;overflow-y:visible}

/* no bottom scrollbar: each pane scrolls with its arrows, Shift+wheel or a
   drag (Chrome/Edge; Firefox keeps its bar — see the scrollbar note in
   layout.css: its scrollbar-width cannot hide one axis only) */
.grid-pane[data-gmode="split"] .grid-scroll::-webkit-scrollbar:horizontal{height:0}
/* nor while measuring: a bar there could bring on the vertical one and
   change the width being measured */
.grid-pane[data-gmode="measure"] .grid-scroll::-webkit-scrollbar:horizontal{height:0}
/* a mouse drag scrolling a pane (gridsplit.js): the hand closes and no text
   is picked up on the way */
.grid-pane.gs-dragging,.grid-pane.gs-dragging *{cursor:grabbing !important;user-select:none}

/* the staff group stays put: drag at 0 (app.css), staff after it (app.css,
   --gs-l-staff), and the select column after that, with the shadow that
   says the days slide under it */
.grid-pane[data-gmode="split"] .grid th.sel,
.grid-pane[data-gmode="split"] .grid td.sel{position:sticky;left:var(--gs-l-sel, 0px);z-index:1;
  box-shadow:6px 0 8px -6px rgba(0,0,0,.28)}
.grid-pane[data-gmode="split"] .grid thead th.sel{z-index:3}

/* the extras: pinned right, clipped on the left, above the day cells (whose
   clipboard toolbar sits at z-index 2) and on an opaque fill. The head cells
   keep their sticky top. */
.grid-pane[data-gmode="split"] .grid [data-gx]{position:sticky;z-index:3}
.grid-pane[data-gmode="split"] .grid thead [data-gx]{z-index:4}
/* a finger over the extras: the browser keeps the up-and-down scroll (and
   the pinch), and leaves a sideways swipe to gridsplit.js, which moves the
   extras with it rather than the week (backlog item 3, 2026-10-20) */
.grid-pane[data-gmode="split"] .grid [data-gx]{touch-action:pan-y pinch-zoom}
.grid-pane[data-gmode="split"] .grid [data-gx="tw"]{right:var(--gx-r-tw, 0px);clip-path:inset(0 0 0 var(--gx-cl-tw, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="balg"]{right:var(--gx-r-balg, 0px);clip-path:inset(0 0 0 var(--gx-cl-balg, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="bal_rd"]{right:var(--gx-r-bal_rd, 0px);clip-path:inset(0 0 0 var(--gx-cl-bal_rd, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="bal_phsh"]{right:var(--gx-r-bal_phsh, 0px);clip-path:inset(0 0 0 var(--gx-cl-bal_phsh, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="bal_al"]{right:var(--gx-r-bal_al, 0px);clip-path:inset(0 0 0 var(--gx-cl-bal_al, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="acc"]{right:var(--gx-r-acc, 0px);clip-path:inset(0 0 0 var(--gx-cl-acc, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="lw"]{right:var(--gx-r-lw, 0px);clip-path:inset(0 0 0 var(--gx-cl-lw, 0px))}
.grid-pane[data-gmode="split"] .grid [data-gx="foot"]{right:var(--gx-r-foot, 0px);clip-path:inset(0 0 0 var(--gx-cl-foot, 0px))}

/* the extras read as their own block (the approved mockup): a lavender fill
   and a rule down their left side — an inset shadow, so no width moves.
   A borrowed row and the row being dragged keep their own fill across. */
.grid-pane:is([data-gmode="plain"],[data-gmode="split"]) .grid tr:not(.dragging):not(.row-borrowed) > td[data-gx]{background:#f6f2fb}
.grid-pane:is([data-gmode="plain"],[data-gmode="split"]) .grid th[data-gx]{background:#ece4f5}
.grid-pane:is([data-gmode="plain"],[data-gmode="split"]) .grid [data-gx="tw"]{box-shadow:inset 3px 0 0 #c9b8e0}

/* the separator bands' note and the add-row label stay in view while the
   week scrolls (the band itself spans the whole table) */
.grid-pane[data-gmode="split"] .grid tr.sep-row .sep-body{position:sticky;left:calc(var(--gs-l-staff, 22px) + 10px);
  width:max-content;max-width:calc(var(--gs-staff-w, 0px) + var(--gs-week-w, 0px) - var(--gs-l-staff, 22px) - 20px)}
/* and so does a band's editor (a band is added in it): without this the form
   was as wide as the whole table, and Save, Cancel and Remove sat at its far
   right end, out of view until the week was scrolled (customer 2026-10-26).
   It runs to the VISIBLE table's right edge — the extras pane's — so the
   note box spans what is in view and the buttons end at that edge whichever
   pane has been scrolled sideways (customer 2026-10-27: "always at the
   right edge of the table"; on 2026-10-26 it stopped at the week pane's
   edge and the extras' part of the band stayed empty). The extras' own
   scroll moves nothing in a band (it has no data-gx cell), and the week's
   is what the sticky left answers. Always narrower than the band (the
   table is at least staff + week + extras wide), so no column's width
   moves. */
.grid-pane[data-gmode="split"] .grid tr.sep-editing .sep-form{position:sticky;left:calc(var(--gs-l-staff, 22px) + 10px);
  width:calc(var(--gs-staff-w, 0px) + var(--gs-week-w, 0px) + var(--gx-w, 0px) - var(--gs-l-staff, 22px) - 20px)}
.grid-pane[data-gmode="split"] .grid .add-row td{text-align:left}
.grid-pane[data-gmode="split"] .grid .add-row .add-lbl{position:sticky;left:calc(var(--gs-l-staff, 22px) + 8px);display:inline-block;
  width:calc(var(--gs-staff-w, 0px) + var(--gs-week-w, 0px) - var(--gs-l-staff, 22px) - 16px);text-align:center}

/* compact, under 1100 px of grid: the hours under the time, tighter cells,
   no position line, smaller header controls. gridsplit.js measures again
   after setting it, so these may change widths. Grid cells only — `.rec`
   is also the cell editor's record box. */
.grid-pane.g-compact .grid td.cell{padding:4px}
.grid-pane.g-compact .grid td.cell .cell-drag-handle{margin:-4px -4px 4px}
.grid-pane.g-compact .grid td.cell > .rec{line-height:1.2}
.grid-pane.g-compact .grid td.cell > .rec .rec-h{display:block;font-size:calc(11px * var(--fs, 1))}
.grid-pane.g-compact .grid thead th:not(.drag):not(.sel){padding:4px}
.grid-pane.g-compact .grid td.staff{padding:4px 6px;max-width:9.5em;white-space:normal}
.grid-pane.g-compact .grid td.staff .staff-pos{display:none}
.grid-pane.g-compact .grid th .col-sel{width:calc(12px * var(--fs, 1));height:calc(12px * var(--fs, 1));margin-top:2px}
.grid-pane.g-compact .grid th .day-remark-add{font-size:calc(9px * var(--fs, 1))}

/* a row's focus ring (2px + 2px offset) is not cut at the scroller's bottom: Tab
   (scrollIntoView) leaves a control 4px clear of the edge (scroll-padding), and the
   scroll range carries 4px of room after the table. Padding, not a margin: the
   scroller keeps its size where it fills the pane, so nothing moves (a grid that
   merely sizes to its rows grows by those 4px). Cards keep their own. */
@media screen{
.grid-pane:is([data-gmode="plain"],[data-gmode="split"],[data-gmode="measure"]) .grid-scroll{padding-bottom:4px;scroll-padding-bottom:4px}
}
