/* =====================================================================
   Hotel Website Development — interactive layered process visual
   Loaded only on web-development.php. Scoped entirely under .hdev so it
   cannot collide with anything in the site-wide css/style.css.

   Structure follows the reference layout the client supplied: an isometric
   deck of slabs on the left, permanently fanned out, each one connected by
   a short colour-coded line to a numbered row on the right (number badge,
   icon, title, description).

   IMPORTANT when editing .development-layer: it must not pick up `filter`,
   `opacity` below 1, or `overflow: hidden`. Each of those silently forces
   `transform-style` back to `flat`, which collapses the slab's under-faces
   into the top face and the plates lose their thickness. Anything of that
   kind belongs on the faces (img / ::before / ::after) instead.

   This file consumes the design tokens already defined in style.css
   (--teal, --navy, --ink, --muted, --line, --soft, --serif, --sans) and
   layers its own tunable custom properties on top. Per-step accents come
   in from the template as --c / --c-soft on each row.
   ===================================================================== */

.hdev {
  --hdev-accent: var(--teal);
  --hdev-ink: var(--navy);
  --hdev-muted: var(--muted);
  --hdev-line: var(--line);
  --hdev-soft: var(--soft);

  --hdev-radius: 10px;
  --hdev-dur: 420ms; /* hover/focus transition duration */

  /* The isometric camera angle, how far apart the plates sit permanently
     (the deck stays fanned out at rest, not a closed stack), and how much
     further the one active plate pushes beyond that on hover/focus. */
  --hdev-tilt-x: 57deg;
  /* Positive Z rotation fans the deck off its bottom-RIGHT corner; negate it
     to mirror the whole stack back to the bottom-left. */
  --hdev-tilt-z: 19deg;
  /* Free to set for how it looks: the list is what follows the deck, not the
     other way round. Changing it does mean re-measuring --hdev-row-pitch and
     friends further down, which pin the rows to the plates. */
  --hdev-tz-step: 84px;
  --hdev-tz-boost: 94px;

  /* Sizing lives in these four, so a breakpoint only has to restate them.
     A fanned deck projects far taller and wider than its own box — the
     plates are pushed toward the viewer and the tilt throws them upward —
     so --hdev-headroom reserves the space it overflows into. Without it the
     top plates render up over whatever sits above this section. */
  --hdev-plate: 300px;
  --hdev-final-w: 515px;
  /* --hdev-headroom sets how far down the deck sits, --hdev-final-overlap how
     far the finished-site panel tucks up behind it. Both are free choices;
     the row variables below are what get re-measured to match them. */
  --hdev-final-overlap: -286px;
  --hdev-headroom: 424px;
  --hdev-link-reach: 182px; /* how far each connector line runs back toward the deck */
  /* The deck reads as rising out of the laptop's display, so it is centred on
     the SCREEN rather than on the photo. The screen sits right of the photo's
     middle (there is a plant and a coffee on the left), hence the offset. */
  --hdev-stack-shift-x: 66px;

  /* Slab thickness, drawn as two under-faces below each plate. */
  --hdev-slab: 16px;
  --hdev-slab-top: #EDF2F6;
  --hdev-slab-base: #D7E0E8;

  padding: 80px 0 110px;
  background: #fff;
}

.hdev-grid {
  display: grid;
  grid-template-columns: 3fr 2fr; /* ~60% visual / 40% text, as specified */
  /* start, not center: the plate-to-row alignment is measured from a common
     top edge, and centring would re-offset the deck whenever either column
     changed height. */
  align-items: start;
  gap: 40px 48px;
}

/* ---------------------------------------------------------------------
   Left column — the isometric 3D deck
   --------------------------------------------------------------------- */
.hdev-visual {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-top: var(--hdev-headroom);
  /* Very long, so the projection is close to parallel. Two reasons: every
     plate stays about the same size (as in the reference), and — the load
     bearing one — a short perspective spaces the plates non-linearly on
     screen, which no single --hdev-tz-step can align against evenly spaced
     list rows. At 2800px the residual drift was ±18px; here it is ±10px,
     the rest being the rows' own uneven heights. */
  perspective: 6000px;
}

