/* ========================== *
 * ## Property Declaration ##
 * ========================== */

:root {
    --cdm-list-row-height: 32px;
    --cdm-list-row-padding: 5px;

    --flighttracking-header-height: 112px;

    --stand-editor-list-rows-max: 10;
    --user-management-list-row-max: 10;
}

/* =========== *
 * ## Pages ##
 * =========== */

body[data-page="login"],
body[data-page="stand-editor"],
body[data-page="user-management"]{
    background: var(--grey);
}


/* ==================== *
 * ## Airport Search ##
 * ==================== */

.airport-search-container {
   grid-area: search;
   z-index: 3;
   display: flex;
   align-self: center;
}

.airport-search-container .container {
   display: flex;
   flex-direction: row;
   gap: 12px;
}


/* ============================= *
 * ## CDM Interactive Editors ##
 * ============================= */

.cdm-interactive-editor {
    border-style: solid;
    border-width: 1px;
    display: flex;
    flex-direction: column;
    left: 50%;
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 75%;
}

.cdm-interactive-editor > .header {
    font-size: 18px;
    font-weight: bold;
    line-height:18px;
    padding: 10px;
    text-transform: uppercase;
}

.cdm-interactive-editor .list-container {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.cdm-interactive-editor .list-container .button-container {
    display: flex;
    flex-direction: row;
}

.cdm-interactive-editor .section {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 10px;
}

.cdm-interactive-editor .section > .header {
    font-size: 14px;
    font-weight: bold;
    text-transform: uppercase;
}

.cdm-interactive-editor .section > .content {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.cdm-interactive-editor .action-button-container {
    display:flex;
    flex-direction: row;
    gap: 20px;
    position: relative;
    width: 100%;
}

.cdm-interactive-editor .ui-dynamic-list .list .list-row {
    height: var(--cdm-list-row-height);
    line-height: calc(var(--cdm-list-row-height) - (var(--cdm-list-row-padding) * 2));
    padding: var(--cdm-list-row-padding);
}


/* ========================= *
 * ## CDM Login Interface ##
 * ========================= */

.cdm-login-interface {
    background: var(--login-bg);
    border-color: var(--login-border);
    border-style: solid;
    border-width: 1px;
    left: 50%;
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
}

.cdm-login-interface .content {
    padding: 10px;
}

.cdm-login-interface .content .login-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.cdm-login-interface .content .login-form .login-form-row {
    display: flex;
    flex-direction: row;
    gap: 10px;
}

.cdm-login-interface .content .login-form .login-form-row > label {
    color: var(--login-row-text);
    font-weight: bold;
    line-height: 24px;
    width: 70px;
}

.cdm-login-interface .content .login-form .login-form-row > input {
    width: 200px;
}

.cdm-login-interface .content .login-form .login-button {
    line-height: 20px;
    margin: 0;
}

.cdm-login-interface .content .login-form .forgot-password-link {
    display: none;
}

.cdm-login-interface .footer {
    background: var(--login-footer-bg);
    color: var(--login-footer-text);
    display: flex;
    flex-direction: row;
    justify-content: end;
    line-height: 16px;
    padding: 10px;
}

.cdm-login-interface .footer .version-container {
    display: flex;
    flex-direction: row;
    font-weight: bold;
    gap: 5px;
    height: 16px;
    line-height: 16px;
}

.cdm-login-interface .header {
    background: var(--login-header-bg);
    color: var(--login-header-text);
    font-size: 18px;
    font-weight: bold;
    line-height: 18px;
    padding: 10px;
    text-transform: uppercase;
}


/* =========================== *
 * ## Flighttracking Header ##
 * =========================== */

.flighttracking-header .airport-search-container {
   grid-area: search;
   justify-self: end;
}

.flighttracking-header .header-flex-container {
    display: grid;
    grid-template-columns: 350px auto 350px;
    grid-template-rows: 1fr 1fr;
    grid-template-areas:
      "meteo datetime datetime"
      "alerts alerts search";
}


/* ================== *
 * ## Stand Editor ##
 * ================== */

.stand-editor-component {
    background: var(--se-bg);
    border-color: var(--se-border);
    max-width: 400px;
}

.stand-editor-component > .header {
    background-color: var(--se-header-bg);
    color: var(--se-header-text);
}

.stand-editor-component .list-container .role-status-list .list.custom_scroll {
    max-height: 320px;
}

.stand-editor-component .section > .header {
    color: var(--se-section-header-font);
}

.stand-editor-component .action-button-container .role-logout {}
.stand-editor-component .action-button-container .role-back-to-cdm {}
.stand-editor-component .action-button-container .role-documentation {}

.stand-editor-component .ui-dynamic-list .list {
    max-height: calc(var(--stand-editor-list-rows-max) * var(--cdm-list-row-height));
}


/* ========================= *
 * ## Taxiway Block Layer ##
 * ========================= */

.taxiway-block-layer .taxiway-block-label {
    transform: translate(-50%, -10px);
}


/* ===================== *
 * ## User Management ##
 * ===================== */

.user-management-component {
    background: var(--um-bg);
    border-color: var(--um-border);
    max-width: 1100px;
}

.user-management-component > .header {
    background-color: var(--um-header-bg);
    color: var(--um-header-text);
}

.user-management-component .list-container .role-status-list .list.custom_scroll {
    max-height: 640px;
}

.user-management-component .section > .header {
    color: var(--um-section-header-font);
}

.user-management-component .ui-dynamic-list .list {
    max-height: calc(var(--user-management-list-row-max) * var(--cdm-list-row-height));
}

.user-management-list-popup .ui-input .input-container { width: 250px; }


/* =============================== *
 * ## CDM Times section filtering ##
 * =============================== */

/*
 * Show only the CDM Times block that matches the flight's state. The three blocks are all included
 * by tab-flight-info-summary-cdm_times.inc.tpl, so without this every flight showed departure and
 * arrival milestones at once. States come from config/products/cdm/javascript/FlightProvider.js
 * flightStateGetter; a local flight is both a departure and an arrival, so it shows both.
 *
 * These rules live here rather than in a customer stylesheet because the templates are product-level.
 */
.casper-tab .section-description-container.inbound-section,
.casper-tab .section-description-container.outbound-section,
.casper-tab .section-description-container.inblock-section {
   display: none;
}

.casper-tab .section-description-container.inbound-section[data-fl_state="INB"],
.casper-tab .section-description-container.inbound-section[data-fl_state="LOC"],
.casper-tab .section-description-container.outbound-section[data-fl_state="OUT"],
.casper-tab .section-description-container.outbound-section[data-fl_state="LOC"],
.casper-tab .section-description-container.inblock-section[data-fl_state="IBK"] {
   display: block;
}

/* Sub-header follows the blocks, so a state with no block loses the section rather than the heading. */
.casper-tab .section-sub-header.cdm-times {
   display: none;
}

.casper-tab .section-sub-header.cdm-times[data-fl_state="INB"],
.casper-tab .section-sub-header.cdm-times[data-fl_state="LOC"],
.casper-tab .section-sub-header.cdm-times[data-fl_state="OUT"],
.casper-tab .section-sub-header.cdm-times[data-fl_state="IBK"] {
   display: block;
}


/* ================================= *
 * ## Map label section filtering ## *
 * ================================= */

/*
 * Show exactly one section of the map hover label (see map-layer-aircraft.inc.tpl and the per-state
 * templates it includes). States come from config/products/cdm/javascript/FlightProvider.js
 * flightStateGetter.
 *
 * The .cdm class scopes these rules to the CDM label. AMS and LGW carry their own aircraft-layer
 * templates using the same .label-section names, and LGW has no filtering rules of its own.
 *
 * The label node carries both .casper-vehicle-label and .map-icon-label
 * (components/AircraftLayer.class.js) and is created lazily, on FLIGHT_INTERACTED.
 */
.casper-vehicle .map-icon-label .label-section.cdm {
   display: none;
}

.casper-vehicle .map-icon-label .label-section.cdm.vehicle[data-fl_state="VEH"],
.casper-vehicle .map-icon-label .label-section.cdm.inbound[data-fl_state="INB"],
.casper-vehicle .map-icon-label .label-section.cdm.outbound[data-fl_state="OUT"],
.casper-vehicle .map-icon-label .label-section.cdm.local[data-fl_state="LOC"],
.casper-vehicle .map-icon-label .label-section.cdm.inblock[data-fl_state="IBK"],
.casper-vehicle .map-icon-label .label-section.cdm.other {
   display: grid;
   grid-template-columns: max-content auto max-content auto;
   column-gap: 5px;
}

/*
 * .other is the fallback for an unknown state and is last in the template, so suppress it (and any
 * later sibling) once a state-specific section has matched.
 */
.casper-vehicle .map-icon-label .label-section.cdm.vehicle[data-fl_state="VEH"] ~ .label-section.cdm,
.casper-vehicle .map-icon-label .label-section.cdm.inbound[data-fl_state="INB"] ~ .label-section.cdm,
.casper-vehicle .map-icon-label .label-section.cdm.outbound[data-fl_state="OUT"] ~ .label-section.cdm,
.casper-vehicle .map-icon-label .label-section.cdm.local[data-fl_state="LOC"] ~ .label-section.cdm,
.casper-vehicle .map-icon-label .label-section.cdm.inblock[data-fl_state="IBK"] ~ .label-section.cdm {
   display: none;
}


/* ====================== *
 * ## Map label layout ## *
 * ====================== */

/*
 * Lay the label out as a table: every row spans all four columns, so each label and value lands in a
 * shared column and a row carrying two pairs lines up with a row carrying one. A row with a single
 * pair leaves columns 3 and 4 empty.
 */
.casper-vehicle .map-icon-label .label-section.cdm .label-row { display: contents; }

/* Anchor each row's first cell to column 1, or auto-placement flows it into the previous row's
   spare columns. A row's first label/value pair is never wrapped in a <lock> and never guarded, so
   the anchor survives skin gating; a later pair may be absent, which only leaves its columns empty. */
.casper-vehicle .map-icon-label .label-section.cdm .label-row > :first-child { grid-column: 1; }

.casper-vehicle .map-icon-label .label-section.cdm .label-row-label,
.casper-vehicle .map-icon-label .label-section.cdm .label-row-value {
   white-space: nowrap;
}

.casper-vehicle .map-icon-label .label-section.cdm .label-row.header {
   display: block;
   grid-column: 1 / -1;
}

/* Keep the flight number's separator off the callsign. The header is display: block, so the two
   labels flow inline and a gutter here does the job for all five state templates at once. */
.casper-vehicle .map-icon-label .label-section.cdm .label-row.header .label-row-label + .label-row-label {
   margin-left: 0.25em;
}

/* active-stand layer */
/* Sits above the flighttracking noise-monitor layer (z-index 8) and below its aircraft layer
   (z-index 10) -- see config/products/flighttracking/css/styles.css, whose cascade this skin
   also loads via config/products/cdm/skins/cdm.xml including flighttracking.xml. The halo must
   read above the basemap and other overlays but never obscure an aircraft icon. */
.active-stand-layer {
   z-index: 9;
}

.active-stand-layer .active-stand-container {
   position: absolute;
   pointer-events: none;
}

/* Every mark kind shares one footprint: a 44px halo, a 34px ring and a 10px dot, all centred on
   the same point. Which of the three actually renders is decided below by the container's own
   class (searched/inbound/both) alone, so the mark never grows or shrinks with what it marks. */
.active-stand-layer .active-stand-halo {
   position: absolute;
   width: 44px;
   height: 44px;
   margin-left: -22px;
   margin-top: -22px;
   border-radius: 50%;
   border-style: solid;
   border-color: var(--active-stand);
   border-width: 1.5px;
   box-sizing: border-box;
   /* Cartographic halo: a dark line then a light line around the same edge. One of the two always
      separates from whatever the basemap tile renders underneath, unlike the border colour alone,
      which only works on tiles it happens to contrast with. */
   box-shadow: 0 0 0 1px rgba(10, 12, 16, .6), 0 0 0 2.5px rgba(255, 255, 255, .9);
   display: none;
}

.active-stand-layer .active-stand-label {
   position: absolute;
   transform: translate(-50%, 26px);
   white-space: nowrap;
   font-size: 10px;
   font-weight: 600;
   background: var(--active-stand-label-bg);
   border: 1px solid var(--active-stand-label-border);
   border-radius: 4px;
   padding: 2px 7px;
   color: var(--white);
}

/* Animated halo: only while an inbound flight is the thing being tracked -- plain inbound, or the
   coincident case where the searched stand is also its target. A searched stand on its own gets
   the static outline below instead, immediately, with no pulse. */
.active-stand-layer .inbound .active-stand-halo,
.active-stand-layer .both .active-stand-halo {
   display: block;
   animation: active-stand-heartbeat 5s ease-out infinite;
   opacity: 0;
}

.active-stand-layer .inbound .active-stand-halo:nth-of-type(2),
.active-stand-layer .both .active-stand-halo:nth-of-type(2) { animation-delay: 1.7s; }
.active-stand-layer .inbound .active-stand-halo:nth-of-type(3),
.active-stand-layer .both .active-stand-halo:nth-of-type(3) { animation-delay: 3.4s; }

@keyframes active-stand-heartbeat {
   0%   { transform: scale(0.32); opacity: 0.45; }
   100% { transform: scale(1);    opacity: 0; }
}

.active-stand-layer .active-stand-ring {
   position: absolute;
   width: 34px;
   height: 34px;
   margin-left: -17px;
   margin-top: -17px;
   border-radius: 50%;
   border-style: solid;
   border-color: var(--active-stand-icon-border);
   border-width: 2.5px;
   box-sizing: border-box;
   box-shadow: 0 0 0 1px rgba(10, 12, 16, .6), 0 0 0 2.5px rgba(255, 255, 255, .9);
   display: none;
}

/* Static outline: shown immediately, with no animate-in, whenever the stand itself is the thing
   being pointed at -- searched on its own, or the coincident case with an inbound flight. Never
   shown for a plain inbound target, which relies on the animated halo alone. */
.active-stand-layer .searched .active-stand-ring,
.active-stand-layer .both .active-stand-ring {
   display: block;
}

.active-stand-layer .active-stand-dot {
   position: absolute;
   width: 10px;
   height: 10px;
   margin-left: -5px;
   margin-top: -5px;
   border-radius: 50%;
   background-color: var(--active-stand-icon-bg);
   box-shadow: 0 0 0 1px rgba(10, 12, 16, .55), 0 0 0 2px rgba(255, 255, 255, .85);
}
