/* ==========================================================================
   USRSE'26 program room grid
   Styles the markup generated by scripts/build-program.js
   (_includes/program-grid.html) and the List / Grid toolbar hand-authored
   in pages/program/program.md.

   The grid is a CSS Grid per day: column 1 is the time rail, columns 2..N
   are rooms, and every row is five minutes. The generator places each
   session with inline grid-column / grid-row and emits the track counts as
   --grid-cols / --grid-rows; this sheet owns the track sizes, so the
   vertical scale lives in the single --grid-row-h token.

   The palette mirrors assets/css/program.css so the two views read as one
   system: the US-RSE brand purple (#741755, --us-rse-main) as the single
   accent (plenary field, eyebrow, focus), #4a4a4a body, #363636 titles,
   #dbdbdb hairlines, and #757575 for muted text (the theme's #7a7a7a nudged
   one step darker — the raw swatch is 4.3:1 on white, which fails WCAG AA at
   the small sizes used here). The tokens are duplicated rather than shared
   because program.css scopes its block to `.program`, a sibling of this
   view. Cards are never tinted by track or type — the eyebrow carries the
   category as text, so colour is never the only cue.

   The include renders inside the theme's Bulma `.content` wrapper, whose
   typography hits the generated h2/h3/p/ol/li at up to (0,2,1) specificity.
   The reset block below re-zeroes those at matching specificity (this sheet
   loads after the theme, so ties land here). CONVENTION, as in program.css:
   component rules create space with padding, which `.content` never sets.
   ========================================================================== */

.program-grid {
  --grid-accent: var(--us-rse-main);
  --grid-ink: #4a4a4a;
  --grid-strong: #363636;
  --grid-muted: #757575;
  --grid-hairline: #dbdbdb;
  --grid-rule: #ececec;      /* half-hour gridline, one step lighter */
  --grid-wash: #f4ecf1;
  --grid-band: #fafafa;

  /* Track geometry. The rail clears "10:30am" at 11px semibold; a room
     column never shrinks below --grid-col-min, so the scroller overflows
     horizontally instead of crushing cards. 0.5rem per five minutes puts a
     90-minute session at 9rem. */
  --grid-rail: 3.5rem;
  --grid-col-min: 10rem;
  --grid-row-h: 0.5rem;
  --grid-gap: 0.375rem;      /* between room columns and between lanes */

  color: var(--grid-ink);
}

/* --------------------------------------------------------------------------
   Theme neutralization — see the header comment. Bare variants cover the
   include rendering outside a `.content` wrapper.
   -------------------------------------------------------------------------- */

.content .program-grid :is(h2, h3, p),
.program-grid :is(h2, h3, p) {
  margin: 0;
}

.content .program-grid ol,
.program-grid ol {
  margin: 0;
  padding-left: 0;
  list-style: none;
}

.content .program-grid li + li,
.program-grid li + li {
  margin-top: 0;
}

/* Visually hidden, still read: the card's room, which sighted readers get
   from the column header. */
.grid__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   Toolbar — the List / Grid segmented control. Hand-authored in
   program.md, shipped hidden, revealed by program-view.js.
   Pills match .program-nav__pill; the pressed state carries the accent.
   -------------------------------------------------------------------------- */

.program-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding-bottom: 1.1rem;
}

.program-toolbar__views {
  display: inline-flex;
  gap: 0.25rem;
}

.program-toolbar__view {
  padding: 0.3rem 1rem;
  border: 1px solid #dbdbdb;
  border-radius: 999px;
  background: #fff;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.5;
  color: #363636;
  cursor: pointer;
}

.program-toolbar__view:hover,
.program-toolbar__view:focus-visible {
  border-color: var(--us-rse-main);
  color: var(--us-rse-main);
}

.program-toolbar__view:focus-visible {
  outline: 2px solid var(--us-rse-main);
  outline-offset: 2px;
}

.program-toolbar__view[aria-pressed="true"] {
  border-color: var(--us-rse-main);
  background: #f4ecf1;
  color: var(--us-rse-main);
}

/* --------------------------------------------------------------------------
   Day pills — the grid's own jump nav (grid-day-* targets)
   -------------------------------------------------------------------------- */

.program-grid__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--grid-hairline);
}

.program-grid__nav-label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--grid-muted);
}

.program-grid__pill {
  padding: 0.3rem 1rem;
  border: 1px solid var(--grid-hairline);
  border-radius: 999px;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--grid-strong);
}

.program-grid__pill:hover,
.program-grid__pill:focus-visible {
  border-color: var(--grid-accent);
  color: var(--grid-accent);
}

