@charset "utf-8";
/* ============================================================================
   VCE BRAND THEME FOR VT ONE  —  v3.8
   Re-skins any vt-one / Ensemble AEM site to Virginia Cooperative Extension
   branding, per VCE Brand Guidelines V1.1.

   INSTALL
     This is the whole file. Replace modifyGlobalTemplate.css with it, e.g.
     /local_assets/www.ext.vt.edu/local/modifyGlobalTemplate.css
     Publish the file and flush the dispatcher — editing it is not enough.

   ── WHAT CHANGED FROM v3.7 ───────────────────────────────────────────────
     NEW      §11.5  pagination. vt-one shipped it as near-black squares.
              Now Light Grey pills with a 5.03:1 border, Maroon for the
              current page, 44px targets.

     Three things were wrong with it and only one was the colour:
       • IT STACKED. col-lg-3/6/3 only sits in a row above 992px, which
         inside #vt_main beside the right column almost never happens.
         Replaced with a flex row that wraps on its own terms.
       • CURRENT PAGE AND FOCUS LOOKED THE SAME. Both were a ring, so
         tabbing onto the current page told a keyboard user nothing. Current
         is now a filled pill; focus stays the §16 ring.
       • THE BOXES ARE BUTTONS, NOT LINKS. onclick="vtListPageAjax(…)" and
         no href, so a page number is not a URL — no middle-click, no open
         in new tab, no history entry. Ensemble architecture; CSS cannot
         reach it. Listed so it does not get filed as a styling bug.

     ⚠ THE BORDER ON THE PILLS IS 1.4.11, NOT DECORATION
       Light Grey is 1.20:1 on white. Fine for a §11.1e tag, where the shape
       is decorative and the text carries the meaning — not fine for a
       control, whose boundary has to be identifiable at 3:1. Don't tidy the
       border away.

     ⚠ DON'T ADD !important TO display IN §11.5b
       Numbers 5–9 carry Bootstrap's d-none/d-sm-flex, both !important,
       which is how the middle of the range drops on a phone. Our display
       sits under them on purpose. Add !important and all nine come back at
       320px.

     ⚠ aria-current="true" SHOULD BE aria-current="page" — in the
       component's HTML, not here. §11.5d matches the class and the
       attribute, so fixing it upstream won't break the styling.

     NOT DONE  the "Page 2 of 23 | 448 Results" line is a separate element
              that wasn't in the markup, so it has no selector yet.

   ── WHAT CHANGED FROM v3.6 ───────────────────────────────────────────────
     ── people pages: the offices a person covers ──
     NEW      §11.1f  :offices/ pills, Dark Green, prefixed "Serves ", shown
              on bio cards only. They are scoped to li.bio-page, a class the
              List component stamps on every bio item by itself — so no
              CSS-class field to fill in on 107 sites, but it IS vt-one's
              class, not ours. Grep bio-page after an Ensemble upgrade.
     NEW      §11.4  the bio page tag cloud, ul.tagcloud / a.vt-tag-link.
              A different component with different markup: no inner span for
              the label, no role="listitem", and the ?tag= query swapped for
              a /tags.html/ path. Three things that change the CSS and not
              just the selector — the §11.4 header walks through each.
              Shares §11.1's --pill-bg / --pill-ink, so a category colour
              still changes in one place for both components.
     CHANGED  §11.1b order ladder 1/2/3 → 10/20/30/40, spaced like the §2
              z-index ladder so the next category slots in without a
              renumber. :offices/ takes 20, between location and specialism.
     RENAMED  §11.1f/g/h → §11.1g/h/i, to make room for the new §11.1f.
              Cross-references updated; nothing else moved.

     ⚠ TWO THINGS THE CSS CANNOT DO, BOTH IN THE JS
       People are normally tagged :home-office/x AND :offices/x, which
       renders "Housed in Nottoway" beside "Serves Nottoway"; and on a
       county's own page every staff card would read "Serves <that county>".
       Comparing a tag's slug against a sibling's, or against the URL, is
       not expressible in a selector. vce-tag-pills-disable.html v3.1 does
       both. Ship the two together — v3.0 of the JS leaves the duplicates.

     ⚠ THE TAG CLOUD LINKS STAY LIVE, THE CARD PILLS STAY DEAD
       Looks like an inconsistency, isn't. The card pills are killed because
       the card title's stretched ::before makes the whole card one click
       target and a live link inside it fights for the same pixels. A bio
       page has no stretched link, so there is no conflict and no reason to
       take away a working route to the tag search. Both notes in §11.4.

     ⚠ "Serves" IS OUR READING OF THE TAG
       The taxonomy only says a person is associated with that office. If an
       office means something else by it, change the string in §11.1f and
       §11.4d — not the tags.

   ── WHAT CHANGED FROM v3.5 ───────────────────────────────────────────────
     CHANGED  §8.1 the solid block now sizes to its own content — the
              heading, or the button if that's wider — instead of a set
              width. The curve is a fixed --hero-curve-w (12rem) sitting at
              left:100%, outside the panel, so heading length and curve
              thickness are fully independent. --hero-solid-w is replaced by
              --hero-solid-max, a wrap ceiling rather than a width.

   ── WHAT CHANGED FROM v3.4 ───────────────────────────────────────────────
     FIXED    §8.1 the curve grew to span the hero whenever the panel was
              widened. --hero-curve-w was a percentage OF THE PANEL, so the
              two were coupled. Replaced by --hero-solid-w and
              --hero-curve-w, both in vw, so each is independent of the
              other. Defaults 32vw solid + 10vw curve; --hero-split is gone.

   ── WHAT CHANGED FROM v3.3 ───────────────────────────────────────────────
     CHANGED  §8.1 the hero panel's solid fill and its curve are now two
              pseudo-elements, sized independently, instead of one mask with
              the split baked into its viewBox.
              Both use top/bottom rather than inset, so they follow the
              panel's height rather than imposing one.

   ── WHAT CHANGED FROM v3.2 ───────────────────────────────────────────────
     NEW      §8.1 hero swoosh panel — the popover's Light Grey box becomes a
              brand panel with the swoosh as its right edge, over a
              full-bleed photo. Same guide curve as the swoosh cards, filled
              on the left.
              ⚠ Panel defaults to Dark Grey (white 5.03:1), not the mockup's
              #508590, which is off-palette and 4.12:1.
              ⚠ The button's white border is required, not trim — maroon
              scores 1.04–1.81 against every palette panel colour, so
              without it the control has no visible boundary (1.4.11).

   ── WHAT CHANGED FROM v3.1 ───────────────────────────────────────────────
     FIXED    §11.3 card titles went Maroon on hover — 1.04:1 on the Dark
              Green fill, i.e. invisible. §4 and §11 both style
              .vt-list-item-title-link:hover, at the same (0,2,2) as the
              unstated base rule here, so it hung on source order. Every
              state is now named at (0,3,2), and the hover affordance is an
              underline plus the card shadow rather than a colour change.

   ── WHAT CHANGED FROM v3.0 ───────────────────────────────────────────────
     NEW      §11.3 cardify list — swoosh cards driven by the List
              component. ext-office-cardify-list-component on the List's
              CSS-class field. Pure CSS, same approach as §14.
              Art panel uses the item's own image when it has one, and falls
              back to a DAM pattern when it doesn't.
              ⚠ The fallback may be redundant: your sample card's image is
              already a DAM pattern, so authors can pick one in the image
              field and skip the lookup entirely. The rotation is a floor
              for cards nobody set an image on, and it is positional, not
              semantic — see §11.3 for the semantic alternative using the
              taxonomy classes the li already carries.
              ⚠ Undoes §11's card rules the same way §14 does, so it must
              stay after §11.

   ── WHAT CHANGED FROM v2.12 ──────────────────────────────────────────────
     §11.1    REWRITTEN around the new :home-office/ tag namespace.
              THE GUESS IS GONE. The home office used to be inferred as
              "the last :offices/ tag" — unverified, and load-bearing
              enough to put a wrong county on a person's card. The tag now
              states it, so the sibling-position selectors, the
              vce-tags-show-services opt-out and the standing "verify this
              before shipping" warning are all deleted.
              Only two categories render: Housed in, and specializations.
              Everything else is hidden; vce-tags-show-all brings it back.
              ⚠ MIGRATION — this reads ONLY :home-office/. Anyone still
              carrying just the old :offices/ tags now shows no location
              tag. Query for people with a specialization and no home
              office before calling the migration done.
     COMPANION vce-tag-pills-disable.html updated for the new tag namespace
              AND the new URL shape (offices.ext.vt.edu/<countyId>, no
              /local/). Both files have to be deployed together.

   ── WHAT CHANGED FROM v2.11 ──────────────────────────────────────────────
     CHANGED  swoosh seam overlap is calc(100% - 1px) rather than 99.9%, so
              it's a constant 1px at every panel width. Applied to the
              mirrored vce-about--left variant too, which had no fix.

   ── WHAT CHANGED FROM v2.10 ──────────────────────────────────────────────
     ── your changes, placed ──
     §5.1     home content well, right column and its briefs forced white;
              content-area top padding removed. Moved off the white token
              onto --vce-page-bg, same value — so a site that retints its
              page ground carries these along with it.
     §8       hero popover message padding/margin and button sizing.
              ⚠ 5em vertical margin — check the hero under ~400px wide.
     §15      swoosh left: 100% → 99.9% to close the seam.
              Superseded in v2.12 by calc(100% - 1px), both variants.

   ── WHAT CHANGED FROM v2.9 ───────────────────────────────────────────────
     NEW      §2 stacking ladder — --z-decor 1, --z-content 100, and reserved
              --z-sticky/-dropdown/-overlay/-modal at 200–500. Every z-index
              in the file now reads from it; there were only two.
     CHANGED  swoosh 100 → --z-decor (1); #vt_right_col 1000 → --z-content
              (100). Same relative order, decoration where it belongs, and
              room either side of both. See §15.3 for the two things to test.

   ── WHAT CHANGED FROM v2.8 ───────────────────────────────────────────────
     §6.7     NEW — your university-footer hide and footer-content margin.
              ⚠⚠ Removes the Accessibility, Privacy, Equal Opportunity and
              Consumer Information links from every page. Needs sign-off.
              Also listed in a new "University chrome this file changes"
              block at the top, beside the pre-header, so it can't be missed.
     §15.3    NEW — your #vt_right_col z-index, moved beside the swoosh's.
              Superseded in v2.10 by the §2 stacking ladder.

   ── WHAT CHANGED FROM v2.7 ───────────────────────────────────────────────
     ── your template fixes, merged and placed ──
     §5.1     #vt_main / #vt_one_content_area forced white. §5 is now
              "header row and page ground"; the header row is §5.2.
     §10      .vce-office-coords. §10 is now "Lozenges, eyebrows & utilities".
              ⚠ display:none also removes it from the accessibility tree —
              right for machine-readable data, wrong if a screen-reader user
              needs it. See the note there.
     §11      horizontal-scroll cover and item gutters, .ext-staff-list cap.
              ⚠ You had the .vt-list-columns::after rule twice, identical,
              with the same comment. Deduplicated.
     §11.2    Timely calendar container. This does NOT contradict the
              "deliberately does not touch" note — that's about the
              cross-origin iframe; the container is ours. ⚠ 40vh is ~290px
              on a phone, see the note.
     §13.1    .vce-rule-out::after margin-bottom. ⚠ With align-items:center a
              bottom margin moves the line UP by half its value.
     §15      swoosh z-index. Superseded in v2.10 by the §2 stacking ladder.

     Everything landed in a section rather than after the END marker, so the
     next person looking for "why is the content area white" finds it beside
     the other light-chrome rules instead of in a trailing pile.

   ── WHAT CHANGED FROM v2.6 ───────────────────────────────────────────────
     NEW      specialization tags get a Light Grey pill with Dark Blue text,
              12.68:1. (Renumbered to §11.1e in v3.0.)
     ADDED    --pill-ink in §11.1c. Every pill was white-on-colour until now,
              so the ink was hard-coded in two places; specializations are
              the first dark-on-light one. A new category is now two lines.
     CHANGED  tag order is housed-in 1, services 2, specialization 3,
              topics 4 — was 1 / 2 / 3 with topics and specializations
              sharing the last slot.
     RENUMBERED §11.1f/g/h are now §11.1g/h/i to make room. All references
              updated; nothing else moved.

   ── WHAT CHANGED FROM v2.5 ───────────────────────────────────────────────
     FIXED    Office tags lost their colour and prefix once the companion JS
              ran. Every office selector matched a[href*=":offices/"], and
              the JS removes href to neutralise the links — so after it ran,
              nothing matched and the home-office pill fell back to the
              Maroon default with no "Housed in ". It LOOKED like only a
              colour bug because the JS had already deleted the Services
              tags from the DOM before stripping the hrefs.
              Every office selector now matches data-vce-tag-href as well,
              which is where the JS parks the URL. See §11.1 preamble.

   ── WHAT CHANGED FROM v2.4 ───────────────────────────────────────────────
     NEW      only the home office tag is shown; serviced offices hidden.
              The inference this relied on was retired in v3.0 — see the
              v2.12 entry above.

   ── WHAT CHANGED FROM v2.3 ───────────────────────────────────────────────
     FIXED    §14 nav items now fill their row's height. When one label wraps
              to two lines the row grows, but the anchors inside the shorter
              cells were not growing with it — so the hover fill and the teal
              rail stopped short. Every box between the li and the anchor now
              stretches explicitly. See §14.3.

     ── your edits, reviewed ──
     KEPT     §6.6 pre-header, .vt-actions-header, .vt-wordMark-text.
              Right section. Full warning comment restored — it explains why
              this reverses a documented decision, which matters for whoever
              reads this next.
     KEPT     §7 subnav droplist margin. Right section.
     MOVED    .vt-page-info.row padding from §7 to §6.1. It was the only
              .vt-page-info rule outside §6; anyone retuning that band would
              have found the colour and missed the padding.
     MERGED   §12.1 had .vt-accordion declared twice, the second cancelling
              the first's border-bottom. Now one rule. Net effect unchanged —
              no separator between accordion items, which is your call.
     ⚠ FLAG   §6.1 `footer.footer-content` matches ZERO elements — it needs
              <footer class="footer-content">, and the markup is <footer>
              containing <div class="footer-content">. Left as you wrote it,
              but see the note in §6.1: as dead code it means the footer
              ground is unset while §6.2 still forces white ink onto it.
     ⚠ FIXED  §6.3 links inside dark panels were changed to white — the same
              colour as the body text around them, with no underline in the
              default state. Colour was the only thing marking them as links,
              so that fails 1.4.1. Your white is kept and an underline added.

   ── WHAT CHANGED FROM v2.2 ───────────────────────────────────────────────
     CHANGED  §14 now drives the office nav from EITHER markup shape — the
              text-component list it always handled, or the List component's
              card markup. Same class, same result. Shape B is the one to
              standardise on: real page references, so titles and URLs
              follow the pages when they move.
     ⚠ NOTE   §14.2 undoes §11's card rules with !important against
              !important. That's the only place in the file where that
              happens, and it means §14 must stay AFTER §11.
     UPDATED  §16 and §17 gained the Shape B selectors — they only knew the
              text-component anchor before, so forced-colors and print would
              have missed the List-component nav entirely.

   ── WHAT CHANGED FROM v2.1 ───────────────────────────────────────────────
     NEW      §11.1 tag pills — categories told apart by href, with a
              "Housed in" prefix. Needs the companion
              vce-tag-pills-disable.html if the tags should not be
              clickable; §11.1g explains why CSS alone can't do it.
     CHANGED  --vce-link is now Maroon (9.09:1), per your edit.
     ⚠ REVERTED --vce-link-hover from Orange back to Maroon shade. Orange on
              white is 2.87:1 and 1.4.3 wants 4.5:1 for body text, so every
              link on every site would have become HARDER to read on hover.
              Your version is preserved as a one-liner in §18 if you want it
              back knowing the number.
     MERGED   the card-wrapper flex rule into the existing §11 wrapper rule
              rather than declaring the same selector twice.

   ── WHAT CHANGED FROM v2.0 ───────────────────────────────────────────────
     NEW      §3.1 Epilogue forced on everything, with carve-outs for icon
              fonts and code. Inverts the default so a missed selector can
              no longer leak Acherus.
     NEW      §3.3 Bootstrap container reset — vt-one puts Acherus/#000/
              line-height:2 on .container-fluid, which main#vt_main carries,
              so it was the inherited default for the whole page.
     NEW      §13.1 .vce-rule-out trailing gradient rule utility
     FIXED    <footer> itself is now a dark ground (§6.1). Its authored
              footer-briefs parsys went with it, so §6.2 and §6.3 gained the
              in-page items — without that they'd have been 1.0:1.

   ── WHAT CHANGED FROM v1 ─────────────────────────────────────────────────
     NEW      §12 accordions and tabs (vtmultitab), previously unthemed
     FIXED    .vt-page-title on the dark band was 1.45:1 — see §6
     MERGED   every dark surface into one section (§6). Was scattered across
              old §5.2, §5.3, §10 and §12, which is how the page-title band
              got missed.
     MERGED   three @media print blocks into one (§17)
     MERGED   two forced-colors blocks into one (§16)
     ADDED    --vce-heading token for your ink→green change (§2, §3)
     ADDED    --vce-pageinfo-bg, --about-panel-w tokens
     REMOVED  --about-swoosh-min (declared, never referenced)
     REMOVED  :not(#vt_offcanvas_nav *) guards — the ancestor-scoped rules
              in §6 already outrank the base rules on specificity, so the
              :not() was doing nothing. Source order does the work instead.
     MOVED    .ext-list-portrait into §11 where it belongs
     MOVED    h1.vt-bio-name / h2.vt-tagcloud-heading into §6

   ── THE ONE RULE THAT MATTERS ────────────────────────────────────────────
     Never set a colour on a vt-one class without knowing every context it
     renders in. Half the bugs in v1 were one class living on both a light
     and a dark ground. Light chrome goes in §5, dark grounds go in §6.
     If you add a colour anywhere else, check §6 first.

   ── UNIVERSITY CHROME THIS FILE CHANGES ──────────────────────────────────
     Two sections override Virginia Tech's own chrome rather than VCE's.
     Both are policy decisions as much as design ones, and both are one-line
     reverts. Worth a sign-off before this reaches the office sites.
       §6.6  pre-header repainted Dark Green, Apply/Visit/Give/Shop hidden
       §6.7  university footer HIDDEN — including the Accessibility,
             Privacy, Equal Opportunity and Consumer Information links

   ── WHAT THIS DELIBERATELY DOES NOT TOUCH ────────────────────────────────
     - The Timely events iframe. Cross-origin; style it in Timely's admin.
     - DAM images, the Swoosh assets, icon patterns. Assets, not CSS.

   ── CONTRAST (measured, sRGB, WCAG 2.x) ──────────────────────────────────
     white on Maroon #8b1843 .......... 9.09:1   AAA
     white on Dark Green #005267 ...... 8.74:1   AAA
     white on Dark Grey #4c748b ....... 5.03:1   AA
     white on Dark Blue #072938 ...... 15.18:1   AAA
     Dark Blue on white .............. 15.18:1   AAA
     Dark Blue on Light Grey ......... 12.68:1   AAA
     Dark Blue on Teal ................ 9.23:1   AAA
     Dark Blue on Yellow .............. 7.41:1   AAA
     Dark Blue on Orange .............. 5.28:1   AA
     Dark Green on white .............. 8.74:1   AAA
     Dark Green on Light Grey ......... 7.30:1   AAA
     Maroon on white .................. 9.09:1   AAA   (--vce-link)
     Maroon shade on white ........... 12.59:1   AAA   (--vce-link-hover)
     — tag pills, §11.1 —
     white on Dark Grey ............... 5.03:1   AA    (Housed in)
     Dark Blue on Light Grey ......... 12.68:1   AAA   (specializations)
     white on Maroon .................. 9.09:1   AAA   (only w/ show-all)

     ⚠ Teal, Yellow and Orange NEVER carry text on white (1.64 / 2.05 /
       2.87:1). Fills and accents only, always with Dark Blue on top.
     ⚠ Teal also fails as a NON-TEXT indicator on white (1.64:1 against the
       3:1 floor in 1.4.11). It works on Dark Green (5.31:1) and Dark Blue
       (9.23:1) only. Tab and accordion rails use Dark Green instead — see
       §12. Don't swap them to teal to match the nav bar.
============================================================================ */


