/* ══════════════════════════════════════════════════════════════════════
   VIP — Landing page (login + cockpit chooser)
   Light grey backdrop, compact navy-headed card, yellow primary buttons,
   flat shadows.

   Token policy
   ------------
   The single source of truth for the brand palette is assets/vip-shell.css
   (the shared shell, loaded BEFORE this file — see index.php). The block
   below only aliases those --vip-* tokens to the short names used throughout
   this stylesheet, so the landing page and the cockpit can never drift apart.
   Each alias carries a literal fallback, so the page still renders correctly
   if the shell stylesheet ever fails to load.

   Never introduce a raw colour literal below this block: if a shade is
   missing, add it to vip-shell.css and alias it here.
   ══════════════════════════════════════════════════════════════════════ */

:root {
    --navy:      var(--vip-navy,     #25273A);
    --navy-70:   var(--vip-navy-70,  #696975);
    --navy-50:   var(--vip-navy-50,  #91929C);
    --navy-20:   var(--vip-navy-20,  #D2D2D6);
    --navy-10:   var(--vip-navy-10,  #E8E8EB);
    --yellow:    var(--vip-yellow,   #FFDF00);
    --yellow-d:  var(--vip-yellow-d, #F2D200);
    --steel:     var(--vip-steel,    #79828C);
    --cream-50:  var(--vip-cream-50, #F5F2F0);
    --teal:      var(--vip-teal,     #238291);
    --red:       var(--vip-red,      #CE181E);
    --green:     var(--vip-green,    #2E7D32);
    --white:     var(--vip-white,    #FFFFFF);

    /* Washed-out status surfaces used as message backgrounds. */
    --tint-red:   var(--vip-tint-red,   #FCE8E8);
    --tint-green: var(--vip-tint-green, #ECF6EC);

    /* Veil laid over a tile while its cockpit is being opened. Deliberately
       translucent, so the tile stays legible underneath the spinner. */
    --scrim-white: rgba(255, 255, 255, .88);

    --focus-ring: var(--vip-focus-ring, 0 0 0 3px rgba(37, 39, 58, .12));

    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 10px;
    --shadow-card: 0 6px 24px rgba(37, 39, 58, .18);
    --shadow-sm:   0 1px 3px rgba(37, 39, 58, .12);
    --shadow-md:   0 4px 14px rgba(37, 39, 58, .14);
    --transition:  0.18s ease;
}

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

html { height: 100%; }
body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    font-family: var(--vip-font-stack);
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    color: var(--navy);
    background: var(--navy-10);
    -webkit-font-smoothing: antialiased;
}

/* The page-level mount fills the viewport height as a flex column so the auth
   card (and the boot loader) centre vertically; the chooser stacks topbar + grid. */
#app {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

button { font-family: inherit; }
a { color: var(--teal); text-decoration: none; }
a:hover { text-decoration: underline; }

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

/* ══════════════════════════════════════════════════════════════════════
   AUTH CARD
   ══════════════════════════════════════════════════════════════════════ */
.auth-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 28px 16px;
}

.card {
    background: var(--white);
    width: 360px;
    max-width: 92vw;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

/* Navy header bar carrying the brand lock-up: the yellow claim continues the
   "savills" wordmark on its own baseline, with the product name set quietly
   above it. Bottom alignment plus the baseline inset (matching the wordmark's
   inset within the logo artwork) put the claim on the same optical footing as
   "savills"; --vip-brand-baseline is defined in vip-shell.css, which is loaded
   alongside this file. The same lock-up appears in the shared top bar
   (vip-shell.css), which scopes its own copy under .topbar — the two never
   collide. The two spans (tool-name / tool-tagline) are rendered by app.js. */
.card-head {
    background: var(--navy);
    color: var(--white);
    padding: 12px 24px;
    display: flex;
    align-items: flex-end;
    gap: 9px;
}
.card-head .logo { height: 40px; width: auto; display: block; }
.card-head .brand-text {
    display: block;
    line-height: 1;
    padding-bottom: var(--vip-brand-baseline, 3px);
    white-space: nowrap;
}
/* The product name sits one step smaller and quieter than the claim (dimmed
   white, regular weight), so the eye lands on the yellow claim first. */
.card-head .brand-text .tool-name {
    display: block;
    font-size: 11px;
    font-weight: 400;
    letter-spacing: .02em;
    color: rgba(255, 255, 255, .78);
    margin-bottom: 3px;
}
.card-head .brand-text .tool-tagline {
    display: block;
    font-family: var(--vip-font-voice);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .01em;
    color: var(--yellow);
}

.card-body { padding: 24px; }

.screen-title { font-size: 17px; font-weight: 600; margin: 0 0 4px; color: var(--navy); }
.screen-intro { font-size: 13px; color: var(--steel); margin: 0 0 18px; line-height: 1.5; }

/* ── Form atoms ───────────────────────────────────────────────────────── */
.field { margin-bottom: 14px; }
label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    margin-bottom: 6px;
    color: var(--navy);
}
.form-control {
    width: 100%;
    padding: 10px 12px;
    font-size: 14px;
    color: var(--navy);
    background: var(--white);
    border: 1px solid var(--navy-10);
    border-radius: var(--radius-md);
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.form-control:focus { border-color: var(--navy); box-shadow: var(--focus-ring); }
.form-control::placeholder { color: var(--navy-50); }
.form-control:disabled { background: var(--cream-50); color: var(--navy-50); }

/* 6-digit code entry. */
.code-input {
    letter-spacing: .4em;
    text-align: center;
    font-size: 20px;
    font-weight: 600;
    padding: 11px 12px;
}

/* Primary action: navy text on yellow. */
.action-btn {
    width: 100%;
    margin-top: 16px;
    padding: 11px;
    font-size: 14px;
    font-weight: 600;
    border: 0;
    border-radius: var(--radius-md);
    background: var(--yellow);
    color: var(--navy);
    cursor: pointer;
    transition: background var(--transition), opacity var(--transition);
}
.action-btn:hover { background: var(--yellow-d); }
.action-btn:disabled { opacity: .6; cursor: default; }

/* Secondary text link. */
.btn-link {
    background: none;
    border: 0;
    color: var(--steel);
    font-size: 12px;
    cursor: pointer;
    padding: 0;
    width: auto;
    text-decoration: underline;
}
.btn-link:hover { color: var(--navy); }
.btn-link:disabled { opacity: .5; cursor: default; text-decoration: none; }

.form-foot {
    margin-top: 14px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
}

.note { font-size: 11px; color: var(--steel); margin-top: 14px; line-height: 1.5; }

/* ── Inline messages ──────────────────────────────────────────────────── */
.msg {
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    line-height: 1.45;
    margin-bottom: 14px;
}
.msg.error { background: var(--tint-red);   border-left: 4px solid var(--red);   color: var(--navy); }
.msg.info  { background: var(--cream-50);   border-left: 4px solid var(--teal);  color: var(--navy); }
.msg.ok    { background: var(--tint-green); border-left: 4px solid var(--green); color: var(--navy); }

/* ── 2FA enrolment ────────────────────────────────────────────────────── */
.qr-box { display: flex; justify-content: center; margin: 4px 0 14px; }
.qr-box svg {
    width: 180px; height: 180px;
    border: 1px solid var(--navy-10);
    border-radius: var(--radius-md);
    padding: 8px;
    background: var(--white);
}
.secret-box {
    background: var(--cream-50);
    border: 1px dashed var(--navy-20);
    border-radius: var(--radius-md);
    padding: 10px 12px;
    margin-bottom: 16px;
    text-align: center;
}
.secret-box .secret-label {
    font-size: 10px; font-weight: 700; letter-spacing: .6px;
    text-transform: uppercase; color: var(--steel);
}
.secret-box .secret-val {
    font-family: var(--vip-font-mono);
    font-size: 14px; font-weight: 600; color: var(--navy);
    word-break: break-all; margin-top: 4px; user-select: all;
}

/* ── Password strength meter (advisory) ───────────────────────────────── */
.pw-meter { height: 5px; border-radius: 3px; background: var(--navy-10); margin: 8px 0 4px; overflow: hidden; }
.pw-meter > span { display: block; height: 100%; width: 0; background: var(--red); transition: width var(--transition), background var(--transition); }
.pw-hint { font-size: 11px; color: var(--steel); min-height: 14px; }

/* ── Spinner (navy, on yellow button / light backdrop) ────────────────── */
.spin {
    display: inline-block;
    width: 15px; height: 15px;
    vertical-align: -2px;
    margin-right: 8px;
    border: 2px solid rgba(37, 39, 58, .35);
    border-top-color: var(--navy);
    border-radius: 50%;
    animation: sc-spin .65s linear infinite;
}
@keyframes sc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spin { animation-duration: 1.4s; } }

/* ══════════════════════════════════════════════════════════════════════
   COCKPIT CHOOSER
   ══════════════════════════════════════════════════════════════════════ */
.chooser {
    flex: 1;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 30px 22px 48px;
}
.chooser h1 { font-size: 20px; font-weight: 700; color: var(--navy); margin: 6px 0 2px; }
.chooser .sub { font-size: 13px; color: var(--steel); margin: 0 0 22px; }

/* ── Filter bar ───────────────────────────────────────────────────────── */
.chooser-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin: 4px 0 20px;
}
.chooser-filters .cf-search { flex: 1 1 280px; min-width: 200px; }
.chooser-filters .cf-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

.cf-input,
.cf-select {
    width: 100%;
    height: 40px;
    padding: 0 12px;
    font: inherit;
    color: var(--navy);
    background: var(--white);
    border: 1px solid var(--navy-20);
    border-radius: var(--radius-md);
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.cf-select { width: auto; min-width: 160px; cursor: pointer; }
.cf-input:focus,
.cf-select:focus {
    border-color: var(--navy);
    box-shadow: var(--focus-ring);
}
.cf-input::placeholder { color: var(--navy-50); }

/* Sort order. Sits to the right of the visited segment and is the last control
   in the bar; the options carry their own "Sort:" prefix, so no visible label
   is needed and the bar keeps a single row on desktop. */
.cf-sort { min-width: 190px; }

/* ── Visited segmented control ────────────────────────────────────────── */
.cf-seg {
    display: inline-flex;
    padding: 3px;
    background: var(--navy-10);
    border: 1px solid var(--navy-20);
    border-radius: var(--radius-md);
}
.cf-seg-btn {
    appearance: none;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 14px;
    line-height: 1;
    color: var(--navy-70);
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.cf-seg-btn:hover { color: var(--navy); }
.cf-seg-btn.is-active {
    background: var(--navy);
    color: var(--white);
}
.cf-seg-btn:focus-visible {
    outline: 2px solid var(--navy);
    outline-offset: 2px;
}

/* ── Tile grid ────────────────────────────────────────────────────────── */
.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
}
.tile {
    position: relative;
    text-align: left;
    background: var(--white);
    border: 1px solid var(--navy-10);
    border-left: 3px solid var(--yellow);
    border-radius: var(--radius-md);
    padding: 16px 18px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-height: 132px;
    transition: transform var(--transition), box-shadow var(--transition);
}
.tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.tile:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

/* Header: project/client left, last visit pinned right. */
.tile .t-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
.tile .t-headline { min-width: 0; }      /* allow text truncation if needed */
.tile .t-project { font-size: 15px; font-weight: 700; color: var(--navy); line-height: 1.25; }
.tile .t-client { font-size: 13px; color: var(--steel); margin-top: 2px; line-height: 1.4; }

.tile .t-lastvisit {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    white-space: nowrap;
}
.tile .t-lv-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--navy-50);
}
.tile .t-lv-date { font-size: 13px; font-weight: 600; color: var(--navy); }
.tile .t-lv-date.is-never { color: var(--navy-50); font-weight: 500; }

/* Meta row: team flag left, badges right. Pinned to the bottom of the tile and
   separated by a hairline, so every card in a row closes on the same line. */
.tile .t-meta {
    margin-top: auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--navy-10);
    font-size: 11px;
    color: var(--steel);
}
.tile .t-meta-left,
.tile .t-meta-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.tile .badge {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
    padding: 3px 7px; border-radius: 999px; white-space: nowrap; flex-shrink: 0;
}
.badge.svc { background: var(--navy-10); color: var(--navy-70); }

/* Team flag chip. */
.team-flag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px 4px 8px;
    background: var(--navy-10);
    border: 1px solid var(--navy-20);
    border-radius: 999px;
    font-size: 11px;
    color: var(--navy);
}
.team-flag-glyph {
    font-size: 15px;
    line-height: 1;
    /* Emoji flags need a colour-emoji font; the neutral pennant (⚑) renders
       everywhere as a fallback when no country mapping is configured. */
}
.team-flag-name { font-weight: 600; }

/* Cockpit tiles that cannot be opened (no launch target configured). */
.tile.is-disabled {
    opacity: .55;
    cursor: not-allowed;
    filter: grayscale(1);
}
.tile.is-disabled:hover { transform: none; box-shadow: none; }
.tile .t-note {
    font-size: 12px;
    color: var(--steel);
}

/* ── Inline launch (case a): the tile is busy until cockpit.php replies ───
   The endpoint runs PHP before it returns any HTML, so the browser keeps showing
   this page for a moment after the click. The veil marks the tile that was chosen
   and the rest of the chooser is put out of reach, so a second launch cannot be
   started while the first is on its way. */
.tile .t-launch {
    position: absolute;
    inset: 0;                          /* padding-box: the yellow spine stays visible */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    border-radius: inherit;
    background: var(--scrim-white);
    font-size: 13px;
    font-weight: 600;
    color: var(--navy);
}
.tile.is-launching { cursor: progress; }
.tile.is-launching:hover { transform: none; box-shadow: var(--shadow-md); }

body.is-launching .tile:not(.is-launching),
body.is-launching .chooser-filters {
    opacity: .5;
    pointer-events: none;
}

.empty { text-align: center; color: var(--steel); padding: 60px 20px; font-size: 13px; }

/* ── Responsive: stack filter controls on narrow viewports ────────────── */
@media (max-width: 720px) {
    .chooser-filters .cf-controls { width: 100%; }
    .cf-select { flex: 1 1 180px; }
}
@media (max-width: 560px) {
    .cf-seg { width: 100%; }
    .cf-seg-btn { flex: 1 1 0; }
    .cf-sort { flex: 1 1 100%; width: 100%; }
}

/* ── Full-page boot state: valuation-themed calculator loader ──────────── */
.boot { flex: 1; display: flex; align-items: center; justify-content: center; }

.calc-loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
}
.calc {
    width: 156px;
    background: var(--navy);
    border-radius: 16px;
    padding: 14px;
    box-shadow: var(--shadow-card);
}
.calc-display {
    background: #15161f;               /* deeper than navy: the LCD recess */
    color: var(--yellow);
    border-radius: 7px;
    padding: 10px 12px;
    text-align: right;
    font-family: var(--vip-font-mono);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: .4px;
    min-height: 22px;
    line-height: 22px;
    overflow: hidden;
    white-space: nowrap;
}
.calc-keys {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 7px;
    margin-top: 12px;
}
.calc-key {
    height: 22px;
    border-radius: 5px;
    background: #3a3c52;               /* raised key on the navy body */
    animation: calc-press 2s linear infinite;
    will-change: transform, filter;
}
.calc-key.op { background: var(--yellow); }
@keyframes calc-press {
    0%   { transform: translateY(0);     filter: brightness(1);   }
    4%   { transform: translateY(1.5px); filter: brightness(1.9); }
    8%   { transform: translateY(0);     filter: brightness(1);   }
    100% { transform: translateY(0);     filter: brightness(1);   }
}
.calc-caption {
    font-size: 13px;
    color: var(--steel);
    letter-spacing: .2px;
}
@media (prefers-reduced-motion: reduce) {
    .calc-key { animation: none; }
}

@media (max-width: 520px) {
    .topbar .who .email { display: none; }
}
