/* ================================================================
   Product page: /{course}/{specialisation}/{college}/

   Loaded as sidenotes-routes-spec-product, after style.css and
   components.css, on all 46 product URLs.

   LAYER 1 OF THIS FILE IS THE GLOBAL LAYER. Tokens, rhythm, and the
   primitives more than one section uses. Sections come after it and
   may only arrange these, never redefine them.

   SCOPE. Everything is under .sn-product, which the part file puts
   on <main>. No rule here uses a bare element selector and nothing
   uses *, so the header, the navigation and the footer cannot be
   reached from this file. That is the reset rule from the KB and it
   is what stops a page stylesheet breaking the chrome.

   TOKENS. The spacing, radius, elevation and motion scales come from
   the design system addendum, sections 9 to 13. They are declared on
   .sn-product rather than :root because only this page type uses
   them today. When the listing page adopts them they move to :root
   in style.css and this block is deleted, not copied.

   The colour and type tokens are NOT redeclared. They are in
   style.css and locked. A second declaration of --teal here would be
   a second place for it to drift.

   CONTENT WIDTH. The addendum proposes 1200px. The theme's .wrap is
   1160 and is used by the header, the footer and every other page
   type. 1160 wins: one content width, decided once, is worth more
   than the extra 40px, and a page whose sections do not line up with
   the header above them reads as broken.
   ================================================================ */

.sn-product{
  /* Spacing. Four point base. Every margin, padding and gap is one
     of these. */
  --s-1:4px;
  --s-2:8px;
  --s-3:12px;
  --s-4:16px;
  --s-5:24px;
  --s-6:32px;
  --s-7:48px;
  --s-8:64px;
  --s-9:96px;

  /* Radius. --r-1 and --r-2 are the same values as style.css's
     --r-sm and --r-md, aliased rather than reused so one vocabulary
     runs through this file. */
  --r-1:6px;
  --r-2:10px;
  --r-3:14px;
  --r-4:20px;
  --r-full:999px;

  /* One elevation exists. The floating hero card and the section
     navigation once it is stuck. Nothing else casts a shadow: a
     directory reads as a document, not as a dashboard. */
  --lift:0 2px 8px rgba(14,22,24,0.06);

  /* Motion. */
  --m-hover:120ms ease-out;
  --m-panel:200ms cubic-bezier(0.2, 0, 0, 1);
  --m-page:300ms cubic-bezier(0.2, 0, 0, 1);
}

/* ---------------------------------------------------------------
   Section rhythm

   style.css already sets section padding to 64px, and 48px below
   900px, which is exactly --s-8 and --s-7. So the rhythm is
   inherited rather than restated. What is set here is what the
   product page does differently: full bleed bands, and the rule that
   a band never carries the hairline rule a normal section does.

   A section that drops takes its padding with it, because the
   padding is on the section element and a dropped section emits no
   element at all. Two adjacent drops therefore leave one gap, not
   two. That is the whole reason every section function returns null
   rather than an empty wrapper.
   --------------------------------------------------------------- */

.sn-product .band{
  padding:var(--s-7) 0;
  background:var(--teal-deep);
  color:var(--surface);
  border-top:none;
}
.sn-product .band + section{border-top:none}
.sn-product .band h1,
.sn-product .band h2,
.sn-product .band h3{color:var(--surface)}
.sn-product .band p{color:var(--teal-lite)}

@media(min-width:900px){
  .sn-product .band{padding:var(--s-8) 0}
}

/* ---------------------------------------------------------------
   Group bands

   The page is five named parts, from the Page groups sheet. Each
   part carries a background, and the point of them is rhythm: a
   reader scrolling past twenty one sections in one flat colour has
   nothing telling them they have moved from cost to careers.

   Three treatments, not five. Course and Studying and Careers sit
   on --surface, which is the page, so they emit a wrapper and no
   paint. That is deliberate: a movement needs somewhere to rest as
   much as it needs somewhere to change, and five painted bands is
   the wallpaper the review warned about.

   The wrapper is emitted by sn_p_page() only where a part actually
   rendered a section, so none of these can paint an empty strip.
   --------------------------------------------------------------- */

.sn-product .pgroup{background:var(--surface)}
.sn-product .pgroup-alt{background:var(--surface-2)}
.sn-product .pgroup-teal{background:var(--teal-deep);color:var(--surface)}

/* A section already dark does not paint itself again inside a dark
   part. Accreditation is the case: it was a standalone band before
   the University part existed around it, and two --teal-deep layers
   with their own padding read as a seam. */
.sn-product .pgroup-teal .band{background:none;padding-bottom:0}

/* The hairline between sections is a --line rule on --surface. On
   teal it disappears, and on --surface-2 it is louder than it needs
   to be, so each part states its own. */
.sn-product .pgroup-teal section{border-top-color:rgba(255,255,255,0.14)}
.sn-product .pgroup-alt section{border-top-color:rgba(14,22,24,0.08)}

/* A part boundary is the one place the hairline is wrong: the colour
   change is already the boundary, and a rule on top of it reads as a
   divider inside the part above. */
.sn-product .pgroup > section:first-child{border-top:none}

/* The colours for this part are the last thing in the file. See the
   inversion layer at the foot: putting them here loses to every
   section rule below, which is how the University part shipped with
   --ink body copy on --teal-deep. */

/* ---------------------------------------------------------------
   Section heading

   Two colours: the first clause in --ink, the final clause in
   --teal. One split per heading, never two. The split is made in PHP
   by sn_p_heading(), which wraps the final clause in <em>, so the
   markup carries the meaning and the stylesheet only carries the
   colour.

   <em> rather than <span> so the emphasis survives a stylesheet
   failure as emphasis rather than as nothing. font-style is reset
   because the emphasis here is colour, not italic.
   --------------------------------------------------------------- */

.sn-product h2 em{font-style:normal;color:var(--teal)}
.sn-product .band h2 em{color:var(--teal-lite)}

/* The 4px teal bar to the left of every h2 is style.css's. On a dark
   band it disappears into the background, so it goes light there. */
.sn-product .band h2::before{background:var(--teal-lite)}

.sn-product .sec-sub{max-width:68ch}

/* Prose caps at 68 characters, which at 16px is about 720px. Applied
   to the block rather than to every paragraph, so a section with
   three paragraphs measures once. */