.hdev-stack {
  position: relative;
  z-index: 2; /* the deck paints over the finished-site panel behind it */
  left: var(--hdev-stack-shift-x, 0px); /* paint-only nudge; does not move the box */
  width: 100%;
  max-width: var(--hdev-plate);
  aspect-ratio: 1 / 1; /* the artwork is square (1254×1254), so the plates are too */
  flex: none; /* a flex item with an aspect-ratio will otherwise be shrunk to fit the column */
  transform-style: preserve-3d;
  /* --hdev-tilt-dx/dy are set from JS as the pointer moves, giving the
     "tilt the camera" effect the reference describes; they default to 0
     so the deck still renders its base isometric angle with no JS at all. */
  transform: rotateX(calc(var(--hdev-tilt-x) + var(--hdev-tilt-dy, 0deg)))
             rotateZ(calc(var(--hdev-tilt-z) + var(--hdev-tilt-dx, 0deg)));
  transition: transform 200ms ease-out;
}

.development-layer {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  cursor: pointer;
  /* Permanently fanned out: --d is the depth rank handed down by the
     template (highest for step 1, at the front of the deck; 0 for the last
     plate), so the whole deck reads as a stack without needing a hover to
     reveal it, and adding or removing a stage needs no change here. */
  transform: translateZ(calc(var(--d) * var(--hdev-tz-step)));
  transition: transform var(--hdev-dur) ease;
}

/* The two under-faces that give each plate its thickness. Sitting a little
   deeper in Z than the artwork, they peek out along the lower edges under
   the isometric angle and read as the side wall of a solid slab. */
.development-layer::before,
.development-layer::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--hdev-radius);
  transition: opacity var(--hdev-dur) ease, box-shadow var(--hdev-dur) ease;
}
.development-layer::before {
  background: var(--hdev-slab-top);
  transform: translateZ(calc(var(--hdev-slab) * -.5));
}
.development-layer::after {
  background: var(--hdev-slab-base);
  transform: translateZ(calc(var(--hdev-slab) * -1));
  /* In-plane, so it projects with the slab and reads as its ground shadow.
     A filter: drop-shadow() here would flatten the 3D — see the note up top. */
  box-shadow: 0 16px 30px rgba(11, 35, 64, .20);
}

.development-layer img {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: contain; /* square artwork in a square plate, so this is a no-op until one isn't */
  display: block;
  pointer-events: none;
  background: #fff;
  border-radius: var(--hdev-radius);
  transition: opacity var(--hdev-dur) ease, filter var(--hdev-dur) ease;
}

/* Every opacity rule below lands on the faces rather than on the layer
   itself: opacity under 1 on .development-layer would flatten the slab (see
   the note at the top of this file). */

/* Plates stacked on top of the active one are peeled away completely, so
   whichever stage you point at is revealed rather than half-buried. The
   class comes from JS — CSS cannot compare one element's --d to another's —
   and the layer stops taking pointer events so it cannot swallow hovers
   aimed at what is now visible beneath it. */
.hdev-grid.is-hovering .development-layer.is-above { pointer-events: none; }
.hdev-grid.is-hovering .development-layer.is-above img,
.hdev-grid.is-hovering .development-layer.is-above::before,
.hdev-grid.is-hovering .development-layer.is-above::after {
  opacity: 0;
}

/* The rest of the deck sits behind the active plate — dimmed rather than
   removed, so the remaining depth still reads. */
.hdev-grid.is-hovering .development-layer:not(.is-active):not(.is-above) img,
.hdev-grid.is-hovering .development-layer:not(.is-active):not(.is-above)::before,
.hdev-grid.is-hovering .development-layer:not(.is-active):not(.is-above)::after {
  opacity: .45;
}

.hdev-grid.is-hovering .development-layer.is-active {
  transform: translateZ(calc(var(--d) * var(--hdev-tz-step) + var(--hdev-tz-boost)));
}
.hdev-grid.is-hovering .development-layer.is-active img { filter: brightness(1.04); }
.hdev-grid.is-hovering .development-layer.is-active::after {
  box-shadow: 0 28px 48px rgba(11, 35, 64, .32);
}

