/* page-specific styles for discover; shared components belong in dibs.css.
   Every stylesheet loads on every route, so each rule here is scoped to .disc, #hours-pop, .dhours, .dwk,
   .dbd-pop or body.disc-pane (spec/discover-hours-filler-dock.md, spec/busy-hours-drag.md 9). */

/* 3.1 Docked detail by list width: Discover and Directory dock from a 1024 viewport whenever the list column
   keeps 360 (BT, L32, SB208). body.disc-pane is set only while the detail is docked on those routes. */
/* W30 (owner 3 Nov 2026 22:4x, followups/owner-feedback-20261103-w30-w31.md W30: "move the content on the long
   form over and have the sheet cover instead of resizing the box"): on Discover and Directory the docked pane is a
   sheet over the list. The shell takes no dock margin (--dock 0 overrides dibs.css's 480 for pane-open and the W22
   rule), so the list keeps the width and layout it has with the pane closed, before, during and after the slide;
   the pane slides over its right part and away again, and no row narrows, folds or refits. The covered rows stay in
   the page: they scroll as before, and their links and add buttons stay Tab stops. A pane over content casts the
   overlay shadow the modal drawer has (dibs.css #drawer), so its edge reads as above the list, not beside it. The
   busy hours pane keeps its own 320 dock (dibs.css body.hours-open). */
/* W30 round 2 (drw:check1 M1): the sheet covers the list, never the page's controls. Its top is the bottom of the
   sticky toolbar or of the count and Sort line, whichever is lower (discover.js placeDiscPane writes
   --disc-pane-top), so search, the segments, Fits my schedule, Requirement, Filters and Sort stay in view and in
   reach; the toolbar itself does not move or refit. A list control that keyboard focus reaches under the sheet is
   never drawn hidden: the sheet slides aside (body.pane-yield, discover.js) while focus browses the list, and comes
   back when focus or a pointer goes anywhere else or a row is opened (WCAG 2.2 SC 2.4.11). */
@media (min-width: 1024px) {
  body.disc-pane:not(.hours-open) .shell { --dock: 0px; }
  body.disc-pane #drawer.as-pane { box-shadow: var(--shadow-overlay); }
  body.disc-pane:not(.hours-open) #drawer.as-pane {
    top: var(--disc-pane-top, 0px);
    height: calc(100dvh - var(--disc-pane-top, 0px)); max-height: calc(100dvh - var(--disc-pane-top, 0px));
  }
  body.disc-pane.pane-yield:not(.hours-open) #drawer.as-pane[open] { translate: calc(100% + 48px) 0; }
}

/* 3.2 The results list is the long form again (W30, undoing the W26 cards): one .clist container with its 36 head
   and 92 tall .crow rows, figures at grid column 3 and the add button at column 5 (dibs.css .clist and .crow).
   Kept from W26: the meta line crossfade on a content change (discover.js cardsDrawn). The old meta line of a
   crossfade is a copy over the new one: never a target. */
.disc #results .crow-meta-ghost, .disc #results .crow-meta-ghost * { pointer-events: none; }

/* 3.3 Narrow row: under a 540 list column the row takes the phone anatomy (disc 12), keyed to the list's own width so
   it follows the sidebar. The A range and DFW lead meta group B instead of being dropped. W30: back to 540 from the
   W26 440, because 540 is where the full-width row's five columns stop fitting its figures and meta, and since the
   pane covers the list instead of narrowing it, the threshold is now reached only by the viewport and sidebar. */
.disc .clist { container: dlist / inline-size; }
@container dlist (max-width: 539px) {
  .disc .crow { grid-template-columns: minmax(0, 1fr) 8px auto 8px 28px; }
  .disc .crow-main { grid-column: 1 / -1; }
  .disc .crow-l1 { margin-right: 92px; }
  .disc .crow-grades { grid-row: 1; grid-template-rows: 22px; }
  .disc .crow-grades .crow-figs { display: none; }
  .disc .crow .crow-figs-b { display: inline-flex; }
  /* W11: the muted line under the figures follows them into group B (dibs.css .crow-gnote) */
  .disc .crow-grades.has-gnote { grid-row: 1; grid-template-rows: 22px; }
  .disc .crow-grades .crow-gnote { display: none; }
  .disc .crow:has(> .crow-grades.has-gnote) .crow-meta { grid-column: 1 / -1; }
  .disc .crow .crow-gnote-b { display: inline-flex; }
  .disc .clist-head-gpa { width: auto; }
}

