/* ==========================================================================
   JSM 2026 — Jabatan Standard Malaysia portal template
   Loaded on top of Cassiopeia's compiled CSS.

   Everything is written against custom properties. index.php redefines any of
   them from the template style, after this file, so the whole portal can be
   recoloured and re-spaced without touching a stylesheet.
   ========================================================================== */

:root {
    /* Palette */
    --jsm-navy:      #21395c;
    --jsm-navy-d:    #1a2e4a;
    --jsm-blue:      #0e4a86;
    --jsm-blue-d:    #0b3c6e;
    --jsm-blue-l:    #1c82b8;
    --jsm-red:       #e0242a;
    --jsm-yellow:    #f2b307;
    --jsm-gold:      #f0a92b;

    --jsm-ink:       #333d4d;
    --jsm-muted:     #5d6b7c;
    --jsm-line:      #e2e6ec;
    --jsm-surface:   #f5f7fa;
    --jsm-white:     #ffffff;

    /* Type */
    --jsm-font-head: "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --jsm-font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --jsm-base-size: 16px;

    /* Measure */
    --jsm-wrap:      1240px;
    --jsm-gutter:    24px;
    --jsm-band-pad:  4.5rem;

    --jsm-radius-lg: 18px;
    --jsm-radius-md: 12px;
    --jsm-radius-sm: 8px;

    --jsm-shadow:    0 1px 2px rgba(33, 57, 92, .06), 0 10px 28px -18px rgba(33, 57, 92, .45);
    --jsm-shadow-lg: 0 2px 6px rgba(33, 57, 92, .08), 0 22px 48px -24px rgba(33, 57, 92, .55);

    --jsm-hero-min:   clamp(26rem, 46vw, 38rem);
    --jsm-hero-focus: center 38%;

    --jsm-focus: 3px solid var(--jsm-blue-l);
}

/* ==========================================================================
   Base
   ========================================================================== */

body.jsm {
    font-family: var(--jsm-font-body);
    font-size: var(--jsm-base-size);
    line-height: 1.6;
    color: var(--jsm-ink);
    background: var(--jsm-white);
    -webkit-font-smoothing: antialiased;
}

/**
 * Element defaults, pitched at exactly 0,0,1 — the prefix is wrapped in
 * :where() so it adds nothing, and the bare element supplies the one point.
 *
 * That number is the whole trick. `body.jsm a` scores 0,1,1 and quietly
 * outranks `.jsm-btn-primary` at 0,1,0, which paints the hero buttons blue on
 * blue. Dropping to 0,0,0 goes too far the other way: Cassiopeia's own `a` and
 * `h1` are 0,0,1 and win instead. At 0,0,1 these tie with Cassiopeia and take
 * it on load order, while any class rule below still beats them outright.
 */
:where(body.jsm) h1,
:where(body.jsm) h2,
:where(body.jsm) h3,
:where(body.jsm) h4 {
    font-family: var(--jsm-font-head);
    font-weight: 700;
    line-height: 1.18;
    letter-spacing: -.015em;
    color: var(--jsm-navy);
}

:where(body.jsm) a {
    color: var(--jsm-blue);
    text-underline-offset: 2px;
}

body.jsm :focus-visible {
    outline: var(--jsm-focus);
    outline-offset: 2px;
    border-radius: 4px;
}

:where(body.jsm) :where(img) {
    max-width: 100%;
    height: auto;
}

.jsm .wrap {
    max-width: var(--jsm-wrap);
    margin-inline: auto;
    padding-inline: var(--jsm-gutter);
}

.jsm.wrapper-fluid .wrap {
    max-width: none;
}

.jsm-visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------- Buttons */

.jsm-btn {
    display: inline-flex;
    align-items: center;
    gap: .5em;
    padding: .8em 1.6em;
    border: 2px solid transparent;
    border-radius: 999px;
    font-family: var(--jsm-font-head);
    font-weight: 600;
    font-size: .95rem;
    line-height: 1.1;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease, transform .1s ease;
}

.jsm-btn svg {
    width: 1.05em;
    height: 1.05em;
    flex: none;
}

.jsm-btn:active {
    transform: translateY(1px);
}

.jsm-btn-primary {
    color: var(--jsm-white);
    background: var(--jsm-blue);
    border-color: var(--jsm-blue);
}

.jsm-btn-primary:hover,
.jsm-btn-primary:focus {
    color: var(--jsm-white);
    background: var(--jsm-blue-d);
    border-color: var(--jsm-blue-d);
}

.jsm-btn-ghost {
    color: var(--jsm-white);
    border-color: rgba(255, 255, 255, .7);
}

.jsm-btn-ghost:hover,
.jsm-btn-ghost:focus {
    color: var(--jsm-navy);
    background: var(--jsm-white);
    border-color: var(--jsm-white);
}

/* Solid white on a photograph — the inverse of the ghost. */
.jsm-btn-light {
    color: var(--jsm-navy);
    background: var(--jsm-white);
    border-color: var(--jsm-white);
}

.jsm-btn-light:hover,
.jsm-btn-light:focus {
    color: var(--jsm-navy-d);
    background: var(--jsm-surface);
    border-color: var(--jsm-surface);
}

/* Solid red — the hero's first call to action. */
.jsm-btn-red {
    color: var(--jsm-white);
    background: var(--jsm-red);
    border-color: var(--jsm-red);
}

.jsm-btn-red:hover,
.jsm-btn-red:focus {
    color: var(--jsm-white);
    /* No darker red token, so this is the one mixed on the spot. */
    background: color-mix(in srgb, var(--jsm-red) 84%, #000);
    border-color: color-mix(in srgb, var(--jsm-red) 84%, #000);
}

/* Solid gold — the landing page's call to action. */
.jsm-btn-gold {
    color: var(--jsm-navy-d);
    background: var(--jsm-yellow);
    border-color: var(--jsm-yellow);
}

.jsm-btn-gold:hover,
.jsm-btn-gold:focus {
    color: var(--jsm-navy-d);
    background: var(--jsm-gold);
    border-color: var(--jsm-gold);
}

/* The chevron the landing design uses in place of the arrow glyph. */
.jsm-btn-chev {
    font-size: 1.35em;
    line-height: 0;
    translate: 0 -.04em;
}

.jsm-textlink {
    display: inline-flex;
    align-items: center;
    gap: .4em;
    font-weight: 600;
    text-decoration: none;
    border-bottom: 2px solid currentColor;
    padding-bottom: 2px;
}

.jsm-textlink svg {
    width: 1em;
    height: 1em;
}

/* ---------------------------------------------------------------- Skip links */

.jsm-skiplinks {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 999;
}

.jsm-skiplink {
    position: absolute;
    left: -9999px;
    padding: .6rem 1rem;
    background: var(--jsm-navy);
    color: var(--jsm-white);
    text-decoration: none;
    white-space: nowrap;
}

.jsm-skiplink:focus {
    left: .5rem;
    top: .5rem;
    color: var(--jsm-white);
}

/* ==========================================================================
   Government identification bar
   ========================================================================== */

.jsm-govbar {
    background: var(--jsm-surface);
    border-bottom: 1px solid var(--jsm-line);
    font-size: .8rem;
}

.jsm-govbar-inner {
    padding-block: .45rem;
}

.jsm-govbar-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1rem;
    cursor: pointer;
    list-style: none;
    color: var(--jsm-muted);
}

.jsm-govbar-summary::-webkit-details-marker {
    display: none;
}

.jsm-govbar-brand {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

.jsm-govbar-flag {
    width: 26px;
    height: auto;
    border-radius: 2px;
}

.jsm-govbar-toggle {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    color: var(--jsm-blue);
    font-weight: 600;
}

.jsm-govbar-chevron {
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    transition: transform .15s ease;
}

.jsm-govbar-inner[open] .jsm-govbar-chevron {
    transform: rotate(180deg);
}

.jsm-govbar-panel {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    gap: 1rem 2rem;
    padding: .9rem 0 .6rem;
}

.jsm-govbar-item {
    display: flex;
    gap: .6rem;
}

.jsm-govbar-ico {
    font-size: 1.1rem;
    line-height: 1.2;
}

.jsm-govbar-h {
    margin: 0 0 .15rem;
    font-weight: 700;
    color: var(--jsm-navy);
}

.jsm-govbar-p {
    margin: 0;
    color: var(--jsm-muted);
}

/* ==========================================================================
   Header
   ========================================================================== */

.jsm-header {
    background: var(--jsm-white);
    border-bottom: 1px solid var(--jsm-line);
}

.jsm-header.is-sticky {
    position: sticky;
    top: 0;
    z-index: 100;
}

/**
 * The masthead block — identity row plus search — and the soft shadow it casts
 * onto the navigation below.
 *
 * A radial gradient rather than a box-shadow, because the design feathers it
 * away at both ends instead of running it edge to edge: an ellipse centred on
 * the page, strongest in the middle, gone by the margins. z-index keeps it
 * painting over the nav, which is a later sibling and would otherwise cover it.
 */
.jsm-masthead {
    position: relative;
    z-index: 2;
    background: var(--jsm-white);
    border-bottom: 1px solid var(--jsm-line);
}

.jsm-masthead::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 24px;
    pointer-events: none;
    background: radial-gradient(58% 100% at 50% 0%,
        rgba(13, 31, 54, .18) 0%,
        rgba(13, 31, 54, .08) 42%,
        rgba(13, 31, 54, .02) 68%,
        rgba(13, 31, 54, 0) 100%);
}

/**
 * flex-wrap matters here: the search bar is a sibling at flex 1 1 100%, and
 * without wrapping it cannot claim a line of its own — it squeezes in beside
 * the icon rail and forces that into two rows instead.
 */
.jsm-identity {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding-block: 1.1rem;
}

/**
 * The wordmark is the masthead, so it gets the room: a tall lockup that keeps
 * its own width rather than being squeezed by the icon rail beside it. 62px is
 * the height the design draws it at — roughly 540px wide for the full
 * crest-plus-ministry lockup.
 */
.jsm-brand {
    display: inline-flex;
    align-items: center;
    gap: .75rem;
    flex: 0 1 auto;
    min-width: 0;
    text-decoration: none;
}

.jsm-brand-jata {
    max-height: 68px;
    width: auto;
    flex: none;
}

.jsm-brand-mark {
    max-height: 62px;
    width: auto;
    flex: none;
}

.jsm-brand-text {
    font-size: .8rem;
    line-height: 1.3;
    color: var(--jsm-muted);
    max-width: 18ch;
}

.jsm-identity-actions {
    display: flex;
    align-items: center;
    gap: 1.2rem;
}

/* ---------------------------------------------------- Utility icon rail */

/**
 * Icon over label, which is why the labels are so small: four of them have to
 * sit across the top right without crowding the wordmark.
 */
.jsm-utilrail {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1.1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.jsm-utilrail a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .25rem;
    max-width: 4.6rem;
    color: var(--jsm-ink);
    font-size: .62rem;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
}

.jsm-utilrail a:hover,
.jsm-utilrail a:focus {
    color: var(--jsm-red);
}

.jsm-utilrail-icon {
    position: relative;
    display: grid;
    place-items: center;
    height: 1.5rem;
}

.jsm-utilrail-icon img {
    max-height: 1.5rem;
    width: auto;
    object-fit: contain;
}

.jsm-utilrail-badge {
    position: absolute;
    top: -.45em;
    left: -.8em;
    padding: .12em .32em;
    border-radius: 2px;
    background: var(--jsm-red);
    color: var(--jsm-white);
    font-size: .5rem;
    font-style: normal;
    font-weight: 700;
    line-height: 1.3;
}

/* ------------------------------------------------------------- Controls */

.jsm-identity-controls {
    display: flex;
    align-items: center;
    gap: .9rem;
    padding-left: 1.2rem;
    border-left: 1px solid var(--jsm-line);
}

.jsm-ctrl {
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    background: none;
    color: var(--jsm-blue-l);
    line-height: 1;
    cursor: pointer;
}

.jsm-ctrl svg {
    width: 1.3rem;
    height: 1.3rem;
}

.jsm-ctrl img {
    max-height: 1.35rem;
    width: auto;
    object-fit: contain;
}

.jsm-lang {
    font-size: .9rem;
    font-weight: 600;
}

.jsm-lang a {
    color: var(--jsm-blue-l);
    text-decoration: none;
}

.jsm-lang ul {
    display: flex;
    gap: .4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* ------------------------------------------------------------ Search bar */

/**
 * A row of its own under the identity line rather than a popover, so the field
 * is the width of the page when it opens.
 */
.jsm-searchbar {
    flex: 1 1 100%;
    padding-top: .9rem;
}

.jsm-searchbar[hidden] {
    display: none;
}

.jsm-searchbar form {
    display: flex;
    align-items: stretch;
    gap: .5rem;
}

/**
 * mod_finder puts the field and the button inside .input-group, so that
 * wrapper is the form's flex child — not the input. Stretching the input alone
 * does nothing; the group has to be the thing that grows, and the label beside
 * it is visually hidden and must not claim a share.
 */
.jsm-searchbar .input-group,
.jsm-searchbar .mod-finder__search {
    flex: 1 1 auto;
    display: flex;
    align-items: stretch;
    min-width: 0;
}

.jsm-searchbar label {
    flex: none;
}

.jsm-searchbar input[type="text"],
.jsm-searchbar input[type="search"] {
    flex: 1 1 auto;
    min-width: 0;
    padding: .75em 1em;
    font: inherit;
    color: var(--jsm-ink);
    background: var(--jsm-white);
    border: 1px solid var(--jsm-line);
    border-right: 0;
    border-radius: var(--jsm-radius-sm) 0 0 var(--jsm-radius-sm);
}

.jsm-searchbar input:focus {
    outline: none;
    border-color: var(--jsm-blue-l);
    box-shadow: 0 0 0 3px rgba(28, 130, 184, .18);
}

.jsm-searchbar button,
.jsm-searchbar .btn {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: .45em;
    padding: .75em 1.6em;
    border: 0;
    border-radius: 0 var(--jsm-radius-sm) var(--jsm-radius-sm) 0;
    background: var(--jsm-navy);
    color: var(--jsm-white);
    font: inherit;
    cursor: pointer;
    transition: background-color .15s ease;
}

.jsm-searchbar button:hover,
.jsm-searchbar .btn:hover {
    background: var(--jsm-blue);
    color: var(--jsm-white);
}

/* ==========================================================================
   Navigation
   ========================================================================== */

/**
 * A white bar with a rule under it, not a coloured one: the hero below is navy
 * and two blocks of navy stacked read as one slab. The active item is carried
 * by colour and weight instead.
 */
.jsm-nav {
    background: var(--jsm-white);
    border-bottom: 1px solid var(--jsm-line);
}

.jsm-nav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.jsm-menu {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    margin: 0;
    padding: 0;
    list-style: none;
}

.jsm-menu-item {
    position: relative;
}

.jsm-menu-link {
    display: flex;
    align-items: center;
    padding: 1.05rem 1.15rem;
    font-family: var(--jsm-font-head);
    font-weight: 500;
    font-size: 1rem;
    color: var(--jsm-ink);
    text-decoration: none;
    transition: color .18s ease;
}

.jsm-menu-item:hover > .jsm-menu-link,
.jsm-menu-item:focus-within > .jsm-menu-link {
    color: var(--jsm-red);
}

.jsm-menu-item.is-active > .jsm-menu-link {
    color: var(--jsm-red);
    font-weight: 700;
}

.jsm-menu-audience .jsm-menu-link {
    font-weight: 500;
}

.jsm-menu-toggle {
    position: absolute;
    top: 50%;
    right: .25rem;
    transform: translateY(-50%);
    display: none;
    width: 1.8rem;
    height: 1.8rem;
    padding: 0;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--jsm-muted);
    cursor: pointer;
}

.jsm-menu-toggle svg {
    width: 1rem;
    height: 1rem;
}

.jsm-submenu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 70;
    min-width: 15rem;
    margin: 0;
    padding: .4rem 0;
    list-style: none;
    background: var(--jsm-white);
    border: 1px solid var(--jsm-line);
    border-radius: 0 0 var(--jsm-radius-md) var(--jsm-radius-md);
    box-shadow: var(--jsm-shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity .15s ease, transform .15s ease, visibility .15s;
}

.jsm-menu-item:hover > .jsm-submenu,
.jsm-menu-item:focus-within > .jsm-submenu {
    opacity: 1;
    visibility: visible;
    transform: none;
}

.jsm-submenu .jsm-menu-link {
    padding: .55rem 1rem;
    color: var(--jsm-ink);
    font-weight: 500;
}

.jsm-submenu .jsm-menu-item:hover > .jsm-menu-link {
    background: var(--jsm-surface);
    color: var(--jsm-blue);
}

.jsm-nav-toggle {
    display: none;
}

.jsm-nav-backdrop[hidden] {
    display: none;
}

/* ==========================================================================
   Hero
   ========================================================================== */

.jsm-hero {
    position: relative;
    display: grid;
    /*
     * minmax(0, 1fr), not the implicit `auto`. An auto track takes its width
     * from its widest content, so the promo rail's columns could make the hero
     * — and with it the page — wider than the window.
     */
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    min-height: var(--jsm-hero-min);
    isolation: isolate;
    color: var(--jsm-white);
}

.jsm-hero-bg {
    position: absolute;
    inset: 0;
    z-index: -2;
    overflow: hidden;
}

.jsm-hero-bg img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--jsm-hero-focus);
    /* The crossfade when the promo slideshow changes slide. */
    transition: opacity .18s ease;
}

