/*************************************************************************
 *  Copyright (C) 2026 SecureFlag Limited
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains the property
 * of SecureFlag Limited. The intellectual and technical concepts contained
 * herein are proprietary to SecureFlag Limited and may be covered by EU
 * and Foreign Patents, patents in process, and are protected by trade secret
 * or copyright law. Dissemination of this information or reproduction of this
 * material is strictly forbidden unless prior written permission is obtained
 * from SecureFlag Limited.
 */

/* =============================================================================
   The public, unauthenticated pages: badge.jsp, share.jsp (certificates, trophies
   and tournament placements) and marketplace-thank-you.jsp.

   Carries the 2026 website's design language -- Inter for text, Poppins for
   display, IBM Plex Mono for identifiers, the brand blue gradient, 24px cards,
   tight tracking on large type -- onto a LIGHT ground. The website itself is
   dark throughout, so there was no light palette to lift; these are its tokens
   re-grounded, not invented ones. Values traced to landing-website-2026:
   tailwind.config.js (primary #2f6fd6, border-light rgba(0,0,0,.16), the type
   scale's -0.04em tracking) and src/styles/common.css (.gradient-text).

   Everything is namespaced `sfb-` and this file is self-contained. The three pages
   used to share share.css with each other, which is why none of them could be
   restyled alone; that sheet is left untouched and unloaded, and these pages own
   their look here.
   ============================================================================= */