/* 3.4 W33 (owner 4 Nov 2026 02:2x PST, followups/owner-feedback-20261104-w33-w34.md: "only with class preview expanded
   should it look like this. orange is worklaod icons red is gpa and dfw rate"). While the docked pane covers the right
   of every row, the part it leaves still carries what a student compares: line 1 is the code, then the workload icons
   (discover.js crow-pw, the word after them), and at the right edge of the visible part the predicted GPA and the DFW
   rate (crow-peek), tabular and right aligned, 16 left of the pane (--disc-cover, discover.js placeDiscPane), with
   the figures column's own tips. The meta line's workload fact keeps its box but is not drawn, since line 1 carries
   it (nothing twice); a row with no workload leaves the icon slot empty. Both are display none with the pane closed,
   and nothing here moves a row box: the add button and the full figures column stay under the pane (W30). Refs:
   mercury 0325 and link 0014 keep the amount at the right edge of a row a detail panel shortens. */
.disc .crow-pw, .disc .crow-peek { display: none; }
@media (min-width: 1024px) {
  @container dlist (min-width: 540px) {
    body.disc-pane:not(.hours-open) .disc #results .crow-pw {
      display: inline-flex; flex: none; align-items: center; gap: var(--s-2); height: 22px;
      font: var(--t-meta); color: var(--muted); white-space: nowrap;
    }
    body.disc-pane:not(.hours-open) .disc #results .crow-pw .bar { margin: 0; }
    body.disc-pane:not(.hours-open) .disc #results .crow-peek {
      position: absolute; top: 12px; right: calc(var(--disc-cover, 0px) + var(--s-4)); z-index: 1;
      display: flex; align-items: center; gap: var(--s-3); height: 22px;
      font: var(--t-meta); line-height: 22px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
      pointer-events: none;
    }
    body.disc-pane:not(.hours-open) .disc #results .crow + .crow > .crow-peek { top: 11px; } /* under the 1px rule */
    body.disc-pane:not(.hours-open) .disc #results .crow-peek [data-tip] { pointer-events: auto; }
    body.disc-pane:not(.hours-open) .disc #results .crow-peek-gpa { font: 600 15px/22px var(--font-ui); color: var(--ink); }
    body.disc-pane:not(.hours-open) .disc #results .crow-meta :is(.fact.work, .work-none) { visibility: hidden; opacity: 0; }
    /* W41b (owner 4 Nov 2026 13:2x PST, "it disappears when its fully gone and the workload just teleports back in"):
       while the pane slides out (body.pane-leaving, discover.js leavePane) the meta line's workload fact fades back in
       and line 1's icons and the right-edge figures fade out, on the pane's own sheetOut time and curve (motion.js), so
       nothing is left to swap in one frame when the pane's classes go. Only opacity moves, never a box. Reduced motion
       never sets pane-leaving, so there the swap stays instant at the end of the fade. */
    body.disc-pane.pane-leaving:not(.hours-open) .disc #results .crow-meta :is(.fact.work, .work-none) {
      visibility: visible; opacity: 1; transition: opacity var(--dm-sheetOut-ms) var(--dm-sheetOut-ease);
    }
    body.disc-pane.pane-leaving:not(.hours-open) .disc #results :is(.crow-pw, .crow-peek) {
      opacity: 0; transition: opacity var(--dm-sheetOut-ms) var(--dm-sheetOut-ease);
    }
  }
}

/* 5.1 "All classes | Filler classes": sys 9.4 segmented control, first on toolbar row R2 (SB127, V338) */
.disc-mode { flex: none; }
.disc-mode > button { white-space: nowrap; }
/* W34: the checked segment is 600 (dibs.css .seg), so each segment reserves its bold width with a hidden, zero-height
   bold copy of its label; the pill no longer grows a pixel when GE classes is picked and pushes what follows it. */
/* W41a (owner 4 Nov 2026 13:2x PST, "filter got fucke"): every button takes dibs.css's 8px flex gap (button, .btn), and
   in this column that gap sat between the label and its zero-height copy, so each label rode 4px above its pill's
   centre and above every other toolbar label. The column has no gap. */