/* ---------------------------------------------------------------------
   The finished site — a fixed panel under the deck, never a plate in it.
   It is the outcome rather than a stage, so it stays fully visible while
   the stages above it peel away.
   --------------------------------------------------------------------- */
.hdev-final {
  position: relative;
  /* Behind the deck. Without this it is a later positioned sibling and wins
     the paint order, so the finished site covered the lower plates instead
     of sitting behind them. */
  z-index: 1;
  width: 100%;
  max-width: var(--hdev-final-w);
  flex: none; /* same reason as .hdev-stack — must not be shrunk to fit */
  margin-top: var(--hdev-final-overlap);
  cursor: pointer;
  /* No radius, no shadow, no clipping: this is the finished site presented as
     an image, not another card in the deck. Hover feedback is the lift plus a
     brightness nudge on the image, since there is no frame left to light up. */
  transition: transform var(--hdev-dur) ease;
}
/* aspect-ratio, not height:auto alone — the image is lazy-loaded, and
   without a reserved box the panel collapses to zero height until it
   arrives, shifting everything below it. */
.hdev-final img {
  width: 100%;
  aspect-ratio: 1 / 1;
  height: auto;
  object-fit: contain;
  display: block;
  pointer-events: none;
  transition: filter var(--hdev-dur) ease;
}
.hdev-final.is-active { transform: translateY(-5px); }
.hdev-final.is-active img { filter: brightness(1.04); }

/* ---------------------------------------------------------------------
   Right column — the numbered rows
   Each row is: connector line → number badge → icon → title + description,
   in the same order and proportions as the reference.
   --------------------------------------------------------------------- */
.hdev-list { list-style: none; margin: 0; padding: 0; }

.hdev-trigger {
  all: unset;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 40px 34px 26px 1fr;
  align-items: start;
  gap: 0 14px;
  width: 100%;
  padding: 16px 14px 16px 0;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--hdev-dur) ease;
}
.hdev-trigger:hover,
.hdev-trigger:focus-visible,
.hdev-trigger.is-active { background: var(--c-soft, var(--hdev-soft)); }
.hdev-trigger:focus-visible { outline: 2px solid var(--hdev-accent); outline-offset: 2px; }

/* The short line running back toward the plate this row describes, with a
   dot at the far end — a fixed segment rather than a line computed to the
   plate itself, which would jump on every resize and pointer tilt for no
   real gain in what it communicates. */
.hdev-link {
  position: relative;
  align-self: center;
  height: 8px;
  /* Reaches back out of the row, into the gap between the two columns, so
     the line reads as coming off the deck rather than floating beside it.
     Retune --hdev-link-reach whenever --hdev-plate changes: a narrower deck
     ends further from the rows and the line has further to travel. */
  margin-left: calc(var(--hdev-link-reach) * -1);
}
.hdev-link::before {
  content: "";
  position: absolute;
  left: 8px; right: 0; top: 50%;
  height: 1px;
  background: var(--c, var(--hdev-line));
  opacity: .55;
  transition: opacity var(--hdev-dur) ease;
}
.hdev-link::after {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 6px; height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--c, var(--hdev-line));
  transition: transform var(--hdev-dur) ease;
}
.hdev-trigger.is-active .hdev-link::before { opacity: 1; }
.hdev-trigger.is-active .hdev-link::after { transform: scale(1.4); }

.hdev-badge {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--c-soft, var(--hdev-soft));
  color: var(--c, var(--hdev-accent));
  font: 700 14px/1 var(--sans);
  transition: background var(--hdev-dur) ease, color var(--hdev-dur) ease, transform var(--hdev-dur) ease;
}
.hdev-trigger.is-active .hdev-badge {
  background: var(--c, var(--hdev-accent));
  color: #fff;
  transform: scale(1.06);
}

.hdev-icon {
  display: grid;
  place-items: center;
  height: 34px;
  color: var(--hdev-ink);
}

.hdev-copy { display: flex; flex-direction: column; gap: 4px; text-align: left; min-width: 0; padding-top: 4px; }
.hdev-title {
  font: 400 21px/1.25 var(--serif);
  color: var(--hdev-ink);
}
.hdev-body { font-size: 13.5px; line-height: 1.55; color: var(--hdev-muted); max-width: 44ch; }

