/* ============================================================================
   screens/schedule.css - the weekly shift roster
   ----------------------------------------------------------------------------
   Two presentations of one week:

     desktop   a single flat CSS grid, 8 columns wide - a header row of days, a
               coverage row that summarises each day under it, then one row per
               team member. Every child is a direct sibling in row-major order,
               so the row/column structure is pure geometry and the JS only ever
               appends a flat list. That is why the last-row border fix below can
               still be expressed as :nth-last-child(-n + 8) now that there are
               three kinds of row.

     mobile    a scrolling day-pill tablist plus the selected day's roster,
               grouped by shift. Screen-specific mobile blocks live here rather
               than in mobile.css, per contract section 7.

   The shift classes (.sh-m / .sh-a / .sh-n / .sh-c / .sh-o / .sh-leave) are the
   screen's one colour vocabulary. Four differently-shaped elements consume them
   - the grid cell chip (.shift), the mobile row tag (.shift-tag), the coverage
   count (.sumtag) and the legend swatch (.shift-sw) - so the legend physically
   cannot drift away from the cells it explains.

   A shift type added later in Settings has no class here. It takes .sh-x, whose
   only colour comes from --shift-color: the screen script writes the type's own
   `color_token` there with node.style.setProperty(), which is the one way the
   build contract lets a dynamic value reach CSS. So a new type is legible the
   day it is created, and nothing in this file has to be edited to make it so.

   EVERY control on this screen is a <button> or an <a href>. The grid cells
   that can be acted on are buttons, which is why .cell and .hc reset border,
   background, font and colour before painting: those rules serve a <div> and a
   <button> at the same time.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   1. Toolbars above the grid

   Row one is the week stepper and the writing actions; row two is the KPI strip
   for the focused day. Both wrap rather than scroll, because at desktop widths
   there is room and a wrapped toolbar is easier to hit than a scrolled one.
   --------------------------------------------------------------------------- */

.sch-acts {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.sweeknav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

/* The week picker. Sized to its own content so it never stretches the toolbar:
   a date input reports a much wider intrinsic width than it needs. */
.sjump {
  display: inline-flex;
  min-width: 0;
}

.sjump-in {
  width: 148px;
  min-height: 34px;
  padding: var(--s-1) var(--s-2);
  font-size: 12.5px;
}

.skpis {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-4);
}

/* The KPI tile is a shared component; here it only needs to stop growing so a
   row of them sits beside the chips instead of filling the line. */
.skpi {
  flex: 0 0 auto;
  min-width: 132px;
}


/* ---------------------------------------------------------------------------
   2. Legend

   A real component (a <ul> of <li>) rendered from the server's own shift type
   list, so adding a shift type adds a legend entry with no edit here.
   --------------------------------------------------------------------------- */

.slegend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  margin: 0 0 var(--s-3);
  padding: 0;
  list-style: none;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--muted);
}

.slegend-item {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}


/* ---------------------------------------------------------------------------
   3. Shift vocabulary - four shapes, one set of modifiers

   Each shape declares `border: 1.5px solid transparent` up front so the dashed
   on-call variant does not grow by 3px relative to its neighbours.
   --------------------------------------------------------------------------- */

/* The chip inside a grid cell.

   NAME COLLISION FIX. home.css declares a roster badge that is also called
   `.shift`, at the same (0,1,0) specificity, in a sheet index.html loads first
   - so each file won for whichever properties it happened to declare and both
   components broke. Scoping to .sgrid separates them for good. */
.sgrid .shift {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--s-2);
  border: 1.5px solid transparent;
  border-radius: calc(var(--r-sm) - 3px);
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.15;
}

/* The chip's second line: the shift's clock range. */
.shift-t {
  display: block;
  margin-top: 1px;
  font-family: var(--f-mono);
  font-size: 10px;
  font-weight: 500;
  opacity: .85;
}

/* A shift carrying a note gets a marker rather than the note itself: the cell
   is 84px wide and the note can be 160 characters. The text is read out by the
   cell's own screen-reader label and shown in full in the edit dialog. */
.shift-note .ic {
  width: 11px;
  height: 11px;
  margin-top: 2px;
  opacity: .75;
}

/* An unrostered day. Deliberately quiet: a gap is information, not an alarm,
   and the grid has seventy of these in an empty week. */
.sgrid .shift--gap {
  border-style: dashed;
  border-color: var(--gray-200);
  color: var(--gray-400);
  font-size: 13px;
}

