/* One semantic colour contract, across every EduLibrary page family. */
body.edu {
  --edu-paper:#f5f8fb; --edu-surface:#fff; --edu-ink:#1c2a38;
  --edu-muted:#526575; --edu-line:#d6e2eb; --edu-control-line:#718797;
  --edu-accent:#12669b; --edu-action:#12669b; --edu-on-action:#fff;
  --edu-action-hover:#094b78; --edu-accent-soft:#e6f4fd; --edu-navy:#0c315b;
  --edu-sky:#7fc9ee; --edu-route:#ef866d;
  --edu-warning:#784919; --edu-warning-bg:#fff3df; --edu-error:#a12635;
  --edu-success:#176748; --edu-success-bg:#e6f5ec;
  --ice-color-bg:var(--edu-paper); --ice-color-canvas:var(--edu-paper);
  --ice-color-surface:var(--edu-surface); --ice-color-surface-muted:var(--edu-paper);
  --ice-color-surface-field:var(--edu-paper); --ice-color-surface-brand:var(--edu-navy);
  --ice-color-on-surface-brand:#fff; --ice-color-text-accent-on-brand:#8ed7ff;
  --ice-color-text:var(--edu-ink); --ice-color-text-muted:var(--edu-muted);
  --ice-color-text-action:var(--edu-accent); --ice-color-text-accent:var(--edu-accent);
  --ice-color-border:var(--edu-line); --ice-color-hairline:var(--edu-line);
  --ice-color-border-strong:var(--edu-control-line);
  --ice-color-action:var(--edu-action); --ice-color-action-hover:var(--edu-action-hover);
  --ice-color-action-lift:var(--edu-action); --ice-color-on-action:var(--edu-on-action);
  --ice-color-on-action-hover:var(--edu-on-action);
  --ice-color-accent:var(--edu-action); --ice-color-on-accent:var(--edu-on-action);
  --ice-color-terracotta:var(--edu-accent); --ice-color-terracotta-soft:#8ed7ff;
  --card:var(--edu-surface); --ink:var(--edu-ink); --slate:var(--edu-muted);
  --hairline:var(--edu-line); --navy:var(--edu-ink); --terracotta:var(--edu-accent); --crimson:var(--edu-action);
  --pf-surface:var(--edu-surface); --pf-ink:var(--edu-ink); --pf-muted:var(--edu-muted);
  --pf-line:var(--edu-line); --pf-brand:var(--edu-ink); --pf-accent:var(--edu-accent); --pf-live:var(--edu-action);
  --pf-field:var(--edu-navy); --pf-on-field:#fff; --pf-on-field-muted:#d6e2eb; --pf-accent-on-field:#8ed7ff;
}
html[data-theme="dark"] body.edu {
  --pf-brand:var(--edu-ink); --pf-accent:var(--edu-accent); --pf-live:var(--edu-action);
  --edu-paper:#101b26; --edu-surface:#162533; --edu-ink:#eef5fb;
  --edu-muted:#b3c4d3; --edu-line:#354b5d; --edu-control-line:#7f97aa;
  --edu-accent:#8ed7ff; --edu-action:#8ed7ff; --edu-on-action:#142b3c;
  --edu-action-hover:#b5e5ff; --edu-accent-soft:#203b50; --edu-navy:#0c315b;
  --edu-sky:#7fc9ee; --edu-route:#ef866d;
  --edu-warning:#ffd598; --edu-warning-bg:#3b2d1d; --edu-error:#ffadb7;
  --edu-success:#9ee4c0; --edu-success-bg:#173a2d;
}
body.edu .edu-shell { max-width:1360px; width:100%; margin-inline:auto; padding-inline:32px; }
@media(max-width:767px) { body.edu .edu-shell { padding-inline:16px; } }
@media(max-width:359px) { body.edu .edu-shell { padding-inline:12px; } }
/* ⚠️ THE MARK'S INHERITED COLOUR *IS* THE LOCKUP'S FAILURE STATE (R-03.3).
   `.edu-brand__mark` holds one `<img alt="EduLibrary">` and nothing else, so a
   404, a blocked host or images-off leaves the browser painting that alt text
   in whatever colour the span passes down. `edulibrary-refined.css` declared
   `.edu-brand__mark { color:#8ed7ff }` at `(0,1,0)`; nothing here overrode it,
   so the fallback rendered sky blue on the #F5F8FB canvas — the coordinator
   measured **1.48:1** at 390px against a 4.5:1 requirement, and BRAND_KIT says
   outright "Do not use sky blue as small text on white". Ink is stated here, at
   `body.edu`, and the refined declaration is deleted so ONE rule owns it (T-08).
   The dark path does not regress: line 45's `brightness(0) invert(1)` paints the
   alt text white whatever it inherits, and `--edu-ink` is #EEF5FB in dark
   anyway, so the fallback stays legible even if that filter is ever dropped. */