/* ══ §1  TYPEFACE ══════════════════════════════════════════════════════════
   Self-hosted: no third-party request, no CSP argument, and @font-face is
   legal anywhere in a file (an @import must be line 1, which it won't be).

   Files from https://fonts.google.com/specimen/Epilogue — rename to strip
   the brackets, drop in your local_assets fonts folder, fix the paths.

   Prefer Google's CDN? Delete both blocks and put this on LINE 1:
   @import url('https://fonts.googleapis.com/css2?family=Epilogue:ital,wght@0,400;0,500;0,800;1,400&display=swap');
========================================================================== */

@font-face {
  font-family: "Epilogue";
  src: url("/local_assets/www.ext.vt.edu/fonts/Epilogue-Variable.woff2") format("woff2-variations"),
       url("/local_assets/www.ext.vt.edu/fonts/Epilogue-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Epilogue";
  src: url("/local_assets/www.ext.vt.edu/fonts/Epilogue-Italic-Variable.woff2") format("woff2-variations"),
       url("/local_assets/www.ext.vt.edu/fonts/Epilogue-Italic-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}


/* ══ §2  TOKENS ════════════════════════════════════════════════════════════
   Reskin a site by redefining tokens (§18), never the declarations.
========================================================================== */

:root {
  /* Primary backgrounds — guide p.39 */
  --vce-maroon:        #8b1843;
  --vce-green:         #005267;
  --vce-grey-dark:     #4c748b;

  /* Secondary backgrounds */
  --vce-teal:          #51ded6;
  --vce-yellow:        #ff9f2b;
  --vce-blue-dark:     #072938;
  --vce-orange:        #fe6a29;

  /* Tertiary */
  --vce-grey-light:    #e3ebfb;
  --vce-white:         #ffffff;

  /* Pattern shades — p.41. Tone-on-tone only, never standalone. */
  --vce-maroon-shade:  #6b0030;
  --vce-green-shade:   #00445c;
  --vce-grey-shade:    #3e6982;
  --vce-teal-shade:    #15cec8;
  --vce-yellow-shade:  #ff8900;

  /* ---- Semantic assignments ---- */
  --vce-ink:              var(--vce-blue-dark);   /* body copy. never #000 */
  --vce-ink-muted:        #3e5b6b;                /* 7.21:1 on white */

  /* Headings. Guide p.36 says type is always Dark Blue — this is a
     deliberate departure to Dark Green for hierarchy. 8.74:1 on white,
     7.30:1 on Light Grey. Set to var(--vce-ink) to go back to the guide. */
  --vce-heading:          var(--vce-green);

  --vce-page-bg:          var(--vce-white);
  --vce-surface:          var(--vce-grey-light);
  --vce-rule:             #c3d2ea;                /* decorative dividers */
  --vce-rule-strong:      var(--vce-grey-dark);   /* 5.03:1 — interactive */

  --vce-link:             var(--vce-maroon);       /*  9.09:1 on white */

  /* ⚠ NOT Orange. Orange on white is 2.87:1, and 1.4.3 wants 4.5:1 for
     body text — a hover state that makes links harder to read is a
     regression, not a style choice. Maroon shade darkens on hover instead,
     which is the same gesture at 12.59:1. See §18 to override. */
  --vce-link-hover:       var(--vce-maroon-shade);  /* 12.59:1 on white */
  --vce-link-visited:     var(--vce-maroon-shade);

  --vce-brand:            var(--vce-maroon);      /* primary actions */
  --vce-brand-hover:      var(--vce-maroon-shade);
  --vce-brand-ink:        var(--vce-white);

  --vce-brand-2:          var(--vce-green);       /* wayfinding chrome */
  --vce-brand-2-hover:    var(--vce-green-shade);
  --vce-brand-2-ink:      var(--vce-white);

  --vce-accent:           var(--vce-teal);        /* rules, marks, hovers */
  --vce-accent-ink:       var(--vce-blue-dark);

  --vce-focus:            var(--vce-blue-dark);
  --vce-focus-halo:       var(--vce-white);

  /* Ground for every dark surface in §6. One value, one place. */
  --vce-dark-bg:          var(--vce-blue-dark);
  --vce-dark-ink:         var(--vce-white);
  --vce-dark-ink-muted:   var(--vce-grey-light);  /* 12.68:1 on Dark Blue */
  --vce-dark-link-hover:  var(--vce-teal);        /*  9.23:1 on Dark Blue */

  /* The page-title band. vt-one ships this near-black. */
  --vce-pageinfo-bg:      var(--vce-blue-dark);

  /* About panel — see §15 */
  --about-panel-w:        70vw;

  /* Type */
  --vce-font: "Epilogue", Arial, Helvetica, sans-serif;   /* Arial = p.35 */
  --vce-wt-display: 800;   /* ExtraBold — headlines, subheads, numerals */
  --vce-wt-label:   500;   /* Medium — lozenges, eyebrows, buttons, nav */
  --vce-wt-body:    400;   /* Regular */
  --vce-track-tight: -0.005em;   /* InDesign tracking -5  */
  --vce-track-label: -0.01em;    /* InDesign tracking -10 */

  /* Lozenges are fully rounded, panels are square */
  --vce-radius-pill: 999px;
  --vce-radius-flat: 0;

  /* ---- Stacking ladder ----
     Every z-index this file sets comes from here. Spaced by hundreds so a
     new layer can slot in between without renumbering the rest.

     ⚠ z-index only compares within one stacking context. transform,
     opacity < 1, filter, isolation and any positioned element with its own
     z-index all start a new one, and inside it the numbers restart from
     zero. The ladder describes intent; it cannot force two elements in
     different contexts onto the same line. If a layer won't obey its tier,
     look for a stacking context between it and the page before reaching
     for a bigger number.

     IN USE:    decor, content.
     RESERVED:  sticky, dropdown, overlay, modal. vt-one sets its own
                z-indexes on its drawer, search panel and droplists, and
                this file deliberately doesn't override them — taking
                ownership of those risks fighting vt-one's own JS. The tiers
                are declared so the ladder reads complete, and so the next
                layer we DO own has an obvious slot. */
  --z-decor:       1;   /* swooshes, rules, background art. never interactive */
  --z-content:   100;   /* sidebars and cards that must sit over decoration */
  --z-sticky:    200;   /* reserved — sticky headers, pinned nav */
  --z-dropdown:  300;   /* reserved — menus, droplists */
  --z-overlay:   400;   /* reserved — drawers, search panels */
  --z-modal:     500;   /* reserved — dialogs */
}


/* ══ §3  BASE TYPOGRAPHY ═══════════════════════════════════════════════════
   ⚠ The blanket `html body { color: … !important }` in §3.2 reaches anything
   in vt-one that relied on inheriting white from a dark parent. That is why
   §6 exists and why it must stay after this section.
========================================================================== */

/* §3.1  Epilogue everywhere --------------------------------------------- */
/* vt-one sets Acherus on far more selectors than are practical to list, and
   every one we miss shows up as a visual bug. So this inverts the default:
   everything is Epilogue, and the two carve-outs below opt back out.

   Both carve-outs outrank the blanket on specificity — the universal
   selector contributes nothing, so `html body *` is (0,0,2) against
   (0,0,3) for `html body code` and (0,1,2) for the icon classes. They win
   regardless of source order.

   ⚠ If Epilogue isn't rendering at all, this isn't the cause. Check
   `document.fonts.check('16px Epilogue')` first — Google Fonts ships
   Epilogue as a variable TTF, and §1 expects .woff2. Rename without
   converting and the browser rejects the file and silently falls back. */

html body,
html body *,
html body *::before,
html body *::after {
  font-family: var(--vce-font) !important;
}

/* Icon fonts keep their own family or the glyphs render as tofu. The icons
   are inline SVG today (svg-inline--fa), so this is insurance — but the
   markup still carries commented-out <span class="far fa-times"> fallbacks,
   and if that JS ever fails to run this is what stops a page of squares. */
html body .fa,  html body .fas, html body .far,
html body .fal, html body .fab, html body .fad,
html body [class^="fa-"], html body [class*=" fa-"],
html body .fa::before,  html body .fas::before, html body .far::before,
html body .fal::before, html body .fab::before,
html body [class^="fa-"]::before, html body [class*=" fa-"]::before {
  font-family: "Font Awesome 6 Pro", "Font Awesome 6 Free",
               "Font Awesome 6 Brands", "Font Awesome 5 Pro",
               "Font Awesome 5 Free", "Font Awesome 5 Brands",
               FontAwesome !important;
}

/* Epilogue has no fixed-width alignment, so code keeps a monospace face. */
html body code, html body pre, html body kbd, html body samp {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               monospace !important;
}


/* §3.2  Base copy -------------------------------------------------------- */

html body,
html body .vt-text,
html body .vt-text p,
html body .vt-text li,
html body .vt-text td,
html body .vt-text th,
html body .vt-list,
html body .vt-vtcontainer,
html body .vt-multicolumn,
html body .vt-col {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-body) !important;
  letter-spacing: var(--vce-track-tight);
  color: var(--vce-ink) !important;
}

html body .vt-text p,
html body .vt-text li { line-height: 1.6; }

/* Guide p.36: headlines, subheads and numerals are ExtraBold, sentence
   case, tracking -5. */
html body h1, html body h2, html body h3,
html body h4, html body h5, html body h6,
html body .vt-page-title,
html body .vt-callToAction-primary,
html body .vt-widget-heading,
html body .vt-c-card-title,
html body .vt-list-item-title,
html body .vt-list-item-heading-text,
html body .vt-accordion-title,
html body .vt-bio-name,
html body .vt-tagcloud-heading {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-display) !important;
  letter-spacing: var(--vce-track-tight) !important;
  color: var(--vce-heading) !important;
  text-transform: none !important;
  line-height: 1.12;
  text-wrap: balance;
}

html body h2 { line-height: 1.15; }
html body h3, html body h4 { line-height: 1.25; }

/* Lozenges, eyebrows, nav, buttons: Medium, tracking -10, sentence case. */
html body .vt-ctaLink,
html body .vt-breadcrumbs-link,
html body .vt-subnav-page-title,
html body .vt-subnav-droplist-item,
html body .vt-nav-toggleLabel,
html body .vt-search-toggleLabel,
html body .vt-currentSiteTitle-link,
html body .vt-footer-link,
html body .vt-see-more-link,
html body .vt-accordion-trigger,
html body .vt-tab,
html body .vce-lozenge {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
}

/* Numerals are ExtraBold — .vce-stat on a big figure in a rawhtml. */
html body .vce-stat {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-display) !important;
  letter-spacing: var(--vce-track-tight) !important;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--vce-ink) !important;
  line-height: 1;
}

html body strong, html body b { font-weight: 700 !important; }


/* §3.3  Bootstrap containers -------------------------------------------- */
/* vt-one puts font-size:1.125em / line-height:2 / Acherus / color:#000 on
   the Bootstrap containers. main#vt_main carries .container-fluid, so that
   was the inherited default for everything §3 doesn't name directly.

   ⚠ This is an INHERITED default, not a local change. Every element the
   rest of the theme doesn't explicitly colour now renders Dark Green —
   stray rawhtml text, third-party widgets, components not yet themed.
   8.74:1 on white either way, so it's a look question, not a contrast one.
   Prefer var(--vce-ink) here if you'd rather only kill the black.

   ⚠ Same specificity as the §6 dark-surface rules, (0,1,2) both. §6 wins
   only because it comes later in the file. Don't move §6 above §3. */

html body .container-fluid,
html body .container-lg,
html body .container-md,
html body .container-sm,
html body .container-xl {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-body) !important;
  font-size: 1rem;
  line-height: 1.6;
  letter-spacing: var(--vce-track-tight);
  color: var(--vce-brand-2) !important;
}


/* ══ §4  LINKS ═════════════════════════════════════════════════════════════
   vt-one ships #c64600 (4.91:1 — passing). Dark Green is 8.74:1 and on
   palette. Underlines stay: WCAG 1.4.1, colour is never the only signal.

   ⚠ These are scoped to content wrappers on purpose, so they can't reach
   the dark surfaces in §6. Widen any of them to a bare `html body a` and
   the drawer, search panel and page-title band all break again.
========================================================================== */

html body .vt-text a,
html body .vt-vtcontainer-content a,
html body .vt-list-item-title-link,
html body .vt-image-caption a {
  color: var(--vce-link) !important;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-skip-ink: auto;
}

html body .vt-text a:hover,
html body .vt-vtcontainer-content a:hover,
html body .vt-list-item-title-link:hover {
  color: var(--vce-link-hover) !important;
  text-decoration-thickness: 2px;
}

html body .vt-text a:visited { color: var(--vce-link-visited) !important; }


/* ══ §5  LIGHT CHROME — header row and page ground ═════════════════════════
   Only surfaces that genuinely sit on white. Anything dark is §6, which
   follows this section and outranks it on specificity.
========================================================================== */

/* §5.1  Page ground ------------------------------------------------------ */
/* vt-one tints the content area on some templates; this forces white so the
   cards, panels and the Light Grey about panel all read against a known
   ground rather than an inherited one. Same reasoning as §6 — set both
   halves of the pair, don't inherit one of them. */

html body .vt-home.rightcol #vt_main,
html body #vt_one_content_area {
  background-color: var(--vce-page-bg) !important;
}

/* The home-page content well and the right column, including its briefs.
   `background` shorthand rather than background-color on purpose — it also
   clears any background-image vt-one sets on these, which the longhand in
   the rule above would leave in place. Kept separate for that reason.
   (#vt_right_col's stacking lives in §15.3.) */
html body .home-content,
html body #vt_right_col,
html body #vt_right_col .vt-nav-briefs,
html body #vt_right_col .nav-briefs {
  background: var(--vce-page-bg) !important;
}

/* vt-one pads the top of the content area; the hero or page-title band
   already provides that separation, so it read as a double gap. */
html body #vt_one_content_area {
  padding-top: 0 !important;
}

/* §5.2  The header row --------------------------------------------------- */

html body .vt-one-headerRow {
  background: var(--vce-page-bg) !important;
  border-bottom: 3px solid var(--vce-accent) !important;
}

html body .vt-logo-text,
html body .vt-currentSiteTitle-link {
  color: var(--vce-brand-2) !important;
  text-transform: none !important;
}

html body .vt-currentSiteTitle-link:hover {
  color: var(--vce-brand-2-hover) !important;
}

html body .vt-nav-toggleLabel,
html body .vt-search-toggleLabel,
html body .vt-nav-toggle,
html body .vt-search-toggle {
  color: var(--vce-ink) !important;
  text-transform: none !important;
}


/* ══ §6  DARK SURFACES ═════════════════════════════════════════════════════
   Every dark ground in the theme, in one place, because scattering them is
   exactly how the page-title band got missed in v1.

   THE SURFACES
     #vt_offcanvas_nav ............ the off-canvas drawer
     .vt-header-search-wrapper .... the search overlay
     .vt-page-info ................ the page-title band
     .vt-one-preHeader ............ the university bar (§6.6)
     footer ....................... the university footer — ⚠ §6.1, §6.7
     .vce-panel-dark .............. opt-in content panel
     .vce-hero-dark ............... opt-in hero variant
     .vce-on-dark ................. escape hatch for anything else

   WHY BOTH GROUND AND INK
     Setting only the text colour means guessing at a vt-one background we
     can't see. Setting both makes the contrast pair known. Dark Blue is on
     brand — the guide is explicit that nothing is black.

   ⚠ Every one of these rules is ancestor-scoped, which puts it above the
   base rules in §3, §4 and §5 on specificity. That is what makes the
   :not() guards in v1 unnecessary. Keep this section AFTER §5.

   ADDING A NEW DARK SURFACE
     Add its selector to the ground (§6.1), ink (§6.2), hover (§6.3) and
     focus (§6.4) groups. Miss one and you get the 1.45:1 bug again.
========================================================================== */

/* §6.1  Grounds ---------------------------------------------------------- */

/* ⚠ footer.footer-content MATCHES NOTHING. It requires <footer
   class="footer-content">; vt-one renders <footer> containing
   <div class="footer-content">. Confirm in one line:
     document.querySelectorAll('footer.footer-content').length   // 0 today
   Left as written because the effect — vt-one's own footer ground, not
   ours — may well be what you wanted. But it is dead code, and §6.2 still
   forces white ink onto the footer, so if any part of that footer is light
   you get white on white. Pick one:
     • delete the selector, and check the footer briefs area is dark
     • `html body footer,` to darken the whole element (the v2.2 behaviour)
     • `html body footer .footer-content,` to darken just the briefs band */

html body #vt_offcanvas_nav,
html body .vt-header-search-wrapper,
html body .vt-search-wrapper,
html body footer.footer-content,
html body .vce-on-dark {
  background: var(--vce-dark-bg) !important;
}

/* The page-title band. vt-one ships it near-black; Dark Green heading on
   that measured 1.45:1, which is the "Local offices" bug. */
html body .vt-page-info {
  background: var(--vce-pageinfo-bg) !important;
}

/* Moved here from §7 so every .vt-page-info rule sits together. */
html body .vt-page-info.row { padding-top: 2em !important; }

html body .vt-vtcontainer.vce-panel-dark {
  background: var(--vce-brand-2) !important;   /* Dark Green, 8.74:1 */
  padding: 2rem;
}

html body .vce-hero-dark .vt-callToAction-message {
  background: var(--vce-brand-2) !important;
  border-top-color: var(--vce-accent) !important;
}

/* Child panels carrying their own fill are flattened so the ground stays
   uniform — the drawer has at least one black band of its own. */
html body #vt_offcanvas_nav > *,
html body #vt_offcanvas_nav .vt-parent-org,
html body #vt_offcanvas_nav #vt_main_nav,
html body #vt_offcanvas_nav .submenu,
html body #vt_offcanvas_nav .nav-item,
html body #vt_offcanvas_nav .link-wrapper,
html body #vt_offcanvas_nav .vt-common-wrapper,
html body #vt_offcanvas_nav .vt-actions-nav,
html body #vt_offcanvas_nav .vt-shop-options,
html body #vt_offcanvas_nav .vt-resources-options,
html body #vt_offcanvas_nav .vt-nav-shop-wrapper,
html body #vt_offcanvas_nav .vt-nav-resources-wrapper {
  background: transparent !important;
}

