/* ==========================================================================
   EC · Room Guides — block styles
   ==========================================================================
   Ported from the v9b mockup css/size-shape-guide.css §7 "FINDING THE RIGHT
   FIT", §7b "ROOM JUMP PILLS", §7c "ROOM FOOTER", plus rounds 13, 14, 15, 24,
   28 and 30 and the matching responsive rules from §10. Section-isolated per
   docs/DESIGN-SYNC rule 3: only this section's CSS lives here. Enqueued only
   when the block is present via block.json's file:./style.css.

   REBUILT 2026-08-18. The 4B build drew each room's figure as a bespoke CSS
   diagram; upstream that whole tree is gone. What replaced it:
     - a real PHOTOGRAPH per room in the branch's rounded media frame;
     - a footer row of four supplied Do/Don't SVG diagrams per room;
     - a sticky row of jump pills above the rooms.
   The dimfield primitive and the hairline furniture glyphs are deleted rather
   than kept, because nothing on the page renders one any more — v9b's own file
   head says the same of its §3 and §4.

   WHERE v9b DECLARES A PROPERTY MORE THAN ONCE, this sheet carries the value
   that actually won. v9b states .room__footer three times across rounds 14 and
   15 (grid, then flex, then the centring), which is a revision history rather
   than a cascade — reproducing all three here would only invite someone to
   "fix" the dead ones. The effective result is stated once, with the round noted
   in the comment.
   ========================================================================== */

/* Tighten the head-to-pills gap. The shell gives every .section-head --space-xl
   below it and the pill row's own margin-top would collapse into it, so 48px was
   the painted result and the row floated clear of the heading it belongs to.
   --space-lg makes the two collapse to one number. Page-scoped to .finding, so
   the other section heads on the guide keep the shell's standard 48px. */
.finding .section-head { margin-bottom: var(--space-lg); }
.finding__rooms { display: flex; flex-direction: column; gap: var(--section-gap-s); }

/* --------------------------------------------------------------------------
   ROOM
   Each room stacks its two-column main row (copy + photo) over the Do/Don't
   footer. No hairline separators between rooms — the generous inter-room space
   alone sets them apart (v9b round of 2026-07-14).
   -------------------------------------------------------------------------- */
.room {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  /* When a jump lands on a room, keep it clear of the fixed glass chrome (the
     established --chrome-bottom scroll-margin pattern). */
  scroll-margin-top: var(--chrome-bottom);
}
/* The room takes programmatic focus when a pill is used, so that a keyboard
   reader continues INSIDE the room rather than back in the pill row. That is a
   -1 tabindex and never a visible ring, and THIS RULE IS WHAT MAKES THAT TRUE —
   do not delete it as redundant. The reason previously written here was wrong and
   was measured wrong: it claimed Blink does not match :focus-visible on a
   scripted focus. It does. After a real Enter keypress on a pill, the focused
   .room matches :focus-visible (measured 2026-08-19 with genuine
   Input.dispatchKeyEvent keystrokes, not element.focus()), because Blink's
   heuristic looks at the LAST USER INTERACTION, and that was the keyboard. So
   pb-shell's (0,1,0) `:focus-visible { outline: 2px solid ... }` would otherwise
   paint a full ring around the entire room panel — the whole two-column row plus
   its four diagrams — on every pill activation. This rule is (0,2,0) and takes
   outline-style to `none`, which is what actually stops it: verified computed
   `outline: rgb(84, 96, 103) none 3px` on the focused room, i.e. a UA width and
   colour with no style, so nothing is drawn. Deliberately keyed to :focus and
   NOT :focus-visible, so a mouse activation is covered by the same rule, and
   deliberately carrying no border-radius (see the shell's own note). */
.room:focus { outline: none; }
.room__main {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2xl);
  align-items: center;
}
.room--flip .room__figure { order: -1; }
.room__text { display: flex; flex-direction: column; gap: var(--space-sm); max-width: 46ch; }