/* The tag at the end of a mobile roster row (.prow > .p-tail). */
.shift-tag {
  display: inline-flex;
  align-items: center;
  padding: var(--s-2) var(--s-3);
  border: 1.5px solid transparent;
  border-radius: var(--r-sm);
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.shift-tag--gap {
  border-style: dashed;
  border-color: var(--gray-300);
  color: var(--gray-500);
}

/* The legend swatch. */
.shift-sw {
  flex: none;
  width: 11px;
  height: 11px;
  border: 1.5px solid transparent;
  border-radius: calc(var(--r-sm) - 7px);
}

/* The coverage count in the summary row: "2 M". */
.sumtag {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 2px var(--s-2);
  border: 1.5px solid transparent;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.3;
}

.sumtag b {
  font-family: var(--f-disp);
  font-size: 12px;
  font-weight: 600;
}

.sumk {
  letter-spacing: .04em;
}

/* --- the modifiers themselves -------------------------------------------
   Declared after all four shapes so their border-color and border-style land
   on top of the transparent base, and written as longhands so the 1.5px width
   survives. */

.sh-m { background: var(--gold);      color: var(--navy-900); }
.sh-a { background: var(--navy);      color: var(--white); }
.sh-n { background: var(--navy-900);  color: var(--white); }
.sh-o { background: var(--gray-100);  color: var(--gray-600); }

.sgrid .shift.sh-c,
.shift-tag.sh-c,
.shift-sw.sh-c,
.sumtag.sh-c {
  background: var(--white);
  border-color: var(--gold-600);
  border-style: dashed;
  color: var(--gold-700);
}

/* Approved leave. Not a shift type, so it never comes back from the API as one;
   the grid paints it from the cell's `kind` and this is its only colour. */
.sgrid .shift.sh-leave,
.shift-tag.sh-leave,
.shift-sw.sh-leave,
.sumtag.sh-leave {
  background: var(--red-100);
  border-color: var(--red-100);
  color: var(--red-700);
}

/* The fallback for a shift type this stylesheet has never heard of. Its colour
   is the type's own token, handed over as --shift-color by the screen script. */
.sgrid .shift.sh-x,
.shift-tag.sh-x,
.shift-sw.sh-x,
.sumtag.sh-x {
  background: var(--white);
  border-color: var(--shift-color, var(--gray-300));
  color: var(--ink);
}

.shift-sw.sh-x {
  background: var(--shift-color, var(--gray-300));
}


/* ---------------------------------------------------------------------------
   4. The week grid

   .sview-week is the toggle target for the "nothing matches the filter" state,
   so it deliberately declares no `display` - [hidden] in base.css must be able
   to win against it without a priority flag.
   --------------------------------------------------------------------------- */

.sview-week {
  min-width: 0;
}

/* Eight columns need roughly 812px. Below that the grid scrolls sideways in its
   own container rather than squeezing the day columns into unreadable slivers.
   The container is the scroller, never the body: at phone widths the whole
   .view-desktop is display:none, so this never reaches a 390px screen at all. */
.sgrid-scroll {
  /* Positioned so the .sr-only text in the grid stays inside this sideways
     scroller. Without it that text sits past the grid's right edge outside
     any scroller: at 1024px and 900px wide the document grew to 1029px, and
     with .content positioned it becomes a horizontal scrollbar on .content. */
  position: relative;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.sgrid {
  display: grid;
  grid-template-columns: 212px repeat(7, minmax(84px, 1fr));
  min-width: 812px;
  background: var(--white);
  border: 1px solid var(--gray-200);
  border-radius: var(--r);
  /* Clips the four corner cells to the container's rounding. */
  overflow: hidden;
}

/* --- header row ---
   .hc serves a <div> (the corner) and a <button> (each day), so the resets come
   before the paint. */

.sgrid .hc {
  padding: var(--s-3) var(--s-2);
  border: 0;
  border-bottom: 1px solid var(--gray-200);
  background: var(--gray-50);
  font-family: var(--f-ui);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--navy);
  text-align: center;
}

/* The top-left corner cell: a column label, not a date. */
.sgrid .hc-left {
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: left;
}

/* Each day header selects that day for the KPI strip and the phone roster, so
   it really is a button and says so on hover and focus. */
.sgrid .hc-day {
  cursor: pointer;
  touch-action: manipulation;
  transition: background var(--t-fast), color var(--t-fast);
}

.sgrid .hc-day:hover {
  background: var(--gray-100);
}

.sgrid .hc-day.is-on {
  background: var(--navy);
  color: var(--white);
}

.sgrid .dnum {
  display: block;
  margin-top: 1px;
  font-family: var(--f-disp);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

/* --- coverage row ---
   Sits directly under the header, which is where a supervisor looks first:
   how many mornings, how many afternoons, who has the phone, how many holes. */

.sgrid .sumcell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  padding: var(--s-2);
  border-right: 1px solid var(--gray-100);
  border-bottom: 1px solid var(--gray-200);
  background: var(--gray-50);
  text-align: center;
}

.sgrid .sumcell--head {
  align-items: flex-start;
  padding-left: var(--s-3);
  border-right: 1px solid var(--gray-200);
}

.sumhead {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.sumrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  min-width: 0;
}

.sumcall,
.sumgap,
.sumleave,
.sumnone {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  max-width: 100%;
  overflow: hidden;
  font-size: 10.5px;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
}

/* "No cover" is a sentence, not a count: it wraps to two lines inside the day
   column instead of being cut mid-word ("Tidak ada yang terjad"). A flex box
   cannot draw an ellipsis, which is why the cut had none. */
.sumnone {
  display: block;
  text-align: center;
  white-space: normal;
}

.sumcall .ic {
  width: 11px;
  height: 11px;
  color: var(--gold-600);
}

.sumgap {
  color: var(--red-700);
}

.sumleave {
  color: var(--gray-600);
}

/* --- member column --- */

.sgrid .mc {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-3);
  border-right: 1px solid var(--gray-200);
  border-bottom: 1px solid var(--gray-100);
}

