/* ============================================================================
   room-loupe-console.css — the interior of the Face Tagging Room.

   furnishing-vessel-interiors S7 (DT authoring). Presentation only.
   Spec: docs/room-specs/14-face-tagging.md — committed before this file.
   Pattern: the S2-accepted pair, applied to a SCENE-OWNED host.

   ── THE SEAM — and why it has no descendant combinator to a shell ──────────
   This is NOT the view-room seam. dressScene() stamps the marker classes onto
   `.face-training-content` ITSELF (room-windows.js:803) — there is no wrapper
   between the marker and the room:

       shell.classList.add('ffrw-vessel', 'ffrw-scene', 'ffrw-' + slug)

   so every rule here rides

       .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) <descendant>

   ⭐ `.modal-content` and `.face-training-content` are the SAME element
   (index.html:3646), so the admitted token root (launcher-visual.css:1063)
   and the scene shell coincide exactly — the --ffvr-* tokens land precisely
   where this interior lives.

   ── THE STAND-DOWN (scene-owned host discipline) ───────────────────────────
   Every rule carries `:not(.ffrw-stripped)`, the discipline
   switching-vessel-dress S3 proved and room-windows.css:786 documents:
   stripped, the decoration selectors DECLINE TO MATCH and the host's own
   surface returns byte-exact. The interior rules STEP ASIDE; they never
   override the host.

   ── WHY THIS FILE IS CSS-ONLY AND INJECTS NOTHING ──────────────────────────
   The host owns its shell's innerHTML and rewrites it on every state change.
   A stylesheet survives a re-render by construction; an injected descendant
   would be deleted by the next one. No MutationObserver work is needed here
   and none is added.

   ── WHAT THIS FILE MAY NOT DO ──────────────────────────────────────────────
   ⛔ NOT ONE GEOMETRY DECLARATION AND NOT ONE `!important`. styles.css:32590
   pins this shell at inset 0 with !important on every geometry property
   including padding; the fleet already answers that with @layer
   ffrw-scene-unpin. This file touches only descendants, none of them pinned.

   ⛔ THE HEADER BAND IS NOT REPAINTED. `.face-training-header` is
   HEADER_SELECTORS entry 5, so the overlay stamps `.ffvl-chromed-header`,
   whose `background: var(--ffvc-header-surface)` is the Room's own
   `linear-gradient(90deg,#17353C,#263021)` — and it WINS, because
   launcher-visual.css is attached at runtime (not <link>ed) and so lands
   after styles.css at equal specificity. Reading styles.css:32620 alone says
   this Room's largest surface is foreign indigo; that reading is wrong. Room
   ink measures 12.44:1 on the band as it actually renders. See spec §1.2 —
   and S8 must verify this in a browser, since it is a cascade argument.

   ⛔ NO STATUS HUE MOVES. In this Room colour IS data: confirmed/auto-tagged/
   predicted/unidentified, the five similarity-group hues, the four provenance
   chips, and the action-row hues (a documented cross-surface alignment with
   the review grids). Erasing a truthful state signal falsifies as surely as
   inventing one. The composition here is SUBTRACTIVE — three foreign
   materials leave, nothing ornamental arrives.

   WITHHELD (spec §6): the seven inline-gradient header buttons (inline styles
   outrank room-scoped CSS and this pattern forbids !important — excising them
   is host-renderer surgery, a JS change); the Fergi aperture; the selection
   hues (§6.2 — the Room accent is GREEN and green already means *confirmed*,
   so an accent selection ring would read as a confirmed face); and every
   census behavioral finding (BR-117, BR-118).

   STRUCK by the element-mapping gate (spec §2.1): `.ft-training-badge` and
   `.ft-tile-value` are dead CSS — present only in styles.css, zero render
   sites anywhere in app/. They are not styled here.

   Single-step revert: delete this file and its one <link> in index.html.
   ============================================================================ */

