/* ==========================================================================
   Card sections — courses grid, "We Don't Just Prepare You", and
   "Infrastructure & Student Life"
   Added 2026-07-28. Companion to home-hero.css.

   Revised 2026-07-28: the card grid now also serves the "Explore Our
   Departments" section on admissions.php. Those are the same cards, and they
   had the same three faults the homepage grid did — a different grey per card,
   ragged heights, and icons sized as a percentage of the card so they changed
   size at every breakpoint. The rules were already written; only the scope is
   new. The file name is now a slight misnomer, kept so the <link> in
   header.php and its cache-buster do not have to churn.

   SCOPING
   -------
   .ExploreProgramBlock is also used by admissions.php and PDSHome.php, and
   .whyTrinity by PDSHome.php. PDSHome.php is left exactly as it is, so every
   rule here is scoped to a class that only the pages we have touched carry:
     .homeCourses     -> the UG/PG courses section (home.php)
     .admissionsDepts -> the "Explore Our Departments" section (admissions.php)
     .courseGrid      -> the card rows inside either of those
     .homePropel      -> the "We Don't Just Prepare You" carousel section
     .homeInfra       -> section.whyTrinity

   Each card rule below is listed against both page scopes rather than being
   reduced to a bare `.courseGrid`. Dropping the scope would look tidier but
   lowers specificity to (0,1,0)-(0,2,0), and style.css already has
   `.ExploreProgramBlock img` at (0,1,1) and `.ExploreProgramBlock .bgNN` at
   (0,2,0) — the icon sizing in particular would silently stop applying.

   THE ROOT CAUSE OF THE INCONSISTENT SPACING
   ------------------------------------------
   Almost every gap in these sections was expressed as a PERCENTAGE, and
   percentage margins/padding resolve against the *container's width* — not
   against font size or a fixed value. So every gap grew on wide screens and
   collapsed on narrow ones, which is why spacing never matched between
   desktop and mobile:

     .ExploreProgramBlock img { width:30%; margin-top:12%; margin-bottom:4% }
     .ParagraphClass          { margin-bottom:2% }

   On a ~400px desktop card that img margin-top is ~48px and the icon ~120px
   wide; on a ~150px mobile card, ~18px and ~45px. Fixed values throughout now.

   (.mgTopDesktop15's margin-top:15% is inert — a later top-level
   `.mgTopDesktop15{margin-top:0}` at style.css:2425 overrides the 15% at
   line 1556. Same specificity, later wins. Noted so nobody "fixes" it twice.)
   ========================================================================== */

/* ==========================================================================
   1. COURSES GRID — always N per row, never ragged
   ==========================================================================
   Uses CSS Grid rather than flex with calc() widths. An earlier attempt set
   `display:flex` plus `width:calc((100% - 2*gap)/3)` on the columns, and the
   cards wrapped 2 / 3 / 1 instead of 3 / 3: the Bootstrap `col-*` classes on
   those same elements still carried their own `width` and `float`, and the
   interaction produced sub-pixel overflow that pushed the third card onto the
   next line.

   `grid-template-columns: repeat(3, 1fr)` cannot do that. The track count is
   declared outright, 1fr absorbs the gaps arithmetically, and no percentage
   width is involved — so the row count is exact at every viewport size.

   Neutralising `width` and `float` from the Bootstrap columns (below) is
   essential: a leftover `width:33.33%` would shrink each card inside its own
   grid cell and reintroduce uneven gaps.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Breathing room around the "Under Graduate" / "Post Graduate" headings
   --------------------------------------------------------------------------
   These two h3s sit between the two card grids. They used to get their space
   from the cards' own margin-bottom:25px (.ExploreProgramBlock .bgNN), which the
   grid below removes because `gap` handles row separation instead. Without it,
   "Post Graduate Courses" was pressed straight against the bottom of the
   undergraduate grid with only Bootstrap's default h3 margin-top:20px in
   between.

   .headingClass also sets margin-bottom:3%, another width-relative value that
   grows and shrinks with the container, so it is pinned to a fixed value here.

   .homeCourses h3.headingClass is (0,2,1), which beats .headingClass (0,1,0)
   and Bootstrap's bare h3 (0,0,1).
   -------------------------------------------------------------------------- */