:root {
    --sfb-blue: #007bff;
    --sfb-blue-mid: #2a94ff;
    --sfb-blue-light: #8cc8ff;
    --sfb-primary: #2f6fd6;
    /* The website's signature text gradient, same stops and angle. */
    --sfb-gradient: linear-gradient(-16deg, #8cc8ff 5%, #2a94ff 40.4%, #007bff 93.5%);

    --sfb-ink: #1a1b1c;          /* tailwind.config.js `dark` */
    --sfb-ink-mid: #4a5058;
    --sfb-ink-soft: #79818b;
    --sfb-line: rgba(0, 0, 0, 0.10);
    --sfb-line-strong: rgba(0, 0, 0, 0.16);   /* `border-light` */
    --sfb-surface: #ffffff;
    --sfb-surface-sub: #f7f9fc;
    --sfb-ground: #eef1f6;

    --sfb-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --sfb-display: 'Poppins', var(--sfb-sans);
    --sfb-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

*,
*::before,
*::after { box-sizing: border-box; }

/* The UA sheet's `[hidden] { display: none }` is only (0,1,0), so any class here
   that sets display -- .sfb-form, .sfb-download, .sfb-stats -- silently beats it and
   the element stays on screen. Restate it as a winner once, rather than discovering
   it one element at a time. */
[hidden] { display: none !important; }

html,
body {
    margin: 0;
    padding: 0;
}

body {
    min-height: 100vh;
    background: var(--sfb-ground);
    color: var(--sfb-ink);
    font-family: var(--sfb-sans);
    font-weight: 300;
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* The site's hero glow, inverted for a light ground: the same blue, at a
   fraction of the opacity, so it reads as a tint behind the card rather than
   the spotlight it is on black. */
.sfb-page {
    position: relative;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background-image: radial-gradient(ellipse 70% 45% at 50% 0%, rgba(42, 148, 255, 0.16), transparent 70%);
}

/* .logo-img is the whitelabel hook: the per-tenant sheet swaps the image through
   `content: url(...) !important`. It is written for the user portal's header
   though, so it also carries `position: absolute; top: 16px; left: 24px`, which
   would tear the logo out of the flex row here. wtl.css loads after this file, so
   only a higher-specificity selector can put it back -- hence .sfb-top on the
   front. The tenant keeps control of the image and its height; only the
   positioning is overridden. */
.sfb-top .sfb-brand.logo-img {
    position: static;
    top: auto;
    left: auto;
}

/* ---------------------------------------------------------------- top bar */
.sfb-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 28px 32px;
}
.sfb-brand {
    height: 30px;
    width: auto;
    display: block;
}

/* Primary action, in the site's button shape: solid brand blue, 10px radius.
   `hidden` until badge.js confirms jsPDF is present, so it is never a dead
   control -- [hidden] needs restating because the display below would win. */
.sfb-download {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border: 0;
    border-radius: 10px;
    background: var(--sfb-primary);
    color: #fff;
    font-family: var(--sfb-sans);
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: background-color .15s ease;
}
.sfb-download[hidden] { display: none; }
.sfb-download:hover { background: #245bb5; }   /* tailwind.config.js primary-dark */
.sfb-download:disabled { opacity: .6; cursor: default; }
.sfb-download:focus-visible {
    outline: 2px solid var(--sfb-blue);
    outline-offset: 2px;
}
.sfb-download-icon {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
}

/* ------------------------------------------------------------------ card */
.sfb-main {
    flex: 1 1 auto;
    display: flex;
    justify-content: center;
    /* flex-start, or the card stretches to fill the row and trails empty white
       below its last line. */
    align-items: flex-start;
    padding: 40px 24px 56px;
}

.sfb-card {
    position: relative;
    width: 100%;
    max-width: 720px;
    overflow: hidden;
    border: 1px solid var(--sfb-line);
    border-radius: 24px;
    background: var(--sfb-surface);
    box-shadow: 0 24px 60px -28px rgba(16, 32, 64, 0.28),
                0 2px 6px rgba(16, 32, 64, 0.04);
}

/* The one piece of full-strength brand colour on the page. */
.sfb-rail {
    height: 5px;
    background-image: var(--sfb-gradient);
}

.sfb-body {
    padding: 34px 38px 30px;
}

/* ---------------------------------------------------------------- heading */
.sfb-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 24px;
}

.sfb-eyebrow {
    margin: 0 0 10px;
    font-family: var(--sfb-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--sfb-primary);
}

/* Poppins with the type scale's negative tracking, which is what makes the
   website's large headings read the way they do. */
.sfb-name {
    margin: 0;
    font-family: var(--sfb-display);
    font-size: 40px;
    line-height: 1.1;
    font-weight: 600;
    letter-spacing: -0.04em;
    color: var(--sfb-ink);
    overflow-wrap: anywhere;
}

.sfb-role {
    display: inline-block;
    margin: 14px 0 0;
    padding: 4px 12px;
    border-radius: 999px;
    background: rgba(47, 111, 214, 0.09);
    color: var(--sfb-primary);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: capitalize;
}

/* share.jsp still puts the issuer's square mark in the header; badge.jsp gives that
   slot to the ranking instead. */
.sfb-issuer-mark {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    object-fit: contain;
}

/* The name takes whatever the ranking does not, and can shrink -- a long display
   name wraps rather than pushing the ranking off the card. */
.sfb-head-main {
    min-width: 0;
    flex: 1 1 auto;
}

/* ---------------------------------------------------------------- ranking
   The badge's one competitive fact, so it is typeset as a figure rather than as
   another label/value pair. The rule on the left is what makes it read as a
   separate claim about the person instead of a continuation of the name.

   Absent entirely for anyone the servlet did not rank: this is a flex item, so
   the name simply reclaims the width and nothing has to be reserved for it. */
.sfb-rank {
    flex: 0 0 auto;
    padding-left: 26px;
    border-left: 1px solid var(--sfb-line);
    text-align: right;
}

.sfb-rank-label {
    display: block;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sfb-ink-soft);
}

/* Set at the name's size, in the brand gradient -- the two things on the card
   that carry display weight are who it is and where they place. */
.sfb-rank-value {
    display: block;
    margin-top: 6px;
    font-family: var(--sfb-display);
    font-size: 44px;
    line-height: 1.05;
    font-weight: 600;
    letter-spacing: -0.045em;
    background-image: var(--sfb-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The hash is punctuation, not part of the figure, so it is dropped back a size
   and lifted off the baseline rather than competing with the digits. */
.sfb-rank-hash {
    font-size: 0.56em;
    font-weight: 500;
    vertical-align: 0.42em;
    margin-right: 1px;
}


/* ------------------------------------------------------------------ stats */
.sfb-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    margin-top: 30px;
}

.sfb-stat {
    padding: 18px 16px;
    border: 1px solid var(--sfb-line);
    border-radius: 16px;
    background: var(--sfb-surface-sub);
    text-align: center;
}

.sfb-stat-value {
    display: block;
    font-family: var(--sfb-display);
    font-size: 30px;
    line-height: 1.1;
    font-weight: 600;
    letter-spacing: -0.03em;
    /* .gradient-text from the site's common.css, applied to the figures that
       are the point of the badge. */
    background-image: var(--sfb-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-variant-numeric: tabular-nums;
}

.sfb-stat-label {
    display: block;
    margin-top: 8px;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sfb-ink-soft);
}

/* ------------------------------------------------------------------- meta */
.sfb-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 36px;
    margin-top: 28px;
    padding-top: 22px;
    border-top: 1px solid var(--sfb-line);
}

.sfb-meta-label {
    display: block;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sfb-ink-soft);
}

