/* ==========================================================================
   Commercial Units — Interactive Floor Plan

   Copyright © 2026 Ali Salih. All rights reserved.
   SPDX-License-Identifier: LicenseRef-AliSalih-Proprietary-1.0

   PROPRIETARY AND CONFIDENTIAL. Licensed, not sold.
   Licensed for use on the client's own website only, under the terms of the
   Software License Agreement supplied with this file (LICENSE.txt).

   Unauthorised copying, modification, distribution or use of this file, by
   any means, is prohibited and is an infringement of copyright. This notice
   forms part of that licence and must not be removed or altered.

   Ali Salih · https://github.com/AliSalih-ops
   ========================================================================== */

/* ==========================================================================
   Interactive floor plan — all rules scoped to .fp so the component can be
   dropped into a larger site without collisions.
   ========================================================================== */

/* page-level reset (harmless when the component is embedded elsewhere) */

.fp {
  /* light grey, orange and white */
  --fp-bg:        #f4f4f4;
  --fp-surface:   #ffffff;
  --fp-ink:       #1b1b1b;
  --fp-ink-soft:  #6a6a6a;
  --fp-ink-faint: #9b9b9b;
  --fp-line:      #e6e6e6;
  --fp-line-firm: #d2d2d2;

  /* plan hierarchy: structure reads, units are the white figure on top */
  --fp-plate:     #ebebeb;
  --fp-plate-edge:#dadada;
  --fp-common:    #ebebeb;
  --fp-terrace:   #f2f2f2;
  --fp-terrace-edge: #c9c9c9;
  --fp-core:      #e2e2e2;
  --fp-structure: #d3d3d3;
  --fp-structure-edge: #c4c4c4;
  --fp-unit:      #ffffff;
  --fp-unit-edge: #cccccc;
  --fp-street:      #ededed;
  --fp-street-edge: #dedede;

  /* leasing availability — the only semantic colour in the component */
  --fp-free:  #15803d;
  --fp-held:  #b45309;
  --fp-taken: #8a8a8a;

  /* an occupied unit on the plan. Built to sit in the same family as the unit
     colours it replaces — same lightness, red hue — so the plan still reads as
     one drawing rather than one unit shouting. */
  --fp-occ:      #fbe4e6;   /* rest fill  */
  --fp-occ-edge: #d98d97;   /* rest edge  */
  --fp-occ-soft: #f7d2d6;   /* hover fill */
  --fp-occ-solid:#c0304a;   /* selected   */
  --fp-occ-ink:  #a02338;   /* the code, on the rest fill */

  --fp-accent:    #f97316;   /* bright orange */
  --fp-accent-sf: #fdebdc;   /* hover tint */
  --fp-accent-dp: #b8480b;   /* orange text */

  --fp-shadow:    #6b3a15;
  --fp-plate-shadow: rgb(20 30 28 / .16);
  --fp-radius:    14px;
  --fp-ease:      cubic-bezier(.22, .61, .36, 1);

  box-sizing: border-box;
  /* the unavailable notice covers the component, so anchor it here rather than
     letting it escape to the page */
  position: relative;
  display: flex;
  flex-direction: column;
  /* a definite height, so the panel scrolls internally instead of stretching
     the page. Override this when embedding in a taller host layout. */
  /*height: 100vh;*/
  /*height: 100svh;*/
  margin: 0;
  background: var(--fp-bg);
  color: var(--fp-ink);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto,
               "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* Two palettes, one stylesheet. Dark is what ships: index.html carries
   data-theme="dark" on the mount point. The light scale below stays as the base, so
   data-theme="light" (or no attribute at all) falls back to it. Never keyed to
   prefers-color-scheme — which palette a client sees is the sender's decision, not
   their OS setting.

   The dark scale is built on the client's #010114 (hsl 240 90% 4%), holding that hue
   the whole way up so the greys stay navy rather than drifting to slate. The light
   plan reads as a white figure on grey ground; the dark one keeps that relationship
   by luminance, not by colour — units stay the lightest thing on the plate, and
   orange stays the only saturated colour so it still means "selected". */
.fp[data-theme="dark"] {
  --fp-bg:        #010114;   /* the client's navy */
  --fp-surface:   #0a0a1e;
  --fp-ink:       #f2f3f8;
  --fp-ink-soft:  #a8abbd;
  --fp-ink-faint: #6e7186;
  --fp-line:      #1b1c33;
  --fp-line-firm: #2a2c46;

  --fp-plate:     #0e0f22;
  --fp-plate-edge:#23253f;
  --fp-common:    #0e0f22;
  --fp-terrace:   #14162c;
  --fp-terrace-edge: #2e3050;
  --fp-core:      #191b33;
  --fp-structure: #262943;
  --fp-structure-edge: #343757;
  --fp-unit:      #1d1f3a;   /* the figure: lightest thing on the plan */
  --fp-unit-edge: #3a3d5e;

  --fp-accent:    #f97316;
  --fp-accent-sf: #3a2312;   /* hover tint, warmed rather than paled */
  --fp-accent-dp: #fb923c;   /* orange text, lifted to hold contrast on navy */

  --fp-shadow:    #00000a;
  --fp-plate-shadow: rgb(0 0 0 / .55);

  --fp-street:      #0c0d20;
  --fp-street-edge: #22243c;

  --fp-free:  #4ade80;
  --fp-held:  #fbbf24;
  --fp-taken: #8a8ea3;

  /* Red at the navy's own lightness, so an occupied unit sits in the plan
     rather than burning a hole in it. The hue is held the whole way up, the
     same way the greys are, which is what keeps it looking like this theme's
     red and not a warning sticker. */
  --fp-occ:      #3a1522;
  --fp-occ-edge: #7e2c40;
  --fp-occ-soft: #4e1b2c;
  --fp-occ-solid:#b3273f;
  --fp-occ-ink:  #f0a2b0;
}

/* the pill is orange in both themes, so its label stays white in both */
.fp[data-theme="dark"] .fp__floor[aria-selected="true"] { color: #ffffff; }

/* the two light-on-light warnings would burn a hole in a dark panel */
.fp[data-theme="dark"] .fp-form__status.is-bad {
  background: #2a1216;
  color: #ff9a9a;
  border-color: #4d2027;
}
.fp[data-theme="dark"] .fp-field__err { color: #ff9a9a; }
.fp[data-theme="dark"] .fp-form input.is-bad,
.fp[data-theme="dark"] .fp-form textarea.is-bad { border-color: #b3555a; }

.fp *,
.fp *::before,
.fp *::after { box-sizing: inherit; }

/* ---------- top bar ---------- */

/* The bar holds only the floor switcher, centred. It takes the page colour and
   drops its rule, so the top of the component is one continuous surface instead
   of a lighter band above the plan. */
.fp__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px clamp(16px, 3vw, 34px);
  background: var(--fp-bg);
}

/* segmented floor switcher with a sliding indicator */
.fp__floors {
  position: relative;
  display: flex;
  gap: 2px;
  padding: 4px;
  border-radius: 999px;
  /* lifted off the bar rather than matching it, now that the bar is page colour */
  background: var(--fp-surface);
  border: 1px solid var(--fp-line);
}

.fp__floors-ink {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 0;                 /* anchor it, or a centred flex parent shifts it */
  border-radius: 999px;
  background: var(--fp-accent);
  transition: transform .42s var(--fp-ease), width .42s var(--fp-ease);
  pointer-events: none;
}

.fp__floor {
  position: relative;
  z-index: 1;
  appearance: none;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 8px 18px;
  border-radius: 999px;
  font: inherit;
  font-size: 1.66rem;
  font-weight: 500;
  color: var(--fp-ink-soft);
  white-space: nowrap;
  transition: color .3s var(--fp-ease);
}

.fp__floor[aria-selected="true"] { color: var(--fp-surface); }
.fp__floor:focus-visible { outline: 2px solid var(--fp-accent); outline-offset: 3px; }

/* ---------- stage ---------- */

.fp__stage {
  position: relative;
  flex: 1;
  display: flex;
  min-height: 0;
  overflow: hidden;          /* keeps the off-canvas panel from creating scrollbars */
}

.fp__canvas {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  overflow: hidden;
  touch-action: none;

  padding-block-end: 5rem;
}

.fp__svg {
  width: 100%;
  height: 100%;
  display: block;
  cursor: grab;

  margin-block-start: 10rem;
}
.fp__svg.is-panning { cursor: grabbing; }

/* ---------- plan geometry ---------- */

.fp-floor { opacity: 0; visibility: hidden; transition: opacity .34s var(--fp-ease); }
.fp-floor.is-active { opacity: 1; visibility: visible; }
/* belt and braces with visibleFill above: nothing on a floor you cannot see should
   ever take a pointer event, whatever a descendant asks for */
.fp-floor:not(.is-active) { pointer-events: none; }

.fp-plate {
  fill: var(--fp-plate);
  stroke: var(--fp-plate-edge);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 18px 30px var(--fp-plate-shadow));
}

.fp-common {
  fill: var(--fp-common);
  stroke: none;
}

/* outdoor terraces, named on the drawing but not lettable units */
.fp-common--terrace {
  fill: var(--fp-terrace);
  stroke: var(--fp-common);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* vertical circulation — worth reading distinctly from ordinary corridor */
.fp-common--core { fill: var(--fp-core); }

/* ---------- streets ----------
   Reference only. Kept deliberately quiet — they frame the plan without competing
   with it, and they stay grey so orange keeps meaning "selected" and nothing else.
   Sized in plan units, so they hold their proportions at any embed size. */

.fp-streets { pointer-events: none; }

.fp-street__band {
  fill: var(--fp-street);
  stroke: var(--fp-street-edge);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.fp-street__name {
  text-anchor: middle;
  dominant-baseline: central;
  font-size: 250px;
  font-weight: 600;
  /* the tracking is what makes these read as signage rather than as a label */
  letter-spacing: 0.22em;
  text-transform: uppercase;
  /* the same ink as a unit code: a street name is a label, not a whisper — but the
     band stays grey so orange keeps meaning "selected" */
  fill: var(--fp-ink-soft);
}

/* ---------- terraces ----------
   Outdoor space attached to a unit. Its area is deliberately NOT folded into the
   unit's own area; the two are only added up in the detail panel. */

.fp-terrace { cursor: pointer; transition: opacity .34s var(--fp-ease); }

/* The art lifts; the hit target underneath it does not. pointer-events:fill hits
   the geometry whether or not it is painted, so the target stays invisible. */
/* visibleFill, NOT fill: the bare `fill` value hit-tests regardless of visibility,
   so the hidden floor's targets stayed live and — being drawn after Ground — swallowed
   every pointer event on it. visibleFill still hits the geometry with fill:none, but
   honours the visibility:hidden on an inactive floor. */
.fp-terrace__hit { fill: none; stroke: none; pointer-events: visibleFill; }
.fp-terrace__lift {
  pointer-events: none;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform .34s var(--fp-ease), filter .34s var(--fp-ease);
}
.fp-terrace--unlinked { cursor: default; }
/* © 2026 Ali Salih · https://github.com/AliSalih-ops · all rights reserved */

.fp-terrace__shape {
  fill: var(--fp-terrace);
  stroke: var(--fp-terrace-edge);
  stroke-width: 1.4;
  stroke-dasharray: 34 20;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: fill .28s var(--fp-ease), stroke .28s var(--fp-ease);
}

/* rises and warms with the unit it serves */
.fp-terrace.is-linked .fp-terrace__lift,
.fp-terrace.is-selected .fp-terrace__lift { transform: translateY(-95px); filter: none; }
.fp-terrace.is-linked .fp-terrace__shape {
  fill: var(--fp-accent-sf);
  stroke: var(--fp-accent);
}
.fp-terrace.is-selected .fp-terrace__lift { transform: translateY(-125px); }
.fp-terrace.is-selected .fp-terrace__shape {
  fill: var(--fp-accent);
  stroke: var(--fp-accent-dp);
  fill-opacity: .55;
}
.fp-terrace:focus-visible { outline: none; }
.fp-terrace:focus-visible .fp-terrace__shape { stroke: var(--fp-accent); stroke-width: 3; }

.fp-floor.has-selection .fp-terrace:not(.is-selected) { opacity: .55; }

/* Hover styling lives on .is-linked (set from JS on both the unit and its
   terraces) rather than :hover. The hovered unit is reparented into the
   .fp-raised group so its whole outline paints above its neighbours, and a
   :hover rule would apply mid-move and snap the lift transition. */
.fp-unit.is-linked .fp-unit__lift { transform: translateY(-95px); filter: none; }
.fp-unit.is-linked .fp-unit__shape {
  fill: var(--fp-accent-sf);
  stroke: var(--fp-accent);
  stroke-width: 2.4;
}
.fp-unit.is-linked .fp-unit__code { fill: var(--fp-accent-dp); }

/* wall, column and core mass */
.fp-structure {
  fill: var(--fp-structure);
  stroke: var(--fp-structure-edge);
  stroke-width: 0.8;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

/* columns that stand inside a unit are part of that unit's group, so they
   lift, dim and stay visible together with it */
.fp-unit__structure {
  fill: var(--fp-structure);
  stroke: var(--fp-structure-edge);
  stroke-width: 0.8;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.fp-unit { cursor: pointer; }

/* The art lifts; the hit target underneath it does not — see fp-terrace__hit. */
.fp-unit__hit { fill: none; stroke: none; pointer-events: visibleFill; }
.fp-unit__lift {
  pointer-events: none;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform .34s var(--fp-ease), filter .34s var(--fp-ease);
  will-change: transform;
}

.fp-unit__shape {
  fill: var(--fp-unit);
  stroke: var(--fp-unit-edge);
  stroke-width: 1.6;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: fill .28s var(--fp-ease), stroke .28s var(--fp-ease),
              stroke-width .28s var(--fp-ease);
}

.fp-unit__code,
.fp-unit__area {
  pointer-events: none;
  text-anchor: middle;
  font-weight: 600;
  fill: var(--fp-ink-soft);
  transition: fill .28s var(--fp-ease);
}
.fp-unit__code { font-size: 190px; letter-spacing: -0.01em; }
.fp-unit__area {
  font-size: 150px;
  font-weight: 500;
  fill: var(--fp-ink-faint);
  font-variant-numeric: tabular-nums;
}

/* ================================================================
   FIX for Chrome click artifact: remove default focus ring and only
   apply focus-visible styles when not selected or linked.
   ================================================================ */
.fp-unit:focus,
.fp-terrace:focus {
  outline: none;
}
.fp-unit:focus-visible:not(.is-selected):not(.is-linked) .fp-unit__lift {
  transform: translateY(-95px);
  filter: none;
}
.fp-unit:focus-visible:not(.is-selected):not(.is-linked) .fp-unit__shape {
  fill: var(--fp-accent-sf);
  stroke: var(--fp-accent);
  stroke-width: 3;
  stroke-dasharray: 26 14;
}
.fp-terrace:focus-visible:not(.is-selected):not(.is-linked) .fp-terrace__shape {
  fill: var(--fp-accent-sf);
  stroke: var(--fp-accent);
  stroke-width: 3;
}
.fp-unit,
.fp-terrace {
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
/* End of fix */

/* selected — goes solid bright orange */
.fp-unit.is-selected .fp-unit__lift { transform: translateY(-125px); filter: url(#fp-lift); }
.fp-unit.is-selected .fp-unit__shape {
  fill: var(--fp-accent);
  stroke: var(--fp-accent-dp);
  stroke-width: 3;
}
.fp-unit.is-selected .fp-unit__code { fill: #ffffff; }
.fp-unit.is-selected .fp-unit__area { fill: rgb(255 255 255 / .85); }

/* ---------- occupied ----------
   A unit that is already let reads red on the plan, in every state. Orange keeps
   meaning "you are looking at this one", so an occupied unit that is hovered or
   selected goes a deeper red rather than borrowing the accent. Each selector
   carries the status attribute as well as the state class, so it outranks the
   generic rule above whatever the source order. */

.fp-unit[data-status="occupied"] .fp-unit__shape {
  fill: var(--fp-occ);
  stroke: var(--fp-occ-edge);
}
.fp-unit[data-status="occupied"] .fp-unit__code { fill: var(--fp-occ-ink); }

.fp-unit[data-status="occupied"].is-linked .fp-unit__shape,
.fp-unit[data-status="occupied"]:focus-visible .fp-unit__shape {
  fill: var(--fp-occ-soft);
  stroke: var(--fp-occ-edge);
}
.fp-unit[data-status="occupied"].is-linked .fp-unit__code { fill: var(--fp-occ-ink); }

.fp-unit[data-status="occupied"].is-selected .fp-unit__shape {
  fill: var(--fp-occ-solid);
  stroke: var(--fp-occ-solid);
}
.fp-unit[data-status="occupied"].is-selected .fp-unit__code { fill: #ffffff; }

/* its terrace goes with it, or the pair stops reading as one unit */
.fp-terrace[data-status="occupied"] .fp-terrace__shape {
  fill: var(--fp-occ);
  stroke: var(--fp-occ-edge);
}
.fp-terrace[data-status="occupied"].is-linked .fp-terrace__shape {
  fill: var(--fp-occ-soft);
  stroke: var(--fp-occ-edge);
}
.fp-terrace[data-status="occupied"].is-selected .fp-terrace__shape {
  fill: var(--fp-occ-solid);
  stroke: var(--fp-occ-solid);
  fill-opacity: .55;
}

/* everything else recedes while a unit is selected — but a unit being hovered
   at the same time comes back to full strength, so it can still be compared */
.fp-floor.has-selection .fp-unit:not(.is-selected) { opacity: .55; }
.fp-floor.has-selection .fp-unit.is-linked:not(.is-selected),
.fp-floor.has-selection .fp-terrace.is-linked:not(.is-selected) { opacity: 1; }
.fp-unit { transition: opacity .34s var(--fp-ease); }

/* ---------- floating controls ---------- */

/* Sits over the plan, top left. Same quiet chrome as the reset control so it reads
   as a map affordance rather than a page button. */
.fp__full {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 3;
  appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 21px 12px 17px;
  border-radius: 999px;
  border: 1px solid var(--fp-line);
  background: var(--fp-surface);
  /* orange label — the icon takes currentColor, so the two read as one control */
  color: var(--fp-accent);
  font: inherit;
  font-size: 1.9rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgb(0 0 0 / .10);
  transition: color .22s var(--fp-ease), border-color .22s var(--fp-ease),
              background .22s var(--fp-ease);
}
.fp__full:hover { color: var(--fp-accent-dp); border-color: var(--fp-accent); }
.fp__full:focus-visible { outline: 2px solid var(--fp-accent); outline-offset: 3px; }
.fp__full svg {
  width: 19px; height: 19px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
/* one icon at a time: enter while windowed, exit while full screen */
.fp__full .fp__full-out { display: none; }
.fp__full[aria-pressed="true"] .fp__full-in  { display: none; }
.fp__full[aria-pressed="true"] .fp__full-out { display: block; }
/* no API, or blocked by the embedding page — then there is nothing to offer */
.fp__full[hidden] { display: none; }

.fp__reset {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 18px;
}

.fp__reset {
  appearance: none;
  cursor: pointer;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--fp-line);
  background: var(--fp-surface);
  color: var(--fp-ink-soft);
  font: inherit;
  font-size: 1.56rem;
  box-shadow: 0 6px 20px rgb(0 0 0 / .08);
}
.fp__reset:hover { color: var(--fp-ink); border-color: var(--fp-line-firm); }


/* ---------- detail panel ---------- */

.fp__panel {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  width: min(400px, 34vw);
  min-height: 0;
  border-left: 1px solid var(--fp-line);
  background: var(--fp-surface);
  /* The panel itself never scrolls — it only clips. The application form is parked a
     full panel-width to the right (translateX(100%)) and a transform still counts
     toward scrollable overflow, so a scrolling panel could be dragged sideways into
     empty space. Scrolling belongs to the body inside it instead; that also pins the
     close button, which used to scroll away with the content.
     `clip` and not `hidden`: hidden would still make this a scroll port, so the
     parked form kept the panel programmatically scrollable sideways. clip on both
     axes creates no scroll container at all. (It only computes to hidden when the
     other axis scrolls — which is exactly why this had to move off the panel.) */
  overflow: clip;
  margin-right: calc(-1 * min(400px, 34vw));
  opacity: 0;
  visibility: hidden;
  transition: margin-right .46s var(--fp-ease), opacity .32s var(--fp-ease),
              visibility .46s;
}

.fp[data-panel="open"] .fp__panel {
  margin-right: 0;
  opacity: 1;
  visibility: visible;
}

.fp__close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  appearance: none;
  cursor: pointer;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--fp-line);
  background: var(--fp-surface);
  color: var(--fp-ink-soft);
}
.fp__close svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.fp__close:hover { color: var(--fp-ink); border-color: var(--fp-line-firm); }

.fp__panel-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 26px clamp(20px, 2.4vw, 30px) 30px;
}

/* staged entrance for the panel contents */
.fp-reveal > * {
  opacity: 0;
  transform: translateY(9px);
  animation: fp-in .44s var(--fp-ease) forwards;
}
.fp-reveal > *:nth-child(1) { animation-delay: .04s; }
.fp-reveal > *:nth-child(2) { animation-delay: .09s; }
.fp-reveal > *:nth-child(3) { animation-delay: .14s; }
.fp-reveal > *:nth-child(4) { animation-delay: .19s; }
.fp-reveal > *:nth-child(5) { animation-delay: .24s; }
.fp-reveal > *:nth-child(6) { animation-delay: .29s; }
.fp-reveal > *:nth-child(7) { animation-delay: .34s; }
.fp-reveal > *:nth-child(8) { animation-delay: .39s; }
/* © 2026 Ali Salih · https://github.com/AliSalih-ops · all rights reserved */

@keyframes fp-in { to { opacity: 1; transform: none; } }

/* The identity block reads as a title page for the unit, so it is centred on the
   same axis as the headline figure below it rather than ragged left. */
.fp-ident { text-align: center; }

.fp-eyebrow {
  margin: 0 0 6px;
  font-size: 1.4rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--fp-accent);
}

.fp-code {
  margin: 0;
  font-size: 3.9rem;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.1;
}

.fp-tenant {
  margin: 5px 0 0;
  font-size: 1.9rem;
  color: var(--fp-ink-soft);
}

/* centred to stay on the identity block's axis */
.fp-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 7px;
  margin: 13px 0 0;
}

.fp-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--fp-line);
  background: var(--fp-bg);
  font-size: 1.51rem;
  color: var(--fp-ink-soft);
}
.fp-chip--accent {
  border-color: transparent;
  background: var(--fp-accent-sf);
  color: var(--fp-accent-dp);
  font-weight: 600;
}
.fp-chip--warn { border-style: dashed; }

/* The headline figure carries the panel — no box around it, just the number.
   Centred, the label quiet and black above it, the value the one loud thing. */
.fp-figure {
  margin: 24px 0 4px;
  padding: 0;
  text-align: center;
}
.fp-figure__label {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--fp-ink);
}
.fp-figure__value {
  margin: 10px 0 0;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 9px;
  color: var(--fp-accent);
  font-size: clamp(5.8rem, 3.1vw + 3.8rem, 7.5rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.045em;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "ss01", "cv01";   /* flat-topped 1 where the face has it */
}
.fp-figure__unit {
  font-size: 0.3em;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.fp-figure__value--none {
  font-size: 2.8rem;
  font-weight: 500;
  color: var(--fp-ink-faint);
  font-style: italic;
}

.fp-section { margin: 21px 0 0; }
.fp-section__title {
  margin: 0 0 10px;
  font-size: 1.46rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fp-ink-faint);
}

.fp-rows { display: grid; gap: 1px; background: var(--fp-line); border-radius: 10px; overflow: hidden; }
.fp-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 14px;
  background: var(--fp-surface);
  font-size: 1.71rem;
}
.fp-row__k { color: var(--fp-ink-soft); }
.fp-row__v { font-weight: 550; text-align: right; font-variant-numeric: tabular-nums; }
/* rent carries the section, so it is set heavier than an ordinary value */
.fp-row__v--strong { font-size: 2.1rem; font-weight: 700; }
.fp-row__k--strong { font-weight: 700; color: var(--fp-ink); }

/* availability reads at a glance, so it gets a dot and the one semantic colour
   in the component; everything else stays grey so orange keeps its meaning */
.fp-avail { font-weight: 600; display: inline-flex; align-items: center; gap: 7px; }
.fp-avail::before {
  content: "";
  width: 8px; height: 8px; border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}
.fp-avail--available { color: var(--fp-free); }
.fp-avail--reserved  { color: var(--fp-held); }
.fp-avail--occupied  { color: var(--fp-taken); }

/* ---------- occupied: the whole panel ----------
   An occupied unit's panel is its identity and this, nothing else. */

.fp-taken {
  margin: 26px 0 0;
  display: grid;
  justify-items: center;
  gap: 8px;
  padding: 30px 24px;
  border-radius: var(--fp-radius);
  background: var(--fp-bg);
  border: 1px solid var(--fp-line);
  text-align: center;
}
.fp-taken__mark {
  color: var(--fp-occ-solid);
  margin-bottom: 4px;
}
.fp-taken__mark svg {
  width: 40px; height: 40px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round;
}
.fp-taken__title {
  margin: 0;
  font-size: 2.2rem;
  font-weight: 650;
  letter-spacing: -0.015em;
}
.fp-taken__body {
  margin: 0;
  font-size: 1.7rem;
  line-height: 1.6;
  color: var(--fp-ink-soft);
}

/* ---------- unavailable notice ----------
   Shown instead of the application form when a unit is reserved or occupied. */

.fp-notice {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  padding: 24px;
}
.fp-notice[hidden] { display: none; }

.fp-notice__scrim {
  position: absolute;
  inset: 0;
  background: rgb(15 15 20 / .38);
  opacity: 0;
  transition: opacity .26s var(--fp-ease);
}
.fp-notice.is-open .fp-notice__scrim { opacity: 1; }

.fp-notice__box {
  position: relative;
  width: min(360px, 100%);
  padding: 26px 26px 22px;
  border-radius: var(--fp-radius);
  background: var(--fp-surface);
  border: 1px solid var(--fp-line);
  box-shadow: 0 24px 60px rgb(0 0 0 / .22);
  text-align: center;
  opacity: 0;
  transform: translateY(10px) scale(.97);
  transition: opacity .26s var(--fp-ease), transform .26s var(--fp-ease);
}
.fp-notice.is-open .fp-notice__box { opacity: 1; transform: none; }
.fp-notice__box:focus-visible { outline: 2px solid var(--fp-accent); outline-offset: 3px; }

.fp-notice__mark { color: var(--fp-held); margin-bottom: 12px; }
.fp-notice[data-state="occupied"] .fp-notice__mark { color: var(--fp-taken); }
.fp-notice__mark svg {
  width: 42px; height: 42px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round;
}
.fp-notice__mark circle:last-of-type { fill: currentColor; stroke: none; }

.fp-notice__title {
  margin: 0 0 8px;
  font-size: 2.32rem;
  font-weight: 600;
  letter-spacing: -0.015em;
}
.fp-notice__body {
  margin: 0 0 20px;
  font-size: 1.75rem;
  line-height: 1.55;
  color: var(--fp-ink-soft);
}
.fp-notice__ok {
  appearance: none;
  cursor: pointer;
  border: 0;
  border-radius: 10px;
  padding: 11px 22px;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--fp-accent);
  transition: background .2s var(--fp-ease);
}
.fp-notice__ok:hover { background: #ea6a0c; }
.fp-notice__ok:focus-visible { outline: 2px solid var(--fp-accent); outline-offset: 3px; }

.fp-row__v--none { color: var(--fp-ink-faint); font-weight: 400; font-style: italic; }

.fp-note {
  margin: 12px 0 0;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px dashed var(--fp-line-firm);
  font-size: 1.58rem;
  line-height: 1.5;
  color: var(--fp-ink-soft);
  text-align: left;          /* the figure centres its children */
}

.fp-source {
  margin: 22px 0 0;
  font-size: 1.58rem;
  color: var(--fp-ink-faint);
}
.fp-source summary { cursor: pointer; color: var(--fp-ink-soft); }
.fp-source code {
  display: block;
  margin-top: 9px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--fp-bg);
  border: 1px solid var(--fp-line);
  font-size: 1.5rem;
  line-height: 1.55;
  word-break: break-word;
  color: var(--fp-ink-soft);
}

/* slot kept for imagery / specs / pricing added later */
.fp-slot {
  margin: 22px 0 0;
  display: grid;
  place-items: center;
  min-height: 96px;
  border-radius: var(--fp-radius);
  border: 1px dashed var(--fp-line-firm);
  color: var(--fp-ink-faint);
  font-size: 1.56rem;
  text-align: center;
  padding: 16px;
}

/* ---------- application ---------- */

.fp-apply { margin: 15px 0 0; }

.fp-apply__btn {
  appearance: none;
  cursor: pointer;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 14px 20px;
  border: 0;
  border-radius: 12px;
  background: var(--fp-accent);
  color: #fff;
  font: inherit;
  font-size: 1.8rem;
  font-weight: 650;
  letter-spacing: -0.005em;
  box-shadow: 0 6px 18px rgb(249 115 22 / .26);
  transition: background .22s var(--fp-ease), box-shadow .22s var(--fp-ease),
              transform .22s var(--fp-ease);
}
.fp-apply__btn:hover {
  background: #ea6a0c;
  box-shadow: 0 9px 24px rgb(249 115 22 / .34);
  transform: translateY(-1px);
}
.fp-apply__btn:active { transform: translateY(0); box-shadow: 0 4px 12px rgb(249 115 22 / .3); }
.fp-apply__btn:focus-visible { outline: 2px solid var(--fp-accent-dp); outline-offset: 3px; }
/* © 2026 Ali Salih · https://github.com/AliSalih-ops · all rights reserved */

.fp-apply__arrow {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .24s var(--fp-ease);
}
.fp-apply__btn:hover .fp-apply__arrow { transform: translateX(3px); }

/* once sent, the panel behind stops offering a second submission */
.fp-apply.is-sent .fp-apply__btn {
  background: var(--fp-surface);
  color: var(--fp-ink-soft);
  box-shadow: inset 0 0 0 1px var(--fp-line-firm);
  pointer-events: none;
}
.fp-apply.is-sent .fp-apply__btn span::after { content: ' · sent'; }

/* ---------- application page (slides in over the panel) ----------
   Anchored to the panel, which stops scrolling while this is up, so the page
   covers exactly what you were looking at. The panel's close button sits above
   it, so the × stays available from both pages. */

.fp-appview {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  background: var(--fp-surface);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform .42s var(--fp-ease), visibility .42s;
}
.fp[data-form="open"] .fp-appview { transform: none; visibility: visible; }
.fp[data-form="open"] .fp__panel-body { overflow: hidden; }

.fp-appview__bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 64px 14px clamp(16px, 2vw, 22px);
  border-bottom: 1px solid var(--fp-line);
  background: var(--fp-surface);
}

.fp-appview__back {
  flex: 0 0 auto;
  appearance: none;
  cursor: pointer;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--fp-line);
  background: var(--fp-surface);
  color: var(--fp-ink-soft);
  transition: color .2s var(--fp-ease), border-color .2s var(--fp-ease),
              background .2s var(--fp-ease);
}
.fp-appview__back svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.fp-appview__back:hover {
  color: var(--fp-accent-dp);
  border-color: var(--fp-accent);
  background: var(--fp-accent-sf);
}
.fp-appview__back:focus-visible { outline: 2px solid var(--fp-accent); outline-offset: 2px; }

