/* ================================================================
   Component layer. Every card and block that appears on more than
   one page type.

   Load order is style.css, then this file, then assets/{path}.css.
   Enqueued in functions.php as 'sidenotes-components' with
   'sidenotes-child' as its dependency, and every per-page
   stylesheet declares this file as its dependency in turn. Nothing
   here may depend on a rule in a page stylesheet.

   What belongs here: anything rendered by a file under
   templates/parts/components/, plus the tint-context overrides for
   those components.

   What does not: tokens, the reset, the header, the footer, section
   grammar and utilities, which are all in style.css; and the
   composition rules that arrange these components on one specific
   page, which stay in that page's own stylesheet. The homepage FAQ
   rail is the worked example: .faq-item and .faqlist are here
   because every page type renders them, while .faqwrap and
   .faqrail are the homepage's two-column arrangement and stay in
   home.css.

   Media queries sit with the component they modify rather than in
   one block at the end. A component moved here without its
   breakpoint rules would collapse on the first narrow viewport of
   whichever page type adopts it next, and the page that broke it
   would not be the page that introduced it.
   ================================================================ */


/* ===================== programme cards ===================== */
.proggrid{display:flex;flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory;
  gap:14px;padding-bottom:2px;min-width:0}
.proggrid>*{flex:0 0 clamp(256px,86%,340px);scroll-snap-align:start}
.progcard{border:1.5px solid var(--line);border-radius:var(--r-md);overflow:hidden;display:flex;flex-direction:column;background:#fff;text-decoration:none;transition:border-color var(--t),box-shadow var(--t)}
.progcard .img-slot{aspect-ratio:16/7}
.progcard-b{padding:18px;display:flex;flex-direction:column;flex:1;min-width:0}
.progcard h3{font-size:var(--fs-md);margin-bottom:5px}
.pmeta{font-size:var(--fs-sm);color:var(--ink-2);font-weight:600;margin-bottom:16px}
.pfee small{display:block;color:var(--ink-2);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;font-weight:600;margin-bottom:1px}
.pfee b{display:block;font-weight:800;font-size:var(--fs-xl);letter-spacing:-0.02em;color:var(--teal-deep);font-variant-numeric:tabular-nums}
.cardlink{margin-top:auto;padding-top:16px;font-size:var(--fs-base);font-weight:700;color:var(--teal)}

/* ====================== college cards ====================== */
.collgrid{display:flex;flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory;
  gap:14px;padding-bottom:2px;min-width:0}
.collgrid>*{flex:0 0 clamp(256px,86%,340px);scroll-snap-align:start}
.collcard{border:1.5px solid var(--line);border-radius:var(--r-md);text-decoration:none;display:flex;flex-direction:column;background:#fff;padding:18px;transition:border-color var(--t),box-shadow var(--t)}
.cbody{min-width:0}
.ulogo{display:block;width:54px;height:54px;flex:none;margin-bottom:14px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface-2);object-fit:contain}
section.tint .ulogo{background:#fff}

.collcard h3{font-size:var(--fs-md);margin-bottom:8px}
.badgerow{display:flex;flex-wrap:wrap;gap:6px}
.badge{font-size:var(--fs-xs);padding:3px 8px;background:var(--teal-tint);color:var(--teal-dark);border-radius:var(--r-sm);font-weight:700}
.srcnote{font-size:var(--fs-sm);color:var(--ink-2);margin-top:16px}

/* ==================== specialisation list ==================== */
.speccols{display:grid;grid-template-columns:repeat(3,1fr);gap:0 32px;border-top:1px solid var(--line)}
.speccols a{display:flex;align-items:center;min-height:52px;padding:8px 0;border-bottom:1px solid var(--line);font-size:var(--fs-base);text-decoration:none;color:var(--ink)}
.showall{display:none;margin-top:16px;width:100%;padding:13px;min-height:44px;border:1.5px solid var(--line);border-radius:var(--r-md);background:#fff;font-family:inherit;font-size:var(--fs-base);font-weight:700;color:var(--teal);cursor:pointer}

/* ======================== check strip ======================== */
.checkstrip{display:grid;grid-template-columns:repeat(4,1fr);border:1.5px solid var(--line);border-radius:var(--r-md);background:#fff}
.checkstrip>div{padding:18px 20px;border-right:1px solid var(--line)}
.checkstrip>div:last-child{border-right:none}
.checkstrip b{display:block;font-weight:700;font-size:var(--fs-md);letter-spacing:-0.01em;margin-bottom:5px}
.checkstrip span{font-size:var(--fs-sm);color:var(--ink-2)}
.checkstrip a{color:var(--teal);font-weight:600}

/* ======================== guide cards ======================== */
.guidegrid{display:flex;flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory;
  gap:14px;padding-bottom:2px;min-width:0}
.guidegrid>*{flex:0 0 clamp(256px,86%,340px);scroll-snap-align:start}
.guide{border:1.5px solid var(--line);border-radius:var(--r-md);overflow:hidden;text-decoration:none;display:flex;flex-direction:column;background:#fff;transition:border-color var(--t)}
.guide-b{flex:1;min-width:0}
.guide .img-slot{aspect-ratio:16/7}
.guide-b{padding:16px;display:flex;flex-direction:column;flex:1}
.guide h3{font-size:var(--fs-md);margin-bottom:6px}
.guide p{font-size:var(--fs-sm);color:var(--ink-2)}

/* ========================== faq list ========================== */
/* The list and the item. How the list is placed on the page is the
   page's business: the homepage puts it beside a rail, the hub and
   the programme page run it full width. */
.faqlist{max-width:none}
.faq-item{border-bottom:1px solid var(--line-soft)}
.faq-item summary{padding:16px 0;cursor:pointer;font-weight:700;font-size:var(--fs-md);letter-spacing:-0.01em;list-style:none;display:flex;justify-content:space-between;gap:14px;align-items:center}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{content:"+";width:26px;height:26px;border-radius:50%;background:var(--teal-tint);color:var(--teal-dark);display:flex;align-items:center;justify-content:center;font-size:var(--fs-md);line-height:1;flex:none}
section.tint .faq-item summary::after{background:#fff}
.faq-item[open] summary::after{content:"\2013";background:var(--teal);color:#fff}
.faq-item p{padding:0 0 16px;color:var(--ink-2);font-size:var(--fs-base);max-width:70ch}

/* ======================== contact card ======================== */
.callback{border:1.5px solid var(--line);border-radius:var(--r-md);padding:20px 22px;background:#fff}
.callback strong{display:block;font-weight:700;font-size:var(--fs-md);letter-spacing:-0.01em;margin-bottom:3px}
.callback p{color:var(--ink-2);font-size:var(--fs-sm)}
.cbtns{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.cbtns .cbtn{flex:1;text-align:center}
.cbtn{text-decoration:none;font-weight:700;font-size:var(--fs-base);color:var(--ink);border:1.5px solid var(--line);border-radius:var(--r-md);padding:11px 20px;white-space:nowrap}
.cbtn.wa{background:var(--wa);border-color:var(--wa);color:#fff}

/* ========================= page head ========================= */
/* Opens every page type except the homepage. Breadcrumb, H1, one
   line, optional fact row. */
.phead{padding:32px 0 28px;border-bottom:1px solid var(--line)}
.phead h1{font-size:clamp(26px,3.6vw,38px);max-width:20ch;margin-bottom:10px}
.phead-lead{color:var(--ink-2);font-size:var(--fs-lead);max-width:62ch}

.crumbs{margin-bottom:14px}
.crumbs ol{display:flex;flex-wrap:wrap;align-items:center;gap:6px;list-style:none;padding:0;margin:0}
.crumbs li{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--ink-2)}
.crumbs li + li::before{content:"/";color:var(--line);flex:none}
.crumbs a{color:var(--ink-2);text-decoration:none}
.crumbs [aria-current]{font-weight:600;color:var(--ink)}

.factrow{display:flex;flex-wrap:wrap;gap:0 40px;margin:22px 0 0;padding:0}
.factrow div{padding:0}
.factrow dt{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:var(--ink-2);margin-bottom:3px}
.factrow dd{margin:0;font-weight:700;font-size:var(--fs-md);letter-spacing:-0.01em;font-variant-numeric:tabular-nums}

/* ========================== terminal ========================== */
/* Closes every page type except the homepage. Never carries a gate:
   a form at the foot of a page reads as a last grab. */
.terminal{border-top:1px solid var(--line)}
.terminal-grid{display:grid;grid-template-columns:1fr 260px;gap:44px;align-items:start}
.terminal-grid>*{min-width:0}
.terminal .callback{background:#fff}
.terminal-links{display:flex;flex-direction:column;gap:2px}
.terminal-links .eyebrow{margin-bottom:8px}
.terminal-links a{display:block;padding:9px 0;font-size:var(--fs-base);font-weight:600;color:var(--ink);text-decoration:none;border-bottom:1px solid var(--line)}

/* ======================== listing card ======================== */
/* The wide row on /colleges/. Separate from .collcard, which is the
   narrow carousel tile: a listing row carries enough to rule a
   college in or out, a tile has to survive at 256px. */
.lcard{position:relative;display:grid;grid-template-columns:64px 1fr 148px;gap:20px;align-items:start;
  padding:20px;border:1.5px solid var(--line);border-radius:var(--r-md);background:#fff;
  transition:border-color var(--t),box-shadow var(--t)}

/* The heading link is stretched over the whole row, so the target is the card
   rather than three words in the corner. One link per card, not two: the
   visible control beside the fee is a span, because a second anchor to the
   same place doubles what a screen reader has to read through and doubles the
   tab stops on a page of a hundred rows.

   The trade is that text inside the card cannot be selected by dragging. On a
   listing row that is worth it; on a page of prose it would not be. */
.lcard h3 a::after{content:"";position:absolute;inset:0;border-radius:var(--r-md)}

/* Touch has no hover, so the press itself is the feedback. */
.lcard:active{border-color:var(--teal)}

/* Focus lands on the heading link, which is invisible where it is stretched,
   so the ring is drawn on the card instead. Without this a keyboard user
   tabbing the list has no idea where they are. */
.lcard h3 a:focus-visible{outline:none}
.lcard:has(h3 a:focus-visible){outline:2px solid var(--teal);outline-offset:2px;border-color:var(--teal)}
.lcard>*{min-width:0}
.lcard .ulogo{width:64px;height:64px;margin-bottom:0}
.lcard h3{font-size:var(--fs-md);margin-bottom:5px}
.lcard h3 a{color:inherit;text-decoration:none}
/* Offering mode: the college name sits between the specialisation heading and
   the location line, so it reads as the answer to "whose". */
.lcard-college{font-size:var(--fs-base);font-weight:700;color:var(--ink);margin-bottom:2px}
.lcard-meta{font-size:var(--fs-sm);color:var(--ink-2);margin-bottom:11px}
.lcard .badgerow{margin-bottom:11px}
.lcard-prog{font-size:var(--fs-sm);color:var(--ink-2)}
.lcard-fee{text-align:right}
.lcard-fee small{display:block;color:var(--ink-2);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;font-weight:600;margin-bottom:1px}
/* --fs-xl, matching the fee on the homepage programme card. This read
   --fs-lg, which is not one of the seven tokens, so the declaration was
   invalid and the figure fell back to inherited 14.5px: the most important
   number on the card was rendering smaller than the college name above it. */
.lcard-fee b{display:block;font-weight:800;font-size:var(--fs-xl);letter-spacing:-0.02em;color:var(--teal-deep);font-variant-numeric:tabular-nums;margin-bottom:12px}
/* An outlined control rather than a text link. A hundred filled buttons down
   a page would shout over the fee beside them and over the one action the page
   actually reserves colour for, but plain text in a corner reads as a caption
   rather than a way in. */
.lcard-cta{display:inline-flex;align-items:center;gap:7px;min-height:40px;padding:9px 16px;
  border:1.5px solid var(--line);border-radius:var(--r-md);
  font-size:var(--fs-base);font-weight:700;color:var(--teal);white-space:nowrap;
  transition:background var(--t),border-color var(--t),color var(--t)}
.lcard-cta::after{content:"\2192";font-weight:700;transition:transform var(--t)}

/* ============================ gate ============================ */
/* Shell only. No blur, no overlay: the summary above is real content and the
   box below states plainly what unlocking adds. */
.gate-summary{color:var(--ink-2);font-size:var(--fs-base);max-width:70ch;margin-bottom:18px}
.gate-box{border:1.5px dashed var(--line);border-radius:var(--r-md);background:var(--surface-2);padding:26px;text-align:center}
.gate-h{font-weight:800;font-size:var(--fs-md);letter-spacing:-0.01em;margin-bottom:5px}
.gate-note{color:var(--ink-2);font-size:var(--fs-sm);max-width:52ch;margin:0 auto 16px}
.gate-btn{min-height:44px;padding:12px 26px;border:none;border-radius:var(--r-md);background:var(--teal);color:#fff;font-family:inherit;font-size:var(--fs-base);font-weight:800;cursor:pointer}
.gate-btn:disabled{background:var(--ink-2);opacity:.5;cursor:not-allowed}

/* ========================== filters ========================== */
/* Hidden until sn_facets() says a filter can do work. Rendered
   `hidden` and revealed by script, so a JavaScript-off visitor sees
   the full list rather than dead controls. */
.filters-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:16px}
/* The h2 stays for document structure, but not the teal section bar. That
   bar marks a section of content, and a panel of controls beside the results
   is not one: given the bar it competes with the listing it filters. */
.filters-title{font-size:var(--fs-md);padding-left:0;margin-bottom:0}
.filters-title::before{display:none}
.filters-clear{border:none;background:none;padding:0;font-family:inherit;font-size:var(--fs-sm);font-weight:600;color:var(--teal);cursor:pointer;text-decoration:underline}
.facet{border:none;padding:0;margin:0;min-width:0;border-bottom:1px solid var(--line)}
.facet:last-of-type{border-bottom:none}
.facet legend{display:block;width:100%;padding:0;float:left}

/* The disclosure header. A legend cannot be a button in a way every browser
   agrees on, so the button sits inside it and is made to fill it. */
/* user-select:none because a disclosure header is clicked repeatedly, and a
   double click or a click that drags a pixel selects the label instead. The
   legend wrapping it is width:100% and floated, so the browser paints the
   selection as a filled bar across the whole rail. Nothing here sets a
   background; that bar is the selection highlight. */
.facet-toggle{display:flex;align-items:center;gap:8px;width:100%;min-height:48px;
  padding:0;border:none;background:none;cursor:pointer;font-family:inherit;
  font-size:var(--fs-sm);font-weight:700;color:var(--ink);text-align:left;
  -webkit-user-select:none;user-select:none}
.facet-name{flex:1;min-width:0}
.facet-picked{flex:none;min-width:20px;height:20px;padding:0 6px;border-radius:var(--r-pill);
  background:var(--teal);color:#fff;font-size:var(--fs-xs);line-height:20px;
  text-align:center;font-variant-numeric:tabular-nums}
.facet-toggle::after{content:"";flex:none;width:8px;height:8px;margin-left:2px;
  border-right:2px solid var(--ink-2);border-bottom:2px solid var(--ink-2);
  transform:rotate(45deg) translate(-2px,-2px);transition:transform var(--t)}
.facet-toggle[aria-expanded="true"]::after{transform:rotate(-135deg) translate(-2px,-2px)}
.facet.has-picked .facet-toggle{color:var(--teal-dark)}
.facet-opts{display:flex;flex-direction:column;padding-bottom:12px;clear:both}
.facet-opts[hidden]{display:none}
.facet-opt{display:flex;align-items:center;gap:9px;min-height:38px;font-size:var(--fs-base);cursor:pointer}
.facet-opt input{width:17px;height:17px;flex:none;accent-color:var(--teal);margin:0;cursor:pointer}
.facet-label{flex:1;min-width:0}
.facet-count{font-size:var(--fs-sm);color:var(--ink-2);font-variant-numeric:tabular-nums;flex:none}
.facet-opt.is-empty{opacity:.4}
.facet-opt.is-empty input{cursor:not-allowed}
.filters-toggle{display:none;align-items:center;justify-content:center;gap:8px;padding:10px 16px;min-height:44px;border:1.5px solid var(--line);border-radius:var(--r-md);background:#fff;font-family:inherit;font-size:var(--fs-base);font-weight:700;color:var(--ink);cursor:pointer}
.filters-toggle[data-active]{border-color:var(--teal);color:var(--teal)}
.filters-toggle .tcount{display:none;min-width:21px;height:21px;padding:0 6px;border-radius:var(--r-pill);background:var(--teal);color:#fff;font-size:var(--fs-xs);line-height:21px;font-variant-numeric:tabular-nums}
.filters-toggle[data-active] .tcount{display:inline-block}

/* The close button and the apply footer belong to the mobile sheet only. The
   desktop rail is always open and always beside the results, so it needs
   neither. */
.filters-close,
.filters-foot{display:none}



/* ================================================================
   Hover states, gathered and gated.

   iOS latches :hover onto the last element tapped and holds it
   until something else is tapped. Ungated, a card keeps its teal
   border and filled button long after the person has scrolled
   past it, so one row in the list looks selected for no reason.
   Reported from a device; no desktop render shows it.

   pointer:fine as well as hover:hover, because a stylus and some
   hybrid laptops report hover support while still being touched.

   Every hover rule in this file belongs in here. One left outside
   is one element that stays stuck, and it will be found on a
   phone rather than in review.
   ================================================================ */
@media (hover:hover) and (pointer:fine){
  .progcard:hover{border-color:var(--teal);box-shadow:0 4px 0 var(--teal-tint)}
  .progcard:hover .cardlink{text-decoration:underline}
  .collcard:hover{border-color:var(--teal);box-shadow:0 4px 0 var(--teal-tint)}
  .speccols a:hover{color:var(--teal)}
  .guide:hover{border-color:var(--teal)}
  .cbtn:hover{border-color:var(--teal);color:var(--teal)}
  .cbtn.wa:hover{background:var(--wa-dark);border-color:var(--wa-dark);color:#fff}
  .crumbs a:hover{color:var(--teal);text-decoration:underline}
  .terminal-links a:hover{color:var(--teal)}
  .lcard:hover{border-color:var(--teal);box-shadow:0 4px 0 var(--teal-tint)}
  .lcard h3 a:hover{color:var(--teal)}
  .lcard:hover .lcard-cta{background:var(--teal);border-color:var(--teal);color:#fff}
  .lcard:hover .lcard-cta::after{transform:translateX(3px)}
}

/* ============ responsive overrides, kept last ============ */
@media(max-width:900px){
  .terminal-grid{grid-template-columns:1fr;gap:30px}
  .lcard{grid-template-columns:52px 1fr;gap:16px}
  .lcard .ulogo{width:52px;height:52px}
  /* The fee and the action stack rather than sharing a line. At 390px the
     label, the figure and the button do not fit together, so the button
     wrapped onto its own line and sat right-aligned against nothing, reading
     as a stray element rather than as the row's action. Full width under the
     fee is unambiguous and lands where a thumb already is. */
  /* Fee on the left, action on the right, one band.

     Laid out with named areas rather than a flex row, because "TOTAL FEE" and
     "₹2,25,000" side by side came to 177px and the button to 115px, which is
     302px inside a card that has exactly 302px at 390 wide. It fitted at 430
     and wrapped on every phone below it. Stacking the label over the figure
     costs a line that was already there and leaves the button far inside the
     width at 320. */
  .lcard-fee{grid-column:1/-1;text-align:left;display:grid;
    grid-template-columns:1fr auto;
    grid-template-areas:"label action" "value action";
    column-gap:14px;padding-top:14px;border-top:1px solid var(--line)}
  .lcard-fee small{grid-area:label;display:block;margin:0}
  .lcard-fee b{grid-area:value;margin-bottom:0}

  /* Filled at rest. There is no hover on a phone to reveal that this is a
     control, and outlined was a desktop compromise for a hundred buttons in
     one column, which a phone never shows at once. */
  /* Filled, because there is no hover on a phone to reveal it as a control.
     Pushed right by auto margin so it sits at the thumb edge rather than
     against the fee it is not part of. Compact padding: it only has to be
     tappable, and 44px of height does that without 44px of width to spare. */
  .lcard-cta{grid-area:action;align-self:center;min-height:44px;padding:9px 16px;
    background:var(--teal);border-color:var(--teal);color:#fff}
  .filters-toggle{display:flex}

  /* ---- filter sheet ----
     Below this width the panel stops being a rail and becomes a sheet over
     the page. Inline it was 1246px tall, which pushed the first result more
     than three screens down: a filter panel that buries the thing it filters
     is worse than no filter at all.

     Fixed rather than absolute so it does not scroll with the page, and its
     own body scrolls inside a fixed frame, which keeps the heading and the
     apply button reachable however long the facet list grows. */
  .filters{position:fixed;inset:0;z-index:80;display:flex;flex-direction:column;
    background:#fff;margin:0;padding:0}
  .filters[hidden]{display:none}

  /* --gut, not --gutter. The token is named --gut in style.css, and an
     undefined custom property in a shorthand makes the whole declaration
     invalid, so padding fell to zero and every label in the sheet sat flush
     against the screen edge. It renders, it just looks wrong, which is why a
     screenshot caught it and no test did. */
  .filters-head{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:12px;
    margin:0;padding:14px var(--gut);border-bottom:1px solid var(--line);background:#fff}
  .filters-title{flex:1;font-size:var(--fs-lead)}
  .filters-clear{min-height:44px;display:flex;align-items:center}

  .filters-close{display:flex;align-items:center;justify-content:center;flex:none;
    width:44px;height:44px;margin-right:-10px;border:none;background:none;padding:0;
    font-family:inherit;font-size:26px;line-height:1;color:var(--ink-2);cursor:pointer}
  .filters-close:hover{color:var(--ink)}

  .filters-form{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding:20px var(--gut) 12px}

  /* 38px is under the 44px minimum for a thumb, and a mis-tap in a filter
     list silently returns the wrong set of colleges. */
  .facet-opt{min-height:46px}
  .facet-opt input{width:20px;height:20px}

  .filters-foot{display:block;flex:none;padding:12px var(--gut);
    padding-bottom:calc(12px + env(safe-area-inset-bottom));
    border-top:1px solid var(--line);background:#fff}
  .filters-apply{width:100%;min-height:48px;border:none;border-radius:var(--r-md);
    background:var(--teal);color:#fff;font-family:inherit;font-size:var(--fs-md);
    font-weight:800;cursor:pointer}
  .filters-apply:disabled{background:var(--ink-2);opacity:.55}

  .speccols{grid-template-columns:repeat(2,1fr)}
  .checkstrip{grid-template-columns:1fr}
  .checkstrip>div{border-right:none;border-bottom:1px solid var(--line)}
  .checkstrip>div:last-child{border-bottom:none}
}
@media(max-width:600px){
  .phead{padding:24px 0 22px}
  .factrow{gap:0 26px}
  .speccols{grid-template-columns:1fr}
  .showall{display:block}
  .speccols.collapsed a:nth-of-type(n+9){display:none}
}

/* ================================================================
   Listing pages.

   The two-column arrangement that puts the filter rail beside the
   results. Used by /colleges/, every course page, and every routed
   specialisation listing page.

   Moved here from assets/online-mba.css and assets/colleges.css on
   4 September 2026. It was byte-identical in both, and its own
   comment said it was copied to each. A third copy was about to be
   made for the routed listing pages, which is the point at which
   copying stops being a shortcut.
   ================================================================ */
.listing{padding:36px 0 56px}

.listing-grid{display:grid;grid-template-columns:1fr;gap:0}
.listing-grid>*{min-width:0}

/* The rail appears only when the filter panel does. sn_facets()
   returns empty below twelve colleges, the .listing-side element is
   not rendered at all, and this rule never matches, so the results
   run full width without a placeholder column. */
.listing-grid:has(.listing-side){grid-template-columns:236px 1fr;gap:44px}

.listing-side{position:sticky;top:88px;align-self:start}

.listing-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding-bottom:14px;margin-bottom:18px;border-bottom:1px solid var(--line)}
.listing-count{font-size:var(--fs-sm);color:var(--ink-2);font-weight:600;font-variant-numeric:tabular-nums}
.listing-sort{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm);color:var(--ink-2);font-weight:600}
.listing-sort select{font-family:inherit;font-size:var(--fs-sm);font-weight:600;color:var(--ink);
  border:1.5px solid var(--line);border-radius:var(--r-sm);padding:7px 10px;min-height:38px;background:#fff;cursor:pointer}
.listing-sort select:hover{border-color:var(--teal)}

.listing-cards{display:flex;flex-direction:column;gap:12px}
.listing-cards .lcard.is-hidden{display:none}

.listing-empty{padding:34px 0;color:var(--ink-2);font-size:var(--fs-base);max-width:52ch}

.listing .srcnote{margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}

.listing-controls{display:flex;align-items:center;gap:10px}

@media(max-width:900px){
  /* Filter and Sort sit together on one row under the count.

     Before this, Filter was a full width button in the rail, the count was a
     line of its own, and Sort was a third row: three bands of controls
     stacked above the first result, on the screen with the least room for
     them. They are one decision, so they get one row. */
  .listing-bar{flex-wrap:wrap;gap:10px;padding-bottom:12px;margin-bottom:14px}
  .listing-count{flex:1 0 100%}
  .listing-controls{flex:1 1 auto;width:100%}
  .listing-controls .filters-toggle{flex:0 0 auto}
  .listing-sort{flex:1;justify-content:flex-end;gap:8px;min-width:0}

  /* The word "Sort" goes, the label stays. The select already reads "College
     name, A to Z", which says what it does better than a caption beside it,
     and the 46px it was taking is 46px the select did not have. */
  .listing-sort > span{position:absolute;width:1px;height:1px;margin:-1px;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .listing-sort select{flex:1;min-width:0}
}

@media(max-width:900px){
  /* The rail becomes a disclosure above the results. :has() is
     overridden rather than removed, so the same markup serves both. */
  .listing-grid:has(.listing-side){grid-template-columns:1fr;gap:0}
  .listing-side{position:static;margin-bottom:20px}
  /* 16px, not 26px. The head block already ends in a rule and a margin, and
     the gap above the count read as a mistake rather than as separation.
     Set in the shorthand here rather than as padding-top earlier in the file:
     both rules sit in a max-width:900px block, so the shorthand won and the
     override did nothing. */
  .listing{padding:16px 0 44px}
}