/* Room labels carry the deepest heading ink at --fs-h3, a clear step below the
   section head (46.4/28 at 1440, 31.2/22 at 390).

   The FACE is IvyPresto so the room labels read as headings like everything else
   on the site: pb-shell's folded [J] only reaches the h2 tier, which is why
   these would otherwise still be Gordita.

   THE WEIGHT HAS TO BE STATED, NOT INHERITED, and this is the trap. pb-shell
   sets every h1-h6 to --w-light, and the Typekit family ships 100/400/600/700
   with no 300: asking for 300 sends CSS font-matching to the nearest weight
   BELOW, i.e. IvyPresto Thin 100, which is far too pale for a sub-head at this
   size. --w-regular is both the brief's ask and the only safe value.

   Tracking follows [J]'s serif reasoning rather than the shell's sans default,
   so the two heading tiers read as one system. Leading keeps --lh-heading; at
   28px the taller serif ascenders want the extra hair of room over [J]'s 1.12. */
.room__text h3 {
  font-family: var(--font-serif);
  font-size: var(--fs-h3);
  font-weight: var(--w-regular);
  line-height: var(--lh-heading);
  letter-spacing: -0.01em;
  color: var(--text-strong);
}
/* The sentence that used to be the heading, now a standfirst opening the room's
   copy. At body size the ink alone is not enough separation from the list items
   below it, so the weight goes to --w-medium — the same weight/ink pairing
   .room__point-key already uses, so the column has one emphasis language rather
   than two. */
.room__lead {
  color: var(--text-strong);
  font-size: var(--fs-body);
  font-weight: var(--w-medium);
  line-height: var(--lh-body);
}
.room__points { display: flex; flex-direction: column; gap: var(--space-sm); margin-top: var(--space-2xs); }
.room__points li { color: var(--text); line-height: var(--lh-body); }
.room__point-key { color: var(--text-strong); font-weight: var(--w-medium); }

/* The room photograph, in the branch's standard rounded media frame at 4:3 so
   all four rooms hold the same row rhythm. The block's own .ph > img rule below
   fills it; no hover scale (branch invariant). */
.room__photo {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-media);
  overflow: hidden;
  box-shadow: var(--shadow-pop);
  isolation: isolate;
}
.room__photo .ph { position: absolute; inset: 0; border-radius: 0; }
/* Real-photography drop-in. The theme ships NO global `.ph > img` rule — every
   block that puts a photo in a .ph carries its own copy (pb_ec_hero,
   pb_ec_cta_band, pb_ec_image_hero, pb_ec_category_grid, pb_ec_product_rail,
   pb_ec_two_up_feature, pb_ec_entry_tiles, pb_ec_trio_benefits), and the comment
   above this one used to say the photo filled its frame "via the shell's
   .ph > img drop-in", describing a rule that does not exist here. Measured
   against v9b before this landed: object-fit computed `fill` against v9b's
   `cover`, and position `static` against `absolute`, at all three widths.

   BE PRECISE ABOUT WHAT THAT COST, because it is easy to overstate. Nothing was
   visibly wrong: all four shipped photographs are exactly 1200x900, the frame is
   4:3, and pb-shell's `img { max-width: 100% }` sized them to it, so `fill` and
   `cover` produced the SAME 628x471 box. Measured both ways on the live page to
   be sure. What the missing rule really was is a LATENT defect keyed to the one
   thing the `photo` field exists to allow: swap in a non-4:3 image and the
   unfitted <img> keeps its own ratio inside the frame. Measured with a 2000x400
   source in this slot — 628x126 without this rule against 628x471 with it, i.e.
   345px of bare .ph tone banding the frame, which is the same defect pb_ec_hero
   hit and fixed. So this is prevention, not repair, and it is also simply what
   v9b does. */
.room__photo .ph > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.room__photo img { transition: none; }