.sgrid .mc-nm {
  min-width: 0;
  line-height: 1.25;
}

.sgrid .mc-nm b,
.sgrid .mc-nm span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sgrid .mc-nm b {
  font-size: 13px;
  font-weight: 600;
  color: var(--navy);
}

.sgrid .mc-nm span {
  font-size: 10.5px;
  color: var(--muted);
}

/* --- day cells ---
   .cell also serves both a <div> and a <button>, hence the same reset order as
   .hc above. */

.sgrid .cell {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  min-height: 56px;
  padding: var(--s-2);
  border: 0;
  border-right: 1px solid var(--gray-100);
  border-bottom: 1px solid var(--gray-100);
  background: transparent;
  font: inherit;
  color: inherit;
  text-align: center;
}

/* Only the cells this user may actually change look touchable. A cell with no
   edit right is rendered as a <div> by the screen script, so there is no
   disabled control to discover and no tooltip apologising for it. */
.sgrid .cell--act {
  cursor: pointer;
  touch-action: manipulation;
  transition: background var(--t-fast);
}

.sgrid .cell--act:hover {
  background: var(--gold-a05);
}

.sgrid .cell--act:hover .shift--gap {
  border-color: var(--gold-600);
  color: var(--gold-700);
}

/* Today's column, derived from the server's own `is_today` flag - never a typed
   class in the markup, which is how the prototype ended up highlighting the
   wrong weekday. */
.sgrid .hc.is-today,
.sgrid .sumcell.is-today { background: var(--gold-100); }
.sgrid .cell.is-today { background: var(--gold-a05); }

.sgrid .cell.is-weekend:not(.is-today) { background: var(--gray-50); }

/* --- grid edges -----------------------------------------------------------
   The last row simply IS the last eight children, and the right-hand edge every
   eighth child - no class, and nothing to keep in sync when rows are added,
   removed or filtered out by the search. */
.sgrid > :nth-last-child(-n + 8) {
  border-bottom: 0;
}

.sgrid > :nth-child(8n) {
  border-right: 0;
}


/* ---------------------------------------------------------------------------
   5. Day roster - the mobile view's body (and the shape the day pills switch)
   --------------------------------------------------------------------------- */

.sday {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-width: 0;
}

/* Breathing room above each group heading except the first. mobile.css resets
   .sec-t's margin to 0; this two-class selector re-adds only the top. */
.sday .sec-t {
  margin-top: var(--s-3);
}

.sday .sec-t:first-of-type {
  margin-top: 0;
}

/* A roster row that opens the edit dialog. .prow already resets font and
   background for exactly this reason; the rest is the touch affordance. */