.fp-appview__eyebrow {
  margin: 0;
  font-size: 1.32rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fp-accent);
}
.fp-appview__title {
  margin: 1px 0 0;
  font-size: 2.24rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.fp-appview__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px clamp(16px, 2vw, 22px) 34px;
}

.fp-form { margin: 0; }

/* the auto-filled unit */
.fp-locked { position: relative; }
.fp-locked input {
  background: var(--fp-accent-sf);
  border-color: transparent;
  color: var(--fp-accent-dp);
  font-weight: 650;
  padding-right: 38px;
  cursor: default;
}
.fp-locked input:focus { box-shadow: none; border-color: var(--fp-accent); }
.fp-locked__pin {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  width: 15px; height: 15px;
  fill: none; stroke: var(--fp-accent); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  pointer-events: none;
}
.fp-field__note {
  margin: 6px 0 0;
  font-size: 1.44rem;
  color: var(--fp-ink-faint);
}

.fp-form__pair { display: grid; gap: 12px; }
@media (min-width: 420px) {
  .fp-form__pair { grid-template-columns: 1fr 1fr; }
}

.fp-field { margin: 0 0 12px; }
.fp-field__label {
  display: block;
  margin: 0 0 6px;
  font-size: 1.51rem;
  font-weight: 600;
  color: var(--fp-ink);
}
.fp-field__opt { font-weight: 400; color: var(--fp-ink-faint); }