/* §6.2  Ink -------------------------------------------------------------- */
/* Named explicitly because the blanket colour rule in §3 reaches all of
   these by inheritance. */

html body #vt_offcanvas_nav,
html body #vt_offcanvas_nav a,
html body #vt_offcanvas_nav a:visited,
html body #vt_offcanvas_nav button,
html body #vt_offcanvas_nav span,
html body #vt_offcanvas_nav .vt-currentSiteTitle-link,
html body #vt_offcanvas_nav .vt-common-link,
html body #vt_offcanvas_nav .vt-shop-item-link,
html body #vt_offcanvas_nav .vt-shop-title,
html body #vt_offcanvas_nav .vt-nav-shop-title,
html body #vt_offcanvas_nav .vt-resources-item-link,
html body #vt_offcanvas_nav .vt-nav-resources-title,
html body #vt_offcanvas_nav .fold-icon,

html body .vt-header-search-wrapper a,
html body .vt-header-search-wrapper button,
html body .vt-header-search-wrapper label,
html body .vt-header-search-wrapper legend,
html body .vt-header-search-wrapper span,
html body .vt-search-wrapper a,
html body .vt-search-wrapper label,
html body .vt-search-wrapper span,
html body .vt-frequent-searches-link,
html body .vt-frequent-searches-label,
html body .vt-site-search-label-text,
html body .vt-search-options-label,
html body .vt-search-options-legend,

html body .vt-page-info,
html body .vt-page-info .vt-page-title,
html body .vt-page-info h1,
html body .vt-page-info p,

html body .vt-footer-link,
html body .vt-footer-link:visited,
html body .footer-info-link,
html body .vt-copyright,
html body .vt-social-follow-link,

/* The authored footer-briefs parsys. It used to sit on white, so §3's ink
   was fine; now that <footer> itself is dark it would be 1.0:1 body copy
   and 1.74:1 headings. */
html body .vt-footer-inPage-items,
html body .vt-footer-inPage-items p,
html body .vt-footer-inPage-items li,
html body .vt-footer-inPage-items h2,
html body .vt-footer-inPage-items h3,
html body .footer-content .vt-text,
html body .footer-content .vt-text p,
html body .footer-content .vt-text h2,
html body .footer-content .vt-text h3,

html body .vt-vtcontainer.vce-panel-dark,
html body .vt-vtcontainer.vce-panel-dark h2,
html body .vt-vtcontainer.vce-panel-dark h3,
html body .vt-vtcontainer.vce-panel-dark p,
html body .vce-hero-dark .vt-callToAction-primary,
html body .vce-hero-dark .vt-callToAction-message p,

html body .vce-on-dark,
html body .vce-on-dark h1,
html body .vce-on-dark h2,
html body .vce-on-dark h3,
html body .vce-on-dark p {
  color: var(--vce-dark-ink) !important;
}

/* Bio and tag-cloud headings. These sit on dark grounds vt-one supplies;
   I don't have their container markup, so they're named directly rather
   than scoped. If you ever get me that markup they can fold into the
   ancestor lists above. */
html body h1.vt-bio-name,
html body h2.vt-tagcloud-heading {
  color: var(--vce-dark-ink) !important;
}

/* Subordinate copy — still 12.68:1, just visibly quieter. */
html body #vt_offcanvas_nav .vt-shop-description,
html body #vt_offcanvas_nav .vt-parentOrgTitle {
  color: var(--vce-dark-ink-muted) !important;
}

/* §6.3  Hover ------------------------------------------------------------ */

html body #vt_offcanvas_nav a:hover,
html body #vt_offcanvas_nav .vt-currentSiteTitle-link:hover,
html body #vt_offcanvas_nav .vt-common-link:hover,
html body #vt_offcanvas_nav .vt-shop-item-link:hover,
html body #vt_offcanvas_nav .vt-resources-item-link:hover,
html body #vt_offcanvas_nav .fold-icon:hover,
html body .vt-header-search-wrapper a:hover,
html body .vt-search-wrapper a:hover,
html body .vt-frequent-searches-link:hover,
html body .vt-footer-link:hover,
html body .footer-info-link:hover,
html body .vt-social-follow-link:hover,
html body .vt-footer-inPage-items a:hover,
html body .footer-content .vt-text a:hover,
html body .vce-on-dark a:hover {
  color: var(--vce-dark-link-hover) !important;
  text-decoration: underline;
}

/* Links inside dark content panels need to read as links from the start.
   ⚠ White here is the same colour as the body text beside it, so colour
   alone no longer marks a link — 1.4.1. The underline is what carries it
   instead, and it is not optional while the colour matches. Switch back to
   var(--vce-teal) (9.23:1) and the underline becomes a style choice. */
html body .vt-vtcontainer.vce-panel-dark a,
html body .vt-footer-inPage-items a,
html body .footer-content .vt-text a,
html body .vce-on-dark a {
  color: var(--vce-white) !important;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* §6.4  Focus ------------------------------------------------------------ */
/* The §16 ring is Dark Blue, which vanishes on these grounds. Flip it. */

html body #vt_offcanvas_nav a:focus-visible,
html body #vt_offcanvas_nav button:focus-visible,
html body .vt-header-search-wrapper a:focus-visible,
html body .vt-header-search-wrapper button:focus-visible,
html body .vt-search-wrapper a:focus-visible,
html body .vt-page-info a:focus-visible,
html body footer a:focus-visible,
html body .vt-page-path a:focus-visible,
html body .vce-panel-dark a:focus-visible,
html body .vce-hero-dark a:focus-visible,
html body .vce-on-dark a:focus-visible {
  outline: 3px solid var(--vce-white) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 6px var(--vce-blue-dark) !important;
}

/* §6.5  Exceptions ------------------------------------------------------- */
/* The search input is a light field sitting on the dark panel. */

html body .vt-header-search-q,
html body input.vt-header-search-q {
  background: var(--vce-white) !important;
  color: var(--vce-ink) !important;
}

/* The fold-icon chevrons use fill="currentColor", so they follow §6.2. */
html body #vt_offcanvas_nav .fold-icon {
  background: transparent !important;
  border-color: var(--vce-white) !important;
}

/* Drawer typography */
html body #vt_offcanvas_nav a,
html body #vt_offcanvas_nav .vt-parentOrgTitle,
html body #vt_offcanvas_nav .vt-nav-shop-title,
html body #vt_offcanvas_nav .vt-nav-resources-title {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
}

html body .vt-footer-link,
html body .footer-info-link,
html body .vt-copyright {
  font-family: var(--vce-font) !important;
  letter-spacing: var(--vce-track-label);
}

/* §6.6  University pre-header ------------------------------------------- */
/* ⚠ THIS REVERSES A DOCUMENTED DECISION. Through v2.2 the file header listed
   the pre-header and VT wordmark as deliberately untouched — university
   brand, not ours. That bar is VT's identity strip and Chicago Maroon is
   VT's colour, so repainting it VCE Dark Green is a call for whoever owns
   brand compliance, not a CSS question. Worth asking before this reaches
   the offices; it's a one-line revert if the answer is no.

   Ground AND ink together, per the rule at the top of §6. White on Dark
   Green is 8.74:1; --vce-ink leaking in from §3 would be 1.74:1.

   ⚠ Check the VT wordmark. If its SVG carries a hard-coded fill rather than
   currentColor, the `fill: currentColor` below will not reach it and it may
   still be rendering in maroon or have gone invisible. */

html body .vt-one-preHeader { background: var(--vce-brand-2) !important; }

html body .vt-one-preHeader,
html body .vt-one-preHeader a,
html body .vt-one-preHeader a:visited,
html body .vt-one-preHeader button,
html body .vt-one-preHeader span,
html body .vt-one-preHeader svg {
  color: var(--vce-white) !important;
  fill: currentColor;
}

html body .vt-one-preHeader a:hover,
html body .vt-one-preHeader button:hover {
  color: var(--vce-teal) !important;   /* 5.31:1 on Dark Green */
}

html body .vt-one-preHeader a:focus-visible,
html body .vt-one-preHeader button:focus-visible {
  outline: 3px solid var(--vce-white) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 6px var(--vce-blue-dark) !important;
}

/* Apply / Visit / Give / Shop. Hidden here only — the same links stay in
   the off-canvas drawer (.vt-actions-nav), so nothing becomes unreachable.
   Verify that in the drawer before shipping; if they're gone from both,
   this removes university functionality rather than tidying it. */
html body .vt-actions-header { display: none !important; }

html body .vt-wordMark-text { text-transform: none !important; }

/* §6.7  University footer ------------------------------------------------ */
/* ⚠⚠ THIS IS THE ONE CHANGE IN THE FILE THAT NEEDS SIGN-OFF BEFORE IT SHIPS.
   §6.6 recolours university chrome; this REMOVES it. The hidden row carries
   twelve links and the copyright line, including:

     Accessibility · Privacy Statement · Equal Opportunity ·
     Consumer Information · Policies

   On a VT web property those are very likely policy-required, and the
   Accessibility link is the one with the most weight: it is how a visitor
   reaches the university's accessibility statement and barrier-reporting
   route, which Title II compliance leans on. Removing it from 107 sites is
   a compliance question, not a styling one. Confirm with whoever owns
   university web policy — a one-line revert if the answer is no.

   What survives: the office's own footer-briefs parsys, which lives in the
   first footer .row and doesn't contain .vt-footer-row.

   A middle path, if the problem is visual weight rather than the links: hide
   the map, logo and social icons, keep the link list and copyright. Send me
   the footer markup and I'll target just those.

   While this rule is on, several rules elsewhere are inert rather than
   wrong — the footer-link ink in §6.2, its hover in §6.3, the footer
   typography in §6.5, the footer rows in §17 print, and the black-footer
   override in §18. Left in place deliberately: this rule is the one most
   likely to be reverted, and when it is, they need to still be there. */

html body footer .row:has(.vt-footer-row) {
  display: none !important;
}

/* The briefs band is now the last thing in the footer, so its bottom margin
   was leaving a gap before the page edge. */
html body footer .row .footer-content {
  margin-bottom: 0 !important;
}


/* ══ §7  BREADCRUMBS + SECTION NAV ═════════════════════════════════════════
   Was a #861f41 bar directly under the university's #861f41 bar. Dark Green
   separates the two and reads unmistakably VCE.
========================================================================== */

html body .vt-page-path,
html body .vt-page-path .gateway {
  background: var(--vce-brand-2) !important;
}

html body .vt-breadcrumbs-link,
html body .vt-breadcrumbs-link:visited,
html body .breadcrumb-slash {
  color: var(--vce-brand-2-ink) !important;
  text-decoration: none;
}

html body .vt-breadcrumbs-link:hover {
  color: var(--vce-accent) !important;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

html body .vt-subnav {
  background: var(--vce-surface) !important;
  border-bottom: 1px solid var(--vce-rule) !important;
}

html body .vt-subnav-droplist-control,
html body .vt-subnav-page-title {
  color: var(--vce-ink) !important;
  background: transparent !important;
  text-transform: none !important;
}

html body .vt-subnav-droplist {
  background: var(--vce-surface) !important;
  border-color: var(--vce-rule) !important;
  margin-bottom: 0 !important;
}

html body a.vt-subnav-droplist-item,
html body .vt-subnav-droplist-item > a {
  color: var(--vce-ink) !important;
  text-decoration: none;
}

html body a.vt-subnav-droplist-item:hover {
  color: var(--vce-link) !important;
  background: var(--vce-white) !important;
  box-shadow: inset 4px 0 0 var(--vce-accent);
  text-decoration: underline;
}

html body .vt-subnav-droplist-toggle-symbol { color: var(--vce-brand-2) !important; }


/* ══ §8  HERO / CALL TO ACTION ═════════════════════════════════════════════
   Popover was #e5e1e6 Hokie Stone → Light Grey. Dark Blue on it is 12.68:1.
   The .vce-hero-dark variant lives in §6 with the other dark grounds.
========================================================================== */

html body .vt-callToAction-message,
html body .vt-callToAction-message.light {
  background: var(--vce-surface) !important;
  border-radius: var(--vce-radius-flat) !important;
  border-top: 6px solid var(--vce-brand) !important;
}

html body .vt-callToAction-primary,
html body .vt-callToAction-message-heading h1,
html body .vt-callToAction-message-heading h2,
html body .vt-callToAction-message-heading h3,
html body .vt-callToAction-message p {
  color: var(--vce-ink) !important;
}

/* Popover variant — the panel sitting over the hero image.
   ⚠ 5em top and bottom is a lot of margin on a phone. If the hero has a
   fixed height, a tall message plus 10em of margin can push the panel past
   the image's bottom edge — worth checking under ~400px. */
html body .vt-callToAction-popover .vt-callToAction-message {
  padding: 2em !important;
  margin: 5em 5% !important;
}

/* The popover's button — roomier than the §9 default, sized to its label
   rather than stretched across the panel.
   The !important is genuinely needed: the hero button carries .light,
   .acherus and .uppercase, so it matches §9's modifier selectors at
   (0,2,3), which beats this rule's (0,2,2). Drop the !important and §9's
   padding quietly wins. */
html body .vt-callToAction-popover .vt-ctaLink {
  padding: 0.75rem 2rem !important;
  margin-bottom: 0 !important;
  width: fit-content !important;
}


/* ── §8.1  HERO SWOOSH PANEL ───────────────────────────────────────────────
   Replaces the popover's Light Grey box with a brand-coloured panel whose
   right edge is the swoosh, over a full-bleed photo.

   ── THE CURVE ────────────────────────────────────────────────────────────
   The same path as the swoosh cards, filled on the LEFT instead of the
   right. You asked for it vertically inverted; the guide curve turns out to
   be point-symmetric (checked at 19 samples, max deviation 0.011), so
   flipping it vertically and mirroring it to put the fill on the left lands
   back on exactly the same path. Only the filled side changes.

   The panel is built from two pseudo-elements: ::before is the solid fill,
   ::after is the curve, sitting immediately to its right at left:100%.
   The solid block sizes to its own content; the curve is a fixed width.
   (v3.3 baked the split into the mask's viewBox; v3.4 made it a percentage
   OF THE PANEL, so widening the panel widened the curve; v3.5 split it into
   two vw tokens. v3.6 drops the solid width entirely — the content sets
   it.)

   ⚠ Your mockup's curve is NOT this one — it stays flat longer at the top
     and crosses the midpoint at 76% rather than 50%. p.51 forbids redrawing
     the swoosh, so this is the guide path. Side by side the difference is
     slight; if the mockup's shape was deliberate, say so and we'll talk
     about what it's worth.

   ── COLOUR ───────────────────────────────────────────────────────────────
   Your mockup samples #508590, which isn't in the VCE palette. White on it
   is 4.12:1 — under the 4.5:1 floor for normal text, so the heading passes
   (it's large) but nothing else would, and the maroon button's edge against
   it is 2.21:1.

   Default here is Dark Grey #4c748b: white at 5.03:1, closest palette match
   to the mockup. --hero-panel takes Dark Green (8.74:1) or Dark Blue
   (15.18:1) if you want more headroom.

   ⚠ THE BUTTON NEEDS ITS WHITE OUTLINE. Maroon on Dark Grey is 1.81:1 —
     the control's own boundary is invisible against the panel, which is
     1.4.11. The white border below is what makes it a visible control, not
     decoration. It is not optional on any panel colour in the palette:
     maroon scores 1.04–1.81 against all three.
-------------------------------------------------------------------------- */

html body .vt-callToAction-popover {
  --hero-panel:  var(--vce-grey-dark);
  --hero-ink:    var(--vce-white);
  /* The solid block sizes itself to its own content — the heading, or the
     button if that's wider — and the curve is a fixed width sitting just
     past it. Neither can move the other.

     --hero-solid-max  a ceiling, not a width. A long county name wraps at
                       this rather than eating the hero. "Accomack County"
                       lands nowhere near it; "Northumberland County" at a
                       narrow viewport is the case it exists for.
     --hero-curve-w    fixed, so the curve is the same thickness on every
                       page regardless of how long the name is.

     ⚠ The curve stretches to fill its box, so its proportions are
     --hero-curve-w : hero height. A fixed width means a taller hero makes
     it steeper, never flatter, so it can't breach the 16:9 limit in p.51
     by growing — only by the hero becoming very short. At 12rem against a
     620px hero it is about 0.31:1. */
  --hero-solid-max: 60vw;
  --hero-curve-w:   12rem;
  --hero-min-h:  22rem;

  position: relative;
  overflow: hidden;
}

/* The photo becomes the full-bleed ground rather than a sibling block. */
html body .vt-callToAction-popover .vt-callToAction-supplement {
  position: absolute;
  inset: 0;
  margin: 0 !important;
  padding: 0 !important;
}

html body .vt-callToAction-popover .vt-callToAction-supplement .vt-objectFit,
html body .vt-callToAction-popover .vt-callToAction-supplement .vt-image,
html body .vt-callToAction-popover .vt-callToAction-supplement figure,
html body .vt-callToAction-popover .vt-callToAction-supplement picture {
  display: block;
  height: 100%;
  width: 100%;
  margin: 0 !important;
}

html body .vt-callToAction-popover .vt-callToAction-supplement img {
  width: 100% !important;
  height: 100% !important;
  max-height: none !important;
  object-fit: cover;
  display: block;
}

/* §8.1a  The panel ------------------------------------------------------- */

html body .vt-callToAction-popover .vt-callToAction-flexContainer-left {
  position: relative;
  z-index: var(--z-content);
  /* Shrink-to-fit. flex:0 0 auto stops the hero's flex container from
     stretching or squashing it; max-width is the wrap point. */
  flex: 0 0 auto;
  width: fit-content;
  max-width: var(--hero-solid-max);
  min-height: var(--hero-min-h);
  display: flex;
  align-items: center;
  margin: 0 !important;
  padding: 0 !important;
}

/* ::before is the solid block, filling the panel exactly. ::after is the
   curve, starting at left:100% — outside the panel, so it can't crowd the
   text and its width is independent of how long the heading is. Same
   arrangement as the about-section wedge in §15.

   Both use top/bottom rather than inset, so they follow whatever height the
   panel ends up with instead of imposing one. */

html body .vt-callToAction-popover .vt-callToAction-flexContainer-left::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;                       /* the panel IS the solid block now */
  z-index: -1;
  background: var(--hero-panel);
}

html body .vt-callToAction-popover .vt-callToAction-flexContainer-left::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 100%;                     /* starts where the solid block ends */
  width: var(--hero-curve-w);
  z-index: -1;
  background: var(--hero-panel);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 425 381.3' preserveAspectRatio='none'%3E%3Cpath d='M424.6 0C424.6 77.06 332.4 134.68 212.6 190.65C92.7 246.63 0 315 0 381.3L0 0Z' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 425 381.3' preserveAspectRatio='none'%3E%3Cpath d='M424.6 0C424.6 77.06 332.4 134.68 212.6 190.65C92.7 246.63 0 315 0 381.3L0 0Z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  pointer-events: none;
}