.jsm-hero-bg img.is-swapping {
    opacity: 0;
}

/**
 * Two overlays, because one cannot do both jobs. The horizontal ramp keeps the
 * headline column dark while the photograph stays visible on the right; the
 * vertical wash stops a bright patch of sky washing out the top line. The
 * photograph is uncontrolled — editors swap it — so this has to hold for any
 * image, not just the one shipped.
 */
.jsm-hero::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        linear-gradient(180deg, rgba(26, 46, 74, .22) 0%, rgba(26, 46, 74, 0) 35%),
        linear-gradient(100deg,
            rgba(26, 46, 74, .95) 0%,
            rgba(26, 46, 74, .86) 42%,
            rgba(26, 46, 74, .44) 68%,
            rgba(26, 46, 74, .08) 100%);
}

.jsm-hero-inner {
    padding-block: 3.5rem;
    width: 100%;
}

/*
 * 24ch and a smaller ramp. The copy here is a sentence rather than a slogan,
 * and at slogan size it filled the hero on its own; this leaves room for the
 * buttons and keeps the photograph in the picture.
 */
.jsm-hero h1 {
    margin: 0 0 1.1rem;
    max-width: 24ch;
    font-size: clamp(1.5rem, 2.5vw, 2.1rem);
    font-weight: 800;
    line-height: 1.22;
    color: var(--jsm-white);
    text-wrap: balance;
    /* The crossfade when the promo slideshow changes slide. */
    transition: opacity .18s ease;
}

.jsm-hero h1.is-swapping {
    opacity: 0;
}

.jsm-hero h1 .accent {
    color: var(--jsm-yellow);
}

.jsm-lede {
    margin: 0 0 1.6rem;
    max-width: 48ch;
    font-size: 1.05rem;
    color: rgba(255, 255, 255, .9);
}

.jsm-hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
}

/* ---------------------------------------------------------- Hero promo rail */

/**
 * The upcoming headlines, standing against the hero photograph. It is inside
 * the hero rather than under it, so the hero keeps its stated height and the
 * rail reads as part of the image.
 *
 * Two arrangements, chosen on the style: a column down the right, which is the
 * approved design, or a strip along the foot.
 */
.jsm-hero {
    position: relative;
    padding-bottom: 0;
}

.jsm-hero-rail {
    position: relative;
    z-index: 1;
    /* So a grid item can be narrower than its content and scroll instead. */
    min-width: 0;
}

.jsm-rail-item {
    display: flex;
    text-decoration: none;
    color: rgba(255, 255, 255, .82);
    background: rgba(13, 25, 48, .5);
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

.jsm-rail-item:hover,
.jsm-rail-item:focus-visible {
    color: var(--jsm-white);
    background: rgba(13, 25, 48, .78);
}

.jsm-rail-item.is-active {
    color: var(--jsm-white);
    background: rgba(13, 25, 48, .82);
}

.jsm-rail-thumb {
    overflow: hidden;
}

.jsm-rail-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.jsm-rail-title {
    font-size: .84rem;
    font-weight: 600;
    line-height: 1.35;
}

/* ------------------------------------------------- The rail as a foot strip */

/*
 * Unscoped, so this is also what the right-hand column falls back to below the
 * breakpoint — a narrow screen has no width to give a column away. Putting
 * these behind the `bottom` modifier left the column variant with no styling
 * at all on a phone.
 */
.jsm-hero-rail {
    margin-top: auto;
    background: linear-gradient(180deg, rgba(26, 46, 74, 0) 0%, rgba(26, 46, 74, .72) 42%);
}

.jsm-hero-rail-inner {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 1px;
    padding-block: 0;
}

.jsm-rail-item {
    align-items: center;
    gap: .7rem;
    padding: 1rem;
    border-top: 3px solid transparent;
}

.jsm-rail-item.is-active {
    border-top-color: var(--jsm-yellow);
}

.jsm-rail-thumb {
    flex: none;
    width: 3.1rem;
    height: 2.3rem;
    border-radius: 5px;
}

/*
 * On a phone four equal columns leave about 90px each, which wraps the titles
 * to four lines. Give each item a readable width instead and let the strip
 * scroll sideways.
 */
@media (max-width: 48rem) {
    .jsm-hero-rail-inner {
        grid-auto-columns: minmax(10.5rem, 1fr);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
    }

    .jsm-hero-rail-inner::-webkit-scrollbar {
        display: none;
    }
}

/* --------------------------------------------- The rail as a right-hand column */

@media (min-width: 62.0625rem) {
    .jsm-hero--rail-right {
        /*
         * The second track is the rail. It is sized in vw rather than fr so
         * that a long headline cannot squeeze it, and capped so it does not
         * swallow the photograph on a very wide screen.
         */
        grid-template-columns: minmax(0, 1fr) clamp(15rem, 19vw, 21rem);
    }

    .jsm-hero--rail-right .jsm-hero-inner {
        grid-area: 1 / 1 / 2 / 2;
    }

    /* Full height of the hero, against its right edge. */
    .jsm-hero--rail-right .jsm-hero-rail {
        grid-area: 1 / 2 / 2 / -1;
        align-self: stretch;
        display: flex;
        /* The strip's gradient and its auto top margin both belong to the foot. */
        margin-top: 0;
        background: rgba(13, 25, 48, .9);
    }

    .jsm-hero--rail-right .jsm-hero-rail-inner {
        /* It is a .wrap; the content measure is wrong inside a column. */
        max-width: none;
        padding: 0;
        flex: 1 1 auto;
        display: grid;
        grid-auto-flow: row;
        /*
         * A floor so each cell has room to be a picture, and 1fr so that when
         * the headline column is taller than the rail the cells share the
         * difference rather than leaving a gap at the foot.
         */
        grid-auto-rows: minmax(9rem, 1fr);
        grid-auto-columns: auto;
        gap: 0;
    }

    /*
     * Each cell is the picture, with the title laid over its foot — not a
     * thumbnail with a caption beneath. Nothing is drawn between cells: the
     * photographs and the dark gaps between them do that work themselves.
     */
    .jsm-hero--rail-right .jsm-rail-item {
        position: relative;
        display: grid;
        align-content: end;
        padding: 1.15rem 1.25rem;
        overflow: hidden;
        background: none;
        border: 0;
    }

    /*
     * The picture, stretched behind the cell. It is a grid area rather than a
     * background-image because the markup gives us a real <img>, which keeps
     * the alt text and the lazy loading the template already sets.
     */
    .jsm-hero--rail-right .jsm-rail-thumb {
        position: absolute;
        inset: 0;
        z-index: 0;
        width: auto;
        height: auto;
        border-radius: 0;
    }

    /*
     * A wash under the title. Without it a bright patch of sky takes the words
     * with it, and the photographs are swapped by editors — so this has to hold
     * for any image, not just the ones shipped.
     */
    /*
     * Held back by default so the slide that is showing stands out — the rail
     * is the slideshow's index as well as its controls, and the current slide
     * has to be readable as such at a glance.
     */
    .jsm-hero--rail-right .jsm-rail-item::after {
        content: '';
        position: absolute;
        inset: 0;
        z-index: 1;
        background: linear-gradient(180deg,
            rgba(13, 25, 48, .5) 0%,
            rgba(13, 25, 48, .72) 55%,
            rgba(13, 25, 48, .92) 100%);
        transition: background .25s ease;
    }

    .jsm-hero--rail-right .jsm-rail-title {
        position: relative;
        z-index: 2;
        font-size: .95rem;
        text-shadow: 0 1px 10px rgba(13, 25, 48, .6);
    }

    /* A cell with no picture still needs to read as one of the set. */
    .jsm-hero--rail-right .jsm-rail-item:not(:has(.jsm-rail-thumb)) {
        background: rgba(13, 25, 48, .55);
    }

    .jsm-hero--rail-right .jsm-rail-item:hover::after,
    .jsm-hero--rail-right .jsm-rail-item:focus-visible::after {
        background: linear-gradient(180deg,
            rgba(13, 25, 48, .1) 0%,
            rgba(13, 25, 48, .4) 55%,
            rgba(13, 25, 48, .8) 100%);
    }

    .jsm-hero--rail-right .jsm-rail-item.is-active::after {
        background: linear-gradient(180deg,
            rgba(13, 25, 48, .05) 0%,
            rgba(13, 25, 48, .3) 55%,
            rgba(13, 25, 48, .8) 100%);
    }

    /* A thin mark down the showing slide, so it is not colour alone. */
    .jsm-hero--rail-right .jsm-rail-item.is-active::before {
        content: '';
        position: absolute;
        inset: 0 auto 0 0;
        z-index: 2;
        width: 3px;
        background: var(--jsm-yellow);
    }
}

/* A slider module takes the band whole; it brings its own height. */
.jsm-showcase > * {
    display: block;
}

/* ---------------------------------------------------------------- Page hero */

.jsm-page-hero {
    background: var(--jsm-navy);
    color: var(--jsm-white);
    padding-block: 2rem 2.2rem;
}

.jsm-page-title {
    margin: .4rem 0 0;
    font-family: var(--jsm-font-head);
    font-weight: 700;
    font-size: clamp(1.5rem, 3vw, 2.2rem);
    line-height: 1.2;
    color: var(--jsm-white);
}

.jsm-page-hero .jsm-lede {
    margin-top: .5rem;
    margin-bottom: 0;
    font-size: .98rem;
}

.jsm-page-hero nav,
.jsm-page-hero .breadcrumb {
    margin: 0;
    padding: 0;
    background: none;
    font-size: .82rem;
}

.jsm-page-hero .breadcrumb {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    list-style: none;
}

.jsm-page-hero .breadcrumb a,
.jsm-page-hero .breadcrumb li {
    color: rgba(255, 255, 255, .78);
}

/* ==========================================================================
   Bands
   ========================================================================== */

.jsm-band {
    padding-block: var(--jsm-band-pad);
}

.jsm-pad-tight {
    padding-block: calc(var(--jsm-band-pad) * .45);
}

.jsm-pad-none {
    padding-block: 0;
}

.jsm-bg-surface {
    background: var(--jsm-surface);
}

.jsm-bg-navy {
    background: var(--jsm-navy);
    color: rgba(255, 255, 255, .88);
}

.jsm-bg-navy h2,
.jsm-bg-navy h3 {
    color: var(--jsm-white);
}

.jsm-bg-yellow {
    background: var(--jsm-yellow);
    color: var(--jsm-navy-d);
}

/* Two navy bands in a row read as one: drop the seam between them. */
.jsm-bg-navy + .jsm-bg-navy {
    padding-top: 0;
}

/**
 * Two sections sharing a band. The column widths come from the row's span as an
 * inline grid-template-columns, so the ratio is the editor's and only the
 * collapse point is ours.
 */
.jsm-band-cols {
    display: grid;
    gap: 2rem;
    align-items: start;
}

@media (max-width: 62rem) {
    .jsm-band-cols {
        grid-template-columns: minmax(0, 1fr) !important;
    }
}

/* ---------------------------------------------------------------- Band head */

.jsm-band-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: .75rem 2rem;
    margin-bottom: 2rem;
}