.disc-mode > button { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; }
.disc-mode > button::after { content: attr(data-label); height: 0; overflow: hidden; visibility: hidden; font-weight: 600; pointer-events: none; user-select: none; }

/* 4.1 Fits my schedule as a split button (C120 "Send invite" and its chevron): one outline, a 1px divider,
   outer corners 6, inner corners 0. The pressed style (sys 9.4) is the toggle segment's alone. */
.fit-split { position: relative; display: inline-flex; flex: none; }
.fit-split > #fit { position: relative; border-top-right-radius: 0; border-bottom-right-radius: 0; }
.fit-split > #fit[aria-pressed="true"], .fit-split > #fit:focus-visible { z-index: 1; } /* its ink-2 edge is the divider */
.fit-split > #fit-edit {
  width: 32px; padding: 0; margin-left: -1px;
  border-top-left-radius: 0; border-bottom-left-radius: 0; color: var(--ink-2);
}
.fit-split > #fit-edit[aria-expanded="true"] { background: var(--surface-2); }
@media (pointer: coarse), (max-width: 599px) { .fit-split > #fit-edit { width: 44px; } }

/* 4.2 The busy hours popover (#hours-pop): the .fmenu anchor pattern, 360 wide (BT rail), anchored 4 under the
   split button with left edges aligned (V164, ST197), non-modal with no scrim (L246). */
.disc-sticky:has(.hpop:not([hidden])) { z-index: 40; }
.hpop {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 50;
  display: flex; flex-direction: column; width: 360px; max-width: calc(100vw - 32px);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-panel); box-shadow: var(--shadow-overlay);
  text-align: left;
}
.hpop[hidden] { display: none; }
.hpop.hpop--flip { left: auto; right: 0; }
.hpop:focus-visible { outline: none; } /* opening onto saved groups focuses the popover itself, as Plan's pane does */
.hpop-title { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); min-height: 32px; padding: var(--s-2) var(--s-4) 0; font: var(--t-control); font-weight: 600; color: var(--ink); }
.hpop-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; overscroll-behavior: contain; padding: var(--s-1) var(--s-4) 0; }
.dh-clear-slot:empty { display: none; }
#hours-pop .dh-clear, .dhours-frame .dh-clear { margin-right: calc(-1 * var(--s-2)); font: var(--t-control); }
/* the line over the week: how to make a block, and the touch and keyboard route beside it (busy-hours-drag 7) */
.dh-how { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); min-height: 28px; margin: 0 0 var(--s-2); font: var(--t-meta); color: var(--muted); }
.dh-how .dh-add { flex: none; gap: 4px; margin-right: calc(-1 * var(--s-2)); font: var(--t-control); white-space: nowrap; }
.dh-how .dh-add .icon { width: 16px; height: 16px; }
@media (pointer: fine) and (min-width: 600px) { .dh-how .dh-add { display: none; } } /* a mouse drags; the keyboard has the slot cursor */

/* The mini week (busy-hours-drag 9): Plan's grid anatomy (C120) at a 32 hour pitch, Mon to Fri, 8 AM to at least
   10 PM. Busy blocks carry Plan's hatch; the plan's classes are faint context and never a target. */
.dwk { --gut: 36px; margin: 0 0 var(--s-3); }
.dwk .wk-head { top: 0; height: 28px; }
.dhours-sheet .dwk .wk-head { position: static; }
.dwk .wk-body { height: calc(16px + var(--rows) * var(--pitch)); }
.dwk .wk-hl { right: 6px; }
.dwk .wk-block { padding: 1px 4px 1px 7px; }
.dwk .wk-code, .dwk .wk-block .wk-code { font-size: 12px; line-height: 15px; white-space: nowrap; }
.dwk .wk-time { display: none; } /* b5r4 B1: no 11px, no truncated time; the block's popover and aria-label carry it */
.dwk .wk-busy, .dwk .wk-busy:hover { padding: 1px 4px; background: repeating-linear-gradient(135deg, var(--busy-stripe, var(--line)) 0 3px, var(--bg) 3px 6px); }
.dwk .wk-faint, .dwk .wk-faint.wk-dis { z-index: 0; pointer-events: none; cursor: default; background: var(--surface-2); border-color: var(--line); } /* b5r4 B2: fill fades, label stays legible */
.dwk .wk-faint::before { opacity: .5; }
.dwk .wk-faint .wk-code { color: var(--muted); }
/* a busy block's popover sits above the hours popover (z 50 inside the sticky toolbar) */
.bd-pop.dbd-pop { z-index: 60; }
.dh-note { flex: none; margin: 0; padding: var(--s-3) var(--s-4); border-top: 1px solid var(--line); font: var(--t-label); font-weight: 400; color: var(--muted); }
.dh-note a { color: var(--accent); font-weight: 500; }
.dh-note .dh-plan { margin-left: var(--s-2); white-space: nowrap; }

