/* Floor-plan editor.
   A global stylesheet rather than component-scoped CSS, matching gvs-locations.css and its
   siblings. It has to be global: the editor is one page composed of several child components
   (worklist, rail, inspector, issues) that share these classes, and Blazor's CSS isolation scopes
   a .razor.css file to its own component only -- which left every child unstyled. */

.fp-editor {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 8rem);
    min-height: 32rem;
}

.fp-toolbar {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding: .5rem .75rem;
    background: #eceff3;
    border-bottom: 1px solid #c9ced6;
    flex-wrap: wrap;
}

.fp-title { font-weight: 600; margin-right: .75rem; }
.fp-spacer { flex: 1; }

/* Location breadcrumb. Sits where the plan title used to, because it names what the whole editor
   is scoped to -- the floor rail below it only makes sense once you know the building. */
.fp-crumbs { display: flex; align-items: center; flex-wrap: wrap; margin-right: .75rem; }
.fp-crumb { position: relative; display: flex; align-items: center; }
.fp-crumb-sep { color: #a8aeb8; margin: 0 .1rem; }

.fp-crumb-btn {
    display: inline-flex;
    align-items: baseline;
    gap: .3rem;
    background: none;
    border: 1px solid transparent;
    border-radius: 3px;
    padding: .2rem .4rem;
    font-size: .8rem;
    color: #3f4854;
    cursor: pointer;
}

.fp-crumb-btn:hover { background: #eef1f5; border-color: #d6dae1; }
.fp-crumb-btn--current { font-weight: 600; color: #12213a; }
.fp-crumb-btn:focus-visible { outline: 2px solid #1565c0; outline-offset: 1px; }

/* The level name, so a crumb reads as "Site: Sacred Heart Annexe" rather than a bare word whose
   place in the hierarchy you have to infer. */
.fp-crumb-kind { font-size: .6rem; text-transform: uppercase; letter-spacing: .05em; color: #7b8494; font-weight: 600; }
.fp-crumb-caret { font-size: .55rem; color: #7b8494; }

/* Above the backdrop, so the dropdown itself stays clickable. */
.fp-crumb-menu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 40;
    min-width: 15rem;
    max-width: 24rem;
    max-height: 22rem;
    overflow-y: auto;
    margin-top: .2rem;
    padding: .25rem;
    background: #fff;
    border: 1px solid #c9ced6;
    border-radius: 4px;
    box-shadow: 0 6px 18px rgba(16, 24, 40, .14);
}

.fp-crumb-search {
    width: 100%;
    box-sizing: border-box;
    margin-bottom: .25rem;
    padding: .3rem .45rem;
    font-size: .8rem;
    border: 1px solid #c9ced6;
    border-radius: 3px;
}

.fp-crumb-empty { margin: .4rem .45rem; font-size: .75rem; color: #7b8494; }

.fp-crumb-opt {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: 0;
    border-radius: 3px;
    padding: .35rem .45rem;
    font-size: .8rem;
    color: #22303f;
    cursor: pointer;
}

.fp-crumb-opt:hover:not(:disabled) { background: #eef1f5; }
.fp-crumb-opt--current { background: #e7effb; font-weight: 600; }
.fp-crumb-opt:disabled { color: #9aa2ae; cursor: default; }
.fp-crumb-opt:focus-visible { outline: 2px solid #1565c0; outline-offset: -2px; }
.fp-crumb-opt-name { display: block; }
.fp-crumb-opt-path { display: block; font-size: .68rem; color: #7b8494; }
.fp-crumb-opt-note { display: block; font-size: .68rem; font-style: italic; color: #9aa2ae; }

.fp-crumb-backdrop { position: fixed; inset: 0; z-index: 30; }

.fp-btn {
    background: #fff;
    border: 1px solid #c9ced6;
    border-radius: 3px;
    padding: .25rem .6rem;
    font-size: .8rem;
    line-height: 1.4;
    cursor: pointer;
    color: #1c2024;
    text-decoration: none;
    display: inline-block;
}

.fp-btn:hover { background: #f2f5f9; }

/* The Import button is a label wrapping a real file input: only an input can open a file picker,
   and an input cannot be styled to match the buttons beside it. The input is taken out of the
   layout rather than hidden with display:none, which stops some browsers opening the picker. */
.fp-file-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.fp-btn--on { background: #2f6bd8; border-color: #2f6bd8; color: #fff; font-weight: 600; }
.fp-btn--on:hover { background: #2a5fc0; }
.fp-btn--primary { background: #2e9e5b; border-color: #2e9e5b; color: #fff; font-weight: 600; }
.fp-btn--danger { background: #fff; border-color: #eaa8a8; color: #8f2020; }
.fp-btn--danger:hover { background: #fdeaea; }
.fp-btn:disabled { opacity: .5; cursor: default; }

.fp-status { margin: 0; padding: .4rem .75rem; background: #fdf3e3; color: #7a5514; font-size: .8rem;
    display: flex; align-items: center; gap: .6rem; }

/* A publish the server accepted -- distinct from a warning, because it is the one moment the
   editor has genuinely finished something. */
.fp-status--ok { background: #eaf6ee; color: #1e6b3d; }

/* A whole-plan trace, while it runs. Sits where the status line sits and looks like it, because
   it is the same thing: the editor saying what it is doing. */
.fp-trace { padding: .4rem .75rem; background: #fdf3e3; color: #7a5514; font-size: .8rem; }

.fp-trace__line { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }

.fp-trace__step { font-weight: 600; }

.fp-trace__of { opacity: .75; font-variant-numeric: tabular-nums; }

.fp-trace__track {
    margin-top: .3rem;
    height: .35rem;
    border-radius: .2rem;
    background: #eadcc0;
    overflow: hidden;
}

/* Steps, not seconds -- so the fill jumps between stages. The transition stops that reading as a
   glitch without pretending to a smoothness the measurement does not have. */
.fp-trace__fill {
    height: 100%;
    background: #7a5514;
    transition: width .2s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .fp-trace__fill { transition: none; }
}

.fp-body { display: flex; flex: 1; min-height: 0; }

.fp-worklist {
    width: 20rem;
    min-width: 14rem;
    background: #fff;
    border-right: 1px solid #c9ced6;
    overflow-y: auto;
    padding: .5rem .6rem;
}

.fp-canvas-host { flex: 1; min-width: 0; position: relative; background: #fdfdfe; }

.fp-inspector {
    width: 18rem;
    min-width: 13rem;
    background: #fff;
    border-left: 1px solid #c9ced6;
    overflow-y: auto;
    padding: .5rem .6rem;
}

/* The canvas fills its host. Its pixel size is set from the measured box by a ResizeObserver in
   the module, so this is the only place its display size is decided. */
/* The cursor is set by the module, which knows whether a press here would draw, move, resize or
   pan -- so it is deliberately not fixed here. */
.plan-canvas { display: block; width: 100%; height: 100%; touch-action: none; }

/* ---- Floor rail ---- */

.fp-rail {
    width: 8.5rem;
    background: #eceff3;
    border-right: 1px solid #c9ced6;
    padding: .4rem .3rem;
    display: flex;
    flex-direction: column;
    gap: .2rem;
    overflow-y: auto;
}

.fp-rail-title {
    font-size: .62rem;
    text-transform: uppercase;
    letter-spacing: .5px;
    color: #68707c;
    font-weight: 700;
    margin-bottom: .15rem;
}

.fp-lvl {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .2rem;
    border: 1px solid #c9ced6;
    background: #fff;
    border-radius: 3px;
    padding: .2rem .25rem;
    font-size: .72rem;
}

.fp-lvl--on { background: #2f6bd8; border-color: #2f6bd8; color: #fff; font-weight: 700; }
.fp-lvl--ghost { background: #f2ecfb; border-color: #c3a6e8; }

.fp-lvl-name { cursor: pointer; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The level number, so which floor sits above which is visible without reading names. */
.fp-lvl-level { font-size: .62rem; opacity: .7; font-variant-numeric: tabular-nums; }

/* The eye needs a real hit area of its own, or it is a few unclickable pixels. */
.fp-eye {
    cursor: pointer;
    opacity: .35;
    font-size: .8rem;
    line-height: 1;
    padding: .15rem .2rem;
    border-radius: 3px;
}

.fp-eye:hover { opacity: .8; background: rgba(0, 0, 0, .06); }
.fp-eye--on { opacity: 1; color: #8a4fd0; }

/* ---- Worklist ---- */

.fp-panel-title { font-size: .8rem; margin: .2rem 0 .3rem; font-weight: 700; }
.fp-panel-sub { font-size: .74rem; color: #68707c; margin: 0 0 .4rem; }

/* Full width of the panel, matching .fp-crumb-search's input conventions. The clear button sits
   inside the field's right edge instead of beside it, so the box keeps the panel's full width. */
.fp-search { position: relative; margin: 0 0 .5rem; }

.fp-search-input {
    width: 100%;
    box-sizing: border-box;
    padding: .3rem 1.6rem .3rem .45rem;
    font-size: .8rem;
    border: 1px solid #c9ced6;
    border-radius: 3px;
}

.fp-search-clear {
    position: absolute;
    top: 50%;
    right: .3rem;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.1rem;
    height: 1.1rem;
    padding: 0;
    margin: 0;
    background: none;
    border: none;
    font-size: .85rem;
    line-height: 1;
    color: #68707c;
    cursor: pointer;
    border-radius: 2px;
}

.fp-search-clear:hover { background: rgba(0, 0, 0, .06); }

.fp-progress { height: 5px; background: #e3e6ea; border-radius: 3px; overflow: hidden; }
.fp-progress span { display: block; height: 100%; background: #2e9e5b; }

.fp-group { margin-top: .6rem; }

/* A group header is a CONTAINER, not a choice. It gets no hover and no pointer cursor, because a
   bold row that looks clickable is what made it read as another selectable room. */
.fp-group-head {
    display: flex;
    align-items: baseline;
    gap: .35rem;
    font-weight: 700;
    font-size: .76rem;
    padding: .15rem .1rem;
    border-bottom: 1px solid #dfe3e9;
    cursor: default;
    color: #2a3038;
}

/* A bare tap target for folding the group -- no background or border of its own, so it reads as
   part of the header rather than another control competing with it. */
.fp-group-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.1rem;
    height: 1.1rem;
    padding: 0;
    margin: 0;
    background: none;
    border: none;
    cursor: pointer;
    border-radius: 2px;
}

.fp-group-toggle:hover { background: rgba(0, 0, 0, .06); }

.fp-group-chevron {
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid #68707c;
    transition: transform .12s ease;
}

.fp-group-chevron--closed { transform: rotate(-90deg); }

.fp-group-name { flex: 0 1 auto; }

/* Names the container's type, so 'Diagnostic Medicine' is visibly an area rather than a room. */
.fp-group-kind {
    font-size: .62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .4px;
    color: #68707c;
    background: #eceff3;
    border-radius: 2px;
    padding: 0 .25rem;
}

.fp-group-head .fp-count { margin-left: auto; }

/* The indent is what makes the list read as a hierarchy rather than a flat run of rows with the
   occasional bold one. */
.fp-group-items { padding-left: .55rem; border-left: 2px solid #eef0f3; margin-left: .15rem; }

/* While an area is being picked for a pin, the rooms stay visible as CONTEXT -- that is the whole
   point of picking in the tree -- but must not look selectable. */
.fp-group-items--muted { opacity: .55; }
.fp-row--inert { cursor: default; }
.fp-row--inert:hover { background: none; }

/* The heading becomes the click target only in pick mode. */
.fp-group-head--pickable { cursor: pointer; border-radius: 3px; padding: .25rem .3rem; }
.fp-group-head--pickable:hover { background: #eaf1fd; box-shadow: inset 0 0 0 1px #9dbcf0; }

.fp-group-pick {
    font-size: .62rem;
    font-weight: 700;
    color: #2f6bd8;
    border: 1px solid #9dbcf0;
    border-radius: 2px;
    padding: 0 .25rem;
}

.fp-group--pickable { background: #fbfcfe; border-radius: 3px; }

.fp-panel-sub--prompt { color: #7a5514; font-weight: 600; }

.fp-subhead {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .4px;
    color: #68707c;
    font-weight: 700;
    margin: .9rem 0 .2rem;
}

.fp-panel-hint { font-size: .7rem; color: #7a8290; margin: 0 0 .45rem; line-height: 1.35; }

/* A lift stop checkbox row. */
.fp-stop {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding: .2rem .1rem;
    font-size: .76rem;
    cursor: pointer;
    border-radius: 3px;
}

.fp-stop:hover { background: #f2f5f9; }
.fp-stop-name { flex: 1; }

.fp-count { font-size: .68rem; font-weight: 700; }
.fp-count--done { color: #2e9e5b; }
.fp-count--part { color: #b4610f; }

.fp-row {
    display: flex;
    align-items: center;
    padding: .22rem .35rem;
    font-size: .76rem;
    border-radius: 3px;
    cursor: pointer;
}

.fp-row:hover { background: #eaf1fd; }
.fp-row--placed { color: #68707c; }
.fp-row--unplaced { font-weight: 500; }

/* The status marker beside each room. This is the "bullet point" -- it was invisible before,
   because these styles were scoped to a component that does not render them. */
.fp-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    min-width: 7px;
    border-radius: 50%;
    margin-right: .4rem;
    background: #fff;
    border: 1px solid #b6bcc6;
}

.fp-dot--ok { background: #2e9e5b; border-color: #2e9e5b; }

/* ---- Inspector ---- */

.fp-row-kv {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    padding: .2rem 0;
    border-bottom: 1px solid #eef0f3;
    font-size: .76rem;
}

.fp-row-kv > span { color: #68707c; }
.fp-warn { color: #b4610f; }

/* ---- Issues ---- */

.fp-issue {
    border-radius: 3px;
    padding: .3rem .4rem;
    margin-top: .3rem;
    font-size: .72rem;
    display: flex;
    flex-direction: column;
    gap: .1rem;
}

.fp-issue--error { background: #fdeaea; border: 1px solid #eaa8a8; color: #8f2020; }
.fp-issue--warning { background: #fdf3e3; border: 1px solid #e8c98d; color: #7a5514; }

/* ---- Canvas overlays ---- */

.fp-empty {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    color: #4a5261;
    text-align: left;
}

.fp-empty h4 { margin: 0 0 .5rem; font-size: .95rem; }

.fp-empty ol {
    margin: 0;
    padding-left: 1.4rem;
    font-size: .82rem;
    line-height: 1.7;
    max-width: 32rem;
    list-style: decimal outside;
}

.fp-empty-hint { margin-top: .75rem; font-size: .78rem; color: #68707c; }


.fp-hud {
    position: absolute;
    left: .5rem;
    bottom: .5rem;
    background: rgba(255, 255, 255, .92);
    border: 1px solid #c9ced6;
    border-radius: 3px;
    padding: .2rem .5rem;
    font-size: .75rem;
    color: #3a4048;
    pointer-events: none;
}

/* Below lg the side panels stack under the canvas rather than squeezing it out of usefulness. */
@media (max-width: 1200px) {
    .fp-body { flex-direction: column; }

    .fp-worklist,
    .fp-inspector {
        width: auto;
        max-height: 14rem;
        border: none;
        border-top: 1px solid #c9ced6;
    }

    .fp-rail { width: auto; flex-direction: row; border-right: none; border-bottom: 1px solid #c9ced6; }
    .fp-canvas-host { min-height: 24rem; }
}

/* Underlay panel: uploading and placing the scan being traced over. */
.fp-underlay {
    border-top: 1px solid var(--gvs-neutral-200, #e3e6ea);
    padding-top: 12px;
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.fp-underlay-h {
    font-weight: 600;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gvs-neutral-600, #5b6672);
}

.fp-underlay-drop {
    display: block;
    border: 1px dashed var(--gvs-neutral-300, #c9cfd6);
    border-radius: 6px;
    padding: 14px 10px;
    text-align: center;
    cursor: pointer;
}

.fp-underlay-drop:hover {
    border-color: var(--gvs-primary-500, #2b6cb0);
}

.fp-underlay-drop-t {
    font-weight: 600;
}

.fp-underlay-drop-s {
    font-size: 0.78rem;
    color: var(--gvs-neutral-600, #5b6672);
}

.fp-underlay-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.82rem;
}

.fp-underlay-row input[type="range"] {
    flex: 1 1 auto;
    min-width: 0;
}

.fp-underlay-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* Loud on purpose: drawing over an uncalibrated underlay produces rooms of the wrong size, and
   nothing else on screen would reveal that until someone measured one. */
.fp-underlay-warn {
    background: var(--gvs-warning-50, #fff8e1);
    color: var(--gvs-warning-800, #7a5300);
    border-left: 3px solid var(--gvs-warning-500, #d99e00);
    padding: 8px 10px;
    font-size: 0.8rem;
    border-radius: 4px;
}

.fp-underlay-err {
    background: var(--gvs-danger-50, #fdecec);
    color: var(--gvs-danger-700, #a12622);
    padding: 8px 10px;
    font-size: 0.8rem;
    border-radius: 4px;
}

.fp-underlay-busy {
    font-size: 0.8rem;
    color: var(--gvs-neutral-600, #5b6672);
}

/* Floats over the canvas while the two calibration clicks are turned into a distance. */
.fp-calibrate {
    position: absolute;
    left: 50%;
    top: 16px;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--gvs-surface, #fff);
    border: 1px solid var(--gvs-neutral-300, #c9cfd6);
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(16, 24, 40, 0.12);
    padding: 10px 12px;
    z-index: 5;
}

.fp-calibrate input {
    width: 90px;
    margin-left: 6px;
}

@media (max-width: 720px) {
    .fp-calibrate {
        left: 8px;
        right: 8px;
        transform: none;
        flex-wrap: wrap;
    }
}

/* The loading message, over the plan area rather than replacing it: the toolbar and the rail stay
   usable and in place, so the page does not jump when the plan arrives. Pointer events pass
   through everywhere except the card itself, which is why this is not a modal -- nothing here
   needs dismissing, and a scrim over a plan that is about to appear reads as an error dialog. */
.fp-loading {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 5;
}

.fp-loading__card {
    display: flex;
    align-items: center;
    gap: .55rem;
    flex-wrap: wrap;
    justify-content: center;
    max-width: 22rem;
    padding: .6rem .9rem;
    border: 1px solid #c9ced6;
    border-radius: 4px;
    background: rgba(255, 255, 255, .94);
    box-shadow: 0 1px 6px rgba(20, 30, 45, .12);
    pointer-events: auto;
}

.fp-loading__spinner { font-size: 1.15rem; color: #2f6bd8; }
.fp-loading__text { font-size: .85rem; color: #1c2024; }

/* The second line takes the whole width, so a named detail sits under the message rather than
   pushing it off-centre. */
.fp-loading__detail { flex-basis: 100%; text-align: center; font-size: .75rem; color: #5b636e; }

/* The plan manager. A real scrim and a real modal, unlike .fp-loading above: this one asks a
   question that cannot be undone, and the canvas behind it must not take a stray click while the
   answer is a red button away. */
.fp-plans {
    /* Fixed, not absolute: .fp-editor is an unpositioned flex column, so an absolute overlay would
       resolve against whatever ancestor happened to be positioned. A modal should not depend on
       that. */
    position: fixed;
    inset: 0;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 3rem 1rem 1rem;
    background: rgba(16, 24, 40, 0.35);
    z-index: 20;
}

.fp-plans__card {
    width: min(46rem, 100%);
    max-height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--gvs-surface, #fff);
    border: 1px solid var(--gvs-neutral-300, #c9cfd6);
    border-radius: 6px;
    box-shadow: 0 8px 28px rgba(16, 24, 40, 0.22);
}

.fp-plans__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .7rem .9rem;
    border-bottom: 1px solid #e3e7ec;
}

.fp-plans__head h4 { margin: 0; font-size: .95rem; }

.fp-plans__error { margin: 0; padding: .5rem .9rem; background: #fdeaea; color: #8f2020; font-size: .8rem; }

.fp-plans__empty { margin: 0; padding: 1.25rem .9rem; font-size: .82rem; color: #68707c; text-align: center; }

.fp-plans__list { overflow-y: auto; }

.fp-plan-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: .75rem;
    flex-wrap: wrap;
    padding: .6rem .9rem;
    border-bottom: 1px solid #eef1f4;
    font-size: .82rem;
}

.fp-plan-row:last-child { border-bottom: none; }

/* A plan nothing can open. Marked on the row itself rather than sorted into its own section: these
   sit next to the building's working plans, and which building they were drawn for is the thing
   somebody needs to recognise before deleting one. */
.fp-plan-row--orphaned { background: #fdf6e7; }

.fp-plan-row__main { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; min-width: 12rem; }

.fp-plan-row__name { font-weight: 600; color: #1c2024; }

.fp-plan-row__badge {
    padding: .05rem .35rem;
    border-radius: 3px;
    background: #2f6bd8;
    color: #fff;
    font-size: .68rem;
    font-weight: 600;
}

.fp-plan-row__status { font-size: .72rem; color: #5b636e; text-transform: uppercase; letter-spacing: .02em; }

.fp-plan-row__meta { display: flex; flex-direction: column; gap: .15rem; color: #68707c; font-size: .76rem; }

.fp-plan-row__missing { color: #8a6116; font-weight: 600; }

.fp-plan-row__date { font-variant-numeric: tabular-nums; }

.fp-plan-row__actions { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-left: auto; }

/* Takes the full row width so the warning is read rather than clipped beside the button it is
   warning about. */
.fp-plan-row__warning { flex-basis: 100%; margin: 0 0 .3rem; font-size: .76rem; color: #8f2020; }

.fp-plan-row__busy { font-size: .76rem; color: #5b636e; }

@media (max-width: 720px) {
    .fp-plans { padding: 1rem .5rem; }

    .fp-plan-row__actions { margin-left: 0; }
}