/* --------------------------------------------------------------------------
   ROOM JUMP PILLS
   A horizontal row of pills under the section head that follows the reader down
   the section (position: sticky, below).

   THESE ARE NOT TABS and have not been since v9b's round 14. There is no
   tab/panel model: all four rooms render at once, nothing is hidden, and no
   pill carries role="tab" or aria-selected. The selected treatment below is
   keyed to aria-current, which is the honest attribute for "the section you are
   currently in" — see script.js, which sets it.

   AA, AND IT IS A KNOWN SHORTFALL. White on --woodland-sage measures 2.56:1
   (3.45:1 on the deep step the hover and selected states use), below AA for body
   copy. This is the standing house decision for FILLED primaries in v9b — every
   primary button takes white on-fill ink for the same reason, and the footer
   band does the same. Matched here rather than inventing a darker fill for this
   one row; flagged, not rediscovered.
   -------------------------------------------------------------------------- */
.finding__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin-top: var(--space-lg);
  /* One stop off --section-gap-s: a fixed token, not a clamp, because the clamp
     bottoms out at 22px on a phone — below what a jump row wants above the
     content it introduces — while --space-md cuts the desktop gap by a third,
     which is where the row read loose. */
  margin-bottom: var(--space-md);
  /* The row follows the reader down the room subsections, pinned below the
     CONDENSED floating header (inset + header height + a small gap; by the time
     the row can pin, the utility strip has already hidden). Sticky is bounded by
     the parent container, which ends with the last room's footer, so the row
     releases naturally before the next section — no JS for that part. */
  position: sticky;
  top: calc(var(--chrome-inset) + var(--header-h) + var(--space-2xs));
  z-index: 5;
}
.room-tab {
  min-height: var(--tap-min);
  padding: var(--space-sm) var(--space-lg);
  /* Border kept at the same 1px geometry so the pill's box does not move between
     states; only the COLOUR carries state. At rest it matches the fill, so the
     pill reads as a clean sage chip with no lighter hairline ringing it. */
  border: var(--hairline-width) solid var(--woodland-sage);
  border-radius: var(--radius-pill);
  background: var(--woodland-sage);
  color: var(--white);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: background-color var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard),
              color var(--dur-base) var(--ease-standard),
              padding var(--dur-base) var(--ease-standard),
              font-size var(--dur-base) var(--ease-standard),
              min-height var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.room-tab:hover {
  background: var(--woodland-sage-deep);
  border-color: var(--woodland-sage-deep);
}
/* No deeper step exists on the Woodland Sage ramp below --woodland-sage-deep, so
   :active holds the hover tone rather than inventing a fifth value. */
.room-tab:active {
  background: var(--woodland-sage-deep);
  border-color: var(--woodland-sage-deep);
}
/* THE CURRENT PILL — the room the reader is in.
   Once all four pills are filled sage they are interchangeable, so the current
   one is marked THREE ways, none of them colour alone and none colliding with a
   state the pill already uses:
     1. FILL — the deep step, so it reads darker than its three siblings;
     2. RIM — --woodland-sage-ink, the ramp's darkest step. Deliberately a
        BORDER: the focus ring is a detached outline and the sticky row's lift
        already owns box-shadow, so either of those would have collided;
     3. WEIGHT — the label to --w-medium. This is the cue that survives the
        collision with :hover, which also uses the deep fill.
   Stated AFTER :hover and :active on purpose — all three are (0,2,0), so source
   order is what lets the current pill hold its rim and weight while hovered.

   aria-selected is matched as well as aria-current only because v9b keeps both
   selectors against a tabset ever returning. Nothing here sets it. */
.room-tab[aria-current="location"],
.room-tab[aria-current="true"],
.room-tab[aria-selected="true"] {
  background: var(--woodland-sage-deep);
  border-color: var(--woodland-sage-ink);
  color: var(--white);
  font-weight: var(--w-medium);
}
/* The same ring pb-shell gives everything; restated for parity with v9b, and
   deliberately WITHOUT a border-radius — :focus-visible is a pseudo-class, not a
   state layer, so a radius here would be the resting radius of every focused
   pill and would fight the base rule. */