.sfb-meta-value {
    display: block;
    margin-top: 5px;
    font-family: var(--sfb-display);
    font-size: 16px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--sfb-ink);
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------- foot */
.sfb-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    margin-top: 26px;
    padding-top: 20px;
    border-top: 1px solid var(--sfb-line);
}

.sfb-issuer-logo {
    max-height: 30px;
    max-width: 190px;
    width: auto;
    object-fit: contain;
}

/* Mono, because it is an identifier meant to be read character by character --
   the same reason the website sets IBM Plex Mono for code. */
.sfb-id {
    font-family: var(--sfb-mono);
    font-size: 11.5px;
    letter-spacing: 0.02em;
    color: var(--sfb-ink-soft);
    overflow-wrap: anywhere;
    text-align: right;
}

/* --------------------------------------------------------- powered-by foot
   badge.js hides this element entirely on SecureFlag's own hosts, so it must
   stay a plain <footer> for that selector to keep matching. */
.sfb-poweredby {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 0 24px 34px;
}
.sfb-poweredby p {
    margin: 0;
    font-size: 12px;
    color: var(--sfb-ink-soft);
}
.sfb-poweredby img {
    height: 17px;
    width: auto;
}

/* ===========================================================================
   share.jsp additions -- a credential card rather than a stats card. Same
   shell, same type, so only the middle differs from the badge.
   =========================================================================== */

/* The kicker sits above the subject: "Certificate of Completion", "Trophy",
   "Tournament". */
.sfb-kicker {
    margin: 0;
    font-family: var(--sfb-display);
    font-size: 34px;
    line-height: 1.12;
    font-weight: 600;
    letter-spacing: -0.035em;
    color: var(--sfb-ink);
}

.sfb-awarded {
    margin: 26px 0 6px;
    font-size: 13px;
    color: var(--sfb-ink-soft);
}

.sfb-recipient {
    margin: 0;
    font-family: var(--sfb-display);
    font-size: 30px;
    line-height: 1.15;
    font-weight: 600;
    letter-spacing: -0.03em;
    color: var(--sfb-ink);
    overflow-wrap: anywhere;
}

.sfb-subject {
    display: block;
    margin-top: 18px;
    padding: 16px 18px;
    border: 1px solid var(--sfb-line);
    border-left: 3px solid var(--sfb-primary);
    border-radius: 12px;
    background: var(--sfb-surface-sub);
    font-family: var(--sfb-display);
    font-size: 17px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--sfb-ink);
    overflow-wrap: anywhere;
}