.jsm-eyebrow {
    margin: 0 0 .35rem;
    font-family: var(--jsm-font-head);
    font-size: .76rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--jsm-blue-l);
}

.jsm-band-title {
    margin: 0;
    font-size: clamp(1.45rem, 2.6vw, 2.1rem);
}

.jsm-band-lead {
    margin: .5rem 0 0;
    max-width: 52ch;
    color: var(--jsm-muted);
}

.jsm-bg-navy .jsm-band-lead {
    color: rgba(255, 255, 255, .72);
}

.jsm-band-more {
    display: inline-flex;
    align-items: center;
    gap: .4em;
    flex: none;
    font-weight: 600;
    font-size: .92rem;
    text-decoration: none;
}

.jsm-band-more svg {
    width: 1em;
    height: 1em;
}

.jsm-bg-navy .jsm-band-more {
    color: var(--jsm-yellow);
}

/* ==========================================================================
   Section: highlights
   ========================================================================== */

.jsm-highlights {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-block: .85rem;
}

.jsm-highlights-label {
    flex: none;
    margin: 0;
    padding: .3rem .8rem;
    border-radius: 999px;
    background: var(--jsm-navy);
    color: var(--jsm-white);
    font-family: var(--jsm-font-head);
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.jsm-highlights-track {
    flex: 1;
    min-width: 0;
}

.jsm-highlights-item {
    display: flex;
    align-items: baseline;
    gap: .75rem;
    color: var(--jsm-navy-d);
    font-weight: 600;
    text-decoration: none;
    min-width: 0;
}

.jsm-highlights-date {
    flex: none;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .02em;
    opacity: .72;
}

.jsm-highlights-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.jsm-highlights-more {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: .35em;
    font-size: .82rem;
    font-weight: 700;
    color: var(--jsm-navy-d);
    text-decoration: none;
    border-bottom: 2px solid currentColor;
}

.jsm-highlights-more svg {
    width: .95em;
    height: .95em;
}

.jsm-highlights-item[hidden] {
    display: none;
}

.jsm-highlights-item:hover {
    text-decoration: underline;
}

.jsm-highlights-nav {
    display: flex;
    gap: .25rem;
    flex: none;
}

.jsm-highlights-nav button {
    display: grid;
    place-items: center;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    border: 1px solid rgba(26, 46, 74, .3);
    border-radius: 50%;
    background: none;
    color: var(--jsm-navy-d);
    cursor: pointer;
}

.jsm-highlights-nav button:hover {
    background: rgba(255, 255, 255, .5);
}

.jsm-highlights-nav svg {
    width: .9rem;
    height: .9rem;
}

/* ==========================================================================
   Section: Easy Access cards
   ========================================================================== */

/**
 * Accent colours, set per card. They tint the caption bar in the overlay shape
 * and the rule under the title in the stacked one, and they are what the
 * featured link card fills itself with.
 */
.jsm-accent-yellow { --jsm-accent: var(--jsm-yellow); --jsm-accent-ink: var(--jsm-navy-d); }
.jsm-accent-red    { --jsm-accent: var(--jsm-red);    --jsm-accent-ink: #fff; }
.jsm-accent-blue   { --jsm-accent: var(--jsm-blue-l); --jsm-accent-ink: #fff; }
.jsm-accent-green  { --jsm-accent: #1f9d6b;           --jsm-accent-ink: #fff; }
.jsm-accent-navy   { --jsm-accent: var(--jsm-navy);   --jsm-accent-ink: #fff; }

.jsm-cards {
    display: grid;
    /* The row holds as many cards as the style defines, down to a floor where
       the caption stops fitting; below that it reflows. */
    grid-template-columns: repeat(var(--jsm-cards-cols, 5), minmax(0, 1fr));
    gap: 1.25rem;
}

@media (max-width: 78rem) {
    .jsm-cards {
        grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    }
}

.jsm-card {
    display: flex;
    flex-direction: column;
    background: var(--jsm-white);
    border: 1px solid var(--jsm-line);
    border-radius: var(--jsm-radius-lg);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    box-shadow: var(--jsm-shadow);
    transition: transform .15s ease, box-shadow .15s ease;
}

.jsm-card:hover,
.jsm-card:focus-visible {
    transform: translateY(-3px);
    box-shadow: var(--jsm-shadow-lg);
}

/**
 * The media box is a fixed shape. "cover" fills it and crops the overflow,
 * which suits a photograph; "contain" shows the whole graphic on a padding
 * colour, which is what a poster or a logo needs. background-repeat is set
 * explicitly — without it a contained graphic tiles to fill the box.
 */
.jsm-card-media {
    display: block;
    aspect-ratio: 4 / 3;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    background-color: var(--jsm-surface);
}

.jsm-card--fit-contain .jsm-card-media {
    background-size: contain;
    background-color: var(--jsm-white);
    margin: .75rem .75rem 0;
    border-radius: var(--jsm-radius-md);
}

.jsm-card-body {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .6rem;
    padding: .9rem 1rem;
    flex: 1;
}

.jsm-card-title {
    font-family: var(--jsm-font-head);
    font-weight: 700;
    font-size: .95rem;
    line-height: 1.3;
    color: var(--jsm-navy);
}

.jsm-card-go {
    display: inline-flex;
    flex: none;
    color: var(--jsm-blue);
}

.jsm-card-go svg {
    width: 1.15rem;
    height: 1.15rem;
}

/**
 * Overlay: the caption sits on the photograph in an accent bar. The card is a
 * grid with one cell so the media and the caption stack in the same box.
 */
.jsm-cards--overlay .jsm-card {
    display: grid;
    position: relative;
}

.jsm-cards--overlay .jsm-card-media {
    grid-area: 1 / 1;
    aspect-ratio: 4 / 3;
}

.jsm-cards--overlay .jsm-card-body {
    grid-area: 1 / 1;
    align-self: end;
    background: color-mix(in srgb, var(--jsm-accent, var(--jsm-yellow)) 92%, transparent);
    color: var(--jsm-accent-ink, var(--jsm-navy-d));
}

.jsm-cards--overlay .jsm-card-title,
.jsm-cards--overlay .jsm-card-go {
    color: inherit;
}

/* Stacked: caption under the image, with the accent as a rule above it. */
.jsm-cards--stacked .jsm-card-body {
    border-top: 3px solid var(--jsm-accent, var(--jsm-yellow));
}

/* ==========================================================================
   Section: explainer columns
   ========================================================================== */

.jsm-infoduo {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
    gap: 1.5rem;
}

.jsm-info {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .6rem;
    padding: 1.6rem;
    background: var(--jsm-white);
    border: 1px solid var(--jsm-line);
    border-radius: var(--jsm-radius-lg);
}

.jsm-info-icon {
    display: grid;
    place-items: center;
    width: 3.2rem;
    height: 3.2rem;
    border-radius: var(--jsm-radius-md);
    background: rgba(28, 130, 184, .12);
}

.jsm-info-icon img {
    width: 1.7rem;
    height: 1.7rem;
    object-fit: contain;
}

.jsm-info h3 {
    margin: 0;
    font-size: 1.15rem;
}

.jsm-info p {
    margin: 0;
    color: var(--jsm-muted);
    flex: 1;
}

/* ==========================================================================
   Section: link cards
   ========================================================================== */

.jsm-linkcards {
    display: grid;
    gap: .9rem;
    align-content: start;
}

.jsm-linkcard {
    display: flex;
    align-items: flex-start;
    gap: .85rem;
    padding: 1.1rem;
    background: var(--jsm-white);
    border: 1px solid var(--jsm-line);
    border-left: 4px solid var(--jsm-accent, var(--jsm-blue-l));
    border-radius: var(--jsm-radius-md);
    text-decoration: none;
    color: inherit;
    transition: transform .15s ease, box-shadow .15s ease;
}

.jsm-linkcard:hover,
.jsm-linkcard:focus-visible {
    transform: translateX(2px);
    box-shadow: var(--jsm-shadow);
}

/* The featured card fills with its accent instead of outlining. */
.jsm-linkcard.is-featured {
    background: var(--jsm-accent, var(--jsm-blue-l));
    border-color: var(--jsm-accent, var(--jsm-blue-l));
    color: var(--jsm-accent-ink, #fff);
}

.jsm-linkcard.is-featured .jsm-linkcard-title,
.jsm-linkcard.is-featured .jsm-linkcard-body,
.jsm-linkcard.is-featured .jsm-linkcard-go {
    color: inherit;
}

.jsm-linkcard-icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.6rem;
    height: 2.6rem;
}

.jsm-linkcard-icon img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.jsm-linkcard-text {
    flex: 1;
    min-width: 0;
    display: grid;
    gap: .2rem;
}

.jsm-linkcard-title {
    font-family: var(--jsm-font-head);
    font-weight: 700;
    font-size: .98rem;
    color: var(--jsm-navy);
}

.jsm-linkcard-body {
    font-size: .85rem;
    line-height: 1.45;
    color: var(--jsm-muted);
}

.jsm-linkcard-go {
    flex: none;
    align-self: center;
    color: var(--jsm-blue);
}

.jsm-linkcard-go svg {
    width: 1.1rem;
    height: 1.1rem;
}

/* ==========================================================================
   Section: activities
   ========================================================================== */

.jsm-activities {
    position: relative;
    display: flex;
    align-items: center;
    gap: .5rem;
}

.jsm-activities-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(14rem, 1fr);
    gap: 1.1rem;
    overflow-x: auto;
    scroll-behavior: smooth;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    padding-bottom: .25rem;
}

.jsm-activities-track::-webkit-scrollbar {
    display: none;
}

.jsm-activity {
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    gap: .6rem;
    text-decoration: none;
    color: inherit;
}

.jsm-activity-media {
    display: block;
    aspect-ratio: 4 / 5;
    border-radius: var(--jsm-radius-lg);
    overflow: hidden;
    background: var(--jsm-surface);
}

.jsm-bg-navy .jsm-activity-media {
    background: rgba(255, 255, 255, .08);
}

.jsm-activity-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .25s ease;
}

.jsm-activity:hover .jsm-activity-media img {
    transform: scale(1.04);
}

/**
 * These bands default to light and get their dark treatment from .jsm-bg-navy,
 * rather than the other way round. The background is a per-row setting, so a
 * band that assumes it will be dark goes white-on-white the moment someone
 * changes it — which is exactly what happened to the activities captions.
 */
.jsm-activity-caption {
    font-size: .88rem;
    line-height: 1.45;
    color: var(--jsm-ink);
}

.jsm-bg-navy .jsm-activity-caption {
    color: rgba(255, 255, 255, .82);
}

.jsm-activities-embed {
    min-height: 320px;
    overflow: hidden;
}

.jsm-activities-embed > * {
    max-width: 100%;
}

/* Carousel buttons, shared with the agency rail */

.jsm-carousel-btn {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.4rem;
    height: 2.4rem;
    padding: 0;
    border: 1px solid var(--jsm-line);
    border-radius: 50%;
    background: var(--jsm-white);
    color: var(--jsm-navy);
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.jsm-carousel-btn:hover {
    background: var(--jsm-blue);
    border-color: var(--jsm-blue);
    color: var(--jsm-white);
}

.jsm-carousel-btn svg {
    width: 1.1rem;
    height: 1.1rem;
}

.jsm-carousel-btn[disabled] {
    opacity: .35;
    cursor: default;
}

.jsm-bg-navy .jsm-carousel-btn {
    background: transparent;
    border-color: rgba(255, 255, 255, .35);
    color: var(--jsm-white);
}

.jsm-bg-navy .jsm-carousel-btn:hover {
    background: var(--jsm-white);
    color: var(--jsm-navy);
}

/* ==========================================================================
   Section: statistics
   ========================================================================== */

.jsm-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 1.5rem;
}

/**
 * Beside the activities carousel the statistics are a narrow column, so the
 * figures stack and read left-aligned rather than centred in a wide row.
 */
.jsm-col-stats .jsm-stats {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.1rem;
}

.jsm-col-stats .jsm-stat {
    flex-direction: row;
    align-items: center;
    text-align: left;
    gap: .9rem;
    padding: .9rem 1rem;
    background: var(--jsm-surface);
    border: 1px solid var(--jsm-line);
    border-radius: var(--jsm-radius-md);
}

.jsm-bg-navy .jsm-col-stats .jsm-stat {
    background: rgba(255, 255, 255, .06);
    border-color: transparent;
}

.jsm-col-stats .jsm-stat-icon {
    margin-bottom: 0;
    width: 2.6rem;
    height: 2.6rem;
}

.jsm-col-stats .jsm-stat-value {
    font-size: 1.9rem;
}

.jsm-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .25rem;
    text-decoration: none;
    color: inherit;
}

.jsm-stat-icon {
    width: 3rem;
    height: 3rem;
    object-fit: contain;
    margin-bottom: .4rem;
}

/**
 * #f0a92b is a 2:1 contrast on white, so the light band takes the blue and the
 * gold is kept for the navy one where it was drawn to sit.
 */
.jsm-stat-value {
    display: block;
    margin: 0;
    font-family: var(--jsm-font-head);
    font-weight: 800;
    font-size: clamp(2rem, 4vw, 2.8rem);
    line-height: 1.05;
    color: var(--jsm-blue);
}

.jsm-bg-navy .jsm-stat-value {
    color: var(--jsm-gold);
}

.jsm-stat-label {
    display: block;
    margin: 0;
    font-size: .9rem;
    color: var(--jsm-muted);
}

.jsm-bg-navy .jsm-stat-label {
    color: rgba(255, 255, 255, .78);
}

/* ==========================================================================
   Section: official social media
   ========================================================================== */

.jsm-social {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 1.25rem;
}

.jsm-social-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--jsm-line);
    border-radius: var(--jsm-radius-lg);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    background: var(--jsm-white);
    box-shadow: var(--jsm-shadow);
    transition: transform .15s ease, box-shadow .15s ease;
}