/* §8.1b  The message box loses its own box ------------------------------- */
/* §8 gives .vt-callToAction-message a Light Grey ground and a maroon top
   rail. Inside the popover the panel IS the ground, so both come off. */

html body .vt-callToAction-popover .vt-callToAction-message,
html body .vt-callToAction-popover .vt-callToAction-message.light,
html body .vt-callToAction-popover .vt-callToAction-message.maroon {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding: 2rem clamp(1.5rem, 4vw, 3.5rem) !important;
  margin: 0 !important;
}

html body .vt-callToAction-popover .vt-callToAction-message,
html body .vt-callToAction-popover .vt-callToAction-primary,
html body .vt-callToAction-popover .vt-callToAction-message-heading h1,
html body .vt-callToAction-popover .vt-callToAction-message-heading h2,
html body .vt-callToAction-popover .vt-callToAction-message-heading h3,
html body .vt-callToAction-popover .vt-callToAction-message p {
  color: var(--hero-ink) !important;
}

/* §8.1c  The button ------------------------------------------------------ */
/* See the warning at the top — the white border is load-bearing, not trim. */

html body .vt-callToAction-popover .vt-ctaLink,
html body .vt-callToAction-popover .vt-ctaLink.maroon {
  background: var(--vce-brand) !important;   /* white on it = 9.09:1 */
  color: var(--vce-brand-ink) !important;
  border: 2px solid var(--vce-white) !important;
  padding: 0.75rem 2rem !important;
  margin-bottom: 0 !important;
  width: fit-content !important;
}

html body .vt-callToAction-popover .vt-ctaLink:hover {
  background: var(--vce-brand-hover) !important;
  border-color: var(--vce-white) !important;
  color: var(--vce-brand-ink) !important;
}

html body .vt-callToAction-popover .vt-ctaLink:focus-visible {
  outline: 3px solid var(--vce-white) !important;
  outline-offset: 3px !important;
  box-shadow: 0 0 0 6px var(--vce-blue-dark) !important;
}

/* §8.1d  Narrow viewports ------------------------------------------------ */
/* Below this the panel would be too narrow to hold a county name, so it
   goes full width with the curve rotated flat along its bottom edge —
   the Stack configuration from p.50, same as §15.2. */

@media (max-width: 48rem) {
  html body .vt-callToAction-popover {
    --hero-min-h: 0;
    display: block !important;
  }
  html body .vt-callToAction-popover .vt-callToAction-supplement {
    position: relative;
    height: 42vw;
  }
  html body .vt-callToAction-popover .vt-callToAction-flexContainer-left {
    width: 100%;
    max-width: none;
    min-height: 0;
  }
  html body .vt-callToAction-popover .vt-callToAction-flexContainer-left::after {
    display: none;                /* no room for the curve down here */
  }
}

@supports not (mask-image: url("")) {
  /* No mask support: a square panel rather than a curved one. Legible,
     just not branded. */
  html body .vt-callToAction-popover .vt-callToAction-flexContainer-left::after {
    display: none;
  }
}

@media print {
  html body .vt-callToAction-popover .vt-callToAction-flexContainer-left::before,
  html body .vt-callToAction-popover .vt-callToAction-flexContainer-left::after {
    display: none;
  }
  html body .vt-callToAction-popover .vt-callToAction-message,
  html body .vt-callToAction-popover .vt-callToAction-primary {
    color: #000 !important;
  }
}


/* ══ §9  BUTTONS & CTA LINKS ═══════════════════════════════════════════════
   Guide p.36 sets lozenges in sentence case, so .uppercase is neutralised.
   Want the shouty version back? Delete the text-transform line.
========================================================================== */

html body a.vt-ctaLink,
html body a.vt-ctaLink.light,
html body a.vt-ctaLink.acherus,
html body a.vt-ctaLink.uppercase {
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  text-transform: none !important;
  text-decoration: none !important;
  background: var(--vce-brand) !important;
  color: var(--vce-brand-ink) !important;
  border: 2px solid var(--vce-brand) !important;
  border-radius: var(--vce-radius-pill) !important;
  padding: 0.6em 1.5em;
  line-height: 1.3;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

html body a.vt-ctaLink:hover,
html body a.vt-ctaLink.light:hover {
  background: var(--vce-brand-hover) !important;
  border-color: var(--vce-brand-hover) !important;
  color: var(--vce-brand-ink) !important;
}

/* Office quick links. Light Grey ground, Dark Blue type (12.68:1), Teal on
   hover — the fill moves too, so it isn't colour-only signalling. */
html body a.vt-ctaLink.ext-top-cta {
  background: var(--vce-surface) !important;
  color: var(--vce-ink) !important;
  border: 2px solid var(--vce-rule-strong) !important;   /* 5.03:1, 1.4.11 */
  border-radius: var(--vce-radius-pill) !important;
  font-weight: var(--vce-wt-label) !important;
}

html body a.vt-ctaLink.ext-top-cta:hover {
  background: var(--vce-accent) !important;
  border-color: var(--vce-accent-ink) !important;
  color: var(--vce-accent-ink) !important;
}

/* Secondary/ghost — .vce-btn-ghost alongside .vt-ctaLink */
html body a.vt-ctaLink.vce-btn-ghost {
  background: transparent !important;
  color: var(--vce-brand-2) !important;
  border-color: var(--vce-brand-2) !important;
}
html body a.vt-ctaLink.vce-btn-ghost:hover {
  background: var(--vce-brand-2) !important;
  color: var(--vce-brand-2-ink) !important;
}

html body .vt-see-more-link,
html body .vt-refinement-btn {
  color: var(--vce-link) !important;
}


/* ══ §10  LOZENGES, EYEBROWS & UTILITIES ═══════════════════════════════════
   Guide p.36. Use in a rawhtml: <span class="vce-lozenge">…</span>
   Modifiers follow the p.40 pairing chart — those combinations only.
========================================================================== */

html body .vce-lozenge {
  display: inline-block;
  padding: 0.3em 1em;
  border-radius: var(--vce-radius-pill);
  background: var(--vce-brand) !important;
  color: var(--vce-white) !important;
  font-size: 0.8125rem;
  line-height: 1.4;
  text-transform: none !important;
}

html body .vce-lozenge--green  { background: var(--vce-green) !important;     color: var(--vce-white) !important; }
html body .vce-lozenge--blue   { background: var(--vce-blue-dark) !important; color: var(--vce-white) !important; }
html body .vce-lozenge--grey   { background: var(--vce-grey-dark) !important; color: var(--vce-white) !important; }
html body .vce-lozenge--teal   { background: var(--vce-teal) !important;      color: var(--vce-blue-dark) !important; }
html body .vce-lozenge--yellow { background: var(--vce-yellow) !important;    color: var(--vce-blue-dark) !important; }
html body .vce-lozenge--orange { background: var(--vce-orange) !important;    color: var(--vce-blue-dark) !important; }
html body .vce-lozenge--white  { background: var(--vce-white) !important;     color: var(--vce-blue-dark) !important; }

/* Hides an authored element outright — used for the office coordinates
   block that feeds the locality map but shouldn't render.
   ⚠ display:none removes it from the accessibility tree as well as the
   page. That's correct if it's machine-readable data for a script. If it
   is information a screen-reader user should still get, it wants the
   sr-only pattern instead (clip to 1px, keep it in the tree) — the two
   look identical on screen and are opposites to assistive tech. */
html body .vce-office-coords {
  display: none !important;
}

html body .vce-eyebrow {
  display: block;
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: 0.875rem;
  color: var(--vce-brand-2) !important;
  margin-bottom: 0.4em;
  text-transform: none !important;
}


/* ══ §11  LISTS, CARDS & CONTAINERS ════════════════════════════════════════ */

html body .vt-c-card-list .vt-list-item-wrapper {
  background: var(--vce-white) !important;
  border: 1px solid var(--vce-rule) !important;
  border-top: 4px solid var(--vce-brand-2) !important;
  border-radius: var(--vce-radius-flat) !important;
  transition: border-top-color .15s ease, box-shadow .15s ease;

  /* Column flex so §11.1a can pin the tag row to the card bottom and keep
     rows level across a grid where only some items carry tags.
     ⚠ This is the riskiest line in §11. The children are all block-level
     already so they should behave, but if a list layout goes strange, take
     these three out first and the auto margin in §11.1a second. */
  display: flex;
  flex-direction: column;
  height: 100%;
}

html body .vt-c-card-list .vt-list-item-wrapper:hover,
html body .vt-c-card-list .vt-list-item-wrapper:focus-within {
  border-top-color: var(--vce-accent) !important;
  box-shadow: 0 2px 10px rgba(7, 41, 56, 0.14);
}

html body .vt-c-card-title,
html body .vt-list-item-title-link { color: var(--vce-ink) !important; }

html body .vt-list-item-title-link:hover { color: var(--vce-link) !important; }

html body .vt-list-item-heading-text {
  color: var(--vce-brand-2) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  text-transform: none !important;
}

/* Bio cards read as portraits — guide p.44 wants the 50% Dark Grey tint. */
html body .vt-c-card-list li.bio-page .vt-list-item-imgWrapper {
  background: color-mix(in srgb, var(--vce-grey-dark) 50%, #fff) !important;
}

/* Portrait-crop list variant */
html body .ext-list-portrait .vt-list-item-imgWrapper .vt-list-item-img {
  height: fit-content !important;
  aspect-ratio: 3 / 4 !important;
  max-height: fit-content !important;
}

/* Horizontal-scroll lists. vt-one paints a gradient "there's more" cover
   over the right edge and offsets it; these pull it flush and take the
   Bootstrap gutter off the items so the scroll rhythm is even.
   You had the ::after rule twice, identically — deduplicated. */
html body .vt-list-horizontal-scroll.vt-list .vt-list-columns::after {
  right: 0 !important;
}

html body .vt-list-horizontal-scroll.vt-list .item {
  margin-left: 0 !important;
  margin-right: 0.75em !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* Staff list width cap.
   ⚠ This one is px, not rem, on purpose — 992px is Bootstrap's lg
   breakpoint and vt-one's grid switches there. Converting it to 62rem
   would drift apart from the grid if the root font-size is ever not 16px.
   The theme's own breakpoints (34/56/62rem) are content-driven and stay in
   rem; this one tracks somebody else's grid, so it stays in px. */
@media (min-width: 992px) {
  html body .ext-staff-list {
    max-width: 68vw;
  }
}


/* ── §11.1  TAG PILLS ───────────────────────────────────────────────────────
   Companion file: vce-tag-pills-disable.html (see §11.1f and §11.1g).

   WHAT RENDERS
     Two categories, and nothing else:

       Housed in <office>   :home-office/…   Dark Grey  #4c748b  white      5.03:1  AA
       <specialization>     :specialization/ Light Grey #e3ebfb  Dark Blue 12.68:1  AAA

     Every other tag is hidden (§11.1f) — the :offices/ tags a person is
     merely tagged into, and any topic tags. vce-tags-show-all on a list
     brings them all back as Maroon pills.

     The location tag only appears when it ISN'T this page's own office,
     which the JS companion handles. On Dinwiddie's staff page you see
     "Housed in Southampton" on the people based elsewhere and nothing on
     the ones based there — exactly when it carries information.

   ── THE GUESS IS GONE ────────────────────────────────────────────────────
     Through v2.12 the home office was INFERRED as "the last :offices/ tag",
     which was never verified and was load-bearing enough to put a wrong
     office on a person's card. The :home-office/ namespace states it
     outright, so that whole mechanism is deleted: no sibling-position
     selectors, no "verify this before shipping" warning, no way for tag
     order to change the meaning.

   ⚠ MIGRATION: this reads ONLY :home-office/. A person still carrying just
     the old :offices/ tags now shows no location tag at all — not a wrong
     one, but not a label either. Worth a query for people with a
     :specialization/ tag and no :home-office/ tag before calling it done.

   ── EVERY SELECTOR MATCHES TWO ATTRIBUTES, AND BOTH ARE REQUIRED ─────────
     The companion JS neutralises these links by removing href and parking
     the URL in data-vce-tag-href. That is the right accessibility fix — an
     <a> with no href is not focusable and exposes no link role — but it
     means href-only selectors stop matching the moment the JS runs, and
     every pill silently reverts to the default. So each one tests href
     (before the JS, and if the JS never loads) and data-vce-tag-href
     (after it). Both colon encodings too: AEM emits ":home-office/" today,
     but a URL-encoded "%3Ahome-office/" would fall through silently.

     If you ever rename data-vce-tag-href in the JS, rename it here too —
     nothing will error, the colours will just quietly stop applying.

   ⚠ THE "Housed in" PREFIX LIVES IN CSS, NOT THE DOM
     Generated content is announced by current Chrome, Safari and Firefox,
     but it can't be copied, searched or translated, and it vanishes if
     this stylesheet fails. Without it the pill reads as a bare county
     name with no indication of what the county means.
-------------------------------------------------------------------------- */

/* §11.1a  The row -------------------------------------------------------- */
/* margin-top:auto pins the tags to the bottom of the card so rows line up
   across a grid where some people have tags and some don't. Needs the
   wrapper to be a column flex container, which §11 above now sets on
   .vt-list-item-wrapper. Both halves are needed; see the note there. */

html body .vt-list-item-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.4rem;
  list-style: none !important;
  margin: auto 0 0 !important;      /* auto top margin = pin to card bottom */
  padding: 0.85rem 1rem 1rem !important;
  border-top: 1px solid var(--vce-rule);
}

/* role="listitem" is in the markup, so list semantics survive both the
   list-style removal and the flex container. Don't use display:contents —
   that drops the role in several engines. */
html body .vt-list-item-tags-tag {
  display: block;
  margin: 0 !important;
  padding: 0 !important;
  line-height: 1.3 !important;
}

/* §11.1b  Reading order -------------------------------------------------- */
/* Location first, specialisms after. Flex `order` moves boxes only; the DOM
   sequence a screen reader follows is unchanged, so this is visual grouping,
   not semantic. Fine here because the pills are a flat set with no inherent
   sequence — do NOT reach for this where order carries meaning. */

/* Spaced by tens, same reasoning as the z-index ladder in §2: a category
   added later can slot between two of these without renumbering the rest. */

html body .vt-list-item-tags-tag { order: 40; }  /* anything else, if shown */

html body .vt-list-item-tags-tag:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"], a[data-vce-tag-href*=":home-office/"], a[data-vce-tag-href*="%3Ahome-office/"]) {
  order: 10;                                                   /* housed in */
}

html body .vt-list-item-tags-tag:has(a[href*=":offices/"], a[href*="%3Aoffices/"], a[data-vce-tag-href*=":offices/"], a[data-vce-tag-href*="%3Aoffices/"]) {
  order: 20;                             /* other offices — bio cards only */
}

html body .vt-list-item-tags-tag:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"], a[data-vce-tag-href*=":specialization/"], a[data-vce-tag-href*="%3Aspecialization/"]) {
  order: 30;                                             /* specializations */
}

/* §11.1c  The pill ------------------------------------------------------- */
/* Maroon is the default. It only ever shows on a list carrying
   vce-tags-show-all, since everything uncategorised is hidden by §11.1g. */

html body .vt-list-item-tags .vt-list-item-tags-link {
  --pill-bg: var(--vce-maroon);
  --pill-ink: var(--vce-white);   /* categories may flip this — see §11.1e */

  display: inline-block;
  max-width: 100%;         /* never wider than the card */
  padding: 0.32em 0.85em;
  border-radius: var(--vce-radius-pill);

  /* Measured with the longest realistic label, "Housed in Northumberland"
     (~214px). In a 4-up grid it stays on one line down to about a 1100px
     container and wraps to two below that. A two-line pill with a fully
     round radius reads as a rounded rectangle, which is fine — but if you'd
     rather it never wrapped, white-space:nowrap here plus vce-nav--rail-
     style horizontal scrolling on the row is the trade. */

  background: var(--pill-bg) !important;
  color: var(--pill-ink) !important;

  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-body) !important;          /* Regular: prefix */
  letter-spacing: var(--vce-track-label) !important;   /* tracking -10 */
  font-size: 0.8125rem;
  line-height: 1.4;
  text-decoration: none !important;

  /* Not a link any more — see §11.1h for why the JS companion is required. */
  pointer-events: none;
  cursor: default;
  -webkit-user-select: none;
          user-select: none;
}

/* The tag name sits at Medium against the Regular prefix, so "Housed in"
   reads as a label and "Southampton" as the value. Cheaper than a second
   colour, and it survives greyscale. */
html body .vt-list-item-tags .vt-list-item-tags-title {
  font-weight: var(--vce-wt-label) !important;
  text-transform: capitalize;
}

/* ⚠ The prefix must opt OUT of capitalize, or you get "Housed In
   Southampton" — capitalize hits every word, generated content included.

   Note `capitalize` on the tag name is itself a departure from p.36, which
   asks for sentence case. It's here so "natural resources" matches
   "Forestry" instead of sitting beside it in lower case. Delete the
   text-transform above to follow the guide. */
html body .vt-list-item-tags .vt-list-item-tags-title::before {
  font-weight: var(--vce-wt-body) !important;
  text-transform: none;
}

/* vt-one appends a comma between tags. The flex gap does that job now. */
html body .vt-list-item-tags-title::after {
  content: none !important;
}

/* §11.1d  Home office — Dark Grey ---------------------------------------- */
/* Stated by the :home-office/ tag, not inferred. One per person. */

html body .vt-list-item-tags-tag:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"], a[data-vce-tag-href*=":home-office/"], a[data-vce-tag-href*="%3Ahome-office/"])
  .vt-list-item-tags-link {
  --pill-bg: var(--vce-grey-dark);   /* white on it = 5.03:1 */
}

html body .vt-list-item-tags-tag:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"], a[data-vce-tag-href*=":home-office/"], a[data-vce-tag-href*="%3Ahome-office/"])
  .vt-list-item-tags-title::before {
  content: "Housed in ";
}

/* §11.1e  Specializations — Light Grey ----------------------------------- */
/* The quieter of the two, which suits them: location reads first, the
   specialisms sit under it. First category to flip --pill-ink.

   ⚠ The pill EDGE is 1.2:1 against the white card, so this reads as tinted
   text rather than as a chip. Not a WCAG failure — the shape is decorative
   and the text carries the meaning at 12.68:1 — but uncomment the border
   below if you want it to read as a chip. */

html body .vt-list-item-tags-tag:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"], a[data-vce-tag-href*=":specialization/"], a[data-vce-tag-href*="%3Aspecialization/"])
  .vt-list-item-tags-link {
  --pill-bg: var(--vce-grey-light);
  --pill-ink: var(--vce-ink);      /* 12.68:1 */
  /* border: 1px solid var(--vce-rule); */
}