/* ── Token attach (D1 §11 step 3) ─────────────────────────────────────────
   The four derived constants are the FLEET's, copied verbatim from the six
   accepted Rooms. D1 §3.2: no percentage is re-picked per Room — including
   where the measurement tempted it (spec §4.1). Fallbacks are this Room's
   own derived values, so the file degrades to the same paint if the token
   root is ever absent. */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) {
  --lc-ink: var(--ffvr-ink, #EFFCFF);
  --lc-ink-muted: var(--ffvr-ink-muted, #B5C2C5);
  --lc-rule: color-mix(in srgb, var(--ffvr-rule, #50AFD1) 32%, transparent);
  --lc-rule-strong: color-mix(in srgb, var(--ffvr-rule, #50AFD1) 58%, transparent);
  --lc-control: color-mix(in srgb, var(--ffvr-surface-raised, #1E2A2D) 72%, var(--ffvr-surface-sunken, #000000) 28%);
  --lc-plane-hover: color-mix(in srgb, var(--ffvr-surface-raised, #1E2A2D) 90%, var(--ffvr-ink, #EFFCFF) 10%);
  --lc-accent: var(--ffvr-accent, #4FD1A1);
  --lc-on-accent: var(--ffvr-on-accent, #000000);
}

/* ── The empty queue: the worst legibility defect this train measured ──────
   `.ft-empty-queue` reads `var(--color-text-secondary, #6b7280)` and
   `.ft-empty-queue strong` reads `var(--color-text-primary, #111827)`
   (styles.css:35250, :35253). ⚠️ BOTH custom properties are undefined
   ANYWHERE in the tree — verified by exhaustive search, 0 definitions each —
   so the literal fallbacks are what actually paint. On this Room's ground
   that is 1.02:1 for the emphasis line: near-black on near-black, text that
   is effectively invisible.

   ftRenderEmptyQueueState writes into #ftPhotoPreview (sunken, #000000),
   falling back to #ftMainContent (surface). Measured on both:
     strong  1.18 / 1.02:1  ->  20.04 / 17.22:1
     body    4.34 / 3.73:1  ->  11.49 /  9.87:1
   The STRINGS are renderer truth and are untouched; only their ink moves. */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-empty-queue {
  color: var(--lc-ink-muted);
}

.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-empty-queue strong {
  color: var(--lc-ink);
}

/* ── The Community Service lane toggle ────────────────────────────────────
   `.ft-lane-btn.active` paints `background:#fff` — a WHITE PILL on a dark
   teal band, the Room's one remaining light material. It becomes the binary
   accent pill the fleet uses (D1 §4.4): on-accent on accent, 10.97:1, with
   the accent itself 6.81:1 against the band (non-text floor 3:1).

   ⚠️ FOR THE S8 GATE: `#ftLaneSwitch` carries `display:none` unless
   Community Service mode is on (ffa-curator.js:3079). These two rules are
   UNREACHABLE until that mode is enabled — the gate must turn it on to see
   them, or it will report a rule it never rendered. */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-lane-btn {
  border-color: var(--lc-rule-strong);
}

.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-lane-btn.active {
  background: var(--lc-accent);
  color: var(--lc-on-accent);
}

/* ── The S/M/L display-size toggle ────────────────────────────────────────
   furnishing-vessel-interiors S9, from the S8 return.

   `.size-toggle-btn.active` paints `rgba(102,126,234,.4)` (styles.css:33212)
   — the fleet's signature indigo again. ⚠️ S7 wrote above that the Review-All
   pill was "the ONLY reachable instance of it inside this seam"; that was an
   UNDERCOUNT, and the correction is recorded rather than the sentence quietly
   edited. This one is reachable for the same reason the Review-All pill is:
   it lives in a stylesheet, not an inline `style` attribute. Measured in the
   browser at v1.0.249 — `inline: false`, background-color
   `rgba(102, 126, 234, 0.4)`.

   ⛔ S8 filed this as riding the stamping failure. It does not. The stamping
   fix restores the header BAND and changes nothing here — verified by
   re-measuring after the fix, where this remained and the band did not. Two
   defects wearing one hue.

   It takes the SAME binary-selected grammar `.ft-lane-btn.active` was
   accepted with three rules above — the accent pill of D1 §4.4 — because it
   is the same kind of control: a binary selected state in the header band,
   not a face. (Withhold §6.2's green-means-confirmed collision governs
   selection on FACES; it does not reach a header toggle.) */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .size-toggle-btn.active {
  background: var(--lc-accent);
  color: var(--lc-on-accent);
}

/* ── The Review-All pill ──────────────────────────────────────────────────
   `rgba(102,126,234,.2)` / border `.4` — #667eea, the fleet's signature
   foreigner, and the ONLY reachable instance of it inside this seam (the
   other seven live in inline style attributes; see the withhold). It takes
   the Room's own control grammar, identical to the one the Documentation
   Room's `.btn` was accepted with at S6: control ground, rule-strong edge,
   Room ink. Ink measures 16.13:1 on that ground; the edge 3.16:1 against it.
   The label text is untouched. */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-header-btn.review-all-btn {
  background: var(--lc-control);
  border-color: var(--lc-rule-strong);
  color: var(--lc-ink);
}

.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-header-btn.review-all-btn:hover {
  background: var(--lc-plane-hover);
}

/* ── The Bulk-Review pill (S10) ───────────────────────────────────────────
   ⚠️ THE COMMENT ABOVE SAID THE REVIEW-ALL PILL WAS "THE ONLY REACHABLE
   INSTANCE" OF #667eea IN THIS SEAM. That was true when it was written and is
   NOT true now — the correction is recorded here rather than the sentence
   quietly edited, the same way S9 corrected S7's undercount.

   S7 withheld this one because it lived in an inline `style` attribute on the
   host renderer (`ffa-curator.js`), and reasoned it was safe to leave because
   the pill "already sits on the Room's own dark band today." ⛔ That reasoning
   rested on the band being indigo. S8 proved the band was never repainted, S9
   repainted it teal-olive for real — so the pill stopped being camouflaged and
   became PROMINENT, which is the exact "rainbow pills on a freshly-darkened
   band" state S7 believed it was avoiding. The train created the prominence,
   so the train owns the fix.

   The withheld question — may a presentation train excise an inline `style`
   from a host renderer? — is answered YES for this shape and only this shape:
   the attribute carried `background`, `color` and `border` and nothing else.
   No handler, no geometry, no state authority, no control moved. Excising a
   purely-presentational declaration is presentation work by definition.

   It takes the ACCENT pill rather than Review-All's control grammar because
   the gradient encoded EMPHASIS — Bulk Review is the header's primary action —
   and that emphasis is truthful. Demoting it to the control ground would have
   silently flattened a real hierarchy while claiming only to change a hue. */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-header-btn.bulk-review-btn {
  background: var(--lc-accent);
  border-color: transparent;
  color: var(--lc-on-accent);
}

/* ── Focus (D1 §3.6) ──────────────────────────────────────────────────────
   A SHAPE, not a hue — which is precisely what keeps it readable in a Room
   where every hue already means something. The same three declarations the
   six accepted Rooms carry. Applied to the in-seam controls whose render
   sites are verified: .ft-header-btn (9 refs), .ft-lane-btn (3), and the
   action row's .action-btn. */
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-header-btn:focus-visible,
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-lane-btn:focus-visible,
.ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-actions-row .action-btn:focus-visible {
  outline: 3px solid #FFFFFF;
  outline-offset: 2px;
  box-shadow: 0 0 0 1px #000000;
}

/* ── Reduced motion (the floor plus the list — pilot pattern) ─────────────*/
@media (prefers-reduced-motion: reduce) {
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped),
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) * {
    transition: none;
  }

  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-header-btn,
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-lane-btn,
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-actions-row .action-btn {
    transform: none;
  }
}

/* ── Forced colors (D1 §10.1) ─────────────────────────────────────────────
   In High Contrast the system palette replaces every colour above, so what
   matters is that BOUNDARY and SELECTED-ness survive as system-keyword
   structure rather than as Room paint. The active lane pill is the one
   binary-state control here, so it takes Highlight — the same treatment the
   accepted Rooms give an active tab. */
@media (forced-colors: active) {
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-header-btn,
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-lane-btn {
    border: 1px solid ButtonBorder;
  }

  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-lane-btn.active {
    border: 2px solid Highlight;
  }

  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-empty-queue,
  .ffrw-face-tagging.ffrw-scene:not(.ffrw-stripped) .ft-empty-queue strong {
    color: CanvasText;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   FACE TAGGING v14 — the ported Loupe Console.  (porting-perimeter-souls S3)

   Everything below this line is reached ONLY through `html.ffv-modal-fleet-v14`,
   the reflection FFAFlags writes for `ffa_modal_fleet_v14`. With the flag off
   not one selector here matches, and the room renders exactly as the lines
   above render it. The SHELL half needs the flag class because `.ffvc-rim-glow`,
   `.ffvc-body` and `.ffvc-lip` are drawn by room-windows.css in BOTH states;
   an unconditioned override would break the byte-identity that makes this flag
   a rollback path.

   ── THIS IS A SCENE HOST, AND NOTHING HERE TOUCHES THE SCENE ─────────────
   Face Tagging renders faces into a scene the host re-render observer owns.
   The port is a CHASSIS port: no rule below reaches the face sidebar, the photo
   preview, the thumbnail strip, the candidate source colours, the actions row
   or the pool chips, and none of the horizontal insets move. The port's only
   geometry is vertical and it moves through the theme's own DERIVED keep-outs
   (137 / 97, from 71 / 65) — of which FIVE units are the decoration: the barrel
   lip asks 132 / 97 on its own. The old 71 (10.1%) was less than half the
   accepted standard; 137/700 is 19.6% against the Navigator's praised 20.4%.

   Widths are the lab's times the geometric mean sqrt(0.625 * 0.7) = 0.6614 and
   each is written `lab N x 0.6614` so the arithmetic is checkable.
   ═══════════════════════════════════════════════════════════════════════════ */

html.ffv-modal-fleet-v14 .ffrw-face-tagging {
  --v14-azure: #50d8ff;   /* the lab's --room-a     */
  --v14-jade:  #4fd1a1;   /* the lab's --room-b     */
  --v14-coral: #f06a67;   /* the lab's --room-c     */
  --v14-metal: #f2b84b;   /* the lab's --room-metal */
}

html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-rim-glow { stroke-width: 6.61; opacity: .24; }   /* lab 10  x 0.6614 */
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-body     { stroke-width: 2.65; }                 /* lab 4   x 0.6614 */
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-lip      { stroke: rgba(220, 246, 255, .45); stroke-width: .99; opacity: 1; }  /* lab 1.5 x 0.6614 */

html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-inspection path,
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-bed path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* the head: the examination beam, clamped to stop above the plate. Its FILL is
   what makes it read as light rather than as an outline, and it is the lab's
   own translucent wash — carried unchanged, being unitless. */
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-inspection-beam {
  fill: color-mix(in srgb, var(--v14-jade) 9%, transparent);
  stroke: color-mix(in srgb, var(--v14-jade) 38%, transparent);
  stroke-width: .93;                                                                              /* lab 1.4 x 0.6614 */
}

/* the loupe, seated on the crown (sunk 8.6 — see the theme) */
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-hero-ring { fill: rgba(4, 15, 26, .96); stroke-width: 1.46; }  /* lab 2.2 x 0.6614 */
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-hero-line {
  fill: none;
  stroke: color-mix(in srgb, var(--v14-azure) 78%, #ffffff 8%);
  stroke-width: 1.32;                                                                             /* lab 2   x 0.6614 */
}

/* the foot: the focus rail and the lit point the loupe is sighted on */
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-focus-line {
  stroke: var(--v14-azure);
  stroke-width: 1.65;                                                                             /* lab 2.5 x 0.6614 */
}
html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-focus-dot {
  fill: #07141b;
  stroke: var(--v14-coral);
  stroke-width: 1.98;                                                                             /* lab 3   x 0.6614 */
}

/* ── motion: NONE, and that is a decision, not an omission ─────────────────
   The lab gives this room exactly one moving part — `@keyframes loupe-focus`,
   which translates the crest (-250, 10) lab units and scales it 1.035 so the
   loupe sweeps the plate. It is NOT carried, and the reason is measurement
   rather than taste: a CSS transform moves the RENDERED ink while leaving the
   geometry `getPointAtLength` reports unchanged, so a translating crest would
   cross 156 units of the head band and BOTH capture gates would report the room
   clean, at every geometry, forever. That is the exact shape of the failure S1
   found in the shelf rail and S2 found in eight hero crests: a render no
   measurement can see. An ornament this fleet cannot measure in motion does not
   move. The only movement in the room is the drifting inspection dust the
   theme's particle recipe seeds into the two flank reveals, which the chassis
   already stands down under reduced motion. */

/* ── forced colours ────────────────────────────────────────────────────────
   The UA discards the fills and strokes above. The chassis may disappear; what
   may not happen is the beam, the focus rail and the loupe surviving as
   unstyled black-on-black shapes across the room's head and foot. */
@media (forced-colors: active) {
  html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-focus-dot,
  html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-inspection-beam {
    fill: Canvas;
    stroke: CanvasText;
  }
  html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-focus-line,
  html.ffv-modal-fleet-v14 .ffrw-face-tagging .ffvc-v14-hero-line {
    stroke: CanvasText;
  }
}