.sn-product .prose{max-width:68ch}
.sn-product .prose p{color:var(--ink-2);font-size:var(--fs-md)}
.sn-product .prose p + p{margin-top:var(--s-4)}

/* ---------------------------------------------------------------
   Shared primitives

   Used by more than one section. A section may arrange these and may
   not restyle them: a chip that looks different in two places is two
   components with one name.
   --------------------------------------------------------------- */

/* Chip list. Roles, industries, skills, other subjects, related
   subjects. */
.sn-product .chips{display:flex;flex-wrap:wrap;gap:var(--s-2)}
.sn-product .chip{
  display:inline-flex;align-items:center;
  padding:0 var(--s-3);
  border:1px solid var(--line);border-radius:var(--r-full);
  background:var(--surface);
  font-size:var(--fs-base);color:var(--ink-2);
  text-decoration:none;
}
.sn-product a.chip{transition:border-color var(--m-hover),color var(--m-hover)}
@media (hover:hover) and (pointer:fine){.sn-product a.chip:hover{border-color:var(--teal);color:var(--teal)}}

/* Ticked list. Who it suits, eligibility, fee inclusions.

   The tick is a background image on the <li>, not a child element
   and not a ::before carrying a glyph. A glyph would be read aloud
   by a screen reader once per item, and on iOS Safari an inline svg
   inside a flex child is the sizing bug the header already worked
   around. */
.sn-product .ticks li{
  position:relative;
  padding-left:calc(var(--s-5) + var(--s-1));
  color:var(--ink-2);
  font-size:var(--fs-md);
  background-repeat:no-repeat;
  background-position:0 0.28em;
  background-size:16px 16px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2300707A'%3E%3Cpath d='M8 0a8 8 0 100 16A8 8 0 008 0zm3.7 6.1-4.2 4.4a.9.9 0 01-1.3 0L4.3 8.6l1.3-1.3 1.2 1.3 3.6-3.8z'/%3E%3C/svg%3E");
}
.sn-product .ticks li + li{margin-top:var(--s-3)}
.sn-product .band .ticks li{color:var(--teal-lite);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%234FC7CE'%3E%3Cpath d='M8 0a8 8 0 100 16A8 8 0 008 0zm3.7 6.1-4.2 4.4a.9.9 0 01-1.3 0L4.3 8.6l1.3-1.3 1.2 1.3 3.6-3.8z'/%3E%3C/svg%3E");
}

/* Small table. Fee routes, what the fee leaves out, concessions,
   attribute rows. Four columns and above are wrapped in an
   overflow-x div by the PHP, per the QA checklist. */
.sn-product .dtable{width:100%;border-collapse:collapse;
  font-variant-numeric:tabular-nums}
.sn-product .dtable th,
.sn-product .dtable td{
  text-align:left;padding:var(--s-3) var(--s-4);
  border-bottom:1px solid var(--line-soft);
  font-size:var(--fs-base);vertical-align:top;
}
.sn-product .dtable thead th{
  background:var(--surface-2);color:var(--ink);
  font-weight:600;font-size:var(--fs-sm);
  border-bottom:1px solid var(--line);
}
.sn-product .dtable tbody th{font-weight:600;color:var(--ink)}
.sn-product .dtable td{color:var(--ink-2)}
.sn-product .dtable tr:last-child th,
.sn-product .dtable tr:last-child td{border-bottom:none}
.sn-product .tscroll{overflow-x:auto;border:1px solid var(--line);
  border-radius:var(--r-3)}
.sn-product .tscroll .dtable{min-width:640px}
.sn-product .tflat{border:1px solid var(--line);border-radius:var(--r-3);
  overflow:hidden}

/* Label and value strip. Exams, location, credits. Not a table:
   these are pairs, not rows of one thing, and a table would promise
   a comparison that is not there. */
.sn-product .lv{display:grid;gap:var(--s-4)}
.sn-product .lv > div{
  display:grid;gap:var(--s-1);
  padding-bottom:var(--s-4);
  border-bottom:1px solid var(--line-soft);
}
.sn-product .lv > div:last-child{border-bottom:none;padding-bottom:0}
.sn-product .lv dt{font-size:var(--fs-sm);color:var(--ink-2);font-weight:600}
.sn-product .lv dd{font-size:var(--fs-md);color:var(--ink)}
@media(min-width:900px){
  .sn-product .lv{grid-template-columns:repeat(2,1fr);gap:var(--s-4) var(--s-6)}
}

/* Card. One border, no shadow. Borders carry the structure. */
.sn-product .card{
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r-3);
  padding:var(--s-4);
}
@media(min-width:600px){
  .sn-product .card{padding:var(--s-5)}
}

/* Note. What a section says when it is standing in for something the
   university does not publish, or when it is stating a general rule
   rather than this university's own. Never styled as a warning: an
   absence is content here, not an error. */
.sn-product .note{
  border-left:3px solid var(--teal);
  background:var(--surface-2);
  padding:var(--s-4);
  border-radius:0 var(--r-2) var(--r-2) 0;
  font-size:var(--fs-base);
  color:var(--ink-2);
}
.sn-product .note strong{color:var(--ink);font-weight:600}
.sn-product .note + .note{margin-top:var(--s-3)}

/* The label a tier 2 substitute carries. Absence rule AR07: a
   general requirement is never presented as though the university
   had stated it, so the label is part of the block rather than a
   sentence someone has to remember to write. */
.sn-product .general-tag{
  display:inline-block;margin-bottom:var(--s-2);
  padding:var(--s-1) var(--s-2);
  border-radius:var(--r-1);
  background:var(--teal-tint);color:var(--teal-dark);
  font-size:var(--fs-xs);font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;
}

/* ---------------------------------------------------------------
   Interaction and accessibility

   Focus is style.css's teal outline and is never removed here.
   Touch targets are 44px minimum on every control, including at 375.
   --------------------------------------------------------------- */

.sn-product .tap{min-height:44px}

@media(prefers-reduced-motion:reduce){
  .sn-product *{transition:none !important;animation:none !important;
    scroll-behavior:auto !important}
}


/* ================================================================
   LAYER 2. SECTIONS, in page order.
   ================================================================ */