.fp-form input,
.fp-form textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--fp-line-firm);
  border-radius: 10px;
  background: var(--fp-surface);
  color: var(--fp-ink);
  font: inherit;
  font-size: 1.7rem;
  transition: border-color .2s var(--fp-ease), box-shadow .2s var(--fp-ease);
}
.fp-form textarea { resize: vertical; min-height: 86px; line-height: 1.5; }
.fp-form input::placeholder,
.fp-form textarea::placeholder { color: var(--fp-ink-faint); }
.fp-form input:focus,
.fp-form textarea:focus {
  outline: none;
  border-color: var(--fp-accent);
  box-shadow: 0 0 0 3px rgb(249 115 22 / .16);
}
.fp-form input.is-bad,
.fp-form textarea.is-bad { border-color: #d64545; }

.fp-field__err {
  margin: 6px 0 0;
  font-size: 1.47rem;
  line-height: 1.45;
  color: #c23b3b;
}

/* attachments */
.fp-drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 20px 16px;
  border: 1.5px dashed var(--fp-line-firm);
  border-radius: 12px;
  background: var(--fp-surface);
  cursor: pointer;
  text-align: center;
  transition: border-color .2s var(--fp-ease), background .2s var(--fp-ease);
}
.fp-drop:hover, .fp-drop.is-over {
  border-color: var(--fp-accent);
  background: var(--fp-accent-sf);
}
.fp-drop__input {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
  margin: -1px;
}
.fp-drop__input:focus-visible + .fp-drop__icon { outline: 2px solid var(--fp-accent); }
.fp-drop:focus-within {
  border-color: var(--fp-accent);
  box-shadow: 0 0 0 3px rgb(249 115 22 / .16);
}
.fp-drop__icon {
  width: 22px; height: 22px;
  fill: none; stroke: var(--fp-ink-faint); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.fp-drop:hover .fp-drop__icon, .fp-drop.is-over .fp-drop__icon { stroke: var(--fp-accent); }
.fp-drop__title { font-size: 1.64rem; font-weight: 550; color: var(--fp-ink); }
.fp-drop__link { color: var(--fp-accent-dp); text-decoration: underline; }
.fp-drop__hint { font-size: 1.44rem; color: var(--fp-ink-faint); line-height: 1.45; }

.fp-drop__list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.fp-file {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--fp-line);
  border-radius: 9px;
  background: var(--fp-surface);
  font-size: 1.55rem;
  animation: fp-in .3s var(--fp-ease) both;
}
.fp-file__icon {
  flex: 0 0 auto;
  width: 15px; height: 15px;
  fill: none; stroke: var(--fp-accent); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.fp-file__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--fp-ink);
}
.fp-file__size { flex: 0 0 auto; color: var(--fp-ink-faint); font-variant-numeric: tabular-nums; }
.fp-file__x {
  flex: 0 0 auto;
  appearance: none;
  cursor: pointer;
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--fp-ink-faint);
}
.fp-file__x svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2; }
.fp-file__x:hover { background: var(--fp-bg); color: var(--fp-ink); }