body.edu .edu-brand__mark { width:192px; height:40px; border-radius:0; overflow:visible; color:var(--edu-ink); }
/* ⚠️ THE SOLE OWNER OF THE WORDMARK, AT EVERY WIDTH, AND DELIBERATELY (R-03.1).
   `horizontal.png` already contains the lettering, so an un-clipped span would
   print the name twice beside its own lockup. `EduBrand.astro` marks the span
   `aria-hidden` and puts the accessible name on the img alt, so this element is
   neither seen nor announced — it stays in the DOM because
   `tests/homepage.spec.mjs:189` asserts its text. Four rules in
   `edulibrary-refined.css` used to try to un-clip and re-size it and could never
   win (this selector is `(0,2,1)` and loads last); they are deleted rather than
   left to read as live. Un-clipping it means changing THIS rule. */
body.edu .edu-brand__word { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; }
body.edu .edu-brand--footer .edu-brand__mark { width:160px; height:100px; }
html[data-theme="dark"] body.edu .edu-brand__mark img { filter:brightness(0) invert(1); }
@media(max-width:600px) { body.edu .edu-brand__mark { width:164px; height:34px; } }
body.edu .record-trust, body.edu .ccard__flag { color:var(--edu-warning); background:var(--edu-warning-bg); border-color:var(--edu-line); }
body.edu .record-trust strong { color:var(--edu-warning); }
body.edu :is(input,select,textarea) { border-color:var(--edu-control-line); caret-color:var(--edu-accent); }
body.edu :focus-visible { outline:2px solid var(--edu-accent); outline-offset:3px; }
body.edu .edu-nav__item.is-current { color:var(--edu-ink); background:var(--edu-accent-soft); font-weight:750; }
body.edu .post__body > p, body.edu .ans-body > p { max-width:70ch; }
body.edu .prail__go { padding:12px 16px; min-height:44px; }
body.edu .prail__head { color:var(--edu-accent); }
body.edu :is(.prail__go,.pf-btn--quiet) { background:var(--edu-surface); border:1px solid var(--edu-line); box-shadow:none; color:var(--edu-accent); }

/* The footer is a wayfinding object, not an end-of-page link dump. The
   sequence mirrors the useful path through the record and marks the visitor's
   current section without turning any institution into a recommendation. */