.jsm-social-card:hover,
.jsm-social-card:focus-visible {
    transform: translateY(-3px);
    box-shadow: var(--jsm-shadow-lg);
}

.jsm-social-media {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--jsm-surface);
}

.jsm-social-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.jsm-social-body {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .9rem 1.1rem;
}

.jsm-social-glyph {
    width: 1.3rem;
    height: 1.3rem;
    object-fit: contain;
}

.jsm-social-label {
    font-family: var(--jsm-font-head);
    font-weight: 600;
    color: var(--jsm-navy);
}

/* ==========================================================================
   Section: agency rail
   ========================================================================== */

.jsm-agencies {
    position: relative;
    display: flex;
    align-items: center;
    gap: .5rem;
}

.jsm-agencies-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(8rem, 1fr);
    align-items: center;
    gap: 2rem;
    overflow-x: auto;
    scroll-behavior: smooth;
    scrollbar-width: none;
}

.jsm-agencies-track::-webkit-scrollbar {
    display: none;
}

.jsm-agency img {
    width: 100%;
    max-height: 4.5rem;
    object-fit: contain;
    filter: grayscale(1);
    opacity: .75;
    transition: filter .2s ease, opacity .2s ease;
}

.jsm-agency img:hover {
    filter: none;
    opacity: 1;
}

/* ==========================================================================
   Section: page content
   ========================================================================== */

.jsm-s-content {
    padding-block: calc(var(--jsm-band-pad) * .7);
}

.jsm-content-grid {
    display: grid;
    gap: 2rem;
    grid-template-columns: minmax(0, 1fr);
}

.jsm-s-content.has-left .jsm-content-grid {
    grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
}

.jsm-s-content.has-right .jsm-content-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 17rem);
}

.jsm-s-content.has-left.has-right .jsm-content-grid {
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 15rem);
}

.jsm-main {
    min-width: 0;
}

.jsm-sidebar {
    display: grid;
    gap: 1.25rem;
    align-content: start;
}

/* Article typography inside the content band */

.jsm-main h1 {
    margin-top: 0;
    font-size: clamp(1.6rem, 3vw, 2.2rem);
}

.jsm-main h2 {
    margin-top: 2rem;
    font-size: 1.4rem;
}

.jsm-main h3 {
    margin-top: 1.5rem;
    font-size: 1.15rem;
}

.jsm-main img {
    border-radius: var(--jsm-radius-md);
}

.jsm-main table {
    width: 100%;
    border-collapse: collapse;
}

.jsm-main table th,
.jsm-main table td {
    padding: .6rem .8rem;
    border: 1px solid var(--jsm-line);
    text-align: left;
    vertical-align: top;
}

.jsm-main table th {
    background: var(--jsm-surface);
    font-family: var(--jsm-font-head);
    font-size: .85rem;
    color: var(--jsm-navy);
}

/* A wide table should scroll rather than push the layout sideways. */
.jsm-main .table-responsive,
.jsm-main figure.table {
    overflow-x: auto;
}

/* ---------------------------------------------------------------- Module cards */

.jsm-modcard {
    background: var(--jsm-white);
    border: 1px solid var(--jsm-line);
    border-radius: var(--jsm-radius-lg);
    padding: 1.25rem;
}

.jsm-card-heading {
    margin: 0 0 .75rem;
    font-size: 1.05rem;
}

.jsm-modcard ul {
    margin: 0;
    padding-left: 1.1rem;
}

.jsm-modules,
.jsm-cards--module,
.jsm-social--module,
.jsm-infoduo--module {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 1.25rem;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.jsm-footer {
    background: var(--jsm-navy-d);
    color: rgba(255, 255, 255, .78);
    font-size: .92rem;
}

.jsm-footer a {
    color: rgba(255, 255, 255, .85);
    text-decoration: none;
}

.jsm-footer a:hover {
    color: var(--jsm-white);
    text-decoration: underline;
}

.jsm-footer-top {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(11rem, 1fr));
    gap: 2rem;
    padding-block: 3rem 2rem;
}

.jsm-footer-brand img {
    max-width: 13rem;
    margin-bottom: 1rem;
    /* The wordmark is dark-on-light artwork; on navy it needs inverting. */
    filter: brightness(0) invert(1);
}

.jsm-footer-address {
    margin: 0 0 .9rem;
    line-height: 1.55;
}

.jsm-footer-contact {
    margin: 0 0 1rem;
    padding: 0;
    list-style: none;
    display: grid;
    gap: .4rem;
}

.jsm-footer-contact li {
    display: flex;
    align-items: center;
    gap: .55rem;
}

.jsm-footer-contact img {
    width: 1rem;
    height: 1rem;
    object-fit: contain;
    filter: brightness(0) invert(1);
    opacity: .8;
}

.jsm-footer-social {
    display: flex;
    gap: .5rem;
}

.jsm-footer-social a {
    display: grid;
    place-items: center;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, .1);
    transition: background-color .15s ease;
}

.jsm-footer-social a:hover {
    background: var(--jsm-blue-l);
}

.jsm-footer-social img {
    width: 1.05rem;
    height: 1.05rem;
    object-fit: contain;
    filter: brightness(0) invert(1);
}

.jsm-footer-title {
    margin: 0 0 .75rem;
    font-family: var(--jsm-font-head);
    font-size: .95rem;
    font-weight: 700;
    color: var(--jsm-white);
}

.jsm-footer-col ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: .4rem;
}

.jsm-footer-extra {
    padding-bottom: 1.5rem;
}

/* ---------------------------------------------------------- Visitor counter */

.jsm-visitors {
    margin: 0;
    display: grid;
    gap: .3rem;
    font-size: .86rem;
}

.jsm-visitors > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: .3rem;
    border-bottom: 1px solid rgba(255, 255, 255, .1);
}

.jsm-visitors dt {
    margin: 0;
    color: rgba(255, 255, 255, .68);
}

.jsm-visitors dd {
    margin: 0;
    font-family: var(--jsm-font-head);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--jsm-white);
}

/* The portal's own counter module, when it is used instead. */
.jsm-footer-visitors .jsm-footer-title + * {
    font-size: .86rem;
}

/* ------------------------------------------------- Module beside the gov bar */

.jsm-govbar-extra {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-left: .5rem;
}

.jsm-govbar-extra img {
    max-height: 1.1rem;
    width: auto;
}

/* ---------------------------------------------------------------- Footer bar */

.jsm-footerbar {
    border-top: 1px solid rgba(255, 255, 255, .12);
    font-size: .82rem;
}

.jsm-footerbar-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .5rem 1.5rem;
    padding-block: 1rem;
}

.jsm-footerbar-left,
.jsm-footerbar-legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem 1rem;
}

/* ---------------------------------------------------------------- Back to top */

.jsm-backtotop {
    position: fixed;
    right: 1.1rem;
    bottom: 1.1rem;
    z-index: 90;
    display: grid;
    place-items: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    background: var(--jsm-blue);
    color: var(--jsm-white);
    text-decoration: none;
    box-shadow: var(--jsm-shadow-lg);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, visibility .2s, background-color .15s ease;
}

.jsm-backtotop.is-visible {
    opacity: 1;
    visibility: visible;
}

.jsm-backtotop:hover {
    background: var(--jsm-navy);
    color: var(--jsm-white);
}

/* ==========================================================================
   Error, maintenance and offline
   ========================================================================== */

.jsm-error-shell {
    max-width: 34rem;
    margin: 0 auto;
    padding: 5rem var(--jsm-gutter);
    text-align: center;
}

.jsm-error-logo,
.jsm-error-brand img {
    max-width: 13rem;
    margin-bottom: 2rem;
}

/*
 * The Site Offline artwork. It had no rule at all, so a 2160px notice was
 * printed at its natural size and pushed the whole page sideways.
 */
.jsm-error-art {
    display: block;
    width: 100%;
    max-width: 30rem;
    height: auto;
    margin: 0 auto 2rem;
    border-radius: var(--jsm-radius-md);
}

.jsm-error-code {
    margin: 0;
    font-family: var(--jsm-font-head);
    font-size: 4.5rem;
    font-weight: 800;
    line-height: 1;
    color: var(--jsm-line);
}

.jsm-error-title {
    margin: .5rem 0 .75rem;
    font-size: 1.5rem;
}

.jsm-error-lead {
    margin: 0 0 1.75rem;
    color: var(--jsm-muted);
}

.jsm-offline-login {
    display: grid;
    gap: .85rem;
    text-align: left;
    margin-top: 2rem;
}