/* ---------------------------------------------------------------
   2. Hero

   Dark band. A photograph sits behind at 25 per cent opacity under a
   --teal-deep overlay, so text contrast never depends on the image
   and an absent image changes nothing but the texture. No image is
   uploaded today: hero_id is 0 on all 46 rows, so what renders is
   the flat band, which is the designed state and not a fallback.
   --------------------------------------------------------------- */

.sn-product .hero{position:relative;overflow:hidden}
.sn-product .hero-bg{
  position:absolute;inset:0;
  object-fit:cover;width:100%;height:100%;
  opacity:.25;
}
.sn-product .hero-bg + .hero-veil{
  position:absolute;inset:0;
  background:linear-gradient(90deg,var(--teal-deep) 0%,rgba(0,54,60,.82) 100%);
}
.sn-product .hero .wrap{position:relative;z-index:1}
.sn-product .hero-grid{display:grid;gap:var(--s-6)}

.sn-product .ulogo-tile{
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--surface);border-radius:var(--r-2);
  padding:var(--s-3) var(--s-4);
  min-height:56px;min-width:96px;
  margin-bottom:var(--s-5);
}
.sn-product .ulogo-tile img{display:block;max-height:38px;width:auto}
/* No logo attachment uploaded yet. The tile carries the university's
   short name set in the wordmark's ink, which is a mark of the right
   shape rather than an empty white box. */
.sn-product .ulogo-tile span{
  font-weight:800;font-size:var(--fs-md);color:var(--ink);
  letter-spacing:-0.02em;
}

.sn-product .hero h1{
  font-size:clamp(26px,4.4vw,40px);
  color:var(--surface);
  margin-bottom:var(--s-4);
}
.sn-product .hero .ticks{margin-top:var(--s-4)}

/* The floating card. Below 1200 it sits under the heading at full
   width; at 1200 and above it floats right. */
.sn-product .hero-card{
  background:var(--surface);color:var(--ink);
  border-radius:var(--r-4);
  box-shadow:var(--lift);
  padding:var(--s-5);
  align-self:start;
}
.sn-product .hero-card h2{
  font-size:var(--fs-xl);margin-bottom:var(--s-4);padding-left:0;
  color:var(--ink);
}
.sn-product .hero-card h2::before{display:none}
.sn-product .hero-card .lv{gap:var(--s-3);margin-bottom:var(--s-5);
  grid-template-columns:1fr}
.sn-product .hero-card .lv dd{font-weight:700}
.sn-product .hero-card .fig{
  font-size:26px;font-weight:800;color:var(--teal);
  letter-spacing:-0.022em;font-variant-numeric:tabular-nums;
}
.sn-product .hero-card .fig-note{
  display:block;font-size:var(--fs-sm);font-weight:400;color:var(--ink-2);
  margin-top:var(--s-1);letter-spacing:0;
}

.sn-product .btn{
  display:flex;align-items:center;justify-content:center;
  /* width:100% plus padding without border-box resolves to the card's full
     width and then adds the padding on top, which is why the button broke out
     of every university card by exactly its horizontal padding. */
  box-sizing:border-box;
  width:100%;min-height:48px;padding:var(--s-3) var(--s-5);
  border-radius:var(--r-2);border:1.5px solid var(--teal);
  background:var(--teal);color:var(--surface);
  font-family:inherit;font-size:var(--fs-md);font-weight:700;
  cursor:pointer;text-decoration:none;
  transition:background var(--m-hover),border-color var(--m-hover);
}
@media (hover:hover) and (pointer:fine){.sn-product .btn:hover{background:var(--teal-dark);border-color:var(--teal-dark)}}
.sn-product .btn-ghost{
  background:var(--surface);color:var(--teal);
}
@media (hover:hover) and (pointer:fine){.sn-product .btn-ghost:hover{background:var(--teal-tint);border-color:var(--teal-dark)}}

@media(min-width:1200px){
  .sn-product .hero-grid{grid-template-columns:1fr 360px;gap:var(--s-8);align-items:start}
}

/* ---------------------------------------------------------------
   3. Highlight card grid

   Six cards, two across on mobile and three above 600. A card whose
   value is empty drops. The grid never renders a placeholder and
   never rebalances to fill a hole, so five cards is an acceptable
   state and four is too.
   --------------------------------------------------------------- */

.sn-product .hgrid{
  display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s-3);
}
.sn-product .hcard{
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-3);padding:var(--s-4);
  text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:var(--s-3);
}
.sn-product .hicon{
  width:40px;height:40px;border-radius:var(--r-full);
  background:var(--teal-tint);
  background-repeat:no-repeat;background-position:50% 50%;
  background-size:24px 24px;
  flex:none;
}
.sn-product .hcard .hlabel{
  font-size:var(--fs-sm);color:var(--ink-2);font-weight:500;
}
.sn-product .hcard .hvalue{
  font-size:var(--fs-md);color:var(--ink);font-weight:700;
  font-variant-numeric:tabular-nums;
}
@media(min-width:600px){
  .sn-product .hgrid{grid-template-columns:repeat(3,1fr);gap:var(--s-5)}
  .sn-product .hcard{padding:var(--s-5)}
}

/* ---------------------------------------------------------------
   4. Sticky section navigation

   Full width bar on --surface with a --line bottom border. Once
   stuck it gains the single elevation.

   Horizontally scrollable at every width, with a fade mask at both
   ends rather than arrows. The reference uses arrows; a fade is
   smaller, needs no hit target, and cannot be mistaken for
   pagination, which matters at fifteen to twenty five items.

   It sticks below the site header, whose height chrome.js measures
   into --hdr. Hard-coding a number here breaks the moment the header
   wraps at 359px.
   --------------------------------------------------------------- */

.sn-product .jumpnav{
  position:sticky;top:var(--hdr);z-index:40;
  background:var(--surface);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  padding:0;
  transition:box-shadow 150ms ease-out;
}
.sn-product .jumpnav.stuck{box-shadow:var(--lift)}
/* The list carries the gutter, not the wrap. The mask fades the element's own
   box, so with the padding on .wrap the fade landed on the first item's first
   letter instead of on the space before it. */