.room-tab:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
/* While the row is pinned, the pills compact so the following state takes less
   room under the floating header. script.js adds the class. */
.finding__tabs--stuck .room-tab {
  min-height: 34px;
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--fs-xs);
  box-shadow: var(--shadow-pop);
}

/* --------------------------------------------------------------------------
   ROOM FOOTER — four Do/Don't diagrams
   Do, Do, Don't, Don't, in that order, consistent across all four rooms.

   NO HTML CAPTION, and this is a constraint rather than a preference: the
   artwork carries the DO / DON'T word as live text INSIDE the frame, so a
   figcaption would print the word twice. Anything that needs a caption here has
   to account for that. The verdict reaches assistive tech through each image's
   alt instead (render.php).

   The row is a compact centred flex row of fixed-width diagrams that wraps on
   narrow screens (round 14) — a four-across 1fr grid stretched the cluster
   across the full content width. The margin below is the largest break inside
   the section, so the cluster reads as the END of its room rather than the start
   of what follows (round 15, halved by the client round of 2026-08-14).

   The one property this sheet still reads differently from v9b's COMPUTED style
   is grid-template-columns: `none` here against `repeat(4, 1fr)` there (measured
   at 1500/1024, `repeat(2, 1fr)` at 390). That is v9b's dead §7c grid
   declaration surviving on the computed style of a container that round 14 made
   `display: flex`, where grid-template-columns does nothing. Every property that
   DOES lay this row out — display, flex-wrap, justify-content, gap,
   margin-bottom — matches at all three widths. Restating the dead value here to
   make a probe green would be copying a revision history, not a design.
   -------------------------------------------------------------------------- */
.room__footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-xl);
}
/* The gap is v9b's and is restored rather than dropped, but it paints nothing
   today: round 24 took the Do/Don't figcaption out, so the figure holds a single
   child. It is here so that anything added back under the artwork lands on the
   design's own spacing instead of flush against it. */
.room__diagram { margin: 0; display: flex; flex-direction: column; align-items: center; gap: var(--space-2xs); flex: 0 0 auto; }
/* Height is auto off the artwork's own 1:1 viewBox; the width and height
   attributes in the markup match it, so the row reserves its space before the
   SVGs arrive and the section does not shift as they load. */
.room__diagram-svg { width: 170px; height: auto; display: block; }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 820px) {
  /* Rooms stack: the two-column main row collapses to one column and the figure
     always drops below the text (flip resets). The stacked copy-to-figure gap
     has to stay SMALLER than the .room gap, or the two halves of a room's main
     row would sit as far apart as the main row is from the room's footer. */
  .room__main { grid-template-columns: 1fr; gap: var(--space-md); }
  .room--flip .room__figure { order: 0; }
  .room__text { max-width: none; }
  /* NO room__footer override here, and that is measured rather than assumed.
     v9b writes one — `grid-template-columns: repeat(2, 1fr); gap: var(--space-md)`
     — but its round-14 block restates `.room__footer` LATER in the same file at
     the same specificity, so the flex row and its --space-sm gap win at every
     width and the media-query pair is dead. Measured in Chrome against the
     mockup: the footer gap computes 16px at 390px there, not 24px. Carrying the
     declaration across would have been a 24px divergence from the design that
     looked like fidelity. The grid-template-columns half is inert regardless,
     since the row is a flex container. */
}

/* On phones the four pills compress hard and hold ONE row: nowrap plus a heavy
   size cut in both the at-rest and pinned states. If a very narrow screen still
   cannot fit all four, the row pans horizontally (scrollbar hidden) rather than
   wrapping — the pills never split onto multiple rows. The row is its own scroll
   container, so this pans the pills, not the page. */
@media (max-width: 640px) {
  .finding__tabs {
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .finding__tabs::-webkit-scrollbar { display: none; }
  .room-tab,
  .finding__tabs--stuck .room-tab {
    flex: 0 0 auto;
    white-space: nowrap;
    min-height: 30px;
    padding: 4px 10px;
    font-size: 0.6875rem;
  }
}