.jsm-field label {
    display: block;
    margin-bottom: .3rem;
    font-weight: 600;
    font-size: .88rem;
}

.jsm-field input {
    width: 100%;
    padding: .7rem .9rem;
    font: inherit;
    border: 1.5px solid var(--jsm-line);
    border-radius: var(--jsm-radius-sm);
}

.jsm-error-debug {
    margin-top: 2.5rem;
    text-align: left;
    font-size: .8rem;
}

/* ------------------------------------------------------- Maintenance page */

.jsm-maintenance {
    background: var(--jsm-surface);
}

.jsm-maint {
    display: grid;
    place-items: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 2rem var(--jsm-gutter);
}

.jsm-maint-card {
    width: 100%;
    max-width: 34rem;
    padding: clamp(2rem, 5vw, 3.25rem);
    border-radius: var(--jsm-radius-lg);
    background: var(--jsm-white);
    box-shadow: var(--jsm-shadow-lg);
    text-align: center;
}

.jsm-maint-logo {
    max-width: 15rem;
    height: auto;
    margin-bottom: 1.75rem;
}

.jsm-maint-eyebrow {
    margin: 0 0 .5rem;
    font-family: var(--jsm-font-head);
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--jsm-blue-l);
}

.jsm-maint-card h1 {
    margin: 0 0 .9rem;
    font-size: clamp(1.4rem, 3vw, 1.9rem);
    line-height: 1.2;
}

.jsm-maint-lead {
    margin: 0;
    color: var(--jsm-muted);
    line-height: 1.7;
}

.jsm-maint-until,
.jsm-maint-contact {
    margin: 1.25rem 0 0;
    font-size: .92rem;
    color: var(--jsm-ink);
}

.jsm-maint-until {
    padding-top: 1.25rem;
    border-top: 1px solid var(--jsm-line);
}

/*
 * Image-only: the notice is the page. It is centred and held to its own size
 * rather than stretched, because these are usually exported at a fixed width
 * and blowing one up past it only softens the type on it.
 */
.jsm-maintenance.is-image-only {
    background: var(--jsm-navy-d);
}

.jsm-maint-only {
    display: grid;
    place-items: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 1.5rem;
}

.jsm-maint-only img {
    max-width: min(100%, 64rem);
    max-height: calc(100dvh - 3rem);
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--jsm-radius-md);
}

/* ==========================================================================
   Landing page — the splash door and the audience chooser
   ========================================================================== */

/*
 * The landing shell has no masthead, no navigation and no footer, so its band
 * fills the window rather than sitting in the content measure. The band
 * machinery is otherwise untouched: the 60/40 pair is the ordinary two-column
 * band, un-contained here and nowhere else.
 */
body.is-landing {
    background: var(--jsm-navy-d);
}

/*
 * The landing page is one grid at every width, not a stack of bands.
 *
 * Every wrapper between <main> and the pieces steps out of the layout with
 * `display: contents` so that the photograph, the marquee and the policy strip
 * can reach across both columns while the headline keeps to one — and so that
 * the reading order can be set here rather than being dictated by which band a
 * piece happens to live in. In source order the policy strip arrives before
 * the chooser and the service cards; stacked, it has to come last.
 */
body.is-landing .jsm-landing {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    background: var(--jsm-navy-d);
    /* Keeps the photograph's negative z-index inside the page. */
    isolation: isolate;
}

body.is-landing .jsm-band {
    padding-block: 0;
}

body.is-landing .jsm-landing > .jsm-s-splash,
body.is-landing .jsm-s-splash > .wrap,
body.is-landing .jsm-band-cols,
body.is-landing .jsm-band-cols > .jsm-col,
body.is-landing .jsm-col-splash > .jsm-splash {
    display: contents;
}

/* Stacked: headline, chooser, cards, marquee, policy strip. */
body.is-landing .jsm-splash::before,
body.is-landing .jsm-splash-media,
body.is-landing .jsm-splash-body {
    grid-area: 1 / 1 / 2 / -1;
    position: static;
}

body.is-landing .jsm-splash-media { z-index: -2; }
body.is-landing .jsm-splash::before { z-index: -1; }

body.is-landing .jsm-audience    { grid-area: 2 / 1 / 3 / -1; }
body.is-landing .jsm-s-products  { grid-area: 3 / 1 / 4 / -1; }
body.is-landing .jsm-ticker      { grid-area: 4 / 1 / 5 / -1; }
body.is-landing .jsm-splash-foot { grid-area: 5 / 1 / 6 / -1; }

body.is-landing .jsm-splash-body {
    min-height: 60vh;
}

/* ------------------------------------------------------------------ Splash */

.jsm-splash {
    position: relative;
    display: grid;
    /*
     * The explicit column matters. Without it the implicit track is `auto`,
     * which sizes to max-content — and the .wrap inside each row has a 1240px
     * max-width, so the ticker and the foot would both lay themselves out at
     * 1240px and hang over the audience column beside them.
     */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 1fr auto auto;
    min-height: 100%;
    isolation: isolate;
    color: var(--jsm-white);
    background: var(--jsm-navy-d);
}

.jsm-splash-media {
    position: absolute;
    inset: 0;
    z-index: -2;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}

/*
 * The wash over the photograph. It is heavier at the bottom than the top so the
 * policy strip stays legible wherever the image is cropped, and heavier on the
 * left because that is where the headline sits.
 */
.jsm-splash::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        linear-gradient(180deg, rgba(26, 46, 74, .35) 0%, rgba(26, 46, 74, .55) 45%, rgba(26, 46, 74, .92) 100%),
        linear-gradient(90deg, rgba(26, 46, 74, .72) 0%, rgba(26, 46, 74, .34) 55%, rgba(26, 46, 74, .18) 100%);
}

.jsm-splash--blue::before {
    background:
        linear-gradient(180deg, rgba(14, 74, 134, .34) 0%, rgba(11, 60, 110, .58) 45%, rgba(11, 60, 110, .93) 100%),
        linear-gradient(90deg, rgba(11, 60, 110, .74) 0%, rgba(11, 60, 110, .32) 55%, rgba(11, 60, 110, .16) 100%);
}

.jsm-splash--dark::before {
    background:
        linear-gradient(180deg, rgba(0, 0, 0, .38) 0%, rgba(0, 0, 0, .6) 45%, rgba(0, 0, 0, .9) 100%);
}

.jsm-splash--none::before {
    display: none;
}

.jsm-splash-body {
    display: flex;
    align-items: center;
    padding-block: clamp(3rem, 7vh, 6rem);
}

/*
 * The splash sits in a column of its own rather than across the page, so the
 * 24px content gutter leaves the headline against the window edge. Widen it
 * for every row of the splash.
 */
.jsm-splash .wrap {
    --jsm-gutter: clamp(1.5rem, 4vw, 3.25rem);
}

.jsm-splash-inner {
    width: 100%;
}

.jsm-splash-badge {
    display: inline-block;
    margin: 0 0 1.25rem;
    padding: .45em 1.1em;
    border: 1px solid rgba(255, 255, 255, .45);
    border-radius: 999px;
    font-family: var(--jsm-font-head);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--jsm-white);
    background: rgba(255, 255, 255, .1);
    backdrop-filter: blur(2px);
}

/*
 * Pitched at 0,1,1 so it beats the `:where(body.jsm) h1` element default, which
 * would otherwise paint the headline navy on a navy wash.
 */
.jsm-splash .jsm-splash-title {
    margin: 0 0 1.1rem;
    font-size: clamp(2.1rem, 4.2vw, 3.6rem);
    line-height: 1.08;
    letter-spacing: -.01em;
    color: var(--jsm-white);
    text-wrap: balance;
    text-shadow: 0 2px 18px rgba(0, 0, 0, .3);
}

.jsm-splash-lead {
    max-width: 34rem;
    margin: 0 0 2rem;
    font-size: clamp(1rem, 1.2vw, 1.12rem);
    line-height: 1.65;
    color: rgba(255, 255, 255, .88);
}

.jsm-splash-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .85rem;
}

/* ------------------------------------------------------- Announcement marquee */

.jsm-ticker {
    position: relative;
    border-block: 1px solid rgba(255, 255, 255, .16);
    background: rgba(13, 31, 54, .55);
    backdrop-filter: blur(3px);
}

.jsm-ticker-inner {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-block: .7rem;
}

.jsm-ticker-label {
    flex: none;
    margin: 0;
    padding: .35em .9em;
    border-radius: 999px;
    font-family: var(--jsm-font-head);
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--jsm-navy-d);
    background: var(--jsm-yellow);
}

.jsm-ticker-viewport {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    /* Fade the text out at both ends instead of clipping it mid-letter. */
    mask-image: linear-gradient(90deg, transparent 0, #000 2.5rem, #000 calc(100% - 2.5rem), transparent 100%);
}

/*
 * The rail holds the item list twice over. Translating it by exactly half its
 * own width lands on the start of the second copy, which is pixel-identical to
 * where the first one began — so the loop has no visible seam and needs no
 * measurement in script.
 */
.jsm-ticker-rail {
    display: flex;
    width: max-content;
    animation: jsm-marquee var(--jsm-ticker-speed, 34s) linear infinite;
}

.jsm-ticker:hover .jsm-ticker-rail,
.jsm-ticker:focus-within .jsm-ticker-rail,
.jsm-ticker.is-paused .jsm-ticker-rail {
    animation-play-state: paused;
}

@keyframes jsm-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

.jsm-ticker-track {
    display: flex;
    align-items: center;
    gap: 3rem;
    margin: 0;
    padding: 0 1.5rem 0 0;
    list-style: none;
}

.jsm-ticker-item {
    font-size: .9rem;
    white-space: nowrap;
}

.jsm-ticker-item::before {
    content: '\2022';
    margin-right: .9rem;
    color: var(--jsm-yellow);
}

.jsm-ticker .jsm-ticker-item a,
.jsm-ticker .jsm-ticker-item span {
    color: rgba(255, 255, 255, .9);
    text-decoration: none;
}

.jsm-ticker .jsm-ticker-item a:hover,
.jsm-ticker .jsm-ticker-item a:focus {
    color: var(--jsm-white);
    text-decoration: underline;
}

.jsm-ticker-pause {
    flex: none;
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, .28);
    border-radius: 50%;
    color: var(--jsm-white);
    background: transparent;
    cursor: pointer;
}

.jsm-ticker-pause:hover,
.jsm-ticker-pause:focus {
    background: rgba(255, 255, 255, .14);
}

/* Two bars while running, one triangle while paused. */
.jsm-ticker-pause span {
    width: 9px;
    height: 10px;
    background: linear-gradient(90deg,
        currentColor 0 3px, transparent 3px 6px, currentColor 6px 9px);
}

.jsm-ticker.is-paused .jsm-ticker-pause span {
    width: 0;
    height: 0;
    margin-left: 2px;
    background: none;
    border-left: 9px solid currentColor;
    border-block: 5px solid transparent;
}

/* ------------------------------------------------------------- Splash foot */

.jsm-splash-foot {
    background: rgba(13, 31, 54, .72);
    backdrop-filter: blur(3px);
}

.jsm-splash-foot-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .75rem 1.5rem;
    padding-block: 1rem;
    font-size: .82rem;
}

.jsm-splash-policy,
.jsm-splash-copy {
    margin: 0;
}

.jsm-splash-policy {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .55rem;
}

.jsm-splash-foot .jsm-splash-policy a,
.jsm-splash-foot .jsm-splash-a11y {
    color: rgba(255, 255, 255, .85);
    text-decoration: none;
}

.jsm-splash-foot .jsm-splash-policy a:hover,
.jsm-splash-foot .jsm-splash-policy a:focus,
.jsm-splash-foot .jsm-splash-a11y:hover,
.jsm-splash-foot .jsm-splash-a11y:focus {
    color: var(--jsm-white);
    text-decoration: underline;
}

.jsm-sep {
    color: rgba(255, 255, 255, .35);
}

.jsm-splash-copy {
    margin-top: .35rem;
    color: rgba(255, 255, 255, .62);
    font-size: .76rem;
}

.jsm-splash-foot-right {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.jsm-splash-social {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.jsm-splash-social a {
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, .12);
    transition: background-color .15s ease;
}

.jsm-splash-social a:hover,
.jsm-splash-social a:focus {
    background: rgba(255, 255, 255, .26);
}

.jsm-splash-social img {
    width: 1.05rem;
    height: 1.05rem;
    object-fit: contain;
}

/* ---------------------------------------------------------------- Audience */

.jsm-audience {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    min-height: 100%;
    padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.5rem, 3.5vw, 3.25rem) clamp(2rem, 4vw, 3rem);
    background: var(--jsm-white);
}

.jsm-audience-utility {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .75rem 1rem;
    padding-bottom: 1.1rem;
    border-bottom: 1px solid var(--jsm-line);
}