.sn-product .jumpnav .wrap{padding:0;max-width:none}
.sn-product .jumplist{
  display:flex;gap:var(--s-1);
  max-width:1160px;margin:0 auto;
  padding:0 var(--gut);
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
  /* Transparent across the gutter at each end, opaque between, so an item
     scrolled under the edge fades rather than being cut. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 var(--gut),#000 calc(100% - var(--gut)),transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 var(--gut),#000 calc(100% - var(--gut)),transparent 100%);
}
.sn-product .jumplist a{
  display:flex;align-items:center;
  padding:0 var(--s-3);min-height:44px;
  scroll-snap-align:start;
  font-size:var(--fs-base);font-weight:600;color:var(--ink-2);
  text-decoration:none;white-space:nowrap;
  border-bottom:2px solid transparent;
  transition:color var(--m-hover);
}
@media (hover:hover) and (pointer:fine){.sn-product .jumplist a:hover{color:var(--ink)}}
.sn-product .jumplist a[aria-current="true"]{
  color:var(--teal);border-bottom-color:var(--teal);
}

/* ---------------------------------------------------------------
   5. Accreditation band

   Sits immediately below the section navigation, because it answers
   the first question a person asks and that is where the first
   question is asked.

   Regulator marks sit in white rounded tiles so a mark reads
   regardless of its own colour. No logo files are held, so the tiles
   carry the body's name set in ink, which is honest and needs no
   permission.
   --------------------------------------------------------------- */

.sn-product .accred-grid{display:grid;gap:var(--s-5)}
.sn-product .accred-img{
  border-radius:var(--r-3);overflow:hidden;background:rgba(255,255,255,.08);
  min-height:120px;
}
.sn-product .marks{display:flex;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-5)}
/* The card is light inside a dark band, so it has to reset the ink the
   band set. Without this the body name is #FFF on #FFF: NIRF, NAAC and
   UGC rendered as blank cards carrying only their award line. */
.sn-product .mark{
  color:var(--ink);
  background:var(--surface);border-radius:var(--r-2);
  padding:var(--s-4);min-height:64px;
  display:flex;flex-direction:column;justify-content:center;
  gap:2px;
}
.sn-product .mark b{font-size:var(--fs-md);font-weight:800;color:var(--ink);
  letter-spacing:-0.01em}
.sn-product .mark span{font-size:var(--fs-xs);color:var(--ink-2)}

@media(min-width:900px){
  .sn-product .accred-grid{grid-template-columns:300px 1fr;gap:var(--s-8);align-items:center}
  .sn-product .accred-grid.accred-solo{grid-template-columns:1fr}
}
/* Marks sit in a row that wraps, so a college with three reads as three and one
   with six reads as six, rather than both reading as a column. */
.sn-product .accred-solo .marks{max-width:none}
.sn-product .accred-solo p{max-width:68ch}

/* ---------------------------------------------------------------
   6. Semester tabs

   Four tabs, one panel each. A semester with no published subjects
   has no tab at all, which is what lets the same component render a
   college publishing eight elective subjects and one publishing
   none.
   --------------------------------------------------------------- */

.sn-product .tabs{
  display:flex;gap:var(--s-3);
  overflow-x:auto;overscroll-behavior-x:contain;
  padding-bottom:var(--s-2);
}
.sn-product .tab{
  flex:1 0 auto;min-width:150px;min-height:44px;
  text-align:left;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-2);padding:var(--s-4);
  font-family:inherit;cursor:pointer;
  display:block;
  transition:border-color var(--m-hover),background var(--m-hover);
}
.sn-product .tab .tnum{
  display:block;font-size:var(--fs-sm);color:var(--ink-2);margin-bottom:2px;
}
.sn-product .tab .ttitle{
  display:block;font-size:var(--fs-base);font-weight:600;color:var(--ink);
}
.sn-product .tab[aria-selected="true"]{
  border-color:var(--teal);background:var(--teal-tint);
}
.sn-product .tab[aria-selected="true"] .ttitle{color:var(--teal-dark)}

.sn-product .tpanel{
  background:var(--surface-2);border-radius:var(--r-3);
  padding:var(--s-5);margin-top:var(--s-4);
}
.sn-product .tpanel[hidden]{display:none}
.sn-product .tpanel h3{font-size:var(--fs-lead);margin-bottom:var(--s-2)}
.sn-product .tpanel .tlead{color:var(--ink-2);font-size:var(--fs-base);
  margin-bottom:var(--s-5)}
.sn-product .subjects li{
  display:flex;justify-content:space-between;gap:var(--s-4);
  padding:var(--s-3) 0;border-bottom:1px solid var(--line);
}
.sn-product .subjects li:last-child{border-bottom:none}
.sn-product .subjects b{font-weight:600;color:var(--ink);font-size:var(--fs-md)}
.sn-product .subjects span{color:var(--ink-2);font-size:var(--fs-sm);
  white-space:nowrap;font-variant-numeric:tabular-nums}

@media(min-width:600px){
  .sn-product .tpanel{padding:var(--s-6)}
}

/* ---------------------------------------------------------------
   7. Two tab rail

   Below 900 the tabs stack above the panel as full width buttons.
   At 900 and above they sit in a left column at 260px with the panel
   to the right.
   --------------------------------------------------------------- */

.sn-product .rail-grid{display:grid;gap:var(--s-5)}
.sn-product .rail{display:grid;gap:var(--s-3);align-content:start}
.sn-product .rail-btn{
  width:100%;min-height:44px;text-align:left;
  padding:var(--s-4);
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-2);
  font-family:inherit;font-size:var(--fs-md);font-weight:600;color:var(--ink-2);
  cursor:pointer;
  transition:border-color var(--m-hover),color var(--m-hover);
}
.sn-product .rail-btn[aria-selected="true"]{
  border-color:var(--teal);color:var(--teal);
}
.sn-product .rail-panel[hidden]{display:none}
.sn-product .rail-panel h3{font-size:var(--fs-lead);margin-bottom:var(--s-4)}

@media(min-width:900px){
  .sn-product .rail-grid{grid-template-columns:260px 1fr;gap:var(--s-8);align-items:start}
}

/* ---------------------------------------------------------------
   8. Overview
   --------------------------------------------------------------- */

.sn-product .sub-h{
  font-size:var(--fs-md);font-weight:700;color:var(--ink);
  margin:var(--s-6) 0 var(--s-3);
}