/* 4.5 Phone: the editor is a full-screen sheet (the phone Filters sheet frame); Clear all sits in its header */
.dhours-sheet > * + * { margin-top: 0; }
.dhours-sheet .dh-note { padding: var(--s-3) 0 0; }
.dhours-frame .dh-nav { gap: var(--s-2); }

/* 5.2 Filler: the plain-noun title takes the search field's place (S252 "Customers"). W34 (owner 4 Nov 2026 02:2x
   PST, "the bubbles below the search bar move a couple pixels"): the title block is as tall as the search field (44
   since owner walk 2 W5, dibs.css .disc-search; it was left at the old 36), so the toolbar under it starts at one y
   in every mode and the segments, Fits my schedule and Filters keep their boxes. */
.disc-titlewrap { display: flex; align-items: center; height: 44px; }
.disc-title { margin: 0; font: var(--t-title); color: var(--ink); white-space: nowrap; }
.disc--filler .disc-toolbar { margin-top: var(--s-3); }

/* 5.5 Production's count sentences are long, so in Filler the count line wraps instead of running off a phone */
.disc--filler .disc-count-l { flex: 1 1 auto; }
.disc--filler .disc-count-n { white-space: normal; }
/* The unopened line: one muted meta line under the count line */
.disc-unopened { max-width: 760px; margin: 2px 0 0; font: var(--t-meta); color: var(--muted); }
.disc-unopened:empty { display: none; }
/* The who-can-enroll line (R14 b): the same muted meta line, with its one Include press after the sentence */
/* one line at every width (owner 2 Nov 2026, U4: the explanation must not take the screen; W48, owner 4 Nov 2026: the
   cut-off reasons "looks dumb"): a short count and the Include press, nothing clipped and no ellipsis. The count is a
   quiet tip button, its dotted underline the only cue that it opens the reasons (the shared #tip, dibs.css) */
.disc-hidden { display: flex; align-items: baseline; min-width: 0; margin: 2px 0 0; font: var(--t-meta); color: var(--muted); white-space: nowrap; }
.disc-hidden:empty { display: none; }
.disc-hidden .disc-hidden-n {
  flex: none; display: inline; min-height: 0; padding: 0; margin: 0; border: 0; border-radius: 0;
  background: transparent; color: inherit; font: inherit; cursor: default;
  text-decoration: underline dotted var(--line-strong); text-underline-offset: 3px;
}
.disc-hidden .disc-hidden-n:hover { background: transparent; color: var(--ink-2); }
.disc-hidden .text-btn { flex: none; margin-left: var(--s-2); font: inherit; }