/* --------------------------------------------------------------------------
   Day header — the accent day rule, as in the list view
   -------------------------------------------------------------------------- */

.program-grid__day {
  margin-top: 2.75rem;
  scroll-margin-top: 5rem;   /* pill anchors clear the fixed navbar */
}

.program-grid__nav + .program-grid__day {
  margin-top: 1.75rem;
}

/* Two classes out-rank the theme's `.content h2` (size, weight, color). */
.program-grid .program-grid__title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  padding-bottom: 0.45rem;
  border-bottom: 3px solid var(--grid-accent);
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--grid-strong);
}

.program-grid__draft {
  margin-left: auto;
  padding-left: 1rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--grid-muted);
}

/* --------------------------------------------------------------------------
   Scroller — the one element that scrolls, on both axes. Sticky headers pin
   to the nearest scrollport, so the vertical scroll has to live here too,
   not on the page; that is also what keeps the page body from ever
   scrolling sideways. Focusable (tabindex in the markup) so keyboards can
   scroll it; the ring says so.
   -------------------------------------------------------------------------- */

.program-grid__scroller {
  margin-top: 0.9rem;
  max-height: 85vh;
  overflow: auto;
  border: 1px solid var(--grid-hairline);
  border-radius: 3px;
}

.program-grid__scroller:focus-visible {
  outline: 2px solid var(--grid-accent);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Grid tracks — counts from the generator, sizes from here
   -------------------------------------------------------------------------- */

/* The theme's reboot.css also has a `.grid` (a flex row with -0.9375em
   side margins); this two-class rule out-ranks it, and the margin reset
   is what keeps the rail from sliding under the scroller's left edge. */
.program-grid .grid {
  display: grid;
  grid-template-columns: var(--grid-rail) repeat(var(--grid-cols), minmax(var(--grid-col-min), 1fr));
  grid-template-rows: auto repeat(var(--grid-rows), var(--grid-row-h));
  column-gap: var(--grid-gap);
  margin: 0;
  background: #fff;
}

/* Sticky chrome: room headers hold the top edge, the rail holds the left,
   the corner holds both. Solid backgrounds so cards slide beneath. */
.grid__corner,
.grid__room {
  position: sticky;
  top: 0;
  grid-row: 1;
  background: #fff;
  border-bottom: 1px solid var(--grid-hairline);
}

.grid__corner {
  grid-column: 1;
  left: 0;
  z-index: 4;
}

.grid__room {
  z-index: 3;
  padding: 0.55rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  color: var(--grid-strong);
}

/* Half-hour gridlines span the full width; hours are one step darker. */
.grid__rule {
  grid-column: 1 / -1;
  border-top: 1px solid var(--grid-rule);
  pointer-events: none;
}

.grid__rule--hour {
  border-top-color: var(--grid-hairline);
}

/* Hour labels: sticky at the left, each spanning down to the next hour.
   Own top border so the hour tick stays visible in the rail while the
   white background hides the gridlines cards would otherwise show through
   when scrolled under it. */
.grid__time {
  position: sticky;
  left: 0;
  grid-column: 1;
  z-index: 2;
  padding: 0.15rem 0.5rem 0 0;
  background: #fff;
  border-top: 1px solid var(--grid-hairline);
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-align: right;
  white-space: nowrap;
  color: var(--grid-muted);
}

/* --------------------------------------------------------------------------
   Bands — breaks, meals, registration, and anything venue-wide. Span every
   room column; the dashed rules survive greyscale print. The label is
   sticky so a wide day still shows it wherever the reader has scrolled.
   -------------------------------------------------------------------------- */

.grid__band {
  grid-column: 2 / -1;
  display: flex;
  align-items: flex-start;   /* label at the top, clear of a card that
                                starts mid-band (Working Group Fair in
                                the middle of lunch) */
  min-width: 0;
  padding: 0.2rem 0.5rem;
  background: var(--grid-band);
  border-top: 1px dashed var(--grid-hairline);
  border-bottom: 1px dashed var(--grid-hairline);
}

.grid__band-label {
  position: sticky;
  left: calc(var(--grid-rail) + 0.5rem);
  overflow: hidden;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.25;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--grid-muted);
}

.grid__band-room {
  font-style: italic;
}