body.edu .edu-foot__route {
  margin:0 0 clamp(26px,4vw,38px);
  padding:0 0 clamp(24px,3vw,32px);
  border-bottom:1px solid rgb(255 255 255 / 24%);
}
body.edu .edu-foot__route h2 {
  margin:0 0 18px;
  color:#fff;
  font-size:clamp(18px,1.7vw,22px);
  font-weight:720;
  letter-spacing:-.02em;
}
body.edu .edu-foot__route ol {
  position:relative;
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  gap:16px;
  margin:0;
  padding:0;
  list-style:none;
}
body.edu .edu-foot__route ol::before {
  content:'';
  position:absolute;
  z-index:0;
  top:15px;
  right:10%;
  left:10%;
  height:1px;
  background:rgb(142 215 255 / 42%);
}
body.edu .edu-foot__route li { position:relative; z-index:1; min-width:0; }
body.edu .edu-foot__route a {
  display:grid;
  grid-template-rows:32px auto;
  gap:10px;
  min-height:78px;
  color:#fff;
  text-decoration:none;
}
body.edu .edu-foot__route-marker {
  display:grid;
  width:32px;
  height:32px;
  justify-self:center;
  place-items:center;
  border:1px solid rgb(142 215 255 / 72%);
  border-radius:50%;
  background:var(--edu-navy);
  color:#d6e2eb;
  font-size:13px;
  font-weight:750;
  font-variant-numeric:tabular-nums;
  transition:background-color 180ms ease-out,border-color 180ms ease-out,color 180ms ease-out;
}
body.edu .edu-foot__route-copy { display:grid; gap:3px; min-width:0; text-align:center; }
body.edu .edu-foot__route-copy strong { color:#fff; font-size:14px; line-height:1.35; }
body.edu .edu-foot__route-copy small { color:#d6e2eb; font-size:13px; line-height:1.45; }
body.edu .edu-foot__route a:hover .edu-foot__route-marker,
body.edu .edu-foot__route a:focus-visible .edu-foot__route-marker {
  border-color:#fff;
  background:#8ed7ff;
  color:#142b3c;
}
body.edu .edu-foot__route li.is-current .edu-foot__route-marker {
  border-color:var(--edu-route);
  background:var(--edu-route);
  color:#142b3c;
}
body.edu .edu-foot__route li.is-current .edu-foot__route-copy strong { color:#8ed7ff; }
@media(max-width:700px) {
  body.edu .edu-foot__route ol { grid-template-columns:minmax(0,1fr); gap:0; }
  body.edu .edu-foot__route ol::before {
    top:16px;
    right:auto;
    bottom:16px;
    left:15px;
    width:1px;
    height:auto;
  }
  body.edu .edu-foot__route a {
    grid-template:1fr / 32px minmax(0,1fr);
    align-items:center;
    gap:14px;
    min-height:64px;
  }
  body.edu .edu-foot__route-marker { justify-self:start; }
  body.edu .edu-foot__route-copy { text-align:left; }
}
@media(prefers-reduced-motion:reduce) {
  body.edu .edu-foot__route-marker { transition:none; }
}

/* Impeccable refinement: shared reading, control and recovery surfaces. */
/* ⚠️ NO `color-scheme` HERE, AND THAT IS CHECKED, NOT ASSUMED (R-03.2).
   `site-20260716b.css` already declares it on the ROOT element — `:root
   { color-scheme:light }` at :362 and `color-scheme:dark` inside
   `html[data-theme="dark"]` at :236-299 — which is where it has to be: the
   viewport's own scrollbar resolves its scheme from the root, not from `body`.
   Measured on the built page at 1280x800: `getComputedStyle(document
   .documentElement).colorScheme` is `light` under `data-theme="light"` and
   `dark` under `data-theme="dark"`. Adding a `body.edu` pair would be a second,
   weaker owner of a property that is already correct (T-08). */
body.edu { scrollbar-color:var(--edu-control-line) var(--edu-paper); }
body.edu ::selection { background:var(--edu-accent-soft); color:var(--edu-ink); }
body.edu :is(h1,h2,h3) { text-wrap:balance; }
body.edu a { text-underline-offset:.18em; }
body.edu :is(input,textarea)::placeholder { color:var(--edu-muted); opacity:1; }
body.edu :is(.pf-btn--primary,.pf-btn--primary:hover) { background:var(--edu-action); color:var(--edu-on-action); box-shadow:none; border:1px solid transparent; }
body.edu .pf-btn--primary:hover { background:var(--edu-action-hover); }
body.edu .prail__card { box-shadow:none; border:1px solid var(--edu-line); }
body.edu .post__avatar:has(img) { background:var(--edu-surface); border-radius:8px; }
body.edu .post__avatar img { width:100%; height:100%; object-fit:contain; padding:5px; }
body.edu .answer-section-head { display:grid; grid-template-columns:minmax(0,1.65fr) minmax(0,1fr); align-items:center; gap:32px; padding:24px 0 32px; }
body.edu .answer-section-head h1 { font-size:clamp(30px,3vw,44px); font-weight:750; line-height:1.12; letter-spacing:-.035em; margin:16px 0; }
body.edu .answer-section-head p { max-width:65ch; margin:0 0 16px; }
body.edu .answer-section-head__meta { color:var(--edu-muted); font-size:14px; }
body.edu .answer-section-head > img { width:100%; height:auto; border-radius:14px; }
body.edu .compare-help summary { cursor:pointer; min-height:44px; display:list-item; align-content:center; font-weight:650; color:var(--edu-accent); }
body.edu .compare-help p { max-width:70ch; }
body.edu .cled-status, body.edu .pf-head__stats, body.edu .cdir__count { font-variant-numeric:tabular-nums; }
body.edu.page-search .search-head h1 { font-size:clamp(30px,3vw,40px); font-weight:750; letter-spacing:-.035em; }
body.edu.page-search .search-head { padding:0; }
body.edu.page-search .search-lede { margin-bottom:24px; }
body.edu.page-not-found .col { max-width:none; padding-inline:0; }
/* ⚠️ THE THUMBNAIL TRACK IS THE ENHANCEMENT NOW, NOT THE DEFAULT.
   This was one `:not(:has(.pcard__thumb))` override and it was the ONLY thing
   collapsing the thumbnail-less cards, so on a browser without `:has()`
   (Chrome <105, Firefox <121, Safari <15.4) the whole selector is dropped and
   `ice-feed.css:323`'s `72px minmax(0,1fr)` stands. A thumbnail-less `.pcard`
   has exactly ONE child — `.pcard__text` — which auto-places into COLUMN ONE,
   so the failure is not a dead gutter but a 72px-wide column of prose beside an
   empty `1fr`, on `/answers` and all four `/answers/category/*` hubs.
   Single column is the base; the track is added where `:has()` exists. The
   unsupported path therefore lands on the layout this file already ships below
   768px — thumb above text — which is a designed state, not a broken one.
   ⚠️ Gated to >=768px on purpose: at `(0,4,1)` the enhancement would otherwise
   outrank the phone rule further down this file and reinstate two columns. */
body.edu.page-answer .pcard { grid-template-columns:minmax(0,1fr); }
@media(min-width:768px) {
 body.edu.page-answer .pcard:has(.pcard__thumb) { grid-template-columns:72px minmax(0,1fr); }
}
@media(max-width:767px) {
 body.edu .answer-section-head { grid-template-columns:minmax(0,1fr); gap:16px; padding:12px 0 24px; }
 body.edu .answer-section-head > img { width:270px; max-width:100%; height:auto; justify-self:start; }
}

/* Surface composition: tools expose results; articles expose the answer. */
body.edu :is(.ans-body,.post__body) { color:var(--edu-ink); }
body.edu .ans-body :is(p,ul,ol,dl) { max-width:70ch; font-size:16px; line-height:1.7; }
body.edu .ans-body h2 { margin:32px 0 12px; font-size:26px; line-height:1.25; scroll-margin-top:24px; }
body.edu .ans-body h3 { margin:24px 0 10px; font-size:21px; }
body.edu .ans-reading-meta { font-size:14px; color:var(--edu-muted); line-height:1.6; }
body.edu .ans-toc { margin:20px 0; padding:12px 18px; background:var(--edu-paper); border:1px solid var(--edu-line); border-radius:10px; }
body.edu .ans-toc summary { cursor:pointer; min-height:44px; align-content:center; font-weight:700; }
body.edu .ans-toc a { display:inline-block; padding-block:8px; }
body.edu .pf-panel { border-radius:12px; border:1px solid var(--edu-line); box-shadow:none; padding:28px; }
body.edu .pf-panel > h1 { max-width:28ch; font-size:clamp(30px,3vw,42px); line-height:1.15; font-weight:750; margin:16px 0; }
body.edu .pf-panel > .ans-lede { font-size:18px; line-height:1.6; max-width:65ch; }
body.edu .pcard__q { font-size:16px; line-height:1.45; }
body.edu .pcard__a { font-size:15px; line-height:1.6; }
body.edu .pcard__meta { font-size:13px; letter-spacing:0; text-transform:none; }
body.edu .prail__head { font-size:16px; font-weight:700; line-height:1.4; letter-spacing:0; text-transform:none; }
body.edu .prail__card { padding:20px; border-radius:12px; }
body.edu .prail__note { font-size:14px; line-height:1.6; }
body.edu .prail__sibname { white-space:normal; overflow:visible; text-overflow:clip; }
body.edu .prail .ctile { flex:none; }
body.edu .gal__wait--empty { margin:12px 0; padding:20px; border:1px dashed var(--edu-control-line); border-radius:10px; background:var(--edu-paper); color:var(--edu-muted); font-size:16px; }
/* ⚠️ THE FAILURE MESSAGE WAS BEING CLIPPED AWAY. MEASURED, NOT REASONED.
   `edulibrary-media.js` sets `img.hidden` and flags the `<li
   data-media-frame>`; `edulibrary-refined.css:21` forces `display:none
   !important` on that image. The anchor then filled the tile
   (`height:100%`, `ice-feed.css:706`) and the `::after` was a BLOCK AFTER IT,
   pushed past the tile's own box — which is `overflow:hidden`.
   Measured on the built `/answers` album at 1280x800 with all six tiles failed:
   `.gal` rows collapse to `100px 100px`, the anchor is 384x100, and the tile
   reports `clientHeight 100` against `scrollHeight 166`. **The 66px carrying
   "Image unavailable" was clipped, so a failed linked tile rendered as a blank
   plate that explained nothing** — and the message was outside the link
   regardless (D-16, T-16).
   The tile becomes a single-cell grid: the anchor takes that cell with
   `block-size:auto` so it STRETCHES to the row rather than resolving a
   percentage against a height that may not be definite, and the message is
   painted over it and made click-through. Re-measured with these three rules
   injected into the same page: tile 100, anchor 384x100, `scrollHeight ===
   clientHeight` — nothing clipped. An unlinked failed tile has no anchor, so
   the same cell holds the message alone and looks identical.
   No `:has()` anywhere: this has to work on the browsers the `.pcard` note
   above is about. */
body.edu .gal__tile[data-media-failed] { aspect-ratio:auto; min-block-size:100px; display:grid; grid-template:1fr / 1fr; }
body.edu .gal__tile[data-media-failed] > a { grid-area:1 / 1; block-size:auto; }
body.edu .gal__tile[data-media-failed]::after { content:'Image unavailable'; grid-area:1 / 1; display:grid; place-items:center; padding:20px; color:var(--edu-muted); pointer-events:none; }
body.edu [data-profile-save][aria-pressed="true"] { background:var(--edu-accent-soft); color:var(--edu-ink); border-color:var(--edu-accent); }
body.edu [data-profile-save][hidden] { display:none; }
body.edu :is(.page-directory,.page-compare) { min-width:0; }
body.edu.page-directory .col-hero, body.edu.page-compare .col-hero { background:transparent; border:0; box-shadow:none; margin-bottom:24px; }
body.edu.page-directory .col-hero__text, body.edu.page-compare .col-hero__text { padding:8px 0 0; }
body.edu.page-directory .col-hero__name { font-size:clamp(30px,3vw,42px); }
body.edu.page-directory .cdir__group { padding-block:0; }
body.edu.page-directory .cdir-filter { box-shadow:none; border:1px solid var(--edu-line); margin-bottom:24px; }
body.edu.page-directory .ccard { border:0; border-top:1px solid var(--edu-line); box-shadow:none; border-radius:0; padding:16px 0; background:transparent; }
/* ⚠️ THE CARD HAD NO HOVER OR FOCUS STATE OF ITS OWN. `ice-directory.css:287`
   draws both with an inset action-coloured ring plus two drop shadows; the
   `box-shadow:none` above is `(0,3,1)` against that rule's `(0,2,0)` and loads
   later, so it erases all three — and the flat refined surface has no shadow to
   give back. Measured by focusing a card's link on the built `/colleges` at
   1280x800: `:focus-within` true, `box-shadow: none`, `border-color`
   unchanged at `rgb(214,226,235)`, `transform` an identity matrix. Every
   card-level state signal was gone; only `.ccard__link:focus-visible`'s own
   outline remained, and that does not fire for the Save button inside the card.
   Same failure class the coordinator fixed for `.cpx__mark`: a later
   flat-surface rule silently deleting the earlier sheet's only state signal.
   The border this rule already introduced carries the state instead, so nothing
   here reintroduces the shadow language this pass removed. Re-measured with
   this rule injected: `border-color: rgb(18,102,155)` — `--edu-accent`. */
body.edu.page-directory .ccard:is(:hover,:focus-within) { border-color:var(--edu-accent); background:color-mix(in srgb,var(--edu-accent) 4%,transparent); }
body.edu.page-directory .ccard__link { font-size:16px; line-height:1.45; }
body.edu.page-directory .ccard__meta { line-height:1.5; }
body.edu .search-more { min-height:44px; padding:10px 18px; border:1px solid var(--edu-control-line); background:var(--edu-surface); color:var(--edu-accent); border-radius:10px; }
/* ⚠️ THE GRID PLACEMENT HERE WAS REPORTED AS TWO BUGS AND MEASURED AS NEITHER.
   Task 07 read `.cdir { grid-row:3 / span 2 }` plus `.cdir-bar`'s auto `1 / -1`
   placement as putting the bar in row 5 with a sticky containing block the size
   of its own grid area, and the rail as losing its pin halfway down the list.
   Measured on the built page at 1280x800 before changing anything:
     `.col-shell` used rows `38.8 / 199.5 / 672.3 / 105265 / 79.6 / 94 / …`
     `.cdir-bar` static top 106278 (row 5, under every card) — but RENDERED top
       736, i.e. pinned at `bottom:12px` of an 800px viewport, still there at
       scrollY 3000, with two cards behind it.
     `.cdir-filter` still at viewport top 20 at scrollY 3000, four times past
       the 672px row it sits in.
   `position:sticky` is IN FLOW, so its constraint rectangle is the nearest
   block container — `.col-shell` — not the grid area. The grid area rule is for
   ABSOLUTELY positioned grid items. Both controls therefore travel the whole
   list already, and re-rowing them would have been churn on a working layout.
   NOT CHANGED. Do not re-raise without a rendered measurement. */
@media(min-width:1100px) {
 body.edu.page-directory .col-shell { display:grid; grid-template-columns:280px minmax(0,1fr); gap:0 28px; align-items:start; }
 body.edu.page-directory .col-shell > :not(.cdir-filter):not(.cdir) { grid-column:1 / -1; }
 body.edu.page-directory .cdir-filter { grid-column:1; position:sticky; top:20px; max-height:calc(100dvh - 40px); overflow-y:auto; }
 body.edu.page-directory .cdir-filter[data-ready="true"] { display:block; }
 /* ⚠️ BLOCK LAYOUT HAS NO `gap`, AND NOTHING REPLACED IT. `display:block` above
    outranks `ice-directory.css:132`'s `display:grid` and takes its
    `gap:0.75rem` with it, and `.cdir-filter__field { margin-bottom:0 }` below
    blocks the margin a block box would otherwise fall back on. Measured child
    tops on the built page: field 358 (h74) → facets 432 → foot 896 → three
    joints at exactly 0px, so the search field, the Filters disclosure, the chip
    row and the count line sat flush against one another for the whole width
    range this rail exists in. Block layout has to state its own rhythm. */
 body.edu.page-directory .cdir-filter[data-ready="true"] > * + * { margin-block-start:12px; }
 /* ⚠️ THE BAR FLOATS OVER THE FOOT OF THE RAIL, SO THE RAIL GIVES UP THAT STRIP.
    Both are sticky against the same scrollport: the rail from the top, the bar
    from `bottom:12px`. At 1280x800 they clear each other (rail bottom 668, bar
    top 736), but the rail's own cap is what decides that, and on a 700px-tall
    window with the shortlist tray open the bar is 118px and its top is 570
    against a rail bottom of 668 — 98px of the rail's foot, which is the result
    count, Clear all filters and the method note, permanently behind the tray.
    172px = 20px top + 12px bottom + the 118px the coordinator measured the bar
    at under the 12-college cap + 22px. The rail already scrolls its own
    overflow, so nothing becomes unreachable; it just ends above the bar.
    `:has()` only ever ADDS the reserve, so a browser without it lands on
    exactly today's behaviour rather than on a broken one. */
 body.edu.page-directory .col-shell:has(.cdir-bar:not([hidden])) .cdir-filter { max-height:calc(100dvh - 172px); }
 body.edu.page-directory .col-shell:has(.cdir-filter:not([data-ready])) .cdir { grid-column:1 / -1; grid-row:auto; }
 body.edu.page-directory .cdir { grid-column:2; grid-row:3 / span 2; }
 body.edu.page-directory .cdir-facets__grid { grid-template-columns:minmax(0,1fr); }
 body.edu.page-directory .cdir__grid { grid-template-columns:repeat(2,minmax(0,1fr)); }
 body.edu.page-directory .cdir-filter__field { margin-bottom:0; }
}
@media(max-width:767px) {
 body.edu .pf-panel { padding:20px 16px; }
 body.edu .pf-panel > .ans-lede { font-size:17px; }
 body.edu .ans-body h2 { font-size:23px; }
 /* The single-column declaration that stood here is now the base rule above,
    which outranks this block anyway; only the thumb size is width-specific. */
 body.edu .pcard__thumb { width:64px; height:64px; }
 body.edu.page-directory .col-hero__text, body.edu.page-compare .col-hero__text { padding:4px 0 0; }
}

body.edu .hsearch label { font-size:13px; letter-spacing:0; text-transform:none; }
/* `body.edu .search-result__snippet { font-size:16px }` was here to correct
   `site-search.css` from outside. Task 19 made that sheet declare `1rem`
   itself and asked for the override back; one sheet owns the snippet now
   (`site-search.css:239`) instead of two agreeing by coincidence (T-08).
   `.search-more` stays split ON PURPOSE and is not duplicated: colour, border
   and the 44px target are below in this file, the gap above the button is
   `site-search.css:184`. Neither declares the other's property. */
body.edu .cdir__rule summary { font-size:14px; }
body.edu .ans-body .ans-tablewrap { max-width:100%; }

/* ⚠️ THE WHOLE ROW IS THE TARGET, BECAUSE THE NAME ALONE WAS 20px.
   MEASURED on /colleges/pulchowk-campus at 390px: `div.prail__institution` 63px
   tall, and the only anchor inside it — `a.prail__sibname` — 20px, with
   computed `display:block; padding:0; min-height:0` from the rule below. That
   rule beats `ice-college-profile.css`'s `.prail__sibs a { padding:7px 8px }`
   at (0,3,0) and loads later, so the sibling list on every college page offered
   a 20px tap target inside a 63px row (D-13).

   The fix is the directory's own proven pattern (`ice-directory.css` §card), not
   re-padding the anchor: an inset `::after` stretches the link's hit area over
   the whole row while the text stays where it is. Wrapping the markup instead
   was rejected by task 13 for a concrete reason — the stitched anchor text on a
   long college name crosses `audit:onpage`'s 80-character ceiling and would add
   an `anchor-long` finding to a ratcheted gate.

   `position:relative` on the row is what the inset resolves against; the hover
   fill moves to the row so the whole target lights up, not just the text. */
body.edu .prail__institution { position:relative; display:flex; gap:12px; align-items:center; padding:12px 0; }
body.edu .prail__institution .prail__sibname { padding:0; min-height:0; display:block; }
body.edu .prail__institution .prail__sibname::after { content:''; position:absolute; inset:0; border-radius:14px; }
body.edu .prail__institution:hover { background:var(--edu-paper); border-radius:14px; }

body.edu .cpx__shortlist { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
body.edu .cpx__shortlist .cpx__btn { padding:10px; min-height:48px; font-size:14px; text-align:center; justify-content:center; }
/* ⚠️ `margin:0` MOVED HERE FROM A DEAD SELECTOR. This file also carried
   `body.edu .cpx__save-status`, which matches nothing: `ProfileMasthead.astro`
   ships `.cpx__save-note`. The size and colour were already restated below, but
   its `margin:0` was not, so the live rule left the paragraph's UA `1em`
   margins in place — and `.cpx__acts` is a wrapping flex row
   (`college-profile-clarity.css:304`) where an item's margins ADD to the gap.
   The note is `:empty` until a save happens, so appearing pushed the actions
   row by ~32px on the first press of Save. One rule owns the note now (T-08). */
body.edu .cpx__save-note:empty { display:none; }
body.edu .cpx__save-note { font-size:14px; line-height:1.5; margin:0; }

body.edu .ans-srcs { padding:0; margin-top:28px; }
body.edu .ans-srcs__head { margin-top:0; }

/* Answer pages are reading surfaces, not a feed of nested social cards. The
   existing post and panel components keep their semantics while their page
   variant uses ruled sections, an editorial lead band and one quiet side rail. */
body.edu.page-answer .col-hero {
  border:0;
  border-top:2px solid #7fc9ee;
  border-radius:0;
  background:transparent;
  box-shadow:none;
}
body.edu.page-answer .col-hero__text { padding:clamp(26px,4vw,48px) 0 30px; }
body.edu.page-answer .answer-section-head {
  display:block;
  max-width:900px;
  padding:clamp(26px,4vw,48px) 0 32px;
  border-top:2px solid #7fc9ee;
}
body.edu.page-answer .post {
  border:0;
  border-top:1px solid var(--edu-line);
  border-radius:0;
  background:transparent;
  box-shadow:none;
}
body.edu.page-answer .post__head { padding:22px 0 0; }
body.edu.page-answer .post__body { padding:22px 0 30px; }
body.edu.page-answer .pcards { gap:0; }
body.edu.page-answer .pcard {
  min-height:0;
  padding:16px 0;
  border:0;
  border-top:1px solid var(--edu-line);
  border-radius:0;
  background:transparent;
  box-shadow:none;
  transition:background-color 140ms ease;
}
body.edu.page-answer .pcard:is(:hover,:focus-within) {
  transform:none;
  box-shadow:none;
  background:color-mix(in srgb,var(--edu-accent) 4%,transparent);
}
body.edu.page-answer .pcard__q::after { border-radius:0; }
body.edu.page-answer .pf-panel {
  padding:clamp(28px,4vw,48px) 0;
  border:0;
  border-top:2px solid #7fc9ee;
  border-radius:0;
  background:transparent;
  box-shadow:none;
}
body.edu.page-answer .prail__card { border-radius:0; border-inline:0; border-top:2px solid var(--edu-accent); background:var(--edu-paper); }
body.edu.page-answer .pf-list li { min-height:44px; align-items:center; }

body.edu.page-not-found .col-hero { margin-bottom:0; }
body.edu.page-not-found .col-block {
  margin-top:0;
  padding:24px 0;
  border:0;
  border-top:1px solid var(--edu-line);
  border-radius:0;
  background:transparent;
  box-shadow:none;
}
body.edu.page-compare :is(.col-block,.col-disclosure) {
  border:0;
  border-top:1px solid var(--edu-line);
  border-radius:0;
  background:transparent;
  box-shadow:none;
}

@media(max-width:767px) {
  body.edu.page-answer .col-hero__text,
  body.edu.page-answer .post__head,
  body.edu.page-answer .post__body,
  body.edu.page-answer .pf-panel { padding-inline:0; }
}

@media(prefers-reduced-motion:reduce) {
  body.edu.page-answer .pcard { transition:none; }
}