/*
 * Icon over label, the same arrangement and the same measurements as the
 * masthead's utility rail on the portal pages — these are the same four links,
 * and they should not be a different thing in two places.
 */
.jsm-audience-util {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1.1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.jsm-audience .jsm-audience-util a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .25rem;
    max-width: 4.6rem;
    font-size: .62rem;
    font-weight: 500;
    line-height: 1.2;
    text-align: center;
    color: var(--jsm-ink);
    text-decoration: none;
}

.jsm-audience .jsm-audience-util a:hover,
.jsm-audience .jsm-audience-util a:focus {
    color: var(--jsm-red);
}

.jsm-audience-util img {
    /* A fixed box, so a tall icon and a wide one still sit on one baseline. */
    height: 1.5rem;
    width: auto;
    max-width: 2.4rem;
    object-fit: contain;
}

.jsm-audience .jsm-audience-lang {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .3em .85em .3em .35em;
    border: 1px solid var(--jsm-line);
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 600;
    color: var(--jsm-navy);
    text-decoration: none;
}

.jsm-audience .jsm-audience-lang:hover,
.jsm-audience .jsm-audience-lang:focus {
    border-color: var(--jsm-blue-l);
    color: var(--jsm-blue);
}

.jsm-audience-lang img {
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 50%;
    object-fit: cover;
}

/*
 * The mark takes the panel's full width. It is a wide lockup — jata, "Official
 * Portal", the department and the ministry on four lines of type — and at the
 * 22rem it used to be capped at, the ministry line was down at 5px and
 * unreadable. The height cap is only there so a square logo cannot run away
 * with the panel.
 */
.jsm-audience-identity img {
    max-width: 100%;
    max-height: 6.5rem;
    width: auto;
    height: auto;
}

/* ------------------------------------------------------------------- Tabs */

.jsm-audience-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    padding-bottom: .15rem;
    border-bottom: 2px solid var(--jsm-line);
}

.jsm-audience-tab {
    position: relative;
    padding: .65em 1.15em;
    border: 0;
    border-radius: var(--jsm-radius-sm) var(--jsm-radius-sm) 0 0;
    font-family: var(--jsm-font-head);
    font-size: .86rem;
    font-weight: 600;
    color: var(--jsm-muted);
    background: transparent;
    cursor: pointer;
    transition: color .15s ease, background-color .15s ease;
}

.jsm-audience-tab:hover {
    color: var(--jsm-blue);
    background: var(--jsm-surface);
}

.jsm-audience-tab.is-active {
    color: var(--jsm-navy);
}

/* Sits on the track's own 2px line rather than adding height to the button. */
.jsm-audience-tab.is-active::after {
    content: '';
    position: absolute;
    inset: auto 0 -.15rem;
    height: 3px;
    border-radius: 3px 3px 0 0;
    background: var(--jsm-red);
}

.jsm-audience-panels {
    flex: 1 1 auto;
}

.jsm-audience-panel {
    margin: 0;
    padding: 0;
    list-style: none;
}

.jsm-audience-panel[hidden] {
    display: none;
}

.jsm-audience-panel > li + li {
    border-top: 1px solid var(--jsm-line);
}

.jsm-audience .jsm-audience-panel a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .85rem .35rem;
    font-size: .92rem;
    font-weight: 500;
    color: var(--jsm-ink);
    text-decoration: none;
    transition: color .15s ease, background-color .15s ease, padding-left .15s ease;
}

.jsm-audience .jsm-audience-panel a:hover,
.jsm-audience .jsm-audience-panel a:focus {
    color: var(--jsm-blue);
    background: var(--jsm-surface);
    padding-left: .75rem;
}

.jsm-audience-label {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    min-width: 0;
}

/*
 * A small outlined square at the head of each link, as the design draws it.
 *
 * Drawn with an inset box-shadow rather than a border. A 1px border on an 8px
 * box is a hairline: on a 1x display it lands on a fractional pixel, gets
 * antialiased to about half strength, and at the opacity this started on it
 * disappeared altogether. A shadow is painted inside the box and survives that,
 * and the opacity is high enough now to read on the photograph behind it.
 */
.jsm-audience-bullet {
    flex: none;
    width: .55rem;
    height: .55rem;
    box-shadow: inset 0 0 0 1px currentColor;
    opacity: .8;
}

.jsm-audience-badge {
    flex: none;
    padding: .18em .55em;
    border-radius: 4px;
    font-family: var(--jsm-font-head);
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--jsm-white);
    background: var(--jsm-red);
}

.jsm-audience-go {
    flex: none;
    font-size: 1.3rem;
    line-height: 0;
    color: var(--jsm-blue-l);
}

.jsm-audience-empty {
    padding: .85rem .35rem;
    font-size: .88rem;
    color: var(--jsm-muted);
}

/* ==========================================================================
   Landing page — the approved gold scheme

   The second mockup turns the landing page warm: the photograph is tinted gold
   and runs behind the whole band, the chooser becomes a translucent blue panel
   floating on it with a yellow tab bar, and the marquee and the policy strip
   span the full page rather than the splash column.

   It is all opt-out. The splash side keys off the Overlay setting (`gold`) and
   the chooser off its Tone setting (`photo`); set Overlay back to Navy and Tone
   back to Light and the first scheme returns untouched.
   ========================================================================== */

/* ------------------------------------------- Letting the splash span the band */

/*
 * On a wide screen the page is one grid, not a stack of bands: the chooser runs
 * the full height of the left column's two rows, while the marquee, the policy
 * strip and the photograph reach across both columns.
 *
 * Rather than move any of that out of the sections it belongs to — an editor
 * should find the marquee with the splash, not somewhere else — every wrapper
 * between <main> and the pieces steps out of the layout with `display:
 * contents`, which hands them all to one grid. No markup changes, and the
 * mobile stack below is untouched because this is `min-width` scoped.
 *
 *   row 1   splash headline        │  chooser
 *   row 2   products               │  (same chooser, spanning)
 *   row 3   marquee, full width
 *   row 4   policy strip, full width
 */
@media (min-width: 62.0625rem) {
    body.is-landing .jsm-landing {
        grid-template-columns: minmax(0, 60fr) minmax(0, 40fr);
        grid-template-rows: 1fr auto auto auto;
        min-height: 100vh;
        min-height: 100dvh;
    }

    /*
     *   row 1   splash headline        │  chooser
     *   row 2   service cards          │  (same chooser, spanning)
     *   row 3   marquee, full width
     *   row 4   policy strip, full width
     */
    body.is-landing .jsm-splash::before,
    body.is-landing .jsm-splash-media {
        /* Behind the headline and the chooser, but not the cards. */
        grid-area: 1 / 1 / 3 / -1;
    }

    body.is-landing .jsm-splash-body {
        grid-area: 1 / 1 / 2 / 2;
        min-height: 0;
    }

    /* Opaque, which is what hides the photograph behind this row. */
    body.is-landing .jsm-s-products {
        grid-area: 2 / 1 / 3 / 2;
        padding: clamp(1.75rem, 3vw, 2.75rem) clamp(1.5rem, 4vw, 3.25rem);
        background: var(--jsm-white);
    }

    body.is-landing .jsm-audience    { grid-area: 1 / 2 / 3 / -1; }
    body.is-landing .jsm-ticker      { grid-area: 3 / 1 / 4 / -1; }
    body.is-landing .jsm-splash-foot { grid-area: 4 / 1 / 5 / -1; }

    /* Both strips run edge to edge now, so the content measure comes off. */
    body.is-landing .jsm-ticker-inner,
    body.is-landing .jsm-splash-foot-inner {
        max-width: none;
    }
}

/*
 * The cards keep their own padding when stacked; only the content measure goes,
 * so they fill the column rather than sitting in a 1240px well inside it.
 */
body.is-landing .jsm-s-products {
    background: var(--jsm-white);
}

body.is-landing .jsm-s-products > .wrap {
    max-width: none;
}

/* ------------------------------------------------------------- Gold splash */

/*
 * The photograph is graded rather than merely dimmed: a touch of sepia and a
 * lift in brightness is what makes the warm wash above it read as one image
 * instead of a yellow film laid over a cold one.
 */
.jsm-splash--gold .jsm-splash-media {
    filter: sepia(.4) saturate(.8) brightness(1.12) contrast(.94);
}

.jsm-splash--gold::before {
    background:
        /*
         * Shade for the white type, in bronze rather than navy. A navy veil
         * over a gold-graded photograph pulls the left third back to blue and
         * the two halves of the image stop looking like one picture.
         */
        linear-gradient(90deg, rgba(64, 44, 16, .46) 0%, rgba(64, 44, 16, .16) 46%, rgba(64, 44, 16, 0) 72%),
        linear-gradient(170deg, rgba(242, 179, 7, .38) 0%, rgba(240, 169, 43, .28) 52%, rgba(255, 238, 204, .22) 100%);
}

/* A solid plate, not the glassy outline the navy scheme uses. */
.jsm-splash--gold .jsm-splash-badge {
    border-color: var(--jsm-navy);
    border-radius: 5px;
    color: var(--jsm-white);
    background: var(--jsm-navy);
    backdrop-filter: none;
}

.jsm-splash--gold .jsm-splash-lead {
    color: rgba(255, 255, 255, .92);
    text-shadow: 0 1px 10px rgba(26, 46, 74, .45);
}

/* -------------------------------------------------------- Gold marquee strip */

.jsm-splash--gold .jsm-ticker {
    border-block: 1px solid var(--jsm-line);
    background: var(--jsm-white);
    backdrop-filter: none;
}

.jsm-splash--gold .jsm-ticker-inner {
    /* The label is flush to the page edge, so the row carries no gutter. */
    --jsm-gutter: 0;
    gap: 0;
    padding-block: 0;
}

.jsm-splash--gold .jsm-ticker-label {
    align-self: stretch;
    display: flex;
    align-items: center;
    padding: .9em 1.15em;
    border-radius: 0;
    color: var(--jsm-navy-d);
    background: var(--jsm-yellow);
}

.jsm-splash--gold .jsm-ticker-viewport {
    padding-inline: 1.35rem;
}

.jsm-splash--gold .jsm-ticker-item {
    color: var(--jsm-navy);
}

.jsm-splash--gold .jsm-ticker-item::before {
    color: var(--jsm-blue-l);
}

.jsm-splash--gold .jsm-ticker-item a,
.jsm-splash--gold .jsm-ticker-item span {
    color: var(--jsm-navy);
}

.jsm-splash--gold .jsm-ticker-item a:hover,
.jsm-splash--gold .jsm-ticker-item a:focus {
    color: var(--jsm-blue);
}

.jsm-splash--gold .jsm-ticker-pause {
    margin-right: 1.1rem;
    border-color: var(--jsm-line);
    color: var(--jsm-navy);
}

.jsm-splash--gold .jsm-ticker-pause:hover,
.jsm-splash--gold .jsm-ticker-pause:focus {
    background: var(--jsm-surface);
}

/* ------------------------------------------------------- Gold policy strip */

.jsm-splash--gold .jsm-splash-foot {
    background: var(--jsm-navy);
    backdrop-filter: none;
}

/*
 * Three tracks with nothing in the third: that is what centres the social row
 * against the page rather than against the text beside it.
 */
.jsm-splash--gold .jsm-splash-foot-inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    padding-block: 1.15rem;
}

/* Outlined discs, as the design draws them on the navy strip. */
.jsm-splash--gold .jsm-splash-social a {
    width: 1.95rem;
    height: 1.95rem;
    border: 1px solid rgba(255, 255, 255, .34);
    background: none;
}

.jsm-splash--gold .jsm-splash-social a:hover,
.jsm-splash--gold .jsm-splash-social a:focus {
    border-color: rgba(255, 255, 255, .7);
    background: rgba(255, 255, 255, .14);
}

@media (max-width: 40rem) {
    .jsm-splash--gold .jsm-splash-foot-inner {
        grid-template-columns: minmax(0, 1fr);
        justify-items: start;
        gap: .9rem;
    }
}

/* ------------------------------------------------- Main products & services */

.jsm-s-products .jsm-band-title {
    margin: 0 0 1.25rem;
    font-size: clamp(1.25rem, 2.2vw, 1.6rem);
}

.jsm-products {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 1rem;
}

/*
 * The gold rule along the top is the card's whole decoration, so it is a border
 * rather than a pseudo-element: it keeps its place if a card grows a different
 * background later.
 */
.jsm-product {
    display: flex;
    flex-direction: column;
    gap: .7rem;
    padding: 1.1rem 1.1rem 1.25rem;
    border: 1px solid var(--jsm-line);
    border-top: 3px solid var(--jsm-yellow);
    border-radius: 0 0 var(--jsm-radius-sm) var(--jsm-radius-sm);
    background: var(--jsm-white);
    box-shadow: var(--jsm-shadow);
}