.grid__band-time {
  padding-left: 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Cards — one per session, a link to its list entry. The area is the
   session's time range; overflow clips inside the card so a busy session
   never spills into the next one. Lanes: cards sharing a room and time
   split the column by width + offset (grid items sharing an area overlap
   by default), and with --lane:0;--lanes:1 the maths collapses to full
   width and zero offset, so the common case needs no special rule.
   -------------------------------------------------------------------------- */

.program-grid .grid__card {
  --lane-w: calc((100% - var(--grid-gap) * (var(--lanes) - 1)) / var(--lanes));
  position: relative;
  display: block;
  box-sizing: border-box;
  width: var(--lane-w);
  min-width: 0;
  margin: 1px 0 1px calc((var(--lane-w) + var(--grid-gap)) * var(--lane));
  padding: 0.3rem 0.5rem 0.35rem 0.6rem;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--grid-hairline);
  border-radius: 3px;
  font-size: 0.8125rem;
  line-height: 1.3;
  color: var(--grid-ink);
  text-decoration: none;
}

.program-grid .grid__card:hover,
.program-grid .grid__card:focus-visible {
  border-color: var(--grid-accent);
  color: var(--grid-ink);
}

.program-grid .grid__card:focus-visible {
  outline: 2px solid var(--grid-accent);
  outline-offset: -2px;
}

/* Plenary field — the wash and inset accent bar of .session--plenary. */
.program-grid .grid__card--plenary {
  background: var(--grid-wash);
  box-shadow: inset 3px 0 0 var(--grid-accent);
}

.grid__card-time {
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--grid-muted);
}

.grid__card-eyebrow {
  padding-top: 0.1rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--grid-accent);
}

.grid__card-chair {
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--grid-muted);
}

/* Two classes out-rank the theme's `.content h3` (size, weight, color).
   A title that will not fit its card ends in an ellipsis rather than a
   sliced line: program-view.js measures the room left under the time and
   eyebrow and sets -webkit-line-clamp per card, which is why the box
   model here is -webkit-box. */
.program-grid .grid__card-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
  padding-top: 0.1rem;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--grid-strong);
}

/* --------------------------------------------------------------------------
   Mobile — narrower minimum columns and a tighter ramp so the scroller
   shows more than one room at a time without the cards going unreadable.
   -------------------------------------------------------------------------- */

@media (max-width: 40rem) {
  .program-grid {
    --grid-rail: 2.75rem;
    --grid-col-min: 7.5rem;
    --grid-gap: 0.25rem;
  }

  .program-grid__scroller {
    max-height: 80vh;
  }

  .grid__room {
    padding: 0.45rem 0.35rem;
    font-size: 0.75rem;
  }

  .program-grid .grid__card {
    padding: 0.2rem 0.35rem 0.25rem 0.45rem;
    font-size: 0.75rem;
  }

  .program-grid .grid__card-title {
    font-size: 0.8125rem;
  }

  .grid__band-label {
    font-size: 0.75rem;
  }
}

/* --------------------------------------------------------------------------
   Print — a room chart, one day per page. The scroller unclamps so nothing
   is cut off, sticky comes off, columns lose their minimum so every room
   fits the page width, and the ramp drops to ~8pt. Which view prints is not
   decided here: the inactive view carries `hidden`, so the page prints
   whichever the reader had active. Plenary swaps its wash for a solid
   border and bands keep their dashed rules — the distinctions that survive
   greyscale, where backgrounds and shadows do not.
   -------------------------------------------------------------------------- */

@media print {
  .program-grid {
    --grid-rail: 2.5rem;
    --grid-col-min: 0;
    --grid-row-h: 0.3rem;
    --grid-gap: 0.2rem;
    color: #000;
  }

  .program-toolbar,
  .program-grid__nav,
  .program-grid__draft {
    display: none;
  }

  .program-grid__day {
    margin-top: 0;
    break-before: page;
  }

  .program-grid__nav + .program-grid__day {
    break-before: auto;
  }

  .program-grid__scroller {
    max-height: none;
    overflow: visible;
    border: 0;
  }

  .grid__corner,
  .grid__room,
  .grid__time,
  .grid__band-label {
    position: static;
  }

  .grid__corner,
  .grid__room,
  .grid__time,
  .grid__band {
    border-color: #999;
  }

  .grid__room {
    padding: 0.25rem 0.2rem;
    font-size: 8pt;
  }

  .grid__time {
    font-size: 7pt;
  }

  .program-grid .grid__card {
    padding: 0.15rem 0.25rem 0.15rem 0.3rem;
    border-color: #999;
    font-size: 7pt;
    line-height: 1.2;
    color: #000;
  }

  .program-grid .grid__card--plenary {
    background: none;
    box-shadow: none;
    border-left: 3px solid #000;
  }

  .grid__card-time,
  .grid__card-eyebrow {
    font-size: 6pt;
  }

  .program-grid .grid__card-title {
    font-size: 8pt;
    color: #000;
  }

  .grid__band {
    background: none;
  }

  .grid__band-label {
    font-size: 7pt;
  }

  .grid__band-time {
    font-size: 6pt;
  }
}
