/* OSA Production — shared application stylesheet.
 *
 * Extracted verbatim from the two inline <style> blocks in base.html, which had
 * grown to 351 lines and were re-shipped, uncacheable, on every page load.
 * Behaviour is unchanged: this <link> sits exactly where those blocks did --
 * and still before any page CSS, because pages inject their <style> inside
 * {% block content %} (in the BODY), not into <head>.
 *
 * THIS FILE IS NOW THE WHOLE CASCADE. Bootstrap 5.3.3 used to load ahead of it
 * and is gone: 227KB carrying 2,025 class definitions, of which the app used 38
 * -- utilities and a grid, in four templates. What it really provided was Reboot,
 * invisibly, and that was a liability rather than a service. Its reset set
 * `body { color: #212529 }`, off-palette, on every page, and beat app.css until
 * the D6 audit caught it; its `:root` shipped --bs-blue #0d6efd and --bs-red
 * #dc3545 into a codebase whose whole point is that OSA Red and OSA Blue are the
 * only red and blue; and the colour guard could not see any of it, because
 * SKIP_PARTS skips the file named bootstrap. The reset below replaces Reboot's
 * load-bearing parts and is byte-identical to osa-operations' -- which is the
 * point: the two sites now differ in colour, not in architecture.
 *
 * Linked via static_v() so ?v=<mtime> busts the cache on deploy. Inline CSS was
 * self-busting (it shipped with the HTML); a cacheable stylesheet is not, so the
 * versioned URL is load-bearing, not decorative.
 *
 * The :root token block here is the home for the design-system tokens. The three
 * scales are shared with osa-operations and must not be forked -- see
 * osa-operations/docs/STYLE_GUIDE.md.
 */
        :root {
            /* ══ SHARED DESIGN SYSTEM ══ byte-identical to osa-operations'
               app.css. These three scales are the "one product family" part:
               Production and Operations differ in COLOUR, not in geometry or
               type. Do not fork these values here -- the canonical guide is
               osa-operations/docs/STYLE_GUIDE.md; change them there first.

               Always reference the token, never the literal: it keeps a later
               px->rem move a five-line change instead of another app-wide sweep. */

            /* Type scale — five steps. Production's dominant sizes (13px x51,
               11px x40, 15px, 22px) were ALREADY these values; the sprawl was
               12/14/10 plus one-off half-pixel sizes around them. */
            --fs-sm:   11px;  /* dense — table cells, meta, badges, uppercase labels */
            --fs-base: 13px;  /* body, inputs */
            --fs-lg:   15px;  /* subheads */
            --fs-xl:   18px;  /* card / section headings */
            --fs-2xl:  22px;  /* page titles */

            /* Spacing — 4px base. Bootstrap 5's default spacers are 4/8/16/24/48,
               so this is not a new convention here; --sp-1/-4/-7 are the additions
               that Operations' dense, table-heavy UI needed. */
            --sp-1:  2px;
            --sp-2:  4px;
            --sp-3:  8px;
            --sp-4: 12px;
            --sp-5: 16px;
            --sp-6: 24px;
            --sp-7: 32px;
            --sp-8: 48px;

            /* Corner radius. 8px was already Production's dominant value (x33),
               and 6px (x13) and 12px (x4) line up with -sm and -lg. */
            --radius-sm:   6px;
            --radius:      8px;
            --radius-lg:  12px;
            --radius-pill: 999px;  /* previously spelled 99px here */

            /* ══ NEUTRALS ══ one grey scale. This repo previously ran THREE
               overlapping palettes at once -- a Tailwind-ish cool set
               (#9ca3af/#6b7280/#374151), a warm set (#5a5a56/#1a1a18/#f7f7f5),
               and one stray value lifted from Operations (#5b6472) -- which is
               most of why pages looked subtly unlike each other.

               Cool, and shared with Operations. Worth stating because it looks
               like a preference and is not: Production's page background and
               primary were ALREADY cool (#f2f4f8 is r-b -6, the navy -87) while
               its greys were warm (#8a8a84 is r-b +6). Warm text on a cool page
               was an existing mismatch; unifying cool REMOVES it rather than
               introducing one.

               Five subtle-background greys and nine border greys collapsed to
               one each. Mapped on measured perceptual shift -- every fold moved
               under ~6 L units, i.e. invisible in place. */
            /* ══════════════════════════════════════════════════════════
               CANONICAL PALETTE — shared with osa-operations.
               Reference: osa-operations/docs/brand/palette.svg

               Every hue is OSA Red, OSA Blue, one of their complements, or
               the bisector of a gap between those four:

                 red 26 ANCHOR · orange 54 bisector Red–Gold · gold 83
                 complement of Blue · green 144 bisector Gold–Teal ·
                 teal 206 complement of Red · blue 263 ANCHOR ·
                 violet 324 bisector Blue–Red

               Do NOT fork these values here. Change an anchor and the whole
               set regenerates — see the reference.
               ══════════════════════════════════════════════════════════ */

            /* Neutrals — TRUE neutral, R=G=B. Identical to Operations. */
            --bg:        #ffffff;
            --bg2:       #f6f6f6;
            --bg3:       #eeeeee;
            --border:    #e3e3e3;
            --border2:   #c8c8c8;
            --text:      #1c1c1c;
            --text2:     #474747;
            --text3:     #777777;

            /* Status hues. `-bg` is the tint tier; the bare token is deep,
               which is the text-on-tint rung, so they pair by construction. */
            --blue:        #1f3d7c;  /* ANCHOR — OSA Blue */
            --blue-bg:     #ebeff5;
            --green:       #148624;
            --green-bg:    #e1f5e0;
            --gold:        #8c6811;
            --gold-bg:     #f5eee0;
            --orange:      #a65611;
            --orange-bg:   #f5ede7;
            --red:         #ad2828;
            --red-bg:      #f5eceb;
            --teal:        #147d88;
            --teal-bg:     #e0f3f5;
            --violet:      #9d44a5;
            --violet-bg:   #f5ebf5;

            /* Fill rungs — phase squares. A direction pair shares one hue and
               separates by these, 10 L* apart. `ink` is the label colour ON a
               fill; the `deep` rung is too light for that and collapses to
               1.4-3.0:1. */
            --blue-f1:     #b4c7e9;  --blue-f2:     #89a6dc;  --blue-f3:   #6b8ed3;
            --green-f1:    #99d999;  --green-f2:    #6fbb70;  --green-f3:  #5ba35d;
            --gold-f1:     #e6c077;  --gold-f2:     #c1a163;  --gold-f3:   #a78b54;
            --orange-f1:   #e9bb9d;  --orange-f2:   #db9362;  --orange-f3: #bd7e54;
            --teal-f1:     #80d6e1;  --teal-f2:     #6ab4bd;
            --violet-f1:   #e6b1e9;  --violet-f2:   #d680dd;  --violet-f3: #c461cc;
            --red-f1:      #eab8b3;  --red-f2:      #df8c84;
            --blue-ink:    #021852;  --gold-ink:    #2a1d03;
            --violet-ink:  #350539;  --green-ink:   #042707;  --orange-ink: #331703;

            /* Brand, exact. Everything else derives FROM these. */
            --osa-blue:  #1f3d7c;
            --osa-red:   #d9272d;
        }
        /* ══ RESET ══ byte-identical to osa-operations' app.css.
           Replaces Bootstrap Reboot, which used to load ahead of this file.
           Reboot's box-sizing was load-bearing on every padded element; the rest
           of it was opinion (h1 2.5rem, p margin-bottom 1rem, ul padding-left
           2rem) that nothing here relied on -- verified by diffing computed
           styles across five pages at two widths before and after removal. */
        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

        /* Form controls do NOT inherit font by default -- the UA gives them
           13.33px Arial. Reboot papered over that; without this line every
           input, select, textarea and unstyled button reverts to it. */
        button, input, select, textarea, optgroup {
            font-family: inherit; font-size: inherit; line-height: inherit;
        }
        /* Reboot set headings to 1.2; without it they inherit the body's 1.5 and
           every card header grows ~4px taller. Sizes are NOT reset here — every
           heading in this app already sets its own. */
        h1, h2, h3, h4, h5, h6 { line-height: 1.2; }
        table { border-collapse: collapse; }
        img, svg { vertical-align: middle; }
        summary { cursor: pointer; }
        textarea { resize: vertical; }
        /* Links with no class: Reboot painted these --bs-blue #0d6efd, and with
           it gone the UA default is #0000EE. Both are foreign blues. */
        a { color: var(--blue); }

        body {
            background: var(--bg3);
            color: var(--text);
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            font-size: var(--fs-base);
            line-height: 1.5;
        }
        .topnav {
            background: #fff;
            border-bottom: 0.5px solid rgba(0,0,0,0.12);
            display: flex;
            align-items: center;
            padding: 0 var(--sp-6);
            height: 52px;
            position: sticky;
            /* Sits below the sticky dev banner when present (var set by JS to the
               banner's measured height); 0 in production where there's no banner. */
            top: var(--dev-banner-h, 0px);
            z-index: 100;
        }
        .topnav-brand {
            font-size: var(--fs-lg);
            font-weight: 500;
            color: var(--text);
            text-decoration: none;
            margin-right: var(--sp-7);
            display: flex;
            align-items: center;
            gap: var(--sp-3);
        }
        /* was #8a8a84, a warm grey off the neutral ramp — and Operations'
           .topnav-brand span already used --text3. This restores that parity;
           the subtitle darkens ~6 L* to match the sibling app exactly. */
        .topnav-brand span { color: var(--text3); font-weight: 400; }
        .topnav-logo { height: 26px; width: auto; display: block; }
        .topnav-links { display: flex; gap: var(--sp-2); flex: 1; }
        .topnav-links a {
            padding: var(--sp-2) var(--sp-4);
            border-radius: var(--radius);
            color: var(--text2);
            text-decoration: none;
            font-size: var(--fs-base);
            transition: background .12s, color .12s;
        }
        .topnav-links a:hover { background: var(--bg2); color: var(--text); }
        .topnav-links a.active { background: var(--bg2); color: var(--text); font-weight: 500; }
        .topnav-user {
            display: flex;
            align-items: center;
            gap: var(--sp-4);
            font-size: var(--fs-base);
            color: var(--text2);
            position: relative;
        }
        .user-menu-btn {
            background: none;
            border: none;
            font-size: var(--fs-base);
            color: var(--text2);
            cursor: pointer;
            font-family: inherit;
            padding: var(--sp-2) 0;
            display: flex;
            align-items: center;
            gap: var(--sp-2);
        }
        .user-menu-btn:hover { color: var(--text); }
        .user-dropdown {
            display: none;
            position: absolute;
            top: calc(100% + 8px);
            right: 0;
            background: #fff;
            border: 0.5px solid rgba(0,0,0,0.22);
            border-radius: var(--radius);
            box-shadow: 0 4px 16px rgba(0,0,0,.1);
            min-width: 180px;
            z-index: 200;
            overflow: hidden;
        }
        .user-dropdown a {
            display: block;
            padding: var(--sp-3) var(--sp-4);
            font-size: var(--fs-base);
            color: var(--text);
            text-decoration: none;
            border-bottom: 0.5px solid rgba(0,0,0,0.12);
        }
        .user-dropdown a:last-child { border-bottom: none; }
        .user-dropdown a:hover { background: var(--bg2); }
        .user-dropdown a.danger { color: #d9272d; }
        .user-dropdown.open { display: block; }
        .nav-toggle { display:none; background:none; border:none; cursor:pointer; padding:var(--sp-2); color:var(--text2); font-size:var(--fs-xl); line-height:1; }
        .mobile-nav { display:none; position:fixed; top:52px; left:0; right:0; bottom:0; background:#fff; z-index:99; padding:var(--sp-4); border-top:0.5px solid rgba(0,0,0,0.12); overflow-y:auto; }
        .mobile-nav a { display:block; padding:var(--sp-4) var(--sp-5); font-size:var(--fs-lg); text-decoration:none; color:var(--text); border-radius:var(--radius); margin-bottom:var(--sp-2); }
        .mobile-nav a:hover, .mobile-nav a.active { background:var(--bg2); }
        .mobile-nav .divider { height:0.5px; background:rgba(0,0,0,0.12); margin:var(--sp-3) 0; }
        /* Bootstrap's .card supplied the background, the column flex and the
           min-width:0 that stops a long unbroken string from blowing the track
           out; this rule only ever added the radius and border on top. All of it
           lives here now. `bg-white` was in the markup to compensate and is gone. */
        .card {
            position: relative;
            display: flex;
            flex-direction: column;
            min-width: 0;
            background: var(--bg);
            border-radius: var(--radius);
            border: 0.5px solid var(--border);
        }

        /* Responsive card grid — replaces Bootstrap's .row.g-3 + .col-12
           .col-md-6 .col-lg-4. Same breakpoints (768 / 992) and the same 16px
           gutter, without the negative-margin row or the 12-column arithmetic.
           Lives here rather than in the page so the media queries stay out of a
           template <style> block (D4). */
        .card-grid {
            display: grid;
            grid-template-columns: 1fr;
            gap: var(--sp-5);
        }
        @media (min-width: 768px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
        @media (min-width: 992px) { .card-grid { grid-template-columns: repeat(3, 1fr); } }
        /* Production had NO .badge base rule — Bootstrap's supplied the shape
           (inline-block, .35em/.65em padding, weight 700, 6px radius) and only
           the colours lived here. This is osa-operations' .badge verbatim, which
           is the point: the badge is the most-used component in both apps and it
           should be one component, not two that happen to look similar.

           It is also the one deliberate visual change in this pass. The status
           key on /jobs/ and the chips on job detail move from Bootstrap's shape
           to the shared one: weight 700 -> 500, radius 6px -> pill. Every badge
           that already carried .jl-badge-sm was ALREADY overriding toward these
           values, so most of the surface does not move at all. */
        .badge {
            display: inline-flex;
            align-items: center;
            padding: var(--sp-1) var(--sp-3);
            border-radius: 20px;
            font-size: var(--fs-sm);
            font-weight: 500;
            /* A status chip never wraps its label — see osa-operations. */
            white-space: nowrap;
        }
        .badge-active { background: var(--green-bg); color: var(--green); }
        .badge-held { background: var(--gold-bg); color: var(--gold); }
        .badge-complete { background: var(--blue-bg); color: var(--blue); }
        .badge-closed { background: var(--bg2); color: var(--text2); }
		.badge-inquiry     { background: var(--bg2); color: var(--text2); }
		.badge-provisional { background: var(--gold-bg); color: var(--gold); }
		.badge-confirmed   { background: var(--green-bg); color: var(--green); }
		.badge-cancelled   { background: var(--red-bg); color: var(--red); }
        .flash-error { background: var(--red-bg); border: 0.5px solid var(--red-f1); color: #d9272d; padding: var(--sp-3) var(--sp-4); border-radius: var(--radius); margin-bottom: var(--sp-5); font-size: var(--fs-base); }
        .flash-success { background: var(--green-bg); border: 0.5px solid var(--green-f1); color: var(--green); padding: var(--sp-3) var(--sp-4); border-radius: var(--radius); margin-bottom: var(--sp-5); font-size: var(--fs-base); }
        .flash-info { background: var(--blue-bg); border: 0.5px solid var(--border2); color: var(--blue); padding: var(--sp-3) var(--sp-4); border-radius: var(--radius); margin-bottom: var(--sp-5); font-size: var(--fs-base); }
        @media(max-width:768px) {
            .topnav-links { display: none; }
            .topnav-user { display: none; }
            .nav-toggle { display: block; }
        }
        .job-card-hover { cursor: pointer; transition: border-color .15s; }
        .job-card-hover:hover { border-color: var(--blue); }
        .dev-banner { background:var(--red); color:#fff; text-align:center; padding:var(--sp-2) var(--sp-4);
                      font-size:var(--fs-sm); font-weight:500; letter-spacing:.04em;
                      position:sticky; top:0; z-index:101; }
        .topnav-links a.nav-crumb { color:var(--blue); background:var(--blue-bg); }
        .mobile-nav a.nav-crumb { color:var(--blue); }
        .page-shell { max-width:1440px; margin:0 auto; }
        /* was `px-4 pt-3` — Bootstrap's 1.5rem sides / 1rem top, on the scale. */
        .flash-wrap { padding: var(--sp-5) var(--sp-6) 0; }
        /* Auth-card layout, shared by /auth/* templates that
           override the app_layout block */
        body.auth-layout { min-height: 100vh; display: flex; flex-direction: column; }
        .auth-wrap { flex:1; display:flex; align-items:center; justify-content:center; padding:var(--sp-5); }
        /* Size matches Operations' .auth-card (max-width 400 / sp-7 sp-8 padding)
           — shared by every /auth/* page (login, change/forgot/reset/set-password,
           the SAML denied page). */
        .auth-card { background:#fff; border-radius:var(--radius-lg); padding:var(--sp-7) var(--sp-8);
                     width:100%; max-width:400px; box-shadow:0 2px 12px rgba(0,0,0,.06);
                     border:0.5px solid var(--border); }
        .auth-title { font-size:var(--fs-xl); font-weight:500; color:var(--blue); margin-bottom:var(--sp-2); }
        .auth-title span { font-weight:400; color:var(--blue-f1); }
        .auth-title img { float:left; height:42px; width:auto; margin:var(--sp-2) var(--sp-4) 0 0; }
        /* The brand mark on the login card is a quiet SSO shortcut (auth/login.html):
           a returning staff user clicks it to jump straight to Entra. Subtle hover,
           no loud button. */
        .sso-logo img { cursor:pointer; transition:opacity .12s ease; }
        .sso-logo img:hover { opacity:.72; }
        /* Own block-formatting context so the sub sits BESIDE the floated logo as
           a column (media-object pattern): every wrapped line aligns under the
           title text instead of the 2nd line dropping to the far left under the
           logo. Shared by all /auth/* + memo cards using this header. */
        .auth-sub { display:flow-root; font-size:var(--fs-base); color:var(--text2); margin-bottom:var(--sp-6); }
        .auth-card label { display:block; font-size:var(--fs-base); font-weight:500; color:var(--text); margin-bottom:var(--sp-2); }
        .auth-card label .label-note { font-size:var(--fs-sm); color:var(--text3); font-weight:400; }
        .auth-card input[type=email],
        .auth-card input[type=password],
        .auth-card input[type=text] { width:100%; height:44px; border:1px solid var(--border2);
                                      border-radius:var(--radius); padding:0 var(--sp-4); font-size:var(--fs-base);
                                      color:var(--text); background:#fff; outline:none; margin-bottom:var(--sp-5); }
        .auth-card input:focus { border-color:var(--blue); box-shadow:0 0 0 3px rgba(40,56,127,.08); }
        .auth-card input:disabled { background:var(--bg2); color:var(--text3); }
        .auth-card .hint { background:var(--blue-bg); border-left:3px solid #d9272d;
                           border-radius:0 var(--radius-sm) var(--radius-sm) 0; padding:var(--sp-3) var(--sp-4);
                           font-size:var(--fs-base); color:var(--blue); line-height:1.5; margin-bottom:var(--sp-6); }
        .btn-signin { width:100%; height:48px; background:var(--blue); color:#fff; border:none;
                      border-radius:var(--radius); font-size:var(--fs-lg); font-weight:500; cursor:pointer; margin-top:var(--sp-2); }
        .btn-signin:hover { background:var(--blue-ink); }
        .btn-decline { width:100%; height:44px; background:#fff; color:var(--red); border:1px solid var(--red-f1);
                       border-radius:var(--radius); font-size:var(--fs-base); font-weight:500; cursor:pointer; margin-top:var(--sp-3); }
        .btn-decline:hover { background:var(--red-bg); }  /* was #FEF3F2 — the button is red-themed; --red-bg is its own tint tier */
        /* Memo accept/decline pages — replaces the mb-*/mt-3/text-muted
           utilities they borrowed from Bootstrap. Same resolved values: mb-3 and
           mt-3 are 1rem (--sp-5), mb-2 is .5rem (--sp-3), mb-1 is .25rem
           (--sp-2). .text-muted was rgba(33,37,41,.75) — L* 41 on white, which
           is --text2's rung, not --text3's. */
        .auth-card .memo-intro { margin-bottom:var(--sp-5); }
        .auth-card .memo-field { margin-bottom:var(--sp-3); }
        .auth-card .memo-leg   { margin-bottom:var(--sp-2); }
        .auth-card .memo-form  { margin-top:var(--sp-5); }
        .auth-card .memo-muted { color:var(--text2); }

        .auth-card .form-foot { text-align:center; margin-top:var(--sp-5); font-size:var(--fs-base); }
        .auth-card .form-foot a { color:var(--blue); text-decoration:none; }
        .auth-card .form-foot a:hover { text-decoration:underline; }
        .auth-card .flash-error { background:var(--red-bg); border:1px solid var(--red-f1); color:#d9272d;
                                  padding:var(--sp-3) var(--sp-4); border-radius:var(--radius); margin-bottom:var(--sp-5); font-size:var(--fs-base); }
        .auth-card .flash-success { background:var(--green-bg); border:1px solid var(--green-f1); color:var(--green);
                                    padding:var(--sp-3) var(--sp-4); border-radius:var(--radius); margin-bottom:var(--sp-5); font-size:var(--fs-base); }
        .auth-card .flash-info { background:var(--blue-bg); border:1px solid var(--border2); color:var(--blue);
                                 padding:var(--sp-3) var(--sp-4); border-radius:var(--radius); margin-bottom:var(--sp-5); font-size:var(--fs-base); }

        /* ── Address autocomplete dropdown (Google Places via server proxy) ──
           Ported from Operations base.html; concrete colours substituted for
           the Operations CSS variables. */
        .addr-autocomplete { position: relative; }
        .addr-dropdown {
            display: none;
            position: absolute;
            top: calc(100% + 2px);
            left: 0;
            right: 0;
            background: #fff;
            border: 0.5px solid rgba(0,0,0,0.22);
            border-radius: var(--radius);
            z-index: 250;
            max-height: 240px;
            overflow-y: auto;
            box-shadow: 0 4px 16px rgba(0,0,0,.1);
        }
        .addr-dropdown.open { display: block; }
        .addr-option {
            padding: var(--sp-3) var(--sp-4);
            font-size: var(--fs-base);
            cursor: pointer;
            border-bottom: 0.5px solid rgba(0,0,0,0.12);
        }
        .addr-option:last-child { border-bottom: none; }
        .addr-option:hover,
        .addr-option.active { background: var(--bg2); }

        /* ── Airport autocomplete dropdown ── */
        .airport-ac { position: relative; }
        .airport-dropdown {
            display: none;
            position: absolute;
            top: calc(100% + 2px);
            left: 0;
            right: 0;
            background: #fff;
            border: 0.5px solid rgba(0,0,0,0.22);
            border-radius: var(--radius);
            z-index: 250;
            max-height: 240px;
            overflow-y: auto;
            box-shadow: 0 4px 16px rgba(0,0,0,.08);
        }
        .airport-dropdown.open { display: block; }
        .airport-option {
            display: flex;
            align-items: center;
            gap: var(--sp-3);
            padding: var(--sp-3) var(--sp-4);
            font-size: var(--fs-base);
            cursor: pointer;
            border-bottom: 0.5px solid rgba(0,0,0,0.12);
        }
        .airport-option:last-child { border-bottom: none; }
        .airport-option:hover,
        .airport-option.active { background: var(--bg2); }
        .airport-code {
            font-weight: 600;
            min-width: 34px;
            font-variant-numeric: tabular-nums;
            letter-spacing: .04em;
        }
        .airport-detail { color: var(--text2); font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

        /* ── Shared date-field rendering (mirrors osa-operations base.html) ──
           One global enhancer so every date input behaves identically across the
           site. The value is ALWAYS #111 (filled, editable or disabled),
           !important so no page-specific rule can re-grey it; an empty field
           shows nothing (no grey mm/dd/yyyy) unless it's being edited. The JS
           enhancer (below) toggles .date-empty + injects the Clear control. */
        /* Date/time inputs are drawn by US, not the platform (ported from
           Operations). A native-appearance control sizes itself from font-size
           and ignores our height/padding, so on iOS/iPad Safari these render
           visibly taller than the text inputs beside them while looking fine in
           Chrome. Opting out puts our own sizing back in charge. The calendar
           affordance the native widget gave us is redrawn as an inline SVG, and
           the picker's Clear link is already replaced by .date-clear-btn below,
           so nothing is lost. */
        input[type="date"], input[type="time"], input[type="datetime-local"] {
            -webkit-appearance:none; -moz-appearance:none; appearance:none;
            background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23474747' stroke-width='2'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
            background-repeat:no-repeat; background-position:right 10px center;
            padding-right:var(--sp-6);
        }
        /* WebKit still reserves room for the (now hidden) native indicator. */
        input[type="date"]::-webkit-calendar-picker-indicator,
        input[type="time"]::-webkit-calendar-picker-indicator {
            opacity:0; -webkit-appearance:none; appearance:none;
            width:18px; margin:0; padding:0; cursor:pointer;
        }
        /* iOS sizes the inner value box from the font — pin it to the line. */
        input[type="date"]::-webkit-date-and-time-value,
        input[type="time"]::-webkit-date-and-time-value { margin:0; line-height:1.2; }
        input[type="date"] { color:var(--text) !important; -webkit-text-fill-color:var(--text) !important; }
        input[type="date"].date-empty:not(:focus),
        input[type="date"].date-empty:not(:focus)::-webkit-datetime-edit { color:transparent !important; -webkit-text-fill-color:transparent !important; }
        input[type="date"]:focus::-webkit-datetime-edit-text,
        input[type="date"]:focus::-webkit-datetime-edit-month-field,
        input[type="date"]:focus::-webkit-datetime-edit-day-field,
        input[type="date"]:focus::-webkit-datetime-edit-year-field { color:var(--text); }
        /* Clear control sits BELOW the input, right-aligned; the row reserves a
           little height even when the button is hidden so the field doesn't jump. */
        .date-clear-row { display:flex; justify-content:flex-end; min-height:13px; margin-top:var(--sp-1); }
        .date-clear-btn {
            font-size:var(--fs-sm); color:var(--text2); background:none; border:none; padding:0;
            font-weight:normal; letter-spacing:0; white-space:nowrap; cursor:pointer; user-select:none;
        }
        .date-clear-btn:hover { color:var(--osa-blue); text-decoration:underline; }
        .date-clear-btn[hidden] { display:none; }
        /* Brand accent on every checkbox/radio. Also stops the OS desaturating
           them to grey when the browser window is inactive — the page shouldn't
           change appearance just because it isn't the focused window. */
        /* Explicit box, not the platform's (ported from Operations). A native
           checkbox derives its size from font-size, so it visibly grew/shrank
           as the page crossed a breakpoint that moves the type scale — reading
           as the checkboxes "zooming" while resizing. A fixed size makes them
           identical at every width, on every page. */
        input[type="checkbox"], input[type="radio"] {
            accent-color:var(--osa-blue);
            width:15px; height:15px; flex:none;
        }

        /* ── Horizontal scroller (ported from Operations) ──
           One utility for every element that scrolls sideways, so they all
           announce hidden content the same way instead of each page inventing
           it (or, mostly, not).
           How it works: the two `local` gradients scroll WITH the content and
           mask the shadow when you are at that end; the two `scroll` radials
           stay pinned to the box. Net effect — a soft edge shadow appears only
           on the side that still has content, and fades as you reach it. Pure
           CSS: no scroll listener, nothing to keep in sync. */
        .hscroll {
            overflow-x:auto;
            -webkit-overflow-scrolling:touch;
            background:
                linear-gradient(90deg, var(--bg), rgba(255,255,255,0)) 0 0/44px 100% no-repeat local,
                linear-gradient(90deg, rgba(255,255,255,0), var(--bg)) 100% 0/44px 100% no-repeat local,
                radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.13), transparent) 0 0/16px 100% no-repeat scroll,
                radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.13), transparent) 100% 0/16px 100% no-repeat scroll;
        }
        /* Children must not wrap, or there is nothing to scroll. */
        .hscroll > * { flex-shrink:0; }

    /* Privacy blur toggle — ported from the Operations site (app.css). Marked
       fields wear .private; the cascade blurs them while privacy mode is on.
       Focusing an input or tapping a masked element reveals just that one
       (.peek), so a value can be read without flipping the whole page. */
    .privacy-toggle { display:inline-flex; align-items:center; justify-content:center;
        background:none; border:none; cursor:pointer; padding:var(--sp-2); margin-right:var(--sp-2);
        color:var(--text2); border-radius:var(--radius); line-height:0; transition:background .12s, color .12s; }
    .privacy-toggle:hover { background:var(--bg2); color:var(--text); }
    .privacy-toggle .icon-eye-off { display:none; }
    html.privacy-on .privacy-toggle { color:var(--blue); background:var(--blue-bg); }
    html.privacy-on .privacy-toggle .icon-eye { display:none; }
    html.privacy-on .privacy-toggle .icon-eye-off { display:inline-block; }
    html.privacy-on .private { filter:blur(5px) saturate(.6); user-select:none; cursor:pointer; transition:filter .12s; }
    html.privacy-on .private.peek { filter:none; user-select:text; cursor:auto; }

    /* Self-service PII preview modal */
    #pii-reveal-modal { position:fixed; inset:0; z-index:1200; display:flex;
        align-items:center; justify-content:center; padding:var(--sp-5); background:rgba(17,24,39,.55); }
    #pii-reveal-modal[hidden] { display:none !important; }
    .pr-dialog { background:#fff; border-radius:14px; width:100%; max-width:420px;
        box-shadow:0 20px 60px rgba(0,0,0,.28); padding:26px 26px var(--sp-6); font-family:inherit; }
    .pr-dialog h2 { font-size:var(--fs-xl); font-weight:600; color:var(--blue); margin:0 0 var(--sp-3); }
    /* was #4b5563 — a Tailwind slate, one of the cool-grey leftovers the palette
       comment describes. --text2 is the secondary-text tier (nearest rung). */
    .pr-dialog p { font-size:var(--fs-base); color:var(--text2); line-height:1.55; margin:0 0 var(--sp-4); }
    .pr-lock { font-size:26px; line-height:1; margin-bottom:var(--sp-2); }
    .pr-actions { display:flex; gap:var(--sp-3); margin-top:var(--sp-5); }
    .pr-btn { flex:1; padding:var(--sp-4); font-size:var(--fs-base); font-weight:500; border-radius:var(--radius);
        border:none; cursor:pointer; font-family:inherit; }
    .pr-btn-primary { background:var(--blue); color:#fff; }
    .pr-btn-primary:hover { background:var(--blue-ink); }
    .pr-btn-ghost { background:var(--bg2); color:var(--text); }
    .pr-btn-ghost:hover { background:var(--border); }
    .pr-code-input { width:100%; box-sizing:border-box; text-align:center; font-size:26px;
        letter-spacing:10px; padding:var(--sp-4); border:1px solid var(--border2); border-radius:var(--radius);
        font-family:inherit; color:var(--text); }
    .pr-code-input:focus { outline:none; border-color:var(--blue); box-shadow:0 0 0 3px rgba(40,56,127,.08); }
    .pr-msg { min-height:18px; font-size:var(--fs-sm); margin-top:var(--sp-3); }
    .pr-msg-error { color:var(--red); }
    .pr-intro-msg { font-size:var(--fs-sm); color:var(--red); margin-top:var(--sp-3); }
    .pr-dest { font-weight:600; color:var(--blue); }
    .pr-resend { background:none; border:none; color:var(--blue); font-size:var(--fs-sm); cursor:pointer;
        padding:var(--sp-2) 0; font-family:inherit; text-decoration:underline; }
    .pr-center { text-align:center; }
    .pr-spinner { width:34px; height:34px; margin:var(--sp-2) auto var(--sp-4); border-radius:50%;
        border:3px solid var(--border); border-top-color:var(--blue); animation:pr-spin .8s linear infinite; }
    @keyframes pr-spin { to { transform:rotate(360deg); } }
    .pii-reveal-toast { position:fixed; left:50%; bottom:24px; transform:translate(-50%,20px);
        max-width:520px; width:calc(100% - 40px); background:var(--blue); color:#fff; font-size:var(--fs-base);
        line-height:1.5; padding:var(--sp-4) var(--sp-5); border-radius:var(--radius); box-shadow:0 10px 30px rgba(0,0,0,.25);
        opacity:0; transition:opacity .3s, transform .3s; z-index:1300; }
    .pii-reveal-toast.show { opacity:1; transform:translate(-50%,0); }
    @media (max-width:640px) { .privacy-toggle { display:none; } }

    /* ── Crew avatars + photo upload (P5). Mirrors the ops app's vocabulary so
       the two sites read identically. .avatar* is reused site-wide (topnav,
       roster, finder); .crew-photo* is the onboarding-form pick/crop widget. */
    .avatar { border-radius: 50%; object-fit: cover; background: var(--bg3); display: inline-block; vertical-align: middle; flex: none; }
    .avatar-mono { display: inline-flex; align-items: center; justify-content: center; background: var(--blue); color: #fff; font-weight: 600; text-transform: uppercase; line-height: 1; }
    .avatar-xs { width: 32px; height: 32px; font-size: 13px; }
    .avatar-sm { width: 48px; height: 48px; font-size: 18px; }
    .avatar-md { width: 120px; height: 120px; font-size: 44px; }
    .avatar-lg { width: 200px; height: 200px; font-size: 72px; }

    .crew-photo { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-5); }
    .crew-photo-actions { display: flex; flex-direction: column; gap: var(--sp-2); }
    .crew-photo-modal { position: fixed; inset: 0; z-index: 1000; display: none; align-items: center; justify-content: center; background: rgba(0, 0, 0, .5); }
    .crew-photo-modal.is-open { display: flex; }
    .crew-photo-modal-inner { background: var(--bg); border-radius: var(--radius); padding: var(--sp-5); max-width: 92vw; }
    .crew-photo-crop-wrap { max-width: 70vw; max-height: 60vh; }
    .crew-photo-crop-wrap img { display: block; max-width: 100%; }
    .crew-photo-modal-actions { display: flex; justify-content: flex-end; gap: var(--sp-3); margin-top: var(--sp-4); }
    .crew-photo-modal .cropper-view-box, .crew-photo-modal .cropper-face { border-radius: 50%; }
    .crew-photo-zoom { display: block; width: 100%; margin-top: var(--sp-3); }
    body.crew-photo-lock { overflow: hidden; }
    .crew-photo-error { color: var(--red); font-size: var(--fs-sm); margin-bottom: var(--sp-5); }
    /* Scoped buttons — prod has no shared .btn-sm/.btn-primary system, so the
       widget carries its own (blue primary, outline secondary). */
    .cp-btn { padding: var(--sp-2) var(--sp-4); border: 1px solid var(--border2); border-radius: var(--radius);
              background: #fff; color: var(--text); font-size: var(--fs-sm); font-weight: 500; cursor: pointer; }
    .cp-btn:hover { background: var(--bg2); }
    .cp-btn-primary { background: var(--blue); color: #fff; border-color: var(--blue); }
    .cp-btn-primary:hover { background: var(--blue-ink); }