.prow--act {
  cursor: pointer;
  text-align: left;
  touch-action: manipulation;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.prow--act:hover {
  border-color: var(--gold-300);
  box-shadow: var(--sh-md);
}

/* The coverage card above the day's rows: the same numbers the desktop grid
   shows in its coverage row, written for a 390px column. */
.sdaysum {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--gray-200);
  border-radius: var(--r);
  background: var(--white);
  box-shadow: var(--sh-sm);
}

.sdaysum-h {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
}

.sdaysum-h b {
  font-family: var(--f-disp);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

.sdaysum-f {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-3);
}

/* Inside the card the counts sit on one wrapping line and read left to right,
   unlike the centred grid cell. */
.sdaysum .sumrow {
  justify-content: flex-start;
}

.sdaysum .sumcall,
.sdaysum .sumgap,
.sdaysum .sumleave,
.sdaysum .sumnone {
  font-size: 12px;
  white-space: normal;
}

.sdaysum .sumtag {
  font-size: 11.5px;
}

/* Seven day pills that SHRINK to fit the row. This used to be a scrolling
   strip with a 44px floor per pill, which read as the careful choice and was
   the wrong one on a phone: Android Chrome sizes the layout viewport to the
   minimum width the page needs, and a scrolling strip of pills with a 44px
   floor still reports seven times 44 plus the gaps to that sum. At 320px the
   viewport grew to 336px and the whole screen was drawn zoomed out, which is
   worse for a thumb than a slightly narrower pill. Measured on 12 September
   2026, the same day the filter bar in components.css taught the same lesson.

   At 390px each pill is still 44px. At 360px it is 40px, at 320px it is 37px,
   with the row gap tightened below 360px; the height stays at the 44px floor
   throughout, and a whole week stays visible with nothing hidden off the edge. */
.dpills--track {
  gap: var(--s-2);
  min-width: 0;
  padding-bottom: 2px;
}

.dpills--track .dpill {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
}

@media (max-width: 359.98px) {
  .dpills--track {
    gap: var(--s-1);
  }
}

/* Today is marked even when another day is selected, so stepping through the
   week never loses the anchor. */
.dpills--track .dpill.is-today:not(.is-on) {
  box-shadow: inset 0 0 0 1.5px var(--gold-300);
}


/* ---------------------------------------------------------------------------
   6. Leave and swap requests

   Two panels, side by side once there is room. Every row is the same shape in
   both views, and the approve, reject, accept and decline buttons are only in
   the DOM when the signed in user may actually press them.
   --------------------------------------------------------------------------- */

.sreq {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-4);
  margin-top: var(--s-5);
  min-width: 0;
}

@media (min-width: 1180px) {
  .sreq {
    grid-template-columns: 1fr 1fr;
  }
}

.sreq-panel {
  min-width: 0;
}

.sreq-panel .panel-t .ic {
  width: 16px;
  height: 16px;
  margin-right: var(--s-1);
  color: var(--gold-600);
  vertical-align: -3px;
}

/* Push the header button to the end of the row without a wrapper element. */
.sreq-add {
  margin-left: auto;
}

.sreq-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}

.sreq-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-3);
  border: 1px solid var(--gray-200);
  border-radius: var(--r);
  background: var(--white);
}

.sreq-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: var(--gray-100);
  color: var(--gray-600);
}

.sreq-ic .ic {
  width: 15px;
  height: 15px;
}

.sreq-m {
  flex: 1 1 180px;
  min-width: 0;
  line-height: 1.35;
}

.sreq-m b {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}

/* Written as the week header writes a day ("Kam 15 Okt") since 22 October
   2026, in the text face: it was a mono ISO date, and .mono carried the size. */
.sreq-dates {
  display: block;
  margin-top: 1px;
  font-size: 12.5px;
  color: var(--navy);
}

.sreq-meta {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--muted);
}

.sreq-tail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

.sreq-btns {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.sreq-more {
  margin: var(--s-3) 0 0;
}


/* ---------------------------------------------------------------------------
   7. Error state

   Every failed fetch on this screen shows the SERVER's sentence, not a generic
   one, plus a single button that tries again. A roster that silently shows last
   week's numbers is worse than one that says it could not read them.
   --------------------------------------------------------------------------- */

.serr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-6) var(--s-4);
  text-align: center;
}

.serr-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: var(--red-100);
  color: var(--red-700);
}

