/* ============================================================================
   Programme selector - the three-way chooser on /Login/Login and
   /Login/Registration.

   WHY THIS IS ITS OWN FILE, and not part of cutom.css.

   cutom.css is loaded by SIX views - LearnerAudit/Index, Login, Registration,
   Login/WelcomeMSG, Subscriber/NewsSubscribers and Subscriber/WelcomeSubsMsg -
   and several of them use .left-side-sc and .pic-ft. Editing those rules to suit
   this component would silently restyle four unrelated screens. So nothing in
   cutom.css is touched: everything here is new and scoped under .fte-prog or
   .fte-*. This file used to carry a few .pic-ft / .left-side-sc h2 overrides
   inside media queries; both elements have since left these two pages - the logo
   moved to the right column as .fte-brand, the h2 was deleted - so those rules
   could no longer match anything and have gone with them.

   It needs no bundle registration - Startup.cs bundles only the public-site
   _Layout list, and these two views link their stylesheets individually.

   Same shape as wwwroot/css/entry-header.css, for the same reasons.
   ========================================================================= */


/* ============================================================================
   THE TYPE, and why this block exists.

   cutom.css declares exactly one face - `font-family: Helvetica` pointing at
   HelveticaNeueLTStd-Cn.otf, the CONDENSED REGULAR - and then asks for bold all
   over the app. There is no bold in that file, so the browser SYNTHESISES one by
   smearing the regular sideways. That is why every heading on this page looked
   flat and soft: nothing was ever set in a real bold.

   wwwroot/fonts already carries the whole Helvetica Neue LT Std family - Roman,
   Md, Bd, Hv, Blk and the condensed cuts - all sitting unused. Nothing here is a
   new download or a new licence; these are the same files the app already ships.

   TWO FAMILIES, DELIBERATELY NAMED, so cutom.css's `Helvetica` is untouched and
   the five other views that share it cannot be affected:

     FTDisplay   Bold Condensed / Black Condensed. The house heading style -
                 Fairtrade.css already sets headings in HelveticaNeue-BoldCN -
                 and the same condensed idiom as the FAIRTRADE wordmark itself.
     FTText      Roman / Medium. Upright and readable at small sizes, for the
                 sub-labels and eyebrows that Condensed makes hard work of.

   font-display: swap - the text paints in the fallback immediately and reflows
   when the face lands. Never a blank heading.
   ========================================================================== */

@font-face {
    font-family: 'FTDisplay';
    src: url('../fonts/HelveticaNeueLTStd-BdCn.otf') format('opentype');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'FTDisplay';
    src: url('../fonts/HelveticaNeueLTStd-BlkCn.otf') format('opentype');
    font-weight: 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'FTText';
    src: url('../fonts/HelveticaNeueLTStd-Roman.otf') format('opentype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'FTText';
    src: url('../fonts/HelveticaNeueLTStd-Md.otf') format('opentype');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

/* ============================================================================
   THE SHELL - one set of measurements for /Login/Login and /Login/Registration.

   These two pages were built to different numbers, which is why everything on
   screen shifted when you moved between them:

       Login          col-lg-6 / col-lg-6   .right-side-sc-login (flex, centred)
       Registration   col-lg-5 / col-lg-7   .right-side-sc       (no rule at all)

   Both are now col-lg-5 / col-lg-7 in the markup, and both carry the two classes
   below, so the legacy difference between .right-side-sc and .right-side-sc-login
   stops mattering without editing cutom.css - which five views share.

   THE PATTERN, top to bottom. Anything added here should follow it:

       .login-main-wrp                      the white card, 80% wide, 90vh
         .row.new-lg
           .col-lg-5 > .fte-shell-left      no vertical centring
               .fte-shell-left-inner        full-height column
                   .fte-prog                three colour blocks   - the WHOLE panel,
                                                                    a third each
           .col-lg-7 > .fte-shell-right
               .scroll-right-wp.fte-prog-scroll
                   .fte-brand               the Fairtrade mark   - never moves
                   .fte-prog-head           programme name       - never moves
                   [role=tabpanel]
                       .fte-pane-head       tab bar / slogan     - never moves
                       .fte-pane-body .fte-scrollbox   the only thing that scrolls

   Every "- never moves" above is held by a FIXED size, not by content that
   happens to be the same length. Content-driven boxes are what caused the drift.

   Desktop only. Below 992px the columns stack and the page scrolls, which is what
   cutom.css already arranges and what a phone wants.
   ========================================================================== */

@media (min-width: 992px) {
    /* cutom.css centres the figure vertically (align-items:center), so the whole
       left panel floated up or down depending on how tall its contents happened to
       be. stretch instead, and NO PADDING: there is nothing above the blocks to hold
       off the top edge any more - the logo has gone to the right column - so the
       chooser starts at the panel's top edge and the three blocks are the whole of
       the left half, corner to corner. */
    .fte-shell-left {
        align-items: stretch;
        justify-content: center;
        padding-top: 0;
    }

    /* No max-width. This column once capped its contents at 420px, which was right when
       it held a logo and three cards; the blocks are full-bleed sections now and the logo
       is no longer here, so there is nothing left to cap. */
    .fte-shell-left-inner {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
    }

    /* .fte-shell-left-head is GONE, along with the element it sized. It was 244px of
       logo and a "Welcome To" heading, then 172px of logo alone; now the logo lives at
       the top of the right column and the head has no reason to exist. Every pixel it
       held goes to .fte-prog below, which is flex:1.

       Nothing else styles that class - checked before deleting - so the rule is removed
       rather than zeroed out. */

    /* The blocks ARE the panel: this is the only child of the column now. */
    .fte-shell-left-inner > .fte-prog {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }

    /* .right-side-sc-login sets align-items/justify-content: center, which made a
       short pane float in the middle of the card. Same specificity, later file,
       so this wins - and .right-side-sc, which has no base rule at all, gets the
       identical box from the same declaration. */
    .fte-shell-right {
        display: flex;
        align-items: stretch;
        justify-content: flex-start;
        height: 100%;
    }
}

/* ---- letting the photograph back in ----
   cutom.css lays a 90%-opaque lime sheet over bg1.jpg (.left-side-sc:before). At that
   strength the photograph underneath is all but gone, and with the three blocks now
   covering the panel corner to corner nothing of it reached the eye at all.

   Thinned to 55%, so the market photo reads through the lime, and the blocks above are
   translucent so it carries on through them.

   SCOPED TO .fte-shell-left, which only these two views carry. .left-side-sc alone is
   shared with five other screens; same specificity, and programme-panel.css is linked
   after cutom.css on both pages, so this wins here and changes nothing there. */
.fte-shell-left::before {
    background: rgba(185, 223, 0, .55);
}

/* ---------------------------------------------------------------- tablist */

.fte-prog {
    width: 100%;
    margin: 0;
    text-align: left;
}

/* ===========================================================================
   THREE EQUAL BLOCKS.

   Thirds of whatever height is left under the header - not three fixed cards.
   The old min-height:80px is exactly what made them unequal: the Schools
   sub-label is longer than the other two, so its card grew and the three
   stopped matching. 1fr each cannot drift, whatever the copy does.

   gap:0 on purpose. These read as sections of one panel, which is what the
   colour is for; a gap would turn them back into three buttons floating on the
   lime background.
   ========================================================================= */
.fte-prog-nav {
    flex: 1;
    min-height: 0;
    /* FLEX, NOT GRID. It was `grid-template-rows: repeat(3, 1fr)`, which gives the same
       equal thirds - but a grid TRACK cannot be collapsed by the item sitting in it, and
       the two-step flow needs exactly that: fold two cards away and let the third take
       the room. flex-grow is a number, so it animates; grid-template-rows would have to
       be rewritten on the container for every state. */
    display: flex;
    flex-direction: column;
    gap: 0;
}

.fte-prog-item {
    display: flex;
    align-items: center;
    gap: 15px;
    width: 100%;
    flex: 1 1 0;                /* equal thirds, and collapsible one at a time */
    min-height: 0;
    padding: 14px 22px;
    border: 0;
    border-radius: 0;
    /* TRANSLUCENT, so the photograph behind the panel shows through. rgba() and not
       the hex --prog-bg, because a hex cannot take an alpha - hence --prog-rgb, which
       is the same colour with its channels loose.

       .78 is not a taste decision. Below it the label on the PINK block drops under
       4.5:1 somewhere in the photo: the alphas were chosen by compositing lime over
       every pixel of the real bg1.jpg, then the block, then the raking light's darkest
       stop, and taking the worst pixel in the image. At lime .55 / block .78 the worst
       case is 4.62:1 on pink, 9.19 on turquoise, 6.93 on orange. Pink is always the
       binding one; lower either alpha and it is the first to fail. */
    background: rgba(var(--prog-rgb, 255,59,99), .78);
    /* PURE black, not the near-black #0A0F1F used elsewhere. Over a flat colour the two
       are indistinguishable, but the block is no longer flat - it varies with the photo
       - and that last bit of depth is what keeps pink above 4.5. #0A0F1F measures 4.26
       here, which fails. */
    color: #000;
    text-align: left;
    cursor: pointer;
    position: relative;         /* the ::before below is positioned against this */
    overflow: hidden;
    transition: box-shadow .18s ease, transform .18s ease;
}

/* A raking light across each block - bright at the top left, shading off to the
   bottom right. Flat colour was most of why these read as three plain swatches; this
   gives them a surface without touching the hue, so the programme colours are still
   exactly the colours that were chosen.

   pointer-events:none so it never eats a click, and no z-index so it paints under the
   icon and the text, which come after it in the box's own paint order. */
.fte-prog-item::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(135deg,
                                rgba(255, 255, 255, .26) 0%,
                                rgba(255, 255, 255, .04) 38%,
                                rgba(0, 0, 0, .03) 72%,
                                rgba(0, 0, 0, .06) 100%);
}

/* A hairline between the blocks, in the ink of the colour above rather than a grey line
   that would belong to neither. */
.fte-prog-item + .fte-prog-item {
    border-top: 1px solid rgba(10, 15, 31, .13);
}

/* UNSELECTED IS VEILED, NOT GREYED. A translucent white over the brand colour keeps the
   programme identifiable while making the chosen one obviously chosen - and because the
   veil only LIGHTENS, the dark text above gets more contrast rather than less, so no
   second reading is needed for this state. */
.fte-prog-item:not(.is-current) {
    box-shadow: inset 0 0 0 999px rgba(255, 255, 255, .22);
}

.fte-prog-item:hover {
    box-shadow: inset 0 0 0 999px rgba(255, 255, 255, .12);
    transform: none;
}

.fte-prog-item:focus-visible {
    outline: 3px solid #0A0F1F;
    outline-offset: -5px;      /* inset: an outside ring would be clipped by the block above */
}

/* The selected block shows its colour at full strength and is ringed in white. It cannot go
   white itself any more - that would remove the colour this whole change exists for. */
.fte-prog-item.is-current {
    box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .92),
                0 10px 26px rgba(0, 48, 64, .22);
    z-index: 1;                /* so the ring is not overdrawn by the next block's border */
    position: relative;
}