/* ---------------------------------------------------------------
   9. Attribute row comparison

   The column for the college whose page this is takes a teal border
   on all sides and a teal tint header, which is what the reference
   does with its own column and is the one thing about its layout
   that is straightforwardly right.

   No ticks and no crosses. A cell either states a fact or says the
   university does not publish it.
   --------------------------------------------------------------- */

.sn-product .cmp th.mine{
  background:var(--teal-tint);color:var(--teal-dark);
  border-left:1px solid var(--teal);border-right:1px solid var(--teal);
  border-top:1px solid var(--teal);
}
.sn-product .cmp td.mine{
  border-left:1px solid var(--teal);border-right:1px solid var(--teal);
  color:var(--ink);
}
.sn-product .cmp tr:last-child td.mine{border-bottom:1px solid var(--teal)}
.sn-product .cmp tbody th{white-space:normal;min-width:120px}

/* An unpublished value is set quieter than a published one and is
   never styled as an error. On this site an absence is a finding. */
/* No opacity. --ink-2 at .62 composites to about 2.9:1 on --surface,
   under the 4.5:1 body copy needs, and this is the cell that tells a
   reader a university has not published something. Full --ink-2 is
   7:1 and still reads as the quieter of the two states. */
.sn-product .unsaid{color:var(--ink-2);font-style:normal}

/* ---------------------------------------------------------------
   10. Fee card
   --------------------------------------------------------------- */

.sn-product .fee-card{max-width:560px;padding:var(--s-5)}
.sn-product .pill{
  display:inline-block;padding:var(--s-1) var(--s-3);
  border-radius:var(--r-full);background:var(--teal-tint);
  color:var(--teal-dark);font-size:var(--fs-xs);font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;
}
.sn-product .fee-label{
  margin-top:var(--s-4);font-size:var(--fs-md);font-weight:600;color:var(--ink);
}
.sn-product .fee-fig{
  font-size:32px;font-weight:800;color:var(--teal);
  letter-spacing:-0.022em;font-variant-numeric:tabular-nums;
  margin-top:var(--s-1);
}
.sn-product .fee-sub{
  margin:var(--s-5) 0 var(--s-3);
  font-size:var(--fs-sm);font-weight:700;color:var(--ink);
  letter-spacing:.04em;text-transform:uppercase;
}
.sn-product .fee-card .note{margin-top:var(--s-4)}
.sn-product .fee-card .btn{margin-top:var(--s-6)}