/* ---------------------------------------------------------------------
   Reduced motion — keep the depth relationships (the stack still reads
   as a stack) but drop the animated push/pull and the pointer-tilt,
   which js/hotel-development.js also skips attaching entirely.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .hdev-stack { transition: none; }
  .development-layer { transition: none; }
  .development-layer img,
  .development-layer::before,
  .development-layer::after { transition: opacity 120ms linear; }
  .hdev-trigger, .hdev-badge, .hdev-link::after { transition-duration: 1ms; }
  /* The finished-site panel animates too — it lifts on hover — so it needs
     to be listed here as well, not just the deck. */
  .hdev-final { transition: none; }
  .hdev-final.is-active { transform: none; }
}

/* ---------------------------------------------------------------------
   Two columns only: pin the rows to the plates.

   The deck's spacing is chosen for how it looks, so the LIST follows it
   rather than the other way round — each row is forced to the plates'
   on-screen pitch instead of taking its natural text height. Three
   consequences, all deliberate:

     - the type is a step smaller here than in the stacked layout, because a
       title plus two lines has to fit inside one plate's pitch;
     - --hdev-row-lead offsets the list so row 1 starts level with plate 1;
     - the last row gets extra space, since the finished-site panel sits much
       further below plate 7 than the plates sit from each other.

   Re-measure --hdev-row-pitch / --hdev-row-lead / --hdev-row-last after
   changing --hdev-tz-step, --hdev-tilt-x or --hdev-plate: all three move the
   plates on screen. The plate gaps are not perfectly even (perspective makes
   them shrink about 1px per step), so a single pitch leaves a couple of px
   of drift across the deck, which is well inside what the eye reads as
   lined up.
   --------------------------------------------------------------------- */
@media (min-width: 1081px) {
  .hdev {
    --hdev-row-pitch: 72.5px;
    --hdev-row-lead: 106px;
    --hdev-row-last: 46px;
  }
  .hdev-list { padding-top: var(--hdev-row-lead); }
  .hdev-item { height: var(--hdev-row-pitch); }
  .hdev-item:last-child { margin-top: var(--hdev-row-last); }

  .hdev-trigger { height: 100%; align-items: center; padding: 4px 14px 4px 0; }
  .hdev-copy { gap: 2px; padding-top: 0; }
  .hdev-title { font-size: 18px; line-height: 1.2; }
  .hdev-body {
    font-size: 12.5px;
    line-height: 1.45;
    /* Safety net, not a content decision: every description fits two lines
       today, and this stops a longer one from spilling into the next row. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* ---------------------------------------------------------------------
   Responsive
   --------------------------------------------------------------------- */
@media (max-width: 1080px) {
  /* The whole visual column goes below this width — deck and finished-site
     panel both. Side by side with its list the deck explains the steps, but
     stacked above them it is a tall decorative block pushing the real
     content down, on the screens least able to afford it. The list carries
     everything on its own: it already holds every step's title and
     description, which is why the visual is aria-hidden in the first place.
     Dropping the column also retires every deck-sizing variable here. */
  .hdev-visual { display: none; }
  .hdev-grid { grid-template-columns: 1fr; }
  /* No plates left to point at, so the connector line would just be a stray
     mark — drop it and close up the column it occupied. */
  .hdev-link { display: none; }
  .hdev-trigger { grid-template-columns: 34px 26px 1fr; padding-left: 4px; }
}

@media (max-width: 640px) {
  /* The visual is already gone by this width; only the list is left to size. */
  .hdev { padding: 66px 0; }
  .hdev-trigger { grid-template-columns: 30px 24px 1fr; gap: 0 11px; padding: 14px 8px 14px 4px; }
  .hdev-badge { width: 30px; height: 30px; font-size: 13px; }
  .hdev-icon { height: 30px; }
  .hdev-icon svg { width: 19px; height: 19px; }
  .hdev-title { font-size: 18px; }
  /* Touch has no hover or pointer position to tilt with; tapping a row
     still drives the same active state via JS, so the deck stays fully
     functional — just without the ambient camera-follow. */
}