.fp-form__send {
  appearance: none;
  cursor: pointer;
  width: 100%;
  margin-top: 4px;
  padding: 13px 20px;
  border: 0;
  border-radius: 11px;
  background: var(--fp-accent);
  color: #fff;
  font: inherit;
  font-size: 1.75rem;
  font-weight: 650;
  box-shadow: 0 5px 16px rgb(249 115 22 / .24);
  transition: background .22s var(--fp-ease), box-shadow .22s var(--fp-ease);
}
.fp-form__send:hover:not(:disabled) { background: #ea6a0c; box-shadow: 0 8px 22px rgb(249 115 22 / .32); }
.fp-form__send:disabled { opacity: .62; cursor: default; box-shadow: none; }
.fp-form__send:focus-visible { outline: 2px solid var(--fp-accent-dp); outline-offset: 3px; }

.fp-form__status {
  margin: 12px 0 0;
  padding: 11px 13px;
  border-radius: 10px;
  font-size: 1.55rem;
  line-height: 1.5;
}
.fp-form__status.is-bad { background: #fdecec; color: #a33; border: 1px solid #f3cfcf; }

/* sent */
.fp-sent {
  margin-top: 22px;
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 34px 22px;
  border: 1px solid var(--fp-line);
  border-radius: var(--fp-radius);
  background: var(--fp-bg);
  text-align: center;
  animation: fp-in .4s var(--fp-ease) both;
}
.fp-sent__back {
  appearance: none;
  cursor: pointer;
  margin-top: 14px;
  padding: 10px 20px;
  border-radius: 999px;
  border: 1px solid var(--fp-line-firm);
  background: var(--fp-surface);
  color: var(--fp-ink-soft);
  font: inherit;
  font-size: 1.6rem;
  font-weight: 550;
}
.fp-sent__back:hover { color: var(--fp-ink); border-color: var(--fp-ink-faint); }
.fp-sent__tick {
  width: 34px; height: 34px;
  padding: 7px;
  border-radius: 50%;
  background: var(--fp-accent-sf);
  fill: none; stroke: var(--fp-accent); stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.fp-sent__title { margin: 4px 0 0; font-size: 2rem; font-weight: 650; }
.fp-sent__sub { margin: 0; font-size: 1.6rem; line-height: 1.55; color: var(--fp-ink-soft); }
/* © 2026 Ali Salih · https://github.com/AliSalih-ops · all rights reserved */

/* ---------- responsive: panel becomes a bottom sheet ---------- */

@media (max-width: 860px) {
  .fp__bar { padding: 14px 16px; }
  .fp__floors { width: 100%; justify-content: center; }

  /* stack: plan on top, details as a sheet below. The canvas gives up height
     when the sheet opens so the selected unit is never hidden behind it. */
  .fp__stage { flex-direction: column; }
  .fp__canvas {
    flex: 1 1 auto;
    min-height: 0;
    transition: flex-basis .46s var(--fp-ease);
  }
  .fp[data-panel="open"] .fp__canvas { flex: 0 0 40%; }

  .fp__panel {
    position: absolute;
    inset: auto 0 0 0;
    width: auto;
    max-height: 60%;
    margin-right: 0;
    border-left: 0;
    border-top: 1px solid var(--fp-line);
    border-radius: var(--fp-radius) var(--fp-radius) 0 0;
    transform: translateY(101%);
    box-shadow: 0 -14px 44px rgb(0 0 0 / .16);
    transition: transform .46s var(--fp-ease), opacity .3s var(--fp-ease), visibility .46s;
  }
  .fp[data-panel="open"] .fp__panel { transform: none; }
  .fp__panel-body { padding: 26px 20px 34px; }
  .fp__full { top: 12px; left: 12px; padding: 10px 16px 10px 13px; font-size: 1.72rem; }
  .fp-code { font-size: 3.4rem; }

  /* the sheet gives the application page the full height it needs */
  .fp[data-form="open"] .fp__panel { max-height: 100%; border-radius: 0; }
  .fp[data-panel="open"][data-form="open"] .fp__canvas { flex: 0 0 0%; }
  .fp-appview__scroll { padding: 18px 18px 30px; }
  .fp-appview__bar { padding: 14px 60px 12px 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .fp *, .fp *::before, .fp *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
  .fp-unit.is-linked .fp-unit__lift,
  .fp-unit.is-selected .fp-unit__lift,
  .fp-terrace.is-linked .fp-terrace__lift,
  .fp-terrace.is-selected .fp-terrace__lift { transform: none; }
}

/* ==========================================================================
   Copyright © 2026 Ali Salih. All rights reserved. · https://github.com/AliSalih-ops
   SPDX-License-Identifier: LicenseRef-AliSalih-Proprietary-1.0 · see LICENSE.txt
   ========================================================================== */