/*
 * The agency's service marks are wide lockups — around 360x150 — so the cap is
 * on height and the width follows. A fixed minimum keeps the three cards'
 * text on the same line whatever shape each mark turns out to be.
 */
.jsm-product-mark {
    display: flex;
    align-items: center;
    min-height: 3.4rem;
}

.jsm-product-mark img {
    max-width: 100%;
    max-height: 3.4rem;
    width: auto;
    object-fit: contain;
}

.jsm-product-name {
    margin: 0;
    font-family: var(--jsm-font-head);
    font-weight: 700;
    color: var(--jsm-navy);
}

.jsm-product-body {
    flex: 1 1 auto;
    margin: 0;
    font-size: .88rem;
    line-height: 1.55;
    color: var(--jsm-ink);
}

.jsm-s-products .jsm-product-go {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-weight: 600;
    font-size: .88rem;
    color: var(--jsm-blue);
    text-decoration: none;
}

.jsm-s-products .jsm-product-go:hover,
.jsm-s-products .jsm-product-go:focus {
    color: var(--jsm-blue-d);
    text-decoration: underline;
}

.jsm-product-chev {
    font-size: 1.2em;
    line-height: 0;
}

/* ---------------------------------------------- Chooser as a panel on the photo */

/*
 * Only the utility strip and the agency mark keep a white plate; everything
 * below floats on the photograph. The panel supplies its own padding, so the
 * wrapper gives all of it up.
 */
.jsm-audience--photo {
    position: relative;
    gap: 0;
    padding: 0;
    background: none;
}

/*
 * The announcement flag, stood on its end against the page's right edge —
 * inside the panel, not hanging off it: translated outwards it pushed past the
 * document width and put a horizontal scrollbar on the page.
 */
.jsm-audience-flag {
    position: absolute;
    top: 38%;
    right: 0;
    z-index: 2;
    padding: 1.1rem .5rem;
    border-radius: var(--jsm-radius-sm) 0 0 var(--jsm-radius-sm);
    writing-mode: vertical-rl;
    font-family: var(--jsm-font-head);
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--jsm-navy-d);
    background: var(--jsm-yellow);
    pointer-events: none;
}

/* Stacked, the panel is the full width and the flag would sit over the links. */
@media (max-width: 62rem) {
    .jsm-audience-flag {
        display: none;
    }
}

.jsm-audience--photo .jsm-audience-utility,
.jsm-audience--photo .jsm-audience-identity {
    background: var(--jsm-white);
    padding-inline: clamp(1.25rem, 2.6vw, 2.25rem);
}

.jsm-audience--photo .jsm-audience-utility {
    padding-block: 1.4rem 1.1rem;
    border-bottom: 0;
}

.jsm-audience--photo .jsm-audience-identity {
    padding-bottom: 1.6rem;
}

/* ------------------------------------------------------------ Yellow tab bar */

.jsm-audience--photo .jsm-audience-tabs {
    gap: 0;
    padding: 0;
    border-bottom: 0;
    background: var(--jsm-yellow);
}

.jsm-audience--photo .jsm-audience-tab {
    /* Equal shares of the bar, which is what makes it read as a bar. */
    flex: 1 1 0;
    padding: .95em .75em;
    border-radius: 0;
    font-size: .88rem;
    text-align: center;
    color: var(--jsm-navy);
}

.jsm-audience--photo .jsm-audience-tab:hover {
    color: var(--jsm-navy-d);
    background: rgba(255, 255, 255, .22);
}

.jsm-audience--photo .jsm-audience-tab.is-active {
    font-weight: 700;
    color: var(--jsm-navy-d);
    background: rgba(255, 255, 255, .38);
}

/* The red rule under the active tab is the light scheme's marker, not this one. */
.jsm-audience--photo .jsm-audience-tab.is-active::after {
    display: none;
}

/* ------------------------------------------------------- Links on the photo */

.jsm-audience--photo .jsm-audience-panels {
    padding: .35rem clamp(1.25rem, 2.6vw, 2.25rem) 2.25rem;
    background: rgba(14, 74, 134, .74);
}

.jsm-audience--photo .jsm-audience-panel > li + li {
    border-top-color: rgba(255, 255, 255, .17);
}

.jsm-audience--photo .jsm-audience-panel a {
    color: rgba(255, 255, 255, .94);
}

.jsm-audience--photo .jsm-audience-panel a:hover,
.jsm-audience--photo .jsm-audience-panel a:focus {
    color: var(--jsm-white);
    background: rgba(255, 255, 255, .13);
}

.jsm-audience--photo .jsm-audience-go {
    color: rgba(255, 255, 255, .6);
}

/* Inverted against the blue: white plate, red word. */
.jsm-audience--photo .jsm-audience-badge {
    color: var(--jsm-red);
    background: var(--jsm-white);
}

.jsm-audience--photo .jsm-audience-empty {
    color: rgba(255, 255, 255, .72);
}

/*
 * Stacked, the panel no longer has a photograph behind it — the splash ends
 * above it — so the blue has to stand on its own.
 */
@media (max-width: 62rem) {
    .jsm-audience--photo .jsm-audience-panels {
        background: var(--jsm-blue);
    }
}

/* ==========================================================================
   Login page — the intranet's sign-in door
   ========================================================================== */

:root {
    --jsm-login-from: #16205f;
    --jsm-login-mid:  #2b1e80;
    --jsm-login-to:   #553ac6;
}

body.is-login {
    background: var(--jsm-white);
}

.jsm-login {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    min-height: 100vh;
    min-height: 100dvh;
}

.jsm-login--brandwide { grid-template-columns: 1.4fr .95fr; }
.jsm-login--formwide  { grid-template-columns: .95fr 1.25fr; }

/* ------------------------------------------------------------ Brand panel */

.jsm-login-brand {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    color: var(--jsm-white);
    background: linear-gradient(170deg,
        var(--jsm-login-from) 0%, var(--jsm-login-mid) 58%, var(--jsm-login-to) 100%);
}

/*
 * The photograph is a band, not a full-bleed background: the source is around
 * 537px wide, so stretched over a tall panel it goes soft. At band height it
 * sits close to its native size.
 */
.jsm-login-photo {
    position: relative;
    flex: 0 0 42%;
    min-height: 14rem;
    background-repeat: no-repeat;
    background-size: cover;
}

/*
 * A light tint for cohesion that fades to solid at the foot, so the seam into
 * the block below disappears instead of cutting hard.
 */
.jsm-login-photo::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--jsm-login-from) 34%, transparent) 0%,
        color-mix(in srgb, var(--jsm-login-from) 20%, transparent) 42%,
        color-mix(in srgb, var(--jsm-login-from) 90%, transparent) 90%,
        var(--jsm-login-from) 100%);
}

.jsm-login-brandbody {
    position: relative;
    flex: 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, .78fr);
    gap: 2.4rem;
    align-items: center;
    padding: 2rem clamp(1.5rem, 3.4vw, 3rem) 2.4rem;
}

/*
 * The brand side's wording arrives from a module, so the template cannot know
 * its markup — these rules dress whatever an editor puts there rather than a
 * fixed structure. Pitched at 0,1,1 so they beat the element defaults without
 * needing to out-specify a module's own classes.
 */
.jsm-login-brandmain :is(h1, h2, h3) {
    margin: 0 0 .5rem;
    font-family: var(--jsm-font-head);
    font-weight: 800;
    font-size: clamp(1.9rem, 3.1vw, 2.7rem);
    line-height: 1.08;
    letter-spacing: -.02em;
    max-width: 14ch;
    text-transform: uppercase;
    text-wrap: balance;
    color: var(--jsm-white);
}

.jsm-login-brandmain p {
    margin: 0 0 1rem;
    color: rgba(255, 255, 255, .82);
    max-width: 42ch;
}

.jsm-login-brandmain p:last-child {
    margin-bottom: 0;
}

.jsm-login-brandmain a {
    color: var(--jsm-white);
}

/*
 * The design's three-part opening: a small eyebrow over the name, then a gold
 * tagline under it. A module's editor marks them up with these classes.
 */
.jsm-login-brandmain .jsm-eyebrow {
    margin-bottom: .35rem;
    font-size: .95rem;
    font-weight: 500;
    letter-spacing: .02em;
    text-transform: none;
    color: rgba(255, 255, 255, .88);
}

.jsm-login-brandmain .jsm-tagline {
    margin-bottom: 1.6rem;
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: .01em;
    color: var(--jsm-gold);
}

.jsm-login-brandmain .jsm-lead {
    padding-top: 1.4rem;
    border-top: 1px solid rgba(255, 255, 255, .18);
}

/*
 * The disclaimer, as the right column of the welcome block. A rule rather than
 * a filled band, so it reads as a footnote and not as another panel.
 */
.jsm-login-note {
    padding-left: 2.2rem;
    border-left: 1px solid rgba(255, 255, 255, .2);
}

.jsm-login-note :is(h1, h2, h3, h4, p.jsm-note-title) {
    margin: 0 0 .55rem;
    font-family: var(--jsm-font-body);
    font-size: .68rem;
    font-weight: 500;
    letter-spacing: .32em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .62);
}

.jsm-login-note p {
    margin: 0;
    font-size: .78rem;
    line-height: 1.6;
    color: rgba(255, 255, 255, .82);
}

/* ------------------------------------------------------------- Form panel */

.jsm-login-panel {
    display: grid;
    place-items: center;
    padding: 2.5rem 2rem;
    background: var(--jsm-white);
}

.jsm-login-card {
    width: 100%;
    max-width: 25rem;
}

.jsm-login-card .jsm-login-title,
.jsm-login-card .page-header h1 {
    margin: 0 0 .3rem;
    font-family: var(--jsm-font-head);
    font-weight: 700;
    font-size: 1.7rem;
    letter-spacing: -.02em;
}

.jsm-login-sub {
    margin: 0 0 1.6rem;
    font-size: .95rem;
    color: var(--jsm-muted);
}

.jsm-login-image {
    max-width: 100%;
    height: auto;
    margin-bottom: 1.4rem;
}

/*
 * Joomla's system messages, as the design's compact inline alert rather than
 * the full-bleed banner Cassiopeia draws. This is the "please sign in first"
 * notice a visitor meets when they are bounced here from a protected page, so
 * it is the one piece of the card most people will actually read.
 */
/*
 * Joomla's system messages, as the design's compact inline alert rather than
 * the full-bleed banner Cassiopeia draws. This is the "please sign in first"
 * notice a visitor meets when they are bounced here from a protected page, so
 * it is the one piece of the card most people will actually read.
 *
 * Two shapes are covered. With scripting on, messages.js builds a
 * <joomla-alert> custom element; with it off, the server's <noscript> fallback
 * is a plain .alert div. Both are dressed, because the fallback is exactly the
 * case where a visitor most needs to be told what went wrong.
 */
.jsm-login-card #system-message-container {
    display: block;
    margin-bottom: 1.2rem;
}

.jsm-login-card #system-message-container:empty {
    margin-bottom: 0;
}

.jsm-login-card :is(joomla-alert, .alert) {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    margin: 0 0 .6rem;
    padding: .7rem .85rem;
    border: 1px solid var(--jsm-line);
    border-radius: 10px;
    background: var(--jsm-surface);
    font-size: .88rem;
    line-height: 1.5;
    color: var(--jsm-ink);
}

.jsm-login-card :is(joomla-alert, .alert):last-child {
    margin-bottom: 0;
}

/*
 * The heading is an icon plus a visually-hidden word — there is no visible
 * text in it — so it is sized as the glyph it actually is.
 */
.jsm-login-card .alert-heading {
    display: grid;
    place-items: center;
    flex: none;
    width: 1.2rem;
    height: 1.2rem;
    margin: .1rem 0 0;
    padding: 0;
    border-radius: 4px;
    color: inherit;
    font-size: 1rem;
    line-height: 1;
    /*
     * The fill stays Cassiopeia's — it is the severity badge, amber for a
     * warning and red for an error, and it is the only colour on the alert
     * that tells them apart. Only the size is taken in hand: left alone it is
     * a 42px block beside two lines of type.
     */
}

.jsm-login-card .alert-heading > span {
    display: block;
    width: 1em;
    height: 1em;
}

.jsm-login-card .alert-wrapper {
    flex: 1 1 auto;
    min-width: 0;
}

.jsm-login-card .alert-message :is(p, ul) {
    margin: 0;
}

.jsm-login-card .alert-message ul {
    padding-left: 1.1rem;
}

/* Warning and error carry the red; the body text stays readable ink. */
.jsm-login-card :is(joomla-alert[type="warning"], joomla-alert[type="danger"],
                    .alert-warning, .alert-danger, .alert-error) {
    border-color: color-mix(in srgb, var(--jsm-red) 35%, var(--jsm-line));
    background: color-mix(in srgb, var(--jsm-red) 7%, var(--jsm-white));
    color: var(--jsm-red);
}