/* 5.6 Group header rows inside the one container (L246 "Todo 2 / 3"), production's heading and paragraph */
.disc .clist-group { padding: var(--s-4); background: var(--bg); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.disc .clist-group h3 { margin: 0; font: var(--t-item); color: var(--ink); }
.disc .clist-group p { max-width: 72ch; margin: var(--s-1) 0 0; font: var(--t-meta); color: var(--muted); }
.disc .clist-head + .clist-group { border-top: 0; }
.disc .clist-group + .crow { padding-top: var(--s-3); border-top: 0; }

/* 5.3 Filler Filters menu: the grades minimum under a rule, with production's helper line */
.fmenu-main--filler .fmenu-num { display: flex; flex-direction: column; gap: var(--s-1); padding: var(--s-2); }
.fmenu-main--filler .fmenu-num label { font: var(--t-control); color: var(--ink); }
.fmenu-main--filler .fmenu-num input { width: 96px; height: 32px; min-height: 32px; font-variant-numeric: tabular-nums; }
.fmenu-main--filler .fmenu-num .fmenu-hint { margin: 0; }
.fmenu-sub--top { top: 0; }
/* R2 folded (b2r1 m1): when the full toolbar row would wrap, its desk-only controls leave the row and lead the
   Filters menu instead (Linear 0038: every view control on one row, never one left alone below) */
.disc-toolbar.is-compact .desk-only { display: none; }
/* b9r5 and b10r1 m1 second fold: when the folded row still wraps (pane docked at 1024 to 1059), Filters becomes the 32px
   toolbar icon button (.icon-btn.in-toolbar, Linear 0038 row-end icon buttons). Its word stays as screen reader
   text, so the name is still "Filters" plus the count, and the count stays visible beside the icon. */
.disc .disc-toolbar.is-compact-2 #filters-btn { min-width: 32px; padding: 0 var(--s-2); }
.disc .disc-toolbar.is-compact-2 #filters-btn:not(:has(.filters-n:not(:empty))) { width: 32px; padding: 0; }
.disc .disc-toolbar.is-compact-2 #filters-btn > span:not(.filters-n) { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (pointer: coarse) {
  .disc .disc-toolbar.is-compact-2 #filters-btn { min-width: 44px; }
  .disc .disc-toolbar.is-compact-2 #filters-btn:not(:has(.filters-n:not(:empty))) { width: 44px; }
}
/* W37a (owner 4 Nov 2026, "looks stupid please move up"): the sort chooser ends the toolbar row, right after Filters,
   in the Filters box: its icon 12 in from the border with an 8 gap to the label, the order, then the select chevron.
   On phones it stays at the right of the count line, as before, with no icon (discover.js placeSort). */
.dsort { position: relative; display: inline-flex; flex: none; }
.dsort:has(> #sort[hidden]) { display: none; }
.dsort > .icon { display: none; }
.disc-toolbar .dsort > .icon { display: block; position: absolute; left: 13px; top: 50%; z-index: 1; margin-top: -8px; color: var(--ink); pointer-events: none; }
.disc-toolbar .dsort :is(select, :where(.csel)) { padding-left: 36px; }
/* the folds: is-compact keeps the label (Filters keeps its word there too); is-compact-2 shows the icon box alone,
   as Filters does, so the row never wraps; the name stays "Sort results" and the tip names the order */
.disc .disc-toolbar.is-compact-2 .dsort :is(select, :where(.csel)) { width: 32px !important; min-width: 32px; padding: 0; background-image: none; }
.disc .disc-toolbar.is-compact-2 .dsort > .icon { left: 50%; margin-left: -8px; }
.disc .disc-toolbar.is-compact-2 .dsort .csel-box { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (pointer: coarse) {
  .disc .disc-toolbar.is-compact-2 .dsort :is(select, :where(.csel)) { width: 44px !important; min-width: 44px; }
}
/* the Requirement submenu: foundation names head their groups, as the select's optgroups do */
.fmenu-group-h { display: flex; align-items: center; min-height: 28px; padding: var(--s-1) var(--s-2) 0; font: var(--t-label); color: var(--muted); }
.disc .sheet-field .fmenu-hint { display: block; margin-top: 2px; }

@media (max-width: 599px) {
  /* 4.5, 5.1: the mode control on its own full-width row, then the split button and Filters, all 44 tall */
  .disc .disc-mode { flex: 1 0 100%; }
  .disc .disc-mode > button { flex: 1 1 0; min-width: 0; }
  .disc--filler .disc-titlewrap { height: auto; padding-top: var(--s-1); }
  .disc--filler .disc-toolbar { margin-top: var(--s-3); }
  .disc-unopened, .disc-hidden { margin-top: var(--s-1); }
}

/* b8r1 m1 R1 near-miss: the search is 100% of the list column up to 640, but a column only slightly wider than
   the cap (655 at 1440 with the pane) left a 15px step against the toolbar, sort and list edge. Under a 700
   column the field takes the whole column, so it shares the list right edge as in BT catalog (search 372-731
   over cards 372-731) and Linear 0038. Owner walk 2 W5 lifted the 640 cap for every column (dibs.css .disc-search):
   the field always runs to the list edge, so this rule now only restates it. */
.disc .disc-searchwrap { container: dsearch / inline-size; }
@container dsearch (max-width: 700px) {
  .disc .disc-search { max-width: none; }
}