/* ---- the icon, on a white tile ----
   All three tabs now use the same structure: this span IS the tile, the img inside is the
   artwork. They used to differ - Schools was a gradient tile wrapping a 26px image, the other
   two were bare 44px images - so this class meant two different things and no one rule could
   size both. */
.fte-prog-icon {
    width: 52px;
    height: 52px;
    flex: none;
    border-radius: 15px;
    /* Not flat white any more: a top-lit tile, with a hairline highlight along its top
       edge and a real shadow under it, so it sits ON the block rather than in it. */
    background: linear-gradient(158deg, #FFFFFF 0%, #F2F5FA 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 5px 14px rgba(10, 15, 31, .20),
                inset 0 1px 0 rgba(255, 255, 255, .95);
    transition: transform .22s cubic-bezier(.2, .8, .3, 1),
                box-shadow .22s ease;
}

.fte-prog-item:hover .fte-prog-icon,
.fte-prog-item.is-current .fte-prog-icon {
    transform: translateY(-3px);
    box-shadow: 0 9px 20px rgba(10, 15, 31, .26),
                inset 0 1px 0 rgba(255, 255, 255, .95);
}

.fte-prog-icon img {
    display: block;
}

.fte-prog-text {
    flex: 1;
    min-width: 0;
    line-height: 1.3;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* Was 1rem at a synthesised 800 and sentence case - the same soft, smeared bold as
   the old heading. A real Black Condensed in upper case instead: it reads as a title
   rather than a sentence, it echoes the FAIRTRADE wordmark, and being condensed it
   takes LESS width at a larger size, so the long Schools name still holds one line. */
.fte-prog-text b {
    display: block;
    font-family: 'FTDisplay', 'Helvetica', Arial, sans-serif;
    font-size: 1.12rem;
    font-weight: 900;
    line-height: 1.1;
    letter-spacing: .022em;
    text-transform: uppercase;
}

/* Was #5A6580, which measures 2.94:1 on the pink. Even #2A3040 only reaches 3.80. This is
   5.06:1 at worst - and the worst is always the pink. Raising the opacity only improves
   that; a real Medium replaces a condensed regular, so it holds its own under the much
   heavier title above without competing with it. */
.fte-prog-text span {
    display: block;
    font-family: 'FTText', 'Helvetica', Arial, sans-serif;
    font-size: .8rem;
    font-weight: 500;
    letter-spacing: .012em;
    /* Was #141926 at .84 opacity. Opacity on text is a blend with WHATEVER IS BEHIND
       it, and what is behind it is now a photograph - so the effective ink, and the
       contrast with it, changed from pixel to pixel. Measured, that came out at 3.39:1
       on the pink block, well under the 4.5 small text needs. A solid pure black is
       4.62 in the same worst case. The hierarchy against the title is carried by size
       and weight, which is enough, and does not move when the picture does. */
    color: #000;
    margin-top: 5px;
}

.fte-prog-mark {
    flex: none;
    display: inline-flex;
    color: #000;               /* not the accent: on these grounds it would half-disappear */
    /* .38 was fine on a flat block. Against the photo it measured under the 3:1 that
       non-text UI needs; .62 puts the worst case at 3.08 on pink. */
    opacity: .62;
    transition: opacity .18s ease, transform .18s ease;
}

.fte-prog-item.is-current .fte-prog-mark {
    opacity: 1;
    transform: translateX(3px);
}

.fte-prog-badge {
    flex: none;
    font-family: 'FTDisplay', 'Helvetica', Arial, sans-serif;
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: #0A0F1F;
    background: rgba(255, 255, 255, .82);
    border-radius: 999px;
    padding: 5px 11px;
    white-space: nowrap;
    box-shadow: 0 1px 3px rgba(10, 15, 31, .12);
}

/* ---- LOGIN / REGISTRATION, the pane's own tab row ----
   Scoped to .fte-prog-scroll, and .tab-log-btn appears in no other view, so this
   cannot reach anything else. It was two flat grey slabs in a synthesised bold; it is
   a segmented control now, with the selected half lifted onto white and carrying the
   programme's accent. cutom.css marks the selected one with .text-primary, which is a
   Bootstrap utility and lands with !important - hence the !important here to beat it,
   which is the only place on this page that needs one. */
.fte-prog-scroll .tab-log-btn {
    display: inline-flex;
    gap: 5px;
    background: #EEF2F8;
    padding: 5px;
    border-radius: 14px;
}

.fte-prog-scroll .tab-log-btn .btn {
    font-family: 'FTDisplay', 'Helvetica', Arial, sans-serif;
    font-size: .84rem;
    font-weight: 700;
    letter-spacing: .13em;
    padding: 11px 34px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: #67718C;
    transition: background .18s ease, color .18s ease, box-shadow .18s ease;
}

.fte-prog-scroll .tab-log-btn .btn:hover {
    color: #0A0F1F;
}

.fte-prog-scroll .tab-log-btn .btn.text-primary {
    background: #FFFFFF;
    color: var(--prog-accent, #DB3355) !important;
    box-shadow: 0 2px 8px rgba(10, 15, 31, .13);
}

/* The narrow-screen treatment is NOT here. This file already carries a
   @media (max-width: 991px) block further down, and two blocks at one breakpoint would
   fight over flex-direction. It is updated in place instead - see "stacked, one under
   another" below, where the cards keep this same row structure at full width. */


/* ============================================================================
   THE TWO-STEP FLOW - choose a programme, then sign in to it.

   Step 1  the three cards, and nothing else
   Step 2  the chosen card alone beside its form, with a Go back out of it

   NOTHING HERE APPLIES UNTIL THE SCRIPT SAYS SO. Every rule is scoped under
   .fte-flow, and programme-panel.js puts that class on .login-main-wrp only once
   it has wired the whole thing up. With no JavaScript - and ~/js/main.js already
   throws on this page, so a broken script is the normal case rather than a
   hypothetical - none of this matches, and what renders is the previous
   one-screen layout: three cards, a visible Schools form, and a working POST.
   That is also why the form is never `display:none`; it is a width and an
   opacity, so it is still there for anything that ignores this file.

   THE TRICK THAT MAKES THE MOVE READ WELL. In step 2 the left column is
   col-lg-5 of a card that is 80% of the viewport - 0.80 x 0.41667 = 33.33% of
   the viewport. So step 1 sets the WHOLE CARD to 33.33% with the left column at
   100% of it. The cards therefore occupy the same pixels in both steps and do
   not move at all: the panel simply unfolds to the right and the form arrives in
   the space that opens. Change the 80% in cutom.css and this number must follow.
   ========================================================================== */

.fte-flow {
    transition: width .55s cubic-bezier(.65, 0, .35, 1);
}

/* The starting state must not animate INTO existence. For the first two frames after
   the script takes over, every transition inside the shell is off - otherwise the card
   is seen shrinking from full width to the chooser on load, and a page carrying a login
   failure plays the whole thing backwards and then forwards again. */
.fte-flow-boot,
.fte-flow-boot * {
    transition: none !important;
}

/* An author `display` beats the UA sheet's `[hidden] { display: none }`, so without
   this the Go back button would render straight through its own hidden attribute -
   on the landing screen, and on a page with no JavaScript at all. */
.fte-goback[hidden] {
    display: none;
}

.fte-flow .fte-col-left,
.fte-flow .fte-col-right {
    /* flex-shrink 1, against Bootstrap's 0, and it is not cosmetic. The two bases only
       add up to 100% at the two ENDS of the move - 100+0 landing, 41.667+58.333 picked.
       Every frame in between sums to more than 100, and with shrink:0 the row cannot
       compress, so the form visibly spilled outside the white card for the whole half
       second. Allowing them to shrink keeps the row at 100% throughout; at both ends
       there is nothing to shrink, so the settled layout is untouched. */
    flex-shrink: 1;
    transition: flex-basis .55s cubic-bezier(.65, 0, .35, 1),
                max-width  .55s cubic-bezier(.65, 0, .35, 1),
                width      .55s cubic-bezier(.65, 0, .35, 1);
}

/* The form fades and slides as the room for it appears. The delay lets the panel
   start opening first, so the two do not arrive on top of each other. */
.fte-flow .fte-prog-scroll {
    transition: opacity .38s ease .14s,
                transform .5s cubic-bezier(.65, 0, .35, 1) .14s;
}

.fte-flow .fte-prog-item {
    transition: flex-grow .55s cubic-bezier(.65, 0, .35, 1),
                opacity .34s ease,
                transform .45s cubic-bezier(.65, 0, .35, 1),
                padding .55s cubic-bezier(.65, 0, .35, 1),
                box-shadow .18s ease;
}

/* ---------------------------------------------------------- step 1: landing */

@media (min-width: 992px) {
    /* NO WRAPPING, and this is load-bearing. Bootstrap's .row is flex-wrap: wrap, and the
       landing state gives the left column flex-basis:100% - which is a full line, so the
       right column wraps onto a SECOND one. Flex items stretch to the height of their own
       line, so the left column then sized to the cards' content (about 90px) while the
       invisible right column sat below it holding the card open to 90vh. The symptom was
       three squashed strips at the top of a tall empty card.

       nowrap is safe in both states: 100 + 0 in step one, 41.667 + 58.333 in step two. */
    .fte-flow .row.new-lg {
        flex-wrap: nowrap;
    }

    /* 33.33% = the width the left column ends up at in step 2. See the note above. */
    .fte-flow.is-landing {
        width: 33.3333%;
    }

    .fte-flow.is-landing .fte-col-left {
        flex: 0 0 100%;
        max-width: 100%;
        width: 100%;
    }

    .fte-flow.is-landing .fte-col-right {
        flex: 0 0 0%;
        max-width: 0;
        width: 0;
        overflow: hidden;
    }
}

/* visibility, not just opacity: it takes the form out of the tab order, so Tab from
   the last card does not disappear into an invisible username box. Delayed to the end
   of the move on the way out, immediate on the way in. */
.fte-flow.is-landing .fte-col-right {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: flex-basis .55s cubic-bezier(.65, 0, .35, 1),
                max-width  .55s cubic-bezier(.65, 0, .35, 1),
                width      .55s cubic-bezier(.65, 0, .35, 1),
                opacity .3s ease,
                visibility 0s linear .55s;
}

.fte-flow.is-landing .fte-prog-scroll {
    opacity: 0;
    transform: translateX(30px);
}

/* All three are equal offers here, so none of them wears the selected state - and
   none wears the white veil either, so the landing screen shows the three brand
   colours at full strength. Contrast is fine: this is the same case as a selected
   block, measured at 4.62:1 on the pink. */
.fte-flow.is-landing .fte-prog-item,
.fte-flow.is-landing .fte-prog-item.is-current {
    box-shadow: none;
}

.fte-flow.is-landing .fte-prog-item:hover {
    box-shadow: inset 0 0 0 999px rgba(255, 255, 255, .14);
}

.fte-flow.is-landing .fte-prog-item.is-current .fte-prog-mark {
    opacity: .62;
    transform: none;
}

/* ---------------------------------------------------------- step 2: chosen */

.fte-flow.is-picked .fte-col-right {
    opacity: 1;
    visibility: visible;
}

.fte-flow.is-picked .fte-prog-scroll {
    opacity: 1;
    transform: none;
}

/* The two that were not chosen fold up and slide out. flex-grow 1 -> 0 against a
   flex-basis that is already 0 is what closes the height; overflow:hidden on the
   item (set with the raking light) keeps the icon from spilling as it goes. */
.fte-flow.is-picked .fte-prog-item:not(.is-current) {
    flex-grow: 0;
    opacity: 0;
    transform: translateX(-34px);
    padding-top: 0;
    padding-bottom: 0;
    border-top-width: 0;
    pointer-events: none;
    visibility: hidden;
    transition: flex-grow .55s cubic-bezier(.65, 0, .35, 1),
                opacity .28s ease,
                transform .42s cubic-bezier(.65, 0, .35, 1),
                padding .55s cubic-bezier(.65, 0, .35, 1),
                visibility 0s linear .55s;
}

/* Stacked layout: the columns are full width and stacked, so a right column that is
   merely invisible still leaves a screen of blank card under the three cards. There is
   no width to collapse here - the height is the thing. */
@media (max-width: 991px) {
    .fte-flow .fte-col-right {
        max-height: 400vh;
        transition: max-height .55s cubic-bezier(.65, 0, .35, 1),
                    opacity .3s ease,
                    visibility 0s linear;
    }

    .fte-flow.is-landing .fte-col-right {
        max-height: 0;
        padding-top: 0;
        padding-bottom: 0;
        overflow: hidden;
    }
}

/* ---------------------------------------------------------- Go back */

/* Top of the left column, above SIGN IN TO. align-self so it is only as wide as its
   own text rather than stretching across the column. */
.fte-goback {
    flex: none;
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    margin: 0 0 16px;
    padding: 9px 18px 9px 14px;
    border: 1px solid #E2E7F0;
    border-radius: 999px;
    background: #FFFFFF;
    font-family: 'FTDisplay', 'Helvetica', Arial, sans-serif;
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: #4A5468;
    cursor: pointer;
    transition: color .18s ease, border-color .18s ease,
                background .18s ease, transform .18s ease;
}

.fte-goback span {
    font-size: 1rem;
    line-height: 1;
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
}

.fte-goback:hover {
    color: #0A0F1F;
    border-color: var(--prog-accent, #DB3355);
    background: #F7F9FC;
}

.fte-goback:hover span {
    transform: translateX(-3px);
}

.fte-goback:focus-visible {
    outline: 3px solid var(--prog-accent, #DB3355);
    outline-offset: 3px;
}

/* ---------------------------------------------------------- reduced motion */

/* The flow still works - it is the movement that goes, not the steps. */
@media (prefers-reduced-motion: reduce) {
    .fte-flow,
    .fte-flow .fte-col-left,
    .fte-flow .fte-col-right,
    .fte-flow .fte-prog-scroll,
    .fte-flow .fte-prog-item,
    .fte-flow.is-picked .fte-prog-item:not(.is-current),
    .fte-flow.is-landing .fte-col-right {
        transition-duration: .01ms;
        transition-delay: 0s;
    }

    .fte-flow.is-landing .fte-prog-scroll {
        transform: none;
    }

    .fte-flow.is-picked .fte-prog-item:not(.is-current) {
        transform: none;
    }
}

/* -------------------------------------------------- heading, right column */

/* ============================================================================
   THE HEADER - two columns, and they cannot overlap.

       .fte-prog-header            space-between, top-aligned
         .fte-prog-header-main     Go back, then SIGN IN TO, then the name + rule
         .fte-brandbox             the mark, docked into the card's corner

   The mark used to be absolutely positioned. Out of flow it was invisible to the
   text's layout, so the only thing keeping a long programme name from running
   underneath it was a 78% width cap - a number to re-check against the longest
   title every time the type changed. Two real columns cannot overlap at all, and
   min-width:0 on the left one lets the name wrap rather than push the mark off.
   ========================================================================== */

.fte-prog-header {
    flex: none;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    margin-bottom: 22px;
}

.fte-prog-header-main {
    flex: 1 1 auto;
    min-width: 0;              /* or the title cannot wrap and shoves the mark aside */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

/* DOCKED, not inset. The negative margins cancel .fte-prog-scroll's own 15px padding,
   which is the only thing between this box and the card's edge - the column's Bootstrap
   padding is already cancelled by the row's negative margin, so the scroll box's content
   edge IS the card's edge plus that 15. Take it back and the box sits in the true corner.

   Safe against the overflow:hidden on .fte-prog-scroll: a negative margin of exactly the
   padding lands on the border box, which is where the clip happens - not past it.

   The small padding that remains is optical, so the artwork is not touching the card's
   cut edge. It is the only inset left. */
.fte-brandbox {
    flex: none;
    margin: -15px -15px 0 0;
    padding: 10px 12px 12px 14px;
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
}

/* ---- the Fairtrade mark ----
   Moved here from the left panel so the three programme blocks could have that column
   to themselves. It also reads better here: it now sits directly above the name of the
   programme it is branding.

   IT IS A REAL TRANSPARENT PNG NOW. It used to be logo.jpg, and a JPEG cannot hold
   transparency at all - worse, 2251 of that file's 20086 pixels were near-white but
   not quite white, which is compression ringing and reads as a faint dirty rectangle.
   logo-india.png is the same artwork keyed to a true alpha channel, 64% of it fully
   clear, with the anti-aliased edges un-premultiplied so they carry no white fringe.

   Being honest about what that buys: on this white card a white-backed image and a
   transparent one look identical. The visible win here is the ringing going away and
   the mark being set larger; the transparency is what makes it CORRECT, and what lets
   it sit on a colour later without a box appearing around it.

   NO WRAPPER, and do not add one. In the left panel it wore .pic-ft, which fills white
   and draws a 2px black border - that is what a box around it looks like.

   IN FLOW, inside .fte-brandbox - the right-hand column of the header row. It was
   absolutely positioned; see the note on .fte-prog-header for why that had to go. */
.fte-brand {
    display: block;
    margin: 0;
    line-height: 0;            /* kills the descender gap under an inline image */
    transition: transform .25s cubic-bezier(.2, .8, .3, 1);
}

.fte-brand:hover {
    transform: translateY(-2px);
}

/* max-height rather than a fixed height: the file is 97x117, so the height binds and the
   width follows - 73px at 88. object-fit:contain keeps the proportions if a max-width
   ever ends up binding instead.

   THE FILE IS CROPPED TO ITS INK, and that matters more than the number here. It used to
   be 121x166 of canvas holding 97x117 of mark - 30% of the height and 20% of the width
   was transparent padding carried over from the original JPEG's framing. CSS sizes the
   ELEMENT, not the ink inside it, so a max-height of 88 was drawing a mark that measured
   62px on screen and read as small no matter how far the number was pushed. Cropped, the
   number in this rule is the size actually seen. Do not re-export this asset with
   padding round it. */
.fte-brand-logo {
    display: block;
    max-height: 104px;
    max-width: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
}

.fte-brand:focus-visible {
    outline: 3px solid var(--prog-accent, #DB3355);
    outline-offset: 4px;
    border-radius: 4px;
}

/* Names the selected programme above whichever pane is showing, so the right
   half is never ambiguous about what is being signed into. The rule below the
   title is the tab's own accent, which is the only thing tying the two columns
   together once the left panel scrolls out of view on a phone. */
/* Full width of the LEFT COLUMN, so the rule under the title stops where the text does
   and never runs behind the mark. The row below it owns the gap to the pane. */
.fte-prog-head {
    width: 100%;
    padding-bottom: 18px;
    border-bottom: 1px solid #E7EBF3;
}

/* The 78% cap that used to live here is GONE. It existed to keep the text out from under
   an absolutely positioned mark; the mark is a real column now, so the text simply cannot
   reach it and the words get the full width of their own column. */

/* The eyebrow carries the PROGRAMME'S OWN COLOUR rather than a neutral grey. It is
   the smallest type on the page and it was the dullest; in the accent it becomes the
   thing that visibly changes when you pick a different programme.

   Safe at this size: the three accents were darkened specifically to work on white
   and measure 4.55 / 4.82 / 4.64 to one, all clear of the 4.5 small text needs. Do
   not put the BRIGHT --prog-bg here - those are 1.60 to 3.47 and vanish. */
.fte-prog-head-eyebrow {
    font-family: 'FTDisplay', 'Helvetica', Arial, sans-serif;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--prog-accent, #DB3355);
    margin: 0 0 6px;
}

/* Was 1.16rem at a SYNTHESISED 800 - a condensed regular smeared sideways by the
   browser, which is most of why this page read as flat. Now a real Black Condensed,
   set nearly twice the size and upper case, the same idiom as the FAIRTRADE wordmark
   directly above it. clamp() so it can be big on a wide card without overrunning a
   narrow one. */
.fte-prog-head-title {
    font-family: 'FTDisplay', 'Helvetica', Arial, sans-serif;
    /* Trimmed from clamp(1.5, 2.3vw, 2.05rem) now that it lives in 80% of the column
       rather than all of it. At the old size "FAIRTRADE INDIA SCHOOLS PROGRAMME" - much
       the longest of the three - broke onto a second line on anything under a wide
       desktop. This holds it on one line there and still reads as the biggest thing on
       the page. */
    font-size: clamp(1.3rem, 1.85vw, 1.72rem);
    font-weight: 900;
    line-height: 1.06;
    letter-spacing: .012em;
    text-transform: uppercase;
    color: #0A0F1F;
    margin: 0;
    /* break-word, NOT anywhere. `anywhere` will split a word mid-letter the moment it is
       convenient, which is exactly the awkward wrapping to avoid; this only breaks a word
       that genuinely cannot fit on a line of its own. The overflow it used to guard
       against is handled by the 78% cap above, which keeps the title clear of the mark
       in the corner. */
    overflow-wrap: break-word;
    text-wrap: balance;
}

/* The rule runs from the programme's BRIGHT colour into its darkened one, so it
   carries both halves of the palette that the blocks and this heading each use
   separately. --prog-bg is copied here by programme-panel.js alongside --prog-accent;
   the fallback in the var() is what shows if that script never runs. */
.fte-prog-head-title::after {
    content: "";
    display: block;
    width: 78px;
    height: 5px;
    border-radius: 3px;
    margin-top: 12px;
    background: linear-gradient(90deg,
                                var(--prog-bg, #FF3B63) 0%,
                                var(--prog-accent, #DB3355) 100%);
}

/* ============================================================================
   .fte-scrollbox - REUSABLE. Ask for it by name.

   A region that scrolls INSIDE ITSELF instead of pushing its parent taller, with
   the app's own scrollbar: the lime-to-cyan thumb cutom.css gives
   .scroll-right-wp on the school registration, so a scroll anywhere in the app
   looks like the same app.

   To use it: put .fte-scrollbox on the element that should scroll, and give its
   PARENT a height (or make the parent a flex column and the box flex:1 with
   min-height:0). Without a constrained height, overflow-y:auto does nothing and
   the box simply grows - harmless, which is why this class is safe to leave on
   an element at screen sizes where it should not scroll.

   scrollbar-gutter: stable reserves the bar's width whether or not it is
   showing, so content does not jump sideways when it appears. Where the
   property is unsupported this degrades to a plain auto scroll.
   ========================================================================== */

.fte-scrollbox {
    overflow-y: auto;
    scrollbar-gutter: stable;
    /* Firefox has no ::-webkit- pseudo-elements; these two are its equivalent. */
    scrollbar-width: thin;
    scrollbar-color: #7CC70A #E9ECF2;
}

.fte-scrollbox::-webkit-scrollbar {
    width: 10px;
}

.fte-scrollbox::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgb(206, 206, 206);
    border-radius: 10px;
}

.fte-scrollbox::-webkit-scrollbar-thumb {
    background: linear-gradient(160.85deg, rgba(185, 223, 0, .98) 6.58%, rgba(0, 185, 234, .79) 82.79%);
    border-radius: 10px;
}

.fte-scrollbox::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(160.85deg, rgba(153, 184, 0, .98) 6.58%, rgba(1, 121, 155, .79) 82.79%);
}

/* ------------------------------------------ panes: fixed head, scrolling body */

/* NOTHING ABOVE THE FIELDS EVER MOVES - on either page, for any of the three
   programmes.

   Every pane is built the same way and gets the same box, so switching
   programme, or switching Sign in / Apply, or moving between /Login/Login and
   /Login/Registration, never shifts the heading, the tab bar or the slogan:

       .scroll-right-wp.fte-prog-scroll     fixed-height flex column
         .fte-prog-head                     the programme name      - flex:none
         [role=tabpanel]                    the pane                - flex:1
           .fte-pane-head                   whatever must stay put  - flex:none
           .fte-pane-body .fte-scrollbox    the only thing that scrolls

   Three things used to move it, and all three are answered by the box being a
   CONSTANT size whatever is inside it:

     1. cutom.css caps .scroll-right-wp at 90vh and scrolls it - the scroll the
        school registration has - but removes the cap again for /Login/Login
        (`.right-side-sc-login .scroll-right-wp { max-height: unset; overflow:
        unset }`), so there the page grew instead and the green panel scrolled
        away with it.
     2. .right-side-sc-login centres its child vertically, so a short pane sat
        in the middle of the card and a tall one filled it.
     3. A scrollbar that appeared on some panes and not others moved everything
        sideways by its width.

   HISTORY WORTH KEEPING. An earlier version scoped the parent rule to
   .right-side-sc-login but left the child rules unscoped, so on
   /Login/Registration - which uses .right-side-sc - panes became flex columns
   with no fixed-height parent, their bodies collapsed and the content spilled
   out of the white card. Every rule below is keyed off .fte-prog-scroll alone
   and applies to both pages. Check both.

   Desktop only. Below 992px cutom.css drops the cap deliberately: the columns
   have stacked, the card is height:auto, and the page is the right thing to
   scroll. */
@media (min-width: 992px) {
    /* No .right-side-sc-login prefix: this must win on BOTH pages. It beats
       cutom.css's `max-height: unset` on equal specificity because both views
       link programme-panel.css after cutom.css.

       height, not max-height: a constant box is what stops the vertical jump.
       width/min-width matter just as much and are easier to miss - on
       /Login/Login .scroll-right-wp is a flex item in a centring container with
       the default min-width:auto, so its width followed its CONTENT. */
    .scroll-right-wp.fte-prog-scroll {
        height: 90vh;
        max-height: 90vh;
        width: 100%;
        min-width: 0;
        /* cutom.css gives this padding:15px, then strips the left one back to 0
           for /Login/Login only (`.right-side-sc-login .scroll-right-wp`). That
           lone declaration put the two pages' content 15px apart. Restated here
           so both pages share it. */
        padding: 15px;
        overflow: hidden;
        display: flex;
        flex-direction: column;
    }

    .scroll-right-wp.fte-prog-scroll > .fte-prog-head {
        flex: none;
    }

    /* [role=tabpanel] rather than a class: the Schools pane is written inline in
       each view and carries no class of its own. Direct child only - the Youth
       pane holds two tabpanels of its own that must not be caught. */
    .scroll-right-wp.fte-prog-scroll > [role="tabpanel"] {
        flex: 1;
        min-width: 0;
        /* min-height:0 lets a flex child be shorter than its content, which is
           what allows the body to scroll instead of the column growing. */
        min-height: 0;
        display: flex;
        flex-direction: column;
    }

    .fte-prog-scroll .fte-pane-head {
        flex: none;
    }

    /* Height comes from here; the scrolling and its colours come from
       .fte-scrollbox, which is applied alongside this in the markup. */
    .fte-prog-scroll .fte-pane-body {
        flex: 1;
        min-height: 0;
        padding-right: 6px;
    }
}

/* ------------------------------------------------------------ right panes */

.fte-prog-pane {
    text-align: center;
    padding: 26px 10px;
}

.fte-prog-pane-icon {
    margin: 0 auto 18px;
    display: block;
    border-radius: 16px;
}

.fte-prog-pane-title {
    font-size: 1.5rem;
    font-weight: 700;
    margin: 0 0 10px;
    color: #0A0F1F;
}

.fte-prog-pane-lede {
    color: #5A6580;
    max-width: 42ch;
    margin: 0 auto 22px;
}

.fte-prog-pane-btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
}

.fte-prog-pane-note {
    font-size: .78rem;
    color: #8A93AD;
    margin-top: 16px;
}

/* ==========================================================================
   YOUTH AMBASSADORS PANE - a port of wwwroot/youth/auth.html's sign-in design.

   EVERY CLASS BELOW IS PREFIXED fty- AND SCOPED UNDER .fte-youth, AND THAT IS
   NOT STYLE PEDANTRY. The youth portal's stylesheet names its controls .btn,
   .input, .card, .badge, .steps and .check - all of which Bootstrap or
   cutom.css already define on this page. Linking youth.css here would restyle
   the Schools login form sitting a few pixels away. So the rules are ported
   rather than imported, renamed on the way in, and the values are copied
   verbatim from youth/assets/youth.css so the two screens stay recognisably
   the same design.

   The tokens are likewise local to these classes. They do not leak to :root.

   .fte-camp shares them so the CSM Campaigns pane is built from the same type
   scale, buttons and rules as the Youth one - "the same in all three" is a lot
   easier to hold when there is only one set of values to hold it to.
   ========================================================================== */

.fte-youth,
.fte-camp {
    --fty-cyan: #00B9EA;
    --fty-cyan-d: #0090BC;
    --fty-violet: #7C5CFF;
    --fty-magenta: #FF2D8E;
    --fty-lime: #B6DB01;
    --fty-coral: #FF6B4A;
    --fty-ink: #0A0F1F;
    --fty-slate: #4A5578;
    --fty-muted: #6B7699;
    --fty-line: #E4E8F2;
    --fty-line-2: #EEF1F7;
    --fty-ease: cubic-bezier(.22, .68, .36, 1);
    --fty-shadow-sm: 0 1px 2px rgba(10, 15, 31, .06), 0 2px 8px rgba(10, 15, 31, .05);

    text-align: left;
    padding: 4px 2px 8px;
}

/* ---------------------------------------------------------- the slogan */

/* Sized against the payoff line rather than on its own, the same reasoning as
   auth.html: at its stock size the headline ran about 1.8x "Wear it. Sip it.",
   which read as a statement with a caption. These are two halves of one
   sentence. The right-hand column here is narrower than auth.html's hero, so
   both steps down accordingly. */
.fty-display {
    font-size: clamp(1.25rem, 1.95vw, 1.65rem);
    font-weight: 850;
    letter-spacing: -.036em;
    line-height: 1.14;
    color: var(--fty-ink);
    margin: 0 0 12px;
}

.fty-grad {
    background: linear-gradient(96deg, var(--fty-cyan) 0%, var(--fty-violet) 48%, var(--fty-magenta) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* The three icons sit bare rather than in tinted tiles - all three are line art
   carrying their own gradients, and a coloured backing fights the artwork. */
.fty-wear-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 20px;
}

.fty-wear {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--fty-ink);
    font-size: clamp(.92rem, 1.35vw, 1.15rem);
}

.fty-wear img {
    width: 36px;
    height: 36px;
    object-fit: contain;
    flex: none;
}

.fty-rule {
    height: 1px;
    border: 0;
    margin: 14px 0 13px;
    background: linear-gradient(90deg, rgba(10, 15, 31, .20), rgba(10, 15, 31, .06) 62%, rgba(10, 15, 31, 0));
}

/* ------------------------------------------ segmented Sign in / Apply */

.fty-seg {
    display: flex;
    gap: 4px;
    padding: 4px;
    background: var(--fty-line-2);
    border-radius: 999px;
    margin-bottom: 16px;
}

.fty-seg button {
    flex: 1;
    padding: 9px 16px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    font-weight: 700;
    font-size: .85rem;
    color: var(--fty-slate);
    cursor: pointer;
    transition: all .25s var(--fty-ease);
}

.fty-seg button[aria-selected="true"] {
    background: #fff;
    color: var(--fty-ink);
    box-shadow: var(--fty-shadow-sm);
}

.fty-h2 {
    font-size: 1.3rem;
    font-weight: 800;
    letter-spacing: -.026em;
    text-align: center;
    color: var(--fty-ink);
    margin: 0;
}

.fty-lede {
    font-size: .92rem;
    color: var(--fty-slate);
    line-height: 1.6;
    text-align: center;
    margin: 8px 0 22px;
}

.fty-note {
    font-size: .755rem;
    color: var(--fty-muted);
    text-align: center;
    margin-top: 14px;
}

.fty-note a {
    font-weight: 750;
    color: var(--fty-cyan-d);
}

/* ------------------------------------------------------------- fields */

.fty-field {
    margin-bottom: 12px;
}

.fty-label {
    display: block;
    font-size: .76rem;
    font-weight: 700;
    margin-bottom: 5px;
    color: var(--fty-slate);
}

/* .fty-input, not .input: cutom.css targets .scroll-right-wp .form-control and
   Bootstrap owns .form-control outright, so these fields deliberately share no
   class with the Schools form beside them. */
.fty-input {
    width: 100%;
    padding: 11px 14px;
    border-radius: 12px;
    border: 1.5px solid var(--fty-line);
    background: #fff;
    color: var(--fty-ink);
    transition: border-color .2s var(--fty-ease), box-shadow .2s var(--fty-ease);
}

.fty-input::placeholder {
    color: #A8B0C8;
}

.fty-input:focus {
    outline: none;
    border-color: var(--fty-cyan);
    box-shadow: 0 0 0 4px rgba(0, 185, 234, .14);
}

.fty-input.is-err {
    border-color: var(--fty-coral);
    box-shadow: 0 0 0 4px rgba(255, 107, 74, .13);
}

/* Spinners only appear on hover, differ in every browser, and make the field
   look broken next to the plain ones. inputmode supplies the numeric keypad. */
.fty-input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.fty-input[type="number"]::-webkit-outer-spin-button,
.fty-input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

select.fty-input {
    appearance: none;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B7699' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 17px;
    padding-right: 42px;
}

textarea.fty-input {
    resize: vertical;
    min-height: 96px;
}

.fty-err {
    display: none;
    color: var(--fty-coral);
    font-size: .76rem;
    font-weight: 650;
    margin: 6px 0 0;
}

.fty-err.show {
    display: block;
}

/* Whatever the server refused, at the top of the pane it was refused in.
   .fty-err above is per-field and client-side; this one is per-pane and comes
   back with the page. */
.fty-alert {
    display: block;
    margin: 0 0 14px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid rgba(255, 107, 107, .35);
    background: rgba(255, 107, 107, .10);
    color: var(--fty-coral);
    font-size: .82rem;
    font-weight: 650;
    line-height: 1.35;
}

.fty-alert-ok {
    border-color: rgba(0, 185, 234, .35);
    background: rgba(0, 185, 234, .10);
    color: var(--prog-accent, #DB3355);
}

.fty-input-icon {
    position: relative;
}

.fty-input-icon > svg {
    position: absolute;
    left: 15px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    color: var(--fty-muted);
    pointer-events: none;
}

.fty-input-icon .fty-input {
    padding-left: 44px;
}

.fty-peek {
    position: absolute;
    right: 13px;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: none;
    padding: 2px;
    line-height: 0;
    color: var(--fty-muted);
    cursor: pointer;
}

.fty-check {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    cursor: pointer;
    font-size: .845rem;
    color: var(--fty-slate);
}

.fty-check input {
    width: 18px;
    height: 18px;
    margin: 1px 0 0;
    accent-color: var(--fty-cyan);
    flex: none;
    cursor: pointer;
}

.fty-row-between {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin: 2px 0 14px;
}

.fty-link {
    font-size: .845rem;
    font-weight: 750;
    color: var(--fty-cyan-d);
}

.fty-grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}

/* ------------------------------------------------------------ buttons */

/* .fty-btn rather than .btn: Bootstrap defines .btn on this page and the two
   sets of padding, radius and shadow are not compatible. */
.fty-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 13px 24px;
    border: 0;
    border-radius: 999px;
    font-weight: 700;
    font-size: .89rem;
    cursor: pointer;
    white-space: nowrap;
    position: relative;
    overflow: hidden;
    transition: transform .22s var(--fty-ease), box-shadow .22s var(--fty-ease),
                background .22s var(--fty-ease), color .22s var(--fty-ease), border-color .22s var(--fty-ease);
}

.fty-btn svg {
    width: 18px;
    height: 18px;
    flex: none;
}

.fty-btn:hover {
    transform: translateY(-2px);
}

.fty-btn:active {
    transform: translateY(0);
}

.fty-btn-primary {
    background: linear-gradient(96deg, var(--fty-cyan), var(--fty-violet));
    color: #fff;
    box-shadow: 0 8px 32px rgba(0, 185, 234, .28);
}

.fty-btn-primary:hover {
    color: #fff;
    box-shadow: 0 12px 40px rgba(124, 92, 255, .42);
}

.fty-btn-lime {
    background: var(--fty-lime);
    color: var(--fty-ink);
    box-shadow: 0 8px 28px rgba(182, 219, 1, .34);
}

.fty-btn-lime:hover {
    color: var(--fty-ink);
    box-shadow: 0 12px 38px rgba(182, 219, 1, .46);
}

.fty-btn-ghost {
    border: 1.5px solid var(--fty-line);
    background: #fff;
    color: var(--fty-ink);
}

.fty-btn-ghost:hover {
    border-color: var(--fty-cyan);
    color: var(--fty-cyan-d);
}

.fty-btn-block {
    width: 100%;
}

.fty-btn-lg {
    padding: 14px 28px;
    font-size: .93rem;
}

/* The three group headings that replaced the wizard's step numbers. They carry
   the same grouping - You / Institution / Motivation - so a long single-scroll
   form is still scannable. First one drops its top margin; it follows the
   segmented control, which already has space under it. */
.fty-group {
    font-size: .70rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--fty-muted);
    margin: 20px 0 10px;
    padding-bottom: 7px;
    border-bottom: 1px solid var(--fty-line);
}

.fty-group:first-of-type {
    margin-top: 0;
}

.fty-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
}

.fty-chip {
    display: inline-flex;
    align-items: center;
    padding: 9px 17px;
    border-radius: 999px;
    border: 1.5px solid var(--fty-line);
    background: #fff;
    font-size: .82rem;
    font-weight: 650;
    color: var(--fty-slate);
    cursor: pointer;
    transition: all .2s var(--fty-ease);
}

.fty-chip:hover {
    border-color: var(--fty-cyan);
    color: var(--fty-cyan-d);
    transform: translateY(-1px);
}

.fty-chip[aria-pressed="true"] {
    background: var(--fty-ink);
    border-color: var(--fty-ink);
    color: #fff;
}

/* The success state after "Submit application" - the panel it replaces is
   emptied, so there is no way to submit twice. */
.fty-done {
    text-align: center;
    padding: 26px 6px;
}

.fty-done-mark {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    margin: 0 auto 16px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--fty-cyan), var(--fty-violet));
}

/* The slogan is the first thing to give way when the column is narrow: the
   payoff line stacks instead of sitting in a row, and the icons shrink. */
@media (max-width: 1199px) {
    .fty-wear-row {
        gap: 2px 16px;
    }

    .fty-wear img {
        width: 38px;
        height: 38px;
    }
}

@media (max-width: 575px) {
    .fty-grid-2 {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 479px) {
    .fty-wear {
        font-size: 1.05rem;
    }

    .fty-wear img {
        width: 32px;
        height: 32px;
    }
}

/* SHORT WINDOWS. The card is a fixed 90vh, so on a 768- or 720-tall laptop the
   fixed head was eating enough of it that even the four-field sign-in had to
   scroll - a scrollbar on a form with nothing much below the fold, which reads
   as broken rather than long. The rhythm tightens instead of the content going
   away: the pitch is the one screen a visitor who is not yet enrolled sees, so
   it is not worth dropping to save 40px.

   Same approach, and the same two tiers, as wwwroot/youth/auth.html. */
@media (min-width: 992px) and (max-height: 860px) {
    .fte-prog-head {
        padding-bottom: 8px;
        margin-bottom: 10px;
    }

    .fte-prog-head-title::after {
        margin-top: 6px;
    }

    .fty-display {
        font-size: clamp(1.15rem, 1.7vw, 1.45rem);
        margin-bottom: 9px;
    }

    .fty-wear img {
        width: 30px;
        height: 30px;
    }

    .fty-rule {
        margin: 10px 0 10px;
    }

    .fty-seg {
        margin-bottom: 12px;
    }

    .fty-field {
        margin-bottom: 10px;
    }
}

@media (min-width: 992px) and (max-height: 740px) {
    .fty-display {
        font-size: 1.1rem;
        margin-bottom: 7px;
    }

    .fty-wear {
        font-size: .88rem;
    }

    .fty-wear img {
        width: 26px;
        height: 26px;
    }

    .fty-rule {
        margin: 8px 0;
    }

    .fty-seg button {
        padding: 8px 14px;
    }

    .fty-input {
        padding: 10px 13px;
    }

    .fty-btn-lg {
        padding: 12px 26px;
    }
}

/* --------------------------------------------------- CSM Campaigns pane */

.fty-camp-card {
    border: 1.5px solid var(--fty-line);
    border-radius: 14px;
    padding: 18px;
    margin-bottom: 18px;
    background: #fff;
}

.fty-camp-badge-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

.fty-camp-icon {
    width: 44px;
    height: 44px;
    flex: none;
    border-radius: 12px;
    display: block;
}

.fty-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.fty-list li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: .87rem;
    color: var(--fty-slate);
    padding: 7px 0;
}

/* A tick in the programme's own accent, so the list reads as this programme's
   rather than as generic body copy. */
.fty-list li::before {
    content: "";
    flex: none;
    width: 7px;
    height: 7px;
    margin-top: 7px;
    border-radius: 50%;
    background: var(--prog-accent, #D32F2F);
}

.fty-camp-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 6px;
}

/* ------------------------------------------------- youth sign-in (no form) */

/* Left-aligned, unlike the rest of the pane: these are the same Bootstrap
   .input-group rows the Schools form uses, and they should read as the same
   kind of thing rather than as centred marketing copy. */
.fte-prog-form {
    text-align: left;
    max-width: 420px;
    margin: 0 auto;
}

.fte-prog-err {
    font-size: .85rem;
    font-weight: 600;
    color: #D32F2F;
    margin: -6px 0 12px;
}

.fte-prog-form-foot {
    display: flex;
    justify-content: flex-end;
    font-size: .82rem;
    margin-bottom: 2px;
}

/* Carries the programme's own colour, so the primary action in the Youth pane
   is not the Schools cyan. */
.fte-prog-signin {
    letter-spacing: .03em;
    background: var(--prog-accent, #0055FF);
    border-color: var(--prog-accent, #0055FF);
}

.fte-prog-signin:hover,
.fte-prog-signin:focus {
    filter: brightness(.92);
    background: var(--prog-accent, #0055FF);
    border-color: var(--prog-accent, #0055FF);
}

/* ---------------------------------------------------------------- stacked */

/* Below 992px the Bootstrap columns stack, so the left panel sits ON TOP of the
   right one. The three cards were a compact three-across strip here, and the reason
   was real at the time: with the panel above the form, a vertical list of three would
   push the username field off the first screen.

   THAT REASON IS GONE. The chooser is two steps now (see the .fte-flow block): on the
   landing step the right column is collapsed to max-height:0, so there is no form under
   the cards to push anywhere, and after a programme is picked only ONE card is left.
   The strip was costing legibility to solve a problem that no longer exists - three
   titles in a third of a phone each, with the sub-label and the arrow switched off
   because nothing else fitted.

   So they stack, full width, keeping the desktop's inner structure: icon left, words,
   arrow right. The one case that still pays the old cost is a browser with no
   JavaScript, where there are no steps and the form does sit below all three - it
   scrolls, which is a fair price for the other 99% reading a legible card.

   Breakpoint note: this is 991px and not the 768px a phone-only rule would use, because
   991px is where the columns stack. Between the two the panel is full width but only
   about 900px of it, and three cards across that are just as cramped - one behaviour for
   everything below the desktop layout beats two. */
@media (max-width: 991px) {
    /* THE COLUMN HAS TO OWN ITS OWN BOX FIRST.

       .fte-shell-left-inner is a <figure>, and cutom.css only ever reset its
       margin-BOTTOM - so it still carries the UA default `margin: 1em 40px`. On desktop
       that is invisible because a width:100% rule sits on top of it, but that rule lives
       in the min-width:992px block and does not reach down here. The result was cards
       inset 40px on the left and pushed past the panel's right edge, with the long
       Schools name running off the screen instead of wrapping.

       figure.fte-shell-left-inner, not .fte-shell-left-inner: cutom.css targets
       `.left-side-sc figure`, which is a class plus an element, and a bare class would
       lose to it. Matching its shape and relying on this file loading later wins the
       padding cleanly. */
    figure.fte-shell-left-inner {
        width: 100%;
        margin: 0;
        padding: 22px 16px;
    }

    /* No margin-top: nothing sits above the blocks now, so it would only open a gap. */
    .fte-prog {
        max-width: 100%;
    }

    /* ---- stacked, one under another ---- */
    .fte-prog-nav {
        flex-direction: column;
        /* gap:0 on purpose - the space between cards is a margin on the card itself,
           below. A gap belongs to the container, so it survives even when the card it
           follows has collapsed to nothing, and picking a programme would leave two
           stripes of empty space where the other two used to be. */
        gap: 0;
    }

    /* flex:0 0 auto, NOT the desktop 1 1 0. Down here the card is height:auto, so there
       is no free space for flex-grow to share out and a flex-basis of 0 would collapse
       every one of them to nothing. Content height with a floor under it instead, which
       is also what gives a comfortable touch target. */
    .fte-prog-item {
        flex: 0 0 auto;
        min-width: 0;
        min-height: 88px;
        /* The desktop inner structure is kept deliberately: icon left, words, arrow
           right. These are all row values - they are here to OVERRIDE nothing, but they
           are stated because the old strip turned this into a centred column and the
           next person to read this rule should see the intent, not infer it. */
        flex-direction: row;
        align-items: center;
        text-align: left;
        gap: 14px;
        padding: 16px 18px;
        border-radius: 14px;
    }

    /* The vertical rhythm, and the hairline goes: separate cards with space between them
       do not need a line as well. margin rather than gap - see .fte-prog-nav above. */
    .fte-prog-item + .fte-prog-item {
        border-top: 0;
        margin-top: 12px;
    }

    /* Collapsing a card on the way into step two. On desktop flex-grow:0 against a
       flex-basis of 0 is enough; here the basis is auto, so grow has nothing to give up
       and the card would keep its 88px as an invisible hole. Height, min-height and the
       margin all have to go. */
    .fte-flow.is-picked .fte-prog-item:not(.is-current) {
        min-height: 0;
        height: 0;
        margin-top: 0;
    }

    .fte-prog-item.is-current {
        box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .92),
                    0 6px 16px rgba(0, 48, 64, .18);
    }

    .fte-prog-icon {
        width: 46px;
        height: 46px;
        border-radius: 13px;
    }

    .fte-prog-icon img {
        width: 28px;
        height: 28px;
    }

    .fte-prog-text b {
        font-size: .95rem;
        line-height: 1.15;
    }

    /* Both back on. There is room for them across a full-width card, and the arrow is
       the only thing on it that says "this leads somewhere". */
    .fte-prog-text span {
        font-size: .76rem;
        margin-top: 3px;
    }

    .fte-prog-badge {
        font-size: .58rem;
        padding: 4px 8px;
    }

    /* Narrow screens: the corner is closer to the text, so the mark comes down. */
    .fte-brand-logo {
        max-height: 70px;
    }

    .fte-brandbox {
        padding: 8px 8px 10px 10px;
    }
}

/* The smallest phones. These numbers were built for the three-across strip, where each
   card had a third of the screen; a full-width card has room for far more than .70rem.
   Trimmed only enough to keep the longest of the three names on two lines at 320px. */
@media (max-width: 400px) {
    .fte-prog-text b {
        font-size: .86rem;
        letter-spacing: -.005em;
    }

    .fte-prog-item {
        min-height: 80px;
        gap: 12px;
        padding: 14px 14px;
    }

    .fte-prog-icon {
        width: 42px;
        height: 42px;
    }
}

/* On a short desktop window the white card is a fixed 90vh (cutom.css). The left
   column no longer needs anything here - the blocks are thirds of whatever the panel
   is, so they shrink on their own. The right column does: it is a fixed 90vh flex
   column, and the logo is the one item in it with a fixed height, so it is what should
   give way rather than the form below it. */
@media (min-width: 992px) and (max-height: 760px) {
    .fte-brand-logo {
        max-height: 82px;
    }

    .fte-prog-item {
        padding: 10px 12px;
    }
}