/* Valid / Expired. The dot carries the state so it reads without the label. */
.sfb-status {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--sfb-display);
    font-size: 16px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--sfb-ink);
}
.sfb-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: 0 0 auto;
}
.sfb-dot-ok { background: #2e7d32; }
.sfb-dot-expired { background: #c0392b; }

/* ===========================================================================
   marketplace-thank-you.jsp -- a short form on the same card.
   =========================================================================== */

.sfb-lede {
    margin: 14px 0 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--sfb-ink-mid);
    max-width: 60ch;
}

.sfb-form {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px 18px;
    margin-top: 28px;
}
.sfb-field-wide { grid-column: 1 / -1; }

.sfb-label {
    display: block;
    margin-bottom: 6px;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sfb-ink-soft);
}

.sfb-input {
    width: 100%;
    height: 42px;
    padding: 0 13px;
    border: 1px solid var(--sfb-line-strong);
    border-radius: 10px;
    background: var(--sfb-surface);
    color: var(--sfb-ink);
    font-family: var(--sfb-sans);
    font-size: 14.5px;
}
.sfb-input:focus {
    outline: none;
    border-color: var(--sfb-primary);
    box-shadow: 0 0 0 3px rgba(47, 111, 214, 0.14);
}

/* Same shape as the download control, so the two primary actions match. */
.sfb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 42px;
    padding: 0 22px;
    border: 0;
    border-radius: 10px;
    background: var(--sfb-primary);
    color: #fff;
    font-family: var(--sfb-sans);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: background-color .15s ease;
}
.sfb-btn:hover { background: #245bb5; }
.sfb-btn:focus-visible { outline: 2px solid var(--sfb-blue); outline-offset: 2px; }

.sfb-note {
    margin: 20px 0 0;
    padding: 13px 16px;
    border-radius: 10px;
    font-size: 14px;
    line-height: 1.5;
}
.sfb-note-ok { background: #ecf5ed; color: #2e7d32; }
.sfb-note-bad { background: #fdeceb; color: #c0392b; }

/* ------------------------------------------------------------- responsive */
@media (max-width: 640px) {
    .sfb-top { padding: 20px 18px; flex-wrap: wrap; gap: 12px; }
    .sfb-main { padding: 4px 16px 40px; }
    .sfb-body { padding: 26px 22px 24px; }
    .sfb-name { font-size: 30px; }
    .sfb-issuer-mark { width: 48px; height: 48px; }
    /* The ranking drops to its own line. Done by making the name full-width rather
       than by stacking .sfb-head, because share.jsp shares that header and its
       issuer mark is small enough to stay alongside.

       The ranking then turns on its side -- figure on the left, label beside it --
       so it stays one compact block instead of two centred lines. */
    .sfb-head { flex-wrap: wrap; gap: 22px; }
    .sfb-head-main { flex-basis: 100%; }
    .sfb-rank {
        display: flex;
        align-items: baseline;
        gap: 13px;
        padding-left: 0;
        border-left: 0;
        text-align: left;
    }
    .sfb-rank-value { margin: 0; font-size: 38px; }
    .sfb-stats { grid-template-columns: 1fr; gap: 10px; }
    .sfb-stat { display: flex; align-items: baseline; justify-content: space-between; text-align: left; padding: 14px 16px; }
    .sfb-stat-value { font-size: 24px; }
    .sfb-stat-label { margin-top: 0; }
    .sfb-meta { gap: 22px; }
    .sfb-foot { flex-direction: column; align-items: flex-start; gap: 14px; }
    .sfb-id { text-align: left; }
    .sfb-kicker { font-size: 26px; }
    .sfb-recipient { font-size: 24px; }
    .sfb-form { grid-template-columns: 1fr; }
}

/* A badge is a thing people screenshot and print. */
@media print {
    body { background: #fff; }
    .sfb-page { background-image: none; }
    .sfb-card { box-shadow: none; border-color: var(--sfb-line-strong); }
    .sfb-poweredby,
    .sfb-download { display: none; }
}