/* §11.1f  Offices a person covers — Dark Green --------------------------- */
/* The :offices/ tags say which offices a person works out of. On an office
   page they are noise — you already know which office you are looking at —
   so §11.1g still hides them there. On a people card they are the whole
   point, so this turns them back on inside li.bio-page.

   ⚠ WHY li.bio-page AND NOT A HAND-ADDED CLASS
     The List component stamps a page-type class on every item it renders:
     bio-page, general-page, article-page, resource-page. So a people list
     identifies itself, and nobody has to remember to fill in the CSS-class
     field on 107 sites. The flip side is that it is vt-one's class, not
     ours — if an upgrade renames it, these pills quietly stop showing and
     nothing errors. Grep for bio-page after any Ensemble update.

   ⚠ THE "Serves" PREFIX IS AN ASSERTION, NOT A FACT FROM THE TAG
     The tag only says a person is associated with that office. "Serves"
     is our reading of it. If an office uses the tag to mean something
     else — supervises, is funded by, drops in monthly — change the string
     below, not the taxonomy. One place, 107 sites.

   Dark Green on white is 8.74:1, so it clears 1.4.3 at any size, and it is
   far enough from the Dark Grey home-office pill to read as a different
   category rather than a different shade of the same one. The prefixes do
   the real work though: colour is never the only signal (1.4.1). */

html body li.bio-page .vt-list-item-tags-tag:has(a[href*=":offices/"], a[href*="%3Aoffices/"], a[data-vce-tag-href*=":offices/"], a[data-vce-tag-href*="%3Aoffices/"]) {
  display: block !important;
}

html body li.bio-page .vt-list-item-tags-tag:has(a[href*=":offices/"], a[href*="%3Aoffices/"], a[data-vce-tag-href*=":offices/"], a[data-vce-tag-href*="%3Aoffices/"])
  .vt-list-item-tags-link {
  --pill-bg: var(--vce-brand-2);          /* Dark Green, white on it 8.74:1 */
  --pill-ink: var(--vce-brand-2-ink);
}

html body li.bio-page .vt-list-item-tags-tag:has(a[href*=":offices/"], a[href*="%3Aoffices/"], a[data-vce-tag-href*=":offices/"], a[data-vce-tag-href*="%3Aoffices/"])
  .vt-list-item-tags-title::before {
  content: "Serves ";
}

/* ⚠ THE HOME OFFICE IS USUALLY TAGGED TWICE
   A person tagged :home-office/nottoway is normally also tagged
   :offices/nottoway, which renders as "Housed in Nottoway" next to
   "Serves Nottoway". True, but it reads as a mistake.

   CSS cannot compare one tag's slug against a sibling's, so the de-dupe
   lives in vce-tag-pills-disable.html (v3.1+), which drops the :offices/
   tag whose slug matches the :home-office/ tag. Without the JS you get
   both pills — redundant, never wrong. */

/* §11.1g  What's shown --------------------------------------------------- */
/* Anything that is neither a home office nor a specialization is hidden.
   That covers the :offices/ tags a person is tagged into, and topic tags.
   §11.1f above re-shows the :offices/ tags inside li.bio-page; this rule
   is what it is an exception to, so read the two together.

   This replaced a sibling-position selector that hid all but the last
   :offices/ tag. Reading it now is much simpler: "not one of the two
   categories we show". */

html body .vt-list-item-tags-tag:not(:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"], a[data-vce-tag-href*=":home-office/"], a[data-vce-tag-href*="%3Ahome-office/"])):not(:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"], a[data-vce-tag-href*=":specialization/"], a[data-vce-tag-href*="%3Aspecialization/"])) {
  display: none !important;
}

/* Show everything, as Maroon pills — add vce-tags-show-all to the List
   component's CSS-class field. */
html body .vce-tags-show-all .vt-list-item-tags-tag {
  display: block !important;
}

/* THE OTHER HALF NEEDS JS, AND CANNOT BE DONE HERE
   The home-office tag should also disappear when it IS this page's own
   office. CSS cannot read the URL, and an attribute selector can only
   compare against a literal, so "this tag's slug equals this page's slug"
   is not expressible in a stylesheet shared by 107 sites.

   vce-tag-pills-disable.html does it: it derives the office slug from the
   URL and removes the matching tag. Without the JS you get the safe
   fallback — "Housed in <office>" shows on every page including its own,
   which is redundant but never wrong. */

/* §11.1h  Making them non-interactive ------------------------------------ */
/* ⚠ CSS ALONE IS NOT ENOUGH, AND HALF-DOING THIS IS WORSE THAN NOT DOING IT.
   pointer-events:none stops the mouse, but the anchor stays in the tab
   order, still announces as "link", and still navigates on Enter. A
   focusable control that looks like a link and does nothing fails 2.4.3
   and 4.1.2 — worse for keyboard and screen reader users than leaving the
   links working.

   The pointer-events:none lives up in §11.1c with the rest of the pill, so
   the selector is only declared once.

   So this is the visual half only. Pair it with the JS in
   vce-tag-pills-disable.html, which removes the href. If you can't add JS
   to these sites, leave the links live. */

/* Nothing responds, so nothing gets a hover treatment. Kept explicit so the
   old ring and underline don't creep back in. */
html body .vt-list-item-tags .vt-list-item-tags-link:hover,
html body .vt-list-item-tags .vt-list-item-tags-link:visited {
  color: var(--pill-ink) !important;
  text-decoration: none !important;
  box-shadow: none !important;
}

/* Belt and braces: until the JS runs, a keyboard user can still reach the
   anchor, so it must still show a visible ring. */
html body .vt-list-item-tags .vt-list-item-tags-link:focus-visible {
  outline: 3px solid var(--vce-focus) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 6px var(--vce-focus-halo) !important;
  border-radius: var(--vce-radius-pill) !important;
}

/* §11.1i  Fallbacks ------------------------------------------------------ */

/* ⚠ Without :has() the §11.1g hide rule is dropped too, so EVERY tag shows,
   all Maroon, with no prefixes. Legible and complete rather than broken,
   but it is the opposite of the intended filtering — worth knowing if a
   very old browser turns up in analytics. */
@supports not selector(:has(*)) {
  html body .vt-list-item-tags .vt-list-item-tags-link {
    --pill-bg: var(--vce-maroon);
  }
}

@media (forced-colors: active) {
  html body .vt-list-item-tags .vt-list-item-tags-link {
    background: ButtonFace !important;
    color: ButtonText !important;
    border: 1px solid ButtonBorder !important;
    forced-color-adjust: none;
  }
}

/* Pill fills print as grey mush; the prefix carries the meaning, so keep
   that and drop the colour. */
@media print {
  html body .vt-list-item-tags .vt-list-item-tags-link {
    background: transparent !important;
    color: #000 !important;
    border: 1px solid #000 !important;
  }
  html body .vt-list-item-tags { border-top-color: #000; }
}

html body .vt-vtcontainer.vce-panel {
  background: var(--vce-surface) !important;
  padding: 2rem;
}

html body .vt-image-caption,
html body figcaption {
  color: var(--vce-ink-muted) !important;
  font-size: 0.875rem;
  letter-spacing: var(--vce-track-tight);
}


/* ── §11.2  EMBEDDED CALENDAR (Timely) ─────────────────────────────────────
   The file header says the Timely iframe is deliberately untouched. That
   still holds — this styles the CONTAINER around it, which is ours, not the
   cross-origin document inside it, which we cannot reach. Sizing the box is
   fine; colours and type inside the calendar are still a Timely-admin job.

   ⚠ A scroll container this short hides most of the calendar and adds a
   second scrollbar inside the page. 40vh is about 380px on a laptop —
   roughly three events. Worth checking on a phone, where 40vh is ~290px
   and the inner scroll competes with the page scroll. If the goal was just
   to stop a very long calendar dominating the page, a taller max-height
   with the same overflow behaves better on small screens.
-------------------------------------------------------------------------- */

html body #timely-calendar-container {
  max-height: 40vh !important;
  overflow-y: scroll !important;
}


/* ── §11.3  CARDIFY LIST — swoosh cards from the List component ────────────
   Turns a List component into VCE swoosh cards: art on the left, the brand
   swoosh as the divider, dark fill and the title on the right, whole card
   clickable.

   Put ext-office-cardify-list-component in the List component's CSS-class
   field. Pure CSS, same approach as §14 — nothing to publish, nothing to
   break in author mode, and the plain list still reads fine if this file
   fails to load.

   ── THE ART, IN TWO CASES ────────────────────────────────────────────────
     1. The item has an image  → that image fills the art panel, cover-cropped.
     2. The item has no image  → a DAM pattern fills it instead.

     The test is :not(:has(.vt-list-item-img)), NOT :empty. vt-one leaves
     whitespace inside an empty .vt-list-item-imgWrapper, and Level-3 :empty
     counts whitespace as content, so :empty would never match in a browser.

   ⚠ CASE 2 MAY BE REDUNDANT. Your first sample card's image is already
     /content/dam/ext_vt_edu/patterns/vce-pattern-plant-ag-rgb-maroon.png —
     an author picking the pattern in the image field. That is the better
     route: it's per-card, visible in the dialog, and needs no lookup here.
     The rotation below is only a floor for cards nobody set an image on.

   ── HOW THE FALLBACK PATTERN IS CHOSEN ───────────────────────────────────
     A six-step nth-child rotation, so a run of un-imaged cards doesn't
     repeat one texture. It is positional, not semantic — card 7 gets the
     same pattern as card 1.

     For a semantic mapping instead, the li carries the item's taxonomy as
     classes — this markup shows `trees-shrubs-groundcovers`,
     `fruits-vegetables`, `expert-reviewed`. Map the ones you care about and
     they override the rotation:

       html body .ext-office-cardify-list-component li.fruits-vegetables
         { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-lawn-garden-rgb-yellow.png"); }

     CSS can't build a URL from parts, so each mapping is a whole url().
     Full set: animal-ag, business, community, family, health, knowledge,
     lawn-garden, leadership, natural-res, nutrition, plant-ag, youth ×
     dk-gray, dk-green, maroon, teal, yellow.
     ⚠ animal-ag has no dk-gray file — that combination 404s.

   ── CONTRAST ─────────────────────────────────────────────────────────────
     white on Dark Green fill .... 8.74:1  AAA
     white on Dark Grey fill ..... 5.03:1  AA   (alternate rows)

   ⚠ Like §14, this undoes §11's card rules with !important against
     !important, so it has to stay after §11.
-------------------------------------------------------------------------- */

html body .ext-office-cardify-list-component {
  --card-fill:    var(--vce-green);
  --card-ink:     var(--vce-white);
  --card-split:   44%;          /* width of the art panel */
  --card-min-h:   9rem;
  --card-gap:     1rem;         /* between cards */
  --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-plant-ag-rgb-yellow.png");
}

/* Alternate fill so a column of cards doesn't read as one block. */
html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(even) {
  --card-fill: var(--vce-grey-dark);   /* white on it = 5.03:1 */
}

/* §11.3a  Strip the list chrome ------------------------------------------ */

html body .ext-office-cardify-list-component .vt-list-columns,
html body .ext-office-cardify-list-component .vt-list-items {
  margin: 0 !important;
  padding: 0 !important;
}

html body .ext-office-cardify-list-component .vt-c-card-list {
  list-style: none !important;
  display: flex;
  flex-direction: column;
  gap: var(--card-gap);
}

html body .ext-office-cardify-list-component .vt-c-card-list > li {
  max-width: none !important;
  width: auto !important;
  margin: 0 !important;
  padding: 0 !important;
}

/* The "Article Item" / "Resource Item" heading is boilerplate the component
   emits on every row. Nothing else here is wanted either. */
html body .ext-office-cardify-list-component .vt-list-item-heading,
html body .ext-office-cardify-list-component .vt-list-item-desc,
html body .ext-office-cardify-list-component .vt-list-item-date,
html body .ext-office-cardify-list-component .vt-list-item-time,
html body .ext-office-cardify-list-component .vt-list-item-tags {
  display: none !important;
}

/* §11.3b  The card ------------------------------------------------------- */
/* Undoing §11's card treatment — !important against !important, see above. */

html body .ext-office-cardify-list-component .vt-list-item-wrapper {
  position: relative;
  display: block !important;
  height: auto !important;
  min-height: var(--card-min-h);
  overflow: hidden;
  background: var(--card-fill) !important;
  border: 0 !important;
  border-radius: var(--vce-radius-flat) !important;
  box-shadow: none !important;
  margin: 0 !important;
  padding: 0 !important;
  transition: box-shadow .15s ease;
}

html body .ext-office-cardify-list-component .vt-list-item-row {
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: stretch !important;
  min-height: var(--card-min-h);
  margin: 0 !important;
}

/* §11.3c  The art panel -------------------------------------------------- */

html body .ext-office-cardify-list-component .vt-list-item-col:has(.vt-list-item-imgWrapper) {
  flex: 0 0 var(--card-split);
  max-width: var(--card-split) !important;
  width: var(--card-split) !important;
  padding: 0 !important;
  margin: 0 !important;
  position: relative;
  overflow: hidden;
}

html body .ext-office-cardify-list-component .vt-list-item-imgWrapper {
  position: absolute;
  inset: 0;
  background: var(--card-pattern) left center / cover no-repeat;
}

html body .ext-office-cardify-list-component .vt-list-item-figure,
html body .ext-office-cardify-list-component .vt-list-item-picture {
  display: block;
  height: 100%;
  margin: 0 !important;
}

/* Case 1 — the item's own image fills the panel. */
html body .ext-office-cardify-list-component .vt-list-item-img {
  width: 100% !important;
  height: 100% !important;
  max-height: none !important;
  object-fit: cover;
  display: block;
}

/* §11.3d  The swoosh ----------------------------------------------------- */
/* Authentic brand-guide curve (p.49), same path as the standalone swoosh
   cards. Sized off the panel HEIGHT with its own aspect ratio, so it can
   never be stretched past the p.51 limit however wide the card gets — the
   dark fill simply continues from the curve to the panel edge, because the
   card's own background is already that colour. */

html body .ext-office-cardify-list-component .vt-list-item-imgWrapper::after {
  content: "";
  position: absolute;
  top: 0;
  right: -1px;               /* 1px overlap kills the sub-pixel seam */
  height: 100%;
  aspect-ratio: 425 / 381.3;
  max-width: 100%;
  background: var(--card-fill);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 425 381.3' preserveAspectRatio='none'%3E%3Cpath d='M424.6 0C424.6 77.06 332.4 134.68 212.6 190.65C92.7 246.63 0 315 0 381.3L425 381.3L425 0Z' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 425 381.3' preserveAspectRatio='none'%3E%3Cpath d='M424.6 0C424.6 77.06 332.4 134.68 212.6 190.65C92.7 246.63 0 315 0 381.3L425 381.3L425 0Z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  pointer-events: none;
}

/* §11.3e  The title and the click target --------------------------------- */

html body .ext-office-cardify-list-component .vt-list-item-col:not(:has(.vt-list-item-imgWrapper)) {
  flex: 1 1 auto;
  max-width: none !important;
  width: auto !important;
  display: flex;
  align-items: center;
  padding: 1.25rem 1.5rem !important;
  margin: 0 !important;
}

html body .ext-office-cardify-list-component .vt-list-item-title {
  display: block;
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-display) !important;
  letter-spacing: var(--vce-track-tight) !important;
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  line-height: 1.2 !important;
  color: var(--card-ink) !important;
  text-wrap: balance;
}

/* ⚠ EVERY STATE NAMED, ON PURPOSE.
   §4 and §11 both set .vt-list-item-title-link:hover to a link colour —
   Maroon and Maroon shade. On this card's fill those measure 1.04:1 and
   1.44:1 on Dark Green: the title effectively disappears. Their selectors
   are (0,2,2), exactly the same as an unstated base rule here, so which one
   wins came down to source order — far too fine a margin for a title
   vanishing.

   Naming the states takes these to (0,3,2), which beats both outright.
   Same lesson as §6: a class that renders on two different grounds needs
   every state stated, not just the resting one.

   ⚠ The stretched ::before means hovering ANYWHERE on the card counts as
   hovering the link, so this fires across the whole card, not just the
   words. That is why it reads as the card changing colour. */

html body .ext-office-cardify-list-component .vt-list-item-title,
html body .ext-office-cardify-list-component .vt-list-item-title-link,
html body .ext-office-cardify-list-component .vt-list-item-title-link:link,
html body .ext-office-cardify-list-component .vt-list-item-title-link:visited,
html body .ext-office-cardify-list-component .vt-list-item-title-link:hover,
html body .ext-office-cardify-list-component .vt-list-item-title-link:focus,
html body .ext-office-cardify-list-component .vt-list-item-title-link:active {
  color: var(--card-ink) !important;
  text-decoration: none !important;
}

/* The hover affordance is an underline and the card's shadow, not a colour
   change — so it can't cost contrast, and it still reads in greyscale. */
html body .ext-office-cardify-list-component .vt-list-item-wrapper:hover
  .vt-list-item-title-link,
html body .ext-office-cardify-list-component .vt-list-item-title-link:hover {
  text-decoration: underline !important;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.16em;
}

/* Stretched link: the whole card is the hit area, but there is still only
   ONE link in the tab order and its accessible name is just the title. The
   sr-only ", article" / ", resource" the component emits rides along, which
   is exactly what it's for. */
html body .ext-office-cardify-list-component .vt-list-item-title-link::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: var(--z-content);
}

/* The CTA lozenge. Decorative — the card is already clickable.
   ⚠ It sits inside the link, so a screen reader reads "<title>, resource
   More". Delete this rule if that extra word isn't worth the affordance. */
html body .ext-office-cardify-list-component .vt-list-item-title-link::after {
  content: "More";
  display: table;          /* table, not inline-block: puts it on its own
                              line under the title without a wrapper */
  margin-top: 0.7rem;
  padding: 0.35em 1.1em;
  border-radius: var(--vce-radius-pill);
  background: var(--vce-yellow);
  color: var(--vce-blue-dark);        /* 7.41:1 */
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: 0.875rem;
  line-height: 1.3;
}

/* §11.3f  States --------------------------------------------------------- */

html body .ext-office-cardify-list-component .vt-list-item-wrapper:hover,
html body .ext-office-cardify-list-component .vt-list-item-wrapper:focus-within {
  border: 0 !important;
  box-shadow: 0 2px 12px rgba(7, 41, 56, 0.25) !important;
}

html body .ext-office-cardify-list-component .vt-list-item-title-link:focus-visible::before {
  outline: 3px solid var(--vce-white);
  outline-offset: -5px;
  box-shadow: 0 0 0 3px var(--vce-blue-dark) inset;
}

/* §11.3g  Fallback pattern rotation -------------------------------------- */
/* Positional, not semantic — see the note at the top of §11.3. Only shows
   on cards with no image of their own. */