.serr-ic .ic {
  width: 20px;
  height: 20px;
}

.serr-msg {
  max-width: 46ch;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}


/* ---------------------------------------------------------------------------
   8. Filter feedback

   Shown only while the roster search is narrowing the list, so the coverage row
   and the KPI tiles (which always describe the whole day) can never be mistaken
   for a count of the rows on screen.
   --------------------------------------------------------------------------- */

.sfilter-note {
  margin: 0 0 var(--s-3);
}


/* ---------------------------------------------------------------------------
   9. Mobile chrome

   The head actions, the floating Add shift button, and the room the list has to
   leave for it. Contract section 7: nothing fixed may cover the last row, and
   nothing may make the body scroll sideways at 390px.
   --------------------------------------------------------------------------- */

.sch-phead-acts {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

/* The mobile page head stacks as a column, so .tb-search's desktop
   `flex: 0 1 230px` would be read as a 230px HEIGHT. Reset the flex, keep the
   field's own styling. */
.phead .tb-search {
  flex: none;
}

/* The week stepper on the phone: one wrapping line, and the picker takes the
   rest of the second line rather than forcing a third. */
.sweeknav .chip {
  flex: 1 1 auto;
  min-width: 0;
  justify-content: center;
}

.sweeknav .sjump {
  flex: 1 1 140px;
}

.sweeknav .sjump-in {
  width: 100%;
}

/* The floating Add shift button. Bottom RIGHT: commandbar.css parks its own
   launcher bottom left, and the two must not stack. Cleared of the tab bar and
   of the iPhone home indicator with the same tokens the tab bar itself uses. */
.sfab {
  position: fixed;
  right: calc(var(--s-4) + var(--safe-r));
  bottom: calc(var(--bottombar-h) + var(--safe-b) + var(--s-4));
  z-index: 44;
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--fab-h);
  height: var(--fab-h);
  border: 0;
  border-radius: 999px;
  background: var(--gold);
  color: var(--navy-900);
  box-shadow: var(--sh-lg);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform var(--t-base), background var(--t-fast);
}

.sfab .ic {
  width: 22px;
  height: 22px;
}

.sfab:hover {
  background: var(--gold-600);
}

.sfab:active {
  transform: scale(.94);
}

@media (max-width: 860px) {

  /* The view-mobile wrapper is display:none above this width, so the fixed
     button only exists where the tab bar it clears also exists. */
  .sfab {
    display: inline-flex;
  }

  /* Room under the last row for the floating button, on top of the tab bar
     clearance layout.css already pays. Only when the button is there: the class
     is toggled by the screen script from the same permission check that decides
     whether to render it at all. */
  .pbody.has-fab {
    padding-bottom: calc(var(--s-4) + 68px);
  }

  /* Requests read as a continuation of the day, not as a second screen. */
  .sreq {
    margin-top: var(--s-2);
  }

  /* A 44px target for every decision button on a phone. */
  .sreq-btns .btn {
    min-height: 44px;
  }

  .sreq-row {
    padding: var(--s-3) var(--s-4);
    border-radius: var(--r-lg);
  }
}


/* ---------------------------------------------------------------------------
   10. Print

   print.css owns the shell; this block owns the one screen-specific problem it
   cannot know about. The grid's 812px floor exists so seven day columns stay
   readable on screen, but an A4 portrait content box is only about 700px wide,
   so on paper the floor has to go or the last two days fall off the sheet. The
   sideways scroller goes with it - there is nothing to scroll on paper.
   --------------------------------------------------------------------------- */

@media print {

  .sgrid-scroll {
    overflow: visible;
  }

  .sgrid {
    min-width: 0;
    /* No minmax() floor: the day columns share whatever the sheet allows. */
    grid-template-columns: 150px repeat(7, minmax(0, 1fr));
  }

  .sgrid .mc {
    padding: var(--s-2);
  }

  .sgrid .cell {
    min-height: 0;
    padding: var(--s-1);
  }

  /* A printed roster is pinned to a wall; the requests inbox and the floating
     button are screen furniture. */
  .sreq,
  .sfab,
  .sjump {
    display: none;
  }

  /* Keep the shift colours: a roster printed in greyscale bars is unreadable.
     .rshift is Home's roster badge, which prints from the same palette. */
  .shift,
  .rshift,
  .shift-sw,
  .shift-tag,
  .sumtag {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
}