.jsm-login-card :is(joomla-alert[type="success"], .alert-success) {
    border-color: color-mix(in srgb, #1f9d55 35%, var(--jsm-line));
    background: color-mix(in srgb, #1f9d55 7%, var(--jsm-white));
}

.jsm-login-card .alert-message {
    color: var(--jsm-ink);
}

.jsm-login-card .joomla-alert--close {
    flex: none;
    margin-left: auto;
    padding: 0 .15rem;
    border: 0;
    font-size: 1.15rem;
    line-height: 1;
    color: inherit;
    background: none;
    opacity: .55;
    cursor: pointer;
}

.jsm-login-card .joomla-alert--close:hover,
.jsm-login-card .joomla-alert--close:focus {
    opacity: 1;
}

.jsm-login-field {
    margin-bottom: 1rem;
}

.jsm-login-field label {
    display: block;
    margin-bottom: .35rem;
    font-size: .83rem;
    font-weight: 600;
    color: var(--jsm-muted);
}

/* Joomla marks a required field with a star inside the label. */
.jsm-login-field .star {
    color: var(--jsm-red);
}

.jsm-login-control {
    position: relative;
    display: flex;
    align-items: center;
}

.jsm-login-lead {
    position: absolute;
    left: .85rem;
    color: var(--jsm-muted);
    pointer-events: none;
}

.jsm-login-control input {
    width: 100%;
    font: inherit;
    font-size: .95rem;
    color: inherit;
    background: var(--jsm-surface);
    border: 1.5px solid var(--jsm-line);
    border-radius: 10px;
    /* Room for the glyph on the left and the reveal button on the right. */
    padding: .8rem 2.9rem;
    outline: none;
    transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

.jsm-login-control input::placeholder {
    color: var(--jsm-muted);
}

.jsm-login-control input:focus {
    border-color: var(--jsm-blue);
    background: var(--jsm-white);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--jsm-blue) 16%, transparent);
}

/*
 * Joomla's password field brings its own reveal button, wrapped in an
 * .input-group. Rather than suppress it and write another, the group is
 * flattened and the button dressed as the design's.
 */
/*
 * Joomla nests the password field twice — .password-group wrapping an
 * .input-group — and both are block boxes. Flattening only the inner one left
 * the field sized by its `size="25"` attribute inside the outer block, so both
 * have to go.
 */
.jsm-login-control .password-group,
.jsm-login-control .input-group {
    display: contents;
}

/*
 * With the group flattened, the input becomes a flex child of the control and
 * sizes to its `size` attribute rather than the row. width:100% does not help
 * — a flex item's base size wins — so it has to be told to grow.
 */
.jsm-login-control input {
    flex: 1 1 auto;
    min-width: 0;
}

.jsm-login-control .input-password-toggle {
    position: absolute;
    right: .45rem;
    display: grid;
    place-items: center;
    width: 2.1rem;
    height: 2.1rem;
    padding: 0;
    border: 0;
    border-radius: 8px;
    color: var(--jsm-muted);
    background: none;
    cursor: pointer;
}

.jsm-login-control .input-password-toggle:hover,
.jsm-login-control .input-password-toggle:focus {
    color: var(--jsm-blue);
    background: color-mix(in srgb, var(--jsm-blue) 12%, transparent);
}

.jsm-login-control .input-password-toggle .icon-eye-close::before,
.jsm-login-control .input-password-toggle .icon-eye::before {
    font-size: 1rem;
}

.jsm-login-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin: .2rem 0 1.4rem;
    font-size: .88rem;
}

.jsm-login-check {
    display: flex;
    align-items: center;
    gap: .5rem;
    cursor: pointer;
    color: var(--jsm-muted);
}

.jsm-login-check input {
    width: 1.05rem;
    height: 1.05rem;
    accent-color: var(--jsm-blue);
}

.jsm-login-card .jsm-login-forgot {
    font-weight: 600;
    text-decoration: none;
}

.jsm-login-card .jsm-login-forgot:hover,
.jsm-login-card .jsm-login-forgot:focus {
    text-decoration: underline;
}

.jsm-login-submit {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    width: 100%;
    padding: .85rem 1rem;
    font: inherit;
    font-family: var(--jsm-font-head);
    font-weight: 700;
    font-size: 1rem;
    color: var(--jsm-white);
    background: var(--jsm-blue);
    border: 0;
    border-radius: 10px;
    cursor: pointer;
    transition: background-color .15s ease, transform .1s ease;
}

.jsm-login-submit:hover {
    background: var(--jsm-blue-d);
}

.jsm-login-submit:active {
    transform: translateY(1px);
}

.jsm-login-extra {
    width: 100%;
    margin-bottom: .75rem;
    justify-content: center;
    color: var(--jsm-ink);
    border-color: var(--jsm-line);
}

.jsm-login-extra:hover,
.jsm-login-extra:focus {
    color: var(--jsm-blue);
    background: var(--jsm-surface);
    border-color: var(--jsm-blue);
}

/* A rule either side of a short caption. */
.jsm-login-sep {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: .8rem;
    margin: 1.5rem 0 1.1rem;
    font-size: .78rem;
    color: var(--jsm-muted);
}

.jsm-login-sep::before,
.jsm-login-sep::after {
    content: '';
    height: 1px;
    background: var(--jsm-line);
}

/* --------------------------------------------------- Already signed in */

/*
 * The same card, with the form replaced by a way out and a way on. The
 * sign-out button is the page's one action, so it keeps the submit's weight.
 */
.jsm-login-signedin .jsm-login-sub {
    margin-bottom: 1.8rem;
}

.jsm-login-signedin .jsm-login-sub :is(p, ul) {
    margin: 0;
}

.jsm-login-onward {
    margin-top: 1.1rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--jsm-line);
}

.jsm-login-links,
.jsm-login-help {
    display: grid;
    gap: .5rem;
    font-size: .88rem;
}

.jsm-login-help {
    margin-top: .5rem;
}

.jsm-login-card :is(.jsm-login-links, .jsm-login-help) a {
    display: flex;
    align-items: center;
    gap: .55rem;
    color: var(--jsm-muted);
    text-decoration: none;
}

.jsm-login-card :is(.jsm-login-links, .jsm-login-help) a:hover,
.jsm-login-card :is(.jsm-login-links, .jsm-login-help) a:focus {
    color: var(--jsm-blue);
}

.jsm-login-card :is(.jsm-login-links, .jsm-login-help) svg {
    flex: none;
    color: var(--jsm-muted);
}

/* The help block comes from a module, so it may arrive as a list. */
.jsm-login-help ul {
    display: grid;
    gap: .5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* ----------------------------------------------------------- Narrow login */

@media (max-width: 60rem) {
    .jsm-login,
    .jsm-login--brandwide,
    .jsm-login--formwide {
        grid-template-columns: minmax(0, 1fr);
        min-height: 0;
    }

    .jsm-login-photo {
        flex: 0 0 auto;
        min-height: 9rem;
    }

    .jsm-login-brandbody {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.3rem;
        padding: 1.4rem 1.5rem 1.8rem;
    }

    .jsm-login-brandmain :is(h1, h2, h3) {
        font-size: 1.6rem;
    }

    .jsm-login-note {
        padding-left: 0;
        padding-top: 1.2rem;
        border-left: 0;
        border-top: 1px solid rgba(255, 255, 255, .2);
    }

    .jsm-login-note p {
        font-size: .74rem;
    }

    .jsm-login-panel {
        padding: 2rem 1.25rem 2.5rem;
    }
}

/* ==========================================================================
   Narrow screens
   ========================================================================== */

@media (max-width: 62rem) {
    :root {
        --jsm-band-pad: 3rem;
    }

    .jsm-nav-toggle {
        display: grid;
    }

    .jsm-brand-text {
        display: none;
    }

    /**
     * The navigation becomes a drawer the toggle opens.
     *
     * visibility, not just the transform. A fixed element parked off-screen to
     * the right still counts toward the document's scroll width — the page
     * gained about 30px of sideways scroll with nothing in it — and body
     * overflow cannot clip a fixed box. visibility:hidden takes it out of the
     * scrollable area, and transitioning it keeps the slide.
     */
    .jsm-nav {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        z-index: 120;
        width: min(21rem, 86vw);
        overflow-y: auto;
        border-bottom: 0;
        box-shadow: var(--jsm-shadow-lg);
        visibility: hidden;
        transform: translateX(100%);
        transition: transform .25s ease, visibility .25s;
    }

    .jsm-nav.is-open {
        visibility: visible;
        transform: none;
    }

    .jsm-nav .wrap {
        padding: 4rem 1.25rem 2rem;
    }

    .jsm-nav-inner {
        flex-direction: column;
        align-items: stretch;
    }

    .jsm-menu {
        flex-direction: column;
        align-items: stretch;
    }

    .jsm-menu-link {
        padding: .8rem .25rem;
        border-bottom: 1px solid var(--jsm-line);
    }

    .jsm-menu-toggle {
        display: grid;
        place-items: center;
    }

    /* A submenu opens in flow rather than floating over the drawer. */
    .jsm-submenu {
        position: static;
        display: none;
        min-width: 0;
        margin: 0 0 .5rem;
        padding: .25rem 0 .25rem .9rem;
        background: none;
        border: 0;
        border-radius: 0;
        box-shadow: none;
        opacity: 1;
        visibility: visible;
        transform: none;
    }

    .jsm-menu-item.is-open > .jsm-submenu {
        display: block;
    }

    .jsm-menu-item:hover > .jsm-submenu,
    .jsm-menu-item:focus-within > .jsm-submenu {
        display: none;
    }

    .jsm-menu-item.is-open:hover > .jsm-submenu {
        display: block;
    }

    .jsm-submenu .jsm-menu-link {
        color: var(--jsm-muted);
        border-bottom: 0;
        padding: .45rem .25rem;
    }

    .jsm-submenu .jsm-menu-item:hover > .jsm-menu-link {
        background: none;
        color: var(--jsm-red);
    }

    .jsm-nav-backdrop {
        position: fixed;
        inset: 0;
        z-index: 110;
        background: rgba(26, 46, 74, .5);
    }

    .jsm-s-content.has-left .jsm-content-grid,
    .jsm-s-content.has-right .jsm-content-grid,
    .jsm-s-content.has-left.has-right .jsm-content-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .jsm-footer-top {
        grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    }

    /*
     * Stacked, the headline panel gets a share of the screen rather than a
     * whole one — a full viewport before anything can be chosen is two screens
     * of scrolling to reach the chooser.
     */
    body.is-landing .jsm-splash-body {
        min-height: 60vh;
    }

    body.is-landing .jsm-s-products {
        padding: 1.75rem 0 2.25rem;
    }
}

@media (max-width: 40rem) {
    /* Four labelled icons do not fit beside the wordmark on a phone. */
    .jsm-utilrail {
        display: none;
    }

    .jsm-identity-controls {
        padding-left: 0;
        border-left: 0;
    }

    .jsm-highlights {
        flex-wrap: wrap;
    }

    .jsm-highlights-item {
        white-space: normal;
    }

    .jsm-hero-inner {
        padding-block: 2.5rem;
    }

    .jsm-footerbar-inner {
        justify-content: flex-start;
    }

    .jsm-splash-foot-inner {
        flex-direction: column;
        align-items: flex-start;
    }

    .jsm-audience-utility {
        justify-content: flex-start;
    }

    /* Let the tab row scroll sideways rather than wrap onto three lines. */
    .jsm-audience-tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .jsm-audience-tabs::-webkit-scrollbar {
        display: none;
    }

    .jsm-audience-tab {
        flex: none;
    }
}

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

    /*
     * The blanket rule above would leave the marquee restarting every .01ms,
     * which is worse than the motion it was meant to remove. Stop it outright,
     * drop the duplicate track, and let the strip scroll by hand instead.
     */
    .jsm-ticker-rail {
        animation: none !important;
        width: auto;
    }

    .jsm-ticker-viewport {
        overflow-x: auto;
        mask-image: none;
    }

    .jsm-ticker-track[aria-hidden="true"] {
        display: none;
    }

    .jsm-ticker-pause {
        display: none;
    }
}

@media print {
    .jsm-govbar,
    .jsm-header,
    .jsm-nav,
    .jsm-backtotop,
    .jsm-footer-social,
    .jsm-carousel-btn,
    .jsm-ticker,
    .jsm-splash-media {
        display: none !important;
    }

    /* Every tab's links on paper, since there is nothing to click. */
    .jsm-audience-panel[hidden] {
        display: block !important;
    }

    .jsm-band {
        padding-block: 1rem;
    }
}