html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(6n+1)
  { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-plant-ag-rgb-yellow.png"); }
html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(6n+2)
  { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-lawn-garden-rgb-yellow.png"); }
html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(6n+3)
  { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-natural-res-rgb-yellow.png"); }
html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(6n+4)
  { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-nutrition-rgb-yellow.png"); }
html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(6n+5)
  { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-community-rgb-yellow.png"); }
html body .ext-office-cardify-list-component .vt-c-card-list > li:nth-child(6n+6)
  { --card-pattern: url("/content/dam/ext_vt_edu/patterns/vce-pattern-knowledge-rgb-yellow.png"); }

/* §11.3h  Narrow viewports ----------------------------------------------- */
/* Below this the art panel is too thin to read as anything, so the card
   stacks: art band on top, text under it, swoosh rotated flat. */

@media (max-width: 34rem) {
  html body .ext-office-cardify-list-component .vt-list-item-row {
    flex-direction: column !important;
  }
  html body .ext-office-cardify-list-component .vt-list-item-col:has(.vt-list-item-imgWrapper) {
    flex: 0 0 auto;
    width: 100% !important;
    max-width: none !important;
    height: 38vw;
  }
  html body .ext-office-cardify-list-component .vt-list-item-imgWrapper::after {
    top: auto;
    bottom: -1px;
    right: 0;
    width: 100%;
    height: min(14vw, 5rem);
    aspect-ratio: auto;
    max-width: none;
  }
}

@supports not selector(:has(*)) {
  /* No :has() means neither column can be told apart, so the card layout is
     skipped entirely and the list renders as vt-one's default cards. */
  html body .ext-office-cardify-list-component .vt-list-item-wrapper {
    background: var(--vce-white) !important;
  }
  html body .ext-office-cardify-list-component .vt-list-item-title,
  html body .ext-office-cardify-list-component .vt-list-item-title-link {
    color: var(--vce-ink) !important;
  }
  html body .ext-office-cardify-list-component .vt-list-item-title-link::after {
    content: none;
  }
}

@media print {
  html body .ext-office-cardify-list-component .vt-list-item-wrapper {
    background: #fff !important;
    border: 1px solid #000 !important;
  }
  html body .ext-office-cardify-list-component .vt-list-item-title,
  html body .ext-office-cardify-list-component .vt-list-item-title-link {
    color: #000 !important;
  }
  html body .ext-office-cardify-list-component .vt-list-item-imgWrapper::after,
  html body .ext-office-cardify-list-component .vt-list-item-title-link::after {
    display: none !important;
  }
}


/* ══ §11.4  BIO PAGE TAG CLOUD  (ul.tagcloud) ══════════════════════════════
   The person pages at /people/<person>.html render their tags through a
   different component than the people LIST does, with its own markup:

     <ul class="tagcloud">
       <li><a class="vt-tag-link" href="…/tags.html/ext_vt_edu:specialization/4-h-youth">4-H Youth Development</a></li>
       <li><a class="vt-tag-link" href="…/tags.html/ext_vt_edu:home-office/nottoway">Nottoway</a></li>
       <li><a class="vt-tag-link" href="…/tags.html/ext_vt_edu:offices/nottoway">Nottoway</a></li>
     </ul>

   THREE DIFFERENCES FROM §11.1 THAT CHANGE THE CSS, NOT JUST THE SELECTOR

   1. NO INNER SPAN. The card pills wrap the label in
      .vt-list-item-tags-title, which is where §11.1 hangs the prefix and
      the Medium weight. Here the label is a bare text node inside the
      anchor, so the prefix goes on the ANCHOR's ::before and the weights
      invert: the anchor carries Medium for the value and ::before drops
      back to Regular for the prefix. Same result, opposite direction.

   2. NO role="listitem". The card markup declares the roles, so §11.1 can
      strip list-style safely. This markup doesn't, and list-style:none
      silently removes list semantics in Safari + VoiceOver. The zero-width
      ::before on the li below is the standard workaround — it is not
      decoration and it is not spare, so don't tidy it away.

   3. THE PATH FORM IS DIFFERENT. Cards link ?tag=ext_vt_edu:offices/x;
      this links /tags.html/ext_vt_edu:offices/x. The selectors below match
      on ":offices/" as a substring, so both forms hit. Both colon
      encodings too, same as §11.1.

   ⚠ THESE LINKS STAY LIVE, UNLIKE THE CARD PILLS
     §11.1h makes the card pills inert. That was never about the tags — it
     was about the stretched ::before on the card title, which turns the
     whole card into one click target and leaves a live tag link fighting
     it for the same pixels. A bio page has no stretched link, so there is
     no conflict and no reason to take a working route to "everyone else in
     4-H Youth Development" away from the reader. They are styled the same
     and they behave differently, on purpose.

     If you do want them inert for consistency, it is the §11.1h deal in
     full: pointer-events:none here AND the href removed in
     vce-tag-pills-disable.html. Visual half alone fails 2.4.3 and 4.1.2.

   ⚠ THE HOME OFFICE IS TAGGED TWICE
     The example above is the common shape — :home-office/nottoway and
     :offices/nottoway both present, both labelled "Nottoway", rendering as
     "Housed in Nottoway" beside "Serves Nottoway". CSS cannot compare a
     tag's slug against its sibling's. vce-tag-pills-disable.html v3.1 drops
     the duplicate; without the JS you get both.
   ────────────────────────────────────────────────────────────────────── */

/* §11.4a  The row -------------------------------------------------------- */

html body ul.tagcloud {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.45rem;
  list-style: none !important;
  margin: 1rem 0 !important;
  padding: 0 !important;
}

html body ul.tagcloud > li {
  margin: 0 !important;
  padding: 0 !important;
  line-height: 1.3 !important;
}

/* Keeps the <ul> announcing as a list in Safari after list-style:none.
   See note 2 above. */
html body ul.tagcloud > li::before {
  content: "\200B";
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* §11.4b  Reading order -------------------------------------------------- */
/* Same ladder as §11.1b, spaced by tens. */

html body ul.tagcloud > li { order: 40; }

html body ul.tagcloud > li:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"]) { order: 10; }
html body ul.tagcloud > li:has(a[href*=":offices/"], a[href*="%3Aoffices/"])         { order: 20; }
html body ul.tagcloud > li:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"]) { order: 30; }

/* §11.4c  The pill ------------------------------------------------------- */
/* Same two tokens as §11.1c, so the two components stay in step: change a
   category colour in one place and both the card and the bio page follow. */

html body ul.tagcloud a.vt-tag-link {
  --pill-bg: var(--vce-maroon);
  --pill-ink: var(--vce-white);

  display: inline-block;
  max-width: 100%;
  padding: 0.32em 0.85em;
  border-radius: var(--vce-radius-pill);

  background: var(--pill-bg) !important;
  color: var(--pill-ink) !important;

  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;     /* Medium: the value */
  letter-spacing: var(--vce-track-label) !important;
  font-size: 0.8125rem;
  line-height: 1.4;
  text-transform: capitalize;
  text-decoration: none !important;
}

/* The prefix opts out of both the Medium weight and the capitalize, or you
   get a bold "Housed In". Same trap as §11.1c. */
html body ul.tagcloud a.vt-tag-link::before {
  font-weight: var(--vce-wt-body) !important;
  text-transform: none;
}

/* §11.4d  Categories ----------------------------------------------------- */
/* Prefix strings are duplicated from §11.1d–f rather than shared, because a
   CSS custom property cannot be used as a `content` value without being
   declared as a <string> token. If you change one, change the other —
   there is nothing that will tell you that you didn't. */

html body ul.tagcloud > li:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"]) a.vt-tag-link {
  --pill-bg: var(--vce-grey-dark);                 /* white on it, 5.03:1 */
}
html body ul.tagcloud > li:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"]) a.vt-tag-link::before {
  content: "Housed in ";
}

html body ul.tagcloud > li:has(a[href*=":offices/"], a[href*="%3Aoffices/"]) a.vt-tag-link {
  --pill-bg: var(--vce-brand-2);                   /* Dark Green, 8.74:1 */
  --pill-ink: var(--vce-brand-2-ink);
}
html body ul.tagcloud > li:has(a[href*=":offices/"], a[href*="%3Aoffices/"]) a.vt-tag-link::before {
  content: "Serves ";
}

html body ul.tagcloud > li:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"]) a.vt-tag-link {
  --pill-bg: var(--vce-grey-light);
  --pill-ink: var(--vce-ink);                      /* 14.54:1 */
}

/* Everything else — topic/, pubs_ext_vt_edu: — keeps the Maroon default and
   stays visible. §11.1g hides uncategorised tags on CARDS, where they are
   competing with a title and an image for a few square inches. Here the tag
   cloud is the only thing in the block, so hiding a tag would leave the
   reader with less information and an empty-looking page. If you want the
   card behaviour instead, this is the rule:

     html body ul.tagcloud > li:not(:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"], a[href*=":offices/"], a[href*="%3Aoffices/"], a[href*=":specialization/"], a[href*="%3Aspecialization/"])) {
       display: none !important;
     }

   ⚠ Both colon encodings, or it bites. A shorter version that lists only
     the ":" forms looks right and tests clean against today's markup — AEM
     emits the bare colon — but the moment one page renders "%3Aoffices/"
     that tag falls through the :not() and gets hidden, silently, on one
     page out of hundreds. Caught in regression testing, not in review.
*/

/* §11.4e  States --------------------------------------------------------- */
/* These are live links (see the header note), so every state is named and
   the hover cue is not colour alone — the pill darkens AND underlines. */

html body ul.tagcloud a.vt-tag-link:link,
html body ul.tagcloud a.vt-tag-link:visited {
  background: var(--pill-bg) !important;
  color: var(--pill-ink) !important;
  text-decoration: none !important;
}

/* 85% toward black keeps or improves the text contrast on every one of the
   four pill colours, so there is no state where hover is the failure. */
html body ul.tagcloud a.vt-tag-link:hover,
html body ul.tagcloud a.vt-tag-link:active {
  background: color-mix(in oklab, var(--pill-bg) 85%, #000) !important;
  color: var(--pill-ink) !important;
  text-decoration: underline !important;
  text-underline-offset: 0.2em;
}

/* Light Grey is the one pill with dark ink, so darkening the fill walks it
   toward the text instead of away from it. Lighten that one instead. */
html body ul.tagcloud > li:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"]) a.vt-tag-link:hover,
html body ul.tagcloud > li:has(a[href*=":specialization/"], a[href*="%3Aspecialization/"]) a.vt-tag-link:active {
  background: color-mix(in oklab, var(--pill-bg) 80%, #fff) !important;
}

html body ul.tagcloud a.vt-tag-link:focus-visible {
  outline: 3px solid var(--vce-focus) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 6px var(--vce-focus-halo) !important;
  border-radius: var(--vce-radius-pill) !important;
}

/* §11.4f  Fallbacks ------------------------------------------------------ */

/* No :has() means no categories: every pill is Maroon with no prefix.
   Complete and legible, just undifferentiated. */
@supports not selector(:has(*)) {
  html body ul.tagcloud a.vt-tag-link { --pill-bg: var(--vce-maroon); }
}

@media (forced-colors: active) {
  html body ul.tagcloud a.vt-tag-link {
    background: ButtonFace !important;
    color: LinkText !important;
    border: 1px solid ButtonBorder !important;
    forced-color-adjust: none;
  }
}

@media print {
  html body ul.tagcloud a.vt-tag-link {
    background: transparent !important;
    color: #000 !important;
    border: 1px solid #000 !important;
    text-decoration: none !important;
  }
}


/* ══ §11.5  PAGINATION  (vt-pagination-controls) ═══════════════════════════
   vt-one ships this as a row of near-black squares. Three things are wrong
   with it, and only one of them is the colour.

   1. IT STACKS. The three boxes are col-lg-3 / col-lg-6 / col-lg-3, so they
      only sit side by side above 992px. Inside #vt_main beside the right
      column that almost never happens, and you get Previous, then the
      numbers, then Next, each on its own line, all flush left. The rules
      below replace the Bootstrap grid widths with a flex row that wraps on
      its own terms instead of at one hard breakpoint.

   2. THE CURRENT PAGE AND THE FOCUS RING LOOK THE SAME. vt-one marks the
      current page with a ring, which is also what focus looks like, so a
      keyboard user tabbing onto the current page gets no new information.
      Here the current page is a filled Maroon pill and focus is the §16
      ring — two different gestures that can be told apart when they land
      on the same button.

   3. THE BOXES ARE BUTTONS, NOT LINKS. They carry onclick="vtListPageAjax(…)"
      and no href, so the page number is not a URL and middle-click, open in
      new tab, copy link address and "page 3" in the browser history all do
      nothing. That is an Ensemble architecture decision and CSS cannot
      touch it. Worth knowing before someone reports it as a bug.

   ⚠ DO NOT PUT !important ON display FOR THE NUMBER BUTTONS
     Numbers 5–9 carry Bootstrap's `d-none d-sm-flex`, which is how vt-one
     drops the middle of the range on a phone. Both of those utilities are
     !important. Our display sits underneath them on purpose: without
     !important, Bootstrap keeps winning and the responsive hiding survives.
     Add !important here and every number reappears at 320px.

   ⚠ aria-current="true" SHOULD BE aria-current="page"
     "true" is valid and does announce, but "page" is the token that says
     which kind of current this is. It is in the component's HTML, not here.
     The selectors below match the .current-page class AND [aria-current], so
     fixing it upstream will not break the styling.

   WHAT THIS DELIBERATELY LEAVES ALONE
     The "Page 2 of 23 | 448 Results" line underneath is a separate element
     that was not in the markup I was given, so there is no selector for it
     here. Send it over if you want it picked up.
   ────────────────────────────────────────────────────────────────────── */

/* §11.5a  The row ---------------------------------------------------------
   Replaces .row's negative margins and the col-* percentage widths. The
   number group is the only part allowed to grow, so it stays centred even
   on page 1, where vt-one omits the Previous button entirely rather than
   disabling it — leaving an empty box that would otherwise pull the
   numbers off centre. */

html body .vt-pagination-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem 1rem;
  margin: 2.5rem 0 0 !important;         /* beats .row's -15px side margins */
  padding: 1.5rem 0 0;
  border-top: 1px solid var(--vce-rule);
}

/* Specificity here is (0,1,3) against Bootstrap's (0,1,0) col classes, so
   these win at every breakpoint without !important. Keep the `> div` — it
   must not catch the sr-only live region span. */
html body .vt-pagination-controls > div {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  width: auto;
  max-width: none;
  padding: 0;
}

/* ⚠ KEEP THE `> ` ON THESE THREE, AND ON THE MEDIA QUERY BELOW
   The rule above is html body .vt-pagination-controls > div, which is
   (0,1,3). A plain `html body .vt-pagination-controls-page-numbers` is
   (0,1,2) and quietly loses to it, so the numbers never grow and Previous
   never reaches the left edge — the row renders centred in a huddle and
   nothing anywhere errors. The child combinator costs no specificity; the
   extra class is what buys it. Caught by rendering the real markup, not by
   reading the file. */

/* Below 48rem the full row cannot fit — nine numbers alone are ~464px — so
   the three boxes each take a line and centre. Three short rows instead of
   the natural wrap, which orphans Previous on one line and Next on
   another depending on the exact width.

   ⚠ STACKED IN DOM ORDER, NOT REORDERED WITH `order`
     Putting the numbers on top and Previous/Next beneath is two lines
     instead of three and looks tighter. It is also a 2.4.3 failure: tab
     order follows the DOM, so focus would jump from Previous at the bottom
     up to the numbers and back down to Next. §11.1b uses `order` on the tag
     pills because they are a flat set with no sequence. A pagination
     control is nothing but sequence. Don't. */
html body .vt-pagination-controls > div {
  flex: 1 1 100%;
}

@media (min-width: 48rem) {
  /* One row: Previous at the left edge, numbers centred in what is left,
     Next at the right edge. The numbers are the only box allowed to grow
     from its content, so they stay centred on page 1, where vt-one omits
     the Previous button rather than disabling it. */
  html body .vt-pagination-controls > .vt-pagination-controls-left {
    flex: 1 1 0;
    justify-content: flex-start;
  }
  html body .vt-pagination-controls > .vt-pagination-controls-page-numbers {
    flex: 1 1 auto;
  }
  html body .vt-pagination-controls > .vt-pagination-controls-right {
    flex: 1 1 0;
    justify-content: flex-end;
  }
}

/* §11.5b  The pill --------------------------------------------------------
   One rule for both the numbers and the Previous/Next buttons: they are the
   same class of control and the carets already tell them apart.

   ⚠ THE BORDER IS NOT DECORATION — IT IS 1.4.11
     A Light Grey fill is 1.20:1 against the white page. On a tag that is
     fine: §11.1e is a label, the shape is decorative and the text carries
     the meaning. These are interactive controls, so their boundary is
     "visual information required to identify a user interface component"
     and needs 3:1. --vce-rule-strong is 5.03:1 on white. Drop the border
     and the control stops being identifiable as one. */

html body .vt-pagination-controls button {
  display: inline-flex;              /* no !important — see the header note */
  align-items: center;
  justify-content: center;
  gap: 0.35em;

  /* 2.75rem = 44px. 2.5.8 asks for 24px; the rest of this file holds a 44px
     floor and a pagination row is exactly where a miss costs you a page. */
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0.4rem 0.85rem;

  border: 1px solid var(--vce-rule-strong) !important;   /* 5.03:1 on white */
  border-radius: var(--vce-radius-pill) !important;
  background: var(--vce-grey-light) !important;
  color: var(--vce-ink) !important;                      /* 12.68:1 on fill */

  /* ⚠ CLEARS vt-one's CURRENT-PAGE RING, NOT THE FOCUS RING
     vt-one marks the current page with an outline, which is the whole
     reason a keyboard user cannot tell focus from "you are here". This
     removes it. Deliberately NOT !important: the §11.5c focus rule sets
     outline with !important, so focus still wins here and on every later
     rule, whatever the source order. If you ever drop the !important
     there, focus disappears everywhere in this component. */
  outline: none;

  -webkit-appearance: none;
          appearance: none;
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: 0.9375rem;
  line-height: 1.2;
  text-decoration: none !important;
  cursor: pointer;
}

/* ⚠ PUTTING display ON A BUTTON DEFEATS [hidden]
   The UA stylesheet's [hidden]{display:none} loses to any author display,
   so the rule above would force a hidden button back on screen. vt-one
   omits Previous from the DOM today rather than hiding it, so nothing is
   broken right now — this is here so it stays that way if Ensemble ever
   switches to the attribute. Same reasoning for :disabled below: the
   component tracks data-endpageid, so a disabled end state is one upgrade
   away. */
html body .vt-pagination-controls button[hidden] {
  display: none;
}

html body .vt-pagination-controls button:disabled {
  background: var(--vce-page-bg) !important;
  border-color: var(--vce-rule) !important;
  color: var(--vce-ink-muted) !important;             /* 7.21:1 on white */
  box-shadow: none !important;
  cursor: not-allowed;
}

/* The inner span is the flex line. Numbers 5–9 have Bootstrap forcing this
   to `flex` above 576px, which behaves identically as an only child. */
html body .vt-pagination-controls .vt-list-pagination-item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35em;
}

/* FontAwesome's inline SVG is sized in em and carries fill="currentColor"
   — unlike the accordion chevrons in §12.4, which have no fill at all and
   render black whatever you set `color` to. These follow the text. */
html body .vt-pagination-controls .svg-inline--fa {
  flex: 0 0 auto;
  width: 0.5em;
  height: 0.9em;
}

/* §11.5c  States ----------------------------------------------------------
   Hover thickens the border with an inset shadow rather than a second
   border pixel. A real 2px border would change the box size and shunt every
   sibling sideways on hover. */

html body .vt-pagination-controls button:hover {
  background: color-mix(in oklab, var(--vce-grey-light) 88%, #000) !important;
  color: var(--vce-ink) !important;                            /* 9.69:1 */
  box-shadow: inset 0 0 0 1px var(--vce-rule-strong);
}

html body .vt-pagination-controls button:active {
  background: color-mix(in oklab, var(--vce-grey-light) 78%, #000) !important;
}

/* ⚠ THE outline-offset IS LOAD-BEARING ON THE CURRENT PAGE
   --vce-focus is Dark Blue, which is 15.18:1 against the white page but
   only 1.67:1 against the Maroon current-page pill. The 2px offset is what
   puts the ring on the page rather than on the pill, and the white halo
   guarantees it even on a tinted ground. Remove the offset and focus
   becomes invisible on exactly one button out of nine. */
html body .vt-pagination-controls button:focus-visible {
  outline: 3px solid var(--vce-focus) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 6px var(--vce-focus-halo) !important;
}

/* §11.5d  The current page ------------------------------------------------
   Matches the class and the ARIA attribute, so this survives the
   aria-current="true" → "page" fix noted in the header.

   Not colour alone (1.4.1): the fill flips light-to-dark, the border goes
   to Maroon shade, and the markup already carries an sr-only "current page"
   span. Three signals, one of which is text. */

html body .vt-pagination-controls button.current-page,
html body .vt-pagination-controls button[aria-current] {
  background: var(--vce-maroon) !important;        /* white on it, 9.09:1 */
  border-color: var(--vce-maroon-shade) !important;
  color: var(--vce-white) !important;
  cursor: default;

  /* ⚠ THIS IS THE ONE THAT ACTUALLY KILLS vt-one's RING
     §11.5b also says outline:none, but that selector is (0,1,3) and
     vt-one's current-page rule is class-based, so it out-specifies it and
     the ring survives. This rule is (0,2,3) and beats it. Both are needed:
     this one for the current page, the other for any ring vt-one puts on
     the rest. Still not !important, so §11.5c's focus ring wins on top. */
  outline: none;
}

html body .vt-pagination-controls button.current-page:hover,
html body .vt-pagination-controls button[aria-current]:hover {
  background: var(--vce-maroon-shade) !important;              /* 12.59:1 */
  color: var(--vce-white) !important;
  box-shadow: inset 0 0 0 1px var(--vce-maroon-shade);
}

/* §11.5e  Louder Previous/Next, if you want it --------------------------
   The default above keeps every control in one quiet family so the Maroon
   current page is the only loud thing in the row. If Previous and Next
   should read as the primary action instead, this is the whole change:

     html body .vt-pagination-controls-button {
       background: var(--vce-brand-2) !important;
       border-color: var(--vce-brand-2) !important;
       color: var(--vce-brand-2-ink) !important;
     }
     html body .vt-pagination-controls-button:hover {
       background: var(--vce-brand-2-hover) !important;
       color: var(--vce-brand-2-ink) !important;
     }

   Dark Green carries white at 8.74:1 and its own edge at 8.74:1, so it
   clears both 1.4.3 and 1.4.11 without a contrasting border.
*/

/* §11.5f  Motion, fallbacks, print ---------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html body .vt-pagination-controls button {
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
  }
}

/* color-mix is the only modern feature here. Without it the hover fill
   falls back to no change at all, so name an explicit hover colour. */
@supports not (background: color-mix(in oklab, #fff 50%, #000)) {
  html body .vt-pagination-controls button:hover {
    background: #c7cfde !important;                   /* ink on it, 9.69:1 */
  }
}

@media (forced-colors: active) {
  html body .vt-pagination-controls button {
    background: ButtonFace !important;
    color: ButtonText !important;
    border: 1px solid ButtonBorder !important;
    forced-color-adjust: none;
  }
  html body .vt-pagination-controls button.current-page,
  html body .vt-pagination-controls button[aria-current] {
    background: Highlight !important;
    color: HighlightText !important;
    border-color: HighlightText !important;
  }
}

/* The buttons run JavaScript, so on paper they are nine dead squares. The
   "Page 2 of 23" line sits outside this container and survives. */
@media print {
  html body .vt-pagination-controls { display: none !important; }
}


/* ══ §12  ACCORDIONS & TABS  (vtmultitab) ══════════════════════════════════
   NEW in v2. These shipped unthemed, so they rendered as default browser
   buttons with black hairlines.

   TWO THINGS WORTH KNOWING
   1. The chevron paths carry NO fill attribute, unlike the drawer and
      footer icons which use fill="currentColor". An SVG path with no fill
      renders black, so setting `color` on the button does nothing at all.
      §12.4 forces fill: currentColor so the icon follows the text.
   2. vt-one rotates the same "times" glyph to make the +/× state. Don't
      add your own transform or you'll fight it.

   INDICATOR COLOUR
     Dark Green, not Teal. Teal on white is 1.64:1, which fails the 3:1
     floor for non-text contrast (1.4.11). Dark Green is 8.74:1 on white
     and 7.30:1 on Light Grey. This is why the rails here don't match the
     teal rail in the office nav bar — that one sits on Dark Green, where
     teal is fine.

   State is never colour-only: the weight changes with it.
========================================================================== */

/* §12.1  Accordion ------------------------------------------------------- */

/* No separator between items — your call. Put back
   `border-bottom: 1px solid var(--vce-rule) !important;` for a hairline. */
html body .vt-accordion {
  border: 0 !important;
  margin: 0 !important;
}

html body .vt-accordion-title {
  margin: 0 !important;
  font-size: 1rem !important;
  line-height: 1.3 !important;
}

html body .vt-accordion-trigger {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  text-align: left;

  padding: 0.9rem 1.1rem !important;
  min-height: 2.75rem;                   /* 44px target, 2.5.8 */

  background: var(--vce-surface) !important;
  color: var(--vce-ink) !important;      /* 12.68:1 on Light Grey */
  border: 0 !important;
  border-left: 4px solid transparent !important;
  border-radius: var(--vce-radius-flat) !important;

  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: 1rem !important;
  text-transform: none !important;
  cursor: pointer;

  transition: background-color .15s ease, border-left-color .15s ease;
}

html body .vt-accordion-trigger:hover {
  background: var(--vce-white) !important;
  border-left-color: var(--vce-accent) !important;
}

/* Open state — rail plus a weight bump, so it isn't colour alone. */
html body .vt-accordion-trigger[aria-expanded="true"] {
  background: var(--vce-white) !important;
  border-left-color: var(--vce-brand-2) !important;
  font-weight: var(--vce-wt-display) !important;
  color: var(--vce-heading) !important;
}

html body .vt-accordion-panel {
  background: var(--vce-white) !important;
  border: 0 !important;
  border-left: 4px solid var(--vce-brand-2) !important;
}

html body .vt-accordion-body,
html body .vt-accordion-panel > .vt-item {
  padding: 0.5rem 1.1rem 1.25rem !important;
}

/* §12.2  Tabs ------------------------------------------------------------ */

html body .vt-tab-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  border: 0 !important;
  border-bottom: 2px solid var(--vce-rule) !important;
}

html body .vt-tab {
  padding: 0.75rem 1.25rem !important;
  min-height: 2.75rem;

  background: var(--vce-surface) !important;
  color: var(--vce-ink) !important;
  border: 0 !important;
  border-bottom: 3px solid transparent !important;
  border-radius: var(--vce-radius-flat) !important;

  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: 0.9375rem !important;
  text-transform: none !important;
  cursor: pointer;

  transition: background-color .15s ease, border-bottom-color .15s ease;
}

html body .vt-tab:hover {
  background: var(--vce-white) !important;
  border-bottom-color: var(--vce-accent) !important;
}

html body .vt-tab[aria-selected="true"] {
  background: var(--vce-white) !important;
  border-bottom-color: var(--vce-brand-2) !important;   /* 8.74:1 */
  color: var(--vce-heading) !important;
  font-weight: var(--vce-wt-display) !important;
}

html body .vt-tab-content,
html body .vt-tab-panel {
  background: var(--vce-white) !important;
  border: 0 !important;
}

html body .vt-tab-panel { padding: 1.25rem 0 !important; }

/* §12.3  Focus ----------------------------------------------------------- */
/* Inset, because these sit flush against each other and the §16 offset ring
   gets clipped by the neighbour. */

html body .vt-accordion-trigger:focus-visible,
html body .vt-tab:focus-visible,
html body .vt-tab-panel:focus-visible {
  outline: 3px solid var(--vce-focus) !important;
  outline-offset: -3px !important;
  box-shadow: none !important;
}

/* §12.4  Icons ----------------------------------------------------------- */
/* See the note at the top of §12 — these paths have no fill attribute. */

html body .vt-accordion-trigger svg,
html body .vt-accordion-trigger svg path,
html body .vt-tab svg,
html body .vt-tab svg path {
  fill: currentColor !important;
}

html body .vt-accordion-trigger svg {
  width: 0.85em;
  height: 0.85em;
  flex: 0 0 auto;
}


/* ══ §13  RULES, TABLES & QUOTES ═══════════════════════════════════════════ */

html body hr { border: 0; border-top: 2px solid var(--vce-accent); opacity: 1; }

html body .vt-text table { border-collapse: collapse; width: 100%; }

html body .vt-text th {
  background: var(--vce-brand-2) !important;
  color: var(--vce-brand-2-ink) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  text-align: left;
  padding: 0.6em 0.85em;
}

html body .vt-text td {
  border-bottom: 1px solid var(--vce-rule) !important;
  padding: 0.6em 0.85em;
}

html body .vt-text tbody tr:nth-child(even) td { background: var(--vce-surface) !important; }

html body .vt-text blockquote {
  border-left: 4px solid var(--vce-accent) !important;
  background: var(--vce-surface) !important;
  padding: 1rem 1.25rem;
  margin-inline: 0;
  color: var(--vce-ink) !important;
}

html body ::selection { background: var(--vce-teal); color: var(--vce-blue-dark); }
html body ::marker { color: var(--vce-brand); }


/* §13.1  Trailing rule  (utility) ---------------------------------------- */
/* Line from the end of the text to the right edge of the parent, centred on
   the text. Orange to Dark Blue, fading out across the last third.

     <h2 class="vce-rule-out">News and publications</h2>

   Works on any block element. Colour comes from `background`, the fade from
   `mask-image`, so either can be retuned without touching the other.

   WHY FLEX
     ::after takes exactly the leftover width, so the colour ramp is sized
     to the visible line. The usual overflow:hidden + margin-right:-100%
     trick also reaches the edge, but sizes the gradient to the full parent
     width, so you'd only ever see its first inch.

   ⚠ On a heading that wraps to two lines the rule sits beside the whole
     block, centred on both lines, not tucked against the last line. That's
     inherent to flex, and flex is what makes the gradient size correctly.

   DECORATIVE ON PURPOSE
     Empty ::after, so screen readers skip it — which also exempts it from
     the 3:1 non-text contrast floor. Just as well: Orange on white is
     2.87:1 and would fail if it carried meaning. Don't use it to signal. */

html body .vce-rule-out {
  --rule-h:      3px;
  --rule-gap:    0.75em;
  --rule-fade:   66.67%;   /* opaque to here, transparent by 100% */
  --rule-from:   var(--vce-orange);
  --rule-to:     var(--vce-blue-dark);

  display: flex;
  align-items: center;
  gap: var(--rule-gap);
}

html body .vce-rule-out::after {
  content: "";
  flex: 1 1 auto;
  min-width: 2rem;         /* never collapses on a long heading */
  height: var(--rule-h);
  border-radius: var(--rule-h);

  /* sRGB first as the fallback. Orange to Dark Blue runs muddy through
     sRGB; oklab keeps it clean and older browsers just use the line above. */
  background: linear-gradient(to right, var(--rule-from), var(--rule-to));
  background: linear-gradient(to right in oklab, var(--rule-from), var(--rule-to));

  -webkit-mask-image: linear-gradient(to right, #000 0, #000 var(--rule-fade), transparent 100%);
          mask-image: linear-gradient(to right, #000 0, #000 var(--rule-fade), transparent 100%);

  /* Nudges the line down off the cap-height so it reads as centred on the
     word rather than on the line box.
     ⚠ The parent is align-items:center, so a bottom margin shifts the line
     UP by half its value, not down — 15px here moves it 7.5px. And px won't
     scale if the heading size changes; 0.35em tracks the type. */
  margin-bottom: 15px;
}

/* The Dark Blue end vanishes on a dark ground. Teal is the substitute. */
html body .vce-on-dark .vce-rule-out,
html body .vce-panel-dark .vce-rule-out,
html body footer .vce-rule-out,
html body .vce-rule-out.vce-rule-out--on-dark {
  --rule-to: var(--vce-teal);
}

html body .vce-rule-out--thin  { --rule-h: 2px; }
html body .vce-rule-out--thick { --rule-h: 5px; }
html body .vce-rule-out--solid { --rule-fade: 100%; }


/* ══ §14  OFFICE TOP NAV ═══════════════════════════════════════════════════
   Turns a list of links into the office nav bar. Pure CSS — paints on the
   first frame, nothing to break in author mode.

   ── TWO MARKUP SHAPES, ONE RESULT ────────────────────────────────────────
   Put ext-office-top-nav in the CSS-class field and either shape works:

     SHAPE A — Text component. Author types a bulleted list of links.
       .ext-office-top-nav > … > .vt-text > ul > li > a

     SHAPE B — List component. AEM builds the list from pages.
       .ext-office-top-nav > … > .vt-c-card-list > li > .vt-list-item-wrapper
         > .vt-list-item-row > .vt-list-item-col > .vt-list-item-title
           > a.vt-list-item-title-link

   Shape B is the better one to standardise on: the links are real page
   references, so titles and URLs follow the pages when they move, and
   authors can't typo a path. Shape A is only better when the nav points
   somewhere outside the site tree.

   ── WHAT SHAPE B HAS TO UNDO ─────────────────────────────────────────────
   The List component renders a card, not a nav item, so §14.2 strips three
   layers of it:
     1. Bootstrap. The li carries col-md-12, which is flex:0 0 100% and
        max-width:100% — it would stack every item full width.
     2. vt-one card chrome. The "General Item" heading and its icon, and the
        empty .vt-list-item-imgWrapper column, which would otherwise eat
        half the width of every item.
     3. §11 of this file. The card background, border, top rail and column
        flex are all set with !important there, so undoing them here needs
        !important too. That's the one place in the theme where !important
        is fighting !important, and it's why §14 must stay after §11.

   ── EQUAL HEIGHTS WHEN A LABEL WRAPS ─────────────────────────────────────
   One two-line label makes the whole row taller. The li stretches to match
   (flex default), but everything BELOW the li has to stretch too or the
   anchor stays one line tall — and the anchor is what carries the hover
   fill and the teal rail, so they stop short while the cell around them
   looks fine. That was the v2.3 bug.

   Shape A nests two boxes: li > a.
   Shape B nests five: li > wrapper > row > col > title > a.
   Every one of them now sets align-items/align-self: stretch explicitly.
   Miss a single link in that chain and the symptom comes straight back, so
   if you add a wrapper to either shape, give it stretch as well.

   .vt-list-item-row also carries Bootstrap's .row, which is flex-wrap:wrap.
   A wrapped single line makes stretch depend on align-content instead of
   align-items, which is fragile — §14.2 forces nowrap to take that out of
   the equation.

   ⚠ Turn OFF horizontal scroll in the List dialog. It adds its own scroll
     buttons and a .vt-list-horizontal-scroll wrapper that fights the flex
     row. §14.6 is the scrolling variant if you want one.

   VARIANTS (alongside ext-office-top-nav in the class field)
     (none)           Dark Green bar, white labels, teal rail
     vce-nav--light   Light Grey bar, Dark Blue labels, Maroon rail
     vce-nav--rail    One scrolling row on small screens

   Teal works as the rail here because it sits on Dark Green (5.31:1). On
   the light variant it would be 1.37:1, so that one uses Maroon. Don't
   swap them.
========================================================================== */

/* §14.0  The bar — both shapes ------------------------------------------- */

html body .ext-office-top-nav {
  --nav-bg:        var(--vce-green);
  --nav-ink:       var(--vce-white);
  --nav-hover-bg:  #1f6779;                  /* Dark Green + 12% white */
  --nav-mark:      var(--vce-teal);
  --nav-divider:   rgba(255, 255, 255, 0.22);
  --nav-pad-y:     0.85rem;
  --nav-pad-x:     1rem;

  background: var(--nav-bg) !important;
}

html body .ext-office-top-nav.vce-nav--light {
  --nav-bg:       var(--vce-grey-light);
  --nav-ink:      var(--vce-blue-dark);
  --nav-hover-bg: var(--vce-white);
  --nav-mark:     var(--vce-maroon);
  --nav-divider:  var(--vce-rule);
}

/* Flatten every wrapper between the container and the list, whichever
   shape it is. Bootstrap's .row negative margins live here too. */
html body .ext-office-top-nav .vt-vtcontainer-content,
html body .ext-office-top-nav .text.parbase.section,
html body .ext-office-top-nav .vt-text,
html body .ext-office-top-nav .vt-list-columns,
html body .ext-office-top-nav .vt-list-items {
  margin: 0 !important;
  padding: 0 !important;
}

/* §14.1  Shape A — the text component list ------------------------------- */

html body .ext-office-top-nav .vt-text ul {
  list-style: none !important;
  margin: 0 !important;
  padding: 0 !important;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;      /* cells match the tallest in their row */
}

/* §14.2  Shape B — the List component ------------------------------------ */

html body .ext-office-top-nav .vt-c-card-list {
  list-style: none !important;
  margin: 0 !important;
  padding: 0 !important;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;      /* cells match the tallest in their row */
}

/* Undo Bootstrap's column sizing on the li. */
html body .ext-office-top-nav .vt-c-card-list > li {
  max-width: none !important;
  width: auto !important;
}

/* Undo §11's card treatment. !important against !important — see the note
   at the top of this section. */
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-wrapper {
  display: flex !important;
  flex-direction: row !important;
  flex: 1 1 auto;
  align-items: stretch !important;   /* equal heights — see §14 header */
  align-self: stretch !important;
  height: auto !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  margin: 0 !important;
  padding: 0 !important;
  transition: none !important;
}

html body .ext-office-top-nav .vt-c-card-list .vt-list-item-wrapper:hover,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-wrapper:focus-within {
  border: 0 !important;
  box-shadow: none !important;
}

/* Card furniture a nav item doesn't want. The "General Item" heading is
   boilerplate the component emits for every row, and the image column is
   empty here — left in place it would take half the width of each item. */
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-heading,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-tags,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-desc,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-date,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-time,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-col:has(.vt-list-item-imgWrapper) {
  display: none !important;
}

/* Without :has() the image column survives as dead space. Collapsing it to
   zero width is the graceful degradation. */
@supports not selector(:has(*)) {
  html body .ext-office-top-nav .vt-c-card-list .vt-list-item-imgWrapper {
    display: none !important;
  }
  html body .ext-office-top-nav .vt-c-card-list .vt-list-item-col:empty {
    flex: 0 0 0 !important;
    padding: 0 !important;
  }
}

/* The remaining row / column / title are pass-through boxes. */
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-row,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-col,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title {
  display: flex !important;
  flex: 1 1 auto;
  min-width: 0;

  /* The middle of the five-box chain. nowrap kills Bootstrap's .row wrap so
     stretch comes from align-items, not align-content. */
  align-items: stretch !important;
  align-self: stretch !important;
  flex-wrap: nowrap !important;
  height: auto !important;
  max-width: none !important;
  width: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  font-weight: inherit !important;
  color: inherit !important;
}

/* §14.3  Items and links — both shapes ----------------------------------- */
/* flex-basis drives the columns, so any item count falls out correctly. */

html body .ext-office-top-nav .vt-text ul > li,
html body .ext-office-top-nav .vt-c-card-list > li {
  flex: 1 1 50%;                  /* 2 across */
  min-width: 0;
  margin: 0 !important;
  padding: 0 !important;
  line-height: 1.25 !important;   /* overrides the §3 body 1.6 */
  display: flex;
  align-items: stretch;           /* the child fills the cell */
  align-self: stretch;            /* the cell fills the row */
  border-right: 1px solid var(--nav-divider);
  border-bottom: 1px solid var(--nav-divider);
}

html body .ext-office-top-nav .vt-text ul > li:last-child,
html body .ext-office-top-nav .vt-c-card-list > li:last-child {
  border-right: 0;
}

/* Breakpoints. Content driven, not device driven: the widths at which six
   ~14ch labels stop crowding. Re-tune for longer labels. */

@media (min-width: 34rem) {
  html body .ext-office-top-nav .vt-text ul > li,
  html body .ext-office-top-nav .vt-c-card-list > li { flex-basis: 33.333%; }
}

@media (min-width: 56rem) {
  html body .ext-office-top-nav .vt-text ul > li,
  html body .ext-office-top-nav .vt-c-card-list > li {
    flex: 1 1 auto;
    border-bottom: 0;
  }
}

/* The link itself. Specificity here clears §4's link rules and §11's
   .vt-list-item-title-link colour. */

html body .ext-office-top-nav .vt-text ul > li > a,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link {
  flex: 1 1 auto;
  display: flex;
  align-items: center;            /* centres the label in a taller cell */
  justify-content: center;
  text-align: center;
  gap: .4em;

  /* The end of the chain, and the one that matters most: this element
     paints the hover fill and the rail, so it must fill the cell. */
  align-self: stretch;

  padding: var(--nav-pad-y) var(--nav-pad-x);
  min-height: 2.75rem;            /* 44px pointer target, 2.5.8 */

  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: clamp(.875rem, 1.1vw, .9375rem);
  text-transform: none !important;
  line-height: 1.25 !important;

  color: var(--nav-ink) !important;
  text-decoration: none !important;
  background: transparent;

  box-shadow: inset 0 -3px 0 transparent;
  transition: background-color .15s ease, box-shadow .15s ease;
}

html body .ext-office-top-nav .vt-text ul > li > a:visited,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link:visited {
  color: var(--nav-ink) !important;
}

html body .ext-office-top-nav .vt-text ul > li > a:hover,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link:hover {
  background: var(--nav-hover-bg);
  color: var(--nav-ink) !important;
  text-decoration: none !important;
  box-shadow: inset 0 -3px 0 var(--nav-mark);
}

/* Needs aria-current from vce-office-nav-enhance.html, or author by hand. */
html body .ext-office-top-nav .vt-text ul > li > a[aria-current],
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link[aria-current] {
  background: var(--nav-hover-bg);
  box-shadow: inset 0 -3px 0 var(--nav-mark);
  font-weight: var(--vce-wt-display) !important;
}

/* §14.4  Focus — inset, or the neighbour clips it ------------------------ */

html body .ext-office-top-nav .vt-text ul > li > a:focus-visible,
html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link:focus-visible {
  outline: 3px solid var(--vce-white) !important;
  outline-offset: -5px !important;
  box-shadow: 0 0 0 3px var(--vce-blue-dark) inset !important;
}

html body .ext-office-top-nav.vce-nav--light .vt-text ul > li > a:focus-visible,
html body .ext-office-top-nav.vce-nav--light .vt-c-card-list .vt-list-item-title-link:focus-visible {
  outline-color: var(--vce-blue-dark) !important;
  box-shadow: 0 0 0 3px var(--vce-white) inset !important;
}

/* §14.5  Unlinked items — Shape A only ----------------------------------- */
/* A bare <li> is not navigation: nothing to activate, nothing for a
   keyboard to reach, nothing a screen reader announces. Rendered as dimmed
   text so the gap is obvious in authoring rather than shipping as a dead
   button. Link the item to fix it.

   Shape B can't hit this — the List component always emits an anchor. */

html body .ext-office-top-nav .vt-text ul > li:not(:has(a)) {
  align-items: center;
  justify-content: center;
  padding: var(--nav-pad-y) var(--nav-pad-x);
  min-height: 2.75rem;
  font-family: var(--vce-font) !important;
  font-weight: var(--vce-wt-label) !important;
  letter-spacing: var(--vce-track-label) !important;
  font-size: clamp(.875rem, 1.1vw, .9375rem);
  color: var(--nav-ink) !important;
  opacity: .55;
  font-style: italic;
}

/* §14.6  Scrolling rail variant — both shapes ---------------------------- */
/* Trade-off: off-screen items are less discoverable. Prefer the default
   grid unless you have more than about eight links. */

@media (max-width: 55.99rem) {
  html body .ext-office-top-nav.vce-nav--rail .vt-text ul,
  html body .ext-office-top-nav.vce-nav--rail .vt-c-card-list {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  html body .ext-office-top-nav.vce-nav--rail .vt-text ul > li,
  html body .ext-office-top-nav.vce-nav--rail .vt-c-card-list > li {
    flex: 0 0 auto;
    border-bottom: 0;
    scroll-snap-align: start;
  }
  html body .ext-office-top-nav.vce-nav--rail .vt-text ul > li > a,
  html body .ext-office-top-nav.vce-nav--rail .vt-c-card-list .vt-list-item-title-link {
    white-space: nowrap;
  }
}


/* ══ §15  ABOUT SECTION SWOOSH ═════════════════════════════════════════════
   Curves the right edge of .ext-office-section-about into the background
   photo instead of ending it on a hard rectangle.

   THE CURVE
     Authentic brand-guide swoosh (p.49), flipped vertically so the panel
     widens top to bottom. Measured against the mockup at 19 points: mean
     deviation 0.0067 of the box width. The real path, not a redraw.

   WHY A MASK, NOT A BAKED-IN FILL
     background-color: inherit means the wedge always picks up the panel's
     background. The panel is Light Grey below; change that one line, or add
     vce-about--white, and the curve follows on its own — one place to edit,
     no chance of drift.

   PROPORTIONS
     1:1 by default, which is what the mockup measures (634 x 634), well
     inside the 16:9 ceiling from p.51. --about-swoosh-w only ever makes it
     narrower, never flatter, so the stretch rule holds.
========================================================================== */

html body .ext-office-section-about {
  --about-swoosh-w: min(30vw, 34rem);
  position: relative;
  background-color: var(--vce-grey-light) !important;
}

/* Panel width. Lives here because it was cleared from the container dialog.
   No !important on purpose — an author who sets a width in the dialog
   should still win. */
@media (min-width: 62rem) {
  html body .ext-office-section-about {
    max-width: var(--about-panel-w);
    margin-right: auto;      /* stays flush left, as the wedge assumes */
  }
}

html body .ext-office-section-about::after {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: var(--about-swoosh-w);

  /* Tucked 1px under the panel's edge to close the hairline seam that
     sub-pixel rounding leaves between panel and wedge. A fixed pixel rather
     than a percentage, so the overlap is the same at every panel width.
     The vce-about--left variant in §15.1 mirrors this with `right`. */
  left: calc(100% - 1px);

  /* Guard rail against a horizontal scrollbar. 100% resolves to the panel's
     own width, so this is literally the space left over. The subtraction
     covers the vertical scrollbar, which 100vw includes and the document
     width does not.
     ⚠ Assumes the panel is flush left. If you ever centre it, halve this:
     calc((100vw - 100%) / 2 - 1.25rem). */
  max-width: calc(100vw - 100% - 1.25rem);

  background-color: inherit;

  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 425 381.3' preserveAspectRatio='none'%3E%3Cpath d='M0 0C0 66.31 92.74 134.71 212.67 190.65C332.44 246.63 425 304.28 425 381.3L0 381.3Z' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 425 381.3' preserveAspectRatio='none'%3E%3Cpath d='M0 0C0 66.31 92.74 134.71 212.67 190.65C332.44 246.63 425 304.28 425 381.3L0 381.3Z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;

  pointer-events: none;

  /* Decoration tier — see §15.3. */
  z-index: var(--z-decor);
}

/* §15.1  Variants -------------------------------------------------------- */

/* Light tint panel — needs !important, the dialog writes background-color
   inline. Dark Blue on Light Grey is 12.68:1. */
html body .ext-office-section-about.vce-about--white {
  background-color: var(--vce-white) !important;
}

/* Photo on the left instead — same path, reflected. */
html body .ext-office-section-about.vce-about--left::after {
  left: auto;
  right: calc(100% - 1px);   /* same 1px seam overlap as the default */
  transform: scaleX(-1);
}

/* Shallower curve for a short panel. */
html body .ext-office-section-about.vce-about--subtle {
  --about-swoosh-w: min(18vw, 20rem);
}

/* §15.2  Small viewports — Stack configuration (guide p.50) -------------- */
/* Photo becomes a full-width band above the panel with the swoosh rotated
   horizontal. Requires ext-office-about-band on the PARENT container.
   The max-width release is a guard: the dialog width is cleared today, but
   other sites may still carry one. */

@media (max-width: 61.99rem) {
  html body .ext-office-section-about {
    max-width: none !important;
    width: auto !important;
    padding-left:  clamp(1.25rem, 5vw, 3rem) !important;
    padding-right: clamp(1.25rem, 5vw, 3rem) !important;
  }

  html body .ext-office-about-band {
    background-size: cover !important;
    background-position: center !important;
    padding-top: 42vw !important;
    max-height: none !important;
  }

  html body .ext-office-section-about::after {
    display: block;
    left: 0;
    top: auto;
    bottom: 100%;
    width: 100%;
    height: min(18vw, 7rem);
    max-width: none;
  }
}

/* §15.3  Stacking ------------------------------------------------------- */
/* Two layers on the §2 ladder:

     swoosh (§15)       --z-decor     1   decoration, bottom tier
     #vt_right_col      --z-content 100   chrome that must sit over it

   This used to be swoosh 100, column 1000. The swoosh is decorative, so it
   never belonged in a content tier, and once it was there the column had to
   jump past it. With decoration at the bottom the column needs only the
   next tier up, and there's clean room either side of both.

   ⚠ TEST AFTER PUBLISHING. The swoosh was originally raised to 100 to clear
   something, and I don't know what. If it now disappears behind part of
   the photo band, that element has a z-index between 1 and 99. Tell me what
   it is and it gets a tier of its own — don't just raise the swoosh back.

   ⚠ Check the drawer and search panel still open OVER the right column.
   Those are vt-one's and carry their own z-index, which this file doesn't
   set. At 1000 the column had a real chance of covering them; at 100 it
   is much less likely, but it's the one interaction worth eyeballing.

   #vt_right_col only honours z-index because Bootstrap's .row makes it a
   flex item. If vt-one ever changes that layout, this silently stops
   working — and the fix then is position:relative, not a bigger number. */

/* (#vt_right_col's background lives in §5.1.) */
html body section#vt_right_col {
  z-index: var(--z-content);
}

/* Not carrying ext-office-about-band? Then the panel simply goes full width
   and covers whatever is behind it, and the wedge would float over the top
   of nothing. Switch it off:

@media (max-width: 61.99rem) {
  html body .ext-office-section-about:not(.ext-office-about-band *)::after {
    display: none;
  }
}
*/


/* ══ §16  ACCESSIBILITY FLOOR ══════════════════════════════════════════════
   The dark-ground focus rings live in §6.4 with their surfaces; the inset
   rings for flush components live in §12.3 and §14.4.
========================================================================== */

/* Two-tone ring, 3:1 against both neighbours — WCAG 2.4.11 / 1.4.11. */
html body a:focus-visible,
html body button:focus-visible,
html body input:focus-visible,
html body select:focus-visible,
html body textarea:focus-visible,
html body [tabindex]:focus-visible {
  outline: 3px solid var(--vce-focus) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 6px var(--vce-focus-halo) !important;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  html body *,
  html body *::before,
  html body *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Don't fight Windows High Contrast — hand the colours back to the OS. */
@media (forced-colors: active) {
  html body a.vt-ctaLink,
  html body .vce-lozenge,
  html body .vt-c-card-list .vt-list-item-wrapper {
    border: 2px solid ButtonBorder !important;
    forced-color-adjust: none;
    background: ButtonFace !important;
    color: ButtonText !important;
  }

  html body .vt-accordion-trigger,
  html body .vt-tab {
    background: ButtonFace !important;
    color: ButtonText !important;
    border: 1px solid ButtonBorder !important;
  }
  html body .vt-accordion-trigger[aria-expanded="true"],
  html body .vt-tab[aria-selected="true"] {
    outline: 2px solid Highlight;
    outline-offset: -4px;
  }

  /* Gradients and masks don't survive forced-colors — hand it to the OS. */
  html body .vce-rule-out::after {
    background: CanvasText !important;
    -webkit-mask-image: none !important;
            mask-image: none !important;
  }

  html body .ext-office-top-nav { background: Canvas !important; }
  html body .ext-office-top-nav .vt-text ul > li,
  html body .ext-office-top-nav .vt-c-card-list > li { border-color: ButtonBorder; }
  html body .ext-office-top-nav .vt-text ul > li > a,
  html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link {
    color: LinkText !important;
    box-shadow: none;
  }
  html body .ext-office-top-nav .vt-text ul > li > a[aria-current],
  html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link[aria-current] {
    box-shadow: none;
    outline: 2px solid Highlight;
    outline-offset: -4px;
  }
}


/* ══ §17  PRINT ════════════════════════════════════════════════════════════
   All print rules in one place. v1 had three separate blocks.
========================================================================== */

@media print {
  html body .vt-page-path,
  html body .vt-page-info,
  html body .ext-office-top-nav,
  html body footer .vt-footer-row,
  html body footer .vt-footer-bottom {
    background: #fff !important;
  }

  html body .vt-breadcrumbs-link,
  html body .vt-footer-link,
  html body .vt-page-info .vt-page-title,
  html body .ext-office-top-nav .vt-text ul > li > a,
  html body .ext-office-top-nav .vt-c-card-list .vt-list-item-title-link {
    color: #000 !important;
  }

  html body .ext-office-section-about::after { display: none; }

  /* Most printers render the gradient as a grey smear. */
  html body .vce-rule-out { display: block; }
  html body .vce-rule-out::after { display: none; }

  /* Accordions print collapsed by default, which loses content. */
  html body .vt-accordion-panel,
  html body .vt-tab-panel {
    display: block !important;
    border-left-color: #000 !important;
  }
}


/* ══ §18  PER-SITE OVERRIDES ═══════════════════════════════════════════════
   Redefine tokens, never declarations. Uncomment what a given site needs.
========================================================================== */

/* Headings back to the guide's Dark Blue instead of Dark Green:
:root { --vce-heading: var(--vce-ink); }
*/

/* Dark Grey chrome instead of Dark Green (ARECs, VAES):
:root {
  --vce-brand-2:       var(--vce-grey-dark);
  --vce-brand-2-hover: var(--vce-grey-shade);
  --vce-link:          var(--vce-grey-shade);
}
*/

/* Maroon-forward chrome (main VCE site):
:root {
  --vce-brand-2:       var(--vce-maroon);
  --vce-brand-2-hover: var(--vce-maroon-shade);
}
*/

/* Lighter page-title band instead of Dark Blue — remember to flip the ink
   in §6.2 as well, or the title goes white on Light Grey (1.2:1):
:root { --vce-pageinfo-bg: var(--vce-grey-light); }
html body .vt-page-info,
html body .vt-page-info .vt-page-title { color: var(--vce-heading) !important; }
*/

/* Narrower about panel:
:root { --about-panel-w: 60vw; }
*/

/* Inherited page colour back to Dark Blue instead of Dark Green — see the
   warning in §3.3 about what this affects:
html body .container-fluid,
html body .container-lg,
html body .container-md,
html body .container-sm,
html body .container-xl { color: var(--vce-ink) !important; }
*/

/* Orange link hover — measured at 2.87:1 on white, which fails 1.4.3 for
   body text. Uncomment only as a deliberate, documented exception:
:root { --vce-link-hover: var(--vce-orange); }
*/

/* Weakest pill given more headroom — Dark Grey shade, 5.92:1 not 5.03:1:
html body .vt-list-item-tags-tag:has(a[href*=":home-office/"], a[href*="%3Ahome-office/"], a[data-vce-tag-href*=":home-office/"], a[data-vce-tag-href*="%3Ahome-office/"])
  .vt-list-item-tags-link { --pill-bg: var(--vce-grey-shade); }
*/

/* Tag pills clickable again — skip vce-tag-pills-disable.html and:
html body .vt-list-item-tags .vt-list-item-tags-link { pointer-events: auto; cursor: pointer; }
*/

/* Trailing rule in different brand colours:
html body .vce-rule-out { --rule-from: var(--vce-maroon); --rule-to: var(--vce-green); }
*/

/* Keep vt-one's default black footer:
html body footer .vt-footer-row,
html body footer .vt-footer-bottom { background: #000 !important; }
*/

/* ══ END ══════════════════════════════════════════════════════════════════ */

html body .vt-image {
  border-radius: 0 !important;
}

html body .vt-callToAction-popover {
  width: 100cqw !important;
}

html body .vt-callToAction-message.vt-callToAction-flexContainer {
  /* border-radius: 1em !important; */
  background: color-mix(in srgb, var(--vce-surface) 80%, transparent) !important;
}

@media (min-width: 992px) {
  html body .vt-callToAction-message.vt-callToAction-flexContainer {
    max-width: 50% !important;
  }
}

.vt-callToAction.vt-callToAction-popover .vt-ctaLink {
  width: fit-content !important;
}

html body .ext-table-smallImage .vt-list-table .vt-list-item-picture {
  max-width: 15em !important;
}

html body .vt-list-item-tags .vt-list-item-tags-link {
  padding: 0.5em 1em !important;
  max-width: max-content !important;
}

html body .vt-callToAction.vt-callToAction-popover .vt-callToAction-message {
  margin-left: 10% !important;
  min-width: 100% !important;
  max-width: max-content !important;
}

html body main#vt_main,
html body .home-content {
  background: white !important;
}

@media screen and (min-width: 992px) {
    .vt-callToAction {
        padding-bottom: 0 !important;
    }
}

html body .vt-callToAction.vt-callToAction-popover .vt-callToAction-flexContainer-left {
  max-width: 40vw !important;
}

@media  screen and (max-width: 768.1px ) {
  html body .vt-callToAction.vt-callToAction-popover .vt-callToAction-flexContainer {
    min-width: 100cqw !important;
    margin-left: 0 !important;
  }
}

html body .vce-staff-list-wrapper {
  min-height: 600px !important;
}

html body .ext-office-section-about {
  padding: 5em 5% !important;
}

.vt-callToAction-message-heading .vt-callToAction-message-description {
    margin-bottom: 0 !important;
}