.homeCourses h3.headingClass {
  margin-top: 42px;
  margin-bottom: 20px;
}

@media (max-width: 690px) {
  .homeCourses h3.headingClass {
    margin-top: 30px;
    margin-bottom: 16px;
  }
}

.homeCourses .courseGrid,
.admissionsDepts .courseGrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;

  /* Cancels Bootstrap's -15px .row margins; with grid gap doing the spacing
     they would push the grid outside its container. */
  margin: 0;
}

/* Four across on admissions, not three. That section holds eight departments,
   so four per row divides into two full rows; three would leave a short row of
   two. The homepage grids hold six and three, which divide by three. */
@media (min-width: 1200px) {
  .admissionsDepts .courseGrid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* --------------------------------------------------------------------------
   THIS IS WHY THE FIRST CARD SLOT RENDERED EMPTY
   --------------------------------------------------------------------------
   These elements are also Bootstrap `.row`s, and Bootstrap 3 clears floats on
   .row with generated content:

     .row:before, .row:after { content: " "; display: table; }
     .row:after            { clear: both; }

   Generated pseudo-elements of a grid container become GRID ITEMS (the same is
   true of flex containers). So ::before silently occupied cell 1 and shunted
   every real card along by one position — an empty first box, then the cards,
   with ::after taking one more cell at the end.

   It was also the cause of the earlier 2 / 3 / 1 wrapping when this grid was
   built with flex: ::before was a flex item consuming space in the first line.

   The clearfix is meaningless once the row is a grid — there are no floats left
   to clear — so the generated boxes are removed outright.
   -------------------------------------------------------------------------- */
.homeCourses .courseGrid::before,
.homeCourses .courseGrid::after,
.admissionsDepts .courseGrid::before,
.admissionsDepts .courseGrid::after {
  content: none;
  display: none;
}

@media (max-width: 991px) {
  .homeCourses .courseGrid,
  .admissionsDepts .courseGrid {
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
  }
}

/* One per row on small phones — two 50% columns leave the descriptions too
   narrow to read once icon and padding are accounted for. */
@media (max-width: 575px) {
  .homeCourses .courseGrid,
  .admissionsDepts .courseGrid {
    grid-template-columns: 1fr;
  }
}

/* --------------------------------------------------------------------------
   The cards
   -------------------------------------------------------------------------- */
.homeCourses .courseGrid > [class*="col-"],
.admissionsDepts .courseGrid > [class*="col-"] {
  /* Neutralise the Bootstrap column geometry — see the note above. */
  float: none;
  width: auto;
  max-width: none;
  margin: 0;

  /* .bgNN set min-height:240px, which fought the grid's own row sizing:
     short cards were padded out while tall ones grew anyway. Grid already
     makes every card in a row equal height. */
  min-height: 0;

  padding: 20px;
  display: flex;
  flex-direction: column;

  /* STANDARDISED COLOUR.
     The nine cards were each a different grey — bg11 #a9a8a8, bg12 #b4b4b4,
     bg13 #bfbfbf, bg14 #d0d0d0, bg15 #cbcbcb, bg16 #d7d7d7, bg17 #e3e3e3,
     bg18 #e6e6e6, bg19 #e9e9e9. That is a light-to-dark ladder in class-number
     order, but the cards do not appear in that order in the markup, so on the
     page it read as random shading. One value for all nine.

     #d7d7d7 is taken from the existing palette (bg16) and holds a clear edge
     against the section's #f1f4f8 background. */
  background-color: #d7d7d7;
  border-radius: 10px;

  /* Slight lift, for definition rather than decoration. */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

@media (max-width: 575px) {
  .homeCourses .courseGrid > [class*="col-"],
  .admissionsDepts .courseGrid > [class*="col-"] {
    padding: 16px;
  }
}

/* The icon was width:30% of the card, so it changed size at every breakpoint.
   Fixed box with object-fit so any icon artwork lands identically. */
.homeCourses .courseGrid img,
.admissionsDepts .courseGrid img {
  width: 64px;
  height: 64px;
  object-fit: contain;
  object-position: left center;
  display: block;
  margin: 0 0 16px;
}

@media (max-width: 575px) {
  .homeCourses .courseGrid img,
  .admissionsDepts .courseGrid img {
    width: 52px;
    height: 52px;
    margin-bottom: 12px;
  }
}

/* Replaces .ParagraphClass{margin-bottom:2%; line-height:28px}. A unitless
   line-height scales with the font instead of being pinned at 28px. */
.homeCourses .courseGrid p,
.admissionsDepts .courseGrid p {
  margin: 0 0 8px;
  line-height: 1.5;

  /* style.css:2910 has a bare p{text-align:justify} applying site-wide.
     Justifying a ~40-character column stretches word spacing into rivers —
     the wide gaps in "Sustainable  Infrastructure,  Smart  Cities  &  Green".
     Overridden inside these cards only. */
  text-align: left;
}

/* Just drop the trailing margin. Deliberately NOT margin-top:auto to
   bottom-align the description: grid stretches every card to the tallest in
   its row, so an auto margin would absorb the leftover height and the gap
   above the description would differ from card to card — the exact
   inconsistency this file exists to remove. Leftover height sits at the bottom
   of the card instead, so the internal rhythm is identical everywhere. */
.homeCourses .courseGrid p:last-child,
.admissionsDepts .courseGrid p:last-child {
  margin-bottom: 0;
  padding-top: 4px;
}

/* The admissions section heading sat tight against the grid: .headingClass
   carries margin-bottom:3%, and its "Applied Knowledge, Real Impact" strapline
   is a .ParagraphClass at margin-bottom:2% — both width-relative, so the gap
   moved with the viewport. Same fixed treatment as the homepage h3s above. */
.admissionsDepts .courseGrid {
  margin-top: 24px;
}

/* ==========================================================================
   2. "WE DON'T JUST PREPARE YOU" — mobile centring
   ==========================================================================
   .social_icon (newstyle.css:90) is position:fixed against the left edge with
   z-index 100, and it is not hidden on small screens. This carousel's cells
   are col-sm-4, so below 768px they collapse to full width with a
   left-aligned 30%-wide icon and justified copy — both of which ran underneath
   that rail and became unreadable.

   Centring moves the icon and text into the middle of the column, clear of the
   rail.

   NOTE ON THE SIDE PADDING BELOW. site-fixes.css now pads .container to clear
   both fixed rails at 690px and under, site-wide. Repeating that padding here
   would stack on top of it and squeeze the column twice. So the local padding
   is confined to the 691px to 767px band, which is the only range where these
   cells have already collapsed to full width (col-sm-4 stops applying at 768px)
   but .container is still on Bootstrap's 15px.
   ========================================================================== */
@media (max-width: 767px) {
  .homePropel .carousel-inner > .item > [class*="col-"] {
    text-align: center;
  }

  .homePropel .carousel-inner img {
    display: block;
    margin: 0 auto 14px;
    width: 72px;
    height: 72px;
    object-fit: contain;
  }

  /* Beats the site-wide p{text-align:justify}. */
  .homePropel .carousel-inner p {
    text-align: center;
    margin: 0;
    line-height: 1.5;
  }
}

/* The 691-767px band only: cells are full width here but .container is still on
   Bootstrap's 15px, so this is the one range that needs local clearance for the
   50px social rail. Below 691px site-fixes.css handles it on .container. */
@media (min-width: 691px) and (max-width: 767px) {
  .homePropel .carousel-inner > .item > [class*="col-"] {
    padding-left: 44px;
    padding-right: 44px;
  }
}

@media (max-width: 480px) {
  .homePropel .carousel-inner img {
    width: 60px;
    height: 60px;
  }
}

/* ==========================================================================
   3. INFRASTRUCTURE & STUDENT LIFE
   ==========================================================================
   Alternating image / text cells in a 4-across checkerboard. The text cells
   (.textblock) were already flex-centred by style.css:108, so the copy was
   centred vertically — but it was justified, which reads as ragged
   left-aligned rather than centred.

   The text boxes shrink on mobile; the image boxes deliberately do NOT, so
   the photos stay large enough to read. Two separate variables rather than one.
   ========================================================================== */

.homeInfra {
  --infra-text-h: 250px;
  --infra-img-h: 250px;
}

@media (max-width: 991px) {
  .homeInfra {
    --infra-text-h: 190px;
    --infra-img-h: 230px;
  }
}

@media (max-width: 767px) {
  .homeInfra {
    --infra-text-h: 140px;
    --infra-img-h: 210px;
  }
}

@media (max-width: 480px) {
  .homeInfra {
    --infra-text-h: 120px;
    --infra-img-h: 190px;
  }
}

/* --------------------------------------------------------------------------
   Text cells
   --------------------------------------------------------------------------
   min-height, NOT height, and the min-height must be overridden explicitly:
   style.css:108 sets .textblock{min-height:250px}, and min-height always wins
   over height. An earlier attempt set only `height`, so the boxes stayed 250px
   tall on mobile and appeared not to change at all.

   min-height (rather than a fixed height) also means a long line can still
   grow the box instead of being clipped.
   -------------------------------------------------------------------------- */
.homeInfra .textblock {
  height: auto;
  min-height: var(--infra-text-h);
  padding: 20px;
  text-align: center;

  /* Re-assert the centring at higher specificity. style.css:108 sets these on
     .textblock, but see the .deskshow note below. */
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   WHY HALF THE TEXT BOXES WERE NOT VERTICALLY CENTRED
   --------------------------------------------------------------------------
   style.css:108   .textblock { display:flex; align-items:center; ... }
   style.css:1162  .deskshow  { display:block }

   Both are single-class selectors, so specificity ties and the later one wins:
   .deskshow turned display back to block, the flex centring stopped applying,
   and the copy fell to the top of the box.

   That is why only some boxes looked wrong. The first row's text cells are
   plain .textblock and centred fine; every cell in the second row also carries
   .deskshow (they are the desktop half of the duplicated .deskshow/.mobileShow
   pairs used to reorder this section on mobile) and so did not.

   Re-asserting display:flex has to preserve which copy is visible at which
   width, otherwise the hidden .mobileShow duplicates would appear on desktop
   and the text would show twice. Hence the compound selectors below rather
   than a blanket display:flex on .homeInfra .textblock.
   -------------------------------------------------------------------------- */
.homeInfra .textblock.deskshow {
  display: flex;
}

.homeInfra .textblock.mobileShow {
  display: none;
}

/* 690px is the breakpoint style.css already uses to swap these two. */
@media (max-width: 690px) {
  .homeInfra .textblock.deskshow {
    display: none;
  }

  .homeInfra .textblock.mobileShow {
    display: flex;
  }
}

.homeInfra .textblock p {
  margin: 0; /* was margin-bottom:2%, a width-relative value */
  text-align: center;
  line-height: 1.5;
}

@media (max-width: 767px) {
  .homeInfra .textblock {
    padding: 14px;
  }

  .homeInfra .textblock p {
    font-size: 13px;
    line-height: 1.45;
  }
}

/* --------------------------------------------------------------------------
   Image cells — kept tall on purpose
   --------------------------------------------------------------------------
   Deliberately left as floats rather than converted to grid/flex: the row
   contains <div class="clearfix"> spacers and duplicated .deskshow/.mobileShow
   cells for mobile reordering. As grid or flex children those would occupy
   track slots and scramble the alternating image/text order.
   -------------------------------------------------------------------------- */
.homeInfra .zeroSpace {
  height: var(--infra-img-h);
  min-height: 0;
  overflow: hidden;
}

/* height:100% now resolves against the fixed cell height above, so the photos
   fill their cell and crop, rather than defining the cell's height. */
.homeInfra .zeroSpace img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