.sn-product .route-btns{
  display:flex;gap:var(--s-1);padding:var(--s-1);
  background:var(--surface-2);border-radius:var(--r-full);
}
.sn-product .route-btn{
  flex:1;min-height:40px;padding:var(--s-2) var(--s-3);
  border:none;background:transparent;border-radius:var(--r-full);
  font-family:inherit;font-size:var(--fs-base);font-weight:600;color:var(--ink-2);
  cursor:pointer;
  transition:background var(--m-hover),color var(--m-hover);
}
.sn-product .route-btn[aria-pressed="true"]{
  background:var(--surface);color:var(--ink);box-shadow:var(--lift);
}
.sn-product .route-panel{padding-top:var(--s-4)}
.sn-product .route-panel[hidden]{display:none}
.sn-product .route-fig{
  font-size:var(--fs-xl);font-weight:700;color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.sn-product .route-term{font-size:var(--fs-base);font-weight:400;color:var(--ink-2)}
.sn-product .route-diff{
  margin-top:var(--s-2);font-size:var(--fs-base);color:var(--teal-dark);font-weight:600;
}
.sn-product .route-note{margin-top:var(--s-2);font-size:var(--fs-base);color:var(--ink-2)}

/* ---------------------------------------------------------------
   Capture point

   Replaces a section rather than leaving a hole. Styled as a quiet
   panel, not as a call to action: a person reading it has just been
   told something is missing, and shouting at them about it is the
   wrong response to that.
   --------------------------------------------------------------- */

.sn-product .capture{
  margin-top:var(--s-6);max-width:560px;
  background:var(--surface-2);
  border:1px solid var(--line);
  border-radius:var(--r-3);
  padding:var(--s-5);
}
.sn-product .capture h3{font-size:var(--fs-lead);margin-bottom:var(--s-2)}
.sn-product .capture p{color:var(--ink-2);font-size:var(--fs-base);margin-bottom:var(--s-5)}
.sn-product .capture .btn{max-width:280px}

/* A curriculum with one panel and no tabs. Same panel, sitting directly
   under the lead paragraph with nothing above it to point at. */
.sn-product .tpanel-solo{margin-top:var(--s-5)}

/* ---------------------------------------------------------------
   14. Admission steps
   --------------------------------------------------------------- */

/* Stacked bold paragraphs. No numbers, no list markup, no
   connectors, and every step on screen at every width. The iconed
   row from the reference was built, rendered and rejected: see the
   note on sn_p_admission_steps(). */
.sn-product .steps-b{max-width:68ch}
.sn-product .step-b{font-size:var(--fs-md);color:var(--ink-2)}
.sn-product .step-b + .step-b{margin-top:var(--s-5)}
.sn-product .step-b b{color:var(--ink);font-weight:700}

/* ---------------------------------------------------------------
   19. Roles
   --------------------------------------------------------------- */

.sn-product .roles-grid{display:grid;gap:var(--s-6)}
@media(min-width:600px){
  .sn-product .roles-grid{grid-template-columns:repeat(2,1fr);gap:var(--s-8)}
}

/* ---------------------------------------------------------------
   22. Enquiry band
   --------------------------------------------------------------- */

.sn-product .enquiry-band{
  padding:var(--s-7) 0;background:var(--surface-2);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
.sn-product .enquiry{max-width:640px}
.sn-product .enquiry h2{padding-left:0}
.sn-product .enquiry h2::before{display:none}
.sn-product .enquiry p{color:var(--ink-2);font-size:var(--fs-md);margin:var(--s-3) 0 var(--s-5)}
.sn-product .enquiry .btn{max-width:280px}
@media(min-width:900px){
  .sn-product .enquiry-band{padding:var(--s-8) 0}
}

/* ---------------------------------------------------------------
   23. Card grid with filter

   Count on the left, filter chips on the right. The count is
   template driven and is read back from the visible cards by the
   filter, so it cannot disagree with the grid below it.

   No card image. No image is held for any college, and a grid of
   grey rectangles reads worse than a grid of text.

   NAMED uni-filters, NOT filters. components.css turns .filters into
   a fixed full screen drawer below 900px for the listing page's
   mobile filter. A section reusing the name inherited an overlay
   covering the whole viewport, which read as the page having failed
   to render. Scoping to .sn-product does not help: the theme rule
   sets position and the scoped rule never mentioned it, so there was
   nothing to win the cascade with. Check a new class name against
   style.css and components.css before using it.
   --------------------------------------------------------------- */

.sn-product .grid-head{
  display:flex;flex-wrap:wrap;gap:var(--s-4);
  align-items:center;justify-content:space-between;
  margin-bottom:var(--s-5);
}
.sn-product .grid-count{font-size:var(--fs-md);color:var(--ink-2)}
.sn-product .grid-count b{color:var(--ink);font-weight:700;font-variant-numeric:tabular-nums}
.sn-product .uni-filters{display:flex;flex-wrap:wrap;gap:var(--s-2)}
.sn-product .uni-filter{
  padding:var(--s-2) var(--s-4);
  border:1px solid var(--line);border-radius:var(--r-full);
  background:var(--surface);
  font-family:inherit;font-size:var(--fs-base);font-weight:600;color:var(--ink-2);
  cursor:pointer;
  transition:border-color var(--m-hover),background var(--m-hover),color var(--m-hover);
}
.sn-product .uni-filter[aria-pressed="true"]{
  border-color:var(--teal);background:var(--teal-tint);color:var(--teal-dark);
}

.sn-product .cards{display:grid;gap:var(--s-4);grid-template-columns:minmax(0,1fr)}
.sn-product .cards > *{min-width:0}
.sn-product .ucard{
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-3);padding:var(--s-5);
  display:flex;flex-direction:column;gap:var(--s-3);
}
.sn-product .ucard[hidden]{display:none}
.sn-product .ucard-uni{font-size:var(--fs-sm);color:var(--ink-2)}
.sn-product .ucard h3{font-size:var(--fs-md);font-weight:700;color:var(--ink)}
.sn-product .ucard-standfirst{
  color:var(--ink-2);font-size:var(--fs-base);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.sn-product .ucard-lv{display:grid;gap:var(--s-2);margin-top:auto}
.sn-product .ucard-lv > div{
  display:flex;justify-content:space-between;gap:var(--s-3);
  padding-bottom:var(--s-2);border-bottom:1px solid var(--line-soft);
}
.sn-product .ucard-lv dt{font-size:var(--fs-sm);color:var(--ink-2)}
.sn-product .ucard-lv dd{
  font-size:var(--fs-base);color:var(--ink);font-weight:600;
  font-variant-numeric:tabular-nums;
}
.sn-product .ucard .btn{margin-top:var(--s-3)}

@media(min-width:600px){
  .sn-product .cards{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-5)}
}
@media(min-width:900px){
  .sn-product .cards{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* ---------------------------------------------------------------
   26. FAQ rail and accordion

   Below 900 the categories become a horizontal chip row above the
   accordion. At 900 and above they sit in a left column, which the
   shared .rail-grid already does.

   Panels are hidden rather than removed when closed, so find in page
   still reaches every answer.
   --------------------------------------------------------------- */

@media(max-width:899px){
  .sn-product .faq-rail{
    display:flex;gap:var(--s-2);overflow-x:auto;padding-bottom:var(--s-2);
  }
}

.sn-product .qitem{border-bottom:1px solid var(--line-soft)}
.sn-product .qitem[hidden]{display:none}
.sn-product .qhead{margin:0}
.sn-product .qbtn{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);
  width:100%;padding:var(--s-4) 0;
  background:none;border:none;text-align:left;cursor:pointer;
  font-family:inherit;font-size:var(--fs-md);font-weight:600;color:var(--ink);
  transition:color var(--m-hover);
}
@media (hover:hover) and (pointer:fine){.sn-product .qbtn:hover{color:var(--teal)}}
.sn-product .qbtn[aria-expanded="true"]{color:var(--teal)}
/* The plus and minus, as a background image on the button rather
   than a child element, for the Safari flex sizing reason recorded
   at the top of this file. */
.sn-product .qbtn::after{
  content:"";flex:none;width:20px;height:20px;
  background-repeat:no-repeat;background-position:50%;background-size:20px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%2346545A'%3E%3Cpath d='M9 3h2v14H9z'/%3E%3Cpath d='M3 9h14v2H3z'/%3E%3C/svg%3E");
}
.sn-product .qbtn[aria-expanded="true"]::after{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%2300707A'%3E%3Cpath d='M3 9h14v2H3z'/%3E%3C/svg%3E");
}
.sn-product .qpanel{padding:0 0 var(--s-5)}
.sn-product .qpanel[hidden]{display:none}
.sn-product .qpanel p{color:var(--ink-2);font-size:var(--fs-md);max-width:68ch}

/* The rail buttons in the FAQ are a filter group, not tabs, so they
   carry aria-pressed and take the pressed treatment. */
.sn-product .rail-btn[aria-pressed="true"]{
  border-color:var(--teal);background:var(--teal-tint);color:var(--teal-dark);
}

/* ---------------------------------------------------------------
   27. Variant switcher

   Segmented control above 600, a select below it. Three long labels
   cannot segment at 375, and a select is the control a phone
   already knows how to render.
   --------------------------------------------------------------- */

.sn-product .switch-track{display:none}
.sn-product .switch-select{display:block;max-width:420px}
.sn-product .switch-select select{
  width:100%;min-height:48px;padding:var(--s-3) var(--s-4);
  border:1px solid var(--line-field);border-radius:var(--r-2);
  background:var(--surface);color:var(--ink);
  font-family:inherit;font-size:var(--fs-md);font-weight:600;
}
.sn-product .switch-echo{
  margin-top:var(--s-5);font-size:var(--fs-md);color:var(--ink-2);
}
.sn-product .switch-echo b{color:var(--ink);font-weight:700}

@media(min-width:600px){
  .sn-product .switch-select{display:none}
  .sn-product .switch-track{
    display:inline-flex;gap:var(--s-1);padding:var(--s-1);
    background:var(--surface-2);border-radius:var(--r-full);
  }
  .sn-product .switch-seg{
    padding:var(--s-2) var(--s-5);
    border:none;background:transparent;border-radius:var(--r-full);
    font-family:inherit;font-size:var(--fs-base);font-weight:600;color:var(--ink-2);
    cursor:pointer;
    transition:background var(--m-hover),color var(--m-hover);
  }
  .sn-product .switch-seg[aria-pressed="true"]{
    background:var(--surface);color:var(--ink);box-shadow:var(--lift);
  }
}

/* ===============================================================
   Inversion layer for the teal part

   LAST IN THE FILE ON PURPOSE. Everything above is the global layer
   and then the sections in page order, and each section sets its own
   colours at the same specificity as a band rule would. A band rule
   written beside the band therefore loses every tie to a section
   below it, silently, and the University part shipped with #0E1618
   body copy on #00363C at 1.39:1 against a required 4.5:1.

   So the inversion is not written beside the band. It is written
   after every section that could override it, which is what makes it
   hold without a single !important.

   Scoped to the part rather than to named sections, so a section
   moved into or out of the University group on the Page design sheet
   inverts or stops inverting by moving, with no CSS edit at all.
   =============================================================== */

.sn-product .pgroup-teal h2,
.sn-product .pgroup-teal h3,
.sn-product .pgroup-teal h4,
.sn-product .pgroup-teal dt,
.sn-product .pgroup-teal th,
.sn-product .pgroup-teal b,
.sn-product .pgroup-teal strong,
.sn-product .pgroup-teal .sub-h,
.sn-product .pgroup-teal .lv dt{color:var(--surface)}

/* #CFE3E4 rather than --teal-lite. --teal-lite is #4FC7CE, which is
   3.9:1 on --teal-deep and fails body copy. This clears 9:1 and stays
   in the same family. */
.sn-product .pgroup-teal p,
.sn-product .pgroup-teal li,
.sn-product .pgroup-teal td,
.sn-product .pgroup-teal dd,
.sn-product .pgroup-teal small,
.sn-product .pgroup-teal .lv dd,
.sn-product .pgroup-teal .prose p,
.sn-product .pgroup-teal .note,
.sn-product .pgroup-teal .sec-sub{color:#CFE3E4}

.sn-product .pgroup-teal .sec-head h2 em{color:var(--teal-lite)}
.sn-product .pgroup-teal .sec-head h2::before{background:var(--teal-lite)}

.sn-product .pgroup-teal a{color:var(--teal-lite)}
@media (hover:hover) and (pointer:fine){.sn-product .pgroup-teal a:hover{color:var(--surface)}}

.sn-product .pgroup-teal table,
.sn-product .pgroup-teal .dtable th,
.sn-product .pgroup-teal .dtable td{border-color:rgba(255,255,255,0.18)}

.sn-product .pgroup-teal .note,
.sn-product .pgroup-teal .general{
  background:rgba(255,255,255,0.06);
  border-color:rgba(255,255,255,0.20);
}

/* A card keeps its own light ground inside the dark part, so its own
   ink is correct and must not be inverted with everything else. */
.sn-product .pgroup-teal .card,
.sn-product .pgroup-teal .capture{background:var(--surface);color:var(--ink)}
.sn-product .pgroup-teal .card h3,
.sn-product .pgroup-teal .card p,
.sn-product .pgroup-teal .card li,
.sn-product .pgroup-teal .capture h3,
.sn-product .pgroup-teal .capture p{color:var(--ink)}
.sn-product .pgroup-teal .capture p{color:var(--ink-2)}

/* ===============================================================
   Target size and focus

   Also last, for the same reason as the inversion above: these have
   to beat the component rules that set the padding, and they do it
   on order rather than on !important.
   =============================================================== */

/* WCAG 2.5.5 asks for 44px. The chips were 41px tall, the breadcrumb
   links 21px, which is under even the 24px floor of 2.5.8. The visual
   size of a chip does not change: the height comes from padding that
   was already nearly there, and the breadcrumb grows its hit area
   without growing its type. */
.sn-product .chip,
.sn-product .uni-filter,
.sn-product .rail-btn,
.sn-product .route-btn,
.sn-product .tab{min-height:44px}

.sn-product .crumbs a,
.sn-product .crumbs span{
  display:inline-flex;align-items:center;
  min-height:44px;
}
.sn-product .crumbs ol{align-items:center}

/* The focus ring is --teal, which is 1.9:1 on --teal-deep and cannot
   be seen on the University part. The hero already had this fix; the
   part needed it too. */
.sn-product .pgroup-teal a:focus-visible,
.sn-product .pgroup-teal button:focus-visible,
.sn-product .pgroup-teal [tabindex]:focus-visible{
  outline:2px solid #FFFFFF;outline-offset:2px;
}

/* A named scroll region is a tab stop, so it needs a ring of its own. */
.sn-product .tscroll:focus-visible{
  outline:2px solid var(--teal);outline-offset:2px;border-radius:var(--r-sm);
}

.sn-product .mark b{color:var(--ink)}
.sn-product .mark span{color:var(--ink-2)}

/* A flat table is flat until its content is wider than the phone. The
   concessions table overflowed its wrapper at 375 with no way to reach
   the right of it, which is worse than a scroller because nothing tells
   the reader there is more. It scrolls only when it has to, and the
   wrapper is a labelled tab stop for the same reason .tscroll is. */
.sn-product .tflat{overflow-x:auto;overscroll-behavior-x:contain}
.sn-product .tflat:focus-visible{
  outline:2px solid var(--teal);outline-offset:2px;border-radius:var(--r-sm);
}

/* The three actions, and the only three on the page. Apply carries the fill,
   call and WhatsApp sit beside it as equals to each other and secondary to it,
   because a person who wants to talk to someone should not have to hunt and a
   person who is ready should not have to choose. */
.sn-product .enquiry-actions{display:grid;gap:var(--s-3);margin-top:var(--s-5)}
.sn-product .enquiry-actions .btn{margin:0}
.sn-product .enquiry-actions .wa{border-color:var(--wa);color:var(--wa)}
@media (hover:hover) and (pointer:fine){.sn-product .enquiry-actions .wa:hover{background:var(--wa);color:var(--surface);border-color:var(--wa)}}

@media(min-width:700px){
  .sn-product .enquiry-actions{
    grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,1fr);
    align-items:stretch;
  }
}

/* ===============================================================
   Hero and lead capture

   Ported from the specimen as its resolved state, not as its seven
   appended passes. That file redefines .faqwrap four times and
   .speclist three, so the answer to what a class does is read the
   whole file. Everything below is written once.

   Class names are prefixed lf- and phero-. .btn, .ticks and .card
   already mean something in this stylesheet and in components.css.
   =============================================================== */

.sn-product .phero{
  background:linear-gradient(180deg,var(--surface-2) 0%,var(--surface) 62%);
  padding:26px 0 46px;border-top:none;position:relative;overflow:hidden;
}
.sn-product .phero::after{
  content:"";position:absolute;left:-180px;top:-160px;width:520px;height:520px;
  border-radius:50%;background:radial-gradient(circle,rgba(0,112,122,0.10),transparent 66%);
  pointer-events:none;
}
.sn-product .phero .wrap{
  position:relative;display:grid;grid-template-columns:minmax(0,1fr) 366px;
  gap:44px;align-items:start;
}
.sn-product .phero-main{min-width:0}

.sn-product .lockup{display:flex;align-items:center;gap:11px;margin-bottom:18px}
.sn-product .lockup-mark{
  width:44px;height:44px;flex:none;border-radius:var(--r-2);
  border:1px solid var(--line);background:var(--surface);
  display:flex;align-items:center;justify-content:center;
}
.sn-product .lockup-mark b{font-size:var(--fs-sm);font-weight:800;color:var(--teal-dark);letter-spacing:0.02em}
.sn-product .lockup-mark img{max-height:30px;width:auto;display:block}
.sn-product .lockup-name{font-size:var(--fs-base);font-weight:700;color:var(--ink-2);letter-spacing:-0.01em}

.sn-product .phero h1{
  font-size:clamp(32px,5vw,50px);line-height:1.02;letter-spacing:-0.04em;
  color:var(--ink);margin-bottom:14px;
}
/* Solid, not a gradient. A gradient across two words at 44px reads
   muddy beside near black ink on a phone at partial brightness. */
.sn-product .phero h1 em{font-style:normal;color:var(--teal-dark)}
.sn-product .phero h1 span{
  display:block;font-size:var(--fs-md);font-weight:600;letter-spacing:-0.01em;
  color:var(--ink-2);margin-top:12px;
}
.sn-product .phero-lede{color:var(--ink-2);font-size:var(--fs-md);line-height:1.55}
@media(min-width:901px){.sn-product .phero-lede{max-width:58ch}}

.sn-product .phero-viz{margin-top:22px;border-radius:var(--r-3);overflow:hidden}
.sn-product .phero-viz img{display:block;width:100%;height:auto}

.sn-product .hstrip{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  margin-top:22px;border:1px solid var(--line);border-radius:var(--r-2);
  background:var(--surface);
}
.sn-product .hstrip > div{padding:15px 18px;border-right:1px solid var(--line-soft);min-width:0}
.sn-product .hstrip > div:last-child{border-right:0}
.sn-product .hstrip small{
  display:block;font-size:var(--fs-xs);letter-spacing:0.08em;text-transform:none;
  font-weight:700;color:var(--ink-2);margin-bottom:4px;
}
.sn-product .hstrip b{
  display:block;font-weight:800;font-size:var(--fs-xl);letter-spacing:-0.03em;
  color:var(--teal-deep);font-variant-numeric:tabular-nums;line-height:1.1;white-space:nowrap;
}

.sn-product .hbadges{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px;list-style:none;padding:0}
.sn-product .hbadges li{
  display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-sm);font-weight:600;
  color:var(--ink);background:var(--surface);border:1px solid var(--line);
  padding:8px 13px;border-radius:var(--r-full);
}
.sn-product .hbadges li::before{
  content:"";width:7px;height:7px;border-radius:50%;background:var(--teal);flex:none;
}

/* ---- the form in the hero column ---- */

/* The form itself is the shipped component and is styled in
   components.css. Only its placement is this page's business. */
.sn-product .phero-side{min-width:0}
.sn-product .phero-side .lead-unit{position:sticky;top:calc(var(--hdr) + 60px)}
.sn-product .lf-band{background:var(--surface-2);border-top:none;padding:48px 0}

@media(max-width:1100px){
  .sn-product .phero .wrap{grid-template-columns:minmax(0,1fr) 320px;gap:30px}
}
@media(max-width:900px){
  .sn-product .phero{padding:20px 0 34px}
  .sn-product .phero .wrap{grid-template-columns:1fr;gap:26px}
  .sn-product .phero-side .lead-unit{position:static}
  .sn-product .hstrip{grid-template-columns:1fr 1fr}
  .sn-product .hstrip > div:nth-child(2){border-right:0}
  .sn-product .hstrip > div:nth-child(-n+2){border-bottom:1px solid var(--line-soft)}
  .sn-product .phero h1{font-size:clamp(31px,8.6vw,40px)}
  .sn-product .hbadges{display:grid;grid-template-columns:1fr 1fr}
  .sn-product .hbadges li{justify-content:center;padding:9px 10px;font-size:var(--fs-xs);font-weight:700}
}
@media(max-width:360px){
  .sn-product .hstrip{grid-template-columns:1fr}
  .sn-product .hstrip > div{border-right:0;border-bottom:1px solid var(--line-soft)}
  .sn-product .hstrip > div:last-child{border-bottom:0}
  .sn-product .hbadges{grid-template-columns:1fr}
}

/* The registered name, stated once under the accreditation heading. Quieter
   than body copy because it is a formality, not the argument. */
.sn-product .legal-name{font-size:var(--fs-sm);margin-top:var(--s-3)}


/* The college's own printed name for the subject, beneath the H1. Quieter than
   the lede because it is a disclosure, not the promise of the page. Absent
   where the college prints the canonical name. */
.phero-label{color:var(--ink-2);font-size:var(--fs-sm);margin-top:8px}
